Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/space_nla/nla_edit.c')
-rw-r--r--source/blender/editors/space_nla/nla_edit.c238
1 files changed, 220 insertions, 18 deletions
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index 80b1918ff8e..93d0f7527ef 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -49,6 +49,7 @@
#include "BKE_fcurve.h"
#include "BKE_nla.h"
#include "BKE_context.h"
+#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_screen.h"
@@ -110,7 +111,7 @@ static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op)
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
- int ok = 0;
+ bool ok = false;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -131,7 +132,7 @@ static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op)
AnimData *adt = ale->data;
/* try entering tweakmode if valid */
- ok += BKE_nla_tweakmode_enter(adt);
+ ok |= BKE_nla_tweakmode_enter(adt);
}
/* free temp data */
@@ -161,7 +162,7 @@ void NLA_OT_tweakmode_enter(wmOperatorType *ot)
/* 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";
+ 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;
@@ -257,11 +258,12 @@ void NLA_OT_tweakmode_exit(wmOperatorType *ot)
/* *************************** Calculate Range ************************** */
/* Get the min/max strip extents */
-static void get_nlastrip_extents(bAnimContext *ac, float *min, float *max, const short onlySel)
+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);
@@ -280,10 +282,12 @@ static void get_nlastrip_extents(bAnimContext *ac, float *min, float *max, const
for (strip = nlt->strips.first; strip; strip = strip->next) {
/* only consider selected strips? */
- if ((onlySel == 0) || (strip->flag & NLASTRIP_FLAG_SELECT)) {
+ 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;
}
}
}
@@ -291,8 +295,9 @@ static void get_nlastrip_extents(bAnimContext *ac, float *min, float *max, const
/* free memory */
BLI_freelistN(&anim_data);
}
- else {
- /* set default range */
+
+ /* 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;
@@ -304,9 +309,109 @@ static void get_nlastrip_extents(bAnimContext *ac, float *min, float *max, const
}
}
+/* ****************** 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 = iroundf(min);
+ scene->r.pefra = iroundf(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";
+
+ /* api callbacks */
+ ot->exec = nlaedit_previewrange_exec;
+ ot->poll = ED_operator_nla_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
/* ****************** View-All Operator ****************** */
-static int nlaedit_viewall(bContext *C, const short onlySel)
+/* Find the extents of the active channel
+ * > min: (float) bottom y-extent of channel
+ * > max: (float) top y-extent of channel
+ * > returns: success of finding a selected channel
+ */
+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);
+ short found = 0; /* NOTE: not bool, since we want prioritise individual channels over expanders */
+ 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) {
+ 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 */
+ BLI_freelistN(&anim_data);
+
+ return (found != 0);
+}
+
+static int nlaedit_viewall(bContext *C, const bool only_sel)
{
bAnimContext ac;
View2D *v2d;
@@ -318,15 +423,32 @@ static int nlaedit_viewall(bContext *C, const short onlySel)
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, onlySel);
+ 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 */
- v2d->cur.ymax = 0.0f;
- v2d->cur.ymin = (float)-BLI_rcti_size_y(&v2d->mask);
+ 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);
@@ -513,6 +635,7 @@ void NLA_OT_actionclip_add(wmOperatorType *ot)
// 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;
}
@@ -527,7 +650,7 @@ static int nlaedit_add_transition_exec(bContext *C, wmOperator *op)
bAnimListElem *ale;
int filter;
- int done = false;
+ bool done = false;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -595,7 +718,7 @@ static int nlaedit_add_transition_exec(bContext *C, wmOperator *op)
BKE_nlastrip_validate_name(adt, strip);
/* make note of this */
- done++;
+ done = true;
}
}
@@ -838,7 +961,7 @@ void NLA_OT_meta_remove(wmOperatorType *ot)
* the originals were housed in.
*/
-static int nlaedit_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
+static int nlaedit_duplicate_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
@@ -846,6 +969,7 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
bAnimListElem *ale;
int filter;
+ bool linked = RNA_boolean_get(op->ptr, "linked");
bool done = false;
/* get editor data */
@@ -871,7 +995,7 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
/* if selected, split the strip at its midpoint */
if (strip->flag & NLASTRIP_FLAG_SELECT) {
/* make a copy (assume that this is possible) */
- nstrip = copy_nlastrip(strip);
+ nstrip = copy_nlastrip(strip, linked);
/* 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) {
@@ -936,6 +1060,9 @@ void NLA_OT_duplicate(wmOperatorType *ot)
/* 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", transform_mode_types, TFM_TRANSLATION, "Mode", "");
}
@@ -1053,7 +1180,7 @@ static void nlaedit_split_strip_actclip(AnimData *adt, NlaTrack *nlt, NlaStrip *
/* make a copy (assume that this is possible) and append
* it immediately after the current strip
*/
- nstrip = copy_nlastrip(strip);
+ nstrip = copy_nlastrip(strip, true);
BLI_insertlinkafter(&nlt->strips, strip, nstrip);
/* set the endpoint of the first strip and the start of the new strip
@@ -1656,6 +1783,80 @@ void NLA_OT_action_sync_length(wmOperatorType *ot)
ot->prop = RNA_def_boolean(ot->srna, "active", 1, "Active Strip Only", "Only sync the active length for the active strip");
}
+/* ******************** Make Single User ********************************* */
+/* Ensure that each strip has its own action */
+
+static int nlaedit_make_single_user_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);
+
+ /* 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(strip->act);
+
+ /* decrement user count of our existing action */
+ id_us_min(&strip->act->id);
+
+ /* switch to the new copy */
+ strip->act = new_action;
+ }
+ }
+ }
+ }
+
+ /* free temp data */
+ BLI_freelistN(&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_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;
+}
+
/* ******************** Apply Scale Operator ***************************** */
/* Reset the scaling of the selected strips to 1.0f */
@@ -2087,7 +2288,8 @@ static int nla_fmodifier_copy_exec(bContext *C, wmOperator *op)
bAnimContext ac;
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
- int filter, ok = 0;
+ int filter;
+ bool ok = false;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -2111,7 +2313,7 @@ static int nla_fmodifier_copy_exec(bContext *C, wmOperator *op)
continue;
// TODO: when 'active' vs 'all' boolean is added, change last param!
- ok += ANIM_fmodifiers_copy_to_buf(&strip->modifiers, 0);
+ ok |= ANIM_fmodifiers_copy_to_buf(&strip->modifiers, 0);
}
}