@codexo/exojs 0.8.0 → 0.8.2
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 +318 -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 +1 -1
- package/dist/esm/audio/AudioAnalyser.js +2 -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 +4 -4
- package/dist/esm/audio/BeatDetector.js +68 -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/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/index.d.ts +3 -3
- package/dist/esm/debug/index.js +3 -3
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +99 -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 +11 -10
- package/dist/esm/rendering/filters/WebGpuShaderFilter.js.map +1 -1
- package/dist/esm/rendering/index.d.ts +28 -27
- package/dist/esm/rendering/mesh/Mesh.d.ts +49 -1
- package/dist/esm/rendering/mesh/Mesh.js +3 -1
- package/dist/esm/rendering/mesh/Mesh.js.map +1 -1
- 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/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 +19 -21
- 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 +110 -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 +7 -7
- package/dist/esm/rendering/webgpu/WebGpuBackend.js +44 -30
- 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 +1 -3
- package/dist/esm/rendering/webgpu/WebGpuMaskCompositor.js.map +1 -1
- package/dist/esm/rendering/webgpu/WebGpuMeshRenderer.d.ts +2 -2
- package/dist/esm/rendering/webgpu/WebGpuMeshRenderer.js +25 -23
- 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 +25798 -25144
- package/dist/exo.esm.js.map +1 -1
- package/package.json +15 -4
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,89 @@ 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.2] - 2026-05-09
|
|
8
|
+
|
|
9
|
+
### Engine
|
|
10
|
+
|
|
11
|
+
- **`Mesh` accepts custom WebGL2 shaders.** New `MeshShaderConfig` + `MeshShaderUniformValue`
|
|
12
|
+
exports. Supply `shader: { vertexSource, fragmentSource, uniforms }` in `MeshOptions` to
|
|
13
|
+
bind a custom GLSL ES 3.00 program against the standard mesh vertex layout. Auto-bound
|
|
14
|
+
uniforms (`u_projection`, `u_translation`, `u_tint`, `u_texture`) are set only when the
|
|
15
|
+
shader declares them, so Shadertoy-style fullscreen passes can ignore them entirely.
|
|
16
|
+
Texture uniforms claim slots 1–7. WebGL2 only in this release; the WebGPU mesh
|
|
17
|
+
renderer throws a clear error pointing to the WebGL2 backend if `mesh.shader` is set.
|
|
18
|
+
|
|
19
|
+
- **Filter chain memory: ping-pong RT reuse.** `RenderNode._renderContentToTexture` now
|
|
20
|
+
releases the previous step's RenderTexture immediately after each `filter.apply`, so
|
|
21
|
+
the pool can hand the same memory back to the next step. Multi-filter chains drop from
|
|
22
|
+
N+1 simultaneously-allocated RTs to a steady-state of 2. ~60% RT-memory reduction on
|
|
23
|
+
4-filter 1080p chains. Behaviour-identical; no public API change.
|
|
24
|
+
|
|
25
|
+
### Site / Docs
|
|
26
|
+
|
|
27
|
+
- Part 2 "Core Concepts" guide section published (6 chapters, source-verified):
|
|
28
|
+
Application, Scenes, Scene lifecycle, Scene graph, Coordinates and views,
|
|
29
|
+
Loading and resources.
|
|
30
|
+
- Astro `6.3.0 → 6.3.1`, `@types/node 25.6.0 → 25.6.2` in site/.
|
|
31
|
+
|
|
32
|
+
### Verification
|
|
33
|
+
|
|
34
|
+
- Engine: 100/100 suites, 1266/1266 tests, lint:strict 0/0, typecheck clean.
|
|
35
|
+
- Site: build green (488 pages), check-ts 0/0, screenshot smoke 36/36.
|
|
36
|
+
|
|
37
|
+
## [0.8.1] - 2026-05-08
|
|
38
|
+
|
|
39
|
+
Three small additive features that close the remaining examples-driven API gaps from
|
|
40
|
+
the 0.8.0 audit, plus a long-overdue lint/format tooling consolidation and a 19-chapter
|
|
41
|
+
examples reorganisation.
|
|
42
|
+
|
|
43
|
+
### Added
|
|
44
|
+
|
|
45
|
+
- **`Sound` spatial falloff configuration.** `DistanceModel` type (`'linear' | 'inverse'
|
|
46
|
+
| 'exponential'`), plus optional `distanceModel`, `refDistance`, `maxDistance`, and
|
|
47
|
+
`rolloffFactor` fields on `SoundOptions`. The four are also exposed as live property
|
|
48
|
+
setters that lazy-forward to the attached `PannerNode`. New public `Sound.audioBuffer`
|
|
49
|
+
getter to share one decoded buffer across multiple `Sound` instances.
|
|
50
|
+
- **`LutFilter`** — new colour-pipeline primitive that maps every pixel through a
|
|
51
|
+
Look-Up Table texture. Supports both 1D LUTs (`N×1`, indexed by red channel — palette
|
|
52
|
+
cycling, indexed-colour effects) and 3D LUTs (`N²×N` unwrapped cube with trilinear
|
|
53
|
+
slice interpolation — cinematic colour grading, tone mapping, film stock emulation,
|
|
54
|
+
accessibility filters). Backend selection is automatic. Static helpers
|
|
55
|
+
`LutFilter.identityLut1D(size)`, `LutFilter.identityLut3D(size)`,
|
|
56
|
+
`LutFilter.fromImage(image)` cover the standard DaVinci/OBS/Photoshop LUT-export
|
|
57
|
+
workflows.
|
|
58
|
+
- **`CompressorFilter.reduction`** — public getter forwarding the live gain reduction
|
|
59
|
+
in dB from the underlying `DynamicsCompressorNode`. Use as a meter source for
|
|
60
|
+
visualisations or sidechain triggers.
|
|
61
|
+
|
|
62
|
+
### Examples
|
|
63
|
+
|
|
64
|
+
- Migrated `examples/public/examples/` to a 19-chapter pedagogical structure: getting
|
|
65
|
+
started, application & scenes, sprites & textures, tweens & animation, input, scene
|
|
66
|
+
graph, audio basics, spatial audio, filters, particles, text & fonts, geometry &
|
|
67
|
+
graphics, render targets, performance, audio FX, beat detection, debug layer, custom
|
|
68
|
+
renderers, showcase. Old chapter directories (`collision-detection`, `extras`,
|
|
69
|
+
`particle-system`, `rendering`, `webgpu`) removed.
|
|
70
|
+
- New examples: `spatial-audio/falloff-curves.js`, `filters/palette-cycling.js`,
|
|
71
|
+
`showcase/color-grading.js`. The compressor demo gained a live gain-reduction meter.
|
|
72
|
+
|
|
73
|
+
### Tooling
|
|
74
|
+
|
|
75
|
+
- ESLint config consolidated into a single `eslint.config.ts` driven by ESLint 10 +
|
|
76
|
+
`typescript-eslint`'s type-aware checks plus `simple-import-sort`,
|
|
77
|
+
`unused-imports`, `unicorn`, and `security` plugins. `lint:strict` is the
|
|
78
|
+
release-gate variant, scoped to `src/**/*.ts` and run with `--max-warnings=0` (warnings
|
|
79
|
+
fail the build); `lint` is the broader development view across `src`, `test`, and
|
|
80
|
+
examples. Per-subsystem override blocks are documented as known deviations to tighten
|
|
81
|
+
over time.
|
|
82
|
+
- Tightened to error: `eqeqeq`, `no-floating-promises`, `no-base-to-string`,
|
|
83
|
+
`only-throw-error`, `switch-exhaustiveness-check`, `no-non-null-assertion`,
|
|
84
|
+
`complexity` (cap 20). Added: `no-self-compare`, `no-unreachable-loop`,
|
|
85
|
+
`default-case-last`, `prefer-promise-reject-errors`, `no-promise-executor-return`,
|
|
86
|
+
`no-unmodified-loop-condition`, plus six TypeScript and six Unicorn correctness rules.
|
|
87
|
+
- Prettier `printWidth: 160`, `.editorconfig` matched. Engine code reformatted to
|
|
88
|
+
2-space indent.
|
|
89
|
+
|
|
7
90
|
## [0.8.0] - 2026-05-07
|
|
8
91
|
|
|
9
92
|
Wholesale rewrite of the particle subsystem around a data-oriented core
|
|
@@ -33,19 +116,19 @@ automatic and per-system; user code is unchanged across both paths.
|
|
|
33
116
|
`Uint32Array` / `Uint16Array` channels addressed by slot index:
|
|
34
117
|
|
|
35
118
|
```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
|
|
119
|
+
system.posX[slot];
|
|
120
|
+
system.posY[slot];
|
|
121
|
+
system.velX[slot];
|
|
122
|
+
system.velY[slot];
|
|
123
|
+
system.scaleX[slot];
|
|
124
|
+
system.scaleY[slot];
|
|
125
|
+
system.rotations[slot];
|
|
126
|
+
system.rotationSpeeds[slot];
|
|
127
|
+
system.color[slot]; // packed 0xAABBGGRR
|
|
128
|
+
system.elapsed[slot];
|
|
129
|
+
system.lifetime[slot];
|
|
130
|
+
system.textureIndex[slot];
|
|
131
|
+
system.liveCount; // [0, liveCount) is the live range
|
|
49
132
|
```
|
|
50
133
|
|
|
51
134
|
Capacity is fixed at construction (default 4096) — no reallocations.
|
|
@@ -57,17 +140,17 @@ instead of the previous O(n²) splice loop with scattered expirations).
|
|
|
57
140
|
|
|
58
141
|
Spawn-time random sampling and lifetime-parameterised evaluation:
|
|
59
142
|
|
|
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`
|
|
143
|
+
| Type | Use |
|
|
144
|
+
| --------------- | ----------------------------------------------------------------------------- |
|
|
145
|
+
| `Constant<T>` | Always-same value |
|
|
146
|
+
| `Range` | Uniform random number in `[min, max]` |
|
|
147
|
+
| `VectorRange` | Per-axis random vector |
|
|
148
|
+
| `ConeDirection` | Random unit vector in a cone × speed range |
|
|
149
|
+
| `CircleArea` | Random point in/on a circle |
|
|
150
|
+
| `BoxArea` | Random point in/on an AABB |
|
|
151
|
+
| `LineSegment` | Random point on a segment |
|
|
152
|
+
| `Curve` | Piecewise-linear keyframe scalar by lifetime ratio |
|
|
153
|
+
| `Gradient` | Piecewise-linear keyframe color, with `evaluateRgba()` for direct u32 packing |
|
|
71
154
|
|
|
72
155
|
`Curve` and `Gradient` cache the last segment so monotonically
|
|
73
156
|
advancing `t` (the typical case for per-particle lifetime sampling)
|
|
@@ -79,9 +162,15 @@ Three module bases. Each registered on a system via the corresponding
|
|
|
79
162
|
`addX` method; each runs in its declared phase per-frame.
|
|
80
163
|
|
|
81
164
|
```ts
|
|
82
|
-
abstract class SpawnModule
|
|
83
|
-
|
|
84
|
-
|
|
165
|
+
abstract class SpawnModule {
|
|
166
|
+
apply(system, dt: number): void;
|
|
167
|
+
}
|
|
168
|
+
abstract class UpdateModule {
|
|
169
|
+
apply(system, dt: number): void;
|
|
170
|
+
}
|
|
171
|
+
abstract class DeathModule {
|
|
172
|
+
onDeath(system, slot: number): void;
|
|
173
|
+
}
|
|
85
174
|
```
|
|
86
175
|
|
|
87
176
|
**Built-in spawn modules:**
|
|
@@ -121,7 +210,7 @@ for one `ParticleSystem`. At construction time it:
|
|
|
121
210
|
|
|
122
211
|
1. Walks the registered update modules, collecting each module's
|
|
123
212
|
`WgslContribution` (uniform field declarations + texture bindings
|
|
124
|
-
|
|
213
|
+
- WGSL body snippet).
|
|
125
214
|
2. Generates a composite WGSL compute shader: SoA storage bindings +
|
|
126
215
|
sim/module uniform structs + module texture bindings + a `main`
|
|
127
216
|
function containing integration → all module bodies in registration
|
|
@@ -151,8 +240,8 @@ Opt-in is a single constructor option — no imperative toggle:
|
|
|
151
240
|
|
|
152
241
|
```ts
|
|
153
242
|
const system = new ParticleSystem(texture, {
|
|
154
|
-
|
|
155
|
-
|
|
243
|
+
capacity: 8192,
|
|
244
|
+
backend: app.backend, // CPU-routed on WebGL2, GPU-routed on WebGPU
|
|
156
245
|
});
|
|
157
246
|
```
|
|
158
247
|
|
|
@@ -165,25 +254,25 @@ modules after that throws.
|
|
|
165
254
|
|
|
166
255
|
The following symbols are deleted. Migration recipes follow the table.
|
|
167
256
|
|
|
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`
|
|
257
|
+
| Removed | Replacement |
|
|
258
|
+
| -------------------------------------- | ------------------------------------------------------------- |
|
|
259
|
+
| `Particle` (class) | SoA arrays on `ParticleSystem` (`system.posX[slot]`, etc.) |
|
|
260
|
+
| `ParticleProperties` (interface) | None — slot-indexed arrays replace the per-particle object |
|
|
261
|
+
| `ParticleEmitter` (interface) | `SpawnModule` (abstract class) |
|
|
262
|
+
| `ParticleOptions` | Per-property `Distribution<T>` in the spawn module's config |
|
|
263
|
+
| `UniversalEmitter` | `RateSpawn` |
|
|
264
|
+
| `ParticleAffector` (interface) | `UpdateModule` (abstract class) |
|
|
265
|
+
| `ColorAffector` | `ColorOverLifetime` + `Gradient` |
|
|
266
|
+
| `ForceAffector` | `ApplyForce` |
|
|
267
|
+
| `ScaleAffector` | `ScaleOverLifetime` + `Curve` |
|
|
268
|
+
| `TorqueAffector` | `RotateOverLifetime` |
|
|
269
|
+
| `system.requestParticle()` | `system.spawn(): number` (slot index, or `-1` at capacity) |
|
|
270
|
+
| `system.emitParticle(p)` | (gone — `spawn()` already commits the slot to the live range) |
|
|
271
|
+
| `system.updateParticle(p, dt)` | (gone — internal to `update()`) |
|
|
272
|
+
| `system.addEmitter(e)` | `system.addSpawnModule(m)` |
|
|
273
|
+
| `system.addAffector(a)` | `system.addUpdateModule(m)` |
|
|
274
|
+
| `system.particles` (`Array<Particle>`) | `system.posX` / `system.posY` / ... `system.liveCount` |
|
|
275
|
+
| `system.graveyard` | (gone — no graveyard; slots are recycled in place) |
|
|
187
276
|
|
|
188
277
|
### Migration
|
|
189
278
|
|
|
@@ -203,16 +292,22 @@ options.velocity.set(/* ... */);
|
|
|
203
292
|
|
|
204
293
|
// After — bonfire
|
|
205
294
|
const system = new ParticleSystem(texture);
|
|
206
|
-
system.addSpawnModule(
|
|
295
|
+
system.addSpawnModule(
|
|
296
|
+
new RateSpawn({
|
|
207
297
|
rate: new Constant(50),
|
|
208
298
|
lifetime: new Range(5, 10),
|
|
209
299
|
position: new VectorRange(-50, 50, -10, 10),
|
|
210
300
|
velocity: new ConeDirection(-Math.PI / 2, Math.PI / 36, 60, 80),
|
|
211
|
-
})
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
301
|
+
}),
|
|
302
|
+
);
|
|
303
|
+
system.addUpdateModule(
|
|
304
|
+
new ColorOverLifetime(
|
|
305
|
+
new Gradient([
|
|
306
|
+
{ t: 0, color: new Color(194, 64, 30, 1) },
|
|
307
|
+
{ t: 1, color: new Color(0, 0, 0, 0) },
|
|
308
|
+
]),
|
|
309
|
+
),
|
|
310
|
+
);
|
|
216
311
|
// no per-frame mutation needed.
|
|
217
312
|
```
|
|
218
313
|
|
|
@@ -228,23 +323,23 @@ system.addUpdateModule(new ApplyForce(0, 980));
|
|
|
228
323
|
```ts
|
|
229
324
|
// Before — custom affector
|
|
230
325
|
class AlphaFade {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
326
|
+
apply(particle, delta) {
|
|
327
|
+
particle.tint.a = particle.remainingRatio;
|
|
328
|
+
return this;
|
|
329
|
+
}
|
|
330
|
+
destroy() {}
|
|
236
331
|
}
|
|
237
332
|
|
|
238
333
|
// After
|
|
239
334
|
class AlphaFadeOverLifetime extends UpdateModule {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
335
|
+
apply(system) {
|
|
336
|
+
const { color, elapsed, lifetime, liveCount } = system;
|
|
337
|
+
for (let i = 0; i < liveCount; i++) {
|
|
338
|
+
const remaining = 1 - elapsed[i] / lifetime[i];
|
|
339
|
+
const a = (Math.max(0, Math.min(1, remaining)) * 255) & 255;
|
|
340
|
+
color[i] = (color[i] & 0x00ffffff) | (a << 24);
|
|
247
341
|
}
|
|
342
|
+
}
|
|
248
343
|
}
|
|
249
344
|
```
|
|
250
345
|
|
|
@@ -279,12 +374,12 @@ new ParticleSystem(texture);
|
|
|
279
374
|
new ParticleSystem(texture, 4096);
|
|
280
375
|
|
|
281
376
|
// 0.8.0:
|
|
282
|
-
new ParticleSystem();
|
|
283
|
-
new ParticleSystem(spark);
|
|
284
|
-
new ParticleSystem(spark, { capacity: 8192 });
|
|
285
|
-
new ParticleSystem(atlas, [r0, r1, r2]);
|
|
377
|
+
new ParticleSystem(); // untextured (1×1 white), CPU/GPU auto-routed
|
|
378
|
+
new ParticleSystem(spark); // simple textured particles
|
|
379
|
+
new ParticleSystem(spark, { capacity: 8192 }); // explicit capacity
|
|
380
|
+
new ParticleSystem(atlas, [r0, r1, r2]); // multi-frame atlas
|
|
286
381
|
new ParticleSystem(atlas, frames, { capacity: 8192 }); // atlas + capacity
|
|
287
|
-
new ParticleSystem(sheet);
|
|
382
|
+
new ParticleSystem(sheet); // spritesheet shorthand
|
|
288
383
|
new ParticleSystem(sheet, { capacity: 4096 });
|
|
289
384
|
```
|
|
290
385
|
|
|
@@ -300,9 +395,9 @@ constructor(spritesheet: Spritesheet, options?: ParticleSystemOptions);
|
|
|
300
395
|
Compile-time errors for illegal combinations:
|
|
301
396
|
|
|
302
397
|
```ts
|
|
303
|
-
new ParticleSystem(spark, sheet);
|
|
304
|
-
new ParticleSystem(sheet, frames);
|
|
305
|
-
new ParticleSystem({ frames });
|
|
398
|
+
new ParticleSystem(spark, sheet); // ✗ no overload matches
|
|
399
|
+
new ParticleSystem(sheet, frames); // ✗ frames only valid with Texture
|
|
400
|
+
new ParticleSystem({ frames }); // ✗ frames isn't an option
|
|
306
401
|
```
|
|
307
402
|
|
|
308
403
|
**No `backend` option** — the renderer auto-discovers the active backend
|
|
@@ -326,19 +421,21 @@ frame chooser:
|
|
|
326
421
|
|
|
327
422
|
```ts
|
|
328
423
|
const system = new ParticleSystem({
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
424
|
+
texture: explosionAtlas,
|
|
425
|
+
frames: [
|
|
426
|
+
new Rectangle(0, 0, 32, 32), // index 0 — flame core
|
|
427
|
+
new Rectangle(32, 0, 32, 32), // index 1 — smoke ring
|
|
428
|
+
new Rectangle(64, 0, 32, 32), // index 2 — ember
|
|
429
|
+
],
|
|
335
430
|
});
|
|
336
431
|
|
|
337
|
-
system.addSpawnModule(
|
|
432
|
+
system.addSpawnModule(
|
|
433
|
+
new BurstSpawn({
|
|
338
434
|
schedule: [{ time: 0, count: 60 }],
|
|
339
435
|
velocity: ConeDirection.omni(120, 280),
|
|
340
|
-
textureIndex: new Range(0, 2),
|
|
341
|
-
})
|
|
436
|
+
textureIndex: new Range(0, 2), // each spawn picks a random frame
|
|
437
|
+
}),
|
|
438
|
+
);
|
|
342
439
|
```
|
|
343
440
|
|
|
344
441
|
`Spritesheet` integration via `spritesheet: sheet` extracts texture +
|
|
@@ -373,6 +470,7 @@ update). `spawn()` always returns the next sequential slot.
|
|
|
373
470
|
|
|
374
471
|
In GPU mode, no compaction happens — readback would be required to
|
|
375
472
|
move slots whose authoritative position lives in GPU memory. Instead:
|
|
473
|
+
|
|
376
474
|
- Each particle has an `alive: Uint8Array` flag (1 = alive, 0 = dead).
|
|
377
475
|
- `spawn()` finds the first dead slot via a round-robin hint pointer
|
|
378
476
|
(amortised O(1), worst case O(capacity)).
|
|
@@ -422,7 +520,7 @@ signed stick channels, and Joy-Con-honest mappings.
|
|
|
422
520
|
```ts
|
|
423
521
|
// Per inputManager (manual unbind):
|
|
424
522
|
app.input.onTrigger(GamepadButton.South, () => player.jump());
|
|
425
|
-
app.input.onActive(GamepadAxis.LeftStickX,
|
|
523
|
+
app.input.onActive(GamepadAxis.LeftStickX, v => (player.x += v * 5));
|
|
426
524
|
app.input.onStart([Keyboard.Space, GamepadButton.South], () => fire());
|
|
427
525
|
|
|
428
526
|
// Per gamepad (slot-aware, listener survives disconnect/reconnect):
|
|
@@ -466,8 +564,8 @@ default `'sticky'` (each pad keeps its slot through disconnects).
|
|
|
466
564
|
disconnect (good for hot-seat couch coop where "the first N pads are
|
|
467
565
|
the N players" is the desired semantic).
|
|
468
566
|
|
|
469
|
-
In compact mode, the disconnect signal fires on the slot that
|
|
470
|
-
|
|
567
|
+
In compact mode, the disconnect signal fires on the slot that _ended
|
|
568
|
+
up_ empty after the shift (not the slot the disconnected hardware
|
|
471
569
|
originally occupied), keeping `pad.connected === false` consistent with
|
|
472
570
|
the fired event. Slots that received a different physical pad through
|
|
473
571
|
the shift dispatch a separate signal:
|
|
@@ -481,6 +579,7 @@ player when slots renumber.
|
|
|
481
579
|
### Added — Generic signals
|
|
482
580
|
|
|
483
581
|
Per-pad:
|
|
582
|
+
|
|
484
583
|
- `pad.onConnect: Signal<[]>`
|
|
485
584
|
- `pad.onDisconnect: Signal<[]>`
|
|
486
585
|
- `pad.onButtonDown: Signal<[GamepadButton, number]>`
|
|
@@ -488,6 +587,7 @@ Per-pad:
|
|
|
488
587
|
- `pad.onAxisChange: Signal<[GamepadAxis, number]>`
|
|
489
588
|
|
|
490
589
|
Aggregate across all pads:
|
|
590
|
+
|
|
491
591
|
- `inputManager.onAnyGamepadButtonDown: Signal<[Gamepad, GamepadButton, number]>`
|
|
492
592
|
- `inputManager.onAnyGamepadButtonUp: Signal<[Gamepad, GamepadButton, number]>`
|
|
493
593
|
- `inputManager.onAnyGamepadAxisChange: Signal<[Gamepad, GamepadAxis, number]>`
|
|
@@ -496,7 +596,7 @@ Aggregate across all pads:
|
|
|
496
596
|
|
|
497
597
|
```ts
|
|
498
598
|
if (pad.canVibrate) {
|
|
499
|
-
|
|
599
|
+
await pad.vibrate({ duration: 200, weakMagnitude: 0.5, strongMagnitude: 1.0 });
|
|
500
600
|
}
|
|
501
601
|
pad.stopVibration();
|
|
502
602
|
```
|
|
@@ -517,18 +617,18 @@ remain available for buttons-style 0..1 input.
|
|
|
517
617
|
|
|
518
618
|
```ts
|
|
519
619
|
// Stick-style — one binding per axis, signed value:
|
|
520
|
-
this.inputs.onActive(GamepadAxis.LeftStickX,
|
|
620
|
+
this.inputs.onActive(GamepadAxis.LeftStickX, x => (player.x += x * 5));
|
|
521
621
|
|
|
522
622
|
// Buttons-style — separate bindings per direction, 0..1 each:
|
|
523
|
-
this.inputs.onActive(GamepadAxis.LeftStickLeft,
|
|
524
|
-
this.inputs.onActive(GamepadAxis.LeftStickRight,
|
|
623
|
+
this.inputs.onActive(GamepadAxis.LeftStickLeft, v => (player.x -= v * 5));
|
|
624
|
+
this.inputs.onActive(GamepadAxis.LeftStickRight, v => (player.x += v * 5));
|
|
525
625
|
```
|
|
526
626
|
|
|
527
627
|
### Added — `pad.hasChannel(channel)` capability check
|
|
528
628
|
|
|
529
629
|
```ts
|
|
530
630
|
if (pad.hasChannel(GamepadAxis.RightStickX)) {
|
|
531
|
-
|
|
631
|
+
pad.onActive(GamepadAxis.RightStickX, v => (crosshair.x += v * 8));
|
|
532
632
|
}
|
|
533
633
|
```
|
|
534
634
|
|
|
@@ -545,19 +645,19 @@ Internally tracks each binding and calls `.unbind()` in `Scene.destroy`.
|
|
|
545
645
|
### Added — Steam Deck / Steam Virtual Gamepad / Valve fallback
|
|
546
646
|
|
|
547
647
|
New `SteamDeckGamepadMapping` covers the raw HID layout reported by the
|
|
548
|
-
Steam Deck (and likely future Valve hardware) when Steam Input is
|
|
648
|
+
Steam Deck (and likely future Valve hardware) when Steam Input is _not_
|
|
549
649
|
intercepting the device. Indices follow the SDL_GameControllerDB Linux
|
|
550
650
|
entry: face buttons at 3-6, D-pad at 16-19, paddles at 20-23, triggers
|
|
551
651
|
as analog axes 8/9.
|
|
552
652
|
|
|
553
653
|
Routing rules added to `builtInGamepadDefinitions`:
|
|
554
654
|
|
|
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)
|
|
655
|
+
| Browser ID | Mapping |
|
|
656
|
+
| ---------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
|
|
657
|
+
| `28de:1102`, `28de:1142` | `SteamControllerGamepadMapping` (existing, original Steam Controller raw) |
|
|
658
|
+
| `28de:11ff` (Steam Virtual Gamepad — any controller via Steam Input) | `GenericDualAnalogGamepadMapping` (W3C standard Xbox emulation) |
|
|
659
|
+
| `28de:1205` | `SteamDeckGamepadMapping` (raw Steam Deck) |
|
|
660
|
+
| Vendor `28de` (anything else from Valve, e.g. future Steam Controller 2 raw) | `SteamDeckGamepadMapping` (best-effort fallback) |
|
|
561
661
|
|
|
562
662
|
Enum: `GamepadMappingFamily.SteamDeck` added.
|
|
563
663
|
|
|
@@ -610,7 +710,7 @@ app.input.getGamepad(0);
|
|
|
610
710
|
### Fixed — Compact-mode disconnect ordering
|
|
611
711
|
|
|
612
712
|
In `'compact'` slot strategy, `onDisconnect` previously fired on the
|
|
613
|
-
slot the disconnected hardware originally occupied —
|
|
713
|
+
slot the disconnected hardware originally occupied — _before_ the
|
|
614
714
|
compaction shift moved a different physical pad into that slot. User
|
|
615
715
|
code observing the event would see `pad.connected === true` because
|
|
616
716
|
the slot had been silently re-bound by the shift. Now compaction is
|
|
@@ -622,13 +722,13 @@ ended up empty (the trailing slot). Sticky behaviour is unchanged.
|
|
|
622
722
|
The unified `GamepadChannel` enum is split into two disjoint enums for
|
|
623
723
|
nominal type safety:
|
|
624
724
|
|
|
625
|
-
| Old
|
|
626
|
-
|
|
627
|
-
| `GamepadChannel.ButtonSouth`
|
|
628
|
-
| `GamepadChannel.ButtonEast`
|
|
629
|
-
| `GamepadChannel.LeftShoulder`
|
|
630
|
-
| `GamepadChannel.LeftStickLeft` | `GamepadAxis.LeftStickLeft`
|
|
631
|
-
| ...
|
|
725
|
+
| Old | New (user-facing) | New (internal type) |
|
|
726
|
+
| ------------------------------ | ---------------------------- | ----------------------------------- |
|
|
727
|
+
| `GamepadChannel.ButtonSouth` | `GamepadButton.South` | `GamepadButtonChannel.South` |
|
|
728
|
+
| `GamepadChannel.ButtonEast` | `GamepadButton.East` | `GamepadButtonChannel.East` |
|
|
729
|
+
| `GamepadChannel.LeftShoulder` | `GamepadButton.LeftShoulder` | `GamepadButtonChannel.LeftShoulder` |
|
|
730
|
+
| `GamepadChannel.LeftStickLeft` | `GamepadAxis.LeftStickLeft` | `GamepadAxisChannel.LeftStickLeft` |
|
|
731
|
+
| ... | ... | ... |
|
|
632
732
|
|
|
633
733
|
User code references the namespace mirrors (`GamepadButton.X`,
|
|
634
734
|
`GamepadAxis.Y`) — same `Pointer.X` / `Keyboard.Space` convention. Type
|
|
@@ -670,11 +770,11 @@ instead of firing every frame.
|
|
|
670
770
|
|
|
671
771
|
```ts
|
|
672
772
|
// Before:
|
|
673
|
-
new Gamepad(index, channels, mapping)
|
|
674
|
-
new Gamepad(browserGamepad, channels, definition)
|
|
773
|
+
new Gamepad(index, channels, mapping);
|
|
774
|
+
new Gamepad(browserGamepad, channels, definition);
|
|
675
775
|
|
|
676
776
|
// After (engine-internal — InputManager handles slot allocation):
|
|
677
|
-
new Gamepad(slot, channels)
|
|
777
|
+
new Gamepad(slot, channels);
|
|
678
778
|
// followed by pad._bind(browserGamepad, definition) on connect
|
|
679
779
|
```
|
|
680
780
|
|
|
@@ -696,7 +796,7 @@ import { GamepadButton, Keyboard } from '@codexo/exojs';
|
|
|
696
796
|
|
|
697
797
|
// Manual lifecycle
|
|
698
798
|
const binding = app.input.onTrigger(GamepadButton.South, () => player.jump());
|
|
699
|
-
binding.unbind();
|
|
799
|
+
binding.unbind(); // when done
|
|
700
800
|
|
|
701
801
|
// Auto-disposed on scene unload
|
|
702
802
|
this.inputs.onTrigger(GamepadButton.South, () => player.jump());
|
|
@@ -707,37 +807,31 @@ this.app.input.gamepads[0].onTrigger(GamepadButton.South, () => player.jump());
|
|
|
707
807
|
|
|
708
808
|
```ts
|
|
709
809
|
// Stick movement — before:
|
|
710
|
-
const moveLeft
|
|
810
|
+
const moveLeft = new Input(GamepadChannel.LeftStickLeft);
|
|
711
811
|
const moveRight = new Input(GamepadChannel.LeftStickRight);
|
|
712
812
|
app.input.add(moveLeft);
|
|
713
813
|
app.input.add(moveRight);
|
|
714
814
|
// per frame: const x = moveRight.value - moveLeft.value;
|
|
715
815
|
|
|
716
816
|
// After (signed aggregate channel):
|
|
717
|
-
this.inputs.onActive(GamepadAxis.LeftStickX,
|
|
817
|
+
this.inputs.onActive(GamepadAxis.LeftStickX, x => (player.x += x * 5));
|
|
718
818
|
```
|
|
719
819
|
|
|
720
820
|
```ts
|
|
721
821
|
// Custom mapping — before:
|
|
722
822
|
import { GamepadMapping, GamepadChannel } from '@codexo/exojs';
|
|
723
823
|
const buttons = GamepadMapping.createControls([
|
|
724
|
-
|
|
725
|
-
|
|
824
|
+
[0, GamepadChannel.ButtonSouth],
|
|
825
|
+
[1, GamepadChannel.ButtonEast],
|
|
726
826
|
]);
|
|
727
827
|
|
|
728
828
|
// After:
|
|
729
829
|
import { GamepadButton, GamepadMapping, GamepadMappingFamily } from '@codexo/exojs';
|
|
730
830
|
class MyMapping extends GamepadMapping {
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
new GamepadButton(0, GamepadButton.South),
|
|
736
|
-
new GamepadButton(1, GamepadButton.East),
|
|
737
|
-
],
|
|
738
|
-
[],
|
|
739
|
-
);
|
|
740
|
-
}
|
|
831
|
+
public readonly family = GamepadMappingFamily.GenericDualAnalog;
|
|
832
|
+
public constructor() {
|
|
833
|
+
super([new GamepadButton(0, GamepadButton.South), new GamepadButton(1, GamepadButton.East)], []);
|
|
834
|
+
}
|
|
741
835
|
}
|
|
742
836
|
```
|
|
743
837
|
|
|
@@ -863,7 +957,7 @@ indexing is now automatic and persistent).
|
|
|
863
957
|
audio, collision, scene-graph, interaction. Each domain has its own
|
|
864
958
|
script (`npm run perf:bench:rendering`, `:audio`, `:collision`,
|
|
865
959
|
`:scene-graph`, `:interaction`) plus `:all` aggregator. Output: JSON
|
|
866
|
-
|
|
960
|
+
- Markdown to `test/perf/results/`.
|
|
867
961
|
- **Baseline snapshot** committed as `test/perf/results/baseline.md` —
|
|
868
962
|
reference numbers at 0.7.10 for future regression detection.
|
|
869
963
|
- **Auto-profiler** (`npm run perf:profile`, `:gc` variant with
|
|
@@ -903,6 +997,7 @@ also makes the `useSpatialIndex` opt-in flag unnecessary and **the
|
|
|
903
997
|
flag has been removed entirely**.
|
|
904
998
|
|
|
905
999
|
**How it works now:**
|
|
1000
|
+
|
|
906
1001
|
- A persistent quadtree is created lazily when the first interactive
|
|
907
1002
|
node enters the scene.
|
|
908
1003
|
- `Container.addChild` / `removeChild` walk subtrees and add/remove
|
|
@@ -943,7 +1038,7 @@ actually-moved nodes.
|
|
|
943
1038
|
|
|
944
1039
|
```ts
|
|
945
1040
|
// Before:
|
|
946
|
-
app.interaction.useSpatialIndex = true;
|
|
1041
|
+
app.interaction.useSpatialIndex = true; // flag opt-in
|
|
947
1042
|
|
|
948
1043
|
// After:
|
|
949
1044
|
// Nothing — index is automatic. Just have at least one interactive
|
|
@@ -1046,7 +1141,7 @@ Fixes a GLSL compile-error in the 0.7.8 shader auto-upgrade path.
|
|
|
1046
1141
|
### Fixed
|
|
1047
1142
|
|
|
1048
1143
|
- **`upgradeFragmentShaderToGl300()` now always prepends `precision highp
|
|
1049
|
-
|
|
1144
|
+
float;`** before the `out vec4 fragColor;` declaration. Previously, if
|
|
1050
1145
|
the user's source already contained a precision declaration anywhere
|
|
1051
1146
|
(e.g., `precision lowp float;` mid-source), the upgrader skipped its
|
|
1052
1147
|
own injection — but the user's declaration came AFTER the
|
|
@@ -1057,7 +1152,7 @@ Fixes a GLSL compile-error in the 0.7.8 shader auto-upgrade path.
|
|
|
1057
1152
|
|
|
1058
1153
|
Multiple precision declarations are legal in GLSL ES 3.00 with
|
|
1059
1154
|
last-precision-wins semantics. The fix always injects `precision highp
|
|
1060
|
-
|
|
1155
|
+
float;` at line 2 (before `out vec4 fragColor;`); the user's own
|
|
1061
1156
|
precision declaration further down still applies to their code via
|
|
1062
1157
|
the standard last-precision-wins rule. No semantic change for
|
|
1063
1158
|
user-provided shader logic; previously-broken shaders with custom
|
|
@@ -1256,7 +1351,7 @@ app.backend.setCursor('pointer');
|
|
|
1256
1351
|
const cursor = app.backend.cursor;
|
|
1257
1352
|
|
|
1258
1353
|
// After:
|
|
1259
|
-
app.setCursor('pointer');
|
|
1354
|
+
app.setCursor('pointer'); // or
|
|
1260
1355
|
app.cursor = 'pointer';
|
|
1261
1356
|
const cursor = app.cursor;
|
|
1262
1357
|
```
|
|
@@ -1264,14 +1359,14 @@ const cursor = app.cursor;
|
|
|
1264
1359
|
```ts
|
|
1265
1360
|
// New: react to backend loss
|
|
1266
1361
|
app.onBackendLost.add(() => {
|
|
1267
|
-
|
|
1362
|
+
showReloadDialog();
|
|
1268
1363
|
});
|
|
1269
1364
|
|
|
1270
1365
|
// Or backend-specific:
|
|
1271
1366
|
if (app.backend.backendType === RenderBackendType.WebGpu) {
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1367
|
+
(app.backend as WebGpuBackend).onDeviceLost.add(info => {
|
|
1368
|
+
console.error('GPU device lost:', info.message, info.reason);
|
|
1369
|
+
});
|
|
1275
1370
|
}
|
|
1276
1371
|
```
|
|
1277
1372
|
|
|
@@ -1380,9 +1475,9 @@ etc.).
|
|
|
1380
1475
|
separate `WebGpuShaderFilter`.
|
|
1381
1476
|
- **Backend guard messages updated**:
|
|
1382
1477
|
- `WebGl2ShaderFilter` on WebGPU: `'WebGl2ShaderFilter requires the
|
|
1383
|
-
|
|
1478
|
+
WebGL2 backend. Use WebGpuShaderFilter on WebGPU.'`
|
|
1384
1479
|
- `WebGpuShaderFilter` on WebGL2: `'WebGpuShaderFilter requires the
|
|
1385
|
-
|
|
1480
|
+
WebGPU backend. Use WebGl2ShaderFilter on WebGL2.'`
|
|
1386
1481
|
|
|
1387
1482
|
`ShaderFilterUniformValue` (the polymorphic uniform value type) is
|
|
1388
1483
|
**unchanged** and shared between both backends — same value shapes
|
|
@@ -1443,7 +1538,7 @@ LUT color grading, chromatic aberration, etc.
|
|
|
1443
1538
|
via property assignment; flushed before each apply():
|
|
1444
1539
|
```ts
|
|
1445
1540
|
filter.uniforms.uTime = performance.now() / 1000;
|
|
1446
|
-
filter.uniforms.uColor = [1, 0.5, 0, 1];
|
|
1541
|
+
filter.uniforms.uColor = [1, 0.5, 0, 1]; // vec4
|
|
1447
1542
|
```
|
|
1448
1543
|
- **Polymorphic uniform values**: scalar `number`, tuple `[a, b]` /
|
|
1449
1544
|
`[a, b, c]` / `[a, b, c, d]`, `Float32Array` / `Int32Array`, or
|
|
@@ -1458,8 +1553,8 @@ LUT color grading, chromatic aberration, etc.
|
|
|
1458
1553
|
|
|
1459
1554
|
- **WebGL2-only in V1.** Constructor accepts `wgsl` source, but `apply()`
|
|
1460
1555
|
on the WebGPU backend throws `'ShaderFilter does not yet support the
|
|
1461
|
-
|
|
1462
|
-
|
|
1556
|
+
WebGPU backend. WGSL support is planned for a future release. Use the
|
|
1557
|
+
WebGL2 backend for now.'` Document this limitation; reasoning: WebGPU
|
|
1463
1558
|
requires a separate WGSL pipeline implementation that's substantial
|
|
1464
1559
|
on its own. Coming when there's concrete user demand.
|
|
1465
1560
|
- `fragmentSource` is required at construction. Constructor throws if
|
|
@@ -1476,7 +1571,7 @@ LUT color grading, chromatic aberration, etc.
|
|
|
1476
1571
|
import { ShaderFilter } from '@codexo/exojs';
|
|
1477
1572
|
|
|
1478
1573
|
const filter = new ShaderFilter({
|
|
1479
|
-
|
|
1574
|
+
fragmentSource: `#version 300 es
|
|
1480
1575
|
precision highp float;
|
|
1481
1576
|
in vec2 vUv;
|
|
1482
1577
|
uniform sampler2D uTexture;
|
|
@@ -1489,15 +1584,15 @@ const filter = new ShaderFilter({
|
|
|
1489
1584
|
outColor = texture(uTexture, uv);
|
|
1490
1585
|
}
|
|
1491
1586
|
`,
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1587
|
+
uniforms: {
|
|
1588
|
+
uTime: 0,
|
|
1589
|
+
},
|
|
1495
1590
|
});
|
|
1496
1591
|
|
|
1497
1592
|
sprite.filters = [filter];
|
|
1498
1593
|
|
|
1499
|
-
app.onFrame.add(
|
|
1500
|
-
|
|
1594
|
+
app.onFrame.add(delta => {
|
|
1595
|
+
filter.uniforms.uTime = performance.now() / 1000;
|
|
1501
1596
|
});
|
|
1502
1597
|
```
|
|
1503
1598
|
|
|
@@ -1583,10 +1678,10 @@ const spectrum = analyser.getSpectrum();
|
|
|
1583
1678
|
const waveform = analyser.getWaveform();
|
|
1584
1679
|
|
|
1585
1680
|
// Now also possible:
|
|
1586
|
-
analyser.source = mediaStream;
|
|
1681
|
+
analyser.source = mediaStream; // Mic input
|
|
1587
1682
|
analyser.source = app.audio.master; // Whole mix
|
|
1588
|
-
analyser.getBandEnergy(20, 200);
|
|
1589
|
-
analyser.getLowMidHigh();
|
|
1683
|
+
analyser.getBandEnergy(20, 200); // Bass energy 0..1
|
|
1684
|
+
analyser.getLowMidHigh(); // {low, mid, high}
|
|
1590
1685
|
```
|
|
1591
1686
|
|
|
1592
1687
|
```ts
|
|
@@ -1596,12 +1691,12 @@ detector.source = music;
|
|
|
1596
1691
|
await detector.ready;
|
|
1597
1692
|
|
|
1598
1693
|
detector.onBeat.add(({ audioTime, tempo, isDownbeat, energy }) => {
|
|
1599
|
-
|
|
1600
|
-
|
|
1694
|
+
sprite.scale.set(1.5);
|
|
1695
|
+
new Tween().target(sprite.scale).to({ x: 1, y: 1 }).duration(200).start();
|
|
1601
1696
|
});
|
|
1602
1697
|
|
|
1603
1698
|
detector.onDownbeat.add(() => {
|
|
1604
|
-
|
|
1699
|
+
boss.attack(); // syncs exactly to "the 1" of each bar
|
|
1605
1700
|
});
|
|
1606
1701
|
```
|
|
1607
1702
|
|
|
@@ -1770,22 +1865,22 @@ breaking change.
|
|
|
1770
1865
|
|
|
1771
1866
|
```ts
|
|
1772
1867
|
// Before:
|
|
1773
|
-
sound.play();
|
|
1774
|
-
sound.playPooled();
|
|
1868
|
+
sound.play(); // singleton — second call replaces first
|
|
1869
|
+
sound.playPooled(); // multi-instance — concurrent plays
|
|
1775
1870
|
|
|
1776
1871
|
// After:
|
|
1777
|
-
sound.play();
|
|
1872
|
+
sound.play(); // multi-instance — concurrent plays (default!)
|
|
1778
1873
|
sound.play({ replace: true }); // singleton — equivalent of old play()
|
|
1779
1874
|
```
|
|
1780
1875
|
|
|
1781
1876
|
```ts
|
|
1782
1877
|
// Before — direct destination routing was implicit:
|
|
1783
1878
|
const sound = new Sound(buffer);
|
|
1784
|
-
sound.play();
|
|
1879
|
+
sound.play(); // → audioContext.destination
|
|
1785
1880
|
|
|
1786
1881
|
// After — routes through the soundBus by default:
|
|
1787
1882
|
const sound = new Sound(buffer);
|
|
1788
|
-
sound.play();
|
|
1883
|
+
sound.play(); // → app.audio.sound → app.audio.master → destination
|
|
1789
1884
|
|
|
1790
1885
|
// Override to a custom bus:
|
|
1791
1886
|
const dialogueBus = new AudioBus('dialogue', { parent: app.audio.master });
|
|
@@ -1796,8 +1891,8 @@ sound.bus = dialogueBus;
|
|
|
1796
1891
|
```ts
|
|
1797
1892
|
// Spatial audio:
|
|
1798
1893
|
const explosion = new Sound(buffer);
|
|
1799
|
-
explosion.position = { x: 200, y: 100 };
|
|
1800
|
-
app.audio.listener.target = playerSprite;
|
|
1894
|
+
explosion.position = { x: 200, y: 100 }; // becomes spatial
|
|
1895
|
+
app.audio.listener.target = playerSprite; // ears follow player
|
|
1801
1896
|
|
|
1802
1897
|
explosion.play();
|
|
1803
1898
|
// → routes through equalpower panner with distance falloff
|
|
@@ -1834,7 +1929,7 @@ infrastructure. Pure additive — no behavior changes for existing code.
|
|
|
1834
1929
|
**world-space position** via `getGlobalTransform()`, so following a
|
|
1835
1930
|
Sprite nested under a translated/rotated Container works correctly.
|
|
1836
1931
|
New exported type `ViewFollowTarget = SceneNode | { x: number; y:
|
|
1837
|
-
|
|
1932
|
+
number } | null`.
|
|
1838
1933
|
- **Audio fade helpers on `AbstractMedia`** — both `Sound` and `Music`
|
|
1839
1934
|
inherit:
|
|
1840
1935
|
- `fadeIn(durationMs): this` — ramps gain from 0 to current volume.
|
|
@@ -1901,7 +1996,7 @@ detection. Pure performance change — no public API surface changes.
|
|
|
1901
1996
|
components. Recomputes only when the sprite's transform or local
|
|
1902
1997
|
bounds change. Previously had a `// todo cache this` comment.
|
|
1903
1998
|
- **`Sprite.getNormals()`** returns a stable `[Vector, Vector,
|
|
1904
|
-
|
|
1999
|
+
Vector, Vector]` array. The four `Vector` instances are reused
|
|
1905
2000
|
across calls; previously each call allocated four new `Vector`s.
|
|
1906
2001
|
Recomputes only when vertices change. Reduces GC pressure in
|
|
1907
2002
|
collision-detection hot paths.
|
|
@@ -1983,7 +2078,7 @@ per-frame application hook.
|
|
|
1983
2078
|
|
|
1984
2079
|
- **`Application.debug` removed** — was added in 0.6.15. Apps that
|
|
1985
2080
|
used `app.debug.show()` must migrate to `import { DebugOverlay }
|
|
1986
|
-
|
|
2081
|
+
from '@codexo/exojs/debug'` and instantiate manually. **Breaking
|
|
1987
2082
|
change**, but the affected window is one day (0.6.15 → 0.6.17).
|
|
1988
2083
|
|
|
1989
2084
|
### Notes
|
|
@@ -2080,7 +2175,7 @@ zero cost when not shown.
|
|
|
2080
2175
|
|
|
2081
2176
|
Reshapes the interaction system around a per-frame tick and adds an
|
|
2082
2177
|
opt-in drag-and-drop helper. The public per-node signal API from 0.6.13
|
|
2083
|
-
is unchanged; only event
|
|
2178
|
+
is unchanged; only event _cadence_ and a new `draggable` flag.
|
|
2084
2179
|
|
|
2085
2180
|
### Added
|
|
2086
2181
|
|
|
@@ -2216,12 +2311,13 @@ existing surface changes shape.
|
|
|
2216
2311
|
properties on any target object:
|
|
2217
2312
|
|
|
2218
2313
|
```ts
|
|
2219
|
-
app.tweens
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2314
|
+
app.tweens
|
|
2315
|
+
.create(sprite)
|
|
2316
|
+
.to({ x: 100, alpha: 0.5 }, 1.0) // 1 second
|
|
2317
|
+
.easing(Ease.cubicOut)
|
|
2318
|
+
.delay(0.2)
|
|
2319
|
+
.onComplete(() => console.log('done'))
|
|
2320
|
+
.start();
|
|
2225
2321
|
```
|
|
2226
2322
|
|
|
2227
2323
|
Lifecycle: `Idle → Active → Complete | Stopped` (with
|
|
@@ -2233,6 +2329,7 @@ existing surface changes shape.
|
|
|
2233
2329
|
interpolation), `onUpdate` (per frame), `onRepeat` (cycle
|
|
2234
2330
|
boundaries), `onComplete` (final cycle ends naturally).
|
|
2235
2331
|
`stop()` does NOT fire `onComplete`.
|
|
2332
|
+
|
|
2236
2333
|
- **`TweenManager` class.** Owns active tweens and ticks them
|
|
2237
2334
|
from `Application.update()`. Use `app.tweens.create(target)` to
|
|
2238
2335
|
spawn-and-register a tween in one call; `app.tweens.add(tween)`
|
|
@@ -2328,7 +2425,7 @@ one atlas — memory-efficient at scale, single drawcall per Text.
|
|
|
2328
2425
|
|
|
2329
2426
|
- **`DynamicGlyphAtlas`** — public class. Constructor takes
|
|
2330
2427
|
`width = 1024, height = 1024`. Has `getGlyph(char, family, size,
|
|
2331
|
-
|
|
2428
|
+
weight, style) → GlyphInfo` (cached or rasterizes), `clear()` to
|
|
2332
2429
|
reset, and `texture` for binding to a Mesh. Internal shelf
|
|
2333
2430
|
bin-packing; throws on atlas-full (LRU eviction is V2).
|
|
2334
2431
|
- **`layoutText(text, style, atlas)`** — pure function. Returns
|
|
@@ -2340,7 +2437,7 @@ one atlas — memory-efficient at scale, single drawcall per Text.
|
|
|
2340
2437
|
their own atlas / layout pipelines.
|
|
2341
2438
|
- **TextStyle gets `fillColor: Color`** (defaults to white, used
|
|
2342
2439
|
via mesh.tint after glyph rasterization), **`fontStyle: 'normal'
|
|
2343
|
-
|
|
2440
|
+
| 'italic'`**, and **`lineHeight: number`** (multiplied by
|
|
2344
2441
|
fontSize for line spacing, defaults to 1.2). `align` field is
|
|
2345
2442
|
now strongly typed as `TextAlignment`.
|
|
2346
2443
|
|
|
@@ -2370,8 +2467,8 @@ one atlas — memory-efficient at scale, single drawcall per Text.
|
|
|
2370
2467
|
`document.createElement('canvas')` (works in jsdom / older
|
|
2371
2468
|
browsers).
|
|
2372
2469
|
- First-render of a never-seen glyph costs one canvas2d round-trip
|
|
2373
|
-
|
|
2374
|
-
|
|
2470
|
+
- texture re-upload. Cached glyphs are zero-cost on subsequent
|
|
2471
|
+
renders.
|
|
2375
2472
|
- Per-character animation, MSDF rendering, word-wrap, BiDi, and
|
|
2376
2473
|
text outlines / drop-shadows are all V2.
|
|
2377
2474
|
|
|
@@ -2540,7 +2637,7 @@ one unified rendering path for everything triangle-shaped.
|
|
|
2540
2637
|
(`buildLine`, `buildPath`, `buildCircle`, `buildEllipse`,
|
|
2541
2638
|
`buildRectangle`, `buildPolygon`, `buildStar`) now return a
|
|
2542
2639
|
`MeshGeometryData` plain object — `{ vertices: Float32Array,
|
|
2543
|
-
|
|
2640
|
+
indices: Uint16Array, points: Array<number> }` — directly suitable
|
|
2544
2641
|
for `new Mesh({ ... })`.
|
|
2545
2642
|
- **`WebGl2PrimitiveRenderer` and `WebGpuPrimitiveRenderer` removed.**
|
|
2546
2643
|
Their work moved entirely into the existing `*MeshRenderer`s. Both
|
|
@@ -2569,18 +2666,14 @@ one unified rendering path for everything triangle-shaped.
|
|
|
2569
2666
|
// Before (0.6.4)
|
|
2570
2667
|
import { DrawableShape, Geometry, RenderingPrimitives, Color } from '@codexo/exojs';
|
|
2571
2668
|
|
|
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
|
-
);
|
|
2669
|
+
const shape = new DrawableShape(new Geometry({ vertices: [0, 0, 100, 0, 50, 100], indices: [0, 1, 2] }), Color.red, RenderingPrimitives.Triangles);
|
|
2577
2670
|
|
|
2578
2671
|
// After (0.6.5)
|
|
2579
2672
|
import { Mesh, Color } from '@codexo/exojs';
|
|
2580
2673
|
|
|
2581
2674
|
const mesh = new Mesh({
|
|
2582
|
-
|
|
2583
|
-
|
|
2675
|
+
vertices: new Float32Array([0, 0, 100, 0, 50, 100]),
|
|
2676
|
+
indices: new Uint16Array([0, 1, 2]),
|
|
2584
2677
|
});
|
|
2585
2678
|
mesh.tint = Color.red;
|
|
2586
2679
|
```
|
|
@@ -2656,13 +2749,13 @@ match the rest of ExoJS.
|
|
|
2656
2749
|
```ts
|
|
2657
2750
|
// Before (0.6.3)
|
|
2658
2751
|
import { capabilities, isSupported } from '@codexo/exojs';
|
|
2659
|
-
if (capabilities.webgpu) startWebGpu();
|
|
2752
|
+
if (capabilities.webgpu) startWebGpu(); // false positives possible
|
|
2660
2753
|
if (isSupported('touch')) showTouchUi();
|
|
2661
2754
|
|
|
2662
2755
|
// After (0.6.4)
|
|
2663
2756
|
import { Capabilities } from '@codexo/exojs';
|
|
2664
2757
|
const caps = await Capabilities.ready;
|
|
2665
|
-
if (caps.webgpuAdapter) startWebGpu();
|
|
2758
|
+
if (caps.webgpuAdapter) startWebGpu(); // strict adapter check
|
|
2666
2759
|
if (caps.touch) showTouchUi();
|
|
2667
2760
|
|
|
2668
2761
|
// Or via Application after start:
|
|
@@ -2782,12 +2875,12 @@ and breaks freely between minors.
|
|
|
2782
2875
|
- **`Scene` is class-only; the plain-object definition constructor is
|
|
2783
2876
|
gone.** `new Scene({ update() { ... } })` no longer works. Subclass
|
|
2784
2877
|
to define a scene — `class GameScene extends Scene { override
|
|
2785
|
-
|
|
2786
|
-
|
|
2878
|
+
update(...) { ... } }` for named scenes, `new class extends Scene
|
|
2879
|
+
{ ... }` for one-offs. The `SceneData` interface and
|
|
2787
2880
|
`SceneInstance<T>` type alias are removed (they only existed to
|
|
2788
2881
|
type the spread-into-`this` constructor). Internal Scene fields
|
|
2789
2882
|
move from ECMAScript `#`-private to TS `protected _app/_root/
|
|
2790
|
-
|
|
2883
|
+
_stackMode/_inputMode` — subclasses can now reach internal state
|
|
2791
2884
|
directly when they need to.
|
|
2792
2885
|
- **npm package shape simplified.** Dropped: `dist/exo.global.js` /
|
|
2793
2886
|
`dist/exo.global.min.js` (legacy IIFE for `<script>` use) and
|
|
@@ -2848,33 +2941,49 @@ and breaks freely between minors.
|
|
|
2848
2941
|
```ts
|
|
2849
2942
|
// Before (0.5.x)
|
|
2850
2943
|
class GameScene extends Scene {
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2944
|
+
override draw(runtime: SceneRenderRuntime): void {
|
|
2945
|
+
this.root.render(runtime);
|
|
2946
|
+
}
|
|
2854
2947
|
}
|
|
2855
2948
|
|
|
2856
2949
|
const triangleRenderer = new CustomRenderer(app.renderManager);
|
|
2857
2950
|
|
|
2858
|
-
if (app.renderManager instanceof WebGpuRenderManager) {
|
|
2951
|
+
if (app.renderManager instanceof WebGpuRenderManager) {
|
|
2952
|
+
/* ... */
|
|
2953
|
+
}
|
|
2859
2954
|
|
|
2860
2955
|
// Plain-object scene
|
|
2861
|
-
app.start(
|
|
2956
|
+
app.start(
|
|
2957
|
+
new Scene({
|
|
2958
|
+
update() {
|
|
2959
|
+
/* ... */
|
|
2960
|
+
},
|
|
2961
|
+
}),
|
|
2962
|
+
);
|
|
2862
2963
|
```
|
|
2863
2964
|
|
|
2864
2965
|
```ts
|
|
2865
2966
|
// After (0.6.0)
|
|
2866
2967
|
class GameScene extends Scene {
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2968
|
+
override draw(backend: RenderBackend): void {
|
|
2969
|
+
this.root.render(backend);
|
|
2970
|
+
}
|
|
2870
2971
|
}
|
|
2871
2972
|
|
|
2872
2973
|
const triangleRenderer = new CustomRenderer(app.backend);
|
|
2873
2974
|
|
|
2874
|
-
if (app.backend instanceof WebGpuBackend) {
|
|
2975
|
+
if (app.backend instanceof WebGpuBackend) {
|
|
2976
|
+
/* ... */
|
|
2977
|
+
}
|
|
2875
2978
|
|
|
2876
2979
|
// Anonymous-subclass scene (or named subclass)
|
|
2877
|
-
app.start(
|
|
2980
|
+
app.start(
|
|
2981
|
+
new (class extends Scene {
|
|
2982
|
+
override update() {
|
|
2983
|
+
/* ... */
|
|
2984
|
+
}
|
|
2985
|
+
})(),
|
|
2986
|
+
);
|
|
2878
2987
|
```
|
|
2879
2988
|
|
|
2880
2989
|
## [0.5.1] - 2026-04-28
|
|
@@ -2968,6 +3077,7 @@ Three focused breaking changes targeted at the first pre-1.0 minor: a hierarchy-
|
|
|
2968
3077
|
- `null` — no mask.
|
|
2969
3078
|
|
|
2970
3079
|
Setting `node.mask = node` (self-mask) throws at runtime.
|
|
3080
|
+
|
|
2971
3081
|
- **`SceneRenderRuntime` mask primitives renamed** to match the new vocabulary:
|
|
2972
3082
|
- `pushMask(maskBounds)` / `popMask()` → `pushScissorRect(bounds)` / `popScissorRect()` (lower-level scissor primitive used internally by the `Rectangle` mask path).
|
|
2973
3083
|
- New `composeWithAlphaMask(content, mask, x, y, width, height, blendMode)` — used internally by the Texture/RenderTexture/RenderNode mask paths.
|
|
@@ -2985,19 +3095,19 @@ Three focused breaking changes targeted at the first pre-1.0 minor: a hierarchy-
|
|
|
2985
3095
|
|
|
2986
3096
|
### Migration
|
|
2987
3097
|
|
|
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({})`
|
|
3098
|
+
| Before (0.4.x) | After |
|
|
3099
|
+
| --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
3100
|
+
| `import { Transformable } from '@codexo/exojs'`; `class X extends Transformable` | `import { SceneNode } from '@codexo/exojs'`; `class X extends SceneNode` |
|
|
3101
|
+
| `import { TransformableFlags } from '@codexo/exojs'` | Internal flag enum is no longer public; use SceneNode's high-level transform accessors instead. |
|
|
3102
|
+
| `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)_ |
|
|
3103
|
+
| Want fast axis-aligned clipping? | `node.mask = new Rectangle(x, y, w, h)` |
|
|
3104
|
+
| Want to clip with a texture's alpha channel? | `node.mask = texture` or `node.mask = renderTexture` |
|
|
3105
|
+
| Want a transformed/positioned alpha mask? | `node.mask = new Sprite(texture)` (Sprite's transform/position/scale apply to the mask source) |
|
|
3106
|
+
| `runtime.pushMask(rect)` / `runtime.popMask()` | `runtime.pushScissorRect(rect)` / `runtime.popScissorRect()` (renamed; behavior unchanged) |
|
|
3107
|
+
| `class Group extends SceneNode { override render() {...} }` | `class Group extends RenderNode { override render() {...} }` |
|
|
3108
|
+
| `class CustomContainer extends Container { override addChild(child: SceneNode) {...} }` | `class CustomContainer extends Container { override addChild(child: RenderNode) {...} }` |
|
|
3109
|
+
| `Scene.create({ update() {...} })` | `new Scene({ update() {...} })` (drop-in replacement; same `this` typing via `ThisType<Scene & T>`) |
|
|
3110
|
+
| `Scene.create({})` | `new Scene()` |
|
|
3001
3111
|
|
|
3002
3112
|
No deprecated aliases are provided. The migration is mechanical and the project is pre-1.0 with explicit "may break between minors" policy.
|
|
3003
3113
|
|