@codexo/exojs 0.8.0 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +390 -208
- package/README.md +19 -19
- package/dist/esm/animation/Easing.js +13 -21
- package/dist/esm/animation/Easing.js.map +1 -1
- package/dist/esm/animation/Tween.d.ts +3 -3
- package/dist/esm/animation/Tween.js +7 -5
- package/dist/esm/animation/Tween.js.map +1 -1
- package/dist/esm/animation/TweenManager.js +1 -1
- package/dist/esm/animation/TweenManager.js.map +1 -1
- package/dist/esm/animation/types.js.map +1 -1
- package/dist/esm/audio/AbstractMedia.d.ts +1 -1
- package/dist/esm/audio/AbstractMedia.js +1 -1
- package/dist/esm/audio/AbstractMedia.js.map +1 -1
- package/dist/esm/audio/AudioAnalyser.d.ts +37 -1
- package/dist/esm/audio/AudioAnalyser.js +150 -2
- package/dist/esm/audio/AudioAnalyser.js.map +1 -1
- package/dist/esm/audio/AudioBus.d.ts +1 -1
- package/dist/esm/audio/AudioBus.js.map +1 -1
- package/dist/esm/audio/AudioFilter.js +3 -1
- package/dist/esm/audio/AudioFilter.js.map +1 -1
- package/dist/esm/audio/AudioListener.d.ts +1 -1
- package/dist/esm/audio/AudioListener.js +5 -3
- package/dist/esm/audio/AudioListener.js.map +1 -1
- package/dist/esm/audio/AudioManager.js.map +1 -1
- package/dist/esm/audio/BeatDetector.d.ts +66 -4
- package/dist/esm/audio/BeatDetector.js +145 -44
- package/dist/esm/audio/BeatDetector.js.map +1 -1
- package/dist/esm/audio/Envelope.d.ts +1 -1
- package/dist/esm/audio/Envelope.js +2 -2
- package/dist/esm/audio/Envelope.js.map +1 -1
- package/dist/esm/audio/Music.d.ts +1 -1
- package/dist/esm/audio/Music.js +1 -1
- package/dist/esm/audio/Music.js.map +1 -1
- package/dist/esm/audio/OscillatorSound.d.ts +2 -2
- package/dist/esm/audio/OscillatorSound.js.map +1 -1
- package/dist/esm/audio/Sound.d.ts +40 -2
- package/dist/esm/audio/Sound.js +69 -9
- package/dist/esm/audio/Sound.js.map +1 -1
- package/dist/esm/audio/audio-context.js +1 -1
- package/dist/esm/audio/audio-context.js.map +1 -1
- package/dist/esm/audio/crossFade.js +1 -1
- package/dist/esm/audio/crossFade.js.map +1 -1
- package/dist/esm/audio/dsp/mel.d.ts +2 -2
- package/dist/esm/audio/dsp/mel.js +70 -0
- package/dist/esm/audio/dsp/mel.js.map +1 -0
- package/dist/esm/audio/dsp/tempogram.d.ts +2 -2
- package/dist/esm/audio/filters/ChorusFilter.js +12 -4
- package/dist/esm/audio/filters/ChorusFilter.js.map +1 -1
- package/dist/esm/audio/filters/CompressorFilter.d.ts +9 -0
- package/dist/esm/audio/filters/CompressorFilter.js +11 -0
- package/dist/esm/audio/filters/CompressorFilter.js.map +1 -1
- package/dist/esm/audio/filters/DelayFilter.js.map +1 -1
- package/dist/esm/audio/filters/DuckingFilter.d.ts +1 -1
- package/dist/esm/audio/filters/DuckingFilter.js +13 -5
- package/dist/esm/audio/filters/DuckingFilter.js.map +1 -1
- package/dist/esm/audio/filters/EqualizerFilter.js.map +1 -1
- package/dist/esm/audio/filters/GranularFilter.js +30 -14
- package/dist/esm/audio/filters/GranularFilter.js.map +1 -1
- package/dist/esm/audio/filters/HighpassFilter.js.map +1 -1
- package/dist/esm/audio/filters/LowpassFilter.js.map +1 -1
- package/dist/esm/audio/filters/PitchShiftFilter.js +14 -10
- package/dist/esm/audio/filters/PitchShiftFilter.js.map +1 -1
- package/dist/esm/audio/filters/ReverbFilter.js.map +1 -1
- package/dist/esm/audio/filters/VocoderFilter.d.ts +2 -2
- package/dist/esm/audio/filters/VocoderFilter.js +20 -12
- package/dist/esm/audio/filters/VocoderFilter.js.map +1 -1
- package/dist/esm/audio/filters/WorkletFilter.js +5 -6
- package/dist/esm/audio/filters/WorkletFilter.js.map +1 -1
- package/dist/esm/audio/filters/index.d.ts +7 -7
- package/dist/esm/audio/index.d.ts +9 -9
- package/dist/esm/audio/worklet/registerWorklet.js +7 -3
- package/dist/esm/audio/worklet/registerWorklet.js.map +1 -1
- package/dist/esm/core/Application.d.ts +13 -13
- package/dist/esm/core/Application.js +24 -16
- package/dist/esm/core/Application.js.map +1 -1
- package/dist/esm/core/Bounds.d.ts +1 -1
- package/dist/esm/core/Bounds.js +1 -3
- package/dist/esm/core/Bounds.js.map +1 -1
- package/dist/esm/core/Clock.js +1 -1
- package/dist/esm/core/Clock.js.map +1 -1
- package/dist/esm/core/Color.js +2 -5
- package/dist/esm/core/Color.js.map +1 -1
- package/dist/esm/core/Scene.d.ts +10 -10
- package/dist/esm/core/Scene.js +1 -1
- package/dist/esm/core/Scene.js.map +1 -1
- package/dist/esm/core/SceneManager.d.ts +4 -4
- package/dist/esm/core/SceneManager.js +39 -33
- package/dist/esm/core/SceneManager.js.map +1 -1
- package/dist/esm/core/SceneNode.d.ts +8 -8
- package/dist/esm/core/SceneNode.js +39 -29
- package/dist/esm/core/SceneNode.js.map +1 -1
- package/dist/esm/core/Signal.d.ts +3 -3
- package/dist/esm/core/Signal.js +3 -3
- package/dist/esm/core/Signal.js.map +1 -1
- package/dist/esm/core/Time.js +6 -6
- package/dist/esm/core/Time.js.map +1 -1
- package/dist/esm/core/Timer.d.ts +1 -1
- package/dist/esm/core/Timer.js +1 -1
- package/dist/esm/core/Timer.js.map +1 -1
- package/dist/esm/core/capabilities.js +2 -4
- package/dist/esm/core/capabilities.js.map +1 -1
- package/dist/esm/core/index.d.ts +2 -2
- package/dist/esm/core/utils.d.ts +4 -4
- package/dist/esm/core/utils.js +10 -10
- package/dist/esm/core/utils.js.map +1 -1
- package/dist/esm/debug/BoundingBoxesLayer.d.ts +3 -3
- package/dist/esm/debug/BoundingBoxesLayer.js +6 -13
- package/dist/esm/debug/BoundingBoxesLayer.js.map +1 -1
- package/dist/esm/debug/DebugLayer.d.ts +1 -1
- package/dist/esm/debug/DebugLayer.js.map +1 -1
- package/dist/esm/debug/DebugOverlay.d.ts +2 -2
- package/dist/esm/debug/DebugOverlay.js +2 -2
- package/dist/esm/debug/DebugOverlay.js.map +1 -1
- package/dist/esm/debug/HitTestLayer.d.ts +3 -3
- package/dist/esm/debug/HitTestLayer.js +3 -10
- package/dist/esm/debug/HitTestLayer.js.map +1 -1
- package/dist/esm/debug/PerformanceLayer.d.ts +2 -2
- package/dist/esm/debug/PerformanceLayer.js +6 -6
- package/dist/esm/debug/PerformanceLayer.js.map +1 -1
- package/dist/esm/debug/PointerStackLayer.d.ts +3 -3
- package/dist/esm/debug/PointerStackLayer.js +3 -3
- package/dist/esm/debug/PointerStackLayer.js.map +1 -1
- package/dist/esm/debug/RenderPassInspectorLayer.d.ts +71 -0
- package/dist/esm/debug/RenderPassInspectorLayer.js +201 -0
- package/dist/esm/debug/RenderPassInspectorLayer.js.map +1 -0
- package/dist/esm/debug/index.d.ts +4 -3
- package/dist/esm/debug/index.js +4 -3
- package/dist/esm/debug/index.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +101 -98
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/input/ArcadeStickGamepadMapping.js.map +1 -1
- package/dist/esm/input/GameCubeGamepadMapping.d.ts +1 -1
- package/dist/esm/input/GameCubeGamepadMapping.js +1 -1
- package/dist/esm/input/GameCubeGamepadMapping.js.map +1 -1
- package/dist/esm/input/Gamepad.d.ts +7 -7
- package/dist/esm/input/Gamepad.js +10 -6
- package/dist/esm/input/Gamepad.js.map +1 -1
- package/dist/esm/input/GamepadAxis.js +1 -1
- package/dist/esm/input/GamepadAxis.js.map +1 -1
- package/dist/esm/input/GamepadButton.js +1 -1
- package/dist/esm/input/GamepadButton.js.map +1 -1
- package/dist/esm/input/GamepadDefinitions.d.ts +4 -4
- package/dist/esm/input/GamepadDefinitions.js +12 -14
- package/dist/esm/input/GamepadDefinitions.js.map +1 -1
- package/dist/esm/input/GamepadMapping.d.ts +5 -5
- package/dist/esm/input/GamepadMapping.js.map +1 -1
- package/dist/esm/input/GamepadPromptLayouts.d.ts +2 -2
- package/dist/esm/input/GamepadPromptLayouts.js +8 -8
- package/dist/esm/input/GamepadPromptLayouts.js.map +1 -1
- package/dist/esm/input/GenericDualAnalogGamepadMapping.js.map +1 -1
- package/dist/esm/input/GestureRecognizer.d.ts +1 -1
- package/dist/esm/input/GestureRecognizer.js.map +1 -1
- package/dist/esm/input/InputBinding.d.ts +3 -3
- package/dist/esm/input/InputBinding.js.map +1 -1
- package/dist/esm/input/InputManager.d.ts +9 -9
- package/dist/esm/input/InputManager.js +25 -16
- package/dist/esm/input/InputManager.js.map +1 -1
- package/dist/esm/input/InteractionEvent.d.ts +1 -1
- package/dist/esm/input/InteractionEvent.js.map +1 -1
- package/dist/esm/input/InteractionManager.d.ts +2 -2
- package/dist/esm/input/InteractionManager.js +25 -16
- package/dist/esm/input/InteractionManager.js.map +1 -1
- package/dist/esm/input/JoyConLeftGamepadMapping.js.map +1 -1
- package/dist/esm/input/JoyConRightGamepadMapping.js.map +1 -1
- package/dist/esm/input/PlayStationGamepadMapping.d.ts +1 -1
- package/dist/esm/input/PlayStationGamepadMapping.js +1 -1
- package/dist/esm/input/PlayStationGamepadMapping.js.map +1 -1
- package/dist/esm/input/Pointer.d.ts +2 -2
- package/dist/esm/input/Pointer.js +6 -6
- package/dist/esm/input/Pointer.js.map +1 -1
- package/dist/esm/input/SteamControllerGamepadMapping.d.ts +1 -1
- package/dist/esm/input/SteamControllerGamepadMapping.js +1 -1
- package/dist/esm/input/SteamControllerGamepadMapping.js.map +1 -1
- package/dist/esm/input/SteamDeckGamepadMapping.js.map +1 -1
- package/dist/esm/input/SwitchProGamepadMapping.d.ts +1 -1
- package/dist/esm/input/SwitchProGamepadMapping.js +1 -1
- package/dist/esm/input/SwitchProGamepadMapping.js.map +1 -1
- package/dist/esm/input/XboxGamepadMapping.d.ts +1 -1
- package/dist/esm/input/XboxGamepadMapping.js +1 -1
- package/dist/esm/input/XboxGamepadMapping.js.map +1 -1
- package/dist/esm/input/index.d.ts +16 -16
- package/dist/esm/input/interaction-hooks.js.map +1 -1
- package/dist/esm/input/types.js.map +1 -1
- package/dist/esm/math/AbstractVector.js +8 -9
- package/dist/esm/math/AbstractVector.js.map +1 -1
- package/dist/esm/math/Circle.d.ts +5 -5
- package/dist/esm/math/Circle.js +33 -21
- package/dist/esm/math/Circle.js.map +1 -1
- package/dist/esm/math/Collision.d.ts +2 -2
- package/dist/esm/math/Collision.js.map +1 -1
- package/dist/esm/math/Ellipse.d.ts +5 -5
- package/dist/esm/math/Ellipse.js +28 -19
- package/dist/esm/math/Ellipse.js.map +1 -1
- package/dist/esm/math/Flags.d.ts +4 -4
- package/dist/esm/math/Flags.js.map +1 -1
- package/dist/esm/math/Interval.js.map +1 -1
- package/dist/esm/math/Line.d.ts +5 -5
- package/dist/esm/math/Line.js +23 -15
- package/dist/esm/math/Line.js.map +1 -1
- package/dist/esm/math/Matrix.js +14 -16
- package/dist/esm/math/Matrix.js.map +1 -1
- package/dist/esm/math/ObservableSize.js.map +1 -1
- package/dist/esm/math/ObservableVector.d.ts +1 -1
- package/dist/esm/math/ObservableVector.js.map +1 -1
- package/dist/esm/math/PolarVector.js.map +1 -1
- package/dist/esm/math/Polygon.d.ts +11 -11
- package/dist/esm/math/Polygon.js +37 -26
- package/dist/esm/math/Polygon.js.map +1 -1
- package/dist/esm/math/PolygonLike.d.ts +1 -1
- package/dist/esm/math/Quadtree.js +2 -8
- package/dist/esm/math/Quadtree.js.map +1 -1
- package/dist/esm/math/Random.js +5 -5
- package/dist/esm/math/Random.js.map +1 -1
- package/dist/esm/math/Rectangle.d.ts +4 -4
- package/dist/esm/math/Rectangle.js +59 -41
- package/dist/esm/math/Rectangle.js.map +1 -1
- package/dist/esm/math/Segment.d.ts +1 -1
- package/dist/esm/math/Segment.js +4 -4
- package/dist/esm/math/Segment.js.map +1 -1
- package/dist/esm/math/ShapeLike.d.ts +1 -1
- package/dist/esm/math/Size.js +1 -2
- package/dist/esm/math/Size.js.map +1 -1
- package/dist/esm/math/Vector.d.ts +4 -4
- package/dist/esm/math/Vector.js +19 -13
- package/dist/esm/math/Vector.js.map +1 -1
- package/dist/esm/math/collision-detection.d.ts +3 -3
- package/dist/esm/math/collision-detection.js +49 -49
- package/dist/esm/math/collision-detection.js.map +1 -1
- package/dist/esm/math/collision-primitives.d.ts +8 -8
- package/dist/esm/math/collision-primitives.js +27 -33
- package/dist/esm/math/collision-primitives.js.map +1 -1
- package/dist/esm/math/geometry.d.ts +3 -3
- package/dist/esm/math/geometry.js +55 -48
- package/dist/esm/math/geometry.js.map +1 -1
- package/dist/esm/math/index.d.ts +16 -16
- package/dist/esm/math/swept-collision.d.ts +3 -3
- package/dist/esm/math/swept-collision.js +5 -8
- package/dist/esm/math/swept-collision.js.map +1 -1
- package/dist/esm/math/triangulate.js +34 -24
- package/dist/esm/math/triangulate.js.map +1 -1
- package/dist/esm/math/utils.d.ts +2 -2
- package/dist/esm/math/utils.js +7 -7
- package/dist/esm/math/utils.js.map +1 -1
- package/dist/esm/particles/ParticleSystem.d.ts +9 -9
- package/dist/esm/particles/ParticleSystem.js +29 -29
- package/dist/esm/particles/ParticleSystem.js.map +1 -1
- package/dist/esm/particles/distributions/BoxArea.js.map +1 -1
- package/dist/esm/particles/distributions/CircleArea.js.map +1 -1
- package/dist/esm/particles/distributions/ConeDirection.js.map +1 -1
- package/dist/esm/particles/distributions/Constant.js.map +1 -1
- package/dist/esm/particles/distributions/Curve.d.ts +1 -1
- package/dist/esm/particles/distributions/Curve.js.map +1 -1
- package/dist/esm/particles/distributions/Gradient.d.ts +1 -1
- package/dist/esm/particles/distributions/Gradient.js +1 -1
- package/dist/esm/particles/distributions/Gradient.js.map +1 -1
- package/dist/esm/particles/distributions/LineSegment.js.map +1 -1
- package/dist/esm/particles/distributions/Range.js.map +1 -1
- package/dist/esm/particles/distributions/VectorRange.js.map +1 -1
- package/dist/esm/particles/distributions/index.d.ts +9 -9
- package/dist/esm/particles/gpu/ParticleGpuState.d.ts +3 -3
- package/dist/esm/particles/gpu/ParticleGpuState.js +48 -21
- package/dist/esm/particles/gpu/ParticleGpuState.js.map +1 -1
- package/dist/esm/particles/index.d.ts +1 -1
- package/dist/esm/particles/modules/AlphaFadeOverLifetime.d.ts +2 -2
- package/dist/esm/particles/modules/AlphaFadeOverLifetime.js.map +1 -1
- package/dist/esm/particles/modules/ApplyForce.d.ts +1 -1
- package/dist/esm/particles/modules/ApplyForce.js.map +1 -1
- package/dist/esm/particles/modules/AttractToPoint.d.ts +1 -1
- package/dist/esm/particles/modules/AttractToPoint.js.map +1 -1
- package/dist/esm/particles/modules/BurstSpawn.d.ts +4 -4
- package/dist/esm/particles/modules/BurstSpawn.js +2 -2
- package/dist/esm/particles/modules/BurstSpawn.js.map +1 -1
- package/dist/esm/particles/modules/ColorOverLifetime.d.ts +2 -2
- package/dist/esm/particles/modules/ColorOverLifetime.js +1 -1
- package/dist/esm/particles/modules/ColorOverLifetime.js.map +1 -1
- package/dist/esm/particles/modules/ColorOverSpeed.d.ts +2 -2
- package/dist/esm/particles/modules/ColorOverSpeed.js +1 -1
- package/dist/esm/particles/modules/ColorOverSpeed.js.map +1 -1
- package/dist/esm/particles/modules/DeathModule.js.map +1 -1
- package/dist/esm/particles/modules/Drag.d.ts +1 -1
- package/dist/esm/particles/modules/Drag.js +1 -3
- package/dist/esm/particles/modules/Drag.js.map +1 -1
- package/dist/esm/particles/modules/OrbitalForce.d.ts +1 -1
- package/dist/esm/particles/modules/OrbitalForce.js.map +1 -1
- package/dist/esm/particles/modules/RateSpawn.d.ts +3 -3
- package/dist/esm/particles/modules/RateSpawn.js +2 -2
- package/dist/esm/particles/modules/RateSpawn.js.map +1 -1
- package/dist/esm/particles/modules/RepelFromPoint.d.ts +1 -1
- package/dist/esm/particles/modules/RepelFromPoint.js.map +1 -1
- package/dist/esm/particles/modules/RotateOverLifetime.d.ts +1 -1
- package/dist/esm/particles/modules/RotateOverLifetime.js +1 -3
- package/dist/esm/particles/modules/RotateOverLifetime.js.map +1 -1
- package/dist/esm/particles/modules/ScaleOverLifetime.d.ts +2 -2
- package/dist/esm/particles/modules/ScaleOverLifetime.js.map +1 -1
- package/dist/esm/particles/modules/SpawnModule.js.map +1 -1
- package/dist/esm/particles/modules/SpawnOnDeath.d.ts +1 -1
- package/dist/esm/particles/modules/SpawnOnDeath.js.map +1 -1
- package/dist/esm/particles/modules/Turbulence.d.ts +1 -1
- package/dist/esm/particles/modules/Turbulence.js.map +1 -1
- package/dist/esm/particles/modules/UpdateModule.js.map +1 -1
- package/dist/esm/particles/modules/VelocityOverLifetime.d.ts +2 -2
- package/dist/esm/particles/modules/VelocityOverLifetime.js.map +1 -1
- package/dist/esm/particles/modules/WgslContribution.d.ts +3 -3
- package/dist/esm/particles/modules/WgslContribution.js.map +1 -1
- package/dist/esm/particles/modules/index.d.ts +17 -17
- package/dist/esm/rendering/CallbackRenderPass.js.map +1 -1
- package/dist/esm/rendering/Container.d.ts +2 -2
- package/dist/esm/rendering/Container.js +10 -11
- package/dist/esm/rendering/Container.js.map +1 -1
- package/dist/esm/rendering/Drawable.js.map +1 -1
- package/dist/esm/rendering/RenderBackend.d.ts +6 -6
- package/dist/esm/rendering/RenderBackendType.js.map +1 -1
- package/dist/esm/rendering/RenderNode.d.ts +10 -10
- package/dist/esm/rendering/RenderNode.js +31 -31
- package/dist/esm/rendering/RenderNode.js.map +1 -1
- package/dist/esm/rendering/RenderStats.js.map +1 -1
- package/dist/esm/rendering/RenderTarget.d.ts +2 -2
- package/dist/esm/rendering/RenderTarget.js +5 -5
- package/dist/esm/rendering/RenderTarget.js.map +1 -1
- package/dist/esm/rendering/RenderTargetPass.d.ts +3 -3
- package/dist/esm/rendering/RenderTargetPass.js.map +1 -1
- package/dist/esm/rendering/Renderer.d.ts +2 -2
- package/dist/esm/rendering/RendererRegistry.d.ts +3 -3
- package/dist/esm/rendering/RendererRegistry.js +2 -3
- package/dist/esm/rendering/RendererRegistry.js.map +1 -1
- package/dist/esm/rendering/View.d.ts +3 -3
- package/dist/esm/rendering/View.js +17 -20
- package/dist/esm/rendering/View.js.map +1 -1
- package/dist/esm/rendering/filters/BlurFilter.d.ts +1 -1
- package/dist/esm/rendering/filters/BlurFilter.js +4 -9
- package/dist/esm/rendering/filters/BlurFilter.js.map +1 -1
- package/dist/esm/rendering/filters/ColorFilter.d.ts +1 -1
- package/dist/esm/rendering/filters/ColorFilter.js +3 -9
- package/dist/esm/rendering/filters/ColorFilter.js.map +1 -1
- package/dist/esm/rendering/filters/Filter.d.ts +1 -1
- package/dist/esm/rendering/filters/Filter.js.map +1 -1
- package/dist/esm/rendering/filters/LutFilter.d.ts +87 -0
- package/dist/esm/rendering/filters/LutFilter.js +261 -0
- package/dist/esm/rendering/filters/LutFilter.js.map +1 -0
- package/dist/esm/rendering/filters/WebGl2ShaderFilter.d.ts +2 -2
- package/dist/esm/rendering/filters/WebGl2ShaderFilter.js +7 -14
- package/dist/esm/rendering/filters/WebGl2ShaderFilter.js.map +1 -1
- package/dist/esm/rendering/filters/WebGpuShaderFilter.d.ts +1 -1
- package/dist/esm/rendering/filters/WebGpuShaderFilter.js +16 -11
- package/dist/esm/rendering/filters/WebGpuShaderFilter.js.map +1 -1
- package/dist/esm/rendering/index.d.ts +30 -27
- package/dist/esm/rendering/mesh/Mesh.d.ts +6 -1
- package/dist/esm/rendering/mesh/Mesh.js +3 -1
- package/dist/esm/rendering/mesh/Mesh.js.map +1 -1
- package/dist/esm/rendering/mesh/MeshShader.d.ts +183 -0
- package/dist/esm/rendering/mesh/MeshShader.js +231 -0
- package/dist/esm/rendering/mesh/MeshShader.js.map +1 -0
- package/dist/esm/rendering/primitives/Graphics.d.ts +3 -3
- package/dist/esm/rendering/primitives/Graphics.js +12 -12
- package/dist/esm/rendering/primitives/Graphics.js.map +1 -1
- package/dist/esm/rendering/shader/Shader.js.map +1 -1
- package/dist/esm/rendering/shader/ShaderAttribute.js.map +1 -1
- package/dist/esm/rendering/shader/ShaderUniform.js.map +1 -1
- package/dist/esm/rendering/shader/upgradeFragmentShaderToGl300.js +6 -8
- package/dist/esm/rendering/shader/upgradeFragmentShaderToGl300.js.map +1 -1
- package/dist/esm/rendering/sprite/AnimatedSprite.d.ts +3 -3
- package/dist/esm/rendering/sprite/AnimatedSprite.js.map +1 -1
- package/dist/esm/rendering/sprite/Sprite.d.ts +4 -4
- package/dist/esm/rendering/sprite/Sprite.js +51 -35
- package/dist/esm/rendering/sprite/Sprite.js.map +1 -1
- package/dist/esm/rendering/sprite/Spritesheet.d.ts +5 -9
- package/dist/esm/rendering/sprite/Spritesheet.js +1 -1
- package/dist/esm/rendering/sprite/Spritesheet.js.map +1 -1
- package/dist/esm/rendering/text/DynamicGlyphAtlas.js +3 -9
- package/dist/esm/rendering/text/DynamicGlyphAtlas.js.map +1 -1
- package/dist/esm/rendering/text/Text.js +9 -9
- package/dist/esm/rendering/text/Text.js.map +1 -1
- package/dist/esm/rendering/text/TextLayout.d.ts +2 -2
- package/dist/esm/rendering/text/TextLayout.js.map +1 -1
- package/dist/esm/rendering/text/TextStyle.js.map +1 -1
- package/dist/esm/rendering/text/atlas-singleton.js.map +1 -1
- package/dist/esm/rendering/texture/DataTexture.d.ts +115 -0
- package/dist/esm/rendering/texture/DataTexture.js +173 -0
- package/dist/esm/rendering/texture/DataTexture.js.map +1 -0
- package/dist/esm/rendering/texture/RenderTexture.d.ts +1 -1
- package/dist/esm/rendering/texture/RenderTexture.js +4 -1
- package/dist/esm/rendering/texture/RenderTexture.js.map +1 -1
- package/dist/esm/rendering/texture/Sampler.js.map +1 -1
- package/dist/esm/rendering/texture/Texture.d.ts +2 -2
- package/dist/esm/rendering/texture/Texture.js +8 -5
- package/dist/esm/rendering/texture/Texture.js.map +1 -1
- package/dist/esm/rendering/types.js.map +1 -1
- package/dist/esm/rendering/utils.js.map +1 -1
- package/dist/esm/rendering/video/Video.d.ts +3 -3
- package/dist/esm/rendering/video/Video.js +7 -6
- package/dist/esm/rendering/video/Video.js.map +1 -1
- package/dist/esm/rendering/webgl2/AbstractWebGl2BatchedRenderer.d.ts +6 -6
- package/dist/esm/rendering/webgl2/AbstractWebGl2BatchedRenderer.js +7 -10
- package/dist/esm/rendering/webgl2/AbstractWebGl2BatchedRenderer.js.map +1 -1
- package/dist/esm/rendering/webgl2/AbstractWebGl2Renderer.d.ts +1 -1
- package/dist/esm/rendering/webgl2/AbstractWebGl2Renderer.js +1 -2
- package/dist/esm/rendering/webgl2/AbstractWebGl2Renderer.js.map +1 -1
- package/dist/esm/rendering/webgl2/WebGl2Backend.d.ts +11 -11
- package/dist/esm/rendering/webgl2/WebGl2Backend.js +61 -22
- package/dist/esm/rendering/webgl2/WebGl2Backend.js.map +1 -1
- package/dist/esm/rendering/webgl2/WebGl2MaskCompositor.d.ts +2 -2
- package/dist/esm/rendering/webgl2/WebGl2MaskCompositor.js +6 -8
- package/dist/esm/rendering/webgl2/WebGl2MaskCompositor.js.map +1 -1
- package/dist/esm/rendering/webgl2/WebGl2MeshRenderer.d.ts +7 -4
- package/dist/esm/rendering/webgl2/WebGl2MeshRenderer.js +121 -43
- package/dist/esm/rendering/webgl2/WebGl2MeshRenderer.js.map +1 -1
- package/dist/esm/rendering/webgl2/WebGl2ParticleRenderer.d.ts +1 -1
- package/dist/esm/rendering/webgl2/WebGl2ParticleRenderer.js +10 -18
- package/dist/esm/rendering/webgl2/WebGl2ParticleRenderer.js.map +1 -1
- package/dist/esm/rendering/webgl2/WebGl2RenderBuffer.d.ts +1 -1
- package/dist/esm/rendering/webgl2/WebGl2RenderBuffer.js.map +1 -1
- package/dist/esm/rendering/webgl2/WebGl2ShaderBlock.js.map +1 -1
- package/dist/esm/rendering/webgl2/WebGl2ShaderMappings.js.map +1 -1
- package/dist/esm/rendering/webgl2/WebGl2ShaderProgram.js +54 -22
- package/dist/esm/rendering/webgl2/WebGl2ShaderProgram.js.map +1 -1
- package/dist/esm/rendering/webgl2/WebGl2SpriteRenderer.d.ts +1 -1
- package/dist/esm/rendering/webgl2/WebGl2SpriteRenderer.js +11 -14
- package/dist/esm/rendering/webgl2/WebGl2SpriteRenderer.js.map +1 -1
- package/dist/esm/rendering/webgl2/WebGl2VertexArrayObject.d.ts +1 -1
- package/dist/esm/rendering/webgl2/WebGl2VertexArrayObject.js.map +1 -1
- package/dist/esm/rendering/webgpu/AbstractWebGpuRenderer.d.ts +1 -1
- package/dist/esm/rendering/webgpu/AbstractWebGpuRenderer.js +1 -2
- package/dist/esm/rendering/webgpu/AbstractWebGpuRenderer.js.map +1 -1
- package/dist/esm/rendering/webgpu/WebGpuBackend.d.ts +8 -7
- package/dist/esm/rendering/webgpu/WebGpuBackend.js +104 -37
- package/dist/esm/rendering/webgpu/WebGpuBackend.js.map +1 -1
- package/dist/esm/rendering/webgpu/WebGpuBlendState.js.map +1 -1
- package/dist/esm/rendering/webgpu/WebGpuMaskCompositor.d.ts +2 -2
- package/dist/esm/rendering/webgpu/WebGpuMaskCompositor.js +3 -4
- package/dist/esm/rendering/webgpu/WebGpuMaskCompositor.js.map +1 -1
- package/dist/esm/rendering/webgpu/WebGpuMeshRenderer.d.ts +15 -2
- package/dist/esm/rendering/webgpu/WebGpuMeshRenderer.js +657 -102
- package/dist/esm/rendering/webgpu/WebGpuMeshRenderer.js.map +1 -1
- package/dist/esm/rendering/webgpu/WebGpuParticleRenderer.d.ts +1 -1
- package/dist/esm/rendering/webgpu/WebGpuParticleRenderer.js +100 -56
- package/dist/esm/rendering/webgpu/WebGpuParticleRenderer.js.map +1 -1
- package/dist/esm/rendering/webgpu/WebGpuSpriteRenderer.d.ts +2 -2
- package/dist/esm/rendering/webgpu/WebGpuSpriteRenderer.js +45 -45
- package/dist/esm/rendering/webgpu/WebGpuSpriteRenderer.js.map +1 -1
- package/dist/esm/rendering/webgpu/compute/WebGpuComputePipeline.d.ts +1 -1
- package/dist/esm/rendering/webgpu/compute/index.d.ts +2 -2
- package/dist/esm/resources/AbstractAssetFactory.d.ts +1 -1
- package/dist/esm/resources/AbstractAssetFactory.js.map +1 -1
- package/dist/esm/resources/AssetManifest.d.ts +1 -1
- package/dist/esm/resources/AssetManifest.js +2 -2
- package/dist/esm/resources/AssetManifest.js.map +1 -1
- package/dist/esm/resources/CacheFirstStrategy.d.ts +2 -2
- package/dist/esm/resources/CacheFirstStrategy.js.map +1 -1
- package/dist/esm/resources/CacheStrategy.d.ts +1 -1
- package/dist/esm/resources/FactoryRegistry.d.ts +1 -1
- package/dist/esm/resources/FactoryRegistry.js +2 -3
- package/dist/esm/resources/FactoryRegistry.js.map +1 -1
- package/dist/esm/resources/IndexedDbDatabase.d.ts +1 -1
- package/dist/esm/resources/IndexedDbDatabase.js +11 -14
- package/dist/esm/resources/IndexedDbDatabase.js.map +1 -1
- package/dist/esm/resources/IndexedDbStore.d.ts +1 -1
- package/dist/esm/resources/IndexedDbStore.js +2 -7
- package/dist/esm/resources/IndexedDbStore.js.map +1 -1
- package/dist/esm/resources/Loader.d.ts +9 -9
- package/dist/esm/resources/Loader.js +48 -35
- package/dist/esm/resources/Loader.js.map +1 -1
- package/dist/esm/resources/NetworkOnlyStrategy.d.ts +2 -2
- package/dist/esm/resources/NetworkOnlyStrategy.js.map +1 -1
- package/dist/esm/resources/factories/BinaryFactory.js.map +1 -1
- package/dist/esm/resources/factories/FontFactory.js +1 -1
- package/dist/esm/resources/factories/FontFactory.js.map +1 -1
- package/dist/esm/resources/factories/ImageFactory.js +4 -4
- package/dist/esm/resources/factories/ImageFactory.js.map +1 -1
- package/dist/esm/resources/factories/JsonFactory.d.ts +1 -1
- package/dist/esm/resources/factories/JsonFactory.js +1 -1
- package/dist/esm/resources/factories/JsonFactory.js.map +1 -1
- package/dist/esm/resources/factories/MusicFactory.d.ts +1 -1
- package/dist/esm/resources/factories/MusicFactory.js +4 -4
- package/dist/esm/resources/factories/MusicFactory.js.map +1 -1
- package/dist/esm/resources/factories/SoundFactory.d.ts +1 -1
- package/dist/esm/resources/factories/SoundFactory.js +3 -3
- package/dist/esm/resources/factories/SoundFactory.js.map +1 -1
- package/dist/esm/resources/factories/SvgFactory.js +3 -3
- package/dist/esm/resources/factories/SvgFactory.js.map +1 -1
- package/dist/esm/resources/factories/TextFactory.js +1 -1
- package/dist/esm/resources/factories/TextFactory.js.map +1 -1
- package/dist/esm/resources/factories/TextureFactory.d.ts +1 -1
- package/dist/esm/resources/factories/TextureFactory.js +3 -3
- package/dist/esm/resources/factories/TextureFactory.js.map +1 -1
- package/dist/esm/resources/factories/VideoFactory.d.ts +2 -2
- package/dist/esm/resources/factories/VideoFactory.js +5 -5
- package/dist/esm/resources/factories/VideoFactory.js.map +1 -1
- package/dist/esm/resources/factories/VttFactory.d.ts +2 -2
- package/dist/esm/resources/factories/VttFactory.js +6 -6
- package/dist/esm/resources/factories/VttFactory.js.map +1 -1
- package/dist/esm/resources/factories/WasmFactory.js.map +1 -1
- package/dist/esm/resources/index.d.ts +11 -11
- package/dist/esm/resources/utils.js +30 -25
- package/dist/esm/resources/utils.js.map +1 -1
- package/dist/exo.esm.js +26260 -24256
- package/dist/exo.esm.js.map +1 -1
- package/package.json +15 -4
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,161 @@ All notable changes to ExoJS are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.8.3] - 2026-05-10
|
|
8
|
+
|
|
9
|
+
### Engine — Rendering
|
|
10
|
+
|
|
11
|
+
- **`MeshShader` class with dual GLSL + WGSL support.** The 0.8.2
|
|
12
|
+
`MeshShaderConfig` plain interface is replaced by a `MeshShader` class
|
|
13
|
+
accepting `glsl: { vertex, fragment }` and/or `wgsl` source. The WebGPU
|
|
14
|
+
mesh renderer now has a parallel render path for custom-shader meshes
|
|
15
|
+
inside the same render pass, switching pipeline + bind groups between
|
|
16
|
+
batched default draws and per-shader custom draws. New methods
|
|
17
|
+
`getDeclaredUniforms()` and `detectUniformDrift()` parse uniform
|
|
18
|
+
declarations from both languages for CI-style drift checking. **Breaking
|
|
19
|
+
change against the 0.8.2 plain-interface shape; clean break, no
|
|
20
|
+
backwards-compat shim — the 0.8.x series is pre-1.0.**
|
|
21
|
+
|
|
22
|
+
- **`DataTexture` for CPU-uploaded GPU textures.** New primitive whose
|
|
23
|
+
pixels live in a CPU-side typed array. Mutate the `buffer` directly and
|
|
24
|
+
call `commit()` to upload the whole array, or `commitRect(x, y, w, h)`
|
|
25
|
+
for partial uploads (cheaper for ring-buffer patterns like
|
|
26
|
+
spectrograms). Formats: `r8` / `r32f` / `rgba8` / `rgba32f`; TypeScript
|
|
27
|
+
narrows the buffer typed-array kind from the format. Bring-your-own
|
|
28
|
+
buffer via `options.data` (`Uint8Array | Float32Array | ArrayBuffer`)
|
|
29
|
+
for SharedArrayBuffer / Worker / pool scenarios. Extends `Texture` so
|
|
30
|
+
it's accepted everywhere a `Texture` is.
|
|
31
|
+
|
|
32
|
+
### Engine — Audio
|
|
33
|
+
|
|
34
|
+
- **`BeatDetector` visual getters for per-frame polling.** New derived
|
|
35
|
+
getters `pulse`, `barPulse`, `justBeat`, `secondsSinceLastBeat` and
|
|
36
|
+
method `subdivisionPhase(division)`. All pure derivations from existing
|
|
37
|
+
state — no new event-handling glue required for typical "pulse on the
|
|
38
|
+
beat" / "trigger on every 16th note" visuals. Mutable fields
|
|
39
|
+
`pulseHalfLife` (default 0.15s), `barPulseHalfLife` (0.3s), and
|
|
40
|
+
`justBeatWindow` (0.03s) tune the envelopes.
|
|
41
|
+
|
|
42
|
+
- **`AudioAnalyser` mel and log spectrum mapping.** New methods
|
|
43
|
+
`getSpectrumMel` / `getSpectrumMelFloat` / `getSpectrumLog` /
|
|
44
|
+
`getSpectrumLogFloat` produce perceptually-weighted or octave-uniform
|
|
45
|
+
band sequences from the linear FFT bins. Filterbanks are built from
|
|
46
|
+
the previously-orphaned `dsp/mel.ts` utilities and cached per
|
|
47
|
+
`(bands, fMin, fMax)` combination — rebuild only on parameter change.
|
|
48
|
+
Default 32 bands, 20 Hz to 20 kHz (clamped to nyquist).
|
|
49
|
+
|
|
50
|
+
- **`source` as constructor option for `AudioAnalyser` and `BeatDetector`.**
|
|
51
|
+
Additive ergonomic for one-shot construction:
|
|
52
|
+
`new AudioAnalyser({ source: music, fftSize: 1024 })`. The setter
|
|
53
|
+
remains usable for runtime source switches.
|
|
54
|
+
|
|
55
|
+
### Engine — Debug
|
|
56
|
+
|
|
57
|
+
- **`RenderPassInspectorLayer`.** New debug layer (in the
|
|
58
|
+
`@codexo/exojs/debug` subpath) that lists every `RenderNode` with an
|
|
59
|
+
active filter chain each frame, showing total pass count, per-drawable
|
|
60
|
+
filter sequence, bounding-box dimensions, and mask/cache flags. For
|
|
61
|
+
deep per-pass inspection (intermediate render-target contents, shader
|
|
62
|
+
source, uniform values), use Spector.js or Chrome DevTools' WebGPU
|
|
63
|
+
panel — the engine now emits debug-group labels around filter and
|
|
64
|
+
mesh-custom-shader passes (`WebGpuShaderFilter pass`,
|
|
65
|
+
`MeshShader (custom)`, `WebGpuMaskCompositor pass`) so external capture
|
|
66
|
+
tools display meaningful pass names.
|
|
67
|
+
|
|
68
|
+
### Site / Docs
|
|
69
|
+
|
|
70
|
+
- New guide chapter stubs: `6.4 Custom mesh shaders`,
|
|
71
|
+
`5.5 Audio-reactive visualization`, `7.6 Render pipeline debugging`.
|
|
72
|
+
- API doc auto-regenerated for `MeshShader` and `DataTexture`.
|
|
73
|
+
|
|
74
|
+
### Verification
|
|
75
|
+
|
|
76
|
+
- Engine: 103/103 suites, 1338/1338 tests, lint:strict 0/0, typecheck clean.
|
|
77
|
+
- Site: build green (494 pages), check-ts 0/0.
|
|
78
|
+
|
|
79
|
+
## [0.8.2] - 2026-05-09
|
|
80
|
+
|
|
81
|
+
### Engine
|
|
82
|
+
|
|
83
|
+
- **`Mesh` accepts custom WebGL2 shaders.** New `MeshShaderConfig` + `MeshShaderUniformValue`
|
|
84
|
+
exports. Supply `shader: { vertexSource, fragmentSource, uniforms }` in `MeshOptions` to
|
|
85
|
+
bind a custom GLSL ES 3.00 program against the standard mesh vertex layout. Auto-bound
|
|
86
|
+
uniforms (`u_projection`, `u_translation`, `u_tint`, `u_texture`) are set only when the
|
|
87
|
+
shader declares them, so Shadertoy-style fullscreen passes can ignore them entirely.
|
|
88
|
+
Texture uniforms claim slots 1–7. WebGL2 only in this release; the WebGPU mesh
|
|
89
|
+
renderer throws a clear error pointing to the WebGL2 backend if `mesh.shader` is set.
|
|
90
|
+
|
|
91
|
+
- **Filter chain memory: ping-pong RT reuse.** `RenderNode._renderContentToTexture` now
|
|
92
|
+
releases the previous step's RenderTexture immediately after each `filter.apply`, so
|
|
93
|
+
the pool can hand the same memory back to the next step. Multi-filter chains drop from
|
|
94
|
+
N+1 simultaneously-allocated RTs to a steady-state of 2. ~60% RT-memory reduction on
|
|
95
|
+
4-filter 1080p chains. Behaviour-identical; no public API change.
|
|
96
|
+
|
|
97
|
+
### Site / Docs
|
|
98
|
+
|
|
99
|
+
- Part 2 "Core Concepts" guide section published (6 chapters, source-verified):
|
|
100
|
+
Application, Scenes, Scene lifecycle, Scene graph, Coordinates and views,
|
|
101
|
+
Loading and resources.
|
|
102
|
+
- Astro `6.3.0 → 6.3.1`, `@types/node 25.6.0 → 25.6.2` in site/.
|
|
103
|
+
|
|
104
|
+
### Verification
|
|
105
|
+
|
|
106
|
+
- Engine: 100/100 suites, 1266/1266 tests, lint:strict 0/0, typecheck clean.
|
|
107
|
+
- Site: build green (488 pages), check-ts 0/0, screenshot smoke 36/36.
|
|
108
|
+
|
|
109
|
+
## [0.8.1] - 2026-05-08
|
|
110
|
+
|
|
111
|
+
Three small additive features that close the remaining examples-driven API gaps from
|
|
112
|
+
the 0.8.0 audit, plus a long-overdue lint/format tooling consolidation and a 19-chapter
|
|
113
|
+
examples reorganisation.
|
|
114
|
+
|
|
115
|
+
### Added
|
|
116
|
+
|
|
117
|
+
- **`Sound` spatial falloff configuration.** `DistanceModel` type (`'linear' | 'inverse'
|
|
118
|
+
| 'exponential'`), plus optional `distanceModel`, `refDistance`, `maxDistance`, and
|
|
119
|
+
`rolloffFactor` fields on `SoundOptions`. The four are also exposed as live property
|
|
120
|
+
setters that lazy-forward to the attached `PannerNode`. New public `Sound.audioBuffer`
|
|
121
|
+
getter to share one decoded buffer across multiple `Sound` instances.
|
|
122
|
+
- **`LutFilter`** — new colour-pipeline primitive that maps every pixel through a
|
|
123
|
+
Look-Up Table texture. Supports both 1D LUTs (`N×1`, indexed by red channel — palette
|
|
124
|
+
cycling, indexed-colour effects) and 3D LUTs (`N²×N` unwrapped cube with trilinear
|
|
125
|
+
slice interpolation — cinematic colour grading, tone mapping, film stock emulation,
|
|
126
|
+
accessibility filters). Backend selection is automatic. Static helpers
|
|
127
|
+
`LutFilter.identityLut1D(size)`, `LutFilter.identityLut3D(size)`,
|
|
128
|
+
`LutFilter.fromImage(image)` cover the standard DaVinci/OBS/Photoshop LUT-export
|
|
129
|
+
workflows.
|
|
130
|
+
- **`CompressorFilter.reduction`** — public getter forwarding the live gain reduction
|
|
131
|
+
in dB from the underlying `DynamicsCompressorNode`. Use as a meter source for
|
|
132
|
+
visualisations or sidechain triggers.
|
|
133
|
+
|
|
134
|
+
### Examples
|
|
135
|
+
|
|
136
|
+
- Migrated `examples/public/examples/` to a 19-chapter pedagogical structure: getting
|
|
137
|
+
started, application & scenes, sprites & textures, tweens & animation, input, scene
|
|
138
|
+
graph, audio basics, spatial audio, filters, particles, text & fonts, geometry &
|
|
139
|
+
graphics, render targets, performance, audio FX, beat detection, debug layer, custom
|
|
140
|
+
renderers, showcase. Old chapter directories (`collision-detection`, `extras`,
|
|
141
|
+
`particle-system`, `rendering`, `webgpu`) removed.
|
|
142
|
+
- New examples: `spatial-audio/falloff-curves.js`, `filters/palette-cycling.js`,
|
|
143
|
+
`showcase/color-grading.js`. The compressor demo gained a live gain-reduction meter.
|
|
144
|
+
|
|
145
|
+
### Tooling
|
|
146
|
+
|
|
147
|
+
- ESLint config consolidated into a single `eslint.config.ts` driven by ESLint 10 +
|
|
148
|
+
`typescript-eslint`'s type-aware checks plus `simple-import-sort`,
|
|
149
|
+
`unused-imports`, `unicorn`, and `security` plugins. `lint:strict` is the
|
|
150
|
+
release-gate variant, scoped to `src/**/*.ts` and run with `--max-warnings=0` (warnings
|
|
151
|
+
fail the build); `lint` is the broader development view across `src`, `test`, and
|
|
152
|
+
examples. Per-subsystem override blocks are documented as known deviations to tighten
|
|
153
|
+
over time.
|
|
154
|
+
- Tightened to error: `eqeqeq`, `no-floating-promises`, `no-base-to-string`,
|
|
155
|
+
`only-throw-error`, `switch-exhaustiveness-check`, `no-non-null-assertion`,
|
|
156
|
+
`complexity` (cap 20). Added: `no-self-compare`, `no-unreachable-loop`,
|
|
157
|
+
`default-case-last`, `prefer-promise-reject-errors`, `no-promise-executor-return`,
|
|
158
|
+
`no-unmodified-loop-condition`, plus six TypeScript and six Unicorn correctness rules.
|
|
159
|
+
- Prettier `printWidth: 160`, `.editorconfig` matched. Engine code reformatted to
|
|
160
|
+
2-space indent.
|
|
161
|
+
|
|
7
162
|
## [0.8.0] - 2026-05-07
|
|
8
163
|
|
|
9
164
|
Wholesale rewrite of the particle subsystem around a data-oriented core
|
|
@@ -33,19 +188,19 @@ automatic and per-system; user code is unchanged across both paths.
|
|
|
33
188
|
`Uint32Array` / `Uint16Array` channels addressed by slot index:
|
|
34
189
|
|
|
35
190
|
```ts
|
|
36
|
-
system.posX[slot]
|
|
37
|
-
system.posY[slot]
|
|
38
|
-
system.velX[slot]
|
|
39
|
-
system.velY[slot]
|
|
40
|
-
system.scaleX[slot]
|
|
41
|
-
system.scaleY[slot]
|
|
42
|
-
system.rotations[slot]
|
|
43
|
-
system.rotationSpeeds[slot]
|
|
44
|
-
system.color[slot]
|
|
45
|
-
system.elapsed[slot]
|
|
46
|
-
system.lifetime[slot]
|
|
47
|
-
system.textureIndex[slot]
|
|
48
|
-
system.liveCount
|
|
191
|
+
system.posX[slot];
|
|
192
|
+
system.posY[slot];
|
|
193
|
+
system.velX[slot];
|
|
194
|
+
system.velY[slot];
|
|
195
|
+
system.scaleX[slot];
|
|
196
|
+
system.scaleY[slot];
|
|
197
|
+
system.rotations[slot];
|
|
198
|
+
system.rotationSpeeds[slot];
|
|
199
|
+
system.color[slot]; // packed 0xAABBGGRR
|
|
200
|
+
system.elapsed[slot];
|
|
201
|
+
system.lifetime[slot];
|
|
202
|
+
system.textureIndex[slot];
|
|
203
|
+
system.liveCount; // [0, liveCount) is the live range
|
|
49
204
|
```
|
|
50
205
|
|
|
51
206
|
Capacity is fixed at construction (default 4096) — no reallocations.
|
|
@@ -57,17 +212,17 @@ instead of the previous O(n²) splice loop with scattered expirations).
|
|
|
57
212
|
|
|
58
213
|
Spawn-time random sampling and lifetime-parameterised evaluation:
|
|
59
214
|
|
|
60
|
-
| Type
|
|
61
|
-
|
|
62
|
-
| `Constant<T>`
|
|
63
|
-
| `Range`
|
|
64
|
-
| `VectorRange`
|
|
65
|
-
| `ConeDirection` | Random unit vector in a cone × speed range
|
|
66
|
-
| `CircleArea`
|
|
67
|
-
| `BoxArea`
|
|
68
|
-
| `LineSegment`
|
|
69
|
-
| `Curve`
|
|
70
|
-
| `Gradient`
|
|
215
|
+
| Type | Use |
|
|
216
|
+
| --------------- | ----------------------------------------------------------------------------- |
|
|
217
|
+
| `Constant<T>` | Always-same value |
|
|
218
|
+
| `Range` | Uniform random number in `[min, max]` |
|
|
219
|
+
| `VectorRange` | Per-axis random vector |
|
|
220
|
+
| `ConeDirection` | Random unit vector in a cone × speed range |
|
|
221
|
+
| `CircleArea` | Random point in/on a circle |
|
|
222
|
+
| `BoxArea` | Random point in/on an AABB |
|
|
223
|
+
| `LineSegment` | Random point on a segment |
|
|
224
|
+
| `Curve` | Piecewise-linear keyframe scalar by lifetime ratio |
|
|
225
|
+
| `Gradient` | Piecewise-linear keyframe color, with `evaluateRgba()` for direct u32 packing |
|
|
71
226
|
|
|
72
227
|
`Curve` and `Gradient` cache the last segment so monotonically
|
|
73
228
|
advancing `t` (the typical case for per-particle lifetime sampling)
|
|
@@ -79,9 +234,15 @@ Three module bases. Each registered on a system via the corresponding
|
|
|
79
234
|
`addX` method; each runs in its declared phase per-frame.
|
|
80
235
|
|
|
81
236
|
```ts
|
|
82
|
-
abstract class SpawnModule
|
|
83
|
-
|
|
84
|
-
|
|
237
|
+
abstract class SpawnModule {
|
|
238
|
+
apply(system, dt: number): void;
|
|
239
|
+
}
|
|
240
|
+
abstract class UpdateModule {
|
|
241
|
+
apply(system, dt: number): void;
|
|
242
|
+
}
|
|
243
|
+
abstract class DeathModule {
|
|
244
|
+
onDeath(system, slot: number): void;
|
|
245
|
+
}
|
|
85
246
|
```
|
|
86
247
|
|
|
87
248
|
**Built-in spawn modules:**
|
|
@@ -121,7 +282,7 @@ for one `ParticleSystem`. At construction time it:
|
|
|
121
282
|
|
|
122
283
|
1. Walks the registered update modules, collecting each module's
|
|
123
284
|
`WgslContribution` (uniform field declarations + texture bindings
|
|
124
|
-
|
|
285
|
+
- WGSL body snippet).
|
|
125
286
|
2. Generates a composite WGSL compute shader: SoA storage bindings +
|
|
126
287
|
sim/module uniform structs + module texture bindings + a `main`
|
|
127
288
|
function containing integration → all module bodies in registration
|
|
@@ -151,8 +312,8 @@ Opt-in is a single constructor option — no imperative toggle:
|
|
|
151
312
|
|
|
152
313
|
```ts
|
|
153
314
|
const system = new ParticleSystem(texture, {
|
|
154
|
-
|
|
155
|
-
|
|
315
|
+
capacity: 8192,
|
|
316
|
+
backend: app.backend, // CPU-routed on WebGL2, GPU-routed on WebGPU
|
|
156
317
|
});
|
|
157
318
|
```
|
|
158
319
|
|
|
@@ -165,25 +326,25 @@ modules after that throws.
|
|
|
165
326
|
|
|
166
327
|
The following symbols are deleted. Migration recipes follow the table.
|
|
167
328
|
|
|
168
|
-
| Removed
|
|
169
|
-
|
|
170
|
-
| `Particle` (class)
|
|
171
|
-
| `ParticleProperties` (interface)
|
|
172
|
-
| `ParticleEmitter` (interface)
|
|
173
|
-
| `ParticleOptions`
|
|
174
|
-
| `UniversalEmitter`
|
|
175
|
-
| `ParticleAffector` (interface)
|
|
176
|
-
| `ColorAffector`
|
|
177
|
-
| `ForceAffector`
|
|
178
|
-
| `ScaleAffector`
|
|
179
|
-
| `TorqueAffector`
|
|
180
|
-
| `system.requestParticle()`
|
|
181
|
-
| `system.emitParticle(p)`
|
|
182
|
-
| `system.updateParticle(p, dt)`
|
|
183
|
-
| `system.addEmitter(e)`
|
|
184
|
-
| `system.addAffector(a)`
|
|
185
|
-
| `system.particles` (`Array<Particle>`) | `system.posX` / `system.posY` / ... `system.liveCount`
|
|
186
|
-
| `system.graveyard`
|
|
329
|
+
| Removed | Replacement |
|
|
330
|
+
| -------------------------------------- | ------------------------------------------------------------- |
|
|
331
|
+
| `Particle` (class) | SoA arrays on `ParticleSystem` (`system.posX[slot]`, etc.) |
|
|
332
|
+
| `ParticleProperties` (interface) | None — slot-indexed arrays replace the per-particle object |
|
|
333
|
+
| `ParticleEmitter` (interface) | `SpawnModule` (abstract class) |
|
|
334
|
+
| `ParticleOptions` | Per-property `Distribution<T>` in the spawn module's config |
|
|
335
|
+
| `UniversalEmitter` | `RateSpawn` |
|
|
336
|
+
| `ParticleAffector` (interface) | `UpdateModule` (abstract class) |
|
|
337
|
+
| `ColorAffector` | `ColorOverLifetime` + `Gradient` |
|
|
338
|
+
| `ForceAffector` | `ApplyForce` |
|
|
339
|
+
| `ScaleAffector` | `ScaleOverLifetime` + `Curve` |
|
|
340
|
+
| `TorqueAffector` | `RotateOverLifetime` |
|
|
341
|
+
| `system.requestParticle()` | `system.spawn(): number` (slot index, or `-1` at capacity) |
|
|
342
|
+
| `system.emitParticle(p)` | (gone — `spawn()` already commits the slot to the live range) |
|
|
343
|
+
| `system.updateParticle(p, dt)` | (gone — internal to `update()`) |
|
|
344
|
+
| `system.addEmitter(e)` | `system.addSpawnModule(m)` |
|
|
345
|
+
| `system.addAffector(a)` | `system.addUpdateModule(m)` |
|
|
346
|
+
| `system.particles` (`Array<Particle>`) | `system.posX` / `system.posY` / ... `system.liveCount` |
|
|
347
|
+
| `system.graveyard` | (gone — no graveyard; slots are recycled in place) |
|
|
187
348
|
|
|
188
349
|
### Migration
|
|
189
350
|
|
|
@@ -203,16 +364,22 @@ options.velocity.set(/* ... */);
|
|
|
203
364
|
|
|
204
365
|
// After — bonfire
|
|
205
366
|
const system = new ParticleSystem(texture);
|
|
206
|
-
system.addSpawnModule(
|
|
367
|
+
system.addSpawnModule(
|
|
368
|
+
new RateSpawn({
|
|
207
369
|
rate: new Constant(50),
|
|
208
370
|
lifetime: new Range(5, 10),
|
|
209
371
|
position: new VectorRange(-50, 50, -10, 10),
|
|
210
372
|
velocity: new ConeDirection(-Math.PI / 2, Math.PI / 36, 60, 80),
|
|
211
|
-
})
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
373
|
+
}),
|
|
374
|
+
);
|
|
375
|
+
system.addUpdateModule(
|
|
376
|
+
new ColorOverLifetime(
|
|
377
|
+
new Gradient([
|
|
378
|
+
{ t: 0, color: new Color(194, 64, 30, 1) },
|
|
379
|
+
{ t: 1, color: new Color(0, 0, 0, 0) },
|
|
380
|
+
]),
|
|
381
|
+
),
|
|
382
|
+
);
|
|
216
383
|
// no per-frame mutation needed.
|
|
217
384
|
```
|
|
218
385
|
|
|
@@ -228,23 +395,23 @@ system.addUpdateModule(new ApplyForce(0, 980));
|
|
|
228
395
|
```ts
|
|
229
396
|
// Before — custom affector
|
|
230
397
|
class AlphaFade {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
398
|
+
apply(particle, delta) {
|
|
399
|
+
particle.tint.a = particle.remainingRatio;
|
|
400
|
+
return this;
|
|
401
|
+
}
|
|
402
|
+
destroy() {}
|
|
236
403
|
}
|
|
237
404
|
|
|
238
405
|
// After
|
|
239
406
|
class AlphaFadeOverLifetime extends UpdateModule {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
407
|
+
apply(system) {
|
|
408
|
+
const { color, elapsed, lifetime, liveCount } = system;
|
|
409
|
+
for (let i = 0; i < liveCount; i++) {
|
|
410
|
+
const remaining = 1 - elapsed[i] / lifetime[i];
|
|
411
|
+
const a = (Math.max(0, Math.min(1, remaining)) * 255) & 255;
|
|
412
|
+
color[i] = (color[i] & 0x00ffffff) | (a << 24);
|
|
247
413
|
}
|
|
414
|
+
}
|
|
248
415
|
}
|
|
249
416
|
```
|
|
250
417
|
|
|
@@ -279,12 +446,12 @@ new ParticleSystem(texture);
|
|
|
279
446
|
new ParticleSystem(texture, 4096);
|
|
280
447
|
|
|
281
448
|
// 0.8.0:
|
|
282
|
-
new ParticleSystem();
|
|
283
|
-
new ParticleSystem(spark);
|
|
284
|
-
new ParticleSystem(spark, { capacity: 8192 });
|
|
285
|
-
new ParticleSystem(atlas, [r0, r1, r2]);
|
|
449
|
+
new ParticleSystem(); // untextured (1×1 white), CPU/GPU auto-routed
|
|
450
|
+
new ParticleSystem(spark); // simple textured particles
|
|
451
|
+
new ParticleSystem(spark, { capacity: 8192 }); // explicit capacity
|
|
452
|
+
new ParticleSystem(atlas, [r0, r1, r2]); // multi-frame atlas
|
|
286
453
|
new ParticleSystem(atlas, frames, { capacity: 8192 }); // atlas + capacity
|
|
287
|
-
new ParticleSystem(sheet);
|
|
454
|
+
new ParticleSystem(sheet); // spritesheet shorthand
|
|
288
455
|
new ParticleSystem(sheet, { capacity: 4096 });
|
|
289
456
|
```
|
|
290
457
|
|
|
@@ -300,9 +467,9 @@ constructor(spritesheet: Spritesheet, options?: ParticleSystemOptions);
|
|
|
300
467
|
Compile-time errors for illegal combinations:
|
|
301
468
|
|
|
302
469
|
```ts
|
|
303
|
-
new ParticleSystem(spark, sheet);
|
|
304
|
-
new ParticleSystem(sheet, frames);
|
|
305
|
-
new ParticleSystem({ frames });
|
|
470
|
+
new ParticleSystem(spark, sheet); // ✗ no overload matches
|
|
471
|
+
new ParticleSystem(sheet, frames); // ✗ frames only valid with Texture
|
|
472
|
+
new ParticleSystem({ frames }); // ✗ frames isn't an option
|
|
306
473
|
```
|
|
307
474
|
|
|
308
475
|
**No `backend` option** — the renderer auto-discovers the active backend
|
|
@@ -326,19 +493,21 @@ frame chooser:
|
|
|
326
493
|
|
|
327
494
|
```ts
|
|
328
495
|
const system = new ParticleSystem({
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
496
|
+
texture: explosionAtlas,
|
|
497
|
+
frames: [
|
|
498
|
+
new Rectangle(0, 0, 32, 32), // index 0 — flame core
|
|
499
|
+
new Rectangle(32, 0, 32, 32), // index 1 — smoke ring
|
|
500
|
+
new Rectangle(64, 0, 32, 32), // index 2 — ember
|
|
501
|
+
],
|
|
335
502
|
});
|
|
336
503
|
|
|
337
|
-
system.addSpawnModule(
|
|
504
|
+
system.addSpawnModule(
|
|
505
|
+
new BurstSpawn({
|
|
338
506
|
schedule: [{ time: 0, count: 60 }],
|
|
339
507
|
velocity: ConeDirection.omni(120, 280),
|
|
340
|
-
textureIndex: new Range(0, 2),
|
|
341
|
-
})
|
|
508
|
+
textureIndex: new Range(0, 2), // each spawn picks a random frame
|
|
509
|
+
}),
|
|
510
|
+
);
|
|
342
511
|
```
|
|
343
512
|
|
|
344
513
|
`Spritesheet` integration via `spritesheet: sheet` extracts texture +
|
|
@@ -373,6 +542,7 @@ update). `spawn()` always returns the next sequential slot.
|
|
|
373
542
|
|
|
374
543
|
In GPU mode, no compaction happens — readback would be required to
|
|
375
544
|
move slots whose authoritative position lives in GPU memory. Instead:
|
|
545
|
+
|
|
376
546
|
- Each particle has an `alive: Uint8Array` flag (1 = alive, 0 = dead).
|
|
377
547
|
- `spawn()` finds the first dead slot via a round-robin hint pointer
|
|
378
548
|
(amortised O(1), worst case O(capacity)).
|
|
@@ -422,7 +592,7 @@ signed stick channels, and Joy-Con-honest mappings.
|
|
|
422
592
|
```ts
|
|
423
593
|
// Per inputManager (manual unbind):
|
|
424
594
|
app.input.onTrigger(GamepadButton.South, () => player.jump());
|
|
425
|
-
app.input.onActive(GamepadAxis.LeftStickX,
|
|
595
|
+
app.input.onActive(GamepadAxis.LeftStickX, v => (player.x += v * 5));
|
|
426
596
|
app.input.onStart([Keyboard.Space, GamepadButton.South], () => fire());
|
|
427
597
|
|
|
428
598
|
// Per gamepad (slot-aware, listener survives disconnect/reconnect):
|
|
@@ -466,8 +636,8 @@ default `'sticky'` (each pad keeps its slot through disconnects).
|
|
|
466
636
|
disconnect (good for hot-seat couch coop where "the first N pads are
|
|
467
637
|
the N players" is the desired semantic).
|
|
468
638
|
|
|
469
|
-
In compact mode, the disconnect signal fires on the slot that
|
|
470
|
-
|
|
639
|
+
In compact mode, the disconnect signal fires on the slot that _ended
|
|
640
|
+
up_ empty after the shift (not the slot the disconnected hardware
|
|
471
641
|
originally occupied), keeping `pad.connected === false` consistent with
|
|
472
642
|
the fired event. Slots that received a different physical pad through
|
|
473
643
|
the shift dispatch a separate signal:
|
|
@@ -481,6 +651,7 @@ player when slots renumber.
|
|
|
481
651
|
### Added — Generic signals
|
|
482
652
|
|
|
483
653
|
Per-pad:
|
|
654
|
+
|
|
484
655
|
- `pad.onConnect: Signal<[]>`
|
|
485
656
|
- `pad.onDisconnect: Signal<[]>`
|
|
486
657
|
- `pad.onButtonDown: Signal<[GamepadButton, number]>`
|
|
@@ -488,6 +659,7 @@ Per-pad:
|
|
|
488
659
|
- `pad.onAxisChange: Signal<[GamepadAxis, number]>`
|
|
489
660
|
|
|
490
661
|
Aggregate across all pads:
|
|
662
|
+
|
|
491
663
|
- `inputManager.onAnyGamepadButtonDown: Signal<[Gamepad, GamepadButton, number]>`
|
|
492
664
|
- `inputManager.onAnyGamepadButtonUp: Signal<[Gamepad, GamepadButton, number]>`
|
|
493
665
|
- `inputManager.onAnyGamepadAxisChange: Signal<[Gamepad, GamepadAxis, number]>`
|
|
@@ -496,7 +668,7 @@ Aggregate across all pads:
|
|
|
496
668
|
|
|
497
669
|
```ts
|
|
498
670
|
if (pad.canVibrate) {
|
|
499
|
-
|
|
671
|
+
await pad.vibrate({ duration: 200, weakMagnitude: 0.5, strongMagnitude: 1.0 });
|
|
500
672
|
}
|
|
501
673
|
pad.stopVibration();
|
|
502
674
|
```
|
|
@@ -517,18 +689,18 @@ remain available for buttons-style 0..1 input.
|
|
|
517
689
|
|
|
518
690
|
```ts
|
|
519
691
|
// Stick-style — one binding per axis, signed value:
|
|
520
|
-
this.inputs.onActive(GamepadAxis.LeftStickX,
|
|
692
|
+
this.inputs.onActive(GamepadAxis.LeftStickX, x => (player.x += x * 5));
|
|
521
693
|
|
|
522
694
|
// Buttons-style — separate bindings per direction, 0..1 each:
|
|
523
|
-
this.inputs.onActive(GamepadAxis.LeftStickLeft,
|
|
524
|
-
this.inputs.onActive(GamepadAxis.LeftStickRight,
|
|
695
|
+
this.inputs.onActive(GamepadAxis.LeftStickLeft, v => (player.x -= v * 5));
|
|
696
|
+
this.inputs.onActive(GamepadAxis.LeftStickRight, v => (player.x += v * 5));
|
|
525
697
|
```
|
|
526
698
|
|
|
527
699
|
### Added — `pad.hasChannel(channel)` capability check
|
|
528
700
|
|
|
529
701
|
```ts
|
|
530
702
|
if (pad.hasChannel(GamepadAxis.RightStickX)) {
|
|
531
|
-
|
|
703
|
+
pad.onActive(GamepadAxis.RightStickX, v => (crosshair.x += v * 8));
|
|
532
704
|
}
|
|
533
705
|
```
|
|
534
706
|
|
|
@@ -545,19 +717,19 @@ Internally tracks each binding and calls `.unbind()` in `Scene.destroy`.
|
|
|
545
717
|
### Added — Steam Deck / Steam Virtual Gamepad / Valve fallback
|
|
546
718
|
|
|
547
719
|
New `SteamDeckGamepadMapping` covers the raw HID layout reported by the
|
|
548
|
-
Steam Deck (and likely future Valve hardware) when Steam Input is
|
|
720
|
+
Steam Deck (and likely future Valve hardware) when Steam Input is _not_
|
|
549
721
|
intercepting the device. Indices follow the SDL_GameControllerDB Linux
|
|
550
722
|
entry: face buttons at 3-6, D-pad at 16-19, paddles at 20-23, triggers
|
|
551
723
|
as analog axes 8/9.
|
|
552
724
|
|
|
553
725
|
Routing rules added to `builtInGamepadDefinitions`:
|
|
554
726
|
|
|
555
|
-
| Browser ID
|
|
556
|
-
|
|
557
|
-
| `28de:1102`, `28de:1142`
|
|
558
|
-
| `28de:11ff` (Steam Virtual Gamepad — any controller via Steam Input)
|
|
559
|
-
| `28de:1205`
|
|
560
|
-
| Vendor `28de` (anything else from Valve, e.g. future Steam Controller 2 raw) | `SteamDeckGamepadMapping` (best-effort fallback)
|
|
727
|
+
| Browser ID | Mapping |
|
|
728
|
+
| ---------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
|
|
729
|
+
| `28de:1102`, `28de:1142` | `SteamControllerGamepadMapping` (existing, original Steam Controller raw) |
|
|
730
|
+
| `28de:11ff` (Steam Virtual Gamepad — any controller via Steam Input) | `GenericDualAnalogGamepadMapping` (W3C standard Xbox emulation) |
|
|
731
|
+
| `28de:1205` | `SteamDeckGamepadMapping` (raw Steam Deck) |
|
|
732
|
+
| Vendor `28de` (anything else from Valve, e.g. future Steam Controller 2 raw) | `SteamDeckGamepadMapping` (best-effort fallback) |
|
|
561
733
|
|
|
562
734
|
Enum: `GamepadMappingFamily.SteamDeck` added.
|
|
563
735
|
|
|
@@ -610,7 +782,7 @@ app.input.getGamepad(0);
|
|
|
610
782
|
### Fixed — Compact-mode disconnect ordering
|
|
611
783
|
|
|
612
784
|
In `'compact'` slot strategy, `onDisconnect` previously fired on the
|
|
613
|
-
slot the disconnected hardware originally occupied —
|
|
785
|
+
slot the disconnected hardware originally occupied — _before_ the
|
|
614
786
|
compaction shift moved a different physical pad into that slot. User
|
|
615
787
|
code observing the event would see `pad.connected === true` because
|
|
616
788
|
the slot had been silently re-bound by the shift. Now compaction is
|
|
@@ -622,13 +794,13 @@ ended up empty (the trailing slot). Sticky behaviour is unchanged.
|
|
|
622
794
|
The unified `GamepadChannel` enum is split into two disjoint enums for
|
|
623
795
|
nominal type safety:
|
|
624
796
|
|
|
625
|
-
| Old
|
|
626
|
-
|
|
627
|
-
| `GamepadChannel.ButtonSouth`
|
|
628
|
-
| `GamepadChannel.ButtonEast`
|
|
629
|
-
| `GamepadChannel.LeftShoulder`
|
|
630
|
-
| `GamepadChannel.LeftStickLeft` | `GamepadAxis.LeftStickLeft`
|
|
631
|
-
| ...
|
|
797
|
+
| Old | New (user-facing) | New (internal type) |
|
|
798
|
+
| ------------------------------ | ---------------------------- | ----------------------------------- |
|
|
799
|
+
| `GamepadChannel.ButtonSouth` | `GamepadButton.South` | `GamepadButtonChannel.South` |
|
|
800
|
+
| `GamepadChannel.ButtonEast` | `GamepadButton.East` | `GamepadButtonChannel.East` |
|
|
801
|
+
| `GamepadChannel.LeftShoulder` | `GamepadButton.LeftShoulder` | `GamepadButtonChannel.LeftShoulder` |
|
|
802
|
+
| `GamepadChannel.LeftStickLeft` | `GamepadAxis.LeftStickLeft` | `GamepadAxisChannel.LeftStickLeft` |
|
|
803
|
+
| ... | ... | ... |
|
|
632
804
|
|
|
633
805
|
User code references the namespace mirrors (`GamepadButton.X`,
|
|
634
806
|
`GamepadAxis.Y`) — same `Pointer.X` / `Keyboard.Space` convention. Type
|
|
@@ -670,11 +842,11 @@ instead of firing every frame.
|
|
|
670
842
|
|
|
671
843
|
```ts
|
|
672
844
|
// Before:
|
|
673
|
-
new Gamepad(index, channels, mapping)
|
|
674
|
-
new Gamepad(browserGamepad, channels, definition)
|
|
845
|
+
new Gamepad(index, channels, mapping);
|
|
846
|
+
new Gamepad(browserGamepad, channels, definition);
|
|
675
847
|
|
|
676
848
|
// After (engine-internal — InputManager handles slot allocation):
|
|
677
|
-
new Gamepad(slot, channels)
|
|
849
|
+
new Gamepad(slot, channels);
|
|
678
850
|
// followed by pad._bind(browserGamepad, definition) on connect
|
|
679
851
|
```
|
|
680
852
|
|
|
@@ -696,7 +868,7 @@ import { GamepadButton, Keyboard } from '@codexo/exojs';
|
|
|
696
868
|
|
|
697
869
|
// Manual lifecycle
|
|
698
870
|
const binding = app.input.onTrigger(GamepadButton.South, () => player.jump());
|
|
699
|
-
binding.unbind();
|
|
871
|
+
binding.unbind(); // when done
|
|
700
872
|
|
|
701
873
|
// Auto-disposed on scene unload
|
|
702
874
|
this.inputs.onTrigger(GamepadButton.South, () => player.jump());
|
|
@@ -707,37 +879,31 @@ this.app.input.gamepads[0].onTrigger(GamepadButton.South, () => player.jump());
|
|
|
707
879
|
|
|
708
880
|
```ts
|
|
709
881
|
// Stick movement — before:
|
|
710
|
-
const moveLeft
|
|
882
|
+
const moveLeft = new Input(GamepadChannel.LeftStickLeft);
|
|
711
883
|
const moveRight = new Input(GamepadChannel.LeftStickRight);
|
|
712
884
|
app.input.add(moveLeft);
|
|
713
885
|
app.input.add(moveRight);
|
|
714
886
|
// per frame: const x = moveRight.value - moveLeft.value;
|
|
715
887
|
|
|
716
888
|
// After (signed aggregate channel):
|
|
717
|
-
this.inputs.onActive(GamepadAxis.LeftStickX,
|
|
889
|
+
this.inputs.onActive(GamepadAxis.LeftStickX, x => (player.x += x * 5));
|
|
718
890
|
```
|
|
719
891
|
|
|
720
892
|
```ts
|
|
721
893
|
// Custom mapping — before:
|
|
722
894
|
import { GamepadMapping, GamepadChannel } from '@codexo/exojs';
|
|
723
895
|
const buttons = GamepadMapping.createControls([
|
|
724
|
-
|
|
725
|
-
|
|
896
|
+
[0, GamepadChannel.ButtonSouth],
|
|
897
|
+
[1, GamepadChannel.ButtonEast],
|
|
726
898
|
]);
|
|
727
899
|
|
|
728
900
|
// After:
|
|
729
901
|
import { GamepadButton, GamepadMapping, GamepadMappingFamily } from '@codexo/exojs';
|
|
730
902
|
class MyMapping extends GamepadMapping {
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
new GamepadButton(0, GamepadButton.South),
|
|
736
|
-
new GamepadButton(1, GamepadButton.East),
|
|
737
|
-
],
|
|
738
|
-
[],
|
|
739
|
-
);
|
|
740
|
-
}
|
|
903
|
+
public readonly family = GamepadMappingFamily.GenericDualAnalog;
|
|
904
|
+
public constructor() {
|
|
905
|
+
super([new GamepadButton(0, GamepadButton.South), new GamepadButton(1, GamepadButton.East)], []);
|
|
906
|
+
}
|
|
741
907
|
}
|
|
742
908
|
```
|
|
743
909
|
|
|
@@ -863,7 +1029,7 @@ indexing is now automatic and persistent).
|
|
|
863
1029
|
audio, collision, scene-graph, interaction. Each domain has its own
|
|
864
1030
|
script (`npm run perf:bench:rendering`, `:audio`, `:collision`,
|
|
865
1031
|
`:scene-graph`, `:interaction`) plus `:all` aggregator. Output: JSON
|
|
866
|
-
|
|
1032
|
+
- Markdown to `test/perf/results/`.
|
|
867
1033
|
- **Baseline snapshot** committed as `test/perf/results/baseline.md` —
|
|
868
1034
|
reference numbers at 0.7.10 for future regression detection.
|
|
869
1035
|
- **Auto-profiler** (`npm run perf:profile`, `:gc` variant with
|
|
@@ -903,6 +1069,7 @@ also makes the `useSpatialIndex` opt-in flag unnecessary and **the
|
|
|
903
1069
|
flag has been removed entirely**.
|
|
904
1070
|
|
|
905
1071
|
**How it works now:**
|
|
1072
|
+
|
|
906
1073
|
- A persistent quadtree is created lazily when the first interactive
|
|
907
1074
|
node enters the scene.
|
|
908
1075
|
- `Container.addChild` / `removeChild` walk subtrees and add/remove
|
|
@@ -943,7 +1110,7 @@ actually-moved nodes.
|
|
|
943
1110
|
|
|
944
1111
|
```ts
|
|
945
1112
|
// Before:
|
|
946
|
-
app.interaction.useSpatialIndex = true;
|
|
1113
|
+
app.interaction.useSpatialIndex = true; // flag opt-in
|
|
947
1114
|
|
|
948
1115
|
// After:
|
|
949
1116
|
// Nothing — index is automatic. Just have at least one interactive
|
|
@@ -1046,7 +1213,7 @@ Fixes a GLSL compile-error in the 0.7.8 shader auto-upgrade path.
|
|
|
1046
1213
|
### Fixed
|
|
1047
1214
|
|
|
1048
1215
|
- **`upgradeFragmentShaderToGl300()` now always prepends `precision highp
|
|
1049
|
-
|
|
1216
|
+
float;`** before the `out vec4 fragColor;` declaration. Previously, if
|
|
1050
1217
|
the user's source already contained a precision declaration anywhere
|
|
1051
1218
|
(e.g., `precision lowp float;` mid-source), the upgrader skipped its
|
|
1052
1219
|
own injection — but the user's declaration came AFTER the
|
|
@@ -1057,7 +1224,7 @@ Fixes a GLSL compile-error in the 0.7.8 shader auto-upgrade path.
|
|
|
1057
1224
|
|
|
1058
1225
|
Multiple precision declarations are legal in GLSL ES 3.00 with
|
|
1059
1226
|
last-precision-wins semantics. The fix always injects `precision highp
|
|
1060
|
-
|
|
1227
|
+
float;` at line 2 (before `out vec4 fragColor;`); the user's own
|
|
1061
1228
|
precision declaration further down still applies to their code via
|
|
1062
1229
|
the standard last-precision-wins rule. No semantic change for
|
|
1063
1230
|
user-provided shader logic; previously-broken shaders with custom
|
|
@@ -1256,7 +1423,7 @@ app.backend.setCursor('pointer');
|
|
|
1256
1423
|
const cursor = app.backend.cursor;
|
|
1257
1424
|
|
|
1258
1425
|
// After:
|
|
1259
|
-
app.setCursor('pointer');
|
|
1426
|
+
app.setCursor('pointer'); // or
|
|
1260
1427
|
app.cursor = 'pointer';
|
|
1261
1428
|
const cursor = app.cursor;
|
|
1262
1429
|
```
|
|
@@ -1264,14 +1431,14 @@ const cursor = app.cursor;
|
|
|
1264
1431
|
```ts
|
|
1265
1432
|
// New: react to backend loss
|
|
1266
1433
|
app.onBackendLost.add(() => {
|
|
1267
|
-
|
|
1434
|
+
showReloadDialog();
|
|
1268
1435
|
});
|
|
1269
1436
|
|
|
1270
1437
|
// Or backend-specific:
|
|
1271
1438
|
if (app.backend.backendType === RenderBackendType.WebGpu) {
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1439
|
+
(app.backend as WebGpuBackend).onDeviceLost.add(info => {
|
|
1440
|
+
console.error('GPU device lost:', info.message, info.reason);
|
|
1441
|
+
});
|
|
1275
1442
|
}
|
|
1276
1443
|
```
|
|
1277
1444
|
|
|
@@ -1380,9 +1547,9 @@ etc.).
|
|
|
1380
1547
|
separate `WebGpuShaderFilter`.
|
|
1381
1548
|
- **Backend guard messages updated**:
|
|
1382
1549
|
- `WebGl2ShaderFilter` on WebGPU: `'WebGl2ShaderFilter requires the
|
|
1383
|
-
|
|
1550
|
+
WebGL2 backend. Use WebGpuShaderFilter on WebGPU.'`
|
|
1384
1551
|
- `WebGpuShaderFilter` on WebGL2: `'WebGpuShaderFilter requires the
|
|
1385
|
-
|
|
1552
|
+
WebGPU backend. Use WebGl2ShaderFilter on WebGL2.'`
|
|
1386
1553
|
|
|
1387
1554
|
`ShaderFilterUniformValue` (the polymorphic uniform value type) is
|
|
1388
1555
|
**unchanged** and shared between both backends — same value shapes
|
|
@@ -1443,7 +1610,7 @@ LUT color grading, chromatic aberration, etc.
|
|
|
1443
1610
|
via property assignment; flushed before each apply():
|
|
1444
1611
|
```ts
|
|
1445
1612
|
filter.uniforms.uTime = performance.now() / 1000;
|
|
1446
|
-
filter.uniforms.uColor = [1, 0.5, 0, 1];
|
|
1613
|
+
filter.uniforms.uColor = [1, 0.5, 0, 1]; // vec4
|
|
1447
1614
|
```
|
|
1448
1615
|
- **Polymorphic uniform values**: scalar `number`, tuple `[a, b]` /
|
|
1449
1616
|
`[a, b, c]` / `[a, b, c, d]`, `Float32Array` / `Int32Array`, or
|
|
@@ -1458,8 +1625,8 @@ LUT color grading, chromatic aberration, etc.
|
|
|
1458
1625
|
|
|
1459
1626
|
- **WebGL2-only in V1.** Constructor accepts `wgsl` source, but `apply()`
|
|
1460
1627
|
on the WebGPU backend throws `'ShaderFilter does not yet support the
|
|
1461
|
-
|
|
1462
|
-
|
|
1628
|
+
WebGPU backend. WGSL support is planned for a future release. Use the
|
|
1629
|
+
WebGL2 backend for now.'` Document this limitation; reasoning: WebGPU
|
|
1463
1630
|
requires a separate WGSL pipeline implementation that's substantial
|
|
1464
1631
|
on its own. Coming when there's concrete user demand.
|
|
1465
1632
|
- `fragmentSource` is required at construction. Constructor throws if
|
|
@@ -1476,7 +1643,7 @@ LUT color grading, chromatic aberration, etc.
|
|
|
1476
1643
|
import { ShaderFilter } from '@codexo/exojs';
|
|
1477
1644
|
|
|
1478
1645
|
const filter = new ShaderFilter({
|
|
1479
|
-
|
|
1646
|
+
fragmentSource: `#version 300 es
|
|
1480
1647
|
precision highp float;
|
|
1481
1648
|
in vec2 vUv;
|
|
1482
1649
|
uniform sampler2D uTexture;
|
|
@@ -1489,15 +1656,15 @@ const filter = new ShaderFilter({
|
|
|
1489
1656
|
outColor = texture(uTexture, uv);
|
|
1490
1657
|
}
|
|
1491
1658
|
`,
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1659
|
+
uniforms: {
|
|
1660
|
+
uTime: 0,
|
|
1661
|
+
},
|
|
1495
1662
|
});
|
|
1496
1663
|
|
|
1497
1664
|
sprite.filters = [filter];
|
|
1498
1665
|
|
|
1499
|
-
app.onFrame.add(
|
|
1500
|
-
|
|
1666
|
+
app.onFrame.add(delta => {
|
|
1667
|
+
filter.uniforms.uTime = performance.now() / 1000;
|
|
1501
1668
|
});
|
|
1502
1669
|
```
|
|
1503
1670
|
|
|
@@ -1583,10 +1750,10 @@ const spectrum = analyser.getSpectrum();
|
|
|
1583
1750
|
const waveform = analyser.getWaveform();
|
|
1584
1751
|
|
|
1585
1752
|
// Now also possible:
|
|
1586
|
-
analyser.source = mediaStream;
|
|
1753
|
+
analyser.source = mediaStream; // Mic input
|
|
1587
1754
|
analyser.source = app.audio.master; // Whole mix
|
|
1588
|
-
analyser.getBandEnergy(20, 200);
|
|
1589
|
-
analyser.getLowMidHigh();
|
|
1755
|
+
analyser.getBandEnergy(20, 200); // Bass energy 0..1
|
|
1756
|
+
analyser.getLowMidHigh(); // {low, mid, high}
|
|
1590
1757
|
```
|
|
1591
1758
|
|
|
1592
1759
|
```ts
|
|
@@ -1596,12 +1763,12 @@ detector.source = music;
|
|
|
1596
1763
|
await detector.ready;
|
|
1597
1764
|
|
|
1598
1765
|
detector.onBeat.add(({ audioTime, tempo, isDownbeat, energy }) => {
|
|
1599
|
-
|
|
1600
|
-
|
|
1766
|
+
sprite.scale.set(1.5);
|
|
1767
|
+
new Tween().target(sprite.scale).to({ x: 1, y: 1 }).duration(200).start();
|
|
1601
1768
|
});
|
|
1602
1769
|
|
|
1603
1770
|
detector.onDownbeat.add(() => {
|
|
1604
|
-
|
|
1771
|
+
boss.attack(); // syncs exactly to "the 1" of each bar
|
|
1605
1772
|
});
|
|
1606
1773
|
```
|
|
1607
1774
|
|
|
@@ -1770,22 +1937,22 @@ breaking change.
|
|
|
1770
1937
|
|
|
1771
1938
|
```ts
|
|
1772
1939
|
// Before:
|
|
1773
|
-
sound.play();
|
|
1774
|
-
sound.playPooled();
|
|
1940
|
+
sound.play(); // singleton — second call replaces first
|
|
1941
|
+
sound.playPooled(); // multi-instance — concurrent plays
|
|
1775
1942
|
|
|
1776
1943
|
// After:
|
|
1777
|
-
sound.play();
|
|
1944
|
+
sound.play(); // multi-instance — concurrent plays (default!)
|
|
1778
1945
|
sound.play({ replace: true }); // singleton — equivalent of old play()
|
|
1779
1946
|
```
|
|
1780
1947
|
|
|
1781
1948
|
```ts
|
|
1782
1949
|
// Before — direct destination routing was implicit:
|
|
1783
1950
|
const sound = new Sound(buffer);
|
|
1784
|
-
sound.play();
|
|
1951
|
+
sound.play(); // → audioContext.destination
|
|
1785
1952
|
|
|
1786
1953
|
// After — routes through the soundBus by default:
|
|
1787
1954
|
const sound = new Sound(buffer);
|
|
1788
|
-
sound.play();
|
|
1955
|
+
sound.play(); // → app.audio.sound → app.audio.master → destination
|
|
1789
1956
|
|
|
1790
1957
|
// Override to a custom bus:
|
|
1791
1958
|
const dialogueBus = new AudioBus('dialogue', { parent: app.audio.master });
|
|
@@ -1796,8 +1963,8 @@ sound.bus = dialogueBus;
|
|
|
1796
1963
|
```ts
|
|
1797
1964
|
// Spatial audio:
|
|
1798
1965
|
const explosion = new Sound(buffer);
|
|
1799
|
-
explosion.position = { x: 200, y: 100 };
|
|
1800
|
-
app.audio.listener.target = playerSprite;
|
|
1966
|
+
explosion.position = { x: 200, y: 100 }; // becomes spatial
|
|
1967
|
+
app.audio.listener.target = playerSprite; // ears follow player
|
|
1801
1968
|
|
|
1802
1969
|
explosion.play();
|
|
1803
1970
|
// → routes through equalpower panner with distance falloff
|
|
@@ -1834,7 +2001,7 @@ infrastructure. Pure additive — no behavior changes for existing code.
|
|
|
1834
2001
|
**world-space position** via `getGlobalTransform()`, so following a
|
|
1835
2002
|
Sprite nested under a translated/rotated Container works correctly.
|
|
1836
2003
|
New exported type `ViewFollowTarget = SceneNode | { x: number; y:
|
|
1837
|
-
|
|
2004
|
+
number } | null`.
|
|
1838
2005
|
- **Audio fade helpers on `AbstractMedia`** — both `Sound` and `Music`
|
|
1839
2006
|
inherit:
|
|
1840
2007
|
- `fadeIn(durationMs): this` — ramps gain from 0 to current volume.
|
|
@@ -1901,7 +2068,7 @@ detection. Pure performance change — no public API surface changes.
|
|
|
1901
2068
|
components. Recomputes only when the sprite's transform or local
|
|
1902
2069
|
bounds change. Previously had a `// todo cache this` comment.
|
|
1903
2070
|
- **`Sprite.getNormals()`** returns a stable `[Vector, Vector,
|
|
1904
|
-
|
|
2071
|
+
Vector, Vector]` array. The four `Vector` instances are reused
|
|
1905
2072
|
across calls; previously each call allocated four new `Vector`s.
|
|
1906
2073
|
Recomputes only when vertices change. Reduces GC pressure in
|
|
1907
2074
|
collision-detection hot paths.
|
|
@@ -1983,7 +2150,7 @@ per-frame application hook.
|
|
|
1983
2150
|
|
|
1984
2151
|
- **`Application.debug` removed** — was added in 0.6.15. Apps that
|
|
1985
2152
|
used `app.debug.show()` must migrate to `import { DebugOverlay }
|
|
1986
|
-
|
|
2153
|
+
from '@codexo/exojs/debug'` and instantiate manually. **Breaking
|
|
1987
2154
|
change**, but the affected window is one day (0.6.15 → 0.6.17).
|
|
1988
2155
|
|
|
1989
2156
|
### Notes
|
|
@@ -2080,7 +2247,7 @@ zero cost when not shown.
|
|
|
2080
2247
|
|
|
2081
2248
|
Reshapes the interaction system around a per-frame tick and adds an
|
|
2082
2249
|
opt-in drag-and-drop helper. The public per-node signal API from 0.6.13
|
|
2083
|
-
is unchanged; only event
|
|
2250
|
+
is unchanged; only event _cadence_ and a new `draggable` flag.
|
|
2084
2251
|
|
|
2085
2252
|
### Added
|
|
2086
2253
|
|
|
@@ -2216,12 +2383,13 @@ existing surface changes shape.
|
|
|
2216
2383
|
properties on any target object:
|
|
2217
2384
|
|
|
2218
2385
|
```ts
|
|
2219
|
-
app.tweens
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2386
|
+
app.tweens
|
|
2387
|
+
.create(sprite)
|
|
2388
|
+
.to({ x: 100, alpha: 0.5 }, 1.0) // 1 second
|
|
2389
|
+
.easing(Ease.cubicOut)
|
|
2390
|
+
.delay(0.2)
|
|
2391
|
+
.onComplete(() => console.log('done'))
|
|
2392
|
+
.start();
|
|
2225
2393
|
```
|
|
2226
2394
|
|
|
2227
2395
|
Lifecycle: `Idle → Active → Complete | Stopped` (with
|
|
@@ -2233,6 +2401,7 @@ existing surface changes shape.
|
|
|
2233
2401
|
interpolation), `onUpdate` (per frame), `onRepeat` (cycle
|
|
2234
2402
|
boundaries), `onComplete` (final cycle ends naturally).
|
|
2235
2403
|
`stop()` does NOT fire `onComplete`.
|
|
2404
|
+
|
|
2236
2405
|
- **`TweenManager` class.** Owns active tweens and ticks them
|
|
2237
2406
|
from `Application.update()`. Use `app.tweens.create(target)` to
|
|
2238
2407
|
spawn-and-register a tween in one call; `app.tweens.add(tween)`
|
|
@@ -2328,7 +2497,7 @@ one atlas — memory-efficient at scale, single drawcall per Text.
|
|
|
2328
2497
|
|
|
2329
2498
|
- **`DynamicGlyphAtlas`** — public class. Constructor takes
|
|
2330
2499
|
`width = 1024, height = 1024`. Has `getGlyph(char, family, size,
|
|
2331
|
-
|
|
2500
|
+
weight, style) → GlyphInfo` (cached or rasterizes), `clear()` to
|
|
2332
2501
|
reset, and `texture` for binding to a Mesh. Internal shelf
|
|
2333
2502
|
bin-packing; throws on atlas-full (LRU eviction is V2).
|
|
2334
2503
|
- **`layoutText(text, style, atlas)`** — pure function. Returns
|
|
@@ -2340,7 +2509,7 @@ one atlas — memory-efficient at scale, single drawcall per Text.
|
|
|
2340
2509
|
their own atlas / layout pipelines.
|
|
2341
2510
|
- **TextStyle gets `fillColor: Color`** (defaults to white, used
|
|
2342
2511
|
via mesh.tint after glyph rasterization), **`fontStyle: 'normal'
|
|
2343
|
-
|
|
2512
|
+
| 'italic'`**, and **`lineHeight: number`** (multiplied by
|
|
2344
2513
|
fontSize for line spacing, defaults to 1.2). `align` field is
|
|
2345
2514
|
now strongly typed as `TextAlignment`.
|
|
2346
2515
|
|
|
@@ -2370,8 +2539,8 @@ one atlas — memory-efficient at scale, single drawcall per Text.
|
|
|
2370
2539
|
`document.createElement('canvas')` (works in jsdom / older
|
|
2371
2540
|
browsers).
|
|
2372
2541
|
- First-render of a never-seen glyph costs one canvas2d round-trip
|
|
2373
|
-
|
|
2374
|
-
|
|
2542
|
+
- texture re-upload. Cached glyphs are zero-cost on subsequent
|
|
2543
|
+
renders.
|
|
2375
2544
|
- Per-character animation, MSDF rendering, word-wrap, BiDi, and
|
|
2376
2545
|
text outlines / drop-shadows are all V2.
|
|
2377
2546
|
|
|
@@ -2540,7 +2709,7 @@ one unified rendering path for everything triangle-shaped.
|
|
|
2540
2709
|
(`buildLine`, `buildPath`, `buildCircle`, `buildEllipse`,
|
|
2541
2710
|
`buildRectangle`, `buildPolygon`, `buildStar`) now return a
|
|
2542
2711
|
`MeshGeometryData` plain object — `{ vertices: Float32Array,
|
|
2543
|
-
|
|
2712
|
+
indices: Uint16Array, points: Array<number> }` — directly suitable
|
|
2544
2713
|
for `new Mesh({ ... })`.
|
|
2545
2714
|
- **`WebGl2PrimitiveRenderer` and `WebGpuPrimitiveRenderer` removed.**
|
|
2546
2715
|
Their work moved entirely into the existing `*MeshRenderer`s. Both
|
|
@@ -2569,18 +2738,14 @@ one unified rendering path for everything triangle-shaped.
|
|
|
2569
2738
|
// Before (0.6.4)
|
|
2570
2739
|
import { DrawableShape, Geometry, RenderingPrimitives, Color } from '@codexo/exojs';
|
|
2571
2740
|
|
|
2572
|
-
const shape = new DrawableShape(
|
|
2573
|
-
new Geometry({ vertices: [0, 0, 100, 0, 50, 100], indices: [0, 1, 2] }),
|
|
2574
|
-
Color.red,
|
|
2575
|
-
RenderingPrimitives.Triangles,
|
|
2576
|
-
);
|
|
2741
|
+
const shape = new DrawableShape(new Geometry({ vertices: [0, 0, 100, 0, 50, 100], indices: [0, 1, 2] }), Color.red, RenderingPrimitives.Triangles);
|
|
2577
2742
|
|
|
2578
2743
|
// After (0.6.5)
|
|
2579
2744
|
import { Mesh, Color } from '@codexo/exojs';
|
|
2580
2745
|
|
|
2581
2746
|
const mesh = new Mesh({
|
|
2582
|
-
|
|
2583
|
-
|
|
2747
|
+
vertices: new Float32Array([0, 0, 100, 0, 50, 100]),
|
|
2748
|
+
indices: new Uint16Array([0, 1, 2]),
|
|
2584
2749
|
});
|
|
2585
2750
|
mesh.tint = Color.red;
|
|
2586
2751
|
```
|
|
@@ -2656,13 +2821,13 @@ match the rest of ExoJS.
|
|
|
2656
2821
|
```ts
|
|
2657
2822
|
// Before (0.6.3)
|
|
2658
2823
|
import { capabilities, isSupported } from '@codexo/exojs';
|
|
2659
|
-
if (capabilities.webgpu) startWebGpu();
|
|
2824
|
+
if (capabilities.webgpu) startWebGpu(); // false positives possible
|
|
2660
2825
|
if (isSupported('touch')) showTouchUi();
|
|
2661
2826
|
|
|
2662
2827
|
// After (0.6.4)
|
|
2663
2828
|
import { Capabilities } from '@codexo/exojs';
|
|
2664
2829
|
const caps = await Capabilities.ready;
|
|
2665
|
-
if (caps.webgpuAdapter) startWebGpu();
|
|
2830
|
+
if (caps.webgpuAdapter) startWebGpu(); // strict adapter check
|
|
2666
2831
|
if (caps.touch) showTouchUi();
|
|
2667
2832
|
|
|
2668
2833
|
// Or via Application after start:
|
|
@@ -2782,12 +2947,12 @@ and breaks freely between minors.
|
|
|
2782
2947
|
- **`Scene` is class-only; the plain-object definition constructor is
|
|
2783
2948
|
gone.** `new Scene({ update() { ... } })` no longer works. Subclass
|
|
2784
2949
|
to define a scene — `class GameScene extends Scene { override
|
|
2785
|
-
|
|
2786
|
-
|
|
2950
|
+
update(...) { ... } }` for named scenes, `new class extends Scene
|
|
2951
|
+
{ ... }` for one-offs. The `SceneData` interface and
|
|
2787
2952
|
`SceneInstance<T>` type alias are removed (they only existed to
|
|
2788
2953
|
type the spread-into-`this` constructor). Internal Scene fields
|
|
2789
2954
|
move from ECMAScript `#`-private to TS `protected _app/_root/
|
|
2790
|
-
|
|
2955
|
+
_stackMode/_inputMode` — subclasses can now reach internal state
|
|
2791
2956
|
directly when they need to.
|
|
2792
2957
|
- **npm package shape simplified.** Dropped: `dist/exo.global.js` /
|
|
2793
2958
|
`dist/exo.global.min.js` (legacy IIFE for `<script>` use) and
|
|
@@ -2848,33 +3013,49 @@ and breaks freely between minors.
|
|
|
2848
3013
|
```ts
|
|
2849
3014
|
// Before (0.5.x)
|
|
2850
3015
|
class GameScene extends Scene {
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
3016
|
+
override draw(runtime: SceneRenderRuntime): void {
|
|
3017
|
+
this.root.render(runtime);
|
|
3018
|
+
}
|
|
2854
3019
|
}
|
|
2855
3020
|
|
|
2856
3021
|
const triangleRenderer = new CustomRenderer(app.renderManager);
|
|
2857
3022
|
|
|
2858
|
-
if (app.renderManager instanceof WebGpuRenderManager) {
|
|
3023
|
+
if (app.renderManager instanceof WebGpuRenderManager) {
|
|
3024
|
+
/* ... */
|
|
3025
|
+
}
|
|
2859
3026
|
|
|
2860
3027
|
// Plain-object scene
|
|
2861
|
-
app.start(
|
|
3028
|
+
app.start(
|
|
3029
|
+
new Scene({
|
|
3030
|
+
update() {
|
|
3031
|
+
/* ... */
|
|
3032
|
+
},
|
|
3033
|
+
}),
|
|
3034
|
+
);
|
|
2862
3035
|
```
|
|
2863
3036
|
|
|
2864
3037
|
```ts
|
|
2865
3038
|
// After (0.6.0)
|
|
2866
3039
|
class GameScene extends Scene {
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
3040
|
+
override draw(backend: RenderBackend): void {
|
|
3041
|
+
this.root.render(backend);
|
|
3042
|
+
}
|
|
2870
3043
|
}
|
|
2871
3044
|
|
|
2872
3045
|
const triangleRenderer = new CustomRenderer(app.backend);
|
|
2873
3046
|
|
|
2874
|
-
if (app.backend instanceof WebGpuBackend) {
|
|
3047
|
+
if (app.backend instanceof WebGpuBackend) {
|
|
3048
|
+
/* ... */
|
|
3049
|
+
}
|
|
2875
3050
|
|
|
2876
3051
|
// Anonymous-subclass scene (or named subclass)
|
|
2877
|
-
app.start(
|
|
3052
|
+
app.start(
|
|
3053
|
+
new (class extends Scene {
|
|
3054
|
+
override update() {
|
|
3055
|
+
/* ... */
|
|
3056
|
+
}
|
|
3057
|
+
})(),
|
|
3058
|
+
);
|
|
2878
3059
|
```
|
|
2879
3060
|
|
|
2880
3061
|
## [0.5.1] - 2026-04-28
|
|
@@ -2968,6 +3149,7 @@ Three focused breaking changes targeted at the first pre-1.0 minor: a hierarchy-
|
|
|
2968
3149
|
- `null` — no mask.
|
|
2969
3150
|
|
|
2970
3151
|
Setting `node.mask = node` (self-mask) throws at runtime.
|
|
3152
|
+
|
|
2971
3153
|
- **`SceneRenderRuntime` mask primitives renamed** to match the new vocabulary:
|
|
2972
3154
|
- `pushMask(maskBounds)` / `popMask()` → `pushScissorRect(bounds)` / `popScissorRect()` (lower-level scissor primitive used internally by the `Rectangle` mask path).
|
|
2973
3155
|
- New `composeWithAlphaMask(content, mask, x, y, width, height, blendMode)` — used internally by the Texture/RenderTexture/RenderNode mask paths.
|
|
@@ -2985,19 +3167,19 @@ Three focused breaking changes targeted at the first pre-1.0 minor: a hierarchy-
|
|
|
2985
3167
|
|
|
2986
3168
|
### Migration
|
|
2987
3169
|
|
|
2988
|
-
| Before (0.4.x)
|
|
2989
|
-
|
|
2990
|
-
| `import { Transformable } from '@codexo/exojs'`; `class X extends Transformable`
|
|
2991
|
-
| `import { TransformableFlags } from '@codexo/exojs'`
|
|
2992
|
-
| `node.mask = anyShapeNode`
|
|
2993
|
-
| Want fast axis-aligned clipping?
|
|
2994
|
-
| Want to clip with a texture's alpha channel?
|
|
2995
|
-
| Want a transformed/positioned alpha mask?
|
|
2996
|
-
| `runtime.pushMask(rect)` / `runtime.popMask()`
|
|
2997
|
-
| `class Group extends SceneNode { override render() {...} }`
|
|
2998
|
-
| `class CustomContainer extends Container { override addChild(child: SceneNode) {...} }` | `class CustomContainer extends Container { override addChild(child: RenderNode) {...} }`
|
|
2999
|
-
| `Scene.create({ update() {...} })`
|
|
3000
|
-
| `Scene.create({})`
|
|
3170
|
+
| Before (0.4.x) | After |
|
|
3171
|
+
| --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
3172
|
+
| `import { Transformable } from '@codexo/exojs'`; `class X extends Transformable` | `import { SceneNode } from '@codexo/exojs'`; `class X extends SceneNode` |
|
|
3173
|
+
| `import { TransformableFlags } from '@codexo/exojs'` | Internal flag enum is no longer public; use SceneNode's high-level transform accessors instead. |
|
|
3174
|
+
| `node.mask = anyShapeNode` _(silently clipped to bounding rect)_ | `node.mask = anyShapeNode` _(now a real shape mask via alpha compositing — except bare SceneNode which is rejected at compile time)_ |
|
|
3175
|
+
| Want fast axis-aligned clipping? | `node.mask = new Rectangle(x, y, w, h)` |
|
|
3176
|
+
| Want to clip with a texture's alpha channel? | `node.mask = texture` or `node.mask = renderTexture` |
|
|
3177
|
+
| Want a transformed/positioned alpha mask? | `node.mask = new Sprite(texture)` (Sprite's transform/position/scale apply to the mask source) |
|
|
3178
|
+
| `runtime.pushMask(rect)` / `runtime.popMask()` | `runtime.pushScissorRect(rect)` / `runtime.popScissorRect()` (renamed; behavior unchanged) |
|
|
3179
|
+
| `class Group extends SceneNode { override render() {...} }` | `class Group extends RenderNode { override render() {...} }` |
|
|
3180
|
+
| `class CustomContainer extends Container { override addChild(child: SceneNode) {...} }` | `class CustomContainer extends Container { override addChild(child: RenderNode) {...} }` |
|
|
3181
|
+
| `Scene.create({ update() {...} })` | `new Scene({ update() {...} })` (drop-in replacement; same `this` typing via `ThisType<Scene & T>`) |
|
|
3182
|
+
| `Scene.create({})` | `new Scene()` |
|
|
3001
3183
|
|
|
3002
3184
|
No deprecated aliases are provided. The migration is mechanical and the project is pre-1.0 with explicit "may break between minors" policy.
|
|
3003
3185
|
|