diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h index 8f2e458b296..f39ca7d4c3e 100644 --- a/source/blender/editors/screen/screen_intern.h +++ b/source/blender/editors/screen/screen_intern.h @@ -59,6 +59,7 @@ void ed_screen_context(const bContext *C, bContextDataMember member, bContextDat /* screendump.c */ void SCREEN_OT_screenshot(struct wmOperatorType *ot); +void SCREEN_OT_screencast(struct wmOperatorType *ot); #endif /* ED_SCREEN_INTERN_H */ diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index eabc3bc7993..e973e776c21 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -2038,15 +2038,16 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec return; /* xmin here is first subrect x coord, xmax defines subrect width */ - xmin = renrect->xmin; - xmax = renrect->xmax - xmin; + xmin = renrect->xmin + rr->crop; + xmax = renrect->xmax - xmin - rr->crop; if (xmax<2) return; - ymin= renrect->ymin; - ymax= renrect->ymax - ymin; + ymin= renrect->ymin + rr->crop; + ymax= renrect->ymax - ymin - rr->crop; if(ymax<2) return; renrect->ymin= renrect->ymax; + } else { xmin = ymin = rr->crop; @@ -2087,7 +2088,7 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec float *rf= rectf; char *rc= rectc; - /* crop offset */ + /* XXX temp. because crop offset */ if( rectc >= (char *)(ibuf->rect)) { for(x1= 0; x1dumprect) + MEM_freeN(sj->dumprect); + MEM_freeN(sj); } @@ -198,7 +208,15 @@ static void screenshot_freejob(void *sjv) static void screenshot_updatejob(void *sjv) { ScreenshotJob *sj= sjv; + unsigned int *dumprect; + if(sj->dumprect==NULL) { + dumprect= MEM_mallocN(sizeof(int) * sj->dumpsx * sj->dumpsy, "dumprect"); + glReadPixels(sj->x, sj->y, sj->dumpsx, sj->dumpsy, GL_RGBA, GL_UNSIGNED_BYTE, dumprect); + glFinish(); + + sj->dumprect= dumprect; + } } @@ -206,38 +224,110 @@ static void screenshot_updatejob(void *sjv) static void screenshot_startjob(void *sjv, short *stop, short *do_update) { ScreenshotJob *sj= sjv; + RenderData rd= sj->scene->r; + bMovieHandle *mh= BKE_get_movie_handle(sj->scene->r.imtype); + int cfra= 1; + + /* we need this as local variables for renderdata */ + rd.frs_sec= 10; + rd.frs_sec_base= 1.0f; + + if(BKE_imtype_is_movie(rd.imtype)) + mh->start_movie(&rd, sj->dumpsx, sj->dumpsy); + else + mh= NULL; sj->stop= stop; sj->do_update= do_update; + *do_update= 1; // wait for opengl rect + while(*stop==0 && G.afbreek==0) { + + if(sj->dumprect) { + + if(mh) { + mh->append_movie(&rd, cfra, sj->dumprect, sj->dumpsx, sj->dumpsy); + printf("Append frame %d\n", cfra); + } + else { + ImBuf *ibuf= IMB_allocImBuf(sj->dumpsx, sj->dumpsy, rd.planes, 0, 0); + char name[FILE_MAXDIR+FILE_MAXFILE]; + int ok; + + BKE_makepicstring(sj->scene, name, rd.pic, cfra, rd.imtype); + + ibuf->rect= sj->dumprect; + ok= BKE_write_ibuf(sj->scene, ibuf, name, rd.imtype, rd.subimtype, rd.quality); + + if(ok==0) { + printf("Write error: cannot save %s\n", name); + break; + } + else printf("Saved: %s\n", name); + + /* imbuf knows which rects are not part of ibuf */ + IMB_freeImBuf(ibuf); + } + + MEM_freeN(sj->dumprect); + sj->dumprect= NULL; + + *do_update= 1; + + cfra++; + } + else + PIL_sleep_ms(50); + } + + if(mh) + mh->end_movie(); + printf("screencast job stopped\n"); } -static int screenshot_job_invoke(const bContext *C, wmOperator *op, wmEvent *event) +static int screencast_exec(bContext *C, wmOperator *op) { bScreen *screen= CTX_wm_screen(C); wmJob *steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), screen); ScreenshotJob *sj= MEM_callocN(sizeof(ScreenshotJob), "screenshot job"); - /* customdata for preview thread */ + /* setup sj */ + if(RNA_boolean_get(op->ptr, "full")) { + wmWindow *win= CTX_wm_window(C); + sj->x= 0; + sj->y= 0; + sj->dumpsx= win->sizex; + sj->dumpsy= win->sizey; + } + else { + ScrArea *curarea= CTX_wm_area(C); + sj->x= curarea->totrct.xmin; + sj->y= curarea->totrct.ymin; + sj->dumpsx= curarea->totrct.xmax - sj->x; + sj->dumpsy= curarea->totrct.ymax - sj->y; + } sj->scene= CTX_data_scene(C); - + /* setup job */ WM_jobs_customdata(steve, sj, screenshot_freejob); WM_jobs_timer(steve, 0.1, 0, 0); WM_jobs_callbacks(steve, screenshot_startjob, NULL, screenshot_updatejob); + G.afbreek= 0; // XXX? + WM_jobs_start(steve); + return OPERATOR_FINISHED; } -void SCREEN_OT_screenshot_movie(wmOperatorType *ot) +void SCREEN_OT_screencast(wmOperatorType *ot) { - ot->name= "Make Screenshot"; - ot->idname= "SCREEN_OT_screenshot_movie"; + ot->name= "Make Screencast"; + ot->idname= "SCREEN_OT_screencast"; - ot->invoke= screenshot_invoke; - ot->exec= screenshot_exec; + ot->invoke= WM_operator_confirm; + ot->exec= screencast_exec; ot->poll= WM_operator_winactive; ot->flag= 0; @@ -247,5 +337,4 @@ void SCREEN_OT_screenshot_movie(wmOperatorType *ot) } -#endif