@lightningjs/renderer 3.0.0-beta2 → 3.0.0-beta21

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.
Files changed (587) hide show
  1. package/README.md +16 -26
  2. package/dist/exports/canvas.d.ts +1 -1
  3. package/dist/exports/canvas.js +1 -1
  4. package/dist/exports/canvas.js.map +1 -1
  5. package/dist/exports/index.d.ts +2 -5
  6. package/dist/exports/index.js +1 -5
  7. package/dist/exports/index.js.map +1 -1
  8. package/dist/exports/utils.d.ts +2 -1
  9. package/dist/exports/utils.js +2 -1
  10. package/dist/exports/utils.js.map +1 -1
  11. package/dist/exports/webgl.d.ts +2 -1
  12. package/dist/exports/webgl.js +2 -1
  13. package/dist/exports/webgl.js.map +1 -1
  14. package/dist/src/common/CommonTypes.d.ts +13 -2
  15. package/dist/src/core/Autosizer.d.ts +35 -0
  16. package/dist/src/core/Autosizer.js +196 -0
  17. package/dist/src/core/Autosizer.js.map +1 -0
  18. package/dist/src/core/CoreNode.d.ts +124 -100
  19. package/dist/src/core/CoreNode.js +720 -472
  20. package/dist/src/core/CoreNode.js.map +1 -1
  21. package/dist/src/core/CoreShaderManager.d.ts +3 -5
  22. package/dist/src/core/CoreShaderManager.js.map +1 -1
  23. package/dist/src/core/CoreTextNode.d.ts +74 -87
  24. package/dist/src/core/CoreTextNode.js +355 -232
  25. package/dist/src/core/CoreTextNode.js.map +1 -1
  26. package/dist/src/core/CoreTextureManager.d.ts +25 -13
  27. package/dist/src/core/CoreTextureManager.js +80 -104
  28. package/dist/src/core/CoreTextureManager.js.map +1 -1
  29. package/dist/src/core/Stage.d.ts +93 -33
  30. package/dist/src/core/Stage.js +315 -151
  31. package/dist/src/core/Stage.js.map +1 -1
  32. package/dist/src/core/TextureError.d.ts +11 -0
  33. package/dist/src/core/TextureError.js +37 -0
  34. package/dist/src/core/TextureError.js.map +1 -0
  35. package/dist/src/core/TextureMemoryManager.d.ts +11 -4
  36. package/dist/src/core/TextureMemoryManager.js +128 -109
  37. package/dist/src/core/TextureMemoryManager.js.map +1 -1
  38. package/dist/src/core/animations/Animation.d.ts +21 -0
  39. package/dist/src/core/animations/Animation.js +194 -0
  40. package/dist/src/core/animations/Animation.js.map +1 -0
  41. package/dist/src/core/animations/CoreAnimation.d.ts +3 -3
  42. package/dist/src/core/animations/CoreAnimation.js +8 -3
  43. package/dist/src/core/animations/CoreAnimation.js.map +1 -1
  44. package/dist/src/core/animations/CoreAnimationController.d.ts +1 -0
  45. package/dist/src/core/animations/CoreAnimationController.js +11 -4
  46. package/dist/src/core/animations/CoreAnimationController.js.map +1 -1
  47. package/dist/src/core/animations/Playback.d.ts +64 -0
  48. package/dist/src/core/animations/Playback.js +169 -0
  49. package/dist/src/core/animations/Playback.js.map +1 -0
  50. package/dist/src/core/animations/Transition.d.ts +27 -0
  51. package/dist/src/core/animations/Transition.js +52 -0
  52. package/dist/src/core/animations/Transition.js.map +1 -0
  53. package/dist/src/core/animations/utils.d.ts +2 -0
  54. package/dist/src/core/animations/utils.js +136 -0
  55. package/dist/src/core/animations/utils.js.map +1 -0
  56. package/dist/src/core/lib/ImageWorker.d.ts +2 -2
  57. package/dist/src/core/lib/ImageWorker.js +31 -12
  58. package/dist/src/core/lib/ImageWorker.js.map +1 -1
  59. package/dist/src/core/lib/WebGlContextWrapper.d.ts +41 -3
  60. package/dist/src/core/lib/WebGlContextWrapper.js +105 -28
  61. package/dist/src/core/lib/WebGlContextWrapper.js.map +1 -1
  62. package/dist/src/core/lib/collectionUtils.d.ts +5 -0
  63. package/dist/src/core/lib/collectionUtils.js +100 -0
  64. package/dist/src/core/lib/collectionUtils.js.map +1 -0
  65. package/dist/src/core/lib/colorCache.d.ts +1 -0
  66. package/dist/src/core/lib/colorCache.js +19 -0
  67. package/dist/src/core/lib/colorCache.js.map +1 -0
  68. package/dist/src/core/lib/colorParser.d.ts +21 -0
  69. package/dist/src/core/lib/colorParser.js +72 -0
  70. package/dist/src/core/lib/colorParser.js.map +1 -0
  71. package/dist/src/core/lib/textureCompression.d.ts +14 -2
  72. package/dist/src/core/lib/textureCompression.js +320 -67
  73. package/dist/src/core/lib/textureCompression.js.map +1 -1
  74. package/dist/src/core/lib/utils.d.ts +8 -2
  75. package/dist/src/core/lib/utils.js +43 -21
  76. package/dist/src/core/lib/utils.js.map +1 -1
  77. package/dist/src/core/lib/validateImageBitmap.d.ts +2 -1
  78. package/dist/src/core/lib/validateImageBitmap.js +4 -4
  79. package/dist/src/core/lib/validateImageBitmap.js.map +1 -1
  80. package/dist/src/core/platform.js +30 -5
  81. package/dist/src/core/platform.js.map +1 -1
  82. package/dist/src/core/platforms/Platform.d.ts +42 -0
  83. package/dist/src/{main-api/IRenderDriver.js → core/platforms/Platform.js} +4 -2
  84. package/dist/src/core/platforms/Platform.js.map +1 -0
  85. package/dist/src/core/platforms/web/WebPlatform.d.ts +10 -0
  86. package/dist/src/core/platforms/web/WebPlatform.js +87 -0
  87. package/dist/src/core/platforms/web/WebPlatform.js.map +1 -0
  88. package/dist/src/core/renderers/CoreContextTexture.d.ts +2 -1
  89. package/dist/src/core/renderers/CoreContextTexture.js.map +1 -1
  90. package/dist/src/core/renderers/CoreRenderer.d.ts +5 -30
  91. package/dist/src/core/renderers/CoreRenderer.js +1 -0
  92. package/dist/src/core/renderers/CoreRenderer.js.map +1 -1
  93. package/dist/src/core/renderers/CoreShaderNode.d.ts +12 -1
  94. package/dist/src/core/renderers/CoreShaderNode.js +26 -0
  95. package/dist/src/core/renderers/CoreShaderNode.js.map +1 -1
  96. package/dist/src/core/renderers/canvas/CanvasCoreTexture.d.ts +2 -1
  97. package/dist/src/core/renderers/canvas/CanvasCoreTexture.js +11 -9
  98. package/dist/src/core/renderers/canvas/CanvasCoreTexture.js.map +1 -1
  99. package/dist/src/core/renderers/canvas/CanvasRenderer.d.ts +4 -5
  100. package/dist/src/core/renderers/canvas/CanvasRenderer.js +65 -87
  101. package/dist/src/core/renderers/canvas/CanvasRenderer.js.map +1 -1
  102. package/dist/src/core/renderers/canvas/CanvasShaderNode.d.ts +1 -2
  103. package/dist/src/core/renderers/canvas/CanvasShaderNode.js +3 -5
  104. package/dist/src/core/renderers/canvas/CanvasShaderNode.js.map +1 -1
  105. package/dist/src/core/renderers/canvas/CanvasTexture.d.ts +3 -2
  106. package/dist/src/core/renderers/canvas/CanvasTexture.js +17 -13
  107. package/dist/src/core/renderers/canvas/CanvasTexture.js.map +1 -1
  108. package/dist/src/core/renderers/canvas/internal/C2DShaderUtils.d.ts +13 -0
  109. package/dist/src/core/renderers/canvas/internal/C2DShaderUtils.js +113 -192
  110. package/dist/src/core/renderers/canvas/internal/C2DShaderUtils.js.map +1 -1
  111. package/dist/src/core/renderers/canvas/internal/ColorUtils.d.ts +0 -2
  112. package/dist/src/core/renderers/canvas/internal/ColorUtils.js +0 -14
  113. package/dist/src/core/renderers/canvas/internal/ColorUtils.js.map +1 -1
  114. package/dist/src/core/renderers/webgl/SdfRenderOp.d.ts +33 -0
  115. package/dist/src/core/renderers/webgl/SdfRenderOp.js +97 -0
  116. package/dist/src/core/renderers/webgl/SdfRenderOp.js.map +1 -0
  117. package/dist/src/core/renderers/webgl/WebGlCoreCtxRenderTexture.js +3 -0
  118. package/dist/src/core/renderers/webgl/WebGlCoreCtxRenderTexture.js.map +1 -1
  119. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.d.ts +18 -6
  120. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js +87 -42
  121. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js.map +1 -1
  122. package/dist/src/core/renderers/webgl/WebGlCoreRenderOp.js +1 -1
  123. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.js +53 -17
  124. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.js.map +1 -1
  125. package/dist/src/core/renderers/webgl/WebGlCoreShader.d.ts +2 -7
  126. package/dist/src/core/renderers/webgl/WebGlCoreShader.js +21 -50
  127. package/dist/src/core/renderers/webgl/WebGlCoreShader.js.map +1 -1
  128. package/dist/src/core/renderers/webgl/WebGlCtxRenderTexture.d.ts +2 -0
  129. package/dist/src/core/renderers/webgl/WebGlCtxRenderTexture.js +14 -6
  130. package/dist/src/core/renderers/webgl/WebGlCtxRenderTexture.js.map +1 -1
  131. package/dist/src/core/renderers/webgl/WebGlCtxSubTexture.d.ts +13 -0
  132. package/dist/src/core/renderers/webgl/WebGlCtxSubTexture.js +34 -5
  133. package/dist/src/core/renderers/webgl/WebGlCtxSubTexture.js.map +1 -1
  134. package/dist/src/core/renderers/webgl/WebGlCtxTexture.d.ts +16 -6
  135. package/dist/src/core/renderers/webgl/WebGlCtxTexture.js +102 -52
  136. package/dist/src/core/renderers/webgl/WebGlCtxTexture.js.map +1 -1
  137. package/dist/src/core/renderers/webgl/WebGlRenderOp.d.ts +1 -1
  138. package/dist/src/core/renderers/webgl/WebGlRenderOp.js +11 -4
  139. package/dist/src/core/renderers/webgl/WebGlRenderOp.js.map +1 -1
  140. package/dist/src/core/renderers/webgl/WebGlRenderer.d.ts +11 -21
  141. package/dist/src/core/renderers/webgl/WebGlRenderer.js +168 -152
  142. package/dist/src/core/renderers/webgl/WebGlRenderer.js.map +1 -1
  143. package/dist/src/core/renderers/webgl/WebGlShaderNode.d.ts +2 -4
  144. package/dist/src/core/renderers/webgl/WebGlShaderNode.js +1 -4
  145. package/dist/src/core/renderers/webgl/WebGlShaderNode.js.map +1 -1
  146. package/dist/src/core/renderers/webgl/WebGlShaderProgram.d.ts +9 -7
  147. package/dist/src/core/renderers/webgl/WebGlShaderProgram.js +83 -43
  148. package/dist/src/core/renderers/webgl/WebGlShaderProgram.js.map +1 -1
  149. package/dist/src/core/renderers/webgl/shaders/DefaultShader.js +3 -6
  150. package/dist/src/core/renderers/webgl/shaders/DefaultShader.js.map +1 -1
  151. package/dist/src/core/renderers/webgl/shaders/DefaultShaderBatched.js +0 -11
  152. package/dist/src/core/renderers/webgl/shaders/DefaultShaderBatched.js.map +1 -1
  153. package/dist/src/core/renderers/webgl/shaders/DynamicShader.js +5 -10
  154. package/dist/src/core/renderers/webgl/shaders/DynamicShader.js.map +1 -1
  155. package/dist/src/core/renderers/webgl/shaders/RoundedRectangle.js +5 -10
  156. package/dist/src/core/renderers/webgl/shaders/RoundedRectangle.js.map +1 -1
  157. package/dist/src/core/renderers/webgl/shaders/SdfShader.js +0 -12
  158. package/dist/src/core/renderers/webgl/shaders/SdfShader.js.map +1 -1
  159. package/dist/src/core/renderers/webgl/shaders/effects/BorderBottomEffect.js +1 -1
  160. package/dist/src/core/renderers/webgl/shaders/effects/BorderLeftEffect.js +1 -1
  161. package/dist/src/core/renderers/webgl/shaders/effects/BorderRightEffect.js +1 -1
  162. package/dist/src/core/renderers/webgl/shaders/effects/BorderTopEffect.js +1 -1
  163. package/dist/src/core/renderers/webgl/shaders/effects/FadeOutEffect.js +5 -5
  164. package/dist/src/core/renderers/webgl/shaders/effects/HolePunchEffect.js +1 -1
  165. package/dist/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.js +24 -19
  166. package/dist/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.js.map +1 -1
  167. package/dist/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.d.ts +1 -0
  168. package/dist/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.js +32 -5
  169. package/dist/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.js.map +1 -1
  170. package/dist/src/core/renderers/webgl/shaders/effects/RadialProgressEffect.js +1 -1
  171. package/dist/src/core/renderers/webgl/shaders/effects/RadiusEffect.js +5 -5
  172. package/dist/src/core/shaders/canvas/Border.d.ts +8 -2
  173. package/dist/src/core/shaders/canvas/Border.js +64 -25
  174. package/dist/src/core/shaders/canvas/Border.js.map +1 -1
  175. package/dist/src/core/shaders/canvas/HolePunch.js +4 -3
  176. package/dist/src/core/shaders/canvas/HolePunch.js.map +1 -1
  177. package/dist/src/core/shaders/canvas/LinearGradient.js +11 -7
  178. package/dist/src/core/shaders/canvas/LinearGradient.js.map +1 -1
  179. package/dist/src/core/shaders/canvas/RadialGradient.js +21 -17
  180. package/dist/src/core/shaders/canvas/RadialGradient.js.map +1 -1
  181. package/dist/src/core/shaders/canvas/Rounded.js +3 -3
  182. package/dist/src/core/shaders/canvas/Rounded.js.map +1 -1
  183. package/dist/src/core/shaders/canvas/RoundedWithBorder.d.ts +6 -3
  184. package/dist/src/core/shaders/canvas/RoundedWithBorder.js +45 -7
  185. package/dist/src/core/shaders/canvas/RoundedWithBorder.js.map +1 -1
  186. package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.d.ts +2 -3
  187. package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.js +50 -11
  188. package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.js.map +1 -1
  189. package/dist/src/core/shaders/canvas/RoundedWithShadow.js +10 -7
  190. package/dist/src/core/shaders/canvas/RoundedWithShadow.js.map +1 -1
  191. package/dist/src/core/shaders/canvas/Shadow.js +4 -2
  192. package/dist/src/core/shaders/canvas/Shadow.js.map +1 -1
  193. package/dist/src/core/shaders/canvas/utils/render.d.ts +1 -1
  194. package/dist/src/core/shaders/canvas/utils/render.js +31 -18
  195. package/dist/src/core/shaders/canvas/utils/render.js.map +1 -1
  196. package/dist/src/core/shaders/templates/BorderTemplate.d.ts +12 -2
  197. package/dist/src/core/shaders/templates/BorderTemplate.js +31 -11
  198. package/dist/src/core/shaders/templates/BorderTemplate.js.map +1 -1
  199. package/dist/src/core/shaders/templates/HolePunchTemplate.d.ts +2 -2
  200. package/dist/src/core/shaders/templates/HolePunchTemplate.js +3 -3
  201. package/dist/src/core/shaders/templates/HolePunchTemplate.js.map +1 -1
  202. package/dist/src/core/shaders/templates/RadialGradientTemplate.d.ts +8 -6
  203. package/dist/src/core/shaders/templates/RadialGradientTemplate.js +2 -2
  204. package/dist/src/core/shaders/templates/RadialGradientTemplate.js.map +1 -1
  205. package/dist/src/core/shaders/templates/RoundedTemplate.js +1 -1
  206. package/dist/src/core/shaders/templates/RoundedTemplate.js.map +1 -1
  207. package/dist/src/core/shaders/templates/RoundedWithBorderAndShadowTemplate.d.ts +1 -1
  208. package/dist/src/core/shaders/templates/RoundedWithBorderTemplate.d.ts +1 -1
  209. package/dist/src/core/shaders/templates/RoundedWithShadowTemplate.d.ts +1 -1
  210. package/dist/src/core/shaders/templates/ShadowTemplate.d.ts +1 -1
  211. package/dist/src/core/shaders/{templates/shaderUtils.d.ts → utils.d.ts} +1 -1
  212. package/dist/src/core/shaders/{templates/shaderUtils.js → utils.js} +2 -2
  213. package/dist/src/core/shaders/utils.js.map +1 -0
  214. package/dist/src/core/shaders/webgl/Border.js +116 -35
  215. package/dist/src/core/shaders/webgl/Border.js.map +1 -1
  216. package/dist/src/core/shaders/webgl/Default.js +6 -7
  217. package/dist/src/core/shaders/webgl/Default.js.map +1 -1
  218. package/dist/src/core/shaders/webgl/HolePunch.js +4 -3
  219. package/dist/src/core/shaders/webgl/HolePunch.js.map +1 -1
  220. package/dist/src/core/shaders/webgl/LinearGradient.js +33 -8
  221. package/dist/src/core/shaders/webgl/LinearGradient.js.map +1 -1
  222. package/dist/src/core/shaders/webgl/RadialGradient.js +56 -32
  223. package/dist/src/core/shaders/webgl/RadialGradient.js.map +1 -1
  224. package/dist/src/core/shaders/webgl/Rounded.js +4 -2
  225. package/dist/src/core/shaders/webgl/Rounded.js.map +1 -1
  226. package/dist/src/core/shaders/webgl/RoundedWithBorder.js +153 -39
  227. package/dist/src/core/shaders/webgl/RoundedWithBorder.js.map +1 -1
  228. package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js +158 -43
  229. package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js.map +1 -1
  230. package/dist/src/core/shaders/webgl/RoundedWithShadow.js +6 -4
  231. package/dist/src/core/shaders/webgl/RoundedWithShadow.js.map +1 -1
  232. package/dist/src/core/shaders/webgl/SdfShader.d.ts +0 -2
  233. package/dist/src/core/shaders/webgl/SdfShader.js +7 -17
  234. package/dist/src/core/shaders/webgl/SdfShader.js.map +1 -1
  235. package/dist/src/core/shaders/webgl/SdfShadowShader.d.ts +9 -0
  236. package/dist/src/core/shaders/webgl/SdfShadowShader.js +100 -0
  237. package/dist/src/core/shaders/webgl/SdfShadowShader.js.map +1 -0
  238. package/dist/src/core/shaders/webgl/Shadow.js +12 -6
  239. package/dist/src/core/shaders/webgl/Shadow.js.map +1 -1
  240. package/dist/src/core/text-rendering/CanvasFontHandler.d.ts +59 -0
  241. package/dist/src/core/text-rendering/CanvasFontHandler.js +224 -0
  242. package/dist/src/core/text-rendering/CanvasFontHandler.js.map +1 -0
  243. package/dist/src/core/text-rendering/CanvasTextRenderer.d.ts +17 -0
  244. package/dist/src/core/text-rendering/CanvasTextRenderer.js +157 -0
  245. package/dist/src/core/text-rendering/CanvasTextRenderer.js.map +1 -0
  246. package/dist/src/core/text-rendering/SdfFontHandler.d.ts +182 -0
  247. package/dist/src/core/text-rendering/SdfFontHandler.js +391 -0
  248. package/dist/src/core/text-rendering/SdfFontHandler.js.map +1 -0
  249. package/dist/src/core/text-rendering/SdfTextRenderer.d.ts +17 -0
  250. package/dist/src/core/text-rendering/SdfTextRenderer.js +303 -0
  251. package/dist/src/core/text-rendering/SdfTextRenderer.js.map +1 -0
  252. package/dist/src/core/text-rendering/TextLayoutEngine.d.ts +18 -0
  253. package/dist/src/core/text-rendering/TextLayoutEngine.js +380 -0
  254. package/dist/src/core/text-rendering/TextLayoutEngine.js.map +1 -0
  255. package/dist/src/core/text-rendering/TextRenderer.d.ts +383 -0
  256. package/dist/src/{main-api/ICoreDriver.js → core/text-rendering/TextRenderer.js} +1 -1
  257. package/dist/src/core/text-rendering/TextRenderer.js.map +1 -0
  258. package/dist/src/core/text-rendering/TextTextureRendererUtils.js.map +1 -1
  259. package/dist/src/core/text-rendering/Utils.d.ts +30 -0
  260. package/dist/src/core/text-rendering/Utils.js +84 -0
  261. package/dist/src/core/text-rendering/Utils.js.map +1 -0
  262. package/dist/src/core/text-rendering/font-face-types/SdfTrFontFace/SdfTrFontFace.js +2 -2
  263. package/dist/src/core/text-rendering/font-face-types/SdfTrFontFace/SdfTrFontFace.js.map +1 -1
  264. package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.d.ts +0 -6
  265. package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.js.map +1 -1
  266. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.d.ts +3 -2
  267. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js +35 -38
  268. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js.map +1 -1
  269. package/dist/src/core/text-rendering/renderers/TextRenderer.d.ts +4 -1
  270. package/dist/src/core/text-rendering/renderers/TextRenderer.js.map +1 -1
  271. package/dist/src/core/textures/ColorTexture.d.ts +1 -1
  272. package/dist/src/core/textures/ColorTexture.js +3 -4
  273. package/dist/src/core/textures/ColorTexture.js.map +1 -1
  274. package/dist/src/core/textures/ImageTexture.d.ts +11 -4
  275. package/dist/src/core/textures/ImageTexture.js +31 -40
  276. package/dist/src/core/textures/ImageTexture.js.map +1 -1
  277. package/dist/src/core/textures/NoiseTexture.d.ts +3 -3
  278. package/dist/src/core/textures/NoiseTexture.js +8 -8
  279. package/dist/src/core/textures/NoiseTexture.js.map +1 -1
  280. package/dist/src/core/textures/RenderTexture.d.ts +7 -7
  281. package/dist/src/core/textures/RenderTexture.js +12 -12
  282. package/dist/src/core/textures/RenderTexture.js.map +1 -1
  283. package/dist/src/core/textures/SubTexture.d.ts +6 -8
  284. package/dist/src/core/textures/SubTexture.js +19 -37
  285. package/dist/src/core/textures/SubTexture.js.map +1 -1
  286. package/dist/src/core/textures/Texture.d.ts +87 -10
  287. package/dist/src/core/textures/Texture.js +160 -17
  288. package/dist/src/core/textures/Texture.js.map +1 -1
  289. package/dist/src/core/utils.d.ts +2 -1
  290. package/dist/src/core/utils.js +1 -1
  291. package/dist/src/core/utils.js.map +1 -1
  292. package/dist/src/main-api/INode.d.ts +2 -2
  293. package/dist/src/main-api/Inspector.d.ts +131 -2
  294. package/dist/src/main-api/Inspector.js +345 -28
  295. package/dist/src/main-api/Inspector.js.map +1 -1
  296. package/dist/src/main-api/Renderer.d.ts +295 -82
  297. package/dist/src/main-api/Renderer.js +223 -76
  298. package/dist/src/main-api/Renderer.js.map +1 -1
  299. package/dist/src/utils.d.ts +1 -6
  300. package/dist/src/utils.js +2 -9
  301. package/dist/src/utils.js.map +1 -1
  302. package/dist/tsconfig.dist.tsbuildinfo +1 -1
  303. package/dist/tsconfig.tsbuildinfo +1 -0
  304. package/exports/canvas.ts +1 -1
  305. package/exports/index.ts +2 -8
  306. package/exports/utils.ts +7 -1
  307. package/exports/webgl.ts +3 -1
  308. package/package.json +15 -17
  309. package/src/common/CommonTypes.ts +18 -2
  310. package/src/core/Autosizer.ts +224 -0
  311. package/src/core/CoreNode.test.ts +179 -17
  312. package/src/core/CoreNode.ts +895 -599
  313. package/src/core/CoreShaderManager.ts +5 -10
  314. package/src/core/CoreTextNode.ts +422 -286
  315. package/src/core/CoreTextureManager.ts +110 -130
  316. package/src/core/Stage.ts +397 -195
  317. package/src/core/TextureError.ts +46 -0
  318. package/src/core/TextureMemoryManager.ts +164 -141
  319. package/src/core/animations/CoreAnimation.ts +15 -9
  320. package/src/core/animations/CoreAnimationController.ts +13 -4
  321. package/src/core/lib/ImageWorker.ts +43 -12
  322. package/src/core/lib/WebGlContextWrapper.ts +127 -79
  323. package/src/core/lib/collectionUtils.ts +118 -0
  324. package/src/core/lib/colorCache.ts +20 -0
  325. package/src/core/{renderers/canvas/internal/ColorUtils.ts → lib/colorParser.ts} +2 -2
  326. package/src/core/lib/textureCompression.ts +433 -75
  327. package/src/core/lib/utils.ts +54 -25
  328. package/src/core/lib/validateImageBitmap.ts +17 -6
  329. package/src/core/platforms/Platform.ts +83 -0
  330. package/src/core/platforms/web/WebPlatform.ts +132 -0
  331. package/src/core/renderers/CoreContextTexture.ts +2 -1
  332. package/src/core/renderers/CoreRenderer.ts +5 -32
  333. package/src/core/renderers/CoreShaderNode.ts +38 -3
  334. package/src/core/renderers/canvas/CanvasRenderer.ts +84 -126
  335. package/src/core/renderers/canvas/CanvasShaderNode.ts +4 -8
  336. package/src/core/renderers/canvas/CanvasTexture.ts +22 -18
  337. package/src/core/renderers/webgl/SdfRenderOp.ts +105 -0
  338. package/src/core/renderers/webgl/WebGlCtxRenderTexture.ts +18 -15
  339. package/src/core/renderers/webgl/WebGlCtxSubTexture.ts +50 -5
  340. package/src/core/renderers/webgl/WebGlCtxTexture.ts +134 -84
  341. package/src/core/renderers/webgl/WebGlRenderer.ts +203 -190
  342. package/src/core/renderers/webgl/WebGlShaderNode.ts +4 -11
  343. package/src/core/renderers/webgl/WebGlShaderProgram.ts +101 -53
  344. package/src/core/shaders/canvas/Border.ts +88 -34
  345. package/src/core/shaders/canvas/HolePunch.ts +5 -11
  346. package/src/core/shaders/canvas/LinearGradient.ts +14 -10
  347. package/src/core/shaders/canvas/RadialGradient.ts +24 -41
  348. package/src/core/shaders/canvas/Rounded.ts +7 -7
  349. package/src/core/shaders/canvas/RoundedWithBorder.ts +77 -23
  350. package/src/core/shaders/canvas/RoundedWithBorderAndShadow.ts +84 -36
  351. package/src/core/shaders/canvas/RoundedWithShadow.ts +15 -13
  352. package/src/core/shaders/canvas/Shadow.ts +7 -5
  353. package/src/core/shaders/canvas/utils/render.ts +45 -36
  354. package/src/core/shaders/templates/BorderTemplate.ts +42 -12
  355. package/src/core/shaders/templates/HolePunchTemplate.ts +5 -5
  356. package/src/core/shaders/templates/RadialGradientTemplate.ts +10 -8
  357. package/src/core/shaders/templates/RoundedTemplate.ts +1 -1
  358. package/src/core/shaders/templates/RoundedWithBorderAndShadowTemplate.ts +1 -1
  359. package/src/core/shaders/templates/RoundedWithBorderTemplate.ts +1 -1
  360. package/src/core/shaders/templates/RoundedWithShadowTemplate.ts +1 -1
  361. package/src/core/shaders/templates/ShadowTemplate.ts +1 -1
  362. package/src/core/shaders/{templates/shaderUtils.ts → utils.ts} +2 -3
  363. package/src/core/shaders/webgl/Border.ts +116 -39
  364. package/src/core/shaders/webgl/Default.ts +6 -7
  365. package/src/core/shaders/webgl/HolePunch.ts +4 -7
  366. package/src/core/shaders/webgl/LinearGradient.ts +33 -8
  367. package/src/core/shaders/webgl/RadialGradient.ts +58 -34
  368. package/src/core/shaders/webgl/Rounded.ts +4 -6
  369. package/src/core/shaders/webgl/RoundedWithBorder.ts +154 -46
  370. package/src/core/shaders/webgl/RoundedWithBorderAndShadow.ts +159 -52
  371. package/src/core/shaders/webgl/RoundedWithShadow.ts +6 -8
  372. package/src/core/shaders/webgl/SdfShader.ts +7 -19
  373. package/src/core/shaders/webgl/Shadow.ts +12 -6
  374. package/src/core/text-rendering/CanvasFontHandler.ts +304 -0
  375. package/src/core/text-rendering/CanvasTextRenderer.ts +255 -0
  376. package/src/core/text-rendering/SdfFontHandler.ts +591 -0
  377. package/src/core/text-rendering/SdfTextRenderer.ts +408 -0
  378. package/src/core/text-rendering/TextLayoutEngine.ts +672 -0
  379. package/src/core/text-rendering/TextRenderer.ts +444 -0
  380. package/src/core/text-rendering/Utils.ts +99 -0
  381. package/src/core/text-rendering/tests/TextLayoutEngine.test.ts +453 -0
  382. package/src/core/textures/ColorTexture.ts +7 -5
  383. package/src/core/textures/ImageTexture.ts +78 -66
  384. package/src/core/textures/NoiseTexture.ts +14 -12
  385. package/src/core/textures/RenderTexture.ts +18 -16
  386. package/src/core/textures/SubTexture.ts +25 -46
  387. package/src/core/textures/Texture.ts +207 -24
  388. package/src/core/utils.ts +9 -7
  389. package/src/main-api/INode.ts +4 -3
  390. package/src/main-api/Inspector.ts +577 -36
  391. package/src/main-api/Renderer.ts +518 -139
  392. package/src/utils.ts +10 -10
  393. package/dist/exports/core-api.d.ts +0 -74
  394. package/dist/exports/core-api.js +0 -96
  395. package/dist/exports/core-api.js.map +0 -1
  396. package/dist/exports/main-api.d.ts +0 -30
  397. package/dist/exports/main-api.js +0 -45
  398. package/dist/exports/main-api.js.map +0 -1
  399. package/dist/src/core/CoreExtension.d.ts +0 -12
  400. package/dist/src/core/CoreExtension.js +0 -29
  401. package/dist/src/core/CoreExtension.js.map +0 -1
  402. package/dist/src/core/CoreStuff.d.ts +0 -1
  403. package/dist/src/core/CoreStuff.js +0 -138
  404. package/dist/src/core/CoreStuff.js.map +0 -1
  405. package/dist/src/core/CoreTexturizer.d.ts +0 -14
  406. package/dist/src/core/CoreTexturizer.js +0 -47
  407. package/dist/src/core/CoreTexturizer.js.map +0 -1
  408. package/dist/src/core/LngNode.d.ts +0 -736
  409. package/dist/src/core/LngNode.js +0 -1174
  410. package/dist/src/core/LngNode.js.map +0 -1
  411. package/dist/src/core/Matrix2DContext.d.ts +0 -15
  412. package/dist/src/core/Matrix2DContext.js +0 -45
  413. package/dist/src/core/Matrix2DContext.js.map +0 -1
  414. package/dist/src/core/ShaderNode.d.ts +0 -10
  415. package/dist/src/core/ShaderNode.js +0 -30
  416. package/dist/src/core/ShaderNode.js.map +0 -1
  417. package/dist/src/core/TextNode.d.ts +0 -103
  418. package/dist/src/core/TextNode.js +0 -331
  419. package/dist/src/core/TextNode.js.map +0 -1
  420. package/dist/src/core/lib/Coords.d.ts +0 -14
  421. package/dist/src/core/lib/Coords.js +0 -55
  422. package/dist/src/core/lib/Coords.js.map +0 -1
  423. package/dist/src/core/lib/glm/common.d.ts +0 -162
  424. package/dist/src/core/lib/glm/common.js +0 -81
  425. package/dist/src/core/lib/glm/common.js.map +0 -1
  426. package/dist/src/core/lib/glm/index.d.ts +0 -11
  427. package/dist/src/core/lib/glm/index.js +0 -30
  428. package/dist/src/core/lib/glm/index.js.map +0 -1
  429. package/dist/src/core/lib/glm/mat2.d.ts +0 -219
  430. package/dist/src/core/lib/glm/mat2.js +0 -396
  431. package/dist/src/core/lib/glm/mat2.js.map +0 -1
  432. package/dist/src/core/lib/glm/mat2d.d.ts +0 -237
  433. package/dist/src/core/lib/glm/mat2d.js +0 -442
  434. package/dist/src/core/lib/glm/mat2d.js.map +0 -1
  435. package/dist/src/core/lib/glm/mat3.d.ts +0 -283
  436. package/dist/src/core/lib/glm/mat3.js +0 -680
  437. package/dist/src/core/lib/glm/mat3.js.map +0 -1
  438. package/dist/src/core/lib/glm/mat4.d.ts +0 -550
  439. package/dist/src/core/lib/glm/mat4.js +0 -1802
  440. package/dist/src/core/lib/glm/mat4.js.map +0 -1
  441. package/dist/src/core/lib/glm/quat.d.ts +0 -363
  442. package/dist/src/core/lib/glm/quat.js +0 -693
  443. package/dist/src/core/lib/glm/quat.js.map +0 -1
  444. package/dist/src/core/lib/glm/quat2.d.ts +0 -356
  445. package/dist/src/core/lib/glm/quat2.js +0 -754
  446. package/dist/src/core/lib/glm/quat2.js.map +0 -1
  447. package/dist/src/core/lib/glm/vec2.d.ts +0 -365
  448. package/dist/src/core/lib/glm/vec2.js +0 -569
  449. package/dist/src/core/lib/glm/vec2.js.map +0 -1
  450. package/dist/src/core/lib/glm/vec3.d.ts +0 -406
  451. package/dist/src/core/lib/glm/vec3.js +0 -720
  452. package/dist/src/core/lib/glm/vec3.js.map +0 -1
  453. package/dist/src/core/lib/glm/vec4.d.ts +0 -330
  454. package/dist/src/core/lib/glm/vec4.js +0 -608
  455. package/dist/src/core/lib/glm/vec4.js.map +0 -1
  456. package/dist/src/core/renderers/CoreShaderManager.d.ts +0 -19
  457. package/dist/src/core/renderers/CoreShaderManager.js +0 -33
  458. package/dist/src/core/renderers/CoreShaderManager.js.map +0 -1
  459. package/dist/src/core/renderers/webgl/WebGlCoreShaderManager.d.ts +0 -27
  460. package/dist/src/core/renderers/webgl/WebGlCoreShaderManager.js +0 -82
  461. package/dist/src/core/renderers/webgl/WebGlCoreShaderManager.js.map +0 -1
  462. package/dist/src/core/renderers/webgl/WebGlCoreShaderProgram.d.ts +0 -11
  463. package/dist/src/core/renderers/webgl/WebGlCoreShaderProgram.js +0 -34
  464. package/dist/src/core/renderers/webgl/WebGlCoreShaderProgram.js.map +0 -1
  465. package/dist/src/core/scene/Scene.d.ts +0 -59
  466. package/dist/src/core/scene/Scene.js +0 -106
  467. package/dist/src/core/scene/Scene.js.map +0 -1
  468. package/dist/src/core/shaders/templates/shaderUtils.js.map +0 -1
  469. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/makeRenderWindow.d.ts +0 -20
  470. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/makeRenderWindow.js +0 -55
  471. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/makeRenderWindow.js.map +0 -1
  472. package/dist/src/main-api/ICoreDriver.d.ts +0 -27
  473. package/dist/src/main-api/ICoreDriver.js.map +0 -1
  474. package/dist/src/main-api/IRenderDriver.d.ts +0 -20
  475. package/dist/src/main-api/IRenderDriver.js.map +0 -1
  476. package/dist/src/main-api/IShaderController.d.ts +0 -14
  477. package/dist/src/main-api/IShaderController.js +0 -30
  478. package/dist/src/main-api/IShaderController.js.map +0 -1
  479. package/dist/src/main-api/IShaderNode.d.ts +0 -17
  480. package/dist/src/main-api/IShaderNode.js +0 -19
  481. package/dist/src/main-api/IShaderNode.js.map +0 -1
  482. package/dist/src/main-api/RendererMain.d.ts +0 -375
  483. package/dist/src/main-api/RendererMain.js +0 -365
  484. package/dist/src/main-api/RendererMain.js.map +0 -1
  485. package/dist/src/main-api/texture-usage-trackers/FinalizationRegistryTextureUsageTracker.d.ts +0 -9
  486. package/dist/src/main-api/texture-usage-trackers/FinalizationRegistryTextureUsageTracker.js +0 -38
  487. package/dist/src/main-api/texture-usage-trackers/FinalizationRegistryTextureUsageTracker.js.map +0 -1
  488. package/dist/src/main-api/texture-usage-trackers/ManualCountTextureUsageTracker.d.ts +0 -56
  489. package/dist/src/main-api/texture-usage-trackers/ManualCountTextureUsageTracker.js +0 -101
  490. package/dist/src/main-api/texture-usage-trackers/ManualCountTextureUsageTracker.js.map +0 -1
  491. package/dist/src/main-api/texture-usage-trackers/TextureUsageTracker.d.ts +0 -32
  492. package/dist/src/main-api/texture-usage-trackers/TextureUsageTracker.js +0 -28
  493. package/dist/src/main-api/texture-usage-trackers/TextureUsageTracker.js.map +0 -1
  494. package/dist/src/render-drivers/main/MainCoreDriver.d.ts +0 -24
  495. package/dist/src/render-drivers/main/MainCoreDriver.js +0 -118
  496. package/dist/src/render-drivers/main/MainCoreDriver.js.map +0 -1
  497. package/dist/src/render-drivers/main/MainOnlyNode.d.ts +0 -99
  498. package/dist/src/render-drivers/main/MainOnlyNode.js +0 -396
  499. package/dist/src/render-drivers/main/MainOnlyNode.js.map +0 -1
  500. package/dist/src/render-drivers/main/MainOnlyShaderController.d.ts +0 -6
  501. package/dist/src/render-drivers/main/MainOnlyShaderController.js +0 -15
  502. package/dist/src/render-drivers/main/MainOnlyShaderController.js.map +0 -1
  503. package/dist/src/render-drivers/main/MainOnlyShaderNode.d.ts +0 -7
  504. package/dist/src/render-drivers/main/MainOnlyShaderNode.js +0 -34
  505. package/dist/src/render-drivers/main/MainOnlyShaderNode.js.map +0 -1
  506. package/dist/src/render-drivers/main/MainOnlyTextNode.d.ts +0 -47
  507. package/dist/src/render-drivers/main/MainOnlyTextNode.js +0 -205
  508. package/dist/src/render-drivers/main/MainOnlyTextNode.js.map +0 -1
  509. package/dist/src/render-drivers/main/MainRenderDriver.d.ts +0 -17
  510. package/dist/src/render-drivers/main/MainRenderDriver.js +0 -88
  511. package/dist/src/render-drivers/main/MainRenderDriver.js.map +0 -1
  512. package/dist/src/render-drivers/threadx/NodeStruct.d.ts +0 -90
  513. package/dist/src/render-drivers/threadx/NodeStruct.js +0 -281
  514. package/dist/src/render-drivers/threadx/NodeStruct.js.map +0 -1
  515. package/dist/src/render-drivers/threadx/SharedNode.d.ts +0 -39
  516. package/dist/src/render-drivers/threadx/SharedNode.js +0 -60
  517. package/dist/src/render-drivers/threadx/SharedNode.js.map +0 -1
  518. package/dist/src/render-drivers/threadx/TextNodeStruct.d.ts +0 -44
  519. package/dist/src/render-drivers/threadx/TextNodeStruct.js +0 -201
  520. package/dist/src/render-drivers/threadx/TextNodeStruct.js.map +0 -1
  521. package/dist/src/render-drivers/threadx/ThreadXCoreDriver.d.ts +0 -28
  522. package/dist/src/render-drivers/threadx/ThreadXCoreDriver.js +0 -234
  523. package/dist/src/render-drivers/threadx/ThreadXCoreDriver.js.map +0 -1
  524. package/dist/src/render-drivers/threadx/ThreadXMainAnimationController.d.ts +0 -20
  525. package/dist/src/render-drivers/threadx/ThreadXMainAnimationController.js +0 -84
  526. package/dist/src/render-drivers/threadx/ThreadXMainAnimationController.js.map +0 -1
  527. package/dist/src/render-drivers/threadx/ThreadXMainNode.d.ts +0 -44
  528. package/dist/src/render-drivers/threadx/ThreadXMainNode.js +0 -154
  529. package/dist/src/render-drivers/threadx/ThreadXMainNode.js.map +0 -1
  530. package/dist/src/render-drivers/threadx/ThreadXMainShaderController.d.ts +0 -6
  531. package/dist/src/render-drivers/threadx/ThreadXMainShaderController.js +0 -16
  532. package/dist/src/render-drivers/threadx/ThreadXMainShaderController.js.map +0 -1
  533. package/dist/src/render-drivers/threadx/ThreadXMainShaderNode.d.ts +0 -7
  534. package/dist/src/render-drivers/threadx/ThreadXMainShaderNode.js +0 -15
  535. package/dist/src/render-drivers/threadx/ThreadXMainShaderNode.js.map +0 -1
  536. package/dist/src/render-drivers/threadx/ThreadXMainTextNode.d.ts +0 -28
  537. package/dist/src/render-drivers/threadx/ThreadXMainTextNode.js +0 -55
  538. package/dist/src/render-drivers/threadx/ThreadXMainTextNode.js.map +0 -1
  539. package/dist/src/render-drivers/threadx/ThreadXRenderDriver.d.ts +0 -21
  540. package/dist/src/render-drivers/threadx/ThreadXRenderDriver.js +0 -198
  541. package/dist/src/render-drivers/threadx/ThreadXRenderDriver.js.map +0 -1
  542. package/dist/src/render-drivers/threadx/ThreadXRendererMessage.d.ts +0 -70
  543. package/dist/src/render-drivers/threadx/ThreadXRendererMessage.js +0 -32
  544. package/dist/src/render-drivers/threadx/ThreadXRendererMessage.js.map +0 -1
  545. package/dist/src/render-drivers/threadx/worker/ThreadXRendererNode.d.ts +0 -19
  546. package/dist/src/render-drivers/threadx/worker/ThreadXRendererNode.js +0 -177
  547. package/dist/src/render-drivers/threadx/worker/ThreadXRendererNode.js.map +0 -1
  548. package/dist/src/render-drivers/threadx/worker/ThreadXRendererTextNode.d.ts +0 -27
  549. package/dist/src/render-drivers/threadx/worker/ThreadXRendererTextNode.js +0 -108
  550. package/dist/src/render-drivers/threadx/worker/ThreadXRendererTextNode.js.map +0 -1
  551. package/dist/src/render-drivers/threadx/worker/renderer.d.ts +0 -1
  552. package/dist/src/render-drivers/threadx/worker/renderer.js +0 -145
  553. package/dist/src/render-drivers/threadx/worker/renderer.js.map +0 -1
  554. package/dist/src/render-drivers/utils.d.ts +0 -12
  555. package/dist/src/render-drivers/utils.js +0 -69
  556. package/dist/src/render-drivers/utils.js.map +0 -1
  557. package/scripts/please-use-pnpm.js +0 -13
  558. package/src/core/platform.ts +0 -64
  559. package/src/core/renderers/canvas/internal/C2DShaderUtils.ts +0 -220
  560. package/src/core/renderers/webgl/WebGlRenderOp.ts +0 -161
  561. package/src/core/text-rendering/TextRenderingUtils.ts +0 -36
  562. package/src/core/text-rendering/TextTextureRendererUtils.ts +0 -263
  563. package/src/core/text-rendering/TrFontManager.ts +0 -183
  564. package/src/core/text-rendering/font-face-types/SdfTrFontFace/SdfTrFontFace.ts +0 -176
  565. package/src/core/text-rendering/font-face-types/SdfTrFontFace/internal/FontShaper.ts +0 -139
  566. package/src/core/text-rendering/font-face-types/SdfTrFontFace/internal/SdfFontShaper.test.ts +0 -173
  567. package/src/core/text-rendering/font-face-types/SdfTrFontFace/internal/SdfFontShaper.ts +0 -171
  568. package/src/core/text-rendering/font-face-types/TrFontFace.ts +0 -187
  569. package/src/core/text-rendering/font-face-types/WebTrFontFace.ts +0 -94
  570. package/src/core/text-rendering/font-face-types/utils.ts +0 -39
  571. package/src/core/text-rendering/renderers/CanvasTextRenderer.ts +0 -509
  572. package/src/core/text-rendering/renderers/LightningTextTextureRenderer.ts +0 -815
  573. package/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.ts +0 -840
  574. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/PeekableGenerator.test.ts +0 -48
  575. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/PeekableGenerator.ts +0 -66
  576. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/SpecialCodepoints.ts +0 -52
  577. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/constants.ts +0 -32
  578. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/getStartConditions.ts +0 -117
  579. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/getUnicodeCodepoints.test.ts +0 -133
  580. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/getUnicodeCodepoints.ts +0 -38
  581. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.ts +0 -408
  582. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/measureText.test.ts +0 -49
  583. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/measureText.ts +0 -52
  584. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/setRenderWindow.test.ts +0 -205
  585. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/setRenderWindow.ts +0 -93
  586. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/util.ts +0 -40
  587. package/src/core/text-rendering/renderers/TextRenderer.ts +0 -550
