refactor(animation): share property list between init and clone#8881
Conversation
Hoist the ordered property list to a module-level _properties array and build cloneComponent data from it, routing the clone through addComponent like every other component system instead of assigning properties after adding an empty component. This also means clone now applies properties in the documented init order (activate/enabled before assets) rather than assets-first. The difference is not observable: the auto-play gate in onSetAnimations requires entity.enabled, which is always false for the detached clone entity while cloneComponent runs, in both the old and new code paths. The loaded animations and animationsIndex dictionaries are still copied onto the clone after addComponent, as before. Also drops the unused legacy properties parameter from initializeComponentData. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Refactors AnimationComponentSystem to share a single ordered property list between initialization and cloning, ensuring clone-time property application follows the same documented order as initialization (notably assets last).
Changes:
- Hoists the ordered init/clone property list to a module-level
_propertiesarray. - Updates
initializeComponentDatato iterate_propertiesdirectly and drops the unused legacypropertiesparameter. - Refactors
cloneComponentto build an initdataobject from_propertiesand route cloning throughaddComponent, while preserving post-add cloning ofanimations/animationsIndex.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Address review feedback: avoid assigning the shared assets array reference into the clone data only to immediately overwrite it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
src/framework/components/animation/system.js:54
initializeComponentDataassignsenabled(as part of the ordered_propertiesloop) and then callssuper.initializeComponentData(component, data)without apropertiesargument. The base implementation will then setcomponent.enabled = data.enabledagain (when provided), firing a secondsetevent and also meaningassetsis no longer the last setter invoked despite the ordering requirement.
To keep the ordered setters authoritative, pass an empty properties list to the base initializer ([]) and treat explicit undefined as “not provided” (matching the base initializer semantics) so defaults aren’t clobbered.
initializeComponentData(component, data) {
for (const property of _properties) {
if (data.hasOwnProperty(property)) {
component[property] = data[property];
}
}
super.initializeComponentData(component, data);
}
Summary
Fourth PR in the component-consistency series (follows #8878, #8879, #8880). Animation got its own PR because its clone path was structured differently from every other system.
AnimationComponentSystem.cloneComponentpreviously added an empty component and then assigned properties onto it post-add — duplicating the property list and, notably, assigningassetsbeforeactivate/enabled, the opposite of the orderinitializeComponentDatadocuments as required ("assets needs to be last as it checks other properties to see if it should play").This PR:
_propertiesarray (with the ordering comment) and drives bothinitializeComponentDataandcloneComponentfrom it.addComponentlike every other system, so clone applies properties in the documented init order.addComponentcopying of the loadedanimations/animationsIndexdictionaries, and theassets.slice()so the clone doesn't share the source's array.propertiesparameter.On behavior: the ordering change (assets-first → assets-last) is provably unobservable. The auto-play gate in
onSetAnimationsrequiresthis.entity.enabled, andGraphNode#enabledreturns_enabled && _enabledInHierarchy— which is always false for the detached clone entity whilecloneComponentruns, in both the old and new code paths. Auto-play decisions happen later, when the clone is added to the hierarchy (onEnable), by which point all properties were copied in both versions.Testing
npm testsuite passes (1817 passing)Remaining PRs in the series
beforeremovehandler naming across all systems🤖 Generated with Claude Code