Fix dependency graph for constraints depending on B-Bone shape.
Some constraints have an option to take the final bezier shape of the target B-Bone into account. This shape usually depends on two other bones in addition to the target itself, so the graph should include the relevant dependencies. Reviewers: sergey Differential Revision: https://developer.blender.org/D3591
This commit is contained in:
@@ -140,6 +140,8 @@ typedef struct Mat4 {
|
||||
float mat[4][4];
|
||||
} Mat4;
|
||||
|
||||
void BKE_pchan_get_bbone_handles(struct bPoseChannel *pchan, struct bPoseChannel **r_prev, struct bPoseChannel **r_next);
|
||||
|
||||
void equalize_bbone_bezier(float *data, int desired);
|
||||
void b_bone_spline_setup(struct bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BBONE_SUBDIV]);
|
||||
|
||||
|
@@ -433,6 +433,25 @@ void equalize_bbone_bezier(float *data, int desired)
|
||||
copy_qt_qt(fp, temp[MAX_BBONE_SUBDIV]);
|
||||
}
|
||||
|
||||
/* get "next" and "prev" bones - these are used for handle calculations */
|
||||
void BKE_pchan_get_bbone_handles(bPoseChannel *pchan, bPoseChannel **r_prev, bPoseChannel **r_next)
|
||||
{
|
||||
if (pchan->bboneflag & PCHAN_BBONE_CUSTOM_HANDLES) {
|
||||
/* use the provided bones as the next/prev - leave blank to eliminate this effect altogether */
|
||||
*r_prev = pchan->bbone_prev;
|
||||
*r_next = pchan->bbone_next;
|
||||
}
|
||||
else {
|
||||
/* evaluate next and prev bones */
|
||||
if (pchan->bone->flag & BONE_CONNECTED)
|
||||
*r_prev = pchan->parent;
|
||||
else
|
||||
*r_prev = NULL;
|
||||
|
||||
*r_next = pchan->child;
|
||||
}
|
||||
}
|
||||
|
||||
/* returns pointer to static array, filled with desired amount of bone->segments elements */
|
||||
/* this calculation is done within unit bone space */
|
||||
void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BBONE_SUBDIV])
|
||||
@@ -460,21 +479,7 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB
|
||||
}
|
||||
}
|
||||
|
||||
/* get "next" and "prev" bones - these are used for handle calculations */
|
||||
if (pchan->bboneflag & PCHAN_BBONE_CUSTOM_HANDLES) {
|
||||
/* use the provided bones as the next/prev - leave blank to eliminate this effect altogether */
|
||||
prev = pchan->bbone_prev;
|
||||
next = pchan->bbone_next;
|
||||
}
|
||||
else {
|
||||
/* evaluate next and prev bones */
|
||||
if (bone->flag & BONE_CONNECTED)
|
||||
prev = pchan->parent;
|
||||
else
|
||||
prev = NULL;
|
||||
|
||||
next = pchan->child;
|
||||
}
|
||||
BKE_pchan_get_bbone_handles(pchan, &prev, &next);
|
||||
|
||||
/* find the handle points, since this is inside bone space, the
|
||||
* first point = (0, 0, 0)
|
||||
|
@@ -185,6 +185,23 @@ static bool check_id_has_anim_component(ID *id)
|
||||
(!BLI_listbase_is_empty(&adt->nla_tracks));
|
||||
}
|
||||
|
||||
static eDepsOperation_Code bone_target_opcode(ID *target, const char *subtarget, ID *id, const char *component_subdata, RootPChanMap *root_map)
|
||||
{
|
||||
/* same armature */
|
||||
if (target == id) {
|
||||
/* Using "done" here breaks in-chain deps, while using
|
||||
* "ready" here breaks most production rigs instead.
|
||||
* So, we do a compromise here, and only do this when an
|
||||
* IK chain conflict may occur.
|
||||
*/
|
||||
if (root_map->has_common_root(component_subdata, subtarget)) {
|
||||
return DEG_OPCODE_BONE_READY;
|
||||
}
|
||||
}
|
||||
|
||||
return DEG_OPCODE_BONE_DONE;
|
||||
}
|
||||
|
||||
/* **** General purpose functions **** */
|
||||
|
||||
DepsgraphRelationBuilder::DepsgraphRelationBuilder(Main *bmain,
|
||||
@@ -907,38 +924,42 @@ void DepsgraphRelationBuilder::build_constraints(ID *id,
|
||||
add_relation(target_transform_key, constraint_op_key, cti->name);
|
||||
}
|
||||
else if ((ct->tar->type == OB_ARMATURE) && (ct->subtarget[0])) {
|
||||
/* bone */
|
||||
if (&ct->tar->id == id) {
|
||||
/* same armature */
|
||||
eDepsOperation_Code target_key_opcode;
|
||||
/* Using "done" here breaks in-chain deps, while using
|
||||
* "ready" here breaks most production rigs instead.
|
||||
* So, we do a compromise here, and only do this when an
|
||||
* IK chain conflict may occur.
|
||||
*/
|
||||
if (root_map->has_common_root(component_subdata,
|
||||
ct->subtarget))
|
||||
{
|
||||
target_key_opcode = DEG_OPCODE_BONE_READY;
|
||||
eDepsOperation_Code opcode;
|
||||
/* relation to bone */
|
||||
opcode = bone_target_opcode(&ct->tar->id, ct->subtarget,
|
||||
id, component_subdata, root_map);
|
||||
OperationKey target_key(&ct->tar->id,
|
||||
DEG_NODE_TYPE_BONE,
|
||||
ct->subtarget,
|
||||
opcode);
|
||||
add_relation(target_key, constraint_op_key, cti->name);
|
||||
/* if needs bbone shape, also reference handles */
|
||||
if (con->flag & CONSTRAINT_BBONE_SHAPE) {
|
||||
bPoseChannel *pchan = BKE_pose_channel_find_name(ct->tar->pose, ct->subtarget);
|
||||
/* actually a bbone */
|
||||
if (pchan && pchan->bone && pchan->bone->segments > 1) {
|
||||
bPoseChannel *prev, *next;
|
||||
BKE_pchan_get_bbone_handles(pchan, &prev, &next);
|
||||
/* add handle links */
|
||||
if (prev) {
|
||||
opcode = bone_target_opcode(&ct->tar->id, prev->name,
|
||||
id, component_subdata, root_map);
|
||||
OperationKey prev_key(&ct->tar->id,
|
||||
DEG_NODE_TYPE_BONE,
|
||||
prev->name,
|
||||
opcode);
|
||||
add_relation(prev_key, constraint_op_key, cti->name);
|
||||
}
|
||||
if (next) {
|
||||
opcode = bone_target_opcode(&ct->tar->id, next->name,
|
||||
id, component_subdata, root_map);
|
||||
OperationKey next_key(&ct->tar->id,
|
||||
DEG_NODE_TYPE_BONE,
|
||||
next->name,
|
||||
opcode);
|
||||
add_relation(next_key, constraint_op_key, cti->name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
target_key_opcode = DEG_OPCODE_BONE_DONE;
|
||||
}
|
||||
OperationKey target_key(&ct->tar->id,
|
||||
DEG_NODE_TYPE_BONE,
|
||||
ct->subtarget,
|
||||
target_key_opcode);
|
||||
add_relation(target_key, constraint_op_key, cti->name);
|
||||
}
|
||||
else {
|
||||
/* Different armature - we can safely use the result
|
||||
* of that.
|
||||
*/
|
||||
OperationKey target_key(&ct->tar->id,
|
||||
DEG_NODE_TYPE_BONE,
|
||||
ct->subtarget,
|
||||
DEG_OPCODE_BONE_DONE);
|
||||
add_relation(target_key, constraint_op_key, cti->name);
|
||||
}
|
||||
}
|
||||
else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) &&
|
||||
|
@@ -524,7 +524,7 @@ typedef enum eBConstraint_Flags {
|
||||
CONSTRAINT_PROXY_LOCAL = (1<<8),
|
||||
/* indicates that constraint is temporarily disabled (only used in GE) */
|
||||
CONSTRAINT_OFF = (1<<9),
|
||||
/* use bbone curve shape when calculating headtail values */
|
||||
/* use bbone curve shape when calculating headtail values (also used by dependency graph!) */
|
||||
CONSTRAINT_BBONE_SHAPE = (1<<10),
|
||||
/* That constraint has been inserted in local override (i.e. it can be fully edited!). */
|
||||
CONSTRAINT_STATICOVERRIDE_LOCAL = (1 << 11),
|
||||
|
@@ -52,6 +52,7 @@
|
||||
#include "BKE_armature.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
#include "DEG_depsgraph_build.h"
|
||||
|
||||
static void rna_Armature_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
|
||||
{
|
||||
@@ -62,6 +63,15 @@ static void rna_Armature_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene),
|
||||
/*WM_main_add_notifier(NC_OBJECT|ND_POSE, NULL); */
|
||||
}
|
||||
|
||||
static void rna_Armature_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
|
||||
{
|
||||
ID *id = ptr->id.data;
|
||||
|
||||
DEG_relations_tag_update(bmain);
|
||||
|
||||
DEG_id_tag_update(id, 0);
|
||||
WM_main_add_notifier(NC_GEOM | ND_DATA, id);
|
||||
}
|
||||
|
||||
static void rna_Armature_act_bone_set(PointerRNA *ptr, PointerRNA value)
|
||||
{
|
||||
@@ -722,7 +732,7 @@ static void rna_def_bone_common(StructRNA *srna, int editbone)
|
||||
RNA_def_property_int_sdna(prop, NULL, "segments");
|
||||
RNA_def_property_range(prop, 1, 32);
|
||||
RNA_def_property_ui_text(prop, "B-Bone Segments", "Number of subdivisions of bone (for B-Bones only)");
|
||||
RNA_def_property_update(prop, 0, "rna_Armature_update_data");
|
||||
RNA_def_property_update(prop, 0, "rna_Armature_dependency_update");
|
||||
|
||||
prop = RNA_def_property(srna, "bbone_x", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "xwidth");
|
||||
|
@@ -517,7 +517,7 @@ static void rna_def_constraint_headtail_common(StructRNA *srna)
|
||||
prop = RNA_def_property(srna, "use_bbone_shape", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, "bConstraint", "flag", CONSTRAINT_BBONE_SHAPE);
|
||||
RNA_def_property_ui_text(prop, "Follow B-Bone", "Follow shape of B-Bone segments when calculating Head/Tail position");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
|
||||
}
|
||||
|
||||
static void rna_def_constraint_target_common(StructRNA *srna)
|
||||
|
@@ -127,6 +127,14 @@ static void rna_Pose_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRN
|
||||
WM_main_add_notifier(NC_OBJECT | ND_POSE, ptr->id.data);
|
||||
}
|
||||
|
||||
static void rna_Pose_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
|
||||
{
|
||||
DEG_relations_tag_update(bmain);
|
||||
|
||||
DEG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
|
||||
WM_main_add_notifier(NC_OBJECT | ND_POSE, ptr->id.data);
|
||||
}
|
||||
|
||||
static void rna_Pose_IK_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
|
||||
{
|
||||
/* XXX when to use this? ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK); */
|
||||
@@ -963,7 +971,7 @@ static void rna_def_pose_channel(BlenderRNA *brna)
|
||||
"Use custom reference bones as handles for B-Bones instead of next/previous bones, "
|
||||
"leave these blank to use only B-Bone offset properties to control the shape");
|
||||
RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_dependency_update");
|
||||
|
||||
prop = RNA_def_property(srna, "bbone_custom_handle_start", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "bbone_prev");
|
||||
@@ -972,7 +980,7 @@ static void rna_def_pose_channel(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "B-Bone Start Handle",
|
||||
"Bone that serves as the start handle for the B-Bone curve");
|
||||
RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_dependency_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_bbone_relative_start_handle", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "bboneflag", PCHAN_BBONE_CUSTOM_START_REL);
|
||||
@@ -988,7 +996,7 @@ static void rna_def_pose_channel(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "B-Bone End Handle",
|
||||
"Bone that serves as the end handle for the B-Bone curve");
|
||||
RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_dependency_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_bbone_relative_end_handle", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "bboneflag", PCHAN_BBONE_CUSTOM_END_REL);
|
||||
|
Reference in New Issue
Block a user