2.5
Test: making screencast movies inside Blender! Hotkey: CTRL+F3. Stop with ESC Keep in mind it's unfinished :) Just nice to see how simple cleaner code with the new event system and job manager can be put to work! - it uses currently output directory and image/movie settings from scene. No buttons for this yet. - Framerate is hardcoded 10 fps - Thread job takes care of open/write/close movie or save image files. - For speed it uses glReadPixels from backbuffer. Have to consult Brecht for nifty triple buffer trick. - On file reads it stops now.
This commit is contained in:
@@ -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 */
|
||||
|
||||
|
||||
@@ -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; x1<xmax; x1++, rf += 4, rc+=4) {
|
||||
rc[0]= FTOCHAR(rf[0]);
|
||||
@@ -2267,6 +2268,7 @@ void ED_operatortypes_screen(void)
|
||||
WM_operatortype_append(SCREEN_OT_screen_set);
|
||||
WM_operatortype_append(SCREEN_OT_screen_full_area);
|
||||
WM_operatortype_append(SCREEN_OT_screenshot);
|
||||
WM_operatortype_append(SCREEN_OT_screencast);
|
||||
|
||||
/*frame changes*/
|
||||
WM_operatortype_append(SCREEN_OT_frame_offset);
|
||||
@@ -2303,6 +2305,7 @@ void ED_keymap_screen(wmWindowManager *wm)
|
||||
WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", DOWNARROWKEY, KM_PRESS, KM_CTRL, 0);
|
||||
WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", SPACEKEY, KM_PRESS, KM_CTRL, 0);
|
||||
WM_keymap_add_item(keymap, "SCREEN_OT_screenshot", F3KEY, KM_PRESS, KM_CTRL, 0);
|
||||
WM_keymap_add_item(keymap, "SCREEN_OT_screencast", F3KEY, KM_PRESS, KM_ALT, 0);
|
||||
|
||||
/* tests */
|
||||
WM_keymap_add_item(keymap, "SCREEN_OT_region_split", SKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_utildefines.h"
|
||||
#include "BKE_writeavi.h"
|
||||
|
||||
#include "BIF_gl.h"
|
||||
|
||||
@@ -52,8 +53,13 @@
|
||||
#include "WM_types.h"
|
||||
#include "WM_api.h"
|
||||
|
||||
#include "PIL_time.h"
|
||||
|
||||
#include "ED_fileselect.h"
|
||||
#include "ED_screen.h"
|
||||
#include "ED_screen_types.h"
|
||||
|
||||
#include "screen_intern.h"
|
||||
|
||||
typedef struct ScreenshotData {
|
||||
unsigned int *dumprect;
|
||||
@@ -177,10 +183,11 @@ void SCREEN_OT_screenshot(wmOperatorType *ot)
|
||||
}
|
||||
|
||||
/* *************** screenshot movie job ************************* */
|
||||
#if 0
|
||||
|
||||
typedef struct ScreenshotJob {
|
||||
Scene *scene;
|
||||
unsigned int *dumprect;
|
||||
int dumpsx, dumpsy;
|
||||
int x, y, dumpsx, dumpsy;
|
||||
short *stop;
|
||||
short *do_update;
|
||||
} ScreenshotJob;
|
||||
@@ -190,6 +197,9 @@ static void screenshot_freejob(void *sjv)
|
||||
{
|
||||
ScreenshotJob *sj= sjv;
|
||||
|
||||
if(sj->dumprect)
|
||||
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user