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:
-rw-r--r--source/blender/blenkernel/BKE_anim_data.h4
-rw-r--r--source/blender/blenkernel/intern/action.c2
-rw-r--r--source/blender/blenkernel/intern/anim_data.c22
-rw-r--r--source/blender/editors/animation/keyframing.c2
-rw-r--r--source/blender/makesdna/DNA_anim_types.h6
-rw-r--r--source/blender/makesrna/intern/rna_space.c51
6 files changed, 52 insertions, 35 deletions
diff --git a/source/blender/blenkernel/BKE_anim_data.h b/source/blender/blenkernel/BKE_anim_data.h
index 48ea06ea9d8..5293d8dd9b0 100644
--- a/source/blender/blenkernel/BKE_anim_data.h
+++ b/source/blender/blenkernel/BKE_anim_data.h
@@ -58,6 +58,10 @@ bool BKE_animdata_set_action(struct ReportList *reports, struct ID *id, struct b
bool BKE_animdata_action_editable(const struct AnimData *adt);
+/* Ensure that the action's idroot is set correctly given the ID type of the owner.
+ * Return true if it is, false if it was already set to an incompatible type. */
+bool BKE_animdata_action_ensure_idroot(const struct ID *owner, struct bAction *action);
+
/* Free AnimData */
void BKE_animdata_free(struct ID *id, const bool do_id_user);
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 64a8ae15fd3..1ce0d07a135 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -47,6 +47,7 @@
#include "BLT_translation.h"
#include "BKE_action.h"
+#include "BKE_anim_data.h"
#include "BKE_anim_visualization.h"
#include "BKE_animsys.h"
#include "BKE_armature.h"
@@ -1817,6 +1818,7 @@ void what_does_obaction(Object *ob,
workob->adt = &adt;
adt.action = act;
+ BKE_animdata_action_ensure_idroot(&workob->id, act);
/* execute effects of Action on to workob (or it's PoseChannels) */
BKE_animsys_evaluate_animdata(&workob->id, &adt, anim_eval_context, ADT_RECALC_ANIM, false);
diff --git a/source/blender/blenkernel/intern/anim_data.c b/source/blender/blenkernel/intern/anim_data.c
index 30b75734e77..eb2cdf585c4 100644
--- a/source/blender/blenkernel/intern/anim_data.c
+++ b/source/blender/blenkernel/intern/anim_data.c
@@ -186,6 +186,11 @@ bool BKE_animdata_set_action(ReportList *reports, ID *id, bAction *act)
return false;
}
+ if (adt->action == act) {
+ /* Don't bother reducing and increasing the user count when there is nothing changing. */
+ return true;
+ }
+
if (!BKE_animdata_action_editable(adt)) {
/* Cannot remove, otherwise things turn to custard. */
BKE_report(reports, RPT_ERROR, "Cannot change action, as it is still being edited in NLA");
@@ -204,7 +209,7 @@ bool BKE_animdata_set_action(ReportList *reports, ID *id, bAction *act)
}
/* Action must have same type as owner. */
- if (!ELEM(act->idroot, 0, GS(id->name))) {
+ if (!BKE_animdata_action_ensure_idroot(id, act)) {
/* Cannot set to this type. */
BKE_reportf(
reports,
@@ -230,6 +235,19 @@ bool BKE_animdata_action_editable(const AnimData *adt)
return !is_tweaking_strip;
}
+bool BKE_animdata_action_ensure_idroot(const ID *owner, bAction *action)
+{
+ const int idcode = GS(owner->name);
+
+ if (action->idroot == 0) {
+ /* First time this Action is assigned, lock it to this ID type. */
+ action->idroot = idcode;
+ return true;
+ }
+
+ return (action->idroot == idcode);
+}
+
/* Freeing -------------------------------------------- */
/* Free AnimData used by the nominated ID-block, and clear ID-block's AnimData pointer */
@@ -673,6 +691,7 @@ void BKE_animdata_transfer_by_basepath(Main *bmain, ID *srcID, ID *dstID, ListBa
* and name it in a similar way so that it can be easily found again. */
if (dstAdt->action == NULL) {
dstAdt->action = BKE_action_add(bmain, srcAdt->action->id.name + 2);
+ BKE_animdata_action_ensure_idroot(dstID, dstAdt->action);
}
else if (dstAdt->action == srcAdt->action) {
CLOG_WARN(&LOG,
@@ -685,6 +704,7 @@ void BKE_animdata_transfer_by_basepath(Main *bmain, ID *srcID, ID *dstID, ListBa
/* TODO: review this... */
id_us_min(&dstAdt->action->id);
dstAdt->action = BKE_action_add(bmain, dstAdt->action->id.name + 2);
+ BKE_animdata_action_ensure_idroot(dstID, dstAdt->action);
}
/* loop over base paths, trying to fix for each one... */
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index fb4c0ae0758..3701e9dc91c 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -162,7 +162,7 @@ bAction *ED_id_action_ensure(Main *bmain, ID *id)
* so that users can't accidentally break actions by assigning them
* to the wrong places
*/
- adt->action->idroot = GS(id->name);
+ BKE_animdata_action_ensure_idroot(id, adt->action);
/* Tag depsgraph to be rebuilt to include time dependency. */
DEG_relations_tag_update(bmain);
diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h
index 858daaac47c..7cb9978f768 100644
--- a/source/blender/makesdna/DNA_anim_types.h
+++ b/source/blender/makesdna/DNA_anim_types.h
@@ -1047,8 +1047,12 @@ typedef struct AnimOverride {
* See blenkernel/intern/anim_sys.c for details.
*/
typedef struct AnimData {
- /** active action - acts as the 'tweaking track' for the NLA */
+ /**
+ * Active action - acts as the 'tweaking track' for the NLA.
+ * Either use BKE_animdata_set_action() to set this, or call BKE_animdata_action_ensure_idroot()
+ * after setting. */
bAction *action;
+
/** temp-storage for the 'real' active action (i.e. the one used before the tweaking-action
* took over to be edited in the Animation Editors)
*/
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 59a974b8b0b..3fa577d4230 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -1929,10 +1929,12 @@ static void rna_SpaceDopeSheetEditor_action_update(bContext *C, PointerRNA *ptr)
}
AnimData *adt = NULL;
+ ID *id = NULL;
switch (saction->mode) {
case SACTCONT_ACTION:
/* TODO: context selector could help decide this with more control? */
adt = BKE_animdata_add_id(&obact->id);
+ id = &obact->id;
break;
case SACTCONT_SHAPEKEY: {
Key *key = BKE_key_from_object(obact);
@@ -1940,6 +1942,7 @@ static void rna_SpaceDopeSheetEditor_action_update(bContext *C, PointerRNA *ptr)
return;
}
adt = BKE_animdata_add_id(&key->id);
+ id = &key->id;
break;
}
case SACTCONT_GPENCIL:
@@ -1963,40 +1966,24 @@ static void rna_SpaceDopeSheetEditor_action_update(bContext *C, PointerRNA *ptr)
/* Exit editmode first - we cannot change actions while in tweakmode. */
BKE_nla_tweakmode_exit(adt);
- /* NLA Tweak Mode needs special handling... */
- if (adt->flag & ADT_NLA_EDIT_ON) {
- /* Assign new action, and adjust the usercounts accordingly */
- adt->action = saction->action;
- id_us_plus((ID *)adt->action);
+ /* To prevent data loss (i.e. if users flip between actions using the Browse menu),
+ * stash this action if nothing else uses it.
+ *
+ * EXCEPTION:
+ * This callback runs when unlinking actions. In that case, we don't want to
+ * stash the action, as the user is signaling that they want to detach it.
+ * This can be reviewed again later,
+ * but it could get annoying if we keep these instead.
+ */
+ if (adt->action != NULL && adt->action->id.us <= 0 && saction->action != NULL) {
+ /* XXX: Things here get dodgy if this action is only partially completed,
+ * and the user then uses the browse menu to get back to this action,
+ * assigning it as the active action (i.e. the stash strip gets out of sync)
+ */
+ BKE_nla_action_stash(adt);
}
- else {
- /* Handle old action... */
- if (adt->action) {
- /* Fix id-count of action we're replacing */
- id_us_min(&adt->action->id);
-
- /* To prevent data loss (i.e. if users flip between actions using the Browse menu),
- * stash this action if nothing else uses it.
- *
- * EXCEPTION:
- * This callback runs when unlinking actions. In that case, we don't want to
- * stash the action, as the user is signaling that they want to detach it.
- * This can be reviewed again later,
- * but it could get annoying if we keep these instead.
- */
- if ((adt->action->id.us <= 0) && (saction->action != NULL)) {
- /* XXX: Things here get dodgy if this action is only partially completed,
- * and the user then uses the browse menu to get back to this action,
- * assigning it as the active action (i.e. the stash strip gets out of sync)
- */
- BKE_nla_action_stash(adt);
- }
- }
- /* Assign new action, and adjust the usercounts accordingly */
- adt->action = saction->action;
- id_us_plus((ID *)adt->action);
- }
+ BKE_animdata_set_action(NULL, id, saction->action);
DEG_id_tag_update(&obact->id, ID_RECALC_ANIMATION | ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);