You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Replace the rerender event bus with direct ObjectsManager calls (#311)
* Manage the preview's rerender using events
* Cleanups
* POC: toggle extrusions and travel moves without re-rendering everyting
* Add unit tests for EventsDispatcher and ObjectsManager classes
Tests cover event registration/emission, visibility toggles,
rendering methods, disposal, and clipping plane updates.
* Replace the rerender event bus with direct ObjectsManager calls
Property changes were routed through a string-keyed dispatcher into one
debounced full rebuild. Nothing outside the library listened to any of
them, so 21 of the 23 SceneManagerEvent members existed only to say
"call a method on my own collaborator".
Setters now call the ObjectsManager, which decides how to react:
visibility flips group.visible, colors and lighting mutate material
uniforms, layer ranges move clipping planes, and only the dimension
properties discard geometry and ask for a redraw.
SceneManagerEvent keeps the two real notifications, animationComplete
and frameRendered.
Fixes found along the way:
- clipping planes were built from lineWidth/lineHeight instead of the
layer range, and never applied to materials created later
- every rerender added an empty LineSegments2 and leaked its material
- tube materials were pushed once per progressive frame rather than
cached per tool
- renderPathIndex indexes job.paths but was slicing job.travels, so
re-enabling travels after a completed render drew nothing
- clear() left the old ObjectsManager in disposables, double-disposing
* Hold the new code at 100% coverage
Coverage was not measurable: no provider was installed. Adds
@vitest/coverage-v8, an npm run coverage script, and 100% thresholds
scoped to objects-manager, scene-manager and events-dispatcher.
scene-manager sat at 23% because a real instance needs WebGL. Stubbing
only WebGLRenderer and OrbitControls lets the tests build a genuine
SceneManager and assert on actual scene state -- object identity across
toggles, material uniforms, group visibility -- rather than on spies.
* Stop tracking the workspace .context scratch directory
It was swept in by a git add -A during the develop merge. It holds
agent scratch files, not project files.
* Remove EventsDispatcher entirely
The string-keyed bus is gone along with its last four events. Each
consumer now gets a typed callback instead:
- SceneManager.onFrameRendered replaces frameRendered
- GCodePreview.onJobUpdated replaces jobUpdated
- GCodePreview.onStreamEnd replaces streamReadEnd
- animationComplete is dropped; renderAnimated already returns a promise
that resolves at the same moment
Interpreter no longer takes a dispatcher at all. GCodePreview owns the
execute() calls, so it announces job updates itself.
This removes the public addEventListener API along with EventName and
EventNameType. The demo assigns the callbacks directly.
Also drops a stray console.log(this.eventsDispatcher) from Interpreter.
* Pack line vertices into a pre-sized Float32Array
renderPathsAsLines grew a plain array one push at a time and handed it to
setPositions, which then copied the whole thing into a Float32Array.
Counting segments first and filling the typed array in place skips both
the repeated growth and the conversion. On a 7023 path model that is
652818 floats: 3.1ms -> 0.5ms, and about 5 MB of transient boxed doubles
never allocated. Output is byte for byte identical.
* Cover the remaining scene-manager branches after the merge
Adds tests for rendering without a build volume, a rebuild request firing
after clear, and construction without a build volume, keeping the
scene-manager.ts coverage gate at 100%.
* Reconcile the rebase with develop's newer work
Rebasing onto develop dropped the two merge commits, and with them the
manual resolutions they carried. This restores that work:
- scene-manager-properties gets back the orthographic camera coverage
added while merging develop's camera feature
- renderer-smoke looks up the Extrusions group again
- the scene-manager suite stays branch-side, as the old-architecture
suite tests render paths that now live in ObjectsManager
- the demo drops the unused drawBoundingBox ref
It also adopts what develop gained since the last sync: the
fallbackExtrusionColor guard stays in renderPaths (a tool index past
the configured colors warns once and falls back instead of drawing
with undefined), and its tests are ported to the new-architecture
suite in scene-manager-properties.
* Fix the three review blockers in the ObjectsManager rework
- createColorMaterial returns a fresh ShaderMaterial instead of a
module-global color-keyed cache. The cache made tools with the same
starting color share one instance, so recoloring tool 0 repainted
every alias, and a disposed material could be resurrected by the next
manager with stale uniforms. ObjectsManager already caches per tool,
which is the granularity the mutate-in-place design needs.
- clear() carries renderTubes, ambientLight, directionalLight and
brightness into the replacement manager. It only carried the
dimensions, so loading a second file silently reverted tube rendering
and lighting to defaults.
- updateClippingPlanes computes an unset start layer as undefined
instead of NaN. startLayer?.z - startLayer?.height is NaN when unset,
which passed the !== undefined guards and baked NaN plane constants
and clip uniforms into every material by default — NaN comparisons
are undefined behavior in GLSL, so strict mobile drivers could
discard everything. An open bound now stays -Infinity/Infinity.
* Address the review's should-fix findings
- A scalar extrusionColor now recolors every tool: setExtrusionColor
without a tool index repaints all tube materials and all extrusion
lines. Previously the setter defaulted to tool 0, so tools >= 1 kept
their old color until an unrelated geometry rebuild. A color array
shorter than the tool count likewise repaints the extra tools with
the fallback color instead of leaving them stale.
- The constructor no longer calls initGui() directly. The devMode
setter two lines above already creates the GUI, so devMode previews
got two DevGUI instances and the first was never destroyed.
- processGCode returns the renderAnimated() promise and
processGCodeStream awaits it, so callers can observe the moment the
model is fully drawn. That promise is the documented replacement for
the old animationComplete event, but neither entry point propagated
it.
- Job and SceneManagerOptions are exported from the entry point (the
onJobUpdated callback takes a Job, which consumers could not name),
and the three callback properties document their single-listener
contract.
* Export SceneManagerOptions as a type
It is type-only, so re-exporting it as a value fails rollup's build.
* Restore develop's formatting in the demo page
The page had been fully rewrapped by an editor, drowning the PR's three
real changes in whitespace noise. This rebuilds the file from develop's
version with only those changes: the bounding box toggle binds to
settings.drawBoundingBox, the dev mode widget is added, and the canvas
drops its binding to the removed update handler.
* Hold objects-manager.ts at 100% coverage
Adds the file to the vitest thresholds now that its last four defensive
branches are exercised: uniform-less materials in the all-tools recolor
and lighting paths, non-line children in the travel group, and an
open-ended layer range resetting the clip uniforms to infinities.
* Leave the layer range unclipped at the ends of the stack
A clipping bound that sits at the very end of the layer stack is no
restriction at all, yet it still planted a plane exactly at the top
extrusion layer. Travel moves routinely rise above that layer — a final
park move, a wipe — so a preview with endLayer set to the layer count
(what the demo does by default) silently hid them (#278).
updateClippingPlanes now only bounds a side whose layer is strictly
inside the stack: startLayer 1 and endLayer == countLayers produce no
plane on their side. A genuinely restricted range still clips travel
and extrusion lines alike, which is why the selective-clipping TODO in
updateLineClipping is retired rather than implemented: hiding travels
outside a restricted range is intended, and with no planes in the
unrestricted case there is nothing left to exempt travels from.
Fixes#278
0 commit comments