Fix #121378: Can't snap parent to children with Affect Only Parent activated
The flag that skips objects for snapping (`BA_SNAP_FIX_DEPS_FIASCO`) is set for all objects that have a `DEG_OB_COMP_TRANSFORM` relation. However, when the **Affect Only Parent** option is enabled, children are not transformed and therefore could still be snapped to. Despite this, the `DEG_OB_COMP_TRANSFORM` dependency remains present on them. To address this, a new callback was introduced that skips Transform-to-Transform dependencies while preserving Transform-to-Geometry dependencies in this scenario. This approach may introduce some false positives, leading to spurious dependency cycles (e.g., when constraints are involved). Nevertheless, the trade-off favors accepting these false positives rather than disabling the feature altogether. Also make non-functional change that just removes a flag before the snap loop, thus avoiding checking if the flag exists inside the loop. Ref !142007
This commit is contained in:
committed by
Campbell Barton
parent
1fa2be8a9b
commit
b42e4052b7
@@ -311,7 +311,18 @@ static void trans_object_base_deps_flag_prepare(const TransInfo *t,
|
||||
}
|
||||
}
|
||||
|
||||
static void set_trans_object_base_deps_flag_cb(ID *id, eDepsObjectComponentType component)
|
||||
static void tag_trans_objects_with_geometry_dep_only_fn(ID *id, eDepsObjectComponentType component)
|
||||
{
|
||||
/* Here we only handle object IDs. */
|
||||
if (GS(id->name) != ID_OB) {
|
||||
return;
|
||||
}
|
||||
if (component == DEG_OB_COMP_GEOMETRY) {
|
||||
id->tag |= ID_TAG_DOIT;
|
||||
}
|
||||
}
|
||||
|
||||
static void tag_trans_objects_dep_fn(ID *id, eDepsObjectComponentType component)
|
||||
{
|
||||
/* Here we only handle object IDs. */
|
||||
if (GS(id->name) != ID_OB) {
|
||||
@@ -329,11 +340,21 @@ static void flush_trans_object_base_deps_flag(const TransInfo *t, Object *object
|
||||
return;
|
||||
}
|
||||
object->id.tag |= ID_TAG_DOIT;
|
||||
DEG_foreach_dependent_ID_component(t->depsgraph,
|
||||
&object->id,
|
||||
DEG_OB_COMP_TRANSFORM,
|
||||
DEG_FOREACH_COMPONENT_IGNORE_TRANSFORM_SOLVERS,
|
||||
set_trans_object_base_deps_flag_cb);
|
||||
|
||||
DEG_foreach_dependent_ID_component(
|
||||
t->depsgraph,
|
||||
&object->id,
|
||||
DEG_OB_COMP_TRANSFORM,
|
||||
DEG_FOREACH_COMPONENT_IGNORE_TRANSFORM_SOLVERS,
|
||||
|
||||
/* When we transform parents while skipping children, we only traverse the GEOMETRY-dependent
|
||||
* components. This avoids marking children as not participating in snapping but still marks
|
||||
* objects with modifier dependencies.
|
||||
* Unfortunately, some transform-dependent objects that are not children may also be skipped,
|
||||
* such as constrained ones.
|
||||
* See #121378 for details. */
|
||||
(t->options & CTX_OBMODE_XFORM_SKIP_CHILDREN) ? tag_trans_objects_with_geometry_dep_only_fn :
|
||||
tag_trans_objects_dep_fn);
|
||||
}
|
||||
|
||||
static void trans_object_base_deps_flag_finish(const TransInfo *t,
|
||||
@@ -690,6 +711,7 @@ static void createTransObject(bContext *C, TransInfo *t)
|
||||
tdo->xcs, ob, ob_parent_recurse, object::XFORM_OB_SKIP_CHILD_PARENT_APPLY);
|
||||
BLI_ghash_insert(objects_parent_root, ob, ob_parent_recurse);
|
||||
base->flag_legacy |= BA_TRANSFORM_LOCKED_IN_PLACE;
|
||||
base->flag_legacy &= ~BA_SNAP_FIX_DEPS_FIASCO;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -711,6 +733,7 @@ static void createTransObject(bContext *C, TransInfo *t)
|
||||
object::object_xform_skip_child_container_item_ensure(
|
||||
tdo->xcs, ob, nullptr, object::XFORM_OB_SKIP_CHILD_PARENT_IS_XFORM);
|
||||
base->flag_legacy |= BA_TRANSFORM_LOCKED_IN_PLACE;
|
||||
base->flag_legacy &= ~BA_SNAP_FIX_DEPS_FIASCO;
|
||||
}
|
||||
else {
|
||||
Object *ob_parent_recurse = static_cast<Object *>(
|
||||
|
||||
@@ -409,9 +409,7 @@ static bool snap_object_is_snappable(const SnapObjectContext *sctx,
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((snap_target_select == SCE_SNAP_TARGET_ALL) ||
|
||||
(base->flag_legacy & BA_TRANSFORM_LOCKED_IN_PLACE))
|
||||
{
|
||||
if (snap_target_select == SCE_SNAP_TARGET_ALL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user