diff options
Diffstat (limited to 'source/blender/editors/space_time/space_time.c')
-rw-r--r-- | source/blender/editors/space_time/space_time.c | 321 |
1 files changed, 175 insertions, 146 deletions
diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c index f29d2b30ffe..9a736ae977f 100644 --- a/source/blender/editors/space_time/space_time.c +++ b/source/blender/editors/space_time/space_time.c @@ -58,9 +58,11 @@ #include "WM_api.h" #include "WM_types.h" +#include "WM_message.h" + +#include "RNA_access.h" #include "BIF_gl.h" -#include "BIF_glutil.h" #include "UI_resources.h" #include "UI_view2d.h" @@ -69,6 +71,9 @@ #include "ED_space_api.h" #include "ED_markers.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" + #include "time_intern.h" /* ************************ main time area region *********************** */ @@ -78,30 +83,44 @@ static void time_draw_sfra_efra(Scene *scene, View2D *v2d) /* draw darkened area outside of active timeline * frame range used is preview range or scene range */ - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - glColor4f(0.0f, 0.0f, 0.0f, 0.4f); - + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f); + if (PSFRA < PEFRA) { - glRectf(v2d->cur.xmin, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax); - glRectf((float)PEFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); + immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax); + immRectf(pos, (float)PEFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); } else { - glRectf(v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); + immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); } + glDisable(GL_BLEND); - UI_ThemeColorShade(TH_BACK, -60); /* thin lines where the actual frames are */ - fdrawline((float)PSFRA, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax); - fdrawline((float)PEFRA, v2d->cur.ymin, (float)PEFRA, v2d->cur.ymax); + immUniformThemeColorShade(TH_BACK, -60); + + immBegin(GWN_PRIM_LINES, 4); + + immVertex2f(pos, (float)PSFRA, v2d->cur.ymin); + immVertex2f(pos, (float)PSFRA, v2d->cur.ymax); + + immVertex2f(pos, (float)PEFRA, v2d->cur.ymin); + immVertex2f(pos, (float)PEFRA, v2d->cur.ymax); + + immEnd(); + immUnbindProgram(); } static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene) { PTCacheID *pid; ListBase pidlist; - SpaceTimeCache *stc = stime->caches.first; const float cache_draw_height = (4.0f * UI_DPI_FAC * U.pixelsize); float yoffs = 0.f; @@ -110,12 +129,13 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene) BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* iterate over pointcaches on the active object, * add spacetimecache and vertex array for each */ for (pid = pidlist.first; pid; pid = pid->next) { - float col[4], *fp; - int i, sta = pid->cache->startframe, end = pid->cache->endframe; - int len = (end - sta + 1) * 4; + float col[4]; switch (pid->type) { case PTCACHE_TYPE_SOFTBODY: @@ -142,43 +162,9 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene) if (pid->cache->cached_frames == NULL) continue; - /* make sure we have stc with correct array length */ - if (stc == NULL || MEM_allocN_len(stc->array) != len * 2 * sizeof(float)) { - if (stc) { - MEM_freeN(stc->array); - } - else { - stc = MEM_callocN(sizeof(SpaceTimeCache), "spacetimecache"); - BLI_addtail(&stime->caches, stc); - } - - stc->array = MEM_callocN(len * 2 * sizeof(float), "SpaceTimeCache array"); - } - - /* fill the vertex array with a quad for each cached frame */ - for (i = sta, fp = stc->array; i <= end; i++) { - if (pid->cache->cached_frames[i - sta]) { - fp[0] = (float)i - 0.5f; - fp[1] = 0.0; - fp += 2; - - fp[0] = (float)i - 0.5f; - fp[1] = 1.0; - fp += 2; - - fp[0] = (float)i + 0.5f; - fp[1] = 1.0; - fp += 2; - - fp[0] = (float)i + 0.5f; - fp[1] = 0.0; - fp += 2; - } - } - - glPushMatrix(); - glTranslatef(0.0, (float)V2D_SCROLL_HEIGHT + yoffs, 0.0); - glScalef(1.0, cache_draw_height, 0.0); + gpuPushMatrix(); + gpuTranslate2f(0.0, (float)V2D_SCROLL_HEIGHT + yoffs); + gpuScale2f(1.0, cache_draw_height); switch (pid->type) { case PTCACHE_TYPE_SOFTBODY: @@ -212,12 +198,15 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene) BLI_assert(0); break; } - glColor4fv(col); - + + const int sta = pid->cache->startframe, end = pid->cache->endframe; + const int len = (end - sta + 1) * 6; + glEnable(GL_BLEND); - - glRectf((float)sta, 0.0, (float)end, 1.0); - + + immUniformColor4fv(col); + immRectf(pos, (float)sta, 0.0, (float)end, 1.0); + col[3] = 0.4f; if (pid->cache->flag & PTCACHE_BAKED) { col[0] -= 0.4f; col[1] -= 0.4f; col[2] -= 0.4f; @@ -225,52 +214,38 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene) else if (pid->cache->flag & PTCACHE_OUTDATED) { col[0] += 0.4f; col[1] += 0.4f; col[2] += 0.4f; } - glColor4fv(col); - - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, stc->array); - glDrawArrays(GL_QUADS, 0, (fp - stc->array) / 2); - glDisableClientState(GL_VERTEX_ARRAY); - - glDisable(GL_BLEND); - - glPopMatrix(); - - yoffs += cache_draw_height; - stc = stc->next; - } + immUniformColor4fv(col); - BLI_freelistN(&pidlist); + if (len > 0) { + immBeginAtMost(GWN_PRIM_TRIS, len); - /* free excessive caches */ - while (stc) { - SpaceTimeCache *tmp = stc->next; - BLI_remlink(&stime->caches, stc); - MEM_freeN(stc->array); - MEM_freeN(stc); - stc = tmp; - } -} + /* draw a quad for each cached frame */ + for (int i = sta; i <= end; i++) { + if (pid->cache->cached_frames[i - sta]) { + immVertex2f(pos, (float)i - 0.5f, 0.0f); + immVertex2f(pos, (float)i - 0.5f, 1.0f); + immVertex2f(pos, (float)i + 0.5f, 1.0f); -static void time_cache_free(SpaceTime *stime) -{ - SpaceTimeCache *stc; - - for (stc = stime->caches.first; stc; stc = stc->next) { - if (stc->array) { - MEM_freeN(stc->array); - stc->array = NULL; + immVertex2f(pos, (float)i - 0.5f, 0.0f); + immVertex2f(pos, (float)i + 0.5f, 1.0f); + immVertex2f(pos, (float)i + 0.5f, 0.0f); + } + } + + immEnd(); } + + glDisable(GL_BLEND); + + gpuPopMatrix(); + + yoffs += cache_draw_height; } - - BLI_freelistN(&stime->caches); -} -static void time_cache_refresh(SpaceTime *stime) -{ - /* Free previous caches to indicate full refresh */ - time_cache_free(stime); + immUnbindProgram(); + + BLI_freelistN(&pidlist); } /* helper function - find actkeycolumn that occurs on cframe, or the nearest one if not found */ @@ -296,7 +271,7 @@ static ActKeyColumn *time_cfra_find_ak(ActKeyColumn *ak, float cframe) } /* helper for time_draw_keyframes() */ -static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel) +static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel, const unsigned char color[3]) { bDopeSheet ads = {NULL}; DLRBT_Tree keys; @@ -341,21 +316,40 @@ static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel) * the first visible keyframe (last one can then be easily checked) * - draw within a single GL block to be faster */ - glBegin(GL_LINES); - for (ak = time_cfra_find_ak(keys.root, v2d->cur.xmin); - (ak) && (ak->cfra <= v2d->cur.xmax); - ak = ak->next) - { - glVertex2f(ak->cfra, ymin); - glVertex2f(ak->cfra, ymax); + + ActKeyColumn *link; + int max_len = 0; + + ak = time_cfra_find_ak(keys.root, v2d->cur.xmin); + + for (link = ak; link; link = link->next) { + max_len++; } - glEnd(); // GL_LINES - + + if (max_len > 0) { + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor3ubv(color); + + immBeginAtMost(GWN_PRIM_LINES, max_len * 2); + + for (; (ak) && (ak->cfra <= v2d->cur.xmax); ak = ak->next) { + immVertex2f(pos, ak->cfra, ymin); + immVertex2f(pos, ak->cfra, ymax); + } + + immEnd(); + immUnbindProgram(); + } + /* free temp stuff */ BLI_dlrbTree_free(&keys); } -static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, bool onlysel) +static void time_draw_caches_keyframes(Main *bmain, ViewLayer *view_layer, View2D *v2d, bool onlysel, const unsigned char color[3]) { CacheFile *cache_file; @@ -366,7 +360,7 @@ static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, b cache_file->draw_flag &= ~CACHEFILE_KEYFRAME_DRAWN; } - for (Base *base = scene->base.first; base; base = base->next) { + for (Base *base = view_layer->object_bases.first; base; base = base->next) { Object *ob = base->object; ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache); @@ -382,7 +376,7 @@ static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, b cache_file->draw_flag |= CACHEFILE_KEYFRAME_DRAWN; - time_draw_idblock_keyframes(v2d, (ID *)cache_file, onlysel); + time_draw_idblock_keyframes(v2d, (ID *)cache_file, onlysel, color); } for (bConstraint *con = ob->constraints.first; con; con = con->next) { @@ -400,7 +394,7 @@ static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, b cache_file->draw_flag |= CACHEFILE_KEYFRAME_DRAWN; - time_draw_idblock_keyframes(v2d, (ID *)cache_file, onlysel); + time_draw_idblock_keyframes(v2d, (ID *)cache_file, onlysel, color); } } } @@ -408,25 +402,29 @@ static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, b /* draw keyframe lines for timeline */ static void time_draw_keyframes(const bContext *C, ARegion *ar) { + WorkSpace *workspace = CTX_wm_workspace(C); Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob = CTX_data_active_object(C); View2D *v2d = &ar->v2d; bool onlysel = ((scene->flag & SCE_KEYS_NO_SELONLY) == 0); + unsigned char color[3]; /* set this for all keyframe lines once and for all */ glLineWidth(1.0); /* draw cache files keyframes (if available) */ - UI_ThemeColor(TH_TIME_KEYFRAME); - time_draw_caches_keyframes(CTX_data_main(C), scene, v2d, onlysel); + UI_GetThemeColor3ubv(TH_TIME_KEYFRAME, color); + time_draw_caches_keyframes(CTX_data_main(C), view_layer, v2d, onlysel, color); /* draw grease pencil keyframes (if available) */ - UI_ThemeColor(TH_TIME_GP_KEYFRAME); + UI_GetThemeColor3ubv(TH_TIME_GP_KEYFRAME, color); + if (scene->gpd) { - time_draw_idblock_keyframes(v2d, (ID *)scene->gpd, onlysel); + time_draw_idblock_keyframes(v2d, (ID *)scene->gpd, onlysel, color); } if (ob && ob->gpd) { - time_draw_idblock_keyframes(v2d, (ID *)ob->gpd, onlysel); + time_draw_idblock_keyframes(v2d, (ID *)ob->gpd, onlysel, color); } /* draw scene keyframes first @@ -435,8 +433,8 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar) */ if (onlysel == 0) { /* set draw color */ - UI_ThemeColorShade(TH_TIME_KEYFRAME, -50); - time_draw_idblock_keyframes(v2d, (ID *)scene, onlysel); + UI_GetThemeColorShade3ubv(TH_TIME_KEYFRAME, -50, color); + time_draw_idblock_keyframes(v2d, (ID *)scene, onlysel, color); } /* draw keyframes from selected objects @@ -444,11 +442,11 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar) * OR the onlysel flag was set, which means that only active object's keyframes should * be considered */ - UI_ThemeColor(TH_TIME_KEYFRAME); - - if (ob && ((ob->mode == OB_MODE_POSE) || onlysel)) { + UI_GetThemeColor3ubv(TH_TIME_KEYFRAME, color); + + if (ob && ((workspace->object_mode == OB_MODE_POSE) || onlysel)) { /* draw keyframes for active object only */ - time_draw_idblock_keyframes(v2d, (ID *)ob, onlysel); + time_draw_idblock_keyframes(v2d, (ID *)ob, onlysel, color); } else { bool active_done = false; @@ -457,7 +455,7 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar) CTX_DATA_BEGIN (C, Object *, obsel, selected_objects) { /* last arg is 0, since onlysel doesn't apply here... */ - time_draw_idblock_keyframes(v2d, (ID *)obsel, 0); + time_draw_idblock_keyframes(v2d, (ID *)obsel, 0, color); /* if this object is the active one, set flag so that we don't draw again */ if (obsel == ob) @@ -467,24 +465,15 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar) /* if active object hasn't been done yet, draw it... */ if (ob && (active_done == 0)) - time_draw_idblock_keyframes(v2d, (ID *)ob, 0); + time_draw_idblock_keyframes(v2d, (ID *)ob, 0, color); } } /* ---------------- */ -static void time_refresh(const bContext *UNUSED(C), ScrArea *sa) -{ - /* find the main timeline region and refresh cache display*/ - ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - if (ar) { - SpaceTime *stime = (SpaceTime *)sa->spacedata.first; - time_cache_refresh(stime); - } -} - /* editor level listener */ -static void time_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn) +static void time_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene), + WorkSpace *UNUSED(workspace)) { /* mainly for updating cache display */ @@ -625,7 +614,9 @@ static void time_main_region_draw(const bContext *C, ARegion *ar) UI_view2d_scrollers_free(scrollers); } -static void time_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void time_main_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -654,9 +645,55 @@ static void time_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), if (wmn->data == ND_DATA) ED_region_tag_redraw(ar); break; + case NC_SCREEN: + if (ELEM(wmn->data, ND_LAYER)) { + ED_region_tag_redraw(ar); + } + break; + } +} + +static void time_main_region_message_subscribe( + const struct bContext *UNUSED(C), + struct WorkSpace *UNUSED(workspace), struct Scene *scene, + struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar, + struct wmMsgBus *mbus) +{ + PointerRNA ptr; + RNA_pointer_create(&screen->id, &RNA_SpaceTimeline, sa->spacedata.first, &ptr); + + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { + .owner = ar, + .user_data = ar, + .notify = ED_region_do_msg_notify_tag_redraw, + }; + + /* Timeline depends on scene properties. */ + { + bool use_preview = (scene->r.flag & SCER_PRV_RANGE); + extern PropertyRNA rna_Scene_frame_start; + extern PropertyRNA rna_Scene_frame_end; + extern PropertyRNA rna_Scene_frame_preview_start; + extern PropertyRNA rna_Scene_frame_preview_end; + extern PropertyRNA rna_Scene_use_preview_range; + extern PropertyRNA rna_Scene_frame_current; + const PropertyRNA *props[] = { + use_preview ? &rna_Scene_frame_preview_start : &rna_Scene_frame_start, + use_preview ? &rna_Scene_frame_preview_end : &rna_Scene_frame_end, + &rna_Scene_use_preview_range, + &rna_Scene_frame_current, + }; + + PointerRNA idptr; + RNA_id_pointer_create(&scene->id, &idptr); + + for (int i = 0; i < ARRAY_SIZE(props); i++) { + WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_region_tag_redraw, __func__); + } } } + /* ************************ header time area region *********************** */ /* add handlers, stuff you only do once or on area/region changes */ @@ -670,7 +707,9 @@ static void time_header_region_draw(const bContext *C, ARegion *ar) ED_region_header(C, ar); } -static void time_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void time_header_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -754,13 +793,6 @@ static SpaceLink *time_new(const bContext *C) return (SpaceLink *)stime; } -/* not spacelink itself */ -static void time_free(SpaceLink *sl) -{ - SpaceTime *stime = (SpaceTime *)sl; - - time_cache_free(stime); -} /* spacetype; init callback in ED_area_initialize() */ /* init is called to (re)initialize an existing editor (file read, screen changes) */ /* validate spacedata, add own area level handlers */ @@ -768,8 +800,6 @@ static void time_init(wmWindowManager *UNUSED(wm), ScrArea *sa) { SpaceTime *stime = (SpaceTime *)sa->spacedata.first; - time_cache_free(stime); - /* enable all cache display */ stime->cache_display |= TIME_CACHE_DISPLAY; stime->cache_display |= (TIME_CACHE_SOFTBODY | TIME_CACHE_PARTICLES); @@ -798,13 +828,11 @@ void ED_spacetype_time(void) strncpy(st->name, "Timeline", BKE_ST_MAXNAME); st->new = time_new; - st->free = time_free; st->init = time_init; st->duplicate = time_duplicate; st->operatortypes = time_operatortypes; st->keymap = NULL; st->listener = time_listener; - st->refresh = time_refresh; /* regions: main window */ art = MEM_callocN(sizeof(ARegionType), "spacetype time region"); @@ -814,6 +842,7 @@ void ED_spacetype_time(void) art->init = time_main_region_init; art->draw = time_main_region_draw; art->listener = time_main_region_listener; + art->message_subscribe = time_main_region_message_subscribe; art->keymap = time_keymap; art->lock = 1; /* Due to pointcache, see T4960. */ BLI_addhead(&st->regiontypes, art); |