feat(core): declarative world-space objects + editor bridge object commands - #48
Merged
Conversation
…mmands
objects?: ObjectConfig[] — engine-managed 3D props in the main scene, the
world-space sibling of elements[]:
- Assets: parametric primitives (cube/sphere/torus/knot; standard material
with color/metalness/roughness, or unlit basic material) and GLB models by
URL. GLB roots are bbox-normalized at load (largest dimension = 1 world
unit) so transform.scale is asset-independent; per-instance cloned
materials. A gltf asset auto-detects the GLTFLoader addon — objects are
data, so keyword scanning of function strings can't see them.
- Transforms are raw world units (x/y/z, rx/ry/rz degrees, uniform scale);
apps map their own layout conventions onto world units before authoring.
- Each object becomes an ObjectInstance { config, root, props, dispose } in
an id-keyed Map exposed as ctx.objects and on the result. The props bag is
the animatable/editable surface: the render loop mirrors it onto the mesh
every frame (__syncObjects), so tweens targeting props and editor overrides
compose the same way element props do.
- Bridge protocol 3: SET_OBJECT_PROPS (ephemeral overrides, cleared by LOAD —
durable state stays in the config) and OBJECT_HIT_TEST (main-camera raycast,
nearest object id; child hits walk up to the registered root).
- Lighting stays the author's choice: standard materials expect lights from
createContent; unlit: true renders without any.
Fully additive: configs without objects compile byte-identically (pinned by
test); no config version bump needed. 135 tests pass (7 new).
…casts with it Real-browser verification of the objects bridge caught this: the editor api reads __current.camera for the object raycast, but the result only exposed overlayCamera — every OBJECT_HIT_TEST returned null while rendering worked perfectly. Expose camera alongside the other introspection handles and pin it in the codegen test. Verified end-to-end in headless Chrome against the built package: lit knot / unlit cube / GLB duck all render (pixel checks), hit-tests return the right ids (GLB child hits walk to the root), empty space misses, and SET_OBJECT_PROPS moves an object so the old spot misses and the new spot hits. 136 tests.
Member
Author
|
Real-browser verification (headless Chrome against the built package — compiled config booted through the editor render template):
This pass caught one real bug the unit tests couldn't: the editor api raycasts with |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
objects?: ObjectConfig[]— engine-managed 3D props in the main scene, the world-space sibling ofelements[].The capability
cube | sphere | torus | knot; standard material with color/metalness/roughness, orunlit: truefor a light-free basic material) and GLB models by URL — bbox-normalized at load sotransform.scaleis asset-independent, with per-instance cloned materials. A gltf asset auto-detects the GLTFLoader addon (objects are data — function-string keyword scanning can't see them).ObjectInstance { config, root, props, dispose }in an id-keyed Map exposed asctx.objectsand on the result. The props bag is the single animatable/editable surface — the render loop mirrors it onto the mesh every frame, so tweens targetingctx.objects.get(id).propsand editor overrides compose exactly like element props.createContent;unlitrenders without any.Bridge (protocol 2 → 3)
SET_OBJECT_PROPS { id, props }— ephemeral overrides for gesture-time preview; cleared by LOAD (durable state stays in the config).OBJECT_HIT_TEST { x, y, requestId }→OBJECT_HIT_RESULT { requestId, id | null }— a main-camera raycast; nearest hit wins (real 3D depth, unlike overlay elements), child hits walk up to the registered root.Compatibility
Fully additive: configs without
objectscompile byte-identically (pinned by test); no config version bump. 135 tests pass (7 new: codegen, unlit, GLTFLoader auto-detect + non-detect, context/result exposure, editor/non-editor bridge surface). Changeset: minor.