@@ -20,14 +20,17 @@
20
20
  import {
21
21
  assertTruthy,
22
22
  getNewId,
23
- isProductionEnvironment,
24
23
  mergeColorAlphaPremultiplied,
25
24
  } from '../utils.js';
26
25
  import type { TextureOptions } from './CoreTextureManager.js';
26
+ import type { WebGlRenderer } from './renderers/webgl/WebGlRenderer.js';
27
+ import type { WebGlCtxTexture } from './renderers/webgl/WebGlCtxTexture.js';
28
+ import type { BufferCollection } from './renderers/webgl/internal/BufferCollection.js';
27
29
  import type { CoreRenderer } from './renderers/CoreRenderer.js';
28
30
  import type { Stage } from './Stage.js';
29
31
  import {
30
32
  type Texture,
33
+ type TextureCoords,
31
34
  type TextureFailedEventHandler,
32
35
  type TextureFreedEventHandler,
33
36
  type TextureLoadedEventHandler,
@@ -37,6 +40,7 @@ import type {
37
40
  NodeTextureFailedPayload,
38
41
  NodeTextureFreedPayload,
39
42
  NodeTextureLoadedPayload,
43
+ NodeRenderablePayload,
40
44
  } from '../common/CommonTypes.js';
41
45
  import { EventEmitter } from '../common/EventEmitter.js';
42
46
  import {
@@ -56,6 +60,12 @@ import type { IAnimationController } from '../common/IAnimationController.js';
56
60
  import { CoreAnimation } from './animations/CoreAnimation.js';
57
61
  import { CoreAnimationController } from './animations/CoreAnimationController.js';
58
62
  import type { CoreShaderNode } from './renderers/CoreShaderNode.js';
63
+ import { AutosizeMode, Autosizer } from './Autosizer.js';
64
+ import {
65
+ bucketSortByZIndex,
66
+ incrementalRepositionByZIndex,
67
+ removeChild,
68
+ } from './lib/collectionUtils.js';
59
69
 
60
70
  export enum CoreNodeRenderState {
61
71
  Init = 0,
@@ -64,6 +74,14 @@ export enum CoreNodeRenderState {
64
74
  InViewport = 8,
65
75
  }
66
76
 
77
+ const NO_CLIPPING_RECT: RectWithValid = {
78
+ x: 0,
79
+ y: 0,
80
+ w: 0,
81
+ h: 0,
82
+ valid: false,
83
+ };
84
+
67
85
  const CoreNodeRenderStateMap: Map<CoreNodeRenderState, string> = new Map();
68
86
  CoreNodeRenderStateMap.set(CoreNodeRenderState.Init, 'init');
69
87
  CoreNodeRenderStateMap.set(CoreNodeRenderState.OutOfBounds, 'outOfBounds');
@@ -77,33 +95,24 @@ export enum UpdateType {
77
95
  Children = 1,
78
96
 
79
97
  /**
80
- * Scale/Rotate transform update
81
- *
82
- * @remarks
83
- * CoreNode Properties Updated:
84
- * - `scaleRotateTransform`
85
- */
86
- ScaleRotate = 2,
87
-
88
- /**
89
- * Translate transform update (x/y/width/height/pivot/mount)
98
+ * localTransform
90
99
  *
91
100
  * @remarks
92
101
  * CoreNode Properties Updated:
93
102
  * - `localTransform`
94
103
  */
95
- Local = 4,
104
+ Local = 2,
96
105
 
97
106
  /**
98
- * Global Transform update
107
+ * globalTransform
99
108
  *
100
- * @remarks
109
+ * * @remarks
101
110
  * CoreNode Properties Updated:
102
111
  * - `globalTransform`
112
+ * - `renderBounds`
103
113
  * - `renderCoords`
104
- * - `renderBound`
105
114
  */
106
- Global = 8,
115
+ Global = 4,
107
116
 
108
117
  /**
109
118
  * Clipping rect update
@@ -112,25 +121,16 @@ export enum UpdateType {
112
121
  * CoreNode Properties Updated:
113
122
  * - `clippingRect`
114
123
  */
115
- Clipping = 16,
124
+ Clipping = 8,
116
125
 
117
126
  /**
118
- * Calculated ZIndex update
119
- *
120
- * @remarks
121
- * CoreNode Properties Updated:
122
- * - `calcZIndex`
123
- */
124
- CalculatedZIndex = 32,
125
-
126
- /**
127
- * Z-Index Sorted Children update
127
+ * Sort Z-Index Children update
128
128
  *
129
129
  * @remarks
130
130
  * CoreNode Properties Updated:
131
131
  * - `children` (sorts children by their `calcZIndex`)
132
132
  */
133
- ZIndexSortedChildren = 64,
133
+ SortZIndexChildren = 16,
134
134
 
135
135
  /**
136
136
  * Premultiplied Colors update
@@ -142,7 +142,7 @@ export enum UpdateType {
142
142
  * - `premultipliedColorBl`
143
143
  * - `premultipliedColorBr`
144
144
  */
145
- PremultipliedColors = 128,
145
+ PremultipliedColors = 32,
146
146
 
147
147
  /**
148
148
  * World Alpha update
@@ -151,7 +151,7 @@ export enum UpdateType {
151
151
  * CoreNode Properties Updated:
152
152
  * - `worldAlpha` = `parent.worldAlpha` * `alpha`
153
153
  */
154
- WorldAlpha = 256,
154
+ WorldAlpha = 64,
155
155
 
156
156
  /**
157
157
  * Render State update
@@ -160,7 +160,7 @@ export enum UpdateType {
160
160
  * CoreNode Properties Updated:
161
161
  * - `renderState`
162
162
  */
163
- RenderState = 512,
163
+ RenderState = 128,
164
164
 
165
165
  /**
166
166
  * Is Renderable update
@@ -169,37 +169,41 @@ export enum UpdateType {
169
169
  * CoreNode Properties Updated:
170
170
  * - `isRenderable`
171
171
  */
172
- IsRenderable = 1024,
172
+ IsRenderable = 256,
173
173
 
174
174
  /**
175
175
  * Render Texture update
176
176
  */
177
- RenderTexture = 2048,
177
+ RenderTexture = 512,
178
178
 
179
179
  /**
180
180
  * Track if parent has render texture
181
181
  */
182
- ParentRenderTexture = 4096,
182
+ ParentRenderTexture = 1024,
183
183
 
184
184
  /**
185
185
  * Render Bounds update
186
186
  */
187
- RenderBounds = 8192,
187
+ RenderBounds = 2048,
188
188
 
189
189
  /**
190
- * None
190
+ * RecalcUniforms
191
191
  */
192
- None = 0,
192
+ RecalcUniforms = 4096,
193
193
 
194
194
  /**
195
- * All
195
+ * Autosize update
196
+ */
197
+ Autosize = 8192,
198
+ /**
199
+ * None
196
200
  */
197
- All = 14335,
201
+ None = 0,
198
202
 
199
203
  /**
200
- * RecalcUniforms
204
+ * All
201
205
  */
202
- RecalcUniforms = 16384,
206
+ All = 16383,
203
207
  }
204
208
 
205
209
  /**
@@ -240,16 +244,18 @@ export interface CoreNodeProps {
240
244
  y: number;
241
245
  /**
242
246
  * The width of the Node.
247
+ * @warning This will be deprecated in favor of `w` and `h` properties in the future.
243
248
  *
244
249
  * @default `0`
245
250
  */
246
- width: number;
251
+ w: number;
247
252
  /**
248
253
  * The height of the Node.
254
+ * @warning This will be deprecated in favor of `w` and `h` properties in the future.
249
255
  *
250
256
  * @default `0`
251
257
  */
252
- height: number;
258
+ h: number;
253
259
  /**
254
260
  * The alpha opacity of the Node.
255
261
  *
@@ -261,14 +267,35 @@ export interface CoreNodeProps {
261
267
  */
262
268
  alpha: number;
263
269
  /**
264
- * Autosize mode
270
+ * Autosize
265
271
  *
266
272
  * @remarks
267
- * When enabled, when a texture is loaded into the Node, the Node will
268
- * automatically resize to the dimensions of the texture.
273
+ * When enabled, the Node automatically resizes based on its content
274
+ *
275
+ * **Texture Autosize Mode:**
276
+ * - When the Node has a texture, it automatically resizes to match the
277
+ * texture's dimensions when the texture loads
278
+ * - This ensures images display at their natural size without manual sizing
279
+ * - Text Nodes always use this mode regardless of this setting
280
+ *
281
+ * **Children Autosize Mode:**
282
+ * - When the Node has no texture but contains children, it automatically
283
+ * resizes to encompass all children's bounds
284
+ * - Calculates the bounding box that contains all child positions, dimensions,
285
+ * and transforms (scale, rotation, mount/pivot points)
286
+ * - Creates container behavior where the parent grows to fit its content
287
+ * - Updates dynamically as children are added, removed, or transformed
288
+ *
289
+ * **Mode Selection Logic:**
290
+ * - Texture mode takes precedence over children mode
291
+ * - Mode switches automatically when texture is added/removed
292
+ * - If no texture and no children, autosize has no effect
293
+ *
294
+ * **Performance:**
295
+ * - Children mode uses efficient transform caching and differential updates
296
+ * - Only recalculates when child transforms actually change
297
+ * - Minimal memory allocation with factory function patterns
269
298
  *
270
- * Text Nodes are always autosized based on their text content regardless
271
- * of this mode setting.
272
299
  *
273
300
  * @default `false`
274
301
  */
@@ -396,7 +423,11 @@ export interface CoreNodeProps {
396
423
  * The Node's z-index.
397
424
  *
398
425
  * @remarks
399
- * TBD
426
+ * Max z-index of children under the same parent determines which child
427
+ * is rendered on top. Higher z-index means the Node is rendered on top of
428
+ * children with lower z-index.
429
+ *
430
+ * Max value is 1000 and min value is -1000. Values outside of this range will be clamped.
400
431
  */
401
432
  zIndex: number;
402
433
  /**
@@ -424,15 +455,6 @@ export interface CoreNodeProps {
424
455
  */
425
456
  texture: Texture | null;
426
457
 
427
- /**
428
- * [Deprecated]: Prevents the texture from being cleaned up when the Node is removed
429
- *
430
- * @remarks
431
- * Please use the `preventCleanup` property on {@link TextureOptions} instead.
432
- *
433
- * @default false
434
- */
435
- preventCleanup: boolean;
436
458
  /**
437
459
  * Options to associate with the Node's Texture
438
460
  */
@@ -462,7 +484,6 @@ export interface CoreNodeProps {
462
484
  * settings being defaults)
463
485
  */
464
486
  src: string | null;
465
- zIndexLocked: number;
466
487
  /**
467
488
  * Scale to render the Node at
468
489
  *
@@ -683,20 +704,11 @@ export interface CoreNodeProps {
683
704
  */
684
705
  srcY?: number;
685
706
  /**
686
- * By enabling Strict bounds the renderer will not process & render child nodes of a node that is out of the visible area
687
- *
688
- * @remarks
689
- * When enabled out of bound nodes, i.e. nodes that are out of the visible area, will
690
- * **NOT** have their children processed and renderer anymore. This means the children of a out of bound
691
- * node will not receive update processing such as positioning updates and will not be drawn on screen.
692
- * As such the rest of the branch of the update tree that sits below this node will not be processed anymore
693
- *
694
- * This is a big performance gain but may be disabled in cases where the width of the parent node is
695
- * unknown and the render must process the child nodes regardless of the viewport status of the parent node
696
- *
707
+ * Mark the node as interactive so we can perform hit tests on it
708
+ * when pointer events are registered.
697
709
  * @default false
698
710
  */
699
- strictBounds: boolean;
711
+ interactive?: boolean;
700
712
  }
701
713
 
702
714
  /**
@@ -729,13 +741,26 @@ export class CoreNode extends EventEmitter {
729
741
  readonly children: CoreNode[] = [];
730
742
  protected _id: number = getNewId();
731
743
  readonly props: CoreNodeProps;
744
+ public readonly isCoreNode = true as const;
745
+
746
+ // WebGL Render Op State
747
+ public renderOpBufferIdx: number = 0;
748
+ public numQuads: number = 0;
749
+ public renderOpTextures: WebGlCtxTexture[] = [];
732
750
 
733
751
  private hasShaderUpdater = false;
752
+ public hasShaderTimeFn = false;
753
+ private hasColorProps = false;
754
+ private zIndexMin = 0;
755
+ private zIndexMax = 0;
756
+
757
+ public previousZIndex = -1;
758
+ public zIndexSortList: CoreNode[] = [];
759
+
734
760
  public updateType = UpdateType.All;
735
761
  public childUpdateType = UpdateType.None;
736
762
 
737
763
  public globalTransform?: Matrix3d;
738
- public scaleRotateTransform?: Matrix3d;
739
764
  public localTransform?: Matrix3d;
740
765
  public sceneGlobalTransform?: Matrix3d;
741
766
  public renderCoords?: RenderCoords;
@@ -746,10 +771,12 @@ export class CoreNode extends EventEmitter {
746
771
  public clippingRect: RectWithValid = {
747
772
  x: 0,
748
773
  y: 0,
749
- width: 0,
750
- height: 0,
774
+ w: 0,
775
+ h: 0,
751
776
  valid: false,
752
777
  };
778
+ public textureCoords?: TextureCoords;
779
+ public updateShaderUniforms: boolean = false;
753
780
  public isRenderable = false;
754
781
  public renderState: CoreNodeRenderState = CoreNodeRenderState.Init;
755
782
 
@@ -762,122 +789,193 @@ export class CoreNode extends EventEmitter {
762
789
  public hasRTTupdates = false;
763
790
  public parentHasRenderTexture = false;
764
791
  public rttParent: CoreNode | null = null;
792
+ /**
793
+ * only used when rtt = true
794
+ */
795
+ public framebufferDimensions: Dimensions | null = null;
796
+
797
+ /**Autosize properties */
798
+ autosizer: Autosizer | null = null;
799
+ parentAutosizer: Autosizer | null = null;
800
+
801
+ public destroyed = false;
765
802
 
766
803
  constructor(readonly stage: Stage, props: CoreNodeProps) {
767
804
  super();
805
+ const p = (this.props = {} as CoreNodeProps);
806
+
807
+ // Initialize the renderOpTextures array with a capacity of 16 (typical max textures)
808
+ this.renderOpTextures = [];
809
+
810
+ //inital update type
811
+ let initialUpdateType =
812
+ UpdateType.Local | UpdateType.RenderBounds | UpdateType.RenderState;
813
+
814
+ // Fast-path assign only known keys
815
+ p.x = props.x;
816
+ p.y = props.y;
817
+ p.w = props.w;
818
+ p.h = props.h;
819
+ p.alpha = props.alpha;
820
+ p.autosize = props.autosize;
821
+ p.clipping = props.clipping;
822
+
823
+ p.color = props.color;
824
+ p.colorTop = props.colorTop;
825
+ p.colorBottom = props.colorBottom;
826
+ p.colorLeft = props.colorLeft;
827
+ p.colorRight = props.colorRight;
828
+ p.colorTl = props.colorTl;
829
+ p.colorTr = props.colorTr;
830
+ p.colorBl = props.colorBl;
831
+ p.colorBr = props.colorBr;
832
+
833
+ //check if any color props are set for premultiplied color updates
834
+ if (
835
+ props.color > 0 ||
836
+ props.colorTop > 0 ||
837
+ props.colorBottom > 0 ||
838
+ props.colorLeft > 0 ||
839
+ props.colorRight > 0 ||
840
+ props.colorTl > 0 ||
841
+ props.colorTr > 0 ||
842
+ props.colorBl > 0 ||
843
+ props.colorBr > 0
844
+ ) {
845
+ this.hasColorProps = true;
846
+ initialUpdateType |= UpdateType.PremultipliedColors;
847
+ }
768
848
 
769
- this.props = {
770
- ...props,
771
- parent: null,
772
- texture: null,
773
- shader: null,
774
- src: null,
775
- rtt: false,
776
- };
849
+ p.scaleX = props.scaleX;
850
+ p.scaleY = props.scaleY;
851
+ p.rotation = props.rotation;
852
+ p.pivotX = props.pivotX;
853
+ p.pivotY = props.pivotY;
854
+ p.mountX = props.mountX;
855
+ p.mountY = props.mountY;
856
+ p.mount = props.mount;
857
+ p.pivot = props.pivot;
858
+
859
+ p.zIndex = props.zIndex;
860
+ p.textureOptions = props.textureOptions;
861
+
862
+ p.data = props.data;
863
+ p.imageType = props.imageType;
864
+ p.srcX = props.srcX;
865
+ p.srcY = props.srcY;
866
+ p.srcWidth = props.srcWidth;
867
+ p.srcHeight = props.srcHeight;
868
+ p.autosize = props.autosize;
869
+
870
+ p.parent = props.parent;
871
+ p.texture = null;
872
+ p.shader = null;
873
+ p.src = null;
874
+ p.rtt = false;
875
+ p.boundsMargin = null;
876
+
877
+ // Only set non-default values
878
+ if (props.zIndex !== 0) {
879
+ this.zIndex = props.zIndex;
880
+ }
881
+
882
+ if (props.parent !== null) {
883
+ props.parent.addChild(this);
884
+ }
777
885
 
778
886
  // Assign props to instances
779
- this.parent = props.parent;
780
887
  this.texture = props.texture;
781
888
  this.shader = props.shader;
782
889
  this.src = props.src;
783
890
  this.rtt = props.rtt;
891
+ this.boundsMargin = props.boundsMargin;
892
+ this.interactive = props.interactive;
784
893
 
785
- if (props.boundsMargin) {
786
- this.boundsMargin = Array.isArray(props.boundsMargin)
787
- ? props.boundsMargin
788
- : [
789
- props.boundsMargin,
790
- props.boundsMargin,
791
- props.boundsMargin,
792
- props.boundsMargin,
793
- ];
894
+ // Initialize autosize if enabled
895
+ if (p.autosize === true) {
896
+ this.autosizer = new Autosizer(this);
794
897
  }
795
898
 
796
- this.setUpdateType(
797
- UpdateType.ScaleRotate |
798
- UpdateType.Local |
799
- UpdateType.RenderBounds |
800
- UpdateType.RenderState,
801
- );
802
-
803
- if (isProductionEnvironment() === false && props.preventCleanup === true) {
804
- console.warn(
805
- 'CoreNode.preventCleanup: Is deprecated and will be removed in upcoming release, please use textureOptions.preventCleanup instead',
806
- );
807
- }
899
+ this.setUpdateType(initialUpdateType);
808
900
 
809
901
  // if the default texture isn't loaded yet, wait for it to load
810
902
  // this only happens when the node is created before the stage is ready
811
- if (
812
- this.stage.defaultTexture &&
813
- this.stage.defaultTexture.state !== 'loaded'
814
- ) {
815
- this.stage.defaultTexture.once('loaded', () => {
816
- this.setUpdateType(UpdateType.IsRenderable);
817
- });
903
+ const dt = this.stage.defaultTexture;
904
+ if (dt !== null && dt.state !== 'loaded') {
905
+ dt.once('loaded', () => this.setUpdateType(UpdateType.IsRenderable));
818
906
  }
819
907
  }
820
908
 
821
909
  //#region Textures
822
910
  loadTexture(): void {
823
- const { texture } = this.props;
824
- assertTruthy(texture);
911
+ if (this.props.texture === null) {
912
+ return;
913
+ }
825
914
 
826
915
  // If texture is already loaded / failed, trigger loaded event manually
827
916
  // so that users get a consistent event experience.
828
917
  // We do this in a microtask to allow listeners to be attached in the same
829
918
  // synchronous task after calling loadTexture()
830
- queueMicrotask(() => {
831
- if (this.textureOptions.preload === true) {
832
- this.stage.txManager.loadTexture(texture);
833
- }
919
+ queueMicrotask(this.loadTextureTask);
920
+ }
834
921
 
835
- texture.preventCleanup =
836
- this.props.textureOptions?.preventCleanup ?? false;
837
- texture.on('loaded', this.onTextureLoaded);
838
- texture.on('failed', this.onTextureFailed);
839
- texture.on('freed', this.onTextureFreed);
840
-
841
- // If the parent is a render texture, the initial texture status
842
- // will be set to freed until the texture is processed by the
843
- // Render RTT nodes. So we only need to listen fo changes and
844
- // no need to check the texture.state until we restructure how
845
- // textures are being processed.
846
- if (this.parentHasRenderTexture) {
847
- this.notifyParentRTTOfUpdate();
848
- return;
849
- }
922
+ /**
923
+ * Task for queueMicrotask to loadTexture
924
+ *
925
+ * @remarks
926
+ * This method is called in a microtask to release the texture.
927
+ */
928
+ private loadTextureTask = (): void => {
929
+ const texture = this.props.texture as Texture;
930
+ //it is possible that texture is null here if user sets the texture to null right after loadTexture call
931
+ if (texture === null) {
932
+ return;
933
+ }
934
+ if (this.textureOptions.preload === true) {
935
+ this.stage.txManager.loadTexture(texture);
936
+ }
850
937
 
851
- if (texture.state === 'loaded') {
852
- assertTruthy(texture.dimensions);
853
- this.onTextureLoaded(texture, texture.dimensions);
854
- } else if (texture.state === 'failed') {
855
- assertTruthy(texture.error);
856
- this.onTextureFailed(texture, texture.error);
857
- } else if (texture.state === 'freed') {
858
- this.onTextureFreed(texture);
859
- }
860
- });
861
- }
938
+ texture.preventCleanup = this.props.textureOptions?.preventCleanup ?? false;
939
+ texture.on('loaded', this.onTextureLoaded);
940
+ texture.on('failed', this.onTextureFailed);
941
+ texture.on('freed', this.onTextureFreed);
942
+
943
+ // If the parent is a render texture, the initial texture status
944
+ // will be set to freed until the texture is processed by the
945
+ // Render RTT nodes. So we only need to listen fo changes and
946
+ // no need to check the texture.state until we restructure how
947
+ // textures are being processed.
948
+ if (this.parentHasRenderTexture) {
949
+ this.notifyParentRTTOfUpdate();
950
+ return;
951
+ }
952
+
953
+ if (texture.state === 'loaded') {
954
+ this.onTextureLoaded(texture, texture.dimensions!);
955
+ } else if (texture.state === 'failed') {
956
+ this.onTextureFailed(texture, texture.error!);
957
+ } else if (texture.state === 'freed') {
958
+ this.onTextureFreed(texture);
959
+ }
960
+ };
862
961
 
863
962
  unloadTexture(): void {
864
- if (this.texture !== null) {
865
- this.texture.off('loaded', this.onTextureLoaded);
866
- this.texture.off('failed', this.onTextureFailed);
867
- this.texture.off('freed', this.onTextureFreed);
868
- this.texture.setRenderableOwner(this, false);
963
+ if (this.texture === null) {
964
+ return;
869
965
  }
966
+
967
+ const texture = this.texture;
968
+ texture.off('loaded', this.onTextureLoaded);
969
+ texture.off('failed', this.onTextureFailed);
970
+ texture.off('freed', this.onTextureFreed);
971
+ texture.setRenderableOwner(this._id, false);
870
972
  }
871
973
 
872
- autosizeNode(dimensions: Dimensions) {
873
- if (this.autosize) {
874
- this.width = dimensions.width;
875
- this.height = dimensions.height;
974
+ protected onTextureLoaded: TextureLoadedEventHandler = (_, dimensions) => {
975
+ if (this.autosizer !== null) {
976
+ this.autosizer.update();
876
977
  }
877
- }
878
978
 
879
- private onTextureLoaded: TextureLoadedEventHandler = (_, dimensions) => {
880
- this.autosizeNode(dimensions);
881
979
  this.setUpdateType(UpdateType.IsRenderable);
882
980
 
883
981
  // Texture was loaded. In case the RAF loop has already stopped, we request
@@ -890,13 +988,20 @@ export class CoreNode extends EventEmitter {
890
988
  }
891
989
 
892
990
  // ignore 1x1 pixel textures
893
- if (dimensions.width > 1 && dimensions.height > 1) {
991
+ if (dimensions.w > 1 && dimensions.h > 1) {
894
992
  this.emit('loaded', {
895
993
  type: 'texture',
896
994
  dimensions,
897
995
  } satisfies NodeTextureLoadedPayload);
898
996
  }
899
997
 
998
+ if (
999
+ this.stage.calculateTextureCoord === true &&
1000
+ this.props.textureOptions !== null
1001
+ ) {
1002
+ this.textureCoords = this.stage.renderer.getTextureCoords!(this);
1003
+ }
1004
+
900
1005
  // Trigger a local update if the texture is loaded and the resizeMode is 'contain'
901
1006
  if (this.props.textureOptions?.resizeMode?.type === 'contain') {
902
1007
  this.setUpdateType(UpdateType.Local);
@@ -904,6 +1009,10 @@ export class CoreNode extends EventEmitter {
904
1009
  };
905
1010
 
906
1011
  private onTextureFailed: TextureFailedEventHandler = (_, error) => {
1012
+ // immediately set isRenderable to false, so that we handle the error
1013
+ // without waiting for the next frame loop
1014
+ this.isRenderable = false;
1015
+ this.updateTextureOwnership(false);
907
1016
  this.setUpdateType(UpdateType.IsRenderable);
908
1017
 
909
1018
  // If parent has a render texture, flag that we need to update
@@ -911,13 +1020,22 @@ export class CoreNode extends EventEmitter {
911
1020
  this.notifyParentRTTOfUpdate();
912
1021
  }
913
1022
 
914
- this.emit('failed', {
915
- type: 'texture',
916
- error,
917
- } satisfies NodeTextureFailedPayload);
1023
+ if (
1024
+ this.texture !== null &&
1025
+ this.texture.retryCount > this.texture.maxRetryCount
1026
+ ) {
1027
+ this.emit('failed', {
1028
+ type: 'texture',
1029
+ error,
1030
+ } satisfies NodeTextureFailedPayload);
1031
+ }
918
1032
  };
919
1033
 
920
1034
  private onTextureFreed: TextureFreedEventHandler = () => {
1035
+ // immediately set isRenderable to false, so that we handle the error
1036
+ // without waiting for the next frame loop
1037
+ this.isRenderable = false;
1038
+ this.updateTextureOwnership(false);
921
1039
  this.setUpdateType(UpdateType.IsRenderable);
922
1040
 
923
1041
  // If parent has a render texture, flag that we need to update
@@ -945,46 +1063,26 @@ export class CoreNode extends EventEmitter {
945
1063
  const parent = this.props.parent;
946
1064
  if (!parent) return;
947
1065
 
948
- if ((parent.updateType & UpdateType.Children) === 0) {
949
- // Inform the parent if it doesn’t already have a child update
950
- parent.setUpdateType(UpdateType.Children);
951
- }
952
- }
953
-
954
- sortChildren() {
955
- this.children.sort((a, b) => a.calcZIndex - b.calcZIndex);
956
- }
957
-
958
- updateScaleRotateTransform() {
959
- const { rotation, scaleX, scaleY } = this.props;
960
-
961
- // optimize simple translation cases
962
- if (rotation === 0 && scaleX === 1 && scaleY === 1) {
963
- this.scaleRotateTransform = undefined;
964
- return;
965
- }
966
-
967
- this.scaleRotateTransform = Matrix3d.rotate(
968
- rotation,
969
- this.scaleRotateTransform,
970
- ).scale(scaleX, scaleY);
1066
+ parent.setUpdateType(UpdateType.Children);
971
1067
  }
972
1068
 
973
1069
  updateLocalTransform() {
974
- const { x, y, width, height } = this.props;
975
- const mountTranslateX = this.props.mountX * width;
976
- const mountTranslateY = this.props.mountY * height;
1070
+ const p = this.props;
1071
+ const { x, y, w, h } = p;
1072
+ const mountTranslateX = p.mountX * w;
1073
+ const mountTranslateY = p.mountY * h;
977
1074
 
978
- if (this.scaleRotateTransform) {
979
- const pivotTranslateX = this.props.pivotX * width;
980
- const pivotTranslateY = this.props.pivotY * height;
1075
+ if (p.rotation !== 0 || p.scaleX !== 1 || p.scaleY !== 1) {
1076
+ const scaleRotate = Matrix3d.rotate(p.rotation).scale(p.scaleX, p.scaleY);
1077
+ const pivotTranslateX = p.pivotX * w;
1078
+ const pivotTranslateY = p.pivotY * h;
981
1079
 
982
1080
  this.localTransform = Matrix3d.translate(
983
1081
  x - mountTranslateX + pivotTranslateX,
984
1082
  y - mountTranslateY + pivotTranslateY,
985
1083
  this.localTransform,
986
1084
  )
987
- .multiply(this.scaleRotateTransform)
1085
+ .multiply(scaleRotate)
988
1086
  .translate(-pivotTranslateX, -pivotTranslateY);
989
1087
  } else {
990
1088
  this.localTransform = Matrix3d.translate(
@@ -995,35 +1093,35 @@ export class CoreNode extends EventEmitter {
995
1093
  }
996
1094
 
997
1095
  // Handle 'contain' resize mode
998
- const texture = this.props.texture;
1096
+ const texture = p.texture;
999
1097
  if (
1000
1098
  texture &&
1001
1099
  texture.dimensions &&
1002
- this.props.textureOptions?.resizeMode?.type === 'contain'
1100
+ p.textureOptions.resizeMode?.type === 'contain'
1003
1101
  ) {
1004
1102
  let resizeModeScaleX = 1;
1005
1103
  let resizeModeScaleY = 1;
1006
1104
  let extraX = 0;
1007
1105
  let extraY = 0;
1008
- const { width: tw, height: th } = texture.dimensions;
1106
+ const { w: tw, h: th } = texture.dimensions;
1009
1107
  const txAspectRatio = tw / th;
1010
- const nodeAspectRatio = width / height;
1108
+ const nodeAspectRatio = w / h;
1011
1109
  if (txAspectRatio > nodeAspectRatio) {
1012
1110
  // Texture is wider than node
1013
1111
  // Center the node vertically (shift down by extraY)
1014
1112
  // Scale the node vertically to maintain original aspect ratio
1015
- const scaleX = width / tw;
1113
+ const scaleX = w / tw;
1016
1114
  const scaledTxHeight = th * scaleX;
1017
- extraY = (height - scaledTxHeight) / 2;
1018
- resizeModeScaleY = scaledTxHeight / height;
1115
+ extraY = (h - scaledTxHeight) / 2;
1116
+ resizeModeScaleY = scaledTxHeight / h;
1019
1117
  } else {
1020
1118
  // Texture is taller than node (or equal)
1021
1119
  // Center the node horizontally (shift right by extraX)
1022
1120
  // Scale the node horizontally to maintain original aspect ratio
1023
- const scaleY = height / th;
1121
+ const scaleY = h / th;
1024
1122
  const scaledTxWidth = tw * scaleY;
1025
- extraX = (width - scaledTxWidth) / 2;
1026
- resizeModeScaleX = scaledTxWidth / width;
1123
+ extraX = (w - scaledTxWidth) / 2;
1124
+ resizeModeScaleX = scaledTxWidth / w;
1027
1125
  }
1028
1126
 
1029
1127
  // Apply the extra translation and scale to the local transform
@@ -1031,8 +1129,6 @@ export class CoreNode extends EventEmitter {
1031
1129
  .translate(extraX, extraY)
1032
1130
  .scale(resizeModeScaleX, resizeModeScaleY);
1033
1131
  }
1034
-
1035
- this.setUpdateType(UpdateType.Global);
1036
1132
  }
1037
1133
 
1038
1134
  /**
@@ -1040,27 +1136,39 @@ export class CoreNode extends EventEmitter {
1040
1136
  * @param delta
1041
1137
  */
1042
1138
  update(delta: number, parentClippingRect: RectWithValid): void {
1043
- if (this.updateType & UpdateType.ScaleRotate) {
1044
- this.updateScaleRotateTransform();
1045
- this.setUpdateType(UpdateType.Local);
1139
+ const props = this.props;
1140
+ const parent = props.parent;
1141
+ const parentHasRenderTexture = this.parentHasRenderTexture;
1142
+ const hasParent = props.parent !== null;
1143
+
1144
+ let newRenderState: CoreNodeRenderState | null = null;
1145
+
1146
+ let updateType = this.updateType;
1147
+ let childUpdateType = this.childUpdateType;
1148
+ let updateParent = false;
1149
+
1150
+ //this needs to be handled before setting updateTypes are reset
1151
+ if (updateType & UpdateType.Autosize && this.autosizer !== null) {
1152
+ this.autosizer.update();
1046
1153
  }
1047
1154
 
1048
- if (this.updateType & UpdateType.Local) {
1155
+ // reset update type
1156
+ this.updateType = 0;
1157
+ this.childUpdateType = 0;
1158
+
1159
+ if (updateType & UpdateType.Local) {
1049
1160
  this.updateLocalTransform();
1050
- this.setUpdateType(UpdateType.Global);
1051
- }
1052
1161
 
1053
- const parent = this.props.parent;
1054
- let renderState: CoreNodeRenderState | null = null;
1162
+ updateType |= UpdateType.Global;
1163
+ updateParent = hasParent;
1164
+ }
1055
1165
 
1056
1166
  // Handle specific RTT updates at this node level
1057
- if (this.updateType & UpdateType.RenderTexture && this.rtt) {
1167
+ if (updateType & UpdateType.RenderTexture && this.rtt === true) {
1058
1168
  this.hasRTTupdates = true;
1059
1169
  }
1060
1170
 
1061
- if (this.updateType & UpdateType.Global) {
1062
- assertTruthy(this.localTransform);
1063
-
1171
+ if (updateType & UpdateType.Global) {
1064
1172
  if (this.parentHasRenderTexture === true && parent?.rtt === true) {
1065
1173
  // we are at the start of the RTT chain, so we need to reset the globalTransform
1066
1174
  // for correct RTT rendering
@@ -1069,7 +1177,7 @@ export class CoreNode extends EventEmitter {
1069
1177
  // Maintain a full scene global transform for bounds detection
1070
1178
  this.sceneGlobalTransform = Matrix3d.copy(
1071
1179
  parent?.globalTransform || Matrix3d.identity(),
1072
- ).multiply(this.localTransform);
1180
+ ).multiply(this.localTransform!);
1073
1181
  } else if (
1074
1182
  this.parentHasRenderTexture === true &&
1075
1183
  parent?.rtt === false
@@ -1078,179 +1186,189 @@ export class CoreNode extends EventEmitter {
1078
1186
  // so we need to propogate the sceneGlobalTransform of the parent
1079
1187
  // to maintain a full scene global transform for bounds detection
1080
1188
  this.sceneGlobalTransform = Matrix3d.copy(
1081
- parent?.sceneGlobalTransform || this.localTransform,
1082
- ).multiply(this.localTransform);
1189
+ parent?.sceneGlobalTransform || this.localTransform!,
1190
+ ).multiply(this.localTransform!);
1083
1191
 
1084
1192
  this.globalTransform = Matrix3d.copy(
1085
- parent?.globalTransform || this.localTransform,
1193
+ parent?.globalTransform || this.localTransform!,
1086
1194
  this.globalTransform,
1087
1195
  );
1088
1196
  } else {
1089
1197
  this.globalTransform = Matrix3d.copy(
1090
- parent?.globalTransform || this.localTransform,
1198
+ parent?.globalTransform || this.localTransform!,
1091
1199
  this.globalTransform,
1092
1200
  );
1093
1201
  }
1094
1202
 
1095
1203
  if (parent !== null) {
1096
- this.globalTransform.multiply(this.localTransform);
1204
+ this.globalTransform.multiply(this.localTransform!);
1097
1205
  }
1098
1206
  this.calculateRenderCoords();
1099
1207
  this.updateBoundingRect();
1100
1208
 
1101
- this.setUpdateType(
1102
- UpdateType.RenderState |
1103
- UpdateType.Children |
1104
- UpdateType.RecalcUniforms,
1105
- );
1106
- this.childUpdateType |= UpdateType.Global;
1209
+ updateType |= UpdateType.RenderState | UpdateType.RecalcUniforms;
1210
+ updateParent = hasParent;
1211
+
1212
+ //only propagate children updates if not autosizing
1213
+ if ((updateType & UpdateType.Autosize) === 0) {
1214
+ updateType |= UpdateType.Children;
1215
+ childUpdateType |= UpdateType.Global;
1216
+ }
1107
1217
 
1108
1218
  if (this.clipping === true) {
1109
- this.setUpdateType(UpdateType.Clipping | UpdateType.RenderBounds);
1110
- this.childUpdateType |= UpdateType.RenderBounds;
1219
+ updateType |= UpdateType.Clipping | UpdateType.RenderBounds;
1220
+ updateParent = hasParent;
1221
+ childUpdateType |= UpdateType.RenderBounds;
1111
1222
  }
1112
1223
  }
1113
1224
 
1114
- if (this.updateType & UpdateType.RenderBounds) {
1225
+ if (updateType & UpdateType.RenderBounds) {
1115
1226
  this.createRenderBounds();
1116
- this.setUpdateType(UpdateType.RenderState);
1117
- this.setUpdateType(UpdateType.Children);
1118
1227
 
1119
- this.childUpdateType |= UpdateType.RenderBounds;
1228
+ updateType |= UpdateType.RenderState | UpdateType.Children;
1229
+ updateParent = hasParent;
1230
+ childUpdateType |= UpdateType.RenderBounds;
1120
1231
  }
1121
1232
 
1122
- if (this.updateType & UpdateType.RenderState) {
1123
- renderState = this.checkRenderBounds();
1124
- this.setUpdateType(UpdateType.IsRenderable);
1233
+ if (updateType & UpdateType.RenderState) {
1234
+ newRenderState = this.checkRenderBounds();
1235
+
1236
+ updateType |= UpdateType.IsRenderable;
1237
+ updateParent = hasParent;
1125
1238
 
1126
1239
  // if we're not going out of bounds, update the render state
1127
1240
  // this is done so the update loop can finish before we mark a node
1128
1241
  // as out of bounds
1129
- if (renderState !== CoreNodeRenderState.OutOfBounds) {
1130
- this.updateRenderState(renderState);
1242
+ if (newRenderState !== CoreNodeRenderState.OutOfBounds) {
1243
+ this.updateRenderState(newRenderState);
1131
1244
  }
1132
1245
  }
1133
1246
 
1134
- if (this.updateType & UpdateType.WorldAlpha) {
1135
- if (parent) {
1136
- this.worldAlpha = parent.worldAlpha * this.props.alpha;
1137
- } else {
1138
- this.worldAlpha = this.props.alpha;
1139
- }
1140
- this.setUpdateType(
1247
+ if (updateType & UpdateType.WorldAlpha) {
1248
+ this.worldAlpha = (parent?.worldAlpha ?? 1) * this.props.alpha;
1249
+ updateType |=
1250
+ UpdateType.PremultipliedColors |
1141
1251
  UpdateType.Children |
1142
- UpdateType.PremultipliedColors |
1143
- UpdateType.IsRenderable,
1144
- );
1145
- this.childUpdateType |= UpdateType.WorldAlpha;
1252
+ UpdateType.IsRenderable;
1253
+ updateParent = hasParent;
1254
+ childUpdateType |= UpdateType.WorldAlpha;
1146
1255
  }
1147
1256
 
1148
- if (this.updateType & UpdateType.IsRenderable) {
1257
+ if (updateType & UpdateType.IsRenderable) {
1149
1258
  this.updateIsRenderable();
1150
1259
  }
1151
1260
 
1152
- if (this.updateType & UpdateType.Clipping) {
1261
+ // Handle autosize updates when children transforms change
1262
+ if (
1263
+ updateType & UpdateType.Global &&
1264
+ this.isRenderable === true &&
1265
+ this.parentAutosizer !== null
1266
+ ) {
1267
+ this.parentAutosizer.patch(this.id);
1268
+ }
1269
+
1270
+ if (updateType & UpdateType.Clipping) {
1153
1271
  this.calculateClippingRect(parentClippingRect);
1154
- this.setUpdateType(UpdateType.Children);
1272
+ updateType |= UpdateType.Children;
1273
+ updateParent = hasParent;
1155
1274
 
1156
- this.childUpdateType |= UpdateType.Clipping;
1157
- this.childUpdateType |= UpdateType.RenderBounds;
1275
+ childUpdateType |= UpdateType.Clipping | UpdateType.RenderBounds;
1158
1276
  }
1159
1277
 
1160
- if (this.updateType & UpdateType.PremultipliedColors) {
1161
- this.premultipliedColorTl = mergeColorAlphaPremultiplied(
1162
- this.props.colorTl,
1163
- this.worldAlpha,
1164
- true,
1165
- );
1278
+ if (updateType & UpdateType.PremultipliedColors) {
1279
+ const alpha = this.worldAlpha;
1166
1280
 
1167
- // If all the colors are the same just sent them all to the same value
1168
- if (
1169
- this.props.colorTl === this.props.colorTr &&
1170
- this.props.colorBl === this.props.colorBr &&
1171
- this.props.colorTl === this.props.colorBl
1172
- ) {
1281
+ const tl = props.colorTl;
1282
+ const tr = props.colorTr;
1283
+ const bl = props.colorBl;
1284
+ const br = props.colorBr;
1285
+
1286
+ // Fast equality check (covers all 4 corners)
1287
+ const same = tl === tr && tl === bl && tl === br;
1288
+
1289
+ const merged = mergeColorAlphaPremultiplied(tl, alpha, true);
1290
+
1291
+ this.premultipliedColorTl = merged;
1292
+
1293
+ if (same === true) {
1173
1294
  this.premultipliedColorTr =
1174
1295
  this.premultipliedColorBl =
1175
1296
  this.premultipliedColorBr =
1176
- this.premultipliedColorTl;
1297
+ merged;
1177
1298
  } else {
1178
1299
  this.premultipliedColorTr = mergeColorAlphaPremultiplied(
1179
- this.props.colorTr,
1180
- this.worldAlpha,
1300
+ tr,
1301
+ alpha,
1181
1302
  true,
1182
1303
  );
1183
1304
  this.premultipliedColorBl = mergeColorAlphaPremultiplied(
1184
- this.props.colorBl,
1185
- this.worldAlpha,
1305
+ bl,
1306
+ alpha,
1186
1307
  true,
1187
1308
  );
1188
1309
  this.premultipliedColorBr = mergeColorAlphaPremultiplied(
1189
- this.props.colorBr,
1190
- this.worldAlpha,
1310
+ br,
1311
+ alpha,
1191
1312
  true,
1192
1313
  );
1193
1314
  }
1194
1315
  }
1195
1316
 
1196
- // No need to update zIndex if there is no parent
1197
- if (parent !== null && this.updateType & UpdateType.CalculatedZIndex) {
1198
- this.calculateZIndex();
1199
- // Tell parent to re-sort children
1200
- parent.setUpdateType(UpdateType.ZIndexSortedChildren);
1317
+ if (this.renderState === CoreNodeRenderState.OutOfBounds) {
1318
+ // Delay updating children until the node is in bounds
1319
+ this.updateType = updateType;
1320
+ this.childUpdateType = childUpdateType;
1321
+ return;
1201
1322
  }
1202
1323
 
1203
- if (
1204
- this.props.strictBounds === true &&
1205
- this.renderState === CoreNodeRenderState.OutOfBounds
1206
- ) {
1207
- this.updateType &= ~UpdateType.RenderBounds; // remove render bounds update
1208
- return;
1324
+ if (updateParent === true) {
1325
+ parent!.setUpdateType(UpdateType.Children);
1209
1326
  }
1210
1327
 
1211
1328
  if (
1212
- this.updateType & UpdateType.RecalcUniforms &&
1329
+ updateType & UpdateType.RecalcUniforms &&
1213
1330
  this.hasShaderUpdater === true
1214
1331
  ) {
1332
+ this.updateShaderUniforms = true;
1333
+ }
1334
+
1335
+ if (this.isRenderable === true && this.updateShaderUniforms === true) {
1336
+ this.updateShaderUniforms = false;
1215
1337
  //this exists because the boolean hasShaderUpdater === true
1216
1338
  this.shader!.update!();
1217
1339
  }
1218
1340
 
1219
- if (this.updateType & UpdateType.Children && this.children.length > 0) {
1341
+ if (updateType & UpdateType.Children && this.children.length > 0) {
1342
+ let childClippingRect = this.clippingRect;
1343
+
1344
+ if (this.rtt === true) {
1345
+ childClippingRect = NO_CLIPPING_RECT;
1346
+ }
1347
+
1220
1348
  for (let i = 0, length = this.children.length; i < length; i++) {
1221
1349
  const child = this.children[i] as CoreNode;
1222
1350
 
1223
- child.setUpdateType(this.childUpdateType);
1351
+ if (childUpdateType !== 0) {
1352
+ child.setUpdateType(childUpdateType);
1353
+ }
1224
1354
 
1225
1355
  if (child.updateType === 0) {
1226
1356
  continue;
1227
1357
  }
1228
1358
 
1229
- let childClippingRect = this.clippingRect;
1230
- if (this.rtt === true) {
1231
- childClippingRect = {
1232
- x: 0,
1233
- y: 0,
1234
- width: 0,
1235
- height: 0,
1236
- valid: false,
1237
- };
1238
- }
1239
-
1240
1359
  child.update(delta, childClippingRect);
1241
1360
  }
1242
1361
  }
1243
1362
 
1244
1363
  // If the node has an RTT parent and requires a texture re-render, inform the RTT parent
1245
- // if (this.parentHasRenderTexture && this.updateType & UpdateType.RenderTexture) {
1364
+ // if (this.parentHasRenderTexture && updateType & UpdateType.RenderTexture) {
1246
1365
  // @TODO have a more scoped down updateType for RTT updates
1247
- if (this.parentHasRenderTexture && this.updateType > 0) {
1366
+ if (parentHasRenderTexture === true) {
1248
1367
  this.notifyParentRTTOfUpdate();
1249
1368
  }
1250
1369
 
1251
- // Sorting children MUST happen after children have been updated so
1252
- // that they have the oppotunity to update their calculated zIndex.
1253
- if (this.updateType & UpdateType.ZIndexSortedChildren) {
1370
+ //Resort children if needed
1371
+ if (updateType & UpdateType.SortZIndexChildren) {
1254
1372
  // reorder z-index
1255
1373
  this.sortChildren();
1256
1374
  }
@@ -1258,24 +1376,19 @@ export class CoreNode extends EventEmitter {
1258
1376
  // If we're out of bounds, apply the render state now
1259
1377
  // this is done so nodes can finish their entire update loop before
1260
1378
  // being marked as out of bounds
1261
- if (renderState === CoreNodeRenderState.OutOfBounds) {
1262
- this.updateRenderState(renderState);
1379
+ if (newRenderState === CoreNodeRenderState.OutOfBounds) {
1380
+ this.updateRenderState(newRenderState);
1263
1381
  this.updateIsRenderable();
1264
1382
 
1265
1383
  if (
1266
1384
  this.rtt === true &&
1267
- renderState === CoreNodeRenderState.OutOfBounds
1385
+ newRenderState === CoreNodeRenderState.OutOfBounds
1268
1386
  ) {
1269
1387
  // notify children that we are going out of bounds
1270
1388
  // we have to do this now before we stop processing the render tree
1271
- this.notifyChildrenRTTOfUpdate(renderState);
1272
- // this.childUpdateType |= UpdateType.RenderState;
1389
+ this.notifyChildrenRTTOfUpdate(newRenderState);
1273
1390
  }
1274
1391
  }
1275
-
1276
- // reset update type
1277
- this.updateType = 0;
1278
- this.childUpdateType = 0;
1279
1392
  }
1280
1393
 
1281
1394
  private findParentRTTNode(): CoreNode | null {
@@ -1286,15 +1399,6 @@ export class CoreNode extends EventEmitter {
1286
1399
  return rttNode;
1287
1400
  }
1288
1401
 
1289
- private getRTTParentRenderState(): CoreNodeRenderState | null {
1290
- const rttNode = this.rttParent || this.findParentRTTNode();
1291
- if (!rttNode) {
1292
- return null;
1293
- }
1294
-
1295
- return rttNode.renderState;
1296
- }
1297
-
1298
1402
  private notifyChildrenRTTOfUpdate(renderState: CoreNodeRenderState) {
1299
1403
  for (const child of this.children) {
1300
1404
  // force child to update render state
@@ -1304,7 +1408,7 @@ export class CoreNode extends EventEmitter {
1304
1408
  }
1305
1409
  }
1306
1410
 
1307
- private notifyParentRTTOfUpdate() {
1411
+ protected notifyParentRTTOfUpdate() {
1308
1412
  if (this.parent === null) {
1309
1413
  return;
1310
1414
  }
@@ -1325,28 +1429,21 @@ export class CoreNode extends EventEmitter {
1325
1429
  }
1326
1430
 
1327
1431
  checkRenderBounds(): CoreNodeRenderState {
1328
- assertTruthy(this.renderBound);
1329
- assertTruthy(this.strictBound);
1330
- assertTruthy(this.preloadBound);
1331
-
1332
- if (boundInsideBound(this.renderBound, this.strictBound)) {
1432
+ if (boundInsideBound(this.renderBound!, this.strictBound!)) {
1333
1433
  return CoreNodeRenderState.InViewport;
1334
1434
  }
1335
1435
 
1336
- if (boundInsideBound(this.renderBound, this.preloadBound)) {
1436
+ if (boundInsideBound(this.renderBound!, this.preloadBound!)) {
1337
1437
  return CoreNodeRenderState.InBounds;
1338
1438
  }
1339
1439
 
1340
1440
  // check if we're larger then our parent, we're definitely in the viewport
1341
- if (boundLargeThanBound(this.renderBound, this.strictBound)) {
1441
+ if (boundLargeThanBound(this.renderBound!, this.strictBound!)) {
1342
1442
  return CoreNodeRenderState.InViewport;
1343
1443
  }
1344
1444
 
1345
1445
  // check if we dont have dimensions, take our parent's render state
1346
- if (
1347
- this.parent !== null &&
1348
- (this.props.width === 0 || this.props.height === 0)
1349
- ) {
1446
+ if (this.parent !== null && (this.props.w === 0 || this.props.h === 0)) {
1350
1447
  return this.parent.renderState;
1351
1448
  }
1352
1449
 
@@ -1354,11 +1451,10 @@ export class CoreNode extends EventEmitter {
1354
1451
  }
1355
1452
 
1356
1453
  updateBoundingRect() {
1357
- const transform = this.sceneGlobalTransform || this.globalTransform;
1358
- const renderCoords = this.sceneRenderCoords || this.renderCoords;
1359
-
1360
- assertTruthy(transform);
1361
- assertTruthy(renderCoords);
1454
+ const transform = (this.sceneGlobalTransform ||
1455
+ this.globalTransform) as Matrix3d;
1456
+ const renderCoords = (this.sceneRenderCoords ||
1457
+ this.renderCoords) as RenderCoords;
1362
1458
 
1363
1459
  if (transform.tb === 0 || transform.tc === 0) {
1364
1460
  this.renderBound = createBound(
@@ -1381,8 +1477,6 @@ export class CoreNode extends EventEmitter {
1381
1477
  }
1382
1478
 
1383
1479
  createRenderBounds(): void {
1384
- assertTruthy(this.stage);
1385
-
1386
1480
  if (this.parent !== null && this.parent.strictBound !== undefined) {
1387
1481
  // we have a parent with a valid bound, copy it
1388
1482
  const parentBound = this.parent.strictBound;
@@ -1420,20 +1514,14 @@ export class CoreNode extends EventEmitter {
1420
1514
  }
1421
1515
 
1422
1516
  // clipping is enabled and we are in bounds create our own bounds
1423
- const { x, y, width, height } = this.props;
1517
+ const { x, y, w, h } = this.props;
1424
1518
 
1425
1519
  // Pick the global transform if available, otherwise use the local transform
1426
1520
  // global transform is only available if the node in an RTT chain
1427
1521
  const { tx, ty } = this.sceneGlobalTransform || this.globalTransform || {};
1428
1522
  const _x = tx ?? x;
1429
1523
  const _y = ty ?? y;
1430
- this.strictBound = createBound(
1431
- _x,
1432
- _y,
1433
- _x + width,
1434
- _y + height,
1435
- this.strictBound,
1436
- );
1524
+ this.strictBound = createBound(_x, _y, _x + w, _y + h, this.strictBound);
1437
1525
 
1438
1526
  this.preloadBound = createPreloadBounds(
1439
1527
  this.strictBound,
@@ -1456,6 +1544,17 @@ export class CoreNode extends EventEmitter {
1456
1544
  });
1457
1545
  }
1458
1546
 
1547
+ /**
1548
+ * Checks if the node is renderable based on world alpha, dimensions and out of bounds status.
1549
+ */
1550
+ checkBasicRenderability(): boolean {
1551
+ if (this.worldAlpha === 0 || this.isOutOfBounds() === true) {
1552
+ return false;
1553
+ } else {
1554
+ return true;
1555
+ }
1556
+ }
1557
+
1459
1558
  /**
1460
1559
  * Updates the `isRenderable` property based on various conditions.
1461
1560
  */
@@ -1471,12 +1570,22 @@ export class CoreNode extends EventEmitter {
1471
1570
  }
1472
1571
 
1473
1572
  if (this.texture !== null) {
1474
- needsTextureOwnership = true;
1573
+ // preemptive check for failed textures this will mark the current node as non-renderable
1574
+ // and will prevent further checks until the texture is reloaded or retry is reset on the texture
1575
+ if (this.texture.retryCount > this.texture.maxRetryCount) {
1576
+ // texture has failed to load, we cannot render
1577
+ this.updateTextureOwnership(false);
1578
+ this.setRenderable(false);
1579
+ return;
1580
+ }
1475
1581
 
1582
+ needsTextureOwnership = true;
1476
1583
  // we're only renderable if the texture state is loaded
1477
1584
  newIsRenderable = this.texture.state === 'loaded';
1478
1585
  } else if (
1479
- (this.hasShader() || this.hasColorProperties() === true) &&
1586
+ // check shader
1587
+ (this.props.shader !== null || this.hasColorProps === true) &&
1588
+ // check dimensions
1480
1589
  this.hasDimensions() === true
1481
1590
  ) {
1482
1591
  // This mean we have dimensions and a color set, so we can render a ColorTexture
@@ -1492,30 +1601,28 @@ export class CoreNode extends EventEmitter {
1492
1601
  this.setRenderable(newIsRenderable);
1493
1602
  }
1494
1603
 
1495
- /**
1496
- * Checks if the node is renderable based on world alpha, dimensions and out of bounds status.
1497
- */
1498
- checkBasicRenderability(): boolean {
1499
- if (this.worldAlpha === 0 || this.isOutOfBounds() === true) {
1500
- return false;
1501
- } else {
1502
- return true;
1503
- }
1504
- }
1505
-
1506
1604
  /**
1507
1605
  * Sets the renderable state and triggers changes if necessary.
1508
1606
  * @param isRenderable - The new renderable state
1509
1607
  */
1510
1608
  setRenderable(isRenderable: boolean) {
1609
+ const previousIsRenderable = this.isRenderable;
1511
1610
  this.isRenderable = isRenderable;
1611
+
1612
+ // Emit event if renderable status has changed
1613
+ if (previousIsRenderable !== isRenderable) {
1614
+ this.emit('renderable', {
1615
+ type: 'renderable',
1616
+ isRenderable,
1617
+ } satisfies NodeRenderablePayload);
1618
+ }
1512
1619
  }
1513
1620
 
1514
1621
  /**
1515
1622
  * Changes the renderable state of the node.
1516
1623
  */
1517
1624
  updateTextureOwnership(isRenderable: boolean) {
1518
- this.texture?.setRenderableOwner(this, isRenderable);
1625
+ this.texture?.setRenderableOwner(this._id, isRenderable);
1519
1626
  }
1520
1627
 
1521
1628
  /**
@@ -1529,38 +1636,24 @@ export class CoreNode extends EventEmitter {
1529
1636
  * Checks if the node has dimensions (width/height)
1530
1637
  */
1531
1638
  hasDimensions(): boolean {
1532
- return this.props.width !== 0 && this.props.height !== 0;
1533
- }
1534
-
1535
- /**
1536
- * Checks if the node has any color properties set.
1537
- */
1538
- hasColorProperties(): boolean {
1539
- return (
1540
- this.props.color !== 0 ||
1541
- this.props.colorTop !== 0 ||
1542
- this.props.colorBottom !== 0 ||
1543
- this.props.colorLeft !== 0 ||
1544
- this.props.colorRight !== 0 ||
1545
- this.props.colorTl !== 0 ||
1546
- this.props.colorTr !== 0 ||
1547
- this.props.colorBl !== 0 ||
1548
- this.props.colorBr !== 0
1549
- );
1550
- }
1551
-
1552
- hasShader(): boolean {
1553
- return this.props.shader !== null;
1639
+ return this.props.w !== 0 && this.props.h !== 0;
1554
1640
  }
1555
1641
 
1556
1642
  calculateRenderCoords() {
1557
- const { width, height } = this;
1558
- const { tx, ty, ta, tb, tc, td } = this.globalTransform!;
1643
+ const { w, h } = this.props;
1644
+
1645
+ const g = this.globalTransform!;
1646
+ const tx = g.tx,
1647
+ ty = g.ty,
1648
+ ta = g.ta,
1649
+ tb = g.tb,
1650
+ tc = g.tc,
1651
+ td = g.td;
1559
1652
  if (tb === 0 && tc === 0) {
1560
1653
  const minX = tx;
1561
- const maxX = tx + width * ta;
1654
+ const maxX = tx + w * ta;
1562
1655
  const minY = ty;
1563
- const maxY = ty + height * td;
1656
+ const maxY = ty + h * td;
1564
1657
  this.renderCoords = RenderCoords.translate(
1565
1658
  //top-left
1566
1659
  minX,
@@ -1582,14 +1675,14 @@ export class CoreNode extends EventEmitter {
1582
1675
  tx,
1583
1676
  ty,
1584
1677
  //top-right
1585
- tx + width * ta,
1586
- ty + width * tc,
1678
+ tx + w * ta,
1679
+ ty + w * tc,
1587
1680
  //bottom-right
1588
- tx + width * ta + height * tb,
1589
- ty + width * tc + height * td,
1681
+ tx + w * ta + h * tb,
1682
+ ty + w * tc + h * td,
1590
1683
  //bottom-left
1591
- tx + height * tb,
1592
- ty + height * td,
1684
+ tx + h * tb,
1685
+ ty + h * td,
1593
1686
  this.renderCoords,
1594
1687
  );
1595
1688
  }
@@ -1607,9 +1700,9 @@ export class CoreNode extends EventEmitter {
1607
1700
  } = this.sceneGlobalTransform;
1608
1701
  if (stb === 0 && stc === 0) {
1609
1702
  const minX = stx;
1610
- const maxX = stx + width * sta;
1703
+ const maxX = stx + w * sta;
1611
1704
  const minY = sty;
1612
- const maxY = sty + height * std;
1705
+ const maxY = sty + h * std;
1613
1706
  this.sceneRenderCoords = RenderCoords.translate(
1614
1707
  //top-left
1615
1708
  minX,
@@ -1631,14 +1724,14 @@ export class CoreNode extends EventEmitter {
1631
1724
  stx,
1632
1725
  sty,
1633
1726
  //top-right
1634
- stx + width * sta,
1635
- sty + width * stc,
1727
+ stx + w * sta,
1728
+ sty + w * stc,
1636
1729
  //bottom-right
1637
- stx + width * sta + height * stb,
1638
- sty + width * stc + height * std,
1730
+ stx + w * sta + h * stb,
1731
+ sty + w * stc + h * std,
1639
1732
  //bottom-left
1640
- stx + height * stb,
1641
- sty + height * std,
1733
+ stx + h * stb,
1734
+ sty + h * std,
1642
1735
  this.sceneRenderCoords,
1643
1736
  );
1644
1737
  }
@@ -1653,16 +1746,15 @@ export class CoreNode extends EventEmitter {
1653
1746
  * Finally, the node's parentClippingRect and clippingRect properties are updated.
1654
1747
  */
1655
1748
  calculateClippingRect(parentClippingRect: RectWithValid) {
1656
- assertTruthy(this.globalTransform);
1657
1749
  const { clippingRect, props, globalTransform: gt } = this;
1658
1750
  const { clipping } = props;
1659
- const isRotated = gt.tb !== 0 || gt.tc !== 0;
1751
+ const isRotated = gt!.tb !== 0 || gt!.tc !== 0;
1660
1752
 
1661
1753
  if (clipping === true && isRotated === false) {
1662
- clippingRect.x = gt.tx;
1663
- clippingRect.y = gt.ty;
1664
- clippingRect.width = this.width * gt.ta;
1665
- clippingRect.height = this.height * gt.td;
1754
+ clippingRect.x = gt!.tx;
1755
+ clippingRect.y = gt!.ty;
1756
+ clippingRect.w = this.props.w * gt!.ta;
1757
+ clippingRect.h = this.props.h * gt!.td;
1666
1758
  clippingRect.valid = true;
1667
1759
  } else {
1668
1760
  clippingRect.valid = false;
@@ -1678,95 +1770,183 @@ export class CoreNode extends EventEmitter {
1678
1770
  }
1679
1771
  }
1680
1772
 
1681
- calculateZIndex(): void {
1682
- const props = this.props;
1683
- const z = props.zIndex || 0;
1684
- const p = props.parent?.zIndex || 0;
1685
-
1686
- let zIndex = z;
1687
- if (props.parent?.zIndexLocked) {
1688
- zIndex = z < p ? z : p;
1689
- }
1690
- this.calcZIndex = zIndex;
1691
- }
1692
-
1693
1773
  /**
1694
1774
  * Destroy the node and cleanup all resources
1695
1775
  */
1696
1776
  destroy(): void {
1697
- this.unloadTexture();
1698
-
1699
- this.clippingRect.valid = false;
1700
- this.isRenderable = false;
1777
+ if (this.destroyed === true) {
1778
+ return;
1779
+ }
1701
1780
 
1702
- this.renderCoords = undefined;
1703
- this.renderBound = undefined;
1704
- this.strictBound = undefined;
1705
- this.preloadBound = undefined;
1706
- this.globalTransform = undefined;
1707
- this.scaleRotateTransform = undefined;
1708
- this.localTransform = undefined;
1781
+ this.removeAllListeners();
1709
1782
 
1710
- this.props.texture = null;
1711
- this.props.shader = null;
1783
+ this.destroyed = true;
1784
+ this.unloadTexture();
1785
+ this.isRenderable = false;
1786
+ if (this.hasShaderTimeFn === true) {
1787
+ this.stage.untrackTimedNode(this);
1788
+ }
1712
1789
 
1790
+ // Kill children
1713
1791
  while (this.children.length > 0) {
1714
- this.children[0]?.destroy();
1792
+ this.children[0]!.destroy();
1793
+ }
1794
+
1795
+ const parent = this.parent;
1796
+ if (parent !== null) {
1797
+ parent.removeChild(this);
1715
1798
  }
1716
1799
 
1717
- // This very action will also remove the node from the parent's children array
1718
- this.parent = null;
1800
+ this.props.parent = null;
1801
+ this.props.texture = null;
1719
1802
 
1720
- if (this.rtt) {
1803
+ if (this.rtt === true) {
1721
1804
  this.stage.renderer.removeRTTNode(this);
1722
1805
  }
1723
-
1724
- this.removeAllListeners();
1806
+ this.stage.requestRender();
1725
1807
  }
1726
1808
 
1727
1809
  renderQuads(renderer: CoreRenderer): void {
1728
- // Prevent quad rendering if parent has a render texture
1729
- // and renderer is not currently rendering to a texture
1730
- if (this.parentHasRenderTexture) {
1731
- if (!renderer.renderToTextureActive) {
1810
+ if (this.parentHasRenderTexture === true) {
1811
+ const rtt = renderer.renderToTextureActive;
1812
+ if (rtt === false || this.parentRenderTexture !== renderer.activeRttNode)
1732
1813
  return;
1814
+ }
1815
+
1816
+ const texture = this.props.texture || this.stage.defaultTexture;
1817
+
1818
+ // There is a race condition where the texture can be null
1819
+ // with RTT nodes. Adding this defensively to avoid errors.
1820
+ // Also check if we have a valid texture or default texture to render
1821
+ if (!texture || texture.state !== 'loaded') {
1822
+ return;
1823
+ }
1824
+
1825
+ renderer.addQuad(this);
1826
+ }
1827
+
1828
+ get quadBufferCollection(): BufferCollection {
1829
+ return (this.stage.renderer as WebGlRenderer).quadBufferCollection;
1830
+ }
1831
+
1832
+ get time(): number {
1833
+ if (this.hasShaderTimeFn === true) {
1834
+ return this.getTimerValue();
1835
+ }
1836
+ return 0;
1837
+ }
1838
+
1839
+ getTimerValue(): number {
1840
+ if (typeof this.shader!.time === 'function') {
1841
+ return this.shader!.time(this.stage);
1842
+ }
1843
+ return this.stage.elapsedTime;
1844
+ }
1845
+
1846
+ sortChildren() {
1847
+ const changedCount = this.zIndexSortList.length;
1848
+ if (changedCount === 0) {
1849
+ return;
1850
+ }
1851
+ const children = this.children;
1852
+ let min = Infinity;
1853
+ let max = -Infinity;
1854
+ // find min and max zIndex
1855
+ for (let i = 0; i < children.length; i++) {
1856
+ const zIndex = children[i]!.props.zIndex;
1857
+ if (zIndex < min) {
1858
+ min = zIndex;
1733
1859
  }
1734
- // Prevent quad rendering if parent render texture is not the active render texture
1735
- if (this.parentRenderTexture !== renderer.activeRttNode) {
1736
- return;
1860
+ if (zIndex > max) {
1861
+ max = zIndex;
1737
1862
  }
1738
1863
  }
1739
1864
 
1740
- assertTruthy(this.globalTransform);
1741
- assertTruthy(this.renderCoords);
1742
-
1743
- // add to list of renderables to be sorted before rendering
1744
- renderer.addQuad({
1745
- width: this.props.width,
1746
- height: this.props.height,
1747
- colorTl: this.premultipliedColorTl,
1748
- colorTr: this.premultipliedColorTr,
1749
- colorBl: this.premultipliedColorBl,
1750
- colorBr: this.premultipliedColorBr,
1751
- // if we do not have a texture, use the default texture
1752
- // this assumes any renderable node is either a distinct texture or a ColorTexture
1753
- texture: this.texture || this.stage.defaultTexture,
1754
- textureOptions: this.textureOptions,
1755
- zIndex: this.zIndex,
1756
- shader: this.props.shader as CoreShaderNode<any>,
1757
- alpha: this.worldAlpha,
1758
- clippingRect: this.clippingRect,
1759
- tx: this.globalTransform.tx,
1760
- ty: this.globalTransform.ty,
1761
- ta: this.globalTransform.ta,
1762
- tb: this.globalTransform.tb,
1763
- tc: this.globalTransform.tc,
1764
- td: this.globalTransform.td,
1765
- renderCoords: this.renderCoords,
1766
- rtt: this.rtt,
1767
- parentHasRenderTexture: this.parentHasRenderTexture,
1768
- framebufferDimensions: this.framebufferDimensions,
1769
- });
1865
+ // update min and max zIndex
1866
+ this.zIndexMin = min;
1867
+ this.zIndexMax = max;
1868
+
1869
+ // if min and max are the same, no need to sort
1870
+ if (min === max) {
1871
+ return;
1872
+ }
1873
+
1874
+ const n = children.length;
1875
+ // decide whether to use incremental sort or bucket sort
1876
+ const useIncremental = changedCount <= 2 || changedCount < n * 0.05;
1877
+
1878
+ // when changed count is less than 2 or 5% of total children, use incremental sort
1879
+ if (useIncremental === true) {
1880
+ incrementalRepositionByZIndex(this.zIndexSortList, children);
1881
+ } else {
1882
+ bucketSortByZIndex(children, min);
1883
+ }
1884
+
1885
+ this.zIndexSortList.length = 0;
1886
+ this.zIndexSortList = [];
1887
+ }
1888
+
1889
+ removeChild(node: CoreNode, targetParent: CoreNode | null = null) {
1890
+ if (targetParent === null) {
1891
+ if (this.props.rtt === true && this.parentHasRenderTexture === true) {
1892
+ node.clearRTTInheritance();
1893
+ }
1894
+ const autosizeTarget = this.autosizer || this.parentAutosizer;
1895
+ if (autosizeTarget !== null) {
1896
+ autosizeTarget.detach(node);
1897
+ }
1898
+ }
1899
+ removeChild(node, this.children);
1900
+ }
1901
+
1902
+ addChild(node: CoreNode, previousParent: CoreNode | null = null) {
1903
+ const inRttCluster =
1904
+ this.props.rtt === true || this.parentHasRenderTexture === true;
1905
+ const children = this.children;
1906
+ const min = this.zIndexMin;
1907
+ const max = this.zIndexMax;
1908
+ const zIndex = node.zIndex;
1909
+ const autosizeTarget = this.autosizer || this.parentAutosizer;
1910
+ let attachToAutosizer = autosizeTarget !== null;
1911
+
1912
+ node.parentHasRenderTexture = inRttCluster;
1913
+ if (previousParent !== null) {
1914
+ const previousParentInRttCluster =
1915
+ previousParent.props.rtt === true ||
1916
+ previousParent.parentHasRenderTexture === true;
1917
+ if (inRttCluster === false && previousParentInRttCluster === true) {
1918
+ // update child RTT status
1919
+ node.clearRTTInheritance();
1920
+ }
1921
+ const previousAutosizer = node.autosizer || node.parentAutosizer;
1922
+
1923
+ if (previousAutosizer !== null) {
1924
+ if (
1925
+ autosizeTarget === null ||
1926
+ previousAutosizer.id !== autosizeTarget.id
1927
+ ) {
1928
+ previousAutosizer.detach(node);
1929
+ }
1930
+ attachToAutosizer = false;
1931
+ }
1932
+ }
1933
+
1934
+ if (attachToAutosizer === true) {
1935
+ //if this is true, then the autosizer really exists
1936
+ autosizeTarget!.attach(node);
1937
+ }
1938
+
1939
+ if (inRttCluster === true) {
1940
+ node.markChildrenWithRTT(this);
1941
+ }
1942
+
1943
+ children.push(node);
1944
+
1945
+ if (min !== max || (zIndex !== min && zIndex !== max)) {
1946
+ this.zIndexSortList.push(node);
1947
+ this.setUpdateType(UpdateType.SortZIndexChildren);
1948
+ }
1949
+ this.setUpdateType(UpdateType.Children);
1770
1950
  }
1771
1951
 
1772
1952
  //#region Properties
@@ -1796,7 +1976,7 @@ export class CoreNode extends EventEmitter {
1796
1976
  get absX(): number {
1797
1977
  return (
1798
1978
  this.props.x +
1799
- -this.props.width * this.props.mountX +
1979
+ -this.props.w * this.props.mountX +
1800
1980
  (this.props.parent?.absX || this.props.parent?.globalTransform?.tx || 0)
1801
1981
  );
1802
1982
  }
@@ -1804,7 +1984,7 @@ export class CoreNode extends EventEmitter {
1804
1984
  get absY(): number {
1805
1985
  return (
1806
1986
  this.props.y +
1807
- -this.props.height * this.props.mountY +
1987
+ -this.props.h * this.props.mountY +
1808
1988
  (this.props.parent?.absY ?? 0)
1809
1989
  );
1810
1990
  }
@@ -1820,43 +2000,63 @@ export class CoreNode extends EventEmitter {
1820
2000
  }
1821
2001
  }
1822
2002
 
1823
- get width(): number {
1824
- return this.props.width;
2003
+ get w(): number {
2004
+ return this.props.w;
1825
2005
  }
1826
2006
 
1827
- set width(value: number) {
1828
- if (this.props.width !== value) {
1829
- this.props.width = value;
1830
- this.setUpdateType(UpdateType.Local);
2007
+ set w(value: number) {
2008
+ const props = this.props;
2009
+ if (props.w !== value) {
2010
+ props.w = value;
2011
+ let updateType = UpdateType.Local;
1831
2012
 
1832
- if (this.props.rtt) {
1833
- this.texture = this.stage.txManager.createTexture('RenderTexture', {
1834
- width: this.width,
1835
- height: this.height,
1836
- });
2013
+ if (
2014
+ props.texture !== null &&
2015
+ this.stage.calculateTextureCoord === true &&
2016
+ props.textureOptions !== null
2017
+ ) {
2018
+ this.textureCoords = this.stage.renderer.getTextureCoords!(this);
2019
+ }
1837
2020
 
1838
- this.setUpdateType(UpdateType.RenderTexture);
2021
+ if (props.rtt === true) {
2022
+ this.framebufferDimensions!.w = value;
2023
+ this.texture = this.stage.txManager.createTexture(
2024
+ 'RenderTexture',
2025
+ this.framebufferDimensions!,
2026
+ );
2027
+ updateType |= UpdateType.RenderTexture;
1839
2028
  }
2029
+ this.setUpdateType(updateType);
1840
2030
  }
1841
2031
  }
1842
2032
 
1843
- get height(): number {
1844
- return this.props.height;
2033
+ get h(): number {
2034
+ return this.props.h;
1845
2035
  }
1846
2036
 
1847
- set height(value: number) {
1848
- if (this.props.height !== value) {
1849
- this.props.height = value;
1850
- this.setUpdateType(UpdateType.Local);
2037
+ set h(value: number) {
2038
+ const props = this.props;
2039
+ if (props.h !== value) {
2040
+ props.h = value;
2041
+ let updateType = UpdateType.Local;
1851
2042
 
1852
- if (this.props.rtt) {
1853
- this.texture = this.stage.txManager.createTexture('RenderTexture', {
1854
- width: this.width,
1855
- height: this.height,
1856
- });
2043
+ if (
2044
+ props.texture !== null &&
2045
+ this.stage.calculateTextureCoord === true &&
2046
+ props.textureOptions !== null
2047
+ ) {
2048
+ this.textureCoords = this.stage.renderer.getTextureCoords!(this);
2049
+ }
1857
2050
 
1858
- this.setUpdateType(UpdateType.RenderTexture);
2051
+ if (props.rtt === true) {
2052
+ this.framebufferDimensions!.h = value;
2053
+ this.texture = this.stage.txManager.createTexture(
2054
+ 'RenderTexture',
2055
+ this.framebufferDimensions!,
2056
+ );
2057
+ updateType |= UpdateType.RenderTexture;
1859
2058
  }
2059
+ this.setUpdateType(updateType);
1860
2060
  }
1861
2061
  }
1862
2062
 
@@ -1880,7 +2080,7 @@ export class CoreNode extends EventEmitter {
1880
2080
  set scaleX(value: number) {
1881
2081
  if (this.props.scaleX !== value) {
1882
2082
  this.props.scaleX = value;
1883
- this.setUpdateType(UpdateType.ScaleRotate);
2083
+ this.setUpdateType(UpdateType.Local);
1884
2084
  }
1885
2085
  }
1886
2086
 
@@ -1891,7 +2091,7 @@ export class CoreNode extends EventEmitter {
1891
2091
  set scaleY(value: number) {
1892
2092
  if (this.props.scaleY !== value) {
1893
2093
  this.props.scaleY = value;
1894
- this.setUpdateType(UpdateType.ScaleRotate);
2094
+ this.setUpdateType(UpdateType.Local);
1895
2095
  }
1896
2096
  }
1897
2097
 
@@ -1972,7 +2172,7 @@ export class CoreNode extends EventEmitter {
1972
2172
  set rotation(value: number) {
1973
2173
  if (this.props.rotation !== value) {
1974
2174
  this.props.rotation = value;
1975
- this.setUpdateType(UpdateType.ScaleRotate);
2175
+ this.setUpdateType(UpdateType.Local);
1976
2176
  }
1977
2177
  }
1978
2178
 
@@ -1996,15 +2196,34 @@ export class CoreNode extends EventEmitter {
1996
2196
  }
1997
2197
 
1998
2198
  set autosize(value: boolean) {
2199
+ if (this.props.autosize === value) {
2200
+ return;
2201
+ }
2202
+
1999
2203
  this.props.autosize = value;
2204
+
2205
+ if (value === true && this.autosizer === null) {
2206
+ this.autosizer = new Autosizer(this);
2207
+ } else {
2208
+ this.autosizer = null;
2209
+ }
2000
2210
  }
2001
2211
 
2002
2212
  get boundsMargin(): number | [number, number, number, number] | null {
2003
- return (
2004
- this.props.boundsMargin ??
2005
- this.parent?.boundsMargin ??
2006
- this.stage.boundsMargin
2007
- );
2213
+ const props = this.props;
2214
+ if (props.boundsMargin !== null) {
2215
+ return props.boundsMargin;
2216
+ }
2217
+
2218
+ const parent = this.parent;
2219
+ if (parent !== null) {
2220
+ const margin = parent.boundsMargin;
2221
+ if (margin !== undefined) {
2222
+ return margin;
2223
+ }
2224
+ }
2225
+
2226
+ return this.stage.boundsMargin;
2008
2227
  }
2009
2228
 
2010
2229
  set boundsMargin(value: number | [number, number, number, number] | null) {
@@ -2041,11 +2260,18 @@ export class CoreNode extends EventEmitter {
2041
2260
  }
2042
2261
 
2043
2262
  set color(value: number) {
2044
- this.colorTop = value;
2045
- this.colorBottom = value;
2046
- this.colorLeft = value;
2047
- this.colorRight = value;
2048
- this.props.color = value;
2263
+ const p = this.props;
2264
+ if (p.color === value) return;
2265
+
2266
+ p.color = value;
2267
+
2268
+ const has = value > 0;
2269
+ this.hasColorProps = has;
2270
+
2271
+ if (p.colorTop !== value) this.colorTop = value;
2272
+ if (p.colorBottom !== value) this.colorBottom = value;
2273
+ if (p.colorLeft !== value) this.colorLeft = value;
2274
+ if (p.colorRight !== value) this.colorRight = value;
2049
2275
 
2050
2276
  this.setUpdateType(UpdateType.PremultipliedColors);
2051
2277
  }
@@ -2060,6 +2286,7 @@ export class CoreNode extends EventEmitter {
2060
2286
  this.colorTr = value;
2061
2287
  }
2062
2288
  this.props.colorTop = value;
2289
+ this.hasColorProps = value > 0;
2063
2290
  this.setUpdateType(UpdateType.PremultipliedColors);
2064
2291
  }
2065
2292
 
@@ -2073,6 +2300,7 @@ export class CoreNode extends EventEmitter {
2073
2300
  this.colorBr = value;
2074
2301
  }
2075
2302
  this.props.colorBottom = value;
2303
+ this.hasColorProps = value > 0;
2076
2304
  this.setUpdateType(UpdateType.PremultipliedColors);
2077
2305
  }
2078
2306
 
@@ -2086,6 +2314,7 @@ export class CoreNode extends EventEmitter {
2086
2314
  this.colorBl = value;
2087
2315
  }
2088
2316
  this.props.colorLeft = value;
2317
+ this.hasColorProps = value > 0;
2089
2318
  this.setUpdateType(UpdateType.PremultipliedColors);
2090
2319
  }
2091
2320
 
@@ -2099,6 +2328,7 @@ export class CoreNode extends EventEmitter {
2099
2328
  this.colorBr = value;
2100
2329
  }
2101
2330
  this.props.colorRight = value;
2331
+ this.hasColorProps = value > 0;
2102
2332
  this.setUpdateType(UpdateType.PremultipliedColors);
2103
2333
  }
2104
2334
 
@@ -2108,6 +2338,7 @@ export class CoreNode extends EventEmitter {
2108
2338
 
2109
2339
  set colorTl(value: number) {
2110
2340
  this.props.colorTl = value;
2341
+ this.hasColorProps = value > 0;
2111
2342
  this.setUpdateType(UpdateType.PremultipliedColors);
2112
2343
  }
2113
2344
 
@@ -2117,6 +2348,7 @@ export class CoreNode extends EventEmitter {
2117
2348
 
2118
2349
  set colorTr(value: number) {
2119
2350
  this.props.colorTr = value;
2351
+ this.hasColorProps = value > 0;
2120
2352
  this.setUpdateType(UpdateType.PremultipliedColors);
2121
2353
  }
2122
2354
 
@@ -2126,6 +2358,7 @@ export class CoreNode extends EventEmitter {
2126
2358
 
2127
2359
  set colorBl(value: number) {
2128
2360
  this.props.colorBl = value;
2361
+ this.hasColorProps = value > 0;
2129
2362
  this.setUpdateType(UpdateType.PremultipliedColors);
2130
2363
  }
2131
2364
 
@@ -2135,32 +2368,43 @@ export class CoreNode extends EventEmitter {
2135
2368
 
2136
2369
  set colorBr(value: number) {
2137
2370
  this.props.colorBr = value;
2371
+ this.hasColorProps = value > 0;
2138
2372
  this.setUpdateType(UpdateType.PremultipliedColors);
2139
2373
  }
2140
2374
 
2141
- // we're only interested in parent zIndex to test
2142
- // if we should use node zIndex is higher then parent zIndex
2143
- get zIndexLocked(): number {
2144
- return this.props.zIndexLocked || 0;
2145
- }
2146
-
2147
- set zIndexLocked(value: number) {
2148
- this.props.zIndexLocked = value;
2149
- this.setUpdateType(UpdateType.CalculatedZIndex | UpdateType.Children);
2150
- for (let i = 0, length = this.children.length; i < length; i++) {
2151
- this.children[i]!.setUpdateType(UpdateType.CalculatedZIndex);
2152
- }
2153
- }
2154
-
2155
2375
  get zIndex(): number {
2156
2376
  return this.props.zIndex;
2157
2377
  }
2158
2378
 
2159
2379
  set zIndex(value: number) {
2160
- this.props.zIndex = value;
2161
- this.setUpdateType(UpdateType.CalculatedZIndex | UpdateType.Children);
2162
- for (let i = 0, length = this.children.length; i < length; i++) {
2163
- this.children[i]!.setUpdateType(UpdateType.CalculatedZIndex);
2380
+ let sanitizedValue = value;
2381
+ if (isNaN(sanitizedValue) || Number.isFinite(sanitizedValue) === false) {
2382
+ console.warn(
2383
+ `zIndex was set to an invalid value: ${value}, defaulting to 0`,
2384
+ );
2385
+ sanitizedValue = 0;
2386
+ }
2387
+
2388
+ //Clamp to safe integer range
2389
+ if (sanitizedValue > Number.MAX_SAFE_INTEGER) {
2390
+ sanitizedValue = 1000;
2391
+ } else if (sanitizedValue < Number.MIN_SAFE_INTEGER) {
2392
+ sanitizedValue = -1000;
2393
+ }
2394
+
2395
+ if (this.props.zIndex === sanitizedValue) {
2396
+ return;
2397
+ }
2398
+ this.previousZIndex = this.props.zIndex;
2399
+ this.props.zIndex = sanitizedValue;
2400
+ const parent = this.parent;
2401
+ if (parent !== null) {
2402
+ const min = parent.zIndexMin;
2403
+ const max = parent.zIndexMax;
2404
+ if (min !== max || sanitizedValue < min || sanitizedValue > max) {
2405
+ parent.zIndexSortList.push(this);
2406
+ parent.setUpdateType(UpdateType.SortZIndexChildren);
2407
+ }
2164
2408
  }
2165
2409
  }
2166
2410
 
@@ -2175,48 +2419,13 @@ export class CoreNode extends EventEmitter {
2175
2419
  }
2176
2420
  this.props.parent = newParent;
2177
2421
  if (oldParent) {
2178
- const index = oldParent.children.indexOf(this);
2179
- assertTruthy(
2180
- index !== -1,
2181
- "CoreNode.parent: Node not found in old parent's children!",
2182
- );
2183
- oldParent.children.splice(index, 1);
2184
- oldParent.setUpdateType(
2185
- UpdateType.Children | UpdateType.ZIndexSortedChildren,
2186
- );
2187
- }
2188
- if (newParent) {
2189
- newParent.children.push(this);
2190
- // Since this node has a new parent, to be safe, have it do a full update.
2191
- this.setUpdateType(UpdateType.All);
2192
- // Tell parent that it's children need to be updated and sorted.
2193
- newParent.setUpdateType(
2194
- UpdateType.Children | UpdateType.ZIndexSortedChildren,
2195
- );
2196
-
2197
- // If the new parent has an RTT enabled, apply RTT inheritance
2198
- if (newParent.rtt || newParent.parentHasRenderTexture) {
2199
- this.applyRTTInheritance(newParent);
2200
- }
2422
+ oldParent.removeChild(this, newParent);
2201
2423
  }
2202
- this.updateScaleRotateTransform();
2203
-
2204
- // fetch render bounds from parent
2205
- this.setUpdateType(UpdateType.RenderBounds | UpdateType.Children);
2206
- }
2207
-
2208
- get preventCleanup(): boolean {
2209
- return this.props.textureOptions.preventCleanup || false;
2210
- }
2211
-
2212
- set preventCleanup(value: boolean) {
2213
- if (isProductionEnvironment() === false) {
2214
- console.warn(
2215
- 'CoreNode.preventCleanup: Is deprecated and will be removed in upcoming release, please use textureOptions.preventCleanup instead',
2216
- );
2424
+ if (newParent !== null) {
2425
+ newParent.addChild(this, oldParent);
2217
2426
  }
2218
-
2219
- this.props.textureOptions.preventCleanup = value;
2427
+ //since this node has a new parent, recalc global and render bounds
2428
+ this.setUpdateType(UpdateType.Global | UpdateType.RenderBounds);
2220
2429
  }
2221
2430
 
2222
2431
  get rtt(): boolean {
@@ -2243,11 +2452,14 @@ export class CoreNode extends EventEmitter {
2243
2452
  }
2244
2453
  }
2245
2454
  private initRenderTexture() {
2246
- this.texture = this.stage.txManager.createTexture('RenderTexture', {
2247
- width: this.width,
2248
- height: this.height,
2249
- });
2250
-
2455
+ this.framebufferDimensions = {
2456
+ w: this.props.w,
2457
+ h: this.props.h,
2458
+ };
2459
+ this.texture = this.stage.txManager.createTexture(
2460
+ 'RenderTexture',
2461
+ this.framebufferDimensions,
2462
+ );
2251
2463
  this.stage.renderer.renderToTexture(this);
2252
2464
  }
2253
2465
 
@@ -2257,6 +2469,7 @@ export class CoreNode extends EventEmitter {
2257
2469
 
2258
2470
  this.hasRTTupdates = false;
2259
2471
  this.texture = null;
2472
+ this.framebufferDimensions = null;
2260
2473
  }
2261
2474
 
2262
2475
  private markChildrenWithRTT(node: CoreNode | null = null) {
@@ -2313,10 +2526,17 @@ export class CoreNode extends EventEmitter {
2313
2526
  }
2314
2527
  if (shader.shaderKey !== 'default') {
2315
2528
  this.hasShaderUpdater = shader.update !== undefined;
2529
+ this.hasShaderTimeFn = shader.time !== undefined;
2316
2530
  shader.attachNode(this);
2317
2531
  }
2532
+
2533
+ if (this.hasShaderTimeFn === true) {
2534
+ this.stage.trackTimedNode(this);
2535
+ } else {
2536
+ this.stage.untrackTimedNode(this);
2537
+ }
2318
2538
  this.props.shader = shader;
2319
- this.setUpdateType(UpdateType.IsRenderable);
2539
+ this.setUpdateType(UpdateType.IsRenderable | UpdateType.RecalcUniforms);
2320
2540
  }
2321
2541
 
2322
2542
  get src(): string | null {
@@ -2337,8 +2557,8 @@ export class CoreNode extends EventEmitter {
2337
2557
 
2338
2558
  this.texture = this.stage.txManager.createTexture('ImageTexture', {
2339
2559
  src: imageUrl,
2340
- width: this.props.width,
2341
- height: this.props.height,
2560
+ w: this.props.w,
2561
+ h: this.props.h,
2342
2562
  type: this.props.imageType,
2343
2563
  sx: this.props.srcX,
2344
2564
  sy: this.props.srcY,
@@ -2392,16 +2612,14 @@ export class CoreNode extends EventEmitter {
2392
2612
  }
2393
2613
 
2394
2614
  /**
2395
- * Returns the framebuffer dimensions of the node.
2396
- * If the node has a render texture, the dimensions are the same as the node's dimensions.
2397
- * If the node does not have a render texture, the dimensions are inherited from the parent.
2398
- * If the node parent has a render texture and the node is a render texture, the nodes dimensions are used.
2615
+ * Returns the framebuffer dimensions of the RTT parent
2399
2616
  */
2400
- get framebufferDimensions(): Dimensions {
2401
- if (this.parentHasRenderTexture && !this.rtt && this.parent) {
2402
- return this.parent.framebufferDimensions;
2617
+ get parentFramebufferDimensions(): Dimensions | null {
2618
+ if (this.rttParent !== null) {
2619
+ return this.rttParent.framebufferDimensions;
2403
2620
  }
2404
- return { width: this.width, height: this.height };
2621
+ this.rttParent = this.findParentRTTNode();
2622
+ return this.rttParent ? this.rttParent.framebufferDimensions : null;
2405
2623
  }
2406
2624
 
2407
2625
  /**
@@ -2429,13 +2647,19 @@ export class CoreNode extends EventEmitter {
2429
2647
 
2430
2648
  const oldTexture = this.props.texture;
2431
2649
  if (oldTexture) {
2432
- oldTexture.setRenderableOwner(this, false);
2433
2650
  this.unloadTexture();
2651
+ if (this.autosizer !== null && value === null) {
2652
+ this.autosizer.setMode(AutosizeMode.Children); // Set to children size mode
2653
+ }
2434
2654
  }
2435
2655
 
2656
+ this.textureCoords = undefined;
2436
2657
  this.props.texture = value;
2437
2658
  if (value !== null) {
2438
- value.setRenderableOwner(this, this.isRenderable);
2659
+ if (this.autosizer !== null) {
2660
+ this.autosizer.setMode(AutosizeMode.Texture); // Set to texture size mode
2661
+ }
2662
+ value.setRenderableOwner(this._id, this.isRenderable);
2439
2663
  this.loadTexture();
2440
2664
  }
2441
2665
 
@@ -2444,24 +2668,30 @@ export class CoreNode extends EventEmitter {
2444
2668
 
2445
2669
  set textureOptions(value: TextureOptions) {
2446
2670
  this.props.textureOptions = value;
2671
+ if (this.stage.calculateTextureCoord === true && value !== null) {
2672
+ this.textureCoords = this.stage.renderer.getTextureCoords!(this);
2673
+ }
2447
2674
  }
2448
2675
 
2449
2676
  get textureOptions(): TextureOptions {
2450
2677
  return this.props.textureOptions;
2451
2678
  }
2452
2679
 
2453
- get strictBounds(): boolean {
2454
- return this.props.strictBounds;
2680
+ set interactive(value: boolean | undefined) {
2681
+ this.props.interactive = value;
2682
+ // Update Stage's interactive Set
2683
+ if (value === true) {
2684
+ this.stage.interactiveNodes.add(this);
2685
+ }
2455
2686
  }
2456
2687
 
2457
- set strictBounds(v) {
2458
- if (v === this.props.strictBounds) {
2459
- return;
2460
- }
2688
+ get interactive(): boolean | undefined {
2689
+ return this.props.interactive;
2690
+ }
2461
2691
 
2462
- this.props.strictBounds = v;
2463
- this.setUpdateType(UpdateType.RenderBounds | UpdateType.Children);
2464
- this.childUpdateType |= UpdateType.RenderBounds | UpdateType.Children;
2692
+ setRTTUpdates(type: number) {
2693
+ this.hasRTTupdates = true;
2694
+ this.parent?.setRTTUpdates(type);
2465
2695
  }
2466
2696
 
2467
2697
  animate(
@@ -2482,5 +2712,71 @@ export class CoreNode extends EventEmitter {
2482
2712
  // no-op
2483
2713
  }
2484
2714
 
2715
+ /**
2716
+ * Add a texture to the current RenderOp.
2717
+ *
2718
+ * @param texture
2719
+ * @returns Assigned Texture Index of the texture in the render op
2720
+ */
2721
+ addTexture(texture: WebGlCtxTexture): number {
2722
+ const textures = this.renderOpTextures;
2723
+ const length = textures.length;
2724
+
2725
+ for (let i = 0; i < length; i++) {
2726
+ if (textures[i] === texture) {
2727
+ return i;
2728
+ }
2729
+ }
2730
+
2731
+ if (length >= 1) {
2732
+ return 0xffffffff;
2733
+ }
2734
+
2735
+ textures.push(texture);
2736
+ return length;
2737
+ }
2738
+
2739
+ draw(renderer: WebGlRenderer) {
2740
+ const { glw, options, stage } = renderer;
2741
+ const shader = this.props.shader as any;
2742
+
2743
+ stage.shManager.useShader(shader.program);
2744
+ shader.program.bindRenderOp(this);
2745
+
2746
+ // Clipping
2747
+ if (this.clippingRect.valid === true) {
2748
+ const pixelRatio = this.parentHasRenderTexture ? 1 : stage.pixelRatio;
2749
+
2750
+ const clipX = Math.round(this.clippingRect.x * pixelRatio);
2751
+ const clipWidth = Math.round(this.clippingRect.w * pixelRatio);
2752
+ const clipHeight = Math.round(this.clippingRect.h * pixelRatio);
2753
+ let clipY = Math.round(
2754
+ options.canvas.height - clipHeight - this.clippingRect.y * pixelRatio,
2755
+ );
2756
+ // if parent has render texture, we need to adjust the scissor rect
2757
+ // to be relative to the parent's framebuffer
2758
+ if (this.parentHasRenderTexture) {
2759
+ const parentFramebufferDimensions = this.parentFramebufferDimensions;
2760
+ clipY =
2761
+ parentFramebufferDimensions !== null
2762
+ ? parentFramebufferDimensions.h - this.props.h
2763
+ : 0;
2764
+ }
2765
+
2766
+ glw.setScissorTest(true);
2767
+ glw.scissor(clipX, clipY, clipWidth, clipHeight);
2768
+ } else {
2769
+ glw.setScissorTest(false);
2770
+ }
2771
+
2772
+ const quadIdx = (this.renderOpBufferIdx / 32) * 6 * 2;
2773
+ glw.drawElements(
2774
+ glw.TRIANGLES,
2775
+ 6 * this.numQuads,
2776
+ glw.UNSIGNED_SHORT,
2777
+ quadIdx,
2778
+ );
2779
+ }
2780
+
2485
2781
  //#endregion Properties
2486
2782
  }