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:
2018-08-09 17:17:40 +03:00
parent ff6bd57873
commit a5aeca4a64
7 changed files with 98 additions and 52 deletions

View File

@@ -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]);

View File

@@ -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)

View File

@@ -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) &&

View File

@@ -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),

View File

@@ -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");

View File

@@ -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)

View File

@@ -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);