diff options
Diffstat (limited to 'source/blender/editors/space_graph')
-rw-r--r-- | source/blender/editors/space_graph/CMakeLists.txt | 3 | ||||
-rw-r--r-- | source/blender/editors/space_graph/graph_buttons.c | 313 | ||||
-rw-r--r-- | source/blender/editors/space_graph/graph_draw.c | 646 | ||||
-rw-r--r-- | source/blender/editors/space_graph/graph_edit.c | 12 | ||||
-rw-r--r-- | source/blender/editors/space_graph/graph_ops.c | 3 | ||||
-rw-r--r-- | source/blender/editors/space_graph/graph_utils.c | 45 | ||||
-rw-r--r-- | source/blender/editors/space_graph/space_graph.c | 214 |
7 files changed, 806 insertions, 430 deletions
diff --git a/source/blender/editors/space_graph/CMakeLists.txt b/source/blender/editors/space_graph/CMakeLists.txt index 40a196fa95b..2840324e65e 100644 --- a/source/blender/editors/space_graph/CMakeLists.txt +++ b/source/blender/editors/space_graph/CMakeLists.txt @@ -23,6 +23,7 @@ set(INC ../../blenkernel ../../blenlib ../../blentranslation + ../../depsgraph ../../gpu ../../makesdna ../../makesrna @@ -48,7 +49,7 @@ set(SRC ) if(WITH_AUDASPACE) - add_definitions(${AUDASPACE_DEFINITIONS}) + add_definitions(-DWITH_AUDASPACE) list(APPEND INC_SYS ${AUDASPACE_C_INCLUDE_DIRS} diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index cac379f3786..2a0d5baa5c3 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -48,13 +48,13 @@ #include "BKE_context.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_main.h" #include "BKE_global.h" #include "BKE_screen.h" #include "BKE_unit.h" +#include "DEG_depsgraph_build.h" #include "WM_api.h" #include "WM_types.h" @@ -154,17 +154,12 @@ static void graph_panel_properties(const bContext *C, Panel *pa) PointerRNA fcu_ptr; uiLayout *layout = pa->layout; uiLayout *col, *row, *sub; - // uiBlock *block; // UNUSED char name[256]; int icon = 0; if (!graph_panel_context(C, &ale, &fcu)) return; - // UNUSED - // block = uiLayoutGetBlock(layout); - // UI_block_func_handle_set(block, do_graph_region_buttons, NULL); - /* F-Curve pointer */ RNA_pointer_create(ale->id, &RNA_FCurve, fcu, &fcu_ptr); @@ -472,7 +467,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *pa) #define B_IPO_DEPCHANGE 10 -static void do_graph_region_driver_buttons(bContext *C, void *UNUSED(arg), int event) +static void do_graph_region_driver_buttons(bContext *C, void *fcu_v, int event) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); @@ -480,8 +475,18 @@ static void do_graph_region_driver_buttons(bContext *C, void *UNUSED(arg), int e switch (event) { case B_IPO_DEPCHANGE: { + /* force F-Curve & Driver to get re-evaluated (same as the old Update Dependencies) */ + FCurve *fcu = (FCurve *)fcu_v; + ChannelDriver *driver = (fcu) ? fcu->driver : NULL; + + /* clear invalid flags */ + if (fcu) { + fcu->flag &= ~FCURVE_DISABLED; + driver->flag &= ~DRIVER_FLAG_INVALID; + } + /* rebuild depsgraph for the new deps */ - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); break; } } @@ -490,23 +495,6 @@ static void do_graph_region_driver_buttons(bContext *C, void *UNUSED(arg), int e WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); // XXX could use better notifier } -/* callback to remove the active driver */ -static void driver_remove_cb(bContext *C, void *ale_v, void *UNUSED(arg)) -{ - bAnimListElem *ale = (bAnimListElem *)ale_v; - ID *id = ale->id; - FCurve *fcu = ale->data; - ReportList *reports = CTX_wm_reports(C); - - /* try to get F-Curve that driver lives on, and ID block which has this AnimData */ - if (ELEM(NULL, id, fcu)) - return; - - /* call API method to remove this driver */ - ANIM_remove_driver(reports, id, fcu->rna_path, fcu->array_index, 0); - ED_undo_push(C, "Remove Driver"); -} - /* callback to add a target variable to the active driver */ static void driver_add_var_cb(bContext *C, void *driver_v, void *UNUSED(arg)) { @@ -728,60 +716,91 @@ static void graph_panel_driverVar__transChan(uiLayout *layout, ID *id, DriverVar uiItemR(sub, &dtar_ptr, "transform_space", 0, IFACE_("Space"), ICON_NONE); } -/* driver settings for active F-Curve (only for 'Drivers' mode) */ -static void graph_panel_drivers(const bContext *C, Panel *pa) +/* ----------------------------------------------------------------- */ + + +/* property driven by the driver - duplicates Active FCurve, but useful for clarity */ +static void graph_draw_driven_property_panel(uiLayout *layout, ID *id, FCurve *fcu) { - bAnimListElem *ale; - FCurve *fcu; - ChannelDriver *driver; + PointerRNA fcu_ptr; + uiLayout *row; + char name[256]; + int icon = 0; + + /* F-Curve pointer */ + RNA_pointer_create(id, &RNA_FCurve, fcu, &fcu_ptr); + + /* get user-friendly 'name' for F-Curve */ + icon = getname_anim_fcurve(name, id, fcu); + + /* panel layout... */ + row = uiLayoutRow(layout, true); + uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT); + + /* -> user friendly 'name' for datablock that owns F-Curve */ + /* XXX: Actually, we may need the datablock icons only... (e.g. right now will show bone for bone props) */ + uiItemL(row, id->name + 2, icon); + + /* -> user friendly 'name' for F-Curve/driver target */ + uiItemL(row, "", VICO_SMALL_TRI_RIGHT_VEC); + uiItemL(row, name, ICON_RNA); +} + +/* UI properties panel layout for driver settings - shared for Drivers Editor and for */ +static void graph_draw_driver_settings_panel(uiLayout *layout, ID *id, FCurve *fcu, const bool is_popover) +{ + ChannelDriver *driver = fcu->driver; DriverVar *dvar; PointerRNA driver_ptr; - uiLayout *col; + uiLayout *col, *row; uiBlock *block; uiBut *but; - /* Get settings from context */ - if (!graph_panel_context(C, &ale, &fcu)) - return; - driver = fcu->driver; - /* set event handler for panel */ - block = uiLayoutGetBlock(pa->layout); // xxx? + block = uiLayoutGetBlock(layout); UI_block_func_handle_set(block, do_graph_region_driver_buttons, NULL); - /* general actions - management */ - col = uiLayoutColumn(pa->layout, false); - block = uiLayoutGetBlock(col); - but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_FILE_REFRESH, IFACE_("Update Dependencies"), - 0, 0, 10 * UI_UNIT_X, UI_UNIT_Y, - NULL, 0.0, 0.0, 0, 0, - TIP_("Force updates of dependencies")); - UI_but_func_set(but, driver_update_flags_cb, fcu, NULL); - - but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ZOOMOUT, IFACE_("Remove Driver"), - 0, 0, 10 * UI_UNIT_X, UI_UNIT_Y, - NULL, 0.0, 0.0, 0, 0, - TIP_("Remove this driver")); - UI_but_funcN_set(but, driver_remove_cb, MEM_dupallocN(ale), NULL); - /* driver-level settings - type, expressions, and errors */ - RNA_pointer_create(ale->id, &RNA_Driver, driver, &driver_ptr); + RNA_pointer_create(id, &RNA_Driver, driver, &driver_ptr); - col = uiLayoutColumn(pa->layout, true); + col = uiLayoutColumn(layout, true); block = uiLayoutGetBlock(col); uiItemR(col, &driver_ptr, "type", 0, NULL, ICON_NONE); + { + char valBuf[32]; + + /* value of driver */ + row = uiLayoutRow(col, true); + uiItemL(row, IFACE_("Driver Value:"), ICON_NONE); + BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", driver->curval); + uiItemL(row, valBuf, ICON_NONE); + } + + uiItemS(layout); + uiItemS(layout); + /* show expression box if doing scripted drivers, and/or error messages when invalid drivers exist */ if (driver->type == DRIVER_TYPE_PYTHON) { bool bpy_data_expr_error = (strstr(driver->expression, "bpy.data.") != NULL); bool bpy_ctx_expr_error = (strstr(driver->expression, "bpy.context.") != NULL); /* expression */ - uiItemR(col, &driver_ptr, "expression", 0, IFACE_("Expr"), ICON_NONE); + /* TODO: "Show syntax hints" button */ + col = uiLayoutColumn(layout, true); + block = uiLayoutGetBlock(col); + + uiItemL(col, IFACE_("Expression:"), ICON_NONE); + uiItemR(col, &driver_ptr, "expression", 0, "", ICON_NONE); + uiItemR(col, &driver_ptr, "use_self", 0, NULL, ICON_NONE); /* errors? */ + col = uiLayoutColumn(layout, true); + block = uiLayoutGetBlock(col); + if ((G.f & G_SCRIPT_AUTOEXEC) == 0) { + /* TODO: Add button to enable? */ uiItemL(col, IFACE_("WARNING: Python expressions limited for security"), ICON_ERROR); } else if (driver->flag & DRIVER_FLAG_INVALID) { @@ -803,6 +822,9 @@ static void graph_panel_drivers(const bContext *C, Panel *pa) } else { /* errors? */ + col = uiLayoutColumn(layout, true); + block = uiLayoutGetBlock(col); + if (driver->flag & DRIVER_FLAG_INVALID) uiItemL(col, IFACE_("ERROR: Invalid target channel(s)"), ICON_ERROR); @@ -822,37 +844,31 @@ static void graph_panel_drivers(const bContext *C, Panel *pa) } } - col = uiLayoutColumn(pa->layout, true); - - if (driver->type == DRIVER_TYPE_PYTHON) { - uiItemR(col, &driver_ptr, "use_self", 0, NULL, ICON_NONE); - } - - /* debug setting */ - uiItemR(col, &driver_ptr, "show_debug_info", 0, NULL, ICON_NONE); - - /* value of driver */ - if (driver->flag & DRIVER_FLAG_SHOWDEBUG) { - uiLayout *row = uiLayoutRow(col, true); - char valBuf[32]; - - uiItemL(row, IFACE_("Driver Value:"), ICON_NONE); - - BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", driver->curval); - uiItemL(row, valBuf, ICON_NONE); - } + uiItemS(layout); /* add/copy/paste driver variables */ - { - uiLayout *row; + if (is_popover) { + /* add driver variable - add blank */ + row = uiLayoutRow(layout, true); + block = uiLayoutGetBlock(row); + but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ZOOMIN, IFACE_("Add Input Variable"), + 0, 0, 10 * UI_UNIT_X, UI_UNIT_Y, + NULL, 0.0, 0.0, 0, 0, + TIP_("Add a Driver Variable to keep track an input used by the driver")); + UI_but_func_set(but, driver_add_var_cb, driver, NULL); + /* add driver variable - add using eyedropper */ + /* XXX: will this operator work like this? */ + uiItemO(row, "", ICON_EYEDROPPER, "UI_OT_eyedropper_driver"); + } + else { /* add driver variable */ - row = uiLayoutRow(pa->layout, false); + row = uiLayoutRow(layout, false); block = uiLayoutGetBlock(row); - but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ZOOMIN, IFACE_("Add Variable"), - 0, 0, 10 * UI_UNIT_X, UI_UNIT_Y, - NULL, 0.0, 0.0, 0, 0, - TIP_("Driver variables ensure that all dependencies will be accounted for and that drivers will update correctly")); + but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ZOOMIN, IFACE_("Add Input Variable"), + 0, 0, 10 * UI_UNIT_X, UI_UNIT_Y, + NULL, 0.0, 0.0, 0, 0, + TIP_("Driver variables ensure that all dependencies will be accounted for, eusuring that drivers will update correctly")); UI_but_func_set(but, driver_add_var_cb, driver, NULL); /* copy/paste (as sub-row) */ @@ -866,15 +882,15 @@ static void graph_panel_drivers(const bContext *C, Panel *pa) /* loop over targets, drawing them */ for (dvar = driver->variables.first; dvar; dvar = dvar->next) { PointerRNA dvar_ptr; - uiLayout *box, *row; + uiLayout *box; uiLayout *subrow, *sub; /* sub-layout column for this variable's settings */ - col = uiLayoutColumn(pa->layout, true); + col = uiLayoutColumn(layout, true); /* 1) header panel */ box = uiLayoutBox(col); - RNA_pointer_create(ale->id, &RNA_DriverVariable, dvar, &dvar_ptr); + RNA_pointer_create(id, &RNA_DriverVariable, dvar, &dvar_ptr); row = uiLayoutRow(box, false); block = uiLayoutGetBlock(row); @@ -915,21 +931,21 @@ static void graph_panel_drivers(const bContext *C, Panel *pa) /* controls to draw depends on the type of variable */ switch (dvar->type) { case DVAR_TYPE_SINGLE_PROP: /* single property */ - graph_panel_driverVar__singleProp(box, ale->id, dvar); + graph_panel_driverVar__singleProp(box, id, dvar); break; case DVAR_TYPE_ROT_DIFF: /* rotational difference */ - graph_panel_driverVar__rotDiff(box, ale->id, dvar); + graph_panel_driverVar__rotDiff(box, id, dvar); break; case DVAR_TYPE_LOC_DIFF: /* location difference */ - graph_panel_driverVar__locDiff(box, ale->id, dvar); + graph_panel_driverVar__locDiff(box, id, dvar); break; case DVAR_TYPE_TRANSFORM_CHAN: /* transform channel */ - graph_panel_driverVar__transChan(box, ale->id, dvar); + graph_panel_driverVar__transChan(box, id, dvar); break; } /* 3) value of variable */ - if (driver->flag & DRIVER_FLAG_SHOWDEBUG) { + { char valBuf[32]; box = uiLayoutBox(col); @@ -951,10 +967,108 @@ static void graph_panel_drivers(const bContext *C, Panel *pa) } } + uiItemS(layout); + uiItemS(layout); + + /* XXX: This should become redundant. But sometimes the flushing fails, so keep this around for a while longer as a "last resort" */ + row = uiLayoutRow(layout, true); + block = uiLayoutGetBlock(row); + but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_FILE_REFRESH, IFACE_("Update Dependencies"), + 0, 0, 10 * UI_UNIT_X, UI_UNIT_Y, + NULL, 0.0, 0.0, 0, 0, + TIP_("Force updates of dependencies - Only use this if drivers are not updating correctly")); + UI_but_func_set(but, driver_update_flags_cb, fcu, NULL); +} + +/* ----------------------------------------------------------------- */ + + +/* panel to show property driven by the driver (in Drivers Editor) - duplicates Active FCurve, but useful for clarity */ +static void graph_panel_driven_property(const bContext *C, Panel *pa) +{ + bAnimListElem *ale; + FCurve *fcu; + + if (!graph_panel_context(C, &ale, &fcu)) + return; + + graph_draw_driven_property_panel(pa->layout, ale->id, fcu); + + MEM_freeN(ale); +} + +/* driver settings for active F-Curve (only for 'Drivers' mode in Graph Editor, i.e. the full "Drivers Editor") */ +static void graph_panel_drivers(const bContext *C, Panel *pa) +{ + bAnimListElem *ale; + FCurve *fcu; + + /* Get settings from context */ + if (!graph_panel_context(C, &ale, &fcu)) + return; + + graph_draw_driver_settings_panel(pa->layout, ale->id, fcu, false); + /* cleanup */ MEM_freeN(ale); } +/* ----------------------------------------------------------------- */ + +/* poll to make this not show up in the graph editor, as this is only to be used as a popup elsewhere */ +static int graph_panel_drivers_popover_poll(const bContext *C, PanelType *UNUSED(pt)) +{ + return ED_operator_graphedit_active((bContext *)C) == false; +} + +/* popover panel for driver editing anywhere in ui */ +static void graph_panel_drivers_popover(const bContext *C, Panel *pa) +{ + uiLayout *layout = pa->layout; + + PointerRNA ptr = {{NULL}}; + PropertyRNA *prop = NULL; + int index = -1; + uiBut *but = NULL; + + /* Get active property to show driver properties for */ + but = UI_context_active_but_prop_get((bContext *)C, &ptr, &prop, &index); + if (but) { + FCurve *fcu; + bool driven, special; + + fcu = rna_get_fcurve_context_ui((bContext *)C, + &ptr, prop, index, + NULL, NULL, &driven, &special); + + /* Hack: Force all buttons in this panel to be able to know the driver button + * this panel is getting spawned from, so that things like the "Open Drivers Editor" + * button will work. + */ + uiLayoutSetContextFromBut(layout, but); + + /* Populate Panel - With a combination of the contents of the Driven and Driver panels */ + if (fcu) { + ID *id = ptr.id.data; + + /* Driven Property Settings */ + uiItemL(layout, IFACE_("Driven Property:"), ICON_NONE); + graph_draw_driven_property_panel(pa->layout, id, fcu); + /* TODO: All vs Single */ + + uiItemS(layout); + uiItemS(layout); + + /* Drivers Settings */ + uiItemL(layout, IFACE_("Driver Settings:"), ICON_NONE); + graph_draw_driver_settings_panel(pa->layout, id, fcu, true); + } + } + + /* Show drivers editor is always visible */ + uiItemO(layout, IFACE_("Show in Drivers Editor"), ICON_DRIVER, "SCREEN_OT_drivers_editor_show"); +} + /* ******************* F-Modifiers ******************************** */ /* All the drawing code is in editors/animation/fmodifier_ui.c */ @@ -1035,16 +1149,33 @@ void graph_buttons_register(ARegionType *art) pt->poll = graph_panel_poll; BLI_addtail(&art->paneltypes, pt); + pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel drivers driven"); + strcpy(pt->idname, "GRAPH_PT_driven_property"); + strcpy(pt->label, N_("Driven Property")); + strcpy(pt->category, "Drivers"); + strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + pt->draw = graph_panel_driven_property; + pt->poll = graph_panel_drivers_poll; + BLI_addtail(&art->paneltypes, pt); pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel drivers"); strcpy(pt->idname, "GRAPH_PT_drivers"); - strcpy(pt->label, N_("Drivers")); + strcpy(pt->label, N_("Driver")); strcpy(pt->category, "Drivers"); strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); pt->draw = graph_panel_drivers; pt->poll = graph_panel_drivers_poll; BLI_addtail(&art->paneltypes, pt); + pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel drivers pover"); + strcpy(pt->idname, "GRAPH_PT_drivers_popover"); + strcpy(pt->label, N_("Add/Edit Driver")); + strcpy(pt->category, "Drivers"); + strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + pt->draw = graph_panel_drivers_popover; + pt->poll = graph_panel_drivers_popover_poll; + BLI_addtail(&art->paneltypes, pt); + pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel modifiers"); strcpy(pt->idname, "GRAPH_PT_modifiers"); strcpy(pt->label, N_("Modifiers")); @@ -1076,7 +1207,7 @@ static int graph_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op)) void GRAPH_OT_properties(wmOperatorType *ot) { - ot->name = "Properties"; + ot->name = "Toggle Sidebar"; ot->idname = "GRAPH_OT_properties"; ot->description = "Toggle the properties region visibility"; diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index 9a94bb9072b..7c6af0b4c62 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -46,10 +46,12 @@ #include "BKE_curve.h" #include "BKE_fcurve.h" - -#include "BIF_gl.h" #include "BIF_glutil.h" +#include "GPU_draw.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" + #include "ED_anim_api.h" #include "graph_intern.h" @@ -83,37 +85,58 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d) const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur); int i; + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + glLineWidth(1.0f); + + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + + immUniform1i("num_colors", 0); /* Simple dashes. */ + immUniformColor3f(0.0f, 0.0f, 0.0f); + immUniform1f("dash_width", 10.0f); + immUniform1f("dash_factor", 0.5f); + /* draw two black lines showing the standard reference levels */ - glColor3f(0.0f, 0.0f, 0.0f); - glLineWidth(1); - setlinestyle(5); - glBegin(GL_LINES); - glVertex2f(v2d->cur.xmin, env->midval + env->min); - glVertex2f(v2d->cur.xmax, env->midval + env->min); + immBegin(GWN_PRIM_LINES, 4); + immVertex2f(shdr_pos, v2d->cur.xmin, env->midval + env->min); + immVertex2f(shdr_pos, v2d->cur.xmax, env->midval + env->min); - glVertex2f(v2d->cur.xmin, env->midval + env->max); - glVertex2f(v2d->cur.xmax, env->midval + env->max); - glEnd(); - setlinestyle(0); + immVertex2f(shdr_pos, v2d->cur.xmin, env->midval + env->max); + immVertex2f(shdr_pos, v2d->cur.xmax, env->midval + env->max); + immEnd(); - /* set size of vertices (non-adjustable for now) */ - glPointSize(2.0f); + immUnbindProgram(); - /* for now, point color is fixed, and is white */ - glColor3f(1.0f, 1.0f, 1.0f); + if (env->totvert > 0) { + /* set size of vertices (non-adjustable for now) */ + glPointSize(2.0f); - glBegin(GL_POINTS); - for (i = 0, fed = env->data; i < env->totvert; i++, fed++) { - /* only draw if visible - * - min/max here are fixed, not relative - */ - if (IN_RANGE(fed->time, (v2d->cur.xmin - fac), (v2d->cur.xmax + fac))) { - glVertex2f(fed->time, fed->min); - glVertex2f(fed->time, fed->max); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + /* for now, point color is fixed, and is white */ + immUniformColor3f(1.0f, 1.0f, 1.0f); + + immBeginAtMost(GWN_PRIM_POINTS, env->totvert * 2); + + for (i = 0, fed = env->data; i < env->totvert; i++, fed++) { + /* only draw if visible + * - min/max here are fixed, not relative + */ + if (IN_RANGE(fed->time, (v2d->cur.xmin - fac), (v2d->cur.xmax + fac))) { + immVertex2f(shdr_pos, fed->time, fed->min); + immVertex2f(shdr_pos, fed->time, fed->max); + } } + + immEnd(); + + immUnbindProgram(); } - glEnd(); } /* *************************** */ @@ -121,16 +144,37 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d) /* Points ---------------- */ -/* helper func - draw keyframe vertices only for an F-Curve */ -static void draw_fcurve_vertices_keyframes(FCurve *fcu, SpaceIpo *UNUSED(sipo), View2D *v2d, short edit, short sel) +/* helper func - set color to draw F-Curve data with */ +static void set_fcurve_vertex_color(FCurve *fcu, bool sel) +{ + /* Fade the 'intensity' of the vertices based on the selection of the curves too */ + int alphaOffset = (int)((fcurve_display_alpha(fcu) - 1.0f) * 255); + + float color[4]; + + /* Set color of curve vertex based on state of curve (i.e. 'Edit' Mode) */ + if ((fcu->flag & FCURVE_PROTECTED) == 0) { + /* Curve's points ARE BEING edited */ + UI_GetThemeColorShadeAlpha4fv(sel ? TH_VERTEX_SELECT : TH_VERTEX, 0, alphaOffset, color); + } + else { + /* Curve's points CANNOT BE edited */ + UI_GetThemeColorShadeAlpha4fv(sel ? TH_TEXT_HI : TH_TEXT, 0, alphaOffset, color); + } + + immUniformColor4fv(color); +} + +static void draw_fcurve_selected_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, bool sel, unsigned pos) { - BezTriple *bezt = fcu->bezt; const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur); - int i; - glBegin(GL_POINTS); + set_fcurve_vertex_color(fcu, sel); + + immBeginAtMost(GWN_PRIM_POINTS, fcu->totvert); - for (i = 0; i < fcu->totvert; i++, bezt++) { + BezTriple *bezt = fcu->bezt; + for (int i = 0; i < fcu->totvert; i++, bezt++) { /* as an optimization step, only draw those in view * - we apply a correction factor to ensure that points don't pop in/out due to slight twitches of view size */ @@ -141,79 +185,49 @@ static void draw_fcurve_vertices_keyframes(FCurve *fcu, SpaceIpo *UNUSED(sipo), * - */ if ((bezt->f2 & SELECT) == sel) - glVertex3fv(bezt->vec[1]); + immVertex2fv(pos, bezt->vec[1]); } else { /* no check for selection here, as curve is not editable... */ /* XXX perhaps we don't want to even draw points? maybe add an option for that later */ - glVertex3fv(bezt->vec[1]); + immVertex2fv(pos, bezt->vec[1]); } } } - glEnd(); + immEnd(); } - -/* helper func - draw handle vertex for an F-Curve as a round unfilled circle - * NOTE: the caller MUST HAVE GL_LINE_SMOOTH & GL_BLEND ENABLED, otherwise, the controls don't - * have a consistent appearance (due to off-pixel alignments)... - */ -static void draw_fcurve_handle_control(float x, float y, float xscale, float yscale, float hsize) +/* helper func - draw keyframe vertices only for an F-Curve */ +static void draw_fcurve_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, unsigned pos) { - static GLuint displist = 0; - - /* initialize round circle shape */ - if (displist == 0) { - GLUquadricObj *qobj; + immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); + immUniform1f("size", UI_GetThemeValuef(TH_VERTEX_SIZE) * U.pixelsize); - qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); - gluDisk(qobj, 0, 0.7, 8, 1); - gluDeleteQuadric(qobj); + draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, false, pos); + draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, true, pos); - glEndList(); - } - - /* adjust view transform before starting */ - glTranslatef(x, y, 0.0f); - glScalef(1.0f / xscale * hsize, 1.0f / yscale * hsize, 1.0f); - - /* draw! */ - glCallList(displist); - - /* restore view transform */ - glScalef(xscale / hsize, yscale / hsize, 1.0); - glTranslatef(-x, -y, 0.0f); + immUnbindProgram(); } + /* helper func - draw handle vertices only for an F-Curve (if it is not protected) */ -static void draw_fcurve_vertices_handles(FCurve *fcu, SpaceIpo *sipo, View2D *v2d, short sel, short sel_handle_only, float units_scale) +static void draw_fcurve_selected_handle_vertices(FCurve *fcu, View2D *v2d, bool sel, bool sel_handle_only, unsigned pos) { - BezTriple *bezt = fcu->bezt; - BezTriple *prevbezt = NULL; - float hsize, xscale, yscale; - int i; - - /* get view settings */ - hsize = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize; - UI_view2d_scale_get(v2d, &xscale, &yscale); - - /* Compensate OGL scale sued for unit mapping, so circle will be circle, not ellipse */ - yscale *= units_scale; + (void) v2d; /* TODO: use this to draw only points in view */ /* set handle color */ - if (sel) UI_ThemeColor(TH_HANDLE_VERTEX_SELECT); - else UI_ThemeColor(TH_HANDLE_VERTEX); + float hcolor[3]; + UI_GetThemeColor3fv(sel ? TH_HANDLE_VERTEX_SELECT : TH_HANDLE_VERTEX, hcolor); + immUniform4f("outlineColor", hcolor[0], hcolor[1], hcolor[2], 1.0f); + immUniformColor3fvAlpha(hcolor, 0.01f); /* almost invisible - only keep for smoothness */ - /* anti-aliased lines for more consistent appearance */ - if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glEnable(GL_LINE_SMOOTH); - glEnable(GL_BLEND); + immBeginAtMost(GWN_PRIM_POINTS, fcu->totvert * 2); - for (i = 0; i < fcu->totvert; i++, prevbezt = bezt, bezt++) { + BezTriple *bezt = fcu->bezt; + BezTriple *prevbezt = NULL; + for (int i = 0; i < fcu->totvert; i++, prevbezt = bezt, bezt++) { /* Draw the editmode handles for a bezier curve (others don't have handles) * if their selection status matches the selection status we're drawing for * - first handle only if previous beztriple was bezier-mode @@ -225,68 +239,61 @@ static void draw_fcurve_vertices_handles(FCurve *fcu, SpaceIpo *sipo, View2D *v2 if (!sel_handle_only || BEZT_ISSEL_ANY(bezt)) { if ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) { if ((bezt->f1 & SELECT) == sel) /* && v2d->cur.xmin < bezt->vec[0][0] < v2d->cur.xmax)*/ - draw_fcurve_handle_control(bezt->vec[0][0], bezt->vec[0][1], xscale, yscale, hsize); + immVertex2fv(pos, bezt->vec[0]); } if (bezt->ipo == BEZT_IPO_BEZ) { if ((bezt->f3 & SELECT) == sel) /* && v2d->cur.xmin < bezt->vec[2][0] < v2d->cur.xmax)*/ - draw_fcurve_handle_control(bezt->vec[2][0], bezt->vec[2][1], xscale, yscale, hsize); + immVertex2fv(pos, bezt->vec[2]); } } } - if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glDisable(GL_LINE_SMOOTH); - glDisable(GL_BLEND); + immEnd(); } -/* helper func - set color to draw F-Curve data with */ -static void set_fcurve_vertex_color(FCurve *fcu, short sel) +/* helper func - draw handle vertices only for an F-Curve (if it is not protected) */ +static void draw_fcurve_handle_vertices(FCurve *fcu, View2D *v2d, bool sel_handle_only, unsigned pos) { - /* Fade the 'intensity' of the vertices based on the selection of the curves too */ - int alphaOffset = (int)((fcurve_display_alpha(fcu) - 1.0f) * 255); + /* smooth outlines for more consistent appearance */ + immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA); - /* Set color of curve vertex based on state of curve (i.e. 'Edit' Mode) */ - if ((fcu->flag & FCURVE_PROTECTED) == 0) { - /* Curve's points ARE BEING edited */ - if (sel) UI_ThemeColorShadeAlpha(TH_VERTEX_SELECT, 0, alphaOffset); - else UI_ThemeColorShadeAlpha(TH_VERTEX, 0, alphaOffset); - } - else { - /* Curve's points CANNOT BE edited */ - if (sel) UI_ThemeColorShadeAlpha(TH_TEXT_HI, 0, alphaOffset); - else UI_ThemeColorShadeAlpha(TH_TEXT, 0, alphaOffset); - } + /* set handle size */ + immUniform1f("size", (1.4f * UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE)) * U.pixelsize); + immUniform1f("outlineWidth", 1.5f * U.pixelsize); + + draw_fcurve_selected_handle_vertices(fcu, v2d, false, sel_handle_only, pos); + draw_fcurve_selected_handle_vertices(fcu, v2d, true, sel_handle_only, pos); + + immUnbindProgram(); } -static void draw_fcurve_vertices(SpaceIpo *sipo, ARegion *ar, FCurve *fcu, short do_handles, short sel_handle_only, float units_scale) +static void draw_fcurve_vertices(ARegion *ar, FCurve *fcu, bool do_handles, bool sel_handle_only) { View2D *v2d = &ar->v2d; /* only draw points if curve is visible - * - draw unselected points before selected points as separate passes to minimize color-changing overhead - * (XXX dunno if this is faster than drawing all in one pass though) - * and also to make sure in the case of overlapping points that the selected is always visible + * - draw unselected points before selected points as separate passes + * to make sure in the case of overlapping points that the selected is always visible * - draw handles before keyframes, so that keyframes will overlap handles (keyframes are more important for users) */ - glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + glEnable(GL_BLEND); + GPU_enable_program_point_size(); /* draw the two handles first (if they're shown, the curve doesn't have just a single keyframe, and the curve is being edited) */ if (do_handles) { - set_fcurve_vertex_color(fcu, 0); - draw_fcurve_vertices_handles(fcu, sipo, v2d, 0, sel_handle_only, units_scale); - - set_fcurve_vertex_color(fcu, 1); - draw_fcurve_vertices_handles(fcu, sipo, v2d, 1, sel_handle_only, units_scale); + draw_fcurve_handle_vertices(fcu, v2d, sel_handle_only, pos); } /* draw keyframes over the handles */ - set_fcurve_vertex_color(fcu, 0); - draw_fcurve_vertices_keyframes(fcu, sipo, v2d, !(fcu->flag & FCURVE_PROTECTED), 0); + draw_fcurve_keyframe_vertices(fcu, v2d, !(fcu->flag & FCURVE_PROTECTED), pos); - set_fcurve_vertex_color(fcu, 1); - draw_fcurve_vertices_keyframes(fcu, sipo, v2d, !(fcu->flag & FCURVE_PROTECTED), 1); + GPU_disable_program_point_size(); + glDisable(GL_BLEND); } /* Handles ---------------- */ @@ -303,10 +310,10 @@ static bool draw_fcurve_handles_check(SpaceIpo *sipo, FCurve *fcu) (fcu->totvert <= 1) /* do not show handles if there is only 1 keyframe, otherwise they all clump together in an ugly ball */ ) { - return 0; + return false; } else { - return 1; + return true; } } @@ -316,11 +323,12 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu) { int sel, b; - /* a single call to GL_LINES here around these calls should be sufficient to still - * get separate line segments, but which aren't wrapped with GL_LINE_STRIP every time we - * want a single line - */ - glBegin(GL_LINES); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + + immBeginAtMost(GWN_PRIM_LINES, 4 * 2 * fcu->totvert); /* slightly hacky, but we want to draw unselected points before selected ones * so that selected points are clearly visible @@ -348,18 +356,20 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu) if ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) { UI_GetThemeColor3ubv(basecol + bezt->h1, col); col[3] = fcurve_display_alpha(fcu) * 255; - glColor4ubv((GLubyte *)col); - - glVertex2fv(fp); glVertex2fv(fp + 3); + immAttrib4ubv(color, col); + immVertex2fv(pos, fp); + immAttrib4ubv(color, col); + immVertex2fv(pos, fp + 3); } /* only draw second handle if this segment is bezier */ if (bezt->ipo == BEZT_IPO_BEZ) { UI_GetThemeColor3ubv(basecol + bezt->h2, col); col[3] = fcurve_display_alpha(fcu) * 255; - glColor4ubv((GLubyte *)col); - - glVertex2fv(fp + 3); glVertex2fv(fp + 6); + immAttrib4ubv(color, col); + immVertex2fv(pos, fp + 3); + immAttrib4ubv(color, col); + immVertex2fv(pos, fp + 6); } } else { @@ -370,9 +380,10 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu) fp = bezt->vec[0]; UI_GetThemeColor3ubv(basecol + bezt->h1, col); col[3] = fcurve_display_alpha(fcu) * 255; - glColor4ubv((GLubyte *)col); - - glVertex2fv(fp); glVertex2fv(fp + 3); + immAttrib4ubv(color, col); + immVertex2fv(pos, fp); + immAttrib4ubv(color, col); + immVertex2fv(pos, fp + 3); } /* only draw second handle if this segment is bezier, and selection is ok */ @@ -382,15 +393,17 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu) fp = bezt->vec[1]; UI_GetThemeColor3ubv(basecol + bezt->h2, col); col[3] = fcurve_display_alpha(fcu) * 255; - glColor4ubv((GLubyte *)col); - - glVertex2fv(fp); glVertex2fv(fp + 3); + immAttrib4ubv(color, col); + immVertex2fv(pos, fp); + immAttrib4ubv(color, col); + immVertex2fv(pos, fp + 3); } } } } - glEnd(); /* GL_LINES */ + immEnd(); + immUnbindProgram(); } /* Samples ---------------- */ @@ -399,36 +412,24 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu) * NOTE: the caller MUST HAVE GL_LINE_SMOOTH & GL_BLEND ENABLED, otherwise, the controls don't * have a consistent appearance (due to off-pixel alignments)... */ -static void draw_fcurve_sample_control(float x, float y, float xscale, float yscale, float hsize) +static void draw_fcurve_sample_control(float x, float y, float xscale, float yscale, float hsize, unsigned int pos) { - static GLuint displist = 0; - - /* initialize X shape */ - if (displist == 0) { - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - - glBegin(GL_LINES); - glVertex2f(-0.7f, -0.7f); - glVertex2f(+0.7f, +0.7f); - - glVertex2f(-0.7f, +0.7f); - glVertex2f(+0.7f, -0.7f); - glEnd(); /* GL_LINES */ - - glEndList(); - } - /* adjust view transform before starting */ - glTranslatef(x, y, 0.0f); - glScalef(1.0f / xscale * hsize, 1.0f / yscale * hsize, 1.0f); + gpuPushMatrix(); + gpuTranslate2f(x, y); + gpuScale2f(1.0f / xscale * hsize, 1.0f / yscale * hsize); - /* draw! */ - glCallList(displist); + /* draw X shape */ + immBegin(GWN_PRIM_LINES, 4); + immVertex2f(pos, -0.7f, -0.7f); + immVertex2f(pos, +0.7f, +0.7f); + + immVertex2f(pos, -0.7f, +0.7f); + immVertex2f(pos, +0.7f, -0.7f); + immEnd(); /* restore view transform */ - glScalef(xscale / hsize, yscale / hsize, 1.0); - glTranslatef(-x, -y, 0.0f); + gpuPopMatrix(); } /* helper func - draw keyframe vertices only for an F-Curve */ @@ -441,10 +442,6 @@ static void draw_fcurve_samples(SpaceIpo *sipo, ARegion *ar, FCurve *fcu) hsize = UI_GetThemeValuef(TH_VERTEX_SIZE); UI_view2d_scale_get(&ar->v2d, &xscale, &yscale); - /* set vertex color */ - if (fcu->flag & (FCURVE_ACTIVE | FCURVE_SELECTED)) UI_ThemeColor(TH_TEXT_HI); - else UI_ThemeColor(TH_TEXT); - /* get verts */ first = fcu->fpt; last = (first) ? (first + (fcu->totvert - 1)) : (NULL); @@ -455,8 +452,15 @@ static void draw_fcurve_samples(SpaceIpo *sipo, ARegion *ar, FCurve *fcu) if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); - draw_fcurve_sample_control(first->vec[0], first->vec[1], xscale, yscale, hsize); - draw_fcurve_sample_control(last->vec[0], last->vec[1], xscale, yscale, hsize); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformThemeColor((fcu->flag & FCURVE_SELECTED) ? TH_TEXT_HI : TH_TEXT); + + draw_fcurve_sample_control(first->vec[0], first->vec[1], xscale, yscale, hsize, pos); + draw_fcurve_sample_control(last->vec[0], last->vec[1], xscale, yscale, hsize, pos); + + immUnbindProgram(); glDisable(GL_BLEND); if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glDisable(GL_LINE_SMOOTH); @@ -466,7 +470,7 @@ static void draw_fcurve_samples(SpaceIpo *sipo, ARegion *ar, FCurve *fcu) /* Curve ---------------- */ /* helper func - just draw the F-Curve by sampling the visible region (for drawing curves with modifiers) */ -static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, View2DGrid *grid) +static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, View2DGrid *grid, unsigned int pos) { SpaceIpo *sipo = (SpaceIpo *)ac->sl; ChannelDriver *driver; @@ -536,37 +540,50 @@ static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d * - apply the unit correction factor to the calculated values so that * the displayed values appear correctly in the viewport */ - glBegin(GL_LINE_STRIP); n = (etime - stime) / samplefreq + 0.5f; - for (i = 0; i <= n; i++) { - float ctime = stime + i * samplefreq; - glVertex2f(ctime, (evaluate_fcurve(fcu, ctime) + offset) * unitFac); - } - glEnd(); + if (n > 0) { + immBegin(GWN_PRIM_LINE_STRIP, (n + 1)); + + for (i = 0; i <= n; i++) { + float ctime = stime + i * samplefreq; + immVertex2f(pos, ctime, (evaluate_fcurve(fcu, ctime) + offset) * unitFac); + } + + immEnd(); + } /* restore driver */ fcu->driver = driver; } /* helper func - draw a samples-based F-Curve */ -static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d) +static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, const uint shdr_pos) { FPoint *prevfpt = fcu->fpt; FPoint *fpt = prevfpt + 1; float fac, v[2]; - int b = fcu->totvert - 1; + int b = fcu->totvert; float unit_scale, offset; short mapping_flag = ANIM_get_normalization_flags(ac); + int count = fcu->totvert; + + if (prevfpt->vec[0] > v2d->cur.xmin) { + count++; + } + + if ((prevfpt + b - 1)->vec[0] < v2d->cur.xmax) { + count++; + } /* apply unit mapping */ - glPushMatrix(); + gpuPushMatrix(); unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset); - glScalef(1.0f, unit_scale, 1.0f); - glTranslatef(0.0f, offset, 0.0f); + gpuScale2f(1.0f, unit_scale); + gpuTranslate2f(0.0f, offset); - glBegin(GL_LINE_STRIP); + immBegin(GWN_PRIM_LINE_STRIP, count); /* extrapolate to left? - left-side of view comes before first keyframe? */ if (prevfpt->vec[0] > v2d->cur.xmin) { @@ -584,26 +601,19 @@ static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, Vie v[1] = prevfpt->vec[1] - fac * (prevfpt->vec[1] - fpt->vec[1]); } - glVertex2fv(v); + immVertex2fv(shdr_pos, v); } - /* if only one sample, add it now */ - if (fcu->totvert == 1) - glVertex2fv(prevfpt->vec); - /* loop over samples, drawing segments */ /* draw curve between first and last keyframe (if there are enough to do so) */ while (b--) { /* Linear interpolation: just add one point (which should add a new line segment) */ - glVertex2fv(prevfpt->vec); + immVertex2fv(shdr_pos, prevfpt->vec); /* get next pointers */ - prevfpt = fpt; - fpt++; - - /* last point? */ - if (b == 0) - glVertex2fv(prevfpt->vec); + if (b > 0) { + prevfpt++; + } } /* extrapolate to right? (see code for left-extrapolation above too) */ @@ -623,11 +633,12 @@ static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, Vie v[1] = prevfpt->vec[1] - fac * (prevfpt->vec[1] - fpt->vec[1]); } - glVertex2fv(v); + immVertex2fv(shdr_pos, v); } - glEnd(); - glPopMatrix(); + immEnd(); + + gpuPopMatrix(); } /* helper func - check if the F-Curve only contains easily drawable segments @@ -648,7 +659,7 @@ static bool fcurve_can_use_simple_bezt_drawing(FCurve *fcu) } /* helper func - draw one repeat of an F-Curve (using Bezier curve approximations) */ -static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d) +static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, unsigned int pos) { BezTriple *prevbezt = fcu->bezt; BezTriple *bezt = prevbezt + 1; @@ -661,12 +672,15 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2 short mapping_flag = ANIM_get_normalization_flags(ac); /* apply unit mapping */ - glPushMatrix(); + gpuPushMatrix(); unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset); - glScalef(1.0f, unit_scale, 1.0f); - glTranslatef(0.0f, offset, 0.0f); + gpuScale2f(1.0f, unit_scale); + gpuTranslate2f(0.0f, offset); - glBegin(GL_LINE_STRIP); + /* For now, this assumes the worst case scenario, where all the keyframes have + * bezier interpolation, and are drawn at full res. + * This is tricky to optimize, but maybe can be improved at some point... */ + immBeginAtMost(GWN_PRIM_LINE_STRIP, (b * 32 + 3)); /* extrapolate to left? */ if (prevbezt->vec[1][0] > v2d->cur.xmin) { @@ -691,14 +705,14 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2 v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[0][1] - prevbezt->vec[1][1]); } - glVertex2fv(v1); + immVertex2fv(pos, v1); } /* if only one keyframe, add it now */ if (fcu->totvert == 1) { v1[0] = prevbezt->vec[1][0]; v1[1] = prevbezt->vec[1][1]; - glVertex2fv(v1); + immVertex2fv(pos, v1); } /* draw curve between first and last keyframe (if there are enough to do so) */ @@ -708,17 +722,17 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2 /* Constant-Interpolation: draw segment between previous keyframe and next, but holding same value */ v1[0] = prevbezt->vec[1][0]; v1[1] = prevbezt->vec[1][1]; - glVertex2fv(v1); + immVertex2fv(pos, v1); v1[0] = bezt->vec[1][0]; v1[1] = prevbezt->vec[1][1]; - glVertex2fv(v1); + immVertex2fv(pos, v1); } else if (prevbezt->ipo == BEZT_IPO_LIN) { /* Linear interpolation: just add one point (which should add a new line segment) */ v1[0] = prevbezt->vec[1][0]; v1[1] = prevbezt->vec[1][1]; - glVertex2fv(v1); + immVertex2fv(pos, v1); } else if (prevbezt->ipo == BEZT_IPO_BEZ) { /* Bezier-Interpolation: draw curve as series of segments between keyframes @@ -738,7 +752,7 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2 /* only draw one */ v1[0] = prevbezt->vec[1][0]; v1[1] = prevbezt->vec[1][1]; - glVertex2fv(v1); + immVertex2fv(pos, v1); } else { /* clamp resolution to max of 32 */ @@ -760,8 +774,9 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2 BKE_curve_forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, sizeof(float) * 3); BKE_curve_forward_diff_bezier(v1[1], v2[1], v3[1], v4[1], data + 1, resol, sizeof(float) * 3); - for (fp = data; resol; resol--, fp += 3) - glVertex2fv(fp); + for (fp = data; resol; resol--, fp += 3) { + immVertex2fv(pos, fp); + } } } @@ -773,7 +788,7 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2 if (b == 0) { v1[0] = prevbezt->vec[1][0]; v1[1] = prevbezt->vec[1][1]; - glVertex2fv(v1); + immVertex2fv(pos, v1); } } @@ -800,11 +815,12 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2 v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[2][1] - prevbezt->vec[1][1]); } - glVertex2fv(v1); + immVertex2fv(pos, v1); } - glEnd(); - glPopMatrix(); + immEnd(); + + gpuPopMatrix(); } /* Debugging -------------------------------- */ @@ -826,6 +842,15 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu) //if ((driver->flag & DRIVER_FLAG_SHOWDEBUG) == 0) // return; + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + + immUniform1i("num_colors", 0); /* Simple dashes. */ + /* No curve to modify/visualize the result? * => We still want to show the 1-1 default... */ @@ -833,26 +858,24 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu) float t; /* draw with thin dotted lines in style of what curve would have been */ - glColor3fv(fcu->color); + immUniformColor3fv(fcu->color); - setlinestyle(20); + immUniform1f("dash_width", 40.0f); + immUniform1f("dash_factor", 0.5f); glLineWidth(2.0f); /* draw 1-1 line, stretching just past the screen limits * NOTE: we need to scale the y-values to be valid for the units */ - glBegin(GL_LINES); - { - t = v2d->cur.xmin; - glVertex2f(t, (t + offset) * unitfac); + immBegin(GWN_PRIM_LINES, 2); - t = v2d->cur.xmax; - glVertex2f(t, (t + offset) * unitfac); - } - glEnd(); + t = v2d->cur.xmin; + immVertex2f(shdr_pos, t, (t + offset) * unitfac); - /* cleanup line drawing */ - setlinestyle(0); + t = v2d->cur.xmax; + immVertex2f(shdr_pos, t, (t + offset) * unitfac); + + immEnd(); } /* draw driver only if actually functional */ @@ -866,53 +889,59 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu) float co[2]; /* draw dotted lines leading towards this point from both axes ....... */ - glColor3f(0.9f, 0.9f, 0.9f); - setlinestyle(5); + immUniformColor3f(0.9f, 0.9f, 0.9f); + immUniform1f("dash_width", 10.0f); + immUniform1f("dash_factor", 0.5f); - glBegin(GL_LINES); - { - /* x-axis lookup */ - co[0] = x; + immBegin(GWN_PRIM_LINES, (y >= v2d->cur.ymin) ? 4 : 2); - if (y >= v2d->cur.ymin) { - co[1] = v2d->cur.ymin - 1.0f; - glVertex2fv(co); + /* x-axis lookup */ + co[0] = x; - co[1] = y; - glVertex2fv(co); - } + if (y >= v2d->cur.ymin) { + co[1] = v2d->cur.ymin - 1.0f; + immVertex2fv(shdr_pos, co); - /* y-axis lookup */ co[1] = y; + immVertex2fv(shdr_pos, co); + } - co[0] = v2d->cur.xmin - 1.0f; - glVertex2fv(co); + /* y-axis lookup */ + co[1] = y; - co[0] = x; - glVertex2fv(co); - } - glEnd(); + co[0] = v2d->cur.xmin - 1.0f; + immVertex2fv(shdr_pos, co); + + co[0] = x; + immVertex2fv(shdr_pos, co); + + immEnd(); - setlinestyle(0); + immUnbindProgram(); + + /* GWN_PRIM_POINTS do not survive dashed line geometry shader... */ + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); /* x marks the spot .................................................... */ /* -> outer frame */ - glColor3f(0.9f, 0.9f, 0.9f); + immUniformColor3f(0.9f, 0.9f, 0.9f); glPointSize(7.0); - glBegin(GL_POINTS); - glVertex2f(x, y); - glEnd(); + immBegin(GWN_PRIM_POINTS, 1); + immVertex2f(shdr_pos, x, y); + immEnd(); /* inner frame */ - glColor3f(0.9f, 0.0f, 0.0f); + immUniformColor3f(0.9f, 0.0f, 0.0f); glPointSize(3.0); - glBegin(GL_POINTS); - glVertex2f(x, y); - glEnd(); + immBegin(GWN_PRIM_POINTS, 1); + immVertex2f(shdr_pos, x, y); + immEnd(); } } + + immUnbindProgram(); } /* Public Curve-Drawing API ---------------- */ @@ -925,29 +954,43 @@ void graph_draw_ghost_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar) FCurve *fcu; /* draw with thick dotted lines */ - setlinestyle(10); glLineWidth(3.0f); /* anti-aliased lines for less jagged appearance */ - if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glEnable(GL_LINE_SMOOTH); + if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) { + glEnable(GL_LINE_SMOOTH); + } glEnable(GL_BLEND); + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + + immUniform1i("num_colors", 0); /* Simple dashes. */ + immUniform1f("dash_width", 20.0f); + immUniform1f("dash_factor", 0.5f); + /* the ghost curves are simply sampled F-Curves stored in sipo->ghostCurves */ for (fcu = sipo->ghostCurves.first; fcu; fcu = fcu->next) { /* set whatever color the curve has set * - this is set by the function which creates these * - draw with a fixed opacity of 2 */ - glColor4f(fcu->color[0], fcu->color[1], fcu->color[2], 0.5f); + immUniformColor3fvAlpha(fcu->color, 0.5f); /* simply draw the stored samples */ - draw_fcurve_curve_samples(ac, NULL, fcu, &ar->v2d); + draw_fcurve_curve_samples(ac, NULL, fcu, &ar->v2d, shdr_pos); } - /* restore settings */ - setlinestyle(0); + immUnbindProgram(); - if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glDisable(GL_LINE_SMOOTH); + if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) { + glDisable(GL_LINE_SMOOTH); + } glDisable(GL_BLEND); } @@ -975,8 +1018,9 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid AnimData *adt = ANIM_nla_mapping_get(ac, ale); /* map keyframes for drawing if scaled F-Curve */ - if (adt) + if (adt) { ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0); + } /* draw curve: * - curve line may be result of one or more destructive modifiers or just the raw data, @@ -986,60 +1030,82 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid */ /* 1) draw curve line */ + if (((fcu->modifiers.first) || (fcu->flag & FCURVE_INT_VALUES)) || + (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert))) { /* set color/drawing style for curve itself */ + /* draw active F-Curve thicker than the rest to make it stand out */ + if (fcu->flag & FCURVE_ACTIVE) { + glLineWidth(2.5); + } + else { + glLineWidth(1.0); + } + + /* anti-aliased lines for less jagged appearance */ + if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) { + glEnable(GL_LINE_SMOOTH); + } + glEnable(GL_BLEND); + + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + + immUniform1i("num_colors", 0); /* Simple dashes. */ + if (BKE_fcurve_is_protected(fcu)) { /* protected curves (non editable) are drawn with dotted lines */ - setlinestyle(2); + immUniform1f("dash_width", 4.0f); + immUniform1f("dash_factor", 0.5f); + } + else { + immUniform1f("dash_factor", 2.0f); /* solid line */ } + if (((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) || (fcu->flag & FCURVE_MUTED)) { /* muted curves are drawn in a grayish hue */ /* XXX should we have some variations? */ - UI_ThemeColorShade(TH_HEADER, 50); + immUniformThemeColorShade(TH_HEADER, 50); } else { /* set whatever color the curve has set * - unselected curves draw less opaque to help distinguish the selected ones */ - glColor4f(fcu->color[0], fcu->color[1], fcu->color[2], fcurve_display_alpha(fcu)); - } - - /* draw active F-Curve thicker than the rest to make it stand out */ - if (fcu->flag & FCURVE_ACTIVE) { - glLineWidth(2.0); + immUniformColor3fvAlpha(fcu->color, fcurve_display_alpha(fcu)); } - else { - glLineWidth(1.0); - } - - /* anti-aliased lines for less jagged appearance */ - if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glEnable(GL_LINE_SMOOTH); - glEnable(GL_BLEND); /* draw F-Curve */ if ((fcu->modifiers.first) || (fcu->flag & FCURVE_INT_VALUES)) { /* draw a curve affected by modifiers or only allowed to have integer values * by sampling it at various small-intervals over the visible region */ - draw_fcurve_curve(ac, ale->id, fcu, &ar->v2d, grid); + draw_fcurve_curve(ac, ale->id, fcu, &ar->v2d, grid, shdr_pos); } else if (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert)) { /* just draw curve based on defined data (i.e. no modifiers) */ if (fcu->bezt) { - if (fcurve_can_use_simple_bezt_drawing(fcu)) - draw_fcurve_curve_bezts(ac, ale->id, fcu, &ar->v2d); - else - draw_fcurve_curve(ac, ale->id, fcu, &ar->v2d, grid); + if (fcurve_can_use_simple_bezt_drawing(fcu)) { + draw_fcurve_curve_bezts(ac, ale->id, fcu, &ar->v2d, shdr_pos); + } + else { + draw_fcurve_curve(ac, ale->id, fcu, &ar->v2d, grid, shdr_pos); + } } else if (fcu->fpt) { - draw_fcurve_curve_samples(ac, ale->id, fcu, &ar->v2d); + draw_fcurve_curve_samples(ac, ale->id, fcu, &ar->v2d, shdr_pos); } } - /* restore settings */ - setlinestyle(0); + immUnbindProgram(); - if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glDisable(GL_LINE_SMOOTH); + if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) { + glDisable(GL_LINE_SMOOTH); + } glDisable(GL_BLEND); } @@ -1047,7 +1113,7 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid * - if the option to only show controls if the F-Curve is selected is enabled, we must obey this */ if (!(sipo->flag & SIPO_SELCUVERTSONLY) || (fcu->flag & FCURVE_SELECTED)) { - if (fcurve_are_keyframes_usable(fcu) == 0) { + if (!fcurve_are_keyframes_usable(fcu) && !(fcu->fpt && fcu->totvert)) { /* only draw controls if this is the active modifier */ if ((fcu->flag & FCURVE_ACTIVE) && (fcm)) { switch (fcm->type) { @@ -1063,9 +1129,9 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset); /* apply unit-scaling to all values via OpenGL */ - glPushMatrix(); - glScalef(1.0f, unit_scale, 1.0f); - glTranslatef(0.0f, offset, 0.0f); + gpuPushMatrix(); + gpuScale2f(1.0f, unit_scale); + gpuTranslate2f(0.0f, offset); /* set this once and for all - all handles and handle-verts should use the same thickness */ glLineWidth(1.0); @@ -1080,14 +1146,14 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid glDisable(GL_BLEND); } - draw_fcurve_vertices(sipo, ar, fcu, do_handles, (sipo->flag & SIPO_SELVHANDLESONLY), unit_scale); + draw_fcurve_vertices(ar, fcu, do_handles, (sipo->flag & SIPO_SELVHANDLESONLY)); } else { /* samples: only draw two indicators at either end as indicators */ draw_fcurve_samples(sipo, ar, fcu); } - glPopMatrix(); + gpuPopMatrix(); } } @@ -1163,7 +1229,7 @@ void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar) y = (float)ACHANNEL_FIRST(ac); /* set blending again, as may not be set in previous step */ - 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); for (ale = anim_data.first, i = 0; ale; ale = ale->next, i++) { diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 0b8e89160b7..26a6e93ba57 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -36,7 +36,7 @@ #include <float.h> #ifdef WITH_AUDASPACE -# include AUD_SPECIAL_H +# include <AUD_Special.h> #endif #include "MEM_guardedalloc.h" @@ -55,13 +55,14 @@ #include "BLT_translation.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_nla.h" #include "BKE_report.h" +#include "DEG_depsgraph_build.h" + #include "UI_view2d.h" #include "ED_anim_api.h" @@ -526,6 +527,7 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode) ReportList *reports = ac->reports; SpaceIpo *sipo = (SpaceIpo *)ac->sl; + struct Depsgraph *depsgraph = ac->depsgraph; Scene *scene = ac->scene; ToolSettings *ts = scene->toolsettings; short flag = 0; @@ -608,7 +610,7 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode) * up adding the keyframes on a new F-Curve in the action data instead. */ if (ale->id && !ale->owner && !fcu->driver) { - insert_keyframe(ac->bmain, reports, ale->id, NULL, ((fcu->grp) ? (fcu->grp->name) : (NULL)), + insert_keyframe(ac->bmain, depsgraph, reports, ale->id, NULL, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, ts->keyframe_type, flag); } else { @@ -2716,7 +2718,7 @@ static int graph_driver_vars_paste_exec(bContext *C, wmOperator *op) /* successful or not? */ if (ok) { /* rebuild depsgraph, now that there are extra deps here */ - DAG_relations_tag_update(CTX_data_main(C)); + DEG_relations_tag_update(CTX_data_main(C)); /* set notifier that keyframes have changed */ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, CTX_data_scene(C)); @@ -2790,7 +2792,7 @@ static int graph_driver_delete_invalid_exec(bContext *C, wmOperator *op) if (deleted > 0) { /* notify the world of any changes */ - DAG_relations_tag_update(CTX_data_main(C)); + DEG_relations_tag_update(CTX_data_main(C)); WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL); WM_reportf(RPT_INFO, "Deleted %u drivers", deleted); } diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index b90fdd9ac67..bae5798ca21 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -614,6 +614,8 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) WM_keymap_add_menu(keymap, "GRAPH_MT_delete", XKEY, KM_PRESS, 0, 0); WM_keymap_add_menu(keymap, "GRAPH_MT_delete", DELKEY, KM_PRESS, 0, 0); + WM_keymap_add_menu(keymap, "GRAPH_MT_specials", WKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0); /* insertkey */ @@ -715,4 +717,3 @@ void graphedit_keymap(wmKeyConfig *keyconf) keymap = WM_keymap_find(keyconf, "Graph Editor", SPACE_IPO, 0); graphedit_keymap_keyframes(keyconf, keymap); } - diff --git a/source/blender/editors/space_graph/graph_utils.c b/source/blender/editors/space_graph/graph_utils.c index f55a5511e2d..e543111e662 100644 --- a/source/blender/editors/space_graph/graph_utils.c +++ b/source/blender/editors/space_graph/graph_utils.c @@ -44,17 +44,62 @@ #include "BKE_context.h" #include "BKE_fcurve.h" +#include "BKE_screen.h" #include "WM_api.h" #include "ED_anim_api.h" +#include "ED_screen.h" +#include "UI_interface.h" #include "graph_intern.h" // own include /* ************************************************************** */ +/* Set Up Drivers Editor */ + +/* Set up UI configuration for Drivers Editor */ +/* NOTE: Currently called from windowmanager (new drivers editor window) and RNA (mode switching) */ +void ED_drivers_editor_init(bContext *C, ScrArea *sa) +{ + SpaceIpo *sipo = (SpaceIpo *)sa->spacedata.first; + + /* Set mode */ + sipo->mode = SIPO_MODE_DRIVERS; + + /* Show Properties Region (or else the settings can't be edited) */ + ARegion *ar_props = BKE_area_find_region_type(sa, RGN_TYPE_UI); + if (ar_props) { + UI_panel_category_active_set(ar_props, "Drivers"); + + ar_props->flag &= ~RGN_FLAG_HIDDEN; + /* XXX: Adjust width of this too? */ + + ED_region_visibility_change_update(C, ar_props); + } + else { + printf("%s: Couldn't find properties region for Drivers Editor - %p\n", __func__, sa); + } + + /* Adjust framing in graph region */ + /* TODO: Have a way of not resetting this every time? + * (e.g. So that switching back and forth between editors doesn't keep jumping?) + */ + ARegion *ar_main = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); + if (ar_main) { + /* XXX: Ideally we recenter based on the range instead... */ + ar_main->v2d.tot.xmin = -2.0f; + ar_main->v2d.tot.ymin = -2.0f; + ar_main->v2d.tot.xmax = 2.0f; + ar_main->v2d.tot.ymax = 2.0f; + + ar_main->v2d.cur = ar_main->v2d.tot; + } +} + +/* ************************************************************** */ /* Active F-Curve */ /* Find 'active' F-Curve. It must be editable, since that's the purpose of these buttons (subject to change). diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 383c2b5b220..7c3105843c5 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -53,10 +53,15 @@ #include "ED_anim_api.h" #include "ED_markers.h" -#include "BIF_gl.h" +#include "GPU_immediate.h" #include "WM_api.h" #include "WM_types.h" +#include "WM_message.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" #include "UI_resources.h" #include "UI_view2d.h" @@ -92,9 +97,8 @@ ARegion *graph_has_buttons_region(ScrArea *sa) /* ******************** default callbacks for ipo space ***************** */ -static SpaceLink *graph_new(const bContext *C) +static SpaceLink *graph_new(const ScrArea *UNUSED(sa), const Scene *scene) { - Scene *scene = CTX_data_scene(C); ARegion *ar; SpaceIpo *sipo; @@ -117,7 +121,7 @@ static SpaceLink *graph_new(const bContext *C) BLI_addtail(&sipo->regionbase, ar); ar->regiontype = RGN_TYPE_HEADER; - ar->alignment = RGN_ALIGN_BOTTOM; + ar->alignment = RGN_ALIGN_TOP; /* channels */ ar = MEM_callocN(sizeof(ARegion), "channels region for graphedit"); @@ -179,14 +183,14 @@ static void graph_free(SpaceLink *sl) /* spacetype; init callback */ -static void graph_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa) +static void graph_init(struct wmWindowManager *wm, ScrArea *sa) { SpaceIpo *sipo = (SpaceIpo *)sa->spacedata.first; /* init dopesheet data if non-existent (i.e. for old files) */ if (sipo->ads == NULL) { sipo->ads = MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet"); - sipo->ads->source = (ID *)(G.main->scene.first); // FIXME: this is a really nasty hack here for now... + sipo->ads->source = (ID *)WM_window_get_active_scene(wm->winactive); } /* force immediate init of any invalid F-Curve colors */ @@ -226,12 +230,13 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar) { /* draw entirely, view changes should be handled here */ SpaceIpo *sipo = CTX_wm_space_graph(C); + Scene *scene = CTX_data_scene(C); bAnimContext ac; View2D *v2d = &ar->v2d; View2DGrid *grid; View2DScrollers *scrollers; float col[3]; - short unitx = 0, unity = V2D_UNIT_VALUES, flag = 0; + short unitx = 0, unity = V2D_UNIT_VALUES, cfra_flag = 0; /* clear and setup matrix */ UI_GetThemeColor3fv(TH_BACK, col); @@ -247,6 +252,11 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar) ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW); + /* start and end frame (in F-Curve mode only) */ + if (sipo->mode != SIPO_MODE_DRIVERS) { + ANIM_draw_framerange(scene, v2d); + } + /* draw data */ if (ANIM_animdata_get_context(C, &ac)) { /* draw ghost curves */ @@ -266,46 +276,53 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar) /* only free grid after drawing data, as we need to use it to determine sampling rate */ UI_view2d_grid_free(grid); - /* horizontal component of value-cursor (value line before the current frame line) */ - if ((sipo->flag & SIPO_NODRAWCURSOR) == 0) { + if (((sipo->flag & SIPO_NODRAWCURSOR) == 0) || (sipo->mode == SIPO_MODE_DRIVERS)) { + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - float y = sipo->cursorVal; + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - /* Draw a green line to indicate the cursor value */ - UI_ThemeColorShadeAlpha(TH_CFRAME, -10, -50); - glEnable(GL_BLEND); - glLineWidth(2.0); + /* horizontal component of value-cursor (value line before the current frame line) */ + if ((sipo->flag & SIPO_NODRAWCURSOR) == 0) { + float y = sipo->cursorVal; - glBegin(GL_LINES); - glVertex2f(v2d->cur.xmin, y); - glVertex2f(v2d->cur.xmax, y); - glEnd(); + /* Draw a green line to indicate the cursor value */ + immUniformThemeColorShadeAlpha(TH_CFRAME, -10, -50); + glEnable(GL_BLEND); + glLineWidth(2.0); - glDisable(GL_BLEND); - } + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, v2d->cur.xmin, y); + immVertex2f(pos, v2d->cur.xmax, y); + immEnd(); + + glDisable(GL_BLEND); + } + + /* current frame or vertical component of vertical component of the cursor */ + if (sipo->mode == SIPO_MODE_DRIVERS) { + /* cursor x-value */ + float x = sipo->cursorTime; - /* current frame or vertical component of vertical component of the cursor */ - if (sipo->mode == SIPO_MODE_DRIVERS) { - /* cursor x-value */ - float x = sipo->cursorTime; + /* to help differentiate this from the current frame, draw slightly darker like the horizontal one */ + immUniformThemeColorShadeAlpha(TH_CFRAME, -40, -50); + glEnable(GL_BLEND); + glLineWidth(2.0); - /* to help differentiate this from the current frame, draw slightly darker like the horizontal one */ - UI_ThemeColorShadeAlpha(TH_CFRAME, -40, -50); - glEnable(GL_BLEND); - glLineWidth(2.0); + immBegin(GWN_PRIM_LINES, 2); + immVertex2f(pos, x, v2d->cur.ymin); + immVertex2f(pos, x, v2d->cur.ymax); + immEnd(); - glBegin(GL_LINES); - glVertex2f(x, v2d->cur.ymin); - glVertex2f(x, v2d->cur.ymax); - glEnd(); + glDisable(GL_BLEND); + } - glDisable(GL_BLEND); + immUnbindProgram(); } - else { + + if (sipo->mode != SIPO_MODE_DRIVERS) { /* current frame */ - if (sipo->flag & SIPO_DRAWTIME) flag |= DRAWCFRA_UNIT_SECONDS; - if ((sipo->flag & SIPO_NODRAWCFRANUM) == 0) flag |= DRAWCFRA_SHOW_NUMBOX; - ANIM_draw_cfra(C, v2d, flag); + if (sipo->flag & SIPO_DRAWTIME) cfra_flag |= DRAWCFRA_UNIT_SECONDS; + ANIM_draw_cfra(C, v2d, cfra_flag); } /* markers */ @@ -328,6 +345,12 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar) scrollers = UI_view2d_scrollers_calc(C, v2d, unitx, V2D_GRID_NOCLAMP, unity, V2D_GRID_NOCLAMP); UI_view2d_scrollers_draw(C, v2d, scrollers); UI_view2d_scrollers_free(scrollers); + + /* draw current frame number-indicator on top of scrollers */ + if ((sipo->mode != SIPO_MODE_DRIVERS) && ((sipo->flag & SIPO_NODRAWCFRANUM) == 0)) { + UI_view2d_view_orthoSpecial(ar, v2d, 1); + ANIM_draw_cfra_number(C, v2d, cfra_flag); + } } static void graph_channel_region_init(wmWindowManager *wm, ARegion *ar) @@ -401,10 +424,12 @@ static void graph_buttons_region_init(wmWindowManager *wm, ARegion *ar) static void graph_buttons_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } -static void graph_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void graph_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -416,6 +441,7 @@ static void graph_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), AReg case ND_RENDER_OPTIONS: case ND_OB_ACTIVE: case ND_FRAME: + case ND_FRAME_RANGE: case ND_MARKERS: ED_region_tag_redraw(ar); break; @@ -450,6 +476,11 @@ static void graph_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), AReg if (wmn->action == NA_RENAME) ED_region_tag_redraw(ar); break; + case NC_SCREEN: + if (ELEM(wmn->data, ND_LAYER)) { + ED_region_tag_redraw(ar); + } + break; default: if (wmn->data == ND_KEYS) ED_region_tag_redraw(ar); @@ -458,8 +489,85 @@ static void graph_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), AReg } } +static void graph_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_SpaceGraphEditor, 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__); + } + } + + /* All dopesheet filter settings, etc. affect the drawing of this editor, + * also same applies for all animation-related datatypes that may appear here, + * so just whitelist the entire structs for updates + */ + { + wmMsgParams_RNA msg_key_params = {{{0}}}; + StructRNA *type_array[] = { + &RNA_DopeSheet, /* dopesheet filters */ + + &RNA_ActionGroup, /* channel groups */ + &RNA_FCurve, /* F-Curve */ + &RNA_Keyframe, + &RNA_FCurveSample, + + &RNA_FModifier, /* F-Modifiers (XXX: Why can't we just do all subclasses too?) */ + &RNA_FModifierCycles, + &RNA_FModifierEnvelope, + &RNA_FModifierEnvelopeControlPoint, + &RNA_FModifierFunctionGenerator, + &RNA_FModifierGenerator, + &RNA_FModifierLimits, + &RNA_FModifierNoise, + &RNA_FModifierPython, + &RNA_FModifierStepped, + }; + + for (int i = 0; i < ARRAY_SIZE(type_array); i++) { + msg_key_params.ptr.type = type_array[i]; + WM_msg_subscribe_rna_params( + mbus, + &msg_key_params, + &msg_sub_value_region_tag_redraw, + __func__); + } + } +} + /* editor level listener */ -static void graph_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn) +static void graph_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene), + WorkSpace *UNUSED(workspace)) { SpaceIpo *sipo = (SpaceIpo *)sa->spacedata.first; @@ -685,7 +793,7 @@ static void graph_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID if (sgraph->ads) { if ((ID *)sgraph->ads->filter_grp == old_id) { - sgraph->ads->filter_grp = (Group *)new_id; + sgraph->ads->filter_grp = (Collection *)new_id; } if ((ID *)sgraph->ads->source == old_id) { sgraph->ads->source = new_id; @@ -693,6 +801,24 @@ static void graph_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID } } +static int graph_space_subtype_get(ScrArea *sa) +{ + SpaceIpo *sgraph = sa->spacedata.first; + return sgraph->mode; +} + +static void graph_space_subtype_set(ScrArea *sa, int value) +{ + SpaceIpo *sgraph = sa->spacedata.first; + sgraph->mode = value; +} + +static void graph_space_subtype_item_extend( + bContext *UNUSED(C), EnumPropertyItem **item, int *totitem) +{ + RNA_enum_items_add(item, totitem, rna_enum_space_graph_mode_items); +} + /* only called once, from space/spacetypes.c */ void ED_spacetype_ipo(void) { @@ -711,6 +837,9 @@ void ED_spacetype_ipo(void) st->listener = graph_listener; st->refresh = graph_refresh; st->id_remap = graph_id_remap; + st->space_subtype_item_extend = graph_space_subtype_item_extend; + st->space_subtype_get = graph_space_subtype_get; + st->space_subtype_set = graph_space_subtype_set; /* regions: main window */ art = MEM_callocN(sizeof(ARegionType), "spacetype graphedit region"); @@ -718,6 +847,7 @@ void ED_spacetype_ipo(void) art->init = graph_main_region_init; art->draw = graph_main_region_draw; art->listener = graph_region_listener; + art->message_subscribe = graph_region_message_subscribe; art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES; BLI_addhead(&st->regiontypes, art); @@ -739,6 +869,7 @@ void ED_spacetype_ipo(void) art->prefsizex = 200 + V2D_SCROLL_WIDTH; /* 200 is the 'standard', but due to scrollers, we want a bit more to fit the lock icons in */ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES; art->listener = graph_region_listener; + art->message_subscribe = graph_region_message_subscribe; art->init = graph_channel_region_init; art->draw = graph_channel_region_draw; @@ -759,4 +890,3 @@ void ED_spacetype_ipo(void) BKE_spacetype_register(st); } - |