diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:17:24 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:21:24 +0300 |
commit | e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch) | |
tree | 8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/editors/space_graph | |
parent | b3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff) |
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211.
For details on usage and instructions for migrating branches
without conflicts, see:
https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/editors/space_graph')
-rw-r--r-- | source/blender/editors/space_graph/CMakeLists.txt | 60 | ||||
-rw-r--r-- | source/blender/editors/space_graph/graph_buttons.c | 2121 | ||||
-rw-r--r-- | source/blender/editors/space_graph/graph_draw.c | 2040 | ||||
-rw-r--r-- | source/blender/editors/space_graph/graph_edit.c | 4155 | ||||
-rw-r--r-- | source/blender/editors/space_graph/graph_intern.h | 52 | ||||
-rw-r--r-- | source/blender/editors/space_graph/graph_ops.c | 712 | ||||
-rw-r--r-- | source/blender/editors/space_graph/graph_select.c | 2395 | ||||
-rw-r--r-- | source/blender/editors/space_graph/graph_utils.c | 402 | ||||
-rw-r--r-- | source/blender/editors/space_graph/space_graph.c | 1424 |
9 files changed, 6942 insertions, 6419 deletions
diff --git a/source/blender/editors/space_graph/CMakeLists.txt b/source/blender/editors/space_graph/CMakeLists.txt index e0fc7500f94..cf5ffdb2be5 100644 --- a/source/blender/editors/space_graph/CMakeLists.txt +++ b/source/blender/editors/space_graph/CMakeLists.txt @@ -16,52 +16,52 @@ # ***** END GPL LICENSE BLOCK ***** set(INC - ../include - ../../blenkernel - ../../blenlib - ../../blentranslation - ../../depsgraph - ../../gpu - ../../makesdna - ../../makesrna - ../../windowmanager - ../../../../intern/guardedalloc - ../../../../intern/glew-mx + ../include + ../../blenkernel + ../../blenlib + ../../blentranslation + ../../depsgraph + ../../gpu + ../../makesdna + ../../makesrna + ../../windowmanager + ../../../../intern/guardedalloc + ../../../../intern/glew-mx ) set(INC_SYS - ${GLEW_INCLUDE_PATH} + ${GLEW_INCLUDE_PATH} ) set(SRC - graph_buttons.c - graph_draw.c - graph_edit.c - graph_ops.c - graph_select.c - graph_utils.c - space_graph.c + graph_buttons.c + graph_draw.c + graph_edit.c + graph_ops.c + graph_select.c + graph_utils.c + space_graph.c - graph_intern.h + graph_intern.h ) set(LIB - bf_blenkernel - bf_blenlib + bf_blenkernel + bf_blenlib ) if(WITH_AUDASPACE) - list(APPEND INC_SYS - ${AUDASPACE_C_INCLUDE_DIRS} - ) - list(APPEND LIB - bf_intern_audaspace - ) - add_definitions(-DWITH_AUDASPACE) + list(APPEND INC_SYS + ${AUDASPACE_C_INCLUDE_DIRS} + ) + list(APPEND LIB + bf_intern_audaspace + ) + add_definitions(-DWITH_AUDASPACE) endif() if(WITH_INTERNATIONAL) - add_definitions(-DWITH_INTERNATIONAL) + add_definitions(-DWITH_INTERNATIONAL) endif() add_definitions(${GL_DEFINITIONS}) diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index a4d7b5e9fc9..ac77095cbe2 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -21,7 +21,6 @@ * \ingroup spgraph */ - #include <string.h> #include <stdio.h> #include <math.h> @@ -64,7 +63,7 @@ #include "UI_interface.h" #include "UI_resources.h" -#include "graph_intern.h" // own include +#include "graph_intern.h" // own include /* ******************* graph editor space & buttons ************** */ @@ -74,33 +73,33 @@ static int graph_panel_context(const bContext *C, bAnimListElem **ale, FCurve **fcu) { - bAnimContext ac; - bAnimListElem *elem = NULL; - - /* for now, only draw if we could init the anim-context info (necessary for all animation-related tools) - * to work correctly is able to be correctly retrieved. There's no point showing empty panels? - */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return 0; - - /* try to find 'active' F-Curve */ - elem = get_active_fcurve_channel(&ac); - if (elem == NULL) - return 0; - - if (fcu) - *fcu = (FCurve *)elem->data; - if (ale) - *ale = elem; - else - MEM_freeN(elem); - - return 1; + bAnimContext ac; + bAnimListElem *elem = NULL; + + /* for now, only draw if we could init the anim-context info (necessary for all animation-related tools) + * to work correctly is able to be correctly retrieved. There's no point showing empty panels? + */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return 0; + + /* try to find 'active' F-Curve */ + elem = get_active_fcurve_channel(&ac); + if (elem == NULL) + return 0; + + if (fcu) + *fcu = (FCurve *)elem->data; + if (ale) + *ale = elem; + else + MEM_freeN(elem); + + return 1; } static bool graph_panel_poll(const bContext *C, PanelType *UNUSED(pt)) { - return graph_panel_context(C, NULL, NULL); + return graph_panel_context(C, NULL, NULL); } /* -------------- */ @@ -108,104 +107,104 @@ static bool graph_panel_poll(const bContext *C, PanelType *UNUSED(pt)) /* Graph Editor View Settings */ static void graph_panel_view(const bContext *C, Panel *pa) { - bScreen *sc = CTX_wm_screen(C); - SpaceGraph *sipo = CTX_wm_space_graph(C); - Scene *scene = CTX_data_scene(C); - PointerRNA spaceptr, sceneptr; - uiLayout *col, *sub, *row; - - /* get RNA pointers for use when creating the UI elements */ - RNA_id_pointer_create(&scene->id, &sceneptr); - RNA_pointer_create(&sc->id, &RNA_SpaceGraphEditor, sipo, &spaceptr); - - /* 2D-Cursor */ - col = uiLayoutColumn(pa->layout, false); - uiItemR(col, &spaceptr, "show_cursor", 0, NULL, ICON_NONE); - - sub = uiLayoutColumn(col, true); - uiLayoutSetActive(sub, RNA_boolean_get(&spaceptr, "show_cursor")); - uiItemO(sub, IFACE_("Cursor from Selection"), ICON_NONE, "GRAPH_OT_frame_jump"); - - sub = uiLayoutColumn(col, true); - uiLayoutSetActive(sub, RNA_boolean_get(&spaceptr, "show_cursor")); - row = uiLayoutSplit(sub, 0.7f, true); - if (sipo->mode == SIPO_MODE_DRIVERS) - uiItemR(row, &spaceptr, "cursor_position_x", 0, IFACE_("Cursor X"), ICON_NONE); - else - uiItemR(row, &sceneptr, "frame_current", 0, IFACE_("Cursor X"), ICON_NONE); - uiItemEnumO(row, "GRAPH_OT_snap", IFACE_("To Keys"), 0, "type", GRAPHKEYS_SNAP_CFRA); - - row = uiLayoutSplit(sub, 0.7f, true); - uiItemR(row, &spaceptr, "cursor_position_y", 0, IFACE_("Cursor Y"), ICON_NONE); - uiItemEnumO(row, "GRAPH_OT_snap", IFACE_("To Keys"), 0, "type", GRAPHKEYS_SNAP_VALUE); + bScreen *sc = CTX_wm_screen(C); + SpaceGraph *sipo = CTX_wm_space_graph(C); + Scene *scene = CTX_data_scene(C); + PointerRNA spaceptr, sceneptr; + uiLayout *col, *sub, *row; + + /* get RNA pointers for use when creating the UI elements */ + RNA_id_pointer_create(&scene->id, &sceneptr); + RNA_pointer_create(&sc->id, &RNA_SpaceGraphEditor, sipo, &spaceptr); + + /* 2D-Cursor */ + col = uiLayoutColumn(pa->layout, false); + uiItemR(col, &spaceptr, "show_cursor", 0, NULL, ICON_NONE); + + sub = uiLayoutColumn(col, true); + uiLayoutSetActive(sub, RNA_boolean_get(&spaceptr, "show_cursor")); + uiItemO(sub, IFACE_("Cursor from Selection"), ICON_NONE, "GRAPH_OT_frame_jump"); + + sub = uiLayoutColumn(col, true); + uiLayoutSetActive(sub, RNA_boolean_get(&spaceptr, "show_cursor")); + row = uiLayoutSplit(sub, 0.7f, true); + if (sipo->mode == SIPO_MODE_DRIVERS) + uiItemR(row, &spaceptr, "cursor_position_x", 0, IFACE_("Cursor X"), ICON_NONE); + else + uiItemR(row, &sceneptr, "frame_current", 0, IFACE_("Cursor X"), ICON_NONE); + uiItemEnumO(row, "GRAPH_OT_snap", IFACE_("To Keys"), 0, "type", GRAPHKEYS_SNAP_CFRA); + + row = uiLayoutSplit(sub, 0.7f, true); + uiItemR(row, &spaceptr, "cursor_position_y", 0, IFACE_("Cursor Y"), ICON_NONE); + uiItemEnumO(row, "GRAPH_OT_snap", IFACE_("To Keys"), 0, "type", GRAPHKEYS_SNAP_VALUE); } /* ******************* active F-Curve ************** */ static void graph_panel_properties(const bContext *C, Panel *pa) { - bAnimListElem *ale; - FCurve *fcu; - PointerRNA fcu_ptr; - uiLayout *layout = pa->layout; - uiLayout *col, *row, *sub; - char name[256]; - int icon = 0; - - if (!graph_panel_context(C, &ale, &fcu)) - return; - - /* F-Curve pointer */ - RNA_pointer_create(ale->id, &RNA_FCurve, fcu, &fcu_ptr); - - /* user-friendly 'name' for F-Curve */ - col = uiLayoutColumn(layout, false); - if (ale->type == ANIMTYPE_FCURVE) { - /* get user-friendly name for F-Curve */ - icon = getname_anim_fcurve(name, ale->id, fcu); - } - else { - /* NLA Control Curve, etc. */ - const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); - - /* get name */ - if (acf && acf->name) { - acf->name(ale, name); - } - else { - strcpy(name, IFACE_("<invalid>")); - icon = ICON_ERROR; - } - - /* icon */ - if (ale->type == ANIMTYPE_NLACURVE) - icon = ICON_NLA; - } - uiItemL(col, name, icon); - - /* RNA-Path Editing - only really should be enabled when things aren't working */ - col = uiLayoutColumn(layout, true); - uiLayoutSetEnabled(col, (fcu->flag & FCURVE_DISABLED) != 0); - uiItemR(col, &fcu_ptr, "data_path", 0, "", ICON_RNA); - uiItemR(col, &fcu_ptr, "array_index", 0, NULL, ICON_NONE); - - /* color settings */ - col = uiLayoutColumn(layout, true); - uiItemL(col, IFACE_("Display Color:"), ICON_NONE); - - row = uiLayoutRow(col, true); - uiItemR(row, &fcu_ptr, "color_mode", 0, "", ICON_NONE); - - sub = uiLayoutRow(row, true); - uiLayoutSetEnabled(sub, (fcu->color_mode == FCURVE_COLOR_CUSTOM)); - uiItemR(sub, &fcu_ptr, "color", 0, "", ICON_NONE); - - /* smoothing setting */ - col = uiLayoutColumn(layout, true); - uiItemL(col, IFACE_("Auto Handle Smoothing:"), ICON_NONE); - uiItemR(col, &fcu_ptr, "auto_smoothing", 0, "", ICON_NONE); - - MEM_freeN(ale); + bAnimListElem *ale; + FCurve *fcu; + PointerRNA fcu_ptr; + uiLayout *layout = pa->layout; + uiLayout *col, *row, *sub; + char name[256]; + int icon = 0; + + if (!graph_panel_context(C, &ale, &fcu)) + return; + + /* F-Curve pointer */ + RNA_pointer_create(ale->id, &RNA_FCurve, fcu, &fcu_ptr); + + /* user-friendly 'name' for F-Curve */ + col = uiLayoutColumn(layout, false); + if (ale->type == ANIMTYPE_FCURVE) { + /* get user-friendly name for F-Curve */ + icon = getname_anim_fcurve(name, ale->id, fcu); + } + else { + /* NLA Control Curve, etc. */ + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + + /* get name */ + if (acf && acf->name) { + acf->name(ale, name); + } + else { + strcpy(name, IFACE_("<invalid>")); + icon = ICON_ERROR; + } + + /* icon */ + if (ale->type == ANIMTYPE_NLACURVE) + icon = ICON_NLA; + } + uiItemL(col, name, icon); + + /* RNA-Path Editing - only really should be enabled when things aren't working */ + col = uiLayoutColumn(layout, true); + uiLayoutSetEnabled(col, (fcu->flag & FCURVE_DISABLED) != 0); + uiItemR(col, &fcu_ptr, "data_path", 0, "", ICON_RNA); + uiItemR(col, &fcu_ptr, "array_index", 0, NULL, ICON_NONE); + + /* color settings */ + col = uiLayoutColumn(layout, true); + uiItemL(col, IFACE_("Display Color:"), ICON_NONE); + + row = uiLayoutRow(col, true); + uiItemR(row, &fcu_ptr, "color_mode", 0, "", ICON_NONE); + + sub = uiLayoutRow(row, true); + uiLayoutSetEnabled(sub, (fcu->color_mode == FCURVE_COLOR_CUSTOM)); + uiItemR(sub, &fcu_ptr, "color", 0, "", ICON_NONE); + + /* smoothing setting */ + col = uiLayoutColumn(layout, true); + uiItemL(col, IFACE_("Auto Handle Smoothing:"), ICON_NONE); + uiItemR(col, &fcu_ptr, "auto_smoothing", 0, "", ICON_NONE); + + MEM_freeN(ale); } /* ******************* active Keyframe ************** */ @@ -213,66 +212,68 @@ static void graph_panel_properties(const bContext *C, Panel *pa) /* get 'active' keyframe for panel editing */ static short get_active_fcurve_keyframe_edit(FCurve *fcu, BezTriple **bezt, BezTriple **prevbezt) { - BezTriple *b; - int i; - - /* zero the pointers */ - *bezt = *prevbezt = NULL; - - /* sanity checks */ - if ((fcu->bezt == NULL) || (fcu->totvert == 0)) - return 0; - - /* find first selected keyframe for now, and call it the active one - * - this is a reasonable assumption, given that whenever anyone - * wants to edit numerically, there is likely to only be 1 vert selected - */ - for (i = 0, b = fcu->bezt; i < fcu->totvert; i++, b++) { - if (BEZT_ISSEL_ANY(b)) { - /* found - * - 'previous' is either the one before, of the keyframe itself (which is still fine) - * XXX: we can just make this null instead if needed - */ - *prevbezt = (i > 0) ? b - 1 : b; - *bezt = b; - - return 1; - } - } - - /* not found */ - return 0; + BezTriple *b; + int i; + + /* zero the pointers */ + *bezt = *prevbezt = NULL; + + /* sanity checks */ + if ((fcu->bezt == NULL) || (fcu->totvert == 0)) + return 0; + + /* find first selected keyframe for now, and call it the active one + * - this is a reasonable assumption, given that whenever anyone + * wants to edit numerically, there is likely to only be 1 vert selected + */ + for (i = 0, b = fcu->bezt; i < fcu->totvert; i++, b++) { + if (BEZT_ISSEL_ANY(b)) { + /* found + * - 'previous' is either the one before, of the keyframe itself (which is still fine) + * XXX: we can just make this null instead if needed + */ + *prevbezt = (i > 0) ? b - 1 : b; + *bezt = b; + + return 1; + } + } + + /* not found */ + return 0; } /* update callback for active keyframe properties - base updates stuff */ -static void graphedit_activekey_update_cb(bContext *UNUSED(C), void *fcu_ptr, void *UNUSED(bezt_ptr)) +static void graphedit_activekey_update_cb(bContext *UNUSED(C), + void *fcu_ptr, + void *UNUSED(bezt_ptr)) { - FCurve *fcu = (FCurve *)fcu_ptr; + FCurve *fcu = (FCurve *)fcu_ptr; - /* make sure F-Curve and its handles are still valid after this editing */ - sort_time_fcurve(fcu); - calchandles_fcurve(fcu); + /* make sure F-Curve and its handles are still valid after this editing */ + sort_time_fcurve(fcu); + calchandles_fcurve(fcu); } /* update callback for active keyframe properties - handle-editing wrapper */ static void graphedit_activekey_handles_cb(bContext *C, void *fcu_ptr, void *bezt_ptr) { - BezTriple *bezt = (BezTriple *)bezt_ptr; - - /* since editing the handles, make sure they're set to types which are receptive to editing - * see transform_conversions.c :: createTransGraphEditData(), last step in second loop - */ - if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) && ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM)) { - /* by changing to aligned handles, these can now be moved... */ - bezt->h1 = HD_ALIGN; - bezt->h2 = HD_ALIGN; - } - else { - BKE_nurb_bezt_handle_test(bezt, true); - } - - /* now call standard updates */ - graphedit_activekey_update_cb(C, fcu_ptr, bezt_ptr); + BezTriple *bezt = (BezTriple *)bezt_ptr; + + /* since editing the handles, make sure they're set to types which are receptive to editing + * see transform_conversions.c :: createTransGraphEditData(), last step in second loop + */ + if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) && ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM)) { + /* by changing to aligned handles, these can now be moved... */ + bezt->h1 = HD_ALIGN; + bezt->h2 = HD_ALIGN; + } + else { + BKE_nurb_bezt_handle_test(bezt, true); + } + + /* now call standard updates */ + graphedit_activekey_update_cb(C, fcu_ptr, bezt_ptr); } /* update callback for editing coordinates of right handle in active keyframe properties @@ -281,766 +282,943 @@ static void graphedit_activekey_handles_cb(bContext *C, void *fcu_ptr, void *bez */ static void graphedit_activekey_left_handle_coord_cb(bContext *C, void *fcu_ptr, void *bezt_ptr) { - BezTriple *bezt = (BezTriple *)bezt_ptr; + BezTriple *bezt = (BezTriple *)bezt_ptr; - const char f1 = bezt->f1; - const char f3 = bezt->f3; + const char f1 = bezt->f1; + const char f3 = bezt->f3; - bezt->f1 |= SELECT; - bezt->f3 &= ~SELECT; + bezt->f1 |= SELECT; + bezt->f3 &= ~SELECT; - /* perform normal updates NOW */ - graphedit_activekey_handles_cb(C, fcu_ptr, bezt_ptr); + /* perform normal updates NOW */ + graphedit_activekey_handles_cb(C, fcu_ptr, bezt_ptr); - /* restore selection state so that no-one notices this hack */ - bezt->f1 = f1; - bezt->f3 = f3; + /* restore selection state so that no-one notices this hack */ + bezt->f1 = f1; + bezt->f3 = f3; } static void graphedit_activekey_right_handle_coord_cb(bContext *C, void *fcu_ptr, void *bezt_ptr) { - BezTriple *bezt = (BezTriple *)bezt_ptr; + BezTriple *bezt = (BezTriple *)bezt_ptr; - /* original state of handle selection - to be restored after performing the recalculation */ - const char f1 = bezt->f1; - const char f3 = bezt->f3; + /* original state of handle selection - to be restored after performing the recalculation */ + const char f1 = bezt->f1; + const char f3 = bezt->f3; - /* temporarily make it so that only the right handle is selected, so that updates go correctly - * (i.e. it now acts as if we've just transforming the vert when it is selected by itself) - */ - bezt->f1 &= ~SELECT; - bezt->f3 |= SELECT; + /* temporarily make it so that only the right handle is selected, so that updates go correctly + * (i.e. it now acts as if we've just transforming the vert when it is selected by itself) + */ + bezt->f1 &= ~SELECT; + bezt->f3 |= SELECT; - /* perform normal updates NOW */ - graphedit_activekey_handles_cb(C, fcu_ptr, bezt_ptr); + /* perform normal updates NOW */ + graphedit_activekey_handles_cb(C, fcu_ptr, bezt_ptr); - /* restore selection state so that no-one notices this hack */ - bezt->f1 = f1; - bezt->f3 = f3; + /* restore selection state so that no-one notices this hack */ + bezt->f1 = f1; + bezt->f3 = f3; } static void graph_panel_key_properties(const bContext *C, Panel *pa) { - bAnimListElem *ale; - FCurve *fcu; - BezTriple *bezt, *prevbezt; - - uiLayout *layout = pa->layout; - uiLayout *col; - uiBlock *block; - - if (!graph_panel_context(C, &ale, &fcu)) - return; - - block = uiLayoutGetBlock(layout); - /* UI_block_func_handle_set(block, do_graph_region_buttons, NULL); */ - - /* only show this info if there are keyframes to edit */ - if (get_active_fcurve_keyframe_edit(fcu, &bezt, &prevbezt)) { - PointerRNA bezt_ptr, id_ptr, fcu_prop_ptr; - PropertyRNA *fcu_prop = NULL; - uiBut *but; - int unit = B_UNIT_NONE; - - /* RNA pointer to keyframe, to allow editing */ - RNA_pointer_create(ale->id, &RNA_Keyframe, bezt, &bezt_ptr); - - /* get property that F-Curve affects, for some unit-conversion magic */ - RNA_id_pointer_create(ale->id, &id_ptr); - if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &fcu_prop_ptr, &fcu_prop)) { - /* determine the unit for this property */ - unit = RNA_SUBTYPE_UNIT(RNA_property_subtype(fcu_prop)); - } - - /* interpolation */ - col = uiLayoutColumn(layout, false); - if (fcu->flag & FCURVE_DISCRETE_VALUES) { - uiLayout *split = uiLayoutSplit(col, 0.33f, true); - uiItemL(split, IFACE_("Interpolation:"), ICON_NONE); - uiItemL(split, IFACE_("None for Enum/Boolean"), ICON_IPO_CONSTANT); - } - else { - uiItemR(col, &bezt_ptr, "interpolation", 0, NULL, ICON_NONE); - } - - /* easing type */ - if (bezt->ipo > BEZT_IPO_BEZ) - uiItemR(col, &bezt_ptr, "easing", 0, NULL, 0); - - /* easing extra */ - switch (bezt->ipo) { - case BEZT_IPO_BACK: - col = uiLayoutColumn(layout, 1); - uiItemR(col, &bezt_ptr, "back", 0, NULL, 0); - break; - case BEZT_IPO_ELASTIC: - col = uiLayoutColumn(layout, 1); - uiItemR(col, &bezt_ptr, "amplitude", 0, NULL, 0); - uiItemR(col, &bezt_ptr, "period", 0, NULL, 0); - break; - default: - break; - } - - /* numerical coordinate editing - * - we use the button-versions of the calls so that we can attach special update handlers - * and unit conversion magic that cannot be achieved using a purely RNA-approach - */ - col = uiLayoutColumn(layout, true); - /* keyframe itself */ - { - uiItemL(col, IFACE_("Key:"), ICON_NONE); - - but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, IFACE_("Frame:"), 0, 0, UI_UNIT_X, UI_UNIT_Y, - &bezt_ptr, "co", 0, 0, 0, -1, -1, NULL); - UI_but_func_set(but, graphedit_activekey_update_cb, fcu, bezt); - - but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, IFACE_("Value:"), 0, 0, UI_UNIT_X, UI_UNIT_Y, - &bezt_ptr, "co", 1, 0, 0, -1, -1, NULL); - UI_but_func_set(but, graphedit_activekey_update_cb, fcu, bezt); - UI_but_unit_type_set(but, unit); - } - - /* previous handle - only if previous was Bezier interpolation */ - if ((prevbezt) && (prevbezt->ipo == BEZT_IPO_BEZ)) { - uiItemL(col, IFACE_("Left Handle:"), ICON_NONE); - - but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, "X:", 0, 0, UI_UNIT_X, UI_UNIT_Y, - &bezt_ptr, "handle_left", 0, 0, 0, -1, -1, NULL); - UI_but_func_set(but, graphedit_activekey_left_handle_coord_cb, fcu, bezt); - - but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, "Y:", 0, 0, UI_UNIT_X, UI_UNIT_Y, - &bezt_ptr, "handle_left", 1, 0, 0, -1, -1, NULL); - UI_but_func_set(but, graphedit_activekey_left_handle_coord_cb, fcu, bezt); - UI_but_unit_type_set(but, unit); - - /* XXX: with label? */ - but = uiDefButR(block, UI_BTYPE_MENU, B_REDR, NULL, 0, 0, UI_UNIT_X, UI_UNIT_Y, - &bezt_ptr, "handle_left_type", 0, 0, 0, -1, -1, "Type of left handle"); - UI_but_func_set(but, graphedit_activekey_handles_cb, fcu, bezt); - } - - /* next handle - only if current is Bezier interpolation */ - if (bezt->ipo == BEZT_IPO_BEZ) { - /* NOTE: special update callbacks are needed on the coords here due to T39911 */ - uiItemL(col, IFACE_("Right Handle:"), ICON_NONE); - - but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, "X:", 0, 0, UI_UNIT_X, UI_UNIT_Y, - &bezt_ptr, "handle_right", 0, 0, 0, -1, -1, NULL); - UI_but_func_set(but, graphedit_activekey_right_handle_coord_cb, fcu, bezt); - - but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, "Y:", 0, 0, UI_UNIT_X, UI_UNIT_Y, - &bezt_ptr, "handle_right", 1, 0, 0, -1, -1, NULL); - UI_but_func_set(but, graphedit_activekey_right_handle_coord_cb, fcu, bezt); - UI_but_unit_type_set(but, unit); - - /* XXX: with label? */ - but = uiDefButR(block, UI_BTYPE_MENU, B_REDR, NULL, 0, 0, UI_UNIT_X, UI_UNIT_Y, - &bezt_ptr, "handle_right_type", 0, 0, 0, -1, -1, "Type of right handle"); - UI_but_func_set(but, graphedit_activekey_handles_cb, fcu, bezt); - } - } - else { - if ((fcu->bezt == NULL) && (fcu->modifiers.first)) { - /* modifiers only - so no keyframes to be active */ - uiItemL(layout, IFACE_("F-Curve only has F-Modifiers"), ICON_NONE); - uiItemL(layout, IFACE_("See Modifiers panel below"), ICON_INFO); - } - else if (fcu->fpt) { - /* samples only */ - uiItemL(layout, IFACE_("F-Curve doesn't have any keyframes as it only contains sampled points"), - ICON_NONE); - } - else - uiItemL(layout, IFACE_("No active keyframe on F-Curve"), ICON_NONE); - } - - MEM_freeN(ale); + bAnimListElem *ale; + FCurve *fcu; + BezTriple *bezt, *prevbezt; + + uiLayout *layout = pa->layout; + uiLayout *col; + uiBlock *block; + + if (!graph_panel_context(C, &ale, &fcu)) + return; + + block = uiLayoutGetBlock(layout); + /* UI_block_func_handle_set(block, do_graph_region_buttons, NULL); */ + + /* only show this info if there are keyframes to edit */ + if (get_active_fcurve_keyframe_edit(fcu, &bezt, &prevbezt)) { + PointerRNA bezt_ptr, id_ptr, fcu_prop_ptr; + PropertyRNA *fcu_prop = NULL; + uiBut *but; + int unit = B_UNIT_NONE; + + /* RNA pointer to keyframe, to allow editing */ + RNA_pointer_create(ale->id, &RNA_Keyframe, bezt, &bezt_ptr); + + /* get property that F-Curve affects, for some unit-conversion magic */ + RNA_id_pointer_create(ale->id, &id_ptr); + if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &fcu_prop_ptr, &fcu_prop)) { + /* determine the unit for this property */ + unit = RNA_SUBTYPE_UNIT(RNA_property_subtype(fcu_prop)); + } + + /* interpolation */ + col = uiLayoutColumn(layout, false); + if (fcu->flag & FCURVE_DISCRETE_VALUES) { + uiLayout *split = uiLayoutSplit(col, 0.33f, true); + uiItemL(split, IFACE_("Interpolation:"), ICON_NONE); + uiItemL(split, IFACE_("None for Enum/Boolean"), ICON_IPO_CONSTANT); + } + else { + uiItemR(col, &bezt_ptr, "interpolation", 0, NULL, ICON_NONE); + } + + /* easing type */ + if (bezt->ipo > BEZT_IPO_BEZ) + uiItemR(col, &bezt_ptr, "easing", 0, NULL, 0); + + /* easing extra */ + switch (bezt->ipo) { + case BEZT_IPO_BACK: + col = uiLayoutColumn(layout, 1); + uiItemR(col, &bezt_ptr, "back", 0, NULL, 0); + break; + case BEZT_IPO_ELASTIC: + col = uiLayoutColumn(layout, 1); + uiItemR(col, &bezt_ptr, "amplitude", 0, NULL, 0); + uiItemR(col, &bezt_ptr, "period", 0, NULL, 0); + break; + default: + break; + } + + /* numerical coordinate editing + * - we use the button-versions of the calls so that we can attach special update handlers + * and unit conversion magic that cannot be achieved using a purely RNA-approach + */ + col = uiLayoutColumn(layout, true); + /* keyframe itself */ + { + uiItemL(col, IFACE_("Key:"), ICON_NONE); + + but = uiDefButR(block, + UI_BTYPE_NUM, + B_REDR, + IFACE_("Frame:"), + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + &bezt_ptr, + "co", + 0, + 0, + 0, + -1, + -1, + NULL); + UI_but_func_set(but, graphedit_activekey_update_cb, fcu, bezt); + + but = uiDefButR(block, + UI_BTYPE_NUM, + B_REDR, + IFACE_("Value:"), + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + &bezt_ptr, + "co", + 1, + 0, + 0, + -1, + -1, + NULL); + UI_but_func_set(but, graphedit_activekey_update_cb, fcu, bezt); + UI_but_unit_type_set(but, unit); + } + + /* previous handle - only if previous was Bezier interpolation */ + if ((prevbezt) && (prevbezt->ipo == BEZT_IPO_BEZ)) { + uiItemL(col, IFACE_("Left Handle:"), ICON_NONE); + + but = uiDefButR(block, + UI_BTYPE_NUM, + B_REDR, + "X:", + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + &bezt_ptr, + "handle_left", + 0, + 0, + 0, + -1, + -1, + NULL); + UI_but_func_set(but, graphedit_activekey_left_handle_coord_cb, fcu, bezt); + + but = uiDefButR(block, + UI_BTYPE_NUM, + B_REDR, + "Y:", + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + &bezt_ptr, + "handle_left", + 1, + 0, + 0, + -1, + -1, + NULL); + UI_but_func_set(but, graphedit_activekey_left_handle_coord_cb, fcu, bezt); + UI_but_unit_type_set(but, unit); + + /* XXX: with label? */ + but = uiDefButR(block, + UI_BTYPE_MENU, + B_REDR, + NULL, + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + &bezt_ptr, + "handle_left_type", + 0, + 0, + 0, + -1, + -1, + "Type of left handle"); + UI_but_func_set(but, graphedit_activekey_handles_cb, fcu, bezt); + } + + /* next handle - only if current is Bezier interpolation */ + if (bezt->ipo == BEZT_IPO_BEZ) { + /* NOTE: special update callbacks are needed on the coords here due to T39911 */ + uiItemL(col, IFACE_("Right Handle:"), ICON_NONE); + + but = uiDefButR(block, + UI_BTYPE_NUM, + B_REDR, + "X:", + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + &bezt_ptr, + "handle_right", + 0, + 0, + 0, + -1, + -1, + NULL); + UI_but_func_set(but, graphedit_activekey_right_handle_coord_cb, fcu, bezt); + + but = uiDefButR(block, + UI_BTYPE_NUM, + B_REDR, + "Y:", + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + &bezt_ptr, + "handle_right", + 1, + 0, + 0, + -1, + -1, + NULL); + UI_but_func_set(but, graphedit_activekey_right_handle_coord_cb, fcu, bezt); + UI_but_unit_type_set(but, unit); + + /* XXX: with label? */ + but = uiDefButR(block, + UI_BTYPE_MENU, + B_REDR, + NULL, + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + &bezt_ptr, + "handle_right_type", + 0, + 0, + 0, + -1, + -1, + "Type of right handle"); + UI_but_func_set(but, graphedit_activekey_handles_cb, fcu, bezt); + } + } + else { + if ((fcu->bezt == NULL) && (fcu->modifiers.first)) { + /* modifiers only - so no keyframes to be active */ + uiItemL(layout, IFACE_("F-Curve only has F-Modifiers"), ICON_NONE); + uiItemL(layout, IFACE_("See Modifiers panel below"), ICON_INFO); + } + else if (fcu->fpt) { + /* samples only */ + uiItemL(layout, + IFACE_("F-Curve doesn't have any keyframes as it only contains sampled points"), + ICON_NONE); + } + else + uiItemL(layout, IFACE_("No active keyframe on F-Curve"), ICON_NONE); + } + + MEM_freeN(ale); } /* ******************* drivers ******************************** */ -#define B_IPO_DEPCHANGE 10 +#define B_IPO_DEPCHANGE 10 static void do_graph_region_driver_buttons(bContext *C, void *id_v, int event) { - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - - switch (event) { - case B_IPO_DEPCHANGE: - { - /* Was not actually run ever (NULL always passed as arg to this callback). - * If needed again, will need to check how to pass both fcurve and ID... :/ */ + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + + switch (event) { + case B_IPO_DEPCHANGE: { + /* Was not actually run ever (NULL always passed as arg to this callback). + * If needed again, will need to check how to pass both fcurve and ID... :/ */ #if 0 - /* 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; - } + /* 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; + } #endif - ID *id = id_v; - AnimData *adt = BKE_animdata_from_id(id); - - /* rebuild depsgraph for the new deps, and ensure COW copies get flushed. */ - DEG_relations_tag_update(bmain); - DEG_id_tag_update_ex(bmain, id, ID_RECALC_COPY_ON_WRITE); - if (adt != NULL) { - if (adt->action != NULL) { - DEG_id_tag_update_ex(bmain, &adt->action->id, ID_RECALC_COPY_ON_WRITE); - } - if (adt->tmpact != NULL) { - DEG_id_tag_update_ex(bmain, &adt->tmpact->id, ID_RECALC_COPY_ON_WRITE); - } - } - - break; - } - } - - /* default for now */ - WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); // XXX could use better notifier + ID *id = id_v; + AnimData *adt = BKE_animdata_from_id(id); + + /* rebuild depsgraph for the new deps, and ensure COW copies get flushed. */ + DEG_relations_tag_update(bmain); + DEG_id_tag_update_ex(bmain, id, ID_RECALC_COPY_ON_WRITE); + if (adt != NULL) { + if (adt->action != NULL) { + DEG_id_tag_update_ex(bmain, &adt->action->id, ID_RECALC_COPY_ON_WRITE); + } + if (adt->tmpact != NULL) { + DEG_id_tag_update_ex(bmain, &adt->tmpact->id, ID_RECALC_COPY_ON_WRITE); + } + } + + break; + } + } + + /* default for now */ + WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); // XXX could use better notifier } /* callback to add a target variable to the active driver */ static void driver_add_var_cb(bContext *C, void *driver_v, void *UNUSED(arg)) { - ChannelDriver *driver = (ChannelDriver *)driver_v; + ChannelDriver *driver = (ChannelDriver *)driver_v; - /* add a new variable */ - driver_add_new_variable(driver); - ED_undo_push(C, "Add Driver Variable"); + /* add a new variable */ + driver_add_new_variable(driver); + ED_undo_push(C, "Add Driver Variable"); } /* callback to remove target variable from active driver */ static void driver_delete_var_cb(bContext *C, void *driver_v, void *dvar_v) { - ChannelDriver *driver = (ChannelDriver *)driver_v; - DriverVar *dvar = (DriverVar *)dvar_v; + ChannelDriver *driver = (ChannelDriver *)driver_v; + DriverVar *dvar = (DriverVar *)dvar_v; - /* remove the active variable */ - driver_free_variable_ex(driver, dvar); - ED_undo_push(C, "Delete Driver Variable"); + /* remove the active variable */ + driver_free_variable_ex(driver, dvar); + ED_undo_push(C, "Delete Driver Variable"); } /* callback to report why a driver variable is invalid */ static void driver_dvar_invalid_name_query_cb(bContext *C, void *dvar_v, void *UNUSED(arg)) { - uiPopupMenu *pup = UI_popup_menu_begin(C, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Invalid Variable Name"), ICON_NONE); - uiLayout *layout = UI_popup_menu_layout(pup); - - DriverVar *dvar = (DriverVar *)dvar_v; - - if (dvar->flag & DVAR_FLAG_INVALID_EMPTY) { - uiItemL(layout, "It cannot be left blank", ICON_ERROR); - } - if (dvar->flag & DVAR_FLAG_INVALID_START_NUM) { - uiItemL(layout, "It cannot start with a number", ICON_ERROR); - } - if (dvar->flag & DVAR_FLAG_INVALID_START_CHAR) { - uiItemL(layout, - "It cannot start with a special character," - " including '$', '@', '!', '~', '+', '-', '_', '.', or ' '", - ICON_NONE); - } - if (dvar->flag & DVAR_FLAG_INVALID_HAS_SPACE) { - uiItemL(layout, "It cannot contain spaces (e.g. 'a space')", ICON_ERROR); - } - if (dvar->flag & DVAR_FLAG_INVALID_HAS_DOT) { - uiItemL(layout, "It cannot contain dots (e.g. 'a.dot')", ICON_ERROR); - } - if (dvar->flag & DVAR_FLAG_INVALID_HAS_SPECIAL) { - uiItemL(layout, "It cannot contain special (non-alphabetical/numeric) characters", ICON_ERROR); - } - if (dvar->flag & DVAR_FLAG_INVALID_PY_KEYWORD) { - uiItemL(layout, "It cannot be a reserved keyword in Python", ICON_INFO); - } - - UI_popup_menu_end(C, pup); + uiPopupMenu *pup = UI_popup_menu_begin( + C, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Invalid Variable Name"), ICON_NONE); + uiLayout *layout = UI_popup_menu_layout(pup); + + DriverVar *dvar = (DriverVar *)dvar_v; + + if (dvar->flag & DVAR_FLAG_INVALID_EMPTY) { + uiItemL(layout, "It cannot be left blank", ICON_ERROR); + } + if (dvar->flag & DVAR_FLAG_INVALID_START_NUM) { + uiItemL(layout, "It cannot start with a number", ICON_ERROR); + } + if (dvar->flag & DVAR_FLAG_INVALID_START_CHAR) { + uiItemL(layout, + "It cannot start with a special character," + " including '$', '@', '!', '~', '+', '-', '_', '.', or ' '", + ICON_NONE); + } + if (dvar->flag & DVAR_FLAG_INVALID_HAS_SPACE) { + uiItemL(layout, "It cannot contain spaces (e.g. 'a space')", ICON_ERROR); + } + if (dvar->flag & DVAR_FLAG_INVALID_HAS_DOT) { + uiItemL(layout, "It cannot contain dots (e.g. 'a.dot')", ICON_ERROR); + } + if (dvar->flag & DVAR_FLAG_INVALID_HAS_SPECIAL) { + uiItemL(layout, "It cannot contain special (non-alphabetical/numeric) characters", ICON_ERROR); + } + if (dvar->flag & DVAR_FLAG_INVALID_PY_KEYWORD) { + uiItemL(layout, "It cannot be a reserved keyword in Python", ICON_INFO); + } + + UI_popup_menu_end(C, pup); } /* callback to reset the driver's flags */ static void driver_update_flags_cb(bContext *UNUSED(C), void *fcu_v, void *UNUSED(arg)) { - FCurve *fcu = (FCurve *)fcu_v; - ChannelDriver *driver = fcu->driver; + FCurve *fcu = (FCurve *)fcu_v; + ChannelDriver *driver = fcu->driver; - /* clear invalid flags */ - fcu->flag &= ~FCURVE_DISABLED; - driver->flag &= ~DRIVER_FLAG_INVALID; + /* clear invalid flags */ + fcu->flag &= ~FCURVE_DISABLED; + driver->flag &= ~DRIVER_FLAG_INVALID; } /* drivers panel poll */ static bool graph_panel_drivers_poll(const bContext *C, PanelType *UNUSED(pt)) { - SpaceGraph *sipo = CTX_wm_space_graph(C); + SpaceGraph *sipo = CTX_wm_space_graph(C); - if (sipo->mode != SIPO_MODE_DRIVERS) - return 0; + if (sipo->mode != SIPO_MODE_DRIVERS) + return 0; - return graph_panel_context(C, NULL, NULL); + return graph_panel_context(C, NULL, NULL); } /* settings for 'single property' driver variable type */ static void graph_panel_driverVar__singleProp(uiLayout *layout, ID *id, DriverVar *dvar) { - DriverTarget *dtar = &dvar->targets[0]; - PointerRNA dtar_ptr; - uiLayout *row, *col; - - /* initialize RNA pointer to the target */ - RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr); - - /* Target ID */ - row = uiLayoutRow(layout, false); - uiLayoutSetRedAlert(row, ((dtar->flag & DTAR_FLAG_INVALID) && !dtar->id)); - uiTemplateAnyID(row, &dtar_ptr, "id", "id_type", IFACE_("Prop:")); - - /* Target Property */ - if (dtar->id) { - PointerRNA root_ptr; - - /* get pointer for resolving the property selected */ - RNA_id_pointer_create(dtar->id, &root_ptr); - - /* rna path */ - col = uiLayoutColumn(layout, true); - uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); - uiTemplatePathBuilder(col, &dtar_ptr, "data_path", &root_ptr, IFACE_("Path")); - } + DriverTarget *dtar = &dvar->targets[0]; + PointerRNA dtar_ptr; + uiLayout *row, *col; + + /* initialize RNA pointer to the target */ + RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr); + + /* Target ID */ + row = uiLayoutRow(layout, false); + uiLayoutSetRedAlert(row, ((dtar->flag & DTAR_FLAG_INVALID) && !dtar->id)); + uiTemplateAnyID(row, &dtar_ptr, "id", "id_type", IFACE_("Prop:")); + + /* Target Property */ + if (dtar->id) { + PointerRNA root_ptr; + + /* get pointer for resolving the property selected */ + RNA_id_pointer_create(dtar->id, &root_ptr); + + /* rna path */ + col = uiLayoutColumn(layout, true); + uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); + uiTemplatePathBuilder(col, &dtar_ptr, "data_path", &root_ptr, IFACE_("Path")); + } } /* settings for 'rotation difference' driver variable type */ /* FIXME: 1) Must be same armature for both dtars, 2) Alignment issues... */ static void graph_panel_driverVar__rotDiff(uiLayout *layout, ID *id, DriverVar *dvar) { - DriverTarget *dtar = &dvar->targets[0]; - DriverTarget *dtar2 = &dvar->targets[1]; - Object *ob1 = (Object *)dtar->id; - Object *ob2 = (Object *)dtar2->id; - PointerRNA dtar_ptr, dtar2_ptr; - uiLayout *col; - - /* initialize RNA pointer to the target */ - RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr); - RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr); - - /* Object 1 */ - col = uiLayoutColumn(layout, true); - uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */ - uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Object 1"), ICON_NONE); - - if (dtar->id && GS(dtar->id->name) == ID_OB && ob1->pose) { - PointerRNA tar_ptr; - - RNA_pointer_create(dtar->id, &RNA_Pose, ob1->pose, &tar_ptr); - uiItemPointerR(col, &dtar_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA); - } - - /* Object 2 */ - col = uiLayoutColumn(layout, true); - uiLayoutSetRedAlert(col, (dtar2->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */ - uiItemR(col, &dtar2_ptr, "id", 0, IFACE_("Object 2"), ICON_NONE); - - if (dtar2->id && GS(dtar2->id->name) == ID_OB && ob2->pose) { - PointerRNA tar_ptr; - - RNA_pointer_create(dtar2->id, &RNA_Pose, ob2->pose, &tar_ptr); - uiItemPointerR(col, &dtar2_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA); - } + DriverTarget *dtar = &dvar->targets[0]; + DriverTarget *dtar2 = &dvar->targets[1]; + Object *ob1 = (Object *)dtar->id; + Object *ob2 = (Object *)dtar2->id; + PointerRNA dtar_ptr, dtar2_ptr; + uiLayout *col; + + /* initialize RNA pointer to the target */ + RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr); + RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr); + + /* Object 1 */ + col = uiLayoutColumn(layout, true); + uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */ + uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Object 1"), ICON_NONE); + + if (dtar->id && GS(dtar->id->name) == ID_OB && ob1->pose) { + PointerRNA tar_ptr; + + RNA_pointer_create(dtar->id, &RNA_Pose, ob1->pose, &tar_ptr); + uiItemPointerR(col, &dtar_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA); + } + + /* Object 2 */ + col = uiLayoutColumn(layout, true); + uiLayoutSetRedAlert(col, (dtar2->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */ + uiItemR(col, &dtar2_ptr, "id", 0, IFACE_("Object 2"), ICON_NONE); + + if (dtar2->id && GS(dtar2->id->name) == ID_OB && ob2->pose) { + PointerRNA tar_ptr; + + RNA_pointer_create(dtar2->id, &RNA_Pose, ob2->pose, &tar_ptr); + uiItemPointerR(col, &dtar2_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA); + } } /* settings for 'location difference' driver variable type */ static void graph_panel_driverVar__locDiff(uiLayout *layout, ID *id, DriverVar *dvar) { - DriverTarget *dtar = &dvar->targets[0]; - DriverTarget *dtar2 = &dvar->targets[1]; - Object *ob1 = (Object *)dtar->id; - Object *ob2 = (Object *)dtar2->id; - PointerRNA dtar_ptr, dtar2_ptr; - uiLayout *col; + DriverTarget *dtar = &dvar->targets[0]; + DriverTarget *dtar2 = &dvar->targets[1]; + Object *ob1 = (Object *)dtar->id; + Object *ob2 = (Object *)dtar2->id; + PointerRNA dtar_ptr, dtar2_ptr; + uiLayout *col; - /* initialize RNA pointer to the target */ - RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr); - RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr); + /* initialize RNA pointer to the target */ + RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr); + RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr); - /* Object 1 */ - col = uiLayoutColumn(layout, true); - uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */ - uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Object 1"), ICON_NONE); + /* Object 1 */ + col = uiLayoutColumn(layout, true); + uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */ + uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Object 1"), ICON_NONE); - if (dtar->id && GS(dtar->id->name) == ID_OB && ob1->pose) { - PointerRNA tar_ptr; + if (dtar->id && GS(dtar->id->name) == ID_OB && ob1->pose) { + PointerRNA tar_ptr; - RNA_pointer_create(dtar->id, &RNA_Pose, ob1->pose, &tar_ptr); - uiItemPointerR(col, &dtar_ptr, "bone_target", &tar_ptr, "bones", IFACE_("Bone"), ICON_BONE_DATA); - } + RNA_pointer_create(dtar->id, &RNA_Pose, ob1->pose, &tar_ptr); + uiItemPointerR( + col, &dtar_ptr, "bone_target", &tar_ptr, "bones", IFACE_("Bone"), ICON_BONE_DATA); + } - /* we can clear it again now - it's only needed when creating the ID/Bone fields */ - uiLayoutSetRedAlert(col, false); + /* we can clear it again now - it's only needed when creating the ID/Bone fields */ + uiLayoutSetRedAlert(col, false); - uiItemR(col, &dtar_ptr, "transform_space", 0, NULL, ICON_NONE); + uiItemR(col, &dtar_ptr, "transform_space", 0, NULL, ICON_NONE); - /* Object 2 */ - col = uiLayoutColumn(layout, true); - uiLayoutSetRedAlert(col, (dtar2->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */ - uiItemR(col, &dtar2_ptr, "id", 0, IFACE_("Object 2"), ICON_NONE); + /* Object 2 */ + col = uiLayoutColumn(layout, true); + uiLayoutSetRedAlert(col, (dtar2->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */ + uiItemR(col, &dtar2_ptr, "id", 0, IFACE_("Object 2"), ICON_NONE); - if (dtar2->id && GS(dtar2->id->name) == ID_OB && ob2->pose) { - PointerRNA tar_ptr; + if (dtar2->id && GS(dtar2->id->name) == ID_OB && ob2->pose) { + PointerRNA tar_ptr; - RNA_pointer_create(dtar2->id, &RNA_Pose, ob2->pose, &tar_ptr); - uiItemPointerR(col, &dtar2_ptr, "bone_target", &tar_ptr, "bones", IFACE_("Bone"), ICON_BONE_DATA); - } + RNA_pointer_create(dtar2->id, &RNA_Pose, ob2->pose, &tar_ptr); + uiItemPointerR( + col, &dtar2_ptr, "bone_target", &tar_ptr, "bones", IFACE_("Bone"), ICON_BONE_DATA); + } - /* we can clear it again now - it's only needed when creating the ID/Bone fields */ - uiLayoutSetRedAlert(col, false); + /* we can clear it again now - it's only needed when creating the ID/Bone fields */ + uiLayoutSetRedAlert(col, false); - uiItemR(col, &dtar2_ptr, "transform_space", 0, NULL, ICON_NONE); + uiItemR(col, &dtar2_ptr, "transform_space", 0, NULL, ICON_NONE); } /* settings for 'transform channel' driver variable type */ static void graph_panel_driverVar__transChan(uiLayout *layout, ID *id, DriverVar *dvar) { - DriverTarget *dtar = &dvar->targets[0]; - Object *ob = (Object *)dtar->id; - PointerRNA dtar_ptr; - uiLayout *col, *sub; - - /* initialize RNA pointer to the target */ - RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr); - - /* properties */ - col = uiLayoutColumn(layout, true); - uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */ - uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Object"), ICON_NONE); - - if (dtar->id && GS(dtar->id->name) == ID_OB && ob->pose) { - PointerRNA tar_ptr; - - RNA_pointer_create(dtar->id, &RNA_Pose, ob->pose, &tar_ptr); - uiItemPointerR(col, &dtar_ptr, "bone_target", &tar_ptr, "bones", IFACE_("Bone"), ICON_BONE_DATA); - } - - sub = uiLayoutColumn(layout, true); - uiItemR(sub, &dtar_ptr, "transform_type", 0, NULL, ICON_NONE); - uiItemR(sub, &dtar_ptr, "transform_space", 0, IFACE_("Space"), ICON_NONE); + DriverTarget *dtar = &dvar->targets[0]; + Object *ob = (Object *)dtar->id; + PointerRNA dtar_ptr; + uiLayout *col, *sub; + + /* initialize RNA pointer to the target */ + RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr); + + /* properties */ + col = uiLayoutColumn(layout, true); + uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */ + uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Object"), ICON_NONE); + + if (dtar->id && GS(dtar->id->name) == ID_OB && ob->pose) { + PointerRNA tar_ptr; + + RNA_pointer_create(dtar->id, &RNA_Pose, ob->pose, &tar_ptr); + uiItemPointerR( + col, &dtar_ptr, "bone_target", &tar_ptr, "bones", IFACE_("Bone"), ICON_BONE_DATA); + } + + sub = uiLayoutColumn(layout, true); + uiItemR(sub, &dtar_ptr, "transform_type", 0, NULL, ICON_NONE); + uiItemR(sub, &dtar_ptr, "transform_space", 0, IFACE_("Space"), ICON_NONE); } /* ----------------------------------------------------------------- */ - /* 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) { - PointerRNA fcu_ptr; - uiLayout *row; - char name[256]; - int icon = 0; + PointerRNA fcu_ptr; + uiLayout *row; + char name[256]; + int icon = 0; - /* F-Curve pointer */ - RNA_pointer_create(id, &RNA_FCurve, fcu, &fcu_ptr); + /* 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); + /* 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); + /* 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 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, "", ICON_SMALL_TRI_RIGHT_VEC); - uiItemL(row, name, ICON_RNA); + /* -> user friendly 'name' for F-Curve/driver target */ + uiItemL(row, "", ICON_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) +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, *row; - uiBlock *block; - uiBut *but; - - /* set event handler for panel */ - block = uiLayoutGetBlock(layout); - UI_block_func_handle_set(block, do_graph_region_driver_buttons, id); - - /* driver-level settings - type, expressions, and errors */ - RNA_pointer_create(id, &RNA_Driver, driver, &driver_ptr); - - 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 */ - /* 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 (driver->flag & DRIVER_FLAG_INVALID) { - uiItemL(col, IFACE_("ERROR: Invalid Python expression"), ICON_CANCEL); - } - else if (!BKE_driver_has_simple_expression(driver)) { - if ((G.f & G_FLAG_SCRIPT_AUTOEXEC) == 0) { - /* TODO: Add button to enable? */ - uiItemL(col, IFACE_("WARNING: Python expressions limited for security"), ICON_ERROR); - } - else { - uiItemL(col, IFACE_("Slow Python expression"), ICON_INFO); - } - } - - /* Explicit bpy-references are evil. Warn about these to prevent errors */ - /* TODO: put these in a box? */ - if (bpy_data_expr_error || bpy_ctx_expr_error) { - uiItemL(col, IFACE_("WARNING: Driver expression may not work correctly"), ICON_HELP); - - if (bpy_data_expr_error) { - uiItemL(col, IFACE_("TIP: Use variables instead of bpy.data paths (see below)"), ICON_ERROR); - } - if (bpy_ctx_expr_error) { - uiItemL(col, IFACE_("TIP: bpy.context is not safe for renderfarm usage"), ICON_ERROR); - } - } - } - 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); - - /* Warnings about a lack of variables - * NOTE: The lack of variables is generally a bad thing, since it indicates - * that the driver doesn't work at all. This particular scenario arises - * primarily when users mistakenly try to use drivers for procedural - * property animation - */ - if (BLI_listbase_is_empty(&driver->variables)) { - uiItemL(col, IFACE_("ERROR: Driver is useless without any inputs"), ICON_ERROR); - - if (!BLI_listbase_is_empty(&fcu->modifiers)) { - uiItemL(col, IFACE_("TIP: Use F-Curves for procedural animation instead"), ICON_INFO); - uiItemL(col, IFACE_("F-Modifiers can generate curves for those too"), ICON_INFO); - } - } - } - - uiItemS(layout); - - /* add/copy/paste driver variables */ - 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_ADD, 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(layout, false); - block = uiLayoutGetBlock(row); - but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ADD, 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, ensuring that drivers will update correctly")); - UI_but_func_set(but, driver_add_var_cb, driver, NULL); - - /* copy/paste (as sub-row) */ - row = uiLayoutRow(row, true); - block = uiLayoutGetBlock(row); - - uiItemO(row, "", ICON_COPYDOWN, "GRAPH_OT_driver_variables_copy"); - uiItemO(row, "", ICON_PASTEDOWN, "GRAPH_OT_driver_variables_paste"); - } - - /* loop over targets, drawing them */ - for (dvar = driver->variables.first; dvar; dvar = dvar->next) { - PointerRNA dvar_ptr; - uiLayout *box; - uiLayout *subrow, *sub; - - /* sub-layout column for this variable's settings */ - col = uiLayoutColumn(layout, true); - - /* 1) header panel */ - box = uiLayoutBox(col); - RNA_pointer_create(id, &RNA_DriverVariable, dvar, &dvar_ptr); - - row = uiLayoutRow(box, false); - block = uiLayoutGetBlock(row); - - /* 1.1) variable type and name */ - subrow = uiLayoutRow(row, true); - - /* 1.1.1) variable type */ - - /* HACK: special group just for the enum, - * otherwise we get ugly layout with text included too... */ - sub = uiLayoutRow(subrow, true); - - uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT); - - uiItemR(sub, &dvar_ptr, "type", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); - - /* 1.1.2) variable name */ - - /* HACK: special group to counteract the effects of the previous enum, - * which now pushes everything too far right */ - sub = uiLayoutRow(subrow, true); - - uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_EXPAND); - - uiItemR(sub, &dvar_ptr, "name", 0, "", ICON_NONE); - - /* 1.2) invalid name? */ - UI_block_emboss_set(block, UI_EMBOSS_NONE); - - if (dvar->flag & DVAR_FLAG_INVALID_NAME) { - but = uiDefIconBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ERROR, 290, 0, UI_UNIT_X, UI_UNIT_Y, - NULL, 0.0, 0.0, 0.0, 0.0, IFACE_("Invalid variable name, click here for details")); - UI_but_func_set(but, driver_dvar_invalid_name_query_cb, dvar, NULL); // XXX: reports? - } - - /* 1.3) remove button */ - but = uiDefIconBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_X, 290, 0, UI_UNIT_X, UI_UNIT_Y, - NULL, 0.0, 0.0, 0.0, 0.0, IFACE_("Delete target variable")); - UI_but_func_set(but, driver_delete_var_cb, driver, dvar); - UI_block_emboss_set(block, UI_EMBOSS); - - - /* 2) variable type settings */ - box = uiLayoutBox(col); - /* controls to draw depends on the type of variable */ - switch (dvar->type) { - case DVAR_TYPE_SINGLE_PROP: /* single property */ - graph_panel_driverVar__singleProp(box, id, dvar); - break; - case DVAR_TYPE_ROT_DIFF: /* rotational difference */ - graph_panel_driverVar__rotDiff(box, id, dvar); - break; - case DVAR_TYPE_LOC_DIFF: /* location difference */ - graph_panel_driverVar__locDiff(box, id, dvar); - break; - case DVAR_TYPE_TRANSFORM_CHAN: /* transform channel */ - graph_panel_driverVar__transChan(box, id, dvar); - break; - } - - /* 3) value of variable */ - { - char valBuf[32]; - - box = uiLayoutBox(col); - row = uiLayoutRow(box, true); - uiItemL(row, IFACE_("Value:"), ICON_NONE); - - if ((dvar->type == DVAR_TYPE_ROT_DIFF) || - (dvar->type == DVAR_TYPE_TRANSFORM_CHAN && - dvar->targets[0].transChan >= DTAR_TRANSCHAN_ROTX && - dvar->targets[0].transChan < DTAR_TRANSCHAN_SCALEX)) - { - BLI_snprintf(valBuf, sizeof(valBuf), "%.3f (%4.1f°)", dvar->curval, RAD2DEGF(dvar->curval)); - } - else { - BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", dvar->curval); - } - - uiItemL(row, valBuf, ICON_NONE); - } - } - - 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); + ChannelDriver *driver = fcu->driver; + DriverVar *dvar; + + PointerRNA driver_ptr; + uiLayout *col, *row; + uiBlock *block; + uiBut *but; + + /* set event handler for panel */ + block = uiLayoutGetBlock(layout); + UI_block_func_handle_set(block, do_graph_region_driver_buttons, id); + + /* driver-level settings - type, expressions, and errors */ + RNA_pointer_create(id, &RNA_Driver, driver, &driver_ptr); + + 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 */ + /* 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 (driver->flag & DRIVER_FLAG_INVALID) { + uiItemL(col, IFACE_("ERROR: Invalid Python expression"), ICON_CANCEL); + } + else if (!BKE_driver_has_simple_expression(driver)) { + if ((G.f & G_FLAG_SCRIPT_AUTOEXEC) == 0) { + /* TODO: Add button to enable? */ + uiItemL(col, IFACE_("WARNING: Python expressions limited for security"), ICON_ERROR); + } + else { + uiItemL(col, IFACE_("Slow Python expression"), ICON_INFO); + } + } + + /* Explicit bpy-references are evil. Warn about these to prevent errors */ + /* TODO: put these in a box? */ + if (bpy_data_expr_error || bpy_ctx_expr_error) { + uiItemL(col, IFACE_("WARNING: Driver expression may not work correctly"), ICON_HELP); + + if (bpy_data_expr_error) { + uiItemL( + col, IFACE_("TIP: Use variables instead of bpy.data paths (see below)"), ICON_ERROR); + } + if (bpy_ctx_expr_error) { + uiItemL(col, IFACE_("TIP: bpy.context is not safe for renderfarm usage"), ICON_ERROR); + } + } + } + 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); + + /* Warnings about a lack of variables + * NOTE: The lack of variables is generally a bad thing, since it indicates + * that the driver doesn't work at all. This particular scenario arises + * primarily when users mistakenly try to use drivers for procedural + * property animation + */ + if (BLI_listbase_is_empty(&driver->variables)) { + uiItemL(col, IFACE_("ERROR: Driver is useless without any inputs"), ICON_ERROR); + + if (!BLI_listbase_is_empty(&fcu->modifiers)) { + uiItemL(col, IFACE_("TIP: Use F-Curves for procedural animation instead"), ICON_INFO); + uiItemL(col, IFACE_("F-Modifiers can generate curves for those too"), ICON_INFO); + } + } + } + + uiItemS(layout); + + /* add/copy/paste driver variables */ + 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_ADD, + 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(layout, false); + block = uiLayoutGetBlock(row); + but = uiDefIconTextBut(block, + UI_BTYPE_BUT, + B_IPO_DEPCHANGE, + ICON_ADD, + 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, ensuring that drivers will update correctly")); + UI_but_func_set(but, driver_add_var_cb, driver, NULL); + + /* copy/paste (as sub-row) */ + row = uiLayoutRow(row, true); + block = uiLayoutGetBlock(row); + + uiItemO(row, "", ICON_COPYDOWN, "GRAPH_OT_driver_variables_copy"); + uiItemO(row, "", ICON_PASTEDOWN, "GRAPH_OT_driver_variables_paste"); + } + + /* loop over targets, drawing them */ + for (dvar = driver->variables.first; dvar; dvar = dvar->next) { + PointerRNA dvar_ptr; + uiLayout *box; + uiLayout *subrow, *sub; + + /* sub-layout column for this variable's settings */ + col = uiLayoutColumn(layout, true); + + /* 1) header panel */ + box = uiLayoutBox(col); + RNA_pointer_create(id, &RNA_DriverVariable, dvar, &dvar_ptr); + + row = uiLayoutRow(box, false); + block = uiLayoutGetBlock(row); + + /* 1.1) variable type and name */ + subrow = uiLayoutRow(row, true); + + /* 1.1.1) variable type */ + + /* HACK: special group just for the enum, + * otherwise we get ugly layout with text included too... */ + sub = uiLayoutRow(subrow, true); + + uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT); + + uiItemR(sub, &dvar_ptr, "type", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); + + /* 1.1.2) variable name */ + + /* HACK: special group to counteract the effects of the previous enum, + * which now pushes everything too far right */ + sub = uiLayoutRow(subrow, true); + + uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_EXPAND); + + uiItemR(sub, &dvar_ptr, "name", 0, "", ICON_NONE); + + /* 1.2) invalid name? */ + UI_block_emboss_set(block, UI_EMBOSS_NONE); + + if (dvar->flag & DVAR_FLAG_INVALID_NAME) { + but = uiDefIconBut(block, + UI_BTYPE_BUT, + B_IPO_DEPCHANGE, + ICON_ERROR, + 290, + 0, + UI_UNIT_X, + UI_UNIT_Y, + NULL, + 0.0, + 0.0, + 0.0, + 0.0, + IFACE_("Invalid variable name, click here for details")); + UI_but_func_set(but, driver_dvar_invalid_name_query_cb, dvar, NULL); // XXX: reports? + } + + /* 1.3) remove button */ + but = uiDefIconBut(block, + UI_BTYPE_BUT, + B_IPO_DEPCHANGE, + ICON_X, + 290, + 0, + UI_UNIT_X, + UI_UNIT_Y, + NULL, + 0.0, + 0.0, + 0.0, + 0.0, + IFACE_("Delete target variable")); + UI_but_func_set(but, driver_delete_var_cb, driver, dvar); + UI_block_emboss_set(block, UI_EMBOSS); + + /* 2) variable type settings */ + box = uiLayoutBox(col); + /* controls to draw depends on the type of variable */ + switch (dvar->type) { + case DVAR_TYPE_SINGLE_PROP: /* single property */ + graph_panel_driverVar__singleProp(box, id, dvar); + break; + case DVAR_TYPE_ROT_DIFF: /* rotational difference */ + graph_panel_driverVar__rotDiff(box, id, dvar); + break; + case DVAR_TYPE_LOC_DIFF: /* location difference */ + graph_panel_driverVar__locDiff(box, id, dvar); + break; + case DVAR_TYPE_TRANSFORM_CHAN: /* transform channel */ + graph_panel_driverVar__transChan(box, id, dvar); + break; + } + + /* 3) value of variable */ + { + char valBuf[32]; + + box = uiLayoutBox(col); + row = uiLayoutRow(box, true); + uiItemL(row, IFACE_("Value:"), ICON_NONE); + + if ((dvar->type == DVAR_TYPE_ROT_DIFF) || + (dvar->type == DVAR_TYPE_TRANSFORM_CHAN && + dvar->targets[0].transChan >= DTAR_TRANSCHAN_ROTX && + dvar->targets[0].transChan < DTAR_TRANSCHAN_SCALEX)) { + BLI_snprintf( + valBuf, sizeof(valBuf), "%.3f (%4.1f°)", dvar->curval, RAD2DEGF(dvar->curval)); + } + else { + BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", dvar->curval); + } + + uiItemL(row, valBuf, ICON_NONE); + } + } + + 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; + bAnimListElem *ale; + FCurve *fcu; - if (!graph_panel_context(C, &ale, &fcu)) - return; + if (!graph_panel_context(C, &ale, &fcu)) + return; - graph_draw_driven_property_panel(pa->layout, ale->id, fcu); + graph_draw_driven_property_panel(pa->layout, ale->id, fcu); - MEM_freeN(ale); + 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; + bAnimListElem *ale; + FCurve *fcu; - /* Get settings from context */ - if (!graph_panel_context(C, &ale, &fcu)) - return; + /* Get settings from context */ + if (!graph_panel_context(C, &ale, &fcu)) + return; - graph_draw_driver_settings_panel(pa->layout, ale->id, fcu, false); + graph_draw_driver_settings_panel(pa->layout, ale->id, fcu, false); - /* cleanup */ - MEM_freeN(ale); + /* cleanup */ + MEM_freeN(ale); } /* ----------------------------------------------------------------- */ @@ -1048,205 +1226,206 @@ static void graph_panel_drivers(const bContext *C, Panel *pa) /* poll to make this not show up in the graph editor, as this is only to be used as a popup elsewhere */ static bool graph_panel_drivers_popover_poll(const bContext *C, PanelType *UNUSED(pt)) { - return ED_operator_graphedit_active((bContext *)C) == false; + 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"); + 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 */ -#define B_FMODIFIER_REDRAW 20 +#define B_FMODIFIER_REDRAW 20 static void do_graph_region_modifier_buttons(bContext *C, void *UNUSED(arg), int event) { - switch (event) { - case B_FMODIFIER_REDRAW: // XXX this should send depsgraph updates too - WM_event_add_notifier(C, NC_ANIMATION, NULL); // XXX need a notifier specially for F-Modifiers - break; - } + switch (event) { + case B_FMODIFIER_REDRAW: // XXX this should send depsgraph updates too + WM_event_add_notifier( + C, NC_ANIMATION, NULL); // XXX need a notifier specially for F-Modifiers + break; + } } static void graph_panel_modifiers(const bContext *C, Panel *pa) { - bAnimListElem *ale; - FCurve *fcu; - FModifier *fcm; - uiLayout *col, *row; - uiBlock *block; - bool active; - - if (!graph_panel_context(C, &ale, &fcu)) - return; - - block = uiLayoutGetBlock(pa->layout); - UI_block_func_handle_set(block, do_graph_region_modifier_buttons, NULL); - - /* 'add modifier' button at top of panel */ - { - row = uiLayoutRow(pa->layout, false); - - /* this is an operator button which calls a 'add modifier' operator... - * a menu might be nicer but would be tricky as we need some custom filtering - */ - uiItemMenuEnumO(row, (bContext *)C, "GRAPH_OT_fmodifier_add", "type", IFACE_("Add Modifier"), ICON_NONE); - - /* copy/paste (as sub-row) */ - row = uiLayoutRow(row, true); - uiItemO(row, "", ICON_COPYDOWN, "GRAPH_OT_fmodifier_copy"); - uiItemO(row, "", ICON_PASTEDOWN, "GRAPH_OT_fmodifier_paste"); - } - - active = !(fcu->flag & FCURVE_MOD_OFF); - /* draw each modifier */ - for (fcm = fcu->modifiers.first; fcm; fcm = fcm->next) { - col = uiLayoutColumn(pa->layout, true); - uiLayoutSetActive(col, active); - - ANIM_uiTemplate_fmodifier_draw(col, ale->fcurve_owner_id, &fcu->modifiers, fcm); - } - - MEM_freeN(ale); + bAnimListElem *ale; + FCurve *fcu; + FModifier *fcm; + uiLayout *col, *row; + uiBlock *block; + bool active; + + if (!graph_panel_context(C, &ale, &fcu)) + return; + + block = uiLayoutGetBlock(pa->layout); + UI_block_func_handle_set(block, do_graph_region_modifier_buttons, NULL); + + /* 'add modifier' button at top of panel */ + { + row = uiLayoutRow(pa->layout, false); + + /* this is an operator button which calls a 'add modifier' operator... + * a menu might be nicer but would be tricky as we need some custom filtering + */ + uiItemMenuEnumO( + row, (bContext *)C, "GRAPH_OT_fmodifier_add", "type", IFACE_("Add Modifier"), ICON_NONE); + + /* copy/paste (as sub-row) */ + row = uiLayoutRow(row, true); + uiItemO(row, "", ICON_COPYDOWN, "GRAPH_OT_fmodifier_copy"); + uiItemO(row, "", ICON_PASTEDOWN, "GRAPH_OT_fmodifier_paste"); + } + + active = !(fcu->flag & FCURVE_MOD_OFF); + /* draw each modifier */ + for (fcm = fcu->modifiers.first; fcm; fcm = fcm->next) { + col = uiLayoutColumn(pa->layout, true); + uiLayoutSetActive(col, active); + + ANIM_uiTemplate_fmodifier_draw(col, ale->fcurve_owner_id, &fcu->modifiers, fcm); + } + + MEM_freeN(ale); } /* ******************* general ******************************** */ void graph_buttons_register(ARegionType *art) { - PanelType *pt; - - pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel properties"); - strcpy(pt->idname, "GRAPH_PT_properties"); - strcpy(pt->label, N_("Active F-Curve")); - strcpy(pt->category, "F-Curve"); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = graph_panel_properties; - pt->poll = graph_panel_poll; - BLI_addtail(&art->paneltypes, pt); - - pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel properties"); - strcpy(pt->idname, "GRAPH_PT_key_properties"); - strcpy(pt->label, N_("Active Keyframe")); - strcpy(pt->category, "F-Curve"); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = graph_panel_key_properties; - 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_("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); - /* This panel isn't used in this region. - * Add explicitly to global list (so popovers work). */ - WM_paneltype_add(pt); - - pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel modifiers"); - strcpy(pt->idname, "GRAPH_PT_modifiers"); - strcpy(pt->label, N_("Modifiers")); - strcpy(pt->category, "Modifiers"); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = graph_panel_modifiers; - pt->poll = graph_panel_poll; - BLI_addtail(&art->paneltypes, pt); - - pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel view"); - strcpy(pt->idname, "GRAPH_PT_view"); - strcpy(pt->label, N_("View Properties")); - strcpy(pt->category, "View"); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = graph_panel_view; - BLI_addtail(&art->paneltypes, pt); + PanelType *pt; + + pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel properties"); + strcpy(pt->idname, "GRAPH_PT_properties"); + strcpy(pt->label, N_("Active F-Curve")); + strcpy(pt->category, "F-Curve"); + strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + pt->draw = graph_panel_properties; + pt->poll = graph_panel_poll; + BLI_addtail(&art->paneltypes, pt); + + pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel properties"); + strcpy(pt->idname, "GRAPH_PT_key_properties"); + strcpy(pt->label, N_("Active Keyframe")); + strcpy(pt->category, "F-Curve"); + strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + pt->draw = graph_panel_key_properties; + 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_("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); + /* This panel isn't used in this region. + * Add explicitly to global list (so popovers work). */ + WM_paneltype_add(pt); + + pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel modifiers"); + strcpy(pt->idname, "GRAPH_PT_modifiers"); + strcpy(pt->label, N_("Modifiers")); + strcpy(pt->category, "Modifiers"); + strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + pt->draw = graph_panel_modifiers; + pt->poll = graph_panel_poll; + BLI_addtail(&art->paneltypes, pt); + + pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel view"); + strcpy(pt->idname, "GRAPH_PT_view"); + strcpy(pt->label, N_("View Properties")); + strcpy(pt->category, "View"); + strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + pt->draw = graph_panel_view; + BLI_addtail(&art->paneltypes, pt); } static int graph_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op)) { - ScrArea *sa = CTX_wm_area(C); - ARegion *ar = graph_has_buttons_region(sa); + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = graph_has_buttons_region(sa); - if (ar) - ED_region_toggle_hidden(C, ar); + if (ar) + ED_region_toggle_hidden(C, ar); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_properties(wmOperatorType *ot) { - ot->name = "Toggle Sidebar"; - ot->idname = "GRAPH_OT_properties"; - ot->description = "Toggle the properties region visibility"; + ot->name = "Toggle Sidebar"; + ot->idname = "GRAPH_OT_properties"; + ot->description = "Toggle the properties region visibility"; - ot->exec = graph_properties_toggle_exec; - ot->poll = ED_operator_graphedit_active; + ot->exec = graph_properties_toggle_exec; + ot->poll = ED_operator_graphedit_active; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; } diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index 52f45a66c0d..5bfe1c1aadd 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -20,7 +20,6 @@ * \ingroup spgraph */ - #include <stdio.h> #include <math.h> #include <string.h> @@ -40,7 +39,6 @@ #include "BKE_curve.h" #include "BKE_fcurve.h" - #include "GPU_draw.h" #include "GPU_immediate.h" #include "GPU_matrix.h" @@ -63,7 +61,7 @@ */ static float fcurve_display_alpha(FCurve *fcu) { - return (fcu->flag & FCURVE_SELECTED) ? 1.0f : U.fcu_inactive_alpha; + return (fcu->flag & FCURVE_SELECTED) ? 1.0f : U.fcu_inactive_alpha; } /* *************************** */ @@ -74,63 +72,64 @@ static float fcurve_display_alpha(FCurve *fcu) /* TODO: draw a shaded poly showing the region of influence too!!! */ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d) { - FMod_Envelope *env = (FMod_Envelope *)fcm->data; - FCM_EnvelopeData *fed; - const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur); - int i; + FMod_Envelope *env = (FMod_Envelope *)fcm->data; + FCM_EnvelopeData *fed; + const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur); + int i; - const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + const uint shdr_pos = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - GPU_line_width(1.0f); + GPU_line_width(1.0f); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); - float viewport_size[4]; - GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + float viewport_size[4]; + GPU_viewport_size_get_f(viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); - immUniform1i("colors_len", 0); /* Simple dashes. */ - immUniformColor3f(0.0f, 0.0f, 0.0f); - immUniform1f("dash_width", 10.0f); - immUniform1f("dash_factor", 0.5f); + immUniform1i("colors_len", 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 */ + /* draw two black lines showing the standard reference levels */ - immBegin(GPU_PRIM_LINES, 4); - immVertex2f(shdr_pos, v2d->cur.xmin, env->midval + env->min); - immVertex2f(shdr_pos, v2d->cur.xmax, env->midval + env->min); + immBegin(GPU_PRIM_LINES, 4); + immVertex2f(shdr_pos, v2d->cur.xmin, env->midval + env->min); + immVertex2f(shdr_pos, v2d->cur.xmax, env->midval + env->min); - immVertex2f(shdr_pos, v2d->cur.xmin, env->midval + env->max); - immVertex2f(shdr_pos, v2d->cur.xmax, env->midval + env->max); - immEnd(); + immVertex2f(shdr_pos, v2d->cur.xmin, env->midval + env->max); + immVertex2f(shdr_pos, v2d->cur.xmax, env->midval + env->max); + immEnd(); - immUnbindProgram(); + immUnbindProgram(); - if (env->totvert > 0) { - /* set size of vertices (non-adjustable for now) */ - GPU_point_size(2.0f); + if (env->totvert > 0) { + /* set size of vertices (non-adjustable for now) */ + GPU_point_size(2.0f); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - /* for now, point color is fixed, and is white */ - immUniformColor3f(1.0f, 1.0f, 1.0f); + /* for now, point color is fixed, and is white */ + immUniformColor3f(1.0f, 1.0f, 1.0f); - immBeginAtMost(GPU_PRIM_POINTS, env->totvert * 2); + immBeginAtMost(GPU_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); - } - } + 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(); + immEnd(); - immUnbindProgram(); - } + immUnbindProgram(); + } } /* *************************** */ @@ -141,283 +140,282 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d) /* helper func - set color to draw F-Curve data with */ static void set_fcurve_vertex_color(FCurve *fcu, bool sel) { - float color[4]; - float diff; - - /* 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_GetThemeColor3fv(sel ? TH_VERTEX_SELECT : TH_VERTEX, color); - } - else { - /* Curve's points CANNOT BE edited */ - UI_GetThemeColor3fv(sel ? TH_TEXT_HI : TH_TEXT, color); - } - - /* Fade the 'intensity' of the vertices based on the selection of the curves too - * - Only fade by 50% the amount the curves were faded by, so that the points - * still stand out for easier selection - */ - diff = 1.0f - fcurve_display_alpha(fcu); - color[3] = 1.0f - (diff * 0.5f); - CLAMP(color[3], 0.2f, 1.0f); - - immUniformColor4fv(color); + float color[4]; + float diff; + + /* 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_GetThemeColor3fv(sel ? TH_VERTEX_SELECT : TH_VERTEX, color); + } + else { + /* Curve's points CANNOT BE edited */ + UI_GetThemeColor3fv(sel ? TH_TEXT_HI : TH_TEXT, color); + } + + /* Fade the 'intensity' of the vertices based on the selection of the curves too + * - Only fade by 50% the amount the curves were faded by, so that the points + * still stand out for easier selection + */ + diff = 1.0f - fcurve_display_alpha(fcu); + color[3] = 1.0f - (diff * 0.5f); + CLAMP(color[3], 0.2f, 1.0f); + + immUniformColor4fv(color); } -static void draw_fcurve_selected_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, bool sel, unsigned pos) +static void draw_fcurve_selected_keyframe_vertices( + FCurve *fcu, View2D *v2d, bool edit, bool sel, unsigned pos) { - const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur); - - set_fcurve_vertex_color(fcu, sel); - - immBeginAtMost(GPU_PRIM_POINTS, fcu->totvert); - - 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 - */ - if (IN_RANGE(bezt->vec[1][0], (v2d->cur.xmin - fac), (v2d->cur.xmax + fac))) { - if (edit) { - /* 'Keyframe' vertex only, as handle lines and handles have already been drawn - * - only draw those with correct selection state for the current drawing color - * - - */ - if ((bezt->f2 & SELECT) == sel) - 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 */ - immVertex2fv(pos, bezt->vec[1]); - } - } - } - - immEnd(); + const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur); + + set_fcurve_vertex_color(fcu, sel); + + immBeginAtMost(GPU_PRIM_POINTS, fcu->totvert); + + 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 + */ + if (IN_RANGE(bezt->vec[1][0], (v2d->cur.xmin - fac), (v2d->cur.xmax + fac))) { + if (edit) { + /* 'Keyframe' vertex only, as handle lines and handles have already been drawn + * - only draw those with correct selection state for the current drawing color + * - + */ + if ((bezt->f2 & SELECT) == sel) + 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 */ + immVertex2fv(pos, bezt->vec[1]); + } + } + } + + immEnd(); } /* helper func - draw keyframe vertices only for an F-Curve */ static void draw_fcurve_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, unsigned pos) { - immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); + immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); - immUniform1f("size", UI_GetThemeValuef(TH_VERTEX_SIZE) * U.pixelsize); + immUniform1f("size", UI_GetThemeValuef(TH_VERTEX_SIZE) * U.pixelsize); - draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, false, pos); - draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, true, pos); + draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, false, pos); + draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, true, pos); - immUnbindProgram(); + immUnbindProgram(); } - /* helper func - draw handle vertices only for an F-Curve (if it is not protected) */ -static void draw_fcurve_selected_handle_vertices(FCurve *fcu, View2D *v2d, bool sel, bool sel_handle_only, unsigned pos) +static void draw_fcurve_selected_handle_vertices( + FCurve *fcu, View2D *v2d, bool sel, bool sel_handle_only, unsigned pos) { - (void) v2d; /* TODO: use this to draw only points in view */ - - /* set handle color */ - 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 */ - - immBeginAtMost(GPU_PRIM_POINTS, fcu->totvert * 2); - - 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 - * - second handle only if current beztriple is bezier-mode - * - * Also, need to take into account whether the keyframe was selected - * if a Graph Editor option to only show handles of selected keys is on. - */ - 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) */ ) - { - 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) */ ) - { - immVertex2fv(pos, bezt->vec[2]); - } - } - } - } - - immEnd(); + (void)v2d; /* TODO: use this to draw only points in view */ + + /* set handle color */ + 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 */ + + immBeginAtMost(GPU_PRIM_POINTS, fcu->totvert * 2); + + 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 + * - second handle only if current beztriple is bezier-mode + * + * Also, need to take into account whether the keyframe was selected + * if a Graph Editor option to only show handles of selected keys is on. + */ + 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) */) { + 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) */) { + immVertex2fv(pos, bezt->vec[2]); + } + } + } + } + + immEnd(); } /* 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) +static void draw_fcurve_handle_vertices(FCurve *fcu, + View2D *v2d, + bool sel_handle_only, + unsigned pos) { - /* smooth outlines for more consistent appearance */ - immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA); + /* smooth outlines for more consistent appearance */ + immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA); - /* set handle size */ - immUniform1f("size", (1.4f * UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE)) * U.pixelsize); - immUniform1f("outlineWidth", 1.5f * U.pixelsize); + /* 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); + 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(); + immUnbindProgram(); } - static void draw_fcurve_vertices(ARegion *ar, FCurve *fcu, bool do_handles, bool sel_handle_only) { - View2D *v2d = &ar->v2d; + View2D *v2d = &ar->v2d; - /* only draw points if curve is 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) - */ + /* only draw points if curve is 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) + */ - uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - GPU_blend(true); - GPU_enable_program_point_size(); + GPU_blend(true); + 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) { - draw_fcurve_handle_vertices(fcu, v2d, sel_handle_only, pos); - } + /* 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) { + draw_fcurve_handle_vertices(fcu, v2d, sel_handle_only, pos); + } - /* draw keyframes over the handles */ - draw_fcurve_keyframe_vertices(fcu, v2d, !(fcu->flag & FCURVE_PROTECTED), pos); + /* draw keyframes over the handles */ + draw_fcurve_keyframe_vertices(fcu, v2d, !(fcu->flag & FCURVE_PROTECTED), pos); - GPU_disable_program_point_size(); - GPU_blend(false); + GPU_disable_program_point_size(); + GPU_blend(false); } /* Handles ---------------- */ static bool draw_fcurve_handles_check(SpaceGraph *sipo, FCurve *fcu) { - /* don't draw handle lines if handles are not to be shown */ - if ( - /* handles shouldn't be shown anywhere */ - (sipo->flag & SIPO_NOHANDLES) || - /* keyframes aren't editable */ - (fcu->flag & FCURVE_PROTECTED) || -#if 0 /* handles can still be selected and handle types set, better draw - campbell */ - /* editing the handles here will cause weird/incorrect interpolation issues */ - (fcu->flag & FCURVE_INT_VALUES) || + /* don't draw handle lines if handles are not to be shown */ + if ( + /* handles shouldn't be shown anywhere */ + (sipo->flag & SIPO_NOHANDLES) || + /* keyframes aren't editable */ + (fcu->flag & FCURVE_PROTECTED) || +#if 0 /* handles can still be selected and handle types set, better draw - campbell */ + /* editing the handles here will cause weird/incorrect interpolation issues */ + (fcu->flag & FCURVE_INT_VALUES) || #endif - /* group that curve belongs to is not editable */ - ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) || - /* do not show handles if there is only 1 keyframe, - * otherwise they all clump together in an ugly ball */ - (fcu->totvert <= 1) - ) - { - return false; - } - else { - return true; - } + /* group that curve belongs to is not editable */ + ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) || + /* do not show handles if there is only 1 keyframe, + * otherwise they all clump together in an ugly ball */ + (fcu->totvert <= 1)) { + return false; + } + else { + return true; + } } /* draw lines for F-Curve handles only (this is only done in EditMode) * note: draw_fcurve_handles_check must be checked before running this. */ static void draw_fcurve_handles(SpaceGraph *sipo, FCurve *fcu) { - int sel, b; - - GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); - - immBeginAtMost(GPU_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 - */ - for (sel = 0; sel < 2; sel++) { - BezTriple *bezt = fcu->bezt, *prevbezt = NULL; - int basecol = (sel) ? TH_HANDLE_SEL_FREE : TH_HANDLE_FREE; - const float *fp; - unsigned char col[4]; - - for (b = 0; b < fcu->totvert; b++, prevbezt = bezt, bezt++) { - /* if only selected keyframes can get their handles shown, - * check that keyframe is selected - */ - if (sipo->flag & SIPO_SELVHANDLESONLY) { - if (BEZT_ISSEL_ANY(bezt) == 0) - continue; - } - - /* draw handle with appropriate set of colors if selection is ok */ - if ((bezt->f2 & SELECT) == sel) { - fp = bezt->vec[0]; - - /* only draw first handle if previous segment had handles */ - 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; - immAttr4ubv(color, col); - immVertex2fv(pos, fp); - immAttr4ubv(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; - immAttr4ubv(color, col); - immVertex2fv(pos, fp + 3); - immAttr4ubv(color, col); - immVertex2fv(pos, fp + 6); - } - } - else { - /* only draw first handle if previous segment was had handles, and selection is ok */ - if (((bezt->f1 & SELECT) == sel) && - ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ)))) - { - fp = bezt->vec[0]; - UI_GetThemeColor3ubv(basecol + bezt->h1, col); - col[3] = fcurve_display_alpha(fcu) * 255; - immAttr4ubv(color, col); - immVertex2fv(pos, fp); - immAttr4ubv(color, col); - immVertex2fv(pos, fp + 3); - } - - /* only draw second handle if this segment is bezier, and selection is ok */ - if (((bezt->f3 & SELECT) == sel) && - (bezt->ipo == BEZT_IPO_BEZ)) - { - fp = bezt->vec[1]; - UI_GetThemeColor3ubv(basecol + bezt->h2, col); - col[3] = fcurve_display_alpha(fcu) * 255; - immAttr4ubv(color, col); - immVertex2fv(pos, fp); - immAttr4ubv(color, col); - immVertex2fv(pos, fp + 3); - } - } - } - } - - immEnd(); - immUnbindProgram(); + int sel, b; + + GPUVertFormat *format = immVertexFormat(); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + uint color = GPU_vertformat_attr_add( + format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + + immBeginAtMost(GPU_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 + */ + for (sel = 0; sel < 2; sel++) { + BezTriple *bezt = fcu->bezt, *prevbezt = NULL; + int basecol = (sel) ? TH_HANDLE_SEL_FREE : TH_HANDLE_FREE; + const float *fp; + unsigned char col[4]; + + for (b = 0; b < fcu->totvert; b++, prevbezt = bezt, bezt++) { + /* if only selected keyframes can get their handles shown, + * check that keyframe is selected + */ + if (sipo->flag & SIPO_SELVHANDLESONLY) { + if (BEZT_ISSEL_ANY(bezt) == 0) + continue; + } + + /* draw handle with appropriate set of colors if selection is ok */ + if ((bezt->f2 & SELECT) == sel) { + fp = bezt->vec[0]; + + /* only draw first handle if previous segment had handles */ + 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; + immAttr4ubv(color, col); + immVertex2fv(pos, fp); + immAttr4ubv(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; + immAttr4ubv(color, col); + immVertex2fv(pos, fp + 3); + immAttr4ubv(color, col); + immVertex2fv(pos, fp + 6); + } + } + else { + /* only draw first handle if previous segment was had handles, and selection is ok */ + if (((bezt->f1 & SELECT) == sel) && ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) || + (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ)))) { + fp = bezt->vec[0]; + UI_GetThemeColor3ubv(basecol + bezt->h1, col); + col[3] = fcurve_display_alpha(fcu) * 255; + immAttr4ubv(color, col); + immVertex2fv(pos, fp); + immAttr4ubv(color, col); + immVertex2fv(pos, fp + 3); + } + + /* only draw second handle if this segment is bezier, and selection is ok */ + if (((bezt->f3 & SELECT) == sel) && (bezt->ipo == BEZT_IPO_BEZ)) { + fp = bezt->vec[1]; + UI_GetThemeColor3ubv(basecol + bezt->h2, col); + col[3] = fcurve_display_alpha(fcu) * 255; + immAttr4ubv(color, col); + immVertex2fv(pos, fp); + immAttr4ubv(color, col); + immVertex2fv(pos, fp + 3); + } + } + } + } + + immEnd(); + immUnbindProgram(); } /* Samples ---------------- */ @@ -426,230 +424,236 @@ static void draw_fcurve_handles(SpaceGraph *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, unsigned int pos) +static void draw_fcurve_sample_control( + float x, float y, float xscale, float yscale, float hsize, unsigned int pos) { - /* adjust view transform before starting */ - GPU_matrix_push(); - GPU_matrix_translate_2f(x, y); - GPU_matrix_scale_2f(1.0f / xscale * hsize, 1.0f / yscale * hsize); - - /* draw X shape */ - immBegin(GPU_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 */ - GPU_matrix_pop(); + /* adjust view transform before starting */ + GPU_matrix_push(); + GPU_matrix_translate_2f(x, y); + GPU_matrix_scale_2f(1.0f / xscale * hsize, 1.0f / yscale * hsize); + + /* draw X shape */ + immBegin(GPU_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 */ + GPU_matrix_pop(); } /* helper func - draw keyframe vertices only for an F-Curve */ static void draw_fcurve_samples(SpaceGraph *sipo, ARegion *ar, FCurve *fcu) { - FPoint *first, *last; - float hsize, xscale, yscale; + FPoint *first, *last; + float hsize, xscale, yscale; - /* get view settings */ - hsize = UI_GetThemeValuef(TH_VERTEX_SIZE); - UI_view2d_scale_get(&ar->v2d, &xscale, &yscale); + /* get view settings */ + hsize = UI_GetThemeValuef(TH_VERTEX_SIZE); + UI_view2d_scale_get(&ar->v2d, &xscale, &yscale); - /* get verts */ - first = fcu->fpt; - last = (first) ? (first + (fcu->totvert - 1)) : (NULL); + /* get verts */ + first = fcu->fpt; + last = (first) ? (first + (fcu->totvert - 1)) : (NULL); - /* draw */ - if (first && last) { - /* anti-aliased lines for more consistent appearance */ - if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) GPU_line_smooth(true); - GPU_blend(true); + /* draw */ + if (first && last) { + /* anti-aliased lines for more consistent appearance */ + if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) + GPU_line_smooth(true); + GPU_blend(true); - uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - immUniformThemeColor((fcu->flag & FCURVE_SELECTED) ? TH_TEXT_HI : TH_TEXT); + 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); + 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(); + immUnbindProgram(); - GPU_blend(false); - if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) GPU_line_smooth(false); - } + GPU_blend(false); + if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) + GPU_line_smooth(false); + } } /* 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, unsigned int pos) +static void draw_fcurve_curve( + bAnimContext *ac, ID *id, FCurve *fcu_, View2D *v2d, View2DGrid *grid, unsigned int pos) { - SpaceGraph *sipo = (SpaceGraph *)ac->sl; - float samplefreq; - float stime, etime; - float unitFac, offset; - float dx, dy; - short mapping_flag = ANIM_get_normalization_flags(ac); - int i, n; - - /* when opening a blend file on a different sized screen or while dragging the toolbar this can happen - * best just bail out in this case */ - UI_view2d_grid_size(grid, &dx, &dy); - if (dx <= 0.0f) - return; - - - /* disable any drivers */ - FCurve fcurve_for_draw = *fcu_; - fcurve_for_draw.driver = NULL; - - /* compute unit correction factor */ - unitFac = ANIM_unit_mapping_get_factor(ac->scene, id, &fcurve_for_draw, mapping_flag, &offset); - - /* Note about sampling frequency: - * Ideally, this is chosen such that we have 1-2 pixels = 1 segment - * which means that our curves can be as smooth as possible. However, - * this does mean that curves may not be fully accurate (i.e. if they have - * sudden spikes which happen at the sampling point, we may have problems). - * Also, this may introduce lower performance on less densely detailed curves, - * though it is impossible to predict this from the modifiers! - * - * If the automatically determined sampling frequency is likely to cause an infinite - * loop (i.e. too close to 0), then clamp it to a determined "safe" value. The value - * chosen here is just the coarsest value which still looks reasonable... - */ - /* grid->dx represents the number of 'frames' between gridlines, - * but we divide by U.v2d_min_gridsize to get pixels-steps */ - /* TODO: perhaps we should have 1.0 frames as upper limit so that curves don't get too distorted? */ - samplefreq = dx / (U.v2d_min_gridsize * U.pixelsize); - - if (sipo->flag & SIPO_BEAUTYDRAW_OFF) { - /* Low Precision = coarse lower-bound clamping - * - * Although the "Beauty Draw" flag was originally for AA'd - * line drawing, the sampling rate here has a much greater - * impact on performance (e.g. for T40372)! - * - * This one still amounts to 10 sample-frames for each 1-frame interval - * which should be quite a decent approximation in many situations. - */ - if (samplefreq < 0.1f) - samplefreq = 0.1f; - } - else { - /* "Higher Precision" but slower - especially on larger windows (e.g. T40372) */ - if (samplefreq < 0.00001f) - samplefreq = 0.00001f; - } - - - /* the start/end times are simply the horizontal extents of the 'cur' rect */ - stime = v2d->cur.xmin; - etime = v2d->cur.xmax + samplefreq; /* + samplefreq here so that last item gets included... */ - - - /* at each sampling interval, add a new vertex - * - apply the unit correction factor to the calculated values so that - * the displayed values appear correctly in the viewport - */ - - n = (etime - stime) / samplefreq + 0.5f; - - if (n > 0) { - immBegin(GPU_PRIM_LINE_STRIP, (n + 1)); - - for (i = 0; i <= n; i++) { - float ctime = stime + i * samplefreq; - immVertex2f(pos, ctime, (evaluate_fcurve(&fcurve_for_draw, ctime) + offset) * unitFac); - } - - immEnd(); - } + SpaceGraph *sipo = (SpaceGraph *)ac->sl; + float samplefreq; + float stime, etime; + float unitFac, offset; + float dx, dy; + short mapping_flag = ANIM_get_normalization_flags(ac); + int i, n; + + /* when opening a blend file on a different sized screen or while dragging the toolbar this can happen + * best just bail out in this case */ + UI_view2d_grid_size(grid, &dx, &dy); + if (dx <= 0.0f) + return; + + /* disable any drivers */ + FCurve fcurve_for_draw = *fcu_; + fcurve_for_draw.driver = NULL; + + /* compute unit correction factor */ + unitFac = ANIM_unit_mapping_get_factor(ac->scene, id, &fcurve_for_draw, mapping_flag, &offset); + + /* Note about sampling frequency: + * Ideally, this is chosen such that we have 1-2 pixels = 1 segment + * which means that our curves can be as smooth as possible. However, + * this does mean that curves may not be fully accurate (i.e. if they have + * sudden spikes which happen at the sampling point, we may have problems). + * Also, this may introduce lower performance on less densely detailed curves, + * though it is impossible to predict this from the modifiers! + * + * If the automatically determined sampling frequency is likely to cause an infinite + * loop (i.e. too close to 0), then clamp it to a determined "safe" value. The value + * chosen here is just the coarsest value which still looks reasonable... + */ + /* grid->dx represents the number of 'frames' between gridlines, + * but we divide by U.v2d_min_gridsize to get pixels-steps */ + /* TODO: perhaps we should have 1.0 frames as upper limit so that curves don't get too distorted? */ + samplefreq = dx / (U.v2d_min_gridsize * U.pixelsize); + + if (sipo->flag & SIPO_BEAUTYDRAW_OFF) { + /* Low Precision = coarse lower-bound clamping + * + * Although the "Beauty Draw" flag was originally for AA'd + * line drawing, the sampling rate here has a much greater + * impact on performance (e.g. for T40372)! + * + * This one still amounts to 10 sample-frames for each 1-frame interval + * which should be quite a decent approximation in many situations. + */ + if (samplefreq < 0.1f) + samplefreq = 0.1f; + } + else { + /* "Higher Precision" but slower - especially on larger windows (e.g. T40372) */ + if (samplefreq < 0.00001f) + samplefreq = 0.00001f; + } + + /* the start/end times are simply the horizontal extents of the 'cur' rect */ + stime = v2d->cur.xmin; + etime = v2d->cur.xmax + samplefreq; /* + samplefreq here so that last item gets included... */ + + /* at each sampling interval, add a new vertex + * - apply the unit correction factor to the calculated values so that + * the displayed values appear correctly in the viewport + */ + + n = (etime - stime) / samplefreq + 0.5f; + + if (n > 0) { + immBegin(GPU_PRIM_LINE_STRIP, (n + 1)); + + for (i = 0; i <= n; i++) { + float ctime = stime + i * samplefreq; + immVertex2f(pos, ctime, (evaluate_fcurve(&fcurve_for_draw, ctime) + offset) * unitFac); + } + + immEnd(); + } } /* helper func - draw a samples-based F-Curve */ -static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, const uint shdr_pos) +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; - 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 */ - GPU_matrix_push(); - unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset); - GPU_matrix_scale_2f(1.0f, unit_scale); - GPU_matrix_translate_2f(0.0f, offset); - - immBegin(GPU_PRIM_LINE_STRIP, count); - - /* extrapolate to left? - left-side of view comes before first keyframe? */ - if (prevfpt->vec[0] > v2d->cur.xmin) { - v[0] = v2d->cur.xmin; - - /* y-value depends on the interpolation */ - if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (fcu->totvert == 1)) { - /* just extend across the first keyframe's value */ - v[1] = prevfpt->vec[1]; - } - else { - /* extrapolate linear doesn't use the handle, use the next points center instead */ - fac = (prevfpt->vec[0] - fpt->vec[0]) / (prevfpt->vec[0] - v[0]); - if (fac) fac = 1.0f / fac; - v[1] = prevfpt->vec[1] - fac * (prevfpt->vec[1] - fpt->vec[1]); - } - - immVertex2fv(shdr_pos, v); - } - - /* 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) */ - immVertex2fv(shdr_pos, prevfpt->vec); - - /* get next pointers */ - if (b > 0) { - prevfpt++; - } - } - - /* extrapolate to right? (see code for left-extrapolation above too) */ - if (prevfpt->vec[0] < v2d->cur.xmax) { - v[0] = v2d->cur.xmax; - - /* y-value depends on the interpolation */ - if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (fcu->totvert == 1)) { - /* based on last keyframe's value */ - v[1] = prevfpt->vec[1]; - } - else { - /* extrapolate linear doesn't use the handle, use the previous points center instead */ - fpt = prevfpt - 1; - fac = (prevfpt->vec[0] - fpt->vec[0]) / (prevfpt->vec[0] - v[0]); - if (fac) fac = 1.0f / fac; - v[1] = prevfpt->vec[1] - fac * (prevfpt->vec[1] - fpt->vec[1]); - } - - immVertex2fv(shdr_pos, v); - } - - immEnd(); - - GPU_matrix_pop(); + FPoint *prevfpt = fcu->fpt; + FPoint *fpt = prevfpt + 1; + float fac, v[2]; + 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 */ + GPU_matrix_push(); + unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset); + GPU_matrix_scale_2f(1.0f, unit_scale); + GPU_matrix_translate_2f(0.0f, offset); + + immBegin(GPU_PRIM_LINE_STRIP, count); + + /* extrapolate to left? - left-side of view comes before first keyframe? */ + if (prevfpt->vec[0] > v2d->cur.xmin) { + v[0] = v2d->cur.xmin; + + /* y-value depends on the interpolation */ + if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || + (fcu->totvert == 1)) { + /* just extend across the first keyframe's value */ + v[1] = prevfpt->vec[1]; + } + else { + /* extrapolate linear doesn't use the handle, use the next points center instead */ + fac = (prevfpt->vec[0] - fpt->vec[0]) / (prevfpt->vec[0] - v[0]); + if (fac) + fac = 1.0f / fac; + v[1] = prevfpt->vec[1] - fac * (prevfpt->vec[1] - fpt->vec[1]); + } + + immVertex2fv(shdr_pos, v); + } + + /* 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) */ + immVertex2fv(shdr_pos, prevfpt->vec); + + /* get next pointers */ + if (b > 0) { + prevfpt++; + } + } + + /* extrapolate to right? (see code for left-extrapolation above too) */ + if (prevfpt->vec[0] < v2d->cur.xmax) { + v[0] = v2d->cur.xmax; + + /* y-value depends on the interpolation */ + if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || + (fcu->totvert == 1)) { + /* based on last keyframe's value */ + v[1] = prevfpt->vec[1]; + } + else { + /* extrapolate linear doesn't use the handle, use the previous points center instead */ + fpt = prevfpt - 1; + fac = (prevfpt->vec[0] - fpt->vec[0]) / (prevfpt->vec[0] - v[0]); + if (fac) + fac = 1.0f / fac; + v[1] = prevfpt->vec[1] - fac * (prevfpt->vec[1] - fpt->vec[1]); + } + + immVertex2fv(shdr_pos, v); + } + + immEnd(); + + GPU_matrix_pop(); } /* helper func - check if the F-Curve only contains easily drawable segments @@ -657,183 +661,192 @@ static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, Vie */ static bool fcurve_can_use_simple_bezt_drawing(FCurve *fcu) { - BezTriple *bezt; - int i; + BezTriple *bezt; + int i; - for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { - if (ELEM(bezt->ipo, BEZT_IPO_CONST, BEZT_IPO_LIN, BEZT_IPO_BEZ) == false) { - return false; - } - } + for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { + if (ELEM(bezt->ipo, BEZT_IPO_CONST, BEZT_IPO_LIN, BEZT_IPO_BEZ) == false) { + return false; + } + } - return true; + return true; } /* 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, unsigned int pos) +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; - float v1[2], v2[2], v3[2], v4[2]; - float *fp, data[120]; - float fac = 0.0f; - int b = fcu->totvert - 1; - int resol; - float unit_scale, offset; - short mapping_flag = ANIM_get_normalization_flags(ac); - - /* apply unit mapping */ - GPU_matrix_push(); - unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset); - GPU_matrix_scale_2f(1.0f, unit_scale); - GPU_matrix_translate_2f(0.0f, offset); - - /* 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(GPU_PRIM_LINE_STRIP, (b * 32 + 3)); - - /* extrapolate to left? */ - if (prevbezt->vec[1][0] > v2d->cur.xmin) { - /* left-side of view comes before first keyframe, so need to extend as not cyclic */ - v1[0] = v2d->cur.xmin; - - /* y-value depends on the interpolation */ - if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (prevbezt->ipo == BEZT_IPO_CONST) || (fcu->totvert == 1)) { - /* just extend across the first keyframe's value */ - v1[1] = prevbezt->vec[1][1]; - } - else if (prevbezt->ipo == BEZT_IPO_LIN) { - /* extrapolate linear dosnt use the handle, use the next points center instead */ - fac = (prevbezt->vec[1][0] - bezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]); - if (fac) fac = 1.0f / fac; - v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[1][1] - bezt->vec[1][1]); - } - else { - /* based on angle of handle 1 (relative to keyframe) */ - fac = (prevbezt->vec[0][0] - prevbezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]); - if (fac) fac = 1.0f / fac; - v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[0][1] - prevbezt->vec[1][1]); - } - - 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]; - immVertex2fv(pos, v1); - } - - /* draw curve between first and last keyframe (if there are enough to do so) */ - /* TODO: optimize this to not have to calc stuff out of view too? */ - while (b--) { - if (prevbezt->ipo == BEZT_IPO_CONST) { - /* 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]; - immVertex2fv(pos, v1); - - v1[0] = bezt->vec[1][0]; - v1[1] = prevbezt->vec[1][1]; - 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]; - immVertex2fv(pos, v1); - } - else if (prevbezt->ipo == BEZT_IPO_BEZ) { - /* Bezier-Interpolation: draw curve as series of segments between keyframes - * - resol determines number of points to sample in between keyframes - */ - - /* resol depends on distance between points - * (not just horizontal) OR is a fixed high res */ - /* TODO: view scale should factor into this someday too... */ - if (fcu->driver) { - resol = 32; - } - else { - resol = (int)(5.0f * len_v2v2(bezt->vec[1], prevbezt->vec[1])); - } - - if (resol < 2) { - /* only draw one */ - v1[0] = prevbezt->vec[1][0]; - v1[1] = prevbezt->vec[1][1]; - immVertex2fv(pos, v1); - } - else { - /* clamp resolution to max of 32 */ - /* NOTE: higher values will crash */ - if (resol > 32) resol = 32; - - v1[0] = prevbezt->vec[1][0]; - v1[1] = prevbezt->vec[1][1]; - v2[0] = prevbezt->vec[2][0]; - v2[1] = prevbezt->vec[2][1]; - - v3[0] = bezt->vec[0][0]; - v3[1] = bezt->vec[0][1]; - v4[0] = bezt->vec[1][0]; - v4[1] = bezt->vec[1][1]; - - correct_bezpart(v1, v2, v3, v4); - - 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) { - immVertex2fv(pos, fp); - } - } - } - - /* get next pointers */ - prevbezt = bezt; - bezt++; - - /* last point? */ - if (b == 0) { - v1[0] = prevbezt->vec[1][0]; - v1[1] = prevbezt->vec[1][1]; - immVertex2fv(pos, v1); - } - } - - /* extrapolate to right? (see code for left-extrapolation above too) */ - if (prevbezt->vec[1][0] < v2d->cur.xmax) { - v1[0] = v2d->cur.xmax; - - /* y-value depends on the interpolation */ - if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (prevbezt->ipo == BEZT_IPO_CONST) || (fcu->totvert == 1)) { - /* based on last keyframe's value */ - v1[1] = prevbezt->vec[1][1]; - } - else if (prevbezt->ipo == BEZT_IPO_LIN) { - /* extrapolate linear dosnt use the handle, use the previous points center instead */ - bezt = prevbezt - 1; - fac = (prevbezt->vec[1][0] - bezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]); - if (fac) fac = 1.0f / fac; - v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[1][1] - bezt->vec[1][1]); - } - else { - /* based on angle of handle 1 (relative to keyframe) */ - fac = (prevbezt->vec[2][0] - prevbezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]); - if (fac) fac = 1.0f / fac; - v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[2][1] - prevbezt->vec[1][1]); - } - - immVertex2fv(pos, v1); - } - - immEnd(); - - GPU_matrix_pop(); + BezTriple *prevbezt = fcu->bezt; + BezTriple *bezt = prevbezt + 1; + float v1[2], v2[2], v3[2], v4[2]; + float *fp, data[120]; + float fac = 0.0f; + int b = fcu->totvert - 1; + int resol; + float unit_scale, offset; + short mapping_flag = ANIM_get_normalization_flags(ac); + + /* apply unit mapping */ + GPU_matrix_push(); + unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset); + GPU_matrix_scale_2f(1.0f, unit_scale); + GPU_matrix_translate_2f(0.0f, offset); + + /* 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(GPU_PRIM_LINE_STRIP, (b * 32 + 3)); + + /* extrapolate to left? */ + if (prevbezt->vec[1][0] > v2d->cur.xmin) { + /* left-side of view comes before first keyframe, so need to extend as not cyclic */ + v1[0] = v2d->cur.xmin; + + /* y-value depends on the interpolation */ + if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (prevbezt->ipo == BEZT_IPO_CONST) || + (fcu->totvert == 1)) { + /* just extend across the first keyframe's value */ + v1[1] = prevbezt->vec[1][1]; + } + else if (prevbezt->ipo == BEZT_IPO_LIN) { + /* extrapolate linear dosnt use the handle, use the next points center instead */ + fac = (prevbezt->vec[1][0] - bezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]); + if (fac) + fac = 1.0f / fac; + v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[1][1] - bezt->vec[1][1]); + } + else { + /* based on angle of handle 1 (relative to keyframe) */ + fac = (prevbezt->vec[0][0] - prevbezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]); + if (fac) + fac = 1.0f / fac; + v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[0][1] - prevbezt->vec[1][1]); + } + + 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]; + immVertex2fv(pos, v1); + } + + /* draw curve between first and last keyframe (if there are enough to do so) */ + /* TODO: optimize this to not have to calc stuff out of view too? */ + while (b--) { + if (prevbezt->ipo == BEZT_IPO_CONST) { + /* 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]; + immVertex2fv(pos, v1); + + v1[0] = bezt->vec[1][0]; + v1[1] = prevbezt->vec[1][1]; + 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]; + immVertex2fv(pos, v1); + } + else if (prevbezt->ipo == BEZT_IPO_BEZ) { + /* Bezier-Interpolation: draw curve as series of segments between keyframes + * - resol determines number of points to sample in between keyframes + */ + + /* resol depends on distance between points + * (not just horizontal) OR is a fixed high res */ + /* TODO: view scale should factor into this someday too... */ + if (fcu->driver) { + resol = 32; + } + else { + resol = (int)(5.0f * len_v2v2(bezt->vec[1], prevbezt->vec[1])); + } + + if (resol < 2) { + /* only draw one */ + v1[0] = prevbezt->vec[1][0]; + v1[1] = prevbezt->vec[1][1]; + immVertex2fv(pos, v1); + } + else { + /* clamp resolution to max of 32 */ + /* NOTE: higher values will crash */ + if (resol > 32) + resol = 32; + + v1[0] = prevbezt->vec[1][0]; + v1[1] = prevbezt->vec[1][1]; + v2[0] = prevbezt->vec[2][0]; + v2[1] = prevbezt->vec[2][1]; + + v3[0] = bezt->vec[0][0]; + v3[1] = bezt->vec[0][1]; + v4[0] = bezt->vec[1][0]; + v4[1] = bezt->vec[1][1]; + + correct_bezpart(v1, v2, v3, v4); + + 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) { + immVertex2fv(pos, fp); + } + } + } + + /* get next pointers */ + prevbezt = bezt; + bezt++; + + /* last point? */ + if (b == 0) { + v1[0] = prevbezt->vec[1][0]; + v1[1] = prevbezt->vec[1][1]; + immVertex2fv(pos, v1); + } + } + + /* extrapolate to right? (see code for left-extrapolation above too) */ + if (prevbezt->vec[1][0] < v2d->cur.xmax) { + v1[0] = v2d->cur.xmax; + + /* y-value depends on the interpolation */ + if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || + (prevbezt->ipo == BEZT_IPO_CONST) || (fcu->totvert == 1)) { + /* based on last keyframe's value */ + v1[1] = prevbezt->vec[1][1]; + } + else if (prevbezt->ipo == BEZT_IPO_LIN) { + /* extrapolate linear dosnt use the handle, use the previous points center instead */ + bezt = prevbezt - 1; + fac = (prevbezt->vec[1][0] - bezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]); + if (fac) + fac = 1.0f / fac; + v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[1][1] - bezt->vec[1][1]); + } + else { + /* based on angle of handle 1 (relative to keyframe) */ + fac = (prevbezt->vec[2][0] - prevbezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]); + if (fac) + fac = 1.0f / fac; + v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[2][1] - prevbezt->vec[1][1]); + } + + immVertex2fv(pos, v1); + } + + immEnd(); + + GPU_matrix_pop(); } /* Debugging -------------------------------- */ @@ -845,116 +858,117 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2 */ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu) { - ChannelDriver *driver = fcu->driver; - View2D *v2d = &ac->ar->v2d; - short mapping_flag = ANIM_get_normalization_flags(ac); - float offset; - float unitfac = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset); + ChannelDriver *driver = fcu->driver; + View2D *v2d = &ac->ar->v2d; + short mapping_flag = ANIM_get_normalization_flags(ac); + float offset; + float unitfac = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset); - /* for now, only show when debugging driver... */ - //if ((driver->flag & DRIVER_FLAG_SHOWDEBUG) == 0) - // return; + /* for now, only show when debugging driver... */ + //if ((driver->flag & DRIVER_FLAG_SHOWDEBUG) == 0) + // return; - const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + const uint shdr_pos = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); - float viewport_size[4]; - GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + float viewport_size[4]; + GPU_viewport_size_get_f(viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); - immUniform1i("colors_len", 0); /* Simple dashes. */ + immUniform1i("colors_len", 0); /* Simple dashes. */ - /* No curve to modify/visualize the result? - * => We still want to show the 1-1 default... - */ - if ((fcu->totvert == 0) && BLI_listbase_is_empty(&fcu->modifiers)) { - float t; + /* No curve to modify/visualize the result? + * => We still want to show the 1-1 default... + */ + if ((fcu->totvert == 0) && BLI_listbase_is_empty(&fcu->modifiers)) { + float t; - /* draw with thin dotted lines in style of what curve would have been */ - immUniformColor3fv(fcu->color); + /* draw with thin dotted lines in style of what curve would have been */ + immUniformColor3fv(fcu->color); - immUniform1f("dash_width", 40.0f); - immUniform1f("dash_factor", 0.5f); - GPU_line_width(2.0f); + immUniform1f("dash_width", 40.0f); + immUniform1f("dash_factor", 0.5f); + GPU_line_width(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 - */ - immBegin(GPU_PRIM_LINES, 2); + /* draw 1-1 line, stretching just past the screen limits + * NOTE: we need to scale the y-values to be valid for the units + */ + immBegin(GPU_PRIM_LINES, 2); - t = v2d->cur.xmin; - immVertex2f(shdr_pos, t, (t + offset) * unitfac); + t = v2d->cur.xmin; + immVertex2f(shdr_pos, t, (t + offset) * unitfac); - t = v2d->cur.xmax; - immVertex2f(shdr_pos, t, (t + offset) * unitfac); + t = v2d->cur.xmax; + immVertex2f(shdr_pos, t, (t + offset) * unitfac); - immEnd(); - } + immEnd(); + } - /* draw driver only if actually functional */ - if ((driver->flag & DRIVER_FLAG_INVALID) == 0) { - /* grab "coordinates" for driver outputs */ - float x = driver->curval; - float y = fcu->curval * unitfac; + /* draw driver only if actually functional */ + if ((driver->flag & DRIVER_FLAG_INVALID) == 0) { + /* grab "coordinates" for driver outputs */ + float x = driver->curval; + float y = fcu->curval * unitfac; - /* only draw indicators if the point is in range*/ - if (x >= v2d->cur.xmin) { - float co[2]; + /* only draw indicators if the point is in range*/ + if (x >= v2d->cur.xmin) { + float co[2]; - /* draw dotted lines leading towards this point from both axes ....... */ - immUniformColor3f(0.9f, 0.9f, 0.9f); - immUniform1f("dash_width", 10.0f); - immUniform1f("dash_factor", 0.5f); + /* draw dotted lines leading towards this point from both axes ....... */ + immUniformColor3f(0.9f, 0.9f, 0.9f); + immUniform1f("dash_width", 10.0f); + immUniform1f("dash_factor", 0.5f); - immBegin(GPU_PRIM_LINES, (y >= v2d->cur.ymin) ? 4 : 2); + immBegin(GPU_PRIM_LINES, (y >= v2d->cur.ymin) ? 4 : 2); - /* x-axis lookup */ - co[0] = x; + /* x-axis lookup */ + co[0] = x; - if (y >= v2d->cur.ymin) { - co[1] = v2d->cur.ymin - 1.0f; - immVertex2fv(shdr_pos, co); + if (y >= v2d->cur.ymin) { + co[1] = v2d->cur.ymin - 1.0f; + immVertex2fv(shdr_pos, co); - co[1] = y; - immVertex2fv(shdr_pos, co); - } + co[1] = y; + immVertex2fv(shdr_pos, co); + } - /* y-axis lookup */ - co[1] = y; + /* y-axis lookup */ + co[1] = y; - co[0] = v2d->cur.xmin - 1.0f; - immVertex2fv(shdr_pos, co); + co[0] = v2d->cur.xmin - 1.0f; + immVertex2fv(shdr_pos, co); - co[0] = x; - immVertex2fv(shdr_pos, co); + co[0] = x; + immVertex2fv(shdr_pos, co); - immEnd(); + immEnd(); - immUnbindProgram(); + immUnbindProgram(); - /* GPU_PRIM_POINTS do not survive dashed line geometry shader... */ - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* GPU_PRIM_POINTS do not survive dashed line geometry shader... */ + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - /* x marks the spot .................................................... */ - /* -> outer frame */ - immUniformColor3f(0.9f, 0.9f, 0.9f); - GPU_point_size(7.0); + /* x marks the spot .................................................... */ + /* -> outer frame */ + immUniformColor3f(0.9f, 0.9f, 0.9f); + GPU_point_size(7.0); - immBegin(GPU_PRIM_POINTS, 1); - immVertex2f(shdr_pos, x, y); - immEnd(); + immBegin(GPU_PRIM_POINTS, 1); + immVertex2f(shdr_pos, x, y); + immEnd(); - /* inner frame */ - immUniformColor3f(0.9f, 0.0f, 0.0f); - GPU_point_size(3.0); + /* inner frame */ + immUniformColor3f(0.9f, 0.0f, 0.0f); + GPU_point_size(3.0); - immBegin(GPU_PRIM_POINTS, 1); - immVertex2f(shdr_pos, x, y); - immEnd(); - } - } + immBegin(GPU_PRIM_POINTS, 1); + immVertex2f(shdr_pos, x, y); + immEnd(); + } + } - immUnbindProgram(); + immUnbindProgram(); } /* Public Curve-Drawing API ---------------- */ @@ -964,224 +978,227 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu) */ void graph_draw_ghost_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *ar) { - FCurve *fcu; + FCurve *fcu; - /* draw with thick dotted lines */ - GPU_line_width(3.0f); + /* draw with thick dotted lines */ + GPU_line_width(3.0f); - /* anti-aliased lines for less jagged appearance */ - if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) { - GPU_line_smooth(true); - } - GPU_blend(true); + /* anti-aliased lines for less jagged appearance */ + if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) { + GPU_line_smooth(true); + } + GPU_blend(true); - const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + const uint shdr_pos = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); - float viewport_size[4]; - GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + float viewport_size[4]; + GPU_viewport_size_get_f(viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); - immUniform1i("colors_len", 0); /* Simple dashes. */ - immUniform1f("dash_width", 20.0f); - immUniform1f("dash_factor", 0.5f); + immUniform1i("colors_len", 0); /* Simple dashes. */ + immUniform1f("dash_width", 20.0f); + immUniform1f("dash_factor", 0.5f); - /* the ghost curves are simply sampled F-Curves stored in sipo->runtime.ghost_curves */ - for (fcu = sipo->runtime.ghost_curves.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 - */ - immUniformColor3fvAlpha(fcu->color, 0.5f); + /* the ghost curves are simply sampled F-Curves stored in sipo->runtime.ghost_curves */ + for (fcu = sipo->runtime.ghost_curves.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 + */ + immUniformColor3fvAlpha(fcu->color, 0.5f); - /* simply draw the stored samples */ - draw_fcurve_curve_samples(ac, NULL, fcu, &ar->v2d, shdr_pos); - } + /* simply draw the stored samples */ + draw_fcurve_curve_samples(ac, NULL, fcu, &ar->v2d, shdr_pos); + } - immUnbindProgram(); + immUnbindProgram(); - if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) { - GPU_line_smooth(false); - } - GPU_blend(false); + if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) { + GPU_line_smooth(false); + } + GPU_blend(false); } /* This is called twice from space_graph.c -> graph_main_region_draw() * Unselected then selected F-Curves are drawn so that they do not occlude each other. */ -void graph_draw_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *ar, View2DGrid *grid, short sel) +void graph_draw_curves( + bAnimContext *ac, SpaceGraph *sipo, ARegion *ar, View2DGrid *grid, short sel) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - /* build list of curves to draw */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE); - filter |= ((sel) ? (ANIMFILTER_SEL) : (ANIMFILTER_UNSEL)); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* for each curve: - * draw curve, then handle-lines, and finally vertices in this order so that - * the data will be layered correctly - */ - for (ale = anim_data.first; ale; ale = ale->next) { - FCurve *fcu = (FCurve *)ale->key_data; - FModifier *fcm = find_active_fmodifier(&fcu->modifiers); - AnimData *adt = ANIM_nla_mapping_get(ac, ale); - - /* map keyframes for drawing if scaled F-Curve */ - 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, - * so we need to check which method should be used - * - controls from active modifier take precedence over keyframes - * (XXX! editing tools need to take this into account!) - */ - - /* 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) { - GPU_line_width(2.5); - } - else { - GPU_line_width(1.0); - } - - /* anti-aliased lines for less jagged appearance */ - if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) { - GPU_line_smooth(true); - } - GPU_blend(true); - - const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); - - float viewport_size[4]; - GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); - - immUniform1i("colors_len", 0); /* Simple dashes. */ - - if (BKE_fcurve_is_protected(fcu)) { - /* protected curves (non editable) are drawn with dotted lines */ - 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? */ - immUniformThemeColorShade(TH_HEADER, 50); - } - else { - /* set whatever color the curve has set - * - unselected curves draw less opaque to help distinguish the selected ones - */ - immUniformColor3fvAlpha(fcu->color, fcurve_display_alpha(fcu)); - } - - /* 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, 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, 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, shdr_pos); - } - } - - immUnbindProgram(); - - if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) { - GPU_line_smooth(false); - } - GPU_blend(false); - } - - /* 2) draw handles and vertices as appropriate based on active - * - 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) && !(fcu->fpt && fcu->totvert)) { - /* only draw controls if this is the active modifier */ - if ((fcu->flag & FCURVE_ACTIVE) && (fcm)) { - switch (fcm->type) { - case FMODIFIER_TYPE_ENVELOPE: /* envelope */ - draw_fcurve_modifier_controls_envelope(fcm, &ar->v2d); - break; - } - } - } - else if (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert)) { - short mapping_flag = ANIM_get_normalization_flags(ac); - float offset; - float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset); - - /* apply unit-scaling to all values via OpenGL */ - GPU_matrix_push(); - GPU_matrix_scale_2f(1.0f, unit_scale); - GPU_matrix_translate_2f(0.0f, offset); - - /* set this once and for all - all handles and handle-verts should use the same thickness */ - GPU_line_width(1.0); - - if (fcu->bezt) { - bool do_handles = draw_fcurve_handles_check(sipo, fcu); - - if (do_handles) { - /* only draw handles/vertices on keyframes */ - GPU_blend(true); - draw_fcurve_handles(sipo, fcu); - GPU_blend(false); - } - - 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); - } - - GPU_matrix_pop(); - } - } - - /* 3) draw driver debugging stuff */ - if ((ac->datatype == ANIMCONT_DRIVERS) && (fcu->flag & FCURVE_ACTIVE)) { - graph_draw_driver_debug(ac, ale->id, fcu); - } - - /* undo mapping of keyframes for drawing if scaled F-Curve */ - if (adt) - ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0); - } - - /* free list of curves */ - ANIM_animdata_freelist(&anim_data); + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* build list of curves to draw */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE); + filter |= ((sel) ? (ANIMFILTER_SEL) : (ANIMFILTER_UNSEL)); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* for each curve: + * draw curve, then handle-lines, and finally vertices in this order so that + * the data will be layered correctly + */ + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu = (FCurve *)ale->key_data; + FModifier *fcm = find_active_fmodifier(&fcu->modifiers); + AnimData *adt = ANIM_nla_mapping_get(ac, ale); + + /* map keyframes for drawing if scaled F-Curve */ + 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, + * so we need to check which method should be used + * - controls from active modifier take precedence over keyframes + * (XXX! editing tools need to take this into account!) + */ + + /* 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) { + GPU_line_width(2.5); + } + else { + GPU_line_width(1.0); + } + + /* anti-aliased lines for less jagged appearance */ + if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) { + GPU_line_smooth(true); + } + GPU_blend(true); + + const uint shdr_pos = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + GPU_viewport_size_get_f(viewport_size); + immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + + immUniform1i("colors_len", 0); /* Simple dashes. */ + + if (BKE_fcurve_is_protected(fcu)) { + /* protected curves (non editable) are drawn with dotted lines */ + 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? */ + immUniformThemeColorShade(TH_HEADER, 50); + } + else { + /* set whatever color the curve has set + * - unselected curves draw less opaque to help distinguish the selected ones + */ + immUniformColor3fvAlpha(fcu->color, fcurve_display_alpha(fcu)); + } + + /* 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, 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, 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, shdr_pos); + } + } + + immUnbindProgram(); + + if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) { + GPU_line_smooth(false); + } + GPU_blend(false); + } + + /* 2) draw handles and vertices as appropriate based on active + * - 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) && !(fcu->fpt && fcu->totvert)) { + /* only draw controls if this is the active modifier */ + if ((fcu->flag & FCURVE_ACTIVE) && (fcm)) { + switch (fcm->type) { + case FMODIFIER_TYPE_ENVELOPE: /* envelope */ + draw_fcurve_modifier_controls_envelope(fcm, &ar->v2d); + break; + } + } + } + else if (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert)) { + short mapping_flag = ANIM_get_normalization_flags(ac); + float offset; + float unit_scale = ANIM_unit_mapping_get_factor( + ac->scene, ale->id, fcu, mapping_flag, &offset); + + /* apply unit-scaling to all values via OpenGL */ + GPU_matrix_push(); + GPU_matrix_scale_2f(1.0f, unit_scale); + GPU_matrix_translate_2f(0.0f, offset); + + /* set this once and for all - all handles and handle-verts should use the same thickness */ + GPU_line_width(1.0); + + if (fcu->bezt) { + bool do_handles = draw_fcurve_handles_check(sipo, fcu); + + if (do_handles) { + /* only draw handles/vertices on keyframes */ + GPU_blend(true); + draw_fcurve_handles(sipo, fcu); + GPU_blend(false); + } + + 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); + } + + GPU_matrix_pop(); + } + } + + /* 3) draw driver debugging stuff */ + if ((ac->datatype == ANIMCONT_DRIVERS) && (fcu->flag & FCURVE_ACTIVE)) { + graph_draw_driver_debug(ac, ale->id, fcu); + } + + /* undo mapping of keyframes for drawing if scaled F-Curve */ + if (adt) + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0); + } + + /* free list of curves */ + ANIM_animdata_freelist(&anim_data); } /* ************************************************************************* */ @@ -1190,86 +1207,85 @@ void graph_draw_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *ar, View2DGr /* left hand part */ void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - View2D *v2d = &ar->v2d; - float y = 0.0f, height; - size_t items; - int i = 0; - - /* build list of channels to draw */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); - items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* Update max-extent of channels here (taking into account scrollers): - * - this is done to allow the channel list to be scrollable, but must be done here - * to avoid regenerating the list again and/or also because channels list is drawn first - * - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for - * start of list offset, and the second is as a correction for the scrollers. - */ - height = (float)((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac) * 2)); - UI_view2d_totRect_set(v2d, BLI_rcti_size_x(&ar->v2d.mask), height); - - /* loop through channels, and set up drawing depending on their type */ - { /* first pass: just the standard GL-drawing for backdrop + text */ - size_t channel_index = 0; - - y = (float)ACHANNEL_FIRST(ac); - - for (ale = anim_data.first, i = 0; ale; ale = ale->next, i++) { - const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac)); - const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac)); - - /* check if visible */ - if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || - IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) - { - /* draw all channels using standard channel-drawing API */ - ANIM_channel_draw(ac, ale, yminc, ymaxc, channel_index); - } - - /* adjust y-position for next one */ - y -= ACHANNEL_STEP(ac); - channel_index++; - } - } - { /* second pass: widgets */ - uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS); - size_t channel_index = 0; - - y = (float)ACHANNEL_FIRST(ac); - - /* set blending again, as may not be set in previous step */ - GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - GPU_blend(true); - - for (ale = anim_data.first, i = 0; ale; ale = ale->next, i++) { - const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac)); - const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac)); - - /* check if visible */ - if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || - IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) - { - /* draw all channels using standard channel-drawing API */ - rctf channel_rect; - BLI_rctf_init(&channel_rect, 0, v2d->cur.xmax - V2D_SCROLL_WIDTH, yminc, ymaxc); - ANIM_channel_draw_widgets(C, ac, ale, block, &channel_rect, channel_index); - } - - /* adjust y-position for next one */ - y -= ACHANNEL_STEP(ac); - channel_index++; - } - - UI_block_end(C, block); - UI_block_draw(C, block); - - GPU_blend(false); - } - - /* free tempolary channels */ - ANIM_animdata_freelist(&anim_data); + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + View2D *v2d = &ar->v2d; + float y = 0.0f, height; + size_t items; + int i = 0; + + /* build list of channels to draw */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); + items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* Update max-extent of channels here (taking into account scrollers): + * - this is done to allow the channel list to be scrollable, but must be done here + * to avoid regenerating the list again and/or also because channels list is drawn first + * - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for + * start of list offset, and the second is as a correction for the scrollers. + */ + height = (float)((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac) * 2)); + UI_view2d_totRect_set(v2d, BLI_rcti_size_x(&ar->v2d.mask), height); + + /* loop through channels, and set up drawing depending on their type */ + { /* first pass: just the standard GL-drawing for backdrop + text */ + size_t channel_index = 0; + + y = (float)ACHANNEL_FIRST(ac); + + for (ale = anim_data.first, i = 0; ale; ale = ale->next, i++) { + const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac)); + const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac)); + + /* check if visible */ + if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || + IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) { + /* draw all channels using standard channel-drawing API */ + ANIM_channel_draw(ac, ale, yminc, ymaxc, channel_index); + } + + /* adjust y-position for next one */ + y -= ACHANNEL_STEP(ac); + channel_index++; + } + } + { /* second pass: widgets */ + uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS); + size_t channel_index = 0; + + y = (float)ACHANNEL_FIRST(ac); + + /* set blending again, as may not be set in previous step */ + GPU_blend_set_func_separate( + GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); + GPU_blend(true); + + for (ale = anim_data.first, i = 0; ale; ale = ale->next, i++) { + const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac)); + const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac)); + + /* check if visible */ + if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || + IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) { + /* draw all channels using standard channel-drawing API */ + rctf channel_rect; + BLI_rctf_init(&channel_rect, 0, v2d->cur.xmax - V2D_SCROLL_WIDTH, yminc, ymaxc); + ANIM_channel_draw_widgets(C, ac, ale, block, &channel_rect, channel_index); + } + + /* adjust y-position for next one */ + y -= ACHANNEL_STEP(ac); + channel_index++; + } + + UI_block_end(C, block); + UI_block_draw(C, block); + + GPU_blend(false); + } + + /* free tempolary channels */ + ANIM_animdata_freelist(&anim_data); } diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index a85e638e6d8..29058e47199 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -21,7 +21,6 @@ * \ingroup spgraph */ - #include <math.h> #include <stdlib.h> #include <string.h> @@ -76,253 +75,288 @@ /* Get the min/max keyframes*/ /* note: it should return total boundbox, filter for selection only can be argument... */ -void get_graph_keyframe_extents(bAnimContext *ac, float *xmin, float *xmax, float *ymin, float *ymax, - const bool do_sel_only, const bool include_handles) -{ - Scene *scene = ac->scene; - - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - /* get data to filter, from Dopesheet */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* set large values initial values that will be easy to override */ - if (xmin) *xmin = 999999999.0f; - if (xmax) *xmax = -999999999.0f; - if (ymin) *ymin = 999999999.0f; - if (ymax) *ymax = -999999999.0f; - - /* check if any channels to set range with */ - if (anim_data.first) { - bool foundBounds = false; - - /* go through channels, finding max extents */ - for (ale = anim_data.first; ale; ale = ale->next) { - AnimData *adt = ANIM_nla_mapping_get(ac, ale); - FCurve *fcu = (FCurve *)ale->key_data; - float txmin, txmax, tymin, tymax; - float unitFac, offset; - - /* get range */ - if (calc_fcurve_bounds(fcu, &txmin, &txmax, &tymin, &tymax, do_sel_only, include_handles)) { - short mapping_flag = ANIM_get_normalization_flags(ac); - - /* apply NLA scaling */ - if (adt) { - txmin = BKE_nla_tweakedit_remap(adt, txmin, NLATIME_CONVERT_MAP); - txmax = BKE_nla_tweakedit_remap(adt, txmax, NLATIME_CONVERT_MAP); - } - - /* apply unit corrections */ - unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset); - tymin += offset; - tymax += offset; - tymin *= unitFac; - tymax *= unitFac; - - /* try to set cur using these values, if they're more extreme than previously set values */ - if ((xmin) && (txmin < *xmin)) *xmin = txmin; - if ((xmax) && (txmax > *xmax)) *xmax = txmax; - if ((ymin) && (tymin < *ymin)) *ymin = tymin; - if ((ymax) && (tymax > *ymax)) *ymax = tymax; - - foundBounds = true; - } - } - - /* ensure that the extents are not too extreme that view implodes...*/ - if (foundBounds) { - if ((xmin && xmax) && (fabsf(*xmax - *xmin) < 0.001f)) { - *xmin -= 0.0005f; - *xmax += 0.0005f; - } - if ((ymin && ymax) && (fabsf(*ymax - *ymin) < 0.001f)) { - *ymax -= 0.0005f; - *ymax += 0.0005f; - } - } - else { - if (xmin) *xmin = (float)PSFRA; - if (xmax) *xmax = (float)PEFRA; - if (ymin) *ymin = -5; - if (ymax) *ymax = 5; - } - - /* free memory */ - ANIM_animdata_freelist(&anim_data); - } - else { - /* set default range */ - if (ac->scene) { - if (xmin) *xmin = (float)PSFRA; - if (xmax) *xmax = (float)PEFRA; - } - else { - if (xmin) *xmin = -5; - if (xmax) *xmax = 100; - } - - if (ymin) *ymin = -5; - if (ymax) *ymax = 5; - } +void get_graph_keyframe_extents(bAnimContext *ac, + float *xmin, + float *xmax, + float *ymin, + float *ymax, + const bool do_sel_only, + const bool include_handles) +{ + Scene *scene = ac->scene; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* get data to filter, from Dopesheet */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* set large values initial values that will be easy to override */ + if (xmin) + *xmin = 999999999.0f; + if (xmax) + *xmax = -999999999.0f; + if (ymin) + *ymin = 999999999.0f; + if (ymax) + *ymax = -999999999.0f; + + /* check if any channels to set range with */ + if (anim_data.first) { + bool foundBounds = false; + + /* go through channels, finding max extents */ + for (ale = anim_data.first; ale; ale = ale->next) { + AnimData *adt = ANIM_nla_mapping_get(ac, ale); + FCurve *fcu = (FCurve *)ale->key_data; + float txmin, txmax, tymin, tymax; + float unitFac, offset; + + /* get range */ + if (calc_fcurve_bounds(fcu, &txmin, &txmax, &tymin, &tymax, do_sel_only, include_handles)) { + short mapping_flag = ANIM_get_normalization_flags(ac); + + /* apply NLA scaling */ + if (adt) { + txmin = BKE_nla_tweakedit_remap(adt, txmin, NLATIME_CONVERT_MAP); + txmax = BKE_nla_tweakedit_remap(adt, txmax, NLATIME_CONVERT_MAP); + } + + /* apply unit corrections */ + unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset); + tymin += offset; + tymax += offset; + tymin *= unitFac; + tymax *= unitFac; + + /* try to set cur using these values, if they're more extreme than previously set values */ + if ((xmin) && (txmin < *xmin)) + *xmin = txmin; + if ((xmax) && (txmax > *xmax)) + *xmax = txmax; + if ((ymin) && (tymin < *ymin)) + *ymin = tymin; + if ((ymax) && (tymax > *ymax)) + *ymax = tymax; + + foundBounds = true; + } + } + + /* ensure that the extents are not too extreme that view implodes...*/ + if (foundBounds) { + if ((xmin && xmax) && (fabsf(*xmax - *xmin) < 0.001f)) { + *xmin -= 0.0005f; + *xmax += 0.0005f; + } + if ((ymin && ymax) && (fabsf(*ymax - *ymin) < 0.001f)) { + *ymax -= 0.0005f; + *ymax += 0.0005f; + } + } + else { + if (xmin) + *xmin = (float)PSFRA; + if (xmax) + *xmax = (float)PEFRA; + if (ymin) + *ymin = -5; + if (ymax) + *ymax = 5; + } + + /* free memory */ + ANIM_animdata_freelist(&anim_data); + } + else { + /* set default range */ + if (ac->scene) { + if (xmin) + *xmin = (float)PSFRA; + if (xmax) + *xmax = (float)PEFRA; + } + else { + if (xmin) + *xmin = -5; + if (xmax) + *xmax = 100; + } + + if (ymin) + *ymin = -5; + if (ymax) + *ymax = 5; + } } /* ****************** Automatic Preview-Range Operator ****************** */ static int graphkeys_previewrange_exec(bContext *C, wmOperator *UNUSED(op)) { - bAnimContext ac; - Scene *scene; - float min, max; + bAnimContext ac; + Scene *scene; + float min, max; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - if (ac.scene == NULL) - return OPERATOR_CANCELLED; - else - scene = ac.scene; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + if (ac.scene == NULL) + return OPERATOR_CANCELLED; + else + scene = ac.scene; - /* set the range directly */ - get_graph_keyframe_extents(&ac, &min, &max, NULL, NULL, false, false); - scene->r.flag |= SCER_PRV_RANGE; - scene->r.psfra = round_fl_to_int(min); - scene->r.pefra = round_fl_to_int(max); + /* set the range directly */ + get_graph_keyframe_extents(&ac, &min, &max, NULL, NULL, false, false); + scene->r.flag |= SCER_PRV_RANGE; + scene->r.psfra = round_fl_to_int(min); + scene->r.pefra = round_fl_to_int(max); - /* set notifier that things have changed */ - // XXX err... there's nothing for frame ranges yet, but this should do fine too - WM_event_add_notifier(C, NC_SCENE | ND_FRAME, ac.scene); + /* set notifier that things have changed */ + // XXX err... there's nothing for frame ranges yet, but this should do fine too + WM_event_add_notifier(C, NC_SCENE | ND_FRAME, ac.scene); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_previewrange_set(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Auto-Set Preview Range"; - ot->idname = "GRAPH_OT_previewrange_set"; - ot->description = "Automatically set Preview Range based on range of keyframes"; + /* identifiers */ + ot->name = "Auto-Set Preview Range"; + ot->idname = "GRAPH_OT_previewrange_set"; + ot->description = "Automatically set Preview Range based on range of keyframes"; - /* api callbacks */ - ot->exec = graphkeys_previewrange_exec; - ot->poll = ED_operator_graphedit_active; // XXX: unchecked poll to get fsamples working too, but makes modifier damage trickier... + /* api callbacks */ + ot->exec = graphkeys_previewrange_exec; + ot->poll = + ED_operator_graphedit_active; // XXX: unchecked poll to get fsamples working too, but makes modifier damage trickier... - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ****************** View-All Operator ****************** */ -static int graphkeys_viewall(bContext *C, const bool do_sel_only, const bool include_handles, +static int graphkeys_viewall(bContext *C, + const bool do_sel_only, + const bool include_handles, const int smooth_viewtx) { - bAnimContext ac; - rctf cur_new; + bAnimContext ac; + rctf cur_new; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* set the horizontal range, with an extra offset so that the extreme keys will be in view */ - get_graph_keyframe_extents(&ac, - &cur_new.xmin, &cur_new.xmax, - &cur_new.ymin, &cur_new.ymax, - do_sel_only, include_handles); + /* set the horizontal range, with an extra offset so that the extreme keys will be in view */ + get_graph_keyframe_extents(&ac, + &cur_new.xmin, + &cur_new.xmax, + &cur_new.ymin, + &cur_new.ymax, + do_sel_only, + include_handles); - BLI_rctf_scale(&cur_new, 1.1f); + BLI_rctf_scale(&cur_new, 1.1f); - UI_view2d_smooth_view(C, ac.ar, &cur_new, smooth_viewtx); + UI_view2d_smooth_view(C, ac.ar, &cur_new, smooth_viewtx); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } /* ......... */ static int graphkeys_viewall_exec(bContext *C, wmOperator *op) { - const bool include_handles = RNA_boolean_get(op->ptr, "include_handles"); - const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); + const bool include_handles = RNA_boolean_get(op->ptr, "include_handles"); + const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - /* whole range */ - return graphkeys_viewall(C, false, include_handles, smooth_viewtx); + /* whole range */ + return graphkeys_viewall(C, false, include_handles, smooth_viewtx); } static int graphkeys_view_selected_exec(bContext *C, wmOperator *op) { - const bool include_handles = RNA_boolean_get(op->ptr, "include_handles"); - const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); + const bool include_handles = RNA_boolean_get(op->ptr, "include_handles"); + const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - /* only selected */ - return graphkeys_viewall(C, true, include_handles, smooth_viewtx); + /* only selected */ + return graphkeys_viewall(C, true, include_handles, smooth_viewtx); } /* ......... */ void GRAPH_OT_view_all(wmOperatorType *ot) { - /* identifiers */ - ot->name = "View All"; - ot->idname = "GRAPH_OT_view_all"; - ot->description = "Reset viewable area to show full keyframe range"; + /* identifiers */ + ot->name = "View All"; + ot->idname = "GRAPH_OT_view_all"; + ot->description = "Reset viewable area to show full keyframe range"; - /* api callbacks */ - ot->exec = graphkeys_viewall_exec; - /* XXX: unchecked poll to get fsamples working too, but makes modifier damage trickier... */ - ot->poll = ED_operator_graphedit_active; + /* api callbacks */ + ot->exec = graphkeys_viewall_exec; + /* XXX: unchecked poll to get fsamples working too, but makes modifier damage trickier... */ + ot->poll = ED_operator_graphedit_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* props */ - ot->prop = RNA_def_boolean(ot->srna, "include_handles", true, "Include Handles", - "Include handles of keyframes when calculating extents"); + /* props */ + ot->prop = RNA_def_boolean(ot->srna, + "include_handles", + true, + "Include Handles", + "Include handles of keyframes when calculating extents"); } void GRAPH_OT_view_selected(wmOperatorType *ot) { - /* identifiers */ - ot->name = "View Selected"; - ot->idname = "GRAPH_OT_view_selected"; - ot->description = "Reset viewable area to show selected keyframe range"; + /* identifiers */ + ot->name = "View Selected"; + ot->idname = "GRAPH_OT_view_selected"; + ot->description = "Reset viewable area to show selected keyframe range"; - /* api callbacks */ - ot->exec = graphkeys_view_selected_exec; - /* XXX: unchecked poll to get fsamples working too, but makes modifier damage trickier... */ - ot->poll = ED_operator_graphedit_active; + /* api callbacks */ + ot->exec = graphkeys_view_selected_exec; + /* XXX: unchecked poll to get fsamples working too, but makes modifier damage trickier... */ + ot->poll = ED_operator_graphedit_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* props */ - ot->prop = RNA_def_boolean(ot->srna, "include_handles", true, "Include Handles", - "Include handles of keyframes when calculating extents"); + /* props */ + ot->prop = RNA_def_boolean(ot->srna, + "include_handles", + true, + "Include Handles", + "Include handles of keyframes when calculating extents"); } /* ********************** View Frame Operator ****************************** */ static int graphkeys_view_frame_exec(bContext *C, wmOperator *op) { - const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - ANIM_center_frame(C, smooth_viewtx); - return OPERATOR_FINISHED; + const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); + ANIM_center_frame(C, smooth_viewtx); + return OPERATOR_FINISHED; } void GRAPH_OT_view_frame(wmOperatorType *ot) { - /* identifiers */ - ot->name = "View Frame"; - ot->idname = "GRAPH_OT_view_frame"; - ot->description = "Reset viewable area to show range around current frame"; + /* identifiers */ + ot->name = "View Frame"; + ot->idname = "GRAPH_OT_view_frame"; + ot->description = "Reset viewable area to show range around current frame"; - /* api callbacks */ - ot->exec = graphkeys_view_frame_exec; - ot->poll = ED_operator_graphedit_active; + /* api callbacks */ + ot->exec = graphkeys_view_frame_exec; + ot->poll = ED_operator_graphedit_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ******************** Create Ghost-Curves Operator *********************** */ @@ -333,114 +367,116 @@ void GRAPH_OT_view_frame(wmOperatorType *ot) /* Bake each F-Curve into a set of samples, and store as a ghost curve */ static void create_ghost_curves(bAnimContext *ac, int start, int end) { - SpaceGraph *sipo = (SpaceGraph *)ac->sl; - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - /* free existing ghost curves */ - free_fcurves(&sipo->runtime.ghost_curves); - - /* sanity check */ - if (start >= end) { - printf("Error: Frame range for Ghost F-Curve creation is inappropriate\n"); - return; - } - - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* loop through filtered data and add keys between selected keyframes on every frame */ - for (ale = anim_data.first; ale; ale = ale->next) { - FCurve *fcu = (FCurve *)ale->key_data; - FCurve *gcu = MEM_callocN(sizeof(FCurve), "Ghost FCurve"); - AnimData *adt = ANIM_nla_mapping_get(ac, ale); - ChannelDriver *driver = fcu->driver; - FPoint *fpt; - float unitFac, offset; - int cfra; - short mapping_flag = ANIM_get_normalization_flags(ac); - - /* disable driver so that it don't muck up the sampling process */ - fcu->driver = NULL; - - /* calculate unit-mapping factor */ - unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset); - - /* create samples, but store them in a new curve - * - we cannot use fcurve_store_samples() as that will only overwrite the original curve - */ - gcu->fpt = fpt = MEM_callocN(sizeof(FPoint) * (end - start + 1), "Ghost FPoint Samples"); - gcu->totvert = end - start + 1; - - /* use the sampling callback at 1-frame intervals from start to end frames */ - for (cfra = start; cfra <= end; cfra++, fpt++) { - float cfrae = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP); - - fpt->vec[0] = cfrae; - fpt->vec[1] = (fcurve_samplingcb_evalcurve(fcu, NULL, cfrae) + offset) * unitFac; - } - - /* set color of ghost curve - * - make the color slightly darker - */ - gcu->color[0] = fcu->color[0] - 0.07f; - gcu->color[1] = fcu->color[1] - 0.07f; - gcu->color[2] = fcu->color[2] - 0.07f; - - /* store new ghost curve */ - BLI_addtail(&sipo->runtime.ghost_curves, gcu); - - /* restore driver */ - fcu->driver = driver; - } - - /* admin and redraws */ - ANIM_animdata_freelist(&anim_data); + SpaceGraph *sipo = (SpaceGraph *)ac->sl; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* free existing ghost curves */ + free_fcurves(&sipo->runtime.ghost_curves); + + /* sanity check */ + if (start >= end) { + printf("Error: Frame range for Ghost F-Curve creation is inappropriate\n"); + return; + } + + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL | + ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* loop through filtered data and add keys between selected keyframes on every frame */ + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu = (FCurve *)ale->key_data; + FCurve *gcu = MEM_callocN(sizeof(FCurve), "Ghost FCurve"); + AnimData *adt = ANIM_nla_mapping_get(ac, ale); + ChannelDriver *driver = fcu->driver; + FPoint *fpt; + float unitFac, offset; + int cfra; + short mapping_flag = ANIM_get_normalization_flags(ac); + + /* disable driver so that it don't muck up the sampling process */ + fcu->driver = NULL; + + /* calculate unit-mapping factor */ + unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset); + + /* create samples, but store them in a new curve + * - we cannot use fcurve_store_samples() as that will only overwrite the original curve + */ + gcu->fpt = fpt = MEM_callocN(sizeof(FPoint) * (end - start + 1), "Ghost FPoint Samples"); + gcu->totvert = end - start + 1; + + /* use the sampling callback at 1-frame intervals from start to end frames */ + for (cfra = start; cfra <= end; cfra++, fpt++) { + float cfrae = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP); + + fpt->vec[0] = cfrae; + fpt->vec[1] = (fcurve_samplingcb_evalcurve(fcu, NULL, cfrae) + offset) * unitFac; + } + + /* set color of ghost curve + * - make the color slightly darker + */ + gcu->color[0] = fcu->color[0] - 0.07f; + gcu->color[1] = fcu->color[1] - 0.07f; + gcu->color[2] = fcu->color[2] - 0.07f; + + /* store new ghost curve */ + BLI_addtail(&sipo->runtime.ghost_curves, gcu); + + /* restore driver */ + fcu->driver = driver; + } + + /* admin and redraws */ + ANIM_animdata_freelist(&anim_data); } /* ------------------- */ static int graphkeys_create_ghostcurves_exec(bContext *C, wmOperator *UNUSED(op)) { - bAnimContext ac; - View2D *v2d; - int start, end; + bAnimContext ac; + View2D *v2d; + int start, end; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* ghost curves are snapshots of the visible portions of the curves, so set range to be the visible range */ - v2d = &ac.ar->v2d; - start = (int)v2d->cur.xmin; - end = (int)v2d->cur.xmax; + /* ghost curves are snapshots of the visible portions of the curves, so set range to be the visible range */ + v2d = &ac.ar->v2d; + start = (int)v2d->cur.xmin; + end = (int)v2d->cur.xmax; - /* bake selected curves into a ghost curve */ - create_ghost_curves(&ac, start, end); + /* bake selected curves into a ghost curve */ + create_ghost_curves(&ac, start, end); - /* update this editor only */ - ED_area_tag_redraw(CTX_wm_area(C)); + /* update this editor only */ + ED_area_tag_redraw(CTX_wm_area(C)); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_ghost_curves_create(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Create Ghost Curves"; - ot->idname = "GRAPH_OT_ghost_curves_create"; - ot->description = "Create snapshot (Ghosts) of selected F-Curves as background aid for active Graph Editor"; + /* identifiers */ + ot->name = "Create Ghost Curves"; + ot->idname = "GRAPH_OT_ghost_curves_create"; + ot->description = + "Create snapshot (Ghosts) of selected F-Curves as background aid for active Graph Editor"; - /* api callbacks */ - ot->exec = graphkeys_create_ghostcurves_exec; - ot->poll = graphop_visible_keyframes_poll; + /* api callbacks */ + ot->exec = graphkeys_create_ghostcurves_exec; + ot->poll = graphop_visible_keyframes_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - // todo: add props for start/end frames + // todo: add props for start/end frames } /* ******************** Clear Ghost-Curves Operator *********************** */ @@ -448,40 +484,40 @@ void GRAPH_OT_ghost_curves_create(wmOperatorType *ot) static int graphkeys_clear_ghostcurves_exec(bContext *C, wmOperator *UNUSED(op)) { - bAnimContext ac; - SpaceGraph *sipo; + bAnimContext ac; + SpaceGraph *sipo; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - sipo = (SpaceGraph *)ac.sl; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + sipo = (SpaceGraph *)ac.sl; - /* if no ghost curves, don't do anything */ - if (BLI_listbase_is_empty(&sipo->runtime.ghost_curves)) { - return OPERATOR_CANCELLED; - } - /* free ghost curves */ - free_fcurves(&sipo->runtime.ghost_curves); + /* if no ghost curves, don't do anything */ + if (BLI_listbase_is_empty(&sipo->runtime.ghost_curves)) { + return OPERATOR_CANCELLED; + } + /* free ghost curves */ + free_fcurves(&sipo->runtime.ghost_curves); - /* update this editor only */ - ED_area_tag_redraw(CTX_wm_area(C)); + /* update this editor only */ + ED_area_tag_redraw(CTX_wm_area(C)); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_ghost_curves_clear(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Clear Ghost Curves"; - ot->idname = "GRAPH_OT_ghost_curves_clear"; - ot->description = "Clear F-Curve snapshots (Ghosts) for active Graph Editor"; + /* identifiers */ + ot->name = "Clear Ghost Curves"; + ot->idname = "GRAPH_OT_ghost_curves_clear"; + ot->description = "Clear F-Curve snapshots (Ghosts) for active Graph Editor"; - /* api callbacks */ - ot->exec = graphkeys_clear_ghostcurves_exec; - ot->poll = ED_operator_graphedit_active; + /* api callbacks */ + ot->exec = graphkeys_clear_ghostcurves_exec; + ot->poll = ED_operator_graphedit_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ************************************************************************** */ @@ -491,310 +527,350 @@ void GRAPH_OT_ghost_curves_clear(wmOperatorType *ot) /* Mode defines for insert keyframes tool */ typedef enum eGraphKeys_InsertKey_Types { - GRAPHKEYS_INSERTKEY_ALL = (1 << 0), - GRAPHKEYS_INSERTKEY_SEL = (1 << 1), - GRAPHKEYS_INSERTKEY_CURSOR = (1 << 2), - GRAPHKEYS_INSERTKEY_ACTIVE = (1 << 3), + GRAPHKEYS_INSERTKEY_ALL = (1 << 0), + GRAPHKEYS_INSERTKEY_SEL = (1 << 1), + GRAPHKEYS_INSERTKEY_CURSOR = (1 << 2), + GRAPHKEYS_INSERTKEY_ACTIVE = (1 << 3), } eGraphKeys_InsertKey_Types; /* RNA mode types for insert keyframes tool */ static const EnumPropertyItem prop_graphkeys_insertkey_types[] = { - {GRAPHKEYS_INSERTKEY_ALL, "ALL", 0, "All Channels", - "Insert a keyframe on all visible and editable F-Curves using each curve's current value"}, - {GRAPHKEYS_INSERTKEY_SEL, "SEL", 0, "Only Selected Channels", - "Insert a keyframe on selected F-Curves using each curve's current value"}, - {0, "", 0, "", ""}, - {GRAPHKEYS_INSERTKEY_ACTIVE | GRAPHKEYS_INSERTKEY_CURSOR, "CURSOR_ACTIVE", 0, - "Active Channels At Cursor", "Insert a keyframe for the active F-Curve at the cursor point"}, - {GRAPHKEYS_INSERTKEY_SEL | GRAPHKEYS_INSERTKEY_CURSOR, "CURSOR_SEL", 0, - "Selected Channels At Cursor", "Insert a keyframe for selected F-Curves at the cursor point"}, - {0, NULL, 0, NULL, NULL}, + {GRAPHKEYS_INSERTKEY_ALL, + "ALL", + 0, + "All Channels", + "Insert a keyframe on all visible and editable F-Curves using each curve's current value"}, + {GRAPHKEYS_INSERTKEY_SEL, + "SEL", + 0, + "Only Selected Channels", + "Insert a keyframe on selected F-Curves using each curve's current value"}, + {0, "", 0, "", ""}, + {GRAPHKEYS_INSERTKEY_ACTIVE | GRAPHKEYS_INSERTKEY_CURSOR, + "CURSOR_ACTIVE", + 0, + "Active Channels At Cursor", + "Insert a keyframe for the active F-Curve at the cursor point"}, + {GRAPHKEYS_INSERTKEY_SEL | GRAPHKEYS_INSERTKEY_CURSOR, + "CURSOR_SEL", + 0, + "Selected Channels At Cursor", + "Insert a keyframe for selected F-Curves at the cursor point"}, + {0, NULL, 0, NULL, NULL}, }; /* this function is responsible for snapping keyframes to frame-times */ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode) { - ListBase anim_data = {NULL, NULL}; - ListBase nla_cache = {NULL, NULL}; - bAnimListElem *ale; - int filter; - size_t num_items; - - ReportList *reports = ac->reports; - SpaceGraph *sipo = (SpaceGraph *)ac->sl; - struct Depsgraph *depsgraph = ac->depsgraph; - Scene *scene = ac->scene; - ToolSettings *ts = scene->toolsettings; - short flag = 0; - - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); - if (mode & GRAPHKEYS_INSERTKEY_SEL) - filter |= ANIMFILTER_SEL; - else if (mode & GRAPHKEYS_INSERTKEY_ACTIVE) - filter |= ANIMFILTER_ACTIVE; - - num_items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - if (num_items == 0) { - if (mode & GRAPHKEYS_INSERTKEY_ACTIVE) - BKE_report(reports, RPT_ERROR, "No active F-Curve to add a keyframe to. Select an editable F-Curve first"); - else if (mode & GRAPHKEYS_INSERTKEY_SEL) - BKE_report(reports, RPT_ERROR, "No selected F-Curves to add keyframes to"); - else - BKE_report(reports, RPT_ERROR, "No channels to add keyframes to"); - - return; - } - - /* init keyframing flag */ - flag = ANIM_get_keyframing_flags(scene, 1); - - /* insert keyframes */ - if (mode & GRAPHKEYS_INSERTKEY_CURSOR) { - for (ale = anim_data.first; ale; ale = ale->next) { - AnimData *adt = ANIM_nla_mapping_get(ac, ale); - FCurve *fcu = (FCurve *)ale->key_data; - - short mapping_flag = ANIM_get_normalization_flags(ac); - float offset; - float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, ale->key_data, mapping_flag, &offset); - - float x, y; - - - /* perform time remapping for x-coordinate (if necessary) */ - if ((sipo) && (sipo->mode == SIPO_MODE_DRIVERS)) - x = sipo->cursorTime; - else if (adt) - x = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); - else - x = (float)CFRA; - - /* normalise units of cursor's value */ - if (sipo) - y = (sipo->cursorVal / unit_scale) - offset; - else - y = 0.0f; - - /* insert keyframe directly into the F-Curve */ - insert_vert_fcurve(fcu, x, y, ts->keyframe_type, 0); - - ale->update |= ANIM_UPDATE_DEFAULT; - } - } - else { - for (ale = anim_data.first; ale; ale = ale->next) { - FCurve *fcu = (FCurve *)ale->key_data; - float cfra = (float)CFRA; - - /* read value from property the F-Curve represents, or from the curve only? - * - ale->id != NULL: Typically, this means that we have enough info to try resolving the path - * - ale->owner != NULL: If this is set, then the path may not be resolvable from the ID alone, - * so it's easier for now to just read the F-Curve directly. - * (TODO: add the full-blown PointerRNA relative parsing case here...) - * - fcu->driver != NULL: If this is set, then it's a driver. If we don't check for this, we'd end - * 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, depsgraph, reports, ale->id, NULL, ((fcu->grp) ? (fcu->grp->name) : (NULL)), - fcu->rna_path, fcu->array_index, cfra, ts->keyframe_type, &nla_cache, flag); - } - else { - AnimData *adt = ANIM_nla_mapping_get(ac, ale); - - /* adjust current frame for NLA-mapping */ - if ((sipo) && (sipo->mode == SIPO_MODE_DRIVERS)) - cfra = sipo->cursorTime; - else if (adt) - cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); - - const float curval = evaluate_fcurve_only_curve(fcu, cfra); - insert_vert_fcurve(fcu, cfra, curval, ts->keyframe_type, 0); - } - - ale->update |= ANIM_UPDATE_DEFAULT; - } - } - - BKE_animsys_free_nla_keyframing_context_cache(&nla_cache); - - ANIM_animdata_update(ac, &anim_data); - ANIM_animdata_freelist(&anim_data); + ListBase anim_data = {NULL, NULL}; + ListBase nla_cache = {NULL, NULL}; + bAnimListElem *ale; + int filter; + size_t num_items; + + ReportList *reports = ac->reports; + SpaceGraph *sipo = (SpaceGraph *)ac->sl; + struct Depsgraph *depsgraph = ac->depsgraph; + Scene *scene = ac->scene; + ToolSettings *ts = scene->toolsettings; + short flag = 0; + + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | + ANIMFILTER_NODUPLIS); + if (mode & GRAPHKEYS_INSERTKEY_SEL) + filter |= ANIMFILTER_SEL; + else if (mode & GRAPHKEYS_INSERTKEY_ACTIVE) + filter |= ANIMFILTER_ACTIVE; + + num_items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + if (num_items == 0) { + if (mode & GRAPHKEYS_INSERTKEY_ACTIVE) + BKE_report(reports, + RPT_ERROR, + "No active F-Curve to add a keyframe to. Select an editable F-Curve first"); + else if (mode & GRAPHKEYS_INSERTKEY_SEL) + BKE_report(reports, RPT_ERROR, "No selected F-Curves to add keyframes to"); + else + BKE_report(reports, RPT_ERROR, "No channels to add keyframes to"); + + return; + } + + /* init keyframing flag */ + flag = ANIM_get_keyframing_flags(scene, 1); + + /* insert keyframes */ + if (mode & GRAPHKEYS_INSERTKEY_CURSOR) { + for (ale = anim_data.first; ale; ale = ale->next) { + AnimData *adt = ANIM_nla_mapping_get(ac, ale); + FCurve *fcu = (FCurve *)ale->key_data; + + short mapping_flag = ANIM_get_normalization_flags(ac); + float offset; + float unit_scale = ANIM_unit_mapping_get_factor( + ac->scene, ale->id, ale->key_data, mapping_flag, &offset); + + float x, y; + + /* perform time remapping for x-coordinate (if necessary) */ + if ((sipo) && (sipo->mode == SIPO_MODE_DRIVERS)) + x = sipo->cursorTime; + else if (adt) + x = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); + else + x = (float)CFRA; + + /* normalise units of cursor's value */ + if (sipo) + y = (sipo->cursorVal / unit_scale) - offset; + else + y = 0.0f; + + /* insert keyframe directly into the F-Curve */ + insert_vert_fcurve(fcu, x, y, ts->keyframe_type, 0); + + ale->update |= ANIM_UPDATE_DEFAULT; + } + } + else { + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu = (FCurve *)ale->key_data; + float cfra = (float)CFRA; + + /* read value from property the F-Curve represents, or from the curve only? + * - ale->id != NULL: Typically, this means that we have enough info to try resolving the path + * - ale->owner != NULL: If this is set, then the path may not be resolvable from the ID alone, + * so it's easier for now to just read the F-Curve directly. + * (TODO: add the full-blown PointerRNA relative parsing case here...) + * - fcu->driver != NULL: If this is set, then it's a driver. If we don't check for this, we'd end + * 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, + depsgraph, + reports, + ale->id, + NULL, + ((fcu->grp) ? (fcu->grp->name) : (NULL)), + fcu->rna_path, + fcu->array_index, + cfra, + ts->keyframe_type, + &nla_cache, + flag); + } + else { + AnimData *adt = ANIM_nla_mapping_get(ac, ale); + + /* adjust current frame for NLA-mapping */ + if ((sipo) && (sipo->mode == SIPO_MODE_DRIVERS)) + cfra = sipo->cursorTime; + else if (adt) + cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); + + const float curval = evaluate_fcurve_only_curve(fcu, cfra); + insert_vert_fcurve(fcu, cfra, curval, ts->keyframe_type, 0); + } + + ale->update |= ANIM_UPDATE_DEFAULT; + } + } + + BKE_animsys_free_nla_keyframing_context_cache(&nla_cache); + + ANIM_animdata_update(ac, &anim_data); + ANIM_animdata_freelist(&anim_data); } /* ------------------- */ static int graphkeys_insertkey_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - eGraphKeys_InsertKey_Types mode; + bAnimContext ac; + eGraphKeys_InsertKey_Types mode; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* which channels to affect? */ - mode = RNA_enum_get(op->ptr, "type"); + /* which channels to affect? */ + mode = RNA_enum_get(op->ptr, "type"); - /* insert keyframes */ - insert_graph_keys(&ac, mode); + /* insert keyframes */ + insert_graph_keys(&ac, mode); - /* set notifier that keyframes have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_keyframe_insert(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Insert Keyframes"; - ot->idname = "GRAPH_OT_keyframe_insert"; - ot->description = "Insert keyframes for the specified channels"; + /* identifiers */ + ot->name = "Insert Keyframes"; + ot->idname = "GRAPH_OT_keyframe_insert"; + ot->description = "Insert keyframes for the specified channels"; - /* api callbacks */ - ot->invoke = WM_menu_invoke; - ot->exec = graphkeys_insertkey_exec; - ot->poll = graphop_editable_keyframes_poll; + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = graphkeys_insertkey_exec; + ot->poll = graphop_editable_keyframes_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* id-props */ - ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_insertkey_types, 0, "Type", ""); + /* id-props */ + ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_insertkey_types, 0, "Type", ""); } /* ******************** Click-Insert Keyframes Operator ************************* */ static int graphkeys_click_insert_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - bAnimListElem *ale; - AnimData *adt; - FCurve *fcu; - float frame, val; - - /* get animation context */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* get active F-Curve 'anim-list-element' */ - ale = get_active_fcurve_channel(&ac); - if (ELEM(NULL, ale, ale->data)) { - if (ale) MEM_freeN(ale); - return OPERATOR_CANCELLED; - } - fcu = ale->data; - - /* when there are F-Modifiers on the curve, only allow adding - * keyframes if these will be visible after doing so... - */ - if (fcurve_is_keyframable(fcu)) { - ListBase anim_data; - ToolSettings *ts = ac.scene->toolsettings; - - short mapping_flag = ANIM_get_normalization_flags(&ac); - float scale, offset; - - /* preserve selection? */ - if (RNA_boolean_get(op->ptr, "extend") == false) { - /* deselect all keyframes first, so that we can immediately start manipulating the newly added one(s) - * - only affect the keyframes themselves, as we don't want channels popping in and out... - */ - deselect_graph_keys(&ac, false, SELECT_SUBTRACT, false); - } - - /* get frame and value from props */ - frame = RNA_float_get(op->ptr, "frame"); - val = RNA_float_get(op->ptr, "value"); - - /* apply inverse NLA-mapping to frame to get correct time in un-scaled action */ - adt = ANIM_nla_mapping_get(&ac, ale); - frame = BKE_nla_tweakedit_remap(adt, frame, NLATIME_CONVERT_UNMAP); - - /* apply inverse unit-mapping to value to get correct value for F-Curves */ - scale = ANIM_unit_mapping_get_factor(ac.scene, ale->id, fcu, mapping_flag | ANIM_UNITCONV_RESTORE, &offset); - - val = val * scale - offset; - - /* insert keyframe on the specified frame + value */ - insert_vert_fcurve(fcu, frame, val, ts->keyframe_type, 0); - - ale->update |= ANIM_UPDATE_DEPS; - - BLI_listbase_clear(&anim_data); - BLI_addtail(&anim_data, ale); - - ANIM_animdata_update(&ac, &anim_data); - } - else { - /* warn about why this can't happen */ - if (fcu->fpt) - BKE_report(op->reports, RPT_ERROR, "Keyframes cannot be added to sampled F-Curves"); - else if (fcu->flag & FCURVE_PROTECTED) - BKE_report(op->reports, RPT_ERROR, "Active F-Curve is not editable"); - else - BKE_report(op->reports, RPT_ERROR, "Remove F-Modifiers from F-Curve to add keyframes"); - } - - /* free temp data */ - MEM_freeN(ale); - - /* set notifier that keyframes have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); - - /* done */ - return OPERATOR_FINISHED; + bAnimContext ac; + bAnimListElem *ale; + AnimData *adt; + FCurve *fcu; + float frame, val; + + /* get animation context */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get active F-Curve 'anim-list-element' */ + ale = get_active_fcurve_channel(&ac); + if (ELEM(NULL, ale, ale->data)) { + if (ale) + MEM_freeN(ale); + return OPERATOR_CANCELLED; + } + fcu = ale->data; + + /* when there are F-Modifiers on the curve, only allow adding + * keyframes if these will be visible after doing so... + */ + if (fcurve_is_keyframable(fcu)) { + ListBase anim_data; + ToolSettings *ts = ac.scene->toolsettings; + + short mapping_flag = ANIM_get_normalization_flags(&ac); + float scale, offset; + + /* preserve selection? */ + if (RNA_boolean_get(op->ptr, "extend") == false) { + /* deselect all keyframes first, so that we can immediately start manipulating the newly added one(s) + * - only affect the keyframes themselves, as we don't want channels popping in and out... + */ + deselect_graph_keys(&ac, false, SELECT_SUBTRACT, false); + } + + /* get frame and value from props */ + frame = RNA_float_get(op->ptr, "frame"); + val = RNA_float_get(op->ptr, "value"); + + /* apply inverse NLA-mapping to frame to get correct time in un-scaled action */ + adt = ANIM_nla_mapping_get(&ac, ale); + frame = BKE_nla_tweakedit_remap(adt, frame, NLATIME_CONVERT_UNMAP); + + /* apply inverse unit-mapping to value to get correct value for F-Curves */ + scale = ANIM_unit_mapping_get_factor( + ac.scene, ale->id, fcu, mapping_flag | ANIM_UNITCONV_RESTORE, &offset); + + val = val * scale - offset; + + /* insert keyframe on the specified frame + value */ + insert_vert_fcurve(fcu, frame, val, ts->keyframe_type, 0); + + ale->update |= ANIM_UPDATE_DEPS; + + BLI_listbase_clear(&anim_data); + BLI_addtail(&anim_data, ale); + + ANIM_animdata_update(&ac, &anim_data); + } + else { + /* warn about why this can't happen */ + if (fcu->fpt) + BKE_report(op->reports, RPT_ERROR, "Keyframes cannot be added to sampled F-Curves"); + else if (fcu->flag & FCURVE_PROTECTED) + BKE_report(op->reports, RPT_ERROR, "Active F-Curve is not editable"); + else + BKE_report(op->reports, RPT_ERROR, "Remove F-Modifiers from F-Curve to add keyframes"); + } + + /* free temp data */ + MEM_freeN(ale); + + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; } static int graphkeys_click_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - bAnimContext ac; - ARegion *ar; - View2D *v2d; - int mval[2]; - float x, y; + bAnimContext ac; + ARegion *ar; + View2D *v2d; + int mval[2]; + float x, y; - /* get animation context */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get animation context */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* store mouse coordinates in View2D space, into the operator's properties */ - ar = ac.ar; - v2d = &ar->v2d; + /* store mouse coordinates in View2D space, into the operator's properties */ + ar = ac.ar; + v2d = &ar->v2d; - mval[0] = (event->x - ar->winrct.xmin); - mval[1] = (event->y - ar->winrct.ymin); + mval[0] = (event->x - ar->winrct.xmin); + mval[1] = (event->y - ar->winrct.ymin); - UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y); + UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y); - RNA_float_set(op->ptr, "frame", x); - RNA_float_set(op->ptr, "value", y); + RNA_float_set(op->ptr, "frame", x); + RNA_float_set(op->ptr, "value", y); - /* run exec now */ - return graphkeys_click_insert_exec(C, op); + /* run exec now */ + return graphkeys_click_insert_exec(C, op); } void GRAPH_OT_click_insert(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Click-Insert Keyframes"; - ot->idname = "GRAPH_OT_click_insert"; - ot->description = "Insert new keyframe at the cursor position for the active F-Curve"; - - /* api callbacks */ - ot->invoke = graphkeys_click_insert_invoke; - ot->exec = graphkeys_click_insert_exec; - ot->poll = graphop_active_fcurve_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - RNA_def_float(ot->srna, "frame", 1.0f, -FLT_MAX, FLT_MAX, "Frame Number", "Frame to insert keyframe on", 0, 100); - RNA_def_float(ot->srna, "value", 1.0f, -FLT_MAX, FLT_MAX, "Value", "Value for keyframe on", 0, 100); - - RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first"); + /* identifiers */ + ot->name = "Click-Insert Keyframes"; + ot->idname = "GRAPH_OT_click_insert"; + ot->description = "Insert new keyframe at the cursor position for the active F-Curve"; + + /* api callbacks */ + ot->invoke = graphkeys_click_insert_invoke; + ot->exec = graphkeys_click_insert_exec; + ot->poll = graphop_active_fcurve_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + RNA_def_float(ot->srna, + "frame", + 1.0f, + -FLT_MAX, + FLT_MAX, + "Frame Number", + "Frame to insert keyframe on", + 0, + 100); + RNA_def_float( + ot->srna, "value", 1.0f, -FLT_MAX, FLT_MAX, "Value", "Value for keyframe on", 0, 100); + + RNA_def_boolean(ot->srna, + "extend", + false, + "Extend", + "Extend selection instead of deselecting everything first"); } /* ******************** Copy/Paste Keyframes Operator ************************* */ @@ -802,342 +878,359 @@ void GRAPH_OT_click_insert(wmOperatorType *ot) static short copy_graph_keys(bAnimContext *ac) { - ListBase anim_data = {NULL, NULL}; - int filter, ok = 0; + ListBase anim_data = {NULL, NULL}; + int filter, ok = 0; - /* clear buffer first */ - ANIM_fcurves_copybuf_free(); + /* clear buffer first */ + ANIM_fcurves_copybuf_free(); - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - /* copy keyframes */ - ok = copy_animedit_keys(ac, &anim_data); + /* copy keyframes */ + ok = copy_animedit_keys(ac, &anim_data); - /* clean up */ - ANIM_animdata_freelist(&anim_data); + /* clean up */ + ANIM_animdata_freelist(&anim_data); - return ok; + return ok; } static short paste_graph_keys(bAnimContext *ac, - const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode, bool flip) + const eKeyPasteOffset offset_mode, + const eKeyMergeMode merge_mode, + bool flip) { - ListBase anim_data = {NULL, NULL}; - int filter, ok = 0; + ListBase anim_data = {NULL, NULL}; + int filter, ok = 0; - /* filter data - * - First time we try to filter more strictly, allowing only selected channels - * to allow copying animation between channels - * - Second time, we loosen things up if nothing was found the first time, allowing - * users to just paste keyframes back into the original curve again [#31670] - */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); + /* filter data + * - First time we try to filter more strictly, allowing only selected channels + * to allow copying animation between channels + * - Second time, we loosen things up if nothing was found the first time, allowing + * users to just paste keyframes back into the original curve again [#31670] + */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | + ANIMFILTER_NODUPLIS); - if (ANIM_animdata_filter(ac, &anim_data, filter | ANIMFILTER_SEL, ac->data, ac->datatype) == 0) - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + if (ANIM_animdata_filter(ac, &anim_data, filter | ANIMFILTER_SEL, ac->data, ac->datatype) == 0) + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - /* paste keyframes */ - ok = paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode, flip); + /* paste keyframes */ + ok = paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode, flip); - /* clean up */ - ANIM_animdata_freelist(&anim_data); + /* clean up */ + ANIM_animdata_freelist(&anim_data); - return ok; + return ok; } /* ------------------- */ static int graphkeys_copy_exec(bContext *C, wmOperator *op) { - bAnimContext ac; + bAnimContext ac; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* copy keyframes */ - if (copy_graph_keys(&ac)) { - BKE_report(op->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer"); - return OPERATOR_CANCELLED; - } + /* copy keyframes */ + if (copy_graph_keys(&ac)) { + BKE_report(op->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer"); + return OPERATOR_CANCELLED; + } - /* just return - no operator needed here (no changes) */ - return OPERATOR_FINISHED; + /* just return - no operator needed here (no changes) */ + return OPERATOR_FINISHED; } void GRAPH_OT_copy(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Copy Keyframes"; - ot->idname = "GRAPH_OT_copy"; - ot->description = "Copy selected keyframes to the copy/paste buffer"; + /* identifiers */ + ot->name = "Copy Keyframes"; + ot->idname = "GRAPH_OT_copy"; + ot->description = "Copy selected keyframes to the copy/paste buffer"; - /* api callbacks */ - ot->exec = graphkeys_copy_exec; - ot->poll = graphop_editable_keyframes_poll; + /* api callbacks */ + ot->exec = graphkeys_copy_exec; + ot->poll = graphop_editable_keyframes_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } - - static int graphkeys_paste_exec(bContext *C, wmOperator *op) { - bAnimContext ac; + bAnimContext ac; - const eKeyPasteOffset offset_mode = RNA_enum_get(op->ptr, "offset"); - const eKeyMergeMode merge_mode = RNA_enum_get(op->ptr, "merge"); - const bool flipped = RNA_boolean_get(op->ptr, "flipped"); + const eKeyPasteOffset offset_mode = RNA_enum_get(op->ptr, "offset"); + const eKeyMergeMode merge_mode = RNA_enum_get(op->ptr, "merge"); + const bool flipped = RNA_boolean_get(op->ptr, "flipped"); - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* ac.reports by default will be the global reports list, which won't show warnings */ - ac.reports = op->reports; + /* ac.reports by default will be the global reports list, which won't show warnings */ + ac.reports = op->reports; - /* paste keyframes - non-zero return means an error occurred while trying to paste */ - if (paste_graph_keys(&ac, offset_mode, merge_mode, flipped)) { - return OPERATOR_CANCELLED; - } + /* paste keyframes - non-zero return means an error occurred while trying to paste */ + if (paste_graph_keys(&ac, offset_mode, merge_mode, flipped)) { + return OPERATOR_CANCELLED; + } - /* set notifier that keyframes have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_paste(wmOperatorType *ot) { - PropertyRNA *prop; - - /* identifiers */ - ot->name = "Paste Keyframes"; - ot->idname = "GRAPH_OT_paste"; - ot->description = "Paste keyframes from copy/paste buffer for the selected channels, starting on the current frame"; - - /* api callbacks */ -// ot->invoke = WM_operator_props_popup; // better wait for graph redo panel - ot->exec = graphkeys_paste_exec; - ot->poll = graphop_editable_keyframes_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* props */ - RNA_def_enum(ot->srna, "offset", rna_enum_keyframe_paste_offset_items, KEYFRAME_PASTE_OFFSET_CFRA_START, "Offset", "Paste time offset of keys"); - RNA_def_enum(ot->srna, "merge", rna_enum_keyframe_paste_merge_items, KEYFRAME_PASTE_MERGE_MIX, "Type", "Method of merging pasted keys and existing"); - prop = RNA_def_boolean(ot->srna, "flipped", false, "Flipped", "Paste keyframes from mirrored bones if they exist"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Paste Keyframes"; + ot->idname = "GRAPH_OT_paste"; + ot->description = + "Paste keyframes from copy/paste buffer for the selected channels, starting on the current " + "frame"; + + /* api callbacks */ + // ot->invoke = WM_operator_props_popup; // better wait for graph redo panel + ot->exec = graphkeys_paste_exec; + ot->poll = graphop_editable_keyframes_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* props */ + RNA_def_enum(ot->srna, + "offset", + rna_enum_keyframe_paste_offset_items, + KEYFRAME_PASTE_OFFSET_CFRA_START, + "Offset", + "Paste time offset of keys"); + RNA_def_enum(ot->srna, + "merge", + rna_enum_keyframe_paste_merge_items, + KEYFRAME_PASTE_MERGE_MIX, + "Type", + "Method of merging pasted keys and existing"); + prop = RNA_def_boolean( + ot->srna, "flipped", false, "Flipped", "Paste keyframes from mirrored bones if they exist"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* ******************** Duplicate Keyframes Operator ************************* */ static void duplicate_graph_keys(bAnimContext *ac) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | + ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - /* loop through filtered data and delete selected keys */ - for (ale = anim_data.first; ale; ale = ale->next) { - duplicate_fcurve_keys((FCurve *)ale->key_data); + /* loop through filtered data and delete selected keys */ + for (ale = anim_data.first; ale; ale = ale->next) { + duplicate_fcurve_keys((FCurve *)ale->key_data); - ale->update |= ANIM_UPDATE_DEFAULT; - } + ale->update |= ANIM_UPDATE_DEFAULT; + } - ANIM_animdata_update(ac, &anim_data); - ANIM_animdata_freelist(&anim_data); + ANIM_animdata_update(ac, &anim_data); + ANIM_animdata_freelist(&anim_data); } /* ------------------- */ static int graphkeys_duplicate_exec(bContext *C, wmOperator *UNUSED(op)) { - bAnimContext ac; + bAnimContext ac; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* duplicate keyframes */ - duplicate_graph_keys(&ac); + /* duplicate keyframes */ + duplicate_graph_keys(&ac); - /* set notifier that keyframes have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_duplicate(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Duplicate Keyframes"; - ot->idname = "GRAPH_OT_duplicate"; - ot->description = "Make a copy of all selected keyframes"; + /* identifiers */ + ot->name = "Duplicate Keyframes"; + ot->idname = "GRAPH_OT_duplicate"; + ot->description = "Make a copy of all selected keyframes"; - /* api callbacks */ - ot->exec = graphkeys_duplicate_exec; - ot->poll = graphop_editable_keyframes_poll; + /* api callbacks */ + ot->exec = graphkeys_duplicate_exec; + ot->poll = graphop_editable_keyframes_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* to give to transform */ - RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", ""); + /* to give to transform */ + RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", ""); } /* ******************** Delete Keyframes Operator ************************* */ static bool delete_graph_keys(bAnimContext *ac) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - bool changed_final = false; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + bool changed_final = false; - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | + ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - /* loop through filtered data and delete selected keys */ - for (ale = anim_data.first; ale; ale = ale->next) { - FCurve *fcu = (FCurve *)ale->key_data; - AnimData *adt = ale->adt; - bool changed; + /* loop through filtered data and delete selected keys */ + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu = (FCurve *)ale->key_data; + AnimData *adt = ale->adt; + bool changed; - /* delete selected keyframes only */ - changed = delete_fcurve_keys(fcu); + /* delete selected keyframes only */ + changed = delete_fcurve_keys(fcu); - if (changed) { - ale->update |= ANIM_UPDATE_DEFAULT; - changed_final = true; - } + if (changed) { + ale->update |= ANIM_UPDATE_DEFAULT; + changed_final = true; + } - /* Only delete curve too if it won't be doing anything anymore */ - if ((fcu->totvert == 0) && - (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0) && - (fcu->driver == NULL)) - { - ANIM_fcurve_delete_from_animdata(ac, adt, fcu); - ale->key_data = NULL; - } - } + /* Only delete curve too if it won't be doing anything anymore */ + if ((fcu->totvert == 0) && + (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0) && + (fcu->driver == NULL)) { + ANIM_fcurve_delete_from_animdata(ac, adt, fcu); + ale->key_data = NULL; + } + } - ANIM_animdata_update(ac, &anim_data); - ANIM_animdata_freelist(&anim_data); + ANIM_animdata_update(ac, &anim_data); + ANIM_animdata_freelist(&anim_data); - return changed_final; + return changed_final; } /* ------------------- */ static int graphkeys_delete_exec(bContext *C, wmOperator *UNUSED(op)) { - bAnimContext ac; + bAnimContext ac; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* delete keyframes */ - if (!delete_graph_keys(&ac)) - return OPERATOR_CANCELLED; + /* delete keyframes */ + if (!delete_graph_keys(&ac)) + return OPERATOR_CANCELLED; - /* set notifier that keyframes have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_delete(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Delete Keyframes"; - ot->idname = "GRAPH_OT_delete"; - ot->description = "Remove all selected keyframes"; + /* identifiers */ + ot->name = "Delete Keyframes"; + ot->idname = "GRAPH_OT_delete"; + ot->description = "Remove all selected keyframes"; - /* api callbacks */ - ot->invoke = WM_operator_confirm; - ot->exec = graphkeys_delete_exec; - ot->poll = graphop_editable_keyframes_poll; + /* api callbacks */ + ot->invoke = WM_operator_confirm; + ot->exec = graphkeys_delete_exec; + ot->poll = graphop_editable_keyframes_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ******************** Clean Keyframes Operator ************************* */ static void clean_graph_keys(bAnimContext *ac, float thresh, bool clean_chan) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | + ANIMFILTER_SEL | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - /* loop through filtered data and clean curves */ - for (ale = anim_data.first; ale; ale = ale->next) { - clean_fcurve(ac, ale, thresh, clean_chan); + /* loop through filtered data and clean curves */ + for (ale = anim_data.first; ale; ale = ale->next) { + clean_fcurve(ac, ale, thresh, clean_chan); - ale->update |= ANIM_UPDATE_DEFAULT; - } + ale->update |= ANIM_UPDATE_DEFAULT; + } - ANIM_animdata_update(ac, &anim_data); - ANIM_animdata_freelist(&anim_data); + ANIM_animdata_update(ac, &anim_data); + ANIM_animdata_freelist(&anim_data); } /* ------------------- */ static int graphkeys_clean_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - float thresh; - bool clean_chan; + bAnimContext ac; + float thresh; + bool clean_chan; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* get cleaning threshold */ - thresh = RNA_float_get(op->ptr, "threshold"); - clean_chan = RNA_boolean_get(op->ptr, "channels"); - /* clean keyframes */ - clean_graph_keys(&ac, thresh, clean_chan); + /* get cleaning threshold */ + thresh = RNA_float_get(op->ptr, "threshold"); + clean_chan = RNA_boolean_get(op->ptr, "channels"); + /* clean keyframes */ + clean_graph_keys(&ac, thresh, clean_chan); - /* set notifier that keyframes have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_clean(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Clean Keyframes"; - ot->idname = "GRAPH_OT_clean"; - ot->description = "Simplify F-Curves by removing closely spaced keyframes"; + /* identifiers */ + ot->name = "Clean Keyframes"; + ot->idname = "GRAPH_OT_clean"; + ot->description = "Simplify F-Curves by removing closely spaced keyframes"; - /* api callbacks */ - //ot->invoke = // XXX we need that number popup for this! - ot->exec = graphkeys_clean_exec; - ot->poll = graphop_editable_keyframes_poll; + /* api callbacks */ + //ot->invoke = // XXX we need that number popup for this! + ot->exec = graphkeys_clean_exec; + ot->poll = graphop_editable_keyframes_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ - ot->prop = RNA_def_float(ot->srna, "threshold", 0.001f, 0.0f, FLT_MAX, "Threshold", "", 0.0f, 1000.0f); - RNA_def_boolean(ot->srna, "channels", false, "Channels", ""); + /* properties */ + ot->prop = RNA_def_float( + ot->srna, "threshold", 0.001f, 0.0f, FLT_MAX, "Threshold", "", 0.0f, 1000.0f); + RNA_def_boolean(ot->srna, "channels", false, "Channels", ""); } /* ******************** Bake F-Curve Operator *********************** */ @@ -1146,79 +1239,80 @@ void GRAPH_OT_clean(wmOperatorType *ot) /* Bake each F-Curve into a set of samples */ static void bake_graph_curves(bAnimContext *ac, int start, int end) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL | + ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - /* loop through filtered data and add keys between selected keyframes on every frame */ - for (ale = anim_data.first; ale; ale = ale->next) { - FCurve *fcu = (FCurve *)ale->key_data; - ChannelDriver *driver = fcu->driver; + /* loop through filtered data and add keys between selected keyframes on every frame */ + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu = (FCurve *)ale->key_data; + ChannelDriver *driver = fcu->driver; - /* disable driver so that it don't muck up the sampling process */ - fcu->driver = NULL; + /* disable driver so that it don't muck up the sampling process */ + fcu->driver = NULL; - /* create samples */ - fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve); + /* create samples */ + fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve); - /* restore driver */ - fcu->driver = driver; + /* restore driver */ + fcu->driver = driver; - ale->update |= ANIM_UPDATE_DEPS; - } + ale->update |= ANIM_UPDATE_DEPS; + } - ANIM_animdata_update(ac, &anim_data); - ANIM_animdata_freelist(&anim_data); + ANIM_animdata_update(ac, &anim_data); + ANIM_animdata_freelist(&anim_data); } /* ------------------- */ static int graphkeys_bake_exec(bContext *C, wmOperator *UNUSED(op)) { - bAnimContext ac; - Scene *scene = NULL; - int start, end; + bAnimContext ac; + Scene *scene = NULL; + int start, end; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* for now, init start/end from preview-range extents */ - // TODO: add properties for this - scene = ac.scene; - start = PSFRA; - end = PEFRA; + /* for now, init start/end from preview-range extents */ + // TODO: add properties for this + scene = ac.scene; + start = PSFRA; + end = PEFRA; - /* bake keyframes */ - bake_graph_curves(&ac, start, end); + /* bake keyframes */ + bake_graph_curves(&ac, start, end); - /* set notifier that keyframes have changed */ - // NOTE: some distinction between order/number of keyframes and type should be made? - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + /* set notifier that keyframes have changed */ + // NOTE: some distinction between order/number of keyframes and type should be made? + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_bake(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Bake Curve"; - ot->idname = "GRAPH_OT_bake"; - ot->description = "Bake selected F-Curves to a set of sampled points defining a similar curve"; + /* identifiers */ + ot->name = "Bake Curve"; + ot->idname = "GRAPH_OT_bake"; + ot->description = "Bake selected F-Curves to a set of sampled points defining a similar curve"; - /* api callbacks */ - ot->invoke = WM_operator_confirm; // FIXME... - ot->exec = graphkeys_bake_exec; - ot->poll = graphop_selected_fcurve_poll; + /* api callbacks */ + ot->invoke = WM_operator_confirm; // FIXME... + ot->exec = graphkeys_bake_exec; + ot->poll = graphop_selected_fcurve_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - // todo: add props for start/end frames + // todo: add props for start/end frames } #ifdef WITH_AUDASPACE @@ -1232,9 +1326,9 @@ void GRAPH_OT_bake(wmOperatorType *ot) * which provides the necessary info for baking the sound */ typedef struct tSoundBakeInfo { - float *samples; - int length; - int cfra; + float *samples; + int length; + int cfra; } tSoundBakeInfo; /* ------------------- */ @@ -1244,154 +1338,214 @@ typedef struct tSoundBakeInfo { */ static float fcurve_samplingcb_sound(FCurve *UNUSED(fcu), void *data, float evaltime) { - tSoundBakeInfo *sbi = (tSoundBakeInfo *)data; + tSoundBakeInfo *sbi = (tSoundBakeInfo *)data; - int position = evaltime - sbi->cfra; - if ((position < 0) || (position >= sbi->length)) - return 0.0f; + int position = evaltime - sbi->cfra; + if ((position < 0) || (position >= sbi->length)) + return 0.0f; - return sbi->samples[position]; + return sbi->samples[position]; } /* ------------------- */ static int graphkeys_sound_bake_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; + bAnimContext ac; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; - tSoundBakeInfo sbi; - Scene *scene = NULL; - int start, end; + tSoundBakeInfo sbi; + Scene *scene = NULL; + int start, end; - char path[FILE_MAX]; + char path[FILE_MAX]; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - RNA_string_get(op->ptr, "filepath", path); + RNA_string_get(op->ptr, "filepath", path); - if (!BLI_is_file(path)) { - BKE_reportf(op->reports, RPT_ERROR, "File not found '%s'", path); - return OPERATOR_CANCELLED; - } + if (!BLI_is_file(path)) { + BKE_reportf(op->reports, RPT_ERROR, "File not found '%s'", path); + return OPERATOR_CANCELLED; + } - scene = ac.scene; /* current scene */ + scene = ac.scene; /* current scene */ - /* store necessary data for the baking steps */ - sbi.samples = AUD_readSoundBuffer(path, - RNA_float_get(op->ptr, "low"), - RNA_float_get(op->ptr, "high"), - RNA_float_get(op->ptr, "attack"), - RNA_float_get(op->ptr, "release"), - RNA_float_get(op->ptr, "threshold"), - RNA_boolean_get(op->ptr, "use_accumulate"), - RNA_boolean_get(op->ptr, "use_additive"), - RNA_boolean_get(op->ptr, "use_square"), - RNA_float_get(op->ptr, "sthreshold"), - FPS, &sbi.length); + /* store necessary data for the baking steps */ + sbi.samples = AUD_readSoundBuffer(path, + RNA_float_get(op->ptr, "low"), + RNA_float_get(op->ptr, "high"), + RNA_float_get(op->ptr, "attack"), + RNA_float_get(op->ptr, "release"), + RNA_float_get(op->ptr, "threshold"), + RNA_boolean_get(op->ptr, "use_accumulate"), + RNA_boolean_get(op->ptr, "use_additive"), + RNA_boolean_get(op->ptr, "use_square"), + RNA_float_get(op->ptr, "sthreshold"), + FPS, + &sbi.length); - if (sbi.samples == NULL) { - BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); - return OPERATOR_CANCELLED; - } + if (sbi.samples == NULL) { + BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); + return OPERATOR_CANCELLED; + } - /* determine extents of the baking */ - sbi.cfra = start = CFRA; - end = CFRA + sbi.length - 1; + /* determine extents of the baking */ + sbi.cfra = start = CFRA; + end = CFRA + sbi.length - 1; - /* filter anim channels */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + /* filter anim channels */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL | + ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - /* loop through all selected F-Curves, replacing its data with the sound samples */ - for (ale = anim_data.first; ale; ale = ale->next) { - FCurve *fcu = (FCurve *)ale->key_data; + /* loop through all selected F-Curves, replacing its data with the sound samples */ + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu = (FCurve *)ale->key_data; - /* sample the sound */ - fcurve_store_samples(fcu, &sbi, start, end, fcurve_samplingcb_sound); + /* sample the sound */ + fcurve_store_samples(fcu, &sbi, start, end, fcurve_samplingcb_sound); - ale->update |= ANIM_UPDATE_DEFAULT; - } + ale->update |= ANIM_UPDATE_DEFAULT; + } - /* free sample data */ - free(sbi.samples); + /* free sample data */ + free(sbi.samples); - /* validate keyframes after editing */ - ANIM_animdata_update(&ac, &anim_data); - ANIM_animdata_freelist(&anim_data); + /* validate keyframes after editing */ + ANIM_animdata_update(&ac, &anim_data); + ANIM_animdata_freelist(&anim_data); - /* set notifier that 'keyframes' have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + /* set notifier that 'keyframes' have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } -#else //WITH_AUDASPACE +#else //WITH_AUDASPACE static int graphkeys_sound_bake_exec(bContext *UNUSED(C), wmOperator *op) { - BKE_report(op->reports, RPT_ERROR, "Compiled without sound support"); + BKE_report(op->reports, RPT_ERROR, "Compiled without sound support"); - return OPERATOR_CANCELLED; + return OPERATOR_CANCELLED; } -#endif //WITH_AUDASPACE +#endif //WITH_AUDASPACE static int graphkeys_sound_bake_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - bAnimContext ac; + bAnimContext ac; - /* verify editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* verify editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - return WM_operator_filesel(C, op, event); + return WM_operator_filesel(C, op, event); } void GRAPH_OT_sound_bake(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Bake Sound to F-Curves"; - ot->idname = "GRAPH_OT_sound_bake"; - ot->description = "Bakes a sound wave to selected F-Curves"; - - /* api callbacks */ - ot->invoke = graphkeys_sound_bake_invoke; - ot->exec = graphkeys_sound_bake_exec; - ot->poll = graphop_selected_fcurve_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - WM_operator_properties_filesel( - ot, FILE_TYPE_FOLDER | FILE_TYPE_SOUND | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE, - WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); - RNA_def_float(ot->srna, "low", 0.0f, 0.0, 100000.0, "Lowest frequency", - "Cutoff frequency of a high-pass filter that is applied to the audio data", 0.1, 1000.00); - RNA_def_float(ot->srna, "high", 100000.0, 0.0, 100000.0, "Highest frequency", - "Cutoff frequency of a low-pass filter that is applied to the audio data", 0.1, 1000.00); - RNA_def_float(ot->srna, "attack", 0.005, 0.0, 2.0, "Attack time", - "Value for the hull curve calculation that tells how fast the hull curve can rise " - "(the lower the value the steeper it can rise)", 0.01, 0.1); - RNA_def_float(ot->srna, "release", 0.2, 0.0, 5.0, "Release time", - "Value for the hull curve calculation that tells how fast the hull curve can fall " - "(the lower the value the steeper it can fall)", 0.01, 0.2); - RNA_def_float(ot->srna, "threshold", 0.0, 0.0, 1.0, "Threshold", - "Minimum amplitude value needed to influence the hull curve", 0.01, 0.1); - RNA_def_boolean(ot->srna, "use_accumulate", 0, "Accumulate", - "Only the positive differences of the hull curve amplitudes are summarized to produce the output"); - RNA_def_boolean(ot->srna, "use_additive", 0, "Additive", - "The amplitudes of the hull curve are summarized (or, when Accumulate is enabled, " - "both positive and negative differences are accumulated)"); - RNA_def_boolean(ot->srna, "use_square", 0, "Square", - "The output is a square curve (negative values always result in -1, and positive ones in 1)"); - RNA_def_float(ot->srna, "sthreshold", 0.1, 0.0, 1.0, "Square Threshold", - "Square only: all values with an absolute amplitude lower than that result in 0", 0.01, 0.1); + /* identifiers */ + ot->name = "Bake Sound to F-Curves"; + ot->idname = "GRAPH_OT_sound_bake"; + ot->description = "Bakes a sound wave to selected F-Curves"; + + /* api callbacks */ + ot->invoke = graphkeys_sound_bake_invoke; + ot->exec = graphkeys_sound_bake_exec; + ot->poll = graphop_selected_fcurve_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + WM_operator_properties_filesel(ot, + FILE_TYPE_FOLDER | FILE_TYPE_SOUND | FILE_TYPE_MOVIE, + FILE_SPECIAL, + FILE_OPENFILE, + WM_FILESEL_FILEPATH, + FILE_DEFAULTDISPLAY, + FILE_SORT_ALPHA); + RNA_def_float(ot->srna, + "low", + 0.0f, + 0.0, + 100000.0, + "Lowest frequency", + "Cutoff frequency of a high-pass filter that is applied to the audio data", + 0.1, + 1000.00); + RNA_def_float(ot->srna, + "high", + 100000.0, + 0.0, + 100000.0, + "Highest frequency", + "Cutoff frequency of a low-pass filter that is applied to the audio data", + 0.1, + 1000.00); + RNA_def_float(ot->srna, + "attack", + 0.005, + 0.0, + 2.0, + "Attack time", + "Value for the hull curve calculation that tells how fast the hull curve can rise " + "(the lower the value the steeper it can rise)", + 0.01, + 0.1); + RNA_def_float(ot->srna, + "release", + 0.2, + 0.0, + 5.0, + "Release time", + "Value for the hull curve calculation that tells how fast the hull curve can fall " + "(the lower the value the steeper it can fall)", + 0.01, + 0.2); + RNA_def_float(ot->srna, + "threshold", + 0.0, + 0.0, + 1.0, + "Threshold", + "Minimum amplitude value needed to influence the hull curve", + 0.01, + 0.1); + RNA_def_boolean(ot->srna, + "use_accumulate", + 0, + "Accumulate", + "Only the positive differences of the hull curve amplitudes are summarized to " + "produce the output"); + RNA_def_boolean( + ot->srna, + "use_additive", + 0, + "Additive", + "The amplitudes of the hull curve are summarized (or, when Accumulate is enabled, " + "both positive and negative differences are accumulated)"); + RNA_def_boolean(ot->srna, + "use_square", + 0, + "Square", + "The output is a square curve (negative values always result in -1, and " + "positive ones in 1)"); + RNA_def_float(ot->srna, + "sthreshold", + 0.1, + 0.0, + 1.0, + "Square Threshold", + "Square only: all values with an absolute amplitude lower than that result in 0", + 0.01, + 0.1); } /* ******************** Sample Keyframes Operator *********************** */ @@ -1402,171 +1556,188 @@ void GRAPH_OT_sound_bake(wmOperatorType *ot) /* Evaluates the curves between each selected keyframe on each frame, and keys the value */ static void sample_graph_keys(bAnimContext *ac) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | + ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - /* loop through filtered data and add keys between selected keyframes on every frame */ - for (ale = anim_data.first; ale; ale = ale->next) { - sample_fcurve((FCurve *)ale->key_data); + /* loop through filtered data and add keys between selected keyframes on every frame */ + for (ale = anim_data.first; ale; ale = ale->next) { + sample_fcurve((FCurve *)ale->key_data); - ale->update |= ANIM_UPDATE_DEPS; - } + ale->update |= ANIM_UPDATE_DEPS; + } - ANIM_animdata_update(ac, &anim_data); - ANIM_animdata_freelist(&anim_data); + ANIM_animdata_update(ac, &anim_data); + ANIM_animdata_freelist(&anim_data); } /* ------------------- */ static int graphkeys_sample_exec(bContext *C, wmOperator *UNUSED(op)) { - bAnimContext ac; + bAnimContext ac; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* sample keyframes */ - sample_graph_keys(&ac); + /* sample keyframes */ + sample_graph_keys(&ac); - /* set notifier that keyframes have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_sample(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Sample Keyframes"; - ot->idname = "GRAPH_OT_sample"; - ot->description = "Add keyframes on every frame between the selected keyframes"; + /* identifiers */ + ot->name = "Sample Keyframes"; + ot->idname = "GRAPH_OT_sample"; + ot->description = "Add keyframes on every frame between the selected keyframes"; - /* api callbacks */ - ot->exec = graphkeys_sample_exec; - ot->poll = graphop_editable_keyframes_poll; + /* api callbacks */ + ot->exec = graphkeys_sample_exec; + ot->poll = graphop_editable_keyframes_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } - /* ************************************************************************** */ /* SETTINGS STUFF */ /* ******************** Set Extrapolation-Type Operator *********************** */ /* defines for make/clear cyclic extrapolation tools */ -#define MAKE_CYCLIC_EXPO -1 -#define CLEAR_CYCLIC_EXPO -2 +#define MAKE_CYCLIC_EXPO -1 +#define CLEAR_CYCLIC_EXPO -2 /* defines for set extrapolation-type for selected keyframes tool */ static const EnumPropertyItem prop_graphkeys_expo_types[] = { - {FCURVE_EXTRAPOLATE_CONSTANT, "CONSTANT", 0, "Constant Extrapolation", "Values on endpoint keyframes are held"}, - {FCURVE_EXTRAPOLATE_LINEAR, "LINEAR", 0, "Linear Extrapolation", "Straight-line slope of end segments are extended past the endpoint keyframes"}, - - {MAKE_CYCLIC_EXPO, "MAKE_CYCLIC", 0, "Make Cyclic (F-Modifier)", "Add Cycles F-Modifier if one doesn't exist already"}, - {CLEAR_CYCLIC_EXPO, "CLEAR_CYCLIC", 0, "Clear Cyclic (F-Modifier)", "Remove Cycles F-Modifier if not needed anymore"}, - {0, NULL, 0, NULL, NULL}, + {FCURVE_EXTRAPOLATE_CONSTANT, + "CONSTANT", + 0, + "Constant Extrapolation", + "Values on endpoint keyframes are held"}, + {FCURVE_EXTRAPOLATE_LINEAR, + "LINEAR", + 0, + "Linear Extrapolation", + "Straight-line slope of end segments are extended past the endpoint keyframes"}, + + {MAKE_CYCLIC_EXPO, + "MAKE_CYCLIC", + 0, + "Make Cyclic (F-Modifier)", + "Add Cycles F-Modifier if one doesn't exist already"}, + {CLEAR_CYCLIC_EXPO, + "CLEAR_CYCLIC", + 0, + "Clear Cyclic (F-Modifier)", + "Remove Cycles F-Modifier if not needed anymore"}, + {0, NULL, 0, NULL, NULL}, }; /* this function is responsible for setting extrapolation mode for keyframes */ static void setexpo_graph_keys(bAnimContext *ac, short mode) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* loop through setting mode per F-Curve */ - for (ale = anim_data.first; ale; ale = ale->next) { - FCurve *fcu = (FCurve *)ale->data; - - if (mode >= 0) { - /* just set mode setting */ - fcu->extend = mode; - - ale->update |= ANIM_UPDATE_HANDLES; - } - else { - /* shortcuts for managing Cycles F-Modifiers to make it easier to toggle cyclic animation - * without having to go through FModifier UI in Graph Editor to do so - */ - if (mode == MAKE_CYCLIC_EXPO) { - /* only add if one doesn't exist */ - if (list_has_suitable_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES, -1) == 0) { - // TODO: add some more preset versions which set different extrapolation options? - add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES, fcu); - } - } - else if (mode == CLEAR_CYCLIC_EXPO) { - /* remove all the modifiers fitting this description */ - FModifier *fcm, *fcn = NULL; - - for (fcm = fcu->modifiers.first; fcm; fcm = fcn) { - fcn = fcm->next; - - if (fcm->type == FMODIFIER_TYPE_CYCLES) - remove_fmodifier(&fcu->modifiers, fcm); - } - } - } - - ale->update |= ANIM_UPDATE_DEPS; - } - - ANIM_animdata_update(ac, &anim_data); - ANIM_animdata_freelist(&anim_data); + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL | + ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* loop through setting mode per F-Curve */ + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu = (FCurve *)ale->data; + + if (mode >= 0) { + /* just set mode setting */ + fcu->extend = mode; + + ale->update |= ANIM_UPDATE_HANDLES; + } + else { + /* shortcuts for managing Cycles F-Modifiers to make it easier to toggle cyclic animation + * without having to go through FModifier UI in Graph Editor to do so + */ + if (mode == MAKE_CYCLIC_EXPO) { + /* only add if one doesn't exist */ + if (list_has_suitable_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES, -1) == 0) { + // TODO: add some more preset versions which set different extrapolation options? + add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES, fcu); + } + } + else if (mode == CLEAR_CYCLIC_EXPO) { + /* remove all the modifiers fitting this description */ + FModifier *fcm, *fcn = NULL; + + for (fcm = fcu->modifiers.first; fcm; fcm = fcn) { + fcn = fcm->next; + + if (fcm->type == FMODIFIER_TYPE_CYCLES) + remove_fmodifier(&fcu->modifiers, fcm); + } + } + } + + ale->update |= ANIM_UPDATE_DEPS; + } + + ANIM_animdata_update(ac, &anim_data); + ANIM_animdata_freelist(&anim_data); } /* ------------------- */ static int graphkeys_expo_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - short mode; + bAnimContext ac; + short mode; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* get handle setting mode */ - mode = RNA_enum_get(op->ptr, "type"); + /* get handle setting mode */ + mode = RNA_enum_get(op->ptr, "type"); - /* set handle type */ - setexpo_graph_keys(&ac, mode); + /* set handle type */ + setexpo_graph_keys(&ac, mode); - /* set notifier that keyframe properties have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); + /* set notifier that keyframe properties have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_extrapolation_type(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Set Keyframe Extrapolation"; - ot->idname = "GRAPH_OT_extrapolation_type"; - ot->description = "Set extrapolation mode for selected F-Curves"; + /* identifiers */ + ot->name = "Set Keyframe Extrapolation"; + ot->idname = "GRAPH_OT_extrapolation_type"; + ot->description = "Set extrapolation mode for selected F-Curves"; - /* api callbacks */ - ot->invoke = WM_menu_invoke; - ot->exec = graphkeys_expo_exec; - ot->poll = graphop_editable_keyframes_poll; + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = graphkeys_expo_exec; + ot->poll = graphop_editable_keyframes_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* id-props */ - ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_expo_types, 0, "Type", ""); + /* id-props */ + ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_expo_types, 0, "Type", ""); } /* ******************** Set Interpolation-Type Operator *********************** */ @@ -1574,134 +1745,140 @@ void GRAPH_OT_extrapolation_type(wmOperatorType *ot) /* this function is responsible for setting interpolation mode for keyframes */ static void setipo_graph_keys(bAnimContext *ac, short mode) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - KeyframeEditFunc set_cb = ANIM_editkeyframes_ipo(mode); + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + KeyframeEditFunc set_cb = ANIM_editkeyframes_ipo(mode); - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | + ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - /* loop through setting BezTriple interpolation - * Note: we do not supply KeyframeEditData to the looper yet. Currently that's not necessary here... - */ - for (ale = anim_data.first; ale; ale = ale->next) { - ANIM_fcurve_keyframes_loop(NULL, ale->key_data, NULL, set_cb, calchandles_fcurve); + /* loop through setting BezTriple interpolation + * Note: we do not supply KeyframeEditData to the looper yet. Currently that's not necessary here... + */ + for (ale = anim_data.first; ale; ale = ale->next) { + ANIM_fcurve_keyframes_loop(NULL, ale->key_data, NULL, set_cb, calchandles_fcurve); - ale->update |= ANIM_UPDATE_DEFAULT_NOHANDLES; - } + ale->update |= ANIM_UPDATE_DEFAULT_NOHANDLES; + } - ANIM_animdata_update(ac, &anim_data); - ANIM_animdata_freelist(&anim_data); + ANIM_animdata_update(ac, &anim_data); + ANIM_animdata_freelist(&anim_data); } /* ------------------- */ static int graphkeys_ipo_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - short mode; + bAnimContext ac; + short mode; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* get handle setting mode */ - mode = RNA_enum_get(op->ptr, "type"); + /* get handle setting mode */ + mode = RNA_enum_get(op->ptr, "type"); - /* set handle type */ - setipo_graph_keys(&ac, mode); + /* set handle type */ + setipo_graph_keys(&ac, mode); - /* set notifier that keyframe properties have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); + /* set notifier that keyframe properties have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_interpolation_type(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Set Keyframe Interpolation"; - ot->idname = "GRAPH_OT_interpolation_type"; - ot->description = "Set interpolation mode for the F-Curve segments starting from the selected keyframes"; + /* identifiers */ + ot->name = "Set Keyframe Interpolation"; + ot->idname = "GRAPH_OT_interpolation_type"; + ot->description = + "Set interpolation mode for the F-Curve segments starting from the selected keyframes"; - /* api callbacks */ - ot->invoke = WM_menu_invoke; - ot->exec = graphkeys_ipo_exec; - ot->poll = graphop_editable_keyframes_poll; + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = graphkeys_ipo_exec; + ot->poll = graphop_editable_keyframes_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* id-props */ - ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_beztriple_interpolation_mode_items, 0, "Type", ""); + /* id-props */ + ot->prop = RNA_def_enum( + ot->srna, "type", rna_enum_beztriple_interpolation_mode_items, 0, "Type", ""); } /* ******************** Set Easing Operator *********************** */ static void seteasing_graph_keys(bAnimContext *ac, short mode) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - KeyframeEditFunc set_cb = ANIM_editkeyframes_easing(mode); + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + KeyframeEditFunc set_cb = ANIM_editkeyframes_easing(mode); - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | + ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - /* loop through setting BezTriple easing - * Note: we do not supply KeyframeEditData to the looper yet. Currently that's not necessary here... - */ - for (ale = anim_data.first; ale; ale = ale->next) { - ANIM_fcurve_keyframes_loop(NULL, ale->key_data, NULL, set_cb, calchandles_fcurve); + /* loop through setting BezTriple easing + * Note: we do not supply KeyframeEditData to the looper yet. Currently that's not necessary here... + */ + for (ale = anim_data.first; ale; ale = ale->next) { + ANIM_fcurve_keyframes_loop(NULL, ale->key_data, NULL, set_cb, calchandles_fcurve); - ale->update |= ANIM_UPDATE_DEFAULT_NOHANDLES; - } + ale->update |= ANIM_UPDATE_DEFAULT_NOHANDLES; + } - ANIM_animdata_update(ac, &anim_data); - ANIM_animdata_freelist(&anim_data); + ANIM_animdata_update(ac, &anim_data); + ANIM_animdata_freelist(&anim_data); } static int graphkeys_easing_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - short mode; + bAnimContext ac; + short mode; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* get handle setting mode */ - mode = RNA_enum_get(op->ptr, "type"); + /* get handle setting mode */ + mode = RNA_enum_get(op->ptr, "type"); - /* set handle type */ - seteasing_graph_keys(&ac, mode); + /* set handle type */ + seteasing_graph_keys(&ac, mode); - /* set notifier that keyframe properties have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); + /* set notifier that keyframe properties have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_easing_type(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Set Keyframe Easing Type"; - ot->idname = "GRAPH_OT_easing_type"; - ot->description = "Set easing type for the F-Curve segments starting from the selected keyframes"; + /* identifiers */ + ot->name = "Set Keyframe Easing Type"; + ot->idname = "GRAPH_OT_easing_type"; + ot->description = + "Set easing type for the F-Curve segments starting from the selected keyframes"; - /* api callbacks */ - ot->invoke = WM_menu_invoke; - ot->exec = graphkeys_easing_exec; - ot->poll = graphop_editable_keyframes_poll; + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = graphkeys_easing_exec; + ot->poll = graphop_editable_keyframes_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* id-props */ - ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_beztriple_interpolation_easing_items, 0, "Type", ""); + /* id-props */ + ot->prop = RNA_def_enum( + ot->srna, "type", rna_enum_beztriple_interpolation_easing_items, 0, "Type", ""); } /* ******************** Set Handle-Type Operator *********************** */ @@ -1709,75 +1886,76 @@ void GRAPH_OT_easing_type(wmOperatorType *ot) /* this function is responsible for setting handle-type of selected keyframes */ static void sethandles_graph_keys(bAnimContext *ac, short mode) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; - KeyframeEditFunc edit_cb = ANIM_editkeyframes_handles(mode); - KeyframeEditFunc sel_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED); + KeyframeEditFunc edit_cb = ANIM_editkeyframes_handles(mode); + KeyframeEditFunc sel_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED); - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | + ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - /* loop through setting flags for handles - * Note: we do not supply KeyframeEditData to the looper yet. Currently that's not necessary here... - */ - for (ale = anim_data.first; ale; ale = ale->next) { - FCurve *fcu = (FCurve *)ale->key_data; + /* loop through setting flags for handles + * Note: we do not supply KeyframeEditData to the looper yet. Currently that's not necessary here... + */ + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu = (FCurve *)ale->key_data; - /* any selected keyframes for editing? */ - if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, sel_cb, NULL)) { - /* change type of selected handles */ - ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, edit_cb, calchandles_fcurve); + /* any selected keyframes for editing? */ + if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, sel_cb, NULL)) { + /* change type of selected handles */ + ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, edit_cb, calchandles_fcurve); - ale->update |= ANIM_UPDATE_DEFAULT; - } - } + ale->update |= ANIM_UPDATE_DEFAULT; + } + } - ANIM_animdata_update(ac, &anim_data); - ANIM_animdata_freelist(&anim_data); + ANIM_animdata_update(ac, &anim_data); + ANIM_animdata_freelist(&anim_data); } /* ------------------- */ static int graphkeys_handletype_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - short mode; + bAnimContext ac; + short mode; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* get handle setting mode */ - mode = RNA_enum_get(op->ptr, "type"); + /* get handle setting mode */ + mode = RNA_enum_get(op->ptr, "type"); - /* set handle type */ - sethandles_graph_keys(&ac, mode); + /* set handle type */ + sethandles_graph_keys(&ac, mode); - /* set notifier that keyframe properties have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); + /* set notifier that keyframe properties have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_handle_type(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Set Keyframe Handle Type"; - ot->idname = "GRAPH_OT_handle_type"; - ot->description = "Set type of handle for selected keyframes"; + /* identifiers */ + ot->name = "Set Keyframe Handle Type"; + ot->idname = "GRAPH_OT_handle_type"; + ot->description = "Set type of handle for selected keyframes"; - /* api callbacks */ - ot->invoke = WM_menu_invoke; - ot->exec = graphkeys_handletype_exec; - ot->poll = graphop_editable_keyframes_poll; + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = graphkeys_handletype_exec; + ot->poll = graphop_editable_keyframes_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* id-props */ - ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_keyframe_handle_type_items, 0, "Type", ""); + /* id-props */ + ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_keyframe_handle_type_items, 0, "Type", ""); } /* ************************************************************************** */ @@ -1792,599 +1970,652 @@ void GRAPH_OT_handle_type(wmOperatorType *ot) /* set of three euler-rotation F-Curves */ typedef struct tEulerFilter { - struct tEulerFilter *next, *prev; - - /** ID-block which owns the channels */ - ID *id; - /** 3 Pointers to F-Curves */ - FCurve *(fcurves[3]); - /** Pointer to one of the RNA Path's used by one of the F-Curves */ - const char *rna_path; + struct tEulerFilter *next, *prev; + + /** ID-block which owns the channels */ + ID *id; + /** 3 Pointers to F-Curves */ + FCurve *(fcurves[3]); + /** Pointer to one of the RNA Path's used by one of the F-Curves */ + const char *rna_path; } tEulerFilter; static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - ListBase eulers = {NULL, NULL}; - tEulerFilter *euf = NULL; - int groups = 0, failed = 0; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* The process is done in two passes: - * 1) Sets of three related rotation curves are identified from the selected channels, - * and are stored as a single 'operation unit' for the next step - * 2) Each set of three F-Curves is processed for each keyframe, with the values being - * processed as necessary - */ - - /* step 1: extract only the rotation f-curves */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - for (ale = anim_data.first; ale; ale = ale->next) { - FCurve *fcu = (FCurve *)ale->data; - - /* check if this is an appropriate F-Curve - * - only rotation curves - * - for pchan curves, make sure we're only using the euler curves - */ - if (strstr(fcu->rna_path, "rotation_euler") == NULL) - continue; - else if (ELEM(fcu->array_index, 0, 1, 2) == 0) { - BKE_reportf(op->reports, RPT_WARNING, - "Euler Rotation F-Curve has invalid index (ID='%s', Path='%s', Index=%d)", - (ale->id) ? ale->id->name : TIP_("<No ID>"), fcu->rna_path, fcu->array_index); - continue; - } - - /* optimization: assume that xyz curves will always be stored consecutively, - * so if the paths or the ID's don't match up, then a curve needs to be added - * to a new group - */ - if ((euf) && (euf->id == ale->id) && (STREQ(euf->rna_path, fcu->rna_path))) { - /* this should be fine to add to the existing group then */ - euf->fcurves[fcu->array_index] = fcu; - } - else { - /* just add to a new block */ - euf = MEM_callocN(sizeof(tEulerFilter), "tEulerFilter"); - BLI_addtail(&eulers, euf); - groups++; - - euf->id = ale->id; - /* this should be safe, since we're only using it for a short time */ - euf->rna_path = fcu->rna_path; - euf->fcurves[fcu->array_index] = fcu; - } - - ale->update |= ANIM_UPDATE_DEFAULT; - } - - if (groups == 0) { - ANIM_animdata_freelist(&anim_data); - BKE_report(op->reports, RPT_WARNING, "No Euler Rotation F-Curves to fix up"); - return OPERATOR_CANCELLED; - } - - /* step 2: go through each set of curves, processing the values at each keyframe - * - it is assumed that there must be a full set of keyframes at each keyframe position - */ - for (euf = eulers.first; euf; euf = euf->next) { - int f; - - /* sanity check: ensure that there are enough F-Curves to work on in this group */ - /* TODO: also enforce assumption that there be a full set of keyframes - * at each position by ensuring that totvert counts are same? */ - if (ELEM(NULL, euf->fcurves[0], euf->fcurves[1], euf->fcurves[2])) { - /* report which components are missing */ - BKE_reportf(op->reports, RPT_WARNING, - "Missing %s%s%s component(s) of euler rotation for ID='%s' and RNA-Path='%s'", - (euf->fcurves[0] == NULL) ? "X" : "", - (euf->fcurves[1] == NULL) ? "Y" : "", - (euf->fcurves[2] == NULL) ? "Z" : "", - euf->id->name, euf->rna_path); - - /* keep track of number of failed sets, and carry on to next group */ - failed++; - continue; - } - - /* simple method: just treat any difference between keys of greater than 180 degrees as being a flip */ - /* FIXME: there are more complicated methods that will be needed to fix more cases than just some */ - for (f = 0; f < 3; f++) { - FCurve *fcu = euf->fcurves[f]; - BezTriple *bezt, *prev; - unsigned int i; - - /* skip if not enough vets to do a decent analysis of... */ - if (fcu->totvert <= 2) - continue; - - /* prev follows bezt, bezt = "current" point to be fixed */ - /* our method depends on determining a "difference" from the previous vert */ - for (i = 1, prev = fcu->bezt, bezt = fcu->bezt + 1; i < fcu->totvert; i++, prev = bezt++) { - const float sign = (prev->vec[1][1] > bezt->vec[1][1]) ? 1.0f : -1.0f; - - /* > 180 degree flip? */ - if ((sign * (prev->vec[1][1] - bezt->vec[1][1])) >= (float)M_PI) { - /* 360 degrees to add/subtract frame value until difference - * is acceptably small that there's no more flip */ - const float fac = sign * 2.0f * (float)M_PI; - - while ((sign * (prev->vec[1][1] - bezt->vec[1][1])) >= (float)M_PI) { - bezt->vec[0][1] += fac; - bezt->vec[1][1] += fac; - bezt->vec[2][1] += fac; - } - } - } - } - } - BLI_freelistN(&eulers); - - ANIM_animdata_update(&ac, &anim_data); - ANIM_animdata_freelist(&anim_data); - - /* updates + finishing warnings */ - if (failed == groups) { - BKE_report(op->reports, RPT_ERROR, - "No Euler Rotations could be corrected, ensure each rotation has keys for all components, " - "and that F-Curves for these are in consecutive XYZ order and selected"); - return OPERATOR_CANCELLED; - } - else { - if (failed) { - BKE_report(op->reports, RPT_ERROR, - "Some Euler Rotations could not be corrected due to missing/unselected/out-of-order F-Curves, " - "ensure each rotation has keys for all components, and that F-Curves for these are in " - "consecutive XYZ order and selected"); - } - - /* set notifier that keyframes have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); - - /* done at last */ - return OPERATOR_FINISHED; - } + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + ListBase eulers = {NULL, NULL}; + tEulerFilter *euf = NULL; + int groups = 0, failed = 0; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* The process is done in two passes: + * 1) Sets of three related rotation curves are identified from the selected channels, + * and are stored as a single 'operation unit' for the next step + * 2) Each set of three F-Curves is processed for each keyframe, with the values being + * processed as necessary + */ + + /* step 1: extract only the rotation f-curves */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_CURVE_VISIBLE | + ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu = (FCurve *)ale->data; + + /* check if this is an appropriate F-Curve + * - only rotation curves + * - for pchan curves, make sure we're only using the euler curves + */ + if (strstr(fcu->rna_path, "rotation_euler") == NULL) + continue; + else if (ELEM(fcu->array_index, 0, 1, 2) == 0) { + BKE_reportf(op->reports, + RPT_WARNING, + "Euler Rotation F-Curve has invalid index (ID='%s', Path='%s', Index=%d)", + (ale->id) ? ale->id->name : TIP_("<No ID>"), + fcu->rna_path, + fcu->array_index); + continue; + } + + /* optimization: assume that xyz curves will always be stored consecutively, + * so if the paths or the ID's don't match up, then a curve needs to be added + * to a new group + */ + if ((euf) && (euf->id == ale->id) && (STREQ(euf->rna_path, fcu->rna_path))) { + /* this should be fine to add to the existing group then */ + euf->fcurves[fcu->array_index] = fcu; + } + else { + /* just add to a new block */ + euf = MEM_callocN(sizeof(tEulerFilter), "tEulerFilter"); + BLI_addtail(&eulers, euf); + groups++; + + euf->id = ale->id; + /* this should be safe, since we're only using it for a short time */ + euf->rna_path = fcu->rna_path; + euf->fcurves[fcu->array_index] = fcu; + } + + ale->update |= ANIM_UPDATE_DEFAULT; + } + + if (groups == 0) { + ANIM_animdata_freelist(&anim_data); + BKE_report(op->reports, RPT_WARNING, "No Euler Rotation F-Curves to fix up"); + return OPERATOR_CANCELLED; + } + + /* step 2: go through each set of curves, processing the values at each keyframe + * - it is assumed that there must be a full set of keyframes at each keyframe position + */ + for (euf = eulers.first; euf; euf = euf->next) { + int f; + + /* sanity check: ensure that there are enough F-Curves to work on in this group */ + /* TODO: also enforce assumption that there be a full set of keyframes + * at each position by ensuring that totvert counts are same? */ + if (ELEM(NULL, euf->fcurves[0], euf->fcurves[1], euf->fcurves[2])) { + /* report which components are missing */ + BKE_reportf(op->reports, + RPT_WARNING, + "Missing %s%s%s component(s) of euler rotation for ID='%s' and RNA-Path='%s'", + (euf->fcurves[0] == NULL) ? "X" : "", + (euf->fcurves[1] == NULL) ? "Y" : "", + (euf->fcurves[2] == NULL) ? "Z" : "", + euf->id->name, + euf->rna_path); + + /* keep track of number of failed sets, and carry on to next group */ + failed++; + continue; + } + + /* simple method: just treat any difference between keys of greater than 180 degrees as being a flip */ + /* FIXME: there are more complicated methods that will be needed to fix more cases than just some */ + for (f = 0; f < 3; f++) { + FCurve *fcu = euf->fcurves[f]; + BezTriple *bezt, *prev; + unsigned int i; + + /* skip if not enough vets to do a decent analysis of... */ + if (fcu->totvert <= 2) + continue; + + /* prev follows bezt, bezt = "current" point to be fixed */ + /* our method depends on determining a "difference" from the previous vert */ + for (i = 1, prev = fcu->bezt, bezt = fcu->bezt + 1; i < fcu->totvert; i++, prev = bezt++) { + const float sign = (prev->vec[1][1] > bezt->vec[1][1]) ? 1.0f : -1.0f; + + /* > 180 degree flip? */ + if ((sign * (prev->vec[1][1] - bezt->vec[1][1])) >= (float)M_PI) { + /* 360 degrees to add/subtract frame value until difference + * is acceptably small that there's no more flip */ + const float fac = sign * 2.0f * (float)M_PI; + + while ((sign * (prev->vec[1][1] - bezt->vec[1][1])) >= (float)M_PI) { + bezt->vec[0][1] += fac; + bezt->vec[1][1] += fac; + bezt->vec[2][1] += fac; + } + } + } + } + } + BLI_freelistN(&eulers); + + ANIM_animdata_update(&ac, &anim_data); + ANIM_animdata_freelist(&anim_data); + + /* updates + finishing warnings */ + if (failed == groups) { + BKE_report( + op->reports, + RPT_ERROR, + "No Euler Rotations could be corrected, ensure each rotation has keys for all components, " + "and that F-Curves for these are in consecutive XYZ order and selected"); + return OPERATOR_CANCELLED; + } + else { + if (failed) { + BKE_report( + op->reports, + RPT_ERROR, + "Some Euler Rotations could not be corrected due to missing/unselected/out-of-order " + "F-Curves, " + "ensure each rotation has keys for all components, and that F-Curves for these are in " + "consecutive XYZ order and selected"); + } + + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + + /* done at last */ + return OPERATOR_FINISHED; + } } void GRAPH_OT_euler_filter(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Euler Discontinuity Filter"; - ot->idname = "GRAPH_OT_euler_filter"; - ot->description = "Fix large jumps and flips in the selected " - "Euler Rotation F-Curves arising from rotation " - "values being clipped when baking physics"; + /* identifiers */ + ot->name = "Euler Discontinuity Filter"; + ot->idname = "GRAPH_OT_euler_filter"; + ot->description = + "Fix large jumps and flips in the selected " + "Euler Rotation F-Curves arising from rotation " + "values being clipped when baking physics"; - /* api callbacks */ - ot->exec = graphkeys_euler_filter_exec; - ot->poll = graphop_editable_keyframes_poll; + /* api callbacks */ + ot->exec = graphkeys_euler_filter_exec; + ot->poll = graphop_editable_keyframes_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ***************** Jump to Selected Frames Operator *********************** */ static bool graphkeys_framejump_poll(bContext *C) { - /* prevent changes during render */ - if (G.is_rendering) - return 0; + /* prevent changes during render */ + if (G.is_rendering) + return 0; - return graphop_visible_keyframes_poll(C); + return graphop_visible_keyframes_poll(C); } /* snap current-frame indicator to 'average time' of selected keyframe */ static int graphkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op)) { - bAnimContext ac; - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - KeyframeEditData ked; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* init edit data */ - memset(&ked, 0, sizeof(KeyframeEditData)); - - /* loop over action data, averaging values */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - for (ale = anim_data.first; ale; ale = ale->next) { - AnimData *adt = ANIM_nla_mapping_get(&ac, ale); - short mapping_flag = ANIM_get_normalization_flags(&ac); - KeyframeEditData current_ked; - float offset; - float unit_scale = ANIM_unit_mapping_get_factor(ac.scene, ale->id, ale->key_data, mapping_flag | ANIM_UNITCONV_ONLYKEYS, &offset); - - memset(¤t_ked, 0, sizeof(current_ked)); - - if (adt) { - ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); - ANIM_fcurve_keyframes_loop(¤t_ked, ale->key_data, NULL, bezt_calc_average, NULL); - ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); - } - else - ANIM_fcurve_keyframes_loop(¤t_ked, ale->key_data, NULL, bezt_calc_average, NULL); - - ked.f1 += current_ked.f1; - ked.i1 += current_ked.i1; - ked.f2 += (current_ked.f2 + offset) * unit_scale; - ked.i2 += current_ked.i2; - } - - ANIM_animdata_freelist(&anim_data); - - /* set the new current frame and cursor values, based on the average time and value */ - if (ked.i1) { - SpaceGraph *sipo = (SpaceGraph *)ac.sl; - Scene *scene = ac.scene; - - /* take the average values, rounding to the nearest int as necessary for int results */ - if (sipo->mode == SIPO_MODE_DRIVERS) { - /* Drivers Mode - Affects cursor (float) */ - sipo->cursorTime = ked.f1 / (float)ked.i1; - sipo->cursorVal = ked.f2 / (float)ked.i1; - } - else { - /* Animation Mode - Affects current frame (int) */ - CFRA = round_fl_to_int(ked.f1 / ked.i1); - SUBFRA = 0.f; - sipo->cursorVal = ked.f2 / (float)ked.i1; - } - } - - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_SCENE | ND_FRAME, ac.scene); - - return OPERATOR_FINISHED; + bAnimContext ac; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + KeyframeEditData ked; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* init edit data */ + memset(&ked, 0, sizeof(KeyframeEditData)); + + /* loop over action data, averaging values */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + for (ale = anim_data.first; ale; ale = ale->next) { + AnimData *adt = ANIM_nla_mapping_get(&ac, ale); + short mapping_flag = ANIM_get_normalization_flags(&ac); + KeyframeEditData current_ked; + float offset; + float unit_scale = ANIM_unit_mapping_get_factor( + ac.scene, ale->id, ale->key_data, mapping_flag | ANIM_UNITCONV_ONLYKEYS, &offset); + + memset(¤t_ked, 0, sizeof(current_ked)); + + if (adt) { + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); + ANIM_fcurve_keyframes_loop(¤t_ked, ale->key_data, NULL, bezt_calc_average, NULL); + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); + } + else + ANIM_fcurve_keyframes_loop(¤t_ked, ale->key_data, NULL, bezt_calc_average, NULL); + + ked.f1 += current_ked.f1; + ked.i1 += current_ked.i1; + ked.f2 += (current_ked.f2 + offset) * unit_scale; + ked.i2 += current_ked.i2; + } + + ANIM_animdata_freelist(&anim_data); + + /* set the new current frame and cursor values, based on the average time and value */ + if (ked.i1) { + SpaceGraph *sipo = (SpaceGraph *)ac.sl; + Scene *scene = ac.scene; + + /* take the average values, rounding to the nearest int as necessary for int results */ + if (sipo->mode == SIPO_MODE_DRIVERS) { + /* Drivers Mode - Affects cursor (float) */ + sipo->cursorTime = ked.f1 / (float)ked.i1; + sipo->cursorVal = ked.f2 / (float)ked.i1; + } + else { + /* Animation Mode - Affects current frame (int) */ + CFRA = round_fl_to_int(ked.f1 / ked.i1); + SUBFRA = 0.f; + sipo->cursorVal = ked.f2 / (float)ked.i1; + } + } + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_SCENE | ND_FRAME, ac.scene); + + return OPERATOR_FINISHED; } void GRAPH_OT_frame_jump(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Jump to Keyframes"; - ot->idname = "GRAPH_OT_frame_jump"; - ot->description = "Place the cursor on the midpoint of selected keyframes"; + /* identifiers */ + ot->name = "Jump to Keyframes"; + ot->idname = "GRAPH_OT_frame_jump"; + ot->description = "Place the cursor on the midpoint of selected keyframes"; - /* api callbacks */ - ot->exec = graphkeys_framejump_exec; - ot->poll = graphkeys_framejump_poll; + /* api callbacks */ + ot->exec = graphkeys_framejump_exec; + ot->poll = graphkeys_framejump_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ******************** Snap Keyframes Operator *********************** */ /* defines for snap keyframes tool */ static const EnumPropertyItem prop_graphkeys_snap_types[] = { - {GRAPHKEYS_SNAP_CFRA, "CFRA", 0, "Current Frame", - "Snap selected keyframes to the current frame"}, - {GRAPHKEYS_SNAP_VALUE, "VALUE", 0, "Cursor Value", - "Set values of selected keyframes to the cursor value (Y/Horizontal component)"}, - {GRAPHKEYS_SNAP_NEAREST_FRAME, "NEAREST_FRAME", 0, "Nearest Frame", - "Snap selected keyframes to the nearest (whole) frame (use to fix accidental sub-frame offsets)"}, - {GRAPHKEYS_SNAP_NEAREST_SECOND, "NEAREST_SECOND", 0, "Nearest Second", - "Snap selected keyframes to the nearest second"}, - {GRAPHKEYS_SNAP_NEAREST_MARKER, "NEAREST_MARKER", 0, "Nearest Marker", - "Snap selected keyframes to the nearest marker"}, - {GRAPHKEYS_SNAP_HORIZONTAL, "HORIZONTAL", 0, "Flatten Handles", - "Flatten handles for a smoother transition"}, - {0, NULL, 0, NULL, NULL}, + {GRAPHKEYS_SNAP_CFRA, + "CFRA", + 0, + "Current Frame", + "Snap selected keyframes to the current frame"}, + {GRAPHKEYS_SNAP_VALUE, + "VALUE", + 0, + "Cursor Value", + "Set values of selected keyframes to the cursor value (Y/Horizontal component)"}, + {GRAPHKEYS_SNAP_NEAREST_FRAME, + "NEAREST_FRAME", + 0, + "Nearest Frame", + "Snap selected keyframes to the nearest (whole) frame (use to fix accidental sub-frame " + "offsets)"}, + {GRAPHKEYS_SNAP_NEAREST_SECOND, + "NEAREST_SECOND", + 0, + "Nearest Second", + "Snap selected keyframes to the nearest second"}, + {GRAPHKEYS_SNAP_NEAREST_MARKER, + "NEAREST_MARKER", + 0, + "Nearest Marker", + "Snap selected keyframes to the nearest marker"}, + {GRAPHKEYS_SNAP_HORIZONTAL, + "HORIZONTAL", + 0, + "Flatten Handles", + "Flatten handles for a smoother transition"}, + {0, NULL, 0, NULL, NULL}, }; /* this function is responsible for snapping keyframes to frame-times */ static void snap_graph_keys(bAnimContext *ac, short mode) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - SpaceGraph *sipo = (SpaceGraph *)ac->sl; - KeyframeEditData ked; - KeyframeEditFunc edit_cb; - float cursor_value = 0.0f; - - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* init custom data for iterating over keyframes */ - memset(&ked, 0, sizeof(KeyframeEditData)); - ked.scene = ac->scene; - if (mode == GRAPHKEYS_SNAP_NEAREST_MARKER) { - ked.list.first = (ac->markers) ? ac->markers->first : NULL; - ked.list.last = (ac->markers) ? ac->markers->last : NULL; - } - else if (mode == GRAPHKEYS_SNAP_VALUE) { - cursor_value = (sipo) ? sipo->cursorVal : 0.0f; - } - else if (mode == GRAPHKEYS_SNAP_CFRA) { - /* In drivers mode, use the cursor value instead - * (We need to use a different callback for that though) - */ - if (sipo->mode == SIPO_MODE_DRIVERS) { - ked.f1 = sipo->cursorTime; - mode = SNAP_KEYS_TIME; - } - } - - /* get beztriple editing callbacks */ - edit_cb = ANIM_editkeyframes_snap(mode); - - /* snap keyframes */ - for (ale = anim_data.first; ale; ale = ale->next) { - AnimData *adt = ANIM_nla_mapping_get(ac, ale); - - /* normalise cursor value (for normalised F-Curves display) */ - if (mode == GRAPHKEYS_SNAP_VALUE) { - short mapping_flag = ANIM_get_normalization_flags(ac); - float offset; - float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, ale->key_data, mapping_flag, &offset); - - ked.f1 = (cursor_value / unit_scale) - offset; - } - - /* perform snapping */ - if (adt) { - ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0); - ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve); - ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0); - } - else - ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve); - - ale->update |= ANIM_UPDATE_DEFAULT; - } - - ANIM_animdata_update(ac, &anim_data); - ANIM_animdata_freelist(&anim_data); + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + SpaceGraph *sipo = (SpaceGraph *)ac->sl; + KeyframeEditData ked; + KeyframeEditFunc edit_cb; + float cursor_value = 0.0f; + + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | + ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* init custom data for iterating over keyframes */ + memset(&ked, 0, sizeof(KeyframeEditData)); + ked.scene = ac->scene; + if (mode == GRAPHKEYS_SNAP_NEAREST_MARKER) { + ked.list.first = (ac->markers) ? ac->markers->first : NULL; + ked.list.last = (ac->markers) ? ac->markers->last : NULL; + } + else if (mode == GRAPHKEYS_SNAP_VALUE) { + cursor_value = (sipo) ? sipo->cursorVal : 0.0f; + } + else if (mode == GRAPHKEYS_SNAP_CFRA) { + /* In drivers mode, use the cursor value instead + * (We need to use a different callback for that though) + */ + if (sipo->mode == SIPO_MODE_DRIVERS) { + ked.f1 = sipo->cursorTime; + mode = SNAP_KEYS_TIME; + } + } + + /* get beztriple editing callbacks */ + edit_cb = ANIM_editkeyframes_snap(mode); + + /* snap keyframes */ + for (ale = anim_data.first; ale; ale = ale->next) { + AnimData *adt = ANIM_nla_mapping_get(ac, ale); + + /* normalise cursor value (for normalised F-Curves display) */ + if (mode == GRAPHKEYS_SNAP_VALUE) { + short mapping_flag = ANIM_get_normalization_flags(ac); + float offset; + float unit_scale = ANIM_unit_mapping_get_factor( + ac->scene, ale->id, ale->key_data, mapping_flag, &offset); + + ked.f1 = (cursor_value / unit_scale) - offset; + } + + /* perform snapping */ + if (adt) { + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0); + ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve); + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0); + } + else + ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve); + + ale->update |= ANIM_UPDATE_DEFAULT; + } + + ANIM_animdata_update(ac, &anim_data); + ANIM_animdata_freelist(&anim_data); } /* ------------------- */ static int graphkeys_snap_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - short mode; + bAnimContext ac; + short mode; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* get snapping mode */ - mode = RNA_enum_get(op->ptr, "type"); + /* get snapping mode */ + mode = RNA_enum_get(op->ptr, "type"); - /* snap keyframes */ - snap_graph_keys(&ac, mode); + /* snap keyframes */ + snap_graph_keys(&ac, mode); - /* set notifier that keyframes have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_snap(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Snap Keys"; - ot->idname = "GRAPH_OT_snap"; - ot->description = "Snap selected keyframes to the chosen times/values"; + /* identifiers */ + ot->name = "Snap Keys"; + ot->idname = "GRAPH_OT_snap"; + ot->description = "Snap selected keyframes to the chosen times/values"; - /* api callbacks */ - ot->invoke = WM_menu_invoke; - ot->exec = graphkeys_snap_exec; - ot->poll = graphop_editable_keyframes_poll; + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = graphkeys_snap_exec; + ot->poll = graphop_editable_keyframes_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* id-props */ - ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_snap_types, 0, "Type", ""); + /* id-props */ + ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_snap_types, 0, "Type", ""); } /* ******************** Mirror Keyframes Operator *********************** */ /* defines for mirror keyframes tool */ static const EnumPropertyItem prop_graphkeys_mirror_types[] = { - {GRAPHKEYS_MIRROR_CFRA, "CFRA", 0, "By Times over Current Frame", - "Flip times of selected keyframes using the current frame as the mirror line"}, - {GRAPHKEYS_MIRROR_VALUE, "VALUE", 0, "By Values over Cursor Value", - "Flip values of selected keyframes using the cursor value (Y/Horizontal component) as the mirror line"}, - {GRAPHKEYS_MIRROR_YAXIS, "YAXIS", 0, "By Times over Time=0", - "Flip times of selected keyframes, effectively reversing the order they appear in"}, - {GRAPHKEYS_MIRROR_XAXIS, "XAXIS", 0, "By Values over Value=0", - "Flip values of selected keyframes (i.e. negative values become positive, and vice versa)"}, - {GRAPHKEYS_MIRROR_MARKER, "MARKER", 0, "By Times over First Selected Marker", - "Flip times of selected keyframes using the first selected marker as the reference point"}, - {0, NULL, 0, NULL, NULL}, + {GRAPHKEYS_MIRROR_CFRA, + "CFRA", + 0, + "By Times over Current Frame", + "Flip times of selected keyframes using the current frame as the mirror line"}, + {GRAPHKEYS_MIRROR_VALUE, + "VALUE", + 0, + "By Values over Cursor Value", + "Flip values of selected keyframes using the cursor value (Y/Horizontal component) as the " + "mirror line"}, + {GRAPHKEYS_MIRROR_YAXIS, + "YAXIS", + 0, + "By Times over Time=0", + "Flip times of selected keyframes, effectively reversing the order they appear in"}, + {GRAPHKEYS_MIRROR_XAXIS, + "XAXIS", + 0, + "By Values over Value=0", + "Flip values of selected keyframes (i.e. negative values become positive, and vice versa)"}, + {GRAPHKEYS_MIRROR_MARKER, + "MARKER", + 0, + "By Times over First Selected Marker", + "Flip times of selected keyframes using the first selected marker as the reference point"}, + {0, NULL, 0, NULL, NULL}, }; /* this function is responsible for mirroring keyframes */ static void mirror_graph_keys(bAnimContext *ac, short mode) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - SpaceGraph *sipo = (SpaceGraph *)ac->sl; - KeyframeEditData ked; - KeyframeEditFunc edit_cb; - float cursor_value = 0.0f; - - /* init custom data for looping over keyframes */ - memset(&ked, 0, sizeof(KeyframeEditData)); - ked.scene = ac->scene; - - /* store mode-specific custom data... */ - if (mode == GRAPHKEYS_MIRROR_MARKER) { - TimeMarker *marker = NULL; - - /* find first selected marker */ - marker = ED_markers_get_first_selected(ac->markers); - - /* store marker's time (if available) */ - if (marker) - ked.f1 = (float)marker->frame; - else - return; - } - else if (mode == GRAPHKEYS_MIRROR_VALUE) { - cursor_value = (sipo) ? sipo->cursorVal : 0.0f; - } - else if (mode == GRAPHKEYS_MIRROR_CFRA) { - /* In drivers mode, use the cursor value instead - * (We need to use a different callback for that though) - */ - if (sipo->mode == SIPO_MODE_DRIVERS) { - ked.f1 = sipo->cursorTime; - mode = MIRROR_KEYS_TIME; - } - } - - /* get beztriple editing callbacks */ - edit_cb = ANIM_editkeyframes_mirror(mode); - - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* mirror keyframes */ - for (ale = anim_data.first; ale; ale = ale->next) { - AnimData *adt = ANIM_nla_mapping_get(ac, ale); - - /* apply unit corrections */ - if (mode == GRAPHKEYS_MIRROR_VALUE) { - short mapping_flag = ANIM_get_normalization_flags(ac); - float offset; - float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, ale->key_data, mapping_flag | ANIM_UNITCONV_ONLYKEYS, &offset); - - ked.f1 = (cursor_value + offset) * unit_scale; - } - - /* perform actual mirroring */ - if (adt) { - ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0); - ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve); - ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0); - } - else - ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve); - - ale->update |= ANIM_UPDATE_DEFAULT; - } - - ANIM_animdata_update(ac, &anim_data); - ANIM_animdata_freelist(&anim_data); + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + SpaceGraph *sipo = (SpaceGraph *)ac->sl; + KeyframeEditData ked; + KeyframeEditFunc edit_cb; + float cursor_value = 0.0f; + + /* init custom data for looping over keyframes */ + memset(&ked, 0, sizeof(KeyframeEditData)); + ked.scene = ac->scene; + + /* store mode-specific custom data... */ + if (mode == GRAPHKEYS_MIRROR_MARKER) { + TimeMarker *marker = NULL; + + /* find first selected marker */ + marker = ED_markers_get_first_selected(ac->markers); + + /* store marker's time (if available) */ + if (marker) + ked.f1 = (float)marker->frame; + else + return; + } + else if (mode == GRAPHKEYS_MIRROR_VALUE) { + cursor_value = (sipo) ? sipo->cursorVal : 0.0f; + } + else if (mode == GRAPHKEYS_MIRROR_CFRA) { + /* In drivers mode, use the cursor value instead + * (We need to use a different callback for that though) + */ + if (sipo->mode == SIPO_MODE_DRIVERS) { + ked.f1 = sipo->cursorTime; + mode = MIRROR_KEYS_TIME; + } + } + + /* get beztriple editing callbacks */ + edit_cb = ANIM_editkeyframes_mirror(mode); + + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | + ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* mirror keyframes */ + for (ale = anim_data.first; ale; ale = ale->next) { + AnimData *adt = ANIM_nla_mapping_get(ac, ale); + + /* apply unit corrections */ + if (mode == GRAPHKEYS_MIRROR_VALUE) { + short mapping_flag = ANIM_get_normalization_flags(ac); + float offset; + float unit_scale = ANIM_unit_mapping_get_factor( + ac->scene, ale->id, ale->key_data, mapping_flag | ANIM_UNITCONV_ONLYKEYS, &offset); + + ked.f1 = (cursor_value + offset) * unit_scale; + } + + /* perform actual mirroring */ + if (adt) { + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0); + ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve); + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0); + } + else + ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve); + + ale->update |= ANIM_UPDATE_DEFAULT; + } + + ANIM_animdata_update(ac, &anim_data); + ANIM_animdata_freelist(&anim_data); } /* ------------------- */ static int graphkeys_mirror_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - short mode; + bAnimContext ac; + short mode; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* get mirroring mode */ - mode = RNA_enum_get(op->ptr, "type"); + /* get mirroring mode */ + mode = RNA_enum_get(op->ptr, "type"); - /* mirror keyframes */ - mirror_graph_keys(&ac, mode); + /* mirror keyframes */ + mirror_graph_keys(&ac, mode); - /* set notifier that keyframes have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_mirror(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Mirror Keys"; - ot->idname = "GRAPH_OT_mirror"; - ot->description = "Flip selected keyframes over the selected mirror line"; + /* identifiers */ + ot->name = "Mirror Keys"; + ot->idname = "GRAPH_OT_mirror"; + ot->description = "Flip selected keyframes over the selected mirror line"; - /* api callbacks */ - ot->invoke = WM_menu_invoke; - ot->exec = graphkeys_mirror_exec; - ot->poll = graphop_editable_keyframes_poll; + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = graphkeys_mirror_exec; + ot->poll = graphop_editable_keyframes_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* id-props */ - ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_mirror_types, 0, "Type", ""); + /* id-props */ + ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_mirror_types, 0, "Type", ""); } /* ******************** Smooth Keyframes Operator *********************** */ static int graphkeys_smooth_exec(bContext *C, wmOperator *UNUSED(op)) { - bAnimContext ac; - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; + bAnimContext ac; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | + ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - /* smooth keyframes */ - for (ale = anim_data.first; ale; ale = ale->next) { - /* For now, we can only smooth by flattening handles AND smoothing curve values. - * Perhaps the mode argument could be removed, as that functionality is offered through - * Snap->Flatten Handles anyway. - */ - smooth_fcurve(ale->key_data); + /* smooth keyframes */ + for (ale = anim_data.first; ale; ale = ale->next) { + /* For now, we can only smooth by flattening handles AND smoothing curve values. + * Perhaps the mode argument could be removed, as that functionality is offered through + * Snap->Flatten Handles anyway. + */ + smooth_fcurve(ale->key_data); - ale->update |= ANIM_UPDATE_DEFAULT; - } + ale->update |= ANIM_UPDATE_DEFAULT; + } - ANIM_animdata_update(&ac, &anim_data); - ANIM_animdata_freelist(&anim_data); + ANIM_animdata_update(&ac, &anim_data); + ANIM_animdata_freelist(&anim_data); - /* set notifier that keyframes have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_smooth(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Smooth Keys"; - ot->idname = "GRAPH_OT_smooth"; - ot->description = "Apply weighted moving means to make selected F-Curves less bumpy"; + /* identifiers */ + ot->name = "Smooth Keys"; + ot->idname = "GRAPH_OT_smooth"; + ot->description = "Apply weighted moving means to make selected F-Curves less bumpy"; - /* api callbacks */ - ot->exec = graphkeys_smooth_exec; - ot->poll = graphop_editable_keyframes_poll; + /* api callbacks */ + ot->exec = graphkeys_smooth_exec; + ot->poll = graphop_editable_keyframes_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ************************************************************************** */ @@ -2392,246 +2623,258 @@ void GRAPH_OT_smooth(wmOperatorType *ot) /* ******************** Add F-Modifier Operator *********************** */ -static const EnumPropertyItem *graph_fmodifier_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) +static const EnumPropertyItem *graph_fmodifier_itemf(bContext *C, + PointerRNA *UNUSED(ptr), + PropertyRNA *UNUSED(prop), + bool *r_free) { - EnumPropertyItem *item = NULL; - int totitem = 0; - int i = 0; + EnumPropertyItem *item = NULL; + int totitem = 0; + int i = 0; - if (C == NULL) { - return rna_enum_fmodifier_type_items; - } + if (C == NULL) { + return rna_enum_fmodifier_type_items; + } - /* start from 1 to skip the 'Invalid' modifier type */ - for (i = 1; i < FMODIFIER_NUM_TYPES; i++) { - const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(i); - int index; + /* start from 1 to skip the 'Invalid' modifier type */ + for (i = 1; i < FMODIFIER_NUM_TYPES; i++) { + const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(i); + int index; - /* check if modifier is valid for this context */ - if (fmi == NULL) - continue; + /* check if modifier is valid for this context */ + if (fmi == NULL) + continue; - index = RNA_enum_from_value(rna_enum_fmodifier_type_items, fmi->type); - if (index != -1) { /* Not all types are implemented yet... */ - RNA_enum_item_add(&item, &totitem, &rna_enum_fmodifier_type_items[index]); - } - } + index = RNA_enum_from_value(rna_enum_fmodifier_type_items, fmi->type); + if (index != -1) { /* Not all types are implemented yet... */ + RNA_enum_item_add(&item, &totitem, &rna_enum_fmodifier_type_items[index]); + } + } - RNA_enum_item_end(&item, &totitem); - *r_free = true; + RNA_enum_item_end(&item, &totitem); + *r_free = true; - return item; + return item; } static int graph_fmodifier_add_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - short type; + bAnimContext ac; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + short type; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* get type of modifier to add */ - type = RNA_enum_get(op->ptr, "type"); + /* get type of modifier to add */ + type = RNA_enum_get(op->ptr, "type"); - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); - if (RNA_boolean_get(op->ptr, "only_active")) - filter |= ANIMFILTER_ACTIVE; // FIXME: enforce in this case only a single channel to get handled? - else - filter |= (ANIMFILTER_SEL | ANIMFILTER_CURVE_VISIBLE); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); + if (RNA_boolean_get(op->ptr, "only_active")) + filter |= + ANIMFILTER_ACTIVE; // FIXME: enforce in this case only a single channel to get handled? + else + filter |= (ANIMFILTER_SEL | ANIMFILTER_CURVE_VISIBLE); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - /* add f-modifier to each curve */ - for (ale = anim_data.first; ale; ale = ale->next) { - FCurve *fcu = (FCurve *)ale->data; - FModifier *fcm; + /* add f-modifier to each curve */ + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu = (FCurve *)ale->data; + FModifier *fcm; - /* add F-Modifier of specified type to active F-Curve, and make it the active one */ - fcm = add_fmodifier(&fcu->modifiers, type, fcu); - if (fcm) { - set_active_fmodifier(&fcu->modifiers, fcm); - } - else { - BKE_report(op->reports, RPT_ERROR, "Modifier could not be added (see console for details)"); - break; - } + /* add F-Modifier of specified type to active F-Curve, and make it the active one */ + fcm = add_fmodifier(&fcu->modifiers, type, fcu); + if (fcm) { + set_active_fmodifier(&fcu->modifiers, fcm); + } + else { + BKE_report(op->reports, RPT_ERROR, "Modifier could not be added (see console for details)"); + break; + } - ale->update |= ANIM_UPDATE_DEPS; - } + ale->update |= ANIM_UPDATE_DEPS; + } - ANIM_animdata_update(&ac, &anim_data); - ANIM_animdata_freelist(&anim_data); + ANIM_animdata_update(&ac, &anim_data); + ANIM_animdata_freelist(&anim_data); - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_fmodifier_add(wmOperatorType *ot) { - PropertyRNA *prop; + PropertyRNA *prop; - /* identifiers */ - ot->name = "Add F-Curve Modifier"; - ot->idname = "GRAPH_OT_fmodifier_add"; - ot->description = "Add F-Modifier to the active/selected F-Curves"; + /* identifiers */ + ot->name = "Add F-Curve Modifier"; + ot->idname = "GRAPH_OT_fmodifier_add"; + ot->description = "Add F-Modifier to the active/selected F-Curves"; - /* api callbacks */ - ot->invoke = WM_menu_invoke; - ot->exec = graph_fmodifier_add_exec; - ot->poll = graphop_selected_fcurve_poll; + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = graph_fmodifier_add_exec; + ot->poll = graphop_selected_fcurve_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* id-props */ - prop = RNA_def_enum(ot->srna, "type", rna_enum_fmodifier_type_items, 0, "Type", ""); - RNA_def_enum_funcs(prop, graph_fmodifier_itemf); - ot->prop = prop; + /* id-props */ + prop = RNA_def_enum(ot->srna, "type", rna_enum_fmodifier_type_items, 0, "Type", ""); + RNA_def_enum_funcs(prop, graph_fmodifier_itemf); + ot->prop = prop; - RNA_def_boolean(ot->srna, "only_active", 1, "Only Active", "Only add F-Modifier to active F-Curve"); + RNA_def_boolean( + ot->srna, "only_active", 1, "Only Active", "Only add F-Modifier to active F-Curve"); } /* ******************** Copy F-Modifiers Operator *********************** */ static int graph_fmodifier_copy_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - bAnimListElem *ale; - bool ok = false; + bAnimContext ac; + bAnimListElem *ale; + bool ok = false; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* clear buffer first */ - ANIM_fmodifiers_copybuf_free(); + /* clear buffer first */ + ANIM_fmodifiers_copybuf_free(); - /* get the active F-Curve */ - ale = get_active_fcurve_channel(&ac); + /* get the active F-Curve */ + ale = get_active_fcurve_channel(&ac); - /* if this exists, call the copy F-Modifiers API function */ - if (ale && ale->data) { - FCurve *fcu = (FCurve *)ale->data; + /* if this exists, call the copy F-Modifiers API function */ + if (ale && ale->data) { + FCurve *fcu = (FCurve *)ale->data; - /* TODO: when 'active' vs 'all' boolean is added, change last param! */ - ok = ANIM_fmodifiers_copy_to_buf(&fcu->modifiers, 0); + /* TODO: when 'active' vs 'all' boolean is added, change last param! */ + ok = ANIM_fmodifiers_copy_to_buf(&fcu->modifiers, 0); - /* free temp data now */ - MEM_freeN(ale); - } + /* free temp data now */ + MEM_freeN(ale); + } - /* successful or not? */ - if (ok == 0) { - BKE_report(op->reports, RPT_ERROR, "No F-Modifiers available to be copied"); - return OPERATOR_CANCELLED; - } - else - return OPERATOR_FINISHED; + /* successful or not? */ + if (ok == 0) { + BKE_report(op->reports, RPT_ERROR, "No F-Modifiers available to be copied"); + return OPERATOR_CANCELLED; + } + else + return OPERATOR_FINISHED; } void GRAPH_OT_fmodifier_copy(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Copy F-Modifiers"; - ot->idname = "GRAPH_OT_fmodifier_copy"; - ot->description = "Copy the F-Modifier(s) of the active F-Curve"; + /* identifiers */ + ot->name = "Copy F-Modifiers"; + ot->idname = "GRAPH_OT_fmodifier_copy"; + ot->description = "Copy the F-Modifier(s) of the active F-Curve"; - /* api callbacks */ - ot->exec = graph_fmodifier_copy_exec; - ot->poll = graphop_active_fcurve_poll; + /* api callbacks */ + ot->exec = graph_fmodifier_copy_exec; + ot->poll = graphop_active_fcurve_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* id-props */ - //ot->prop = RNA_def_boolean(ot->srna, "all", 1, "All F-Modifiers", "Copy all the F-Modifiers, instead of just the active one"); + /* id-props */ + //ot->prop = RNA_def_boolean(ot->srna, "all", 1, "All F-Modifiers", "Copy all the F-Modifiers, instead of just the active one"); } /* ******************** Paste F-Modifiers Operator *********************** */ static int graph_fmodifier_paste_exec(bContext *C, wmOperator *op) { - bAnimContext ac; + bAnimContext ac; - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; - const bool replace = RNA_boolean_get(op->ptr, "replace"); - bool ok = false; + const bool replace = RNA_boolean_get(op->ptr, "replace"); + bool ok = false; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* filter data */ - if (RNA_boolean_get(op->ptr, "only_active")) { - /* This should be the default (for buttons) - Just paste to the active FCurve */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); - } - else { - /* This is only if the operator gets called from a hotkey or search - Paste to all visible curves */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); - } + /* filter data */ + if (RNA_boolean_get(op->ptr, "only_active")) { + /* This should be the default (for buttons) - Just paste to the active FCurve */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_FOREDIT | + ANIMFILTER_NODUPLIS); + } + else { + /* This is only if the operator gets called from a hotkey or search - Paste to all visible curves */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL | + ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); + } - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - /* paste modifiers */ - for (ale = anim_data.first; ale; ale = ale->next) { - FCurve *fcu = (FCurve *)ale->data; - int tot; + /* paste modifiers */ + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu = (FCurve *)ale->data; + int tot; - tot = ANIM_fmodifiers_paste_from_buf(&fcu->modifiers, replace, fcu); + tot = ANIM_fmodifiers_paste_from_buf(&fcu->modifiers, replace, fcu); - if (tot) { - ale->update |= ANIM_UPDATE_DEPS; - ok = true; - } - } + if (tot) { + ale->update |= ANIM_UPDATE_DEPS; + ok = true; + } + } - if (ok) { - ANIM_animdata_update(&ac, &anim_data); - } - ANIM_animdata_freelist(&anim_data); + if (ok) { + ANIM_animdata_update(&ac, &anim_data); + } + ANIM_animdata_freelist(&anim_data); - /* successful or not? */ - if (ok) { - /* set notifier that keyframes have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + /* successful or not? */ + if (ok) { + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); - return OPERATOR_FINISHED; - } - else { - BKE_report(op->reports, RPT_ERROR, "No F-Modifiers to paste"); - return OPERATOR_CANCELLED; - } + return OPERATOR_FINISHED; + } + else { + BKE_report(op->reports, RPT_ERROR, "No F-Modifiers to paste"); + return OPERATOR_CANCELLED; + } } void GRAPH_OT_fmodifier_paste(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Paste F-Modifiers"; - ot->idname = "GRAPH_OT_fmodifier_paste"; - ot->description = "Add copied F-Modifiers to the selected F-Curves"; + /* identifiers */ + ot->name = "Paste F-Modifiers"; + ot->idname = "GRAPH_OT_fmodifier_paste"; + ot->description = "Add copied F-Modifiers to the selected F-Curves"; - /* api callbacks */ - ot->exec = graph_fmodifier_paste_exec; - ot->poll = graphop_active_fcurve_poll; + /* api callbacks */ + ot->exec = graph_fmodifier_paste_exec; + ot->poll = graphop_active_fcurve_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ - RNA_def_boolean(ot->srna, "only_active", true, "Only Active", "Only paste F-Modifiers on active F-Curve"); - RNA_def_boolean(ot->srna, "replace", false, "Replace Existing", - "Replace existing F-Modifiers, instead of just appending to the end of the existing list"); + /* properties */ + RNA_def_boolean( + ot->srna, "only_active", true, "Only Active", "Only paste F-Modifiers on active F-Curve"); + RNA_def_boolean( + ot->srna, + "replace", + false, + "Replace Existing", + "Replace existing F-Modifiers, instead of just appending to the end of the existing list"); } /* ************************************************************************** */ @@ -2641,200 +2884,204 @@ void GRAPH_OT_fmodifier_paste(wmOperatorType *ot) static int graph_driver_vars_copy_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - bAnimListElem *ale; - bool ok = false; + bAnimContext ac; + bAnimListElem *ale; + bool ok = false; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* clear buffer first */ - ANIM_driver_vars_copybuf_free(); + /* clear buffer first */ + ANIM_driver_vars_copybuf_free(); - /* get the active F-Curve */ - ale = get_active_fcurve_channel(&ac); + /* get the active F-Curve */ + ale = get_active_fcurve_channel(&ac); - /* if this exists, call the copy driver vars API function */ - if (ale && ale->data) { - FCurve *fcu = (FCurve *)ale->data; + /* if this exists, call the copy driver vars API function */ + if (ale && ale->data) { + FCurve *fcu = (FCurve *)ale->data; - ok = ANIM_driver_vars_copy(op->reports, fcu); + ok = ANIM_driver_vars_copy(op->reports, fcu); - /* free temp data now */ - MEM_freeN(ale); - } + /* free temp data now */ + MEM_freeN(ale); + } - /* successful or not? */ - if (ok) - return OPERATOR_FINISHED; - else - return OPERATOR_CANCELLED; + /* successful or not? */ + if (ok) + return OPERATOR_FINISHED; + else + return OPERATOR_CANCELLED; } void GRAPH_OT_driver_variables_copy(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Copy Driver Variables"; - ot->idname = "GRAPH_OT_driver_variables_copy"; - ot->description = "Copy the driver variables of the active F-Curve"; + /* identifiers */ + ot->name = "Copy Driver Variables"; + ot->idname = "GRAPH_OT_driver_variables_copy"; + ot->description = "Copy the driver variables of the active F-Curve"; - /* api callbacks */ - ot->exec = graph_driver_vars_copy_exec; - ot->poll = graphop_active_fcurve_poll; + /* api callbacks */ + ot->exec = graph_driver_vars_copy_exec; + ot->poll = graphop_active_fcurve_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ******************** Paste Driver Vars Operator *********************** */ static int graph_driver_vars_paste_exec(bContext *C, wmOperator *op) { - bAnimContext ac; + bAnimContext ac; - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; - const bool replace = RNA_boolean_get(op->ptr, "replace"); - bool ok = false; + const bool replace = RNA_boolean_get(op->ptr, "replace"); + bool ok = false; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_FOREDIT | + ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - /* paste variables */ - for (ale = anim_data.first; ale; ale = ale->next) { - FCurve *fcu = (FCurve *)ale->data; - ok |= ANIM_driver_vars_paste(op->reports, fcu, replace); - } + /* paste variables */ + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu = (FCurve *)ale->data; + ok |= ANIM_driver_vars_paste(op->reports, fcu, replace); + } - /* cleanup */ - ANIM_animdata_freelist(&anim_data); + /* cleanup */ + ANIM_animdata_freelist(&anim_data); - /* successful or not? */ - if (ok) { - /* rebuild depsgraph, now that there are extra deps here */ - DEG_relations_tag_update(CTX_data_main(C)); + /* successful or not? */ + if (ok) { + /* rebuild depsgraph, now that there are extra deps here */ + 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)); + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_SCENE | ND_FRAME, CTX_data_scene(C)); - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; - } + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } void GRAPH_OT_driver_variables_paste(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Paste Driver Variables"; - ot->idname = "GRAPH_OT_driver_variables_paste"; - ot->description = "Add copied driver variables to the active driver"; + /* identifiers */ + ot->name = "Paste Driver Variables"; + ot->idname = "GRAPH_OT_driver_variables_paste"; + ot->description = "Add copied driver variables to the active driver"; - /* api callbacks */ - ot->exec = graph_driver_vars_paste_exec; - ot->poll = graphop_active_fcurve_poll; + /* api callbacks */ + ot->exec = graph_driver_vars_paste_exec; + ot->poll = graphop_active_fcurve_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ - RNA_def_boolean(ot->srna, "replace", false, "Replace Existing", - "Replace existing driver variables, instead of just appending to the end of the existing list"); + /* properties */ + RNA_def_boolean(ot->srna, + "replace", + false, + "Replace Existing", + "Replace existing driver variables, instead of just appending to the end of the " + "existing list"); } /* ************************************************************************** */ static int graph_driver_delete_invalid_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - bool ok = false; - unsigned int deleted = 0; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* NOTE: we might need a scene update to evaluate the driver flags */ - - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - /* find invalid drivers */ - for (ale = anim_data.first; ale; ale = ale->next) { - FCurve *fcu = (FCurve *)ale->data; - if (ELEM(NULL, fcu, fcu->driver)) { - continue; - } - if (!(fcu->driver->flag & DRIVER_FLAG_INVALID)) { - continue; - } - - ok |= ANIM_remove_driver(op->reports, ale->id, fcu->rna_path, fcu->array_index, 0); - if (!ok) { - break; - } - deleted += 1; - } - - /* cleanup */ - ANIM_animdata_freelist(&anim_data); - - if (deleted > 0) { - /* notify the world of any changes */ - 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); - } - else { - WM_report(RPT_INFO, "No drivers deleted"); - } - - /* successful or not? */ - if (!ok) { - return OPERATOR_CANCELLED; - } - - return OPERATOR_FINISHED; + bAnimContext ac; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + bool ok = false; + unsigned int deleted = 0; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* NOTE: we might need a scene update to evaluate the driver flags */ + + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* find invalid drivers */ + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu = (FCurve *)ale->data; + if (ELEM(NULL, fcu, fcu->driver)) { + continue; + } + if (!(fcu->driver->flag & DRIVER_FLAG_INVALID)) { + continue; + } + + ok |= ANIM_remove_driver(op->reports, ale->id, fcu->rna_path, fcu->array_index, 0); + if (!ok) { + break; + } + deleted += 1; + } + + /* cleanup */ + ANIM_animdata_freelist(&anim_data); + + if (deleted > 0) { + /* notify the world of any changes */ + 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); + } + else { + WM_report(RPT_INFO, "No drivers deleted"); + } + + /* successful or not? */ + if (!ok) { + return OPERATOR_CANCELLED; + } + + return OPERATOR_FINISHED; } static bool graph_driver_delete_invalid_poll(bContext *C) { - bAnimContext ac; - ScrArea *sa = CTX_wm_area(C); + bAnimContext ac; + ScrArea *sa = CTX_wm_area(C); - /* firstly, check if in Graph Editor */ - if ((sa == NULL) || (sa->spacetype != SPACE_GRAPH)) - return 0; + /* firstly, check if in Graph Editor */ + if ((sa == NULL) || (sa->spacetype != SPACE_GRAPH)) + return 0; - /* try to init Anim-Context stuff ourselves and check */ - return ANIM_animdata_get_context(C, &ac) != 0; + /* try to init Anim-Context stuff ourselves and check */ + return ANIM_animdata_get_context(C, &ac) != 0; } - void GRAPH_OT_driver_delete_invalid(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Delete Invalid Drivers"; - ot->idname = "GRAPH_OT_driver_delete_invalid"; - ot->description = "Delete all visible drivers considered invalid"; + /* identifiers */ + ot->name = "Delete Invalid Drivers"; + ot->idname = "GRAPH_OT_driver_delete_invalid"; + ot->description = "Delete all visible drivers considered invalid"; - /* api callbacks */ - ot->exec = graph_driver_delete_invalid_exec; - ot->poll = graph_driver_delete_invalid_poll; + /* api callbacks */ + ot->exec = graph_driver_delete_invalid_exec; + ot->poll = graph_driver_delete_invalid_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h index 617233f2a20..7d0a3a1f13d 100644 --- a/source/blender/editors/space_graph/graph_intern.h +++ b/source/blender/editors/space_graph/graph_intern.h @@ -43,7 +43,11 @@ struct ARegion *graph_has_buttons_region(struct ScrArea *sa); /* graph_draw.c */ void graph_draw_channel_names(struct bContext *C, struct bAnimContext *ac, struct ARegion *ar); -void graph_draw_curves(struct bAnimContext *ac, struct SpaceGraph *sipo, struct ARegion *ar, struct View2DGrid *grid, short sel); +void graph_draw_curves(struct bAnimContext *ac, + struct SpaceGraph *sipo, + struct ARegion *ar, + struct View2DGrid *grid, + short sel); void graph_draw_ghost_curves(struct bAnimContext *ac, struct SpaceGraph *sipo, struct ARegion *ar); /* ***************************************** */ @@ -64,24 +68,29 @@ void GRAPH_OT_clickselect(struct wmOperatorType *ot); /* defines for left-right select tool */ enum eGraphKeys_LeftRightSelect_Mode { - GRAPHKEYS_LRSEL_TEST = 0, - GRAPHKEYS_LRSEL_LEFT, - GRAPHKEYS_LRSEL_RIGHT, + GRAPHKEYS_LRSEL_TEST = 0, + GRAPHKEYS_LRSEL_LEFT, + GRAPHKEYS_LRSEL_RIGHT, }; /* defines for column-select mode */ enum eGraphKeys_ColumnSelect_Mode { - GRAPHKEYS_COLUMNSEL_KEYS = 0, - GRAPHKEYS_COLUMNSEL_CFRA, - GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN, - GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN, + GRAPHKEYS_COLUMNSEL_KEYS = 0, + GRAPHKEYS_COLUMNSEL_CFRA, + GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN, + GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN, }; /* ***************************************** */ /* graph_edit.c */ -void get_graph_keyframe_extents(struct bAnimContext *ac, float *xmin, float *xmax, float *ymin, float *ymax, - const bool do_selected, const bool include_handles); +void get_graph_keyframe_extents(struct bAnimContext *ac, + float *xmin, + float *xmax, + float *ymin, + float *ymax, + const bool do_selected, + const bool include_handles); void GRAPH_OT_previewrange_set(struct wmOperatorType *ot); void GRAPH_OT_view_all(struct wmOperatorType *ot); @@ -116,23 +125,23 @@ void GRAPH_OT_mirror(struct wmOperatorType *ot); * NOTE: keep in sync with eEditKeyframes_Snap (in ED_keyframes_edit.h) */ enum eGraphKeys_Snap_Mode { - GRAPHKEYS_SNAP_CFRA = 1, - GRAPHKEYS_SNAP_NEAREST_FRAME, - GRAPHKEYS_SNAP_NEAREST_SECOND, - GRAPHKEYS_SNAP_NEAREST_MARKER, - GRAPHKEYS_SNAP_HORIZONTAL, - GRAPHKEYS_SNAP_VALUE, + GRAPHKEYS_SNAP_CFRA = 1, + GRAPHKEYS_SNAP_NEAREST_FRAME, + GRAPHKEYS_SNAP_NEAREST_SECOND, + GRAPHKEYS_SNAP_NEAREST_MARKER, + GRAPHKEYS_SNAP_HORIZONTAL, + GRAPHKEYS_SNAP_VALUE, }; /* defines for mirror keyframes * NOTE: keep in sync with eEditKeyframes_Mirror (in ED_keyframes_edit.h) */ enum eGraphKeys_Mirror_Mode { - GRAPHKEYS_MIRROR_CFRA = 1, - GRAPHKEYS_MIRROR_YAXIS, - GRAPHKEYS_MIRROR_XAXIS, - GRAPHKEYS_MIRROR_MARKER, - GRAPHKEYS_MIRROR_VALUE, + GRAPHKEYS_MIRROR_CFRA = 1, + GRAPHKEYS_MIRROR_YAXIS, + GRAPHKEYS_MIRROR_XAXIS, + GRAPHKEYS_MIRROR_MARKER, + GRAPHKEYS_MIRROR_VALUE, }; /* ----------- */ @@ -173,5 +182,4 @@ bool graphop_selected_fcurve_poll(struct bContext *C); void graphedit_keymap(struct wmKeyConfig *keyconf); void graphedit_operatortypes(void); - #endif /* __GRAPH_INTERN_H__ */ diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 1c9bbbcdae5..6bbc6a2de1c 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -21,7 +21,6 @@ * \ingroup spgraph */ - #include <stdlib.h> #include <math.h> @@ -64,55 +63,55 @@ static bool graphview_cursor_poll(bContext *C) { - /* prevent changes during render */ - if (G.is_rendering) - return 0; + /* prevent changes during render */ + if (G.is_rendering) + return 0; - return ED_operator_graphedit_active(C); + return ED_operator_graphedit_active(C); } /* Set the new frame number */ static void graphview_cursor_apply(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - SpaceGraph *sipo = CTX_wm_space_graph(C); - /* this isn't technically "frame", but it'll do... */ - float frame = RNA_float_get(op->ptr, "frame"); - - /* adjust the frame or the cursor x-value */ - if (sipo->mode == SIPO_MODE_DRIVERS) { - /* adjust cursor x-value */ - sipo->cursorTime = frame; - } - else { - /* adjust the frame - * NOTE: sync this part of the code with ANIM_OT_change_frame - */ - /* 1) frame is rounded to the nearest int, since frames are ints */ - CFRA = round_fl_to_int(frame); - - if (scene->r.flag & SCER_LOCK_FRAME_SELECTION) { - /* Clip to preview range - * NOTE: Preview range won't go into negative values, - * so only clamping once should be fine. - */ - CLAMP(CFRA, PSFRA, PEFRA); - } - else { - /* Prevent negative frames */ - FRAMENUMBER_MIN_CLAMP(CFRA); - } - - SUBFRA = 0.0f; - BKE_sound_seek_scene(bmain, scene); - } - - /* set the cursor value */ - sipo->cursorVal = RNA_float_get(op->ptr, "value"); - - /* send notifiers - notifiers for frame should force an update for both vars ok... */ - WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + SpaceGraph *sipo = CTX_wm_space_graph(C); + /* this isn't technically "frame", but it'll do... */ + float frame = RNA_float_get(op->ptr, "frame"); + + /* adjust the frame or the cursor x-value */ + if (sipo->mode == SIPO_MODE_DRIVERS) { + /* adjust cursor x-value */ + sipo->cursorTime = frame; + } + else { + /* adjust the frame + * NOTE: sync this part of the code with ANIM_OT_change_frame + */ + /* 1) frame is rounded to the nearest int, since frames are ints */ + CFRA = round_fl_to_int(frame); + + if (scene->r.flag & SCER_LOCK_FRAME_SELECTION) { + /* Clip to preview range + * NOTE: Preview range won't go into negative values, + * so only clamping once should be fine. + */ + CLAMP(CFRA, PSFRA, PEFRA); + } + else { + /* Prevent negative frames */ + FRAMENUMBER_MIN_CLAMP(CFRA); + } + + SUBFRA = 0.0f; + BKE_sound_seek_scene(bmain, scene); + } + + /* set the cursor value */ + sipo->cursorVal = RNA_float_get(op->ptr, "value"); + + /* send notifiers - notifiers for frame should force an update for both vars ok... */ + WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); } /* ... */ @@ -120,8 +119,8 @@ static void graphview_cursor_apply(bContext *C, wmOperator *op) /* Non-modal callback for running operator without user input */ static int graphview_cursor_exec(bContext *C, wmOperator *op) { - graphview_cursor_apply(C, op); - return OPERATOR_FINISHED; + graphview_cursor_apply(C, op); + return OPERATOR_FINISHED; } /* ... */ @@ -129,374 +128,377 @@ static int graphview_cursor_exec(bContext *C, wmOperator *op) /* set the operator properties from the initial event */ static void graphview_cursor_setprops(bContext *C, wmOperator *op, const wmEvent *event) { - ARegion *ar = CTX_wm_region(C); - float viewx, viewy; + ARegion *ar = CTX_wm_region(C); + float viewx, viewy; - /* abort if not active region (should not really be possible) */ - if (ar == NULL) - return; + /* abort if not active region (should not really be possible) */ + if (ar == NULL) + return; - /* convert from region coordinates to View2D 'tot' space */ - UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &viewx, &viewy); + /* convert from region coordinates to View2D 'tot' space */ + UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &viewx, &viewy); - /* store the values in the operator properties */ - /* NOTE: we don't clamp frame here, as it might be used for the drivers cursor */ - RNA_float_set(op->ptr, "frame", viewx); - RNA_float_set(op->ptr, "value", viewy); + /* store the values in the operator properties */ + /* NOTE: we don't clamp frame here, as it might be used for the drivers cursor */ + RNA_float_set(op->ptr, "frame", viewx); + RNA_float_set(op->ptr, "value", viewy); } /* Modal Operator init */ static int graphview_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - bScreen *screen = CTX_wm_screen(C); - - /* Change to frame that mouse is over before adding modal handler, - * as user could click on a single frame (jump to frame) as well as - * click-dragging over a range (modal scrubbing). Apply this change. - */ - graphview_cursor_setprops(C, op, event); - graphview_cursor_apply(C, op); - - /* Signal that a scrubbing operating is starting */ - if (screen) - screen->scrubbing = true; - - /* add temp handler */ - WM_event_add_modal_handler(C, op); - return OPERATOR_RUNNING_MODAL; + bScreen *screen = CTX_wm_screen(C); + + /* Change to frame that mouse is over before adding modal handler, + * as user could click on a single frame (jump to frame) as well as + * click-dragging over a range (modal scrubbing). Apply this change. + */ + graphview_cursor_setprops(C, op, event); + graphview_cursor_apply(C, op); + + /* Signal that a scrubbing operating is starting */ + if (screen) + screen->scrubbing = true; + + /* add temp handler */ + WM_event_add_modal_handler(C, op); + return OPERATOR_RUNNING_MODAL; } /* Modal event handling of cursor changing */ static int graphview_cursor_modal(bContext *C, wmOperator *op, const wmEvent *event) { - bScreen *screen = CTX_wm_screen(C); - Scene *scene = CTX_data_scene(C); - - /* execute the events */ - switch (event->type) { - case ESCKEY: - if (screen) - screen->scrubbing = false; - - WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); - return OPERATOR_FINISHED; - - case MOUSEMOVE: - /* set the new values */ - graphview_cursor_setprops(C, op, event); - graphview_cursor_apply(C, op); - break; - - case LEFTMOUSE: - case RIGHTMOUSE: - case MIDDLEMOUSE: - /* We check for either mouse-button to end, to work with all user keymaps. */ - if (event->val == KM_RELEASE) { - if (screen) - screen->scrubbing = false; - - WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); - return OPERATOR_FINISHED; - } - break; - } - - return OPERATOR_RUNNING_MODAL; + bScreen *screen = CTX_wm_screen(C); + Scene *scene = CTX_data_scene(C); + + /* execute the events */ + switch (event->type) { + case ESCKEY: + if (screen) + screen->scrubbing = false; + + WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); + return OPERATOR_FINISHED; + + case MOUSEMOVE: + /* set the new values */ + graphview_cursor_setprops(C, op, event); + graphview_cursor_apply(C, op); + break; + + case LEFTMOUSE: + case RIGHTMOUSE: + case MIDDLEMOUSE: + /* We check for either mouse-button to end, to work with all user keymaps. */ + if (event->val == KM_RELEASE) { + if (screen) + screen->scrubbing = false; + + WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); + return OPERATOR_FINISHED; + } + break; + } + + return OPERATOR_RUNNING_MODAL; } static void GRAPH_OT_cursor_set(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Set Cursor"; - ot->idname = "GRAPH_OT_cursor_set"; - ot->description = "Interactively set the current frame and value cursor"; - - /* api callbacks */ - ot->exec = graphview_cursor_exec; - ot->invoke = graphview_cursor_invoke; - ot->modal = graphview_cursor_modal; - ot->poll = graphview_cursor_poll; - - /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO; - - /* rna */ - RNA_def_float(ot->srna, "frame", 0, MINAFRAMEF, MAXFRAMEF, "Frame", "", MINAFRAMEF, MAXFRAMEF); - RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Value", "", -100.0f, 100.0f); + /* identifiers */ + ot->name = "Set Cursor"; + ot->idname = "GRAPH_OT_cursor_set"; + ot->description = "Interactively set the current frame and value cursor"; + + /* api callbacks */ + ot->exec = graphview_cursor_exec; + ot->invoke = graphview_cursor_invoke; + ot->modal = graphview_cursor_modal; + ot->poll = graphview_cursor_poll; + + /* flags */ + ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO; + + /* rna */ + RNA_def_float(ot->srna, "frame", 0, MINAFRAMEF, MAXFRAMEF, "Frame", "", MINAFRAMEF, MAXFRAMEF); + RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Value", "", -100.0f, 100.0f); } /* Hide/Reveal ------------------------------------------------------------ */ static int graphview_curves_hide_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - ListBase anim_data = {NULL, NULL}; - ListBase all_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - const bool unselected = RNA_boolean_get(op->ptr, "unselected"); - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* get list of all channels that selection may need to be flushed to - * - hierarchy must not affect what we have access to here... - */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype); - - /* filter data - * - of the remaining visible curves, we want to hide the ones that are - * selected/unselected (depending on "unselected" prop) - */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); - if (unselected) - filter |= ANIMFILTER_UNSEL; - else - filter |= ANIMFILTER_SEL; - - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - for (ale = anim_data.first; ale; ale = ale->next) { - /* hack: skip object channels for now, since flushing those will always flush everything, - * but they are always included */ - /* TODO: find out why this is the case, and fix that */ - if (ale->type == ANIMTYPE_OBJECT) - continue; - - /* change the hide setting, and unselect it... */ - ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_CLEAR); - ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_SELECT, ACHANNEL_SETFLAG_CLEAR); - - /* now, also flush selection status up/down as appropriate */ - ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_CLEAR); - } - - /* cleanup */ - ANIM_animdata_freelist(&anim_data); - BLI_freelistN(&all_data); - - /* unhide selected */ - if (unselected) { - /* turn off requirement for visible */ - filter = ANIMFILTER_SEL | ANIMFILTER_NODUPLIS | ANIMFILTER_LIST_CHANNELS; - - /* flushing has been done */ - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - for (ale = anim_data.first; ale; ale = ale->next) { - /* hack: skip object channels for now, since flushing those - * will always flush everything, but they are always included */ - - /* TODO: find out why this is the case, and fix that */ - if (ale->type == ANIMTYPE_OBJECT) - continue; - - /* change the hide setting, and unselect it... */ - ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD); - ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_SELECT, ACHANNEL_SETFLAG_ADD); - - /* now, also flush selection status up/down as appropriate */ - ANIM_flush_setting_anim_channels(&ac, &anim_data, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD); - } - ANIM_animdata_freelist(&anim_data); - } - - - /* send notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - - return OPERATOR_FINISHED; + bAnimContext ac; + ListBase anim_data = {NULL, NULL}; + ListBase all_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + const bool unselected = RNA_boolean_get(op->ptr, "unselected"); + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get list of all channels that selection may need to be flushed to + * - hierarchy must not affect what we have access to here... + */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype); + + /* filter data + * - of the remaining visible curves, we want to hide the ones that are + * selected/unselected (depending on "unselected" prop) + */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); + if (unselected) + filter |= ANIMFILTER_UNSEL; + else + filter |= ANIMFILTER_SEL; + + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + for (ale = anim_data.first; ale; ale = ale->next) { + /* hack: skip object channels for now, since flushing those will always flush everything, + * but they are always included */ + /* TODO: find out why this is the case, and fix that */ + if (ale->type == ANIMTYPE_OBJECT) + continue; + + /* change the hide setting, and unselect it... */ + ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_CLEAR); + ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_SELECT, ACHANNEL_SETFLAG_CLEAR); + + /* now, also flush selection status up/down as appropriate */ + ANIM_flush_setting_anim_channels( + &ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_CLEAR); + } + + /* cleanup */ + ANIM_animdata_freelist(&anim_data); + BLI_freelistN(&all_data); + + /* unhide selected */ + if (unselected) { + /* turn off requirement for visible */ + filter = ANIMFILTER_SEL | ANIMFILTER_NODUPLIS | ANIMFILTER_LIST_CHANNELS; + + /* flushing has been done */ + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + for (ale = anim_data.first; ale; ale = ale->next) { + /* hack: skip object channels for now, since flushing those + * will always flush everything, but they are always included */ + + /* TODO: find out why this is the case, and fix that */ + if (ale->type == ANIMTYPE_OBJECT) + continue; + + /* change the hide setting, and unselect it... */ + ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD); + ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_SELECT, ACHANNEL_SETFLAG_ADD); + + /* now, also flush selection status up/down as appropriate */ + ANIM_flush_setting_anim_channels( + &ac, &anim_data, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD); + } + ANIM_animdata_freelist(&anim_data); + } + + /* send notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + + return OPERATOR_FINISHED; } static void GRAPH_OT_hide(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Hide Curves"; - ot->idname = "GRAPH_OT_hide"; - ot->description = "Hide selected curves from Graph Editor view"; + /* identifiers */ + ot->name = "Hide Curves"; + ot->idname = "GRAPH_OT_hide"; + ot->description = "Hide selected curves from Graph Editor view"; - /* api callbacks */ - ot->exec = graphview_curves_hide_exec; - ot->poll = ED_operator_graphedit_active; + /* api callbacks */ + ot->exec = graphview_curves_hide_exec; + ot->poll = ED_operator_graphedit_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* props */ - RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected curves"); + /* props */ + RNA_def_boolean( + ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected curves"); } /* ........ */ static int graphview_curves_reveal_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - ListBase anim_data = {NULL, NULL}; - ListBase all_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - const bool select = RNA_boolean_get(op->ptr, "select"); - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* get list of all channels that selection may need to be flushed to - * - hierarchy must not affect what we have access to here... - */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype); - - /* filter data - * - just go through all visible channels, ensuring that everything is set to be curve-visible - */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - for (ale = anim_data.first; ale; ale = ale->next) { - /* hack: skip object channels for now, since flushing those will always flush everything, - * but they are always included. */ - /* TODO: find out why this is the case, and fix that */ - if (ale->type == ANIMTYPE_OBJECT) - continue; - - /* select if it is not visible */ - if (ANIM_channel_setting_get(&ac, ale, ACHANNEL_SETTING_VISIBLE) == 0) { - ANIM_channel_setting_set( - &ac, ale, ACHANNEL_SETTING_SELECT, - select ? ACHANNEL_SETFLAG_ADD : ACHANNEL_SETFLAG_CLEAR); - } - - /* change the visibility setting */ - ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD); - - /* now, also flush selection status up/down as appropriate */ - ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, true); - } - - /* cleanup */ - ANIM_animdata_freelist(&anim_data); - BLI_freelistN(&all_data); - - /* send notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - - return OPERATOR_FINISHED; + bAnimContext ac; + ListBase anim_data = {NULL, NULL}; + ListBase all_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + const bool select = RNA_boolean_get(op->ptr, "select"); + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get list of all channels that selection may need to be flushed to + * - hierarchy must not affect what we have access to here... + */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype); + + /* filter data + * - just go through all visible channels, ensuring that everything is set to be curve-visible + */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + for (ale = anim_data.first; ale; ale = ale->next) { + /* hack: skip object channels for now, since flushing those will always flush everything, + * but they are always included. */ + /* TODO: find out why this is the case, and fix that */ + if (ale->type == ANIMTYPE_OBJECT) + continue; + + /* select if it is not visible */ + if (ANIM_channel_setting_get(&ac, ale, ACHANNEL_SETTING_VISIBLE) == 0) { + ANIM_channel_setting_set(&ac, + ale, + ACHANNEL_SETTING_SELECT, + select ? ACHANNEL_SETFLAG_ADD : ACHANNEL_SETFLAG_CLEAR); + } + + /* change the visibility setting */ + ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD); + + /* now, also flush selection status up/down as appropriate */ + ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, true); + } + + /* cleanup */ + ANIM_animdata_freelist(&anim_data); + BLI_freelistN(&all_data); + + /* send notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + + return OPERATOR_FINISHED; } static void GRAPH_OT_reveal(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Reveal Curves"; - ot->idname = "GRAPH_OT_reveal"; - ot->description = "Make previously hidden curves visible again in Graph Editor view"; + /* identifiers */ + ot->name = "Reveal Curves"; + ot->idname = "GRAPH_OT_reveal"; + ot->description = "Make previously hidden curves visible again in Graph Editor view"; - /* api callbacks */ - ot->exec = graphview_curves_reveal_exec; - ot->poll = ED_operator_graphedit_active; + /* api callbacks */ + ot->exec = graphview_curves_reveal_exec; + ot->poll = ED_operator_graphedit_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_boolean(ot->srna, "select", true, "Select", ""); + RNA_def_boolean(ot->srna, "select", true, "Select", ""); } /* ************************** registration - operator types **********************************/ void graphedit_operatortypes(void) { - /* view */ - WM_operatortype_append(GRAPH_OT_cursor_set); - - WM_operatortype_append(GRAPH_OT_previewrange_set); - WM_operatortype_append(GRAPH_OT_view_all); - WM_operatortype_append(GRAPH_OT_view_selected); - WM_operatortype_append(GRAPH_OT_properties); - WM_operatortype_append(GRAPH_OT_view_frame); - - WM_operatortype_append(GRAPH_OT_ghost_curves_create); - WM_operatortype_append(GRAPH_OT_ghost_curves_clear); - - WM_operatortype_append(GRAPH_OT_hide); - WM_operatortype_append(GRAPH_OT_reveal); - - /* keyframes */ - /* selection */ - WM_operatortype_append(GRAPH_OT_clickselect); - WM_operatortype_append(GRAPH_OT_select_all); - WM_operatortype_append(GRAPH_OT_select_box); - WM_operatortype_append(GRAPH_OT_select_lasso); - WM_operatortype_append(GRAPH_OT_select_circle); - WM_operatortype_append(GRAPH_OT_select_column); - WM_operatortype_append(GRAPH_OT_select_linked); - WM_operatortype_append(GRAPH_OT_select_more); - WM_operatortype_append(GRAPH_OT_select_less); - WM_operatortype_append(GRAPH_OT_select_leftright); - - /* editing */ - WM_operatortype_append(GRAPH_OT_snap); - WM_operatortype_append(GRAPH_OT_mirror); - WM_operatortype_append(GRAPH_OT_frame_jump); - WM_operatortype_append(GRAPH_OT_handle_type); - WM_operatortype_append(GRAPH_OT_interpolation_type); - WM_operatortype_append(GRAPH_OT_extrapolation_type); - WM_operatortype_append(GRAPH_OT_easing_type); - WM_operatortype_append(GRAPH_OT_sample); - WM_operatortype_append(GRAPH_OT_bake); - WM_operatortype_append(GRAPH_OT_sound_bake); - WM_operatortype_append(GRAPH_OT_smooth); - WM_operatortype_append(GRAPH_OT_clean); - WM_operatortype_append(GRAPH_OT_euler_filter); - WM_operatortype_append(GRAPH_OT_delete); - WM_operatortype_append(GRAPH_OT_duplicate); - - WM_operatortype_append(GRAPH_OT_copy); - WM_operatortype_append(GRAPH_OT_paste); - - WM_operatortype_append(GRAPH_OT_keyframe_insert); - WM_operatortype_append(GRAPH_OT_click_insert); - - /* F-Curve Modifiers */ - WM_operatortype_append(GRAPH_OT_fmodifier_add); - WM_operatortype_append(GRAPH_OT_fmodifier_copy); - WM_operatortype_append(GRAPH_OT_fmodifier_paste); - - /* Drivers */ - WM_operatortype_append(GRAPH_OT_driver_variables_copy); - WM_operatortype_append(GRAPH_OT_driver_variables_paste); - WM_operatortype_append(GRAPH_OT_driver_delete_invalid); + /* view */ + WM_operatortype_append(GRAPH_OT_cursor_set); + + WM_operatortype_append(GRAPH_OT_previewrange_set); + WM_operatortype_append(GRAPH_OT_view_all); + WM_operatortype_append(GRAPH_OT_view_selected); + WM_operatortype_append(GRAPH_OT_properties); + WM_operatortype_append(GRAPH_OT_view_frame); + + WM_operatortype_append(GRAPH_OT_ghost_curves_create); + WM_operatortype_append(GRAPH_OT_ghost_curves_clear); + + WM_operatortype_append(GRAPH_OT_hide); + WM_operatortype_append(GRAPH_OT_reveal); + + /* keyframes */ + /* selection */ + WM_operatortype_append(GRAPH_OT_clickselect); + WM_operatortype_append(GRAPH_OT_select_all); + WM_operatortype_append(GRAPH_OT_select_box); + WM_operatortype_append(GRAPH_OT_select_lasso); + WM_operatortype_append(GRAPH_OT_select_circle); + WM_operatortype_append(GRAPH_OT_select_column); + WM_operatortype_append(GRAPH_OT_select_linked); + WM_operatortype_append(GRAPH_OT_select_more); + WM_operatortype_append(GRAPH_OT_select_less); + WM_operatortype_append(GRAPH_OT_select_leftright); + + /* editing */ + WM_operatortype_append(GRAPH_OT_snap); + WM_operatortype_append(GRAPH_OT_mirror); + WM_operatortype_append(GRAPH_OT_frame_jump); + WM_operatortype_append(GRAPH_OT_handle_type); + WM_operatortype_append(GRAPH_OT_interpolation_type); + WM_operatortype_append(GRAPH_OT_extrapolation_type); + WM_operatortype_append(GRAPH_OT_easing_type); + WM_operatortype_append(GRAPH_OT_sample); + WM_operatortype_append(GRAPH_OT_bake); + WM_operatortype_append(GRAPH_OT_sound_bake); + WM_operatortype_append(GRAPH_OT_smooth); + WM_operatortype_append(GRAPH_OT_clean); + WM_operatortype_append(GRAPH_OT_euler_filter); + WM_operatortype_append(GRAPH_OT_delete); + WM_operatortype_append(GRAPH_OT_duplicate); + + WM_operatortype_append(GRAPH_OT_copy); + WM_operatortype_append(GRAPH_OT_paste); + + WM_operatortype_append(GRAPH_OT_keyframe_insert); + WM_operatortype_append(GRAPH_OT_click_insert); + + /* F-Curve Modifiers */ + WM_operatortype_append(GRAPH_OT_fmodifier_add); + WM_operatortype_append(GRAPH_OT_fmodifier_copy); + WM_operatortype_append(GRAPH_OT_fmodifier_paste); + + /* Drivers */ + WM_operatortype_append(GRAPH_OT_driver_variables_copy); + WM_operatortype_append(GRAPH_OT_driver_variables_paste); + WM_operatortype_append(GRAPH_OT_driver_delete_invalid); } void ED_operatormacros_graph(void) { - wmOperatorType *ot; - wmOperatorTypeMacro *otmacro; - - ot = WM_operatortype_append_macro("GRAPH_OT_duplicate_move", "Duplicate", - "Make a copy of all selected keyframes and move them", - OPTYPE_UNDO | OPTYPE_REGISTER); - WM_operatortype_macro_define(ot, "GRAPH_OT_duplicate"); - otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_transform"); - RNA_enum_set(otmacro->ptr, "mode", TFM_TIME_DUPLICATE); - RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF); + wmOperatorType *ot; + wmOperatorTypeMacro *otmacro; + + ot = WM_operatortype_append_macro("GRAPH_OT_duplicate_move", + "Duplicate", + "Make a copy of all selected keyframes and move them", + OPTYPE_UNDO | OPTYPE_REGISTER); + WM_operatortype_macro_define(ot, "GRAPH_OT_duplicate"); + otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_transform"); + RNA_enum_set(otmacro->ptr, "mode", TFM_TIME_DUPLICATE); + RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF); } - /* ************************** registration - keymaps **********************************/ void graphedit_keymap(wmKeyConfig *keyconf) { - /* keymap for all regions */ - WM_keymap_ensure(keyconf, "Graph Editor Generic", SPACE_GRAPH, 0); + /* keymap for all regions */ + WM_keymap_ensure(keyconf, "Graph Editor Generic", SPACE_GRAPH, 0); - /* channels */ - /* Channels are not directly handled by the Graph Editor module, but are inherited from the Animation module. - * All the relevant operations, keymaps, drawing, etc. can therefore all be found in that module instead, as these - * are all used for the Graph Editor too. - */ + /* channels */ + /* Channels are not directly handled by the Graph Editor module, but are inherited from the Animation module. + * All the relevant operations, keymaps, drawing, etc. can therefore all be found in that module instead, as these + * are all used for the Graph Editor too. + */ - /* keyframes */ - WM_keymap_ensure(keyconf, "Graph Editor", SPACE_GRAPH, 0); + /* keyframes */ + WM_keymap_ensure(keyconf, "Graph Editor", SPACE_GRAPH, 0); } diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index 6c6c0d451cc..a109282978c 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -20,7 +20,6 @@ * \ingroup spgraph */ - #include <math.h> #include <stdlib.h> #include <string.h> @@ -57,7 +56,6 @@ #include "graph_intern.h" - /* ************************************************************************** */ /* KEYFRAMES STUFF */ @@ -80,137 +78,137 @@ */ void deselect_graph_keys(bAnimContext *ac, bool test, short sel, bool do_channels) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - SpaceGraph *sipo = (SpaceGraph *)ac->sl; - KeyframeEditData ked = {{NULL}}; - KeyframeEditFunc test_cb, sel_cb; - - /* determine type-based settings */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); - - /* filter data */ - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* init BezTriple looping data */ - test_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED); - - /* See if we should be selecting or deselecting */ - if (test) { - for (ale = anim_data.first; ale; ale = ale->next) { - if (ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, test_cb, NULL)) { - sel = SELECT_SUBTRACT; - break; - } - } - } - - /* convert sel to selectmode, and use that to get editor */ - sel_cb = ANIM_editkeyframes_select(sel); - - /* Now set the flags */ - for (ale = anim_data.first; ale; ale = ale->next) { - FCurve *fcu = (FCurve *)ale->key_data; - - /* Keyframes First */ - ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL); - - /* affect channel selection status? */ - if (do_channels) { - /* only change selection of channel when the visibility of keyframes doesn't depend on this */ - if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) { - /* deactivate the F-Curve, and deselect if deselecting keyframes. - * otherwise select the F-Curve too since we've selected all the keyframes - */ - if (sel == SELECT_SUBTRACT) - fcu->flag &= ~FCURVE_SELECTED; - else - fcu->flag |= FCURVE_SELECTED; - } - - /* always deactivate all F-Curves if we perform batch ops for selection */ - fcu->flag &= ~FCURVE_ACTIVE; - } - } - - /* Cleanup */ - ANIM_animdata_freelist(&anim_data); + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + SpaceGraph *sipo = (SpaceGraph *)ac->sl; + KeyframeEditData ked = {{NULL}}; + KeyframeEditFunc test_cb, sel_cb; + + /* determine type-based settings */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); + + /* filter data */ + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* init BezTriple looping data */ + test_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED); + + /* See if we should be selecting or deselecting */ + if (test) { + for (ale = anim_data.first; ale; ale = ale->next) { + if (ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, test_cb, NULL)) { + sel = SELECT_SUBTRACT; + break; + } + } + } + + /* convert sel to selectmode, and use that to get editor */ + sel_cb = ANIM_editkeyframes_select(sel); + + /* Now set the flags */ + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu = (FCurve *)ale->key_data; + + /* Keyframes First */ + ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL); + + /* affect channel selection status? */ + if (do_channels) { + /* only change selection of channel when the visibility of keyframes doesn't depend on this */ + if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) { + /* deactivate the F-Curve, and deselect if deselecting keyframes. + * otherwise select the F-Curve too since we've selected all the keyframes + */ + if (sel == SELECT_SUBTRACT) + fcu->flag &= ~FCURVE_SELECTED; + else + fcu->flag |= FCURVE_SELECTED; + } + + /* always deactivate all F-Curves if we perform batch ops for selection */ + fcu->flag &= ~FCURVE_ACTIVE; + } + } + + /* Cleanup */ + ANIM_animdata_freelist(&anim_data); } /* ------------------- */ static int graphkeys_deselectall_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - bAnimListElem *ale_active = NULL; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* find active F-Curve, and preserve this for later - * or else it becomes annoying with the current active - * curve keeps fading out even while you're editing it - */ - ale_active = get_active_fcurve_channel(&ac); - - /* 'standard' behavior - check if selected, then apply relevant selection */ - const int action = RNA_enum_get(op->ptr, "action"); - switch (action) { - case SEL_TOGGLE: - deselect_graph_keys(&ac, 1, SELECT_ADD, true); - break; - case SEL_SELECT: - deselect_graph_keys(&ac, 0, SELECT_ADD, true); - break; - case SEL_DESELECT: - deselect_graph_keys(&ac, 0, SELECT_SUBTRACT, true); - break; - case SEL_INVERT: - deselect_graph_keys(&ac, 0, SELECT_INVERT, true); - break; - default: - BLI_assert(0); - break; - } - - /* restore active F-Curve... */ - if (ale_active) { - FCurve *fcu = (FCurve *)ale_active->data; - - /* all others should not be disabled, so we should be able to just set this directly... - * - selection needs to be set too, or else this won't work... - */ - fcu->flag |= (FCURVE_SELECTED | FCURVE_ACTIVE); - - MEM_freeN(ale_active); - ale_active = NULL; - } - - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); - - return OPERATOR_FINISHED; + bAnimContext ac; + bAnimListElem *ale_active = NULL; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* find active F-Curve, and preserve this for later + * or else it becomes annoying with the current active + * curve keeps fading out even while you're editing it + */ + ale_active = get_active_fcurve_channel(&ac); + + /* 'standard' behavior - check if selected, then apply relevant selection */ + const int action = RNA_enum_get(op->ptr, "action"); + switch (action) { + case SEL_TOGGLE: + deselect_graph_keys(&ac, 1, SELECT_ADD, true); + break; + case SEL_SELECT: + deselect_graph_keys(&ac, 0, SELECT_ADD, true); + break; + case SEL_DESELECT: + deselect_graph_keys(&ac, 0, SELECT_SUBTRACT, true); + break; + case SEL_INVERT: + deselect_graph_keys(&ac, 0, SELECT_INVERT, true); + break; + default: + BLI_assert(0); + break; + } + + /* restore active F-Curve... */ + if (ale_active) { + FCurve *fcu = (FCurve *)ale_active->data; + + /* all others should not be disabled, so we should be able to just set this directly... + * - selection needs to be set too, or else this won't work... + */ + fcu->flag |= (FCURVE_SELECTED | FCURVE_ACTIVE); + + MEM_freeN(ale_active); + ale_active = NULL; + } + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); + + return OPERATOR_FINISHED; } void GRAPH_OT_select_all(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Select All"; - ot->idname = "GRAPH_OT_select_all"; - ot->description = "Toggle selection of all keyframes"; + /* identifiers */ + ot->name = "Select All"; + ot->idname = "GRAPH_OT_select_all"; + ot->description = "Toggle selection of all keyframes"; - /* api callbacks */ - ot->exec = graphkeys_deselectall_exec; - ot->poll = graphop_visible_keyframes_poll; + /* api callbacks */ + ot->exec = graphkeys_deselectall_exec; + ot->poll = graphop_visible_keyframes_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ - WM_operator_properties_select_all(ot); + /* properties */ + WM_operator_properties_select_all(ot); } /* ******************** Box Select Operator **************************** */ @@ -228,336 +226,341 @@ void GRAPH_OT_select_all(wmOperatorType *ot) * this, and allow handles to be considered independently too. * Also, for convenience, handles should get same status as keyframe (if it was within bounds). */ -static void box_select_graphkeys( - bAnimContext *ac, const rctf *rectf_view, short mode, short selectmode, bool incl_handles, - void *data) +static void box_select_graphkeys(bAnimContext *ac, + const rctf *rectf_view, + short mode, + short selectmode, + bool incl_handles, + void *data) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter, mapping_flag; - - SpaceGraph *sipo = (SpaceGraph *)ac->sl; - KeyframeEditData ked; - KeyframeEditFunc ok_cb, select_cb; - View2D *v2d = &ac->ar->v2d; - rctf rectf, scaled_rectf; - - /* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */ - UI_view2d_region_to_view_rctf(v2d, rectf_view, &rectf); - - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* get beztriple editing/validation funcs */ - select_cb = ANIM_editkeyframes_select(selectmode); - ok_cb = ANIM_editkeyframes_ok(mode); - - /* init editing data */ - memset(&ked, 0, sizeof(KeyframeEditData)); - if (mode == BEZT_OK_REGION_LASSO) { - KeyframeEdit_LassoData *data_lasso = data; - data_lasso->rectf_scaled = &scaled_rectf; - ked.data = data_lasso; - } - else if (mode == BEZT_OK_REGION_CIRCLE) { - KeyframeEdit_CircleData *data_circle = data; - data_circle->rectf_scaled = &scaled_rectf; - ked.data = data; - } - else { - ked.data = &scaled_rectf; - } - - /* treat handles separately? */ - if (incl_handles) { - ked.iterflags |= KEYFRAME_ITER_INCL_HANDLES; - mapping_flag = 0; - } - else - mapping_flag = ANIM_UNITCONV_ONLYKEYS; - - mapping_flag |= ANIM_get_normalization_flags(ac); - - /* loop over data, doing box select */ - for (ale = anim_data.first; ale; ale = ale->next) { - AnimData *adt = ANIM_nla_mapping_get(ac, ale); - FCurve *fcu = (FCurve *)ale->key_data; - float offset; - float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset); - - /* apply NLA mapping to all the keyframes, since it's easier than trying to - * guess when a callback might use something different - */ - if (adt) - ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, incl_handles == 0); - - scaled_rectf.xmin = rectf.xmin; - scaled_rectf.xmax = rectf.xmax; - scaled_rectf.ymin = rectf.ymin / unit_scale - offset; - scaled_rectf.ymax = rectf.ymax / unit_scale - offset; - - /* set horizontal range (if applicable) - * NOTE: these values are only used for x-range and y-range but not region - * (which uses ked.data, i.e. rectf) - */ - if (mode != BEZT_OK_VALUERANGE) { - ked.f1 = rectf.xmin; - ked.f2 = rectf.xmax; - } - else { - ked.f1 = rectf.ymin; - ked.f2 = rectf.ymax; - } - - /* firstly, check if any keyframes will be hit by this */ - if (ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, ok_cb, NULL)) { - /* select keyframes that are in the appropriate places */ - ANIM_fcurve_keyframes_loop(&ked, fcu, ok_cb, select_cb, NULL); - - /* only change selection of channel when the visibility of keyframes doesn't depend on this */ - if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) { - /* select the curve too now that curve will be touched */ - if (selectmode == SELECT_ADD) - fcu->flag |= FCURVE_SELECTED; - } - } - - /* un-apply NLA mapping from all the keyframes */ - if (adt) - ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, incl_handles == 0); - } - - /* cleanup */ - ANIM_animdata_freelist(&anim_data); + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter, mapping_flag; + + SpaceGraph *sipo = (SpaceGraph *)ac->sl; + KeyframeEditData ked; + KeyframeEditFunc ok_cb, select_cb; + View2D *v2d = &ac->ar->v2d; + rctf rectf, scaled_rectf; + + /* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */ + UI_view2d_region_to_view_rctf(v2d, rectf_view, &rectf); + + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* get beztriple editing/validation funcs */ + select_cb = ANIM_editkeyframes_select(selectmode); + ok_cb = ANIM_editkeyframes_ok(mode); + + /* init editing data */ + memset(&ked, 0, sizeof(KeyframeEditData)); + if (mode == BEZT_OK_REGION_LASSO) { + KeyframeEdit_LassoData *data_lasso = data; + data_lasso->rectf_scaled = &scaled_rectf; + ked.data = data_lasso; + } + else if (mode == BEZT_OK_REGION_CIRCLE) { + KeyframeEdit_CircleData *data_circle = data; + data_circle->rectf_scaled = &scaled_rectf; + ked.data = data; + } + else { + ked.data = &scaled_rectf; + } + + /* treat handles separately? */ + if (incl_handles) { + ked.iterflags |= KEYFRAME_ITER_INCL_HANDLES; + mapping_flag = 0; + } + else + mapping_flag = ANIM_UNITCONV_ONLYKEYS; + + mapping_flag |= ANIM_get_normalization_flags(ac); + + /* loop over data, doing box select */ + for (ale = anim_data.first; ale; ale = ale->next) { + AnimData *adt = ANIM_nla_mapping_get(ac, ale); + FCurve *fcu = (FCurve *)ale->key_data; + float offset; + float unit_scale = ANIM_unit_mapping_get_factor( + ac->scene, ale->id, fcu, mapping_flag, &offset); + + /* apply NLA mapping to all the keyframes, since it's easier than trying to + * guess when a callback might use something different + */ + if (adt) + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, incl_handles == 0); + + scaled_rectf.xmin = rectf.xmin; + scaled_rectf.xmax = rectf.xmax; + scaled_rectf.ymin = rectf.ymin / unit_scale - offset; + scaled_rectf.ymax = rectf.ymax / unit_scale - offset; + + /* set horizontal range (if applicable) + * NOTE: these values are only used for x-range and y-range but not region + * (which uses ked.data, i.e. rectf) + */ + if (mode != BEZT_OK_VALUERANGE) { + ked.f1 = rectf.xmin; + ked.f2 = rectf.xmax; + } + else { + ked.f1 = rectf.ymin; + ked.f2 = rectf.ymax; + } + + /* firstly, check if any keyframes will be hit by this */ + if (ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, ok_cb, NULL)) { + /* select keyframes that are in the appropriate places */ + ANIM_fcurve_keyframes_loop(&ked, fcu, ok_cb, select_cb, NULL); + + /* only change selection of channel when the visibility of keyframes doesn't depend on this */ + if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) { + /* select the curve too now that curve will be touched */ + if (selectmode == SELECT_ADD) + fcu->flag |= FCURVE_SELECTED; + } + } + + /* un-apply NLA mapping from all the keyframes */ + if (adt) + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, incl_handles == 0); + } + + /* cleanup */ + ANIM_animdata_freelist(&anim_data); } /* ------------------- */ static int graphkeys_box_select_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - rcti rect; - rctf rect_fl; - short mode = 0; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); - const int selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - deselect_graph_keys(&ac, 1, SELECT_SUBTRACT, true); - } - - /* 'include_handles' from the operator specifies whether to include handles in the selection. */ - const bool incl_handles = RNA_boolean_get(op->ptr, "include_handles"); - - /* get settings from operator */ - WM_operator_properties_border_to_rcti(op, &rect); - - /* selection 'mode' depends on whether box_select region only matters on one axis */ - if (RNA_boolean_get(op->ptr, "axis_range")) { - /* mode depends on which axis of the range is larger to determine which axis to use - * - checking this in region-space is fine, as it's fundamentally still going to be a different rect size - * - the frame-range select option is favored over the channel one (x over y), as frame-range one is often - * used for tweaking timing when "blocking", while channels is not that useful... - */ - if ((BLI_rcti_size_x(&rect)) >= (BLI_rcti_size_y(&rect))) - mode = BEZT_OK_FRAMERANGE; - else - mode = BEZT_OK_VALUERANGE; - } - else - mode = BEZT_OK_REGION; - - BLI_rctf_rcti_copy(&rect_fl, &rect); - - /* apply box_select action */ - box_select_graphkeys(&ac, &rect_fl, mode, selectmode, incl_handles, NULL); - - /* send notifier that keyframe selection has changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); - - return OPERATOR_FINISHED; + bAnimContext ac; + rcti rect; + rctf rect_fl; + short mode = 0; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); + const int selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT; + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + deselect_graph_keys(&ac, 1, SELECT_SUBTRACT, true); + } + + /* 'include_handles' from the operator specifies whether to include handles in the selection. */ + const bool incl_handles = RNA_boolean_get(op->ptr, "include_handles"); + + /* get settings from operator */ + WM_operator_properties_border_to_rcti(op, &rect); + + /* selection 'mode' depends on whether box_select region only matters on one axis */ + if (RNA_boolean_get(op->ptr, "axis_range")) { + /* mode depends on which axis of the range is larger to determine which axis to use + * - checking this in region-space is fine, as it's fundamentally still going to be a different rect size + * - the frame-range select option is favored over the channel one (x over y), as frame-range one is often + * used for tweaking timing when "blocking", while channels is not that useful... + */ + if ((BLI_rcti_size_x(&rect)) >= (BLI_rcti_size_y(&rect))) + mode = BEZT_OK_FRAMERANGE; + else + mode = BEZT_OK_VALUERANGE; + } + else + mode = BEZT_OK_REGION; + + BLI_rctf_rcti_copy(&rect_fl, &rect); + + /* apply box_select action */ + box_select_graphkeys(&ac, &rect_fl, mode, selectmode, incl_handles, NULL); + + /* send notifier that keyframe selection has changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); + + return OPERATOR_FINISHED; } void GRAPH_OT_select_box(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Box Select"; - ot->idname = "GRAPH_OT_select_box"; - ot->description = "Select all keyframes within the specified region"; - - /* api callbacks */ - ot->invoke = WM_gesture_box_invoke; - ot->exec = graphkeys_box_select_exec; - ot->modal = WM_gesture_box_modal; - ot->cancel = WM_gesture_box_cancel; - - ot->poll = graphop_visible_keyframes_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - ot->prop = RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", ""); - RNA_def_boolean(ot->srna, "include_handles", 0, "Include Handles", "Are handles tested individually against the selection criteria"); - - WM_operator_properties_gesture_box(ot); - WM_operator_properties_select_operation_simple(ot); + /* identifiers */ + ot->name = "Box Select"; + ot->idname = "GRAPH_OT_select_box"; + ot->description = "Select all keyframes within the specified region"; + + /* api callbacks */ + ot->invoke = WM_gesture_box_invoke; + ot->exec = graphkeys_box_select_exec; + ot->modal = WM_gesture_box_modal; + ot->cancel = WM_gesture_box_cancel; + + ot->poll = graphop_visible_keyframes_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", ""); + RNA_def_boolean(ot->srna, + "include_handles", + 0, + "Include Handles", + "Are handles tested individually against the selection criteria"); + + WM_operator_properties_gesture_box(ot); + WM_operator_properties_select_operation_simple(ot); } - /* ------------------- */ static int graphkeys_lassoselect_exec(bContext *C, wmOperator *op) { - bAnimContext ac; + bAnimContext ac; - KeyframeEdit_LassoData data_lasso = {0}; - rcti rect; - rctf rect_fl; + KeyframeEdit_LassoData data_lasso = {0}; + rcti rect; + rctf rect_fl; - bool incl_handles; + bool incl_handles; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - data_lasso.rectf_view = &rect_fl; - data_lasso.mcords = WM_gesture_lasso_path_to_array(C, op, &data_lasso.mcords_tot); - if (data_lasso.mcords == NULL) - return OPERATOR_CANCELLED; + data_lasso.rectf_view = &rect_fl; + data_lasso.mcords = WM_gesture_lasso_path_to_array(C, op, &data_lasso.mcords_tot); + if (data_lasso.mcords == NULL) + return OPERATOR_CANCELLED; - const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); - const short selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - deselect_graph_keys(&ac, 0, SELECT_SUBTRACT, true); - } + const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); + const short selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT; + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + deselect_graph_keys(&ac, 0, SELECT_SUBTRACT, true); + } - { - SpaceGraph *sipo = (SpaceGraph *)ac.sl; - if (selectmode == SELECT_ADD) { - incl_handles = ((sipo->flag & SIPO_SELVHANDLESONLY) || - (sipo->flag & SIPO_NOHANDLES)) == 0; - } - else { - incl_handles = (sipo->flag & SIPO_NOHANDLES) == 0; - } - } + { + SpaceGraph *sipo = (SpaceGraph *)ac.sl; + if (selectmode == SELECT_ADD) { + incl_handles = ((sipo->flag & SIPO_SELVHANDLESONLY) || (sipo->flag & SIPO_NOHANDLES)) == 0; + } + else { + incl_handles = (sipo->flag & SIPO_NOHANDLES) == 0; + } + } - /* get settings from operator */ - BLI_lasso_boundbox(&rect, data_lasso.mcords, data_lasso.mcords_tot); - BLI_rctf_rcti_copy(&rect_fl, &rect); + /* get settings from operator */ + BLI_lasso_boundbox(&rect, data_lasso.mcords, data_lasso.mcords_tot); + BLI_rctf_rcti_copy(&rect_fl, &rect); - /* apply box_select action */ - box_select_graphkeys(&ac, &rect_fl, BEZT_OK_REGION_LASSO, selectmode, incl_handles, &data_lasso); + /* apply box_select action */ + box_select_graphkeys(&ac, &rect_fl, BEZT_OK_REGION_LASSO, selectmode, incl_handles, &data_lasso); - MEM_freeN((void *)data_lasso.mcords); + MEM_freeN((void *)data_lasso.mcords); - /* send notifier that keyframe selection has changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); + /* send notifier that keyframe selection has changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_select_lasso(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Lasso Select"; - ot->description = "Select keyframe points using lasso selection"; - ot->idname = "GRAPH_OT_select_lasso"; - - /* api callbacks */ - ot->invoke = WM_gesture_lasso_invoke; - ot->modal = WM_gesture_lasso_modal; - ot->exec = graphkeys_lassoselect_exec; - ot->poll = graphop_visible_keyframes_poll; - ot->cancel = WM_gesture_lasso_cancel; - - /* flags */ - ot->flag = OPTYPE_UNDO; - - /* properties */ - WM_operator_properties_gesture_lasso(ot); - WM_operator_properties_select_operation_simple(ot); + /* identifiers */ + ot->name = "Lasso Select"; + ot->description = "Select keyframe points using lasso selection"; + ot->idname = "GRAPH_OT_select_lasso"; + + /* api callbacks */ + ot->invoke = WM_gesture_lasso_invoke; + ot->modal = WM_gesture_lasso_modal; + ot->exec = graphkeys_lassoselect_exec; + ot->poll = graphop_visible_keyframes_poll; + ot->cancel = WM_gesture_lasso_cancel; + + /* flags */ + ot->flag = OPTYPE_UNDO; + + /* properties */ + WM_operator_properties_gesture_lasso(ot); + WM_operator_properties_select_operation_simple(ot); } /* ------------------- */ static int graph_circle_select_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - bool incl_handles = false; - - KeyframeEdit_CircleData data = {0}; - rctf rect_fl; - - float x = RNA_int_get(op->ptr, "x"); - float y = RNA_int_get(op->ptr, "y"); - float radius = RNA_int_get(op->ptr, "radius"); - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - const eSelectOp sel_op = ED_select_op_modal( - RNA_enum_get(op->ptr, "mode"), WM_gesture_is_modal_first(op->customdata)); - const short selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - deselect_graph_keys(&ac, 0, SELECT_SUBTRACT, true); - } - - data.mval[0] = x; - data.mval[1] = y; - data.radius_squared = radius * radius; - data.rectf_view = &rect_fl; - - rect_fl.xmin = x - radius; - rect_fl.xmax = x + radius; - rect_fl.ymin = y - radius; - rect_fl.ymax = y + radius; - - { - SpaceGraph *sipo = (SpaceGraph *)ac.sl; - if (selectmode == SELECT_ADD) { - incl_handles = ((sipo->flag & SIPO_SELVHANDLESONLY) || - (sipo->flag & SIPO_NOHANDLES)) == 0; - } - else { - incl_handles = (sipo->flag & SIPO_NOHANDLES) == 0; - } - } - - /* apply box_select action */ - box_select_graphkeys(&ac, &rect_fl, BEZT_OK_REGION_CIRCLE, selectmode, incl_handles, &data); - - /* send notifier that keyframe selection has changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); - - return OPERATOR_FINISHED; + bAnimContext ac; + bool incl_handles = false; + + KeyframeEdit_CircleData data = {0}; + rctf rect_fl; + + float x = RNA_int_get(op->ptr, "x"); + float y = RNA_int_get(op->ptr, "y"); + float radius = RNA_int_get(op->ptr, "radius"); + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"), + WM_gesture_is_modal_first(op->customdata)); + const short selectmode = (sel_op != SEL_OP_SUB) ? SELECT_ADD : SELECT_SUBTRACT; + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + deselect_graph_keys(&ac, 0, SELECT_SUBTRACT, true); + } + + data.mval[0] = x; + data.mval[1] = y; + data.radius_squared = radius * radius; + data.rectf_view = &rect_fl; + + rect_fl.xmin = x - radius; + rect_fl.xmax = x + radius; + rect_fl.ymin = y - radius; + rect_fl.ymax = y + radius; + + { + SpaceGraph *sipo = (SpaceGraph *)ac.sl; + if (selectmode == SELECT_ADD) { + incl_handles = ((sipo->flag & SIPO_SELVHANDLESONLY) || (sipo->flag & SIPO_NOHANDLES)) == 0; + } + else { + incl_handles = (sipo->flag & SIPO_NOHANDLES) == 0; + } + } + + /* apply box_select action */ + box_select_graphkeys(&ac, &rect_fl, BEZT_OK_REGION_CIRCLE, selectmode, incl_handles, &data); + + /* send notifier that keyframe selection has changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); + + return OPERATOR_FINISHED; } void GRAPH_OT_select_circle(wmOperatorType *ot) { - ot->name = "Circle Select"; - ot->description = "Select keyframe points using circle selection"; - ot->idname = "GRAPH_OT_select_circle"; - - ot->invoke = WM_gesture_circle_invoke; - ot->modal = WM_gesture_circle_modal; - ot->exec = graph_circle_select_exec; - ot->poll = graphop_visible_keyframes_poll; - ot->cancel = WM_gesture_circle_cancel; - - /* flags */ - ot->flag = OPTYPE_UNDO; - - /* properties */ - WM_operator_properties_gesture_circle(ot); - WM_operator_properties_select_operation_simple(ot); + ot->name = "Circle Select"; + ot->description = "Select keyframe points using circle selection"; + ot->idname = "GRAPH_OT_select_circle"; + + ot->invoke = WM_gesture_circle_invoke; + ot->modal = WM_gesture_circle_modal; + ot->exec = graph_circle_select_exec; + ot->poll = graphop_visible_keyframes_poll; + ot->cancel = WM_gesture_circle_cancel; + + /* flags */ + ot->flag = OPTYPE_UNDO; + + /* properties */ + WM_operator_properties_gesture_circle(ot); + WM_operator_properties_select_operation_simple(ot); } /* ******************** Column Select Operator **************************** */ @@ -570,11 +573,15 @@ void GRAPH_OT_select_circle(wmOperatorType *ot) /* defines for column-select mode */ static const EnumPropertyItem prop_column_select_types[] = { - {GRAPHKEYS_COLUMNSEL_KEYS, "KEYS", 0, "On Selected Keyframes", ""}, - {GRAPHKEYS_COLUMNSEL_CFRA, "CFRA", 0, "On Current Frame", ""}, - {GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN, "MARKERS_COLUMN", 0, "On Selected Markers", ""}, - {GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN, "MARKERS_BETWEEN", 0, "Between Min/Max Selected Markers", ""}, - {0, NULL, 0, NULL, NULL}, + {GRAPHKEYS_COLUMNSEL_KEYS, "KEYS", 0, "On Selected Keyframes", ""}, + {GRAPHKEYS_COLUMNSEL_CFRA, "CFRA", 0, "On Current Frame", ""}, + {GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN, "MARKERS_COLUMN", 0, "On Selected Markers", ""}, + {GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN, + "MARKERS_BETWEEN", + 0, + "Between Min/Max Selected Markers", + ""}, + {0, NULL, 0, NULL, NULL}, }; /* ------------------- */ @@ -584,218 +591,217 @@ static const EnumPropertyItem prop_column_select_types[] = { * should de-duplicate - campbell */ static void markers_selectkeys_between(bAnimContext *ac) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - KeyframeEditFunc ok_cb, select_cb; - KeyframeEditData ked = {{NULL}}; - float min, max; - - /* get extreme markers */ - ED_markers_get_minmax(ac->markers, 1, &min, &max); - min -= 0.5f; - max += 0.5f; - - /* get editing funcs + data */ - ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE); - select_cb = ANIM_editkeyframes_select(SELECT_ADD); - - ked.f1 = min; - ked.f2 = max; - - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* select keys in-between */ - for (ale = anim_data.first; ale; ale = ale->next) { - AnimData *adt = ANIM_nla_mapping_get(ac, ale); - - if (adt) { - ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); - ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); - ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); - } - else { - ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); - } - } - - /* Cleanup */ - ANIM_animdata_freelist(&anim_data); + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + KeyframeEditFunc ok_cb, select_cb; + KeyframeEditData ked = {{NULL}}; + float min, max; + + /* get extreme markers */ + ED_markers_get_minmax(ac->markers, 1, &min, &max); + min -= 0.5f; + max += 0.5f; + + /* get editing funcs + data */ + ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE); + select_cb = ANIM_editkeyframes_select(SELECT_ADD); + + ked.f1 = min; + ked.f2 = max; + + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* select keys in-between */ + for (ale = anim_data.first; ale; ale = ale->next) { + AnimData *adt = ANIM_nla_mapping_get(ac, ale); + + if (adt) { + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); + ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); + } + else { + ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); + } + } + + /* Cleanup */ + ANIM_animdata_freelist(&anim_data); } - /* Selects all visible keyframes in the same frames as the specified elements */ static void columnselect_graph_keys(bAnimContext *ac, short mode) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - Scene *scene = ac->scene; - CfraElem *ce; - KeyframeEditFunc select_cb, ok_cb; - KeyframeEditData ked; - - /* initialize keyframe editing data */ - memset(&ked, 0, sizeof(KeyframeEditData)); - - /* build list of columns */ - switch (mode) { - case GRAPHKEYS_COLUMNSEL_KEYS: /* list of selected keys */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - for (ale = anim_data.first; ale; ale = ale->next) - ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_to_cfraelem, NULL); - - ANIM_animdata_freelist(&anim_data); - break; - - case GRAPHKEYS_COLUMNSEL_CFRA: /* current frame */ - /* make a single CfraElem for storing this */ - ce = MEM_callocN(sizeof(CfraElem), "cfraElem"); - BLI_addtail(&ked.list, ce); - - ce->cfra = (float)CFRA; - break; - - case GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN: /* list of selected markers */ - ED_markers_make_cfra_list(ac->markers, &ked.list, SELECT); - break; - - default: /* invalid option */ - return; - } - - /* set up BezTriple edit callbacks */ - select_cb = ANIM_editkeyframes_select(SELECT_ADD); - ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAME); - - /* loop through all of the keys and select additional keyframes - * based on the keys found to be selected above - */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - for (ale = anim_data.first; ale; ale = ale->next) { - AnimData *adt = ANIM_nla_mapping_get(ac, ale); - - /* loop over cfraelems (stored in the KeyframeEditData->list) - * - we need to do this here, as we can apply fewer NLA-mapping conversions - */ - for (ce = ked.list.first; ce; ce = ce->next) { - /* set frame for validation callback to refer to */ - ked.f1 = BKE_nla_tweakedit_remap(adt, ce->cfra, NLATIME_CONVERT_UNMAP); - - /* select elements with frame number matching cfraelem */ - ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); - } - } - - /* free elements */ - BLI_freelistN(&ked.list); - ANIM_animdata_freelist(&anim_data); + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + Scene *scene = ac->scene; + CfraElem *ce; + KeyframeEditFunc select_cb, ok_cb; + KeyframeEditData ked; + + /* initialize keyframe editing data */ + memset(&ked, 0, sizeof(KeyframeEditData)); + + /* build list of columns */ + switch (mode) { + case GRAPHKEYS_COLUMNSEL_KEYS: /* list of selected keys */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + for (ale = anim_data.first; ale; ale = ale->next) + ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_to_cfraelem, NULL); + + ANIM_animdata_freelist(&anim_data); + break; + + case GRAPHKEYS_COLUMNSEL_CFRA: /* current frame */ + /* make a single CfraElem for storing this */ + ce = MEM_callocN(sizeof(CfraElem), "cfraElem"); + BLI_addtail(&ked.list, ce); + + ce->cfra = (float)CFRA; + break; + + case GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN: /* list of selected markers */ + ED_markers_make_cfra_list(ac->markers, &ked.list, SELECT); + break; + + default: /* invalid option */ + return; + } + + /* set up BezTriple edit callbacks */ + select_cb = ANIM_editkeyframes_select(SELECT_ADD); + ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAME); + + /* loop through all of the keys and select additional keyframes + * based on the keys found to be selected above + */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + for (ale = anim_data.first; ale; ale = ale->next) { + AnimData *adt = ANIM_nla_mapping_get(ac, ale); + + /* loop over cfraelems (stored in the KeyframeEditData->list) + * - we need to do this here, as we can apply fewer NLA-mapping conversions + */ + for (ce = ked.list.first; ce; ce = ce->next) { + /* set frame for validation callback to refer to */ + ked.f1 = BKE_nla_tweakedit_remap(adt, ce->cfra, NLATIME_CONVERT_UNMAP); + + /* select elements with frame number matching cfraelem */ + ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); + } + } + + /* free elements */ + BLI_freelistN(&ked.list); + ANIM_animdata_freelist(&anim_data); } /* ------------------- */ static int graphkeys_columnselect_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - short mode; + bAnimContext ac; + short mode; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* action to take depends on the mode */ - mode = RNA_enum_get(op->ptr, "mode"); + /* action to take depends on the mode */ + mode = RNA_enum_get(op->ptr, "mode"); - if (mode == GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN) - markers_selectkeys_between(&ac); - else - columnselect_graph_keys(&ac, mode); + if (mode == GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN) + markers_selectkeys_between(&ac); + else + columnselect_graph_keys(&ac, mode); - /* set notifier that keyframe selection has changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); + /* set notifier that keyframe selection has changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_select_column(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Select All"; - ot->idname = "GRAPH_OT_select_column"; - ot->description = "Select all keyframes on the specified frame(s)"; + /* identifiers */ + ot->name = "Select All"; + ot->idname = "GRAPH_OT_select_column"; + ot->description = "Select all keyframes on the specified frame(s)"; - /* api callbacks */ - ot->exec = graphkeys_columnselect_exec; - ot->poll = graphop_visible_keyframes_poll; + /* api callbacks */ + ot->exec = graphkeys_columnselect_exec; + ot->poll = graphop_visible_keyframes_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* props */ - ot->prop = RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", ""); + /* props */ + ot->prop = RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", ""); } /* ******************** Select Linked Operator *********************** */ static int graphkeys_select_linked_exec(bContext *C, wmOperator *UNUSED(op)) { - bAnimContext ac; + bAnimContext ac; - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; - KeyframeEditFunc ok_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED); - KeyframeEditFunc sel_cb = ANIM_editkeyframes_select(SELECT_ADD); + KeyframeEditFunc ok_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED); + KeyframeEditFunc sel_cb = ANIM_editkeyframes_select(SELECT_ADD); - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* loop through all of the keys and select additional keyframes based on these */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + /* loop through all of the keys and select additional keyframes based on these */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - for (ale = anim_data.first; ale; ale = ale->next) { - FCurve *fcu = (FCurve *)ale->key_data; + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu = (FCurve *)ale->key_data; - /* check if anything selected? */ - if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, ok_cb, NULL)) { - /* select every keyframe in this curve then */ - ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, sel_cb, NULL); - } - } + /* check if anything selected? */ + if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, ok_cb, NULL)) { + /* select every keyframe in this curve then */ + ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, sel_cb, NULL); + } + } - /* Cleanup */ - ANIM_animdata_freelist(&anim_data); + /* Cleanup */ + ANIM_animdata_freelist(&anim_data); - /* set notifier that keyframe selection has changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); + /* set notifier that keyframe selection has changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_select_linked(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Select Linked"; - ot->idname = "GRAPH_OT_select_linked"; - ot->description = "Select keyframes occurring in the same F-Curves as selected ones"; + /* identifiers */ + ot->name = "Select Linked"; + ot->idname = "GRAPH_OT_select_linked"; + ot->description = "Select keyframes occurring in the same F-Curves as selected ones"; - /* api callbacks */ - ot->exec = graphkeys_select_linked_exec; - ot->poll = graphop_visible_keyframes_poll; + /* api callbacks */ + ot->exec = graphkeys_select_linked_exec; + ot->poll = graphop_visible_keyframes_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ******************** Select More/Less Operators *********************** */ @@ -803,111 +809,110 @@ void GRAPH_OT_select_linked(wmOperatorType *ot) /* Common code to perform selection */ static void select_moreless_graph_keys(bAnimContext *ac, short mode) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - KeyframeEditData ked; - KeyframeEditFunc build_cb; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + KeyframeEditData ked; + KeyframeEditFunc build_cb; - /* init selmap building data */ - build_cb = ANIM_editkeyframes_buildselmap(mode); - memset(&ked, 0, sizeof(KeyframeEditData)); + /* init selmap building data */ + build_cb = ANIM_editkeyframes_buildselmap(mode); + memset(&ked, 0, sizeof(KeyframeEditData)); - /* loop through all of the keys and select additional keyframes based on these */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + /* loop through all of the keys and select additional keyframes based on these */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - for (ale = anim_data.first; ale; ale = ale->next) { - FCurve *fcu = (FCurve *)ale->key_data; + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu = (FCurve *)ale->key_data; - /* only continue if F-Curve has keyframes */ - if (fcu->bezt == NULL) - continue; + /* only continue if F-Curve has keyframes */ + if (fcu->bezt == NULL) + continue; - /* build up map of whether F-Curve's keyframes should be selected or not */ - ked.data = MEM_callocN(fcu->totvert, "selmap graphEdit"); - ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, build_cb, NULL); + /* build up map of whether F-Curve's keyframes should be selected or not */ + ked.data = MEM_callocN(fcu->totvert, "selmap graphEdit"); + ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, build_cb, NULL); - /* based on this map, adjust the selection status of the keyframes */ - ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, bezt_selmap_flush, NULL); + /* based on this map, adjust the selection status of the keyframes */ + ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, bezt_selmap_flush, NULL); - /* free the selmap used here */ - MEM_freeN(ked.data); - ked.data = NULL; - } + /* free the selmap used here */ + MEM_freeN(ked.data); + ked.data = NULL; + } - /* Cleanup */ - ANIM_animdata_freelist(&anim_data); + /* Cleanup */ + ANIM_animdata_freelist(&anim_data); } /* ----------------- */ static int graphkeys_select_more_exec(bContext *C, wmOperator *UNUSED(op)) { - bAnimContext ac; + bAnimContext ac; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* perform select changes */ - select_moreless_graph_keys(&ac, SELMAP_MORE); + /* perform select changes */ + select_moreless_graph_keys(&ac, SELMAP_MORE); - /* set notifier that keyframe selection has changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); + /* set notifier that keyframe selection has changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_select_more(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Select More"; - ot->idname = "GRAPH_OT_select_more"; - ot->description = "Select keyframes beside already selected ones"; + /* identifiers */ + ot->name = "Select More"; + ot->idname = "GRAPH_OT_select_more"; + ot->description = "Select keyframes beside already selected ones"; - /* api callbacks */ - ot->exec = graphkeys_select_more_exec; - ot->poll = graphop_visible_keyframes_poll; + /* api callbacks */ + ot->exec = graphkeys_select_more_exec; + ot->poll = graphop_visible_keyframes_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ----------------- */ static int graphkeys_select_less_exec(bContext *C, wmOperator *UNUSED(op)) { - bAnimContext ac; + bAnimContext ac; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* perform select changes */ - select_moreless_graph_keys(&ac, SELMAP_LESS); + /* perform select changes */ + select_moreless_graph_keys(&ac, SELMAP_LESS); - /* set notifier that keyframe selection has changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); + /* set notifier that keyframe selection has changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void GRAPH_OT_select_less(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Select Less"; - ot->idname = "GRAPH_OT_select_less"; - ot->description = "Deselect keyframes on ends of selection islands"; + /* identifiers */ + ot->name = "Select Less"; + ot->idname = "GRAPH_OT_select_less"; + ot->description = "Deselect keyframes on ends of selection islands"; - /* api callbacks */ - ot->exec = graphkeys_select_less_exec; - ot->poll = graphop_visible_keyframes_poll; + /* api callbacks */ + ot->exec = graphkeys_select_less_exec; + ot->poll = graphop_visible_keyframes_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ******************** Select Left/Right Operator ************************* */ @@ -915,151 +920,152 @@ void GRAPH_OT_select_less(wmOperatorType *ot) /* defines for left-right select tool */ static const EnumPropertyItem prop_graphkeys_leftright_select_types[] = { - {GRAPHKEYS_LRSEL_TEST, "CHECK", 0, "Check if Select Left or Right", ""}, - {GRAPHKEYS_LRSEL_LEFT, "LEFT", 0, "Before current frame", ""}, - {GRAPHKEYS_LRSEL_RIGHT, "RIGHT", 0, "After current frame", ""}, - {0, NULL, 0, NULL, NULL}, + {GRAPHKEYS_LRSEL_TEST, "CHECK", 0, "Check if Select Left or Right", ""}, + {GRAPHKEYS_LRSEL_LEFT, "LEFT", 0, "Before current frame", ""}, + {GRAPHKEYS_LRSEL_RIGHT, "RIGHT", 0, "After current frame", ""}, + {0, NULL, 0, NULL, NULL}, }; /* --------------------------------- */ static void graphkeys_select_leftright(bAnimContext *ac, short leftright, short select_mode) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - KeyframeEditFunc ok_cb, select_cb; - KeyframeEditData ked = {{NULL}}; - Scene *scene = ac->scene; - - /* if select mode is replace, deselect all keyframes (and channels) first */ - if (select_mode == SELECT_REPLACE) { - select_mode = SELECT_ADD; - - /* - deselect all other keyframes, so that just the newly selected remain - * - channels aren't deselected, since we don't re-select any as a consequence - */ - deselect_graph_keys(ac, 0, SELECT_SUBTRACT, false); - } - - /* set callbacks and editing data */ - ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE); - select_cb = ANIM_editkeyframes_select(select_mode); - - if (leftright == GRAPHKEYS_LRSEL_LEFT) { - ked.f1 = MINAFRAMEF; - ked.f2 = (float)(CFRA + 0.1f); - } - else { - ked.f1 = (float)(CFRA - 0.1f); - ked.f2 = MAXFRAMEF; - } - - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* select keys */ - for (ale = anim_data.first; ale; ale = ale->next) { - AnimData *adt = ANIM_nla_mapping_get(ac, ale); - - if (adt) { - ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); - ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); - ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); - } - else - ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); - } - - /* Cleanup */ - ANIM_animdata_freelist(&anim_data); + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + KeyframeEditFunc ok_cb, select_cb; + KeyframeEditData ked = {{NULL}}; + Scene *scene = ac->scene; + + /* if select mode is replace, deselect all keyframes (and channels) first */ + if (select_mode == SELECT_REPLACE) { + select_mode = SELECT_ADD; + + /* - deselect all other keyframes, so that just the newly selected remain + * - channels aren't deselected, since we don't re-select any as a consequence + */ + deselect_graph_keys(ac, 0, SELECT_SUBTRACT, false); + } + + /* set callbacks and editing data */ + ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE); + select_cb = ANIM_editkeyframes_select(select_mode); + + if (leftright == GRAPHKEYS_LRSEL_LEFT) { + ked.f1 = MINAFRAMEF; + ked.f2 = (float)(CFRA + 0.1f); + } + else { + ked.f1 = (float)(CFRA - 0.1f); + ked.f2 = MAXFRAMEF; + } + + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* select keys */ + for (ale = anim_data.first; ale; ale = ale->next) { + AnimData *adt = ANIM_nla_mapping_get(ac, ale); + + if (adt) { + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); + ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); + } + else + ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); + } + + /* Cleanup */ + ANIM_animdata_freelist(&anim_data); } /* ----------------- */ static int graphkeys_select_leftright_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - short leftright = RNA_enum_get(op->ptr, "mode"); - short selectmode; + bAnimContext ac; + short leftright = RNA_enum_get(op->ptr, "mode"); + short selectmode; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* select mode is either replace (deselect all, then add) or add/extend */ - if (RNA_boolean_get(op->ptr, "extend")) - selectmode = SELECT_INVERT; - else - selectmode = SELECT_REPLACE; + /* select mode is either replace (deselect all, then add) or add/extend */ + if (RNA_boolean_get(op->ptr, "extend")) + selectmode = SELECT_INVERT; + else + selectmode = SELECT_REPLACE; - /* if "test" mode is set, we don't have any info to set this with */ - if (leftright == GRAPHKEYS_LRSEL_TEST) - return OPERATOR_CANCELLED; + /* if "test" mode is set, we don't have any info to set this with */ + if (leftright == GRAPHKEYS_LRSEL_TEST) + return OPERATOR_CANCELLED; - /* do the selecting now */ - graphkeys_select_leftright(&ac, leftright, selectmode); + /* do the selecting now */ + graphkeys_select_leftright(&ac, leftright, selectmode); - /* set notifier that keyframe selection (and channels too) have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); - WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL); + /* set notifier that keyframe selection (and channels too) have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static int graphkeys_select_leftright_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - bAnimContext ac; - short leftright = RNA_enum_get(op->ptr, "mode"); - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* handle mode-based testing */ - if (leftright == GRAPHKEYS_LRSEL_TEST) { - Scene *scene = ac.scene; - ARegion *ar = ac.ar; - View2D *v2d = &ar->v2d; - float x; - - /* determine which side of the current frame mouse is on */ - x = UI_view2d_region_to_view_x(v2d, event->mval[0]); - if (x < CFRA) - RNA_enum_set(op->ptr, "mode", GRAPHKEYS_LRSEL_LEFT); - else - RNA_enum_set(op->ptr, "mode", GRAPHKEYS_LRSEL_RIGHT); - } - - /* perform selection */ - return graphkeys_select_leftright_exec(C, op); + bAnimContext ac; + short leftright = RNA_enum_get(op->ptr, "mode"); + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* handle mode-based testing */ + if (leftright == GRAPHKEYS_LRSEL_TEST) { + Scene *scene = ac.scene; + ARegion *ar = ac.ar; + View2D *v2d = &ar->v2d; + float x; + + /* determine which side of the current frame mouse is on */ + x = UI_view2d_region_to_view_x(v2d, event->mval[0]); + if (x < CFRA) + RNA_enum_set(op->ptr, "mode", GRAPHKEYS_LRSEL_LEFT); + else + RNA_enum_set(op->ptr, "mode", GRAPHKEYS_LRSEL_RIGHT); + } + + /* perform selection */ + return graphkeys_select_leftright_exec(C, op); } void GRAPH_OT_select_leftright(wmOperatorType *ot) { - PropertyRNA *prop; + PropertyRNA *prop; - /* identifiers */ - ot->name = "Select Left/Right"; - ot->idname = "GRAPH_OT_select_leftright"; - ot->description = "Select keyframes to the left or the right of the current frame"; + /* identifiers */ + ot->name = "Select Left/Right"; + ot->idname = "GRAPH_OT_select_leftright"; + ot->description = "Select keyframes to the left or the right of the current frame"; - /* api callbacks */ - ot->invoke = graphkeys_select_leftright_invoke; - ot->exec = graphkeys_select_leftright_exec; - ot->poll = graphop_visible_keyframes_poll; + /* api callbacks */ + ot->invoke = graphkeys_select_leftright_invoke; + ot->exec = graphkeys_select_leftright_exec; + ot->poll = graphop_visible_keyframes_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* id-props */ - ot->prop = RNA_def_enum(ot->srna, "mode", prop_graphkeys_leftright_select_types, GRAPHKEYS_LRSEL_TEST, "Mode", ""); - RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); + /* id-props */ + ot->prop = RNA_def_enum( + ot->srna, "mode", prop_graphkeys_leftright_select_types, GRAPHKEYS_LRSEL_TEST, "Mode", ""); + RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* ******************** Mouse-Click Select Operator *********************** */ @@ -1074,32 +1080,32 @@ void GRAPH_OT_select_leftright(wmOperatorType *ot) /* temp info for caching handle vertices close */ typedef struct tNearestVertInfo { - struct tNearestVertInfo *next, *prev; + struct tNearestVertInfo *next, *prev; - FCurve *fcu; /* F-Curve that keyframe comes from */ + FCurve *fcu; /* F-Curve that keyframe comes from */ - BezTriple *bezt; /* keyframe to consider */ - FPoint *fpt; /* sample point to consider */ + BezTriple *bezt; /* keyframe to consider */ + FPoint *fpt; /* sample point to consider */ - short hpoint; /* the handle index that we hit (eHandleIndex) */ - short sel; /* whether the handle is selected or not */ - int dist; /* distance from mouse to vert */ + short hpoint; /* the handle index that we hit (eHandleIndex) */ + short sel; /* whether the handle is selected or not */ + int dist; /* distance from mouse to vert */ - eAnim_ChannelType ctype; /* type of animation channel this FCurve comes from */ + eAnim_ChannelType ctype; /* type of animation channel this FCurve comes from */ - float frame; /* frame that point was on when it matched (global time) */ + float frame; /* frame that point was on when it matched (global time) */ } tNearestVertInfo; /* Tags for the type of graph vert that we have */ typedef enum eGraphVertIndex { - NEAREST_HANDLE_LEFT = -1, - NEAREST_HANDLE_KEY, - NEAREST_HANDLE_RIGHT, + NEAREST_HANDLE_LEFT = -1, + NEAREST_HANDLE_KEY, + NEAREST_HANDLE_RIGHT, } eGraphVertIndex; /* Tolerance for absolute radius (in pixels) of the vert from the cursor to use */ // TODO: perhaps this should depend a bit on the size that the user set the vertices to be? -#define GVERTSEL_TOL 10 +#define GVERTSEL_TOL 10 /* ....... */ @@ -1107,171 +1113,210 @@ typedef enum eGraphVertIndex { // XXX also need to check for int-values only? static bool fcurve_handle_sel_check(SpaceGraph *sipo, BezTriple *bezt) { - if (sipo->flag & SIPO_NOHANDLES) return 0; - if ((sipo->flag & SIPO_SELVHANDLESONLY) && BEZT_ISSEL_ANY(bezt) == 0) return 0; - return 1; + if (sipo->flag & SIPO_NOHANDLES) + return 0; + if ((sipo->flag & SIPO_SELVHANDLESONLY) && BEZT_ISSEL_ANY(bezt) == 0) + return 0; + return 1; } /* check if the given vertex is within bounds or not */ // TODO: should we return if we hit something? -static void nearest_fcurve_vert_store( - ListBase *matches, View2D *v2d, FCurve *fcu, eAnim_ChannelType ctype, - BezTriple *bezt, FPoint *fpt, short hpoint, const int mval[2], float unit_scale, float offset) +static void nearest_fcurve_vert_store(ListBase *matches, + View2D *v2d, + FCurve *fcu, + eAnim_ChannelType ctype, + BezTriple *bezt, + FPoint *fpt, + short hpoint, + const int mval[2], + float unit_scale, + float offset) { - /* Keyframes or Samples? */ - if (bezt) { - int screen_co[2], dist; - - /* convert from data-space to screen coordinates - * NOTE: hpoint+1 gives us 0,1,2 respectively for each handle, - * needed to access the relevant vertex coordinates in the 3x3 - * 'vec' matrix - */ - if (UI_view2d_view_to_region_clip(v2d, - bezt->vec[hpoint + 1][0], (bezt->vec[hpoint + 1][1] + offset) * unit_scale, - &screen_co[0], &screen_co[1]) && - /* check if distance from mouse cursor to vert in screen space is within tolerance */ - ((dist = len_v2v2_int(mval, screen_co)) <= GVERTSEL_TOL)) - { - tNearestVertInfo *nvi = (tNearestVertInfo *)matches->last; - bool replace = false; - - /* if there is already a point for the F-Curve, check if this point is closer than that was */ - if ((nvi) && (nvi->fcu == fcu)) { - /* replace if we are closer, or if equal and that one wasn't selected but we are... */ - if ((nvi->dist > dist) || ((nvi->sel == 0) && BEZT_ISSEL_ANY(bezt))) - replace = 1; - } - /* add new if not replacing... */ - if (replace == 0) - nvi = MEM_callocN(sizeof(tNearestVertInfo), "Nearest Graph Vert Info - Bezt"); - - /* store values */ - nvi->fcu = fcu; - nvi->ctype = ctype; - - nvi->bezt = bezt; - nvi->hpoint = hpoint; - nvi->dist = dist; - - nvi->frame = bezt->vec[1][0]; /* currently in global time... */ - - nvi->sel = BEZT_ISSEL_ANY(bezt); // XXX... should this use the individual verts instead? - - /* add to list of matches if appropriate... */ - if (replace == 0) - BLI_addtail(matches, nvi); - } - } - else if (fpt) { - /* TODO... */ - } + /* Keyframes or Samples? */ + if (bezt) { + int screen_co[2], dist; + + /* convert from data-space to screen coordinates + * NOTE: hpoint+1 gives us 0,1,2 respectively for each handle, + * needed to access the relevant vertex coordinates in the 3x3 + * 'vec' matrix + */ + if (UI_view2d_view_to_region_clip(v2d, + bezt->vec[hpoint + 1][0], + (bezt->vec[hpoint + 1][1] + offset) * unit_scale, + &screen_co[0], + &screen_co[1]) && + /* check if distance from mouse cursor to vert in screen space is within tolerance */ + ((dist = len_v2v2_int(mval, screen_co)) <= GVERTSEL_TOL)) { + tNearestVertInfo *nvi = (tNearestVertInfo *)matches->last; + bool replace = false; + + /* if there is already a point for the F-Curve, check if this point is closer than that was */ + if ((nvi) && (nvi->fcu == fcu)) { + /* replace if we are closer, or if equal and that one wasn't selected but we are... */ + if ((nvi->dist > dist) || ((nvi->sel == 0) && BEZT_ISSEL_ANY(bezt))) + replace = 1; + } + /* add new if not replacing... */ + if (replace == 0) + nvi = MEM_callocN(sizeof(tNearestVertInfo), "Nearest Graph Vert Info - Bezt"); + + /* store values */ + nvi->fcu = fcu; + nvi->ctype = ctype; + + nvi->bezt = bezt; + nvi->hpoint = hpoint; + nvi->dist = dist; + + nvi->frame = bezt->vec[1][0]; /* currently in global time... */ + + nvi->sel = BEZT_ISSEL_ANY(bezt); // XXX... should this use the individual verts instead? + + /* add to list of matches if appropriate... */ + if (replace == 0) + BLI_addtail(matches, nvi); + } + } + else if (fpt) { + /* TODO... */ + } } /* helper for find_nearest_fcurve_vert() - build the list of nearest matches */ static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], ListBase *matches) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - SpaceGraph *sipo = (SpaceGraph *)ac->sl; - View2D *v2d = &ac->ar->v2d; - short mapping_flag = 0; - - /* get curves to search through - * - if the option to only show keyframes that belong to selected F-Curves is enabled, - * include the 'only selected' flag... - */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); - if (sipo->flag & SIPO_SELCUVERTSONLY) // FIXME: this should really be check for by the filtering code... - filter |= ANIMFILTER_SEL; - mapping_flag |= ANIM_get_normalization_flags(ac); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - for (ale = anim_data.first; ale; ale = ale->next) { - FCurve *fcu = (FCurve *)ale->key_data; - AnimData *adt = ANIM_nla_mapping_get(ac, ale); - float offset; - float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset); - - /* apply NLA mapping to all the keyframes */ - if (adt) - ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0); - - if (fcu->bezt) { - BezTriple *bezt1 = fcu->bezt, *prevbezt = NULL; - int i; - - for (i = 0; i < fcu->totvert; i++, prevbezt = bezt1, bezt1++) { - /* keyframe */ - nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_KEY, mval, unit_scale, offset); - - /* handles - only do them if they're visible */ - if (fcurve_handle_sel_check(sipo, bezt1) && (fcu->totvert > 1)) { - /* first handle only visible if previous segment had handles */ - if ((!prevbezt && (bezt1->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) { - nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_LEFT, mval, unit_scale, offset); - } - - /* second handle only visible if this segment is bezier */ - if (bezt1->ipo == BEZT_IPO_BEZ) { - nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_RIGHT, mval, unit_scale, offset); - } - } - } - } - else if (fcu->fpt) { - // TODO; do this for samples too - - } - - /* un-apply NLA mapping from all the keyframes */ - if (adt) - ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0); - } - - /* free channels */ - ANIM_animdata_freelist(&anim_data); + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + SpaceGraph *sipo = (SpaceGraph *)ac->sl; + View2D *v2d = &ac->ar->v2d; + short mapping_flag = 0; + + /* get curves to search through + * - if the option to only show keyframes that belong to selected F-Curves is enabled, + * include the 'only selected' flag... + */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); + if (sipo->flag & + SIPO_SELCUVERTSONLY) // FIXME: this should really be check for by the filtering code... + filter |= ANIMFILTER_SEL; + mapping_flag |= ANIM_get_normalization_flags(ac); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu = (FCurve *)ale->key_data; + AnimData *adt = ANIM_nla_mapping_get(ac, ale); + float offset; + float unit_scale = ANIM_unit_mapping_get_factor( + ac->scene, ale->id, fcu, mapping_flag, &offset); + + /* apply NLA mapping to all the keyframes */ + if (adt) + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0); + + if (fcu->bezt) { + BezTriple *bezt1 = fcu->bezt, *prevbezt = NULL; + int i; + + for (i = 0; i < fcu->totvert; i++, prevbezt = bezt1, bezt1++) { + /* keyframe */ + nearest_fcurve_vert_store(matches, + v2d, + fcu, + ale->type, + bezt1, + NULL, + NEAREST_HANDLE_KEY, + mval, + unit_scale, + offset); + + /* handles - only do them if they're visible */ + if (fcurve_handle_sel_check(sipo, bezt1) && (fcu->totvert > 1)) { + /* first handle only visible if previous segment had handles */ + if ((!prevbezt && (bezt1->ipo == BEZT_IPO_BEZ)) || + (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) { + nearest_fcurve_vert_store(matches, + v2d, + fcu, + ale->type, + bezt1, + NULL, + NEAREST_HANDLE_LEFT, + mval, + unit_scale, + offset); + } + + /* second handle only visible if this segment is bezier */ + if (bezt1->ipo == BEZT_IPO_BEZ) { + nearest_fcurve_vert_store(matches, + v2d, + fcu, + ale->type, + bezt1, + NULL, + NEAREST_HANDLE_RIGHT, + mval, + unit_scale, + offset); + } + } + } + } + else if (fcu->fpt) { + // TODO; do this for samples too + } + + /* un-apply NLA mapping from all the keyframes */ + if (adt) + ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0); + } + + /* free channels */ + ANIM_animdata_freelist(&anim_data); } /* helper for find_nearest_fcurve_vert() - get the best match to use */ static tNearestVertInfo *get_best_nearest_fcurve_vert(ListBase *matches) { - tNearestVertInfo *nvi = NULL; - short found = 0; - - /* abort if list is empty */ - if (BLI_listbase_is_empty(matches)) - return NULL; - - /* if list only has 1 item, remove it from the list and return */ - if (BLI_listbase_is_single(matches)) { - /* need to remove from the list, otherwise it gets freed and then we can't return it */ - return BLI_pophead(matches); - } - - /* try to find the first selected F-Curve vert, then take the one after it */ - for (nvi = matches->first; nvi; nvi = nvi->next) { - /* which mode of search are we in: find first selected, or find vert? */ - if (found) { - /* just take this vert now that we've found the selected one - * - we'll need to remove this from the list so that it can be returned to the original caller - */ - BLI_remlink(matches, nvi); - return nvi; - } - else { - /* if vert is selected, we've got what we want... */ - if (nvi->sel) - found = 1; - } - } - - /* if we're still here, this means that we failed to find anything appropriate in the first pass, - * so just take the first item now... - */ - return BLI_pophead(matches); + tNearestVertInfo *nvi = NULL; + short found = 0; + + /* abort if list is empty */ + if (BLI_listbase_is_empty(matches)) + return NULL; + + /* if list only has 1 item, remove it from the list and return */ + if (BLI_listbase_is_single(matches)) { + /* need to remove from the list, otherwise it gets freed and then we can't return it */ + return BLI_pophead(matches); + } + + /* try to find the first selected F-Curve vert, then take the one after it */ + for (nvi = matches->first; nvi; nvi = nvi->next) { + /* which mode of search are we in: find first selected, or find vert? */ + if (found) { + /* just take this vert now that we've found the selected one + * - we'll need to remove this from the list so that it can be returned to the original caller + */ + BLI_remlink(matches, nvi); + return nvi; + } + else { + /* if vert is selected, we've got what we want... */ + if (nvi->sel) + found = 1; + } + } + + /* if we're still here, this means that we failed to find anything appropriate in the first pass, + * so just take the first item now... + */ + return BLI_pophead(matches); } /* Find the nearest vertices (either a handle or the keyframe) that are nearest to the mouse cursor (in area coordinates) @@ -1279,142 +1324,145 @@ static tNearestVertInfo *get_best_nearest_fcurve_vert(ListBase *matches) */ static tNearestVertInfo *find_nearest_fcurve_vert(bAnimContext *ac, const int mval[2]) { - ListBase matches = {NULL, NULL}; - tNearestVertInfo *nvi; + ListBase matches = {NULL, NULL}; + tNearestVertInfo *nvi; - /* step 1: get the nearest verts */ - get_nearest_fcurve_verts_list(ac, mval, &matches); + /* step 1: get the nearest verts */ + get_nearest_fcurve_verts_list(ac, mval, &matches); - /* step 2: find the best vert */ - nvi = get_best_nearest_fcurve_vert(&matches); + /* step 2: find the best vert */ + nvi = get_best_nearest_fcurve_vert(&matches); - BLI_freelistN(&matches); + BLI_freelistN(&matches); - /* return the best vert found */ - return nvi; + /* return the best vert found */ + return nvi; } /* ------------------- */ /* option 1) select keyframe directly under mouse */ -static void mouse_graph_keys(bAnimContext *ac, const int mval[2], short select_mode, short curves_only) +static void mouse_graph_keys(bAnimContext *ac, + const int mval[2], + short select_mode, + short curves_only) { - SpaceGraph *sipo = (SpaceGraph *)ac->sl; - tNearestVertInfo *nvi; - BezTriple *bezt = NULL; - - /* find the beztriple that we're selecting, and the handle that was clicked on */ - nvi = find_nearest_fcurve_vert(ac, mval); - - /* check if anything to select */ - if (nvi == NULL) - return; - - /* deselect all other curves? */ - if (select_mode == SELECT_REPLACE) { - /* reset selection mode */ - select_mode = SELECT_ADD; - - /* deselect all other keyframes (+ F-Curves too) */ - deselect_graph_keys(ac, 0, SELECT_SUBTRACT, true); - - /* deselect other channels too, but only only do this if - * selection of channel when the visibility of keyframes - * doesn't depend on this - */ - if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) - ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); - } - - /* if points can be selected on this F-Curve */ - // TODO: what about those with no keyframes? - if ((curves_only == 0) && ((nvi->fcu->flag & FCURVE_PROTECTED) == 0)) { - /* only if there's keyframe */ - if (nvi->bezt) { - bezt = nvi->bezt; /* used to check bezt seletion is set */ - /* depends on selection mode */ - if (select_mode == SELECT_INVERT) { - /* keyframe - invert select of all */ - if (nvi->hpoint == NEAREST_HANDLE_KEY) { - if (BEZT_ISSEL_ANY(bezt)) { - BEZT_DESEL_ALL(bezt); - } - else { - BEZT_SEL_ALL(bezt); - } - } - - /* handles - toggle selection of relevant handle */ - else if (nvi->hpoint == NEAREST_HANDLE_LEFT) { - /* toggle selection */ - bezt->f1 ^= SELECT; - } - else { - /* toggle selection */ - bezt->f3 ^= SELECT; - } - } - else { - /* if the keyframe was clicked on, select all verts of given beztriple */ - if (nvi->hpoint == NEAREST_HANDLE_KEY) { - BEZT_SEL_ALL(bezt); - } - /* otherwise, select the handle that applied */ - else if (nvi->hpoint == NEAREST_HANDLE_LEFT) - bezt->f1 |= SELECT; - else - bezt->f3 |= SELECT; - } - } - else if (nvi->fpt) { - // TODO: need to handle sample points - } - } - else { - KeyframeEditFunc select_cb; - KeyframeEditData ked; - - /* initialize keyframe editing data */ - memset(&ked, 0, sizeof(KeyframeEditData)); - - /* set up BezTriple edit callbacks */ - select_cb = ANIM_editkeyframes_select(select_mode); - - /* select all keyframes */ - ANIM_fcurve_keyframes_loop(&ked, nvi->fcu, NULL, select_cb, NULL); - } - - /* only change selection of channel when the visibility of keyframes doesn't depend on this */ - if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) { - /* select or deselect curve? */ - if (bezt) { - /* take selection status from item that got hit, to prevent flip/flop on channel - * selection status when shift-selecting (i.e. "SELECT_INVERT") points - */ - if (BEZT_ISSEL_ANY(bezt)) - nvi->fcu->flag |= FCURVE_SELECTED; - else - nvi->fcu->flag &= ~FCURVE_SELECTED; - } - else { - /* didn't hit any channel, so just apply that selection mode to the curve's selection status */ - if (select_mode == SELECT_INVERT) - nvi->fcu->flag ^= FCURVE_SELECTED; - else if (select_mode == SELECT_ADD) - nvi->fcu->flag |= FCURVE_SELECTED; - } - } - - /* set active F-Curve (NOTE: sync the filter flags with findnearest_fcurve_vert) */ - /* needs to be called with (sipo->flag & SIPO_SELCUVERTSONLY) - * otherwise the active flag won't be set T26452. */ - if (nvi->fcu->flag & FCURVE_SELECTED) { - int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); - ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nvi->fcu, nvi->ctype); - } - - /* free temp sample data for filtering */ - MEM_freeN(nvi); + SpaceGraph *sipo = (SpaceGraph *)ac->sl; + tNearestVertInfo *nvi; + BezTriple *bezt = NULL; + + /* find the beztriple that we're selecting, and the handle that was clicked on */ + nvi = find_nearest_fcurve_vert(ac, mval); + + /* check if anything to select */ + if (nvi == NULL) + return; + + /* deselect all other curves? */ + if (select_mode == SELECT_REPLACE) { + /* reset selection mode */ + select_mode = SELECT_ADD; + + /* deselect all other keyframes (+ F-Curves too) */ + deselect_graph_keys(ac, 0, SELECT_SUBTRACT, true); + + /* deselect other channels too, but only only do this if + * selection of channel when the visibility of keyframes + * doesn't depend on this + */ + if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) + ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); + } + + /* if points can be selected on this F-Curve */ + // TODO: what about those with no keyframes? + if ((curves_only == 0) && ((nvi->fcu->flag & FCURVE_PROTECTED) == 0)) { + /* only if there's keyframe */ + if (nvi->bezt) { + bezt = nvi->bezt; /* used to check bezt seletion is set */ + /* depends on selection mode */ + if (select_mode == SELECT_INVERT) { + /* keyframe - invert select of all */ + if (nvi->hpoint == NEAREST_HANDLE_KEY) { + if (BEZT_ISSEL_ANY(bezt)) { + BEZT_DESEL_ALL(bezt); + } + else { + BEZT_SEL_ALL(bezt); + } + } + + /* handles - toggle selection of relevant handle */ + else if (nvi->hpoint == NEAREST_HANDLE_LEFT) { + /* toggle selection */ + bezt->f1 ^= SELECT; + } + else { + /* toggle selection */ + bezt->f3 ^= SELECT; + } + } + else { + /* if the keyframe was clicked on, select all verts of given beztriple */ + if (nvi->hpoint == NEAREST_HANDLE_KEY) { + BEZT_SEL_ALL(bezt); + } + /* otherwise, select the handle that applied */ + else if (nvi->hpoint == NEAREST_HANDLE_LEFT) + bezt->f1 |= SELECT; + else + bezt->f3 |= SELECT; + } + } + else if (nvi->fpt) { + // TODO: need to handle sample points + } + } + else { + KeyframeEditFunc select_cb; + KeyframeEditData ked; + + /* initialize keyframe editing data */ + memset(&ked, 0, sizeof(KeyframeEditData)); + + /* set up BezTriple edit callbacks */ + select_cb = ANIM_editkeyframes_select(select_mode); + + /* select all keyframes */ + ANIM_fcurve_keyframes_loop(&ked, nvi->fcu, NULL, select_cb, NULL); + } + + /* only change selection of channel when the visibility of keyframes doesn't depend on this */ + if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) { + /* select or deselect curve? */ + if (bezt) { + /* take selection status from item that got hit, to prevent flip/flop on channel + * selection status when shift-selecting (i.e. "SELECT_INVERT") points + */ + if (BEZT_ISSEL_ANY(bezt)) + nvi->fcu->flag |= FCURVE_SELECTED; + else + nvi->fcu->flag &= ~FCURVE_SELECTED; + } + else { + /* didn't hit any channel, so just apply that selection mode to the curve's selection status */ + if (select_mode == SELECT_INVERT) + nvi->fcu->flag ^= FCURVE_SELECTED; + else if (select_mode == SELECT_ADD) + nvi->fcu->flag |= FCURVE_SELECTED; + } + } + + /* set active F-Curve (NOTE: sync the filter flags with findnearest_fcurve_vert) */ + /* needs to be called with (sipo->flag & SIPO_SELCUVERTSONLY) + * otherwise the active flag won't be set T26452. */ + if (nvi->fcu->flag & FCURVE_SELECTED) { + int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); + ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nvi->fcu, nvi->ctype); + } + + /* free temp sample data for filtering */ + MEM_freeN(nvi); } /* Option 2) Selects all the keyframes on either side of the current frame @@ -1424,67 +1472,67 @@ static void mouse_graph_keys(bAnimContext *ac, const int mval[2], short select_m /* Option 3) Selects all visible keyframes in the same frame as the mouse click */ static void graphkeys_mselect_column(bAnimContext *ac, const int mval[2], short select_mode) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - KeyframeEditFunc select_cb, ok_cb; - KeyframeEditData ked; - tNearestVertInfo *nvi; - float selx = (float)ac->scene->r.cfra; - - /* find the beztriple that we're selecting, and the handle that was clicked on */ - nvi = find_nearest_fcurve_vert(ac, mval); - - /* check if anything to select */ - if (nvi == NULL) - return; - - /* get frame number on which elements should be selected */ - // TODO: should we restrict to integer frames only? - selx = nvi->frame; - - /* if select mode is replace, deselect all keyframes first */ - if (select_mode == SELECT_REPLACE) { - /* reset selection mode to add to selection */ - select_mode = SELECT_ADD; - - /* - deselect all other keyframes, so that just the newly selected remain - * - channels aren't deselected, since we don't re-select any as a consequence - */ - deselect_graph_keys(ac, 0, SELECT_SUBTRACT, false); - } - - /* initialize keyframe editing data */ - memset(&ked, 0, sizeof(KeyframeEditData)); - - /* set up BezTriple edit callbacks */ - select_cb = ANIM_editkeyframes_select(select_mode); - ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAME); - - /* loop through all of the keys and select additional keyframes - * based on the keys found to be selected above - */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - for (ale = anim_data.first; ale; ale = ale->next) { - AnimData *adt = ANIM_nla_mapping_get(ac, ale); - - /* set frame for validation callback to refer to */ - if (adt) - ked.f1 = BKE_nla_tweakedit_remap(adt, selx, NLATIME_CONVERT_UNMAP); - else - ked.f1 = selx; - - /* select elements with frame number matching cfra */ - ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); - } - - /* free elements */ - MEM_freeN(nvi); - BLI_freelistN(&ked.list); - ANIM_animdata_freelist(&anim_data); + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + KeyframeEditFunc select_cb, ok_cb; + KeyframeEditData ked; + tNearestVertInfo *nvi; + float selx = (float)ac->scene->r.cfra; + + /* find the beztriple that we're selecting, and the handle that was clicked on */ + nvi = find_nearest_fcurve_vert(ac, mval); + + /* check if anything to select */ + if (nvi == NULL) + return; + + /* get frame number on which elements should be selected */ + // TODO: should we restrict to integer frames only? + selx = nvi->frame; + + /* if select mode is replace, deselect all keyframes first */ + if (select_mode == SELECT_REPLACE) { + /* reset selection mode to add to selection */ + select_mode = SELECT_ADD; + + /* - deselect all other keyframes, so that just the newly selected remain + * - channels aren't deselected, since we don't re-select any as a consequence + */ + deselect_graph_keys(ac, 0, SELECT_SUBTRACT, false); + } + + /* initialize keyframe editing data */ + memset(&ked, 0, sizeof(KeyframeEditData)); + + /* set up BezTriple edit callbacks */ + select_cb = ANIM_editkeyframes_select(select_mode); + ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAME); + + /* loop through all of the keys and select additional keyframes + * based on the keys found to be selected above + */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + for (ale = anim_data.first; ale; ale = ale->next) { + AnimData *adt = ANIM_nla_mapping_get(ac, ale); + + /* set frame for validation callback to refer to */ + if (adt) + ked.f1 = BKE_nla_tweakedit_remap(adt, selx, NLATIME_CONVERT_UNMAP); + else + ked.f1 = selx; + + /* select elements with frame number matching cfra */ + ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); + } + + /* free elements */ + MEM_freeN(nvi); + BLI_freelistN(&ked.list); + ANIM_animdata_freelist(&anim_data); } /* ------------------- */ @@ -1492,69 +1540,80 @@ static void graphkeys_mselect_column(bAnimContext *ac, const int mval[2], short /* handle clicking */ static int graphkeys_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - bAnimContext ac; - short selectmode; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* select mode is either replace (deselect all, then add) or add/extend */ - if (RNA_boolean_get(op->ptr, "extend")) - selectmode = SELECT_INVERT; - else - selectmode = SELECT_REPLACE; - - /* figure out action to take */ - if (RNA_boolean_get(op->ptr, "column")) { - /* select all keyframes in the same frame as the one that was under the mouse */ - graphkeys_mselect_column(&ac, event->mval, selectmode); - } - else if (RNA_boolean_get(op->ptr, "curves")) { - /* select all keyframes in the same F-Curve as the one under the mouse */ - mouse_graph_keys(&ac, event->mval, selectmode, 1); - } - else { - /* select keyframe under mouse */ - mouse_graph_keys(&ac, event->mval, selectmode, 0); - } - - /* set notifier that keyframe selection (and also channel selection in some cases) has changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); - WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL); - - /* for tweak grab to work */ - return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH; + bAnimContext ac; + short selectmode; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* select mode is either replace (deselect all, then add) or add/extend */ + if (RNA_boolean_get(op->ptr, "extend")) + selectmode = SELECT_INVERT; + else + selectmode = SELECT_REPLACE; + + /* figure out action to take */ + if (RNA_boolean_get(op->ptr, "column")) { + /* select all keyframes in the same frame as the one that was under the mouse */ + graphkeys_mselect_column(&ac, event->mval, selectmode); + } + else if (RNA_boolean_get(op->ptr, "curves")) { + /* select all keyframes in the same F-Curve as the one under the mouse */ + mouse_graph_keys(&ac, event->mval, selectmode, 1); + } + else { + /* select keyframe under mouse */ + mouse_graph_keys(&ac, event->mval, selectmode, 0); + } + + /* set notifier that keyframe selection (and also channel selection in some cases) has changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL); + + /* for tweak grab to work */ + return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH; } void GRAPH_OT_clickselect(wmOperatorType *ot) { - PropertyRNA *prop; - - /* identifiers */ - ot->name = "Select Keyframes"; - ot->idname = "GRAPH_OT_clickselect"; - ot->description = "Select keyframes by clicking on them"; - - /* callbacks */ - ot->invoke = graphkeys_clickselect_invoke; - ot->poll = graphop_visible_keyframes_poll; - - /* flags */ - ot->flag = OPTYPE_UNDO; - - /* properties */ - prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", - "Toggle keyframe selection instead of leaving newly selected keyframes only"); // SHIFTKEY - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - - prop = RNA_def_boolean(ot->srna, "column", 0, "Column Select", - "Select all keyframes that occur on the same frame as the one under the mouse"); // ALTKEY - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - - prop = RNA_def_boolean(ot->srna, "curves", 0, "Only Curves", - "Select all the keyframes in the curve"); // CTRLKEY + ALTKEY - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Select Keyframes"; + ot->idname = "GRAPH_OT_clickselect"; + ot->description = "Select keyframes by clicking on them"; + + /* callbacks */ + ot->invoke = graphkeys_clickselect_invoke; + ot->poll = graphop_visible_keyframes_poll; + + /* flags */ + ot->flag = OPTYPE_UNDO; + + /* properties */ + prop = RNA_def_boolean( + ot->srna, + "extend", + 0, + "Extend Select", + "Toggle keyframe selection instead of leaving newly selected keyframes only"); // SHIFTKEY + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_boolean( + ot->srna, + "column", + 0, + "Column Select", + "Select all keyframes that occur on the same frame as the one under the mouse"); // ALTKEY + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_boolean(ot->srna, + "curves", + 0, + "Only Curves", + "Select all the keyframes in the curve"); // CTRLKEY + ALTKEY + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* ************************************************************************** */ diff --git a/source/blender/editors/space_graph/graph_utils.c b/source/blender/editors/space_graph/graph_utils.c index 6bef5072a78..1c3b4f1377b 100644 --- a/source/blender/editors/space_graph/graph_utils.c +++ b/source/blender/editors/space_graph/graph_utils.c @@ -21,7 +21,6 @@ * \ingroup spgraph */ - #include <string.h> #include <stdio.h> #include <math.h> @@ -39,16 +38,13 @@ #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 +#include "graph_intern.h" // own include /* ************************************************************** */ /* Set Up Drivers Editor */ @@ -57,39 +53,39 @@ /* NOTE: Currently called from windowmanager (new drivers editor window) and RNA (mode switching) */ void ED_drivers_editor_init(bContext *C, ScrArea *sa) { - SpaceGraph *sipo = (SpaceGraph *)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; - } + SpaceGraph *sipo = (SpaceGraph *)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; + } } /* ************************************************************** */ @@ -103,25 +99,25 @@ void ED_drivers_editor_init(bContext *C, ScrArea *sa) */ bAnimListElem *get_active_fcurve_channel(bAnimContext *ac) { - ListBase anim_data = {NULL, NULL}; - int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_ACTIVE); - size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + ListBase anim_data = {NULL, NULL}; + int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_ACTIVE); + size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - /* We take the first F-Curve only, since some other ones may have had 'active' flag set - * if they were from linked data. - */ - if (items) { - bAnimListElem *ale = (bAnimListElem *)anim_data.first; + /* We take the first F-Curve only, since some other ones may have had 'active' flag set + * if they were from linked data. + */ + if (items) { + bAnimListElem *ale = (bAnimListElem *)anim_data.first; - /* remove first item from list, then free the rest of the list and return the stored one */ - BLI_remlink(&anim_data, ale); - ANIM_animdata_freelist(&anim_data); + /* remove first item from list, then free the rest of the list and return the stored one */ + BLI_remlink(&anim_data, ale); + ANIM_animdata_freelist(&anim_data); - return ale; - } + return ale; + } - /* no active F-Curve */ - return NULL; + /* no active F-Curve */ + return NULL; } /* ************************************************************** */ @@ -130,171 +126,171 @@ bAnimListElem *get_active_fcurve_channel(bAnimContext *ac) /* Check if there are any visible keyframes (for selection tools) */ bool graphop_visible_keyframes_poll(bContext *C) { - bAnimContext ac; - bAnimListElem *ale; - ListBase anim_data = {NULL, NULL}; - ScrArea *sa = CTX_wm_area(C); - size_t items; - int filter; - short found = 0; - - /* firstly, check if in Graph Editor */ - // TODO: also check for region? - if ((sa == NULL) || (sa->spacetype != SPACE_GRAPH)) - return 0; - - /* try to init Anim-Context stuff ourselves and check */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return 0; - - /* loop over the visible (selection doesn't matter) F-Curves, and see if they're suitable - * stopping on the first successful match - */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE); - items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - if (items == 0) - return 0; - - for (ale = anim_data.first; ale; ale = ale->next) { - FCurve *fcu = (FCurve *)ale->data; - - /* visible curves for selection must fulfill the following criteria: - * - it has bezier keyframes - * - F-Curve modifiers do not interfere with the result too much - * (i.e. the modifier-control drawing check returns false) - */ - if (fcu->bezt == NULL) - continue; - if (fcurve_are_keyframes_usable(fcu)) { - found = 1; - break; - } - } - - /* cleanup and return findings */ - ANIM_animdata_freelist(&anim_data); - return found; + bAnimContext ac; + bAnimListElem *ale; + ListBase anim_data = {NULL, NULL}; + ScrArea *sa = CTX_wm_area(C); + size_t items; + int filter; + short found = 0; + + /* firstly, check if in Graph Editor */ + // TODO: also check for region? + if ((sa == NULL) || (sa->spacetype != SPACE_GRAPH)) + return 0; + + /* try to init Anim-Context stuff ourselves and check */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return 0; + + /* loop over the visible (selection doesn't matter) F-Curves, and see if they're suitable + * stopping on the first successful match + */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE); + items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + if (items == 0) + return 0; + + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu = (FCurve *)ale->data; + + /* visible curves for selection must fulfill the following criteria: + * - it has bezier keyframes + * - F-Curve modifiers do not interfere with the result too much + * (i.e. the modifier-control drawing check returns false) + */ + if (fcu->bezt == NULL) + continue; + if (fcurve_are_keyframes_usable(fcu)) { + found = 1; + break; + } + } + + /* cleanup and return findings */ + ANIM_animdata_freelist(&anim_data); + return found; } /* Check if there are any visible + editable keyframes (for editing tools) */ bool graphop_editable_keyframes_poll(bContext *C) { - bAnimContext ac; - bAnimListElem *ale; - ListBase anim_data = {NULL, NULL}; - ScrArea *sa = CTX_wm_area(C); - size_t items; - int filter; - short found = 0; - - /* firstly, check if in Graph Editor */ - // TODO: also check for region? - if ((sa == NULL) || (sa->spacetype != SPACE_GRAPH)) - return 0; - - /* try to init Anim-Context stuff ourselves and check */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return 0; - - /* loop over the editable F-Curves, and see if they're suitable - * stopping on the first successful match - */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE); - items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - if (items == 0) - return 0; - - for (ale = anim_data.first; ale; ale = ale->next) { - FCurve *fcu = (FCurve *)ale->data; - - /* editable curves must fulfill the following criteria: - * - it has bezier keyframes - * - it must not be protected from editing (this is already checked for with the edit flag - * - F-Curve modifiers do not interfere with the result too much - * (i.e. the modifier-control drawing check returns false) - */ - if (fcu->bezt == NULL) - continue; - if (fcurve_is_keyframable(fcu)) { - found = 1; - break; - } - } - - /* cleanup and return findings */ - ANIM_animdata_freelist(&anim_data); - return found; + bAnimContext ac; + bAnimListElem *ale; + ListBase anim_data = {NULL, NULL}; + ScrArea *sa = CTX_wm_area(C); + size_t items; + int filter; + short found = 0; + + /* firstly, check if in Graph Editor */ + // TODO: also check for region? + if ((sa == NULL) || (sa->spacetype != SPACE_GRAPH)) + return 0; + + /* try to init Anim-Context stuff ourselves and check */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return 0; + + /* loop over the editable F-Curves, and see if they're suitable + * stopping on the first successful match + */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE); + items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + if (items == 0) + return 0; + + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu = (FCurve *)ale->data; + + /* editable curves must fulfill the following criteria: + * - it has bezier keyframes + * - it must not be protected from editing (this is already checked for with the edit flag + * - F-Curve modifiers do not interfere with the result too much + * (i.e. the modifier-control drawing check returns false) + */ + if (fcu->bezt == NULL) + continue; + if (fcurve_is_keyframable(fcu)) { + found = 1; + break; + } + } + + /* cleanup and return findings */ + ANIM_animdata_freelist(&anim_data); + return found; } /* has active F-Curve that's editable */ bool graphop_active_fcurve_poll(bContext *C) { - bAnimContext ac; - bAnimListElem *ale; - ScrArea *sa = CTX_wm_area(C); - bool has_fcurve = 0; - - /* firstly, check if in Graph Editor */ - // TODO: also check for region? - if ((sa == NULL) || (sa->spacetype != SPACE_GRAPH)) - return 0; - - /* try to init Anim-Context stuff ourselves and check */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return 0; - - /* try to get the Active F-Curve */ - ale = get_active_fcurve_channel(&ac); - if (ale == NULL) - return 0; - - /* do we have a suitable F-Curves? - * - For most cases, NLA Control Curves are sufficiently similar to NLA curves to serve this role too. - * Under the hood, they are F-Curves too. The only problems which will arise here are if these need to be - * in an Action too (but drivers would then also be affected!) - */ - has_fcurve = ((ale->data) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)); - if (has_fcurve) { - FCurve *fcu = (FCurve *)ale->data; - has_fcurve = (fcu->flag & FCURVE_VISIBLE) != 0; - } - - /* free temp data... */ - MEM_freeN(ale); - - /* return success */ - return has_fcurve; + bAnimContext ac; + bAnimListElem *ale; + ScrArea *sa = CTX_wm_area(C); + bool has_fcurve = 0; + + /* firstly, check if in Graph Editor */ + // TODO: also check for region? + if ((sa == NULL) || (sa->spacetype != SPACE_GRAPH)) + return 0; + + /* try to init Anim-Context stuff ourselves and check */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return 0; + + /* try to get the Active F-Curve */ + ale = get_active_fcurve_channel(&ac); + if (ale == NULL) + return 0; + + /* do we have a suitable F-Curves? + * - For most cases, NLA Control Curves are sufficiently similar to NLA curves to serve this role too. + * Under the hood, they are F-Curves too. The only problems which will arise here are if these need to be + * in an Action too (but drivers would then also be affected!) + */ + has_fcurve = ((ale->data) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)); + if (has_fcurve) { + FCurve *fcu = (FCurve *)ale->data; + has_fcurve = (fcu->flag & FCURVE_VISIBLE) != 0; + } + + /* free temp data... */ + MEM_freeN(ale); + + /* return success */ + return has_fcurve; } /* has selected F-Curve that's editable */ bool graphop_selected_fcurve_poll(bContext *C) { - bAnimContext ac; - ListBase anim_data = {NULL, NULL}; - ScrArea *sa = CTX_wm_area(C); - size_t items; - int filter; - - /* firstly, check if in Graph Editor */ - // TODO: also check for region? - if ((sa == NULL) || (sa->spacetype != SPACE_GRAPH)) - return 0; - - /* try to init Anim-Context stuff ourselves and check */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return 0; - - /* get the editable + selected F-Curves, and as long as we got some, we can return - * NOTE: curve-visible flag isn't included, otherwise selecting a curve via list to edit is too cumbersome - */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT); - items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - if (items == 0) - return 0; - - /* cleanup and return findings */ - ANIM_animdata_freelist(&anim_data); - return 1; + bAnimContext ac; + ListBase anim_data = {NULL, NULL}; + ScrArea *sa = CTX_wm_area(C); + size_t items; + int filter; + + /* firstly, check if in Graph Editor */ + // TODO: also check for region? + if ((sa == NULL) || (sa->spacetype != SPACE_GRAPH)) + return 0; + + /* try to init Anim-Context stuff ourselves and check */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return 0; + + /* get the editable + selected F-Curves, and as long as we got some, we can return + * NOTE: curve-visible flag isn't included, otherwise selecting a curve via list to edit is too cumbersome + */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT); + items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + if (items == 0) + return 0; + + /* cleanup and return findings */ + ANIM_animdata_freelist(&anim_data); + return 1; } /* ************************************************************** */ diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 9892660c59c..d03431468d8 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -21,7 +21,6 @@ * \ingroup spgraph */ - #include <string.h> #include <stdio.h> @@ -59,848 +58,865 @@ #include "UI_resources.h" #include "UI_view2d.h" -#include "graph_intern.h" // own include +#include "graph_intern.h" // own include /* ******************** manage regions ********************* */ ARegion *graph_has_buttons_region(ScrArea *sa) { - ARegion *ar, *arnew; + ARegion *ar, *arnew; - ar = BKE_area_find_region_type(sa, RGN_TYPE_UI); - if (ar) return ar; + ar = BKE_area_find_region_type(sa, RGN_TYPE_UI); + if (ar) + return ar; - /* add subdiv level; after main */ - ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); + /* add subdiv level; after main */ + ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - /* is error! */ - if (ar == NULL) return NULL; + /* is error! */ + if (ar == NULL) + return NULL; - arnew = MEM_callocN(sizeof(ARegion), "buttons for graph"); + arnew = MEM_callocN(sizeof(ARegion), "buttons for graph"); - BLI_insertlinkafter(&sa->regionbase, ar, arnew); - arnew->regiontype = RGN_TYPE_UI; - arnew->alignment = RGN_ALIGN_RIGHT; + BLI_insertlinkafter(&sa->regionbase, ar, arnew); + arnew->regiontype = RGN_TYPE_UI; + arnew->alignment = RGN_ALIGN_RIGHT; - arnew->flag = RGN_FLAG_HIDDEN; + arnew->flag = RGN_FLAG_HIDDEN; - return arnew; + return arnew; } - /* ******************** default callbacks for ipo space ***************** */ static SpaceLink *graph_new(const ScrArea *UNUSED(sa), const Scene *scene) { - ARegion *ar; - SpaceGraph *sipo; + ARegion *ar; + SpaceGraph *sipo; - /* Graph Editor - general stuff */ - sipo = MEM_callocN(sizeof(SpaceGraph), "init graphedit"); - sipo->spacetype = SPACE_GRAPH; + /* Graph Editor - general stuff */ + sipo = MEM_callocN(sizeof(SpaceGraph), "init graphedit"); + sipo->spacetype = SPACE_GRAPH; - sipo->autosnap = SACTSNAP_FRAME; + sipo->autosnap = SACTSNAP_FRAME; - /* allocate DopeSheet data for Graph Editor */ - sipo->ads = MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet"); - sipo->ads->source = (ID *)scene; + /* allocate DopeSheet data for Graph Editor */ + sipo->ads = MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet"); + sipo->ads->source = (ID *)scene; - /* settings for making it easier by default to just see what you're interested in tweaking */ - sipo->ads->filterflag |= ADS_FILTER_ONLYSEL; - sipo->flag |= SIPO_SELVHANDLESONLY; + /* settings for making it easier by default to just see what you're interested in tweaking */ + sipo->ads->filterflag |= ADS_FILTER_ONLYSEL; + sipo->flag |= SIPO_SELVHANDLESONLY; - /* header */ - ar = MEM_callocN(sizeof(ARegion), "header for graphedit"); + /* header */ + ar = MEM_callocN(sizeof(ARegion), "header for graphedit"); - BLI_addtail(&sipo->regionbase, ar); - ar->regiontype = RGN_TYPE_HEADER; - ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP; + BLI_addtail(&sipo->regionbase, ar); + ar->regiontype = RGN_TYPE_HEADER; + ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP; - /* channels */ - ar = MEM_callocN(sizeof(ARegion), "channels region for graphedit"); + /* channels */ + ar = MEM_callocN(sizeof(ARegion), "channels region for graphedit"); - BLI_addtail(&sipo->regionbase, ar); - ar->regiontype = RGN_TYPE_CHANNELS; - ar->alignment = RGN_ALIGN_LEFT; + BLI_addtail(&sipo->regionbase, ar); + ar->regiontype = RGN_TYPE_CHANNELS; + ar->alignment = RGN_ALIGN_LEFT; - ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM); + ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM); - /* ui buttons */ - ar = MEM_callocN(sizeof(ARegion), "buttons region for graphedit"); + /* ui buttons */ + ar = MEM_callocN(sizeof(ARegion), "buttons region for graphedit"); - BLI_addtail(&sipo->regionbase, ar); - ar->regiontype = RGN_TYPE_UI; - ar->alignment = RGN_ALIGN_RIGHT; - ar->flag = RGN_FLAG_HIDDEN; + BLI_addtail(&sipo->regionbase, ar); + ar->regiontype = RGN_TYPE_UI; + ar->alignment = RGN_ALIGN_RIGHT; + ar->flag = RGN_FLAG_HIDDEN; - /* main region */ - ar = MEM_callocN(sizeof(ARegion), "main region for graphedit"); + /* main region */ + ar = MEM_callocN(sizeof(ARegion), "main region for graphedit"); - BLI_addtail(&sipo->regionbase, ar); - ar->regiontype = RGN_TYPE_WINDOW; + BLI_addtail(&sipo->regionbase, ar); + ar->regiontype = RGN_TYPE_WINDOW; - ar->v2d.tot.xmin = 0.0f; - ar->v2d.tot.ymin = (float)scene->r.sfra - 10.0f; - ar->v2d.tot.xmax = (float)scene->r.efra; - ar->v2d.tot.ymax = 10.0f; + ar->v2d.tot.xmin = 0.0f; + ar->v2d.tot.ymin = (float)scene->r.sfra - 10.0f; + ar->v2d.tot.xmax = (float)scene->r.efra; + ar->v2d.tot.ymax = 10.0f; - ar->v2d.cur = ar->v2d.tot; + ar->v2d.cur = ar->v2d.tot; - ar->v2d.min[0] = FLT_MIN; - ar->v2d.min[1] = FLT_MIN; + ar->v2d.min[0] = FLT_MIN; + ar->v2d.min[1] = FLT_MIN; - ar->v2d.max[0] = MAXFRAMEF; - ar->v2d.max[1] = FLT_MAX; + ar->v2d.max[0] = MAXFRAMEF; + ar->v2d.max[1] = FLT_MAX; - ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL); - ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL); + ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL); + ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL); - ar->v2d.keeptot = 0; + ar->v2d.keeptot = 0; - return (SpaceLink *)sipo; + return (SpaceLink *)sipo; } /* not spacelink itself */ static void graph_free(SpaceLink *sl) { - SpaceGraph *si = (SpaceGraph *)sl; + SpaceGraph *si = (SpaceGraph *)sl; - if (si->ads) { - BLI_freelistN(&si->ads->chanbase); - MEM_freeN(si->ads); - } + if (si->ads) { + BLI_freelistN(&si->ads->chanbase); + MEM_freeN(si->ads); + } - if (si->runtime.ghost_curves.first) { - free_fcurves(&si->runtime.ghost_curves); - } + if (si->runtime.ghost_curves.first) { + free_fcurves(&si->runtime.ghost_curves); + } } - /* spacetype; init callback */ static void graph_init(struct wmWindowManager *wm, ScrArea *sa) { - SpaceGraph *sipo = (SpaceGraph *)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 *)WM_window_get_active_scene(wm->winactive); - } - - /* force immediate init of any invalid F-Curve colors */ - /* XXX: but, don't do SIPO_TEMP_NEEDCHANSYNC (i.e. channel select state sync) - * as this is run on each region resize; setting this here will cause selection - * state to be lost on area/region resizing. [#35744] - */ - ED_area_tag_refresh(sa); + SpaceGraph *sipo = (SpaceGraph *)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 *)WM_window_get_active_scene(wm->winactive); + } + + /* force immediate init of any invalid F-Curve colors */ + /* XXX: but, don't do SIPO_TEMP_NEEDCHANSYNC (i.e. channel select state sync) + * as this is run on each region resize; setting this here will cause selection + * state to be lost on area/region resizing. [#35744] + */ + ED_area_tag_refresh(sa); } static SpaceLink *graph_duplicate(SpaceLink *sl) { - SpaceGraph *sipon = MEM_dupallocN(sl); + SpaceGraph *sipon = MEM_dupallocN(sl); - /* clear or remove stuff from old */ - BLI_duplicatelist(&sipon->runtime.ghost_curves, &((SpaceGraph *)sl)->runtime.ghost_curves); - sipon->ads = MEM_dupallocN(sipon->ads); + /* clear or remove stuff from old */ + BLI_duplicatelist(&sipon->runtime.ghost_curves, &((SpaceGraph *)sl)->runtime.ghost_curves); + sipon->ads = MEM_dupallocN(sipon->ads); - return (SpaceLink *)sipon; + return (SpaceLink *)sipon; } /* add handlers, stuff you only do once or on area/region changes */ static void graph_main_region_init(wmWindowManager *wm, ARegion *ar) { - wmKeyMap *keymap; + wmKeyMap *keymap; - UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy); + UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy); - /* own keymap */ - keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor", SPACE_GRAPH, 0); - WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); - keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor Generic", SPACE_GRAPH, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + /* own keymap */ + keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor", SPACE_GRAPH, 0); + WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); + keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor Generic", SPACE_GRAPH, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); } static void graph_main_region_draw(const bContext *C, ARegion *ar) { - /* draw entirely, view changes should be handled here */ - SpaceGraph *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, cfra_flag = 0; - - /* clear and setup matrix */ - UI_GetThemeColor3fv(TH_BACK, col); - GPU_clear_color(col[0], col[1], col[2], 0.0); - GPU_clear(GPU_COLOR_BIT); - - UI_view2d_view_ortho(v2d); - - /* grid */ - unitx = ((sipo->mode == SIPO_MODE_ANIMATION) && (sipo->flag & SIPO_DRAWTIME)) ? V2D_UNIT_SECONDS : V2D_UNIT_FRAMESCALE; - grid = UI_view2d_grid_calc(CTX_data_scene(C), v2d, unitx, V2D_GRID_NOCLAMP, unity, V2D_GRID_NOCLAMP, ar->winx, ar->winy); - UI_view2d_grid_draw(v2d, grid, V2D_GRIDLINES_ALL); - - 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 */ - graph_draw_ghost_curves(&ac, sipo, ar); - - /* draw curves twice - unselected, then selected, so that the are fewer occlusion problems */ - graph_draw_curves(&ac, sipo, ar, grid, 0); - graph_draw_curves(&ac, sipo, ar, grid, 1); - - /* XXX the slow way to set tot rect... but for nice sliders needed (ton) */ - get_graph_keyframe_extents(&ac, &v2d->tot.xmin, &v2d->tot.xmax, &v2d->tot.ymin, &v2d->tot.ymax, false, true); - /* extra offset so that these items are visible */ - v2d->tot.xmin -= 10.0f; - v2d->tot.xmax += 10.0f; - } - - /* only free grid after drawing data, as we need to use it to determine sampling rate */ - UI_view2d_grid_free(grid); - - if (((sipo->flag & SIPO_NODRAWCURSOR) == 0) || (sipo->mode == SIPO_MODE_DRIVERS)) { - uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - - /* horizontal component of value-cursor (value line before the current frame line) */ - if ((sipo->flag & SIPO_NODRAWCURSOR) == 0) { - float y = sipo->cursorVal; - - /* Draw a green line to indicate the cursor value */ - immUniformThemeColorShadeAlpha(TH_CFRAME, -10, -50); - GPU_blend(true); - GPU_line_width(2.0); - - immBegin(GPU_PRIM_LINES, 2); - immVertex2f(pos, v2d->cur.xmin, y); - immVertex2f(pos, v2d->cur.xmax, y); - immEnd(); - - GPU_blend(false); - } - - /* 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); - GPU_blend(true); - GPU_line_width(2.0); - - immBegin(GPU_PRIM_LINES, 2); - immVertex2f(pos, x, v2d->cur.ymin); - immVertex2f(pos, x, v2d->cur.ymax); - immEnd(); - - GPU_blend(false); - } - - immUnbindProgram(); - } - - if (sipo->mode != SIPO_MODE_DRIVERS) { - /* current frame */ - if (sipo->flag & SIPO_DRAWTIME) cfra_flag |= DRAWCFRA_UNIT_SECONDS; - ANIM_draw_cfra(C, v2d, cfra_flag); - } - - /* markers */ - UI_view2d_view_orthoSpecial(ar, v2d, 1); - int marker_draw_flag = DRAW_MARKERS_MARGIN; - if (sipo->flag & SIPO_MARKER_LINES) { - marker_draw_flag |= DRAW_MARKERS_LINES; - } - ED_markers_draw(C, marker_draw_flag); - - /* preview range */ - UI_view2d_view_ortho(v2d); - ANIM_draw_previewrange(C, v2d, 0); - - /* callback */ - UI_view2d_view_ortho(v2d); - ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); - - /* reset view matrix */ - UI_view2d_view_restore(C); - - /* scrollers */ - // FIXME: args for scrollers depend on the type of data being shown... - scrollers = UI_view2d_scrollers_calc(C, v2d, NULL, 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); - } + /* draw entirely, view changes should be handled here */ + SpaceGraph *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, cfra_flag = 0; + + /* clear and setup matrix */ + UI_GetThemeColor3fv(TH_BACK, col); + GPU_clear_color(col[0], col[1], col[2], 0.0); + GPU_clear(GPU_COLOR_BIT); + + UI_view2d_view_ortho(v2d); + + /* grid */ + unitx = ((sipo->mode == SIPO_MODE_ANIMATION) && (sipo->flag & SIPO_DRAWTIME)) ? + V2D_UNIT_SECONDS : + V2D_UNIT_FRAMESCALE; + grid = UI_view2d_grid_calc(CTX_data_scene(C), + v2d, + unitx, + V2D_GRID_NOCLAMP, + unity, + V2D_GRID_NOCLAMP, + ar->winx, + ar->winy); + UI_view2d_grid_draw(v2d, grid, V2D_GRIDLINES_ALL); + + 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 */ + graph_draw_ghost_curves(&ac, sipo, ar); + + /* draw curves twice - unselected, then selected, so that the are fewer occlusion problems */ + graph_draw_curves(&ac, sipo, ar, grid, 0); + graph_draw_curves(&ac, sipo, ar, grid, 1); + + /* XXX the slow way to set tot rect... but for nice sliders needed (ton) */ + get_graph_keyframe_extents( + &ac, &v2d->tot.xmin, &v2d->tot.xmax, &v2d->tot.ymin, &v2d->tot.ymax, false, true); + /* extra offset so that these items are visible */ + v2d->tot.xmin -= 10.0f; + v2d->tot.xmax += 10.0f; + } + + /* only free grid after drawing data, as we need to use it to determine sampling rate */ + UI_view2d_grid_free(grid); + + if (((sipo->flag & SIPO_NODRAWCURSOR) == 0) || (sipo->mode == SIPO_MODE_DRIVERS)) { + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + /* horizontal component of value-cursor (value line before the current frame line) */ + if ((sipo->flag & SIPO_NODRAWCURSOR) == 0) { + float y = sipo->cursorVal; + + /* Draw a green line to indicate the cursor value */ + immUniformThemeColorShadeAlpha(TH_CFRAME, -10, -50); + GPU_blend(true); + GPU_line_width(2.0); + + immBegin(GPU_PRIM_LINES, 2); + immVertex2f(pos, v2d->cur.xmin, y); + immVertex2f(pos, v2d->cur.xmax, y); + immEnd(); + + GPU_blend(false); + } + + /* 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); + GPU_blend(true); + GPU_line_width(2.0); + + immBegin(GPU_PRIM_LINES, 2); + immVertex2f(pos, x, v2d->cur.ymin); + immVertex2f(pos, x, v2d->cur.ymax); + immEnd(); + + GPU_blend(false); + } + + immUnbindProgram(); + } + + if (sipo->mode != SIPO_MODE_DRIVERS) { + /* current frame */ + if (sipo->flag & SIPO_DRAWTIME) + cfra_flag |= DRAWCFRA_UNIT_SECONDS; + ANIM_draw_cfra(C, v2d, cfra_flag); + } + + /* markers */ + UI_view2d_view_orthoSpecial(ar, v2d, 1); + int marker_draw_flag = DRAW_MARKERS_MARGIN; + if (sipo->flag & SIPO_MARKER_LINES) { + marker_draw_flag |= DRAW_MARKERS_LINES; + } + ED_markers_draw(C, marker_draw_flag); + + /* preview range */ + UI_view2d_view_ortho(v2d); + ANIM_draw_previewrange(C, v2d, 0); + + /* callback */ + UI_view2d_view_ortho(v2d); + ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); + + /* reset view matrix */ + UI_view2d_view_restore(C); + + /* scrollers */ + // FIXME: args for scrollers depend on the type of data being shown... + scrollers = UI_view2d_scrollers_calc( + C, v2d, NULL, 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) { - wmKeyMap *keymap; + wmKeyMap *keymap; - /* make sure we keep the hide flags */ - ar->v2d.scroll |= V2D_SCROLL_RIGHT; + /* make sure we keep the hide flags */ + ar->v2d.scroll |= V2D_SCROLL_RIGHT; - /* prevent any noise of past */ - ar->v2d.scroll &= ~(V2D_SCROLL_LEFT | V2D_SCROLL_TOP | V2D_SCROLL_BOTTOM); + /* prevent any noise of past */ + ar->v2d.scroll &= ~(V2D_SCROLL_LEFT | V2D_SCROLL_TOP | V2D_SCROLL_BOTTOM); - ar->v2d.scroll |= V2D_SCROLL_HORIZONTAL_HIDE; - ar->v2d.scroll |= V2D_SCROLL_VERTICAL_HIDE; + ar->v2d.scroll |= V2D_SCROLL_HORIZONTAL_HIDE; + ar->v2d.scroll |= V2D_SCROLL_VERTICAL_HIDE; - UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy); + UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy); - /* own keymap */ - keymap = WM_keymap_ensure(wm->defaultconf, "Animation Channels", 0, 0); - WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); - keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor Generic", SPACE_GRAPH, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + /* own keymap */ + keymap = WM_keymap_ensure(wm->defaultconf, "Animation Channels", 0, 0); + WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); + keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor Generic", SPACE_GRAPH, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); } static void graph_channel_region_draw(const bContext *C, ARegion *ar) { - bAnimContext ac; - View2D *v2d = &ar->v2d; - View2DScrollers *scrollers; - float col[3]; - - /* clear and setup matrix */ - UI_GetThemeColor3fv(TH_BACK, col); - GPU_clear_color(col[0], col[1], col[2], 0.0); - GPU_clear(GPU_COLOR_BIT); - - UI_view2d_view_ortho(v2d); - - /* draw channels */ - if (ANIM_animdata_get_context(C, &ac)) { - graph_draw_channel_names((bContext *)C, &ac, ar); - } - - /* reset view matrix */ - UI_view2d_view_restore(C); - - /* scrollers */ - scrollers = UI_view2d_scrollers_calc(C, v2d, NULL, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY); - UI_view2d_scrollers_draw(C, v2d, scrollers); - UI_view2d_scrollers_free(scrollers); + bAnimContext ac; + View2D *v2d = &ar->v2d; + View2DScrollers *scrollers; + float col[3]; + + /* clear and setup matrix */ + UI_GetThemeColor3fv(TH_BACK, col); + GPU_clear_color(col[0], col[1], col[2], 0.0); + GPU_clear(GPU_COLOR_BIT); + + UI_view2d_view_ortho(v2d); + + /* draw channels */ + if (ANIM_animdata_get_context(C, &ac)) { + graph_draw_channel_names((bContext *)C, &ac, ar); + } + + /* reset view matrix */ + UI_view2d_view_restore(C); + + /* scrollers */ + scrollers = UI_view2d_scrollers_calc( + C, v2d, NULL, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY); + UI_view2d_scrollers_draw(C, v2d, scrollers); + UI_view2d_scrollers_free(scrollers); } /* add handlers, stuff you only do once or on area/region changes */ static void graph_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar) { - ED_region_header_init(ar); + ED_region_header_init(ar); } static void graph_header_region_draw(const bContext *C, ARegion *ar) { - ED_region_header(C, ar); + ED_region_header(C, ar); } /* add handlers, stuff you only do once or on area/region changes */ static void graph_buttons_region_init(wmWindowManager *wm, ARegion *ar) { - wmKeyMap *keymap; + wmKeyMap *keymap; - ED_region_panels_init(wm, ar); + ED_region_panels_init(wm, ar); - keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor Generic", SPACE_GRAPH, 0); - WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); + keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor Generic", SPACE_GRAPH, 0); + WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } static void graph_buttons_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar); + ED_region_panels(C, ar); } -static void graph_region_listener( - wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar, - wmNotifier *wmn, const Scene *UNUSED(scene)) +static void graph_region_listener(wmWindow *UNUSED(win), + ScrArea *UNUSED(sa), + ARegion *ar, + wmNotifier *wmn, + const Scene *UNUSED(scene)) { - /* context changes */ - switch (wmn->category) { - case NC_ANIMATION: - ED_region_tag_redraw(ar); - break; - case NC_SCENE: - switch (wmn->data) { - case ND_RENDER_OPTIONS: - case ND_OB_ACTIVE: - case ND_FRAME: - case ND_FRAME_RANGE: - case ND_MARKERS: - ED_region_tag_redraw(ar); - break; - case ND_SEQUENCER: - if (wmn->action == NA_SELECTED) - ED_region_tag_redraw(ar); - break; - } - break; - case NC_OBJECT: - switch (wmn->data) { - case ND_BONE_ACTIVE: - case ND_BONE_SELECT: - case ND_KEYS: - ED_region_tag_redraw(ar); - break; - case ND_MODIFIER: - if (wmn->action == NA_RENAME) - ED_region_tag_redraw(ar); - break; - } - break; - case NC_NODE: - switch (wmn->action) { - case NA_EDITED: - case NA_SELECTED: - ED_region_tag_redraw(ar); - break; - } - break; - case NC_ID: - 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); - break; - - } + /* context changes */ + switch (wmn->category) { + case NC_ANIMATION: + ED_region_tag_redraw(ar); + break; + case NC_SCENE: + switch (wmn->data) { + case ND_RENDER_OPTIONS: + case ND_OB_ACTIVE: + case ND_FRAME: + case ND_FRAME_RANGE: + case ND_MARKERS: + ED_region_tag_redraw(ar); + break; + case ND_SEQUENCER: + if (wmn->action == NA_SELECTED) + ED_region_tag_redraw(ar); + break; + } + break; + case NC_OBJECT: + switch (wmn->data) { + case ND_BONE_ACTIVE: + case ND_BONE_SELECT: + case ND_KEYS: + ED_region_tag_redraw(ar); + break; + case ND_MODIFIER: + if (wmn->action == NA_RENAME) + ED_region_tag_redraw(ar); + break; + } + break; + case NC_NODE: + switch (wmn->action) { + case NA_EDITED: + case NA_SELECTED: + ED_region_tag_redraw(ar); + break; + } + break; + case NC_ID: + 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); + break; + } } -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) +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__); - } - } + 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(wmWindow *UNUSED(win), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene)) +static void graph_listener(wmWindow *UNUSED(win), + ScrArea *sa, + wmNotifier *wmn, + Scene *UNUSED(scene)) { - SpaceGraph *sipo = (SpaceGraph *)sa->spacedata.first; - - /* context changes */ - switch (wmn->category) { - case NC_ANIMATION: - /* for selection changes of animation data, we can just redraw... - * otherwise autocolor might need to be done again */ - if (ELEM(wmn->data, ND_KEYFRAME, ND_ANIMCHAN) && (wmn->action == NA_SELECTED)) - ED_area_tag_redraw(sa); - else - ED_area_tag_refresh(sa); - break; - case NC_SCENE: - switch (wmn->data) { - case ND_OB_ACTIVE: /* selection changed, so force refresh to flush - * (needs flag set to do syncing) */ - case ND_OB_SELECT: - sipo->runtime.flag |= SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC; - ED_area_tag_refresh(sa); - break; - - default: /* just redrawing the view will do */ - ED_area_tag_redraw(sa); - break; - } - break; - case NC_OBJECT: - switch (wmn->data) { - case ND_BONE_SELECT: /* selection changed, so force refresh to flush - * (needs flag set to do syncing) */ - case ND_BONE_ACTIVE: - sipo->runtime.flag |= SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC; - ED_area_tag_refresh(sa); - break; - case ND_TRANSFORM: - break; /*do nothing*/ - - default: /* just redrawing the view will do */ - ED_area_tag_redraw(sa); - break; - } - break; - case NC_NODE: - if (wmn->action == NA_SELECTED) { - /* selection changed, so force refresh to flush (needs flag set to do syncing) */ - sipo->runtime.flag |= SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC; - ED_area_tag_refresh(sa); - } - break; - case NC_SPACE: - if (wmn->data == ND_SPACE_GRAPH) - ED_area_tag_redraw(sa); - break; - case NC_WINDOW: - if (sipo->runtime.flag & (SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC | SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR)) { - /* force redraw/refresh after undo/redo - prevents "black curve" problem */ - ED_area_tag_refresh(sa); - } - break; - - // XXX: restore the case below if not enough updates occur... - //default: - // if (wmn->data == ND_KEYS) - // ED_area_tag_redraw(sa); - } + SpaceGraph *sipo = (SpaceGraph *)sa->spacedata.first; + + /* context changes */ + switch (wmn->category) { + case NC_ANIMATION: + /* for selection changes of animation data, we can just redraw... + * otherwise autocolor might need to be done again */ + if (ELEM(wmn->data, ND_KEYFRAME, ND_ANIMCHAN) && (wmn->action == NA_SELECTED)) + ED_area_tag_redraw(sa); + else + ED_area_tag_refresh(sa); + break; + case NC_SCENE: + switch (wmn->data) { + case ND_OB_ACTIVE: /* selection changed, so force refresh to flush + * (needs flag set to do syncing) */ + case ND_OB_SELECT: + sipo->runtime.flag |= SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC; + ED_area_tag_refresh(sa); + break; + + default: /* just redrawing the view will do */ + ED_area_tag_redraw(sa); + break; + } + break; + case NC_OBJECT: + switch (wmn->data) { + case ND_BONE_SELECT: /* selection changed, so force refresh to flush + * (needs flag set to do syncing) */ + case ND_BONE_ACTIVE: + sipo->runtime.flag |= SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC; + ED_area_tag_refresh(sa); + break; + case ND_TRANSFORM: + break; /*do nothing*/ + + default: /* just redrawing the view will do */ + ED_area_tag_redraw(sa); + break; + } + break; + case NC_NODE: + if (wmn->action == NA_SELECTED) { + /* selection changed, so force refresh to flush (needs flag set to do syncing) */ + sipo->runtime.flag |= SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC; + ED_area_tag_refresh(sa); + } + break; + case NC_SPACE: + if (wmn->data == ND_SPACE_GRAPH) + ED_area_tag_redraw(sa); + break; + case NC_WINDOW: + if (sipo->runtime.flag & + (SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC | SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR)) { + /* force redraw/refresh after undo/redo - prevents "black curve" problem */ + ED_area_tag_refresh(sa); + } + break; + + // XXX: restore the case below if not enough updates occur... + //default: + // if (wmn->data == ND_KEYS) + // ED_area_tag_redraw(sa); + } } /* Update F-Curve colors */ static void graph_refresh_fcurve_colors(const bContext *C) { - bAnimContext ac; - - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - size_t items; - int filter; - int i; - - if (ANIM_animdata_get_context(C, &ac) == false) - return; - - UI_SetTheme(SPACE_GRAPH, RGN_TYPE_WINDOW); - - /* build list of F-Curves which will be visible as channels in channel-region - * - we don't include ANIMFILTER_CURVEVISIBLE filter, as that will result in a - * mismatch between channel-colors and the drawn curves - */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS); - items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - /* loop over F-Curves, assigning colors */ - for (ale = anim_data.first, i = 0; ale; ale = ale->next, i++) { - FCurve *fcu = (FCurve *)ale->data; - - /* set color of curve here */ - switch (fcu->color_mode) { - case FCURVE_COLOR_CUSTOM: - { - /* User has defined a custom color for this curve already (we assume it's not going to cause clashes with text colors), - * which should be left alone... Nothing needs to be done here. - */ - break; - } - case FCURVE_COLOR_AUTO_RGB: - { - /* F-Curve's array index is automatically mapped to RGB values. This works best of 3-value vectors. - * TODO: find a way to module the hue so that not all curves have same color... - */ - float *col = fcu->color; - - switch (fcu->array_index) { - case 0: - UI_GetThemeColor3fv(TH_AXIS_X, col); - break; - case 1: - UI_GetThemeColor3fv(TH_AXIS_Y, col); - break; - case 2: - UI_GetThemeColor3fv(TH_AXIS_Z, col); - break; - default: - /* 'unknown' color - bluish so as to not conflict with handles */ - col[0] = 0.3f; col[1] = 0.8f; col[2] = 1.0f; - break; - } - break; - } - case FCURVE_COLOR_AUTO_YRGB: - { - /* Like FCURVE_COLOR_AUTO_RGB, except this is for quaternions... */ - float *col = fcu->color; - - switch (fcu->array_index) { - case 1: - UI_GetThemeColor3fv(TH_AXIS_X, col); - break; - case 2: - UI_GetThemeColor3fv(TH_AXIS_Y, col); - break; - case 3: - UI_GetThemeColor3fv(TH_AXIS_Z, col); - break; - - case 0: - { - /* Special Case: "W" channel should be yellowish, so blend X and Y channel colors... */ - float c1[3], c2[3]; - float h1[3], h2[3]; - float hresult[3]; - - /* - get colors (rgb) */ - UI_GetThemeColor3fv(TH_AXIS_X, c1); - UI_GetThemeColor3fv(TH_AXIS_Y, c2); - - /* - perform blending in HSV space (to keep brightness similar) */ - rgb_to_hsv_v(c1, h1); - rgb_to_hsv_v(c2, h2); - - interp_v3_v3v3(hresult, h1, h2, 0.5f); - - /* - convert back to RGB for display */ - hsv_to_rgb_v(hresult, col); - break; - } - - default: - /* 'unknown' color - bluish so as to not conflict with handles */ - col[0] = 0.3f; col[1] = 0.8f; col[2] = 1.0f; - break; - } - break; - } - case FCURVE_COLOR_AUTO_RAINBOW: - default: - { - /* determine color 'automatically' using 'magic function' which uses the given args - * of current item index + total items to determine some RGB color - */ - getcolor_fcurve_rainbow(i, items, fcu->color); - break; - } - } - } - - /* free temp list */ - ANIM_animdata_freelist(&anim_data); + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + size_t items; + int filter; + int i; + + if (ANIM_animdata_get_context(C, &ac) == false) + return; + + UI_SetTheme(SPACE_GRAPH, RGN_TYPE_WINDOW); + + /* build list of F-Curves which will be visible as channels in channel-region + * - we don't include ANIMFILTER_CURVEVISIBLE filter, as that will result in a + * mismatch between channel-colors and the drawn curves + */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS); + items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* loop over F-Curves, assigning colors */ + for (ale = anim_data.first, i = 0; ale; ale = ale->next, i++) { + FCurve *fcu = (FCurve *)ale->data; + + /* set color of curve here */ + switch (fcu->color_mode) { + case FCURVE_COLOR_CUSTOM: { + /* User has defined a custom color for this curve already (we assume it's not going to cause clashes with text colors), + * which should be left alone... Nothing needs to be done here. + */ + break; + } + case FCURVE_COLOR_AUTO_RGB: { + /* F-Curve's array index is automatically mapped to RGB values. This works best of 3-value vectors. + * TODO: find a way to module the hue so that not all curves have same color... + */ + float *col = fcu->color; + + switch (fcu->array_index) { + case 0: + UI_GetThemeColor3fv(TH_AXIS_X, col); + break; + case 1: + UI_GetThemeColor3fv(TH_AXIS_Y, col); + break; + case 2: + UI_GetThemeColor3fv(TH_AXIS_Z, col); + break; + default: + /* 'unknown' color - bluish so as to not conflict with handles */ + col[0] = 0.3f; + col[1] = 0.8f; + col[2] = 1.0f; + break; + } + break; + } + case FCURVE_COLOR_AUTO_YRGB: { + /* Like FCURVE_COLOR_AUTO_RGB, except this is for quaternions... */ + float *col = fcu->color; + + switch (fcu->array_index) { + case 1: + UI_GetThemeColor3fv(TH_AXIS_X, col); + break; + case 2: + UI_GetThemeColor3fv(TH_AXIS_Y, col); + break; + case 3: + UI_GetThemeColor3fv(TH_AXIS_Z, col); + break; + + case 0: { + /* Special Case: "W" channel should be yellowish, so blend X and Y channel colors... */ + float c1[3], c2[3]; + float h1[3], h2[3]; + float hresult[3]; + + /* - get colors (rgb) */ + UI_GetThemeColor3fv(TH_AXIS_X, c1); + UI_GetThemeColor3fv(TH_AXIS_Y, c2); + + /* - perform blending in HSV space (to keep brightness similar) */ + rgb_to_hsv_v(c1, h1); + rgb_to_hsv_v(c2, h2); + + interp_v3_v3v3(hresult, h1, h2, 0.5f); + + /* - convert back to RGB for display */ + hsv_to_rgb_v(hresult, col); + break; + } + + default: + /* 'unknown' color - bluish so as to not conflict with handles */ + col[0] = 0.3f; + col[1] = 0.8f; + col[2] = 1.0f; + break; + } + break; + } + case FCURVE_COLOR_AUTO_RAINBOW: + default: { + /* determine color 'automatically' using 'magic function' which uses the given args + * of current item index + total items to determine some RGB color + */ + getcolor_fcurve_rainbow(i, items, fcu->color); + break; + } + } + } + + /* free temp list */ + ANIM_animdata_freelist(&anim_data); } static void graph_refresh(const bContext *C, ScrArea *sa) { - SpaceGraph *sipo = (SpaceGraph *)sa->spacedata.first; - - /* updates to data needed depends on Graph Editor mode... */ - switch (sipo->mode) { - case SIPO_MODE_ANIMATION: /* all animation */ - { - break; - } - - case SIPO_MODE_DRIVERS: /* drivers only */ - { - break; - } - } - - /* region updates? */ - // XXX re-sizing y-extents of tot should go here? - - /* update the state of the animchannels in response to changes from the data they represent - * NOTE: the temp flag is used to indicate when this needs to be done, and will be cleared once handled - */ - if (sipo->runtime.flag & SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC) { - ANIM_sync_animchannels_to_data(C); - sipo->runtime.flag &= ~SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC; - ED_area_tag_redraw(sa); - } - - /* We could check 'SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR', but color is recalculated anyway. */ - if (sipo->runtime.flag & SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR) { - sipo->runtime.flag &= ~SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR; -#if 0 /* Done below. */ - graph_refresh_fcurve_colors(C); + SpaceGraph *sipo = (SpaceGraph *)sa->spacedata.first; + + /* updates to data needed depends on Graph Editor mode... */ + switch (sipo->mode) { + case SIPO_MODE_ANIMATION: /* all animation */ + { + break; + } + + case SIPO_MODE_DRIVERS: /* drivers only */ + { + break; + } + } + + /* region updates? */ + // XXX re-sizing y-extents of tot should go here? + + /* update the state of the animchannels in response to changes from the data they represent + * NOTE: the temp flag is used to indicate when this needs to be done, and will be cleared once handled + */ + if (sipo->runtime.flag & SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC) { + ANIM_sync_animchannels_to_data(C); + sipo->runtime.flag &= ~SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC; + ED_area_tag_redraw(sa); + } + + /* We could check 'SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR', but color is recalculated anyway. */ + if (sipo->runtime.flag & SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR) { + sipo->runtime.flag &= ~SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR; +#if 0 /* Done below. */ + graph_refresh_fcurve_colors(C); #endif - ED_area_tag_redraw(sa); - } + ED_area_tag_redraw(sa); + } - /* init/adjust F-Curve colors */ - graph_refresh_fcurve_colors(C); + /* init/adjust F-Curve colors */ + graph_refresh_fcurve_colors(C); } static void graph_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id) { - SpaceGraph *sgraph = (SpaceGraph *)slink; - - if (sgraph->ads) { - if ((ID *)sgraph->ads->filter_grp == old_id) { - sgraph->ads->filter_grp = (Collection *)new_id; - } - if ((ID *)sgraph->ads->source == old_id) { - sgraph->ads->source = new_id; - } - } + SpaceGraph *sgraph = (SpaceGraph *)slink; + + if (sgraph->ads) { + if ((ID *)sgraph->ads->filter_grp == old_id) { + sgraph->ads->filter_grp = (Collection *)new_id; + } + if ((ID *)sgraph->ads->source == old_id) { + sgraph->ads->source = new_id; + } + } } static int graph_space_subtype_get(ScrArea *sa) { - SpaceGraph *sgraph = sa->spacedata.first; - return sgraph->mode; + SpaceGraph *sgraph = sa->spacedata.first; + return sgraph->mode; } static void graph_space_subtype_set(ScrArea *sa, int value) { - SpaceGraph *sgraph = sa->spacedata.first; - sgraph->mode = value; + SpaceGraph *sgraph = sa->spacedata.first; + sgraph->mode = value; } -static void graph_space_subtype_item_extend( - bContext *UNUSED(C), EnumPropertyItem **item, int *totitem) +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); + RNA_enum_items_add(item, totitem, rna_enum_space_graph_mode_items); } /* only called once, from space/spacetypes.c */ void ED_spacetype_ipo(void) { - SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype ipo"); - ARegionType *art; - - st->spaceid = SPACE_GRAPH; - strncpy(st->name, "Graph", BKE_ST_MAXNAME); - - st->new = graph_new; - st->free = graph_free; - st->init = graph_init; - st->duplicate = graph_duplicate; - st->operatortypes = graphedit_operatortypes; - st->keymap = graphedit_keymap; - 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"); - art->regionid = RGN_TYPE_WINDOW; - 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); - - /* regions: header */ - art = MEM_callocN(sizeof(ARegionType), "spacetype graphedit region"); - art->regionid = RGN_TYPE_HEADER; - art->prefsizey = HEADERY; - art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER; - art->listener = graph_region_listener; - art->init = graph_header_region_init; - art->draw = graph_header_region_draw; - - BLI_addhead(&st->regiontypes, art); - - /* regions: channels */ - art = MEM_callocN(sizeof(ARegionType), "spacetype graphedit region"); - art->regionid = RGN_TYPE_CHANNELS; - /* 200 is the 'standard', but due to scrollers, we want a bit more to fit the lock icons in */ - art->prefsizex = 200 + V2D_SCROLL_WIDTH; - 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; - - BLI_addhead(&st->regiontypes, art); - - /* regions: UI buttons */ - art = MEM_callocN(sizeof(ARegionType), "spacetype graphedit region"); - art->regionid = RGN_TYPE_UI; - art->prefsizex = 200; - art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES; - art->listener = graph_region_listener; - art->init = graph_buttons_region_init; - art->draw = graph_buttons_region_draw; - - BLI_addhead(&st->regiontypes, art); - - graph_buttons_register(art); - - BKE_spacetype_register(st); + SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype ipo"); + ARegionType *art; + + st->spaceid = SPACE_GRAPH; + strncpy(st->name, "Graph", BKE_ST_MAXNAME); + + st->new = graph_new; + st->free = graph_free; + st->init = graph_init; + st->duplicate = graph_duplicate; + st->operatortypes = graphedit_operatortypes; + st->keymap = graphedit_keymap; + 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"); + art->regionid = RGN_TYPE_WINDOW; + 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); + + /* regions: header */ + art = MEM_callocN(sizeof(ARegionType), "spacetype graphedit region"); + art->regionid = RGN_TYPE_HEADER; + art->prefsizey = HEADERY; + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER; + art->listener = graph_region_listener; + art->init = graph_header_region_init; + art->draw = graph_header_region_draw; + + BLI_addhead(&st->regiontypes, art); + + /* regions: channels */ + art = MEM_callocN(sizeof(ARegionType), "spacetype graphedit region"); + art->regionid = RGN_TYPE_CHANNELS; + /* 200 is the 'standard', but due to scrollers, we want a bit more to fit the lock icons in */ + art->prefsizex = 200 + V2D_SCROLL_WIDTH; + 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; + + BLI_addhead(&st->regiontypes, art); + + /* regions: UI buttons */ + art = MEM_callocN(sizeof(ARegionType), "spacetype graphedit region"); + art->regionid = RGN_TYPE_UI; + art->prefsizex = 200; + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES; + art->listener = graph_region_listener; + art->init = graph_buttons_region_init; + art->draw = graph_buttons_region_draw; + + BLI_addhead(&st->regiontypes, art); + + graph_buttons_register(art); + + BKE_spacetype_register(st); } |