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--release/scripts/ui/properties_object_constraint.py18
-rw-r--r--source/blender/blenkernel/intern/constraint.c113
-rw-r--r--source/blender/editors/object/object_constraint.c17
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h54
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c60
6 files changed, 257 insertions, 6 deletions
diff --git a/release/scripts/ui/properties_object_constraint.py b/release/scripts/ui/properties_object_constraint.py
index f53bac05a7c..11527ad9bda 100644
--- a/release/scripts/ui/properties_object_constraint.py
+++ b/release/scripts/ui/properties_object_constraint.py
@@ -76,7 +76,7 @@ class ConstraintButtonsPanel(bpy.types.Panel):
else:
layout.prop_object(con, "subtarget", con.target.data, "bones", text="")
- if con.type in ('COPY_LOCATION', 'STRETCH_TO', 'TRACK_TO'):
+ if con.type in ('COPY_LOCATION', 'STRETCH_TO', 'TRACK_TO', 'PIVOT'):
row = layout.row()
row.label(text="Head/Tail:")
row.prop(con, "head_tail", text="")
@@ -730,6 +730,22 @@ class ConstraintButtonsPanel(bpy.types.Panel):
col.prop(con, "xz_scaling_mode", text="")
col.prop(con, "use_curve_radius")
+ def PIVOT(self, context, layout, con, wide_ui):
+ self.target_template(layout, con, wide_ui)
+
+ if con.target:
+ col = layout.column()
+ col.prop(con, "offset", text="Pivot Offset")
+ else:
+ col = layout.column()
+ col.prop(con, "use_relative_position")
+ if con.use_relative_position:
+ col.prop(con, "offset", text="Relative Pivot Point")
+ else:
+ col.prop(con, "offset", text="Absolute Pivot Point")
+
+ col = layout.column()
+ col.prop(con, "enabled_rotation_range", text="Pivot When")
class OBJECT_PT_constraints(ConstraintButtonsPanel):
bl_label = "Object Constraints"
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index a3f1cb0cb0c..1a8d665a91d 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -3831,6 +3831,118 @@ static bConstraintTypeInfo CTI_SPLINEIK = {
NULL /* evaluate - solved as separate loop */
};
+/* ----------- Pivot ------------- */
+
+static void pivotcon_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata)
+{
+ bPivotConstraint *data= con->data;
+
+ /* target only */
+ func(con, (ID**)&data->tar, userdata);
+}
+
+static int pivotcon_get_tars (bConstraint *con, ListBase *list)
+{
+ if (con && list) {
+ bPivotConstraint *data= con->data;
+ bConstraintTarget *ct;
+
+ /* standard target-getting macro for single-target constraints */
+ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static void pivotcon_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+ if (con && list) {
+ bPivotConstraint *data= con->data;
+ bConstraintTarget *ct= list->first;
+
+ /* the following macro is used for all standard single-target constraints */
+ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
+ }
+}
+
+static void pivotcon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+ bPivotConstraint *data= con->data;
+ bConstraintTarget *ct= targets->first;
+
+ float pivot[3], vec[3];
+ float rotMat[3][3];
+
+ /* firstly, check if pivoting should take place based on the current rotation */
+ if (data->rotAxis != PIVOTCON_AXIS_NONE) {
+ float rot[3];
+
+ /* extract euler-rotation of target */
+ mat4_to_eulO(rot, cob->rotOrder, cob->matrix);
+
+ /* check which range might be violated */
+ if (data->rotAxis < PIVOTCON_AXIS_X) {
+ /* negative rotations (data->rotAxis = 0 -> 2) */
+ if (rot[data->rotAxis] > 0.0f)
+ return;
+ }
+ else {
+ /* positive rotations (data->rotAxis = 3 -> 5 */
+ if (rot[data->rotAxis - PIVOTCON_AXIS_X] < 0.0f)
+ return;
+ }
+ }
+
+ /* find the pivot-point to use */
+ if (VALID_CONS_TARGET(ct)) {
+ /* apply offset to target location */
+ add_v3_v3v3(pivot, ct->matrix[3], data->offset);
+ }
+ else {
+ /* no targets to worry about... */
+ if ((data->flag & PIVOTCON_FLAG_OFFSET_ABS) == 0) {
+ /* offset is relative to owner */
+ add_v3_v3v3(pivot, cob->matrix[3], data->offset);
+ }
+ else {
+ /* directly use the 'offset' specified as an absolute position instead */
+ VECCOPY(pivot, data->offset);
+ }
+ }
+
+ /* get rotation matrix representing the rotation of the owner */
+ // TODO: perhaps we might want to include scaling based on the pivot too?
+ copy_m3_m4(rotMat, cob->matrix);
+ normalize_m3(rotMat);
+
+ /* perform the pivoting... */
+ /* 1. take the vector from owner to the pivot */
+ sub_v3_v3v3(vec, pivot, cob->matrix[3]);
+ /* 2. rotate this vector by the rotation of the object... */
+ mul_m3_v3(rotMat, vec);
+ /* 3. make the rotation in terms of the pivot now */
+ add_v3_v3v3(cob->matrix[3], pivot, vec);
+}
+
+
+static bConstraintTypeInfo CTI_PIVOT = {
+ CONSTRAINT_TYPE_PIVOT, /* type */
+ sizeof(bPivotConstraint), /* size */
+ "Pivot", /* name */
+ "bPivotConstraint", /* struct name */
+ NULL, /* free data */
+ NULL, /* relink data */
+ pivotcon_id_looper, /* id looper */
+ NULL, /* copy data */
+ NULL, /* new data */ // XXX: might be needed to get 'normal' pivot behaviour...
+ pivotcon_get_tars, /* get constraint targets */
+ pivotcon_flush_tars, /* flush constraint targets */
+ default_get_tarmat, /* get target matrix */
+ pivotcon_evaluate /* evaluate */
+};
+
/* ************************* Constraints Type-Info *************************** */
/* All of the constraints api functions use bConstraintTypeInfo structs to carry out
* and operations that involve constraint specific code.
@@ -3867,6 +3979,7 @@ static void constraints_init_typeinfo () {
constraintsTypeInfo[22]= &CTI_SPLINEIK; /* Spline IK Constraint */
constraintsTypeInfo[23]= &CTI_TRANSLIKE; /* Copy Transforms Constraint */
constraintsTypeInfo[24]= &CTI_SAMEVOL; /* Maintain Volume Constraint */
+ constraintsTypeInfo[25]= &CTI_PIVOT; /* Pivot Constraint */
}
/* This function should be used for getting the appropriate type-info when only
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 9163baf606f..eaabcd866cd 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -322,6 +322,23 @@ static void test_constraints (Object *owner, bPoseChannel *pchan)
/* targets have already been checked for this */
continue;
}
+ else if (curcon->type == CONSTRAINT_TYPE_PIVOT) {
+ bPivotConstraint *data = curcon->data;
+
+ /* target doesn't have to exist, but if it is non-null, it must exist! */
+ if (data->tar && exist_object(data->tar)==0) {
+ data->tar = NULL;
+ curcon->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (data->tar == owner) {
+ if (!get_named_bone(get_armature(owner), data->subtarget)) {
+ curcon->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+
+ /* targets have already been checked for this */
+ continue;
+ }
else if (curcon->type == CONSTRAINT_TYPE_ACTION) {
bActionConstraint *data = curcon->data;
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index 6c7bda171eb..00694a7ea1f 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -174,6 +174,7 @@ typedef struct bSplineIKConstraint {
/* Single-target subobject constraints --------------------- */
+
/* Track To Constraint */
typedef struct bTrackToConstraint {
Object *tar;
@@ -336,6 +337,24 @@ typedef struct bTransformConstraint {
float to_max[3];
} bTransformConstraint;
+/* Pivot Constraint */
+typedef struct bPivotConstraint {
+ /* Pivot Point:
+ * Either target object + offset, or just offset is used
+ */
+ Object *tar; /* target object (optional) */
+ char subtarget[32]; /* subtarget name (optional) */
+ float offset[3]; /* offset from the target to use, regardless of whether it exists */
+
+ /* Rotation-driven activation:
+ * This option provides easier one-stop setups for footrolls
+ */
+ short rotAxis; /* rotation axes to consider for this (ePivotConstraint_Axis) */
+
+ /* General flags */
+ short flag; /* ePivotConstraint_Flag */
+} bPivotConstraint;
+
/* transform limiting constraints - zero target ---------------------------- */
/* Limit Location Constraint */
typedef struct bLocLimitConstraint {
@@ -419,6 +438,7 @@ typedef enum eBConstraint_Types {
CONSTRAINT_TYPE_SPLINEIK, /* Spline-IK - Align 'n' bones to a curve */
CONSTRAINT_TYPE_TRANSLIKE, /* Copy transform matrix */
CONSTRAINT_TYPE_SAMEVOL, /* Maintain volume during scaling */
+ CONSTRAINT_TYPE_PIVOT, /* Pivot Constraint */
/* NOTE: no constraints are allowed to be added after this */
NUM_CONSTRAINT_TYPES
@@ -469,11 +489,6 @@ typedef enum eConstraintChannel_Flags {
/* -------------------------------------- */
-/**
- * The flags for ROTLIKE, LOCLIKE and SIZELIKE should be kept identical
- * (that is, same effect, different name). It simplifies the Python API access a lot.
- */
-
/* bRotateLikeConstraint.flag */
typedef enum eCopyRotation_Flags {
ROTLIKE_X = (1<<0),
@@ -688,6 +703,35 @@ typedef enum eChildOf_Flags {
CHILDOF_SIZEZ = (1<<8),
} eChildOf_Flags;
+/* Pivot Constraint */
+ /* Restrictions for Pivot Constraint axis to consider for enabling constraint */
+typedef enum ePivotConstraint_Axis {
+ /* do not consider this activity-clamping */
+ PIVOTCON_AXIS_NONE = -1,
+
+ /* consider -ve x-axis rotations */
+ PIVOTCON_AXIS_X_NEG,
+ /* consider -ve y-axis rotations */
+ PIVOTCON_AXIS_Y_NEG,
+ /* consider -ve z-axis rotations */
+ PIVOTCON_AXIS_Z_NEG,
+
+ /* consider +ve x-axis rotations */
+ PIVOTCON_AXIS_X,
+ /* consider +ve y-axis rotations */
+ PIVOTCON_AXIS_Y,
+ /* consider +ve z-axis rotations */
+ PIVOTCON_AXIS_Z,
+} ePivotConstraint_Axis;
+
+ /* settings for Pivot Constraint in general */
+typedef enum ePivotConstraint_Flag {
+ /* offset is to be interpreted as being a fixed-point in space */
+ PIVOTCON_FLAG_OFFSET_ABS = (1<<0),
+ /* rotation-based activation uses negative rotation to drive result */
+ PIVOTCON_FLAG_ROTACT_NEG = (1<<1),
+} ePivotConstraint_Flag;
+
/* Rigid-Body Constraint */
#define CONSTRAINT_DRAW_PIVOT 0x40
#define CONSTRAINT_DISABLE_LINKED_COLLISION 0x80
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index f9802e558bb..3badc401514 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -356,6 +356,7 @@ extern StructRNA RNA_SPHFluidSettings;
extern StructRNA RNA_ParticleSystem;
extern StructRNA RNA_ParticleSystemModifier;
extern StructRNA RNA_ParticleTarget;
+extern StructRNA RNA_PivotConstraint;
extern StructRNA RNA_PluginSequence;
extern StructRNA RNA_PluginTexture;
extern StructRNA RNA_PointCache;
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index b4ae49ae2f4..b1c5cac1865 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -67,6 +67,7 @@ EnumPropertyItem constraint_type_items[] ={
{CONSTRAINT_TYPE_RIGIDBODYJOINT, "RIGID_BODY_JOINT", ICON_CONSTRAINT_DATA, "Rigid Body Joint", ""},
{CONSTRAINT_TYPE_PYTHON, "SCRIPT", ICON_CONSTRAINT_DATA, "Script", ""},
{CONSTRAINT_TYPE_SHRINKWRAP, "SHRINKWRAP", ICON_CONSTRAINT_DATA, "Shrinkwrap", ""},
+ {CONSTRAINT_TYPE_PIVOT, "PIVOT", ICON_CONSTRAINT_DATA, "Pivot", ""},
{0, NULL, 0, NULL, NULL}};
EnumPropertyItem space_pchan_items[] = {
@@ -157,6 +158,8 @@ static StructRNA *rna_ConstraintType_refine(struct PointerRNA *ptr)
return &RNA_SplineIKConstraint;
case CONSTRAINT_TYPE_TRANSLIKE:
return &RNA_CopyTransformsConstraint;
+ case CONSTRAINT_TYPE_PIVOT:
+ return &RNA_PivotConstraint;
default:
return &RNA_UnknownType;
}
@@ -1839,6 +1842,62 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna)
RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
}
+static void rna_def_constraint_pivot(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem pivot_rotAxis_items[] = {
+ {PIVOTCON_AXIS_NONE, "ALWAYS_ACTIVE", 0, "Always", ""},
+ {PIVOTCON_AXIS_X_NEG, "NX", 0, "-X Rot", ""},
+ {PIVOTCON_AXIS_Y_NEG, "NY", 0, "-Y Rot", ""},
+ {PIVOTCON_AXIS_Z_NEG, "NZ", 0, "-Z Rot", ""},
+ {PIVOTCON_AXIS_X, "X", 0, "X Rot", ""},
+ {PIVOTCON_AXIS_Y, "Y", 0, "Y Rot", ""},
+ {PIVOTCON_AXIS_Z, "Z", 0, "Z Rot", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+ srna= RNA_def_struct(brna, "PivotConstraint", "Constraint");
+ RNA_def_struct_ui_text(srna, "Pivot Constraint", "Rotate around a different point");
+
+ prop= RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, "bConstraint", "headtail");
+ RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head=0, Tail=1");
+ RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_def_struct_sdna_from(srna, "bPivotConstraint", "data");
+
+ /* target-defined pivot */
+ prop= RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "tar");
+ RNA_def_property_ui_text(prop, "Target", "Target Object, defining the position of the pivot when defined");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update");
+
+ prop= RNA_def_property(srna, "subtarget", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "subtarget");
+ RNA_def_property_ui_text(prop, "Sub-Target", "");
+ RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update");
+
+ /* pivot offset */
+ prop= RNA_def_property(srna, "use_relative_position", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", PIVOTCON_FLAG_OFFSET_ABS);
+ RNA_def_property_ui_text(prop, "Use Relative Offset", "Offset will be an absolute point in space instead of relative to the target");
+ RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop= RNA_def_property(srna, "offset", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_float_sdna(prop, NULL, "offset");
+ RNA_def_property_ui_text(prop, "Offset", "Offset of pivot from target (when set), or from owner's location (when Fixed Position is off), or the absolute pivot point");
+ RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
+
+ /* rotation-based activation */
+ prop= RNA_def_property(srna, "enabled_rotation_range", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "rotAxis");
+ RNA_def_property_enum_items(prop, pivot_rotAxis_items);
+ RNA_def_property_ui_text(prop, "Enabled Rotation Range", "Rotation range on which pivoting should occur");
+ RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
+}
+
/* base struct for constraints */
void RNA_def_constraint(BlenderRNA *brna)
{
@@ -1943,6 +2002,7 @@ void RNA_def_constraint(BlenderRNA *brna)
rna_def_constraint_shrinkwrap(brna);
rna_def_constraint_damped_track(brna);
rna_def_constraint_spline_ik(brna);
+ rna_def_constraint_pivot(brna);
}
#endif