[Bf-blender-cvs] [330a04d7c79] master: Fix T91393: Duplicating an action with python crashes Blender.

Bastien Montagne noreply at git.blender.org
Tue Sep 28 17:46:07 CEST 2021


Commit: 330a04d7c7928c213c121bedcab9dd77a16d106e
Author: Bastien Montagne
Date:   Tue Sep 28 17:37:35 2021 +0200
Branches: master
https://developer.blender.org/rB330a04d7c7928c213c121bedcab9dd77a16d106e

Fix T91393: Duplicating an action with python crashes Blender.

Own mistake when making NLA overridable, instead of assuming things
about the ID owner of the animation data being processed, properly
return and use the one found by `ED_actedit_animdata_from_context`.

===================================================================

M	source/blender/editors/include/ED_anim_api.h
M	source/blender/editors/space_action/action_data.c

===================================================================

diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index 6a0a42ee77b..e9601220f2e 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -861,7 +861,7 @@ void ED_operatormacros_action(void);
 /* XXX: Should we be doing these here, or at all? */
 
 /* Action Editor - Action Management */
-struct AnimData *ED_actedit_animdata_from_context(struct bContext *C);
+struct AnimData *ED_actedit_animdata_from_context(struct bContext *C, struct ID **r_adt_id_owner);
 void ED_animedit_unlink_action(struct bContext *C,
                                struct ID *id,
                                struct AnimData *adt,
diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c
index 717d87c4972..a4fd2d81778 100644
--- a/source/blender/editors/space_action/action_data.c
+++ b/source/blender/editors/space_action/action_data.c
@@ -71,7 +71,7 @@
 /* ACTION CREATION */
 
 /* Helper function to find the active AnimData block from the Action Editor context */
-AnimData *ED_actedit_animdata_from_context(bContext *C)
+AnimData *ED_actedit_animdata_from_context(bContext *C, ID **r_adt_id_owner)
 {
   SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
   Object *ob = CTX_data_active_object(C);
@@ -82,12 +82,18 @@ AnimData *ED_actedit_animdata_from_context(bContext *C)
     /* Currently, "Action Editor" means object-level only... */
     if (ob) {
       adt = ob->adt;
+      if (r_adt_id_owner) {
+        *r_adt_id_owner = &ob->id;
+      }
     }
   }
   else if (saction->mode == SACTCONT_SHAPEKEY) {
     Key *key = BKE_key_from_object(ob);
     if (key) {
       adt = key->adt;
+      if (r_adt_id_owner) {
+        *r_adt_id_owner = &key->id;
+      }
     }
   }
 
@@ -212,6 +218,7 @@ static int action_new_exec(bContext *C, wmOperator *UNUSED(op))
 
   bAction *oldact = NULL;
   AnimData *adt = NULL;
+  ID *adt_id_owner = NULL;
   /* hook into UI */
   UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
 
@@ -225,13 +232,14 @@ static int action_new_exec(bContext *C, wmOperator *UNUSED(op))
     /* stash the old action to prevent it from being lost */
     if (ptr.type == &RNA_AnimData) {
       adt = ptr.data;
+      adt_id_owner = ptr.owner_id;
     }
     else if (ptr.type == &RNA_SpaceDopeSheetEditor) {
-      adt = ED_actedit_animdata_from_context(C);
+      adt = ED_actedit_animdata_from_context(C, &adt_id_owner);
     }
   }
   else {
-    adt = ED_actedit_animdata_from_context(C);
+    adt = ED_actedit_animdata_from_context(C, &adt_id_owner);
     oldact = adt->action;
   }
   {
@@ -239,8 +247,9 @@ static int action_new_exec(bContext *C, wmOperator *UNUSED(op))
 
     /* Perform stashing operation - But only if there is an action */
     if (adt && oldact) {
+      BLI_assert(adt_id_owner != NULL);
       /* stash the action */
-      if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(ptr.owner_id))) {
+      if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(adt_id_owner))) {
         /* The stash operation will remove the user already
          * (and unlink the action from the AnimData action slot).
          * Hence, we must unset the ref to the action in the
@@ -306,7 +315,7 @@ static bool action_pushdown_poll(bContext *C)
 {
   if (ED_operator_action_active(C)) {
     SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
-    AnimData *adt = ED_actedit_animdata_from_context(C);
+    AnimData *adt = ED_actedit_animdata_from_context(C, NULL);
 
     /* Check for AnimData, Actions, and that tweak-mode is off. */
     if (adt && saction->action) {
@@ -326,7 +335,8 @@ static bool action_pushdown_poll(bContext *C)
 static int action_pushdown_exec(bContext *C, wmOperator *op)
 {
   SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
-  AnimData *adt = ED_actedit_animdata_from_context(C);
+  ID *adt_id_owner = NULL;
+  AnimData *adt = ED_actedit_animdata_from_context(C, &adt_id_owner);
 
   /* Do the deed... */
   if (adt) {
@@ -339,8 +349,7 @@ static int action_pushdown_exec(bContext *C, wmOperator *op)
     }
 
     /* action can be safely added */
-    const Object *ob = CTX_data_active_object(C);
-    BKE_nla_action_pushdown(adt, ID_IS_OVERRIDE_LIBRARY(ob));
+    BKE_nla_action_pushdown(adt, ID_IS_OVERRIDE_LIBRARY(adt_id_owner));
 
     /* Stop displaying this action in this editor
      * NOTE: The editor itself doesn't set a user...
@@ -373,7 +382,8 @@ void ACTION_OT_push_down(wmOperatorType *ot)
 static int action_stash_exec(bContext *C, wmOperator *op)
 {
   SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
-  AnimData *adt = ED_actedit_animdata_from_context(C);
+  ID *adt_id_owner = NULL;
+  AnimData *adt = ED_actedit_animdata_from_context(C, &adt_id_owner);
 
   /* Perform stashing operation */
   if (adt) {
@@ -385,8 +395,7 @@ static int action_stash_exec(bContext *C, wmOperator *op)
     }
 
     /* stash the action */
-    Object *ob = CTX_data_active_object(C);
-    if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(ob))) {
+    if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(adt_id_owner))) {
       /* The stash operation will remove the user already,
        * so the flushing step later shouldn't double up
        * the user-count fixes. Hence, we must unset this ref
@@ -439,7 +448,7 @@ void ACTION_OT_stash(wmOperatorType *ot)
 static bool action_stash_create_poll(bContext *C)
 {
   if (ED_operator_action_active(C)) {
-    AnimData *adt = ED_actedit_animdata_from_context(C);
+    AnimData *adt = ED_actedit_animdata_from_context(C, NULL);
 
     /* Check tweak-mode is off (as you don't want to be tampering with the action in that case) */
     /* NOTE: unlike for pushdown,
@@ -471,7 +480,8 @@ static bool action_stash_create_poll(bContext *C)
 static int action_stash_create_exec(bContext *C, wmOperator *op)
 {
   SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
-  AnimData *adt = ED_actedit_animdata_from_context(C);
+  ID *adt_id_owner = NULL;
+  AnimData *adt = ED_actedit_animdata_from_context(C, &adt_id_owner);
 
   /* Check for no action... */
   if (saction->action == NULL) {
@@ -488,8 +498,7 @@ static int action_stash_create_exec(bContext *C, wmOperator *op)
     }
 
     /* stash the action */
-    Object *ob = CTX_data_active_object(C);
-    if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(ob))) {
+    if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(adt_id_owner))) {
       bAction *new_action = NULL;
 
       /* Create new action not based on the old one
@@ -636,7 +645,7 @@ static bool action_unlink_poll(bContext *C)
 {
   if (ED_operator_action_active(C)) {
     SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
-    AnimData *adt = ED_actedit_animdata_from_context(C);
+    AnimData *adt = ED_actedit_animdata_from_context(C, NULL);
 
     /* Only when there's an active action, in the right modes... */
     if (saction->action && adt) {
@@ -650,7 +659,7 @@ static bool action_unlink_poll(bContext *C)
 
 static int action_unlink_exec(bContext *C, wmOperator *op)
 {
-  AnimData *adt = ED_actedit_animdata_from_context(C);
+  AnimData *adt = ED_actedit_animdata_from_context(C, NULL);
   bool force_delete = RNA_boolean_get(op->ptr, "force_delete");
 
   if (adt && adt->action) {
@@ -775,7 +784,7 @@ static bool action_layer_next_poll(bContext *C)
 {
   /* Action Editor's action editing modes only */
   if (ED_operator_action_active(C)) {
-    AnimData *adt = ED_actedit_animdata_from_context(C);
+    AnimData *adt = ED_actedit_animdata_from_context(C, NULL);
     if (adt) {
       /* only allow if we're in tweak-mode, and there's something above us... */
       if (adt->flag & ADT_NLA_EDIT_ON) {
@@ -809,7 +818,7 @@ static bool action_layer_next_poll(bContext *C)
 
 static int action_layer_next_exec(bContext *C, wmOperator *op)
 {
-  AnimData *adt = ED_actedit_animdata_from_context(C);
+  AnimData *adt = ED_actedit_animdata_from_context(C, NULL);
   NlaTrack *act_track;
 
   Scene *scene = CTX_data_scene(C);
@@ -886,7 +895,7 @@ static bool action_layer_prev_poll(bContext *C)
 {
   /* Action Editor's action editing modes only */
   if (ED_operator_action_active(C)) {
-    AnimData *adt = ED_actedit_animdata_from_context(C);
+    AnimData *adt = ED_actedit_animdata_from_context(C, NULL);
     if (adt) {
       if (adt->flag & ADT_NLA_EDIT_ON) {
         /* Tweak Mode: We need to check if there are any tracks below the active one
@@ -920,7 +929,7 @@ static bool action_layer_prev_poll(bContext *C)
 
 static int action_layer_prev_exec(bContext *C, wmOperator *op)
 {
-  AnimData *adt = ED_actedit_animdata_from_context(C);
+  AnimData *adt = ED_actedit_animdata_from_context(C, NULL);
   NlaTrack *act_track;
   NlaTrack *nlt;



More information about the Bf-blender-cvs mailing list