Fix T51955: Changing Auto-IK length crashes Blender (with new-depsgraph)

New dependency graph is tacking root bone into account when building the graph.
This is required in order to get proper dependencies between bones. so we can
reliably use bones as targets from the same rig (and even indirect relations
via external objects). This forces us to tag relations for update when we change
root IK chain bone.

Since relations rebuild is not fully trivial operation, we only do it for
the new dependency graph. In the future it'll be nice to avoid whole graph
rebuild for such cases, but that's mentioned as a TODO.
This commit is contained in:
Sergey Sharybin 2017-07-05 17:52:42 +02:00
parent bdd814d87d
commit a7a5c20fbc
Notes: blender-bot 2023-02-14 10:54:29 +01:00
Referenced by issue #51955, Changing Auto-IK length crashes Blender (with new-depsgraph)
1 changed files with 32 additions and 7 deletions

View File

@ -771,34 +771,43 @@ int count_set_pose_transflags(int *out_mode, short around, Object *ob)
/* -------- Auto-IK ---------- */
/* adjust pose-channel's auto-ik chainlen */
static void pchan_autoik_adjust(bPoseChannel *pchan, short chainlen)
static bool pchan_autoik_adjust(bPoseChannel *pchan, short chainlen)
{
bConstraint *con;
bool changed = false;
/* don't bother to search if no valid constraints */
if ((pchan->constflag & (PCHAN_HAS_IK | PCHAN_HAS_TARGET)) == 0)
return;
if ((pchan->constflag & (PCHAN_HAS_IK | PCHAN_HAS_TARGET)) == 0) {
return changed;
}
/* check if pchan has ik-constraint */
for (con = pchan->constraints.first; con; con = con->next) {
if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce != 0.0f)) {
bKinematicConstraint *data = con->data;
/* only accept if a temporary one (for auto-ik) */
if (data->flag & CONSTRAINT_IK_TEMP) {
/* chainlen is new chainlen, but is limited by maximum chainlen */
if ((chainlen == 0) || (chainlen > data->max_rootbone))
const int old_rootbone = data->rootbone;
if ((chainlen == 0) || (chainlen > data->max_rootbone)) {
data->rootbone = data->max_rootbone;
else
}
else {
data->rootbone = chainlen;
}
changed |= (data->rootbone != old_rootbone);
}
}
}
return changed;
}
/* change the chain-length of auto-ik */
void transform_autoik_update(TransInfo *t, short mode)
{
const short old_len = t->settings->autoik_chainlen;
short *chainlen = &t->settings->autoik_chainlen;
bPoseChannel *pchan;
@ -812,13 +821,29 @@ void transform_autoik_update(TransInfo *t, short mode)
if (*chainlen > 0) (*chainlen)--;
}
/* IK length did not change, skip any updates. */
if (old_len == *chainlen) {
return;
}
/* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
if (ELEM(NULL, t->poseobj, t->poseobj->pose))
return;
/* apply to all pose-channels */
bool changed = false;
for (pchan = t->poseobj->pose->chanbase.first; pchan; pchan = pchan->next) {
pchan_autoik_adjust(pchan, *chainlen);
changed |= pchan_autoik_adjust(pchan, *chainlen);
}
#ifdef WITH_LEGACY_DEPSGRAPH
if (!DEG_depsgraph_use_legacy())
#endif
{
if (changed) {
/* TODO(sergey): Consider doing partial update only. */
DAG_relations_tag_update(G.main);
}
}
}