Compare commits

...

1 Commits

Author SHA1 Message Date
forbes
f6fa2f0d2c fix(editing-context): trust parentId chain without re-checking ancestor match()
Parent match() functions are designed for flat priority resolution and
may not return true when a more specific child is active (e.g.
assembly.idle checks getActivePartObject() which may not return the
assembly during edit mode). The parentId declaration is the author's
assertion of structural containment — the leaf already matched, so
we walk the full chain unconditionally.
2026-03-04 16:16:05 -06:00

View File

@@ -660,7 +660,13 @@ QString EditingContextResolver::expandLabel(const ContextDefinition& def) const
void EditingContextResolver::buildStack(EditingContext& ctx,
const ContextDefinition& leaf) const
{
// Walk from leaf up through parentId chain, verifying each ancestor matches
// Walk from leaf up through parentId chain.
// We trust the parentId declarations — the leaf already matched, and the
// hierarchy is the addon author's assertion of structural containment.
// Parent match() functions are designed for flat priority resolution and
// may not return true when a more specific child is active (e.g.
// assembly.idle won't match during assembly.edit because the "part"
// active object changes during edit mode).
QStringList reverseStack;
reverseStack.append(leaf.id);
@@ -675,15 +681,8 @@ void EditingContextResolver::buildStack(EditingContext& ctx,
reverseStack.last().toUtf8().constData());
break;
}
// Only include parent if it matches current state
if (parentDef->match && parentDef->match()) {
reverseStack.append(parentDef->id);
currentParent = parentDef->parentId;
}
else {
// Parent doesn't match — stop climbing (partial stack)
break;
}
reverseStack.append(parentDef->id);
currentParent = parentDef->parentId;
}
// Reverse to get root-to-leaf order