@bloopjs/toodle 0.0.100
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/LICENSE +21 -0
- package/README.md +44 -0
- package/dist/Toodle.d.ts +304 -0
- package/dist/Toodle.d.ts.map +1 -0
- package/dist/colors/mod.d.ts +872 -0
- package/dist/colors/mod.d.ts.map +1 -0
- package/dist/coreTypes/Color.d.ts +7 -0
- package/dist/coreTypes/Color.d.ts.map +1 -0
- package/dist/coreTypes/Point.d.ts +8 -0
- package/dist/coreTypes/Point.d.ts.map +1 -0
- package/dist/coreTypes/Size.d.ts +5 -0
- package/dist/coreTypes/Size.d.ts.map +1 -0
- package/dist/coreTypes/Transform.d.ts +16 -0
- package/dist/coreTypes/Transform.d.ts.map +1 -0
- package/dist/coreTypes/Vec2.d.ts +8 -0
- package/dist/coreTypes/Vec2.d.ts.map +1 -0
- package/dist/coreTypes/mod.d.ts +6 -0
- package/dist/coreTypes/mod.d.ts.map +1 -0
- package/dist/docs/snippets/add-remove-children.d.ts +1 -0
- package/dist/docs/snippets/basic-quad.d.ts +1 -0
- package/dist/docs/snippets/filter-linear.d.ts +1 -0
- package/dist/docs/snippets/filter-nearest.d.ts +1 -0
- package/dist/docs/snippets/flipxy.d.ts +1 -0
- package/dist/docs/snippets/hello-text.d.ts +1 -0
- package/dist/docs/snippets/jumbo-textures.d.ts +1 -0
- package/dist/docs/snippets/layer.d.ts +1 -0
- package/dist/docs/snippets/layout-edges.d.ts +1 -0
- package/dist/docs/snippets/layout-screen-and-world-space.d.ts +1 -0
- package/dist/docs/snippets/postprocess.d.ts +1 -0
- package/dist/docs/snippets/quad-size-scale.d.ts +1 -0
- package/dist/docs/snippets/quickstart.d.ts +1 -0
- package/dist/docs/snippets/repeat-texture-loading.d.ts +1 -0
- package/dist/docs/snippets/screen-shaders.d.ts +1 -0
- package/dist/docs/snippets/shader-color-flash.d.ts +1 -0
- package/dist/docs/snippets/shader-default.d.ts +1 -0
- package/dist/docs/snippets/shader-fill.d.ts +1 -0
- package/dist/docs/snippets/shapes-line.d.ts +1 -0
- package/dist/docs/snippets/sprite-region.d.ts +1 -0
- package/dist/docs/snippets/text-alignment.d.ts +1 -0
- package/dist/docs/snippets/text-shrink-to-fit.d.ts +1 -0
- package/dist/docs/snippets/text-word-wrap.d.ts +1 -0
- package/dist/docs/snippets/texture-bundles-prebaked.d.ts +1 -0
- package/dist/docs/snippets/texture-bundles.d.ts +1 -0
- package/dist/docs/snippets/transforms.d.ts +1 -0
- package/dist/docs/snippets/transparent-cropping.d.ts +1 -0
- package/dist/examples/0-hello.d.ts +1 -0
- package/dist/examples/1-hello.d.ts +1 -0
- package/dist/examples/1-hello.d.ts.map +1 -0
- package/dist/examples/1-quad.d.ts +1 -0
- package/dist/examples/10-resize.d.ts +1 -0
- package/dist/examples/10-resize.d.ts.map +1 -0
- package/dist/examples/11-bundle-test.d.ts +1 -0
- package/dist/examples/11-bundle-test.d.ts.map +1 -0
- package/dist/examples/12-transparent-pixel-cropping.d.ts +1 -0
- package/dist/examples/12-transparent-pixel-cropping.d.ts.map +1 -0
- package/dist/examples/13-crop.d.ts +1 -0
- package/dist/examples/13-crop.d.ts.map +1 -0
- package/dist/examples/14-bundle-bench.d.ts +1 -0
- package/dist/examples/14-bundle-bench.d.ts.map +1 -0
- package/dist/examples/15-text-layer.d.ts +1 -0
- package/dist/examples/15-text-layer.d.ts.map +1 -0
- package/dist/examples/16-jumbo-texture.d.ts +1 -0
- package/dist/examples/16-jumbo-textures.d.ts +1 -0
- package/dist/examples/16-screen-shader.d.ts +1 -0
- package/dist/examples/16-screen-shader.d.ts.map +1 -0
- package/dist/examples/17-lighting.d.ts +1 -0
- package/dist/examples/17-lighting.d.ts.map +1 -0
- package/dist/examples/17-translations.d.ts +1 -0
- package/dist/examples/18-blur.d.ts +1 -0
- package/dist/examples/19-postprocess.d.ts +1 -0
- package/dist/examples/19-screenshader.d.ts +1 -0
- package/dist/examples/2-shapes.d.ts +1 -0
- package/dist/examples/2-shapes.d.ts.map +1 -0
- package/dist/examples/3-shader.d.ts +1 -0
- package/dist/examples/3-shader.d.ts.map +1 -0
- package/dist/examples/4-shader-bench.d.ts +1 -0
- package/dist/examples/4-shader-bench.d.ts.map +1 -0
- package/dist/examples/5-z.d.ts +1 -0
- package/dist/examples/5-z.d.ts.map +1 -0
- package/dist/examples/6-atlas.d.ts +1 -0
- package/dist/examples/6-atlas.d.ts.map +1 -0
- package/dist/examples/7-text.d.ts +1 -0
- package/dist/examples/7-text.d.ts.map +1 -0
- package/dist/examples/8-text-bench.d.ts +1 -0
- package/dist/examples/8-text-bench.d.ts.map +1 -0
- package/dist/examples/9-alignment.d.ts +1 -0
- package/dist/examples/9-alignment.d.ts.map +1 -0
- package/dist/examples/main.d.ts +1 -0
- package/dist/examples/main.d.ts.map +1 -0
- package/dist/examples/util.d.ts +82 -0
- package/dist/examples/util.d.ts.map +1 -0
- package/dist/limits.d.ts +23 -0
- package/dist/limits.d.ts.map +1 -0
- package/dist/math/angle.d.ts +13 -0
- package/dist/math/angle.d.ts.map +1 -0
- package/dist/math/matrix.d.ts +26 -0
- package/dist/math/matrix.d.ts.map +1 -0
- package/dist/math/mod.d.ts +3 -0
- package/dist/math/mod.d.ts.map +1 -0
- package/dist/mod.d.ts +17 -0
- package/dist/mod.d.ts.map +1 -0
- package/dist/mod.js +19665 -0
- package/dist/mod.js.map +41 -0
- package/dist/postprocess.d.ts +10 -0
- package/dist/postprocess.d.ts.map +1 -0
- package/dist/scene/Batcher.d.ts +20 -0
- package/dist/scene/Batcher.d.ts.map +1 -0
- package/dist/scene/Camera.d.ts +16 -0
- package/dist/scene/Camera.d.ts.map +1 -0
- package/dist/scene/JumboQuadNode.d.ts +29 -0
- package/dist/scene/JumboQuadNode.d.ts.map +1 -0
- package/dist/scene/QuadNode.d.ts +159 -0
- package/dist/scene/QuadNode.d.ts.map +1 -0
- package/dist/scene/RenderComponent.d.ts +11 -0
- package/dist/scene/RenderComponent.d.ts.map +1 -0
- package/dist/scene/SceneNode.d.ts +300 -0
- package/dist/scene/SceneNode.d.ts.map +1 -0
- package/dist/scene/mod.d.ts +5 -0
- package/dist/scene/mod.d.ts.map +1 -0
- package/dist/screen/mod.d.ts +2 -0
- package/dist/screen/mod.d.ts.map +1 -0
- package/dist/screen/resolution.d.ts +5 -0
- package/dist/screen/resolution.d.ts.map +1 -0
- package/dist/shaders/EngineUniform.d.ts +9 -0
- package/dist/shaders/EngineUniform.d.ts.map +1 -0
- package/dist/shaders/IShader.d.ts +15 -0
- package/dist/shaders/IShader.d.ts.map +1 -0
- package/dist/shaders/QuadShader.d.ts +18 -0
- package/dist/shaders/QuadShader.d.ts.map +1 -0
- package/dist/shaders/ShaderDescriptor.d.ts +7 -0
- package/dist/shaders/ShaderDescriptor.d.ts.map +1 -0
- package/dist/shaders/mod.d.ts +6 -0
- package/dist/shaders/mod.d.ts.map +1 -0
- package/dist/shaders/parser.d.ts +8 -0
- package/dist/shaders/parser.d.ts.map +1 -0
- package/dist/shaders/postprocess/blur.d.ts +3 -0
- package/dist/shaders/postprocess/blur.d.ts.map +1 -0
- package/dist/shaders/postprocess/mod.d.ts +17 -0
- package/dist/shaders/postprocess/mod.d.ts.map +1 -0
- package/dist/shaders/samplers.d.ts +3 -0
- package/dist/shaders/samplers.d.ts.map +1 -0
- package/dist/shaders/wgsl/example.wgsl.d.ts +3 -0
- package/dist/shaders/wgsl/example.wgsl.d.ts.map +1 -0
- package/dist/shaders/wgsl/hello.wgsl.d.ts +3 -0
- package/dist/shaders/wgsl/hello.wgsl.d.ts.map +1 -0
- package/dist/shaders/wgsl/helloInstanced.wgsl.d.ts +3 -0
- package/dist/shaders/wgsl/helloInstanced.wgsl.d.ts.map +1 -0
- package/dist/shaders/wgsl/quad.wgsl.d.ts +3 -0
- package/dist/shaders/wgsl/quad.wgsl.d.ts.map +1 -0
- package/dist/src/Toodle.d.ts +303 -0
- package/dist/src/Toodle.d.ts.map +1 -0
- package/dist/src/colors/mod.d.ts +871 -0
- package/dist/src/coreTypes/Color.d.ts +6 -0
- package/dist/src/coreTypes/Color.d.ts.map +1 -0
- package/dist/src/coreTypes/Point.d.ts +7 -0
- package/dist/src/coreTypes/Point.d.ts.map +1 -0
- package/dist/src/coreTypes/Size.d.ts +4 -0
- package/dist/src/coreTypes/Size.d.ts.map +1 -0
- package/dist/src/coreTypes/Transform.d.ts +15 -0
- package/dist/src/coreTypes/Transform.d.ts.map +1 -0
- package/dist/src/coreTypes/Vec2.d.ts +7 -0
- package/dist/src/coreTypes/Vec2.d.ts.map +1 -0
- package/dist/src/coreTypes/mod.d.ts +5 -0
- package/dist/src/coreTypes/mod.d.ts.map +1 -0
- package/dist/src/limits.d.ts +22 -0
- package/dist/src/limits.d.ts.map +1 -0
- package/dist/src/math/angle.d.ts +12 -0
- package/dist/src/math/angle.d.ts.map +1 -0
- package/dist/src/math/matrix.d.ts +25 -0
- package/dist/src/math/matrix.d.ts.map +1 -0
- package/dist/src/math/mod.d.ts +2 -0
- package/dist/src/math/mod.d.ts.map +1 -0
- package/dist/src/mod.d.ts +16 -0
- package/dist/src/mod.d.ts.map +1 -0
- package/dist/src/postprocess.d.ts +10 -0
- package/dist/src/postprocess.d.ts.map +1 -0
- package/dist/src/scene/Batcher.d.ts +19 -0
- package/dist/src/scene/Batcher.d.ts.map +1 -0
- package/dist/src/scene/Camera.d.ts +15 -0
- package/dist/src/scene/Camera.d.ts.map +1 -0
- package/dist/src/scene/JumboQuadNode.d.ts +28 -0
- package/dist/src/scene/QuadNode.d.ts +158 -0
- package/dist/src/scene/QuadNode.d.ts.map +1 -0
- package/dist/src/scene/RenderComponent.d.ts +10 -0
- package/dist/src/scene/RenderComponent.d.ts.map +1 -0
- package/dist/src/scene/SceneNode.d.ts +299 -0
- package/dist/src/scene/SceneNode.d.ts.map +1 -0
- package/dist/src/scene/mod.d.ts +4 -0
- package/dist/src/scene/mod.d.ts.map +1 -0
- package/dist/src/screen/mod.d.ts +1 -0
- package/dist/src/screen/mod.d.ts.map +1 -0
- package/dist/src/screen/resolution.d.ts +4 -0
- package/dist/src/screen/resolution.d.ts.map +1 -0
- package/dist/src/shaders/EngineUniform.d.ts +8 -0
- package/dist/src/shaders/EngineUniform.d.ts.map +1 -0
- package/dist/src/shaders/IShader.d.ts +14 -0
- package/dist/src/shaders/IShader.d.ts.map +1 -0
- package/dist/src/shaders/QuadShader.d.ts +17 -0
- package/dist/src/shaders/QuadShader.d.ts.map +1 -0
- package/dist/src/shaders/ShaderDescriptor.d.ts +6 -0
- package/dist/src/shaders/ShaderDescriptor.d.ts.map +1 -0
- package/dist/src/shaders/mod.d.ts +5 -0
- package/dist/src/shaders/mod.d.ts.map +1 -0
- package/dist/src/shaders/parser.d.ts +7 -0
- package/dist/src/shaders/parser.d.ts.map +1 -0
- package/dist/src/shaders/postprocess/blur.d.ts +2 -0
- package/dist/src/shaders/postprocess/mod.d.ts +16 -0
- package/dist/src/shaders/postprocess/postprocess.d.ts +8 -0
- package/dist/src/shaders/postprocess/util.d.ts +2 -0
- package/dist/src/shaders/samplers.d.ts +2 -0
- package/dist/src/shaders/samplers.d.ts.map +1 -0
- package/dist/src/shaders/wgsl/example.wgsl.d.ts +2 -0
- package/dist/src/shaders/wgsl/example.wgsl.d.ts.map +1 -0
- package/dist/src/shaders/wgsl/hello.wgsl.d.ts +2 -0
- package/dist/src/shaders/wgsl/hello.wgsl.d.ts.map +1 -0
- package/dist/src/shaders/wgsl/helloInstanced.wgsl.d.ts +2 -0
- package/dist/src/shaders/wgsl/helloInstanced.wgsl.d.ts.map +1 -0
- package/dist/src/shaders/wgsl/quad.wgsl.d.ts +2 -0
- package/dist/src/shaders/wgsl/quad.wgsl.d.ts.map +1 -0
- package/dist/src/text/FontPipeline.d.ts +13 -0
- package/dist/src/text/FontPipeline.d.ts.map +1 -0
- package/dist/src/text/MsdfFont.d.ts +81 -0
- package/dist/src/text/MsdfFont.d.ts.map +1 -0
- package/dist/src/text/TextFormatting.d.ts +18 -0
- package/dist/src/text/TextFormatting.d.ts.map +1 -0
- package/dist/src/text/TextNode.d.ts +18 -0
- package/dist/src/text/TextNode.d.ts.map +1 -0
- package/dist/src/text/TextShader.d.ts +14 -0
- package/dist/src/text/TextShader.d.ts.map +1 -0
- package/dist/src/text/mod.d.ts +3 -0
- package/dist/src/text/mod.d.ts.map +1 -0
- package/dist/src/text/shaping.d.ts +38 -0
- package/dist/src/text/shaping.d.ts.map +1 -0
- package/dist/src/text/text.wgsl.d.ts +2 -0
- package/dist/src/text/text.wgsl.d.ts.map +1 -0
- package/dist/src/textures/AssetManager.d.ts +181 -0
- package/dist/src/textures/AssetManager.d.ts.map +1 -0
- package/dist/src/textures/NewTextureComputeShader.d.ts +28 -0
- package/dist/src/textures/TextureComputeShader.d.ts +20 -0
- package/dist/src/textures/TextureComputeShader.d.ts.map +1 -0
- package/dist/src/textures/crop.wgsl.d.ts +2 -0
- package/dist/src/textures/mod.d.ts +1 -0
- package/dist/src/textures/mod.d.ts.map +1 -0
- package/dist/src/textures/pixel-scraping.wgsl.d.ts +2 -0
- package/dist/src/textures/pixel-scraping.wgsl.d.ts.map +1 -0
- package/dist/src/textures/texture-processing.wgsl.d.ts +2 -0
- package/dist/src/textures/types.d.ts +176 -0
- package/dist/src/textures/types.d.ts.map +1 -0
- package/dist/src/textures/util.d.ts +7 -0
- package/dist/src/textures/util.d.ts.map +1 -0
- package/dist/src/utils/assert.d.ts +1 -0
- package/dist/src/utils/assert.d.ts.map +1 -0
- package/dist/src/utils/boilerplate.d.ts +10 -0
- package/dist/src/utils/boilerplate.d.ts.map +1 -0
- package/dist/src/utils/error.d.ts +7 -0
- package/dist/src/utils/error.d.ts.map +1 -0
- package/dist/src/utils/mod.d.ts +2 -0
- package/dist/src/utils/mod.d.ts.map +1 -0
- package/dist/src/utils/pool.d.ts +22 -0
- package/dist/src/utils/pool.d.ts.map +1 -0
- package/dist/test/math/matrix.test.d.ts +1 -0
- package/dist/test/scene/Batcher.test.d.ts +1 -0
- package/dist/test/scene/SceneNode.test.d.ts +1 -0
- package/dist/test/shader/parser.test.d.ts +1 -0
- package/dist/text/FontPipeline.d.ts +14 -0
- package/dist/text/FontPipeline.d.ts.map +1 -0
- package/dist/text/MsdfFont.d.ts +82 -0
- package/dist/text/MsdfFont.d.ts.map +1 -0
- package/dist/text/TextFormatting.d.ts +19 -0
- package/dist/text/TextFormatting.d.ts.map +1 -0
- package/dist/text/TextNode.d.ts +19 -0
- package/dist/text/TextNode.d.ts.map +1 -0
- package/dist/text/TextShader.d.ts +15 -0
- package/dist/text/TextShader.d.ts.map +1 -0
- package/dist/text/mod.d.ts +4 -0
- package/dist/text/mod.d.ts.map +1 -0
- package/dist/text/shaping.d.ts +39 -0
- package/dist/text/shaping.d.ts.map +1 -0
- package/dist/text/text.wgsl.d.ts +3 -0
- package/dist/text/text.wgsl.d.ts.map +1 -0
- package/dist/textures/AssetManager.d.ts +182 -0
- package/dist/textures/AssetManager.d.ts.map +1 -0
- package/dist/textures/TextureComputeShader.d.ts +21 -0
- package/dist/textures/TextureComputeShader.d.ts.map +1 -0
- package/dist/textures/mod.d.ts +2 -0
- package/dist/textures/mod.d.ts.map +1 -0
- package/dist/textures/pixel-scraping.wgsl.d.ts +3 -0
- package/dist/textures/pixel-scraping.wgsl.d.ts.map +1 -0
- package/dist/textures/types.d.ts +177 -0
- package/dist/textures/types.d.ts.map +1 -0
- package/dist/textures/util.d.ts +8 -0
- package/dist/textures/util.d.ts.map +1 -0
- package/dist/utils/assert.d.ts +2 -0
- package/dist/utils/assert.d.ts.map +1 -0
- package/dist/utils/boilerplate.d.ts +11 -0
- package/dist/utils/boilerplate.d.ts.map +1 -0
- package/dist/utils/error.d.ts +8 -0
- package/dist/utils/error.d.ts.map +1 -0
- package/dist/utils/mod.d.ts +3 -0
- package/dist/utils/mod.d.ts.map +1 -0
- package/dist/utils/pool.d.ts +23 -0
- package/dist/utils/pool.d.ts.map +1 -0
- package/package.json +47 -0
- package/src/Toodle.ts +853 -0
- package/src/colors/mod.ts +151 -0
- package/src/coreTypes/Color.ts +1 -0
- package/src/coreTypes/Point.ts +7 -0
- package/src/coreTypes/Size.ts +4 -0
- package/src/coreTypes/Transform.ts +16 -0
- package/src/coreTypes/Vec2.ts +7 -0
- package/src/coreTypes/mod.ts +5 -0
- package/src/globals.d.ts +4 -0
- package/src/limits.ts +23 -0
- package/src/math/angle.ts +17 -0
- package/src/math/matrix.ts +99 -0
- package/src/math/mod.ts +2 -0
- package/src/mod.ts +22 -0
- package/src/scene/Batcher.ts +61 -0
- package/src/scene/Camera.ts +69 -0
- package/src/scene/JumboQuadNode.ts +219 -0
- package/src/scene/QuadNode.ts +403 -0
- package/src/scene/RenderComponent.ts +12 -0
- package/src/scene/SceneNode.ts +668 -0
- package/src/scene/mod.ts +4 -0
- package/src/screen/mod.ts +1 -0
- package/src/screen/resolution.ts +1 -0
- package/src/shaders/EngineUniform.ts +11 -0
- package/src/shaders/IShader.ts +20 -0
- package/src/shaders/QuadShader.ts +288 -0
- package/src/shaders/ShaderDescriptor.ts +6 -0
- package/src/shaders/mod.ts +5 -0
- package/src/shaders/parser.ts +221 -0
- package/src/shaders/postprocess/blur.ts +245 -0
- package/src/shaders/postprocess/mod.ts +71 -0
- package/src/shaders/samplers.ts +13 -0
- package/src/shaders/wgsl/example.wgsl.ts +24 -0
- package/src/shaders/wgsl/hello.wgsl.ts +62 -0
- package/src/shaders/wgsl/helloInstanced.wgsl.ts +46 -0
- package/src/shaders/wgsl/quad.wgsl.ts +140 -0
- package/src/text/FontPipeline.ts +212 -0
- package/src/text/MsdfFont.ts +190 -0
- package/src/text/TextFormatting.ts +28 -0
- package/src/text/TextNode.ts +82 -0
- package/src/text/TextShader.ts +223 -0
- package/src/text/mod.ts +8 -0
- package/src/text/shaping.ts +280 -0
- package/src/text/text.wgsl.ts +149 -0
- package/src/textures/AssetManager.ts +746 -0
- package/src/textures/TextureComputeShader.ts +434 -0
- package/src/textures/mod.ts +1 -0
- package/src/textures/pixel-scraping.wgsl.ts +131 -0
- package/src/textures/types.ts +182 -0
- package/src/textures/util.ts +352 -0
- package/src/utils/assert.ts +5 -0
- package/src/utils/boilerplate.ts +110 -0
- package/src/utils/error.ts +14 -0
- package/src/utils/mod.ts +2 -0
- package/src/utils/pool.ts +42 -0
|
@@ -0,0 +1,668 @@
|
|
|
1
|
+
import { type Mat3, mat3, vec2 } from "wgpu-matrix";
|
|
2
|
+
import type { Point } from "../coreTypes/Point";
|
|
3
|
+
import type { Size } from "../coreTypes/Size";
|
|
4
|
+
import type { Transform } from "../coreTypes/Transform";
|
|
5
|
+
import type { Vec2 } from "../coreTypes/Vec2";
|
|
6
|
+
import { deg2rad, rad2deg } from "../math/angle";
|
|
7
|
+
import { createModelMatrix } from "../math/matrix";
|
|
8
|
+
import type { RenderComponent } from "./RenderComponent";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A node in the scene graph.
|
|
12
|
+
*
|
|
13
|
+
* This is a base class and is fairly low level. You will probably want to interact with
|
|
14
|
+
* the wrapper classes {@link Toodle['Node']} or {@link Toodle['Quad']} instead.
|
|
15
|
+
*/
|
|
16
|
+
export class SceneNode {
|
|
17
|
+
static nextId = 1;
|
|
18
|
+
|
|
19
|
+
id: number;
|
|
20
|
+
label?: string;
|
|
21
|
+
|
|
22
|
+
#isActive = true;
|
|
23
|
+
#layer: null | number = null;
|
|
24
|
+
#parent: SceneNode | null = null;
|
|
25
|
+
#key: string | null = null;
|
|
26
|
+
#kids: SceneNode[] = [];
|
|
27
|
+
#transform: Transform;
|
|
28
|
+
#matrix: Mat3 = mat3.identity();
|
|
29
|
+
#renderComponent: RenderComponent | null = null;
|
|
30
|
+
#idealSize: Size | null = null;
|
|
31
|
+
#positionProxy: Point;
|
|
32
|
+
#scaleProxy: Vec2;
|
|
33
|
+
|
|
34
|
+
#cache: RenderLayoutCache | null = null;
|
|
35
|
+
|
|
36
|
+
constructor(opts?: NodeOptions) {
|
|
37
|
+
this.id = opts?.id ?? SceneNode.nextId++;
|
|
38
|
+
|
|
39
|
+
if (opts?.rotation && opts?.rotationRadians) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
`Cannot set both rotation and rotationRadians for node ${opts?.label ?? this.id}`,
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
this.#transform = {
|
|
46
|
+
position: opts?.position ?? { x: 0, y: 0 },
|
|
47
|
+
scale: { x: 1, y: 1 },
|
|
48
|
+
size: opts?.idealSize ?? { width: 1, height: 1 },
|
|
49
|
+
rotation: opts?.rotationRadians ?? 0,
|
|
50
|
+
};
|
|
51
|
+
if (opts?.scale) this.scale = opts.scale;
|
|
52
|
+
if (opts?.rotation) this.rotation = opts.rotation;
|
|
53
|
+
|
|
54
|
+
this.#matrix = mat3.identity();
|
|
55
|
+
this.#renderComponent = opts?.render ?? null;
|
|
56
|
+
this.#layer = opts?.layer ?? null;
|
|
57
|
+
this.#isActive = opts?.isActive ?? true;
|
|
58
|
+
this.label = opts?.label ?? undefined;
|
|
59
|
+
this.#idealSize = opts?.idealSize ?? null;
|
|
60
|
+
this.#key = opts?.key ?? null;
|
|
61
|
+
|
|
62
|
+
for (const kid of opts?.kids ?? []) {
|
|
63
|
+
this.add(kid);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const self = this;
|
|
67
|
+
this.#positionProxy = {
|
|
68
|
+
get x() {
|
|
69
|
+
return self.#transform.position.x;
|
|
70
|
+
},
|
|
71
|
+
set x(value: number) {
|
|
72
|
+
self.#transform.position.x = value;
|
|
73
|
+
self.setDirty();
|
|
74
|
+
},
|
|
75
|
+
get y() {
|
|
76
|
+
return self.#transform.position.y;
|
|
77
|
+
},
|
|
78
|
+
set y(value: number) {
|
|
79
|
+
self.#transform.position.y = value;
|
|
80
|
+
self.setDirty();
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
this.#scaleProxy = {
|
|
85
|
+
get x() {
|
|
86
|
+
return self.#transform.scale.x;
|
|
87
|
+
},
|
|
88
|
+
set x(value: number) {
|
|
89
|
+
self.#transform.scale.x = value;
|
|
90
|
+
self.setDirty();
|
|
91
|
+
},
|
|
92
|
+
get y() {
|
|
93
|
+
return self.#transform.scale.y;
|
|
94
|
+
},
|
|
95
|
+
set y(value: number) {
|
|
96
|
+
self.#transform.scale.y = value;
|
|
97
|
+
self.setDirty();
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Add a child node and return the child node with this node set as its parent.
|
|
104
|
+
*/
|
|
105
|
+
add<T extends SceneNode>(kid: T, index?: number) {
|
|
106
|
+
kid.#parent = this;
|
|
107
|
+
if (index === undefined) {
|
|
108
|
+
this.#kids.push(kid);
|
|
109
|
+
} else {
|
|
110
|
+
this.#kids.splice(index, 0, kid);
|
|
111
|
+
}
|
|
112
|
+
kid.setDirty();
|
|
113
|
+
return kid;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Returns an array of the node's immediate kids.
|
|
118
|
+
*
|
|
119
|
+
* Note that these will be returned with a `SceneNode` type, but can be narrowed if you know the type of them,
|
|
120
|
+
* for eg:
|
|
121
|
+
*
|
|
122
|
+
* ```ts
|
|
123
|
+
* for (const kid of node.kids) {
|
|
124
|
+
* if (kid instanceof Scene.QuadNode) {
|
|
125
|
+
* console.log(kid.color)
|
|
126
|
+
* }
|
|
127
|
+
*
|
|
128
|
+
* if (kid instanceof Text.TextNode) {
|
|
129
|
+
* console.log(kid.text)
|
|
130
|
+
* }
|
|
131
|
+
* }
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
get kids() {
|
|
135
|
+
return this.#kids;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* The children of the node. Alias for {@link SceneNode.kids}.
|
|
140
|
+
*/
|
|
141
|
+
get children() {
|
|
142
|
+
return this.#kids;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Returns a reference to the node's transform.
|
|
147
|
+
*
|
|
148
|
+
* Do not edit this transform directly as it won't invalidate cache's correctly.
|
|
149
|
+
* Instead, use convenience properties {@link SceneNode.position}, {@link SceneNode.scale}, and {@link SceneNode.rotation}.
|
|
150
|
+
*/
|
|
151
|
+
get transform(): Transform {
|
|
152
|
+
return this.#transform;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Returns the key of the node as set when the node was created.
|
|
157
|
+
*
|
|
158
|
+
* This key can be used to reference the node from an external lookup system.
|
|
159
|
+
*/
|
|
160
|
+
get key() {
|
|
161
|
+
return this.#key ?? "";
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Returns the parent node. See https://toodle.gg/f849595b3ed13fc956fc1459a5cb5f0228f9d259/examples/transforms.html
|
|
166
|
+
*/
|
|
167
|
+
get parent() {
|
|
168
|
+
return this.#parent;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
set position(value: Point) {
|
|
172
|
+
this.#transform.position = value;
|
|
173
|
+
this.setDirty();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Position of the node in local space. For world space, use {@link SceneNode.bounds}.
|
|
178
|
+
*/
|
|
179
|
+
get position() {
|
|
180
|
+
return this.#positionProxy;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
set x(value: number) {
|
|
184
|
+
this.#transform.position.x = value;
|
|
185
|
+
this.setDirty();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* The local x coordinate of the node.
|
|
190
|
+
*/
|
|
191
|
+
get x() {
|
|
192
|
+
return this.#transform.position.x;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
set y(value: number) {
|
|
196
|
+
this.#transform.position.y = value;
|
|
197
|
+
this.setDirty();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* The local y coordinate of the node.
|
|
202
|
+
*/
|
|
203
|
+
get y() {
|
|
204
|
+
return this.#transform.position.y;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
set rotation(value: number) {
|
|
208
|
+
this.#transform.rotation = deg2rad(value);
|
|
209
|
+
this.setDirty();
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* The rotation of the node in degrees.
|
|
214
|
+
* For radians, see {@link SceneNode.rotationRadians}.
|
|
215
|
+
*/
|
|
216
|
+
get rotation() {
|
|
217
|
+
return rad2deg(this.#transform.rotation);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* The rotation of the node in radians.
|
|
222
|
+
* For degrees, see {@link SceneNode.rotation}.
|
|
223
|
+
*/
|
|
224
|
+
get rotationRadians() {
|
|
225
|
+
return this.#transform.rotation;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
set rotationRadians(value: number) {
|
|
229
|
+
this.#transform.rotation = value;
|
|
230
|
+
this.setDirty();
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* The scale of the node. See https://toodle.gg/f849595b3ed13fc956fc1459a5cb5f0228f9d259/examples/quad-size-scale.html
|
|
235
|
+
*/
|
|
236
|
+
get scale(): Vec2 {
|
|
237
|
+
return this.#scaleProxy;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
set scale(value: Vec2 | number) {
|
|
241
|
+
if (typeof value === "number") {
|
|
242
|
+
this.#transform.scale = { x: value, y: value };
|
|
243
|
+
} else {
|
|
244
|
+
this.#transform.scale = value;
|
|
245
|
+
}
|
|
246
|
+
this.setDirty();
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
set idealSize(value: Size | null) {
|
|
250
|
+
this.#idealSize = value;
|
|
251
|
+
this.setDirty();
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* The size of the node. See https://toodle.gg/f849595b3ed13fc956fc1459a5cb5f0228f9d259/examples/quad-size-scale.html
|
|
256
|
+
*/
|
|
257
|
+
|
|
258
|
+
get size() {
|
|
259
|
+
return this.#idealSize;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* The aspect ratio of the node.
|
|
264
|
+
* If the node has no defined size, the aspect ratio will be 1.
|
|
265
|
+
*/
|
|
266
|
+
get aspectRatio() {
|
|
267
|
+
if (!this.#idealSize) {
|
|
268
|
+
console.warn(
|
|
269
|
+
"Attempted to get aspect ratio of a node with no ideal size",
|
|
270
|
+
);
|
|
271
|
+
return 1;
|
|
272
|
+
}
|
|
273
|
+
return this.#idealSize.width / this.#idealSize.height;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* isActive is a boolean that determines if the node is active.
|
|
278
|
+
* If a node is not active, it will not be drawn.
|
|
279
|
+
* If any of a node's ancestors are not active, the node will not be active.
|
|
280
|
+
*/
|
|
281
|
+
get isActive() {
|
|
282
|
+
if (!this.#cache?.isActive) {
|
|
283
|
+
this.#cache ??= {};
|
|
284
|
+
|
|
285
|
+
let parent = this as SceneNode;
|
|
286
|
+
let isActive = this.#isActive;
|
|
287
|
+
while (isActive && parent.#parent) {
|
|
288
|
+
parent = parent.#parent;
|
|
289
|
+
isActive = isActive && parent.#isActive;
|
|
290
|
+
}
|
|
291
|
+
this.#cache.isActive = isActive;
|
|
292
|
+
}
|
|
293
|
+
return this.#cache.isActive;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
set isActive(value: boolean) {
|
|
297
|
+
this.#isActive = value;
|
|
298
|
+
this.setDirty();
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Nodes are batched for drawing based on their layer. Each layer will submit a separate draw call.
|
|
303
|
+
* Nodes with the same layer will be drawn in the order they are drawn with toodle.Draw
|
|
304
|
+
* Nodes with a higher layer will be drawn on top of nodes with a lower layer.
|
|
305
|
+
*/
|
|
306
|
+
get layer() {
|
|
307
|
+
if (this.#layer != null) {
|
|
308
|
+
return this.#layer;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if (!this.#cache?.layer) {
|
|
312
|
+
this.#cache ??= {};
|
|
313
|
+
|
|
314
|
+
let parent = this as SceneNode;
|
|
315
|
+
while (parent.#parent) {
|
|
316
|
+
parent = parent.#parent;
|
|
317
|
+
if (parent.hasExplicitLayer) {
|
|
318
|
+
this.#cache.layer = parent.#layer!;
|
|
319
|
+
return this.#cache.layer;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
this.#cache.layer = 0;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return this.#cache.layer;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Returns true if the node has an explicit layer set.
|
|
331
|
+
*
|
|
332
|
+
* If the node does not have an explicit layer but one of its ancestors does,
|
|
333
|
+
* its layer will be inherited from its parent.
|
|
334
|
+
*/
|
|
335
|
+
get hasExplicitLayer() {
|
|
336
|
+
return this.#layer != null;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
set layer(value: number) {
|
|
340
|
+
this.#layer = value;
|
|
341
|
+
this.setDirty();
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
get renderComponent() {
|
|
345
|
+
return this.#renderComponent;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* This is the model matrix of the node. See https://webgpufundamentals.org/webgpu/lessons/webgpu-matrix-math.html for more information.
|
|
350
|
+
*
|
|
351
|
+
* Do not edit this matrix directly as it is derived from the node's transform and will be overwritten.
|
|
352
|
+
*/
|
|
353
|
+
get matrix(): Float32Array {
|
|
354
|
+
if (!this.#cache?.matrix) {
|
|
355
|
+
this.#cache ??= {};
|
|
356
|
+
|
|
357
|
+
if (this.#parent) {
|
|
358
|
+
mat3.clone(this.#parent.matrix, this.#matrix);
|
|
359
|
+
} else {
|
|
360
|
+
mat3.identity(this.#matrix);
|
|
361
|
+
}
|
|
362
|
+
this.#cache.matrix = createModelMatrix(this.transform, this.#matrix);
|
|
363
|
+
}
|
|
364
|
+
return this.#cache.matrix;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Get the bounds of the node in world space
|
|
369
|
+
*/
|
|
370
|
+
get bounds(): Bounds {
|
|
371
|
+
if (!this.#cache?.bounds) {
|
|
372
|
+
this.#cache ??= {};
|
|
373
|
+
|
|
374
|
+
const height = this.size?.height ?? 0;
|
|
375
|
+
const width = this.size?.width ?? 0;
|
|
376
|
+
|
|
377
|
+
// we don't need to add the node's position to the points
|
|
378
|
+
// because the points are relative to the node's center
|
|
379
|
+
// and the matrix already applies the node's position
|
|
380
|
+
const corners = [
|
|
381
|
+
vec2.transformMat3([-width / 2, height / 2], this.matrix),
|
|
382
|
+
vec2.transformMat3([width / 2, height / 2], this.matrix),
|
|
383
|
+
vec2.transformMat3([-width / 2, -height / 2], this.matrix),
|
|
384
|
+
vec2.transformMat3([width / 2, -height / 2], this.matrix),
|
|
385
|
+
];
|
|
386
|
+
const center = vec2.transformMat3([0, 0], this.matrix);
|
|
387
|
+
|
|
388
|
+
const xValues = corners.map((c) => c[0]);
|
|
389
|
+
const yValues = corners.map((c) => c[1]);
|
|
390
|
+
|
|
391
|
+
this.#cache.bounds = {
|
|
392
|
+
x: center[0],
|
|
393
|
+
y: center[1],
|
|
394
|
+
left: Math.min(xValues[0], xValues[1], xValues[2], xValues[3]),
|
|
395
|
+
right: Math.max(xValues[0], xValues[1], xValues[2], xValues[3]),
|
|
396
|
+
top: Math.max(yValues[0], yValues[1], yValues[2], yValues[3]),
|
|
397
|
+
bottom: Math.min(yValues[0], yValues[1], yValues[2], yValues[3]),
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
return this.#cache.bounds;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Set the bounds of the node in world space.
|
|
405
|
+
*/
|
|
406
|
+
setBounds(bounds: Partial<Bounds>) {
|
|
407
|
+
if (bounds.left !== undefined) this.left = bounds.left;
|
|
408
|
+
if (bounds.right !== undefined) this.right = bounds.right;
|
|
409
|
+
if (bounds.top !== undefined) this.top = bounds.top;
|
|
410
|
+
if (bounds.bottom !== undefined) this.bottom = bounds.bottom;
|
|
411
|
+
if (bounds.x !== undefined) this.centerX = bounds.x;
|
|
412
|
+
if (bounds.y !== undefined) this.centerY = bounds.y;
|
|
413
|
+
|
|
414
|
+
return this;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Set the left edge of the node in world space.
|
|
419
|
+
*/
|
|
420
|
+
set left(value: number) {
|
|
421
|
+
this.#adjustWorldPosition([value - this.bounds.left, 0]);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Set the bottom edge of the node in world space.
|
|
426
|
+
*/
|
|
427
|
+
set bottom(value: number) {
|
|
428
|
+
this.#adjustWorldPosition([0, value - this.bounds.bottom]);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Set the top edge of the node in world space.
|
|
433
|
+
*/
|
|
434
|
+
set top(value: number) {
|
|
435
|
+
this.#adjustWorldPosition([0, value - this.bounds.top]);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Set the right edge of the node in world space.
|
|
440
|
+
*/
|
|
441
|
+
set right(value: number) {
|
|
442
|
+
this.#adjustWorldPosition([value - this.bounds.right, 0]);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Set the center x of the node in world space.
|
|
447
|
+
*/
|
|
448
|
+
set centerX(value: number) {
|
|
449
|
+
this.#adjustWorldPosition([value - this.bounds.x, 0]);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Set the center y of the node in world space.
|
|
454
|
+
*/
|
|
455
|
+
set centerY(value: number) {
|
|
456
|
+
this.#adjustWorldPosition([0, value - this.bounds.y]);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Removes references to this node and all of its children.
|
|
461
|
+
*
|
|
462
|
+
* Call this to remove a node from a parent's tree and before garbage collection to prevent a node from being retained.
|
|
463
|
+
*
|
|
464
|
+
* @example
|
|
465
|
+
*
|
|
466
|
+
* const parent = toodle.Node();
|
|
467
|
+
* const child = toodle.Quad();
|
|
468
|
+
* const grandchild = toodle.Quad();
|
|
469
|
+
*
|
|
470
|
+
* parent.add(child);
|
|
471
|
+
* child.add(grandchild);
|
|
472
|
+
*
|
|
473
|
+
* // Will delete `child` and `grandchild`
|
|
474
|
+
* child.delete();
|
|
475
|
+
*/
|
|
476
|
+
delete() {
|
|
477
|
+
this.#parent?.remove(this);
|
|
478
|
+
for (const child of this.#kids) {
|
|
479
|
+
child.delete();
|
|
480
|
+
}
|
|
481
|
+
this.#kids = [];
|
|
482
|
+
this.#isActive = false;
|
|
483
|
+
this.#layer = null;
|
|
484
|
+
this.#renderComponent = null;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* Remove any child node from this node. Warns if the child is not found.
|
|
489
|
+
*
|
|
490
|
+
* The node will still exist as an orphaned node and can still be passed to toodle.Draw or added to another parent.
|
|
491
|
+
*
|
|
492
|
+
* Alternatively, calling `node.delete()` on the child will remove it and set it to inactive.
|
|
493
|
+
*
|
|
494
|
+
* @example
|
|
495
|
+
* const parent = toodle.Node();
|
|
496
|
+
* const child = toodle.Quad();
|
|
497
|
+
* const grandchild = toodle.Quad();
|
|
498
|
+
*
|
|
499
|
+
* parent.add(child);
|
|
500
|
+
* child.add(grandchild);
|
|
501
|
+
*
|
|
502
|
+
* parent.remove(child);
|
|
503
|
+
*/
|
|
504
|
+
remove(kid: SceneNode) {
|
|
505
|
+
const childIndex = this.#kids.findIndex((child) => child.id === kid.id);
|
|
506
|
+
if (childIndex <= -1) {
|
|
507
|
+
throw new Error(
|
|
508
|
+
`${kid.label ?? kid.id} is not a child of ${this.label ?? this.id}`,
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
this.#kids.splice(childIndex, 1);
|
|
512
|
+
kid.#parent = null;
|
|
513
|
+
kid.setDirty();
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
#adjustWorldPosition(delta: [number, number]) {
|
|
517
|
+
const inverseMatrix = mat3.inverse(this.#parent?.matrix ?? mat3.identity());
|
|
518
|
+
|
|
519
|
+
// zero out the translation part of the matrix since we're transforming a delta
|
|
520
|
+
// and not a point in space
|
|
521
|
+
inverseMatrix[8] = inverseMatrix[9] = 0;
|
|
522
|
+
|
|
523
|
+
const localDelta = vec2.transformMat3(delta, inverseMatrix);
|
|
524
|
+
|
|
525
|
+
this.#transform.position.x += localDelta[0];
|
|
526
|
+
this.#transform.position.y += localDelta[1];
|
|
527
|
+
|
|
528
|
+
this.setDirty();
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/**
|
|
532
|
+
* This marks the node as dirty, invalidating its cache and causing its matrix to be recalculated.
|
|
533
|
+
* This should not be necessary to call directly, but is available for advanced use cases.
|
|
534
|
+
*/
|
|
535
|
+
setDirty() {
|
|
536
|
+
this.#cache = null;
|
|
537
|
+
this.#kids.forEach((kid) => kid.setDirty());
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Parse a node and its descendants from a JSON string.
|
|
542
|
+
* Can be used for deserialization from a file or other source.
|
|
543
|
+
*
|
|
544
|
+
* @example
|
|
545
|
+
*
|
|
546
|
+
* const node = new Node();
|
|
547
|
+
* const json = JSON.stringify(node);
|
|
548
|
+
* const clonedNode = Node.parse(json);
|
|
549
|
+
*/
|
|
550
|
+
static parse(json: string) {
|
|
551
|
+
const obj = JSON.parse(json, reviver);
|
|
552
|
+
return new SceneNode(obj);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* This method usually is not called directly. It will be called automatically by `JSON.stringify`,
|
|
557
|
+
* see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#description
|
|
558
|
+
* and {@link SceneNode.parse}.
|
|
559
|
+
*
|
|
560
|
+
* @example
|
|
561
|
+
*
|
|
562
|
+
* const node = new Node();
|
|
563
|
+
* const json = JSON.stringify(node); // calls toJSON()
|
|
564
|
+
* console.log(json)
|
|
565
|
+
*/
|
|
566
|
+
toJSON() {
|
|
567
|
+
return {
|
|
568
|
+
id: this.id,
|
|
569
|
+
label: this.label,
|
|
570
|
+
transform: this.#transform,
|
|
571
|
+
layer: this.#layer,
|
|
572
|
+
isActive: this.#isActive,
|
|
573
|
+
kids: this.#kids,
|
|
574
|
+
render: this.#renderComponent,
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
export type NodeOptions = {
|
|
580
|
+
/** The unique identifier for the node. */
|
|
581
|
+
id?: number;
|
|
582
|
+
/** The label for the node. */
|
|
583
|
+
label?: string;
|
|
584
|
+
/** The layer for the node. */
|
|
585
|
+
layer?: number;
|
|
586
|
+
/** The rotation for the node in degrees. Cannot be used with `rotationRadians`. */
|
|
587
|
+
rotation?: number;
|
|
588
|
+
/** The rotation for the node in radians. Cannot be used with `rotation`. */
|
|
589
|
+
rotationRadians?: number;
|
|
590
|
+
/** The position for the node. */
|
|
591
|
+
position?: Point;
|
|
592
|
+
/** The scale for the node. */
|
|
593
|
+
scale?: Vec2 | number;
|
|
594
|
+
/** The desired size for the node. */
|
|
595
|
+
idealSize?: Size;
|
|
596
|
+
/** The active state for the node. */
|
|
597
|
+
isActive?: boolean;
|
|
598
|
+
/** The kids for the node. */
|
|
599
|
+
kids?: SceneNode[];
|
|
600
|
+
/** The render component for the node. */
|
|
601
|
+
render?: RenderComponent;
|
|
602
|
+
/** Flip the node horizontally. */
|
|
603
|
+
flipX?: boolean;
|
|
604
|
+
/** Flip the node vertically. */
|
|
605
|
+
flipY?: boolean;
|
|
606
|
+
/** A string key for the node - can be used to reference the node from an external lookup system */
|
|
607
|
+
key?: string;
|
|
608
|
+
};
|
|
609
|
+
|
|
610
|
+
function reviver(key: string, value: any) {
|
|
611
|
+
if (key === "kids") {
|
|
612
|
+
return value.map((kid: any) => new SceneNode(kid));
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
if (Array.isArray(value) && value.every((v) => typeof v === "number")) {
|
|
616
|
+
if (value.length === 2) {
|
|
617
|
+
return value as [number, number];
|
|
618
|
+
}
|
|
619
|
+
if (value.length === 3) {
|
|
620
|
+
return value as [number, number, number];
|
|
621
|
+
}
|
|
622
|
+
if (value.length === 4) {
|
|
623
|
+
return value as [number, number, number, number];
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
return value;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
type RenderLayoutCache = {
|
|
630
|
+
layer?: number;
|
|
631
|
+
isActive?: boolean;
|
|
632
|
+
matrix?: Mat3;
|
|
633
|
+
bounds?: Bounds;
|
|
634
|
+
};
|
|
635
|
+
|
|
636
|
+
/**
|
|
637
|
+
* Bounds represent a bounding box of a rectangle in world space
|
|
638
|
+
*/
|
|
639
|
+
export type Bounds = {
|
|
640
|
+
/**
|
|
641
|
+
* for an axis-aligned rectangle, top is the top edge.
|
|
642
|
+
* for a rotated rectangle, it is the topmost point
|
|
643
|
+
*/
|
|
644
|
+
top: number;
|
|
645
|
+
/**
|
|
646
|
+
* for an axis-aligned rectangle, left is the left edge.
|
|
647
|
+
* for a rotated rectangle, it is the leftmost point
|
|
648
|
+
*/
|
|
649
|
+
left: number;
|
|
650
|
+
/**
|
|
651
|
+
* for an axis-aligned rectangle, right is the right edge.
|
|
652
|
+
* for a rotated rectangle, it is the rightmost point
|
|
653
|
+
*/
|
|
654
|
+
right: number;
|
|
655
|
+
/**
|
|
656
|
+
* for an axis-aligned rectangle, bottom is the bottom edge.
|
|
657
|
+
* for a rotated rectangle, it is the bottommost point
|
|
658
|
+
*/
|
|
659
|
+
bottom: number;
|
|
660
|
+
/**
|
|
661
|
+
* the center x of the node in world space
|
|
662
|
+
*/
|
|
663
|
+
x: number;
|
|
664
|
+
/**
|
|
665
|
+
* the center y of the node in world space
|
|
666
|
+
*/
|
|
667
|
+
y: number;
|
|
668
|
+
};
|
package/src/scene/mod.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./resolution";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type Resolution = { width: number; height: number };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Mat3 } from "wgpu-matrix";
|
|
2
|
+
import type { Camera } from "../scene/Camera";
|
|
3
|
+
import type { Resolution } from "../screen/resolution";
|
|
4
|
+
|
|
5
|
+
export type EngineUniform = {
|
|
6
|
+
resolution: Resolution;
|
|
7
|
+
camera: Camera;
|
|
8
|
+
viewProjectionMatrix: Mat3;
|
|
9
|
+
|
|
10
|
+
// could add time, deltaTime, etc here if needed
|
|
11
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { SceneNode } from "../scene/SceneNode";
|
|
2
|
+
import type { EngineUniform } from "./EngineUniform";
|
|
3
|
+
|
|
4
|
+
export interface IShader {
|
|
5
|
+
startFrame: (device: GPUDevice, uniform: EngineUniform) => void;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Process a batch of nodes.
|
|
9
|
+
*
|
|
10
|
+
* @param renderPass - The render pass to use.
|
|
11
|
+
* @param nodes - The nodes to process.
|
|
12
|
+
* @returns The number of draw calls made.
|
|
13
|
+
*/
|
|
14
|
+
processBatch: (
|
|
15
|
+
renderPass: GPURenderPassEncoder,
|
|
16
|
+
nodes: SceneNode[],
|
|
17
|
+
) => number;
|
|
18
|
+
|
|
19
|
+
endFrame: () => void;
|
|
20
|
+
}
|