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')
-rw-r--r--source/blender/blenkernel/BKE_constraint.h3
-rw-r--r--source/blender/blenkernel/intern/constraint.c9
-rw-r--r--source/blender/blenloader/intern/versioning_290.c15
-rw-r--r--source/blender/draw/engines/overlay/overlay_extra.c2
-rw-r--r--source/blender/editors/include/UI_interface.h4
-rw-r--r--source/blender/editors/interface/interface_panel.c14
-rw-r--r--source/blender/editors/interface/interface_templates.c297
-rw-r--r--source/blender/editors/object/object_constraint.c71
-rw-r--r--source/blender/editors/object/object_intern.h1
-rw-r--r--source/blender/editors/object/object_ops.c1
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h7
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c10
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c15
13 files changed, 328 insertions, 121 deletions
diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h
index 8fe3bd77a26..020b0f8b913 100644
--- a/source/blender/blenkernel/BKE_constraint.h
+++ b/source/blender/blenkernel/BKE_constraint.h
@@ -136,6 +136,9 @@ typedef struct bConstraintTypeInfo {
const bConstraintTypeInfo *BKE_constraint_typeinfo_get(struct bConstraint *con);
const bConstraintTypeInfo *BKE_constraint_typeinfo_from_type(int type);
+void BKE_constraint_panel_id(int type, char *r_name);
+void BKE_constraint_bone_panel_id(int type, char *r_name);
+
/* ---------------------------------------------------------------------------- */
/* Constraint function prototypes */
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 050e8d434ae..f215297c8a2 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -5412,9 +5412,16 @@ static bConstraint *add_new_constraint_internal(const char *name, short type)
/* Set up a generic constraint data-block. */
con->type = type;
- con->flag |= CONSTRAINT_EXPAND | CONSTRAINT_OVERRIDE_LIBRARY_LOCAL;
+ con->flag |= CONSTRAINT_OVERRIDE_LIBRARY_LOCAL;
con->enforce = 1.0f;
+ /* Only open the main panel when constraints are created, not the subpanels. */
+ con->ui_expand_flag = (1 << 0);
+ if (type == CONSTRAINT_TYPE_ACTION || CONSTRAINT_TYPE_SPLINEIK) {
+ /* Expand the two subpanels in the cases where the main panel barely has any properties. */
+ con->ui_expand_flag |= (1 << 1) | (1 << 2);
+ }
+
/* Determine a basic name, and info */
if (cti) {
/* initialize constraint data */
diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c
index 8d57ef25c4d..0dd1ecd0008 100644
--- a/source/blender/blenloader/intern/versioning_290.c
+++ b/source/blender/blenloader/intern/versioning_290.c
@@ -24,6 +24,7 @@
#include "BLI_utildefines.h"
#include "DNA_brush_types.h"
+#include "DNA_constraint_types.h"
#include "DNA_genfile.h"
#include "DNA_gpencil_modifier_types.h"
#include "DNA_modifier_types.h"
@@ -287,5 +288,19 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
scene->eevee.motion_blur_max = 32;
}
}
+
+ /* Transition to saving expansion for all of a constraint's subpanels. */
+ if (!DNA_struct_elem_find(fd->filesdna, "bConstraint", "short", "ui_expand_flag")) {
+ for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
+ LISTBASE_FOREACH (bConstraint *, con, &object->constraints) {
+ if (con->flag & CONSTRAINT_EXPAND_DEPRECATED) {
+ con->ui_expand_flag = 1;
+ }
+ else {
+ con->ui_expand_flag = 0;
+ }
+ }
+ }
+ }
}
}
diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c
index 15bf26a5fa8..e591f54c750 100644
--- a/source/blender/draw/engines/overlay/overlay_extra.c
+++ b/source/blender/draw/engines/overlay/overlay_extra.c
@@ -1318,7 +1318,7 @@ static void OVERLAY_relationship_lines(OVERLAY_ExtraCallBuffers *cb,
else {
const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon);
- if ((cti && cti->get_constraint_targets) && (curcon->flag & CONSTRAINT_EXPAND)) {
+ if ((cti && cti->get_constraint_targets) && (curcon->ui_expand_flag && (1 << 0))) {
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 59dcc9a8ace..d89e590122c 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -2004,6 +2004,8 @@ void uiTemplatePathBuilder(uiLayout *layout,
struct PointerRNA *root_ptr,
const char *text);
void uiTemplateModifiers(uiLayout *layout, struct bContext *C);
+void uiTemplateConstraints(uiLayout *layout, struct bContext *C, bool use_bone_constraints);
+
uiLayout *uiTemplateGpencilModifier(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr);
void uiTemplateGpencilColorPreview(uiLayout *layout,
struct bContext *C,
@@ -2018,7 +2020,7 @@ uiLayout *uiTemplateShaderFx(uiLayout *layout, struct bContext *C, struct Pointe
void uiTemplateOperatorRedoProperties(uiLayout *layout, const struct bContext *C);
-uiLayout *uiTemplateConstraint(uiLayout *layout, struct PointerRNA *ptr);
+void uiTemplateConstraintHeader(uiLayout *layout, struct PointerRNA *ptr);
void uiTemplatePreview(uiLayout *layout,
struct bContext *C,
struct ID *id,
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 4fff80d5def..924b886f167 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -387,9 +387,19 @@ bool UI_panel_list_matches_data(ARegion *region,
ListBase *data,
uiListPanelIDFromDataFunc panel_idname_func)
{
- int data_len = BLI_listbase_count(data);
+ /* Check for NULL data. */
+ int data_len = 0;
+ Link *data_link = NULL;
+ if (data == NULL) {
+ data_len = 0;
+ data_link = NULL;
+ }
+ else {
+ data_len = BLI_listbase_count(data);
+ data_link = data->first;
+ }
+
int i = 0;
- Link *data_link = data->first;
LISTBASE_FOREACH (Panel *, panel, &region->panels) {
if (panel->type != NULL && panel->type->flag & PNL_INSTANCED) {
/* The panels were reordered by drag and drop. */
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 1ce1e2950d5..189441a1f10 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -1823,6 +1823,20 @@ void uiTemplatePathBuilder(uiLayout *layout,
* Template for building the panel layout for the active object's modifiers.
* \{ */
+/**
+ * Get the active object or the property region's pinned object.
+ */
+static Object *get_context_object(const bContext *C)
+{
+ SpaceProperties *sbuts = CTX_wm_space_properties(C);
+ if (sbuts != NULL && (sbuts->pinid != NULL) && GS(sbuts->pinid->name) == ID_OB) {
+ return (Object *)sbuts->pinid;
+ }
+ else {
+ return CTX_data_active_object(C);
+ }
+}
+
static void modifier_panel_id(void *md_link, char *r_name)
{
ModifierData *md = (ModifierData *)md_link;
@@ -1834,14 +1848,7 @@ void uiTemplateModifiers(uiLayout *UNUSED(layout), bContext *C)
ScrArea *sa = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
- Object *ob;
- SpaceProperties *sbuts = CTX_wm_space_properties(C);
- if (sbuts != NULL && (sbuts->pinid != NULL) && GS(sbuts->pinid->name) == ID_OB) {
- ob = (Object *)sbuts->pinid;
- }
- else {
- ob = CTX_data_active_object(C);
- }
+ Object *ob = get_context_object(C);
ListBase *modifiers = &ob->modifiers;
bool panels_match = UI_panel_list_matches_data(region, modifiers, modifier_panel_id);
@@ -1874,6 +1881,162 @@ void uiTemplateModifiers(uiLayout *UNUSED(layout), bContext *C)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Constraints Template
+ *
+ * Template for building the panel layout for the active object or bone's constraints.
+ * \{ */
+
+/** For building the panel UI for constraints. */
+#define CONSTRAINT_TYPE_PANEL_PREFIX "OBJECT_PT_"
+#define CONSTRAINT_BONE_TYPE_PANEL_PREFIX "BONE_PT_"
+
+/**
+ * Check if the panel's ID starts with 'BONE', meaning it is a bone constraint.
+ */
+static bool constraint_panel_is_bone(Panel *panel)
+{
+ return (panel->panelname[0] == 'B') && (panel->panelname[1] == 'O') &&
+ (panel->panelname[2] == 'N') && (panel->panelname[3] == 'E');
+}
+
+/**
+ * Get the constraints for the active pose bone or the active / pinned object.
+ */
+static ListBase *get_constraints(const bContext *C, bool use_bone_constraints)
+{
+ ListBase *constraints = {NULL};
+ if (use_bone_constraints) {
+ bPoseChannel *pose_bone = CTX_data_pointer_get(C, "pose_bone").data;
+ if (pose_bone != NULL) {
+ constraints = &pose_bone->constraints;
+ }
+ }
+ else {
+ Object *ob = get_context_object(C);
+ if (ob != NULL) {
+ constraints = &ob->constraints;
+ }
+ }
+ return constraints;
+}
+
+/**
+ * Move a constraint to the index it's moved to after a drag and drop.
+ */
+static void constraint_reorder(bContext *C, Panel *panel, int new_index)
+{
+ bool constraint_from_bone = constraint_panel_is_bone(panel);
+ ListBase *lb = get_constraints(C, constraint_from_bone);
+
+ bConstraint *con = BLI_findlink(lb, panel->runtime.list_index);
+ PointerRNA props_ptr;
+ wmOperatorType *ot = WM_operatortype_find("CONSTRAINT_OT_move_to_index", false);
+ WM_operator_properties_create_ptr(&props_ptr, ot);
+ RNA_string_set(&props_ptr, "constraint", con->name);
+ RNA_int_set(&props_ptr, "index", new_index);
+ /* Set owner to #EDIT_CONSTRAINT_OWNER_OBJECT or #EDIT_CONSTRAINT_OWNER_BONE. */
+ RNA_enum_set(&props_ptr, "owner", constraint_from_bone ? 1 : 0);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
+ WM_operator_properties_free(&props_ptr);
+}
+
+/**
+ * Get the expand flag from the active constraint to use for the panel.
+ */
+static short get_constraint_expand_flag(const bContext *C, Panel *panel)
+{
+ bool constraint_from_bone = constraint_panel_is_bone(panel);
+ ListBase *lb = get_constraints(C, constraint_from_bone);
+
+ bConstraint *con = BLI_findlink(lb, panel->runtime.list_index);
+ return con->ui_expand_flag;
+}
+
+/**
+ * Save the expand flag for the panel and subpanels to the constraint.
+ */
+static void set_constraint_expand_flag(const bContext *C, Panel *panel, short expand_flag)
+{
+ bool constraint_from_bone = constraint_panel_is_bone(panel);
+ ListBase *lb = get_constraints(C, constraint_from_bone);
+
+ bConstraint *con = BLI_findlink(lb, panel->runtime.list_index);
+ con->ui_expand_flag = expand_flag;
+}
+
+/**
+ * Function with void * argument for #uiListPanelIDFromDataFunc.
+ *
+ * \note: Constraint panel types are assumed to be named with the struct name field
+ * concatenated to the defined prefix.
+ */
+static void object_constraint_panel_id(void *md_link, char *r_name)
+{
+ bConstraint *con = (bConstraint *)md_link;
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(con->type);
+
+ strcpy(r_name, CONSTRAINT_TYPE_PANEL_PREFIX);
+ strcat(r_name, cti->structName);
+}
+
+static void bone_constraint_panel_id(void *md_link, char *r_name)
+{
+ bConstraint *con = (bConstraint *)md_link;
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(con->type);
+
+ strcpy(r_name, CONSTRAINT_BONE_TYPE_PANEL_PREFIX);
+ strcat(r_name, cti->structName);
+}
+
+/**
+ * Check if the constraint panels don't match the data and rebuild the panels if so.
+ */
+void uiTemplateConstraints(uiLayout *UNUSED(layout), bContext *C, bool use_bone_constraints)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+
+ ListBase *constraints = get_constraints(C, use_bone_constraints);
+
+ /* Switch between the bone panel ID function and the object panel ID function. */
+ uiListPanelIDFromDataFunc panel_id_func = use_bone_constraints ? bone_constraint_panel_id :
+ object_constraint_panel_id;
+
+ bool panels_match = UI_panel_list_matches_data(region, constraints, panel_id_func);
+
+ if (!panels_match) {
+ UI_panels_free_instanced(C, region);
+ bConstraint *con = (constraints == NULL) ? NULL : constraints->first;
+ for (int i = 0; con; i++, con = con->next) {
+ char panel_idname[MAX_NAME];
+ panel_id_func(con, panel_idname);
+
+ Panel *new_panel = UI_panel_add_instanced(sa, region, &region->panels, panel_idname, i);
+ if (new_panel) {
+ /* Set the list panel functionality function pointers since we don't do it with python. */
+ new_panel->type->set_list_data_expand_flag = set_constraint_expand_flag;
+ new_panel->type->get_list_data_expand_flag = get_constraint_expand_flag;
+ new_panel->type->reorder = constraint_reorder;
+
+ UI_panel_set_expand_from_list_data(C, new_panel);
+ }
+ }
+ }
+ else {
+ /* The expansion might have been changed elsewhere, so we still need to set it. */
+ LISTBASE_FOREACH (Panel *, panel, &region->panels) {
+ if ((panel->type != NULL) && (panel->type->flag & PNL_INSTANCED))
+ UI_panel_set_expand_from_list_data(C, panel);
+ }
+ }
+}
+
+#undef CONSTRAINT_TYPE_PANEL_PREFIX
+#undef CONSTRAINT_BONE_TYPE_PANEL_PREFIX
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Grease Pencil Modifier Template
* \{ */
@@ -2441,7 +2604,7 @@ void uiTemplateOperatorRedoProperties(uiLayout *layout, const bContext *C)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Constraint Template
+/** \name Constraint Header Template
* \{ */
static void constraint_active_func(bContext *UNUSED(C), void *ob_v, void *con_v)
@@ -2449,30 +2612,15 @@ static void constraint_active_func(bContext *UNUSED(C), void *ob_v, void *con_v)
ED_object_constraint_active_set(ob_v, con_v);
}
-/* draw panel showing settings for a constraint */
-static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
+static void draw_constraint_header(uiLayout *layout, Object *ob, bConstraint *con)
{
bPoseChannel *pchan = BKE_pose_channel_active(ob);
- const bConstraintTypeInfo *cti;
uiBlock *block;
- uiLayout *result = NULL, *col, *box, *row;
+ uiLayout *sub;
PointerRNA ptr;
- char typestr[32];
short proxy_protected, xco = 0, yco = 0;
// int rb_col; // UNUSED
- /* get constraint typeinfo */
- cti = BKE_constraint_typeinfo_get(con);
- if (cti == NULL) {
- /* exception for 'Null' constraint - it doesn't have constraint typeinfo! */
- BLI_strncpy(typestr,
- (con->type == CONSTRAINT_TYPE_NULL) ? IFACE_("Null") : IFACE_("Unknown"),
- sizeof(typestr));
- }
- else {
- BLI_strncpy(typestr, IFACE_(cti->name), sizeof(typestr));
- }
-
/* determine whether constraint is proxy protected or not */
if (BKE_constraints_proxylocked_owner(ob, pchan)) {
proxy_protected = (con->flag & CONSTRAINT_PROXY_LOCAL) == 0;
@@ -2487,36 +2635,23 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
RNA_pointer_create(&ob->id, &RNA_Constraint, con, &ptr);
- col = uiLayoutColumn(layout, true);
- uiLayoutSetContextPointer(col, "constraint", &ptr);
-
- box = uiLayoutBox(col);
- row = uiLayoutRow(box, false);
- block = uiLayoutGetBlock(box);
-
- /* Draw constraint header */
+ uiLayoutSetContextPointer(layout, "constraint", &ptr);
- /* open/close */
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- uiItemR(row, &ptr, "show_expanded", 0, "", ICON_NONE);
+ /* Constraint type icon. */
+ sub = uiLayoutRow(layout, false);
+ uiLayoutSetEmboss(sub, false);
+ uiLayoutSetRedAlert(sub, (con->flag & CONSTRAINT_DISABLE));
+ uiItemL(sub, "", RNA_struct_ui_icon(ptr.type));
- /* constraint-type icon */
- uiItemL(row, "", RNA_struct_ui_icon(ptr.type));
UI_block_emboss_set(block, UI_EMBOSS);
- if (con->flag & CONSTRAINT_DISABLE) {
- uiLayoutSetRedAlert(row, true);
- }
-
if (proxy_protected == 0) {
- uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
+ uiItemR(layout, &ptr, "name", 0, "", ICON_NONE);
}
else {
- uiItemL(row, con->name, ICON_NONE);
+ uiItemL(layout, con->name, ICON_NONE);
}
- uiLayoutSetRedAlert(row, false);
-
/* proxy-protected constraints cannot be edited, so hide up/down + close buttons */
if (proxy_protected) {
UI_block_emboss_set(block, UI_EMBOSS_NONE);
@@ -2555,54 +2690,20 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
UI_block_emboss_set(block, UI_EMBOSS);
}
else {
- short prev_proxylock, show_upbut, show_downbut;
-
- /* Up/Down buttons:
- * Proxy-constraints are not allowed to occur after local (non-proxy) constraints
- * as that poses problems when restoring them, so disable the "up" button where
- * it may cause this situation.
- *
- * Up/Down buttons should only be shown (or not grayed - todo) if they serve some purpose.
- */
- if (BKE_constraints_proxylocked_owner(ob, pchan)) {
- if (con->prev) {
- prev_proxylock = (con->prev->flag & CONSTRAINT_PROXY_LOCAL) ? 0 : 1;
- }
- else {
- prev_proxylock = 0;
- }
- }
- else {
- prev_proxylock = 0;
- }
-
- show_upbut = ((prev_proxylock == 0) && (con->prev));
- show_downbut = (con->next) ? 1 : 0;
-
/* enabled */
UI_block_emboss_set(block, UI_EMBOSS_NONE);
- uiItemR(row, &ptr, "mute", 0, "", 0);
+ uiItemR(layout, &ptr, "mute", 0, "", 0);
UI_block_emboss_set(block, UI_EMBOSS);
- uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
-
- /* up/down */
- if (show_upbut || show_downbut) {
- UI_block_align_begin(block);
- if (show_upbut) {
- uiItemO(row, "", ICON_TRIA_UP, "CONSTRAINT_OT_move_up");
- }
-
- if (show_downbut) {
- uiItemO(row, "", ICON_TRIA_DOWN, "CONSTRAINT_OT_move_down");
- }
- UI_block_align_end(block);
- }
+ uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
/* Close 'button' - emboss calls here disable drawing of 'button' behind X */
UI_block_emboss_set(block, UI_EMBOSS_NONE);
- uiItemO(row, "", ICON_X, "CONSTRAINT_OT_delete");
+ uiItemO(layout, "", ICON_X, "CONSTRAINT_OT_delete");
UI_block_emboss_set(block, UI_EMBOSS);
+
+ /* Some extra padding at the end, so the 'x' icon isn't too close to drag button. */
+ uiItemS(layout);
}
/* Set but-locks for protected settings (magic numbers are used here!) */
@@ -2610,23 +2711,11 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
UI_block_lock_set(block, true, TIP_("Cannot edit Proxy-Protected Constraint"));
}
- /* Draw constraint data */
- if ((con->flag & CONSTRAINT_EXPAND) == 0) {
- (yco) -= 10.5f * UI_UNIT_Y;
- }
- else {
- box = uiLayoutBox(col);
- block = uiLayoutAbsoluteBlock(box);
- result = box;
- }
-
/* clear any locks set up for proxies/lib-linking */
UI_block_lock_clear(block);
-
- return result;
}
-uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr)
+void uiTemplateConstraintHeader(uiLayout *layout, PointerRNA *ptr)
{
Object *ob;
bConstraint *con;
@@ -2634,7 +2723,7 @@ uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr)
/* verify we have valid data */
if (!RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
RNA_warning("Expected constraint on object");
- return NULL;
+ return;
}
ob = (Object *)ptr->owner_id;
@@ -2642,7 +2731,7 @@ uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr)
if (!ob || !(GS(ob->id.name) == ID_OB)) {
RNA_warning("Expected constraint on object");
- return NULL;
+ return;
}
UI_block_lock_set(uiLayoutGetBlock(layout), (ob && ID_IS_LINKED(ob)), ERROR_LIBDATA_MESSAGE);
@@ -2651,11 +2740,11 @@ uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr)
if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
bKinematicConstraint *data = con->data;
if (data->flag & CONSTRAINT_IK_TEMP) {
- return NULL;
+ return;
}
}
- return draw_constraint(layout, ob, con);
+ draw_constraint_header(layout, ob, con);
}
/** \} */
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index a2d33ffe413..5746480e3f8 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -1557,6 +1557,77 @@ void CONSTRAINT_OT_move_up(wmOperatorType *ot)
/** \} */
/* ------------------------------------------------------------------- */
+/** \name Move Constraint To Index Operator
+ * \{ */
+
+static int constraint_move_to_index_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = ED_object_active_context(C);
+ bConstraint *con = edit_constraint_property_get(op, ob, 0);
+
+ int new_index = RNA_int_get(op->ptr, "index");
+ if (new_index < 0) {
+ new_index = 0;
+ }
+
+ if (con) {
+ ListBase *conlist = ED_object_constraint_list_from_constraint(ob, con, NULL);
+ int current_index = BLI_findindex(conlist, con);
+ BLI_assert(current_index >= 0);
+
+ BLI_listbase_link_move(conlist, con, new_index - current_index);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
+
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+static int constraint_move_to_index_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
+{
+ if (edit_constraint_invoke_properties(C, op)) {
+ return constraint_move_to_index_exec(C, op);
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void CONSTRAINT_OT_move_to_index(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Move Constraint To Index";
+ ot->idname = "CONSTRAINT_OT_move_to_index";
+ ot->description =
+ "Change the constraint's position in the list so it evaluates after the set number of "
+ "others";
+
+ /* callbacks */
+ ot->exec = constraint_move_to_index_exec;
+ ot->invoke = constraint_move_to_index_invoke;
+ ot->poll = edit_constraint_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ edit_constraint_properties(ot);
+ RNA_def_int(ot->srna,
+ "index",
+ 0,
+ 0,
+ INT_MAX,
+ "Index",
+ "The index to move the constraint to",
+ 0,
+ INT_MAX);
+}
+
+/** \} */
+
+/* ------------------------------------------------------------------- */
/** \name Clear Pose Constraints Operator
* \{ */
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index c5a6e38fbcb..1cd91f7c1f3 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -217,6 +217,7 @@ void POSE_OT_ik_clear(struct wmOperatorType *ot);
void CONSTRAINT_OT_delete(struct wmOperatorType *ot);
void CONSTRAINT_OT_move_up(struct wmOperatorType *ot);
+void CONSTRAINT_OT_move_to_index(struct wmOperatorType *ot);
void CONSTRAINT_OT_move_down(struct wmOperatorType *ot);
void CONSTRAINT_OT_stretchto_reset(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index 05f1ced8615..84bc10f8064 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -179,6 +179,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(CONSTRAINT_OT_delete);
WM_operatortype_append(CONSTRAINT_OT_move_up);
WM_operatortype_append(CONSTRAINT_OT_move_down);
+ WM_operatortype_append(CONSTRAINT_OT_move_to_index);
WM_operatortype_append(CONSTRAINT_OT_stretchto_reset);
WM_operatortype_append(CONSTRAINT_OT_limitdistance_reset);
WM_operatortype_append(CONSTRAINT_OT_childof_set_inverse);
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index 65087a6d459..85d9a04a902 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -61,7 +61,8 @@ typedef struct bConstraint {
/** Constraint name, MAX_NAME. */
char name[64];
- char _pad[2];
+ /* Flag for panel and subpanel closed / open state in the UI. */
+ short ui_expand_flag;
/** Amount of influence exherted by constraint (0.0-1.0). */
float enforce;
@@ -689,8 +690,8 @@ typedef enum eBConstraint_Types {
/* flag 0x20 (1 << 5) was used to indicate that a constraint was evaluated
* using a 'local' hack for posebones only. */
typedef enum eBConstraint_Flags {
- /* expand for UI */
- CONSTRAINT_EXPAND = (1 << 0),
+ /* Expansion for old box constraint layouts. Just for versioning. */
+ CONSTRAINT_EXPAND_DEPRECATED = (1 << 0),
/* pre-check for illegal object name or bone name */
CONSTRAINT_DISABLE = (1 << 2),
/* to indicate which Ipo should be shown, maybe for 3d access later too */
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 5405cb4e24a..af300f6e088 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -2483,7 +2483,7 @@ static void rna_def_constraint_location_limit(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_transform_limit", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag2", LIMIT_TRANSFORM);
RNA_def_property_ui_text(
- prop, "For Transform", "Transforms are affected by this constraint as well");
+ prop, "Affect Transform", "Transforms are affected by this constraint as well");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
RNA_define_lib_overridable(false);
@@ -2556,7 +2556,7 @@ static void rna_def_constraint_rotation_limit(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_transform_limit", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag2", LIMIT_TRANSFORM);
RNA_def_property_ui_text(
- prop, "For Transform", "Transforms are affected by this constraint as well");
+ prop, "Affect Transform", "Transforms are affected by this constraint as well");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
RNA_define_lib_overridable(false);
@@ -2644,7 +2644,7 @@ static void rna_def_constraint_size_limit(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_transform_limit", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag2", LIMIT_TRANSFORM);
RNA_def_property_ui_text(
- prop, "For Transform", "Transforms are affected by this constraint as well");
+ prop, "Affect Transform", "Transforms are affected by this constraint as well");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
RNA_define_lib_overridable(false);
@@ -2684,7 +2684,7 @@ static void rna_def_constraint_distance_limit(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_transform_limit", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", LIMITDIST_TRANSFORM);
RNA_def_property_ui_text(
- prop, "For Transform", "Transforms are affected by this constraint as well");
+ prop, "Affect Transform", "Transforms are affected by this constraint as well");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
RNA_define_lib_overridable(false);
@@ -3380,7 +3380,7 @@ void RNA_def_constraint(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_EXPAND);
+ RNA_def_property_boolean_sdna(prop, NULL, "ui_expand_flag", 0);
RNA_def_property_ui_text(prop, "Expanded", "Constraint's panel is expanded in UI");
RNA_def_property_ui_icon(prop, ICON_DISCLOSURE_TRI_RIGHT, 1);
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index fd65b713d15..8bfee4cc26c 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -1213,6 +1213,15 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
RNA_def_function_ui_description(func, "Generates the UI layout for the modifier stack");
+ func = RNA_def_function(srna, "template_constraints", "uiTemplateConstraints");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ RNA_def_function_ui_description(func, "Generates the panels for the constraint stack");
+ RNA_def_boolean(func,
+ "use_bone_constraints",
+ true,
+ "",
+ "Add panels for bone constraints instead of object constraints");
+
func = RNA_def_function(srna, "template_greasepencil_modifier", "uiTemplateGpencilModifier");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
RNA_def_function_ui_description(func, "Generates the UI layout for grease pencil modifiers");
@@ -1251,12 +1260,10 @@ void RNA_api_ui_layout(StructRNA *srna)
"",
"Optionally limit the items which can be selected");
- func = RNA_def_function(srna, "template_constraint", "uiTemplateConstraint");
- RNA_def_function_ui_description(func, "Generates the UI layout for constraints");
+ func = RNA_def_function(srna, "template_constraint_header", "uiTemplateConstraintHeader");
+ RNA_def_function_ui_description(func, "Generates the header for constraint panels");
parm = RNA_def_pointer(func, "data", "Constraint", "", "Constraint data");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
- parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in");
- RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "template_preview", "uiTemplatePreview");
RNA_def_function_ui_description(