Architect: Implement dedicated editor simulation controller, advanced rendering layers, and shared runtime schedule synchronization

This commit is contained in:
2026-04-28 03:28:55 +02:00
parent 0df775fea4
commit 07e6d4af7f
5 changed files with 130 additions and 11 deletions

View File

@@ -35,6 +35,12 @@ Broadly implemented already:
- scheduler/notebook foundation with authored routines over global time
- scheduler-driven NPC presence, path-following, and animation triggering
- first dialogue foundations with runtime dialogue overlay and dialogue-start interaction links
- dedicated editor simulation controller for editor-time playback
- incremental viewport simulation sync using base-scene and frame updates
- richer Player Start input authoring for keyboard, mouse, and gamepad
- Player Start interaction reach/angle and gameplay targeting-related input settings
- advanced rendering layer/category separation for AO-world, post-AO transparent, and overlay visuals
- viewport time transport controls for editor project-time playback
Important consequence:
@@ -81,6 +87,7 @@ Treat current box-brush structures as the starting point for whitebox solids unl
- local authored lights stay in typed entities
- project save/load and runner export are separate concerns
- project time is global, not per scene
- editor project-time playback is driven by a dedicated simulation controller rather than per-frame React clock state
- project-global day/night, control-surface, and scheduler/notebook foundations already exist and should be extended rather than reinvented
- scheduler/notebook work should sit on top of a shared control surface, not a growing pile of one-off scheduler-only effect types
- when a new capability is added that is meaningfully steerable over time, prefer making it control-surface-addressable and scheduler-available instead of adding isolated time fields

View File

