Fix T56170: Fake dependency cycle in new depsgraph + interleaved armature update + proxy
Make proxy copy result more atomic operation.
This commit is contained in:
@@ -201,6 +201,7 @@ void BKE_pose_remove_group_index(struct bPose *pose, const int index);
|
||||
void what_does_obaction(struct Object *ob, struct Object *workob, struct bPose *pose, struct bAction *act, char groupname[], float cframe);
|
||||
|
||||
/* for proxy */
|
||||
void BKE_pose_copyesult_pchan_result(struct bPoseChannel *pchanto, const struct bPoseChannel *pchanfrom);
|
||||
bool BKE_pose_copy_result(struct bPose *to, struct bPose *from);
|
||||
/* clear all transforms */
|
||||
void BKE_pose_rest(struct bPose *pose);
|
||||
|
||||
@@ -231,9 +231,16 @@ void BKE_pose_eval_flush(
|
||||
struct Scene *scene,
|
||||
struct Object *ob);
|
||||
|
||||
void BKE_pose_eval_proxy_copy(
|
||||
void BKE_pose_eval_proxy_pose_init(struct Depsgraph *depsgraph,
|
||||
struct Object *object);
|
||||
|
||||
void BKE_pose_eval_proxy_pose_done(struct Depsgraph *depsgraph,
|
||||
struct Object *object);
|
||||
|
||||
void BKE_pose_eval_proxy_copy_bone(
|
||||
struct Depsgraph *depsgraph,
|
||||
struct Object *ob);
|
||||
struct Object *object,
|
||||
int pchan_index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -1328,6 +1328,37 @@ void BKE_pose_rest(bPose *pose)
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_pose_copyesult_pchan_result(bPoseChannel *pchanto, const bPoseChannel *pchanfrom)
|
||||
{
|
||||
copy_m4_m4(pchanto->pose_mat, pchanfrom->pose_mat);
|
||||
copy_m4_m4(pchanto->chan_mat, pchanfrom->chan_mat);
|
||||
|
||||
/* used for local constraints */
|
||||
copy_v3_v3(pchanto->loc, pchanfrom->loc);
|
||||
copy_qt_qt(pchanto->quat, pchanfrom->quat);
|
||||
copy_v3_v3(pchanto->eul, pchanfrom->eul);
|
||||
copy_v3_v3(pchanto->size, pchanfrom->size);
|
||||
|
||||
copy_v3_v3(pchanto->pose_head, pchanfrom->pose_head);
|
||||
copy_v3_v3(pchanto->pose_tail, pchanfrom->pose_tail);
|
||||
|
||||
pchanto->roll1 = pchanfrom->roll1;
|
||||
pchanto->roll2 = pchanfrom->roll2;
|
||||
pchanto->curveInX = pchanfrom->curveInX;
|
||||
pchanto->curveInY = pchanfrom->curveInY;
|
||||
pchanto->curveOutX = pchanfrom->curveOutX;
|
||||
pchanto->curveOutY = pchanfrom->curveOutY;
|
||||
pchanto->ease1 = pchanfrom->ease1;
|
||||
pchanto->ease2 = pchanfrom->ease2;
|
||||
pchanto->scaleIn = pchanfrom->scaleIn;
|
||||
pchanto->scaleOut = pchanfrom->scaleOut;
|
||||
|
||||
pchanto->rotmode = pchanfrom->rotmode;
|
||||
pchanto->flag = pchanfrom->flag;
|
||||
pchanto->protectflag = pchanfrom->protectflag;
|
||||
pchanto->bboneflag = pchanfrom->bboneflag;
|
||||
}
|
||||
|
||||
/* both poses should be in sync */
|
||||
bool BKE_pose_copy_result(bPose *to, bPose *from)
|
||||
{
|
||||
@@ -1346,34 +1377,8 @@ bool BKE_pose_copy_result(bPose *to, bPose *from)
|
||||
|
||||
for (pchanfrom = from->chanbase.first; pchanfrom; pchanfrom = pchanfrom->next) {
|
||||
pchanto = BKE_pose_channel_find_name(to, pchanfrom->name);
|
||||
if (pchanto) {
|
||||
copy_m4_m4(pchanto->pose_mat, pchanfrom->pose_mat);
|
||||
copy_m4_m4(pchanto->chan_mat, pchanfrom->chan_mat);
|
||||
|
||||
/* used for local constraints */
|
||||
copy_v3_v3(pchanto->loc, pchanfrom->loc);
|
||||
copy_qt_qt(pchanto->quat, pchanfrom->quat);
|
||||
copy_v3_v3(pchanto->eul, pchanfrom->eul);
|
||||
copy_v3_v3(pchanto->size, pchanfrom->size);
|
||||
|
||||
copy_v3_v3(pchanto->pose_head, pchanfrom->pose_head);
|
||||
copy_v3_v3(pchanto->pose_tail, pchanfrom->pose_tail);
|
||||
|
||||
pchanto->roll1 = pchanfrom->roll1;
|
||||
pchanto->roll2 = pchanfrom->roll2;
|
||||
pchanto->curveInX = pchanfrom->curveInX;
|
||||
pchanto->curveInY = pchanfrom->curveInY;
|
||||
pchanto->curveOutX = pchanfrom->curveOutX;
|
||||
pchanto->curveOutY = pchanfrom->curveOutY;
|
||||
pchanto->ease1 = pchanfrom->ease1;
|
||||
pchanto->ease2 = pchanfrom->ease2;
|
||||
pchanto->scaleIn = pchanfrom->scaleIn;
|
||||
pchanto->scaleOut = pchanfrom->scaleOut;
|
||||
|
||||
pchanto->rotmode = pchanfrom->rotmode;
|
||||
pchanto->flag = pchanfrom->flag;
|
||||
pchanto->protectflag = pchanfrom->protectflag;
|
||||
pchanto->bboneflag = pchanfrom->bboneflag;
|
||||
if (pchanto != NULL) {
|
||||
BKE_pose_copyesult_pchan_result(pchanto, pchanfrom);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -558,6 +558,17 @@ void BKE_splineik_execute_tree(
|
||||
|
||||
/* *************** Depsgraph evaluation callbacks ************ */
|
||||
|
||||
static void pose_pchan_index_create(bPose *pose)
|
||||
{
|
||||
const int num_channels = BLI_listbase_count(&pose->chanbase);
|
||||
pose->chan_array = MEM_malloc_arrayN(
|
||||
num_channels, sizeof(bPoseChannel *), "pose->chan_array");
|
||||
int pchan_index = 0;
|
||||
for (bPoseChannel *pchan = pose->chanbase.first; pchan != NULL; pchan = pchan->next) {
|
||||
pose->chan_array[pchan_index++] = pchan;
|
||||
}
|
||||
}
|
||||
|
||||
BLI_INLINE bPoseChannel *pose_pchan_get_indexed(Object *ob, int pchan_index)
|
||||
{
|
||||
bPose *pose = ob->pose;
|
||||
@@ -585,16 +596,12 @@ void BKE_pose_eval_init(struct Depsgraph *depsgraph,
|
||||
/* imat is needed for solvers. */
|
||||
invert_m4_m4(ob->imat, ob->obmat);
|
||||
|
||||
const int num_channels = BLI_listbase_count(&pose->chanbase);
|
||||
pose->chan_array = MEM_malloc_arrayN(
|
||||
num_channels, sizeof(bPoseChannel *), "pose->chan_array");
|
||||
|
||||
/* clear flags */
|
||||
int pchan_index = 0;
|
||||
for (bPoseChannel *pchan = pose->chanbase.first; pchan != NULL; pchan = pchan->next) {
|
||||
pchan->flag &= ~(POSE_DONE | POSE_CHAIN | POSE_IKTREE | POSE_IKSPLINE);
|
||||
pose->chan_array[pchan_index++] = pchan;
|
||||
}
|
||||
|
||||
pose_pchan_index_create(pose);
|
||||
}
|
||||
|
||||
void BKE_pose_eval_init_ik(struct Depsgraph *depsgraph,
|
||||
@@ -752,12 +759,44 @@ void BKE_pose_eval_flush(struct Depsgraph *depsgraph,
|
||||
pose->chan_array = NULL;
|
||||
}
|
||||
|
||||
void BKE_pose_eval_proxy_copy(struct Depsgraph *depsgraph, Object *ob)
|
||||
void BKE_pose_eval_proxy_pose_init(struct Depsgraph *depsgraph, Object *object)
|
||||
{
|
||||
BLI_assert(ID_IS_LINKED(ob) && ob->proxy_from != NULL);
|
||||
DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob);
|
||||
if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) {
|
||||
printf("Proxy copy error, lib Object: %s proxy Object: %s\n",
|
||||
ob->id.name + 2, ob->proxy_from->id.name + 2);
|
||||
}
|
||||
BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL);
|
||||
DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
|
||||
|
||||
pose_pchan_index_create(object->pose);
|
||||
}
|
||||
|
||||
void BKE_pose_eval_proxy_pose_done(struct Depsgraph *depsgraph, Object *object)
|
||||
{
|
||||
BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL);
|
||||
DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
|
||||
|
||||
bPose *pose = object->pose;
|
||||
BLI_assert(pose->chan_array != NULL);
|
||||
MEM_freeN(pose->chan_array);
|
||||
pose->chan_array = NULL;
|
||||
}
|
||||
|
||||
void BKE_pose_eval_proxy_copy_bone(
|
||||
struct Depsgraph *depsgraph,
|
||||
Object *object,
|
||||
int pchan_index)
|
||||
{
|
||||
BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL);
|
||||
DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
|
||||
bPoseChannel *pchan = pose_pchan_get_indexed(object, pchan_index);
|
||||
/* TODO(sergey): Use indexec lookup, once it's guaranteed to be kept
|
||||
* around for the time while proxies are evaluating.
|
||||
*/
|
||||
#if 0
|
||||
bPoseChannel *pchan_from = pose_pchan_get_indexed(
|
||||
object->proxy_from, pchan_index);
|
||||
#else
|
||||
bPoseChannel *pchan_from = BKE_pose_channel_find_name(
|
||||
object->proxy_from->pose, pchan->name);
|
||||
#endif
|
||||
BLI_assert(pchan != NULL);
|
||||
BLI_assert(pchan_from != NULL);
|
||||
BKE_pose_copyesult_pchan_result(pchan, pchan_from);
|
||||
}
|
||||
|
||||
@@ -314,12 +314,13 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object)
|
||||
}
|
||||
op_node = add_operation_node(&object->id,
|
||||
DEG_NODE_TYPE_EVAL_POSE,
|
||||
function_bind(BKE_pose_eval_proxy_copy,
|
||||
function_bind(BKE_pose_eval_proxy_pose_init,
|
||||
_1,
|
||||
object_cow),
|
||||
DEG_OPCODE_POSE_INIT);
|
||||
op_node->set_as_entry();
|
||||
|
||||
int pchan_index = 0;
|
||||
LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
|
||||
op_node = add_operation_node(&object->id,
|
||||
DEG_NODE_TYPE_BONE,
|
||||
@@ -334,10 +335,14 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object)
|
||||
NULL,
|
||||
DEG_OPCODE_BONE_READY);
|
||||
/* Bone is fully evaluated. */
|
||||
op_node = add_operation_node(&object->id,
|
||||
op_node = add_operation_node(
|
||||
&object->id,
|
||||
DEG_NODE_TYPE_BONE,
|
||||
pchan->name,
|
||||
NULL,
|
||||
function_bind(BKE_pose_eval_proxy_copy_bone,
|
||||
_1,
|
||||
object_cow,
|
||||
pchan_index),
|
||||
DEG_OPCODE_BONE_DONE);
|
||||
op_node->set_as_exit();
|
||||
|
||||
@@ -349,10 +354,14 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object)
|
||||
DEG_OPCODE_PARAMETERS_EVAL,
|
||||
pchan->name);
|
||||
}
|
||||
|
||||
pchan_index++;
|
||||
}
|
||||
op_node = add_operation_node(&object->id,
|
||||
DEG_NODE_TYPE_EVAL_POSE,
|
||||
NULL,
|
||||
function_bind(BKE_pose_eval_proxy_pose_done,
|
||||
_1,
|
||||
object_cow),
|
||||
DEG_OPCODE_POSE_DONE);
|
||||
op_node->set_as_exit();
|
||||
}
|
||||
|
||||
@@ -587,10 +587,6 @@ void DepsgraphRelationBuilder::build_object(Base *base, Object *object)
|
||||
/* Proxy object to copy from. */
|
||||
if (object->proxy_from != NULL) {
|
||||
build_object(NULL, object->proxy_from);
|
||||
ComponentKey ob_pose_key(&object->proxy_from->id, DEG_NODE_TYPE_EVAL_POSE);
|
||||
ComponentKey proxy_pose_key(&object->id, DEG_NODE_TYPE_EVAL_POSE);
|
||||
add_relation(ob_pose_key, proxy_pose_key, "Proxy Pose");
|
||||
|
||||
ComponentKey ob_transform_key(&object->proxy_from->id, DEG_NODE_TYPE_TRANSFORM);
|
||||
ComponentKey proxy_transform_key(&object->id, DEG_NODE_TYPE_TRANSFORM);
|
||||
add_relation(ob_transform_key, proxy_transform_key, "Proxy Transform");
|
||||
|
||||
@@ -469,11 +469,20 @@ void DepsgraphRelationBuilder::build_proxy_rig(Object *object)
|
||||
DEG_NODE_TYPE_BONE,
|
||||
pchan->name,
|
||||
DEG_OPCODE_BONE_DONE);
|
||||
OperationKey from_bone_done_key(&proxy_from->id,
|
||||
DEG_NODE_TYPE_BONE,
|
||||
pchan->name,
|
||||
DEG_OPCODE_BONE_DONE);
|
||||
add_relation(pose_init_key, bone_local_key, "Pose Init -> Bone Local");
|
||||
add_relation(bone_local_key, bone_ready_key, "Local -> Ready");
|
||||
add_relation(bone_ready_key, bone_done_key, "Ready -> Done");
|
||||
add_relation(bone_done_key, pose_done_key, "Bone Done -> Pose Done");
|
||||
|
||||
/* Make sure bone in the proxy is not done before it's FROM is done. */
|
||||
add_relation(from_bone_done_key,
|
||||
bone_done_key,
|
||||
"From Bone Done -> Pose Done");
|
||||
|
||||
if (pchan->prop != NULL) {
|
||||
OperationKey bone_parameters(&object->id,
|
||||
DEG_NODE_TYPE_PARAMETERS,
|
||||
|
||||
Reference in New Issue
Block a user