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:
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)
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue