@lightningjs/renderer 3.0.0-beta4 → 3.0.0-beta5
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 +202 -202
- package/NOTICE +3 -3
- package/README.md +147 -147
- package/dist/exports/core-api.d.ts +74 -0
- package/dist/exports/core-api.js +96 -0
- package/dist/exports/core-api.js.map +1 -0
- package/dist/exports/main-api.d.ts +30 -0
- package/dist/exports/main-api.js +45 -0
- package/dist/exports/main-api.js.map +1 -0
- package/dist/src/core/CoreExtension.d.ts +12 -0
- package/dist/src/core/CoreExtension.js +29 -0
- package/dist/src/core/CoreExtension.js.map +1 -0
- package/dist/src/core/CoreNode.js +1 -1
- package/dist/src/core/CoreNode.js.map +1 -1
- package/dist/src/core/CoreStuff.js +138 -0
- package/dist/src/core/CoreStuff.js.map +1 -0
- package/dist/src/core/CoreTextNode.js +1 -0
- package/dist/src/core/CoreTextNode.js.map +1 -1
- package/dist/src/core/CoreTexturizer.d.ts +14 -0
- package/dist/src/core/CoreTexturizer.js +47 -0
- package/dist/src/core/CoreTexturizer.js.map +1 -0
- package/dist/src/core/LngNode.d.ts +736 -0
- package/dist/src/core/LngNode.js +1174 -0
- package/dist/src/core/LngNode.js.map +1 -0
- package/dist/src/core/Matrix2DContext.d.ts +15 -0
- package/dist/src/core/Matrix2DContext.js +45 -0
- package/dist/src/core/Matrix2DContext.js.map +1 -0
- package/dist/src/core/ShaderNode.d.ts +10 -0
- package/dist/src/core/ShaderNode.js +30 -0
- package/dist/src/core/ShaderNode.js.map +1 -0
- package/dist/src/core/TextNode.d.ts +103 -0
- package/dist/src/core/TextNode.js +331 -0
- package/dist/src/core/TextNode.js.map +1 -0
- package/dist/src/core/lib/Coords.d.ts +14 -0
- package/dist/src/core/lib/Coords.js +55 -0
- package/dist/src/core/lib/Coords.js.map +1 -0
- package/dist/src/core/lib/glm/common.d.ts +162 -0
- package/dist/src/core/lib/glm/common.js +81 -0
- package/dist/src/core/lib/glm/common.js.map +1 -0
- package/dist/src/core/lib/glm/index.d.ts +11 -0
- package/dist/src/core/lib/glm/index.js +30 -0
- package/dist/src/core/lib/glm/index.js.map +1 -0
- package/dist/src/core/lib/glm/mat2.d.ts +219 -0
- package/dist/src/core/lib/glm/mat2.js +396 -0
- package/dist/src/core/lib/glm/mat2.js.map +1 -0
- package/dist/src/core/lib/glm/mat2d.d.ts +237 -0
- package/dist/src/core/lib/glm/mat2d.js +442 -0
- package/dist/src/core/lib/glm/mat2d.js.map +1 -0
- package/dist/src/core/lib/glm/mat3.d.ts +283 -0
- package/dist/src/core/lib/glm/mat3.js +680 -0
- package/dist/src/core/lib/glm/mat3.js.map +1 -0
- package/dist/src/core/lib/glm/mat4.d.ts +550 -0
- package/dist/src/core/lib/glm/mat4.js +1802 -0
- package/dist/src/core/lib/glm/mat4.js.map +1 -0
- package/dist/src/core/lib/glm/quat.d.ts +363 -0
- package/dist/src/core/lib/glm/quat.js +693 -0
- package/dist/src/core/lib/glm/quat.js.map +1 -0
- package/dist/src/core/lib/glm/quat2.d.ts +356 -0
- package/dist/src/core/lib/glm/quat2.js +754 -0
- package/dist/src/core/lib/glm/quat2.js.map +1 -0
- package/dist/src/core/lib/glm/vec2.d.ts +365 -0
- package/dist/src/core/lib/glm/vec2.js +569 -0
- package/dist/src/core/lib/glm/vec2.js.map +1 -0
- package/dist/src/core/lib/glm/vec3.d.ts +406 -0
- package/dist/src/core/lib/glm/vec3.js +720 -0
- package/dist/src/core/lib/glm/vec3.js.map +1 -0
- package/dist/src/core/lib/glm/vec4.d.ts +330 -0
- package/dist/src/core/lib/glm/vec4.js +608 -0
- package/dist/src/core/lib/glm/vec4.js.map +1 -0
- package/dist/src/core/renderers/CoreShaderManager.d.ts +19 -0
- package/dist/src/core/renderers/CoreShaderManager.js +33 -0
- package/dist/src/core/renderers/CoreShaderManager.js.map +1 -0
- package/dist/src/core/renderers/webgl/WebGlCoreShaderManager.d.ts +27 -0
- package/dist/src/core/renderers/webgl/WebGlCoreShaderManager.js +82 -0
- package/dist/src/core/renderers/webgl/WebGlCoreShaderManager.js.map +1 -0
- package/dist/src/core/renderers/webgl/WebGlCoreShaderProgram.d.ts +11 -0
- package/dist/src/core/renderers/webgl/WebGlCoreShaderProgram.js +34 -0
- package/dist/src/core/renderers/webgl/WebGlCoreShaderProgram.js.map +1 -0
- package/dist/src/core/renderers/webgl/internal/ShaderUtils.js +35 -35
- package/dist/src/core/renderers/webgl/shaders/DefaultShader.js +45 -45
- package/dist/src/core/renderers/webgl/shaders/DefaultShaderBatched.js +61 -61
- package/dist/src/core/renderers/webgl/shaders/DynamicShader.js +93 -93
- package/dist/src/core/renderers/webgl/shaders/RoundedRectangle.js +63 -63
- package/dist/src/core/renderers/webgl/shaders/SdfShader.js +62 -62
- package/dist/src/core/renderers/webgl/shaders/effects/BorderBottomEffect.js +15 -15
- package/dist/src/core/renderers/webgl/shaders/effects/BorderEffect.js +6 -6
- package/dist/src/core/renderers/webgl/shaders/effects/BorderLeftEffect.js +15 -15
- package/dist/src/core/renderers/webgl/shaders/effects/BorderRightEffect.js +15 -15
- package/dist/src/core/renderers/webgl/shaders/effects/BorderTopEffect.js +15 -15
- package/dist/src/core/renderers/webgl/shaders/effects/FadeOutEffect.js +42 -42
- package/dist/src/core/renderers/webgl/shaders/effects/GlitchEffect.js +44 -44
- package/dist/src/core/renderers/webgl/shaders/effects/GrayscaleEffect.js +3 -3
- package/dist/src/core/renderers/webgl/shaders/effects/HolePunchEffect.js +22 -22
- package/dist/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.js +28 -28
- package/dist/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.js +10 -10
- package/dist/src/core/renderers/webgl/shaders/effects/RadialProgressEffect.js +37 -37
- package/dist/src/core/renderers/webgl/shaders/effects/RadiusEffect.js +19 -19
- package/dist/src/core/scene/Scene.d.ts +59 -0
- package/dist/src/core/scene/Scene.js +106 -0
- package/dist/src/core/scene/Scene.js.map +1 -0
- package/dist/src/core/shaders/webgl/Border.js +59 -59
- package/dist/src/core/shaders/webgl/Default.js +47 -47
- package/dist/src/core/shaders/webgl/DefaultBatched.js +61 -61
- package/dist/src/core/shaders/webgl/HolePunch.js +32 -32
- package/dist/src/core/shaders/webgl/LinearGradient.js +36 -36
- package/dist/src/core/shaders/webgl/RadialGradient.js +33 -33
- package/dist/src/core/shaders/webgl/Rounded.js +71 -71
- package/dist/src/core/shaders/webgl/RoundedWithBorder.js +66 -66
- package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js +79 -79
- package/dist/src/core/shaders/webgl/RoundedWithShadow.js +54 -54
- package/dist/src/core/shaders/webgl/SdfShader.js +62 -62
- package/dist/src/core/shaders/webgl/Shadow.js +83 -83
- package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/makeRenderWindow.d.ts +20 -0
- package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/makeRenderWindow.js +55 -0
- package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/makeRenderWindow.js.map +1 -0
- package/dist/src/main-api/ICoreDriver.d.ts +27 -0
- package/dist/src/main-api/ICoreDriver.js +20 -0
- package/dist/src/main-api/ICoreDriver.js.map +1 -0
- package/dist/src/main-api/IRenderDriver.d.ts +20 -0
- package/dist/src/main-api/IRenderDriver.js +20 -0
- package/dist/src/main-api/IRenderDriver.js.map +1 -0
- package/dist/src/main-api/IShaderController.d.ts +14 -0
- package/dist/src/main-api/IShaderController.js +30 -0
- package/dist/src/main-api/IShaderController.js.map +1 -0
- package/dist/src/main-api/IShaderNode.d.ts +17 -0
- package/dist/src/main-api/IShaderNode.js +19 -0
- package/dist/src/main-api/IShaderNode.js.map +1 -0
- package/dist/src/main-api/RendererMain.d.ts +375 -0
- package/dist/src/main-api/RendererMain.js +365 -0
- package/dist/src/main-api/RendererMain.js.map +1 -0
- package/dist/src/main-api/texture-usage-trackers/FinalizationRegistryTextureUsageTracker.d.ts +9 -0
- package/dist/src/main-api/texture-usage-trackers/FinalizationRegistryTextureUsageTracker.js +38 -0
- package/dist/src/main-api/texture-usage-trackers/FinalizationRegistryTextureUsageTracker.js.map +1 -0
- package/dist/src/main-api/texture-usage-trackers/ManualCountTextureUsageTracker.d.ts +56 -0
- package/dist/src/main-api/texture-usage-trackers/ManualCountTextureUsageTracker.js +101 -0
- package/dist/src/main-api/texture-usage-trackers/ManualCountTextureUsageTracker.js.map +1 -0
- package/dist/src/main-api/texture-usage-trackers/TextureUsageTracker.d.ts +32 -0
- package/dist/src/main-api/texture-usage-trackers/TextureUsageTracker.js +28 -0
- package/dist/src/main-api/texture-usage-trackers/TextureUsageTracker.js.map +1 -0
- package/dist/src/render-drivers/main/MainCoreDriver.d.ts +24 -0
- package/dist/src/render-drivers/main/MainCoreDriver.js +118 -0
- package/dist/src/render-drivers/main/MainCoreDriver.js.map +1 -0
- package/dist/src/render-drivers/main/MainOnlyNode.d.ts +99 -0
- package/dist/src/render-drivers/main/MainOnlyNode.js +396 -0
- package/dist/src/render-drivers/main/MainOnlyNode.js.map +1 -0
- package/dist/src/render-drivers/main/MainOnlyShaderController.d.ts +6 -0
- package/dist/src/render-drivers/main/MainOnlyShaderController.js +15 -0
- package/dist/src/render-drivers/main/MainOnlyShaderController.js.map +1 -0
- package/dist/src/render-drivers/main/MainOnlyShaderNode.d.ts +7 -0
- package/dist/src/render-drivers/main/MainOnlyShaderNode.js +34 -0
- package/dist/src/render-drivers/main/MainOnlyShaderNode.js.map +1 -0
- package/dist/src/render-drivers/main/MainOnlyTextNode.d.ts +47 -0
- package/dist/src/render-drivers/main/MainOnlyTextNode.js +205 -0
- package/dist/src/render-drivers/main/MainOnlyTextNode.js.map +1 -0
- package/dist/src/render-drivers/main/MainRenderDriver.d.ts +17 -0
- package/dist/src/render-drivers/main/MainRenderDriver.js +88 -0
- package/dist/src/render-drivers/main/MainRenderDriver.js.map +1 -0
- package/dist/src/render-drivers/threadx/NodeStruct.d.ts +90 -0
- package/dist/src/render-drivers/threadx/NodeStruct.js +281 -0
- package/dist/src/render-drivers/threadx/NodeStruct.js.map +1 -0
- package/dist/src/render-drivers/threadx/SharedNode.d.ts +39 -0
- package/dist/src/render-drivers/threadx/SharedNode.js +60 -0
- package/dist/src/render-drivers/threadx/SharedNode.js.map +1 -0
- package/dist/src/render-drivers/threadx/TextNodeStruct.d.ts +44 -0
- package/dist/src/render-drivers/threadx/TextNodeStruct.js +201 -0
- package/dist/src/render-drivers/threadx/TextNodeStruct.js.map +1 -0
- package/dist/src/render-drivers/threadx/ThreadXCoreDriver.d.ts +28 -0
- package/dist/src/render-drivers/threadx/ThreadXCoreDriver.js +234 -0
- package/dist/src/render-drivers/threadx/ThreadXCoreDriver.js.map +1 -0
- package/dist/src/render-drivers/threadx/ThreadXMainAnimationController.d.ts +20 -0
- package/dist/src/render-drivers/threadx/ThreadXMainAnimationController.js +84 -0
- package/dist/src/render-drivers/threadx/ThreadXMainAnimationController.js.map +1 -0
- package/dist/src/render-drivers/threadx/ThreadXMainNode.d.ts +44 -0
- package/dist/src/render-drivers/threadx/ThreadXMainNode.js +154 -0
- package/dist/src/render-drivers/threadx/ThreadXMainNode.js.map +1 -0
- package/dist/src/render-drivers/threadx/ThreadXMainShaderController.d.ts +6 -0
- package/dist/src/render-drivers/threadx/ThreadXMainShaderController.js +16 -0
- package/dist/src/render-drivers/threadx/ThreadXMainShaderController.js.map +1 -0
- package/dist/src/render-drivers/threadx/ThreadXMainShaderNode.d.ts +7 -0
- package/dist/src/render-drivers/threadx/ThreadXMainShaderNode.js +15 -0
- package/dist/src/render-drivers/threadx/ThreadXMainShaderNode.js.map +1 -0
- package/dist/src/render-drivers/threadx/ThreadXMainTextNode.d.ts +28 -0
- package/dist/src/render-drivers/threadx/ThreadXMainTextNode.js +55 -0
- package/dist/src/render-drivers/threadx/ThreadXMainTextNode.js.map +1 -0
- package/dist/src/render-drivers/threadx/ThreadXRenderDriver.d.ts +21 -0
- package/dist/src/render-drivers/threadx/ThreadXRenderDriver.js +198 -0
- package/dist/src/render-drivers/threadx/ThreadXRenderDriver.js.map +1 -0
- package/dist/src/render-drivers/threadx/ThreadXRendererMessage.d.ts +70 -0
- package/dist/src/render-drivers/threadx/ThreadXRendererMessage.js +32 -0
- package/dist/src/render-drivers/threadx/ThreadXRendererMessage.js.map +1 -0
- package/dist/src/render-drivers/threadx/worker/ThreadXRendererNode.d.ts +19 -0
- package/dist/src/render-drivers/threadx/worker/ThreadXRendererNode.js +177 -0
- package/dist/src/render-drivers/threadx/worker/ThreadXRendererNode.js.map +1 -0
- package/dist/src/render-drivers/threadx/worker/ThreadXRendererTextNode.d.ts +27 -0
- package/dist/src/render-drivers/threadx/worker/ThreadXRendererTextNode.js +108 -0
- package/dist/src/render-drivers/threadx/worker/ThreadXRendererTextNode.js.map +1 -0
- package/dist/src/render-drivers/threadx/worker/renderer.d.ts +1 -0
- package/dist/src/render-drivers/threadx/worker/renderer.js +145 -0
- package/dist/src/render-drivers/threadx/worker/renderer.js.map +1 -0
- package/dist/src/render-drivers/utils.d.ts +12 -0
- package/dist/src/render-drivers/utils.js +69 -0
- package/dist/src/render-drivers/utils.js.map +1 -0
- package/dist/tsconfig.dist.tsbuildinfo +1 -1
- package/exports/canvas-shaders.ts +28 -28
- package/exports/canvas.ts +45 -45
- package/exports/index.ts +90 -90
- package/exports/inspector.ts +24 -24
- package/exports/utils.ts +44 -44
- package/exports/webgl-shaders.ts +28 -28
- package/exports/webgl.ts +50 -50
- package/package.json +2 -1
- package/scripts/please-use-pnpm.js +13 -13
- package/src/common/CommonTypes.ts +146 -146
- package/src/common/EventEmitter.ts +77 -77
- package/src/common/IAnimationController.ts +92 -92
- package/src/common/IEventEmitter.ts +28 -28
- package/src/core/CoreNode.test.ts +203 -203
- package/src/core/CoreNode.ts +2494 -2494
- package/src/core/CoreShaderManager.ts +188 -188
- package/src/core/CoreTextNode.ts +449 -448
- package/src/core/CoreTextureManager.ts +601 -601
- package/src/core/Stage.ts +754 -754
- package/src/core/TextureMemoryManager.ts +395 -395
- package/src/core/animations/AnimationManager.ts +38 -38
- package/src/core/animations/CoreAnimation.ts +284 -284
- package/src/core/animations/CoreAnimationController.ts +157 -157
- package/src/core/lib/ContextSpy.ts +41 -41
- package/src/core/lib/ImageWorker.ts +280 -280
- package/src/core/lib/Matrix3d.ts +244 -244
- package/src/core/lib/RenderCoords.ts +71 -71
- package/src/core/lib/WebGlContextWrapper.ts +1374 -1374
- package/src/core/lib/textureCompression.ts +152 -152
- package/src/core/lib/textureSvg.ts +78 -78
- package/src/core/lib/utils.ts +386 -386
- package/src/core/lib/validateImageBitmap.ts +87 -87
- package/src/core/platform.ts +64 -64
- package/src/core/platforms/Platform.ts +77 -77
- package/src/core/platforms/web/WebPlatform.ts +84 -84
- package/src/core/renderers/CoreContextTexture.ts +43 -43
- package/src/core/renderers/CoreRenderOp.ts +22 -22
- package/src/core/renderers/CoreRenderer.ts +109 -109
- package/src/core/renderers/CoreShaderNode.ts +165 -165
- package/src/core/renderers/CoreShaderProgram.ts +23 -23
- package/src/core/renderers/canvas/CanvasRenderer.ts +298 -298
- package/src/core/renderers/canvas/CanvasShaderNode.ts +99 -99
- package/src/core/renderers/canvas/CanvasTexture.ts +156 -156
- package/src/core/renderers/canvas/internal/C2DShaderUtils.ts +220 -220
- package/src/core/renderers/canvas/internal/ColorUtils.ts +85 -85
- package/src/core/renderers/webgl/WebGlCtxRenderTexture.ts +86 -86
- package/src/core/renderers/webgl/WebGlCtxSubTexture.ts +50 -50
- package/src/core/renderers/webgl/WebGlCtxTexture.ts +301 -301
- package/src/core/renderers/webgl/WebGlRenderOp.ts +161 -161
- package/src/core/renderers/webgl/WebGlRenderer.ts +750 -750
- package/src/core/renderers/webgl/WebGlShaderNode.ts +437 -437
- package/src/core/renderers/webgl/WebGlShaderProgram.ts +318 -318
- package/src/core/renderers/webgl/internal/BufferCollection.ts +54 -54
- package/src/core/renderers/webgl/internal/RendererUtils.ts +155 -155
- package/src/core/renderers/webgl/internal/ShaderUtils.ts +281 -281
- package/src/core/renderers/webgl/internal/WebGlUtils.ts +35 -35
- package/src/core/shaders/canvas/Border.ts +78 -78
- package/src/core/shaders/canvas/HolePunch.ts +62 -62
- package/src/core/shaders/canvas/LinearGradient.ts +69 -69
- package/src/core/shaders/canvas/RadialGradient.ts +113 -113
- package/src/core/shaders/canvas/Rounded.ts +55 -55
- package/src/core/shaders/canvas/RoundedWithBorder.ts +68 -68
- package/src/core/shaders/canvas/RoundedWithBorderAndShadow.ts +88 -88
- package/src/core/shaders/canvas/RoundedWithShadow.ts +69 -69
- package/src/core/shaders/canvas/Shadow.ts +52 -52
- package/src/core/shaders/canvas/utils/render.ts +151 -151
- package/src/core/shaders/templates/BorderTemplate.ts +115 -115
- package/src/core/shaders/templates/HolePunchTemplate.ts +82 -82
- package/src/core/shaders/templates/LinearGradientTemplate.ts +71 -71
- package/src/core/shaders/templates/RadialGradientTemplate.ts +81 -81
- package/src/core/shaders/templates/RoundedTemplate.ts +98 -98
- package/src/core/shaders/templates/RoundedWithBorderAndShadowTemplate.ts +38 -38
- package/src/core/shaders/templates/RoundedWithBorderTemplate.ts +35 -35
- package/src/core/shaders/templates/RoundedWithShadowTemplate.ts +35 -35
- package/src/core/shaders/templates/ShadowTemplate.ts +106 -106
- package/src/core/shaders/templates/shaderUtils.ts +47 -47
- package/src/core/shaders/webgl/Border.ts +96 -96
- package/src/core/shaders/webgl/Default.ts +89 -89
- package/src/core/shaders/webgl/DefaultBatched.ts +129 -129
- package/src/core/shaders/webgl/HolePunch.ts +78 -78
- package/src/core/shaders/webgl/LinearGradient.ts +81 -81
- package/src/core/shaders/webgl/RadialGradient.ts +84 -84
- package/src/core/shaders/webgl/Rounded.ts +117 -117
- package/src/core/shaders/webgl/RoundedWithBorder.ts +114 -114
- package/src/core/shaders/webgl/RoundedWithBorderAndShadow.ts +133 -133
- package/src/core/shaders/webgl/RoundedWithShadow.ts +98 -98
- package/src/core/shaders/webgl/SdfShader.ts +134 -134
- package/src/core/shaders/webgl/Shadow.ts +115 -115
- package/src/core/text-rendering/TextRenderingUtils.ts +36 -36
- package/src/core/text-rendering/TextTextureRendererUtils.ts +263 -263
- package/src/core/text-rendering/TrFontManager.ts +183 -183
- package/src/core/text-rendering/font-face-types/SdfTrFontFace/SdfTrFontFace.ts +176 -176
- package/src/core/text-rendering/font-face-types/SdfTrFontFace/internal/FontShaper.ts +139 -139
- package/src/core/text-rendering/font-face-types/SdfTrFontFace/internal/SdfFontShaper.test.ts +173 -173
- package/src/core/text-rendering/font-face-types/SdfTrFontFace/internal/SdfFontShaper.ts +171 -171
- package/src/core/text-rendering/font-face-types/TrFontFace.ts +187 -187
- package/src/core/text-rendering/font-face-types/WebTrFontFace.ts +94 -94
- package/src/core/text-rendering/font-face-types/utils.ts +39 -39
- package/src/core/text-rendering/renderers/CanvasTextRenderer.ts +514 -514
- package/src/core/text-rendering/renderers/LightningTextTextureRenderer.ts +863 -863
- package/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.ts +846 -846
- package/src/core/text-rendering/renderers/SdfTextRenderer/internal/PeekableGenerator.test.ts +48 -48
- package/src/core/text-rendering/renderers/SdfTextRenderer/internal/PeekableGenerator.ts +66 -66
- package/src/core/text-rendering/renderers/SdfTextRenderer/internal/SpecialCodepoints.ts +52 -52
- package/src/core/text-rendering/renderers/SdfTextRenderer/internal/constants.ts +32 -32
- package/src/core/text-rendering/renderers/SdfTextRenderer/internal/getStartConditions.ts +117 -117
- package/src/core/text-rendering/renderers/SdfTextRenderer/internal/getUnicodeCodepoints.test.ts +133 -133
- package/src/core/text-rendering/renderers/SdfTextRenderer/internal/getUnicodeCodepoints.ts +38 -38
- package/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.ts +497 -497
- package/src/core/text-rendering/renderers/SdfTextRenderer/internal/measureText.test.ts +49 -49
- package/src/core/text-rendering/renderers/SdfTextRenderer/internal/measureText.ts +52 -52
- package/src/core/text-rendering/renderers/SdfTextRenderer/internal/setRenderWindow.test.ts +205 -205
- package/src/core/text-rendering/renderers/SdfTextRenderer/internal/setRenderWindow.ts +93 -93
- package/src/core/text-rendering/renderers/SdfTextRenderer/internal/util.ts +40 -40
- package/src/core/text-rendering/renderers/TextRenderer.ts +567 -567
- package/src/core/textures/ColorTexture.ts +102 -102
- package/src/core/textures/ImageTexture.ts +410 -410
- package/src/core/textures/NoiseTexture.ts +104 -104
- package/src/core/textures/RenderTexture.ts +85 -85
- package/src/core/textures/SubTexture.ts +205 -205
- package/src/core/textures/Texture.ts +358 -358
- package/src/core/utils.ts +227 -227
- package/src/env.d.ts +7 -7
- package/src/main-api/INode.ts +100 -100
- package/src/main-api/Inspector.ts +522 -522
- package/src/main-api/Renderer.ts +675 -675
- package/src/main-api/utils.ts +45 -45
- package/src/utils.ts +267 -267
- package/COPYING +0 -1
- package/dist/src/core/temp.js +0 -77
- package/dist/src/core/temp.js.map +0 -1
- /package/dist/src/core/{temp.d.ts → CoreStuff.d.ts} +0 -0
package/src/core/Stage.ts
CHANGED
|
@@ -1,754 +1,754 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* If not stated otherwise in this file or this component's LICENSE file the
|
|
3
|
-
* following copyright and licenses apply:
|
|
4
|
-
*
|
|
5
|
-
* Copyright 2023 Comcast Cable Communications Management, LLC.
|
|
6
|
-
*
|
|
7
|
-
* Licensed under the Apache License, Version 2.0 (the License);
|
|
8
|
-
* you may not use this file except in compliance with the License.
|
|
9
|
-
* You may obtain a copy of the License at
|
|
10
|
-
*
|
|
11
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
-
*
|
|
13
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
14
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
-
* See the License for the specific language governing permissions and
|
|
17
|
-
* limitations under the License.
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
import { assertTruthy, setPremultiplyMode } from '../utils.js';
|
|
21
|
-
import { AnimationManager } from './animations/AnimationManager.js';
|
|
22
|
-
import {
|
|
23
|
-
UpdateType,
|
|
24
|
-
CoreNode,
|
|
25
|
-
CoreNodeRenderState,
|
|
26
|
-
type CoreNodeProps,
|
|
27
|
-
} from './CoreNode.js';
|
|
28
|
-
import { CoreTextureManager } from './CoreTextureManager.js';
|
|
29
|
-
import { TrFontManager } from './text-rendering/TrFontManager.js';
|
|
30
|
-
import { CoreShaderManager } from './CoreShaderManager.js';
|
|
31
|
-
import {
|
|
32
|
-
TextRenderer,
|
|
33
|
-
type TextRendererMap,
|
|
34
|
-
type TrProps,
|
|
35
|
-
} from './text-rendering/renderers/TextRenderer.js';
|
|
36
|
-
|
|
37
|
-
import { EventEmitter } from '../common/EventEmitter.js';
|
|
38
|
-
import { ContextSpy } from './lib/ContextSpy.js';
|
|
39
|
-
import type {
|
|
40
|
-
FpsUpdatePayload,
|
|
41
|
-
FrameTickPayload,
|
|
42
|
-
QuadsUpdatePayload,
|
|
43
|
-
} from '../common/CommonTypes.js';
|
|
44
|
-
import {
|
|
45
|
-
TextureMemoryManager,
|
|
46
|
-
type TextureMemoryManagerSettings,
|
|
47
|
-
} from './TextureMemoryManager.js';
|
|
48
|
-
import { CoreRenderer } from './renderers/CoreRenderer.js';
|
|
49
|
-
import type { WebGlRenderer } from './renderers/webgl/WebGlRenderer.js';
|
|
50
|
-
import type { CanvasRenderer } from './renderers/canvas/CanvasRenderer.js';
|
|
51
|
-
import { CoreTextNode, type CoreTextNodeProps } from './CoreTextNode.js';
|
|
52
|
-
import { santizeCustomDataMap } from '../main-api/utils.js';
|
|
53
|
-
import type { SdfTextRenderer } from './text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js';
|
|
54
|
-
import type { CanvasTextRenderer } from './text-rendering/renderers/CanvasTextRenderer.js';
|
|
55
|
-
import type { CoreShaderNode } from './renderers/CoreShaderNode.js';
|
|
56
|
-
import { createBound, createPreloadBounds, type Bound } from './lib/utils.js';
|
|
57
|
-
import type { Texture } from './textures/Texture.js';
|
|
58
|
-
import { ColorTexture } from './textures/ColorTexture.js';
|
|
59
|
-
import type { Platform } from './platforms/Platform.js';
|
|
60
|
-
import type { WebPlatform } from './platforms/web/WebPlatform.js';
|
|
61
|
-
|
|
62
|
-
export interface StageOptions {
|
|
63
|
-
appWidth: number;
|
|
64
|
-
appHeight: number;
|
|
65
|
-
textureMemory: TextureMemoryManagerSettings;
|
|
66
|
-
boundsMargin: number | [number, number, number, number];
|
|
67
|
-
deviceLogicalPixelRatio: number;
|
|
68
|
-
devicePhysicalPixelRatio: number;
|
|
69
|
-
canvas: HTMLCanvasElement | OffscreenCanvas;
|
|
70
|
-
clearColor: number;
|
|
71
|
-
fpsUpdateInterval: number;
|
|
72
|
-
enableContextSpy: boolean;
|
|
73
|
-
forceWebGL2: boolean;
|
|
74
|
-
numImageWorkers: number;
|
|
75
|
-
renderEngine: typeof WebGlRenderer | typeof CanvasRenderer;
|
|
76
|
-
eventBus: EventEmitter;
|
|
77
|
-
quadBufferSize: number;
|
|
78
|
-
fontEngines: (typeof CanvasTextRenderer | typeof SdfTextRenderer)[];
|
|
79
|
-
inspector: boolean;
|
|
80
|
-
strictBounds: boolean;
|
|
81
|
-
textureProcessingTimeLimit: number;
|
|
82
|
-
createImageBitmapSupport: 'auto' | 'basic' | 'options' | 'full';
|
|
83
|
-
platform: Platform | WebPlatform;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export type StageFpsUpdateHandler = (
|
|
87
|
-
stage: Stage,
|
|
88
|
-
fpsData: FpsUpdatePayload,
|
|
89
|
-
) => void;
|
|
90
|
-
|
|
91
|
-
export type StageFrameTickHandler = (
|
|
92
|
-
stage: Stage,
|
|
93
|
-
frameTickData: FrameTickPayload,
|
|
94
|
-
) => void;
|
|
95
|
-
|
|
96
|
-
const autoStart = true;
|
|
97
|
-
|
|
98
|
-
export class Stage {
|
|
99
|
-
/// Module Instances
|
|
100
|
-
public readonly animationManager: AnimationManager;
|
|
101
|
-
public readonly txManager: CoreTextureManager;
|
|
102
|
-
public readonly txMemManager: TextureMemoryManager;
|
|
103
|
-
public readonly fontManager: TrFontManager;
|
|
104
|
-
public readonly textRenderers: Partial<TextRendererMap>;
|
|
105
|
-
public readonly shManager: CoreShaderManager;
|
|
106
|
-
public readonly renderer: CoreRenderer;
|
|
107
|
-
public readonly root: CoreNode;
|
|
108
|
-
public boundsMargin: [number, number, number, number];
|
|
109
|
-
public readonly defShaderNode: CoreShaderNode | null = null;
|
|
110
|
-
public readonly strictBound: Bound;
|
|
111
|
-
public readonly preloadBound: Bound;
|
|
112
|
-
public readonly strictBounds: boolean;
|
|
113
|
-
public readonly defaultTexture: Texture | null = null;
|
|
114
|
-
public readonly pixelRatio: number;
|
|
115
|
-
public readonly bufferMemory: number = 2e6;
|
|
116
|
-
public readonly platform: Platform | WebPlatform;
|
|
117
|
-
public readonly calculateTextureCoord: boolean;
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Renderer Event Bus for the Stage to emit events onto
|
|
121
|
-
*
|
|
122
|
-
* @remarks
|
|
123
|
-
* In reality this is just the RendererMain instance, which is an EventEmitter.
|
|
124
|
-
* this allows us to directly emit events from the Stage to RendererMain
|
|
125
|
-
* without having to set up forwarding handlers.
|
|
126
|
-
*/
|
|
127
|
-
public readonly eventBus: EventEmitter;
|
|
128
|
-
|
|
129
|
-
/// State
|
|
130
|
-
deltaTime = 0;
|
|
131
|
-
lastFrameTime = 0;
|
|
132
|
-
currentFrameTime = 0;
|
|
133
|
-
private clrColor = 0x00000000;
|
|
134
|
-
private fpsNumFrames = 0;
|
|
135
|
-
private fpsElapsedTime = 0;
|
|
136
|
-
private numQuadsRendered = 0;
|
|
137
|
-
private renderRequested = false;
|
|
138
|
-
private frameEventQueue: [name: string, payload: unknown][] = [];
|
|
139
|
-
private fontResolveMap: Record<string, CanvasTextRenderer | SdfTextRenderer> =
|
|
140
|
-
{};
|
|
141
|
-
|
|
142
|
-
/// Debug data
|
|
143
|
-
contextSpy: ContextSpy | null = null;
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Stage constructor
|
|
147
|
-
*/
|
|
148
|
-
constructor(readonly options: StageOptions) {
|
|
149
|
-
const {
|
|
150
|
-
canvas,
|
|
151
|
-
clearColor,
|
|
152
|
-
appWidth,
|
|
153
|
-
appHeight,
|
|
154
|
-
boundsMargin,
|
|
155
|
-
enableContextSpy,
|
|
156
|
-
forceWebGL2,
|
|
157
|
-
numImageWorkers,
|
|
158
|
-
textureMemory,
|
|
159
|
-
renderEngine,
|
|
160
|
-
fontEngines,
|
|
161
|
-
createImageBitmapSupport,
|
|
162
|
-
platform,
|
|
163
|
-
} = options;
|
|
164
|
-
|
|
165
|
-
assertTruthy(
|
|
166
|
-
platform !== null,
|
|
167
|
-
'A CorePlatform is not provided in the options',
|
|
168
|
-
);
|
|
169
|
-
|
|
170
|
-
this.platform = platform;
|
|
171
|
-
|
|
172
|
-
this.eventBus = options.eventBus;
|
|
173
|
-
this.txManager = new CoreTextureManager(this, {
|
|
174
|
-
numImageWorkers,
|
|
175
|
-
createImageBitmapSupport,
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
// Wait for the Texture Manager to initialize
|
|
179
|
-
// once it does, request a render
|
|
180
|
-
this.txManager.on('initialized', () => {
|
|
181
|
-
this.requestRender();
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
this.txMemManager = new TextureMemoryManager(this, textureMemory);
|
|
185
|
-
|
|
186
|
-
this.animationManager = new AnimationManager();
|
|
187
|
-
this.contextSpy = enableContextSpy ? new ContextSpy() : null;
|
|
188
|
-
this.strictBounds = options.strictBounds;
|
|
189
|
-
|
|
190
|
-
let bm = [0, 0, 0, 0] as [number, number, number, number];
|
|
191
|
-
if (boundsMargin) {
|
|
192
|
-
bm = Array.isArray(boundsMargin)
|
|
193
|
-
? boundsMargin
|
|
194
|
-
: [boundsMargin, boundsMargin, boundsMargin, boundsMargin];
|
|
195
|
-
}
|
|
196
|
-
this.boundsMargin = bm;
|
|
197
|
-
|
|
198
|
-
// precalculate our viewport bounds
|
|
199
|
-
this.strictBound = createBound(0, 0, appWidth, appHeight);
|
|
200
|
-
this.preloadBound = createPreloadBounds(this.strictBound, bm);
|
|
201
|
-
|
|
202
|
-
this.clrColor = clearColor;
|
|
203
|
-
|
|
204
|
-
this.pixelRatio =
|
|
205
|
-
options.devicePhysicalPixelRatio * options.deviceLogicalPixelRatio;
|
|
206
|
-
|
|
207
|
-
this.renderer = new renderEngine({
|
|
208
|
-
stage: this,
|
|
209
|
-
canvas,
|
|
210
|
-
contextSpy: this.contextSpy,
|
|
211
|
-
forceWebGL2,
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
this.shManager = new CoreShaderManager(this);
|
|
215
|
-
|
|
216
|
-
this.defShaderNode = this.renderer.getDefaultShaderNode();
|
|
217
|
-
this.calculateTextureCoord = this.renderer.getTextureCoords !== undefined;
|
|
218
|
-
|
|
219
|
-
const renderMode = this.renderer.mode || 'webgl';
|
|
220
|
-
|
|
221
|
-
this.createDefaultTexture();
|
|
222
|
-
setPremultiplyMode(renderMode);
|
|
223
|
-
|
|
224
|
-
// Must do this after renderer is created
|
|
225
|
-
this.txManager.renderer = this.renderer;
|
|
226
|
-
|
|
227
|
-
// Create text renderers
|
|
228
|
-
this.textRenderers = {};
|
|
229
|
-
fontEngines.forEach((fontEngineConstructor) => {
|
|
230
|
-
const fontEngineInstance = new fontEngineConstructor(this);
|
|
231
|
-
const className = fontEngineInstance.type;
|
|
232
|
-
|
|
233
|
-
if (className === 'sdf' && renderMode === 'canvas') {
|
|
234
|
-
console.warn(
|
|
235
|
-
'SdfTextRenderer is not compatible with Canvas renderer. Skipping...',
|
|
236
|
-
);
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
if (fontEngineInstance instanceof TextRenderer) {
|
|
241
|
-
if (className === 'canvas') {
|
|
242
|
-
this.textRenderers['canvas'] =
|
|
243
|
-
fontEngineInstance as CanvasTextRenderer;
|
|
244
|
-
} else if (className === 'sdf') {
|
|
245
|
-
this.textRenderers['sdf'] = fontEngineInstance as SdfTextRenderer;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
if (Object.keys(this.textRenderers).length === 0) {
|
|
251
|
-
console.warn('No text renderers available. Your text will not render.');
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
this.fontManager = new TrFontManager(this.textRenderers);
|
|
255
|
-
|
|
256
|
-
// create root node
|
|
257
|
-
const rootNode = new CoreNode(this, {
|
|
258
|
-
x: 0,
|
|
259
|
-
y: 0,
|
|
260
|
-
width: appWidth,
|
|
261
|
-
height: appHeight,
|
|
262
|
-
alpha: 1,
|
|
263
|
-
autosize: false,
|
|
264
|
-
boundsMargin: null,
|
|
265
|
-
clipping: false,
|
|
266
|
-
color: 0x00000000,
|
|
267
|
-
colorTop: 0x00000000,
|
|
268
|
-
colorBottom: 0x00000000,
|
|
269
|
-
colorLeft: 0x00000000,
|
|
270
|
-
colorRight: 0x00000000,
|
|
271
|
-
colorTl: 0x00000000,
|
|
272
|
-
colorTr: 0x00000000,
|
|
273
|
-
colorBl: 0x00000000,
|
|
274
|
-
colorBr: 0x00000000,
|
|
275
|
-
zIndex: 0,
|
|
276
|
-
zIndexLocked: 0,
|
|
277
|
-
scaleX: 1,
|
|
278
|
-
scaleY: 1,
|
|
279
|
-
mountX: 0,
|
|
280
|
-
mountY: 0,
|
|
281
|
-
mount: 0,
|
|
282
|
-
pivot: 0.5,
|
|
283
|
-
pivotX: 0.5,
|
|
284
|
-
pivotY: 0.5,
|
|
285
|
-
rotation: 0,
|
|
286
|
-
parent: null,
|
|
287
|
-
texture: null,
|
|
288
|
-
textureOptions: {},
|
|
289
|
-
shader: this.defShaderNode,
|
|
290
|
-
rtt: false,
|
|
291
|
-
src: null,
|
|
292
|
-
scale: 1,
|
|
293
|
-
preventCleanup: false,
|
|
294
|
-
strictBounds: this.strictBounds,
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
this.root = rootNode;
|
|
298
|
-
|
|
299
|
-
// execute platform start loop
|
|
300
|
-
if (autoStart === true) {
|
|
301
|
-
this.platform.startLoop(this);
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
setClearColor(color: number) {
|
|
306
|
-
this.clearColor = color;
|
|
307
|
-
this.renderer.updateClearColor(color);
|
|
308
|
-
this.renderRequested = true;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
updateFrameTime() {
|
|
312
|
-
const newFrameTime = this.platform!.getTimeStamp();
|
|
313
|
-
this.lastFrameTime = this.currentFrameTime;
|
|
314
|
-
this.currentFrameTime = newFrameTime;
|
|
315
|
-
this.deltaTime = !this.lastFrameTime
|
|
316
|
-
? 100 / 6
|
|
317
|
-
: newFrameTime - this.lastFrameTime;
|
|
318
|
-
this.txManager.frameTime = newFrameTime;
|
|
319
|
-
this.txMemManager.frameTime = newFrameTime;
|
|
320
|
-
|
|
321
|
-
// This event is emitted at the beginning of the frame (before any updates
|
|
322
|
-
// or rendering), so no need to to use `stage.queueFrameEvent` here.
|
|
323
|
-
this.eventBus.emit('frameTick', {
|
|
324
|
-
time: this.currentFrameTime,
|
|
325
|
-
delta: this.deltaTime,
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
/**
|
|
330
|
-
* Create default PixelTexture
|
|
331
|
-
*/
|
|
332
|
-
createDefaultTexture() {
|
|
333
|
-
console.log('Creating default texture');
|
|
334
|
-
(this.defaultTexture as ColorTexture) = this.txManager.createTexture(
|
|
335
|
-
'ColorTexture',
|
|
336
|
-
{
|
|
337
|
-
color: 0xffffffff,
|
|
338
|
-
},
|
|
339
|
-
);
|
|
340
|
-
|
|
341
|
-
assertTruthy(this.defaultTexture instanceof ColorTexture);
|
|
342
|
-
this.txManager.loadTexture(this.defaultTexture, true);
|
|
343
|
-
|
|
344
|
-
// Mark the default texture as ALWAYS renderable
|
|
345
|
-
// This prevents it from ever being cleaned up.
|
|
346
|
-
// Fixes https://github.com/lightning-js/renderer/issues/262
|
|
347
|
-
this.defaultTexture.setRenderableOwner(this, true);
|
|
348
|
-
|
|
349
|
-
// When the default texture is loaded, request a render in case the
|
|
350
|
-
// RAF is paused. Fixes: https://github.com/lightning-js/renderer/issues/123
|
|
351
|
-
this.defaultTexture.once('loaded', () => {
|
|
352
|
-
this.requestRender();
|
|
353
|
-
});
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
/**
|
|
357
|
-
* Update animations
|
|
358
|
-
*/
|
|
359
|
-
updateAnimations() {
|
|
360
|
-
const { animationManager } = this;
|
|
361
|
-
if (!this.root) {
|
|
362
|
-
return;
|
|
363
|
-
}
|
|
364
|
-
// step animation
|
|
365
|
-
animationManager.update(this.deltaTime);
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
/**
|
|
369
|
-
* Check if the scene has updates
|
|
370
|
-
*/
|
|
371
|
-
hasSceneUpdates() {
|
|
372
|
-
return (
|
|
373
|
-
!!this.root.updateType ||
|
|
374
|
-
this.renderRequested ||
|
|
375
|
-
this.txManager.hasUpdates()
|
|
376
|
-
);
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
/**
|
|
380
|
-
* Start a new frame draw
|
|
381
|
-
*/
|
|
382
|
-
drawFrame() {
|
|
383
|
-
const { renderer, renderRequested } = this;
|
|
384
|
-
assertTruthy(renderer);
|
|
385
|
-
|
|
386
|
-
// Update tree if needed
|
|
387
|
-
if (this.root.updateType !== 0) {
|
|
388
|
-
this.root.update(this.deltaTime, this.root.clippingRect);
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
// Process some textures
|
|
392
|
-
this.txManager.processSome(this.options.textureProcessingTimeLimit);
|
|
393
|
-
|
|
394
|
-
// Reset render operations and clear the canvas
|
|
395
|
-
renderer.reset();
|
|
396
|
-
|
|
397
|
-
// Check if we need to cleanup textures
|
|
398
|
-
if (this.txMemManager.criticalCleanupRequested === true) {
|
|
399
|
-
this.txMemManager.cleanup(false);
|
|
400
|
-
|
|
401
|
-
if (this.txMemManager.criticalCleanupRequested === true) {
|
|
402
|
-
// If we still need to cleanup, request another but aggressive cleanup
|
|
403
|
-
this.txMemManager.cleanup(true);
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
// If we have RTT nodes draw them first
|
|
408
|
-
// So we can use them as textures in the main scene
|
|
409
|
-
if (renderer.rttNodes.length > 0) {
|
|
410
|
-
renderer.renderRTTNodes();
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
// Fill quads buffer
|
|
414
|
-
this.addQuads(this.root);
|
|
415
|
-
|
|
416
|
-
// Perform render pass
|
|
417
|
-
renderer?.render();
|
|
418
|
-
|
|
419
|
-
this.calculateFps();
|
|
420
|
-
this.calculateQuads();
|
|
421
|
-
|
|
422
|
-
// Reset renderRequested flag if it was set
|
|
423
|
-
if (renderRequested) {
|
|
424
|
-
this.renderRequested = false;
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
/**
|
|
429
|
-
* Queue an event to be emitted after the current/next frame is rendered
|
|
430
|
-
*
|
|
431
|
-
* @remarks
|
|
432
|
-
* When we are operating in the context of the render loop, we may want to
|
|
433
|
-
* emit events that are related to the current frame. However, we generally do
|
|
434
|
-
* NOT want to emit events directly in the middle of the render loop, since
|
|
435
|
-
* this could enable event handlers to modify the scene graph and cause
|
|
436
|
-
* unexpected behavior. Instead, we queue up events to be emitted and then
|
|
437
|
-
* flush the queue after the frame has been rendered.
|
|
438
|
-
*
|
|
439
|
-
* @param name
|
|
440
|
-
* @param data
|
|
441
|
-
*/
|
|
442
|
-
queueFrameEvent(name: string, data: unknown) {
|
|
443
|
-
this.frameEventQueue.push([name, data]);
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
/**
|
|
447
|
-
* Emit all queued frame events
|
|
448
|
-
*
|
|
449
|
-
* @remarks
|
|
450
|
-
* This method should be called after the frame has been rendered to emit
|
|
451
|
-
* all events that were queued during the frame.
|
|
452
|
-
*
|
|
453
|
-
* See {@link queueFrameEvent} for more information.
|
|
454
|
-
*/
|
|
455
|
-
flushFrameEvents() {
|
|
456
|
-
for (const [name, data] of this.frameEventQueue) {
|
|
457
|
-
this.eventBus.emit(name, data);
|
|
458
|
-
}
|
|
459
|
-
this.frameEventQueue = [];
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
calculateFps() {
|
|
463
|
-
// If there's an FPS update interval, emit the FPS update event
|
|
464
|
-
// when the specified interval has elapsed.
|
|
465
|
-
const { fpsUpdateInterval } = this.options;
|
|
466
|
-
if (fpsUpdateInterval) {
|
|
467
|
-
this.fpsNumFrames++;
|
|
468
|
-
this.fpsElapsedTime += this.deltaTime;
|
|
469
|
-
if (this.fpsElapsedTime >= fpsUpdateInterval) {
|
|
470
|
-
const fps = Math.round(
|
|
471
|
-
(this.fpsNumFrames * 1000) / this.fpsElapsedTime,
|
|
472
|
-
);
|
|
473
|
-
this.fpsNumFrames = 0;
|
|
474
|
-
this.fpsElapsedTime = 0;
|
|
475
|
-
this.queueFrameEvent('fpsUpdate', {
|
|
476
|
-
fps,
|
|
477
|
-
contextSpyData: this.contextSpy?.getData() ?? null,
|
|
478
|
-
} satisfies FpsUpdatePayload);
|
|
479
|
-
this.contextSpy?.reset();
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
calculateQuads() {
|
|
485
|
-
const quads = this.renderer.getQuadCount();
|
|
486
|
-
if (quads && quads !== this.numQuadsRendered) {
|
|
487
|
-
this.numQuadsRendered = quads;
|
|
488
|
-
this.queueFrameEvent('quadsUpdate', {
|
|
489
|
-
quads,
|
|
490
|
-
} satisfies QuadsUpdatePayload);
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
addQuads(node: CoreNode) {
|
|
495
|
-
assertTruthy(this.renderer);
|
|
496
|
-
|
|
497
|
-
// If the node is renderable and has a loaded texture, render it
|
|
498
|
-
if (node.isRenderable === true) {
|
|
499
|
-
node.renderQuads(this.renderer);
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
for (let i = 0; i < node.children.length; i++) {
|
|
503
|
-
const child = node.children[i];
|
|
504
|
-
|
|
505
|
-
if (child === undefined) {
|
|
506
|
-
continue;
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
if (
|
|
510
|
-
child.worldAlpha === 0 ||
|
|
511
|
-
(child.strictBounds === true &&
|
|
512
|
-
child.renderState === CoreNodeRenderState.OutOfBounds)
|
|
513
|
-
) {
|
|
514
|
-
continue;
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
this.addQuads(child);
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
/**
|
|
522
|
-
* Request a render pass without forcing an update
|
|
523
|
-
*/
|
|
524
|
-
requestRender() {
|
|
525
|
-
this.renderRequested = true;
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
/**
|
|
529
|
-
* Given a font name, and possible renderer override, return the best compatible text renderer.
|
|
530
|
-
*
|
|
531
|
-
* @remarks
|
|
532
|
-
* Will try to return a canvas renderer if no other suitable renderer can be resolved.
|
|
533
|
-
*
|
|
534
|
-
* @param fontFamily
|
|
535
|
-
* @param textRendererOverride
|
|
536
|
-
* @returns
|
|
537
|
-
*/
|
|
538
|
-
resolveTextRenderer(
|
|
539
|
-
trProps: TrProps,
|
|
540
|
-
textRendererOverride: keyof TextRendererMap | null = null,
|
|
541
|
-
): TextRenderer | null {
|
|
542
|
-
const fontCacheString = `${trProps.fontFamily}${trProps.fontStyle}${
|
|
543
|
-
trProps.fontWeight
|
|
544
|
-
}${trProps.fontStretch}${textRendererOverride ? textRendererOverride : ''}`;
|
|
545
|
-
|
|
546
|
-
// check our resolve cache first
|
|
547
|
-
if (this.fontResolveMap[fontCacheString] !== undefined) {
|
|
548
|
-
return this.fontResolveMap[fontCacheString] as unknown as TextRenderer;
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
// Resolve the text renderer
|
|
552
|
-
let rendererId = textRendererOverride;
|
|
553
|
-
let overrideFallback = false;
|
|
554
|
-
|
|
555
|
-
// Check if the override is valid (if one is provided)
|
|
556
|
-
if (rendererId) {
|
|
557
|
-
const possibleRenderer = this.textRenderers[rendererId];
|
|
558
|
-
if (!possibleRenderer) {
|
|
559
|
-
console.warn(`Text renderer override '${rendererId}' not found.`);
|
|
560
|
-
rendererId = null;
|
|
561
|
-
overrideFallback = true;
|
|
562
|
-
} else if (!possibleRenderer.canRenderFont(trProps)) {
|
|
563
|
-
console.warn(
|
|
564
|
-
`Cannot use override text renderer '${rendererId}' for font`,
|
|
565
|
-
trProps,
|
|
566
|
-
);
|
|
567
|
-
rendererId = null;
|
|
568
|
-
overrideFallback = true;
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
if (!rendererId) {
|
|
573
|
-
// Iterate through the text renderers and find the first one that can render the font
|
|
574
|
-
for (const [trId, tr] of Object.entries(this.textRenderers)) {
|
|
575
|
-
if (tr.canRenderFont(trProps)) {
|
|
576
|
-
rendererId = trId as keyof TextRendererMap;
|
|
577
|
-
break;
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
if (!rendererId && this.textRenderers.canvas !== undefined) {
|
|
581
|
-
// If no renderer can be found, use the canvas renderer
|
|
582
|
-
rendererId = 'canvas';
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
if (overrideFallback) {
|
|
587
|
-
console.warn(`Falling back to text renderer ${String(rendererId)}`);
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
if (!rendererId) {
|
|
591
|
-
// silently fail if no renderer can be found, the error is already created
|
|
592
|
-
// at the constructor level
|
|
593
|
-
return null;
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
// By now we are guaranteed to have a valid rendererId (at least Canvas);
|
|
597
|
-
const resolvedTextRenderer = this.textRenderers[rendererId];
|
|
598
|
-
assertTruthy(resolvedTextRenderer, 'resolvedTextRenderer undefined');
|
|
599
|
-
|
|
600
|
-
// cache the resolved renderer for future use with these trProps
|
|
601
|
-
this.fontResolveMap[fontCacheString] = resolvedTextRenderer;
|
|
602
|
-
|
|
603
|
-
// Need to explicitly cast to TextRenderer because TS doesn't like
|
|
604
|
-
// the covariant state argument in the setter method map
|
|
605
|
-
return resolvedTextRenderer as unknown as TextRenderer;
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
createNode(props: Partial<CoreNodeProps>) {
|
|
609
|
-
const resolvedProps = this.resolveNodeDefaults(props);
|
|
610
|
-
return new CoreNode(this, resolvedProps);
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
createTextNode(props: Partial<CoreTextNodeProps>) {
|
|
614
|
-
const fontSize = props.fontSize ?? 16;
|
|
615
|
-
const resolvedProps = Object.assign(this.resolveNodeDefaults(props), {
|
|
616
|
-
text: props.text ?? '',
|
|
617
|
-
textRendererOverride: props.textRendererOverride ?? null,
|
|
618
|
-
fontSize,
|
|
619
|
-
fontFamily: props.fontFamily ?? 'sans-serif',
|
|
620
|
-
fontStyle: props.fontStyle ?? 'normal',
|
|
621
|
-
fontWeight: props.fontWeight ?? 'normal',
|
|
622
|
-
fontStretch: props.fontStretch ?? 'normal',
|
|
623
|
-
textAlign: props.textAlign ?? 'left',
|
|
624
|
-
contain: props.contain ?? 'none',
|
|
625
|
-
scrollable: props.scrollable ?? false,
|
|
626
|
-
scrollY: props.scrollY ?? 0,
|
|
627
|
-
offsetY: props.offsetY ?? 0,
|
|
628
|
-
letterSpacing: props.letterSpacing ?? 0,
|
|
629
|
-
lineHeight: props.lineHeight, // `undefined` is a valid value
|
|
630
|
-
maxLines: props.maxLines ?? 0,
|
|
631
|
-
textBaseline: props.textBaseline ?? 'alphabetic',
|
|
632
|
-
verticalAlign: props.verticalAlign ?? 'middle',
|
|
633
|
-
overflowSuffix: props.overflowSuffix ?? '...',
|
|
634
|
-
wordBreak: props.wordBreak ?? 'normal',
|
|
635
|
-
debug: props.debug ?? {},
|
|
636
|
-
});
|
|
637
|
-
|
|
638
|
-
const resolvedTextRenderer = this.resolveTextRenderer(
|
|
639
|
-
resolvedProps,
|
|
640
|
-
props.textRendererOverride,
|
|
641
|
-
);
|
|
642
|
-
|
|
643
|
-
if (!resolvedTextRenderer) {
|
|
644
|
-
throw new Error(
|
|
645
|
-
`No compatible text renderer found for ${resolvedProps.fontFamily}`,
|
|
646
|
-
);
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
return new CoreTextNode(this, resolvedProps, resolvedTextRenderer);
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
setBoundsMargin(value: number | [number, number, number, number]) {
|
|
653
|
-
this.boundsMargin = Array.isArray(value)
|
|
654
|
-
? value
|
|
655
|
-
: [value, value, value, value];
|
|
656
|
-
|
|
657
|
-
this.root.setUpdateType(UpdateType.RenderBounds);
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
/**
|
|
661
|
-
* Resolves the default property values for a Node
|
|
662
|
-
*
|
|
663
|
-
* @remarks
|
|
664
|
-
* This method is used internally by the RendererMain to resolve the default
|
|
665
|
-
* property values for a Node. It is exposed publicly so that it can be used
|
|
666
|
-
* by Core Driver implementations.
|
|
667
|
-
*
|
|
668
|
-
* @param props
|
|
669
|
-
* @returns
|
|
670
|
-
*/
|
|
671
|
-
protected resolveNodeDefaults(props: Partial<CoreNodeProps>): CoreNodeProps {
|
|
672
|
-
const color = props.color ?? 0xffffffff;
|
|
673
|
-
const colorTl = props.colorTl ?? props.colorTop ?? props.colorLeft ?? color;
|
|
674
|
-
const colorTr =
|
|
675
|
-
props.colorTr ?? props.colorTop ?? props.colorRight ?? color;
|
|
676
|
-
const colorBl =
|
|
677
|
-
props.colorBl ?? props.colorBottom ?? props.colorLeft ?? color;
|
|
678
|
-
const colorBr =
|
|
679
|
-
props.colorBr ?? props.colorBottom ?? props.colorRight ?? color;
|
|
680
|
-
|
|
681
|
-
let data = {};
|
|
682
|
-
if (this.options.inspector === true) {
|
|
683
|
-
data = santizeCustomDataMap(props.data ?? {});
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
return {
|
|
687
|
-
x: props.x ?? 0,
|
|
688
|
-
y: props.y ?? 0,
|
|
689
|
-
width: props.width ?? 0,
|
|
690
|
-
height: props.height ?? 0,
|
|
691
|
-
alpha: props.alpha ?? 1,
|
|
692
|
-
autosize: props.autosize ?? false,
|
|
693
|
-
boundsMargin: props.boundsMargin ?? null,
|
|
694
|
-
clipping: props.clipping ?? false,
|
|
695
|
-
color,
|
|
696
|
-
colorTop: props.colorTop ?? color,
|
|
697
|
-
colorBottom: props.colorBottom ?? color,
|
|
698
|
-
colorLeft: props.colorLeft ?? color,
|
|
699
|
-
colorRight: props.colorRight ?? color,
|
|
700
|
-
colorBl,
|
|
701
|
-
colorBr,
|
|
702
|
-
colorTl,
|
|
703
|
-
colorTr,
|
|
704
|
-
zIndex: props.zIndex ?? 0,
|
|
705
|
-
zIndexLocked: props.zIndexLocked ?? 0,
|
|
706
|
-
parent: props.parent ?? null,
|
|
707
|
-
texture: props.texture ?? null,
|
|
708
|
-
textureOptions: props.textureOptions ?? {},
|
|
709
|
-
shader: props.shader ?? this.defShaderNode,
|
|
710
|
-
// Since setting the `src` will trigger a texture load, we need to set it after
|
|
711
|
-
// we set the texture. Otherwise, problems happen.
|
|
712
|
-
src: props.src ?? null,
|
|
713
|
-
srcHeight: props.srcHeight,
|
|
714
|
-
srcWidth: props.srcWidth,
|
|
715
|
-
srcX: props.srcX,
|
|
716
|
-
srcY: props.srcY,
|
|
717
|
-
scale: props.scale ?? null,
|
|
718
|
-
scaleX: props.scaleX ?? props.scale ?? 1,
|
|
719
|
-
scaleY: props.scaleY ?? props.scale ?? 1,
|
|
720
|
-
mount: props.mount ?? 0,
|
|
721
|
-
mountX: props.mountX ?? props.mount ?? 0,
|
|
722
|
-
mountY: props.mountY ?? props.mount ?? 0,
|
|
723
|
-
pivot: props.pivot ?? 0.5,
|
|
724
|
-
pivotX: props.pivotX ?? props.pivot ?? 0.5,
|
|
725
|
-
pivotY: props.pivotY ?? props.pivot ?? 0.5,
|
|
726
|
-
rotation: props.rotation ?? 0,
|
|
727
|
-
rtt: props.rtt ?? false,
|
|
728
|
-
data: data,
|
|
729
|
-
preventCleanup: props.preventCleanup ?? false,
|
|
730
|
-
imageType: props.imageType,
|
|
731
|
-
strictBounds: props.strictBounds ?? this.strictBounds,
|
|
732
|
-
};
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
/**
|
|
736
|
-
* Cleanup Orphaned Textures
|
|
737
|
-
*
|
|
738
|
-
* @remarks
|
|
739
|
-
* This method is used to cleanup orphaned textures that are no longer in use.
|
|
740
|
-
*/
|
|
741
|
-
cleanup(aggressive: boolean) {
|
|
742
|
-
this.txMemManager.cleanup(aggressive);
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
set clearColor(value: number) {
|
|
746
|
-
this.renderer.updateClearColor(value);
|
|
747
|
-
this.renderRequested = true;
|
|
748
|
-
this.clrColor = value;
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
get clearColor() {
|
|
752
|
-
return this.clrColor;
|
|
753
|
-
}
|
|
754
|
-
}
|
|
1
|
+
/*
|
|
2
|
+
* If not stated otherwise in this file or this component's LICENSE file the
|
|
3
|
+
* following copyright and licenses apply:
|
|
4
|
+
*
|
|
5
|
+
* Copyright 2023 Comcast Cable Communications Management, LLC.
|
|
6
|
+
*
|
|
7
|
+
* Licensed under the Apache License, Version 2.0 (the License);
|
|
8
|
+
* you may not use this file except in compliance with the License.
|
|
9
|
+
* You may obtain a copy of the License at
|
|
10
|
+
*
|
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
*
|
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
* See the License for the specific language governing permissions and
|
|
17
|
+
* limitations under the License.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { assertTruthy, setPremultiplyMode } from '../utils.js';
|
|
21
|
+
import { AnimationManager } from './animations/AnimationManager.js';
|
|
22
|
+
import {
|
|
23
|
+
UpdateType,
|
|
24
|
+
CoreNode,
|
|
25
|
+
CoreNodeRenderState,
|
|
26
|
+
type CoreNodeProps,
|
|
27
|
+
} from './CoreNode.js';
|
|
28
|
+
import { CoreTextureManager } from './CoreTextureManager.js';
|
|
29
|
+
import { TrFontManager } from './text-rendering/TrFontManager.js';
|
|
30
|
+
import { CoreShaderManager } from './CoreShaderManager.js';
|
|
31
|
+
import {
|
|
32
|
+
TextRenderer,
|
|
33
|
+
type TextRendererMap,
|
|
34
|
+
type TrProps,
|
|
35
|
+
} from './text-rendering/renderers/TextRenderer.js';
|
|
36
|
+
|
|
37
|
+
import { EventEmitter } from '../common/EventEmitter.js';
|
|
38
|
+
import { ContextSpy } from './lib/ContextSpy.js';
|
|
39
|
+
import type {
|
|
40
|
+
FpsUpdatePayload,
|
|
41
|
+
FrameTickPayload,
|
|
42
|
+
QuadsUpdatePayload,
|
|
43
|
+
} from '../common/CommonTypes.js';
|
|
44
|
+
import {
|
|
45
|
+
TextureMemoryManager,
|
|
46
|
+
type TextureMemoryManagerSettings,
|
|
47
|
+
} from './TextureMemoryManager.js';
|
|
48
|
+
import { CoreRenderer } from './renderers/CoreRenderer.js';
|
|
49
|
+
import type { WebGlRenderer } from './renderers/webgl/WebGlRenderer.js';
|
|
50
|
+
import type { CanvasRenderer } from './renderers/canvas/CanvasRenderer.js';
|
|
51
|
+
import { CoreTextNode, type CoreTextNodeProps } from './CoreTextNode.js';
|
|
52
|
+
import { santizeCustomDataMap } from '../main-api/utils.js';
|
|
53
|
+
import type { SdfTextRenderer } from './text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js';
|
|
54
|
+
import type { CanvasTextRenderer } from './text-rendering/renderers/CanvasTextRenderer.js';
|
|
55
|
+
import type { CoreShaderNode } from './renderers/CoreShaderNode.js';
|
|
56
|
+
import { createBound, createPreloadBounds, type Bound } from './lib/utils.js';
|
|
57
|
+
import type { Texture } from './textures/Texture.js';
|
|
58
|
+
import { ColorTexture } from './textures/ColorTexture.js';
|
|
59
|
+
import type { Platform } from './platforms/Platform.js';
|
|
60
|
+
import type { WebPlatform } from './platforms/web/WebPlatform.js';
|
|
61
|
+
|
|
62
|
+
export interface StageOptions {
|
|
63
|
+
appWidth: number;
|
|
64
|
+
appHeight: number;
|
|
65
|
+
textureMemory: TextureMemoryManagerSettings;
|
|
66
|
+
boundsMargin: number | [number, number, number, number];
|
|
67
|
+
deviceLogicalPixelRatio: number;
|
|
68
|
+
devicePhysicalPixelRatio: number;
|
|
69
|
+
canvas: HTMLCanvasElement | OffscreenCanvas;
|
|
70
|
+
clearColor: number;
|
|
71
|
+
fpsUpdateInterval: number;
|
|
72
|
+
enableContextSpy: boolean;
|
|
73
|
+
forceWebGL2: boolean;
|
|
74
|
+
numImageWorkers: number;
|
|
75
|
+
renderEngine: typeof WebGlRenderer | typeof CanvasRenderer;
|
|
76
|
+
eventBus: EventEmitter;
|
|
77
|
+
quadBufferSize: number;
|
|
78
|
+
fontEngines: (typeof CanvasTextRenderer | typeof SdfTextRenderer)[];
|
|
79
|
+
inspector: boolean;
|
|
80
|
+
strictBounds: boolean;
|
|
81
|
+
textureProcessingTimeLimit: number;
|
|
82
|
+
createImageBitmapSupport: 'auto' | 'basic' | 'options' | 'full';
|
|
83
|
+
platform: Platform | WebPlatform;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export type StageFpsUpdateHandler = (
|
|
87
|
+
stage: Stage,
|
|
88
|
+
fpsData: FpsUpdatePayload,
|
|
89
|
+
) => void;
|
|
90
|
+
|
|
91
|
+
export type StageFrameTickHandler = (
|
|
92
|
+
stage: Stage,
|
|
93
|
+
frameTickData: FrameTickPayload,
|
|
94
|
+
) => void;
|
|
95
|
+
|
|
96
|
+
const autoStart = true;
|
|
97
|
+
|
|
98
|
+
export class Stage {
|
|
99
|
+
/// Module Instances
|
|
100
|
+
public readonly animationManager: AnimationManager;
|
|
101
|
+
public readonly txManager: CoreTextureManager;
|
|
102
|
+
public readonly txMemManager: TextureMemoryManager;
|
|
103
|
+
public readonly fontManager: TrFontManager;
|
|
104
|
+
public readonly textRenderers: Partial<TextRendererMap>;
|
|
105
|
+
public readonly shManager: CoreShaderManager;
|
|
106
|
+
public readonly renderer: CoreRenderer;
|
|
107
|
+
public readonly root: CoreNode;
|
|
108
|
+
public boundsMargin: [number, number, number, number];
|
|
109
|
+
public readonly defShaderNode: CoreShaderNode | null = null;
|
|
110
|
+
public readonly strictBound: Bound;
|
|
111
|
+
public readonly preloadBound: Bound;
|
|
112
|
+
public readonly strictBounds: boolean;
|
|
113
|
+
public readonly defaultTexture: Texture | null = null;
|
|
114
|
+
public readonly pixelRatio: number;
|
|
115
|
+
public readonly bufferMemory: number = 2e6;
|
|
116
|
+
public readonly platform: Platform | WebPlatform;
|
|
117
|
+
public readonly calculateTextureCoord: boolean;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Renderer Event Bus for the Stage to emit events onto
|
|
121
|
+
*
|
|
122
|
+
* @remarks
|
|
123
|
+
* In reality this is just the RendererMain instance, which is an EventEmitter.
|
|
124
|
+
* this allows us to directly emit events from the Stage to RendererMain
|
|
125
|
+
* without having to set up forwarding handlers.
|
|
126
|
+
*/
|
|
127
|
+
public readonly eventBus: EventEmitter;
|
|
128
|
+
|
|
129
|
+
/// State
|
|
130
|
+
deltaTime = 0;
|
|
131
|
+
lastFrameTime = 0;
|
|
132
|
+
currentFrameTime = 0;
|
|
133
|
+
private clrColor = 0x00000000;
|
|
134
|
+
private fpsNumFrames = 0;
|
|
135
|
+
private fpsElapsedTime = 0;
|
|
136
|
+
private numQuadsRendered = 0;
|
|
137
|
+
private renderRequested = false;
|
|
138
|
+
private frameEventQueue: [name: string, payload: unknown][] = [];
|
|
139
|
+
private fontResolveMap: Record<string, CanvasTextRenderer | SdfTextRenderer> =
|
|
140
|
+
{};
|
|
141
|
+
|
|
142
|
+
/// Debug data
|
|
143
|
+
contextSpy: ContextSpy | null = null;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Stage constructor
|
|
147
|
+
*/
|
|
148
|
+
constructor(readonly options: StageOptions) {
|
|
149
|
+
const {
|
|
150
|
+
canvas,
|
|
151
|
+
clearColor,
|
|
152
|
+
appWidth,
|
|
153
|
+
appHeight,
|
|
154
|
+
boundsMargin,
|
|
155
|
+
enableContextSpy,
|
|
156
|
+
forceWebGL2,
|
|
157
|
+
numImageWorkers,
|
|
158
|
+
textureMemory,
|
|
159
|
+
renderEngine,
|
|
160
|
+
fontEngines,
|
|
161
|
+
createImageBitmapSupport,
|
|
162
|
+
platform,
|
|
163
|
+
} = options;
|
|
164
|
+
|
|
165
|
+
assertTruthy(
|
|
166
|
+
platform !== null,
|
|
167
|
+
'A CorePlatform is not provided in the options',
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
this.platform = platform;
|
|
171
|
+
|
|
172
|
+
this.eventBus = options.eventBus;
|
|
173
|
+
this.txManager = new CoreTextureManager(this, {
|
|
174
|
+
numImageWorkers,
|
|
175
|
+
createImageBitmapSupport,
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// Wait for the Texture Manager to initialize
|
|
179
|
+
// once it does, request a render
|
|
180
|
+
this.txManager.on('initialized', () => {
|
|
181
|
+
this.requestRender();
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
this.txMemManager = new TextureMemoryManager(this, textureMemory);
|
|
185
|
+
|
|
186
|
+
this.animationManager = new AnimationManager();
|
|
187
|
+
this.contextSpy = enableContextSpy ? new ContextSpy() : null;
|
|
188
|
+
this.strictBounds = options.strictBounds;
|
|
189
|
+
|
|
190
|
+
let bm = [0, 0, 0, 0] as [number, number, number, number];
|
|
191
|
+
if (boundsMargin) {
|
|
192
|
+
bm = Array.isArray(boundsMargin)
|
|
193
|
+
? boundsMargin
|
|
194
|
+
: [boundsMargin, boundsMargin, boundsMargin, boundsMargin];
|
|
195
|
+
}
|
|
196
|
+
this.boundsMargin = bm;
|
|
197
|
+
|
|
198
|
+
// precalculate our viewport bounds
|
|
199
|
+
this.strictBound = createBound(0, 0, appWidth, appHeight);
|
|
200
|
+
this.preloadBound = createPreloadBounds(this.strictBound, bm);
|
|
201
|
+
|
|
202
|
+
this.clrColor = clearColor;
|
|
203
|
+
|
|
204
|
+
this.pixelRatio =
|
|
205
|
+
options.devicePhysicalPixelRatio * options.deviceLogicalPixelRatio;
|
|
206
|
+
|
|
207
|
+
this.renderer = new renderEngine({
|
|
208
|
+
stage: this,
|
|
209
|
+
canvas,
|
|
210
|
+
contextSpy: this.contextSpy,
|
|
211
|
+
forceWebGL2,
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
this.shManager = new CoreShaderManager(this);
|
|
215
|
+
|
|
216
|
+
this.defShaderNode = this.renderer.getDefaultShaderNode();
|
|
217
|
+
this.calculateTextureCoord = this.renderer.getTextureCoords !== undefined;
|
|
218
|
+
|
|
219
|
+
const renderMode = this.renderer.mode || 'webgl';
|
|
220
|
+
|
|
221
|
+
this.createDefaultTexture();
|
|
222
|
+
setPremultiplyMode(renderMode);
|
|
223
|
+
|
|
224
|
+
// Must do this after renderer is created
|
|
225
|
+
this.txManager.renderer = this.renderer;
|
|
226
|
+
|
|
227
|
+
// Create text renderers
|
|
228
|
+
this.textRenderers = {};
|
|
229
|
+
fontEngines.forEach((fontEngineConstructor) => {
|
|
230
|
+
const fontEngineInstance = new fontEngineConstructor(this);
|
|
231
|
+
const className = fontEngineInstance.type;
|
|
232
|
+
|
|
233
|
+
if (className === 'sdf' && renderMode === 'canvas') {
|
|
234
|
+
console.warn(
|
|
235
|
+
'SdfTextRenderer is not compatible with Canvas renderer. Skipping...',
|
|
236
|
+
);
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (fontEngineInstance instanceof TextRenderer) {
|
|
241
|
+
if (className === 'canvas') {
|
|
242
|
+
this.textRenderers['canvas'] =
|
|
243
|
+
fontEngineInstance as CanvasTextRenderer;
|
|
244
|
+
} else if (className === 'sdf') {
|
|
245
|
+
this.textRenderers['sdf'] = fontEngineInstance as SdfTextRenderer;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
if (Object.keys(this.textRenderers).length === 0) {
|
|
251
|
+
console.warn('No text renderers available. Your text will not render.');
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
this.fontManager = new TrFontManager(this.textRenderers);
|
|
255
|
+
|
|
256
|
+
// create root node
|
|
257
|
+
const rootNode = new CoreNode(this, {
|
|
258
|
+
x: 0,
|
|
259
|
+
y: 0,
|
|
260
|
+
width: appWidth,
|
|
261
|
+
height: appHeight,
|
|
262
|
+
alpha: 1,
|
|
263
|
+
autosize: false,
|
|
264
|
+
boundsMargin: null,
|
|
265
|
+
clipping: false,
|
|
266
|
+
color: 0x00000000,
|
|
267
|
+
colorTop: 0x00000000,
|
|
268
|
+
colorBottom: 0x00000000,
|
|
269
|
+
colorLeft: 0x00000000,
|
|
270
|
+
colorRight: 0x00000000,
|
|
271
|
+
colorTl: 0x00000000,
|
|
272
|
+
colorTr: 0x00000000,
|
|
273
|
+
colorBl: 0x00000000,
|
|
274
|
+
colorBr: 0x00000000,
|
|
275
|
+
zIndex: 0,
|
|
276
|
+
zIndexLocked: 0,
|
|
277
|
+
scaleX: 1,
|
|
278
|
+
scaleY: 1,
|
|
279
|
+
mountX: 0,
|
|
280
|
+
mountY: 0,
|
|
281
|
+
mount: 0,
|
|
282
|
+
pivot: 0.5,
|
|
283
|
+
pivotX: 0.5,
|
|
284
|
+
pivotY: 0.5,
|
|
285
|
+
rotation: 0,
|
|
286
|
+
parent: null,
|
|
287
|
+
texture: null,
|
|
288
|
+
textureOptions: {},
|
|
289
|
+
shader: this.defShaderNode,
|
|
290
|
+
rtt: false,
|
|
291
|
+
src: null,
|
|
292
|
+
scale: 1,
|
|
293
|
+
preventCleanup: false,
|
|
294
|
+
strictBounds: this.strictBounds,
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
this.root = rootNode;
|
|
298
|
+
|
|
299
|
+
// execute platform start loop
|
|
300
|
+
if (autoStart === true) {
|
|
301
|
+
this.platform.startLoop(this);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
setClearColor(color: number) {
|
|
306
|
+
this.clearColor = color;
|
|
307
|
+
this.renderer.updateClearColor(color);
|
|
308
|
+
this.renderRequested = true;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
updateFrameTime() {
|
|
312
|
+
const newFrameTime = this.platform!.getTimeStamp();
|
|
313
|
+
this.lastFrameTime = this.currentFrameTime;
|
|
314
|
+
this.currentFrameTime = newFrameTime;
|
|
315
|
+
this.deltaTime = !this.lastFrameTime
|
|
316
|
+
? 100 / 6
|
|
317
|
+
: newFrameTime - this.lastFrameTime;
|
|
318
|
+
this.txManager.frameTime = newFrameTime;
|
|
319
|
+
this.txMemManager.frameTime = newFrameTime;
|
|
320
|
+
|
|
321
|
+
// This event is emitted at the beginning of the frame (before any updates
|
|
322
|
+
// or rendering), so no need to to use `stage.queueFrameEvent` here.
|
|
323
|
+
this.eventBus.emit('frameTick', {
|
|
324
|
+
time: this.currentFrameTime,
|
|
325
|
+
delta: this.deltaTime,
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Create default PixelTexture
|
|
331
|
+
*/
|
|
332
|
+
createDefaultTexture() {
|
|
333
|
+
console.log('Creating default texture');
|
|
334
|
+
(this.defaultTexture as ColorTexture) = this.txManager.createTexture(
|
|
335
|
+
'ColorTexture',
|
|
336
|
+
{
|
|
337
|
+
color: 0xffffffff,
|
|
338
|
+
},
|
|
339
|
+
);
|
|
340
|
+
|
|
341
|
+
assertTruthy(this.defaultTexture instanceof ColorTexture);
|
|
342
|
+
this.txManager.loadTexture(this.defaultTexture, true);
|
|
343
|
+
|
|
344
|
+
// Mark the default texture as ALWAYS renderable
|
|
345
|
+
// This prevents it from ever being cleaned up.
|
|
346
|
+
// Fixes https://github.com/lightning-js/renderer/issues/262
|
|
347
|
+
this.defaultTexture.setRenderableOwner(this, true);
|
|
348
|
+
|
|
349
|
+
// When the default texture is loaded, request a render in case the
|
|
350
|
+
// RAF is paused. Fixes: https://github.com/lightning-js/renderer/issues/123
|
|
351
|
+
this.defaultTexture.once('loaded', () => {
|
|
352
|
+
this.requestRender();
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Update animations
|
|
358
|
+
*/
|
|
359
|
+
updateAnimations() {
|
|
360
|
+
const { animationManager } = this;
|
|
361
|
+
if (!this.root) {
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
// step animation
|
|
365
|
+
animationManager.update(this.deltaTime);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Check if the scene has updates
|
|
370
|
+
*/
|
|
371
|
+
hasSceneUpdates() {
|
|
372
|
+
return (
|
|
373
|
+
!!this.root.updateType ||
|
|
374
|
+
this.renderRequested ||
|
|
375
|
+
this.txManager.hasUpdates()
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Start a new frame draw
|
|
381
|
+
*/
|
|
382
|
+
drawFrame() {
|
|
383
|
+
const { renderer, renderRequested } = this;
|
|
384
|
+
assertTruthy(renderer);
|
|
385
|
+
|
|
386
|
+
// Update tree if needed
|
|
387
|
+
if (this.root.updateType !== 0) {
|
|
388
|
+
this.root.update(this.deltaTime, this.root.clippingRect);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Process some textures
|
|
392
|
+
this.txManager.processSome(this.options.textureProcessingTimeLimit);
|
|
393
|
+
|
|
394
|
+
// Reset render operations and clear the canvas
|
|
395
|
+
renderer.reset();
|
|
396
|
+
|
|
397
|
+
// Check if we need to cleanup textures
|
|
398
|
+
if (this.txMemManager.criticalCleanupRequested === true) {
|
|
399
|
+
this.txMemManager.cleanup(false);
|
|
400
|
+
|
|
401
|
+
if (this.txMemManager.criticalCleanupRequested === true) {
|
|
402
|
+
// If we still need to cleanup, request another but aggressive cleanup
|
|
403
|
+
this.txMemManager.cleanup(true);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// If we have RTT nodes draw them first
|
|
408
|
+
// So we can use them as textures in the main scene
|
|
409
|
+
if (renderer.rttNodes.length > 0) {
|
|
410
|
+
renderer.renderRTTNodes();
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// Fill quads buffer
|
|
414
|
+
this.addQuads(this.root);
|
|
415
|
+
|
|
416
|
+
// Perform render pass
|
|
417
|
+
renderer?.render();
|
|
418
|
+
|
|
419
|
+
this.calculateFps();
|
|
420
|
+
this.calculateQuads();
|
|
421
|
+
|
|
422
|
+
// Reset renderRequested flag if it was set
|
|
423
|
+
if (renderRequested) {
|
|
424
|
+
this.renderRequested = false;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Queue an event to be emitted after the current/next frame is rendered
|
|
430
|
+
*
|
|
431
|
+
* @remarks
|
|
432
|
+
* When we are operating in the context of the render loop, we may want to
|
|
433
|
+
* emit events that are related to the current frame. However, we generally do
|
|
434
|
+
* NOT want to emit events directly in the middle of the render loop, since
|
|
435
|
+
* this could enable event handlers to modify the scene graph and cause
|
|
436
|
+
* unexpected behavior. Instead, we queue up events to be emitted and then
|
|
437
|
+
* flush the queue after the frame has been rendered.
|
|
438
|
+
*
|
|
439
|
+
* @param name
|
|
440
|
+
* @param data
|
|
441
|
+
*/
|
|
442
|
+
queueFrameEvent(name: string, data: unknown) {
|
|
443
|
+
this.frameEventQueue.push([name, data]);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Emit all queued frame events
|
|
448
|
+
*
|
|
449
|
+
* @remarks
|
|
450
|
+
* This method should be called after the frame has been rendered to emit
|
|
451
|
+
* all events that were queued during the frame.
|
|
452
|
+
*
|
|
453
|
+
* See {@link queueFrameEvent} for more information.
|
|
454
|
+
*/
|
|
455
|
+
flushFrameEvents() {
|
|
456
|
+
for (const [name, data] of this.frameEventQueue) {
|
|
457
|
+
this.eventBus.emit(name, data);
|
|
458
|
+
}
|
|
459
|
+
this.frameEventQueue = [];
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
calculateFps() {
|
|
463
|
+
// If there's an FPS update interval, emit the FPS update event
|
|
464
|
+
// when the specified interval has elapsed.
|
|
465
|
+
const { fpsUpdateInterval } = this.options;
|
|
466
|
+
if (fpsUpdateInterval) {
|
|
467
|
+
this.fpsNumFrames++;
|
|
468
|
+
this.fpsElapsedTime += this.deltaTime;
|
|
469
|
+
if (this.fpsElapsedTime >= fpsUpdateInterval) {
|
|
470
|
+
const fps = Math.round(
|
|
471
|
+
(this.fpsNumFrames * 1000) / this.fpsElapsedTime,
|
|
472
|
+
);
|
|
473
|
+
this.fpsNumFrames = 0;
|
|
474
|
+
this.fpsElapsedTime = 0;
|
|
475
|
+
this.queueFrameEvent('fpsUpdate', {
|
|
476
|
+
fps,
|
|
477
|
+
contextSpyData: this.contextSpy?.getData() ?? null,
|
|
478
|
+
} satisfies FpsUpdatePayload);
|
|
479
|
+
this.contextSpy?.reset();
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
calculateQuads() {
|
|
485
|
+
const quads = this.renderer.getQuadCount();
|
|
486
|
+
if (quads && quads !== this.numQuadsRendered) {
|
|
487
|
+
this.numQuadsRendered = quads;
|
|
488
|
+
this.queueFrameEvent('quadsUpdate', {
|
|
489
|
+
quads,
|
|
490
|
+
} satisfies QuadsUpdatePayload);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
addQuads(node: CoreNode) {
|
|
495
|
+
assertTruthy(this.renderer);
|
|
496
|
+
|
|
497
|
+
// If the node is renderable and has a loaded texture, render it
|
|
498
|
+
if (node.isRenderable === true) {
|
|
499
|
+
node.renderQuads(this.renderer);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
503
|
+
const child = node.children[i];
|
|
504
|
+
|
|
505
|
+
if (child === undefined) {
|
|
506
|
+
continue;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
if (
|
|
510
|
+
child.worldAlpha === 0 ||
|
|
511
|
+
(child.strictBounds === true &&
|
|
512
|
+
child.renderState === CoreNodeRenderState.OutOfBounds)
|
|
513
|
+
) {
|
|
514
|
+
continue;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
this.addQuads(child);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* Request a render pass without forcing an update
|
|
523
|
+
*/
|
|
524
|
+
requestRender() {
|
|
525
|
+
this.renderRequested = true;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Given a font name, and possible renderer override, return the best compatible text renderer.
|
|
530
|
+
*
|
|
531
|
+
* @remarks
|
|
532
|
+
* Will try to return a canvas renderer if no other suitable renderer can be resolved.
|
|
533
|
+
*
|
|
534
|
+
* @param fontFamily
|
|
535
|
+
* @param textRendererOverride
|
|
536
|
+
* @returns
|
|
537
|
+
*/
|
|
538
|
+
resolveTextRenderer(
|
|
539
|
+
trProps: TrProps,
|
|
540
|
+
textRendererOverride: keyof TextRendererMap | null = null,
|
|
541
|
+
): TextRenderer | null {
|
|
542
|
+
const fontCacheString = `${trProps.fontFamily}${trProps.fontStyle}${
|
|
543
|
+
trProps.fontWeight
|
|
544
|
+
}${trProps.fontStretch}${textRendererOverride ? textRendererOverride : ''}`;
|
|
545
|
+
|
|
546
|
+
// check our resolve cache first
|
|
547
|
+
if (this.fontResolveMap[fontCacheString] !== undefined) {
|
|
548
|
+
return this.fontResolveMap[fontCacheString] as unknown as TextRenderer;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// Resolve the text renderer
|
|
552
|
+
let rendererId = textRendererOverride;
|
|
553
|
+
let overrideFallback = false;
|
|
554
|
+
|
|
555
|
+
// Check if the override is valid (if one is provided)
|
|
556
|
+
if (rendererId) {
|
|
557
|
+
const possibleRenderer = this.textRenderers[rendererId];
|
|
558
|
+
if (!possibleRenderer) {
|
|
559
|
+
console.warn(`Text renderer override '${rendererId}' not found.`);
|
|
560
|
+
rendererId = null;
|
|
561
|
+
overrideFallback = true;
|
|
562
|
+
} else if (!possibleRenderer.canRenderFont(trProps)) {
|
|
563
|
+
console.warn(
|
|
564
|
+
`Cannot use override text renderer '${rendererId}' for font`,
|
|
565
|
+
trProps,
|
|
566
|
+
);
|
|
567
|
+
rendererId = null;
|
|
568
|
+
overrideFallback = true;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
if (!rendererId) {
|
|
573
|
+
// Iterate through the text renderers and find the first one that can render the font
|
|
574
|
+
for (const [trId, tr] of Object.entries(this.textRenderers)) {
|
|
575
|
+
if (tr.canRenderFont(trProps)) {
|
|
576
|
+
rendererId = trId as keyof TextRendererMap;
|
|
577
|
+
break;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
if (!rendererId && this.textRenderers.canvas !== undefined) {
|
|
581
|
+
// If no renderer can be found, use the canvas renderer
|
|
582
|
+
rendererId = 'canvas';
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
if (overrideFallback) {
|
|
587
|
+
console.warn(`Falling back to text renderer ${String(rendererId)}`);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
if (!rendererId) {
|
|
591
|
+
// silently fail if no renderer can be found, the error is already created
|
|
592
|
+
// at the constructor level
|
|
593
|
+
return null;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// By now we are guaranteed to have a valid rendererId (at least Canvas);
|
|
597
|
+
const resolvedTextRenderer = this.textRenderers[rendererId];
|
|
598
|
+
assertTruthy(resolvedTextRenderer, 'resolvedTextRenderer undefined');
|
|
599
|
+
|
|
600
|
+
// cache the resolved renderer for future use with these trProps
|
|
601
|
+
this.fontResolveMap[fontCacheString] = resolvedTextRenderer;
|
|
602
|
+
|
|
603
|
+
// Need to explicitly cast to TextRenderer because TS doesn't like
|
|
604
|
+
// the covariant state argument in the setter method map
|
|
605
|
+
return resolvedTextRenderer as unknown as TextRenderer;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
createNode(props: Partial<CoreNodeProps>) {
|
|
609
|
+
const resolvedProps = this.resolveNodeDefaults(props);
|
|
610
|
+
return new CoreNode(this, resolvedProps);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
createTextNode(props: Partial<CoreTextNodeProps>) {
|
|
614
|
+
const fontSize = props.fontSize ?? 16;
|
|
615
|
+
const resolvedProps = Object.assign(this.resolveNodeDefaults(props), {
|
|
616
|
+
text: props.text ?? '',
|
|
617
|
+
textRendererOverride: props.textRendererOverride ?? null,
|
|
618
|
+
fontSize,
|
|
619
|
+
fontFamily: props.fontFamily ?? 'sans-serif',
|
|
620
|
+
fontStyle: props.fontStyle ?? 'normal',
|
|
621
|
+
fontWeight: props.fontWeight ?? 'normal',
|
|
622
|
+
fontStretch: props.fontStretch ?? 'normal',
|
|
623
|
+
textAlign: props.textAlign ?? 'left',
|
|
624
|
+
contain: props.contain ?? 'none',
|
|
625
|
+
scrollable: props.scrollable ?? false,
|
|
626
|
+
scrollY: props.scrollY ?? 0,
|
|
627
|
+
offsetY: props.offsetY ?? 0,
|
|
628
|
+
letterSpacing: props.letterSpacing ?? 0,
|
|
629
|
+
lineHeight: props.lineHeight, // `undefined` is a valid value
|
|
630
|
+
maxLines: props.maxLines ?? 0,
|
|
631
|
+
textBaseline: props.textBaseline ?? 'alphabetic',
|
|
632
|
+
verticalAlign: props.verticalAlign ?? 'middle',
|
|
633
|
+
overflowSuffix: props.overflowSuffix ?? '...',
|
|
634
|
+
wordBreak: props.wordBreak ?? 'normal',
|
|
635
|
+
debug: props.debug ?? {},
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
const resolvedTextRenderer = this.resolveTextRenderer(
|
|
639
|
+
resolvedProps,
|
|
640
|
+
props.textRendererOverride,
|
|
641
|
+
);
|
|
642
|
+
|
|
643
|
+
if (!resolvedTextRenderer) {
|
|
644
|
+
throw new Error(
|
|
645
|
+
`No compatible text renderer found for ${resolvedProps.fontFamily}`,
|
|
646
|
+
);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
return new CoreTextNode(this, resolvedProps, resolvedTextRenderer);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
setBoundsMargin(value: number | [number, number, number, number]) {
|
|
653
|
+
this.boundsMargin = Array.isArray(value)
|
|
654
|
+
? value
|
|
655
|
+
: [value, value, value, value];
|
|
656
|
+
|
|
657
|
+
this.root.setUpdateType(UpdateType.RenderBounds);
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
* Resolves the default property values for a Node
|
|
662
|
+
*
|
|
663
|
+
* @remarks
|
|
664
|
+
* This method is used internally by the RendererMain to resolve the default
|
|
665
|
+
* property values for a Node. It is exposed publicly so that it can be used
|
|
666
|
+
* by Core Driver implementations.
|
|
667
|
+
*
|
|
668
|
+
* @param props
|
|
669
|
+
* @returns
|
|
670
|
+
*/
|
|
671
|
+
protected resolveNodeDefaults(props: Partial<CoreNodeProps>): CoreNodeProps {
|
|
672
|
+
const color = props.color ?? 0xffffffff;
|
|
673
|
+
const colorTl = props.colorTl ?? props.colorTop ?? props.colorLeft ?? color;
|
|
674
|
+
const colorTr =
|
|
675
|
+
props.colorTr ?? props.colorTop ?? props.colorRight ?? color;
|
|
676
|
+
const colorBl =
|
|
677
|
+
props.colorBl ?? props.colorBottom ?? props.colorLeft ?? color;
|
|
678
|
+
const colorBr =
|
|
679
|
+
props.colorBr ?? props.colorBottom ?? props.colorRight ?? color;
|
|
680
|
+
|
|
681
|
+
let data = {};
|
|
682
|
+
if (this.options.inspector === true) {
|
|
683
|
+
data = santizeCustomDataMap(props.data ?? {});
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
return {
|
|
687
|
+
x: props.x ?? 0,
|
|
688
|
+
y: props.y ?? 0,
|
|
689
|
+
width: props.width ?? 0,
|
|
690
|
+
height: props.height ?? 0,
|
|
691
|
+
alpha: props.alpha ?? 1,
|
|
692
|
+
autosize: props.autosize ?? false,
|
|
693
|
+
boundsMargin: props.boundsMargin ?? null,
|
|
694
|
+
clipping: props.clipping ?? false,
|
|
695
|
+
color,
|
|
696
|
+
colorTop: props.colorTop ?? color,
|
|
697
|
+
colorBottom: props.colorBottom ?? color,
|
|
698
|
+
colorLeft: props.colorLeft ?? color,
|
|
699
|
+
colorRight: props.colorRight ?? color,
|
|
700
|
+
colorBl,
|
|
701
|
+
colorBr,
|
|
702
|
+
colorTl,
|
|
703
|
+
colorTr,
|
|
704
|
+
zIndex: props.zIndex ?? 0,
|
|
705
|
+
zIndexLocked: props.zIndexLocked ?? 0,
|
|
706
|
+
parent: props.parent ?? null,
|
|
707
|
+
texture: props.texture ?? null,
|
|
708
|
+
textureOptions: props.textureOptions ?? {},
|
|
709
|
+
shader: props.shader ?? this.defShaderNode,
|
|
710
|
+
// Since setting the `src` will trigger a texture load, we need to set it after
|
|
711
|
+
// we set the texture. Otherwise, problems happen.
|
|
712
|
+
src: props.src ?? null,
|
|
713
|
+
srcHeight: props.srcHeight,
|
|
714
|
+
srcWidth: props.srcWidth,
|
|
715
|
+
srcX: props.srcX,
|
|
716
|
+
srcY: props.srcY,
|
|
717
|
+
scale: props.scale ?? null,
|
|
718
|
+
scaleX: props.scaleX ?? props.scale ?? 1,
|
|
719
|
+
scaleY: props.scaleY ?? props.scale ?? 1,
|
|
720
|
+
mount: props.mount ?? 0,
|
|
721
|
+
mountX: props.mountX ?? props.mount ?? 0,
|
|
722
|
+
mountY: props.mountY ?? props.mount ?? 0,
|
|
723
|
+
pivot: props.pivot ?? 0.5,
|
|
724
|
+
pivotX: props.pivotX ?? props.pivot ?? 0.5,
|
|
725
|
+
pivotY: props.pivotY ?? props.pivot ?? 0.5,
|
|
726
|
+
rotation: props.rotation ?? 0,
|
|
727
|
+
rtt: props.rtt ?? false,
|
|
728
|
+
data: data,
|
|
729
|
+
preventCleanup: props.preventCleanup ?? false,
|
|
730
|
+
imageType: props.imageType,
|
|
731
|
+
strictBounds: props.strictBounds ?? this.strictBounds,
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
/**
|
|
736
|
+
* Cleanup Orphaned Textures
|
|
737
|
+
*
|
|
738
|
+
* @remarks
|
|
739
|
+
* This method is used to cleanup orphaned textures that are no longer in use.
|
|
740
|
+
*/
|
|
741
|
+
cleanup(aggressive: boolean) {
|
|
742
|
+
this.txMemManager.cleanup(aggressive);
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
set clearColor(value: number) {
|
|
746
|
+
this.renderer.updateClearColor(value);
|
|
747
|
+
this.renderRequested = true;
|
|
748
|
+
this.clrColor = value;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
get clearColor() {
|
|
752
|
+
return this.clrColor;
|
|
753
|
+
}
|
|
754
|
+
}
|