@solidtv/renderer 1.0.0
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 -0
- package/NOTICE +7 -0
- package/README.md +137 -0
- package/dist/exports/canvas-shaders.d.ts +10 -0
- package/dist/exports/canvas-shaders.js +11 -0
- package/dist/exports/canvas-shaders.js.map +1 -0
- package/dist/exports/canvas.d.ts +26 -0
- package/dist/exports/canvas.js +27 -0
- package/dist/exports/canvas.js.map +1 -0
- package/dist/exports/index.d.ts +50 -0
- package/dist/exports/index.js +40 -0
- package/dist/exports/index.js.map +1 -0
- package/dist/exports/inspector.d.ts +4 -0
- package/dist/exports/inspector.js +5 -0
- package/dist/exports/inspector.js.map +1 -0
- package/dist/exports/utils.d.ts +27 -0
- package/dist/exports/utils.js +28 -0
- package/dist/exports/utils.js.map +1 -0
- package/dist/exports/webgl-shaders.d.ts +11 -0
- package/dist/exports/webgl-shaders.js +12 -0
- package/dist/exports/webgl-shaders.js.map +1 -0
- package/dist/exports/webgl.d.ts +28 -0
- package/dist/exports/webgl.js +29 -0
- package/dist/exports/webgl.js.map +1 -0
- package/dist/src/common/CommonTypes.d.ts +110 -0
- package/dist/src/common/CommonTypes.js +2 -0
- package/dist/src/common/CommonTypes.js.map +1 -0
- package/dist/src/common/EventEmitter.d.ts +12 -0
- package/dist/src/common/EventEmitter.js +48 -0
- package/dist/src/common/EventEmitter.js.map +1 -0
- package/dist/src/common/IAnimationController.d.ts +58 -0
- package/dist/src/common/IAnimationController.js +2 -0
- package/dist/src/common/IAnimationController.js.map +1 -0
- package/dist/src/common/IEventEmitter.d.ts +8 -0
- package/dist/src/common/IEventEmitter.js +2 -0
- package/dist/src/common/IEventEmitter.js.map +1 -0
- package/dist/src/core/Autosizer.d.ts +35 -0
- package/dist/src/core/Autosizer.js +178 -0
- package/dist/src/core/Autosizer.js.map +1 -0
- package/dist/src/core/CoreNode.d.ts +908 -0
- package/dist/src/core/CoreNode.js +1837 -0
- package/dist/src/core/CoreNode.js.map +1 -0
- package/dist/src/core/CoreShaderManager.d.ts +38 -0
- package/dist/src/core/CoreShaderManager.js +123 -0
- package/dist/src/core/CoreShaderManager.js.map +1 -0
- package/dist/src/core/CoreTextNode.d.ts +91 -0
- package/dist/src/core/CoreTextNode.js +440 -0
- package/dist/src/core/CoreTextNode.js.map +1 -0
- package/dist/src/core/CoreTextureManager.d.ts +264 -0
- package/dist/src/core/CoreTextureManager.js +318 -0
- package/dist/src/core/CoreTextureManager.js.map +1 -0
- package/dist/src/core/Stage.d.ts +238 -0
- package/dist/src/core/Stage.js +804 -0
- package/dist/src/core/Stage.js.map +1 -0
- package/dist/src/core/TextureError.d.ts +11 -0
- package/dist/src/core/TextureError.js +37 -0
- package/dist/src/core/TextureError.js.map +1 -0
- package/dist/src/core/TextureMemoryManager.d.ts +150 -0
- package/dist/src/core/TextureMemoryManager.js +239 -0
- package/dist/src/core/TextureMemoryManager.js.map +1 -0
- package/dist/src/core/animations/AnimationManager.d.ts +33 -0
- package/dist/src/core/animations/AnimationManager.js +137 -0
- package/dist/src/core/animations/AnimationManager.js.map +1 -0
- package/dist/src/core/animations/CoreAnimation.d.ts +12 -0
- package/dist/src/core/animations/CoreAnimation.js +107 -0
- package/dist/src/core/animations/CoreAnimation.js.map +1 -0
- package/dist/src/core/lib/ContextSpy.d.ts +12 -0
- package/dist/src/core/lib/ContextSpy.js +20 -0
- package/dist/src/core/lib/ContextSpy.js.map +1 -0
- package/dist/src/core/lib/ImageWorker.d.ts +16 -0
- package/dist/src/core/lib/ImageWorker.js +202 -0
- package/dist/src/core/lib/ImageWorker.js.map +1 -0
- package/dist/src/core/lib/Matrix3d.d.ts +74 -0
- package/dist/src/core/lib/Matrix3d.js +218 -0
- package/dist/src/core/lib/Matrix3d.js.map +1 -0
- package/dist/src/core/lib/RenderCoords.d.ts +12 -0
- package/dist/src/core/lib/RenderCoords.js +35 -0
- package/dist/src/core/lib/RenderCoords.js.map +1 -0
- package/dist/src/core/lib/WebGlContextWrapper.d.ts +782 -0
- package/dist/src/core/lib/WebGlContextWrapper.js +1143 -0
- package/dist/src/core/lib/WebGlContextWrapper.js.map +1 -0
- package/dist/src/core/lib/collectionUtils.d.ts +5 -0
- package/dist/src/core/lib/collectionUtils.js +82 -0
- package/dist/src/core/lib/collectionUtils.js.map +1 -0
- package/dist/src/core/lib/colorCache.d.ts +1 -0
- package/dist/src/core/lib/colorCache.js +19 -0
- package/dist/src/core/lib/colorCache.js.map +1 -0
- package/dist/src/core/lib/colorParser.d.ts +21 -0
- package/dist/src/core/lib/colorParser.js +54 -0
- package/dist/src/core/lib/colorParser.js.map +1 -0
- package/dist/src/core/lib/textureCompression.d.ts +28 -0
- package/dist/src/core/lib/textureCompression.js +363 -0
- package/dist/src/core/lib/textureCompression.js.map +1 -0
- package/dist/src/core/lib/textureSvg.d.ts +16 -0
- package/dist/src/core/lib/textureSvg.js +45 -0
- package/dist/src/core/lib/textureSvg.js.map +1 -0
- package/dist/src/core/lib/utils.d.ts +66 -0
- package/dist/src/core/lib/utils.js +268 -0
- package/dist/src/core/lib/utils.js.map +1 -0
- package/dist/src/core/lib/validateImageBitmap.d.ts +7 -0
- package/dist/src/core/lib/validateImageBitmap.js +68 -0
- package/dist/src/core/lib/validateImageBitmap.js.map +1 -0
- package/dist/src/core/platforms/Platform.d.ts +42 -0
- package/dist/src/core/platforms/Platform.js +4 -0
- package/dist/src/core/platforms/Platform.js.map +1 -0
- package/dist/src/core/platforms/web/WebPlatform.d.ts +10 -0
- package/dist/src/core/platforms/web/WebPlatform.js +90 -0
- package/dist/src/core/platforms/web/WebPlatform.js.map +1 -0
- package/dist/src/core/renderers/CoreContextTexture.d.ts +13 -0
- package/dist/src/core/renderers/CoreContextTexture.js +16 -0
- package/dist/src/core/renderers/CoreContextTexture.js.map +1 -0
- package/dist/src/core/renderers/CoreRenderOp.d.ts +3 -0
- package/dist/src/core/renderers/CoreRenderOp.js +3 -0
- package/dist/src/core/renderers/CoreRenderOp.js.map +1 -0
- package/dist/src/core/renderers/CoreRenderer.d.ts +81 -0
- package/dist/src/core/renderers/CoreRenderer.js +14 -0
- package/dist/src/core/renderers/CoreRenderer.js.map +1 -0
- package/dist/src/core/renderers/CoreShaderNode.d.ts +69 -0
- package/dist/src/core/renderers/CoreShaderNode.js +130 -0
- package/dist/src/core/renderers/CoreShaderNode.js.map +1 -0
- package/dist/src/core/renderers/CoreShaderProgram.d.ts +4 -0
- package/dist/src/core/renderers/CoreShaderProgram.js +2 -0
- package/dist/src/core/renderers/CoreShaderProgram.js.map +1 -0
- package/dist/src/core/renderers/canvas/CanvasRenderer.d.ts +36 -0
- package/dist/src/core/renderers/canvas/CanvasRenderer.js +221 -0
- package/dist/src/core/renderers/canvas/CanvasRenderer.js.map +1 -0
- package/dist/src/core/renderers/canvas/CanvasShaderNode.d.ts +21 -0
- package/dist/src/core/renderers/canvas/CanvasShaderNode.js +42 -0
- package/dist/src/core/renderers/canvas/CanvasShaderNode.js.map +1 -0
- package/dist/src/core/renderers/canvas/CanvasTexture.d.ts +17 -0
- package/dist/src/core/renderers/canvas/CanvasTexture.js +110 -0
- package/dist/src/core/renderers/canvas/CanvasTexture.js.map +1 -0
- package/dist/src/core/renderers/webgl/SdfRenderOp.d.ts +41 -0
- package/dist/src/core/renderers/webgl/SdfRenderOp.js +88 -0
- package/dist/src/core/renderers/webgl/SdfRenderOp.js.map +1 -0
- package/dist/src/core/renderers/webgl/WebGlCtxRenderTexture.d.ts +14 -0
- package/dist/src/core/renderers/webgl/WebGlCtxRenderTexture.js +45 -0
- package/dist/src/core/renderers/webgl/WebGlCtxRenderTexture.js.map +1 -0
- package/dist/src/core/renderers/webgl/WebGlCtxSubTexture.d.ts +22 -0
- package/dist/src/core/renderers/webgl/WebGlCtxSubTexture.js +49 -0
- package/dist/src/core/renderers/webgl/WebGlCtxSubTexture.js.map +1 -0
- package/dist/src/core/renderers/webgl/WebGlCtxTexture.d.ts +67 -0
- package/dist/src/core/renderers/webgl/WebGlCtxTexture.js +259 -0
- package/dist/src/core/renderers/webgl/WebGlCtxTexture.js.map +1 -0
- package/dist/src/core/renderers/webgl/WebGlRenderer.d.ts +221 -0
- package/dist/src/core/renderers/webgl/WebGlRenderer.js +1015 -0
- package/dist/src/core/renderers/webgl/WebGlRenderer.js.map +1 -0
- package/dist/src/core/renderers/webgl/WebGlShaderNode.d.ts +213 -0
- package/dist/src/core/renderers/webgl/WebGlShaderNode.js +331 -0
- package/dist/src/core/renderers/webgl/WebGlShaderNode.js.map +1 -0
- package/dist/src/core/renderers/webgl/WebGlShaderProgram.d.ts +37 -0
- package/dist/src/core/renderers/webgl/WebGlShaderProgram.js +240 -0
- package/dist/src/core/renderers/webgl/WebGlShaderProgram.js.map +1 -0
- package/dist/src/core/renderers/webgl/internal/BufferCollection.d.ts +28 -0
- package/dist/src/core/renderers/webgl/internal/BufferCollection.js +39 -0
- package/dist/src/core/renderers/webgl/internal/BufferCollection.js.map +1 -0
- package/dist/src/core/renderers/webgl/internal/RendererUtils.d.ts +55 -0
- package/dist/src/core/renderers/webgl/internal/RendererUtils.js +88 -0
- package/dist/src/core/renderers/webgl/internal/RendererUtils.js.map +1 -0
- package/dist/src/core/renderers/webgl/internal/ShaderUtils.d.ts +74 -0
- package/dist/src/core/renderers/webgl/internal/ShaderUtils.js +83 -0
- package/dist/src/core/renderers/webgl/internal/ShaderUtils.js.map +1 -0
- package/dist/src/core/renderers/webgl/internal/WebGlUtils.d.ts +10 -0
- package/dist/src/core/renderers/webgl/internal/WebGlUtils.js +13 -0
- package/dist/src/core/renderers/webgl/internal/WebGlUtils.js.map +1 -0
- package/dist/src/core/shaders/canvas/Border.d.ts +15 -0
- package/dist/src/core/shaders/canvas/Border.js +83 -0
- package/dist/src/core/shaders/canvas/Border.js.map +1 -0
- package/dist/src/core/shaders/canvas/HolePunch.d.ts +7 -0
- package/dist/src/core/shaders/canvas/HolePunch.js +22 -0
- package/dist/src/core/shaders/canvas/HolePunch.js.map +1 -0
- package/dist/src/core/shaders/canvas/LinearGradient.d.ts +10 -0
- package/dist/src/core/shaders/canvas/LinearGradient.js +32 -0
- package/dist/src/core/shaders/canvas/LinearGradient.js.map +1 -0
- package/dist/src/core/shaders/canvas/RadialGradient.d.ts +11 -0
- package/dist/src/core/shaders/canvas/RadialGradient.js +54 -0
- package/dist/src/core/shaders/canvas/RadialGradient.js.map +1 -0
- package/dist/src/core/shaders/canvas/Rounded.d.ts +7 -0
- package/dist/src/core/shaders/canvas/Rounded.js +17 -0
- package/dist/src/core/shaders/canvas/Rounded.js.map +1 -0
- package/dist/src/core/shaders/canvas/RoundedWithBorder.d.ts +10 -0
- package/dist/src/core/shaders/canvas/RoundedWithBorder.js +57 -0
- package/dist/src/core/shaders/canvas/RoundedWithBorder.js.map +1 -0
- package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.d.ts +7 -0
- package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.js +61 -0
- package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.js.map +1 -0
- package/dist/src/core/shaders/canvas/RoundedWithShadow.d.ts +7 -0
- package/dist/src/core/shaders/canvas/RoundedWithShadow.js +26 -0
- package/dist/src/core/shaders/canvas/RoundedWithShadow.js.map +1 -0
- package/dist/src/core/shaders/canvas/Shadow.d.ts +8 -0
- package/dist/src/core/shaders/canvas/Shadow.js +15 -0
- package/dist/src/core/shaders/canvas/Shadow.js.map +1 -0
- package/dist/src/core/shaders/canvas/utils/render.d.ts +5 -0
- package/dist/src/core/shaders/canvas/utils/render.js +81 -0
- package/dist/src/core/shaders/canvas/utils/render.js.map +1 -0
- package/dist/src/core/shaders/templates/BorderTemplate.d.ts +47 -0
- package/dist/src/core/shaders/templates/BorderTemplate.js +77 -0
- package/dist/src/core/shaders/templates/BorderTemplate.js.map +1 -0
- package/dist/src/core/shaders/templates/HolePunchTemplate.d.ts +46 -0
- package/dist/src/core/shaders/templates/HolePunchTemplate.js +19 -0
- package/dist/src/core/shaders/templates/HolePunchTemplate.js.map +1 -0
- package/dist/src/core/shaders/templates/LinearGradientTemplate.d.ts +23 -0
- package/dist/src/core/shaders/templates/LinearGradientTemplate.js +31 -0
- package/dist/src/core/shaders/templates/LinearGradientTemplate.js.map +1 -0
- package/dist/src/core/shaders/templates/RadialGradientTemplate.d.ts +33 -0
- package/dist/src/core/shaders/templates/RadialGradientTemplate.js +33 -0
- package/dist/src/core/shaders/templates/RadialGradientTemplate.js.map +1 -0
- package/dist/src/core/shaders/templates/RoundedTemplate.d.ts +29 -0
- package/dist/src/core/shaders/templates/RoundedTemplate.js +51 -0
- package/dist/src/core/shaders/templates/RoundedTemplate.js.map +1 -0
- package/dist/src/core/shaders/templates/RoundedWithBorderAndShadowTemplate.d.ts +7 -0
- package/dist/src/core/shaders/templates/RoundedWithBorderAndShadowTemplate.js +8 -0
- package/dist/src/core/shaders/templates/RoundedWithBorderAndShadowTemplate.js.map +1 -0
- package/dist/src/core/shaders/templates/RoundedWithBorderTemplate.d.ts +8 -0
- package/dist/src/core/shaders/templates/RoundedWithBorderTemplate.js +9 -0
- package/dist/src/core/shaders/templates/RoundedWithBorderTemplate.js.map +1 -0
- package/dist/src/core/shaders/templates/RoundedWithShadowTemplate.d.ts +6 -0
- package/dist/src/core/shaders/templates/RoundedWithShadowTemplate.js +7 -0
- package/dist/src/core/shaders/templates/RoundedWithShadowTemplate.js.map +1 -0
- package/dist/src/core/shaders/templates/ShadowTemplate.d.ts +34 -0
- package/dist/src/core/shaders/templates/ShadowTemplate.js +50 -0
- package/dist/src/core/shaders/templates/ShadowTemplate.js.map +1 -0
- package/dist/src/core/shaders/utils.d.ts +5 -0
- package/dist/src/core/shaders/utils.js +25 -0
- package/dist/src/core/shaders/utils.js.map +1 -0
- package/dist/src/core/shaders/webgl/Border.d.ts +3 -0
- package/dist/src/core/shaders/webgl/Border.js +153 -0
- package/dist/src/core/shaders/webgl/Border.js.map +1 -0
- package/dist/src/core/shaders/webgl/Default.d.ts +2 -0
- package/dist/src/core/shaders/webgl/Default.js +51 -0
- package/dist/src/core/shaders/webgl/Default.js.map +1 -0
- package/dist/src/core/shaders/webgl/HolePunch.d.ts +3 -0
- package/dist/src/core/shaders/webgl/HolePunch.js +49 -0
- package/dist/src/core/shaders/webgl/HolePunch.js.map +1 -0
- package/dist/src/core/shaders/webgl/LinearGradient.d.ts +3 -0
- package/dist/src/core/shaders/webgl/LinearGradient.js +114 -0
- package/dist/src/core/shaders/webgl/LinearGradient.js.map +1 -0
- package/dist/src/core/shaders/webgl/RadialGradient.d.ts +3 -0
- package/dist/src/core/shaders/webgl/RadialGradient.js +81 -0
- package/dist/src/core/shaders/webgl/RadialGradient.js.map +1 -0
- package/dist/src/core/shaders/webgl/Rounded.d.ts +7 -0
- package/dist/src/core/shaders/webgl/Rounded.js +88 -0
- package/dist/src/core/shaders/webgl/Rounded.js.map +1 -0
- package/dist/src/core/shaders/webgl/RoundedWithBorder.d.ts +3 -0
- package/dist/src/core/shaders/webgl/RoundedWithBorder.js +202 -0
- package/dist/src/core/shaders/webgl/RoundedWithBorder.js.map +1 -0
- package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.d.ts +3 -0
- package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js +223 -0
- package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js.map +1 -0
- package/dist/src/core/shaders/webgl/RoundedWithShadow.d.ts +3 -0
- package/dist/src/core/shaders/webgl/RoundedWithShadow.js +123 -0
- package/dist/src/core/shaders/webgl/RoundedWithShadow.js.map +1 -0
- package/dist/src/core/shaders/webgl/SdfShader.d.ts +13 -0
- package/dist/src/core/shaders/webgl/SdfShader.js +72 -0
- package/dist/src/core/shaders/webgl/SdfShader.js.map +1 -0
- package/dist/src/core/shaders/webgl/Shadow.d.ts +3 -0
- package/dist/src/core/shaders/webgl/Shadow.js +115 -0
- package/dist/src/core/shaders/webgl/Shadow.js.map +1 -0
- package/dist/src/core/text-rendering/CanvasFontHandler.d.ts +59 -0
- package/dist/src/core/text-rendering/CanvasFontHandler.js +206 -0
- package/dist/src/core/text-rendering/CanvasFontHandler.js.map +1 -0
- package/dist/src/core/text-rendering/CanvasTextRenderer.d.ts +17 -0
- package/dist/src/core/text-rendering/CanvasTextRenderer.js +139 -0
- package/dist/src/core/text-rendering/CanvasTextRenderer.js.map +1 -0
- package/dist/src/core/text-rendering/SdfFontHandler.d.ts +167 -0
- package/dist/src/core/text-rendering/SdfFontHandler.js +371 -0
- package/dist/src/core/text-rendering/SdfFontHandler.js.map +1 -0
- package/dist/src/core/text-rendering/SdfTextRenderer.d.ts +17 -0
- package/dist/src/core/text-rendering/SdfTextRenderer.js +249 -0
- package/dist/src/core/text-rendering/SdfTextRenderer.js.map +1 -0
- package/dist/src/core/text-rendering/TextLayoutEngine.d.ts +18 -0
- package/dist/src/core/text-rendering/TextLayoutEngine.js +380 -0
- package/dist/src/core/text-rendering/TextLayoutEngine.js.map +1 -0
- package/dist/src/core/text-rendering/TextRenderer.d.ts +406 -0
- package/dist/src/core/text-rendering/TextRenderer.js +2 -0
- package/dist/src/core/text-rendering/TextRenderer.js.map +1 -0
- package/dist/src/core/text-rendering/Utils.d.ts +30 -0
- package/dist/src/core/text-rendering/Utils.js +66 -0
- package/dist/src/core/text-rendering/Utils.js.map +1 -0
- package/dist/src/core/textures/ColorTexture.d.ts +36 -0
- package/dist/src/core/textures/ColorTexture.js +57 -0
- package/dist/src/core/textures/ColorTexture.js.map +1 -0
- package/dist/src/core/textures/ImageTexture.d.ts +131 -0
- package/dist/src/core/textures/ImageTexture.js +211 -0
- package/dist/src/core/textures/ImageTexture.js.map +1 -0
- package/dist/src/core/textures/NoiseTexture.d.ts +43 -0
- package/dist/src/core/textures/NoiseTexture.js +50 -0
- package/dist/src/core/textures/NoiseTexture.js.map +1 -0
- package/dist/src/core/textures/RenderTexture.d.ts +29 -0
- package/dist/src/core/textures/RenderTexture.js +36 -0
- package/dist/src/core/textures/RenderTexture.js.map +1 -0
- package/dist/src/core/textures/SubTexture.d.ts +61 -0
- package/dist/src/core/textures/SubTexture.js +99 -0
- package/dist/src/core/textures/SubTexture.js.map +1 -0
- package/dist/src/core/textures/Texture.d.ts +275 -0
- package/dist/src/core/textures/Texture.js +326 -0
- package/dist/src/core/textures/Texture.js.map +1 -0
- package/dist/src/core/utils.d.ts +23 -0
- package/dist/src/core/utils.js +155 -0
- package/dist/src/core/utils.js.map +1 -0
- package/dist/src/main-api/INode.d.ts +65 -0
- package/dist/src/main-api/INode.js +2 -0
- package/dist/src/main-api/INode.js.map +1 -0
- package/dist/src/main-api/Inspector.d.ts +154 -0
- package/dist/src/main-api/Inspector.js +844 -0
- package/dist/src/main-api/Inspector.js.map +1 -0
- package/dist/src/main-api/Renderer.d.ts +629 -0
- package/dist/src/main-api/Renderer.js +471 -0
- package/dist/src/main-api/Renderer.js.map +1 -0
- package/dist/src/main-api/utils.d.ts +2 -0
- package/dist/src/main-api/utils.js +34 -0
- package/dist/src/main-api/utils.js.map +1 -0
- package/dist/src/utils.d.ts +123 -0
- package/dist/src/utils.js +234 -0
- package/dist/src/utils.js.map +1 -0
- package/dist/tsconfig.dist.tsbuildinfo +1 -0
- package/exports/canvas-shaders.ts +11 -0
- package/exports/canvas.ts +27 -0
- package/exports/index.ts +69 -0
- package/exports/inspector.ts +5 -0
- package/exports/utils.ts +32 -0
- package/exports/webgl-shaders.ts +12 -0
- package/exports/webgl.ts +33 -0
- package/package.json +99 -0
- package/src/common/CommonTypes.ts +145 -0
- package/src/common/EventEmitter.ts +58 -0
- package/src/common/IAnimationController.ts +65 -0
- package/src/common/IEventEmitter.ts +11 -0
- package/src/core/Autosizer.ts +205 -0
- package/src/core/CoreNode.test.ts +535 -0
- package/src/core/CoreNode.ts +2883 -0
- package/src/core/CoreShaderManager.ts +170 -0
- package/src/core/CoreTextNode.ts +573 -0
- package/src/core/CoreTextureManager.ts +552 -0
- package/src/core/Stage.ts +1037 -0
- package/src/core/TextureError.ts +46 -0
- package/src/core/TextureMemoryManager.ts +378 -0
- package/src/core/animations/AnimationManager.ts +178 -0
- package/src/core/animations/CoreAnimation.ts +138 -0
- package/src/core/lib/ContextSpy.ts +22 -0
- package/src/core/lib/ImageWorker.ts +292 -0
- package/src/core/lib/Matrix3d.ts +231 -0
- package/src/core/lib/RenderCoords.ts +55 -0
- package/src/core/lib/WebGlContextWrapper.ts +1448 -0
- package/src/core/lib/collectionUtils.ts +99 -0
- package/src/core/lib/colorCache.ts +20 -0
- package/src/core/lib/colorParser.ts +66 -0
- package/src/core/lib/textureCompression.ts +492 -0
- package/src/core/lib/textureSvg.ts +59 -0
- package/src/core/lib/utils.ts +400 -0
- package/src/core/lib/validateImageBitmap.ts +87 -0
- package/src/core/platforms/Platform.ts +64 -0
- package/src/core/platforms/web/WebPlatform.ts +132 -0
- package/src/core/renderers/CoreContextTexture.ts +25 -0
- package/src/core/renderers/CoreRenderOp.ts +3 -0
- package/src/core/renderers/CoreRenderer.ts +101 -0
- package/src/core/renderers/CoreShaderNode.ts +202 -0
- package/src/core/renderers/CoreShaderProgram.ts +4 -0
- package/src/core/renderers/canvas/CanvasRenderer.ts +274 -0
- package/src/core/renderers/canvas/CanvasShaderNode.ts +79 -0
- package/src/core/renderers/canvas/CanvasTexture.ts +141 -0
- package/src/core/renderers/webgl/SdfRenderOp.ts +103 -0
- package/src/core/renderers/webgl/WebGlCtxRenderTexture.ts +70 -0
- package/src/core/renderers/webgl/WebGlCtxSubTexture.ts +76 -0
- package/src/core/renderers/webgl/WebGlCtxTexture.ts +332 -0
- package/src/core/renderers/webgl/WebGlRenderer.ts +1323 -0
- package/src/core/renderers/webgl/WebGlShaderNode.ts +423 -0
- package/src/core/renderers/webgl/WebGlShaderProgram.ts +346 -0
- package/src/core/renderers/webgl/internal/BufferCollection.ts +46 -0
- package/src/core/renderers/webgl/internal/RendererUtils.ts +136 -0
- package/src/core/renderers/webgl/internal/ShaderUtils.ts +262 -0
- package/src/core/renderers/webgl/internal/WebGlUtils.ts +16 -0
- package/src/core/shaders/canvas/Border.ts +119 -0
- package/src/core/shaders/canvas/HolePunch.ts +38 -0
- package/src/core/shaders/canvas/LinearGradient.ts +54 -0
- package/src/core/shaders/canvas/RadialGradient.ts +82 -0
- package/src/core/shaders/canvas/Rounded.ts +38 -0
- package/src/core/shaders/canvas/RoundedWithBorder.ts +105 -0
- package/src/core/shaders/canvas/RoundedWithBorderAndShadow.ts +118 -0
- package/src/core/shaders/canvas/RoundedWithShadow.ts +56 -0
- package/src/core/shaders/canvas/Shadow.ts +35 -0
- package/src/core/shaders/canvas/utils/render.ts +143 -0
- package/src/core/shaders/templates/BorderTemplate.ts +128 -0
- package/src/core/shaders/templates/HolePunchTemplate.ts +65 -0
- package/src/core/shaders/templates/LinearGradientTemplate.ts +54 -0
- package/src/core/shaders/templates/RadialGradientTemplate.ts +66 -0
- package/src/core/shaders/templates/RoundedTemplate.ts +81 -0
- package/src/core/shaders/templates/RoundedWithBorderAndShadowTemplate.ts +21 -0
- package/src/core/shaders/templates/RoundedWithBorderTemplate.ts +23 -0
- package/src/core/shaders/templates/RoundedWithShadowTemplate.ts +18 -0
- package/src/core/shaders/templates/ShadowTemplate.ts +89 -0
- package/src/core/shaders/utils.ts +30 -0
- package/src/core/shaders/webgl/Border.ts +158 -0
- package/src/core/shaders/webgl/Default.ts +52 -0
- package/src/core/shaders/webgl/HolePunch.ts +58 -0
- package/src/core/shaders/webgl/LinearGradient.ts +119 -0
- package/src/core/shaders/webgl/RadialGradient.ts +91 -0
- package/src/core/shaders/webgl/Rounded.ts +97 -0
- package/src/core/shaders/webgl/RoundedWithBorder.ts +212 -0
- package/src/core/shaders/webgl/RoundedWithBorderAndShadow.ts +235 -0
- package/src/core/shaders/webgl/RoundedWithShadow.ts +132 -0
- package/src/core/shaders/webgl/SdfShader.ts +73 -0
- package/src/core/shaders/webgl/Shadow.ts +119 -0
- package/src/core/text-rendering/CanvasFontHandler.ts +285 -0
- package/src/core/text-rendering/CanvasTextRenderer.ts +236 -0
- package/src/core/text-rendering/SdfFontHandler.ts +566 -0
- package/src/core/text-rendering/SdfTextRenderer.ts +352 -0
- package/src/core/text-rendering/TextLayoutEngine.ts +672 -0
- package/src/core/text-rendering/TextRenderer.ts +449 -0
- package/src/core/text-rendering/Utils.ts +80 -0
- package/src/core/text-rendering/tests/TextLayoutEngine.test.ts +434 -0
- package/src/core/textures/ColorTexture.ts +85 -0
- package/src/core/textures/ImageTexture.ts +394 -0
- package/src/core/textures/NoiseTexture.ts +87 -0
- package/src/core/textures/RenderTexture.ts +68 -0
- package/src/core/textures/SubTexture.ts +165 -0
- package/src/core/textures/Texture.ts +505 -0
- package/src/core/utils.ts +210 -0
- package/src/env.d.ts +7 -0
- package/src/main-api/INode.ts +92 -0
- package/src/main-api/Inspector.ts +1267 -0
- package/src/main-api/Renderer.ts +1011 -0
- package/src/main-api/utils.ts +45 -0
- package/src/utils.ts +302 -0
|
@@ -0,0 +1,1267 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CoreNode,
|
|
3
|
+
type CoreNodeAnimateProps,
|
|
4
|
+
type CoreNodeProps,
|
|
5
|
+
} from '../core/CoreNode.js';
|
|
6
|
+
import { type RendererMainSettings } from './Renderer.js';
|
|
7
|
+
import type { AnimationSettings } from '../core/animations/CoreAnimation.js';
|
|
8
|
+
import type {
|
|
9
|
+
IAnimationController,
|
|
10
|
+
AnimationControllerState,
|
|
11
|
+
} from '../common/IAnimationController.js';
|
|
12
|
+
import { isProductionEnvironment } from '../utils.js';
|
|
13
|
+
import { CoreTextNode, type CoreTextNodeProps } from '../core/CoreTextNode.js';
|
|
14
|
+
import type { Texture } from '../core/textures/Texture.js';
|
|
15
|
+
import { TextureType } from '../core/textures/Texture.js';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Inspector Options
|
|
19
|
+
*
|
|
20
|
+
* Configuration options for the Inspector's performance monitoring features.
|
|
21
|
+
*/
|
|
22
|
+
export interface InspectorOptions {
|
|
23
|
+
/**
|
|
24
|
+
* Enable performance monitoring for setter calls
|
|
25
|
+
*
|
|
26
|
+
* @defaultValue true
|
|
27
|
+
*/
|
|
28
|
+
enablePerformanceMonitoring: boolean;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Threshold for excessive setter calls before logging a warning
|
|
32
|
+
*
|
|
33
|
+
* @defaultValue 100
|
|
34
|
+
*/
|
|
35
|
+
excessiveCallThreshold: number;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Time interval in milliseconds to reset the setter call counters
|
|
39
|
+
*
|
|
40
|
+
* @defaultValue 5000
|
|
41
|
+
*/
|
|
42
|
+
resetInterval: number;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Enable animation monitoring and statistics tracking
|
|
46
|
+
*
|
|
47
|
+
* @defaultValue true
|
|
48
|
+
*/
|
|
49
|
+
enableAnimationMonitoring: boolean;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Maximum number of animations to keep in history for statistics
|
|
53
|
+
*
|
|
54
|
+
* @defaultValue 1000
|
|
55
|
+
*/
|
|
56
|
+
maxAnimationHistory: number;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Automatically print animation statistics every X seconds (0 to disable)
|
|
60
|
+
*
|
|
61
|
+
* @defaultValue 0
|
|
62
|
+
*/
|
|
63
|
+
animationStatsInterval: number;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Inspector
|
|
68
|
+
*
|
|
69
|
+
* The inspector is a tool that allows you to inspect the state of the renderer
|
|
70
|
+
* and the nodes that are being rendered. It is a tool that is used for debugging
|
|
71
|
+
* and development purposes.
|
|
72
|
+
*
|
|
73
|
+
* The inspector will generate a DOM tree that mirrors the state of the renderer
|
|
74
|
+
*/
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* stylePropertyMap is a map of renderer properties that are mapped to CSS properties
|
|
78
|
+
*
|
|
79
|
+
* It can either return a string or an object with a prop and value property. Once a
|
|
80
|
+
* property is found in the map, the value is set on the style of the div element.
|
|
81
|
+
* Erik H made me do it.
|
|
82
|
+
*/
|
|
83
|
+
interface StyleResponse {
|
|
84
|
+
prop: string;
|
|
85
|
+
value: string;
|
|
86
|
+
}
|
|
87
|
+
const stylePropertyMap: {
|
|
88
|
+
[key: string]: (
|
|
89
|
+
value: string | number | boolean,
|
|
90
|
+
) => string | StyleResponse | null;
|
|
91
|
+
} = {
|
|
92
|
+
alpha: (v) => {
|
|
93
|
+
if (v === 1) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return { prop: 'opacity', value: `${v}` };
|
|
98
|
+
},
|
|
99
|
+
x: (x) => {
|
|
100
|
+
return { prop: 'left', value: `${x}px` };
|
|
101
|
+
},
|
|
102
|
+
y: (y) => {
|
|
103
|
+
return { prop: 'top', value: `${y}px` };
|
|
104
|
+
},
|
|
105
|
+
w: (w) => {
|
|
106
|
+
if (w === 0) {
|
|
107
|
+
return { prop: 'width', value: 'auto' };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return { prop: 'width', value: `${w}px` };
|
|
111
|
+
},
|
|
112
|
+
h: (h) => {
|
|
113
|
+
if (h === 0) {
|
|
114
|
+
return { prop: 'height', value: 'auto' };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return { prop: 'height', value: `${h}px` };
|
|
118
|
+
},
|
|
119
|
+
fontSize: (fs) => {
|
|
120
|
+
if (fs === 0) {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return { prop: 'font-size', value: `${fs}px` };
|
|
125
|
+
},
|
|
126
|
+
lineHeight: (lh) => {
|
|
127
|
+
if (lh === 0) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return { prop: 'line-height', value: `${lh}px` };
|
|
132
|
+
},
|
|
133
|
+
zIndex: () => 'z-index',
|
|
134
|
+
fontFamily: () => 'font-family',
|
|
135
|
+
fontStyle: () => 'font-style',
|
|
136
|
+
letterSpacing: () => 'letter-spacing',
|
|
137
|
+
textAlign: () => 'text-align',
|
|
138
|
+
overflowSuffix: () => 'overflow-suffix',
|
|
139
|
+
maxLines: () => 'max-lines',
|
|
140
|
+
contain: () => 'contain',
|
|
141
|
+
verticalAlign: () => 'vertical-align',
|
|
142
|
+
clipping: (v) => {
|
|
143
|
+
if (v === false) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return { prop: 'overflow', value: v ? 'hidden' : 'visible' };
|
|
148
|
+
},
|
|
149
|
+
rotation: (v) => {
|
|
150
|
+
if (v === 0) {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return { prop: 'transform', value: `rotate(${v}rad)` };
|
|
155
|
+
},
|
|
156
|
+
scale: (v) => {
|
|
157
|
+
if (v === 1) {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return { prop: 'transform', value: `scale(${v})` };
|
|
162
|
+
},
|
|
163
|
+
scaleX: (v) => {
|
|
164
|
+
if (v === 1) {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return { prop: 'transform', value: `scaleX(${v})` };
|
|
169
|
+
},
|
|
170
|
+
scaleY: (v) => {
|
|
171
|
+
if (v === 1) {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return { prop: 'transform', value: `scaleY(${v})` };
|
|
176
|
+
},
|
|
177
|
+
color: (v) => {
|
|
178
|
+
if (v === 0) {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return { prop: 'color', value: convertColorToRgba(v as number) };
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const convertColorToRgba = (color: number) => {
|
|
187
|
+
const a = (color & 0xff) / 255;
|
|
188
|
+
const b = (color >> 8) & 0xff;
|
|
189
|
+
const g = (color >> 16) & 0xff;
|
|
190
|
+
const r = (color >> 24) & 0xff;
|
|
191
|
+
return `rgba(${r},${g},${b},${a})`;
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
const domPropertyMap: { [key: string]: string } = {
|
|
195
|
+
id: 'test-id',
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const gradientColorPropertyMap = [
|
|
199
|
+
'colorTop',
|
|
200
|
+
'colorBottom',
|
|
201
|
+
'colorLeft',
|
|
202
|
+
'colorRight',
|
|
203
|
+
'colorTl',
|
|
204
|
+
'colorTr',
|
|
205
|
+
'colorBl',
|
|
206
|
+
'colorBr',
|
|
207
|
+
];
|
|
208
|
+
|
|
209
|
+
const textureTypeNames: Record<number, string> = {
|
|
210
|
+
[TextureType.generic]: 'generic',
|
|
211
|
+
[TextureType.color]: 'color',
|
|
212
|
+
[TextureType.image]: 'image',
|
|
213
|
+
[TextureType.noise]: 'noise',
|
|
214
|
+
[TextureType.renderToTexture]: 'renderToTexture',
|
|
215
|
+
[TextureType.subTexture]: 'subTexture',
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
interface TextureMetrics {
|
|
219
|
+
previousState: string;
|
|
220
|
+
loadedCount: number;
|
|
221
|
+
failedCount: number;
|
|
222
|
+
freedCount: number;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const knownProperties = new Set<string>([
|
|
226
|
+
...Object.keys(stylePropertyMap),
|
|
227
|
+
...Object.keys(domPropertyMap),
|
|
228
|
+
// ...gradientColorPropertyMap,
|
|
229
|
+
'src',
|
|
230
|
+
'parent',
|
|
231
|
+
'data',
|
|
232
|
+
'text',
|
|
233
|
+
]);
|
|
234
|
+
|
|
235
|
+
export class Inspector {
|
|
236
|
+
private root: HTMLElement | null = null;
|
|
237
|
+
private canvas: HTMLCanvasElement | null = null;
|
|
238
|
+
private mutationObserver: MutationObserver = new MutationObserver(() => {});
|
|
239
|
+
private resizeObserver: ResizeObserver = new ResizeObserver(() => {});
|
|
240
|
+
private height = 1080;
|
|
241
|
+
private width = 1920;
|
|
242
|
+
private scaleX = 1;
|
|
243
|
+
private scaleY = 1;
|
|
244
|
+
private textureMetrics = new Map<Texture, TextureMetrics>();
|
|
245
|
+
|
|
246
|
+
// Performance monitoring for frequent setter calls
|
|
247
|
+
private static setterCallCount = new Map<
|
|
248
|
+
string,
|
|
249
|
+
{ count: number; lastReset: number; nodeId: number }
|
|
250
|
+
>();
|
|
251
|
+
|
|
252
|
+
// Animation monitoring structures
|
|
253
|
+
private static activeAnimations = new Map<
|
|
254
|
+
string,
|
|
255
|
+
{
|
|
256
|
+
nodeId: number;
|
|
257
|
+
animationId: string;
|
|
258
|
+
startTime: number;
|
|
259
|
+
props: CoreNodeAnimateProps;
|
|
260
|
+
settings: AnimationSettings;
|
|
261
|
+
controller: IAnimationController;
|
|
262
|
+
state: AnimationControllerState;
|
|
263
|
+
}
|
|
264
|
+
>();
|
|
265
|
+
|
|
266
|
+
private static animationHistory: Array<{
|
|
267
|
+
nodeId: number;
|
|
268
|
+
animationId: string;
|
|
269
|
+
startTime: number;
|
|
270
|
+
endTime: number;
|
|
271
|
+
duration: number;
|
|
272
|
+
actualDuration: number;
|
|
273
|
+
props: CoreNodeAnimateProps;
|
|
274
|
+
settings: AnimationSettings;
|
|
275
|
+
completionType: 'finished' | 'stopped' | 'cancelled';
|
|
276
|
+
}> = [];
|
|
277
|
+
|
|
278
|
+
// Performance monitoring settings (configured via constructor)
|
|
279
|
+
private performanceSettings: InspectorOptions = {
|
|
280
|
+
enablePerformanceMonitoring: false,
|
|
281
|
+
excessiveCallThreshold: 100,
|
|
282
|
+
resetInterval: 5000,
|
|
283
|
+
enableAnimationMonitoring: false,
|
|
284
|
+
maxAnimationHistory: 1000,
|
|
285
|
+
animationStatsInterval: 0,
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
// Animation stats printing timer
|
|
289
|
+
private animationStatsTimer: number | null = null;
|
|
290
|
+
|
|
291
|
+
constructor(canvas: HTMLCanvasElement, settings: RendererMainSettings) {
|
|
292
|
+
if (isProductionEnvironment === true) return;
|
|
293
|
+
|
|
294
|
+
if (!settings) {
|
|
295
|
+
throw new Error('settings is required');
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Initialize performance monitoring settings with defaults
|
|
299
|
+
this.performanceSettings = {
|
|
300
|
+
enablePerformanceMonitoring:
|
|
301
|
+
settings.inspectorOptions?.enablePerformanceMonitoring ?? false,
|
|
302
|
+
excessiveCallThreshold:
|
|
303
|
+
settings.inspectorOptions?.excessiveCallThreshold ?? 100,
|
|
304
|
+
resetInterval: settings.inspectorOptions?.resetInterval ?? 5000,
|
|
305
|
+
enableAnimationMonitoring:
|
|
306
|
+
settings.inspectorOptions?.enableAnimationMonitoring ?? false,
|
|
307
|
+
maxAnimationHistory:
|
|
308
|
+
settings.inspectorOptions?.maxAnimationHistory ?? 1000,
|
|
309
|
+
animationStatsInterval:
|
|
310
|
+
settings.inspectorOptions?.animationStatsInterval ?? 0,
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
// calc dimensions based on the devicePixelRatio
|
|
314
|
+
this.height = Math.ceil(
|
|
315
|
+
settings.appHeight ?? 1080 / (settings.deviceLogicalPixelRatio ?? 1),
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
this.width = Math.ceil(
|
|
319
|
+
settings.appWidth ?? 1920 / (settings.deviceLogicalPixelRatio ?? 1),
|
|
320
|
+
);
|
|
321
|
+
|
|
322
|
+
this.scaleX = settings.deviceLogicalPixelRatio ?? 1;
|
|
323
|
+
this.scaleY = settings.deviceLogicalPixelRatio ?? 1;
|
|
324
|
+
|
|
325
|
+
this.canvas = canvas;
|
|
326
|
+
this.root = document.createElement('div');
|
|
327
|
+
this.setRootPosition();
|
|
328
|
+
document.body.appendChild(this.root);
|
|
329
|
+
|
|
330
|
+
//listen for changes on canvas
|
|
331
|
+
this.mutationObserver = new MutationObserver(
|
|
332
|
+
this.setRootPosition.bind(this),
|
|
333
|
+
);
|
|
334
|
+
this.mutationObserver.observe(canvas, {
|
|
335
|
+
attributes: true,
|
|
336
|
+
childList: false,
|
|
337
|
+
subtree: false,
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
// Create a ResizeObserver to watch for changes in the element's size
|
|
341
|
+
this.resizeObserver = new ResizeObserver(this.setRootPosition.bind(this));
|
|
342
|
+
this.resizeObserver.observe(canvas);
|
|
343
|
+
|
|
344
|
+
//listen for changes on window
|
|
345
|
+
window.addEventListener('resize', this.setRootPosition.bind(this));
|
|
346
|
+
|
|
347
|
+
// Start animation stats timer if enabled
|
|
348
|
+
this.startAnimationStatsTimer();
|
|
349
|
+
|
|
350
|
+
console.warn('Inspector is enabled, this will impact performance');
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Track setter calls for performance monitoring
|
|
355
|
+
* Only active when Inspector is loaded
|
|
356
|
+
*/
|
|
357
|
+
private trackSetterCall(nodeId: number, setterName: string): void {
|
|
358
|
+
if (!this.performanceSettings.enablePerformanceMonitoring) {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
const key = `${nodeId}_${setterName}`;
|
|
363
|
+
const now = Date.now();
|
|
364
|
+
const existing = Inspector.setterCallCount.get(key);
|
|
365
|
+
|
|
366
|
+
if (!existing) {
|
|
367
|
+
Inspector.setterCallCount.set(key, { count: 1, lastReset: now, nodeId });
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// Reset counter if enough time has passed
|
|
372
|
+
if (now - existing.lastReset > this.performanceSettings.resetInterval) {
|
|
373
|
+
existing.count = 1;
|
|
374
|
+
existing.lastReset = now;
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
existing.count++;
|
|
379
|
+
|
|
380
|
+
// Log if threshold exceeded
|
|
381
|
+
if (existing.count === this.performanceSettings.excessiveCallThreshold) {
|
|
382
|
+
console.warn(
|
|
383
|
+
`🚨 Inspector Performance Warning: Setter '${setterName}' called ${existing.count} times in ${this.performanceSettings.resetInterval}ms on node ${nodeId}`,
|
|
384
|
+
);
|
|
385
|
+
} else if (
|
|
386
|
+
existing.count > this.performanceSettings.excessiveCallThreshold &&
|
|
387
|
+
existing.count % 50 === 0
|
|
388
|
+
) {
|
|
389
|
+
console.warn(
|
|
390
|
+
`🚨 Inspector Performance Warning: Setter '${setterName}' called ${existing.count} times in ${this.performanceSettings.resetInterval}ms on node ${nodeId} (continuing...)`,
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Get current performance monitoring statistics
|
|
397
|
+
*/
|
|
398
|
+
public static getPerformanceStats(): Array<{
|
|
399
|
+
nodeId: number;
|
|
400
|
+
setterName: string;
|
|
401
|
+
count: number;
|
|
402
|
+
timeWindow: number;
|
|
403
|
+
}> {
|
|
404
|
+
const stats: Array<{
|
|
405
|
+
nodeId: number;
|
|
406
|
+
setterName: string;
|
|
407
|
+
count: number;
|
|
408
|
+
timeWindow: number;
|
|
409
|
+
}> = [];
|
|
410
|
+
const now = Date.now();
|
|
411
|
+
|
|
412
|
+
Inspector.setterCallCount.forEach((data, key) => {
|
|
413
|
+
const parts = key.split('_');
|
|
414
|
+
const nodeIdStr = parts[0];
|
|
415
|
+
const setterName = parts[1];
|
|
416
|
+
|
|
417
|
+
if (nodeIdStr && setterName) {
|
|
418
|
+
const timeWindow = now - data.lastReset;
|
|
419
|
+
|
|
420
|
+
stats.push({
|
|
421
|
+
nodeId: parseInt(nodeIdStr, 10),
|
|
422
|
+
setterName,
|
|
423
|
+
count: data.count,
|
|
424
|
+
timeWindow,
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
return stats.sort((a, b) => b.count - a.count);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Clear performance monitoring statistics
|
|
434
|
+
*/
|
|
435
|
+
public static clearPerformanceStats(): void {
|
|
436
|
+
Inspector.setterCallCount.clear();
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Generate a unique animation ID
|
|
441
|
+
*/
|
|
442
|
+
private static generateAnimationId(): string {
|
|
443
|
+
return `anim_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Wrap animation controller with monitoring capabilities
|
|
448
|
+
*/
|
|
449
|
+
private wrapAnimationController(
|
|
450
|
+
controller: IAnimationController,
|
|
451
|
+
nodeId: number,
|
|
452
|
+
props: CoreNodeAnimateProps,
|
|
453
|
+
settings: AnimationSettings,
|
|
454
|
+
div: HTMLElement,
|
|
455
|
+
): IAnimationController {
|
|
456
|
+
if (!this.performanceSettings.enableAnimationMonitoring) {
|
|
457
|
+
// Just add the basic DOM animation without tracking
|
|
458
|
+
const originalStart = controller.start.bind(controller);
|
|
459
|
+
controller.start = () => {
|
|
460
|
+
this.animateNode(div, props, settings);
|
|
461
|
+
return originalStart();
|
|
462
|
+
};
|
|
463
|
+
return controller;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
const animationId = Inspector.generateAnimationId();
|
|
467
|
+
|
|
468
|
+
// Create wrapper controller
|
|
469
|
+
const wrappedController: IAnimationController = {
|
|
470
|
+
start: () => {
|
|
471
|
+
this.trackAnimationStart(
|
|
472
|
+
animationId,
|
|
473
|
+
nodeId,
|
|
474
|
+
props,
|
|
475
|
+
settings,
|
|
476
|
+
controller,
|
|
477
|
+
);
|
|
478
|
+
this.animateNode(div, props, settings);
|
|
479
|
+
return controller.start();
|
|
480
|
+
},
|
|
481
|
+
|
|
482
|
+
stop: () => {
|
|
483
|
+
this.trackAnimationEnd(animationId, 'stopped');
|
|
484
|
+
return controller.stop();
|
|
485
|
+
},
|
|
486
|
+
|
|
487
|
+
pause: () => {
|
|
488
|
+
this.updateAnimationState(animationId, 'paused');
|
|
489
|
+
return controller.pause();
|
|
490
|
+
},
|
|
491
|
+
|
|
492
|
+
restore: () => {
|
|
493
|
+
this.trackAnimationEnd(animationId, 'cancelled');
|
|
494
|
+
return controller.restore();
|
|
495
|
+
},
|
|
496
|
+
|
|
497
|
+
waitUntilStopped: () => {
|
|
498
|
+
return controller.waitUntilStopped().then(() => {
|
|
499
|
+
this.trackAnimationEnd(animationId, 'finished');
|
|
500
|
+
});
|
|
501
|
+
},
|
|
502
|
+
|
|
503
|
+
get state() {
|
|
504
|
+
return controller.state;
|
|
505
|
+
},
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
controller.waitUntilStopped().then(() => {
|
|
509
|
+
this.trackAnimationEnd(animationId, 'finished');
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
return wrappedController;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Track animation start
|
|
517
|
+
*/
|
|
518
|
+
private trackAnimationStart(
|
|
519
|
+
animationId: string,
|
|
520
|
+
nodeId: number,
|
|
521
|
+
props: CoreNodeAnimateProps,
|
|
522
|
+
settings: AnimationSettings,
|
|
523
|
+
controller: IAnimationController,
|
|
524
|
+
): void {
|
|
525
|
+
const startTime = Date.now();
|
|
526
|
+
|
|
527
|
+
Inspector.activeAnimations.set(animationId, {
|
|
528
|
+
nodeId,
|
|
529
|
+
animationId,
|
|
530
|
+
startTime,
|
|
531
|
+
props,
|
|
532
|
+
settings,
|
|
533
|
+
controller,
|
|
534
|
+
state: 'scheduled',
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Update animation state
|
|
540
|
+
*/
|
|
541
|
+
private updateAnimationState(
|
|
542
|
+
animationId: string,
|
|
543
|
+
state: AnimationControllerState,
|
|
544
|
+
): void {
|
|
545
|
+
const animation = Inspector.activeAnimations.get(animationId);
|
|
546
|
+
if (animation) {
|
|
547
|
+
animation.state = state;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Track animation end
|
|
553
|
+
*/
|
|
554
|
+
private trackAnimationEnd(
|
|
555
|
+
animationId: string,
|
|
556
|
+
completionType: 'finished' | 'stopped' | 'cancelled',
|
|
557
|
+
): void {
|
|
558
|
+
const animation = Inspector.activeAnimations.get(animationId);
|
|
559
|
+
if (!animation) return;
|
|
560
|
+
|
|
561
|
+
const endTime = Date.now();
|
|
562
|
+
const actualDuration = endTime - animation.startTime;
|
|
563
|
+
const expectedDuration = animation.settings.duration || 1000;
|
|
564
|
+
|
|
565
|
+
// Move to history
|
|
566
|
+
Inspector.animationHistory.unshift({
|
|
567
|
+
nodeId: animation.nodeId,
|
|
568
|
+
animationId: animation.animationId,
|
|
569
|
+
startTime: animation.startTime,
|
|
570
|
+
endTime,
|
|
571
|
+
duration: expectedDuration,
|
|
572
|
+
actualDuration,
|
|
573
|
+
props: animation.props,
|
|
574
|
+
settings: animation.settings,
|
|
575
|
+
completionType,
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
// Limit history size for performance
|
|
579
|
+
if (
|
|
580
|
+
Inspector.animationHistory.length >
|
|
581
|
+
this.performanceSettings.maxAnimationHistory
|
|
582
|
+
) {
|
|
583
|
+
Inspector.animationHistory.splice(
|
|
584
|
+
this.performanceSettings.maxAnimationHistory,
|
|
585
|
+
);
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// Remove from active animations
|
|
589
|
+
Inspector.activeAnimations.delete(animationId);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* Get currently active animations
|
|
594
|
+
*/
|
|
595
|
+
public static getActiveAnimations(): Array<{
|
|
596
|
+
nodeId: number;
|
|
597
|
+
animationId: string;
|
|
598
|
+
startTime: number;
|
|
599
|
+
duration: number;
|
|
600
|
+
elapsedTime: number;
|
|
601
|
+
props: CoreNodeAnimateProps;
|
|
602
|
+
settings: AnimationSettings;
|
|
603
|
+
state: AnimationControllerState;
|
|
604
|
+
}> {
|
|
605
|
+
const now = Date.now();
|
|
606
|
+
const activeAnimations: Array<{
|
|
607
|
+
nodeId: number;
|
|
608
|
+
animationId: string;
|
|
609
|
+
startTime: number;
|
|
610
|
+
duration: number;
|
|
611
|
+
elapsedTime: number;
|
|
612
|
+
props: CoreNodeAnimateProps;
|
|
613
|
+
settings: AnimationSettings;
|
|
614
|
+
state: AnimationControllerState;
|
|
615
|
+
}> = [];
|
|
616
|
+
|
|
617
|
+
Inspector.activeAnimations.forEach((animation) => {
|
|
618
|
+
activeAnimations.push({
|
|
619
|
+
nodeId: animation.nodeId,
|
|
620
|
+
animationId: animation.animationId,
|
|
621
|
+
startTime: animation.startTime,
|
|
622
|
+
duration: animation.settings.duration || 1000,
|
|
623
|
+
elapsedTime: now - animation.startTime,
|
|
624
|
+
props: animation.props,
|
|
625
|
+
settings: animation.settings,
|
|
626
|
+
state: animation.state,
|
|
627
|
+
});
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
return activeAnimations.sort((a, b) => b.startTime - a.startTime);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* Get animation statistics
|
|
635
|
+
*/
|
|
636
|
+
public static getAnimationStats(): {
|
|
637
|
+
totalAnimations: number;
|
|
638
|
+
activeCount: number;
|
|
639
|
+
averageDuration: number;
|
|
640
|
+
} {
|
|
641
|
+
const totalAnimations = Inspector.animationHistory.length;
|
|
642
|
+
const activeCount = Inspector.activeAnimations.size;
|
|
643
|
+
|
|
644
|
+
// Calculate average duration from finished animations only
|
|
645
|
+
const finishedAnimations = Inspector.animationHistory.filter(
|
|
646
|
+
(anim) => anim.completionType === 'finished',
|
|
647
|
+
);
|
|
648
|
+
|
|
649
|
+
const averageDuration =
|
|
650
|
+
finishedAnimations.length > 0
|
|
651
|
+
? finishedAnimations.reduce(
|
|
652
|
+
(sum, anim) => sum + anim.actualDuration,
|
|
653
|
+
0,
|
|
654
|
+
) / finishedAnimations.length
|
|
655
|
+
: 0;
|
|
656
|
+
|
|
657
|
+
return {
|
|
658
|
+
totalAnimations,
|
|
659
|
+
activeCount,
|
|
660
|
+
averageDuration,
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
/**
|
|
665
|
+
* Clear animation monitoring data
|
|
666
|
+
*/
|
|
667
|
+
public static clearAnimationStats(): void {
|
|
668
|
+
Inspector.activeAnimations.clear();
|
|
669
|
+
Inspector.animationHistory.length = 0;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* Start the animation stats timer if enabled
|
|
674
|
+
*/
|
|
675
|
+
private startAnimationStatsTimer(): void {
|
|
676
|
+
console.log(
|
|
677
|
+
`Starting animation stats timer with interval: ${this.performanceSettings.animationStatsInterval} seconds`,
|
|
678
|
+
);
|
|
679
|
+
|
|
680
|
+
if (this.performanceSettings.animationStatsInterval > 0) {
|
|
681
|
+
this.animationStatsTimer = setInterval(() => {
|
|
682
|
+
this.printAnimationStats();
|
|
683
|
+
}, this.performanceSettings.animationStatsInterval * 1000) as unknown as number;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
/**
|
|
688
|
+
* Stop the animation stats timer
|
|
689
|
+
*/
|
|
690
|
+
private stopAnimationStatsTimer(): void {
|
|
691
|
+
if (this.animationStatsTimer) {
|
|
692
|
+
clearInterval(this.animationStatsTimer);
|
|
693
|
+
this.animationStatsTimer = null;
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
/**
|
|
698
|
+
* Print current animation statistics to console
|
|
699
|
+
*/
|
|
700
|
+
private printAnimationStats(): void {
|
|
701
|
+
const stats = Inspector.getAnimationStats();
|
|
702
|
+
|
|
703
|
+
console.log(
|
|
704
|
+
`🎬 Animation Stats: ${stats.activeCount} active, ${
|
|
705
|
+
stats.totalAnimations
|
|
706
|
+
} completed, ${Math.round(stats.averageDuration)}ms avg duration`,
|
|
707
|
+
);
|
|
708
|
+
}
|
|
709
|
+
setRootPosition() {
|
|
710
|
+
if (this.root === null || this.canvas === null) {
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
// get the world position of the canvas object, so we can match the inspector to it
|
|
715
|
+
const rect = this.canvas.getBoundingClientRect();
|
|
716
|
+
const top = document.documentElement.scrollTop + rect.top;
|
|
717
|
+
const left = document.documentElement.scrollLeft + rect.left;
|
|
718
|
+
|
|
719
|
+
this.root.id = 'root';
|
|
720
|
+
this.root.style.left = `${left}px`;
|
|
721
|
+
this.root.style.top = `${top}px`;
|
|
722
|
+
this.root.style.width = `${this.width}px`;
|
|
723
|
+
this.root.style.height = `${this.height}px`;
|
|
724
|
+
this.root.style.position = 'absolute';
|
|
725
|
+
this.root.style.transformOrigin = '0 0 0';
|
|
726
|
+
this.root.style.transform = `scale(${this.scaleX}, ${this.scaleY})`;
|
|
727
|
+
this.root.style.overflow = 'hidden';
|
|
728
|
+
this.root.style.zIndex = '65534';
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
createDiv(
|
|
732
|
+
id: number,
|
|
733
|
+
properties: CoreNodeProps | CoreTextNodeProps,
|
|
734
|
+
): HTMLElement {
|
|
735
|
+
const div = document.createElement('div');
|
|
736
|
+
div.style.position = 'absolute';
|
|
737
|
+
div.id = id.toString();
|
|
738
|
+
|
|
739
|
+
// set initial properties
|
|
740
|
+
for (const key in properties) {
|
|
741
|
+
this.updateNodeProperty(
|
|
742
|
+
div,
|
|
743
|
+
// really typescript? really?
|
|
744
|
+
key as keyof CoreNodeProps,
|
|
745
|
+
properties[key as keyof CoreNodeProps],
|
|
746
|
+
properties,
|
|
747
|
+
);
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
return div;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
createNodes(node: CoreNode): boolean {
|
|
754
|
+
if (this.root === null) {
|
|
755
|
+
return false;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
const div = this.root.querySelector(`[id="${node.id}"]`);
|
|
759
|
+
if (div === null && node instanceof CoreTextNode) {
|
|
760
|
+
this.createTextNode(node);
|
|
761
|
+
} else if (div === null && node instanceof CoreNode) {
|
|
762
|
+
this.createNode(node);
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
for (const child of node.children) {
|
|
766
|
+
this.createNodes(child);
|
|
767
|
+
}
|
|
768
|
+
return true;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
createNode(node: CoreNode): CoreNode {
|
|
772
|
+
const div = this.createDiv(node.id, node.props);
|
|
773
|
+
(div as HTMLElement & { node: CoreNode }).node = node;
|
|
774
|
+
(node as CoreNode & { div: HTMLElement }).div = div;
|
|
775
|
+
|
|
776
|
+
node.on('inViewport', () => div.setAttribute('state', 'inViewport'));
|
|
777
|
+
node.on('inBounds', () => div.setAttribute('state', 'inBounds'));
|
|
778
|
+
node.on('outOfBounds', () => div.setAttribute('state', 'outOfBounds'));
|
|
779
|
+
|
|
780
|
+
// Monitor only relevant properties by trapping with selective assignment
|
|
781
|
+
return this.createProxy(node, div);
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
createTextNode(node: CoreTextNode): CoreTextNode {
|
|
785
|
+
// eslint-disable-next-line
|
|
786
|
+
// @ts-ignore - textProps is a private property and keeping it that way
|
|
787
|
+
// but we need it from the inspector to set the initial properties on the div element
|
|
788
|
+
const div = this.createDiv(node.id, node.textProps);
|
|
789
|
+
(div as HTMLElement & { node: CoreNode }).node = node;
|
|
790
|
+
(node as CoreTextNode & { div: HTMLElement }).div = div;
|
|
791
|
+
|
|
792
|
+
return this.createProxy(node, div) as CoreTextNode;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
createProxy(
|
|
796
|
+
node: CoreNode | CoreTextNode,
|
|
797
|
+
div: HTMLElement,
|
|
798
|
+
): CoreNode | CoreTextNode {
|
|
799
|
+
// Store texture event listeners for cleanup
|
|
800
|
+
const textureListeners = new Map<
|
|
801
|
+
Texture,
|
|
802
|
+
{
|
|
803
|
+
onLoaded: () => void;
|
|
804
|
+
onFailed: () => void;
|
|
805
|
+
onFreed: () => void;
|
|
806
|
+
}
|
|
807
|
+
>();
|
|
808
|
+
|
|
809
|
+
const coreNodeListeners = new Map<
|
|
810
|
+
CoreNode,
|
|
811
|
+
{
|
|
812
|
+
onLoaded: () => void;
|
|
813
|
+
}
|
|
814
|
+
>();
|
|
815
|
+
|
|
816
|
+
const setupCoreNodeListeners = (coreNode: CoreNode) => {
|
|
817
|
+
const onLoaded = () => {
|
|
818
|
+
this.updateTextNodeDimensions(div, coreNode as CoreTextNode);
|
|
819
|
+
};
|
|
820
|
+
coreNode.on('loaded', onLoaded);
|
|
821
|
+
coreNodeListeners.set(coreNode, { onLoaded });
|
|
822
|
+
};
|
|
823
|
+
|
|
824
|
+
// Helper function to setup texture event listeners
|
|
825
|
+
const setupTextureListeners = (texture: Texture | null) => {
|
|
826
|
+
// Clean up existing listeners first
|
|
827
|
+
textureListeners.forEach((listeners, oldTexture) => {
|
|
828
|
+
oldTexture.off('loaded', listeners.onLoaded);
|
|
829
|
+
oldTexture.off('failed', listeners.onFailed);
|
|
830
|
+
oldTexture.off('freed', listeners.onFreed);
|
|
831
|
+
});
|
|
832
|
+
textureListeners.clear();
|
|
833
|
+
|
|
834
|
+
// Setup new listeners if texture exists
|
|
835
|
+
if (texture) {
|
|
836
|
+
// Initialize metrics if not exists
|
|
837
|
+
if (!this.textureMetrics.has(texture)) {
|
|
838
|
+
this.textureMetrics.set(texture, {
|
|
839
|
+
previousState: texture.state,
|
|
840
|
+
loadedCount: 0,
|
|
841
|
+
failedCount: 0,
|
|
842
|
+
freedCount: 0,
|
|
843
|
+
});
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
const onLoaded = () => {
|
|
847
|
+
const metrics = this.textureMetrics.get(texture);
|
|
848
|
+
if (metrics) {
|
|
849
|
+
metrics.previousState =
|
|
850
|
+
metrics.previousState !== texture.state
|
|
851
|
+
? metrics.previousState
|
|
852
|
+
: 'loading';
|
|
853
|
+
metrics.loadedCount++;
|
|
854
|
+
}
|
|
855
|
+
this.updateTextureAttributes(div, texture);
|
|
856
|
+
};
|
|
857
|
+
const onFailed = () => {
|
|
858
|
+
const metrics = this.textureMetrics.get(texture);
|
|
859
|
+
if (metrics) {
|
|
860
|
+
metrics.previousState =
|
|
861
|
+
metrics.previousState !== texture.state
|
|
862
|
+
? metrics.previousState
|
|
863
|
+
: 'loading';
|
|
864
|
+
metrics.failedCount++;
|
|
865
|
+
}
|
|
866
|
+
this.updateTextureAttributes(div, texture);
|
|
867
|
+
};
|
|
868
|
+
const onFreed = () => {
|
|
869
|
+
const metrics = this.textureMetrics.get(texture);
|
|
870
|
+
if (metrics) {
|
|
871
|
+
metrics.previousState =
|
|
872
|
+
metrics.previousState !== texture.state
|
|
873
|
+
? metrics.previousState
|
|
874
|
+
: texture.state;
|
|
875
|
+
metrics.freedCount++;
|
|
876
|
+
}
|
|
877
|
+
this.updateTextureAttributes(div, texture);
|
|
878
|
+
};
|
|
879
|
+
|
|
880
|
+
texture.on('loaded', onLoaded);
|
|
881
|
+
texture.on('failed', onFailed);
|
|
882
|
+
texture.on('freed', onFreed);
|
|
883
|
+
|
|
884
|
+
textureListeners.set(texture, { onLoaded, onFailed, onFreed });
|
|
885
|
+
}
|
|
886
|
+
};
|
|
887
|
+
// Define traps for each property in knownProperties
|
|
888
|
+
knownProperties.forEach((property) => {
|
|
889
|
+
let originalProp = Object.getOwnPropertyDescriptor(node, property);
|
|
890
|
+
|
|
891
|
+
if (originalProp === undefined) {
|
|
892
|
+
// Search the prototype chain for the property descriptor
|
|
893
|
+
const proto = Object.getPrototypeOf(node) as CoreNode | CoreTextNode;
|
|
894
|
+
originalProp = Object.getOwnPropertyDescriptor(proto, property);
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
if (originalProp === undefined) {
|
|
898
|
+
return;
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
if (property === 'text') {
|
|
902
|
+
setupCoreNodeListeners(node);
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
Object.defineProperty(node, property, {
|
|
906
|
+
get() {
|
|
907
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
908
|
+
return originalProp?.get?.call(node);
|
|
909
|
+
},
|
|
910
|
+
set: (value) => {
|
|
911
|
+
// Track setter call for performance monitoring
|
|
912
|
+
this.trackSetterCall(node.id, property);
|
|
913
|
+
|
|
914
|
+
originalProp?.set?.call(node, value);
|
|
915
|
+
this.updateNodeProperty(
|
|
916
|
+
div,
|
|
917
|
+
property as keyof CoreNodeProps | keyof CoreTextNodeProps,
|
|
918
|
+
value,
|
|
919
|
+
node.props,
|
|
920
|
+
);
|
|
921
|
+
|
|
922
|
+
// Setup texture event listeners if this is a texture property
|
|
923
|
+
if (property === 'texture') {
|
|
924
|
+
const textureValue =
|
|
925
|
+
value && typeof value === 'object' && 'state' in value
|
|
926
|
+
? (value as Texture)
|
|
927
|
+
: null;
|
|
928
|
+
setupTextureListeners(textureValue);
|
|
929
|
+
}
|
|
930
|
+
},
|
|
931
|
+
configurable: true,
|
|
932
|
+
enumerable: true,
|
|
933
|
+
});
|
|
934
|
+
});
|
|
935
|
+
|
|
936
|
+
const originalDestroy = node.destroy;
|
|
937
|
+
Object.defineProperty(node, 'destroy', {
|
|
938
|
+
value: (isChild: boolean = false) => {
|
|
939
|
+
// Clean up texture event listeners and metrics
|
|
940
|
+
textureListeners.forEach((listeners, texture) => {
|
|
941
|
+
texture.off('loaded', listeners.onLoaded);
|
|
942
|
+
texture.off('failed', listeners.onFailed);
|
|
943
|
+
texture.off('freed', listeners.onFreed);
|
|
944
|
+
// Clean up metrics for this texture
|
|
945
|
+
this.textureMetrics.delete(texture);
|
|
946
|
+
});
|
|
947
|
+
textureListeners.clear();
|
|
948
|
+
|
|
949
|
+
coreNodeListeners.forEach((listeners, coreNode) => {
|
|
950
|
+
coreNode.off('loaded', listeners.onLoaded);
|
|
951
|
+
});
|
|
952
|
+
coreNodeListeners.clear();
|
|
953
|
+
|
|
954
|
+
this.destroyNode(node.id);
|
|
955
|
+
originalDestroy.call(node, isChild);
|
|
956
|
+
},
|
|
957
|
+
configurable: true,
|
|
958
|
+
});
|
|
959
|
+
|
|
960
|
+
const originalAnimate = node.animate;
|
|
961
|
+
Object.defineProperty(node, 'animate', {
|
|
962
|
+
value: (
|
|
963
|
+
props: CoreNodeAnimateProps,
|
|
964
|
+
settings: AnimationSettings,
|
|
965
|
+
): IAnimationController => {
|
|
966
|
+
const animationController = originalAnimate.call(node, props, settings);
|
|
967
|
+
|
|
968
|
+
// Wrap animation controller with monitoring
|
|
969
|
+
return this.wrapAnimationController(
|
|
970
|
+
animationController,
|
|
971
|
+
node.id,
|
|
972
|
+
props,
|
|
973
|
+
settings,
|
|
974
|
+
div,
|
|
975
|
+
);
|
|
976
|
+
},
|
|
977
|
+
configurable: true,
|
|
978
|
+
});
|
|
979
|
+
|
|
980
|
+
return node;
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
updateTextNodeDimensions(div: HTMLElement, node: CoreTextNode) {
|
|
984
|
+
const textMetrics = node.renderInfo;
|
|
985
|
+
if (textMetrics) {
|
|
986
|
+
div.style.width = `${textMetrics.width}px`;
|
|
987
|
+
div.style.height = `${textMetrics.height}px`;
|
|
988
|
+
} else {
|
|
989
|
+
div.style.removeProperty('width');
|
|
990
|
+
div.style.removeProperty('height');
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
updateTextureAttributes(div: HTMLElement, texture: Texture) {
|
|
995
|
+
// Update texture state
|
|
996
|
+
div.setAttribute('data-texture-state', texture.state);
|
|
997
|
+
|
|
998
|
+
// Update texture type
|
|
999
|
+
div.setAttribute(
|
|
1000
|
+
'data-texture-type',
|
|
1001
|
+
textureTypeNames[texture.type] || 'unknown',
|
|
1002
|
+
);
|
|
1003
|
+
|
|
1004
|
+
// Update texture dimensions if available
|
|
1005
|
+
if (texture.dimensions) {
|
|
1006
|
+
div.setAttribute('data-texture-width', String(texture.dimensions.w));
|
|
1007
|
+
div.setAttribute('data-texture-height', String(texture.dimensions.h));
|
|
1008
|
+
} else {
|
|
1009
|
+
div.removeAttribute('data-texture-width');
|
|
1010
|
+
div.removeAttribute('data-texture-height');
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
// Update renderable owners count
|
|
1014
|
+
div.setAttribute(
|
|
1015
|
+
'data-texture-owners',
|
|
1016
|
+
String(texture.renderableOwners.length),
|
|
1017
|
+
);
|
|
1018
|
+
|
|
1019
|
+
// Update retry count
|
|
1020
|
+
div.setAttribute('data-texture-retry-count', String(texture.retryCount));
|
|
1021
|
+
|
|
1022
|
+
// Update max retry count if available
|
|
1023
|
+
if (texture.maxRetryCount !== null) {
|
|
1024
|
+
div.setAttribute(
|
|
1025
|
+
'data-texture-max-retry-count',
|
|
1026
|
+
String(texture.maxRetryCount),
|
|
1027
|
+
);
|
|
1028
|
+
} else {
|
|
1029
|
+
div.removeAttribute('data-texture-max-retry-count');
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
// Update metrics if available
|
|
1033
|
+
const metrics = this.textureMetrics.get(texture);
|
|
1034
|
+
if (metrics) {
|
|
1035
|
+
div.setAttribute('data-texture-previous-state', metrics.previousState);
|
|
1036
|
+
div.setAttribute(
|
|
1037
|
+
'data-texture-loaded-count',
|
|
1038
|
+
String(metrics.loadedCount),
|
|
1039
|
+
);
|
|
1040
|
+
div.setAttribute(
|
|
1041
|
+
'data-texture-failed-count',
|
|
1042
|
+
String(metrics.failedCount),
|
|
1043
|
+
);
|
|
1044
|
+
div.setAttribute('data-texture-freed-count', String(metrics.freedCount));
|
|
1045
|
+
} else {
|
|
1046
|
+
div.removeAttribute('data-texture-previous-state');
|
|
1047
|
+
div.removeAttribute('data-texture-loaded-count');
|
|
1048
|
+
div.removeAttribute('data-texture-failed-count');
|
|
1049
|
+
div.removeAttribute('data-texture-freed-count');
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
// Update error information if present
|
|
1053
|
+
if (texture.error) {
|
|
1054
|
+
div.setAttribute(
|
|
1055
|
+
'data-texture-error',
|
|
1056
|
+
texture.error.code || texture.error.message,
|
|
1057
|
+
);
|
|
1058
|
+
} else {
|
|
1059
|
+
div.removeAttribute('data-texture-error');
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
public destroy() {
|
|
1064
|
+
// Stop animation stats timer
|
|
1065
|
+
this.stopAnimationStatsTimer();
|
|
1066
|
+
|
|
1067
|
+
// Remove DOM observers
|
|
1068
|
+
this.mutationObserver.disconnect();
|
|
1069
|
+
this.resizeObserver.disconnect();
|
|
1070
|
+
|
|
1071
|
+
// Remove resize listener
|
|
1072
|
+
window.removeEventListener('resize', this.setRootPosition.bind(this));
|
|
1073
|
+
if (this.root && this.root.parentNode) {
|
|
1074
|
+
this.root.remove();
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
// Clean up animation monitoring data
|
|
1078
|
+
Inspector.clearAnimationStats();
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
destroyNode(id: number) {
|
|
1082
|
+
const div = document.getElementById(id.toString());
|
|
1083
|
+
div?.remove();
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
updateNodeProperty(
|
|
1087
|
+
div: HTMLElement,
|
|
1088
|
+
property: keyof CoreNodeProps | keyof CoreTextNodeProps,
|
|
1089
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1090
|
+
value: any,
|
|
1091
|
+
props: CoreNodeProps | CoreTextNodeProps,
|
|
1092
|
+
) {
|
|
1093
|
+
if (this.root === null || value === undefined || value === null) {
|
|
1094
|
+
return;
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
/**
|
|
1098
|
+
* Special case for parent property
|
|
1099
|
+
*/
|
|
1100
|
+
if (property === 'parent') {
|
|
1101
|
+
const parentId: number = value.id;
|
|
1102
|
+
|
|
1103
|
+
// only way to detect if the parent is the root node
|
|
1104
|
+
// if you are reading this and have a better way, please let me know
|
|
1105
|
+
if (parentId === 1) {
|
|
1106
|
+
this.root.appendChild(div);
|
|
1107
|
+
return;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
const parent = document.getElementById(parentId.toString());
|
|
1111
|
+
parent?.appendChild(div);
|
|
1112
|
+
return;
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
// special case for text
|
|
1116
|
+
if (property === 'text') {
|
|
1117
|
+
div.innerHTML = String(value);
|
|
1118
|
+
|
|
1119
|
+
// Keep DOM text invisible without breaking visibility checks
|
|
1120
|
+
// Use very low opacity (0.001) instead of 0 so Playwright still detects it
|
|
1121
|
+
div.style.opacity = '0.001';
|
|
1122
|
+
div.style.pointerEvents = 'none';
|
|
1123
|
+
div.style.userSelect = 'none';
|
|
1124
|
+
return;
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
// special case for images
|
|
1128
|
+
// we're not setting any CSS properties to avoid images getting loaded twice
|
|
1129
|
+
// as the renderer will handle the loading of the image. Setting it to `data-src`
|
|
1130
|
+
if (property === 'src' && value) {
|
|
1131
|
+
div.setAttribute(`data-src`, String(value));
|
|
1132
|
+
return;
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
// special case for color gradients (normal colors are handled by the stylePropertyMap)
|
|
1136
|
+
// FIXME the renderer seems to return the same number for all colors
|
|
1137
|
+
// if (gradientColorPropertyMap.includes(property as string)) {
|
|
1138
|
+
// const color = convertColorToRgba(value as number);
|
|
1139
|
+
// div.setAttribute(`data-${property}`, color);
|
|
1140
|
+
// return;
|
|
1141
|
+
// }
|
|
1142
|
+
|
|
1143
|
+
if (property === 'rtt' && value) {
|
|
1144
|
+
div.setAttribute('data-rtt', String(value));
|
|
1145
|
+
return;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
// CSS mappable attribute
|
|
1149
|
+
if (stylePropertyMap[property]) {
|
|
1150
|
+
const mappedStyleResponse = stylePropertyMap[property]?.(value);
|
|
1151
|
+
|
|
1152
|
+
if (mappedStyleResponse === null) {
|
|
1153
|
+
return;
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
if (typeof mappedStyleResponse === 'string') {
|
|
1157
|
+
div.style.setProperty(mappedStyleResponse, String(value));
|
|
1158
|
+
return;
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
if (typeof mappedStyleResponse === 'object') {
|
|
1162
|
+
let value = mappedStyleResponse.value;
|
|
1163
|
+
if (property === 'x') {
|
|
1164
|
+
const mount = props.mountX;
|
|
1165
|
+
const width = props.w;
|
|
1166
|
+
|
|
1167
|
+
if (mount) {
|
|
1168
|
+
value = `${parseInt(value) - width * mount}px`;
|
|
1169
|
+
}
|
|
1170
|
+
} else if (property === 'y') {
|
|
1171
|
+
const mount = props.mountY;
|
|
1172
|
+
const height = props.h;
|
|
1173
|
+
|
|
1174
|
+
if (mount) {
|
|
1175
|
+
value = `${parseInt(value) - height * mount}px`;
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
div.style.setProperty(mappedStyleResponse.prop, value);
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
return;
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
// DOM properties
|
|
1185
|
+
if (domPropertyMap[property]) {
|
|
1186
|
+
const domProperty = domPropertyMap[property];
|
|
1187
|
+
if (!domProperty) {
|
|
1188
|
+
return;
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
div.setAttribute(String(domProperty), String(value));
|
|
1192
|
+
return;
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
// custom data properties
|
|
1196
|
+
if (property === 'data') {
|
|
1197
|
+
for (const key in value) {
|
|
1198
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
1199
|
+
const keyValue: unknown = value[key];
|
|
1200
|
+
if (keyValue === undefined) {
|
|
1201
|
+
div.removeAttribute(`data-${key}`);
|
|
1202
|
+
} else {
|
|
1203
|
+
div.setAttribute(`data-${key}`, String(keyValue));
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
return;
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
updateViewport(
|
|
1211
|
+
width: number,
|
|
1212
|
+
height: number,
|
|
1213
|
+
deviceLogicalPixelRatio: number,
|
|
1214
|
+
) {
|
|
1215
|
+
this.scaleX = deviceLogicalPixelRatio ?? 1;
|
|
1216
|
+
this.scaleY = deviceLogicalPixelRatio ?? 1;
|
|
1217
|
+
|
|
1218
|
+
this.width = width;
|
|
1219
|
+
this.height = height;
|
|
1220
|
+
this.setRootPosition();
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
// simple animation handler
|
|
1224
|
+
animateNode(
|
|
1225
|
+
div: HTMLElement,
|
|
1226
|
+
props: CoreNodeAnimateProps,
|
|
1227
|
+
settings: AnimationSettings,
|
|
1228
|
+
) {
|
|
1229
|
+
const {
|
|
1230
|
+
duration = 1000,
|
|
1231
|
+
delay = 0,
|
|
1232
|
+
// easing = 'linear',
|
|
1233
|
+
// repeat = 0,
|
|
1234
|
+
// loop = false,
|
|
1235
|
+
// stopMethod = false,
|
|
1236
|
+
} = settings;
|
|
1237
|
+
|
|
1238
|
+
const {
|
|
1239
|
+
x,
|
|
1240
|
+
y,
|
|
1241
|
+
w,
|
|
1242
|
+
h,
|
|
1243
|
+
alpha = 1,
|
|
1244
|
+
rotation = 0,
|
|
1245
|
+
scale = 1,
|
|
1246
|
+
color,
|
|
1247
|
+
mountX,
|
|
1248
|
+
mountY,
|
|
1249
|
+
} = props;
|
|
1250
|
+
|
|
1251
|
+
// ignoring loops and repeats for now, as that might be a bit too much for the inspector
|
|
1252
|
+
function animate() {
|
|
1253
|
+
setTimeout(() => {
|
|
1254
|
+
div.style.top = `${y - h * mountY}px`;
|
|
1255
|
+
div.style.left = `${x - w * mountX}px`;
|
|
1256
|
+
div.style.width = `${w}px`;
|
|
1257
|
+
div.style.height = `${h}px`;
|
|
1258
|
+
div.style.opacity = `${alpha}`;
|
|
1259
|
+
div.style.rotate = `${rotation}rad`;
|
|
1260
|
+
div.style.scale = `${scale}`;
|
|
1261
|
+
div.style.color = convertColorToRgba(color);
|
|
1262
|
+
}, duration);
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
setTimeout(animate, delay);
|
|
1266
|
+
}
|
|
1267
|
+
}
|