[Feature] Add UntoldViewOptions for runtime view settings in SwiftUI - #17
Merged
Conversation
…dinator PR B of the physics plugin readiness plan (discussion untoldengine#1116), built on the EngineExtension infrastructure from untoldengine#1127 instead of a custom runFrame seam: - PhysicsCoordinator (EngineExtension) steps the installed backend once per fixed substep: body-set diffing against the RigidBodyComponent + ColliderComponent query, batch kinematic writes, step, batch transform read-back into LocalTransformComponent, event drain into an inert sink (subscriptions arrive in the events PR). - PhysicsBackendRegistry schedules/unschedules the coordinator in EngineExtensionRegistry on install/uninstall and locks for runtime on the first simulated substep. - Gravity for the built-in integrator now reads from the global PhysicsWorldConfiguration (default unchanged at (0, -9.8, 0)), so legacy and backend-owned bodies share one gravity. With no backend installed nothing is scheduled and behavior is unchanged; the built-in integrator keeps running legacy entities either way.
[Chores] Formatted files [Patch] Fixed the guassian-mesh occlusion [Patch] Improved API function call
Replace the nine open-coded per-mesh vertex buffer bind sites in the model-family and shadow-family passes with bindModelVertexStreams / bindShadowVertexStreams encoder helpers. Batched-geometry sites keep their raw batch-buffer binds. Also add a reader regression test covering unknown core-range chunk types so future format chunks cannot brick older runtimes. Groundwork for the deformation compute pass: the helpers are the single point where deformed position/normal buffers will replace the base streams.
Adds a runtime-tunable options struct for the SwiftUI host view, per the UntoldViewOptions proposal (docs/proposals/UntoldViewOptions.md): - UntoldViewOptions (Equatable, Sendable): preferredFramesPerSecond, isPaused, clearColor. Settable via UntoldView(renderer:options:) or the .preferredFramesPerSecond(_:)/.paused(_:)/.options(_:) modifiers. - SceneView's Coordinator now owns the renderer: a fallback renderer is created exactly once instead of on every SwiftUI body re-evaluation, and options are diffed against the last-applied copy so only changed properties touch the live MTKView. The renderer is never recreated. - UntoldView builds its scene content once, when the platform view is created (after the renderer exists, so mesh loading has a Metal device), instead of on every re-evaluation of the view struct. - SceneView.onInit is deferred accordingly: the block now runs once when the platform view is created rather than immediately at body-eval time on every re-evaluation. UntoldRendererConfig stays immutable, create-time only.
miogds
force-pushed
the
feature/untoldview_options
branch
from
August 6, 2026 17:53
e83234a to
9ce94c7
Compare
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.
Implements the
UntoldViewOptionsproposal (doc included in this PR atdocs/proposals/UntoldViewOptions.md), as agreed with Harold:UntoldRendererConfigstays immutable/create-time; runtime view-host settings get their own smallEquatablestruct that is diff-applied to the liveMTKViewwithout ever recreating the renderer.What's in here
UntoldViewOptions—Equatable, Sendablestruct withpreferredFramesPerSecond,isPaused,clearColor. Usable two ways:When a bound SwiftUI value changes, the body re-evaluates,
updateNSView/updateUIViewruns, and the coordinator applies only the properties that differ from the last-applied options. Unrelated re-evaluations cost oneEquatablecompare.Stable renderer ownership (the prerequisite from the proposal) —
SceneView'sCoordinatornow owns the renderer. Previously bothUntoldView.initandSceneView.initranrenderer ?? UntoldRenderer.create()on every SwiftUI re-evaluation. Now the injected renderer is adopted (or a fallback created) exactly once, on firstmakeNSView/makeUIView, and never swapped.Scene content built once —
UntoldViewstores the@SceneBuilderclosure and runs it a single time when the platform view is created, after the renderer exists (sosetEntityMeshAsynchas a Metal device). Previously the builder re-ran on every re-evaluation — in the SceneBuilder demo that meant new entities + mesh reloads every timer tick.SceneView.onInitsemantic change (intentional, please review) — the block used to execute immediately at body-evaluation time, on every re-evaluation, and required the renderer to already exist. It now runs exactly once, when the platform view is created and the renderer is ready. Signature also gained@MainActoron the block. This is what makesSceneView().onInit { ... }with a nil renderer actually safe.Not included (follow-ups per the proposal)
renderScale(needs care:create()pinscontentsScale = 1.0)drawsOnDemand(enableSetNeedsDisplaymode)Testing
swift buildclean for the engine, demos, and Sandbox (allSceneView(renderer:)call sites unchanged — new params are defaulted).UntoldViewOptionsTests(7 tests): struct semantics, modifier copy-on-write, first-apply sets everything, diff-apply leaves unchanged properties untouched, equal options are a no-op. All pass, plus existingSceneBuilderNodeTests.swiftformat --lintclean on changed files (local 0.62.1; CI's pinned 0.60.1 will confirm).