diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h index b8b62dd3451..b027acb88da 100644 --- a/source/blender/blenlib/BLI_listbase.h +++ b/source/blender/blenlib/BLI_listbase.h @@ -93,6 +93,7 @@ void BLI_listbase_sort_r(ListBase *listbase, int (*cmp)(void *, const void *, const void *), void *thunk) ATTR_NONNULL(1, 2); bool BLI_listbase_link_move(ListBase *listbase, void *vlink, int step) ATTR_NONNULL(); +bool BLI_listbase_move_index(ListBase *listbase, int from, int to) ATTR_NONNULL(); void BLI_freelist(struct ListBase *listbase) ATTR_NONNULL(1); int BLI_listbase_count_at_most(const struct ListBase *listbase, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c index 31d372945c6..631978f60fe 100644 --- a/source/blender/blenlib/intern/listbase.c +++ b/source/blender/blenlib/intern/listbase.c @@ -503,6 +503,27 @@ bool BLI_listbase_link_move(ListBase *listbase, void *vlink, int step) return true; } +/** + * Move the link at the index \a from to the position at index \a to. + * + * @return If the move was successful. + */ +bool BLI_listbase_move_index(ListBase *listbase, int from, int to) +{ + if (from == to) { + return false; + } + + /* Find the link to move. */ + void *link = BLI_findlink(listbase, from); + + if (!link) { + return false; + } + + return BLI_listbase_link_move(listbase, link, to - from); +} + /** * Removes and disposes of the entire contents of listbase using direct free(3). */ diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index c8a0d543b70..6dd75100e71 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -1410,6 +1410,22 @@ static void rna_Object_constraints_clear(Object *object, Main *bmain) WM_main_add_notifier(NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, object); } +static void rna_Object_constraints_move( + Object *object, Main *bmain, ReportList *reports, int from, int to) +{ + if (from == to) { + return; + } + + if (!BLI_listbase_move_index(&object->constraints, from, to)) { + BKE_reportf(reports, RPT_ERROR, "Could not move constraint from index '%d' to '%d'", from, to); + return; + } + + ED_object_constraint_tag_update(bmain, object, NULL); + WM_main_add_notifier(NC_OBJECT | ND_CONSTRAINT, object); +} + bool rna_Object_constraints_override_apply(Main *UNUSED(bmain), PointerRNA *ptr_dst, PointerRNA *ptr_src, @@ -2041,6 +2057,15 @@ static void rna_def_object_constraints(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "clear", "rna_Object_constraints_clear"); RNA_def_function_flag(func, FUNC_USE_MAIN); RNA_def_function_ui_description(func, "Remove all constraint from this object"); + + func = RNA_def_function(srna, "move", "rna_Object_constraints_move"); + RNA_def_function_ui_description(func, "Move a constraint to a different position"); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); + parm = RNA_def_int( + func, "from_index", -1, INT_MIN, INT_MAX, "From Index", "Index to move", 0, 10000); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_int(func, "to_index", -1, INT_MIN, INT_MAX, "To Index", "Target index", 0, 10000); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); } /* object.modifiers */ diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index 33d7d7d99cf..2f460e79ec9 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -601,6 +601,24 @@ static void rna_PoseChannel_constraints_remove( } } +static void rna_PoseChannel_constraints_move( + ID *id, bPoseChannel *pchan, Main *bmain, ReportList *reports, int from, int to) +{ + Object *ob = (Object *)id; + + if (from == to) { + return; + } + + if (!BLI_listbase_move_index(&pchan->constraints, from, to)) { + BKE_reportf(reports, RPT_ERROR, "Could not move constraint from index '%d' to '%d'", from, to); + return; + } + + ED_object_constraint_tag_update(bmain, ob, NULL); + WM_main_add_notifier(NC_OBJECT | ND_CONSTRAINT, ob); +} + bool rna_PoseChannel_constraints_override_apply(Main *UNUSED(bmain), PointerRNA *ptr_dst, PointerRNA *ptr_src, @@ -929,6 +947,15 @@ static void rna_def_pose_channel_constraints(BlenderRNA *brna, PropertyRNA *cpro parm = RNA_def_pointer(func, "constraint", "Constraint", "", "Removed constraint"); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0); + + func = RNA_def_function(srna, "move", "rna_PoseChannel_constraints_move"); + RNA_def_function_ui_description(func, "Move a constraint to a different position"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS); + parm = RNA_def_int( + func, "from_index", -1, INT_MIN, INT_MAX, "From Index", "Index to move", 0, 10000); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_int(func, "to_index", -1, INT_MIN, INT_MAX, "To Index", "Target index", 0, 10000); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); } static void rna_def_pose_channel(BlenderRNA *brna)