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_nla | |
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_nla')
-rw-r--r-- | source/blender/editors/space_nla/CMakeLists.txt | 48 | ||||
-rw-r--r-- | source/blender/editors/space_nla/nla_buttons.c | 855 | ||||
-rw-r--r-- | source/blender/editors/space_nla/nla_channels.c | 1343 | ||||
-rw-r--r-- | source/blender/editors/space_nla/nla_draw.c | 1494 | ||||
-rw-r--r-- | source/blender/editors/space_nla/nla_edit.c | 3996 | ||||
-rw-r--r-- | source/blender/editors/space_nla/nla_intern.h | 22 | ||||
-rw-r--r-- | source/blender/editors/space_nla/nla_ops.c | 189 | ||||
-rw-r--r-- | source/blender/editors/space_nla/nla_select.c | 984 | ||||
-rw-r--r-- | source/blender/editors/space_nla/space_nla.c | 985 |
9 files changed, 5024 insertions, 4892 deletions
diff --git a/source/blender/editors/space_nla/CMakeLists.txt b/source/blender/editors/space_nla/CMakeLists.txt index f22cc378a60..3048c64c49e 100644 --- a/source/blender/editors/space_nla/CMakeLists.txt +++ b/source/blender/editors/space_nla/CMakeLists.txt @@ -16,42 +16,42 @@ # ***** 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 - nla_buttons.c - nla_channels.c - nla_draw.c - nla_edit.c - nla_ops.c - nla_select.c - space_nla.c - - nla_intern.h + nla_buttons.c + nla_channels.c + nla_draw.c + nla_edit.c + nla_ops.c + nla_select.c + space_nla.c + + nla_intern.h ) set(LIB - bf_blenkernel - bf_blenlib + bf_blenkernel + bf_blenlib ) if(WITH_INTERNATIONAL) - add_definitions(-DWITH_INTERNATIONAL) + add_definitions(-DWITH_INTERNATIONAL) endif() add_definitions(${GL_DEFINITIONS}) diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index b06b7120faf..b19dc3680bf 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -21,7 +21,6 @@ * \ingroup spnla */ - #include <string.h> #include <stdio.h> #include <math.h> @@ -41,7 +40,6 @@ #include "BKE_context.h" #include "BKE_screen.h" - #include "WM_api.h" #include "WM_types.h" @@ -53,8 +51,7 @@ #include "UI_interface.h" #include "UI_resources.h" -#include "nla_intern.h" // own include - +#include "nla_intern.h" // own include /* ******************* nla editor space & buttons ************** */ @@ -62,177 +59,180 @@ static void do_nla_region_buttons(bContext *C, void *UNUSED(arg), int UNUSED(event)) { - //Scene *scene = CTX_data_scene(C); + //Scene *scene = CTX_data_scene(C); #if 0 - switch (event) { - /* pass */ - } + switch (event) { + /* pass */ + } #endif - /* default for now */ - WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); - WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM, NULL); + /* default for now */ + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); + WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM, NULL); } -bool nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA *nlt_ptr, PointerRNA *strip_ptr) +bool nla_panel_context(const bContext *C, + PointerRNA *adt_ptr, + PointerRNA *nlt_ptr, + PointerRNA *strip_ptr) { - bAnimContext ac; - bAnimListElem *ale = NULL; - ListBase anim_data = {NULL, NULL}; - short found = 0; /* not bool, since we need to indicate "found but not ideal" status */ - int filter; - - /* 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 false; - - /* extract list of active channel(s), of which we should only take the first one - * - we need the channels flag to get the active AnimData block when there are no NLA Tracks - */ - // XXX: double-check active! - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_LIST_CHANNELS); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - for (ale = anim_data.first; ale; ale = ale->next) { - switch (ale->type) { - case ANIMTYPE_NLATRACK: /* NLA Track - The primary data type which should get caught */ - { - NlaTrack *nlt = (NlaTrack *)ale->data; - AnimData *adt = ale->adt; - - /* found it, now set the pointers */ - if (adt_ptr) { - /* AnimData pointer */ - RNA_pointer_create(ale->id, &RNA_AnimData, adt, adt_ptr); - } - if (nlt_ptr) { - /* NLA-Track pointer */ - RNA_pointer_create(ale->id, &RNA_NlaTrack, nlt, nlt_ptr); - } - if (strip_ptr) { - /* NLA-Strip pointer */ - NlaStrip *strip = BKE_nlastrip_find_active(nlt); - RNA_pointer_create(ale->id, &RNA_NlaStrip, strip, strip_ptr); - } - - found = 1; - break; - } - case ANIMTYPE_SCENE: /* Top-Level Widgets doubling up as datablocks */ - case ANIMTYPE_OBJECT: - case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ - case ANIMTYPE_DSLAM: - case ANIMTYPE_DSCAM: - case ANIMTYPE_DSCACHEFILE: - case ANIMTYPE_DSCUR: - case ANIMTYPE_DSSKEY: - case ANIMTYPE_DSWOR: - case ANIMTYPE_DSNTREE: - case ANIMTYPE_DSPART: - case ANIMTYPE_DSMBALL: - case ANIMTYPE_DSARM: - case ANIMTYPE_DSMESH: - case ANIMTYPE_DSTEX: - case ANIMTYPE_DSLAT: - case ANIMTYPE_DSLINESTYLE: - case ANIMTYPE_DSSPK: - case ANIMTYPE_DSGPENCIL: - case ANIMTYPE_PALETTE: - { - /* for these channels, we only do AnimData */ - if (ale->adt && adt_ptr) { - ID *id; - - if ((ale->data == NULL) || (ale->type == ANIMTYPE_OBJECT)) { - /* ale->data is not an ID block! */ - id = ale->id; - } - else { - /* ale->data is always the proper ID block we need, - * but ale->id may not be (i.e. for textures) */ - id = (ID *)ale->data; - } - - /* AnimData pointer */ - if (adt_ptr) { - RNA_pointer_create(id, &RNA_AnimData, ale->adt, adt_ptr); - } - - /* set found status to -1, since setting to 1 would break the loop - * and potentially skip an active NLA-Track in some cases... - */ - found = -1; - } - break; - } - } - - if (found > 0) - break; - } - - /* free temp data */ - ANIM_animdata_freelist(&anim_data); - - return (found != 0); + bAnimContext ac; + bAnimListElem *ale = NULL; + ListBase anim_data = {NULL, NULL}; + short found = 0; /* not bool, since we need to indicate "found but not ideal" status */ + int filter; + + /* 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 false; + + /* extract list of active channel(s), of which we should only take the first one + * - we need the channels flag to get the active AnimData block when there are no NLA Tracks + */ + // XXX: double-check active! + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ACTIVE | + ANIMFILTER_LIST_CHANNELS); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + for (ale = anim_data.first; ale; ale = ale->next) { + switch (ale->type) { + case ANIMTYPE_NLATRACK: /* NLA Track - The primary data type which should get caught */ + { + NlaTrack *nlt = (NlaTrack *)ale->data; + AnimData *adt = ale->adt; + + /* found it, now set the pointers */ + if (adt_ptr) { + /* AnimData pointer */ + RNA_pointer_create(ale->id, &RNA_AnimData, adt, adt_ptr); + } + if (nlt_ptr) { + /* NLA-Track pointer */ + RNA_pointer_create(ale->id, &RNA_NlaTrack, nlt, nlt_ptr); + } + if (strip_ptr) { + /* NLA-Strip pointer */ + NlaStrip *strip = BKE_nlastrip_find_active(nlt); + RNA_pointer_create(ale->id, &RNA_NlaStrip, strip, strip_ptr); + } + + found = 1; + break; + } + case ANIMTYPE_SCENE: /* Top-Level Widgets doubling up as datablocks */ + case ANIMTYPE_OBJECT: + case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ + case ANIMTYPE_DSLAM: + case ANIMTYPE_DSCAM: + case ANIMTYPE_DSCACHEFILE: + case ANIMTYPE_DSCUR: + case ANIMTYPE_DSSKEY: + case ANIMTYPE_DSWOR: + case ANIMTYPE_DSNTREE: + case ANIMTYPE_DSPART: + case ANIMTYPE_DSMBALL: + case ANIMTYPE_DSARM: + case ANIMTYPE_DSMESH: + case ANIMTYPE_DSTEX: + case ANIMTYPE_DSLAT: + case ANIMTYPE_DSLINESTYLE: + case ANIMTYPE_DSSPK: + case ANIMTYPE_DSGPENCIL: + case ANIMTYPE_PALETTE: { + /* for these channels, we only do AnimData */ + if (ale->adt && adt_ptr) { + ID *id; + + if ((ale->data == NULL) || (ale->type == ANIMTYPE_OBJECT)) { + /* ale->data is not an ID block! */ + id = ale->id; + } + else { + /* ale->data is always the proper ID block we need, + * but ale->id may not be (i.e. for textures) */ + id = (ID *)ale->data; + } + + /* AnimData pointer */ + if (adt_ptr) { + RNA_pointer_create(id, &RNA_AnimData, ale->adt, adt_ptr); + } + + /* set found status to -1, since setting to 1 would break the loop + * and potentially skip an active NLA-Track in some cases... + */ + found = -1; + } + break; + } + } + + if (found > 0) + break; + } + + /* free temp data */ + ANIM_animdata_freelist(&anim_data); + + return (found != 0); } #if 0 static bool nla_panel_poll(const bContext *C, PanelType *pt) { - return nla_panel_context(C, NULL, NULL); + return nla_panel_context(C, NULL, NULL); } #endif static bool nla_animdata_panel_poll(const bContext *C, PanelType *UNUSED(pt)) { - PointerRNA ptr; - return (nla_panel_context(C, &ptr, NULL, NULL) && (ptr.data != NULL)); + PointerRNA ptr; + return (nla_panel_context(C, &ptr, NULL, NULL) && (ptr.data != NULL)); } static bool nla_track_panel_poll(const bContext *C, PanelType *UNUSED(pt)) { - PointerRNA ptr; - return (nla_panel_context(C, NULL, &ptr, NULL) && (ptr.data != NULL)); + PointerRNA ptr; + return (nla_panel_context(C, NULL, &ptr, NULL) && (ptr.data != NULL)); } static bool nla_strip_panel_poll(const bContext *C, PanelType *UNUSED(pt)) { - PointerRNA ptr; - return (nla_panel_context(C, NULL, NULL, &ptr) && (ptr.data != NULL)); + PointerRNA ptr; + return (nla_panel_context(C, NULL, NULL, &ptr) && (ptr.data != NULL)); } static bool nla_strip_actclip_panel_poll(const bContext *C, PanelType *UNUSED(pt)) { - PointerRNA ptr; - NlaStrip *strip; + PointerRNA ptr; + NlaStrip *strip; - if (!nla_panel_context(C, NULL, NULL, &ptr)) - return 0; - if (ptr.data == NULL) - return 0; + if (!nla_panel_context(C, NULL, NULL, &ptr)) + return 0; + if (ptr.data == NULL) + return 0; - strip = ptr.data; - return (strip->type == NLASTRIP_TYPE_CLIP); + strip = ptr.data; + return (strip->type == NLASTRIP_TYPE_CLIP); } static bool nla_strip_eval_panel_poll(const bContext *C, PanelType *UNUSED(pt)) { - PointerRNA ptr; - NlaStrip *strip; + PointerRNA ptr; + NlaStrip *strip; - if (!nla_panel_context(C, NULL, NULL, &ptr)) - return 0; - if (ptr.data == NULL) - return 0; + if (!nla_panel_context(C, NULL, NULL, &ptr)) + return 0; + if (ptr.data == NULL) + return 0; - strip = ptr.data; + strip = ptr.data; - if (strip->type == NLASTRIP_TYPE_SOUND) - return 0; + if (strip->type == NLASTRIP_TYPE_SOUND) + return 0; - return 1; + return 1; } /* -------------- */ @@ -240,342 +240,349 @@ static bool nla_strip_eval_panel_poll(const bContext *C, PanelType *UNUSED(pt)) /* active AnimData */ static void nla_panel_animdata(const bContext *C, Panel *pa) { - PointerRNA adt_ptr; - /* AnimData *adt; */ - uiLayout *layout = pa->layout; - uiLayout *row; - uiBlock *block; - - /* check context and also validity of pointer */ - if (!nla_panel_context(C, &adt_ptr, NULL, NULL)) - return; - - /* adt = adt_ptr.data; */ - - block = uiLayoutGetBlock(layout); - UI_block_func_handle_set(block, do_nla_region_buttons, NULL); - - /* AnimData Source Properties ----------------------------------- */ - - /* icon + id-block name of block where AnimData came from to prevent - * accidentally changing the properties of the wrong action - */ - if (adt_ptr.id.data) { - ID *id = adt_ptr.id.data; - PointerRNA id_ptr; - - RNA_id_pointer_create(id, &id_ptr); - - /* ID-block name > AnimData */ - row = uiLayoutRow(layout, true); - uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT); - - uiItemL(row, id->name + 2, RNA_struct_ui_icon(id_ptr.type)); /* id-block (src) */ - uiItemL(row, "", ICON_SMALL_TRI_RIGHT_VEC); /* expander */ - uiItemL(row, IFACE_("Animation Data"), ICON_ANIM_DATA); /* animdata */ - - uiItemS(layout); - } - - /* Active Action Properties ------------------------------------- */ - /* action */ - row = uiLayoutRow(layout, true); - uiTemplateID( - row, (bContext *)C, &adt_ptr, "action", - "ACTION_OT_new", NULL, "NLA_OT_action_unlink", UI_TEMPLATE_ID_FILTER_ALL, false); - - /* extrapolation */ - row = uiLayoutRow(layout, true); - uiItemR(row, &adt_ptr, "action_extrapolation", 0, NULL, ICON_NONE); - - /* blending */ - row = uiLayoutRow(layout, true); - uiItemR(row, &adt_ptr, "action_blend_type", 0, NULL, ICON_NONE); - - /* influence */ - row = uiLayoutRow(layout, true); - uiItemR(row, &adt_ptr, "action_influence", 0, NULL, ICON_NONE); + PointerRNA adt_ptr; + /* AnimData *adt; */ + uiLayout *layout = pa->layout; + uiLayout *row; + uiBlock *block; + + /* check context and also validity of pointer */ + if (!nla_panel_context(C, &adt_ptr, NULL, NULL)) + return; + + /* adt = adt_ptr.data; */ + + block = uiLayoutGetBlock(layout); + UI_block_func_handle_set(block, do_nla_region_buttons, NULL); + + /* AnimData Source Properties ----------------------------------- */ + + /* icon + id-block name of block where AnimData came from to prevent + * accidentally changing the properties of the wrong action + */ + if (adt_ptr.id.data) { + ID *id = adt_ptr.id.data; + PointerRNA id_ptr; + + RNA_id_pointer_create(id, &id_ptr); + + /* ID-block name > AnimData */ + row = uiLayoutRow(layout, true); + uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT); + + uiItemL(row, id->name + 2, RNA_struct_ui_icon(id_ptr.type)); /* id-block (src) */ + uiItemL(row, "", ICON_SMALL_TRI_RIGHT_VEC); /* expander */ + uiItemL(row, IFACE_("Animation Data"), ICON_ANIM_DATA); /* animdata */ + + uiItemS(layout); + } + + /* Active Action Properties ------------------------------------- */ + /* action */ + row = uiLayoutRow(layout, true); + uiTemplateID(row, + (bContext *)C, + &adt_ptr, + "action", + "ACTION_OT_new", + NULL, + "NLA_OT_action_unlink", + UI_TEMPLATE_ID_FILTER_ALL, + false); + + /* extrapolation */ + row = uiLayoutRow(layout, true); + uiItemR(row, &adt_ptr, "action_extrapolation", 0, NULL, ICON_NONE); + + /* blending */ + row = uiLayoutRow(layout, true); + uiItemR(row, &adt_ptr, "action_blend_type", 0, NULL, ICON_NONE); + + /* influence */ + row = uiLayoutRow(layout, true); + uiItemR(row, &adt_ptr, "action_influence", 0, NULL, ICON_NONE); } /* active NLA-Track */ static void nla_panel_track(const bContext *C, Panel *pa) { - PointerRNA nlt_ptr; - uiLayout *layout = pa->layout; - uiLayout *row; - uiBlock *block; + PointerRNA nlt_ptr; + uiLayout *layout = pa->layout; + uiLayout *row; + uiBlock *block; - /* check context and also validity of pointer */ - if (!nla_panel_context(C, NULL, &nlt_ptr, NULL)) - return; + /* check context and also validity of pointer */ + if (!nla_panel_context(C, NULL, &nlt_ptr, NULL)) + return; - block = uiLayoutGetBlock(layout); - UI_block_func_handle_set(block, do_nla_region_buttons, NULL); + block = uiLayoutGetBlock(layout); + UI_block_func_handle_set(block, do_nla_region_buttons, NULL); - /* Info - Active NLA-Context:Track ---------------------- */ - row = uiLayoutRow(layout, true); - uiItemR(row, &nlt_ptr, "name", 0, NULL, ICON_NLA); + /* Info - Active NLA-Context:Track ---------------------- */ + row = uiLayoutRow(layout, true); + uiItemR(row, &nlt_ptr, "name", 0, NULL, ICON_NLA); } /* generic settings for active NLA-Strip */ static void nla_panel_properties(const bContext *C, Panel *pa) { - PointerRNA strip_ptr; - uiLayout *layout = pa->layout; - uiLayout *column, *row, *sub; - uiBlock *block; - short showEvalProps = 1; - - if (!nla_panel_context(C, NULL, NULL, &strip_ptr)) - return; - - block = uiLayoutGetBlock(layout); - UI_block_func_handle_set(block, do_nla_region_buttons, NULL); - - /* Strip Properties ------------------------------------- */ - /* strip type */ - row = uiLayoutColumn(layout, true); - uiItemR(row, &strip_ptr, "name", 0, NULL, ICON_NLA); // XXX icon? - uiItemR(row, &strip_ptr, "type", 0, NULL, ICON_NONE); - - /* strip extents */ - column = uiLayoutColumn(layout, true); - uiItemL(column, IFACE_("Strip Extents:"), ICON_NONE); - uiItemR(column, &strip_ptr, "frame_start", 0, NULL, ICON_NONE); - uiItemR(column, &strip_ptr, "frame_end", 0, NULL, ICON_NONE); - - /* Evaluation-Related Strip Properties ------------------ */ - - /* sound properties strips don't have these settings */ - if (RNA_enum_get(&strip_ptr, "type") == NLASTRIP_TYPE_SOUND) - showEvalProps = 0; - - /* only show if allowed to... */ - if (showEvalProps) { - /* extrapolation */ - row = uiLayoutRow(layout, true); - uiItemR(row, &strip_ptr, "extrapolation", 0, NULL, ICON_NONE); - - /* blending */ - row = uiLayoutRow(layout, true); - uiItemR(row, &strip_ptr, "blend_type", 0, NULL, ICON_NONE); - - /* Blend in/out + auto-blending: - * - blend in/out can only be set when autoblending is off - */ - column = uiLayoutColumn(layout, true); - uiLayoutSetActive(column, RNA_boolean_get(&strip_ptr, "use_animated_influence") == false); - uiItemR(column, &strip_ptr, "use_auto_blend", 0, NULL, ICON_NONE); // XXX as toggle? - - sub = uiLayoutColumn(column, true); - uiLayoutSetActive(sub, RNA_boolean_get(&strip_ptr, "use_auto_blend") == false); - uiItemR(sub, &strip_ptr, "blend_in", 0, NULL, ICON_NONE); - uiItemR(sub, &strip_ptr, "blend_out", 0, NULL, ICON_NONE); - - /* settings */ - column = uiLayoutColumn(layout, true); - uiLayoutSetActive(column, !(RNA_boolean_get(&strip_ptr, "use_animated_influence") || RNA_boolean_get(&strip_ptr, "use_animated_time"))); - uiItemL(column, IFACE_("Playback Settings:"), ICON_NONE); - uiItemR(column, &strip_ptr, "mute", 0, NULL, ICON_NONE); - uiItemR(column, &strip_ptr, "use_reverse", 0, NULL, ICON_NONE); - } + PointerRNA strip_ptr; + uiLayout *layout = pa->layout; + uiLayout *column, *row, *sub; + uiBlock *block; + short showEvalProps = 1; + + if (!nla_panel_context(C, NULL, NULL, &strip_ptr)) + return; + + block = uiLayoutGetBlock(layout); + UI_block_func_handle_set(block, do_nla_region_buttons, NULL); + + /* Strip Properties ------------------------------------- */ + /* strip type */ + row = uiLayoutColumn(layout, true); + uiItemR(row, &strip_ptr, "name", 0, NULL, ICON_NLA); // XXX icon? + uiItemR(row, &strip_ptr, "type", 0, NULL, ICON_NONE); + + /* strip extents */ + column = uiLayoutColumn(layout, true); + uiItemL(column, IFACE_("Strip Extents:"), ICON_NONE); + uiItemR(column, &strip_ptr, "frame_start", 0, NULL, ICON_NONE); + uiItemR(column, &strip_ptr, "frame_end", 0, NULL, ICON_NONE); + + /* Evaluation-Related Strip Properties ------------------ */ + + /* sound properties strips don't have these settings */ + if (RNA_enum_get(&strip_ptr, "type") == NLASTRIP_TYPE_SOUND) + showEvalProps = 0; + + /* only show if allowed to... */ + if (showEvalProps) { + /* extrapolation */ + row = uiLayoutRow(layout, true); + uiItemR(row, &strip_ptr, "extrapolation", 0, NULL, ICON_NONE); + + /* blending */ + row = uiLayoutRow(layout, true); + uiItemR(row, &strip_ptr, "blend_type", 0, NULL, ICON_NONE); + + /* Blend in/out + auto-blending: + * - blend in/out can only be set when autoblending is off + */ + column = uiLayoutColumn(layout, true); + uiLayoutSetActive(column, RNA_boolean_get(&strip_ptr, "use_animated_influence") == false); + uiItemR(column, &strip_ptr, "use_auto_blend", 0, NULL, ICON_NONE); // XXX as toggle? + + sub = uiLayoutColumn(column, true); + uiLayoutSetActive(sub, RNA_boolean_get(&strip_ptr, "use_auto_blend") == false); + uiItemR(sub, &strip_ptr, "blend_in", 0, NULL, ICON_NONE); + uiItemR(sub, &strip_ptr, "blend_out", 0, NULL, ICON_NONE); + + /* settings */ + column = uiLayoutColumn(layout, true); + uiLayoutSetActive(column, + !(RNA_boolean_get(&strip_ptr, "use_animated_influence") || + RNA_boolean_get(&strip_ptr, "use_animated_time"))); + uiItemL(column, IFACE_("Playback Settings:"), ICON_NONE); + uiItemR(column, &strip_ptr, "mute", 0, NULL, ICON_NONE); + uiItemR(column, &strip_ptr, "use_reverse", 0, NULL, ICON_NONE); + } } - /* action-clip only settings for active NLA-Strip */ static void nla_panel_actclip(const bContext *C, Panel *pa) { - PointerRNA strip_ptr; - uiLayout *layout = pa->layout; - uiLayout *column, *row; - uiBlock *block; - - /* check context and also validity of pointer */ - if (!nla_panel_context(C, NULL, NULL, &strip_ptr)) - return; - - block = uiLayoutGetBlock(layout); - UI_block_func_handle_set(block, do_nla_region_buttons, NULL); - - /* Strip Properties ------------------------------------- */ - /* action pointer */ - row = uiLayoutRow(layout, true); - uiItemR(row, &strip_ptr, "action", 0, NULL, ICON_ACTION); - - /* action extents */ - // XXX custom names were used here (to avoid the prefixes)... probably not necessary in future? - column = uiLayoutColumn(layout, true); - uiItemL(column, IFACE_("Action Extents:"), ICON_NONE); - uiItemR(column, &strip_ptr, "action_frame_start", 0, IFACE_("Start Frame"), ICON_NONE); - uiItemR(column, &strip_ptr, "action_frame_end", 0, IFACE_("End Frame"), ICON_NONE); - - // XXX: this layout may actually be too abstract and confusing, and may be better using standard column layout - row = uiLayoutRow(layout, false); - uiItemR(row, &strip_ptr, "use_sync_length", 0, IFACE_("Sync Length"), ICON_NONE); - uiItemO(row, IFACE_("Now"), ICON_FILE_REFRESH, "NLA_OT_action_sync_length"); - - /* action usage */ - column = uiLayoutColumn(layout, true); - uiLayoutSetActive(column, RNA_boolean_get(&strip_ptr, "use_animated_time") == false); - uiItemL(column, IFACE_("Playback Settings:"), ICON_NONE); - uiItemR(column, &strip_ptr, "scale", 0, NULL, ICON_NONE); - uiItemR(column, &strip_ptr, "repeat", 0, NULL, ICON_NONE); + PointerRNA strip_ptr; + uiLayout *layout = pa->layout; + uiLayout *column, *row; + uiBlock *block; + + /* check context and also validity of pointer */ + if (!nla_panel_context(C, NULL, NULL, &strip_ptr)) + return; + + block = uiLayoutGetBlock(layout); + UI_block_func_handle_set(block, do_nla_region_buttons, NULL); + + /* Strip Properties ------------------------------------- */ + /* action pointer */ + row = uiLayoutRow(layout, true); + uiItemR(row, &strip_ptr, "action", 0, NULL, ICON_ACTION); + + /* action extents */ + // XXX custom names were used here (to avoid the prefixes)... probably not necessary in future? + column = uiLayoutColumn(layout, true); + uiItemL(column, IFACE_("Action Extents:"), ICON_NONE); + uiItemR(column, &strip_ptr, "action_frame_start", 0, IFACE_("Start Frame"), ICON_NONE); + uiItemR(column, &strip_ptr, "action_frame_end", 0, IFACE_("End Frame"), ICON_NONE); + + // XXX: this layout may actually be too abstract and confusing, and may be better using standard column layout + row = uiLayoutRow(layout, false); + uiItemR(row, &strip_ptr, "use_sync_length", 0, IFACE_("Sync Length"), ICON_NONE); + uiItemO(row, IFACE_("Now"), ICON_FILE_REFRESH, "NLA_OT_action_sync_length"); + + /* action usage */ + column = uiLayoutColumn(layout, true); + uiLayoutSetActive(column, RNA_boolean_get(&strip_ptr, "use_animated_time") == false); + uiItemL(column, IFACE_("Playback Settings:"), ICON_NONE); + uiItemR(column, &strip_ptr, "scale", 0, NULL, ICON_NONE); + uiItemR(column, &strip_ptr, "repeat", 0, NULL, ICON_NONE); } /* evaluation settings for active NLA-Strip */ static void nla_panel_evaluation(const bContext *C, Panel *pa) { - PointerRNA strip_ptr; - uiLayout *layout = pa->layout; - uiLayout *col, *sub; - uiBlock *block; + PointerRNA strip_ptr; + uiLayout *layout = pa->layout; + uiLayout *col, *sub; + uiBlock *block; - /* check context and also validity of pointer */ - if (!nla_panel_context(C, NULL, NULL, &strip_ptr)) - return; + /* check context and also validity of pointer */ + if (!nla_panel_context(C, NULL, NULL, &strip_ptr)) + return; - block = uiLayoutGetBlock(layout); - UI_block_func_handle_set(block, do_nla_region_buttons, NULL); + block = uiLayoutGetBlock(layout); + UI_block_func_handle_set(block, do_nla_region_buttons, NULL); - col = uiLayoutColumn(layout, true); - uiItemR(col, &strip_ptr, "use_animated_influence", 0, NULL, ICON_NONE); + col = uiLayoutColumn(layout, true); + uiItemR(col, &strip_ptr, "use_animated_influence", 0, NULL, ICON_NONE); - sub = uiLayoutColumn(col, true); - uiLayoutSetEnabled(sub, RNA_boolean_get(&strip_ptr, "use_animated_influence")); - uiItemR(sub, &strip_ptr, "influence", 0, NULL, ICON_NONE); + sub = uiLayoutColumn(col, true); + uiLayoutSetEnabled(sub, RNA_boolean_get(&strip_ptr, "use_animated_influence")); + uiItemR(sub, &strip_ptr, "influence", 0, NULL, ICON_NONE); - col = uiLayoutColumn(layout, true); - sub = uiLayoutRow(col, false); - uiItemR(sub, &strip_ptr, "use_animated_time", 0, NULL, ICON_NONE); - uiItemR(sub, &strip_ptr, "use_animated_time_cyclic", 0, NULL, ICON_NONE); + col = uiLayoutColumn(layout, true); + sub = uiLayoutRow(col, false); + uiItemR(sub, &strip_ptr, "use_animated_time", 0, NULL, ICON_NONE); + uiItemR(sub, &strip_ptr, "use_animated_time_cyclic", 0, NULL, ICON_NONE); - sub = uiLayoutRow(col, false); - uiLayoutSetEnabled(sub, RNA_boolean_get(&strip_ptr, "use_animated_time")); - uiItemR(sub, &strip_ptr, "strip_time", 0, NULL, ICON_NONE); + sub = uiLayoutRow(col, false); + uiLayoutSetEnabled(sub, RNA_boolean_get(&strip_ptr, "use_animated_time")); + uiItemR(sub, &strip_ptr, "strip_time", 0, NULL, ICON_NONE); } /* F-Modifiers for active NLA-Strip */ static void nla_panel_modifiers(const bContext *C, Panel *pa) { - PointerRNA strip_ptr; - NlaStrip *strip; - FModifier *fcm; - uiLayout *col, *row; - uiBlock *block; - - /* check context and also validity of pointer */ - if (!nla_panel_context(C, NULL, NULL, &strip_ptr)) - return; - strip = strip_ptr.data; - - block = uiLayoutGetBlock(pa->layout); - UI_block_func_handle_set(block, do_nla_region_buttons, NULL); - - /* 'add modifier' button at top of panel */ - { - row = uiLayoutRow(pa->layout, false); - block = uiLayoutGetBlock(row); - - // FIXME: we need to set the only-active property so that this will only add modifiers for the active strip (not all selected) - uiItemMenuEnumO(row, (bContext *)C, "NLA_OT_fmodifier_add", "type", IFACE_("Add Modifier"), ICON_NONE); - - /* copy/paste (as sub-row) */ - row = uiLayoutRow(row, true); - uiItemO(row, "", ICON_COPYDOWN, "NLA_OT_fmodifier_copy"); - uiItemO(row, "", ICON_PASTEDOWN, "NLA_OT_fmodifier_paste"); - } - - /* draw each modifier */ - for (fcm = strip->modifiers.first; fcm; fcm = fcm->next) { - col = uiLayoutColumn(pa->layout, true); - - ANIM_uiTemplate_fmodifier_draw(col, strip_ptr.id.data, &strip->modifiers, fcm); - } + PointerRNA strip_ptr; + NlaStrip *strip; + FModifier *fcm; + uiLayout *col, *row; + uiBlock *block; + + /* check context and also validity of pointer */ + if (!nla_panel_context(C, NULL, NULL, &strip_ptr)) + return; + strip = strip_ptr.data; + + block = uiLayoutGetBlock(pa->layout); + UI_block_func_handle_set(block, do_nla_region_buttons, NULL); + + /* 'add modifier' button at top of panel */ + { + row = uiLayoutRow(pa->layout, false); + block = uiLayoutGetBlock(row); + + // FIXME: we need to set the only-active property so that this will only add modifiers for the active strip (not all selected) + uiItemMenuEnumO( + row, (bContext *)C, "NLA_OT_fmodifier_add", "type", IFACE_("Add Modifier"), ICON_NONE); + + /* copy/paste (as sub-row) */ + row = uiLayoutRow(row, true); + uiItemO(row, "", ICON_COPYDOWN, "NLA_OT_fmodifier_copy"); + uiItemO(row, "", ICON_PASTEDOWN, "NLA_OT_fmodifier_paste"); + } + + /* draw each modifier */ + for (fcm = strip->modifiers.first; fcm; fcm = fcm->next) { + col = uiLayoutColumn(pa->layout, true); + + ANIM_uiTemplate_fmodifier_draw(col, strip_ptr.id.data, &strip->modifiers, fcm); + } } /* ******************* general ******************************** */ - void nla_buttons_register(ARegionType *art) { - PanelType *pt; - - pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel animdata"); - strcpy(pt->idname, "NLA_PT_animdata"); - strcpy(pt->label, N_("Animation Data")); - strcpy(pt->category, "Animations"); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = nla_panel_animdata; - pt->poll = nla_animdata_panel_poll; - pt->flag = PNL_DEFAULT_CLOSED; - BLI_addtail(&art->paneltypes, pt); - - pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel track"); - strcpy(pt->idname, "NLA_PT_track"); - strcpy(pt->label, N_("Active Track")); - strcpy(pt->category, "Animations"); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = nla_panel_track; - pt->poll = nla_track_panel_poll; - BLI_addtail(&art->paneltypes, pt); - - pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel properties"); - strcpy(pt->idname, "NLA_PT_properties"); - strcpy(pt->label, N_("Active Strip")); - strcpy(pt->category, "Animations"); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = nla_panel_properties; - pt->poll = nla_strip_panel_poll; - BLI_addtail(&art->paneltypes, pt); - - pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel properties"); - strcpy(pt->idname, "NLA_PT_actionclip"); - strcpy(pt->label, N_("Action Clip")); - strcpy(pt->category, "Animations"); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = nla_panel_actclip; - pt->poll = nla_strip_actclip_panel_poll; - BLI_addtail(&art->paneltypes, pt); - - pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel evaluation"); - strcpy(pt->idname, "NLA_PT_evaluation"); - strcpy(pt->label, N_("Evaluation")); - strcpy(pt->category, "Animations"); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = nla_panel_evaluation; - pt->poll = nla_strip_eval_panel_poll; - BLI_addtail(&art->paneltypes, pt); - - pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel modifiers"); - strcpy(pt->idname, "NLA_PT_modifiers"); - strcpy(pt->label, N_("Modifiers")); - strcpy(pt->category, "Modifiers"); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = nla_panel_modifiers; - pt->poll = nla_strip_eval_panel_poll; - BLI_addtail(&art->paneltypes, pt); + PanelType *pt; + + pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel animdata"); + strcpy(pt->idname, "NLA_PT_animdata"); + strcpy(pt->label, N_("Animation Data")); + strcpy(pt->category, "Animations"); + strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + pt->draw = nla_panel_animdata; + pt->poll = nla_animdata_panel_poll; + pt->flag = PNL_DEFAULT_CLOSED; + BLI_addtail(&art->paneltypes, pt); + + pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel track"); + strcpy(pt->idname, "NLA_PT_track"); + strcpy(pt->label, N_("Active Track")); + strcpy(pt->category, "Animations"); + strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + pt->draw = nla_panel_track; + pt->poll = nla_track_panel_poll; + BLI_addtail(&art->paneltypes, pt); + + pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel properties"); + strcpy(pt->idname, "NLA_PT_properties"); + strcpy(pt->label, N_("Active Strip")); + strcpy(pt->category, "Animations"); + strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + pt->draw = nla_panel_properties; + pt->poll = nla_strip_panel_poll; + BLI_addtail(&art->paneltypes, pt); + + pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel properties"); + strcpy(pt->idname, "NLA_PT_actionclip"); + strcpy(pt->label, N_("Action Clip")); + strcpy(pt->category, "Animations"); + strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + pt->draw = nla_panel_actclip; + pt->poll = nla_strip_actclip_panel_poll; + BLI_addtail(&art->paneltypes, pt); + + pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel evaluation"); + strcpy(pt->idname, "NLA_PT_evaluation"); + strcpy(pt->label, N_("Evaluation")); + strcpy(pt->category, "Animations"); + strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + pt->draw = nla_panel_evaluation; + pt->poll = nla_strip_eval_panel_poll; + BLI_addtail(&art->paneltypes, pt); + + pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel modifiers"); + strcpy(pt->idname, "NLA_PT_modifiers"); + strcpy(pt->label, N_("Modifiers")); + strcpy(pt->category, "Modifiers"); + strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + pt->draw = nla_panel_modifiers; + pt->poll = nla_strip_eval_panel_poll; + BLI_addtail(&art->paneltypes, pt); } static int nla_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op)) { - ScrArea *sa = CTX_wm_area(C); - ARegion *ar = nla_has_buttons_region(sa); + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = nla_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 NLA_OT_properties(wmOperatorType *ot) { - ot->name = "Toggle Sidebar"; - ot->idname = "NLA_OT_properties"; - ot->description = "Toggle the properties region visibility"; + ot->name = "Toggle Sidebar"; + ot->idname = "NLA_OT_properties"; + ot->description = "Toggle the properties region visibility"; - ot->exec = nla_properties_toggle_exec; - ot->poll = ED_operator_nla_active; + ot->exec = nla_properties_toggle_exec; + ot->poll = ED_operator_nla_active; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; } diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index ae3888f6ae0..90e70b835f8 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -21,7 +21,6 @@ * \ingroup spnla */ - #include <string.h> #include <stdio.h> #include <stdlib.h> @@ -58,7 +57,7 @@ #include "UI_view2d.h" -#include "nla_intern.h" // own include +#include "nla_intern.h" // own include /* *********************************************** */ /* Operators for NLA channels-list which need to be different @@ -72,271 +71,273 @@ * --> Most channels are now selection only... */ -static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channel_index, short selectmode) +static int mouse_nla_channels( + bContext *C, bAnimContext *ac, float x, int channel_index, short selectmode) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - View2D *v2d = &ac->ar->v2d; - int notifierFlags = 0; - - /* get the channel that was clicked on */ - /* filter channels */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* get channel from index */ - ale = BLI_findlink(&anim_data, channel_index); - if (ale == NULL) { - /* channel not found */ - if (G.debug & G_DEBUG) - printf("Error: animation channel (index = %d) not found in mouse_anim_channels()\n", channel_index); - - ANIM_animdata_freelist(&anim_data); - return 0; - } - - /* action to take depends on what channel we've got */ - // WARNING: must keep this in sync with the equivalent function in anim_channels_edit.c - switch (ale->type) { - case ANIMTYPE_SCENE: - { - Scene *sce = (Scene *)ale->data; - AnimData *adt = sce->adt; - - /* set selection status */ - if (selectmode == SELECT_INVERT) { - /* swap select */ - sce->flag ^= SCE_DS_SELECTED; - if (adt) adt->flag ^= ADT_UI_SELECTED; - } - else { - sce->flag |= SCE_DS_SELECTED; - if (adt) adt->flag |= ADT_UI_SELECTED; - } - - notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); - break; - } - case ANIMTYPE_OBJECT: - { - ViewLayer *view_layer = ac->view_layer; - Base *base = (Base *)ale->data; - Object *ob = base->object; - AnimData *adt = ob->adt; - - if (nlaedit_is_tweakmode_on(ac) == 0 && (base->flag & BASE_SELECTABLE)) { - /* set selection status */ - if (selectmode == SELECT_INVERT) { - /* swap select */ - ED_object_base_select(base, BA_INVERT); - BKE_scene_object_base_flag_sync_from_base(base); - - if (adt) adt->flag ^= ADT_UI_SELECTED; - } - else { - /* deselect all */ - /* TODO: should this deselect all other types of channels too? */ - for (Base *b = view_layer->object_bases.first; b; b = b->next) { - ED_object_base_select(b, BA_DESELECT); - BKE_scene_object_base_flag_sync_from_base(b); - if (b->object->adt) b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE); - } - - /* select object now */ - ED_object_base_select(base, BA_SELECT); - BKE_scene_object_base_flag_sync_from_base(base); - if (adt) adt->flag |= ADT_UI_SELECTED; - } - - /* change active object - regardless of whether it is now selected [T37883] */ - ED_object_base_activate(C, base); /* adds notifier */ - - if ((adt) && (adt->flag & ADT_UI_SELECTED)) - adt->flag |= ADT_UI_ACTIVE; - - /* notifiers - channel was selected */ - notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); - } - break; - } - case ANIMTYPE_FILLACTD: /* Action Expander */ - case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ - case ANIMTYPE_DSLAM: - case ANIMTYPE_DSCAM: - case ANIMTYPE_DSCACHEFILE: - case ANIMTYPE_DSCUR: - case ANIMTYPE_DSSKEY: - case ANIMTYPE_DSWOR: - case ANIMTYPE_DSNTREE: - case ANIMTYPE_DSPART: - case ANIMTYPE_DSMBALL: - case ANIMTYPE_DSARM: - case ANIMTYPE_DSMESH: - case ANIMTYPE_DSTEX: - case ANIMTYPE_DSLAT: - case ANIMTYPE_DSLINESTYLE: - case ANIMTYPE_DSSPK: - case ANIMTYPE_DSGPENCIL: - case ANIMTYPE_PALETTE: - { - /* sanity checking... */ - if (ale->adt) { - /* select/deselect */ - if (selectmode == SELECT_INVERT) { - /* inverse selection status of this AnimData block only */ - ale->adt->flag ^= ADT_UI_SELECTED; - } - else { - /* select AnimData block by itself */ - ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); - ale->adt->flag |= ADT_UI_SELECTED; - } - - /* set active? */ - if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED)) - ale->adt->flag |= ADT_UI_ACTIVE; - } - - notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); - break; - } - case ANIMTYPE_NLATRACK: - { - NlaTrack *nlt = (NlaTrack *)ale->data; - AnimData *adt = ale->adt; - short offset; - - /* offset for start of channel (on LHS of channel-list) */ - if (ale->id) { - /* special exception for materials and particles */ - if (ELEM(GS(ale->id->name), ID_MA, ID_PA)) - offset = 21 + NLACHANNEL_BUTTON_WIDTH; - else - offset = 14; - } - else - offset = 0; - - if (x >= (v2d->cur.xmax - NLACHANNEL_BUTTON_WIDTH)) { - /* toggle protection (only if there's a toggle there) */ - nlt->flag ^= NLATRACK_PROTECTED; - - /* notifier flags - channel was edited */ - notifierFlags |= (ND_ANIMCHAN | NA_EDITED); - } - else if (x >= (v2d->cur.xmax - 2 * NLACHANNEL_BUTTON_WIDTH)) { - /* toggle mute */ - nlt->flag ^= NLATRACK_MUTED; - - /* notifier flags - channel was edited */ - notifierFlags |= (ND_ANIMCHAN | NA_EDITED); - ale->update |= ANIM_UPDATE_DEPS; - } - else if (x <= ((NLACHANNEL_BUTTON_WIDTH * 2) + offset)) { - /* toggle 'solo' */ - BKE_nlatrack_solo_toggle(adt, nlt); - - /* notifier flags - channel was edited */ - notifierFlags |= (ND_ANIMCHAN | NA_EDITED); - ale->update |= ANIM_UPDATE_DEPS; - } - else if (nlaedit_is_tweakmode_on(ac) == 0) { - /* set selection */ - if (selectmode == SELECT_INVERT) { - /* inverse selection status of this F-Curve only */ - nlt->flag ^= NLATRACK_SELECTED; - } - else { - /* select F-Curve by itself */ - ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); - nlt->flag |= NLATRACK_SELECTED; - } - - /* if NLA-Track is selected now, - * make NLA-Track the 'active' one in the visible list */ - if (nlt->flag & NLATRACK_SELECTED) - ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK); - - /* notifier flags - channel was selected */ - notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); - } - break; - } - case ANIMTYPE_NLAACTION: - { - AnimData *adt = BKE_animdata_from_id(ale->id); - - /* button region... */ - if (x >= (v2d->cur.xmax - NLACHANNEL_BUTTON_WIDTH)) { - if (nlaedit_is_tweakmode_on(ac) == 0) { - /* 'push-down' action - only usable when not in TweakMode */ - /* TODO: make this use the operator instead of calling the function directly - * however, calling the operator requires that we supply the args, - * and that works with proper buttons only */ - BKE_nla_action_pushdown(adt); - } - else { - /* when in tweakmode, this button becomes the toggle for mapped editing */ - adt->flag ^= ADT_NLA_EDIT_NOMAP; - } - - /* changes to NLA-Action occurred */ - notifierFlags |= ND_NLA_ACTCHANGE; - ale->update |= ANIM_UPDATE_DEPS; - } - /* OR rest of name... */ - else { - /* NOTE: rest of NLA-Action name doubles for operating on the AnimData block - * - this is useful when there's no clear divider, and makes more sense in - * the case of users trying to use this to change actions - * - in tweakmode, clicking here gets us out of tweakmode, as changing selection - * while in tweakmode is really evil! - * - we disable "solo" flags too, to make it easier to work with stashed actions - * with less trouble - */ - if (nlaedit_is_tweakmode_on(ac)) { - /* exit tweakmode immediately */ - nlaedit_disable_tweakmode(ac, true); - - /* changes to NLA-Action occurred */ - notifierFlags |= ND_NLA_ACTCHANGE; - ale->update |= ANIM_UPDATE_DEPS; - } - else { - /* select/deselect */ - if (selectmode == SELECT_INVERT) { - /* inverse selection status of this AnimData block only */ - adt->flag ^= ADT_UI_SELECTED; - } - else { - /* select AnimData block by itself */ - ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); - adt->flag |= ADT_UI_SELECTED; - } - - /* set active? */ - if (adt->flag & ADT_UI_SELECTED) - adt->flag |= ADT_UI_ACTIVE; - - notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); - } - } - break; - } - default: - if (G.debug & G_DEBUG) - printf("Error: Invalid channel type in mouse_nla_channels()\n"); - break; - } - - /* free channels */ - ANIM_animdata_update(ac, &anim_data); - ANIM_animdata_freelist(&anim_data); - - /* return the notifier-flags set */ - return notifierFlags; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + View2D *v2d = &ac->ar->v2d; + int notifierFlags = 0; + + /* get the channel that was clicked on */ + /* filter channels */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* get channel from index */ + ale = BLI_findlink(&anim_data, channel_index); + if (ale == NULL) { + /* channel not found */ + if (G.debug & G_DEBUG) + printf("Error: animation channel (index = %d) not found in mouse_anim_channels()\n", + channel_index); + + ANIM_animdata_freelist(&anim_data); + return 0; + } + + /* action to take depends on what channel we've got */ + // WARNING: must keep this in sync with the equivalent function in anim_channels_edit.c + switch (ale->type) { + case ANIMTYPE_SCENE: { + Scene *sce = (Scene *)ale->data; + AnimData *adt = sce->adt; + + /* set selection status */ + if (selectmode == SELECT_INVERT) { + /* swap select */ + sce->flag ^= SCE_DS_SELECTED; + if (adt) + adt->flag ^= ADT_UI_SELECTED; + } + else { + sce->flag |= SCE_DS_SELECTED; + if (adt) + adt->flag |= ADT_UI_SELECTED; + } + + notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); + break; + } + case ANIMTYPE_OBJECT: { + ViewLayer *view_layer = ac->view_layer; + Base *base = (Base *)ale->data; + Object *ob = base->object; + AnimData *adt = ob->adt; + + if (nlaedit_is_tweakmode_on(ac) == 0 && (base->flag & BASE_SELECTABLE)) { + /* set selection status */ + if (selectmode == SELECT_INVERT) { + /* swap select */ + ED_object_base_select(base, BA_INVERT); + BKE_scene_object_base_flag_sync_from_base(base); + + if (adt) + adt->flag ^= ADT_UI_SELECTED; + } + else { + /* deselect all */ + /* TODO: should this deselect all other types of channels too? */ + for (Base *b = view_layer->object_bases.first; b; b = b->next) { + ED_object_base_select(b, BA_DESELECT); + BKE_scene_object_base_flag_sync_from_base(b); + if (b->object->adt) + b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE); + } + + /* select object now */ + ED_object_base_select(base, BA_SELECT); + BKE_scene_object_base_flag_sync_from_base(base); + if (adt) + adt->flag |= ADT_UI_SELECTED; + } + + /* change active object - regardless of whether it is now selected [T37883] */ + ED_object_base_activate(C, base); /* adds notifier */ + + if ((adt) && (adt->flag & ADT_UI_SELECTED)) + adt->flag |= ADT_UI_ACTIVE; + + /* notifiers - channel was selected */ + notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); + } + break; + } + case ANIMTYPE_FILLACTD: /* Action Expander */ + case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ + case ANIMTYPE_DSLAM: + case ANIMTYPE_DSCAM: + case ANIMTYPE_DSCACHEFILE: + case ANIMTYPE_DSCUR: + case ANIMTYPE_DSSKEY: + case ANIMTYPE_DSWOR: + case ANIMTYPE_DSNTREE: + case ANIMTYPE_DSPART: + case ANIMTYPE_DSMBALL: + case ANIMTYPE_DSARM: + case ANIMTYPE_DSMESH: + case ANIMTYPE_DSTEX: + case ANIMTYPE_DSLAT: + case ANIMTYPE_DSLINESTYLE: + case ANIMTYPE_DSSPK: + case ANIMTYPE_DSGPENCIL: + case ANIMTYPE_PALETTE: { + /* sanity checking... */ + if (ale->adt) { + /* select/deselect */ + if (selectmode == SELECT_INVERT) { + /* inverse selection status of this AnimData block only */ + ale->adt->flag ^= ADT_UI_SELECTED; + } + else { + /* select AnimData block by itself */ + ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); + ale->adt->flag |= ADT_UI_SELECTED; + } + + /* set active? */ + if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED)) + ale->adt->flag |= ADT_UI_ACTIVE; + } + + notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); + break; + } + case ANIMTYPE_NLATRACK: { + NlaTrack *nlt = (NlaTrack *)ale->data; + AnimData *adt = ale->adt; + short offset; + + /* offset for start of channel (on LHS of channel-list) */ + if (ale->id) { + /* special exception for materials and particles */ + if (ELEM(GS(ale->id->name), ID_MA, ID_PA)) + offset = 21 + NLACHANNEL_BUTTON_WIDTH; + else + offset = 14; + } + else + offset = 0; + + if (x >= (v2d->cur.xmax - NLACHANNEL_BUTTON_WIDTH)) { + /* toggle protection (only if there's a toggle there) */ + nlt->flag ^= NLATRACK_PROTECTED; + + /* notifier flags - channel was edited */ + notifierFlags |= (ND_ANIMCHAN | NA_EDITED); + } + else if (x >= (v2d->cur.xmax - 2 * NLACHANNEL_BUTTON_WIDTH)) { + /* toggle mute */ + nlt->flag ^= NLATRACK_MUTED; + + /* notifier flags - channel was edited */ + notifierFlags |= (ND_ANIMCHAN | NA_EDITED); + ale->update |= ANIM_UPDATE_DEPS; + } + else if (x <= ((NLACHANNEL_BUTTON_WIDTH * 2) + offset)) { + /* toggle 'solo' */ + BKE_nlatrack_solo_toggle(adt, nlt); + + /* notifier flags - channel was edited */ + notifierFlags |= (ND_ANIMCHAN | NA_EDITED); + ale->update |= ANIM_UPDATE_DEPS; + } + else if (nlaedit_is_tweakmode_on(ac) == 0) { + /* set selection */ + if (selectmode == SELECT_INVERT) { + /* inverse selection status of this F-Curve only */ + nlt->flag ^= NLATRACK_SELECTED; + } + else { + /* select F-Curve by itself */ + ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); + nlt->flag |= NLATRACK_SELECTED; + } + + /* if NLA-Track is selected now, + * make NLA-Track the 'active' one in the visible list */ + if (nlt->flag & NLATRACK_SELECTED) + ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK); + + /* notifier flags - channel was selected */ + notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); + } + break; + } + case ANIMTYPE_NLAACTION: { + AnimData *adt = BKE_animdata_from_id(ale->id); + + /* button region... */ + if (x >= (v2d->cur.xmax - NLACHANNEL_BUTTON_WIDTH)) { + if (nlaedit_is_tweakmode_on(ac) == 0) { + /* 'push-down' action - only usable when not in TweakMode */ + /* TODO: make this use the operator instead of calling the function directly + * however, calling the operator requires that we supply the args, + * and that works with proper buttons only */ + BKE_nla_action_pushdown(adt); + } + else { + /* when in tweakmode, this button becomes the toggle for mapped editing */ + adt->flag ^= ADT_NLA_EDIT_NOMAP; + } + + /* changes to NLA-Action occurred */ + notifierFlags |= ND_NLA_ACTCHANGE; + ale->update |= ANIM_UPDATE_DEPS; + } + /* OR rest of name... */ + else { + /* NOTE: rest of NLA-Action name doubles for operating on the AnimData block + * - this is useful when there's no clear divider, and makes more sense in + * the case of users trying to use this to change actions + * - in tweakmode, clicking here gets us out of tweakmode, as changing selection + * while in tweakmode is really evil! + * - we disable "solo" flags too, to make it easier to work with stashed actions + * with less trouble + */ + if (nlaedit_is_tweakmode_on(ac)) { + /* exit tweakmode immediately */ + nlaedit_disable_tweakmode(ac, true); + + /* changes to NLA-Action occurred */ + notifierFlags |= ND_NLA_ACTCHANGE; + ale->update |= ANIM_UPDATE_DEPS; + } + else { + /* select/deselect */ + if (selectmode == SELECT_INVERT) { + /* inverse selection status of this AnimData block only */ + adt->flag ^= ADT_UI_SELECTED; + } + else { + /* select AnimData block by itself */ + ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); + adt->flag |= ADT_UI_SELECTED; + } + + /* set active? */ + if (adt->flag & ADT_UI_SELECTED) + adt->flag |= ADT_UI_ACTIVE; + + notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); + } + } + break; + } + default: + if (G.debug & G_DEBUG) + printf("Error: Invalid channel type in mouse_nla_channels()\n"); + break; + } + + /* free channels */ + ANIM_animdata_update(ac, &anim_data); + ANIM_animdata_freelist(&anim_data); + + /* return the notifier-flags set */ + return notifierFlags; } /* ------------------- */ @@ -344,66 +345,74 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe /* handle clicking */ static int nlachannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - bAnimContext ac; - SpaceNla *snla; - ARegion *ar; - View2D *v2d; - int channel_index; - int notifierFlags = 0; - short selectmode; - float x, y; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* get useful pointers from animation context data */ - snla = (SpaceNla *)ac.sl; - ar = ac.ar; - v2d = &ar->v2d; - - /* 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 which channel user clicked in - * Note: although channels technically start at y= NLACHANNEL_FIRST, we need to adjust by half a channel's height - * so that the tops of channels get caught ok. Since NLACHANNEL_FIRST is really NLACHANNEL_HEIGHT, we simply use - * NLACHANNEL_HEIGHT_HALF. - */ - UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y); - UI_view2d_listview_view_to_cell(v2d, NLACHANNEL_NAMEWIDTH, NLACHANNEL_STEP(snla), 0, (float)NLACHANNEL_HEIGHT_HALF(snla), x, y, NULL, &channel_index); - - /* handle mouse-click in the relevant channel then */ - notifierFlags = mouse_nla_channels(C, &ac, x, channel_index, selectmode); - - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | notifierFlags, NULL); - - return OPERATOR_FINISHED; + bAnimContext ac; + SpaceNla *snla; + ARegion *ar; + View2D *v2d; + int channel_index; + int notifierFlags = 0; + short selectmode; + float x, y; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get useful pointers from animation context data */ + snla = (SpaceNla *)ac.sl; + ar = ac.ar; + v2d = &ar->v2d; + + /* 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 which channel user clicked in + * Note: although channels technically start at y= NLACHANNEL_FIRST, we need to adjust by half a channel's height + * so that the tops of channels get caught ok. Since NLACHANNEL_FIRST is really NLACHANNEL_HEIGHT, we simply use + * NLACHANNEL_HEIGHT_HALF. + */ + UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y); + UI_view2d_listview_view_to_cell(v2d, + NLACHANNEL_NAMEWIDTH, + NLACHANNEL_STEP(snla), + 0, + (float)NLACHANNEL_HEIGHT_HALF(snla), + x, + y, + NULL, + &channel_index); + + /* handle mouse-click in the relevant channel then */ + notifierFlags = mouse_nla_channels(C, &ac, x, channel_index, selectmode); + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | notifierFlags, NULL); + + return OPERATOR_FINISHED; } void NLA_OT_channels_click(wmOperatorType *ot) { - PropertyRNA *prop; + PropertyRNA *prop; - /* identifiers */ - ot->name = "Mouse Click on NLA Channels"; - ot->idname = "NLA_OT_channels_click"; - ot->description = "Handle clicks to select NLA channels"; + /* identifiers */ + ot->name = "Mouse Click on NLA Channels"; + ot->idname = "NLA_OT_channels_click"; + ot->description = "Handle clicks to select NLA channels"; - /* api callbacks */ - ot->invoke = nlachannels_mouseclick_invoke; - ot->poll = ED_operator_nla_active; + /* api callbacks */ + ot->invoke = nlachannels_mouseclick_invoke; + ot->poll = ED_operator_nla_active; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; - /* props */ - prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + /* props */ + prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* *********************************************** */ @@ -413,169 +422,185 @@ void NLA_OT_channels_click(wmOperatorType *ot) static int nlachannels_pushdown_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - ID *id = NULL; - AnimData *adt = NULL; - int channel_index = RNA_int_get(op->ptr, "channel_index"); - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* get anim-channel to use (or more specifically, the animdata block behind it) */ - if (channel_index == -1) { - PointerRNA adt_ptr = {{NULL}}; - - /* active animdata block */ - if (nla_panel_context(C, &adt_ptr, NULL, NULL) == 0 || (adt_ptr.data == NULL)) { - BKE_report(op->reports, RPT_ERROR, "No active AnimData block to use " - "(select a data-block expander first or set the appropriate flags on an AnimData block)"); - return OPERATOR_CANCELLED; - } - else { - id = adt_ptr.id.data; - adt = adt_ptr.data; - } - } - else { - /* indexed channel */ - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - /* filter channels */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - /* get channel from index */ - ale = BLI_findlink(&anim_data, channel_index); - if (ale == NULL) { - BKE_reportf(op->reports, RPT_ERROR, "No animation channel found at index %d", channel_index); - ANIM_animdata_freelist(&anim_data); - return OPERATOR_CANCELLED; - } - else if (ale->type != ANIMTYPE_NLAACTION) { - BKE_reportf(op->reports, RPT_ERROR, "Animation channel at index %d is not a NLA 'Active Action' channel", channel_index); - ANIM_animdata_freelist(&anim_data); - return OPERATOR_CANCELLED; - } - - /* grab AnimData from the channel */ - adt = ale->adt; - id = ale->id; - - /* we don't need anything here anymore, so free it all */ - ANIM_animdata_freelist(&anim_data); - } - - /* double-check that we are free to push down here... */ - if (adt == NULL) { - BKE_report(op->reports, RPT_WARNING, "Internal Error - AnimData block is not valid"); - return OPERATOR_CANCELLED; - } - else if (nlaedit_is_tweakmode_on(&ac)) { - BKE_report(op->reports, RPT_WARNING, - "Cannot push down actions while tweaking a strip's action, exit tweak mode first"); - return OPERATOR_CANCELLED; - } - else if (adt->action == NULL) { - BKE_report(op->reports, RPT_WARNING, "No active action to push down"); - return OPERATOR_CANCELLED; - } - else { - /* 'push-down' action - only usable when not in TweakMode */ - BKE_nla_action_pushdown(adt); - - DEG_id_tag_update_ex(CTX_data_main(C), id, ID_RECALC_ANIMATION | ID_RECALC_COPY_ON_WRITE); - } - - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL); - return OPERATOR_FINISHED; + bAnimContext ac; + ID *id = NULL; + AnimData *adt = NULL; + int channel_index = RNA_int_get(op->ptr, "channel_index"); + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get anim-channel to use (or more specifically, the animdata block behind it) */ + if (channel_index == -1) { + PointerRNA adt_ptr = {{NULL}}; + + /* active animdata block */ + if (nla_panel_context(C, &adt_ptr, NULL, NULL) == 0 || (adt_ptr.data == NULL)) { + BKE_report(op->reports, + RPT_ERROR, + "No active AnimData block to use " + "(select a data-block expander first or set the appropriate flags on an AnimData " + "block)"); + return OPERATOR_CANCELLED; + } + else { + id = adt_ptr.id.data; + adt = adt_ptr.data; + } + } + else { + /* indexed channel */ + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* filter channels */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* get channel from index */ + ale = BLI_findlink(&anim_data, channel_index); + if (ale == NULL) { + BKE_reportf(op->reports, RPT_ERROR, "No animation channel found at index %d", channel_index); + ANIM_animdata_freelist(&anim_data); + return OPERATOR_CANCELLED; + } + else if (ale->type != ANIMTYPE_NLAACTION) { + BKE_reportf(op->reports, + RPT_ERROR, + "Animation channel at index %d is not a NLA 'Active Action' channel", + channel_index); + ANIM_animdata_freelist(&anim_data); + return OPERATOR_CANCELLED; + } + + /* grab AnimData from the channel */ + adt = ale->adt; + id = ale->id; + + /* we don't need anything here anymore, so free it all */ + ANIM_animdata_freelist(&anim_data); + } + + /* double-check that we are free to push down here... */ + if (adt == NULL) { + BKE_report(op->reports, RPT_WARNING, "Internal Error - AnimData block is not valid"); + return OPERATOR_CANCELLED; + } + else if (nlaedit_is_tweakmode_on(&ac)) { + BKE_report(op->reports, + RPT_WARNING, + "Cannot push down actions while tweaking a strip's action, exit tweak mode first"); + return OPERATOR_CANCELLED; + } + else if (adt->action == NULL) { + BKE_report(op->reports, RPT_WARNING, "No active action to push down"); + return OPERATOR_CANCELLED; + } + else { + /* 'push-down' action - only usable when not in TweakMode */ + BKE_nla_action_pushdown(adt); + + DEG_id_tag_update_ex(CTX_data_main(C), id, ID_RECALC_ANIMATION | ID_RECALC_COPY_ON_WRITE); + } + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL); + return OPERATOR_FINISHED; } void NLA_OT_action_pushdown(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Push Down Action"; - ot->idname = "NLA_OT_action_pushdown"; - ot->description = "Push action down onto the top of the NLA stack as a new strip"; - - /* callbacks */ - ot->exec = nlachannels_pushdown_exec; - ot->poll = nlaop_poll_tweakmode_off; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - ot->prop = RNA_def_int(ot->srna, "channel_index", -1, -1, INT_MAX, "Channel Index", - "Index of NLA action channel to perform pushdown operation on", - 0, INT_MAX); - RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); + /* identifiers */ + ot->name = "Push Down Action"; + ot->idname = "NLA_OT_action_pushdown"; + ot->description = "Push action down onto the top of the NLA stack as a new strip"; + + /* callbacks */ + ot->exec = nlachannels_pushdown_exec; + ot->poll = nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_int(ot->srna, + "channel_index", + -1, + -1, + INT_MAX, + "Channel Index", + "Index of NLA action channel to perform pushdown operation on", + 0, + INT_MAX); + RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); } /* ******************** Action Unlink ******************************** */ static bool nla_action_unlink_poll(bContext *C) { - if (ED_operator_nla_active(C)) { - return nla_panel_context(C, NULL, NULL, NULL); - } + if (ED_operator_nla_active(C)) { + return nla_panel_context(C, NULL, NULL, NULL); + } - /* something failed... */ - return false; + /* something failed... */ + return false; } static int nla_action_unlink_exec(bContext *C, wmOperator *op) { - PointerRNA adt_ptr; - AnimData *adt; + PointerRNA adt_ptr; + AnimData *adt; - /* check context and also validity of pointer */ - if (!nla_panel_context(C, &adt_ptr, NULL, NULL)) - return OPERATOR_CANCELLED; + /* check context and also validity of pointer */ + if (!nla_panel_context(C, &adt_ptr, NULL, NULL)) + return OPERATOR_CANCELLED; - /* get animdata */ - adt = adt_ptr.data; - if (adt == NULL) - return OPERATOR_CANCELLED; + /* get animdata */ + adt = adt_ptr.data; + if (adt == NULL) + return OPERATOR_CANCELLED; - /* do unlinking */ - if (adt && adt->action) { - bool force_delete = RNA_boolean_get(op->ptr, "force_delete"); - ED_animedit_unlink_action(C, adt_ptr.id.data, adt, adt->action, op->reports, force_delete); - } + /* do unlinking */ + if (adt && adt->action) { + bool force_delete = RNA_boolean_get(op->ptr, "force_delete"); + ED_animedit_unlink_action(C, adt_ptr.id.data, adt, adt->action, op->reports, force_delete); + } - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static int nla_action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *evt) { - /* NOTE: this is hardcoded to match the behavior for the unlink button - * (in interface_templates.c) */ - RNA_boolean_set(op->ptr, "force_delete", evt->shift != 0); - return nla_action_unlink_exec(C, op); + /* NOTE: this is hardcoded to match the behavior for the unlink button + * (in interface_templates.c) */ + RNA_boolean_set(op->ptr, "force_delete", evt->shift != 0); + return nla_action_unlink_exec(C, op); } void NLA_OT_action_unlink(wmOperatorType *ot) { - PropertyRNA *prop; - - /* identifiers */ - ot->name = "Unlink Action"; - ot->idname = "NLA_OT_action_unlink"; - ot->description = "Unlink this action from the active action slot (and/or exit Tweak Mode)"; - - /* callbacks */ - ot->invoke = nla_action_unlink_invoke; - ot->exec = nla_action_unlink_exec; - ot->poll = nla_action_unlink_poll; - - /* properties */ - prop = RNA_def_boolean(ot->srna, "force_delete", false, "Force Delete", - "Clear Fake User and remove copy stashed in this datablock's NLA stack"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Unlink Action"; + ot->idname = "NLA_OT_action_unlink"; + ot->description = "Unlink this action from the active action slot (and/or exit Tweak Mode)"; + + /* callbacks */ + ot->invoke = nla_action_unlink_invoke; + ot->exec = nla_action_unlink_exec; + ot->poll = nla_action_unlink_poll; + + /* properties */ + prop = RNA_def_boolean(ot->srna, + "force_delete", + false, + "Force Delete", + "Clear Fake User and remove copy stashed in this datablock's NLA stack"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* ******************** Add Tracks Operator ***************************** */ @@ -584,136 +609,142 @@ void NLA_OT_action_unlink(wmOperatorType *ot) /* helper - add NLA Tracks alongside existing ones */ bool nlaedit_add_tracks_existing(bAnimContext *ac, bool above_sel) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - AnimData *lastAdt = NULL; - bool added = false; - - /* get a list of the (selected) NLA Tracks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* add tracks... */ - for (ale = anim_data.first; ale; ale = ale->next) { - if (ale->type == ANIMTYPE_NLATRACK) { - NlaTrack *nlt = (NlaTrack *)ale->data; - AnimData *adt = ale->adt; - - /* check if just adding a new track above this one, - * or whether we're adding a new one to the top of the stack that this one belongs to - */ - if (above_sel) { - /* just add a new one above this one */ - BKE_nlatrack_add(adt, nlt); - ale->update = ANIM_UPDATE_DEPS; - added = true; - } - else if ((lastAdt == NULL) || (adt != lastAdt)) { - /* add one track to the top of the owning AnimData's stack, - * then don't add anymore to this stack */ - BKE_nlatrack_add(adt, NULL); - lastAdt = adt; - ale->update = ANIM_UPDATE_DEPS; - added = true; - } - } - } - - /* free temp data */ - ANIM_animdata_update(ac, &anim_data); - ANIM_animdata_freelist(&anim_data); - - return added; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + AnimData *lastAdt = NULL; + bool added = false; + + /* get a list of the (selected) NLA Tracks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | + ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* add tracks... */ + for (ale = anim_data.first; ale; ale = ale->next) { + if (ale->type == ANIMTYPE_NLATRACK) { + NlaTrack *nlt = (NlaTrack *)ale->data; + AnimData *adt = ale->adt; + + /* check if just adding a new track above this one, + * or whether we're adding a new one to the top of the stack that this one belongs to + */ + if (above_sel) { + /* just add a new one above this one */ + BKE_nlatrack_add(adt, nlt); + ale->update = ANIM_UPDATE_DEPS; + added = true; + } + else if ((lastAdt == NULL) || (adt != lastAdt)) { + /* add one track to the top of the owning AnimData's stack, + * then don't add anymore to this stack */ + BKE_nlatrack_add(adt, NULL); + lastAdt = adt; + ale->update = ANIM_UPDATE_DEPS; + added = true; + } + } + } + + /* free temp data */ + ANIM_animdata_update(ac, &anim_data); + ANIM_animdata_freelist(&anim_data); + + return added; } /* helper - add NLA Tracks to empty (and selected) AnimData blocks */ bool nlaedit_add_tracks_empty(bAnimContext *ac) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - bool added = false; - - /* get a list of the selected AnimData blocks in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* check if selected AnimData blocks are empty, and add tracks if so... */ - for (ale = anim_data.first; ale; ale = ale->next) { - AnimData *adt = ale->adt; - - /* sanity check */ - BLI_assert(adt->flag & ADT_UI_SELECTED); - - /* ensure it is empty */ - if (BLI_listbase_is_empty(&adt->nla_tracks)) { - /* add new track to this AnimData block then */ - BKE_nlatrack_add(adt, NULL); - ale->update = ANIM_UPDATE_DEPS; - added = true; - } - } - - /* cleanup */ - ANIM_animdata_update(ac, &anim_data); - ANIM_animdata_freelist(&anim_data); - - return added; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + bool added = false; + + /* get a list of the selected AnimData blocks in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA | + ANIMFILTER_SEL | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* check if selected AnimData blocks are empty, and add tracks if so... */ + for (ale = anim_data.first; ale; ale = ale->next) { + AnimData *adt = ale->adt; + + /* sanity check */ + BLI_assert(adt->flag & ADT_UI_SELECTED); + + /* ensure it is empty */ + if (BLI_listbase_is_empty(&adt->nla_tracks)) { + /* add new track to this AnimData block then */ + BKE_nlatrack_add(adt, NULL); + ale->update = ANIM_UPDATE_DEPS; + added = true; + } + } + + /* cleanup */ + ANIM_animdata_update(ac, &anim_data); + ANIM_animdata_freelist(&anim_data); + + return added; } /* ----- */ static int nlaedit_add_tracks_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - bool above_sel = RNA_boolean_get(op->ptr, "above_selected"); - bool op_done = false; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* perform adding in two passes - existing first so that we don't double up for empty */ - op_done |= nlaedit_add_tracks_existing(&ac, above_sel); - op_done |= nlaedit_add_tracks_empty(&ac); - - /* done? */ - if (op_done) { - DEG_relations_tag_update(CTX_data_main(C)); - - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); - - /* done */ - return OPERATOR_FINISHED; - } - else { - /* failed to add any tracks */ - BKE_report(op->reports, RPT_WARNING, - "Select an existing NLA Track or an empty action line first"); - - /* not done */ - return OPERATOR_CANCELLED; - } + bAnimContext ac; + bool above_sel = RNA_boolean_get(op->ptr, "above_selected"); + bool op_done = false; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* perform adding in two passes - existing first so that we don't double up for empty */ + op_done |= nlaedit_add_tracks_existing(&ac, above_sel); + op_done |= nlaedit_add_tracks_empty(&ac); + + /* done? */ + if (op_done) { + DEG_relations_tag_update(CTX_data_main(C)); + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; + } + else { + /* failed to add any tracks */ + BKE_report( + op->reports, RPT_WARNING, "Select an existing NLA Track or an empty action line first"); + + /* not done */ + return OPERATOR_CANCELLED; + } } void NLA_OT_tracks_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Tracks"; - ot->idname = "NLA_OT_tracks_add"; - ot->description = "Add NLA-Tracks above/after the selected tracks"; - - /* api callbacks */ - ot->exec = nlaedit_add_tracks_exec; - ot->poll = nlaop_poll_tweakmode_off; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - RNA_def_boolean(ot->srna, "above_selected", 0, "Above Selected", "Add a new NLA Track above every existing selected one"); + /* identifiers */ + ot->name = "Add Tracks"; + ot->idname = "NLA_OT_tracks_add"; + ot->description = "Add NLA-Tracks above/after the selected tracks"; + + /* api callbacks */ + ot->exec = nlaedit_add_tracks_exec; + ot->poll = nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + RNA_def_boolean(ot->srna, + "above_selected", + 0, + "Above Selected", + "Add a new NLA Track above every existing selected one"); } /* ******************** Delete Tracks Operator ***************************** */ @@ -721,64 +752,65 @@ void NLA_OT_tracks_add(wmOperatorType *ot) static int nlaedit_delete_tracks_exec(bContext *C, wmOperator *UNUSED(op)) { - 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 a list of the AnimData blocks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - /* delete tracks */ - for (ale = anim_data.first; ale; ale = ale->next) { - if (ale->type == ANIMTYPE_NLATRACK) { - NlaTrack *nlt = (NlaTrack *)ale->data; - AnimData *adt = ale->adt; - - /* if track is currently 'solo', then AnimData should have its - * 'has solo' flag disabled - */ - if (nlt->flag & NLATRACK_SOLO) - adt->flag &= ~ADT_NLA_SOLO_TRACK; - - /* call delete on this track - deletes all strips too */ - BKE_nlatrack_free(&adt->nla_tracks, nlt, true); - ale->update = ANIM_UPDATE_DEPS; - } - } - - /* free temp data */ - ANIM_animdata_update(&ac, &anim_data); - ANIM_animdata_freelist(&anim_data); - - DEG_relations_tag_update(ac.bmain); - - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); - - /* done */ - return OPERATOR_FINISHED; + 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 a list of the AnimData blocks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | + ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* delete tracks */ + for (ale = anim_data.first; ale; ale = ale->next) { + if (ale->type == ANIMTYPE_NLATRACK) { + NlaTrack *nlt = (NlaTrack *)ale->data; + AnimData *adt = ale->adt; + + /* if track is currently 'solo', then AnimData should have its + * 'has solo' flag disabled + */ + if (nlt->flag & NLATRACK_SOLO) + adt->flag &= ~ADT_NLA_SOLO_TRACK; + + /* call delete on this track - deletes all strips too */ + BKE_nlatrack_free(&adt->nla_tracks, nlt, true); + ale->update = ANIM_UPDATE_DEPS; + } + } + + /* free temp data */ + ANIM_animdata_update(&ac, &anim_data); + ANIM_animdata_freelist(&anim_data); + + DEG_relations_tag_update(ac.bmain); + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; } void NLA_OT_tracks_delete(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Delete Tracks"; - ot->idname = "NLA_OT_tracks_delete"; - ot->description = "Delete selected NLA-Tracks and the strips they contain"; + /* identifiers */ + ot->name = "Delete Tracks"; + ot->idname = "NLA_OT_tracks_delete"; + ot->description = "Delete selected NLA-Tracks and the strips they contain"; - /* api callbacks */ - ot->exec = nlaedit_delete_tracks_exec; - ot->poll = nlaop_poll_tweakmode_off; + /* api callbacks */ + ot->exec = nlaedit_delete_tracks_exec; + ot->poll = nlaop_poll_tweakmode_off; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* *********************************************** */ @@ -794,47 +826,46 @@ void NLA_OT_tracks_delete(wmOperatorType *ot) static int nlaedit_objects_add_exec(bContext *C, wmOperator *UNUSED(op)) { - bAnimContext ac; - SpaceNla *snla; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* ensure that filters are set so that the effect will be immediately visible */ - snla = (SpaceNla *)ac.sl; - if (snla && snla->ads) { - snla->ads->filterflag &= ~ADS_FILTER_NLA_NOACT; - } - - /* operate on selected objects... */ - CTX_DATA_BEGIN (C, Object *, ob, selected_objects) - { - /* ensure that object has AnimData... that's all */ - BKE_animdata_add_id(&ob->id); - } - CTX_DATA_END; - - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); - - /* done */ - return OPERATOR_FINISHED; + bAnimContext ac; + SpaceNla *snla; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* ensure that filters are set so that the effect will be immediately visible */ + snla = (SpaceNla *)ac.sl; + if (snla && snla->ads) { + snla->ads->filterflag &= ~ADS_FILTER_NLA_NOACT; + } + + /* operate on selected objects... */ + CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { + /* ensure that object has AnimData... that's all */ + BKE_animdata_add_id(&ob->id); + } + CTX_DATA_END; + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; } void NLA_OT_selected_objects_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Include Selected Objects"; - ot->idname = "NLA_OT_selected_objects_add"; - ot->description = "Make selected objects appear in NLA Editor by adding Animation Data"; + /* identifiers */ + ot->name = "Include Selected Objects"; + ot->idname = "NLA_OT_selected_objects_add"; + ot->description = "Make selected objects appear in NLA Editor by adding Animation Data"; - /* api callbacks */ - ot->exec = nlaedit_objects_add_exec; - ot->poll = nlaop_poll_tweakmode_off; + /* api callbacks */ + ot->exec = nlaedit_objects_add_exec; + ot->poll = nlaop_poll_tweakmode_off; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* *********************************************** */ diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 48eb2bdb82b..65115819874 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -21,7 +21,6 @@ * \ingroup spnla */ - #include <string.h> #include <stdio.h> #include <stdlib.h> @@ -46,7 +45,6 @@ #include "ED_anim_api.h" #include "ED_keyframes_draw.h" - #include "GPU_immediate.h" #include "GPU_immediate_util.h" #include "GPU_draw.h" @@ -61,7 +59,6 @@ #include "nla_private.h" #include "nla_intern.h" /* own include */ - /* *********************************************** */ /* Strips */ @@ -72,163 +69,179 @@ */ void nla_action_get_color(AnimData *adt, bAction *act, float color[4]) { - if (adt && (adt->flag & ADT_NLA_EDIT_ON)) { - /* greenish color (same as tweaking strip) */ - UI_GetThemeColor4fv(TH_NLA_TWEAK, color); - } - else { - if (act) { - /* reddish color - same as dopesheet summary */ - UI_GetThemeColor4fv(TH_ANIM_ACTIVE, color); - } - else { - /* grayish-red color */ - UI_GetThemeColor4fv(TH_ANIM_INACTIVE, color); - } - } - - /* when an NLA track is tagged "solo", action doesn't contribute, - * so shouldn't be as prominent */ - if (adt && (adt->flag & ADT_NLA_SOLO_TRACK)) - color[3] *= 0.15f; + if (adt && (adt->flag & ADT_NLA_EDIT_ON)) { + /* greenish color (same as tweaking strip) */ + UI_GetThemeColor4fv(TH_NLA_TWEAK, color); + } + else { + if (act) { + /* reddish color - same as dopesheet summary */ + UI_GetThemeColor4fv(TH_ANIM_ACTIVE, color); + } + else { + /* grayish-red color */ + UI_GetThemeColor4fv(TH_ANIM_INACTIVE, color); + } + } + + /* when an NLA track is tagged "solo", action doesn't contribute, + * so shouldn't be as prominent */ + if (adt && (adt->flag & ADT_NLA_SOLO_TRACK)) + color[3] *= 0.15f; } /* draw the keyframes in the specified Action */ -static void nla_action_draw_keyframes(View2D *v2d, AnimData *adt, bAction *act, float y, float ymin, float ymax) +static void nla_action_draw_keyframes( + View2D *v2d, AnimData *adt, bAction *act, float y, float ymin, float ymax) { - /* get a list of the keyframes with NLA-scaling applied */ - DLRBT_Tree keys; - BLI_dlrbTree_init(&keys); - action_to_keylist(adt, act, &keys, 0); - - if (ELEM(NULL, act, keys.first)) - return; - - /* draw a darkened region behind the strips - * - get and reset the background color, this time without the alpha to stand out better - * (amplified alpha is used instead) - */ - float color[4]; - nla_action_get_color(adt, act, color); - color[3] *= 2.5f; - - GPUVertFormat *format = immVertexFormat(); - uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - - immUniformColor4fv(color); - - /* - draw a rect from the first to the last frame (no extra overlaps for now) - * that is slightly stumpier than the track background (hardcoded 2-units here) - */ - float f1 = ((ActKeyColumn *)keys.first)->cfra; - float f2 = ((ActKeyColumn *)keys.last)->cfra; - - immRectf(pos_id, f1, ymin + 2, f2, ymax - 2); - immUnbindProgram(); - - /* count keys before drawing */ - /* Note: It's safe to cast DLRBT_Tree, as it's designed to degrade down to a ListBase */ - uint key_len = BLI_listbase_count((ListBase *)&keys); - - if (key_len > 0) { - format = immVertexFormat(); - pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - uint outline_color_id = GPU_vertformat_attr_add(format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT); - immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND); - GPU_enable_program_point_size(); - immUniform2f("ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1); - immBegin(GPU_PRIM_POINTS, key_len); - - /* - disregard the selection status of keyframes so they draw a certain way - * - size is 6.0f which is smaller than the editable keyframes, so that there is a distinction - */ - for (ActKeyColumn *ak = keys.first; ak; ak = ak->next) { - draw_keyframe_shape(ak->cfra, y, 6.0f, false, ak->key_type, KEYFRAME_SHAPE_FRAME, 1.0f, - pos_id, size_id, color_id, outline_color_id, - flags_id, KEYFRAME_HANDLE_NONE, KEYFRAME_EXTREME_NONE); - } - - immEnd(); - GPU_disable_program_point_size(); - immUnbindProgram(); - } - - /* free icons */ - BLI_dlrbTree_free(&keys); + /* get a list of the keyframes with NLA-scaling applied */ + DLRBT_Tree keys; + BLI_dlrbTree_init(&keys); + action_to_keylist(adt, act, &keys, 0); + + if (ELEM(NULL, act, keys.first)) + return; + + /* draw a darkened region behind the strips + * - get and reset the background color, this time without the alpha to stand out better + * (amplified alpha is used instead) + */ + float color[4]; + nla_action_get_color(adt, act, color); + color[3] *= 2.5f; + + GPUVertFormat *format = immVertexFormat(); + uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformColor4fv(color); + + /* - draw a rect from the first to the last frame (no extra overlaps for now) + * that is slightly stumpier than the track background (hardcoded 2-units here) + */ + float f1 = ((ActKeyColumn *)keys.first)->cfra; + float f2 = ((ActKeyColumn *)keys.last)->cfra; + + immRectf(pos_id, f1, ymin + 2, f2, ymax - 2); + immUnbindProgram(); + + /* count keys before drawing */ + /* Note: It's safe to cast DLRBT_Tree, as it's designed to degrade down to a ListBase */ + uint key_len = BLI_listbase_count((ListBase *)&keys); + + if (key_len > 0) { + format = immVertexFormat(); + pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + uint color_id = GPU_vertformat_attr_add( + format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + uint outline_color_id = GPU_vertformat_attr_add( + format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT); + immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND); + GPU_enable_program_point_size(); + immUniform2f("ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1); + immBegin(GPU_PRIM_POINTS, key_len); + + /* - disregard the selection status of keyframes so they draw a certain way + * - size is 6.0f which is smaller than the editable keyframes, so that there is a distinction + */ + for (ActKeyColumn *ak = keys.first; ak; ak = ak->next) { + draw_keyframe_shape(ak->cfra, + y, + 6.0f, + false, + ak->key_type, + KEYFRAME_SHAPE_FRAME, + 1.0f, + pos_id, + size_id, + color_id, + outline_color_id, + flags_id, + KEYFRAME_HANDLE_NONE, + KEYFRAME_EXTREME_NONE); + } + + immEnd(); + GPU_disable_program_point_size(); + immUnbindProgram(); + } + + /* free icons */ + BLI_dlrbTree_free(&keys); } /* Strip Markers ------------------------ */ /* Markers inside an action strip */ -static void nla_actionclip_draw_markers(NlaStrip *strip, float yminc, float ymaxc, int shade, const bool dashed) +static void nla_actionclip_draw_markers( + NlaStrip *strip, float yminc, float ymaxc, int shade, const bool dashed) { - const bAction *act = strip->act; - - if (ELEM(NULL, act, act->markers.first)) - return; - - const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - if (dashed) { - 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" mode */ - immUniform1f("dash_width", 6.0f); - immUniform1f("dash_factor", 0.5f); - } - else { - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - } - immUniformThemeColorShade(TH_STRIP_SELECT, shade); - - immBeginAtMost(GPU_PRIM_LINES, BLI_listbase_count(&act->markers) * 2); - for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) { - if ((marker->frame > strip->actstart) && (marker->frame < strip->actend)) { - float frame = nlastrip_get_frame(strip, marker->frame, NLATIME_CONVERT_MAP); - - /* just a simple line for now */ - /* XXX: draw a triangle instead... */ - immVertex2f(shdr_pos, frame, yminc + 1); - immVertex2f(shdr_pos, frame, ymaxc - 1); - } - } - immEnd(); - - immUnbindProgram(); + const bAction *act = strip->act; + + if (ELEM(NULL, act, act->markers.first)) + return; + + const uint shdr_pos = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + if (dashed) { + 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" mode */ + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); + } + else { + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + } + immUniformThemeColorShade(TH_STRIP_SELECT, shade); + + immBeginAtMost(GPU_PRIM_LINES, BLI_listbase_count(&act->markers) * 2); + for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) { + if ((marker->frame > strip->actstart) && (marker->frame < strip->actend)) { + float frame = nlastrip_get_frame(strip, marker->frame, NLATIME_CONVERT_MAP); + + /* just a simple line for now */ + /* XXX: draw a triangle instead... */ + immVertex2f(shdr_pos, frame, yminc + 1); + immVertex2f(shdr_pos, frame, ymaxc - 1); + } + } + immEnd(); + + immUnbindProgram(); } /* Markers inside a NLA-Strip */ static void nla_strip_draw_markers(NlaStrip *strip, float yminc, float ymaxc) { - GPU_line_width(2.0f); - - if (strip->type == NLASTRIP_TYPE_CLIP) { - /* try not to be too conspicuous, while being visible enough when transforming */ - int shade = (strip->flag & NLASTRIP_FLAG_SELECT) ? -60 : -40; - - /* just draw the markers in this clip */ - nla_actionclip_draw_markers(strip, yminc, ymaxc, shade, true); - } - else if (strip->flag & NLASTRIP_FLAG_TEMP_META) { - /* just a solid color, so that it is very easy to spot */ - int shade = 20; - /* draw the markers in the first level of strips only (if they are actions) */ - for (NlaStrip *nls = strip->strips.first; nls; nls = nls->next) { - if (nls->type == NLASTRIP_TYPE_CLIP) { - nla_actionclip_draw_markers(nls, yminc, ymaxc, shade, false); - } - } - } - - GPU_line_width(1.0f); + GPU_line_width(2.0f); + + if (strip->type == NLASTRIP_TYPE_CLIP) { + /* try not to be too conspicuous, while being visible enough when transforming */ + int shade = (strip->flag & NLASTRIP_FLAG_SELECT) ? -60 : -40; + + /* just draw the markers in this clip */ + nla_actionclip_draw_markers(strip, yminc, ymaxc, shade, true); + } + else if (strip->flag & NLASTRIP_FLAG_TEMP_META) { + /* just a solid color, so that it is very easy to spot */ + int shade = 20; + /* draw the markers in the first level of strips only (if they are actions) */ + for (NlaStrip *nls = strip->strips.first; nls; nls = nls->next) { + if (nls->type == NLASTRIP_TYPE_CLIP) { + nla_actionclip_draw_markers(nls, yminc, ymaxc, shade, false); + } + } + } + + GPU_line_width(1.0f); } /* Strips (Proper) ---------------------- */ @@ -236,535 +249,551 @@ static void nla_strip_draw_markers(NlaStrip *strip, float yminc, float ymaxc) /* get colors for drawing NLA-Strips */ static void nla_strip_get_color_inside(AnimData *adt, NlaStrip *strip, float color[3]) { - if (strip->type == NLASTRIP_TYPE_TRANSITION) { - /* Transition Clip */ - if (strip->flag & NLASTRIP_FLAG_SELECT) { - /* selected - use a bright blue color */ - UI_GetThemeColor3fv(TH_NLA_TRANSITION_SEL, color); - } - else { - /* normal, unselected strip - use (hardly noticeable) blue tinge */ - UI_GetThemeColor3fv(TH_NLA_TRANSITION, color); - } - } - else if (strip->type == NLASTRIP_TYPE_META) { - /* Meta Clip */ - // TODO: should temporary metas get different colors too? - if (strip->flag & NLASTRIP_FLAG_SELECT) { - /* selected - use a bold purple color */ - UI_GetThemeColor3fv(TH_NLA_META_SEL, color); - } - else { - /* normal, unselected strip - use (hardly noticeable) dark purple tinge */ - UI_GetThemeColor3fv(TH_NLA_META, color); - } - } - else if (strip->type == NLASTRIP_TYPE_SOUND) { - /* Sound Clip */ - if (strip->flag & NLASTRIP_FLAG_SELECT) { - /* selected - use a bright teal color */ - UI_GetThemeColor3fv(TH_NLA_SOUND_SEL, color); - } - else { - /* normal, unselected strip - use (hardly noticeable) teal tinge */ - UI_GetThemeColor3fv(TH_NLA_SOUND, color); - } - } - else { - /* Action Clip (default/normal type of strip) */ - if (adt && (adt->flag & ADT_NLA_EDIT_ON) && (adt->actstrip == strip)) { - /* active strip should be drawn green when it is acting as the tweaking strip. - * however, this case should be skipped for when not in EditMode... - */ - UI_GetThemeColor3fv(TH_NLA_TWEAK, color); - } - else if (strip->flag & NLASTRIP_FLAG_TWEAKUSER) { - /* alert user that this strip is also used by the tweaking track (this is set when going into - * 'editmode' for that strip), since the edits made here may not be what the user anticipated - */ - UI_GetThemeColor3fv(TH_NLA_TWEAK_DUPLI, color); - } - else if (strip->flag & NLASTRIP_FLAG_SELECT) { - /* selected strip - use theme color for selected */ - UI_GetThemeColor3fv(TH_STRIP_SELECT, color); - } - else { - /* normal, unselected strip - use standard strip theme color */ - UI_GetThemeColor3fv(TH_STRIP, color); - } - } + if (strip->type == NLASTRIP_TYPE_TRANSITION) { + /* Transition Clip */ + if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* selected - use a bright blue color */ + UI_GetThemeColor3fv(TH_NLA_TRANSITION_SEL, color); + } + else { + /* normal, unselected strip - use (hardly noticeable) blue tinge */ + UI_GetThemeColor3fv(TH_NLA_TRANSITION, color); + } + } + else if (strip->type == NLASTRIP_TYPE_META) { + /* Meta Clip */ + // TODO: should temporary metas get different colors too? + if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* selected - use a bold purple color */ + UI_GetThemeColor3fv(TH_NLA_META_SEL, color); + } + else { + /* normal, unselected strip - use (hardly noticeable) dark purple tinge */ + UI_GetThemeColor3fv(TH_NLA_META, color); + } + } + else if (strip->type == NLASTRIP_TYPE_SOUND) { + /* Sound Clip */ + if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* selected - use a bright teal color */ + UI_GetThemeColor3fv(TH_NLA_SOUND_SEL, color); + } + else { + /* normal, unselected strip - use (hardly noticeable) teal tinge */ + UI_GetThemeColor3fv(TH_NLA_SOUND, color); + } + } + else { + /* Action Clip (default/normal type of strip) */ + if (adt && (adt->flag & ADT_NLA_EDIT_ON) && (adt->actstrip == strip)) { + /* active strip should be drawn green when it is acting as the tweaking strip. + * however, this case should be skipped for when not in EditMode... + */ + UI_GetThemeColor3fv(TH_NLA_TWEAK, color); + } + else if (strip->flag & NLASTRIP_FLAG_TWEAKUSER) { + /* alert user that this strip is also used by the tweaking track (this is set when going into + * 'editmode' for that strip), since the edits made here may not be what the user anticipated + */ + UI_GetThemeColor3fv(TH_NLA_TWEAK_DUPLI, color); + } + else if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* selected strip - use theme color for selected */ + UI_GetThemeColor3fv(TH_STRIP_SELECT, color); + } + else { + /* normal, unselected strip - use standard strip theme color */ + UI_GetThemeColor3fv(TH_STRIP, color); + } + } } /* helper call for drawing influence/time control curves for a given NLA-strip */ static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc, unsigned int pos) { - const float yheight = ymaxc - yminc; - - immUniformColor3f(0.7f, 0.7f, 0.7f); - - /* draw with AA'd line */ - GPU_line_smooth(true); - GPU_blend(true); - - /* influence -------------------------- */ - if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) { - FCurve *fcu = list_find_fcurve(&strip->fcurves, "influence", 0); - float cfra; - - /* plot the curve (over the strip's main region) */ - if (fcu) { - immBegin(GPU_PRIM_LINE_STRIP, abs((int)(strip->end - strip->start) + 1)); - - /* sample at 1 frame intervals, and draw - * - min y-val is yminc, max is y-maxc, so clamp in those regions - */ - for (cfra = strip->start; cfra <= strip->end; cfra += 1.0f) { - float y = evaluate_fcurve(fcu, cfra); /* assume this to be in 0-1 range */ - CLAMP(y, 0.0f, 1.0f); - immVertex2f(pos, cfra, ((y * yheight) + yminc)); - } - - immEnd(); - } - } - else { - /* use blend in/out values only if both aren't zero */ - if ((IS_EQF(strip->blendin, 0.0f) && IS_EQF(strip->blendout, 0.0f)) == 0) { - immBeginAtMost(GPU_PRIM_LINE_STRIP, 4); - - /* start of strip - if no blendin, start straight at 1, - * otherwise from 0 to 1 over blendin frames */ - if (IS_EQF(strip->blendin, 0.0f) == 0) { - immVertex2f(pos, strip->start, yminc); - immVertex2f(pos, strip->start + strip->blendin, ymaxc); - } - else - immVertex2f(pos, strip->start, ymaxc); - - /* end of strip */ - if (IS_EQF(strip->blendout, 0.0f) == 0) { - immVertex2f(pos, strip->end - strip->blendout, ymaxc); - immVertex2f(pos, strip->end, yminc); - } - else - immVertex2f(pos, strip->end, ymaxc); - - immEnd(); - } - } - - /* turn off AA'd lines */ - GPU_line_smooth(false); - GPU_blend(false); + const float yheight = ymaxc - yminc; + + immUniformColor3f(0.7f, 0.7f, 0.7f); + + /* draw with AA'd line */ + GPU_line_smooth(true); + GPU_blend(true); + + /* influence -------------------------- */ + if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) { + FCurve *fcu = list_find_fcurve(&strip->fcurves, "influence", 0); + float cfra; + + /* plot the curve (over the strip's main region) */ + if (fcu) { + immBegin(GPU_PRIM_LINE_STRIP, abs((int)(strip->end - strip->start) + 1)); + + /* sample at 1 frame intervals, and draw + * - min y-val is yminc, max is y-maxc, so clamp in those regions + */ + for (cfra = strip->start; cfra <= strip->end; cfra += 1.0f) { + float y = evaluate_fcurve(fcu, cfra); /* assume this to be in 0-1 range */ + CLAMP(y, 0.0f, 1.0f); + immVertex2f(pos, cfra, ((y * yheight) + yminc)); + } + + immEnd(); + } + } + else { + /* use blend in/out values only if both aren't zero */ + if ((IS_EQF(strip->blendin, 0.0f) && IS_EQF(strip->blendout, 0.0f)) == 0) { + immBeginAtMost(GPU_PRIM_LINE_STRIP, 4); + + /* start of strip - if no blendin, start straight at 1, + * otherwise from 0 to 1 over blendin frames */ + if (IS_EQF(strip->blendin, 0.0f) == 0) { + immVertex2f(pos, strip->start, yminc); + immVertex2f(pos, strip->start + strip->blendin, ymaxc); + } + else + immVertex2f(pos, strip->start, ymaxc); + + /* end of strip */ + if (IS_EQF(strip->blendout, 0.0f) == 0) { + immVertex2f(pos, strip->end - strip->blendout, ymaxc); + immVertex2f(pos, strip->end, yminc); + } + else + immVertex2f(pos, strip->end, ymaxc); + + immEnd(); + } + } + + /* turn off AA'd lines */ + GPU_line_smooth(false); + GPU_blend(false); } /* helper call to setup dashed-lines for strip outlines */ static uint nla_draw_use_dashed_outlines(float color[4], bool muted) { - /* Note that we use dashed shader here, and make it draw solid lines if not muted... */ - 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. */ - immUniformColor3fv(color); - - /* line style: dotted for muted */ - if (muted) { - /* dotted - and slightly thicker for readability of the dashes */ - immUniform1f("dash_width", 5.0f); - immUniform1f("dash_factor", 0.4f); - GPU_line_width(1.5f); - } - else { - /* solid line */ - immUniform1f("dash_factor", 2.0f); - GPU_line_width(1.0f); - } - - return shdr_pos; + /* Note that we use dashed shader here, and make it draw solid lines if not muted... */ + 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. */ + immUniformColor3fv(color); + + /* line style: dotted for muted */ + if (muted) { + /* dotted - and slightly thicker for readability of the dashes */ + immUniform1f("dash_width", 5.0f); + immUniform1f("dash_factor", 0.4f); + GPU_line_width(1.5f); + } + else { + /* solid line */ + immUniform1f("dash_factor", 2.0f); + GPU_line_width(1.0f); + } + + return shdr_pos; } /* main call for drawing a single NLA-strip */ -static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStrip *strip, View2D *v2d, float yminc, float ymaxc) +static void nla_draw_strip(SpaceNla *snla, + AnimData *adt, + NlaTrack *nlt, + NlaStrip *strip, + View2D *v2d, + float yminc, + float ymaxc) { - const bool non_solo = ((adt && (adt->flag & ADT_NLA_SOLO_TRACK)) && (nlt->flag & NLATRACK_SOLO) == 0); - const bool muted = ((nlt->flag & NLATRACK_MUTED) || (strip->flag & NLASTRIP_FLAG_MUTED)); - float color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - uint shdr_pos; - - /* get color of strip */ - nla_strip_get_color_inside(adt, strip, color); - - shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - - /* draw extrapolation info first (as backdrop) - * - but this should only be drawn if track has some contribution - */ - if ((strip->extendmode != NLASTRIP_EXTEND_NOTHING) && (non_solo == 0)) { - /* enable transparency... */ - GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - GPU_blend(true); - - switch (strip->extendmode) { - /* since this does both sides, - * only do the 'before' side, and leave the rest to the next case */ - case NLASTRIP_EXTEND_HOLD: - /* only need to draw here if there's no strip before since - * it only applies in such a situation - */ - if (strip->prev == NULL) { - /* set the drawing color to the color of the strip, but with very faint alpha */ - immUniformColor3fvAlpha(color, 0.15f); - - /* draw the rect to the edge of the screen */ - immRectf(shdr_pos, v2d->cur.xmin, yminc, strip->start, ymaxc); - } - ATTR_FALLTHROUGH; - - /* this only draws after the strip */ - case NLASTRIP_EXTEND_HOLD_FORWARD: - /* only need to try and draw if the next strip doesn't occur immediately after */ - if ((strip->next == NULL) || (IS_EQF(strip->next->start, strip->end) == 0)) { - /* set the drawing color to the color of the strip, but this time less faint */ - immUniformColor3fvAlpha(color, 0.3f); - - /* draw the rect to the next strip or the edge of the screen */ - float x2 = strip->next ? strip->next->start : v2d->cur.xmax; - immRectf(shdr_pos, strip->end, yminc, x2, ymaxc); - } - break; - } - - GPU_blend(false); - } - - - /* draw 'inside' of strip itself */ - if (non_solo == 0) { - immUnbindProgram(); - - /* strip is in normal track */ - UI_draw_roundbox_corner_set(UI_CNR_ALL); /* all corners rounded */ - UI_draw_roundbox_shade_x(true, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1, color); - - /* restore current vertex format & program (roundbox trashes it) */ - shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - } - else { - /* strip is in disabled track - make less visible */ - immUniformColor3fvAlpha(color, 0.1f); - - GPU_blend(true); - immRectf(shdr_pos, strip->start, yminc, strip->end, ymaxc); - GPU_blend(false); - } - - - /* draw strip's control 'curves' - * - only if user hasn't hidden them... - */ - if ((snla->flag & SNLA_NOSTRIPCURVES) == 0) - nla_draw_strip_curves(strip, yminc, ymaxc, shdr_pos); - - immUnbindProgram(); - - /* draw markings indicating locations of local markers - * (useful for lining up different actions) */ - if ((snla->flag & SNLA_NOLOCALMARKERS) == 0) - nla_strip_draw_markers(strip, yminc, ymaxc); - - /* draw strip outline - * - color used here is to indicate active vs non-active - */ - if (strip->flag & NLASTRIP_FLAG_ACTIVE) { - /* strip should appear 'sunken', so draw a light border around it */ - color[0] = 0.9f; /* FIXME: hardcoded temp-hack colors */ - color[1] = 1.0f; - color[2] = 0.9f; - } - else { - /* strip should appear to stand out, so draw a dark border around it */ - color[0] = color[1] = color[2] = 0.0f; /* FIXME: or 1.0f ?? */ - } - - /* draw outline - * - dashed-line shader is loaded after this block - */ - if (muted) { - /* muted - draw dotted, squarish outline (for simplicity) */ - shdr_pos = nla_draw_use_dashed_outlines(color, muted); - imm_draw_box_wire_2d(shdr_pos, strip->start, yminc, strip->end, ymaxc); - } - else { - /* non-muted - draw solid, rounded outline */ - UI_draw_roundbox_shade_x(false, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1, color); - - /* restore current vertex format & program (roundbox trashes it) */ - shdr_pos = nla_draw_use_dashed_outlines(color, muted); - } - - /* if action-clip strip, draw lines delimiting repeats too (in the same color as outline) */ - if ((strip->type == NLASTRIP_TYPE_CLIP) && strip->repeat > 1.0f) { - float repeatLen = (strip->actend - strip->actstart) * strip->scale; - - /* only draw lines for whole-numbered repeats, starting from the first full-repeat - * up to the last full repeat (but not if it lies on the end of the strip) - */ - immBeginAtMost(GPU_PRIM_LINES, 2 * floorf(strip->repeat)); - for (int i = 1; i < strip->repeat; i++) { - float repeatPos = strip->start + (repeatLen * i); - - /* don't draw if line would end up on or after the end of the strip */ - if (repeatPos < strip->end) { - immVertex2f(shdr_pos, repeatPos, yminc + 4); - immVertex2f(shdr_pos, repeatPos, ymaxc - 4); - } - } - immEnd(); - } - /* or if meta-strip, draw lines delimiting extents of sub-strips - * (in same color as outline, if more than 1 exists) */ - else if ((strip->type == NLASTRIP_TYPE_META) && (strip->strips.first != strip->strips.last)) { - const float y = (ymaxc - yminc) * 0.5f + yminc; - - /* up to 2 lines per strip */ - immBeginAtMost(GPU_PRIM_LINES, 4 * BLI_listbase_count(&strip->strips)); - - /* only draw first-level of child-strips, but don't draw any lines on the endpoints */ - for (NlaStrip *cs = strip->strips.first; cs; cs = cs->next) { - /* draw start-line if not same as end of previous (and only if not the first strip) - * - on upper half of strip - */ - if ((cs->prev) && IS_EQF(cs->prev->end, cs->start) == 0) { - immVertex2f(shdr_pos, cs->start, y); - immVertex2f(shdr_pos, cs->start, ymaxc); - } - - /* draw end-line if not the last strip - * - on lower half of strip - */ - if (cs->next) { - immVertex2f(shdr_pos, cs->end, yminc); - immVertex2f(shdr_pos, cs->end, y); - } - } - - immEnd(); - } - - immUnbindProgram(); + const bool non_solo = ((adt && (adt->flag & ADT_NLA_SOLO_TRACK)) && + (nlt->flag & NLATRACK_SOLO) == 0); + const bool muted = ((nlt->flag & NLATRACK_MUTED) || (strip->flag & NLASTRIP_FLAG_MUTED)); + float color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + uint shdr_pos; + + /* get color of strip */ + nla_strip_get_color_inside(adt, strip, color); + + shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + /* draw extrapolation info first (as backdrop) + * - but this should only be drawn if track has some contribution + */ + if ((strip->extendmode != NLASTRIP_EXTEND_NOTHING) && (non_solo == 0)) { + /* enable transparency... */ + GPU_blend_set_func_separate( + GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); + GPU_blend(true); + + switch (strip->extendmode) { + /* since this does both sides, + * only do the 'before' side, and leave the rest to the next case */ + case NLASTRIP_EXTEND_HOLD: + /* only need to draw here if there's no strip before since + * it only applies in such a situation + */ + if (strip->prev == NULL) { + /* set the drawing color to the color of the strip, but with very faint alpha */ + immUniformColor3fvAlpha(color, 0.15f); + + /* draw the rect to the edge of the screen */ + immRectf(shdr_pos, v2d->cur.xmin, yminc, strip->start, ymaxc); + } + ATTR_FALLTHROUGH; + + /* this only draws after the strip */ + case NLASTRIP_EXTEND_HOLD_FORWARD: + /* only need to try and draw if the next strip doesn't occur immediately after */ + if ((strip->next == NULL) || (IS_EQF(strip->next->start, strip->end) == 0)) { + /* set the drawing color to the color of the strip, but this time less faint */ + immUniformColor3fvAlpha(color, 0.3f); + + /* draw the rect to the next strip or the edge of the screen */ + float x2 = strip->next ? strip->next->start : v2d->cur.xmax; + immRectf(shdr_pos, strip->end, yminc, x2, ymaxc); + } + break; + } + + GPU_blend(false); + } + + /* draw 'inside' of strip itself */ + if (non_solo == 0) { + immUnbindProgram(); + + /* strip is in normal track */ + UI_draw_roundbox_corner_set(UI_CNR_ALL); /* all corners rounded */ + UI_draw_roundbox_shade_x(true, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1, color); + + /* restore current vertex format & program (roundbox trashes it) */ + shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + } + else { + /* strip is in disabled track - make less visible */ + immUniformColor3fvAlpha(color, 0.1f); + + GPU_blend(true); + immRectf(shdr_pos, strip->start, yminc, strip->end, ymaxc); + GPU_blend(false); + } + + /* draw strip's control 'curves' + * - only if user hasn't hidden them... + */ + if ((snla->flag & SNLA_NOSTRIPCURVES) == 0) + nla_draw_strip_curves(strip, yminc, ymaxc, shdr_pos); + + immUnbindProgram(); + + /* draw markings indicating locations of local markers + * (useful for lining up different actions) */ + if ((snla->flag & SNLA_NOLOCALMARKERS) == 0) + nla_strip_draw_markers(strip, yminc, ymaxc); + + /* draw strip outline + * - color used here is to indicate active vs non-active + */ + if (strip->flag & NLASTRIP_FLAG_ACTIVE) { + /* strip should appear 'sunken', so draw a light border around it */ + color[0] = 0.9f; /* FIXME: hardcoded temp-hack colors */ + color[1] = 1.0f; + color[2] = 0.9f; + } + else { + /* strip should appear to stand out, so draw a dark border around it */ + color[0] = color[1] = color[2] = 0.0f; /* FIXME: or 1.0f ?? */ + } + + /* draw outline + * - dashed-line shader is loaded after this block + */ + if (muted) { + /* muted - draw dotted, squarish outline (for simplicity) */ + shdr_pos = nla_draw_use_dashed_outlines(color, muted); + imm_draw_box_wire_2d(shdr_pos, strip->start, yminc, strip->end, ymaxc); + } + else { + /* non-muted - draw solid, rounded outline */ + UI_draw_roundbox_shade_x(false, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1, color); + + /* restore current vertex format & program (roundbox trashes it) */ + shdr_pos = nla_draw_use_dashed_outlines(color, muted); + } + + /* if action-clip strip, draw lines delimiting repeats too (in the same color as outline) */ + if ((strip->type == NLASTRIP_TYPE_CLIP) && strip->repeat > 1.0f) { + float repeatLen = (strip->actend - strip->actstart) * strip->scale; + + /* only draw lines for whole-numbered repeats, starting from the first full-repeat + * up to the last full repeat (but not if it lies on the end of the strip) + */ + immBeginAtMost(GPU_PRIM_LINES, 2 * floorf(strip->repeat)); + for (int i = 1; i < strip->repeat; i++) { + float repeatPos = strip->start + (repeatLen * i); + + /* don't draw if line would end up on or after the end of the strip */ + if (repeatPos < strip->end) { + immVertex2f(shdr_pos, repeatPos, yminc + 4); + immVertex2f(shdr_pos, repeatPos, ymaxc - 4); + } + } + immEnd(); + } + /* or if meta-strip, draw lines delimiting extents of sub-strips + * (in same color as outline, if more than 1 exists) */ + else if ((strip->type == NLASTRIP_TYPE_META) && (strip->strips.first != strip->strips.last)) { + const float y = (ymaxc - yminc) * 0.5f + yminc; + + /* up to 2 lines per strip */ + immBeginAtMost(GPU_PRIM_LINES, 4 * BLI_listbase_count(&strip->strips)); + + /* only draw first-level of child-strips, but don't draw any lines on the endpoints */ + for (NlaStrip *cs = strip->strips.first; cs; cs = cs->next) { + /* draw start-line if not same as end of previous (and only if not the first strip) + * - on upper half of strip + */ + if ((cs->prev) && IS_EQF(cs->prev->end, cs->start) == 0) { + immVertex2f(shdr_pos, cs->start, y); + immVertex2f(shdr_pos, cs->start, ymaxc); + } + + /* draw end-line if not the last strip + * - on lower half of strip + */ + if (cs->next) { + immVertex2f(shdr_pos, cs->end, yminc); + immVertex2f(shdr_pos, cs->end, y); + } + } + + immEnd(); + } + + immUnbindProgram(); } /* add the relevant text to the cache of text-strings to draw in pixelspace */ -static void nla_draw_strip_text( - AnimData *adt, NlaTrack *nlt, NlaStrip *strip, int index, View2D *v2d, - float xminc, float xmaxc, float yminc, float ymaxc) +static void nla_draw_strip_text(AnimData *adt, + NlaTrack *nlt, + NlaStrip *strip, + int index, + View2D *v2d, + float xminc, + float xmaxc, + float yminc, + float ymaxc) { - const bool non_solo = ((adt && (adt->flag & ADT_NLA_SOLO_TRACK)) && (nlt->flag & NLATRACK_SOLO) == 0); - char str[256]; - size_t str_len; - char col[4]; - - /* just print the name and the range */ - if (strip->flag & NLASTRIP_FLAG_TEMP_META) { - str_len = BLI_snprintf_rlen(str, sizeof(str), "%d) Temp-Meta", index); - } - else { - str_len = BLI_strncpy_rlen(str, strip->name, sizeof(str)); - } - - /* set text color - if colors (see above) are light, draw black text, otherwise draw white */ - if (strip->flag & (NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_TWEAKUSER)) { - col[0] = col[1] = col[2] = 0; - } - else { - col[0] = col[1] = col[2] = 255; - } - - /* text opacity depends on whether if there's a solo'd track, this isn't it */ - if (non_solo == 0) - col[3] = 255; - else - col[3] = 128; - - /* set bounding-box for text - * - padding of 2 'units' on either side - */ - /* TODO: make this centered? */ - rctf rect = { - .xmin = xminc, - .ymin = yminc, - .xmax = xmaxc, - .ymax = ymaxc, - }; - - /* add this string to the cache of texts to draw */ - UI_view2d_text_cache_add_rectf(v2d, &rect, str, str_len, col); + const bool non_solo = ((adt && (adt->flag & ADT_NLA_SOLO_TRACK)) && + (nlt->flag & NLATRACK_SOLO) == 0); + char str[256]; + size_t str_len; + char col[4]; + + /* just print the name and the range */ + if (strip->flag & NLASTRIP_FLAG_TEMP_META) { + str_len = BLI_snprintf_rlen(str, sizeof(str), "%d) Temp-Meta", index); + } + else { + str_len = BLI_strncpy_rlen(str, strip->name, sizeof(str)); + } + + /* set text color - if colors (see above) are light, draw black text, otherwise draw white */ + if (strip->flag & (NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_TWEAKUSER)) { + col[0] = col[1] = col[2] = 0; + } + else { + col[0] = col[1] = col[2] = 255; + } + + /* text opacity depends on whether if there's a solo'd track, this isn't it */ + if (non_solo == 0) + col[3] = 255; + else + col[3] = 128; + + /* set bounding-box for text + * - padding of 2 'units' on either side + */ + /* TODO: make this centered? */ + rctf rect = { + .xmin = xminc, + .ymin = yminc, + .xmax = xmaxc, + .ymax = ymaxc, + }; + + /* add this string to the cache of texts to draw */ + UI_view2d_text_cache_add_rectf(v2d, &rect, str, str_len, col); } /* add frame extents to cache of text-strings to draw in pixelspace * for now, only used when transforming strips */ -static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, View2D *v2d, float UNUSED(yminc), float ymaxc) +static void nla_draw_strip_frames_text( + NlaTrack *UNUSED(nlt), NlaStrip *strip, View2D *v2d, float UNUSED(yminc), float ymaxc) { - const float ytol = 1.0f; /* small offset to vertical positioning of text, for legibility */ - const char col[4] = {220, 220, 220, 255}; /* light gray */ - char numstr[32]; - size_t numstr_len; - - /* Always draw times above the strip, whereas sequencer drew below + above. - * However, we should be fine having everything on top, since these tend to be - * quite spaced out. - * - 1 dp is compromise between lack of precision (ints only, as per sequencer) - * while also preserving some accuracy, since we do use floats - */ - /* start frame */ - numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->start); - UI_view2d_text_cache_add(v2d, strip->start - 1.0f, ymaxc + ytol, numstr, numstr_len, col); - - /* end frame */ - numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->end); - UI_view2d_text_cache_add(v2d, strip->end, ymaxc + ytol, numstr, numstr_len, col); + const float ytol = 1.0f; /* small offset to vertical positioning of text, for legibility */ + const char col[4] = {220, 220, 220, 255}; /* light gray */ + char numstr[32]; + size_t numstr_len; + + /* Always draw times above the strip, whereas sequencer drew below + above. + * However, we should be fine having everything on top, since these tend to be + * quite spaced out. + * - 1 dp is compromise between lack of precision (ints only, as per sequencer) + * while also preserving some accuracy, since we do use floats + */ + /* start frame */ + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->start); + UI_view2d_text_cache_add(v2d, strip->start - 1.0f, ymaxc + ytol, numstr, numstr_len, col); + + /* end frame */ + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->end); + UI_view2d_text_cache_add(v2d, strip->end, ymaxc + ytol, numstr, numstr_len, col); } /* ---------------------- */ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar) { - View2D *v2d = &ar->v2d; - const float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask); - const float text_margin_x = (8 * UI_DPI_FAC) * pixelx; - - /* build list of channels to draw */ - ListBase anim_data = {NULL, NULL}; - int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); - size_t 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 NLACHANNEL_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. - */ - int height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2)); - - /* don't use totrect set, as the width stays the same - * (NOTE: this is ok here, the configuration is pretty straightforward) - */ - v2d->tot.ymin = (float)(-height); - - /* loop through channels, and set up drawing depending on their type */ - float y = (float)(-NLACHANNEL_HEIGHT(snla)); - - for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next) { - const float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla)); - const float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla)); - - /* check if visible */ - if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || - IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) - { - /* data to draw depends on the type of channel */ - switch (ale->type) { - case ANIMTYPE_NLATRACK: - { - AnimData *adt = ale->adt; - NlaTrack *nlt = (NlaTrack *)ale->data; - NlaStrip *strip; - int index; - - /* draw each strip in the track (if visible) */ - for (strip = nlt->strips.first, index = 1; strip; strip = strip->next, index++) { - if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) { - const float xminc = strip->start + text_margin_x; - const float xmaxc = strip->end + text_margin_x; - - /* draw the visualization of the strip */ - nla_draw_strip(snla, adt, nlt, strip, v2d, yminc, ymaxc); - - /* add the text for this strip to the cache */ - if (xminc < xmaxc) { - nla_draw_strip_text(adt, nlt, strip, index, v2d, xminc, xmaxc, yminc, ymaxc); - } - - /* if transforming strips (only real reason for temp-metas currently), - * add to the cache the frame numbers of the strip's extents - */ - if (strip->flag & NLASTRIP_FLAG_TEMP_META) - nla_draw_strip_frames_text(nlt, strip, v2d, yminc, ymaxc); - } - } - break; - } - case ANIMTYPE_NLAACTION: - { - AnimData *adt = ale->adt; - - uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - - /* just draw a semi-shaded rect spanning the width of the viewable area if there's data, - * and a second darker rect within which we draw keyframe indicator dots if there's data - */ - GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - GPU_blend(true); - - /* get colors for drawing */ - float color[4]; - nla_action_get_color(adt, ale->data, color); - immUniformColor4fv(color); - - /* draw slightly shifted up for greater separation from standard channels, - * but also slightly shorter for some more contrast when viewing the strips - */ - immRectf(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP); - - /* draw 'embossed' lines above and below the strip for effect */ - /* white base-lines */ - GPU_line_width(2.0f); - immUniformColor4f(1.0f, 1.0f, 1.0f, 0.3f); - immBegin(GPU_PRIM_LINES, 4); - immVertex2f(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP); - immVertex2f(pos, v2d->cur.xmax, yminc + NLACHANNEL_SKIP); - immVertex2f(pos, v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP); - immVertex2f(pos, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP); - immEnd(); - - /* black top-lines */ - GPU_line_width(1.0f); - immUniformColor3f(0.0f, 0.0f, 0.0f); - immBegin(GPU_PRIM_LINES, 4); - immVertex2f(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP); - immVertex2f(pos, v2d->cur.xmax, yminc + NLACHANNEL_SKIP); - immVertex2f(pos, v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP); - immVertex2f(pos, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP); - immEnd(); - - /* TODO: these lines but better --^ */ - - immUnbindProgram(); - - /* draw keyframes in the action */ - nla_action_draw_keyframes(v2d, adt, ale->data, y, yminc + NLACHANNEL_SKIP, ymaxc - NLACHANNEL_SKIP); - - GPU_blend(false); - break; - } - } - } - - /* adjust y-position for next one */ - y -= NLACHANNEL_STEP(snla); - } - - /* free tempolary channels */ - ANIM_animdata_freelist(&anim_data); + View2D *v2d = &ar->v2d; + const float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask); + const float text_margin_x = (8 * UI_DPI_FAC) * pixelx; + + /* build list of channels to draw */ + ListBase anim_data = {NULL, NULL}; + int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); + size_t 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 NLACHANNEL_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. + */ + int height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2)); + + /* don't use totrect set, as the width stays the same + * (NOTE: this is ok here, the configuration is pretty straightforward) + */ + v2d->tot.ymin = (float)(-height); + + /* loop through channels, and set up drawing depending on their type */ + float y = (float)(-NLACHANNEL_HEIGHT(snla)); + + for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next) { + const float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla)); + const float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla)); + + /* check if visible */ + if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || + IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) { + /* data to draw depends on the type of channel */ + switch (ale->type) { + case ANIMTYPE_NLATRACK: { + AnimData *adt = ale->adt; + NlaTrack *nlt = (NlaTrack *)ale->data; + NlaStrip *strip; + int index; + + /* draw each strip in the track (if visible) */ + for (strip = nlt->strips.first, index = 1; strip; strip = strip->next, index++) { + if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) { + const float xminc = strip->start + text_margin_x; + const float xmaxc = strip->end + text_margin_x; + + /* draw the visualization of the strip */ + nla_draw_strip(snla, adt, nlt, strip, v2d, yminc, ymaxc); + + /* add the text for this strip to the cache */ + if (xminc < xmaxc) { + nla_draw_strip_text(adt, nlt, strip, index, v2d, xminc, xmaxc, yminc, ymaxc); + } + + /* if transforming strips (only real reason for temp-metas currently), + * add to the cache the frame numbers of the strip's extents + */ + if (strip->flag & NLASTRIP_FLAG_TEMP_META) + nla_draw_strip_frames_text(nlt, strip, v2d, yminc, ymaxc); + } + } + break; + } + case ANIMTYPE_NLAACTION: { + AnimData *adt = ale->adt; + + uint pos = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + /* just draw a semi-shaded rect spanning the width of the viewable area if there's data, + * and a second darker rect within which we draw keyframe indicator dots if there's data + */ + GPU_blend_set_func_separate( + GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); + GPU_blend(true); + + /* get colors for drawing */ + float color[4]; + nla_action_get_color(adt, ale->data, color); + immUniformColor4fv(color); + + /* draw slightly shifted up for greater separation from standard channels, + * but also slightly shorter for some more contrast when viewing the strips + */ + immRectf( + pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP); + + /* draw 'embossed' lines above and below the strip for effect */ + /* white base-lines */ + GPU_line_width(2.0f); + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.3f); + immBegin(GPU_PRIM_LINES, 4); + immVertex2f(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP); + immVertex2f(pos, v2d->cur.xmax, yminc + NLACHANNEL_SKIP); + immVertex2f(pos, v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP); + immVertex2f(pos, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP); + immEnd(); + + /* black top-lines */ + GPU_line_width(1.0f); + immUniformColor3f(0.0f, 0.0f, 0.0f); + immBegin(GPU_PRIM_LINES, 4); + immVertex2f(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP); + immVertex2f(pos, v2d->cur.xmax, yminc + NLACHANNEL_SKIP); + immVertex2f(pos, v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP); + immVertex2f(pos, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP); + immEnd(); + + /* TODO: these lines but better --^ */ + + immUnbindProgram(); + + /* draw keyframes in the action */ + nla_action_draw_keyframes( + v2d, adt, ale->data, y, yminc + NLACHANNEL_SKIP, ymaxc - NLACHANNEL_SKIP); + + GPU_blend(false); + break; + } + } + } + + /* adjust y-position for next one */ + y -= NLACHANNEL_STEP(snla); + } + + /* free tempolary channels */ + ANIM_animdata_freelist(&anim_data); } /* *********************************************** */ @@ -772,95 +801,94 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar) void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - SpaceNla *snla = (SpaceNla *)ac->sl; - View2D *v2d = &ar->v2d; - float y = 0.0f; - size_t items; - - /* 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 NLACHANNEL_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. - */ - int height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2)); - /* don't use totrect set, as the width stays the same - * (NOTE: this is ok here, the configuration is pretty straightforward) - */ - v2d->tot.ymin = (float)(-height); - /* need to do a view-sync here, so that the keys area doesn't jump around - * (it must copy this) */ - UI_view2d_sync(NULL, ac->sa, v2d, V2D_LOCK_COPY); - - /* draw channels */ - { /* first pass: just the standard GL-drawing for backdrop + text */ - size_t channel_index = 0; - - y = (float)(-NLACHANNEL_HEIGHT(snla)); - - for (ale = anim_data.first; ale; ale = ale->next) { - float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla)); - float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla)); - - /* 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 -= NLACHANNEL_STEP(snla); - channel_index++; - } - } - { /* second pass: UI widgets */ - uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS); - size_t channel_index = 0; - - y = (float)(-NLACHANNEL_HEIGHT(snla)); - - /* 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); - - /* loop through channels, and set up drawing depending on their type */ - for (ale = anim_data.first; ale; ale = ale->next) { - const float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla)); - const float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla)); - - /* 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, yminc, ymaxc); - ANIM_channel_draw_widgets(C, ac, ale, block, &channel_rect, channel_index); - } - - /* adjust y-position for next one */ - y -= NLACHANNEL_STEP(snla); - channel_index++; - } - - UI_block_end(C, block); - UI_block_draw(C, block); - - GPU_blend(false); - } - - /* free temporary channels */ - ANIM_animdata_freelist(&anim_data); + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + SpaceNla *snla = (SpaceNla *)ac->sl; + View2D *v2d = &ar->v2d; + float y = 0.0f; + size_t items; + + /* 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 NLACHANNEL_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. + */ + int height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2)); + /* don't use totrect set, as the width stays the same + * (NOTE: this is ok here, the configuration is pretty straightforward) + */ + v2d->tot.ymin = (float)(-height); + /* need to do a view-sync here, so that the keys area doesn't jump around + * (it must copy this) */ + UI_view2d_sync(NULL, ac->sa, v2d, V2D_LOCK_COPY); + + /* draw channels */ + { /* first pass: just the standard GL-drawing for backdrop + text */ + size_t channel_index = 0; + + y = (float)(-NLACHANNEL_HEIGHT(snla)); + + for (ale = anim_data.first; ale; ale = ale->next) { + float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla)); + float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla)); + + /* 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 -= NLACHANNEL_STEP(snla); + channel_index++; + } + } + { /* second pass: UI widgets */ + uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS); + size_t channel_index = 0; + + y = (float)(-NLACHANNEL_HEIGHT(snla)); + + /* 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); + + /* loop through channels, and set up drawing depending on their type */ + for (ale = anim_data.first; ale; ale = ale->next) { + const float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla)); + const float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla)); + + /* 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, yminc, ymaxc); + ANIM_channel_draw_widgets(C, ac, ale, block, &channel_rect, channel_index); + } + + /* adjust y-position for next one */ + y -= NLACHANNEL_STEP(snla); + channel_index++; + } + + UI_block_end(C, block); + UI_block_draw(C, block); + + GPU_blend(false); + } + + /* free temporary channels */ + ANIM_animdata_freelist(&anim_data); } /* *********************************************** */ diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 1d21619fbd1..79c2242cd01 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -21,7 +21,6 @@ * \ingroup spnla */ - #include <string.h> #include <stdio.h> #include <math.h> @@ -66,8 +65,8 @@ #include "UI_resources.h" #include "UI_view2d.h" -#include "nla_intern.h" // own include -#include "nla_private.h" // FIXME... maybe this shouldn't be included? +#include "nla_intern.h" // own include +#include "nla_private.h" // FIXME... maybe this shouldn't be included? /* *********************************************** */ /* Utilities exported to other places... */ @@ -75,23 +74,23 @@ /* Perform validation for blending/extend settings */ void ED_nla_postop_refresh(bAnimContext *ac) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA | ANIMFILTER_FOREDIT); + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA | ANIMFILTER_FOREDIT); - /* get blocks to work on */ - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + /* get blocks to work on */ + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - for (ale = anim_data.first; ale; ale = ale->next) { - /* performing auto-blending, extend-mode validation, etc. */ - BKE_nla_validate_state(ale->data); + for (ale = anim_data.first; ale; ale = ale->next) { + /* performing auto-blending, extend-mode validation, etc. */ + BKE_nla_validate_state(ale->data); - ale->update |= ANIM_UPDATE_DEPS; - } + ale->update |= ANIM_UPDATE_DEPS; + } - /* free temp memory */ - ANIM_animdata_update(ac, &anim_data); - ANIM_animdata_freelist(&anim_data); + /* free temp memory */ + ANIM_animdata_update(ac, &anim_data); + ANIM_animdata_freelist(&anim_data); } /* *********************************************** */ @@ -104,92 +103,96 @@ void ED_nla_postop_refresh(bAnimContext *ac) static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - const bool do_solo = RNA_boolean_get(op->ptr, "isolate_action"); - bool ok = false; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* get a list of the AnimData blocks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - /* if no blocks, popup error? */ - if (BLI_listbase_is_empty(&anim_data)) { - BKE_report(op->reports, RPT_ERROR, "No AnimData blocks to enter tweak mode for"); - return OPERATOR_CANCELLED; - } - - /* for each AnimData block with NLA-data, try setting it in tweak-mode */ - for (ale = anim_data.first; ale; ale = ale->next) { - AnimData *adt = ale->data; - - /* try entering tweakmode if valid */ - ok |= BKE_nla_tweakmode_enter(adt); - - /* mark the active track as being "solo"? */ - if (do_solo && adt->actstrip) { - NlaTrack *nlt = BKE_nlatrack_find_tweaked(adt); - - if (nlt && !(nlt->flag & NLATRACK_SOLO)) { - BKE_nlatrack_solo_toggle(adt, nlt); - } - } - - ale->update |= ANIM_UPDATE_DEPS; - } - - /* free temp data */ - ANIM_animdata_update(&ac, &anim_data); - ANIM_animdata_freelist(&anim_data); - - /* if we managed to enter tweakmode on at least one AnimData block, - * set the flag for this in the active scene and send notifiers - */ - if (ac.scene && ok) { - /* set editing flag */ - ac.scene->flag |= SCE_NLA_EDIT_ON; - - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL); - } - else { - BKE_report(op->reports, RPT_ERROR, "No active strip(s) to enter tweak mode on"); - return OPERATOR_CANCELLED; - } - - /* done */ - return OPERATOR_FINISHED; + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + const bool do_solo = RNA_boolean_get(op->ptr, "isolate_action"); + bool ok = false; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the AnimData blocks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* if no blocks, popup error? */ + if (BLI_listbase_is_empty(&anim_data)) { + BKE_report(op->reports, RPT_ERROR, "No AnimData blocks to enter tweak mode for"); + return OPERATOR_CANCELLED; + } + + /* for each AnimData block with NLA-data, try setting it in tweak-mode */ + for (ale = anim_data.first; ale; ale = ale->next) { + AnimData *adt = ale->data; + + /* try entering tweakmode if valid */ + ok |= BKE_nla_tweakmode_enter(adt); + + /* mark the active track as being "solo"? */ + if (do_solo && adt->actstrip) { + NlaTrack *nlt = BKE_nlatrack_find_tweaked(adt); + + if (nlt && !(nlt->flag & NLATRACK_SOLO)) { + BKE_nlatrack_solo_toggle(adt, nlt); + } + } + + ale->update |= ANIM_UPDATE_DEPS; + } + + /* free temp data */ + ANIM_animdata_update(&ac, &anim_data); + ANIM_animdata_freelist(&anim_data); + + /* if we managed to enter tweakmode on at least one AnimData block, + * set the flag for this in the active scene and send notifiers + */ + if (ac.scene && ok) { + /* set editing flag */ + ac.scene->flag |= SCE_NLA_EDIT_ON; + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL); + } + else { + BKE_report(op->reports, RPT_ERROR, "No active strip(s) to enter tweak mode on"); + return OPERATOR_CANCELLED; + } + + /* done */ + return OPERATOR_FINISHED; } void NLA_OT_tweakmode_enter(wmOperatorType *ot) { - PropertyRNA *prop; - - /* identifiers */ - ot->name = "Enter Tweak Mode"; - ot->idname = "NLA_OT_tweakmode_enter"; - ot->description = "Enter tweaking mode for the action referenced by the active strip to edit its keyframes"; - - /* api callbacks */ - ot->exec = nlaedit_enable_tweakmode_exec; - ot->poll = nlaop_poll_tweakmode_off; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - prop = RNA_def_boolean(ot->srna, "isolate_action", 0, "Isolate Action", - "Enable 'solo' on the NLA Track containing the active strip, " - "to edit it without seeing the effects of the NLA stack"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Enter Tweak Mode"; + ot->idname = "NLA_OT_tweakmode_enter"; + ot->description = + "Enter tweaking mode for the action referenced by the active strip to edit its keyframes"; + + /* api callbacks */ + ot->exec = nlaedit_enable_tweakmode_exec; + ot->poll = nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + prop = RNA_def_boolean(ot->srna, + "isolate_action", + 0, + "Isolate Action", + "Enable 'solo' on the NLA Track containing the active strip, " + "to edit it without seeing the effects of the NLA stack"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* ------------- */ @@ -197,99 +200,100 @@ void NLA_OT_tweakmode_enter(wmOperatorType *ot) /* NLA Editor internal API function for exiting tweakmode */ bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - /* get a list of the AnimData blocks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* if no blocks, popup error? */ - if (BLI_listbase_is_empty(&anim_data)) { - BKE_report(ac->reports, RPT_ERROR, "No AnimData blocks in tweak mode to exit from"); - return false; - } - - /* for each AnimData block with NLA-data, try exitting tweak-mode */ - for (ale = anim_data.first; ale; ale = ale->next) { - AnimData *adt = ale->data; - - /* clear solo flags */ - if ((do_solo) & (adt->flag & ADT_NLA_SOLO_TRACK) && - (adt->flag & ADT_NLA_EDIT_ON)) - { - BKE_nlatrack_solo_toggle(adt, NULL); - } - - /* to be sure that we're doing everything right, just exit tweakmode... */ - BKE_nla_tweakmode_exit(adt); - - ale->update |= ANIM_UPDATE_DEPS; - } - - /* free temp data */ - ANIM_animdata_update(ac, &anim_data); - ANIM_animdata_freelist(&anim_data); - - /* if we managed to enter tweakmode on at least one AnimData block, - * set the flag for this in the active scene and send notifiers - */ - if (ac->scene) { - /* clear editing flag */ - ac->scene->flag &= ~SCE_NLA_EDIT_ON; - - /* set notifier that things have changed */ - WM_main_add_notifier(NC_ANIMATION | ND_NLA_ACTCHANGE, NULL); - } - - /* done */ - return true; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* get a list of the AnimData blocks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* if no blocks, popup error? */ + if (BLI_listbase_is_empty(&anim_data)) { + BKE_report(ac->reports, RPT_ERROR, "No AnimData blocks in tweak mode to exit from"); + return false; + } + + /* for each AnimData block with NLA-data, try exitting tweak-mode */ + for (ale = anim_data.first; ale; ale = ale->next) { + AnimData *adt = ale->data; + + /* clear solo flags */ + if ((do_solo) & (adt->flag & ADT_NLA_SOLO_TRACK) && (adt->flag & ADT_NLA_EDIT_ON)) { + BKE_nlatrack_solo_toggle(adt, NULL); + } + + /* to be sure that we're doing everything right, just exit tweakmode... */ + BKE_nla_tweakmode_exit(adt); + + ale->update |= ANIM_UPDATE_DEPS; + } + + /* free temp data */ + ANIM_animdata_update(ac, &anim_data); + ANIM_animdata_freelist(&anim_data); + + /* if we managed to enter tweakmode on at least one AnimData block, + * set the flag for this in the active scene and send notifiers + */ + if (ac->scene) { + /* clear editing flag */ + ac->scene->flag &= ~SCE_NLA_EDIT_ON; + + /* set notifier that things have changed */ + WM_main_add_notifier(NC_ANIMATION | ND_NLA_ACTCHANGE, NULL); + } + + /* done */ + return true; } /* exit tweakmode operator callback */ static int nlaedit_disable_tweakmode_exec(bContext *C, wmOperator *op) { - bAnimContext ac; + bAnimContext ac; - const bool do_solo = RNA_boolean_get(op->ptr, "isolate_action"); - bool ok = false; + const bool do_solo = RNA_boolean_get(op->ptr, "isolate_action"); + 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; - /* perform operation */ - ok = nlaedit_disable_tweakmode(&ac, do_solo); + /* perform operation */ + ok = nlaedit_disable_tweakmode(&ac, do_solo); - /* success? */ - if (ok) - return OPERATOR_FINISHED; - else - return OPERATOR_CANCELLED; + /* success? */ + if (ok) + return OPERATOR_FINISHED; + else + return OPERATOR_CANCELLED; } void NLA_OT_tweakmode_exit(wmOperatorType *ot) { - PropertyRNA *prop; - - /* identifiers */ - ot->name = "Exit Tweak Mode"; - ot->idname = "NLA_OT_tweakmode_exit"; - ot->description = "Exit tweaking mode for the action referenced by the active strip"; - - /* api callbacks */ - ot->exec = nlaedit_disable_tweakmode_exec; - ot->poll = nlaop_poll_tweakmode_on; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - prop = RNA_def_boolean(ot->srna, "isolate_action", 0, "Isolate Action", - "Disable 'solo' on any of the NLA Tracks after exiting tweak mode " - "to get things back to normal"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Exit Tweak Mode"; + ot->idname = "NLA_OT_tweakmode_exit"; + ot->description = "Exit tweaking mode for the action referenced by the active strip"; + + /* api callbacks */ + ot->exec = nlaedit_disable_tweakmode_exec; + ot->poll = nlaop_poll_tweakmode_on; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + prop = RNA_def_boolean(ot->srna, + "isolate_action", + 0, + "Isolate Action", + "Disable 'solo' on any of the NLA Tracks after exiting tweak mode " + "to get things back to normal"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* *********************************************** */ @@ -300,98 +304,98 @@ void NLA_OT_tweakmode_exit(wmOperatorType *ot) /* Get the min/max strip extents */ static void get_nlastrip_extents(bAnimContext *ac, float *min, float *max, const bool only_sel) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - bool found_bounds = false; - - /* get data to filter */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* set large values to try to override */ - *min = 999999999.0f; - *max = -999999999.0f; - - /* check if any channels to set range with */ - if (anim_data.first) { - /* go through channels, finding max extents */ - for (ale = anim_data.first; ale; ale = ale->next) { - NlaTrack *nlt = (NlaTrack *)ale->data; - NlaStrip *strip; - - for (strip = nlt->strips.first; strip; strip = strip->next) { - /* only consider selected strips? */ - if ((only_sel == false) || (strip->flag & NLASTRIP_FLAG_SELECT)) { - /* extend range if appropriate */ - *min = min_ff(*min, strip->start); - *max = max_ff(*max, strip->end); - - found_bounds = true; - } - } - } - - /* free memory */ - ANIM_animdata_freelist(&anim_data); - } - - /* set default range if nothing happened */ - if (found_bounds == false) { - if (ac->scene) { - *min = (float)ac->scene->r.sfra; - *max = (float)ac->scene->r.efra; - } - else { - *min = -5; - *max = 100; - } - } + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + bool found_bounds = false; + + /* get data to filter */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* set large values to try to override */ + *min = 999999999.0f; + *max = -999999999.0f; + + /* check if any channels to set range with */ + if (anim_data.first) { + /* go through channels, finding max extents */ + for (ale = anim_data.first; ale; ale = ale->next) { + NlaTrack *nlt = (NlaTrack *)ale->data; + NlaStrip *strip; + + for (strip = nlt->strips.first; strip; strip = strip->next) { + /* only consider selected strips? */ + if ((only_sel == false) || (strip->flag & NLASTRIP_FLAG_SELECT)) { + /* extend range if appropriate */ + *min = min_ff(*min, strip->start); + *max = max_ff(*max, strip->end); + + found_bounds = true; + } + } + } + + /* free memory */ + ANIM_animdata_freelist(&anim_data); + } + + /* set default range if nothing happened */ + if (found_bounds == false) { + if (ac->scene) { + *min = (float)ac->scene->r.sfra; + *max = (float)ac->scene->r.efra; + } + else { + *min = -5; + *max = 100; + } + } } /* ****************** Automatic Preview-Range Operator ****************** */ static int nlaedit_previewrange_exec(bContext *C, wmOperator *UNUSED(op)) { - 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; - - /* set the range directly */ - get_nlastrip_extents(&ac, &min, &max, true); - 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); - - return OPERATOR_FINISHED; + 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; + + /* set the range directly */ + get_nlastrip_extents(&ac, &min, &max, true); + 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); + + return OPERATOR_FINISHED; } void NLA_OT_previewrange_set(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Auto-Set Preview Range"; - ot->idname = "NLA_OT_previewrange_set"; - ot->description = "Automatically set Preview Range based on range of keyframes"; + /* identifiers */ + ot->name = "Auto-Set Preview Range"; + ot->idname = "NLA_OT_previewrange_set"; + ot->description = "Automatically set Preview Range based on range of keyframes"; - /* api callbacks */ - ot->exec = nlaedit_previewrange_exec; - ot->poll = ED_operator_nla_active; + /* api callbacks */ + ot->exec = nlaedit_previewrange_exec; + ot->poll = ED_operator_nla_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ****************** View-All Operator ****************** */ @@ -405,170 +409,169 @@ void NLA_OT_previewrange_set(wmOperatorType *ot) */ static bool nla_channels_get_selected_extents(bAnimContext *ac, float *min, float *max) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - SpaceNla *snla = (SpaceNla *)ac->sl; - const float half_height = NLACHANNEL_HEIGHT_HALF(snla); - /* NOTE: not bool, since we want prioritise individual channels over expanders */ - short found = 0; - float y; - - /* get all items - we need to do it this way */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* loop through all channels, finding the first one that's selected */ - y = (float)NLACHANNEL_FIRST; - - for (ale = anim_data.first; ale; ale = ale->next) { - const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); - - /* must be selected... */ - if (acf && acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT) && - ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT)) - { - /* update best estimate */ - *min = (float)(y - half_height); - *max = (float)(y + half_height); - - /* is this high enough priority yet? */ - found = acf->channel_role; - - /* only stop our search when we've found an actual channel - * - datablock expanders get less priority so that we don't abort prematurely - */ - if (found == ACHANNEL_ROLE_CHANNEL) { - break; - } - } - - /* adjust y-position for next one */ - y -= NLACHANNEL_STEP(snla); - } - - /* free all temp data */ - ANIM_animdata_freelist(&anim_data); - - return (found != 0); + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + SpaceNla *snla = (SpaceNla *)ac->sl; + const float half_height = NLACHANNEL_HEIGHT_HALF(snla); + /* NOTE: not bool, since we want prioritise individual channels over expanders */ + short found = 0; + float y; + + /* get all items - we need to do it this way */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* loop through all channels, finding the first one that's selected */ + y = (float)NLACHANNEL_FIRST; + + for (ale = anim_data.first; ale; ale = ale->next) { + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + + /* must be selected... */ + if (acf && acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT) && + ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT)) { + /* update best estimate */ + *min = (float)(y - half_height); + *max = (float)(y + half_height); + + /* is this high enough priority yet? */ + found = acf->channel_role; + + /* only stop our search when we've found an actual channel + * - datablock expanders get less priority so that we don't abort prematurely + */ + if (found == ACHANNEL_ROLE_CHANNEL) { + break; + } + } + + /* adjust y-position for next one */ + y -= NLACHANNEL_STEP(snla); + } + + /* free all temp data */ + ANIM_animdata_freelist(&anim_data); + + return (found != 0); } static int nlaedit_viewall(bContext *C, const bool only_sel) { - bAnimContext ac; - View2D *v2d; - float extra; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - v2d = &ac.ar->v2d; - - /* set the horizontal range, with an extra offset so that the extreme keys will be in view */ - get_nlastrip_extents(&ac, &v2d->cur.xmin, &v2d->cur.xmax, only_sel); - - extra = 0.1f * BLI_rctf_size_x(&v2d->cur); - v2d->cur.xmin -= extra; - v2d->cur.xmax += extra; - - /* set vertical range */ - if (only_sel == false) { - /* view all -> the summary channel is usually the shows everything, - * and resides right at the top... */ - v2d->cur.ymax = 0.0f; - v2d->cur.ymin = (float)-BLI_rcti_size_y(&v2d->mask); - } - else { - /* locate first selected channel (or the active one), and frame those */ - float ymin = v2d->cur.ymin; - float ymax = v2d->cur.ymax; - - if (nla_channels_get_selected_extents(&ac, &ymin, &ymax)) { - /* recenter the view so that this range is in the middle */ - float ymid = (ymax - ymin) / 2.0f + ymin; - float x_center; - - UI_view2d_center_get(v2d, &x_center, NULL); - UI_view2d_center_set(v2d, x_center, ymid); - } - } - - /* do View2D syncing */ - UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY); - - /* just redraw this view */ - ED_area_tag_redraw(CTX_wm_area(C)); - - return OPERATOR_FINISHED; + bAnimContext ac; + View2D *v2d; + float extra; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + v2d = &ac.ar->v2d; + + /* set the horizontal range, with an extra offset so that the extreme keys will be in view */ + get_nlastrip_extents(&ac, &v2d->cur.xmin, &v2d->cur.xmax, only_sel); + + extra = 0.1f * BLI_rctf_size_x(&v2d->cur); + v2d->cur.xmin -= extra; + v2d->cur.xmax += extra; + + /* set vertical range */ + if (only_sel == false) { + /* view all -> the summary channel is usually the shows everything, + * and resides right at the top... */ + v2d->cur.ymax = 0.0f; + v2d->cur.ymin = (float)-BLI_rcti_size_y(&v2d->mask); + } + else { + /* locate first selected channel (or the active one), and frame those */ + float ymin = v2d->cur.ymin; + float ymax = v2d->cur.ymax; + + if (nla_channels_get_selected_extents(&ac, &ymin, &ymax)) { + /* recenter the view so that this range is in the middle */ + float ymid = (ymax - ymin) / 2.0f + ymin; + float x_center; + + UI_view2d_center_get(v2d, &x_center, NULL); + UI_view2d_center_set(v2d, x_center, ymid); + } + } + + /* do View2D syncing */ + UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY); + + /* just redraw this view */ + ED_area_tag_redraw(CTX_wm_area(C)); + + return OPERATOR_FINISHED; } /* ......... */ static int nlaedit_viewall_exec(bContext *C, wmOperator *UNUSED(op)) { - /* whole range */ - return nlaedit_viewall(C, false); + /* whole range */ + return nlaedit_viewall(C, false); } static int nlaedit_viewsel_exec(bContext *C, wmOperator *UNUSED(op)) { - /* only selected */ - return nlaedit_viewall(C, true); + /* only selected */ + return nlaedit_viewall(C, true); } void NLA_OT_view_all(wmOperatorType *ot) { - /* identifiers */ - ot->name = "View All"; - ot->idname = "NLA_OT_view_all"; - ot->description = "Reset viewable area to show full strips range"; + /* identifiers */ + ot->name = "View All"; + ot->idname = "NLA_OT_view_all"; + ot->description = "Reset viewable area to show full strips range"; - /* api callbacks */ - ot->exec = nlaedit_viewall_exec; - ot->poll = ED_operator_nla_active; + /* api callbacks */ + ot->exec = nlaedit_viewall_exec; + ot->poll = ED_operator_nla_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } void NLA_OT_view_selected(wmOperatorType *ot) { - /* identifiers */ - ot->name = "View Selected"; - ot->idname = "NLA_OT_view_selected"; - ot->description = "Reset viewable area to show selected strips range"; + /* identifiers */ + ot->name = "View Selected"; + ot->idname = "NLA_OT_view_selected"; + ot->description = "Reset viewable area to show selected strips range"; - /* api callbacks */ - ot->exec = nlaedit_viewsel_exec; - ot->poll = ED_operator_nla_active; + /* api callbacks */ + ot->exec = nlaedit_viewsel_exec; + ot->poll = ED_operator_nla_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* *********************************************** */ static int nlaedit_viewframe_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 NLA_OT_view_frame(wmOperatorType *ot) { - /* identifiers */ - ot->name = "View Frame"; - ot->idname = "NLA_OT_view_frame"; - ot->description = "Reset viewable area to show range around current frame"; + /* identifiers */ + ot->name = "View Frame"; + ot->idname = "NLA_OT_view_frame"; + ot->description = "Reset viewable area to show range around current frame"; - /* api callbacks */ - ot->exec = nlaedit_viewframe_exec; - ot->poll = ED_operator_nla_active; + /* api callbacks */ + ot->exec = nlaedit_viewframe_exec; + ot->poll = ED_operator_nla_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* *********************************************** */ @@ -578,138 +581,144 @@ void NLA_OT_view_frame(wmOperatorType *ot) /* Add a new Action-Clip strip to the active track * (or the active block if no space in the track) */ - /* add the specified action as new strip */ static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - Scene *scene; - - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - size_t items; - int filter; - - bAction *act; - - float cfra; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - scene = ac.scene; - cfra = (float)CFRA; - - /* get action to use */ - act = BLI_findlink(&CTX_data_main(C)->actions, RNA_enum_get(op->ptr, "action")); - - if (act == NULL) { - BKE_report(op->reports, RPT_ERROR, "No valid action to add"); - //printf("Add strip - actname = '%s'\n", actname); - return OPERATOR_CANCELLED; - } - else if (act->idroot == 0) { - /* hopefully in this case (i.e. library of userless actions), - * the user knows what they're doing... */ - BKE_reportf(op->reports, RPT_WARNING, - "Action '%s' does not specify what data-blocks it can be used on " - "(try setting the 'ID Root Type' setting from the data-blocks editor " - "for this action to avoid future problems)", - act->id.name + 2); - } - - /* add tracks to empty but selected animdata blocks so that strips can be added to those directly - * without having to manually add tracks first - */ - nlaedit_add_tracks_empty(&ac); - - /* get a list of the editable tracks being shown in the NLA - * - this is limited to active ones for now, but could be expanded to - */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_FOREDIT); - items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - if (items == 0) { - BKE_report(op->reports, RPT_ERROR, - "No active track(s) to add strip to, select an existing track or add one before trying again"); - return OPERATOR_CANCELLED; - } - - /* for every active track, - * try to add strip to free space in track or to the top of the stack if no space */ - for (ale = anim_data.first; ale; ale = ale->next) { - NlaTrack *nlt = (NlaTrack *)ale->data; - AnimData *adt = ale->adt; - NlaStrip *strip = NULL; - - /* sanity check: only apply actions of the right type for this ID - * NOTE: in the case that this hasn't been set, we've already warned the user about this already - */ - if ((act->idroot) && (act->idroot != GS(ale->id->name))) { - BKE_reportf(op->reports, RPT_ERROR, - "Could not add action '%s' as it cannot be used relative to ID-blocks of type '%s'", - act->id.name + 2, ale->id->name); - continue; - } - - /* create a new strip, and offset it to start on the current frame */ - strip = BKE_nlastrip_new(act); - - strip->end += (cfra - strip->start); - strip->start = cfra; - - /* firstly try adding strip to our current track, but if that fails, add to a new track */ - if (BKE_nlatrack_add_strip(nlt, strip) == 0) { - /* trying to add to the current failed (no space), - * so add a new track to the stack, and add to that... - */ - nlt = BKE_nlatrack_add(adt, NULL); - BKE_nlatrack_add_strip(nlt, strip); - } - - /* auto-name it */ - BKE_nlastrip_validate_name(adt, strip); - } - - /* free temp data */ - ANIM_animdata_freelist(&anim_data); - - /* refresh auto strip properties */ - ED_nla_postop_refresh(&ac); - - DEG_relations_tag_update(ac.bmain); - - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); - - /* done */ - return OPERATOR_FINISHED; + bAnimContext ac; + Scene *scene; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + size_t items; + int filter; + + bAction *act; + + float cfra; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + scene = ac.scene; + cfra = (float)CFRA; + + /* get action to use */ + act = BLI_findlink(&CTX_data_main(C)->actions, RNA_enum_get(op->ptr, "action")); + + if (act == NULL) { + BKE_report(op->reports, RPT_ERROR, "No valid action to add"); + //printf("Add strip - actname = '%s'\n", actname); + return OPERATOR_CANCELLED; + } + else if (act->idroot == 0) { + /* hopefully in this case (i.e. library of userless actions), + * the user knows what they're doing... */ + BKE_reportf(op->reports, + RPT_WARNING, + "Action '%s' does not specify what data-blocks it can be used on " + "(try setting the 'ID Root Type' setting from the data-blocks editor " + "for this action to avoid future problems)", + act->id.name + 2); + } + + /* add tracks to empty but selected animdata blocks so that strips can be added to those directly + * without having to manually add tracks first + */ + nlaedit_add_tracks_empty(&ac); + + /* get a list of the editable tracks being shown in the NLA + * - this is limited to active ones for now, but could be expanded to + */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_FOREDIT); + items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + if (items == 0) { + BKE_report(op->reports, + RPT_ERROR, + "No active track(s) to add strip to, select an existing track or add one before " + "trying again"); + return OPERATOR_CANCELLED; + } + + /* for every active track, + * try to add strip to free space in track or to the top of the stack if no space */ + for (ale = anim_data.first; ale; ale = ale->next) { + NlaTrack *nlt = (NlaTrack *)ale->data; + AnimData *adt = ale->adt; + NlaStrip *strip = NULL; + + /* sanity check: only apply actions of the right type for this ID + * NOTE: in the case that this hasn't been set, we've already warned the user about this already + */ + if ((act->idroot) && (act->idroot != GS(ale->id->name))) { + BKE_reportf( + op->reports, + RPT_ERROR, + "Could not add action '%s' as it cannot be used relative to ID-blocks of type '%s'", + act->id.name + 2, + ale->id->name); + continue; + } + + /* create a new strip, and offset it to start on the current frame */ + strip = BKE_nlastrip_new(act); + + strip->end += (cfra - strip->start); + strip->start = cfra; + + /* firstly try adding strip to our current track, but if that fails, add to a new track */ + if (BKE_nlatrack_add_strip(nlt, strip) == 0) { + /* trying to add to the current failed (no space), + * so add a new track to the stack, and add to that... + */ + nlt = BKE_nlatrack_add(adt, NULL); + BKE_nlatrack_add_strip(nlt, strip); + } + + /* auto-name it */ + BKE_nlastrip_validate_name(adt, strip); + } + + /* free temp data */ + ANIM_animdata_freelist(&anim_data); + + /* refresh auto strip properties */ + ED_nla_postop_refresh(&ac); + + DEG_relations_tag_update(ac.bmain); + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; } void NLA_OT_actionclip_add(wmOperatorType *ot) { - PropertyRNA *prop; - - /* identifiers */ - ot->name = "Add Action Strip"; - ot->idname = "NLA_OT_actionclip_add"; - ot->description = "Add an Action-Clip strip (i.e. an NLA Strip referencing an Action) to the active track"; - - /* api callbacks */ - ot->invoke = WM_enum_search_invoke; - ot->exec = nlaedit_add_actionclip_exec; - ot->poll = nlaop_poll_tweakmode_off; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* props */ - // TODO: this would be nicer as an ID-pointer... - prop = RNA_def_enum(ot->srna, "action", DummyRNA_NULL_items, 0, "Action", ""); - RNA_def_enum_funcs(prop, RNA_action_itemf); - RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE); - ot->prop = prop; + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Add Action Strip"; + ot->idname = "NLA_OT_actionclip_add"; + ot->description = + "Add an Action-Clip strip (i.e. an NLA Strip referencing an Action) to the active track"; + + /* api callbacks */ + ot->invoke = WM_enum_search_invoke; + ot->exec = nlaedit_add_actionclip_exec; + ot->poll = nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* props */ + // TODO: this would be nicer as an ID-pointer... + prop = RNA_def_enum(ot->srna, "action", DummyRNA_NULL_items, 0, "Action", ""); + RNA_def_enum_funcs(prop, RNA_action_itemf); + RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE); + ot->prop = prop; } /* ******************** Add Transition Operator ***************************** */ @@ -717,117 +726,119 @@ void NLA_OT_actionclip_add(wmOperatorType *ot) static int nlaedit_add_transition_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - bool done = false; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* get a list of the editable tracks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - /* for each track, find pairs of strips to add transitions to */ - for (ale = anim_data.first; ale; ale = ale->next) { - NlaTrack *nlt = (NlaTrack *)ale->data; - AnimData *adt = ale->adt; - NlaStrip *s1, *s2; - - /* get initial pair of strips */ - if (ELEM(nlt->strips.first, NULL, nlt->strips.last)) - continue; - s1 = nlt->strips.first; - s2 = s1->next; - - /* loop over strips */ - for (; s1 && s2; s1 = s2, s2 = s2->next) { - NlaStrip *strip; - - /* check if both are selected */ - if (ELEM(0, (s1->flag & NLASTRIP_FLAG_SELECT), (s2->flag & NLASTRIP_FLAG_SELECT))) - continue; - /* check if there's space between the two */ - if (IS_EQF(s1->end, s2->start)) - continue; - /* make sure neither one is a transition - * - although this is impossible to create with the standard tools, - * the user may have altered the settings - */ - if (ELEM(NLASTRIP_TYPE_TRANSITION, s1->type, s2->type)) - continue; - /* also make sure neither one is a soundclip */ - if (ELEM(NLASTRIP_TYPE_SOUND, s1->type, s2->type)) - continue; - - /* allocate new strip */ - strip = MEM_callocN(sizeof(NlaStrip), "NlaStrip"); - BLI_insertlinkafter(&nlt->strips, s1, strip); - - /* set the type */ - strip->type = NLASTRIP_TYPE_TRANSITION; - - /* generic settings - * - selected flag to highlight this to the user - * - auto-blends to ensure that blend in/out values are automatically - * determined by overlaps of strips - */ - strip->flag = NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_AUTO_BLENDS; - - /* range is simply defined as the endpoints of the adjacent strips */ - strip->start = s1->end; - strip->end = s2->start; - - /* scale and repeat aren't of any use, but shouldn't ever be 0 */ - strip->scale = 1.0f; - strip->repeat = 1.0f; - - /* auto-name it */ - BKE_nlastrip_validate_name(adt, strip); - - /* make note of this */ - done = true; - } - } - - /* free temp data */ - ANIM_animdata_freelist(&anim_data); - - /* was anything added? */ - if (done) { - /* refresh auto strip properties */ - ED_nla_postop_refresh(&ac); - - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); - - /* done */ - return OPERATOR_FINISHED; - } - else { - BKE_report(op->reports, RPT_ERROR, "Needs at least a pair of adjacent selected strips with a gap between them"); - return OPERATOR_CANCELLED; - } + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + bool done = false; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the editable tracks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* for each track, find pairs of strips to add transitions to */ + for (ale = anim_data.first; ale; ale = ale->next) { + NlaTrack *nlt = (NlaTrack *)ale->data; + AnimData *adt = ale->adt; + NlaStrip *s1, *s2; + + /* get initial pair of strips */ + if (ELEM(nlt->strips.first, NULL, nlt->strips.last)) + continue; + s1 = nlt->strips.first; + s2 = s1->next; + + /* loop over strips */ + for (; s1 && s2; s1 = s2, s2 = s2->next) { + NlaStrip *strip; + + /* check if both are selected */ + if (ELEM(0, (s1->flag & NLASTRIP_FLAG_SELECT), (s2->flag & NLASTRIP_FLAG_SELECT))) + continue; + /* check if there's space between the two */ + if (IS_EQF(s1->end, s2->start)) + continue; + /* make sure neither one is a transition + * - although this is impossible to create with the standard tools, + * the user may have altered the settings + */ + if (ELEM(NLASTRIP_TYPE_TRANSITION, s1->type, s2->type)) + continue; + /* also make sure neither one is a soundclip */ + if (ELEM(NLASTRIP_TYPE_SOUND, s1->type, s2->type)) + continue; + + /* allocate new strip */ + strip = MEM_callocN(sizeof(NlaStrip), "NlaStrip"); + BLI_insertlinkafter(&nlt->strips, s1, strip); + + /* set the type */ + strip->type = NLASTRIP_TYPE_TRANSITION; + + /* generic settings + * - selected flag to highlight this to the user + * - auto-blends to ensure that blend in/out values are automatically + * determined by overlaps of strips + */ + strip->flag = NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_AUTO_BLENDS; + + /* range is simply defined as the endpoints of the adjacent strips */ + strip->start = s1->end; + strip->end = s2->start; + + /* scale and repeat aren't of any use, but shouldn't ever be 0 */ + strip->scale = 1.0f; + strip->repeat = 1.0f; + + /* auto-name it */ + BKE_nlastrip_validate_name(adt, strip); + + /* make note of this */ + done = true; + } + } + + /* free temp data */ + ANIM_animdata_freelist(&anim_data); + + /* was anything added? */ + if (done) { + /* refresh auto strip properties */ + ED_nla_postop_refresh(&ac); + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; + } + else { + BKE_report(op->reports, + RPT_ERROR, + "Needs at least a pair of adjacent selected strips with a gap between them"); + return OPERATOR_CANCELLED; + } } void NLA_OT_transition_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Transition"; - ot->idname = "NLA_OT_transition_add"; - ot->description = "Add a transition strip between two adjacent selected strips"; + /* identifiers */ + ot->name = "Add Transition"; + ot->idname = "NLA_OT_transition_add"; + ot->description = "Add a transition strip between two adjacent selected strips"; - /* api callbacks */ - ot->exec = nlaedit_add_transition_exec; - ot->poll = nlaop_poll_tweakmode_off; + /* api callbacks */ + ot->exec = nlaedit_add_transition_exec; + ot->poll = nlaop_poll_tweakmode_off; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ******************** Add Sound Clip Operator ***************************** */ @@ -835,84 +846,85 @@ void NLA_OT_transition_add(wmOperatorType *ot) static int nlaedit_add_sound_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; - Scene *scene; - int cfra; + Scene *scene; + int cfra; - /* 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; - scene = ac.scene; - cfra = CFRA; + scene = ac.scene; + cfra = CFRA; - /* get a list of the editable tracks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + /* get a list of the editable tracks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | + ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - /* for each track, add sound clips if it belongs to a speaker */ - // TODO: what happens if there aren't any tracks... well that's a more general problem for later - for (ale = anim_data.first; ale; ale = ale->next) { - Object *ob = (Object *)ale->id; /* may not be object until we actually check! */ + /* for each track, add sound clips if it belongs to a speaker */ + // TODO: what happens if there aren't any tracks... well that's a more general problem for later + for (ale = anim_data.first; ale; ale = ale->next) { + Object *ob = (Object *)ale->id; /* may not be object until we actually check! */ - AnimData *adt = ale->adt; - NlaTrack *nlt = (NlaTrack *)ale->data; - NlaStrip *strip; + AnimData *adt = ale->adt; + NlaTrack *nlt = (NlaTrack *)ale->data; + NlaStrip *strip; - /* does this belong to speaker - assumed to live on Object level only */ - if ((GS(ale->id->name) != ID_OB) || (ob->type != OB_SPEAKER)) - continue; + /* does this belong to speaker - assumed to live on Object level only */ + if ((GS(ale->id->name) != ID_OB) || (ob->type != OB_SPEAKER)) + continue; - /* create a new strip, and offset it to start on the current frame */ - strip = BKE_nla_add_soundstrip(ac.scene, ob->data); + /* create a new strip, and offset it to start on the current frame */ + strip = BKE_nla_add_soundstrip(ac.scene, ob->data); - strip->start += cfra; - strip->end += cfra; + strip->start += cfra; + strip->end += cfra; - /* firstly try adding strip to our current track, but if that fails, add to a new track */ - if (BKE_nlatrack_add_strip(nlt, strip) == 0) { - /* trying to add to the current failed (no space), - * so add a new track to the stack, and add to that... - */ - nlt = BKE_nlatrack_add(adt, NULL); - BKE_nlatrack_add_strip(nlt, strip); - } + /* firstly try adding strip to our current track, but if that fails, add to a new track */ + if (BKE_nlatrack_add_strip(nlt, strip) == 0) { + /* trying to add to the current failed (no space), + * so add a new track to the stack, and add to that... + */ + nlt = BKE_nlatrack_add(adt, NULL); + BKE_nlatrack_add_strip(nlt, strip); + } - /* auto-name it */ - BKE_nlastrip_validate_name(adt, strip); - } + /* auto-name it */ + BKE_nlastrip_validate_name(adt, strip); + } - /* free temp data */ - ANIM_animdata_freelist(&anim_data); + /* free temp data */ + ANIM_animdata_freelist(&anim_data); - /* refresh auto strip properties */ - ED_nla_postop_refresh(&ac); + /* refresh auto strip properties */ + ED_nla_postop_refresh(&ac); - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); - /* done */ - return OPERATOR_FINISHED; + /* done */ + return OPERATOR_FINISHED; } void NLA_OT_soundclip_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Sound Clip"; - ot->idname = "NLA_OT_soundclip_add"; - ot->description = "Add a strip for controlling when speaker plays its sound clip"; + /* identifiers */ + ot->name = "Add Sound Clip"; + ot->idname = "NLA_OT_soundclip_add"; + ot->description = "Add a strip for controlling when speaker plays its sound clip"; - /* api callbacks */ - ot->exec = nlaedit_add_sound_exec; - ot->poll = nlaop_poll_tweakmode_off; + /* api callbacks */ + ot->exec = nlaedit_add_sound_exec; + ot->poll = nlaop_poll_tweakmode_off; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ******************** Add Meta-Strip Operator ***************************** */ @@ -921,63 +933,63 @@ void NLA_OT_soundclip_add(wmOperatorType *ot) /* add the specified action as new strip */ static int nlaedit_add_meta_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; - /* 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 a list of the editable tracks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + /* get a list of the editable tracks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - /* for each track, find pairs of strips to add transitions to */ - for (ale = anim_data.first; ale; ale = ale->next) { - NlaTrack *nlt = (NlaTrack *)ale->data; - AnimData *adt = ale->adt; - NlaStrip *strip; + /* for each track, find pairs of strips to add transitions to */ + for (ale = anim_data.first; ale; ale = ale->next) { + NlaTrack *nlt = (NlaTrack *)ale->data; + AnimData *adt = ale->adt; + NlaStrip *strip; - /* create meta-strips from the continuous chains of selected strips */ - BKE_nlastrips_make_metas(&nlt->strips, 0); + /* create meta-strips from the continuous chains of selected strips */ + BKE_nlastrips_make_metas(&nlt->strips, 0); - /* name the metas */ - for (strip = nlt->strips.first; strip; strip = strip->next) { - /* auto-name this strip if selected (that means it is a meta) */ - if (strip->flag & NLASTRIP_FLAG_SELECT) - BKE_nlastrip_validate_name(adt, strip); - } + /* name the metas */ + for (strip = nlt->strips.first; strip; strip = strip->next) { + /* auto-name this strip if selected (that means it is a meta) */ + if (strip->flag & NLASTRIP_FLAG_SELECT) + BKE_nlastrip_validate_name(adt, strip); + } - ale->update |= ANIM_UPDATE_DEPS; - } + ale->update |= ANIM_UPDATE_DEPS; + } - /* free temp data */ - ANIM_animdata_update(&ac, &anim_data); - ANIM_animdata_freelist(&anim_data); + /* free temp 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_NLA | NA_EDITED, NULL); + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); - /* done */ - return OPERATOR_FINISHED; + /* done */ + return OPERATOR_FINISHED; } void NLA_OT_meta_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Meta-Strips"; - ot->idname = "NLA_OT_meta_add"; - ot->description = "Add new meta-strips incorporating the selected strips"; + /* identifiers */ + ot->name = "Add Meta-Strips"; + ot->idname = "NLA_OT_meta_add"; + ot->description = "Add new meta-strips incorporating the selected strips"; - /* api callbacks */ - ot->exec = nlaedit_add_meta_exec; - ot->poll = nlaop_poll_tweakmode_off; + /* api callbacks */ + ot->exec = nlaedit_add_meta_exec; + ot->poll = nlaop_poll_tweakmode_off; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ******************** Remove Meta-Strip Operator ***************************** */ @@ -985,54 +997,54 @@ void NLA_OT_meta_add(wmOperatorType *ot) static int nlaedit_remove_meta_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; - /* 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 a list of the editable tracks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + /* get a list of the editable tracks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - /* for each track, find pairs of strips to add transitions to */ - for (ale = anim_data.first; ale; ale = ale->next) { - NlaTrack *nlt = (NlaTrack *)ale->data; + /* for each track, find pairs of strips to add transitions to */ + for (ale = anim_data.first; ale; ale = ale->next) { + NlaTrack *nlt = (NlaTrack *)ale->data; - /* clear all selected meta-strips, regardless of whether they are temporary or not */ - BKE_nlastrips_clear_metas(&nlt->strips, 1, 0); + /* clear all selected meta-strips, regardless of whether they are temporary or not */ + BKE_nlastrips_clear_metas(&nlt->strips, 1, 0); - ale->update |= ANIM_UPDATE_DEPS; - } + ale->update |= ANIM_UPDATE_DEPS; + } - /* free temp data */ - ANIM_animdata_update(&ac, &anim_data); - ANIM_animdata_freelist(&anim_data); + /* free temp 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_NLA | NA_EDITED, NULL); + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); - /* done */ - return OPERATOR_FINISHED; + /* done */ + return OPERATOR_FINISHED; } void NLA_OT_meta_remove(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Remove Meta-Strips"; - ot->idname = "NLA_OT_meta_remove"; - ot->description = "Separate out the strips held by the selected meta-strips"; + /* identifiers */ + ot->name = "Remove Meta-Strips"; + ot->idname = "NLA_OT_meta_remove"; + ot->description = "Separate out the strips held by the selected meta-strips"; - /* api callbacks */ - ot->exec = nlaedit_remove_meta_exec; - ot->poll = nlaop_poll_tweakmode_off; + /* api callbacks */ + ot->exec = nlaedit_remove_meta_exec; + ot->poll = nlaop_poll_tweakmode_off; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ******************** Duplicate Strips Operator ************************** */ @@ -1042,113 +1054,118 @@ void NLA_OT_meta_remove(wmOperatorType *ot) static int nlaedit_duplicate_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - bool linked = RNA_boolean_get(op->ptr, "linked"); - bool done = false; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* get a list of editable tracks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - /* duplicate strips in tracks starting from the last one so that we're - * less likely to duplicate strips we just duplicated... - */ - for (ale = anim_data.last; ale; ale = ale->prev) { - NlaTrack *nlt = (NlaTrack *)ale->data; - AnimData *adt = ale->adt; - NlaStrip *strip, *nstrip, *next; - NlaTrack *track; - - for (strip = nlt->strips.first; strip; strip = next) { - next = strip->next; - - /* if selected, split the strip at its midpoint */ - if (strip->flag & NLASTRIP_FLAG_SELECT) { - /* make a copy (assume that this is possible) */ - nstrip = BKE_nlastrip_copy(ac.bmain, strip, linked, 0); - - /* in case there's no space in the track above, - * or we haven't got a reference to it yet, try adding */ - if (BKE_nlatrack_add_strip(nlt->next, nstrip) == 0) { - /* need to add a new track above the one above the current one - * - if the current one is the last one, nlt->next will be NULL, which defaults to adding - * at the top of the stack anyway... - */ - track = BKE_nlatrack_add(adt, nlt->next); - BKE_nlatrack_add_strip(track, nstrip); - } - - /* deselect the original and the active flag */ - strip->flag &= ~(NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_ACTIVE); - - /* auto-name newly created strip */ - BKE_nlastrip_validate_name(adt, nstrip); - - done = true; - } - } - } - - /* free temp data */ - ANIM_animdata_freelist(&anim_data); - - if (done) { - /* refresh auto strip properties */ - ED_nla_postop_refresh(&ac); - - if (!linked) { - DEG_relations_tag_update(ac.bmain); - } - - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); - - /* done */ - return OPERATOR_FINISHED; - } - else - return OPERATOR_CANCELLED; + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + bool linked = RNA_boolean_get(op->ptr, "linked"); + bool done = false; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of editable tracks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* duplicate strips in tracks starting from the last one so that we're + * less likely to duplicate strips we just duplicated... + */ + for (ale = anim_data.last; ale; ale = ale->prev) { + NlaTrack *nlt = (NlaTrack *)ale->data; + AnimData *adt = ale->adt; + NlaStrip *strip, *nstrip, *next; + NlaTrack *track; + + for (strip = nlt->strips.first; strip; strip = next) { + next = strip->next; + + /* if selected, split the strip at its midpoint */ + if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* make a copy (assume that this is possible) */ + nstrip = BKE_nlastrip_copy(ac.bmain, strip, linked, 0); + + /* in case there's no space in the track above, + * or we haven't got a reference to it yet, try adding */ + if (BKE_nlatrack_add_strip(nlt->next, nstrip) == 0) { + /* need to add a new track above the one above the current one + * - if the current one is the last one, nlt->next will be NULL, which defaults to adding + * at the top of the stack anyway... + */ + track = BKE_nlatrack_add(adt, nlt->next); + BKE_nlatrack_add_strip(track, nstrip); + } + + /* deselect the original and the active flag */ + strip->flag &= ~(NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_ACTIVE); + + /* auto-name newly created strip */ + BKE_nlastrip_validate_name(adt, nstrip); + + done = true; + } + } + } + + /* free temp data */ + ANIM_animdata_freelist(&anim_data); + + if (done) { + /* refresh auto strip properties */ + ED_nla_postop_refresh(&ac); + + if (!linked) { + DEG_relations_tag_update(ac.bmain); + } + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; + } + else + return OPERATOR_CANCELLED; } static int nlaedit_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - nlaedit_duplicate_exec(C, op); + nlaedit_duplicate_exec(C, op); - RNA_enum_set(op->ptr, "mode", TFM_TRANSLATION); - WM_operator_name_call(C, "TRANSFORM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr); + RNA_enum_set(op->ptr, "mode", TFM_TRANSLATION); + WM_operator_name_call(C, "TRANSFORM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void NLA_OT_duplicate(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Duplicate Strips"; - ot->idname = "NLA_OT_duplicate"; - ot->description = "Duplicate selected NLA-Strips, adding the new strips in new tracks above the originals"; - - /* api callbacks */ - ot->invoke = nlaedit_duplicate_invoke; - ot->exec = nlaedit_duplicate_exec; - ot->poll = nlaop_poll_tweakmode_off; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* own properties */ - ot->prop = RNA_def_boolean(ot->srna, "linked", false, "Linked", "When duplicating strips, assign new copies of the actions they use"); - - /* to give to transform */ - RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", ""); + /* identifiers */ + ot->name = "Duplicate Strips"; + ot->idname = "NLA_OT_duplicate"; + ot->description = + "Duplicate selected NLA-Strips, adding the new strips in new tracks above the originals"; + + /* api callbacks */ + ot->invoke = nlaedit_duplicate_invoke; + ot->exec = nlaedit_duplicate_exec; + ot->poll = nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* own properties */ + ot->prop = RNA_def_boolean(ot->srna, + "linked", + false, + "Linked", + "When duplicating strips, assign new copies of the actions they use"); + + /* to give to transform */ + RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", ""); } /* ******************** Delete Strips Operator ***************************** */ @@ -1156,72 +1173,72 @@ void NLA_OT_duplicate(wmOperatorType *ot) static int nlaedit_delete_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; - /* 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 a list of the editable tracks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + /* get a list of the editable tracks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - /* for each NLA-Track, delete all selected strips */ - for (ale = anim_data.first; ale; ale = ale->next) { - NlaTrack *nlt = (NlaTrack *)ale->data; - NlaStrip *strip, *nstrip; + /* for each NLA-Track, delete all selected strips */ + for (ale = anim_data.first; ale; ale = ale->next) { + NlaTrack *nlt = (NlaTrack *)ale->data; + NlaStrip *strip, *nstrip; - for (strip = nlt->strips.first; strip; strip = nstrip) { - nstrip = strip->next; + for (strip = nlt->strips.first; strip; strip = nstrip) { + nstrip = strip->next; - /* if selected, delete */ - if (strip->flag & NLASTRIP_FLAG_SELECT) { - /* if a strip either side of this was a transition, delete those too */ - if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION)) - BKE_nlastrip_free(&nlt->strips, strip->prev, true); - if ((nstrip) && (nstrip->type == NLASTRIP_TYPE_TRANSITION)) { - nstrip = nstrip->next; - BKE_nlastrip_free(&nlt->strips, strip->next, true); - } + /* if selected, delete */ + if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* if a strip either side of this was a transition, delete those too */ + if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION)) + BKE_nlastrip_free(&nlt->strips, strip->prev, true); + if ((nstrip) && (nstrip->type == NLASTRIP_TYPE_TRANSITION)) { + nstrip = nstrip->next; + BKE_nlastrip_free(&nlt->strips, strip->next, true); + } - /* finally, delete this strip */ - BKE_nlastrip_free(&nlt->strips, strip, true); - } - } - } + /* finally, delete this strip */ + BKE_nlastrip_free(&nlt->strips, strip, true); + } + } + } - /* free temp data */ - ANIM_animdata_freelist(&anim_data); + /* free temp data */ + ANIM_animdata_freelist(&anim_data); - /* refresh auto strip properties */ - ED_nla_postop_refresh(&ac); + /* refresh auto strip properties */ + ED_nla_postop_refresh(&ac); - DEG_relations_tag_update(ac.bmain); + DEG_relations_tag_update(ac.bmain); - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); - /* done */ - return OPERATOR_FINISHED; + /* done */ + return OPERATOR_FINISHED; } void NLA_OT_delete(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Delete Strips"; - ot->idname = "NLA_OT_delete"; - ot->description = "Delete selected strips"; + /* identifiers */ + ot->name = "Delete Strips"; + ot->idname = "NLA_OT_delete"; + ot->description = "Delete selected strips"; - /* api callbacks */ - ot->exec = nlaedit_delete_exec; - ot->poll = nlaop_poll_tweakmode_off; + /* api callbacks */ + ot->exec = nlaedit_delete_exec; + ot->poll = nlaop_poll_tweakmode_off; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ******************** Split Strips Operator ***************************** */ @@ -1231,142 +1248,143 @@ void NLA_OT_delete(wmOperatorType *ot) // - variable-length splits? /* split a given Action-Clip strip */ -static void nlaedit_split_strip_actclip(Main *bmain, AnimData *adt, NlaTrack *nlt, NlaStrip *strip, float cfra) +static void nlaedit_split_strip_actclip( + Main *bmain, AnimData *adt, NlaTrack *nlt, NlaStrip *strip, float cfra) { - NlaStrip *nstrip; - float splitframe, splitaframe; - - /* calculate the frames to do the splitting at - * - use current frame if within extents of strip - */ - if ((cfra > strip->start) && (cfra < strip->end)) { - /* use the current frame */ - splitframe = cfra; - splitaframe = nlastrip_get_frame(strip, cfra, NLATIME_CONVERT_UNMAP); - } - else { - /* split in the middle */ - float len; - - /* strip extents */ - len = strip->end - strip->start; - if (IS_EQF(len, 0.0f)) - return; - else - splitframe = strip->start + (len / 2.0f); - - /* action range */ - len = strip->actend - strip->actstart; - if (IS_EQF(len, 0.0f)) - splitaframe = strip->actend; - else - splitaframe = strip->actstart + (len / 2.0f); - } - - /* make a copy (assume that this is possible) and append - * it immediately after the current strip - */ - nstrip = BKE_nlastrip_copy(bmain, strip, true, 0); - BLI_insertlinkafter(&nlt->strips, strip, nstrip); - - /* Set the endpoint of the first strip and the start of the new strip - * to the split-frame values calculated above. - */ - strip->end = splitframe; - nstrip->start = splitframe; - - if ((splitaframe > strip->actstart) && (splitaframe < strip->actend)) { - /* only do this if we're splitting down the middle... */ - strip->actend = splitaframe; - nstrip->actstart = splitaframe; - } - - /* clear the active flag from the copy */ - nstrip->flag &= ~NLASTRIP_FLAG_ACTIVE; - - /* auto-name the new strip */ - BKE_nlastrip_validate_name(adt, nstrip); + NlaStrip *nstrip; + float splitframe, splitaframe; + + /* calculate the frames to do the splitting at + * - use current frame if within extents of strip + */ + if ((cfra > strip->start) && (cfra < strip->end)) { + /* use the current frame */ + splitframe = cfra; + splitaframe = nlastrip_get_frame(strip, cfra, NLATIME_CONVERT_UNMAP); + } + else { + /* split in the middle */ + float len; + + /* strip extents */ + len = strip->end - strip->start; + if (IS_EQF(len, 0.0f)) + return; + else + splitframe = strip->start + (len / 2.0f); + + /* action range */ + len = strip->actend - strip->actstart; + if (IS_EQF(len, 0.0f)) + splitaframe = strip->actend; + else + splitaframe = strip->actstart + (len / 2.0f); + } + + /* make a copy (assume that this is possible) and append + * it immediately after the current strip + */ + nstrip = BKE_nlastrip_copy(bmain, strip, true, 0); + BLI_insertlinkafter(&nlt->strips, strip, nstrip); + + /* Set the endpoint of the first strip and the start of the new strip + * to the split-frame values calculated above. + */ + strip->end = splitframe; + nstrip->start = splitframe; + + if ((splitaframe > strip->actstart) && (splitaframe < strip->actend)) { + /* only do this if we're splitting down the middle... */ + strip->actend = splitaframe; + nstrip->actstart = splitaframe; + } + + /* clear the active flag from the copy */ + nstrip->flag &= ~NLASTRIP_FLAG_ACTIVE; + + /* auto-name the new strip */ + BKE_nlastrip_validate_name(adt, nstrip); } /* split a given Meta strip */ static void nlaedit_split_strip_meta(NlaTrack *nlt, NlaStrip *strip) { - /* simply ungroup it for now... */ - BKE_nlastrips_clear_metastrip(&nlt->strips, strip); + /* simply ungroup it for now... */ + BKE_nlastrips_clear_metastrip(&nlt->strips, strip); } /* ----- */ static int nlaedit_split_exec(bContext *C, wmOperator *UNUSED(op)) { - 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 a list of editable tracks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - /* for each NLA-Track, split all selected strips into two strips */ - for (ale = anim_data.first; ale; ale = ale->next) { - NlaTrack *nlt = (NlaTrack *)ale->data; - AnimData *adt = ale->adt; - NlaStrip *strip, *next; - - for (strip = nlt->strips.first; strip; strip = next) { - next = strip->next; - - /* if selected, split the strip at its midpoint */ - if (strip->flag & NLASTRIP_FLAG_SELECT) { - /* splitting method depends on the type of strip */ - switch (strip->type) { - case NLASTRIP_TYPE_CLIP: /* action-clip */ - nlaedit_split_strip_actclip(ac.bmain, adt, nlt, strip, (float)ac.scene->r.cfra); - break; - - case NLASTRIP_TYPE_META: /* meta-strips need special handling */ - nlaedit_split_strip_meta(nlt, strip); - break; - - default: /* for things like Transitions, do not split! */ - break; - } - } - } - } - - /* free temp data */ - ANIM_animdata_freelist(&anim_data); - - /* refresh auto strip properties */ - ED_nla_postop_refresh(&ac); - - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); - - /* done */ - return OPERATOR_FINISHED; + 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 a list of editable tracks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* for each NLA-Track, split all selected strips into two strips */ + for (ale = anim_data.first; ale; ale = ale->next) { + NlaTrack *nlt = (NlaTrack *)ale->data; + AnimData *adt = ale->adt; + NlaStrip *strip, *next; + + for (strip = nlt->strips.first; strip; strip = next) { + next = strip->next; + + /* if selected, split the strip at its midpoint */ + if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* splitting method depends on the type of strip */ + switch (strip->type) { + case NLASTRIP_TYPE_CLIP: /* action-clip */ + nlaedit_split_strip_actclip(ac.bmain, adt, nlt, strip, (float)ac.scene->r.cfra); + break; + + case NLASTRIP_TYPE_META: /* meta-strips need special handling */ + nlaedit_split_strip_meta(nlt, strip); + break; + + default: /* for things like Transitions, do not split! */ + break; + } + } + } + } + + /* free temp data */ + ANIM_animdata_freelist(&anim_data); + + /* refresh auto strip properties */ + ED_nla_postop_refresh(&ac); + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; } void NLA_OT_split(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Split Strips"; - ot->idname = "NLA_OT_split"; - ot->description = "Split selected strips at their midpoints"; + /* identifiers */ + ot->name = "Split Strips"; + ot->idname = "NLA_OT_split"; + ot->description = "Split selected strips at their midpoints"; - /* api callbacks */ - ot->exec = nlaedit_split_exec; - ot->poll = nlaop_poll_tweakmode_off; + /* api callbacks */ + ot->exec = nlaedit_split_exec; + ot->poll = nlaop_poll_tweakmode_off; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* *********************************************** */ @@ -1377,62 +1395,62 @@ void NLA_OT_split(wmOperatorType *ot) static int nlaedit_toggle_mute_exec(bContext *C, wmOperator *UNUSED(op)) { - 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 a list of the editable tracks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - /* go over all selected strips */ - for (ale = anim_data.first; ale; ale = ale->next) { - NlaTrack *nlt = (NlaTrack *)ale->data; - NlaStrip *strip; - - /* for every selected strip, toggle muting */ - for (strip = nlt->strips.first; strip; strip = strip->next) { - if (strip->flag & NLASTRIP_FLAG_SELECT) { - /* just flip the mute flag for now */ - // TODO: have a pre-pass to check if mute all or unmute all? - strip->flag ^= NLASTRIP_FLAG_MUTED; - - /* tag AnimData to get recalculated */ - ale->update |= ANIM_UPDATE_DEPS; - } - } - } - - /* cleanup */ - 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_NLA | NA_EDITED, NULL); - - /* done */ - return OPERATOR_FINISHED; + 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 a list of the editable tracks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* go over all selected strips */ + for (ale = anim_data.first; ale; ale = ale->next) { + NlaTrack *nlt = (NlaTrack *)ale->data; + NlaStrip *strip; + + /* for every selected strip, toggle muting */ + for (strip = nlt->strips.first; strip; strip = strip->next) { + if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* just flip the mute flag for now */ + // TODO: have a pre-pass to check if mute all or unmute all? + strip->flag ^= NLASTRIP_FLAG_MUTED; + + /* tag AnimData to get recalculated */ + ale->update |= ANIM_UPDATE_DEPS; + } + } + } + + /* cleanup */ + 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_NLA | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; } void NLA_OT_mute_toggle(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Toggle Muting"; - ot->idname = "NLA_OT_mute_toggle"; - ot->description = "Mute or un-mute selected strips"; + /* identifiers */ + ot->name = "Toggle Muting"; + ot->idname = "NLA_OT_mute_toggle"; + ot->description = "Mute or un-mute selected strips"; - /* api callbacks */ - ot->exec = nlaedit_toggle_mute_exec; - ot->poll = nlaop_poll_tweakmode_off; + /* api callbacks */ + ot->exec = nlaedit_toggle_mute_exec; + ot->poll = nlaop_poll_tweakmode_off; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ******************** Swap Strips Operator ************************** */ @@ -1440,160 +1458,167 @@ void NLA_OT_mute_toggle(wmOperatorType *ot) static int nlaedit_swap_exec(bContext *C, wmOperator *op) { - 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 a list of the editable tracks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - /* consider each track in turn */ - for (ale = anim_data.first; ale; ale = ale->next) { - NlaTrack *nlt = (NlaTrack *)ale->data; - - NlaStrip *strip, *stripN = NULL; - NlaStrip *sa = NULL, *sb = NULL; - - /* make temporary metastrips so that entire islands of selections can be moved around */ - BKE_nlastrips_make_metas(&nlt->strips, 1); - - /* special case: if there is only 1 island (i.e. temp meta BUT NOT unselected/normal/normal-meta strips) left after this, - * and this island has two strips inside it, then we should be able to just swap these still... - */ - if (BLI_listbase_is_empty(&nlt->strips) == false) { - NlaStrip *mstrip = (NlaStrip *)nlt->strips.first; - - if ((mstrip->flag & NLASTRIP_FLAG_TEMP_META) && - (BLI_listbase_count_at_most(&mstrip->strips, 3) == 2)) - { - /* remove this temp meta, so that we can see the strips inside */ - BKE_nlastrips_clear_metas(&nlt->strips, 0, 1); - } - } - - /* get two selected strips only (these will be metas due to prev step) to operate on - * - only allow swapping 2, as with more the context becomes unclear - */ - for (strip = nlt->strips.first; strip; strip = stripN) { - stripN = strip->next; - - if (strip->flag & NLASTRIP_FLAG_SELECT) { - /* first or second strip? */ - if (sa == NULL) { - /* store as first */ - sa = strip; - } - else if (sb == NULL) { - /* store as second */ - sb = strip; - } - else { - /* too many selected */ - break; - } - } - } - - if (strip) { - /* too many selected warning */ - BKE_reportf(op->reports, RPT_WARNING, - "Too many clusters of strips selected in NLA Track (%s): needs exactly 2 to be selected", - nlt->name); - } - else if (sa == NULL) { - /* no warning as this is just a common case, - * and it may get annoying when doing multiple tracks */ - } - else if (sb == NULL) { - /* too few selected warning */ - BKE_reportf(op->reports, RPT_WARNING, - "Too few clusters of strips selected in NLA Track (%s): needs exactly 2 to be selected", - nlt->name); - } - else { - float nsa[2], nsb[2]; - - /* remove these strips from the track, - * so that we can test if they can fit in the proposed places */ - BLI_remlink(&nlt->strips, sa); - BLI_remlink(&nlt->strips, sb); - - /* calculate new extents for strips */ - /* a --> b */ - nsa[0] = sb->start; - nsa[1] = sb->start + (sa->end - sa->start); - /* b --> a */ - nsb[0] = sa->start; - nsb[1] = sa->start + (sb->end - sb->start); - - /* check if the track has room for the strips to be swapped */ - if (BKE_nlastrips_has_space(&nlt->strips, nsa[0], nsa[1]) && - BKE_nlastrips_has_space(&nlt->strips, nsb[0], nsb[1])) - { - /* set new extents for strips then */ - sa->start = nsa[0]; - sa->end = nsa[1]; - BKE_nlameta_flush_transforms(sa); - - sb->start = nsb[0]; - sb->end = nsb[1]; - BKE_nlameta_flush_transforms(sb); - } - else { - /* not enough room to swap, so show message */ - if ((sa->flag & NLASTRIP_FLAG_TEMP_META) || (sb->flag & NLASTRIP_FLAG_TEMP_META)) { - BKE_report(op->reports, RPT_WARNING, - "Cannot swap selected strips as they will not be able to fit in their new places"); - } - else { - BKE_reportf(op->reports, RPT_WARNING, - "Cannot swap '%s' and '%s' as one or both will not be able to fit in their new places", - sa->name, sb->name); - } - } - - /* add strips back to track now */ - BKE_nlatrack_add_strip(nlt, sa); - BKE_nlatrack_add_strip(nlt, sb); - } - - /* clear (temp) metastrips */ - BKE_nlastrips_clear_metas(&nlt->strips, 0, 1); - } - - /* free temp data */ - ANIM_animdata_freelist(&anim_data); - - /* refresh auto strip properties */ - ED_nla_postop_refresh(&ac); - - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); - - /* done */ - return OPERATOR_FINISHED; + 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 a list of the editable tracks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* consider each track in turn */ + for (ale = anim_data.first; ale; ale = ale->next) { + NlaTrack *nlt = (NlaTrack *)ale->data; + + NlaStrip *strip, *stripN = NULL; + NlaStrip *sa = NULL, *sb = NULL; + + /* make temporary metastrips so that entire islands of selections can be moved around */ + BKE_nlastrips_make_metas(&nlt->strips, 1); + + /* special case: if there is only 1 island (i.e. temp meta BUT NOT unselected/normal/normal-meta strips) left after this, + * and this island has two strips inside it, then we should be able to just swap these still... + */ + if (BLI_listbase_is_empty(&nlt->strips) == false) { + NlaStrip *mstrip = (NlaStrip *)nlt->strips.first; + + if ((mstrip->flag & NLASTRIP_FLAG_TEMP_META) && + (BLI_listbase_count_at_most(&mstrip->strips, 3) == 2)) { + /* remove this temp meta, so that we can see the strips inside */ + BKE_nlastrips_clear_metas(&nlt->strips, 0, 1); + } + } + + /* get two selected strips only (these will be metas due to prev step) to operate on + * - only allow swapping 2, as with more the context becomes unclear + */ + for (strip = nlt->strips.first; strip; strip = stripN) { + stripN = strip->next; + + if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* first or second strip? */ + if (sa == NULL) { + /* store as first */ + sa = strip; + } + else if (sb == NULL) { + /* store as second */ + sb = strip; + } + else { + /* too many selected */ + break; + } + } + } + + if (strip) { + /* too many selected warning */ + BKE_reportf( + op->reports, + RPT_WARNING, + "Too many clusters of strips selected in NLA Track (%s): needs exactly 2 to be selected", + nlt->name); + } + else if (sa == NULL) { + /* no warning as this is just a common case, + * and it may get annoying when doing multiple tracks */ + } + else if (sb == NULL) { + /* too few selected warning */ + BKE_reportf( + op->reports, + RPT_WARNING, + "Too few clusters of strips selected in NLA Track (%s): needs exactly 2 to be selected", + nlt->name); + } + else { + float nsa[2], nsb[2]; + + /* remove these strips from the track, + * so that we can test if they can fit in the proposed places */ + BLI_remlink(&nlt->strips, sa); + BLI_remlink(&nlt->strips, sb); + + /* calculate new extents for strips */ + /* a --> b */ + nsa[0] = sb->start; + nsa[1] = sb->start + (sa->end - sa->start); + /* b --> a */ + nsb[0] = sa->start; + nsb[1] = sa->start + (sb->end - sb->start); + + /* check if the track has room for the strips to be swapped */ + if (BKE_nlastrips_has_space(&nlt->strips, nsa[0], nsa[1]) && + BKE_nlastrips_has_space(&nlt->strips, nsb[0], nsb[1])) { + /* set new extents for strips then */ + sa->start = nsa[0]; + sa->end = nsa[1]; + BKE_nlameta_flush_transforms(sa); + + sb->start = nsb[0]; + sb->end = nsb[1]; + BKE_nlameta_flush_transforms(sb); + } + else { + /* not enough room to swap, so show message */ + if ((sa->flag & NLASTRIP_FLAG_TEMP_META) || (sb->flag & NLASTRIP_FLAG_TEMP_META)) { + BKE_report( + op->reports, + RPT_WARNING, + "Cannot swap selected strips as they will not be able to fit in their new places"); + } + else { + BKE_reportf(op->reports, + RPT_WARNING, + "Cannot swap '%s' and '%s' as one or both will not be able to fit in their " + "new places", + sa->name, + sb->name); + } + } + + /* add strips back to track now */ + BKE_nlatrack_add_strip(nlt, sa); + BKE_nlatrack_add_strip(nlt, sb); + } + + /* clear (temp) metastrips */ + BKE_nlastrips_clear_metas(&nlt->strips, 0, 1); + } + + /* free temp data */ + ANIM_animdata_freelist(&anim_data); + + /* refresh auto strip properties */ + ED_nla_postop_refresh(&ac); + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; } void NLA_OT_swap(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Swap Strips"; - ot->idname = "NLA_OT_swap"; - ot->description = "Swap order of selected strips within tracks"; + /* identifiers */ + ot->name = "Swap Strips"; + ot->idname = "NLA_OT_swap"; + ot->description = "Swap order of selected strips within tracks"; - /* api callbacks */ - ot->exec = nlaedit_swap_exec; - ot->poll = nlaop_poll_tweakmode_off; + /* api callbacks */ + ot->exec = nlaedit_swap_exec; + ot->poll = nlaop_poll_tweakmode_off; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ******************** Move Strips Up Operator ************************** */ @@ -1601,74 +1626,74 @@ void NLA_OT_swap(wmOperatorType *ot) static int nlaedit_move_up_exec(bContext *C, wmOperator *UNUSED(op)) { - 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 a list of the editable tracks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - /* since we're potentially moving strips from lower tracks to higher tracks, we should - * loop over the tracks in reverse order to avoid moving earlier strips up multiple tracks - */ - for (ale = anim_data.last; ale; ale = ale->prev) { - NlaTrack *nlt = (NlaTrack *)ale->data; - NlaTrack *nltn = nlt->next; - NlaStrip *strip, *stripn; - - /* if this track has no tracks after it, skip for now... */ - if (nltn == NULL) - continue; - - /* for every selected strip, try to move */ - for (strip = nlt->strips.first; strip; strip = stripn) { - stripn = strip->next; - - if (strip->flag & NLASTRIP_FLAG_SELECT) { - /* check if the track above has room for this strip */ - if (BKE_nlatrack_has_space(nltn, strip->start, strip->end)) { - /* remove from its current track, and add to the one above - * (it 'should' work, so no need to worry) */ - BLI_remlink(&nlt->strips, strip); - BKE_nlatrack_add_strip(nltn, strip); - } - } - } - } - - /* free temp data */ - ANIM_animdata_freelist(&anim_data); - - /* refresh auto strip properties */ - ED_nla_postop_refresh(&ac); - - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); - - /* done */ - return OPERATOR_FINISHED; + 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 a list of the editable tracks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* since we're potentially moving strips from lower tracks to higher tracks, we should + * loop over the tracks in reverse order to avoid moving earlier strips up multiple tracks + */ + for (ale = anim_data.last; ale; ale = ale->prev) { + NlaTrack *nlt = (NlaTrack *)ale->data; + NlaTrack *nltn = nlt->next; + NlaStrip *strip, *stripn; + + /* if this track has no tracks after it, skip for now... */ + if (nltn == NULL) + continue; + + /* for every selected strip, try to move */ + for (strip = nlt->strips.first; strip; strip = stripn) { + stripn = strip->next; + + if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* check if the track above has room for this strip */ + if (BKE_nlatrack_has_space(nltn, strip->start, strip->end)) { + /* remove from its current track, and add to the one above + * (it 'should' work, so no need to worry) */ + BLI_remlink(&nlt->strips, strip); + BKE_nlatrack_add_strip(nltn, strip); + } + } + } + } + + /* free temp data */ + ANIM_animdata_freelist(&anim_data); + + /* refresh auto strip properties */ + ED_nla_postop_refresh(&ac); + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; } void NLA_OT_move_up(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Move Strips Up"; - ot->idname = "NLA_OT_move_up"; - ot->description = "Move selected strips up a track if there's room"; + /* identifiers */ + ot->name = "Move Strips Up"; + ot->idname = "NLA_OT_move_up"; + ot->description = "Move selected strips up a track if there's room"; - /* api callbacks */ - ot->exec = nlaedit_move_up_exec; - ot->poll = nlaop_poll_tweakmode_off; + /* api callbacks */ + ot->exec = nlaedit_move_up_exec; + ot->poll = nlaop_poll_tweakmode_off; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ******************** Move Strips Down Operator ************************** */ @@ -1676,74 +1701,74 @@ void NLA_OT_move_up(wmOperatorType *ot) static int nlaedit_move_down_exec(bContext *C, wmOperator *UNUSED(op)) { - 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 a list of the editable tracks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - /* loop through the tracks in normal order, since we're pushing strips down, - * strips won't get operated on twice - */ - for (ale = anim_data.first; ale; ale = ale->next) { - NlaTrack *nlt = (NlaTrack *)ale->data; - NlaTrack *nltp = nlt->prev; - NlaStrip *strip, *stripn; - - /* if this track has no tracks before it, skip for now... */ - if (nltp == NULL) - continue; - - /* for every selected strip, try to move */ - for (strip = nlt->strips.first; strip; strip = stripn) { - stripn = strip->next; - - if (strip->flag & NLASTRIP_FLAG_SELECT) { - /* check if the track below has room for this strip */ - if (BKE_nlatrack_has_space(nltp, strip->start, strip->end)) { - /* remove from its current track, and add to the one above - * (it 'should' work, so no need to worry) */ - BLI_remlink(&nlt->strips, strip); - BKE_nlatrack_add_strip(nltp, strip); - } - } - } - } - - /* free temp data */ - ANIM_animdata_freelist(&anim_data); - - /* refresh auto strip properties */ - ED_nla_postop_refresh(&ac); - - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); - - /* done */ - return OPERATOR_FINISHED; + 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 a list of the editable tracks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* loop through the tracks in normal order, since we're pushing strips down, + * strips won't get operated on twice + */ + for (ale = anim_data.first; ale; ale = ale->next) { + NlaTrack *nlt = (NlaTrack *)ale->data; + NlaTrack *nltp = nlt->prev; + NlaStrip *strip, *stripn; + + /* if this track has no tracks before it, skip for now... */ + if (nltp == NULL) + continue; + + /* for every selected strip, try to move */ + for (strip = nlt->strips.first; strip; strip = stripn) { + stripn = strip->next; + + if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* check if the track below has room for this strip */ + if (BKE_nlatrack_has_space(nltp, strip->start, strip->end)) { + /* remove from its current track, and add to the one above + * (it 'should' work, so no need to worry) */ + BLI_remlink(&nlt->strips, strip); + BKE_nlatrack_add_strip(nltp, strip); + } + } + } + } + + /* free temp data */ + ANIM_animdata_freelist(&anim_data); + + /* refresh auto strip properties */ + ED_nla_postop_refresh(&ac); + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; } void NLA_OT_move_down(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Move Strips Down"; - ot->idname = "NLA_OT_move_down"; - ot->description = "Move selected strips down a track if there's room"; + /* identifiers */ + ot->name = "Move Strips Down"; + ot->idname = "NLA_OT_move_down"; + ot->description = "Move selected strips down a track if there's room"; - /* api callbacks */ - ot->exec = nlaedit_move_down_exec; - ot->poll = nlaop_poll_tweakmode_off; + /* api callbacks */ + ot->exec = nlaedit_move_down_exec; + ot->poll = nlaop_poll_tweakmode_off; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ******************** Sync Action Length Operator ***************************** */ @@ -1751,81 +1776,87 @@ void NLA_OT_move_down(wmOperatorType *ot) static int nlaedit_sync_actlen_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - const bool active_only = RNA_boolean_get(op->ptr, "active"); - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* get a list of the editable tracks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); - if (active_only) filter |= ANIMFILTER_ACTIVE; - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - /* for each NLA-Track, apply scale of all selected strips */ - for (ale = anim_data.first; ale; ale = ale->next) { - NlaTrack *nlt = (NlaTrack *)ale->data; - NlaStrip *strip; - - for (strip = nlt->strips.first; strip; strip = strip->next) { - /* strip selection/active status check */ - if (active_only) { - if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0) - continue; - } - else { - if ((strip->flag & NLASTRIP_FLAG_SELECT) == 0) - continue; - } - - /* must be action-clip only (transitions don't have scale) */ - if (strip->type == NLASTRIP_TYPE_CLIP) { - if (strip->act == NULL) - continue; - - /* recalculate the length of the action */ - calc_action_range(strip->act, &strip->actstart, &strip->actend, 0); - - /* adjust the strip extents in response to this */ - BKE_nlastrip_recalculate_bounds(strip); - - ale->update |= ANIM_UPDATE_DEPS; - } - } - } - - /* free temp 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_NLA | NA_EDITED, NULL); - - /* done */ - return OPERATOR_FINISHED; + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + const bool active_only = RNA_boolean_get(op->ptr, "active"); + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the editable tracks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); + if (active_only) + filter |= ANIMFILTER_ACTIVE; + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* for each NLA-Track, apply scale of all selected strips */ + for (ale = anim_data.first; ale; ale = ale->next) { + NlaTrack *nlt = (NlaTrack *)ale->data; + NlaStrip *strip; + + for (strip = nlt->strips.first; strip; strip = strip->next) { + /* strip selection/active status check */ + if (active_only) { + if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0) + continue; + } + else { + if ((strip->flag & NLASTRIP_FLAG_SELECT) == 0) + continue; + } + + /* must be action-clip only (transitions don't have scale) */ + if (strip->type == NLASTRIP_TYPE_CLIP) { + if (strip->act == NULL) + continue; + + /* recalculate the length of the action */ + calc_action_range(strip->act, &strip->actstart, &strip->actend, 0); + + /* adjust the strip extents in response to this */ + BKE_nlastrip_recalculate_bounds(strip); + + ale->update |= ANIM_UPDATE_DEPS; + } + } + } + + /* free temp 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_NLA | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; } void NLA_OT_action_sync_length(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Sync Action Length"; - ot->idname = "NLA_OT_action_sync_length"; - ot->description = "Synchronize the length of the referenced Action with the length used in the strip"; - - /* api callbacks */ - ot->exec = nlaedit_sync_actlen_exec; - ot->poll = nlaop_poll_tweakmode_off; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - ot->prop = RNA_def_boolean(ot->srna, "active", 1, "Active Strip Only", "Only sync the active length for the active strip"); + /* identifiers */ + ot->name = "Sync Action Length"; + ot->idname = "NLA_OT_action_sync_length"; + ot->description = + "Synchronize the length of the referenced Action with the length used in the strip"; + + /* api callbacks */ + ot->exec = nlaedit_sync_actlen_exec; + ot->poll = nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_boolean(ot->srna, + "active", + 1, + "Active Strip Only", + "Only sync the active length for the active strip"); } /* ******************** Make Single User ********************************* */ @@ -1833,83 +1864,83 @@ void NLA_OT_action_sync_length(wmOperatorType *ot) static int nlaedit_make_single_user_exec(bContext *C, wmOperator *UNUSED(op)) { - Main *bmain = CTX_data_main(C); - bAnimContext ac; - - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - bool copied = false; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* get a list of the editable tracks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - /* Ensure that each action used only has a single user - * - This is done in reverse order so that the original strips are - * likely to still get to keep their action - */ - for (ale = anim_data.last; ale; ale = ale->prev) { - NlaTrack *nlt = (NlaTrack *)ale->data; - NlaStrip *strip; - - for (strip = nlt->strips.last; strip; strip = strip->prev) { - /* must be action-clip only (as only these have actions) */ - if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) { - if (strip->act == NULL) - continue; - - /* multi-user? */ - if (ID_REAL_USERS(strip->act) > 1) { - /* make a new copy of the action for us to use (it will have 1 user already) */ - bAction *new_action = BKE_action_copy(bmain, strip->act); - - /* decrement user count of our existing action */ - id_us_min(&strip->act->id); - - /* switch to the new copy */ - strip->act = new_action; - - ale->update |= ANIM_UPDATE_DEPS; - copied = true; - } - } - } - } - - /* free temp data */ - ANIM_animdata_update(&ac, &anim_data); - ANIM_animdata_freelist(&anim_data); - - if (copied) { - DEG_relations_tag_update(ac.bmain); - } - - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); - - /* done */ - return OPERATOR_FINISHED; + Main *bmain = CTX_data_main(C); + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + bool copied = false; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the editable tracks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* Ensure that each action used only has a single user + * - This is done in reverse order so that the original strips are + * likely to still get to keep their action + */ + for (ale = anim_data.last; ale; ale = ale->prev) { + NlaTrack *nlt = (NlaTrack *)ale->data; + NlaStrip *strip; + + for (strip = nlt->strips.last; strip; strip = strip->prev) { + /* must be action-clip only (as only these have actions) */ + if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) { + if (strip->act == NULL) + continue; + + /* multi-user? */ + if (ID_REAL_USERS(strip->act) > 1) { + /* make a new copy of the action for us to use (it will have 1 user already) */ + bAction *new_action = BKE_action_copy(bmain, strip->act); + + /* decrement user count of our existing action */ + id_us_min(&strip->act->id); + + /* switch to the new copy */ + strip->act = new_action; + + ale->update |= ANIM_UPDATE_DEPS; + copied = true; + } + } + } + } + + /* free temp data */ + ANIM_animdata_update(&ac, &anim_data); + ANIM_animdata_freelist(&anim_data); + + if (copied) { + DEG_relations_tag_update(ac.bmain); + } + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; } void NLA_OT_make_single_user(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Make Single User"; - ot->idname = "NLA_OT_make_single_user"; - ot->description = "Ensure that each action is only used once in the set of strips selected"; - - /* api callbacks */ - ot->invoke = WM_operator_confirm; - ot->exec = nlaedit_make_single_user_exec; - ot->poll = nlaop_poll_tweakmode_off; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* identifiers */ + ot->name = "Make Single User"; + ot->idname = "NLA_OT_make_single_user"; + ot->description = "Ensure that each action is only used once in the set of strips selected"; + + /* api callbacks */ + ot->invoke = WM_operator_confirm; + ot->exec = nlaedit_make_single_user_exec; + ot->poll = nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ******************** Apply Scale Operator ***************************** */ @@ -1918,108 +1949,109 @@ void NLA_OT_make_single_user(wmOperatorType *ot) /* apply scaling to keyframe */ static short bezt_apply_nlamapping(KeyframeEditData *ked, BezTriple *bezt) { - /* NLA-strip which has this scaling is stored in ked->data */ - NlaStrip *strip = (NlaStrip *)ked->data; + /* NLA-strip which has this scaling is stored in ked->data */ + NlaStrip *strip = (NlaStrip *)ked->data; - /* adjust all the times */ - bezt->vec[0][0] = nlastrip_get_frame(strip, bezt->vec[0][0], NLATIME_CONVERT_MAP); - bezt->vec[1][0] = nlastrip_get_frame(strip, bezt->vec[1][0], NLATIME_CONVERT_MAP); - bezt->vec[2][0] = nlastrip_get_frame(strip, bezt->vec[2][0], NLATIME_CONVERT_MAP); + /* adjust all the times */ + bezt->vec[0][0] = nlastrip_get_frame(strip, bezt->vec[0][0], NLATIME_CONVERT_MAP); + bezt->vec[1][0] = nlastrip_get_frame(strip, bezt->vec[1][0], NLATIME_CONVERT_MAP); + bezt->vec[2][0] = nlastrip_get_frame(strip, bezt->vec[2][0], NLATIME_CONVERT_MAP); - /* nothing to return or else we exit */ - return 0; + /* nothing to return or else we exit */ + return 0; } static int nlaedit_apply_scale_exec(bContext *C, wmOperator *UNUSED(op)) { - Main *bmain = CTX_data_main(C); - bAnimContext ac; - - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - bool copied = false; - - KeyframeEditData ked = {{NULL}}; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* get a list of the editable tracks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - /* for each NLA-Track, apply scale of all selected strips */ - for (ale = anim_data.first; ale; ale = ale->next) { - NlaTrack *nlt = (NlaTrack *)ale->data; - NlaStrip *strip; - - for (strip = nlt->strips.first; strip; strip = strip->next) { - /* strip must be selected, and must be action-clip only - * (transitions don't have scale) */ - if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) { - /* if the referenced action is used by other strips, - * make this strip use its own copy */ - if (strip->act == NULL) - continue; - if (strip->act->id.us > 1) { - /* make a copy of the Action to work on */ - bAction *act = BKE_action_copy(bmain, strip->act); - - /* set this as the new referenced action, - * decrementing the users of the old one */ - id_us_min(&strip->act->id); - strip->act = act; - - copied = true; - } - - /* setup iterator, and iterate over all the keyframes in the action, - * applying this scaling */ - ked.data = strip; - ANIM_animchanneldata_keyframes_loop(&ked, ac.ads, strip->act, ALE_ACT, NULL, bezt_apply_nlamapping, calchandles_fcurve); - - /* clear scale of strip now that it has been applied, - * and recalculate the extents of the action now that it has been scaled - * but leave everything else alone - */ - strip->scale = 1.0f; - calc_action_range(strip->act, &strip->actstart, &strip->actend, 0); - - ale->update |= ANIM_UPDATE_DEPS; - } - } - } - - /* free temp data */ - ANIM_animdata_update(&ac, &anim_data); - ANIM_animdata_freelist(&anim_data); - - if (copied) { - DEG_relations_tag_update(ac.bmain); - } - - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); - - /* done */ - return OPERATOR_FINISHED; + Main *bmain = CTX_data_main(C); + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + bool copied = false; + + KeyframeEditData ked = {{NULL}}; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the editable tracks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* for each NLA-Track, apply scale of all selected strips */ + for (ale = anim_data.first; ale; ale = ale->next) { + NlaTrack *nlt = (NlaTrack *)ale->data; + NlaStrip *strip; + + for (strip = nlt->strips.first; strip; strip = strip->next) { + /* strip must be selected, and must be action-clip only + * (transitions don't have scale) */ + if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) { + /* if the referenced action is used by other strips, + * make this strip use its own copy */ + if (strip->act == NULL) + continue; + if (strip->act->id.us > 1) { + /* make a copy of the Action to work on */ + bAction *act = BKE_action_copy(bmain, strip->act); + + /* set this as the new referenced action, + * decrementing the users of the old one */ + id_us_min(&strip->act->id); + strip->act = act; + + copied = true; + } + + /* setup iterator, and iterate over all the keyframes in the action, + * applying this scaling */ + ked.data = strip; + ANIM_animchanneldata_keyframes_loop( + &ked, ac.ads, strip->act, ALE_ACT, NULL, bezt_apply_nlamapping, calchandles_fcurve); + + /* clear scale of strip now that it has been applied, + * and recalculate the extents of the action now that it has been scaled + * but leave everything else alone + */ + strip->scale = 1.0f; + calc_action_range(strip->act, &strip->actstart, &strip->actend, 0); + + ale->update |= ANIM_UPDATE_DEPS; + } + } + } + + /* free temp data */ + ANIM_animdata_update(&ac, &anim_data); + ANIM_animdata_freelist(&anim_data); + + if (copied) { + DEG_relations_tag_update(ac.bmain); + } + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; } void NLA_OT_apply_scale(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Apply Scale"; - ot->idname = "NLA_OT_apply_scale"; - ot->description = "Apply scaling of selected strips to their referenced Actions"; + /* identifiers */ + ot->name = "Apply Scale"; + ot->idname = "NLA_OT_apply_scale"; + ot->description = "Apply scaling of selected strips to their referenced Actions"; - /* api callbacks */ - ot->exec = nlaedit_apply_scale_exec; - ot->poll = nlaop_poll_tweakmode_off; + /* api callbacks */ + ot->exec = nlaedit_apply_scale_exec; + ot->poll = nlaop_poll_tweakmode_off; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ******************** Clear Scale Operator ***************************** */ @@ -2027,63 +2059,63 @@ void NLA_OT_apply_scale(wmOperatorType *ot) static int nlaedit_clear_scale_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; - /* 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 a list of the editable tracks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + /* get a list of the editable tracks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - /* for each NLA-Track, reset scale of all selected strips */ - for (ale = anim_data.first; ale; ale = ale->next) { - NlaTrack *nlt = (NlaTrack *)ale->data; - NlaStrip *strip; + /* for each NLA-Track, reset scale of all selected strips */ + for (ale = anim_data.first; ale; ale = ale->next) { + NlaTrack *nlt = (NlaTrack *)ale->data; + NlaStrip *strip; - for (strip = nlt->strips.first; strip; strip = strip->next) { - /* strip must be selected, and must be action-clip only - * (transitions don't have scale) */ - if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) { - PointerRNA strip_ptr; + for (strip = nlt->strips.first; strip; strip = strip->next) { + /* strip must be selected, and must be action-clip only + * (transitions don't have scale) */ + if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) { + PointerRNA strip_ptr; - RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr); - RNA_float_set(&strip_ptr, "scale", 1.0f); - } - } - } + RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr); + RNA_float_set(&strip_ptr, "scale", 1.0f); + } + } + } - /* free temp data */ - ANIM_animdata_freelist(&anim_data); + /* free temp data */ + ANIM_animdata_freelist(&anim_data); - /* refresh auto strip properties */ - ED_nla_postop_refresh(&ac); + /* refresh auto strip properties */ + ED_nla_postop_refresh(&ac); - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); - /* done */ - return OPERATOR_FINISHED; + /* done */ + return OPERATOR_FINISHED; } void NLA_OT_clear_scale(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Clear Scale"; - ot->idname = "NLA_OT_clear_scale"; - ot->description = "Reset scaling of selected strips"; + /* identifiers */ + ot->name = "Clear Scale"; + ot->idname = "NLA_OT_clear_scale"; + ot->description = "Reset scaling of selected strips"; - /* api callbacks */ - ot->exec = nlaedit_clear_scale_exec; - ot->poll = nlaop_poll_tweakmode_off; + /* api callbacks */ + ot->exec = nlaedit_clear_scale_exec; + ot->poll = nlaop_poll_tweakmode_off; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ******************** Snap Strips Operator ************************** */ @@ -2091,149 +2123,153 @@ void NLA_OT_clear_scale(wmOperatorType *ot) /* defines for snap keyframes tool */ static const EnumPropertyItem prop_nlaedit_snap_types[] = { - {NLAEDIT_SNAP_CFRA, "CFRA", 0, "Current Frame", ""}, - {NLAEDIT_SNAP_NEAREST_FRAME, "NEAREST_FRAME", 0, "Nearest Frame", ""}, // XXX as single entry? - {NLAEDIT_SNAP_NEAREST_SECOND, "NEAREST_SECOND", 0, "Nearest Second", ""}, // XXX as single entry? - {NLAEDIT_SNAP_NEAREST_MARKER, "NEAREST_MARKER", 0, "Nearest Marker", ""}, - {0, NULL, 0, NULL, NULL}, + {NLAEDIT_SNAP_CFRA, "CFRA", 0, "Current Frame", ""}, + {NLAEDIT_SNAP_NEAREST_FRAME, "NEAREST_FRAME", 0, "Nearest Frame", ""}, // XXX as single entry? + {NLAEDIT_SNAP_NEAREST_SECOND, + "NEAREST_SECOND", + 0, + "Nearest Second", + ""}, // XXX as single entry? + {NLAEDIT_SNAP_NEAREST_MARKER, "NEAREST_MARKER", 0, "Nearest Marker", ""}, + {0, NULL, 0, NULL, NULL}, }; static int nlaedit_snap_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - Scene *scene; - int mode = RNA_enum_get(op->ptr, "type"); - float secf; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* get a list of the editable tracks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - /* get some necessary vars */ - scene = ac.scene; - secf = (float)FPS; - - /* since we may add tracks, perform this in reverse order */ - for (ale = anim_data.last; ale; ale = ale->prev) { - ListBase tmp_strips = {NULL, NULL}; - AnimData *adt = ale->adt; - NlaTrack *nlt = (NlaTrack *)ale->data; - NlaStrip *strip, *stripn; - NlaTrack *track; - - /* create meta-strips from the continuous chains of selected strips */ - BKE_nlastrips_make_metas(&nlt->strips, 1); - - /* apply the snapping to all the temp meta-strips, then put them in a separate list to be added - * back to the original only if they still fit - */ - for (strip = nlt->strips.first; strip; strip = stripn) { - stripn = strip->next; - - if (strip->flag & NLASTRIP_FLAG_TEMP_META) { - float start, end; - - /* get the existing end-points */ - start = strip->start; - end = strip->end; - - /* calculate new start position based on snapping mode */ - switch (mode) { - case NLAEDIT_SNAP_CFRA: /* to current frame */ - strip->start = (float)CFRA; - break; - case NLAEDIT_SNAP_NEAREST_FRAME: /* to nearest frame */ - strip->start = floorf(start + 0.5f); - break; - case NLAEDIT_SNAP_NEAREST_SECOND: /* to nearest second */ - strip->start = floorf(start / secf + 0.5f) * secf; - break; - case NLAEDIT_SNAP_NEAREST_MARKER: /* to nearest marker */ - strip->start = (float)ED_markers_find_nearest_marker_time(ac.markers, start); - break; - default: /* just in case... no snapping */ - strip->start = start; - break; - } - - /* get new endpoint based on start-point (and old length) */ - strip->end = strip->start + (end - start); - - /* apply transforms to meta-strip to its children */ - BKE_nlameta_flush_transforms(strip); - - /* remove strip from track, and add to the temp buffer */ - BLI_remlink(&nlt->strips, strip); - BLI_addtail(&tmp_strips, strip); - } - } - - /* try adding each meta-strip back to the track one at a time, to make sure they'll fit */ - for (strip = tmp_strips.first; strip; strip = stripn) { - stripn = strip->next; - - /* remove from temp-strips list */ - BLI_remlink(&tmp_strips, strip); - - /* in case there's no space in the current track, try adding */ - if (BKE_nlatrack_add_strip(nlt, strip) == 0) { - /* need to add a new track above the current one */ - track = BKE_nlatrack_add(adt, nlt); - BKE_nlatrack_add_strip(track, strip); - - /* clear temp meta-strips on this new track, - * as we may not be able to get back to it */ - BKE_nlastrips_clear_metas(&track->strips, 0, 1); - } - } - - /* remove the meta-strips now that we're done */ - BKE_nlastrips_clear_metas(&nlt->strips, 0, 1); - - /* tag for recalculating the animation */ - ale->update |= ANIM_UPDATE_DEPS; - } - - /* cleanup */ - ANIM_animdata_update(&ac, &anim_data); - ANIM_animdata_freelist(&anim_data); - - /* refresh auto strip properties */ - ED_nla_postop_refresh(&ac); - - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); - - /* done */ - return OPERATOR_FINISHED; + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + Scene *scene; + int mode = RNA_enum_get(op->ptr, "type"); + float secf; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the editable tracks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* get some necessary vars */ + scene = ac.scene; + secf = (float)FPS; + + /* since we may add tracks, perform this in reverse order */ + for (ale = anim_data.last; ale; ale = ale->prev) { + ListBase tmp_strips = {NULL, NULL}; + AnimData *adt = ale->adt; + NlaTrack *nlt = (NlaTrack *)ale->data; + NlaStrip *strip, *stripn; + NlaTrack *track; + + /* create meta-strips from the continuous chains of selected strips */ + BKE_nlastrips_make_metas(&nlt->strips, 1); + + /* apply the snapping to all the temp meta-strips, then put them in a separate list to be added + * back to the original only if they still fit + */ + for (strip = nlt->strips.first; strip; strip = stripn) { + stripn = strip->next; + + if (strip->flag & NLASTRIP_FLAG_TEMP_META) { + float start, end; + + /* get the existing end-points */ + start = strip->start; + end = strip->end; + + /* calculate new start position based on snapping mode */ + switch (mode) { + case NLAEDIT_SNAP_CFRA: /* to current frame */ + strip->start = (float)CFRA; + break; + case NLAEDIT_SNAP_NEAREST_FRAME: /* to nearest frame */ + strip->start = floorf(start + 0.5f); + break; + case NLAEDIT_SNAP_NEAREST_SECOND: /* to nearest second */ + strip->start = floorf(start / secf + 0.5f) * secf; + break; + case NLAEDIT_SNAP_NEAREST_MARKER: /* to nearest marker */ + strip->start = (float)ED_markers_find_nearest_marker_time(ac.markers, start); + break; + default: /* just in case... no snapping */ + strip->start = start; + break; + } + + /* get new endpoint based on start-point (and old length) */ + strip->end = strip->start + (end - start); + + /* apply transforms to meta-strip to its children */ + BKE_nlameta_flush_transforms(strip); + + /* remove strip from track, and add to the temp buffer */ + BLI_remlink(&nlt->strips, strip); + BLI_addtail(&tmp_strips, strip); + } + } + + /* try adding each meta-strip back to the track one at a time, to make sure they'll fit */ + for (strip = tmp_strips.first; strip; strip = stripn) { + stripn = strip->next; + + /* remove from temp-strips list */ + BLI_remlink(&tmp_strips, strip); + + /* in case there's no space in the current track, try adding */ + if (BKE_nlatrack_add_strip(nlt, strip) == 0) { + /* need to add a new track above the current one */ + track = BKE_nlatrack_add(adt, nlt); + BKE_nlatrack_add_strip(track, strip); + + /* clear temp meta-strips on this new track, + * as we may not be able to get back to it */ + BKE_nlastrips_clear_metas(&track->strips, 0, 1); + } + } + + /* remove the meta-strips now that we're done */ + BKE_nlastrips_clear_metas(&nlt->strips, 0, 1); + + /* tag for recalculating the animation */ + ale->update |= ANIM_UPDATE_DEPS; + } + + /* cleanup */ + ANIM_animdata_update(&ac, &anim_data); + ANIM_animdata_freelist(&anim_data); + + /* refresh auto strip properties */ + ED_nla_postop_refresh(&ac); + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; } void NLA_OT_snap(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Snap Strips"; - ot->idname = "NLA_OT_snap"; - ot->description = "Move start of strips to specified time"; + /* identifiers */ + ot->name = "Snap Strips"; + ot->idname = "NLA_OT_snap"; + ot->description = "Move start of strips to specified time"; - /* api callbacks */ - ot->invoke = WM_menu_invoke; - ot->exec = nlaedit_snap_exec; - ot->poll = nlaop_poll_tweakmode_off; + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = nlaedit_snap_exec; + ot->poll = nlaop_poll_tweakmode_off; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ - ot->prop = RNA_def_enum(ot->srna, "type", prop_nlaedit_snap_types, 0, "Type", ""); + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "type", prop_nlaedit_snap_types, 0, "Type", ""); } /* *********************************************** */ @@ -2241,275 +2277,289 @@ void NLA_OT_snap(wmOperatorType *ot) /* ******************** Add F-Modifier Operator *********************** */ -static const EnumPropertyItem *nla_fmodifier_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) +static const EnumPropertyItem *nla_fmodifier_itemf(bContext *C, + PointerRNA *UNUSED(ptr), + PropertyRNA *UNUSED(prop), + bool *r_free) { - EnumPropertyItem *item = NULL; - int totitem = 0; - int i = 0; - - 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; - - /* check if modifier is valid for this context */ - if (fmi == NULL) - continue; - if (i == FMODIFIER_TYPE_CYCLES) /* we already have repeat... */ - 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]); - } - } - - RNA_enum_item_end(&item, &totitem); - *r_free = true; - - return item; + EnumPropertyItem *item = NULL; + int totitem = 0; + int i = 0; + + 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; + + /* check if modifier is valid for this context */ + if (fmi == NULL) + continue; + if (i == FMODIFIER_TYPE_CYCLES) /* we already have repeat... */ + 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]); + } + } + + RNA_enum_item_end(&item, &totitem); + *r_free = true; + + return item; } - static int nla_fmodifier_add_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - FModifier *fcm; - int type = RNA_enum_get(op->ptr, "type"); - const bool active_only = RNA_boolean_get(op->ptr, "only_active"); - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* get a list of the editable tracks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - /* for each NLA-Track, add the specified modifier to all selected strips */ - for (ale = anim_data.first; ale; ale = ale->next) { - NlaTrack *nlt = (NlaTrack *)ale->data; - NlaStrip *strip; - - for (strip = nlt->strips.first; strip; strip = strip->next) { - /* can F-Modifier be added to the current strip? */ - if (active_only) { - /* if not active, cannot add since we're only adding to active strip */ - if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0) - continue; - } - else { - /* strip must be selected, since we're not just doing active */ - if ((strip->flag & NLASTRIP_FLAG_SELECT) == 0) - continue; - } - - /* sound clips are not affected by FModifiers */ - if (strip->type == NLASTRIP_TYPE_SOUND) - continue; - - /* add F-Modifier of specified type to selected, and make it the active one */ - fcm = add_fmodifier(&strip->modifiers, type, NULL); - - if (fcm) { - set_active_fmodifier(&strip->modifiers, fcm); - ale->update |= ANIM_UPDATE_DEPS; - } - else { - BKE_reportf(op->reports, RPT_ERROR, - "Modifier could not be added to (%s : %s) (see console for details)", - nlt->name, strip->name); - } - } - } - - /* free temp 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_NLA | NA_EDITED, NULL); - - /* done */ - return OPERATOR_FINISHED; + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + FModifier *fcm; + int type = RNA_enum_get(op->ptr, "type"); + const bool active_only = RNA_boolean_get(op->ptr, "only_active"); + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the editable tracks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* for each NLA-Track, add the specified modifier to all selected strips */ + for (ale = anim_data.first; ale; ale = ale->next) { + NlaTrack *nlt = (NlaTrack *)ale->data; + NlaStrip *strip; + + for (strip = nlt->strips.first; strip; strip = strip->next) { + /* can F-Modifier be added to the current strip? */ + if (active_only) { + /* if not active, cannot add since we're only adding to active strip */ + if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0) + continue; + } + else { + /* strip must be selected, since we're not just doing active */ + if ((strip->flag & NLASTRIP_FLAG_SELECT) == 0) + continue; + } + + /* sound clips are not affected by FModifiers */ + if (strip->type == NLASTRIP_TYPE_SOUND) + continue; + + /* add F-Modifier of specified type to selected, and make it the active one */ + fcm = add_fmodifier(&strip->modifiers, type, NULL); + + if (fcm) { + set_active_fmodifier(&strip->modifiers, fcm); + ale->update |= ANIM_UPDATE_DEPS; + } + else { + BKE_reportf(op->reports, + RPT_ERROR, + "Modifier could not be added to (%s : %s) (see console for details)", + nlt->name, + strip->name); + } + } + } + + /* free temp 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_NLA | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; } void NLA_OT_fmodifier_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add F-Modifier"; - ot->idname = "NLA_OT_fmodifier_add"; - ot->description = "Add F-Modifier to the active/selected NLA-Strips"; - - /* api callbacks */ - ot->invoke = WM_menu_invoke; - ot->exec = nla_fmodifier_add_exec; - ot->poll = nlaop_poll_tweakmode_off; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* id-props */ - ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_fmodifier_type_items, 0, "Type", ""); - RNA_def_enum_funcs(ot->prop, nla_fmodifier_itemf); - - RNA_def_boolean(ot->srna, "only_active", true, "Only Active", "Only add a F-Modifier of the specified type to the active strip"); + /* identifiers */ + ot->name = "Add F-Modifier"; + ot->idname = "NLA_OT_fmodifier_add"; + ot->description = "Add F-Modifier to the active/selected NLA-Strips"; + + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = nla_fmodifier_add_exec; + ot->poll = nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* id-props */ + ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_fmodifier_type_items, 0, "Type", ""); + RNA_def_enum_funcs(ot->prop, nla_fmodifier_itemf); + + RNA_def_boolean(ot->srna, + "only_active", + true, + "Only Active", + "Only add a F-Modifier of the specified type to the active strip"); } /* ******************** Copy F-Modifiers Operator *********************** */ static int nla_fmodifier_copy_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - bool ok = false; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* clear buffer first */ - ANIM_fmodifiers_copybuf_free(); - - /* get a list of the editable tracks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - /* for each NLA-Track, add the specified modifier to all selected strips */ - for (ale = anim_data.first; ale; ale = ale->next) { - NlaTrack *nlt = (NlaTrack *)ale->data; - NlaStrip *strip; - - for (strip = nlt->strips.first; strip; strip = strip->next) { - /* only add F-Modifier if on active strip? */ - if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0) - continue; - - // TODO: when 'active' vs 'all' boolean is added, change last param! - ok |= ANIM_fmodifiers_copy_to_buf(&strip->modifiers, 0); - } - } - - /* free temp data */ - ANIM_animdata_freelist(&anim_data); - - /* successful or not? */ - if (ok == 0) { - BKE_report(op->reports, RPT_ERROR, "No F-Modifiers available to be copied"); - return OPERATOR_CANCELLED; - } - else { - /* no updates needed - copy is non-destructive operation */ - return OPERATOR_FINISHED; - } + bAnimContext ac; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + bool ok = false; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* clear buffer first */ + ANIM_fmodifiers_copybuf_free(); + + /* get a list of the editable tracks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* for each NLA-Track, add the specified modifier to all selected strips */ + for (ale = anim_data.first; ale; ale = ale->next) { + NlaTrack *nlt = (NlaTrack *)ale->data; + NlaStrip *strip; + + for (strip = nlt->strips.first; strip; strip = strip->next) { + /* only add F-Modifier if on active strip? */ + if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0) + continue; + + // TODO: when 'active' vs 'all' boolean is added, change last param! + ok |= ANIM_fmodifiers_copy_to_buf(&strip->modifiers, 0); + } + } + + /* free temp data */ + ANIM_animdata_freelist(&anim_data); + + /* successful or not? */ + if (ok == 0) { + BKE_report(op->reports, RPT_ERROR, "No F-Modifiers available to be copied"); + return OPERATOR_CANCELLED; + } + else { + /* no updates needed - copy is non-destructive operation */ + return OPERATOR_FINISHED; + } } void NLA_OT_fmodifier_copy(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Copy F-Modifiers"; - ot->idname = "NLA_OT_fmodifier_copy"; - ot->description = "Copy the F-Modifier(s) of the active NLA-Strip"; + /* identifiers */ + ot->name = "Copy F-Modifiers"; + ot->idname = "NLA_OT_fmodifier_copy"; + ot->description = "Copy the F-Modifier(s) of the active NLA-Strip"; - /* api callbacks */ - ot->exec = nla_fmodifier_copy_exec; - ot->poll = nlaop_poll_tweakmode_off; + /* api callbacks */ + ot->exec = nla_fmodifier_copy_exec; + ot->poll = nlaop_poll_tweakmode_off; - /* 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 nla_fmodifier_paste_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter, ok = 0; - - const bool active_only = RNA_boolean_get(op->ptr, "only_active"); - const bool replace = RNA_boolean_get(op->ptr, "replace"); - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* get a list of the editable tracks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - /* for each NLA-Track, add the specified modifier to all selected strips */ - for (ale = anim_data.first; ale; ale = ale->next) { - NlaTrack *nlt = (NlaTrack *)ale->data; - NlaStrip *strip; - - for (strip = nlt->strips.first; strip; strip = strip->next) { - /* can F-Modifier be added to the current strip? */ - if (active_only) { - /* if not active, cannot add since we're only adding to active strip */ - if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0) - continue; - } - else { - /* strip must be selected, since we're not just doing active */ - if ((strip->flag & NLASTRIP_FLAG_SELECT) == 0) - continue; - } - - /* paste FModifiers from buffer */ - ok += ANIM_fmodifiers_paste_from_buf(&strip->modifiers, replace, NULL); - ale->update |= ANIM_UPDATE_DEPS; - } - } - - /* clean up */ - ANIM_animdata_update(&ac, &anim_data); - ANIM_animdata_freelist(&anim_data); - - /* successful or not? */ - if (ok) { - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); - return OPERATOR_FINISHED; - } - else { - BKE_report(op->reports, RPT_ERROR, "No F-Modifiers to paste"); - return OPERATOR_CANCELLED; - } + bAnimContext ac; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter, ok = 0; + + const bool active_only = RNA_boolean_get(op->ptr, "only_active"); + const bool replace = RNA_boolean_get(op->ptr, "replace"); + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the editable tracks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | + ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* for each NLA-Track, add the specified modifier to all selected strips */ + for (ale = anim_data.first; ale; ale = ale->next) { + NlaTrack *nlt = (NlaTrack *)ale->data; + NlaStrip *strip; + + for (strip = nlt->strips.first; strip; strip = strip->next) { + /* can F-Modifier be added to the current strip? */ + if (active_only) { + /* if not active, cannot add since we're only adding to active strip */ + if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0) + continue; + } + else { + /* strip must be selected, since we're not just doing active */ + if ((strip->flag & NLASTRIP_FLAG_SELECT) == 0) + continue; + } + + /* paste FModifiers from buffer */ + ok += ANIM_fmodifiers_paste_from_buf(&strip->modifiers, replace, NULL); + ale->update |= ANIM_UPDATE_DEPS; + } + } + + /* clean up */ + ANIM_animdata_update(&ac, &anim_data); + ANIM_animdata_freelist(&anim_data); + + /* successful or not? */ + if (ok) { + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); + return OPERATOR_FINISHED; + } + else { + BKE_report(op->reports, RPT_ERROR, "No F-Modifiers to paste"); + return OPERATOR_CANCELLED; + } } void NLA_OT_fmodifier_paste(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Paste F-Modifiers"; - ot->idname = "NLA_OT_fmodifier_paste"; - ot->description = "Add copied F-Modifiers to the selected NLA-Strips"; - - /* api callbacks */ - ot->exec = nla_fmodifier_paste_exec; - ot->poll = nlaop_poll_tweakmode_off; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - RNA_def_boolean(ot->srna, "only_active", true, "Only Active", "Only paste F-Modifiers on active strip"); - RNA_def_boolean(ot->srna, "replace", false, "Replace Existing", - "Replace existing F-Modifiers, instead of just appending to the end of the existing list"); + /* identifiers */ + ot->name = "Paste F-Modifiers"; + ot->idname = "NLA_OT_fmodifier_paste"; + ot->description = "Add copied F-Modifiers to the selected NLA-Strips"; + + /* api callbacks */ + ot->exec = nla_fmodifier_paste_exec; + ot->poll = nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + RNA_def_boolean( + ot->srna, "only_active", true, "Only Active", "Only paste F-Modifiers on active strip"); + RNA_def_boolean( + ot->srna, + "replace", + false, + "Replace Existing", + "Replace existing F-Modifiers, instead of just appending to the end of the existing list"); } /* *********************************************** */ diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index bb52d9d7f76..291dfe17343 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -34,7 +34,10 @@ ARegion *nla_has_buttons_region(ScrArea *sa); -bool nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA *nlt_ptr, PointerRNA *strip_ptr); +bool nla_panel_context(const bContext *C, + PointerRNA *adt_ptr, + PointerRNA *nlt_ptr, + PointerRNA *strip_ptr); void nla_buttons_register(ARegionType *art); void NLA_OT_properties(wmOperatorType *ot); @@ -50,10 +53,10 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar); /* defines for left-right select tool */ enum eNlaEdit_LeftRightSelect_Mode { - NLAEDIT_LRSEL_TEST = -1, - NLAEDIT_LRSEL_NONE, - NLAEDIT_LRSEL_LEFT, - NLAEDIT_LRSEL_RIGHT, + NLAEDIT_LRSEL_TEST = -1, + NLAEDIT_LRSEL_NONE, + NLAEDIT_LRSEL_LEFT, + NLAEDIT_LRSEL_RIGHT, }; /* --- */ @@ -68,10 +71,10 @@ void NLA_OT_click_select(wmOperatorType *ot); /* defines for snap strips */ enum eNlaEdit_Snap_Mode { - NLAEDIT_SNAP_CFRA = 1, - NLAEDIT_SNAP_NEAREST_FRAME, - NLAEDIT_SNAP_NEAREST_SECOND, - NLAEDIT_SNAP_NEAREST_MARKER, + NLAEDIT_SNAP_CFRA = 1, + NLAEDIT_SNAP_NEAREST_FRAME, + NLAEDIT_SNAP_NEAREST_SECOND, + NLAEDIT_SNAP_NEAREST_MARKER, }; /* --- */ @@ -119,7 +122,6 @@ void NLA_OT_fmodifier_add(wmOperatorType *ot); void NLA_OT_fmodifier_copy(wmOperatorType *ot); void NLA_OT_fmodifier_paste(wmOperatorType *ot); - /* **************************************** */ /* nla_channels.c */ diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 6653c3995b5..51d6232cf71 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -40,7 +40,6 @@ #include "RNA_access.h" - #include "nla_intern.h" /* own include */ /* ************************** poll callbacks for operators **********************************/ @@ -48,138 +47,138 @@ /* tweakmode is NOT enabled */ bool nlaop_poll_tweakmode_off(bContext *C) { - Scene *scene; - - /* for now, we check 2 things: - * 1) active editor must be NLA - * 2) tweakmode is currently set as a 'per-scene' flag - * so that it will affect entire NLA data-sets, - * but not all AnimData blocks will be in tweakmode for - * various reasons - */ - if (ED_operator_nla_active(C) == 0) - return 0; - - scene = CTX_data_scene(C); - if ((scene == NULL) || (scene->flag & SCE_NLA_EDIT_ON)) - return 0; - - return 1; + Scene *scene; + + /* for now, we check 2 things: + * 1) active editor must be NLA + * 2) tweakmode is currently set as a 'per-scene' flag + * so that it will affect entire NLA data-sets, + * but not all AnimData blocks will be in tweakmode for + * various reasons + */ + if (ED_operator_nla_active(C) == 0) + return 0; + + scene = CTX_data_scene(C); + if ((scene == NULL) || (scene->flag & SCE_NLA_EDIT_ON)) + return 0; + + return 1; } /* tweakmode IS enabled */ bool nlaop_poll_tweakmode_on(bContext *C) { - Scene *scene; - - /* for now, we check 2 things: - * 1) active editor must be NLA - * 2) tweakmode is currently set as a 'per-scene' flag - * so that it will affect entire NLA data-sets, - * but not all AnimData blocks will be in tweakmode for - * various reasons - */ - if (ED_operator_nla_active(C) == 0) - return 0; - - scene = CTX_data_scene(C); - if ((scene == NULL) || !(scene->flag & SCE_NLA_EDIT_ON)) - return 0; - - return 1; + Scene *scene; + + /* for now, we check 2 things: + * 1) active editor must be NLA + * 2) tweakmode is currently set as a 'per-scene' flag + * so that it will affect entire NLA data-sets, + * but not all AnimData blocks will be in tweakmode for + * various reasons + */ + if (ED_operator_nla_active(C) == 0) + return 0; + + scene = CTX_data_scene(C); + if ((scene == NULL) || !(scene->flag & SCE_NLA_EDIT_ON)) + return 0; + + return 1; } /* is tweakmode enabled - for use in NLA operator code */ bool nlaedit_is_tweakmode_on(bAnimContext *ac) { - if (ac && ac->scene) - return (ac->scene->flag & SCE_NLA_EDIT_ON) != 0; - return 0; + if (ac && ac->scene) + return (ac->scene->flag & SCE_NLA_EDIT_ON) != 0; + return 0; } /* ************************** registration - operator types **********************************/ void nla_operatortypes(void) { - /* view */ - WM_operatortype_append(NLA_OT_properties); + /* view */ + WM_operatortype_append(NLA_OT_properties); - /* channels */ - WM_operatortype_append(NLA_OT_channels_click); + /* channels */ + WM_operatortype_append(NLA_OT_channels_click); - WM_operatortype_append(NLA_OT_action_pushdown); - WM_operatortype_append(NLA_OT_action_unlink); + WM_operatortype_append(NLA_OT_action_pushdown); + WM_operatortype_append(NLA_OT_action_unlink); - WM_operatortype_append(NLA_OT_tracks_add); - WM_operatortype_append(NLA_OT_tracks_delete); + WM_operatortype_append(NLA_OT_tracks_add); + WM_operatortype_append(NLA_OT_tracks_delete); - WM_operatortype_append(NLA_OT_selected_objects_add); + WM_operatortype_append(NLA_OT_selected_objects_add); - /* select */ - WM_operatortype_append(NLA_OT_click_select); - WM_operatortype_append(NLA_OT_select_box); - WM_operatortype_append(NLA_OT_select_all); - WM_operatortype_append(NLA_OT_select_leftright); + /* select */ + WM_operatortype_append(NLA_OT_click_select); + WM_operatortype_append(NLA_OT_select_box); + WM_operatortype_append(NLA_OT_select_all); + WM_operatortype_append(NLA_OT_select_leftright); - /* view */ - WM_operatortype_append(NLA_OT_view_all); - WM_operatortype_append(NLA_OT_view_selected); - WM_operatortype_append(NLA_OT_view_frame); + /* view */ + WM_operatortype_append(NLA_OT_view_all); + WM_operatortype_append(NLA_OT_view_selected); + WM_operatortype_append(NLA_OT_view_frame); - WM_operatortype_append(NLA_OT_previewrange_set); + WM_operatortype_append(NLA_OT_previewrange_set); - /* edit */ - WM_operatortype_append(NLA_OT_tweakmode_enter); - WM_operatortype_append(NLA_OT_tweakmode_exit); + /* edit */ + WM_operatortype_append(NLA_OT_tweakmode_enter); + WM_operatortype_append(NLA_OT_tweakmode_exit); - WM_operatortype_append(NLA_OT_actionclip_add); - WM_operatortype_append(NLA_OT_transition_add); - WM_operatortype_append(NLA_OT_soundclip_add); + WM_operatortype_append(NLA_OT_actionclip_add); + WM_operatortype_append(NLA_OT_transition_add); + WM_operatortype_append(NLA_OT_soundclip_add); - WM_operatortype_append(NLA_OT_meta_add); - WM_operatortype_append(NLA_OT_meta_remove); + WM_operatortype_append(NLA_OT_meta_add); + WM_operatortype_append(NLA_OT_meta_remove); - WM_operatortype_append(NLA_OT_duplicate); - WM_operatortype_append(NLA_OT_delete); - WM_operatortype_append(NLA_OT_split); + WM_operatortype_append(NLA_OT_duplicate); + WM_operatortype_append(NLA_OT_delete); + WM_operatortype_append(NLA_OT_split); - WM_operatortype_append(NLA_OT_mute_toggle); + WM_operatortype_append(NLA_OT_mute_toggle); - WM_operatortype_append(NLA_OT_swap); - WM_operatortype_append(NLA_OT_move_up); - WM_operatortype_append(NLA_OT_move_down); + WM_operatortype_append(NLA_OT_swap); + WM_operatortype_append(NLA_OT_move_up); + WM_operatortype_append(NLA_OT_move_down); - WM_operatortype_append(NLA_OT_action_sync_length); + WM_operatortype_append(NLA_OT_action_sync_length); - WM_operatortype_append(NLA_OT_make_single_user); + WM_operatortype_append(NLA_OT_make_single_user); - WM_operatortype_append(NLA_OT_apply_scale); - WM_operatortype_append(NLA_OT_clear_scale); + WM_operatortype_append(NLA_OT_apply_scale); + WM_operatortype_append(NLA_OT_clear_scale); - WM_operatortype_append(NLA_OT_snap); + WM_operatortype_append(NLA_OT_snap); - WM_operatortype_append(NLA_OT_fmodifier_add); - WM_operatortype_append(NLA_OT_fmodifier_copy); - WM_operatortype_append(NLA_OT_fmodifier_paste); + WM_operatortype_append(NLA_OT_fmodifier_add); + WM_operatortype_append(NLA_OT_fmodifier_copy); + WM_operatortype_append(NLA_OT_fmodifier_paste); } /* ************************** registration - keymaps **********************************/ void nla_keymap(wmKeyConfig *keyconf) { - /* keymap for all regions ------------------------------------------- */ - WM_keymap_ensure(keyconf, "NLA Generic", SPACE_NLA, 0); - - /* channels ---------------------------------------------------------- */ - /* Channels are not directly handled by the NLA Editor module, but are inherited from the Animation module. - * Most of the relevant operations, keymaps, drawing, etc. can therefore all - * be found in that module instead, as there are many similarities with the other Animation Editors. - * - * However, those operations which involve clicking on channels and/or - * the placement of them in the view are implemented here instead - */ - WM_keymap_ensure(keyconf, "NLA Channels", SPACE_NLA, 0); - - /* data ------------------------------------------------------------- */ - WM_keymap_ensure(keyconf, "NLA Editor", SPACE_NLA, 0); + /* keymap for all regions ------------------------------------------- */ + WM_keymap_ensure(keyconf, "NLA Generic", SPACE_NLA, 0); + + /* channels ---------------------------------------------------------- */ + /* Channels are not directly handled by the NLA Editor module, but are inherited from the Animation module. + * Most of the relevant operations, keymaps, drawing, etc. can therefore all + * be found in that module instead, as there are many similarities with the other Animation Editors. + * + * However, those operations which involve clicking on channels and/or + * the placement of them in the view are implemented here instead + */ + WM_keymap_ensure(keyconf, "NLA Channels", SPACE_NLA, 0); + + /* data ------------------------------------------------------------- */ + WM_keymap_ensure(keyconf, "NLA Editor", SPACE_NLA, 0); } diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index f326637f1cd..0df0c5a99da 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -21,7 +21,6 @@ * \ingroup spnla */ - #include <string.h> #include <stdio.h> @@ -49,28 +48,27 @@ #include "UI_view2d.h" -#include "nla_intern.h" // own include +#include "nla_intern.h" // own include /* ******************** Utilities ***************************************** */ /* Convert SELECT_* flags to ACHANNEL_SETFLAG_* flags */ static short selmodes_to_flagmodes(short sel) { - /* convert selection modes to selection modes */ - switch (sel) { - case SELECT_SUBTRACT: - return ACHANNEL_SETFLAG_CLEAR; - - case SELECT_INVERT: - return ACHANNEL_SETFLAG_INVERT; - - case SELECT_ADD: - default: - return ACHANNEL_SETFLAG_ADD; - } + /* convert selection modes to selection modes */ + switch (sel) { + case SELECT_SUBTRACT: + return ACHANNEL_SETFLAG_CLEAR; + + case SELECT_INVERT: + return ACHANNEL_SETFLAG_INVERT; + + case SELECT_ADD: + default: + return ACHANNEL_SETFLAG_ADD; + } } - /* ******************** Deselect All Operator ***************************** */ /* This operator works in one of three ways: * 1) (de)select all (AKEY) - test if select all or deselect all @@ -79,9 +77,9 @@ static short selmodes_to_flagmodes(short sel) */ enum { - DESELECT_STRIPS_NOTEST = 0, - DESELECT_STRIPS_TEST, - DESELECT_STRIPS_CLEARACTIVE, + DESELECT_STRIPS_NOTEST = 0, + DESELECT_STRIPS_TEST, + DESELECT_STRIPS_CLEARACTIVE, } /*eDeselectNlaStrips*/; /* Deselects strips in the NLA Editor @@ -95,113 +93,113 @@ enum { */ static void deselect_nla_strips(bAnimContext *ac, short test, short sel) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - short smode; - - /* determine type-based settings */ - // FIXME: double check whether ANIMFILTER_LIST_VISIBLE is needed! - filter = (ANIMFILTER_DATA_VISIBLE); - - /* filter data */ - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* See if we should be selecting or deselecting */ - if (test == DESELECT_STRIPS_TEST) { - for (ale = anim_data.first; ale; ale = ale->next) { - NlaTrack *nlt = (NlaTrack *)ale->data; - NlaStrip *strip; - - /* if any strip is selected, break out, since we should now be deselecting */ - for (strip = nlt->strips.first; strip; strip = strip->next) { - if (strip->flag & NLASTRIP_FLAG_SELECT) { - sel = SELECT_SUBTRACT; - break; - } - } - - if (sel == SELECT_SUBTRACT) - break; - } - } - - /* convert selection modes to selection modes */ - smode = selmodes_to_flagmodes(sel); - - /* Now set the flags */ - for (ale = anim_data.first; ale; ale = ale->next) { - NlaTrack *nlt = (NlaTrack *)ale->data; - NlaStrip *strip; - - /* apply same selection to all strips */ - for (strip = nlt->strips.first; strip; strip = strip->next) { - /* set selection */ - if (test != DESELECT_STRIPS_CLEARACTIVE) - ACHANNEL_SET_FLAG(strip, smode, NLASTRIP_FLAG_SELECT); - - /* clear active flag */ - // TODO: for clear active, do we want to limit this to only doing this on a certain set of tracks though? - strip->flag &= ~NLASTRIP_FLAG_ACTIVE; - } - } - - /* Cleanup */ - ANIM_animdata_freelist(&anim_data); + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + short smode; + + /* determine type-based settings */ + // FIXME: double check whether ANIMFILTER_LIST_VISIBLE is needed! + filter = (ANIMFILTER_DATA_VISIBLE); + + /* filter data */ + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* See if we should be selecting or deselecting */ + if (test == DESELECT_STRIPS_TEST) { + for (ale = anim_data.first; ale; ale = ale->next) { + NlaTrack *nlt = (NlaTrack *)ale->data; + NlaStrip *strip; + + /* if any strip is selected, break out, since we should now be deselecting */ + for (strip = nlt->strips.first; strip; strip = strip->next) { + if (strip->flag & NLASTRIP_FLAG_SELECT) { + sel = SELECT_SUBTRACT; + break; + } + } + + if (sel == SELECT_SUBTRACT) + break; + } + } + + /* convert selection modes to selection modes */ + smode = selmodes_to_flagmodes(sel); + + /* Now set the flags */ + for (ale = anim_data.first; ale; ale = ale->next) { + NlaTrack *nlt = (NlaTrack *)ale->data; + NlaStrip *strip; + + /* apply same selection to all strips */ + for (strip = nlt->strips.first; strip; strip = strip->next) { + /* set selection */ + if (test != DESELECT_STRIPS_CLEARACTIVE) + ACHANNEL_SET_FLAG(strip, smode, NLASTRIP_FLAG_SELECT); + + /* clear active flag */ + // TODO: for clear active, do we want to limit this to only doing this on a certain set of tracks though? + strip->flag &= ~NLASTRIP_FLAG_ACTIVE; + } + } + + /* Cleanup */ + ANIM_animdata_freelist(&anim_data); } /* ------------------- */ static int nlaedit_deselectall_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* 'standard' behavior - check if selected, then apply relevant selection */ - const int action = RNA_enum_get(op->ptr, "action"); - switch (action) { - case SEL_TOGGLE: - deselect_nla_strips(&ac, DESELECT_STRIPS_TEST, SELECT_ADD); - break; - case SEL_SELECT: - deselect_nla_strips(&ac, DESELECT_STRIPS_NOTEST, SELECT_ADD); - break; - case SEL_DESELECT: - deselect_nla_strips(&ac, DESELECT_STRIPS_NOTEST, SELECT_SUBTRACT); - break; - case SEL_INVERT: - deselect_nla_strips(&ac, DESELECT_STRIPS_NOTEST, SELECT_INVERT); - break; - default: - BLI_assert(0); - break; - } - - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_SELECTED, NULL); - - return OPERATOR_FINISHED; + bAnimContext ac; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* 'standard' behavior - check if selected, then apply relevant selection */ + const int action = RNA_enum_get(op->ptr, "action"); + switch (action) { + case SEL_TOGGLE: + deselect_nla_strips(&ac, DESELECT_STRIPS_TEST, SELECT_ADD); + break; + case SEL_SELECT: + deselect_nla_strips(&ac, DESELECT_STRIPS_NOTEST, SELECT_ADD); + break; + case SEL_DESELECT: + deselect_nla_strips(&ac, DESELECT_STRIPS_NOTEST, SELECT_SUBTRACT); + break; + case SEL_INVERT: + deselect_nla_strips(&ac, DESELECT_STRIPS_NOTEST, SELECT_INVERT); + break; + default: + BLI_assert(0); + break; + } + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_SELECTED, NULL); + + return OPERATOR_FINISHED; } void NLA_OT_select_all(wmOperatorType *ot) { - /* identifiers */ - ot->name = "(De)select All"; - ot->idname = "NLA_OT_select_all"; - ot->description = "Select or deselect all NLA-Strips"; + /* identifiers */ + ot->name = "(De)select All"; + ot->idname = "NLA_OT_select_all"; + ot->description = "Select or deselect all NLA-Strips"; - /* api callbacks */ - ot->exec = nlaedit_deselectall_exec; - ot->poll = nlaop_poll_tweakmode_off; + /* api callbacks */ + ot->exec = nlaedit_deselectall_exec; + ot->poll = nlaop_poll_tweakmode_off; - /* 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 **************************** */ @@ -214,138 +212,134 @@ void NLA_OT_select_all(wmOperatorType *ot) /* defines for box_select mode */ enum { - NLA_BOXSEL_ALLSTRIPS = 0, - NLA_BOXSEL_FRAMERANGE, - NLA_BOXSEL_CHANNELS, + NLA_BOXSEL_ALLSTRIPS = 0, + NLA_BOXSEL_FRAMERANGE, + NLA_BOXSEL_CHANNELS, } /* eNLAEDIT_BoxSelect_Mode */; - static void box_select_nla_strips(bAnimContext *ac, rcti rect, short mode, short selectmode) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - SpaceNla *snla = (SpaceNla *)ac->sl; - View2D *v2d = &ac->ar->v2d; - rctf rectf; - float ymin /* =(float)(-NLACHANNEL_HEIGHT(snla)) */ /* UNUSED */, ymax = 0; - - /* convert border-region to view coordinates */ - UI_view2d_region_to_view(v2d, rect.xmin, rect.ymin + 2, &rectf.xmin, &rectf.ymin); - UI_view2d_region_to_view(v2d, rect.xmax, rect.ymax - 2, &rectf.xmax, &rectf.ymax); - - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* convert selection modes to selection modes */ - selectmode = selmodes_to_flagmodes(selectmode); - - /* loop over data, doing box select */ - for (ale = anim_data.first; ale; ale = ale->next) { - ymin = ymax - NLACHANNEL_STEP(snla); - - /* perform vertical suitability check (if applicable) */ - if ((mode == NLA_BOXSEL_FRAMERANGE) || - !((ymax < rectf.ymin) || (ymin > rectf.ymax))) - { - /* loop over data selecting (only if NLA-Track) */ - if (ale->type == ANIMTYPE_NLATRACK) { - NlaTrack *nlt = (NlaTrack *)ale->data; - NlaStrip *strip; - - /* only select strips if they fall within the required ranges (if applicable) */ - for (strip = nlt->strips.first; strip; strip = strip->next) { - if ((mode == NLA_BOXSEL_CHANNELS) || - BKE_nlastrip_within_bounds(strip, rectf.xmin, rectf.xmax)) - { - /* set selection */ - ACHANNEL_SET_FLAG(strip, selectmode, NLASTRIP_FLAG_SELECT); - - /* clear active flag */ - strip->flag &= ~NLASTRIP_FLAG_ACTIVE; - } - } - } - } - - /* set minimum extent to be the maximum of the next channel */ - ymax = ymin; - } - - /* cleanup */ - ANIM_animdata_freelist(&anim_data); + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + SpaceNla *snla = (SpaceNla *)ac->sl; + View2D *v2d = &ac->ar->v2d; + rctf rectf; + float ymin /* =(float)(-NLACHANNEL_HEIGHT(snla)) */ /* UNUSED */, ymax = 0; + + /* convert border-region to view coordinates */ + UI_view2d_region_to_view(v2d, rect.xmin, rect.ymin + 2, &rectf.xmin, &rectf.ymin); + UI_view2d_region_to_view(v2d, rect.xmax, rect.ymax - 2, &rectf.xmax, &rectf.ymax); + + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* convert selection modes to selection modes */ + selectmode = selmodes_to_flagmodes(selectmode); + + /* loop over data, doing box select */ + for (ale = anim_data.first; ale; ale = ale->next) { + ymin = ymax - NLACHANNEL_STEP(snla); + + /* perform vertical suitability check (if applicable) */ + if ((mode == NLA_BOXSEL_FRAMERANGE) || !((ymax < rectf.ymin) || (ymin > rectf.ymax))) { + /* loop over data selecting (only if NLA-Track) */ + if (ale->type == ANIMTYPE_NLATRACK) { + NlaTrack *nlt = (NlaTrack *)ale->data; + NlaStrip *strip; + + /* only select strips if they fall within the required ranges (if applicable) */ + for (strip = nlt->strips.first; strip; strip = strip->next) { + if ((mode == NLA_BOXSEL_CHANNELS) || + BKE_nlastrip_within_bounds(strip, rectf.xmin, rectf.xmax)) { + /* set selection */ + ACHANNEL_SET_FLAG(strip, selectmode, NLASTRIP_FLAG_SELECT); + + /* clear active flag */ + strip->flag &= ~NLASTRIP_FLAG_ACTIVE; + } + } + } + } + + /* set minimum extent to be the maximum of the next channel */ + ymax = ymin; + } + + /* cleanup */ + ANIM_animdata_freelist(&anim_data); } /* ------------------- */ static int nlaedit_box_select_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - rcti rect; - 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_nla_strips(&ac, DESELECT_STRIPS_TEST, SELECT_SUBTRACT); - } - - /* 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 = NLA_BOXSEL_FRAMERANGE; - else - mode = NLA_BOXSEL_CHANNELS; - } - else - mode = NLA_BOXSEL_ALLSTRIPS; - - /* apply box_select action */ - box_select_nla_strips(&ac, rect, mode, selectmode); - - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_SELECTED, NULL); - - return OPERATOR_FINISHED; + bAnimContext ac; + rcti rect; + 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_nla_strips(&ac, DESELECT_STRIPS_TEST, SELECT_SUBTRACT); + } + + /* 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 = NLA_BOXSEL_FRAMERANGE; + else + mode = NLA_BOXSEL_CHANNELS; + } + else + mode = NLA_BOXSEL_ALLSTRIPS; + + /* apply box_select action */ + box_select_nla_strips(&ac, rect, mode, selectmode); + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_SELECTED, NULL); + + return OPERATOR_FINISHED; } void NLA_OT_select_box(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Box Select"; - ot->idname = "NLA_OT_select_box"; - ot->description = "Use box selection to grab NLA-Strips"; + /* identifiers */ + ot->name = "Box Select"; + ot->idname = "NLA_OT_select_box"; + ot->description = "Use box selection to grab NLA-Strips"; - /* api callbacks */ - ot->invoke = WM_gesture_box_invoke; - ot->exec = nlaedit_box_select_exec; - ot->modal = WM_gesture_box_modal; - ot->cancel = WM_gesture_box_cancel; + /* api callbacks */ + ot->invoke = WM_gesture_box_invoke; + ot->exec = nlaedit_box_select_exec; + ot->modal = WM_gesture_box_modal; + ot->cancel = WM_gesture_box_cancel; - ot->poll = nlaop_poll_tweakmode_off; + ot->poll = nlaop_poll_tweakmode_off; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ - RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", ""); + /* properties */ + RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", ""); - WM_operator_properties_gesture_box(ot); - WM_operator_properties_select_operation_simple(ot); + WM_operator_properties_gesture_box(ot); + WM_operator_properties_select_operation_simple(ot); } /* ******************** Select Left/Right Operator ************************* */ @@ -353,266 +347,276 @@ void NLA_OT_select_box(wmOperatorType *ot) /* defines for left-right select tool */ static const EnumPropertyItem prop_nlaedit_leftright_select_types[] = { - {NLAEDIT_LRSEL_TEST, "CHECK", 0, "Check if Select Left or Right", ""}, - {NLAEDIT_LRSEL_LEFT, "LEFT", 0, "Before current frame", ""}, - {NLAEDIT_LRSEL_RIGHT, "RIGHT", 0, "After current frame", ""}, - {0, NULL, 0, NULL, NULL}, + {NLAEDIT_LRSEL_TEST, "CHECK", 0, "Check if Select Left or Right", ""}, + {NLAEDIT_LRSEL_LEFT, "LEFT", 0, "Before current frame", ""}, + {NLAEDIT_LRSEL_RIGHT, "RIGHT", 0, "After current frame", ""}, + {0, NULL, 0, NULL, NULL}, }; /* ------------------- */ -static void nlaedit_select_leftright(bContext *C, bAnimContext *ac, short leftright, short select_mode) +static void nlaedit_select_leftright(bContext *C, + bAnimContext *ac, + short leftright, + short select_mode) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - Scene *scene = ac->scene; - float xmin, xmax; - - /* if currently in tweakmode, exit tweakmode first */ - if (scene->flag & SCE_NLA_EDIT_ON) - WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL); - - /* 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_nla_strips(ac, 0, SELECT_SUBTRACT); - } - - /* get range, and get the right flag-setting mode */ - if (leftright == NLAEDIT_LRSEL_LEFT) { - xmin = MINAFRAMEF; - xmax = (float)(CFRA + 0.1f); - } - else { - xmin = (float)(CFRA - 0.1f); - xmax = MAXFRAMEF; - } - - select_mode = selmodes_to_flagmodes(select_mode); - - - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* select strips on the side where most data occurs */ - for (ale = anim_data.first; ale; ale = ale->next) { - NlaTrack *nlt = (NlaTrack *)ale->data; - NlaStrip *strip; - - /* check each strip to see if it is appropriate */ - for (strip = nlt->strips.first; strip; strip = strip->next) { - if (BKE_nlastrip_within_bounds(strip, xmin, xmax)) { - ACHANNEL_SET_FLAG(strip, select_mode, NLASTRIP_FLAG_SELECT); - } - } - } - - /* Cleanup */ - ANIM_animdata_freelist(&anim_data); + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + Scene *scene = ac->scene; + float xmin, xmax; + + /* if currently in tweakmode, exit tweakmode first */ + if (scene->flag & SCE_NLA_EDIT_ON) + WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL); + + /* 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_nla_strips(ac, 0, SELECT_SUBTRACT); + } + + /* get range, and get the right flag-setting mode */ + if (leftright == NLAEDIT_LRSEL_LEFT) { + xmin = MINAFRAMEF; + xmax = (float)(CFRA + 0.1f); + } + else { + xmin = (float)(CFRA - 0.1f); + xmax = MAXFRAMEF; + } + + select_mode = selmodes_to_flagmodes(select_mode); + + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* select strips on the side where most data occurs */ + for (ale = anim_data.first; ale; ale = ale->next) { + NlaTrack *nlt = (NlaTrack *)ale->data; + NlaStrip *strip; + + /* check each strip to see if it is appropriate */ + for (strip = nlt->strips.first; strip; strip = strip->next) { + if (BKE_nlastrip_within_bounds(strip, xmin, xmax)) { + ACHANNEL_SET_FLAG(strip, select_mode, NLASTRIP_FLAG_SELECT); + } + } + } + + /* Cleanup */ + ANIM_animdata_freelist(&anim_data); } /* ------------------- */ static int nlaedit_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 == NLAEDIT_LRSEL_TEST) - return OPERATOR_CANCELLED; + /* if "test" mode is set, we don't have any info to set this with */ + if (leftright == NLAEDIT_LRSEL_TEST) + return OPERATOR_CANCELLED; - /* do the selecting now */ - nlaedit_select_leftright(C, &ac, leftright, selectmode); + /* do the selecting now */ + nlaedit_select_leftright(C, &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 nlaedit_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 == NLAEDIT_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", NLAEDIT_LRSEL_LEFT); - else - RNA_enum_set(op->ptr, "mode", NLAEDIT_LRSEL_RIGHT); - } - - /* perform selection */ - return nlaedit_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 == NLAEDIT_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", NLAEDIT_LRSEL_LEFT); + else + RNA_enum_set(op->ptr, "mode", NLAEDIT_LRSEL_RIGHT); + } + + /* perform selection */ + return nlaedit_select_leftright_exec(C, op); } void NLA_OT_select_leftright(wmOperatorType *ot) { - PropertyRNA *prop; + PropertyRNA *prop; - /* identifiers */ - ot->name = "Select Left/Right"; - ot->idname = "NLA_OT_select_leftright"; - ot->description = "Select strips to the left or the right of the current frame"; + /* identifiers */ + ot->name = "Select Left/Right"; + ot->idname = "NLA_OT_select_leftright"; + ot->description = "Select strips to the left or the right of the current frame"; - /* api callbacks */ - ot->invoke = nlaedit_select_leftright_invoke; - ot->exec = nlaedit_select_leftright_exec; - ot->poll = ED_operator_nla_active; + /* api callbacks */ + ot->invoke = nlaedit_select_leftright_invoke; + ot->exec = nlaedit_select_leftright_exec; + ot->poll = ED_operator_nla_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ - ot->prop = RNA_def_enum(ot->srna, "mode", prop_nlaedit_leftright_select_types, NLAEDIT_LRSEL_TEST, "Mode", ""); - RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); + /* properties */ + ot->prop = RNA_def_enum( + ot->srna, "mode", prop_nlaedit_leftright_select_types, NLAEDIT_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 *********************** */ /* select strip directly under mouse */ static void mouse_nla_strips(bContext *C, bAnimContext *ac, const int mval[2], short select_mode) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale = NULL; - int filter; - - SpaceNla *snla = (SpaceNla *)ac->sl; - View2D *v2d = &ac->ar->v2d; - Scene *scene = ac->scene; - NlaStrip *strip = NULL; - int channel_index; - float xmin, xmax; - float x, y; - - - /* use View2D to determine the index of the channel - * (i.e a row in the list) where keyframe was */ - UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y); - UI_view2d_listview_view_to_cell(v2d, 0, NLACHANNEL_STEP(snla), 0, (float)NLACHANNEL_HEIGHT_HALF(snla), x, y, NULL, &channel_index); - - /* x-range to check is +/- 7 (in screen/region-space) on either side of mouse click - * (that is the size of keyframe icons, so user should be expecting similar tolerances) - */ - xmin = UI_view2d_region_to_view_x(v2d, mval[0] - 7); - xmax = UI_view2d_region_to_view_x(v2d, mval[0] + 7); - - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* try to get channel */ - ale = BLI_findlink(&anim_data, channel_index); - if (ale == NULL) { - /* channel not found */ - printf("Error: animation channel (index = %d) not found in mouse_nla_strips()\n", channel_index); - ANIM_animdata_freelist(&anim_data); - return; - } - else { - /* found some channel - we only really should do something when its an Nla-Track */ - if (ale->type == ANIMTYPE_NLATRACK) { - NlaTrack *nlt = (NlaTrack *)ale->data; - - /* loop over NLA-strips in this track, - * trying to find one which occurs in the necessary bounds */ - for (strip = nlt->strips.first; strip; strip = strip->next) { - if (BKE_nlastrip_within_bounds(strip, xmin, xmax)) - break; - } - } - - /* remove active channel from list of channels for separate treatment - * (since it's needed later on) */ - BLI_remlink(&anim_data, ale); - - /* free list of channels, since it's not used anymore */ - ANIM_animdata_freelist(&anim_data); - } - - /* if currently in tweakmode, exit tweakmode before changing selection states - * now that we've found our target... - */ - if (scene->flag & SCE_NLA_EDIT_ON) - WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL); - - /* for replacing selection, firstly need to clear existing selection */ - if (select_mode == SELECT_REPLACE) { - /* reset selection mode for next steps */ - select_mode = SELECT_ADD; - - /* deselect all strips */ - deselect_nla_strips(ac, 0, SELECT_SUBTRACT); - - /* deselect all other channels first */ - ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); - } - - /* only select strip if we clicked on a valid channel and hit something */ - if (ale) { - /* select the strip accordingly (if a matching one was found) */ - if (strip) { - select_mode = selmodes_to_flagmodes(select_mode); - ACHANNEL_SET_FLAG(strip, select_mode, NLASTRIP_FLAG_SELECT); - - /* if we selected it, we can make it active too - * - we always need to clear the active strip flag though... - * - as well as selecting its track... - */ - deselect_nla_strips(ac, DESELECT_STRIPS_CLEARACTIVE, 0); - - if (strip->flag & NLASTRIP_FLAG_SELECT) { - strip->flag |= NLASTRIP_FLAG_ACTIVE; - - /* Highlight NLA-Track */ - if (ale->type == ANIMTYPE_NLATRACK) { - NlaTrack *nlt = (NlaTrack *)ale->data; - - nlt->flag |= NLATRACK_SELECTED; - ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK); - } - } - } - - /* free this channel */ - MEM_freeN(ale); - } + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale = NULL; + int filter; + + SpaceNla *snla = (SpaceNla *)ac->sl; + View2D *v2d = &ac->ar->v2d; + Scene *scene = ac->scene; + NlaStrip *strip = NULL; + int channel_index; + float xmin, xmax; + float x, y; + + /* use View2D to determine the index of the channel + * (i.e a row in the list) where keyframe was */ + UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y); + UI_view2d_listview_view_to_cell(v2d, + 0, + NLACHANNEL_STEP(snla), + 0, + (float)NLACHANNEL_HEIGHT_HALF(snla), + x, + y, + NULL, + &channel_index); + + /* x-range to check is +/- 7 (in screen/region-space) on either side of mouse click + * (that is the size of keyframe icons, so user should be expecting similar tolerances) + */ + xmin = UI_view2d_region_to_view_x(v2d, mval[0] - 7); + xmax = UI_view2d_region_to_view_x(v2d, mval[0] + 7); + + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* try to get channel */ + ale = BLI_findlink(&anim_data, channel_index); + if (ale == NULL) { + /* channel not found */ + printf("Error: animation channel (index = %d) not found in mouse_nla_strips()\n", + channel_index); + ANIM_animdata_freelist(&anim_data); + return; + } + else { + /* found some channel - we only really should do something when its an Nla-Track */ + if (ale->type == ANIMTYPE_NLATRACK) { + NlaTrack *nlt = (NlaTrack *)ale->data; + + /* loop over NLA-strips in this track, + * trying to find one which occurs in the necessary bounds */ + for (strip = nlt->strips.first; strip; strip = strip->next) { + if (BKE_nlastrip_within_bounds(strip, xmin, xmax)) + break; + } + } + + /* remove active channel from list of channels for separate treatment + * (since it's needed later on) */ + BLI_remlink(&anim_data, ale); + + /* free list of channels, since it's not used anymore */ + ANIM_animdata_freelist(&anim_data); + } + + /* if currently in tweakmode, exit tweakmode before changing selection states + * now that we've found our target... + */ + if (scene->flag & SCE_NLA_EDIT_ON) + WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL); + + /* for replacing selection, firstly need to clear existing selection */ + if (select_mode == SELECT_REPLACE) { + /* reset selection mode for next steps */ + select_mode = SELECT_ADD; + + /* deselect all strips */ + deselect_nla_strips(ac, 0, SELECT_SUBTRACT); + + /* deselect all other channels first */ + ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); + } + + /* only select strip if we clicked on a valid channel and hit something */ + if (ale) { + /* select the strip accordingly (if a matching one was found) */ + if (strip) { + select_mode = selmodes_to_flagmodes(select_mode); + ACHANNEL_SET_FLAG(strip, select_mode, NLASTRIP_FLAG_SELECT); + + /* if we selected it, we can make it active too + * - we always need to clear the active strip flag though... + * - as well as selecting its track... + */ + deselect_nla_strips(ac, DESELECT_STRIPS_CLEARACTIVE, 0); + + if (strip->flag & NLASTRIP_FLAG_SELECT) { + strip->flag |= NLASTRIP_FLAG_ACTIVE; + + /* Highlight NLA-Track */ + if (ale->type == ANIMTYPE_NLATRACK) { + NlaTrack *nlt = (NlaTrack *)ale->data; + + nlt->flag |= NLATRACK_SELECTED; + ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK); + } + } + } + + /* free this channel */ + MEM_freeN(ale); + } } /* ------------------- */ @@ -620,56 +624,56 @@ static void mouse_nla_strips(bContext *C, bAnimContext *ac, const int mval[2], s /* handle clicking */ static int nlaedit_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - bAnimContext ac; - /* Scene *scene; */ /* UNUSED */ - /* ARegion *ar; */ /* UNUSED */ - // View2D *v2d; /*UNUSED*/ - short selectmode; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* get useful pointers from animation context data */ - /* scene= ac.scene; */ /* UNUSED */ - /* ar= ac.ar; */ /* UNUSED */ - // v2d= &ar->v2d; - - /* 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 strips based upon mouse position */ - mouse_nla_strips(C, &ac, event->mval, selectmode); - - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_SELECTED, NULL); - - /* for tweak grab to work */ - return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH; + bAnimContext ac; + /* Scene *scene; */ /* UNUSED */ + /* ARegion *ar; */ /* UNUSED */ + // View2D *v2d; /*UNUSED*/ + short selectmode; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get useful pointers from animation context data */ + /* scene= ac.scene; */ /* UNUSED */ + /* ar= ac.ar; */ /* UNUSED */ + // v2d= &ar->v2d; + + /* 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 strips based upon mouse position */ + mouse_nla_strips(C, &ac, event->mval, selectmode); + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_SELECTED, NULL); + + /* for tweak grab to work */ + return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH; } void NLA_OT_click_select(wmOperatorType *ot) { - PropertyRNA *prop; + PropertyRNA *prop; - /* identifiers */ - ot->name = "Select"; - ot->idname = "NLA_OT_click_select"; - ot->description = "Handle clicks to select NLA Strips"; + /* identifiers */ + ot->name = "Select"; + ot->idname = "NLA_OT_click_select"; + ot->description = "Handle clicks to select NLA Strips"; - /* api callbacks - absolutely no exec() this yet... */ - ot->invoke = nlaedit_clickselect_invoke; - ot->poll = ED_operator_nla_active; + /* api callbacks - absolutely no exec() this yet... */ + ot->invoke = nlaedit_clickselect_invoke; + ot->poll = ED_operator_nla_active; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; - /* properties */ - prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + /* properties */ + prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* *********************************************** */ diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index 84b8a64bc62..ccf2e552644 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -21,7 +21,6 @@ * \ingroup spnla */ - #include <string.h> #include <stdio.h> @@ -42,7 +41,6 @@ #include "ED_markers.h" #include "ED_screen.h" - #include "WM_api.h" #include "WM_types.h" #include "WM_message.h" @@ -59,619 +57,632 @@ ARegion *nla_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 nla"); + arnew = MEM_callocN(sizeof(ARegion), "buttons for nla"); - 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 nla space ***************** */ static SpaceLink *nla_new(const ScrArea *sa, const Scene *scene) { - ARegion *ar; - SpaceNla *snla; + ARegion *ar; + SpaceNla *snla; - snla = MEM_callocN(sizeof(SpaceNla), "initnla"); - snla->spacetype = SPACE_NLA; + snla = MEM_callocN(sizeof(SpaceNla), "initnla"); + snla->spacetype = SPACE_NLA; - /* allocate DopeSheet data for NLA Editor */ - snla->ads = MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet"); - snla->ads->source = (ID *)scene; + /* allocate DopeSheet data for NLA Editor */ + snla->ads = MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet"); + snla->ads->source = (ID *)scene; - /* set auto-snapping settings */ - snla->autosnap = SACTSNAP_FRAME; + /* set auto-snapping settings */ + snla->autosnap = SACTSNAP_FRAME; - /* header */ - ar = MEM_callocN(sizeof(ARegion), "header for nla"); + /* header */ + ar = MEM_callocN(sizeof(ARegion), "header for nla"); - BLI_addtail(&snla->regionbase, ar); - ar->regiontype = RGN_TYPE_HEADER; - ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP; + BLI_addtail(&snla->regionbase, ar); + ar->regiontype = RGN_TYPE_HEADER; + ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP; - /* channel list region */ - ar = MEM_callocN(sizeof(ARegion), "channel list for nla"); - BLI_addtail(&snla->regionbase, ar); - ar->regiontype = RGN_TYPE_CHANNELS; - ar->alignment = RGN_ALIGN_LEFT; + /* channel list region */ + ar = MEM_callocN(sizeof(ARegion), "channel list for nla"); + BLI_addtail(&snla->regionbase, ar); + ar->regiontype = RGN_TYPE_CHANNELS; + ar->alignment = RGN_ALIGN_LEFT; - /* only need to set these settings since this will use the 'stack' configuration */ - ar->v2d.scroll = V2D_SCROLL_BOTTOM; - ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL; + /* only need to set these settings since this will use the 'stack' configuration */ + ar->v2d.scroll = V2D_SCROLL_BOTTOM; + ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL; - /* ui buttons */ - ar = MEM_callocN(sizeof(ARegion), "buttons region for nla"); + /* ui buttons */ + ar = MEM_callocN(sizeof(ARegion), "buttons region for nla"); - BLI_addtail(&snla->regionbase, ar); - ar->regiontype = RGN_TYPE_UI; - ar->alignment = RGN_ALIGN_RIGHT; - ar->flag = RGN_FLAG_HIDDEN; + BLI_addtail(&snla->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 nla"); + /* main region */ + ar = MEM_callocN(sizeof(ARegion), "main region for nla"); - BLI_addtail(&snla->regionbase, ar); - ar->regiontype = RGN_TYPE_WINDOW; + BLI_addtail(&snla->regionbase, ar); + ar->regiontype = RGN_TYPE_WINDOW; - ar->v2d.tot.xmin = (float)(SFRA - 10); - ar->v2d.tot.ymin = (float)(-sa->winy) / 3.0f; - ar->v2d.tot.xmax = (float)(EFRA + 10); - ar->v2d.tot.ymax = 0.0f; + ar->v2d.tot.xmin = (float)(SFRA - 10); + ar->v2d.tot.ymin = (float)(-sa->winy) / 3.0f; + ar->v2d.tot.xmax = (float)(EFRA + 10); + ar->v2d.tot.ymax = 0.0f; - ar->v2d.cur = ar->v2d.tot; + ar->v2d.cur = ar->v2d.tot; - ar->v2d.min[0] = 0.0f; - ar->v2d.min[1] = 0.0f; + ar->v2d.min[0] = 0.0f; + ar->v2d.min[1] = 0.0f; - ar->v2d.max[0] = MAXFRAMEF; - ar->v2d.max[1] = 10000.0f; + ar->v2d.max[0] = MAXFRAMEF; + ar->v2d.max[1] = 10000.0f; - ar->v2d.minzoom = 0.01f; - ar->v2d.maxzoom = 50; - ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL); - ar->v2d.scroll |= (V2D_SCROLL_RIGHT); - ar->v2d.keepzoom = V2D_LOCKZOOM_Y; - ar->v2d.keepofs = V2D_KEEPOFS_Y; - ar->v2d.align = V2D_ALIGN_NO_POS_Y; - ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL; + ar->v2d.minzoom = 0.01f; + ar->v2d.maxzoom = 50; + ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL); + ar->v2d.scroll |= (V2D_SCROLL_RIGHT); + ar->v2d.keepzoom = V2D_LOCKZOOM_Y; + ar->v2d.keepofs = V2D_KEEPOFS_Y; + ar->v2d.align = V2D_ALIGN_NO_POS_Y; + ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL; - return (SpaceLink *)snla; + return (SpaceLink *)snla; } /* not spacelink itself */ static void nla_free(SpaceLink *sl) { - SpaceNla *snla = (SpaceNla *) sl; + SpaceNla *snla = (SpaceNla *)sl; - if (snla->ads) { - BLI_freelistN(&snla->ads->chanbase); - MEM_freeN(snla->ads); - } + if (snla->ads) { + BLI_freelistN(&snla->ads->chanbase); + MEM_freeN(snla->ads); + } } - /* spacetype; init callback */ static void nla_init(struct wmWindowManager *wm, ScrArea *sa) { - SpaceNla *snla = (SpaceNla *)sa->spacedata.first; + SpaceNla *snla = (SpaceNla *)sa->spacedata.first; - /* init dopesheet data if non-existent (i.e. for old files) */ - if (snla->ads == NULL) { - snla->ads = MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet"); - snla->ads->source = (ID *)WM_window_get_active_scene(wm->winactive); - } + /* init dopesheet data if non-existent (i.e. for old files) */ + if (snla->ads == NULL) { + snla->ads = MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet"); + snla->ads->source = (ID *)WM_window_get_active_scene(wm->winactive); + } - ED_area_tag_refresh(sa); + ED_area_tag_refresh(sa); } static SpaceLink *nla_duplicate(SpaceLink *sl) { - SpaceNla *snlan = MEM_dupallocN(sl); + SpaceNla *snlan = MEM_dupallocN(sl); - /* clear or remove stuff from old */ - snlan->ads = MEM_dupallocN(snlan->ads); + /* clear or remove stuff from old */ + snlan->ads = MEM_dupallocN(snlan->ads); - return (SpaceLink *)snlan; + return (SpaceLink *)snlan; } /* add handlers, stuff you only do once or on area/region changes */ static void nla_channel_region_init(wmWindowManager *wm, ARegion *ar) { - wmKeyMap *keymap; + wmKeyMap *keymap; - /* ensure the 2d view sync works - main region has bottom scroller */ - ar->v2d.scroll = V2D_SCROLL_BOTTOM; + /* ensure the 2d view sync works - main region has bottom scroller */ + ar->v2d.scroll = V2D_SCROLL_BOTTOM; - 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 */ - /* own channels map first to override some channel keymaps */ - keymap = WM_keymap_ensure(wm->defaultconf, "NLA Channels", SPACE_NLA, 0); - WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); - /* now generic channels map for everything else that can apply */ - keymap = WM_keymap_ensure(wm->defaultconf, "Animation Channels", 0, 0); - WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); + /* own keymap */ + /* own channels map first to override some channel keymaps */ + keymap = WM_keymap_ensure(wm->defaultconf, "NLA Channels", SPACE_NLA, 0); + WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); + /* now generic channels map for everything else that can apply */ + 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, "NLA Generic", SPACE_NLA, 0); - WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); + keymap = WM_keymap_ensure(wm->defaultconf, "NLA Generic", SPACE_NLA, 0); + WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } /* draw entirely, view changes should be handled here */ static void nla_channel_region_draw(const bContext *C, ARegion *ar) { - bAnimContext ac; - View2D *v2d = &ar->v2d; - View2DScrollers *scrollers; + bAnimContext ac; + View2D *v2d = &ar->v2d; + View2DScrollers *scrollers; - /* clear and setup matrix */ - UI_ThemeClearColor(TH_BACK); - GPU_clear(GPU_COLOR_BIT); + /* clear and setup matrix */ + UI_ThemeClearColor(TH_BACK); + GPU_clear(GPU_COLOR_BIT); - UI_view2d_view_ortho(v2d); + UI_view2d_view_ortho(v2d); - /* data */ - if (ANIM_animdata_get_context(C, &ac)) { - draw_nla_channel_list(C, &ac, ar); - } + /* data */ + if (ANIM_animdata_get_context(C, &ac)) { + draw_nla_channel_list(C, &ac, ar); + } - /* reset view matrix */ - UI_view2d_view_restore(C); + /* 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); + /* 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 nla_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, "NLA Editor", SPACE_NLA, 0); - WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); - keymap = WM_keymap_ensure(wm->defaultconf, "NLA Generic", SPACE_NLA, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + /* own keymap */ + keymap = WM_keymap_ensure(wm->defaultconf, "NLA Editor", SPACE_NLA, 0); + WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); + keymap = WM_keymap_ensure(wm->defaultconf, "NLA Generic", SPACE_NLA, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); } static void nla_main_region_draw(const bContext *C, ARegion *ar) { - /* draw entirely, view changes should be handled here */ - SpaceNla *snla = CTX_wm_space_nla(C); - Scene *scene = CTX_data_scene(C); - bAnimContext ac; - View2D *v2d = &ar->v2d; - View2DGrid *grid; - View2DScrollers *scrollers; - short unit = 0, cfra_flag = 0; - - /* clear and setup matrix */ - UI_ThemeClearColor(TH_BACK); - GPU_clear(GPU_COLOR_BIT); - - UI_view2d_view_ortho(v2d); - - /* time grid */ - unit = (snla->flag & SNLA_DRAWTIME) ? V2D_UNIT_SECONDS : V2D_UNIT_FRAMES; - grid = UI_view2d_grid_calc(CTX_data_scene(C), v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY, ar->winx, ar->winy); - UI_view2d_grid_draw(v2d, grid, V2D_GRIDLINES_ALL); - UI_view2d_grid_free(grid); - - ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW); - - /* start and end frame */ - ANIM_draw_framerange(scene, v2d); - - /* data */ - if (ANIM_animdata_get_context(C, &ac)) { - /* strips and backdrops */ - draw_nla_main_data(&ac, snla, ar); - - /* text draw cached, in pixelspace now */ - UI_view2d_text_cache_draw(ar); - } - - UI_view2d_view_ortho(v2d); - - /* current frame */ - if (snla->flag & SNLA_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 (snla->flag & SNLA_SHOW_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 */ - scrollers = UI_view2d_scrollers_calc(C, v2d, NULL, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY); - UI_view2d_scrollers_draw(C, v2d, scrollers); - UI_view2d_scrollers_free(scrollers); - - /* draw current frame number-indicator on top of scrollers */ - if ((snla->flag & SNLA_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 */ + SpaceNla *snla = CTX_wm_space_nla(C); + Scene *scene = CTX_data_scene(C); + bAnimContext ac; + View2D *v2d = &ar->v2d; + View2DGrid *grid; + View2DScrollers *scrollers; + short unit = 0, cfra_flag = 0; + + /* clear and setup matrix */ + UI_ThemeClearColor(TH_BACK); + GPU_clear(GPU_COLOR_BIT); + + UI_view2d_view_ortho(v2d); + + /* time grid */ + unit = (snla->flag & SNLA_DRAWTIME) ? V2D_UNIT_SECONDS : V2D_UNIT_FRAMES; + grid = UI_view2d_grid_calc(CTX_data_scene(C), + v2d, + unit, + V2D_GRID_CLAMP, + V2D_ARG_DUMMY, + V2D_ARG_DUMMY, + ar->winx, + ar->winy); + UI_view2d_grid_draw(v2d, grid, V2D_GRIDLINES_ALL); + UI_view2d_grid_free(grid); + + ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW); + + /* start and end frame */ + ANIM_draw_framerange(scene, v2d); + + /* data */ + if (ANIM_animdata_get_context(C, &ac)) { + /* strips and backdrops */ + draw_nla_main_data(&ac, snla, ar); + + /* text draw cached, in pixelspace now */ + UI_view2d_text_cache_draw(ar); + } + + UI_view2d_view_ortho(v2d); + + /* current frame */ + if (snla->flag & SNLA_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 (snla->flag & SNLA_SHOW_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 */ + scrollers = UI_view2d_scrollers_calc( + C, v2d, NULL, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY); + UI_view2d_scrollers_draw(C, v2d, scrollers); + UI_view2d_scrollers_free(scrollers); + + /* draw current frame number-indicator on top of scrollers */ + if ((snla->flag & SNLA_NODRAWCFRANUM) == 0) { + UI_view2d_view_orthoSpecial(ar, v2d, 1); + ANIM_draw_cfra_number(C, v2d, cfra_flag); + } } - /* add handlers, stuff you only do once or on area/region changes */ static void nla_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar) { - ED_region_header_init(ar); + ED_region_header_init(ar); } static void nla_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 nla_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, "NLA Generic", SPACE_NLA, 0); - WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); + keymap = WM_keymap_ensure(wm->defaultconf, "NLA Generic", SPACE_NLA, 0); + WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } static void nla_buttons_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar); + ED_region_panels(C, ar); } -static void nla_region_listener( - wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar, - wmNotifier *wmn, const Scene *UNUSED(scene)) +static void nla_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_OB_ACTIVE: - case ND_FRAME: - case ND_MARKERS: - 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; - } - 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_OB_ACTIVE: + case ND_FRAME: + case ND_MARKERS: + 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; + } + break; + default: + if (wmn->data == ND_KEYS) + ED_region_tag_redraw(ar); + break; + } } - -static void nla_main_region_listener( - wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar, - wmNotifier *wmn, const Scene *UNUSED(scene)) +static void nla_main_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; - } - break; - case NC_OBJECT: - switch (wmn->data) { - case ND_BONE_ACTIVE: - case ND_BONE_SELECT: - case ND_KEYS: - case ND_TRANSFORM: - ED_region_tag_redraw(ar); - break; - } - break; - case NC_NODE: - switch (wmn->action) { - case NA_EDITED: - 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; + } + break; + case NC_OBJECT: + switch (wmn->data) { + case ND_BONE_ACTIVE: + case ND_BONE_SELECT: + case ND_KEYS: + case ND_TRANSFORM: + ED_region_tag_redraw(ar); + break; + } + break; + case NC_NODE: + switch (wmn->action) { + case NA_EDITED: + 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 nla_main_region_message_subscribe( - const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), struct Scene *scene, - struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar, - struct wmMsgBus *mbus) +static void nla_main_region_message_subscribe(const struct bContext *UNUSED(C), + struct WorkSpace *UNUSED(workspace), + struct Scene *scene, + struct bScreen *screen, + struct ScrArea *sa, + struct ARegion *ar, + struct wmMsgBus *mbus) { - PointerRNA ptr; - RNA_pointer_create(&screen->id, &RNA_SpaceNLA, 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__); - } - } + PointerRNA ptr; + RNA_pointer_create(&screen->id, &RNA_SpaceNLA, 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__); + } + } } -static void nla_channel_region_listener( - wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar, - wmNotifier *wmn, const Scene *UNUSED(scene)) +static void nla_channel_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_OB_ACTIVE: - 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; - } - break; - case NC_ID: - if (wmn->action == NA_RENAME) - 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_OB_ACTIVE: + 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; + } + break; + case NC_ID: + if (wmn->action == NA_RENAME) + ED_region_tag_redraw(ar); + break; + default: + if (wmn->data == ND_KEYS) + ED_region_tag_redraw(ar); + break; + } } -static void nla_channel_region_message_subscribe( - const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), struct Scene *UNUSED(scene), - struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar, - struct wmMsgBus *mbus) +static void nla_channel_region_message_subscribe(const struct bContext *UNUSED(C), + struct WorkSpace *UNUSED(workspace), + struct Scene *UNUSED(scene), + struct bScreen *screen, + struct ScrArea *sa, + struct ARegion *ar, + struct wmMsgBus *mbus) { - PointerRNA ptr; - RNA_pointer_create(&screen->id, &RNA_SpaceNLA, sa->spacedata.first, &ptr); - - wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { - .owner = ar, - .user_data = ar, - .notify = ED_region_do_msg_notify_tag_redraw, - }; - - /* All dopesheet filter settings, etc. affect the drawing of this editor, - * so just whitelist the entire struct for updates - */ - { - wmMsgParams_RNA msg_key_params = {{{0}}}; - StructRNA *type_array[] = { - &RNA_DopeSheet, - }; - - 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_SpaceNLA, sa->spacedata.first, &ptr); + + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { + .owner = ar, + .user_data = ar, + .notify = ED_region_do_msg_notify_tag_redraw, + }; + + /* All dopesheet filter settings, etc. affect the drawing of this editor, + * so just whitelist the entire struct for updates + */ + { + wmMsgParams_RNA msg_key_params = {{{0}}}; + StructRNA *type_array[] = { + &RNA_DopeSheet, + }; + + 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 nla_listener(wmWindow *UNUSED(win), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene)) { - /* context changes */ - switch (wmn->category) { - case NC_ANIMATION: - // TODO: filter specific types of changes? - ED_area_tag_refresh(sa); - break; - case NC_SCENE: + /* context changes */ + switch (wmn->category) { + case NC_ANIMATION: + // TODO: filter specific types of changes? + ED_area_tag_refresh(sa); + break; + case NC_SCENE: #if 0 - switch (wmn->data) { - case ND_OB_ACTIVE: - case ND_OB_SELECT: - ED_area_tag_refresh(sa); - break; - } + switch (wmn->data) { + case ND_OB_ACTIVE: + case ND_OB_SELECT: + ED_area_tag_refresh(sa); + break; + } #endif - ED_area_tag_refresh(sa); - break; - case NC_OBJECT: - switch (wmn->data) { - case ND_TRANSFORM: - /* do nothing */ - break; - default: - ED_area_tag_refresh(sa); - break; - } - break; - case NC_SPACE: - if (wmn->data == ND_SPACE_NLA) - ED_area_tag_redraw(sa); - break; - } + ED_area_tag_refresh(sa); + break; + case NC_OBJECT: + switch (wmn->data) { + case ND_TRANSFORM: + /* do nothing */ + break; + default: + ED_area_tag_refresh(sa); + break; + } + break; + case NC_SPACE: + if (wmn->data == ND_SPACE_NLA) + ED_area_tag_redraw(sa); + break; + } } static void nla_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id) { - SpaceNla *snla = (SpaceNla *)slink; - - if (snla->ads) { - if ((ID *)snla->ads->filter_grp == old_id) { - snla->ads->filter_grp = (Collection *)new_id; - } - if ((ID *)snla->ads->source == old_id) { - snla->ads->source = new_id; - } - } + SpaceNla *snla = (SpaceNla *)slink; + + if (snla->ads) { + if ((ID *)snla->ads->filter_grp == old_id) { + snla->ads->filter_grp = (Collection *)new_id; + } + if ((ID *)snla->ads->source == old_id) { + snla->ads->source = new_id; + } + } } /* only called once, from space/spacetypes.c */ void ED_spacetype_nla(void) { - SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype nla"); - ARegionType *art; - - st->spaceid = SPACE_NLA; - strncpy(st->name, "NLA", BKE_ST_MAXNAME); - - st->new = nla_new; - st->free = nla_free; - st->init = nla_init; - st->duplicate = nla_duplicate; - st->operatortypes = nla_operatortypes; - st->listener = nla_listener; - st->keymap = nla_keymap; - st->id_remap = nla_id_remap; - - /* regions: main window */ - art = MEM_callocN(sizeof(ARegionType), "spacetype nla region"); - art->regionid = RGN_TYPE_WINDOW; - art->init = nla_main_region_init; - art->draw = nla_main_region_draw; - art->listener = nla_main_region_listener; - art->message_subscribe = nla_main_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 nla region"); - art->regionid = RGN_TYPE_HEADER; - art->prefsizey = HEADERY; - art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER; - - art->init = nla_header_region_init; - art->draw = nla_header_region_draw; - - BLI_addhead(&st->regiontypes, art); - - /* regions: channels */ - art = MEM_callocN(sizeof(ARegionType), "spacetype nla region"); - art->regionid = RGN_TYPE_CHANNELS; - art->prefsizex = 200; - art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES; - - art->init = nla_channel_region_init; - art->draw = nla_channel_region_draw; - art->listener = nla_channel_region_listener; - art->message_subscribe = nla_channel_region_message_subscribe; - - BLI_addhead(&st->regiontypes, art); - - /* regions: UI buttons */ - art = MEM_callocN(sizeof(ARegionType), "spacetype nla region"); - art->regionid = RGN_TYPE_UI; - art->prefsizex = 200; - art->keymapflag = ED_KEYMAP_UI; - art->listener = nla_region_listener; - art->init = nla_buttons_region_init; - art->draw = nla_buttons_region_draw; - - BLI_addhead(&st->regiontypes, art); - - nla_buttons_register(art); - - - BKE_spacetype_register(st); + SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype nla"); + ARegionType *art; + + st->spaceid = SPACE_NLA; + strncpy(st->name, "NLA", BKE_ST_MAXNAME); + + st->new = nla_new; + st->free = nla_free; + st->init = nla_init; + st->duplicate = nla_duplicate; + st->operatortypes = nla_operatortypes; + st->listener = nla_listener; + st->keymap = nla_keymap; + st->id_remap = nla_id_remap; + + /* regions: main window */ + art = MEM_callocN(sizeof(ARegionType), "spacetype nla region"); + art->regionid = RGN_TYPE_WINDOW; + art->init = nla_main_region_init; + art->draw = nla_main_region_draw; + art->listener = nla_main_region_listener; + art->message_subscribe = nla_main_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 nla region"); + art->regionid = RGN_TYPE_HEADER; + art->prefsizey = HEADERY; + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER; + + art->init = nla_header_region_init; + art->draw = nla_header_region_draw; + + BLI_addhead(&st->regiontypes, art); + + /* regions: channels */ + art = MEM_callocN(sizeof(ARegionType), "spacetype nla region"); + art->regionid = RGN_TYPE_CHANNELS; + art->prefsizex = 200; + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES; + + art->init = nla_channel_region_init; + art->draw = nla_channel_region_draw; + art->listener = nla_channel_region_listener; + art->message_subscribe = nla_channel_region_message_subscribe; + + BLI_addhead(&st->regiontypes, art); + + /* regions: UI buttons */ + art = MEM_callocN(sizeof(ARegionType), "spacetype nla region"); + art->regionid = RGN_TYPE_UI; + art->prefsizex = 200; + art->keymapflag = ED_KEYMAP_UI; + art->listener = nla_region_listener; + art->init = nla_buttons_region_init; + art->draw = nla_buttons_region_draw; + + BLI_addhead(&st->regiontypes, art); + + nla_buttons_register(art); + + BKE_spacetype_register(st); } |