@@ -263,6 +263,7 @@ Properties:
- disposable
- optimized for interaction and visualization
- may include helpers, overlays, and selection visuals
- may also host a derived editor-time simulation view that stays separate from canonical document state
Contains:
- preview meshes
@@ -291,6 +292,7 @@ Contains:
- animation mixers
- audio emitters
- navigation/controller systems
- runtime schedule/control resolution state
These three representations must remain conceptually separate.
@@ -557,6 +559,8 @@ Responsibilities:
- manage editor cameras and view modes
- render helper visuals
- support high-frequency tool feedback
- host incremental editor-time simulation presentation for project-time playback
- keep editor overlays and excluded visuals separate from AO/post-effect world rendering
Suggested internal subsystems:
@@ -573,8 +577,8 @@ Suggested internal subsystems:
Target minimum by milestone:
- perspective in early slices
- top/front/side orthographic views when the viewport-layout slice lands
- perspective views
- top/front/side orthographic views
---
@@ -592,6 +596,7 @@ Responsibilities:
- play animations
- manage audio
- expose embeddable runtime APIs
- keep runtime ticking and schedule/control synchronization imperative and outside React
### Major subsystems
@@ -603,6 +608,7 @@ Responsibilities:
- `AudioSystem`
- `AnimationSystem`
- `RuntimeUIBridge`
- shared runtime schedule-sync helpers reused by runner and editor simulation
### Collision strategy progression
@@ -996,6 +1002,7 @@ Recommended separation:
- search queries
- dialog state
- viewport mode/layout
- coarse editor simulation UI snapshots such as play/pause and visible clock readout
### Ephemeral viewport state
@@ -1015,6 +1022,7 @@ Recommended separation:
- active dialogue overlay state
- resolved scheduler/control state
- transient sequence/scheduler impulse state
- editor simulation controller snapshots and frame versions
Keep ephemeral rendering and interaction state out of the serialized document.
@@ -1238,11 +1246,18 @@ interface InteractionLink {
trigger: "enter" | "exit" | "click";
action:
| { type: "teleportPlayer"; targetEntityId: string }
| { type: "toggleVisibility"; targetId: string; visible?: boolean }
| { type: "playAnimation"; targetModelInstanceId: string; clipName: string }
| { type: "stopAnimation"; targetModelInstanceId: string; clipName?: string }
| { type: "playSound"; targetEntityId: string }
| { type: "stopSound"; targetEntityId: string };
| { type: "toggleVisibility"; targetBrushId: string; visible?: boolean }
| {
type: "playAnimation";
targetModelInstanceId: string;
clipName: string;
loop?: boolean;
}
| { type: "stopAnimation"; targetModelInstanceId: string }
| { type: "playSound"; targetSoundEmitterId: string }
| { type: "stopSound"; targetSoundEmitterId: string }
| { type: "runSequence"; sequenceId: string }
| { type: "control"; effect: ControlEffect };
}
```
@@ -1250,7 +1265,57 @@ Rules:
- trigger kinds are only valid for compatible entity types
- keep link validation explicit
- do not activate sound or animation actions before those systems exist
- prefer reusable control-surface effects for newly schedulable or steerable runtime behavior instead of inventing one-off action families
---
## Editor simulation and runtime schedule sync
Editor project-time playback should follow the same broad runtime direction as the runner:
- imperative ticking owned by a dedicated controller or host
- canonical document state remains unchanged
- derived runtime/editor simulation state is rebuilt only when document/assets materially change
- schedule and control resolution advance against a live clock without routing every frame through React
Current direction:
- the runner owns ticking inside `RuntimeHost`
- the editor owns ticking inside a dedicated `EditorSimulationController`
- both rely on shared runtime schedule-sync helpers to resolve NPC presence/path/animation and control-surface effects against the current clock
This is important because editor-time playback must not regress into:
- per-frame React state updates for the clock
- per-frame document-scale runtime scene rebuilds
- per-frame viewport-side rebuilds of simulation memberships when only time changed
Shared schedule-sync helpers are the correct seam for keeping runner and editor simulation aligned while still allowing each host to own its own render/update loop.
---
## Advanced rendering layers
Advanced rendering now depends on explicit render categories/layers rather than assuming one monolithic scene pass.
Current categories:
- `ao-world`
- `post-ao-transparent`
- `overlay`
Direction:
- AO-eligible opaque world geometry belongs in the AO/world path
- transparent or post-AO visuals render in the post-AO transparent path
- helpers, gizmos, and explicit overlay visuals render in the overlay path
This separation matters for:
- ambient occlusion correctness
- future screen-space effects
- editor helper readability
- keeping viewport overlays out of world-space post effects
---

View File

@@ -32,6 +32,24 @@ If a roadmap item is too large for one implementation pass, split it into smalle
---
## Recently landed foundations
The roadmap below still contains a lot of historical milestone context. Recent code has already moved some foundational areas forward materially.
Examples already present in the repo:
- dedicated editor simulation playback via `EditorSimulationController`
- incremental viewport simulation sync using base-scene and frame updates instead of document-scale rebuilds every clock tick
- shared runtime schedule synchronization helpers reused by runner and editor simulation
- richer Player Start input authoring for keyboard, mouse, and gamepad
- Player Start interaction reach/angle and targeting-related input settings
- viewport time transport controls for editor project-time playback
- advanced rendering layer/category separation for AO-world, post-AO transparent, and overlay visuals
When roadmap wording below sounds more primitive than the current code, trust the code and treat the older roadmap text as historical context.
---
## Product north star
A browser-based engine/editor with a built-in runner, enabling users to quickly create and share lightweight interactive 3D spaces with:
@@ -629,6 +647,7 @@ The time/living-world direction should stay closer to Majora's Mask than to a fu
- deterministic resolution from time + flags + scene context
- unloaded scenes reconstructed on demand instead of fully simulated all the time
- authored day/night came before the current scheduler/notebook foundation; next work should build on that shared time/control path rather than add one-off per-system timers
- runner and editor simulation now already share a dedicated runtime schedule-sync direction; future time slices should extend that path instead of reintroducing document-scale rebuilds or React-driven per-frame clocks
### Candidate slices

View File

@@ -3061,6 +3061,24 @@ export function App({ store, initialStatusMessage }: AppProps) {
editorState.document.world.advancedRendering.ambientOcclusion.samples
)
);
const [
advancedRenderingDynamicGlobalIlluminationIntensityDraft,
setAdvancedRenderingDynamicGlobalIlluminationIntensityDraft
] = useState(
String(
editorState.document.world.advancedRendering.dynamicGlobalIllumination
.intensity
)
);
const [
advancedRenderingDynamicGlobalIlluminationRadiusDraft,
setAdvancedRenderingDynamicGlobalIlluminationRadiusDraft
] = useState(
String(
editorState.document.world.advancedRendering.dynamicGlobalIllumination
.radius
)
);
const [
advancedRenderingBloomIntensityDraft,
setAdvancedRenderingBloomIntensityDraft
@@ -4127,6 +4145,12 @@ export function App({ store, initialStatusMessage }: AppProps) {
setAdvancedRenderingAmbientOcclusionSamplesDraft(
String(advancedRendering.ambientOcclusion.samples)
);
setAdvancedRenderingDynamicGlobalIlluminationIntensityDraft(
String(advancedRendering.dynamicGlobalIllumination.intensity)
);
setAdvancedRenderingDynamicGlobalIlluminationRadiusDraft(
String(advancedRendering.dynamicGlobalIllumination.radius)
);
setAdvancedRenderingBloomIntensityDraft(
String(advancedRendering.bloom.intensity)
);

View File

@@ -48,9 +48,10 @@ Highest-priority confidence areas:
10. spatial audio and interaction basics
11. critical regressions caught in CI
12. project-time/day-phase determinism where time-driven runtime systems exist
13. control-surface effect resolution and execution across actor/entity/interaction/scene targets
14. scheduler/routine resolution from time + authored rules, and later from time + flags + scene context
15. dialogue library, dialogue start sources, and runtime dialogue overlay correctness
13. editor simulation controller and viewport simulation frame/base synchronization correctness
14. control-surface effect resolution and execution across actor/entity/interaction/scene targets
15. scheduler/routine resolution from time + authored rules, and later from time + flags + scene context
16. dialogue library, dialogue start sources, and runtime dialogue overlay correctness
---
@@ -261,6 +262,7 @@ Use for:
- browser API edge behavior
- audio unlock flows where practical
- pointer lock flows where practical
- viewport overlay transport controls and hold-to-repeat behavior where practical
Examples:
@@ -361,6 +363,8 @@ Manual QA is required for:
- transform ergonomics
- texture workflow speed
- runtime movement feel
- pointer lock and targeting feel
- editor project-time playback responsiveness
- browser UX polish
- spatial audio perception