Skip to content

feat(codegen): SceneSerializer blocks for AssetHandle/UUID-field components (#451) - #467

Merged
drsnuggles8 merged 1 commit into
masterfrom
feature/codegen-serializer-assethandle
Jun 29, 2026
Merged

drsnuggles8 merged 1 commit into
masterfrom
feature/codegen-serializer-assethandle

Conversation

@drsnuggles8

@drsnuggles8 drsnuggles8 commented Jun 29, 2026 •

Copy link
Copy Markdown
Owner

What

First slice of #451 — OloHeaderTool's scene-serializer codegen now recognizes AssetHandle/UUID (a u64 wrapper) as a trivial-ish field type, so a component whose only non-primitive fields are asset handles / entity-reference UUIDs is fully auto-generated instead of needing a hand-written SceneSerializer.cpp block. This closes the single most pervasive instance of the "forgot the handle block → silent scene-data loss" footgun (#451 lists AssetHandle/UUID as "pervasive: materials, meshes, colliders, dialogue, streaming, …").

Follow-up to #380 / #450 (which generated blocks for all-primitive components).

How

  • New PropType::AssetHandle; SceneSerType maps AssetHandle/UUID → it.
  • Serialize emits static_cast<u64>(comp.field); deserialize emits field = node["K"].as<u64>(static_cast<u64>(field)), bridging the implicit UUID(u64) ctor. Format-identical to every existing hand-written handle block (verified against EncodeUUID and the emitter's implicit operator u64()) — no scene-file format change.

Migration & exclusions

Of the 5 components that newly classify as trivial:

  • UIWorldAnchorComponent (UUID + glm::vec3) — clean round-trip; hand-written blocks deleted, now fully generated.
  • DialogueComponent / IKTargetComponent / PerceptionComponent — kept hand-written (added to kComponentsCustomSerialize): they have Sanitize*/clamp deserialize logic the plain round-trip would drop.
  • IDComponent — kept hand-written/excluded: it's entity identity, serialized as the top-level Entity: <uuid> line. Auto-generating it would emit a bogus sub-map and call AddComponent<IDComponent> on an entity that already has one (EnTT double-add). Neither coverage test catches this (existence skips kRuntimeOnly, disjointness only catches hand-written double-emits) — manual exclusion is the only guard. Documented in the generator comment + CLAUDE.md.

Out of scope (remaining #451 follow-up slices)

enums, std::vector / map / set, nested structs, Ref<T>, glm::quat/mat/ivec.

Testing

  • OloEngine-Tests builds (MSVC Debug, exit 0) — the generated AssetHandle/UUID C++ compiles + links.
  • ComponentSerializerCoverage.* (existence + inverse + disjointness) — 3/3 pass.
  • ComponentRoundTrip.* — 69/69 pass; UIWorldAnchorComponentSurvivesYAMLRoundTrip now exercises the generated UUID path end-to-end (sets a distinctive m_TargetEntity, asserts it survives).
  • Tuple / handler / save-game codegen meta-tests, Lua binding, and 52 fuzz/prefab serializer tests — all green.

Part of #451 (first slice; does not close the epic).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Improved scene save/load handling for generated components that use asset or UUID-style references.
    • Fixed several components so they’re handled correctly during serialization instead of relying on inconsistent manual paths.
  • Documentation

    • Updated guidance for generated component serialization rules and the cases that still require manual handling.
    • Clarified round-trip expectations with a test note for generated UUID/asset-handle fields.

…ield components (#451)

OloHeaderTool's scene-serializer codegen now recognizes AssetHandle/UUID (a u64
wrapper) as a trivial-ish field type, so a component whose only non-primitive
fields are asset handles / entity-reference UUIDs is fully auto-generated instead
of needing a hand-written serializer block — closing the most pervasive instance
of the "forgot the handle block -> silent scene-data loss" footgun. First #451
slice; enums / vector / map / nested struct / Ref<T> remain follow-up slices.

- SceneSerType maps AssetHandle/UUID to a new PropType::AssetHandle. Serialize
  emits static_cast<u64>; deserialize reads .as<u64>(static_cast<u64>(...)) and
  bridges back via the implicit UUID(u64) ctor — format-identical to every
  existing hand-written handle block.
- UIWorldAnchorComponent (UUID m_TargetEntity + glm::vec3) is now fully generated;
  its hand-written serialize/deserialize blocks were removed from SceneSerializer.cpp.
- DialogueComponent / IKTargetComponent / PerceptionComponent / IDComponent newly
  classify as trivial but are kept hand-written via kComponentsCustomSerialize: the
  first three have Sanitize/clamp deserialize logic; IDComponent is entity identity
  (its UUID is the top-level "Entity:" line, re-applied via CreateEntityWithUUID),
  which auto-gen would turn into a bogus sub-map + a double-AddComponent on load.
  Neither coverage test catches that case, so the exclusion is the only guard.

Verified: OloEngine-Tests builds (MSVC Debug, exit 0); ComponentSerializerCoverage
existence + disjointness pass; ComponentRoundTrip.UIWorldAnchorComponent exercises
the generated UUID path; tuple/handler/save-game meta-tests and fuzz/prefab
serializer tests green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 29, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

OloHeaderTool gains a PropType::AssetHandle variant that maps AssetHandle/UUID types to u64-based YAML emit/parse in generated serialize and deserialize blocks. kComponentsCustomSerialize is expanded with DialogueComponent, IDComponent, IKTargetComponent, and PerceptionComponent. Hand-written UIWorldAnchorComponent serialization is removed from SceneSerializer.cpp in favor of the generated .inl includes. CLAUDE.md and test comments are updated accordingly.

Changes

AssetHandle codegen and UIWorldAnchorComponent migration

Layer / File(s) Summary
PropType::AssetHandle classification and SceneSerType mapping
tools/OloHeaderTool/main.cpp
PropType enum gains an AssetHandle variant. SceneSerType maps the type strings AssetHandle and UUID to it. Surrounding comments updated to document the trivial-type criteria.
Emit serialize/deserialize blocks for AssetHandle fields
tools/OloHeaderTool/main.cpp
EmitSceneSerializeBlocks and EmitSceneDeserializeBlocks handle PropType::AssetHandle by emitting static_cast<u64>(...) casts for YAML write and UUID/AssetHandle constructor bridging on YAML read.
kComponentsCustomSerialize exclusion set expansion
tools/OloHeaderTool/main.cpp
Documentation block and set updated to add DialogueComponent, IDComponent, IKTargetComponent, and PerceptionComponent as explicit codegen exclusions, with rationale for IDComponent's non-sub-map persistence.
UIWorldAnchorComponent migrated to generated .inl blocks
OloEngine/src/OloEngine/Scene/SceneSerializer.cpp, OloEngine/tests/ComponentRoundTripTest.cpp
Hand-written serialize and deserialize blocks for UIWorldAnchorComponent removed; replaced with comments referencing SceneSerializeComponents.Generated.inl / SceneDeserializeComponents.Generated.inl. Test comment expanded to describe the auto-generated u64 round-trip behavior.
CLAUDE.md documentation updates
CLAUDE.md
Two lines updated to document AssetHandle/UUID as trivial auto-generated types and to expand kComponentsCustomSerialize exclusion rules with the IDComponent blind spot caveat.

Possibly related issues

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: codegen support for AssetHandle/UUID-field scene serialization blocks.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

coderabbitai[bot]

This comment was marked as resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant