@solidtv/renderer 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (424) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +7 -0
  3. package/README.md +137 -0
  4. package/dist/exports/canvas-shaders.d.ts +10 -0
  5. package/dist/exports/canvas-shaders.js +11 -0
  6. package/dist/exports/canvas-shaders.js.map +1 -0
  7. package/dist/exports/canvas.d.ts +26 -0
  8. package/dist/exports/canvas.js +27 -0
  9. package/dist/exports/canvas.js.map +1 -0
  10. package/dist/exports/index.d.ts +50 -0
  11. package/dist/exports/index.js +40 -0
  12. package/dist/exports/index.js.map +1 -0
  13. package/dist/exports/inspector.d.ts +4 -0
  14. package/dist/exports/inspector.js +5 -0
  15. package/dist/exports/inspector.js.map +1 -0
  16. package/dist/exports/utils.d.ts +27 -0
  17. package/dist/exports/utils.js +28 -0
  18. package/dist/exports/utils.js.map +1 -0
  19. package/dist/exports/webgl-shaders.d.ts +11 -0
  20. package/dist/exports/webgl-shaders.js +12 -0
  21. package/dist/exports/webgl-shaders.js.map +1 -0
  22. package/dist/exports/webgl.d.ts +28 -0
  23. package/dist/exports/webgl.js +29 -0
  24. package/dist/exports/webgl.js.map +1 -0
  25. package/dist/src/common/CommonTypes.d.ts +110 -0
  26. package/dist/src/common/CommonTypes.js +2 -0
  27. package/dist/src/common/CommonTypes.js.map +1 -0
  28. package/dist/src/common/EventEmitter.d.ts +12 -0
  29. package/dist/src/common/EventEmitter.js +48 -0
  30. package/dist/src/common/EventEmitter.js.map +1 -0
  31. package/dist/src/common/IAnimationController.d.ts +58 -0
  32. package/dist/src/common/IAnimationController.js +2 -0
  33. package/dist/src/common/IAnimationController.js.map +1 -0
  34. package/dist/src/common/IEventEmitter.d.ts +8 -0
  35. package/dist/src/common/IEventEmitter.js +2 -0
  36. package/dist/src/common/IEventEmitter.js.map +1 -0
  37. package/dist/src/core/Autosizer.d.ts +35 -0
  38. package/dist/src/core/Autosizer.js +178 -0
  39. package/dist/src/core/Autosizer.js.map +1 -0
  40. package/dist/src/core/CoreNode.d.ts +908 -0
  41. package/dist/src/core/CoreNode.js +1837 -0
  42. package/dist/src/core/CoreNode.js.map +1 -0
  43. package/dist/src/core/CoreShaderManager.d.ts +38 -0
  44. package/dist/src/core/CoreShaderManager.js +123 -0
  45. package/dist/src/core/CoreShaderManager.js.map +1 -0
  46. package/dist/src/core/CoreTextNode.d.ts +91 -0
  47. package/dist/src/core/CoreTextNode.js +440 -0
  48. package/dist/src/core/CoreTextNode.js.map +1 -0
  49. package/dist/src/core/CoreTextureManager.d.ts +264 -0
  50. package/dist/src/core/CoreTextureManager.js +318 -0
  51. package/dist/src/core/CoreTextureManager.js.map +1 -0
  52. package/dist/src/core/Stage.d.ts +238 -0
  53. package/dist/src/core/Stage.js +804 -0
  54. package/dist/src/core/Stage.js.map +1 -0
  55. package/dist/src/core/TextureError.d.ts +11 -0
  56. package/dist/src/core/TextureError.js +37 -0
  57. package/dist/src/core/TextureError.js.map +1 -0
  58. package/dist/src/core/TextureMemoryManager.d.ts +150 -0
  59. package/dist/src/core/TextureMemoryManager.js +239 -0
  60. package/dist/src/core/TextureMemoryManager.js.map +1 -0
  61. package/dist/src/core/animations/AnimationManager.d.ts +33 -0
  62. package/dist/src/core/animations/AnimationManager.js +137 -0
  63. package/dist/src/core/animations/AnimationManager.js.map +1 -0
  64. package/dist/src/core/animations/CoreAnimation.d.ts +12 -0
  65. package/dist/src/core/animations/CoreAnimation.js +107 -0
  66. package/dist/src/core/animations/CoreAnimation.js.map +1 -0
  67. package/dist/src/core/lib/ContextSpy.d.ts +12 -0
  68. package/dist/src/core/lib/ContextSpy.js +20 -0
  69. package/dist/src/core/lib/ContextSpy.js.map +1 -0
  70. package/dist/src/core/lib/ImageWorker.d.ts +16 -0
  71. package/dist/src/core/lib/ImageWorker.js +202 -0
  72. package/dist/src/core/lib/ImageWorker.js.map +1 -0
  73. package/dist/src/core/lib/Matrix3d.d.ts +74 -0
  74. package/dist/src/core/lib/Matrix3d.js +218 -0
  75. package/dist/src/core/lib/Matrix3d.js.map +1 -0
  76. package/dist/src/core/lib/RenderCoords.d.ts +12 -0
  77. package/dist/src/core/lib/RenderCoords.js +35 -0
  78. package/dist/src/core/lib/RenderCoords.js.map +1 -0
  79. package/dist/src/core/lib/WebGlContextWrapper.d.ts +782 -0
  80. package/dist/src/core/lib/WebGlContextWrapper.js +1143 -0
  81. package/dist/src/core/lib/WebGlContextWrapper.js.map +1 -0
  82. package/dist/src/core/lib/collectionUtils.d.ts +5 -0
  83. package/dist/src/core/lib/collectionUtils.js +82 -0
  84. package/dist/src/core/lib/collectionUtils.js.map +1 -0
  85. package/dist/src/core/lib/colorCache.d.ts +1 -0
  86. package/dist/src/core/lib/colorCache.js +19 -0
  87. package/dist/src/core/lib/colorCache.js.map +1 -0
  88. package/dist/src/core/lib/colorParser.d.ts +21 -0
  89. package/dist/src/core/lib/colorParser.js +54 -0
  90. package/dist/src/core/lib/colorParser.js.map +1 -0
  91. package/dist/src/core/lib/textureCompression.d.ts +28 -0
  92. package/dist/src/core/lib/textureCompression.js +363 -0
  93. package/dist/src/core/lib/textureCompression.js.map +1 -0
  94. package/dist/src/core/lib/textureSvg.d.ts +16 -0
  95. package/dist/src/core/lib/textureSvg.js +45 -0
  96. package/dist/src/core/lib/textureSvg.js.map +1 -0
  97. package/dist/src/core/lib/utils.d.ts +66 -0
  98. package/dist/src/core/lib/utils.js +268 -0
  99. package/dist/src/core/lib/utils.js.map +1 -0
  100. package/dist/src/core/lib/validateImageBitmap.d.ts +7 -0
  101. package/dist/src/core/lib/validateImageBitmap.js +68 -0
  102. package/dist/src/core/lib/validateImageBitmap.js.map +1 -0
  103. package/dist/src/core/platforms/Platform.d.ts +42 -0
  104. package/dist/src/core/platforms/Platform.js +4 -0
  105. package/dist/src/core/platforms/Platform.js.map +1 -0
  106. package/dist/src/core/platforms/web/WebPlatform.d.ts +10 -0
  107. package/dist/src/core/platforms/web/WebPlatform.js +90 -0
  108. package/dist/src/core/platforms/web/WebPlatform.js.map +1 -0
  109. package/dist/src/core/renderers/CoreContextTexture.d.ts +13 -0
  110. package/dist/src/core/renderers/CoreContextTexture.js +16 -0
  111. package/dist/src/core/renderers/CoreContextTexture.js.map +1 -0
  112. package/dist/src/core/renderers/CoreRenderOp.d.ts +3 -0
  113. package/dist/src/core/renderers/CoreRenderOp.js +3 -0
  114. package/dist/src/core/renderers/CoreRenderOp.js.map +1 -0
  115. package/dist/src/core/renderers/CoreRenderer.d.ts +81 -0
  116. package/dist/src/core/renderers/CoreRenderer.js +14 -0
  117. package/dist/src/core/renderers/CoreRenderer.js.map +1 -0
  118. package/dist/src/core/renderers/CoreShaderNode.d.ts +69 -0
  119. package/dist/src/core/renderers/CoreShaderNode.js +130 -0
  120. package/dist/src/core/renderers/CoreShaderNode.js.map +1 -0
  121. package/dist/src/core/renderers/CoreShaderProgram.d.ts +4 -0
  122. package/dist/src/core/renderers/CoreShaderProgram.js +2 -0
  123. package/dist/src/core/renderers/CoreShaderProgram.js.map +1 -0
  124. package/dist/src/core/renderers/canvas/CanvasRenderer.d.ts +36 -0
  125. package/dist/src/core/renderers/canvas/CanvasRenderer.js +221 -0
  126. package/dist/src/core/renderers/canvas/CanvasRenderer.js.map +1 -0
  127. package/dist/src/core/renderers/canvas/CanvasShaderNode.d.ts +21 -0
  128. package/dist/src/core/renderers/canvas/CanvasShaderNode.js +42 -0
  129. package/dist/src/core/renderers/canvas/CanvasShaderNode.js.map +1 -0
  130. package/dist/src/core/renderers/canvas/CanvasTexture.d.ts +17 -0
  131. package/dist/src/core/renderers/canvas/CanvasTexture.js +110 -0
  132. package/dist/src/core/renderers/canvas/CanvasTexture.js.map +1 -0
  133. package/dist/src/core/renderers/webgl/SdfRenderOp.d.ts +41 -0
  134. package/dist/src/core/renderers/webgl/SdfRenderOp.js +88 -0
  135. package/dist/src/core/renderers/webgl/SdfRenderOp.js.map +1 -0
  136. package/dist/src/core/renderers/webgl/WebGlCtxRenderTexture.d.ts +14 -0
  137. package/dist/src/core/renderers/webgl/WebGlCtxRenderTexture.js +45 -0
  138. package/dist/src/core/renderers/webgl/WebGlCtxRenderTexture.js.map +1 -0
  139. package/dist/src/core/renderers/webgl/WebGlCtxSubTexture.d.ts +22 -0
  140. package/dist/src/core/renderers/webgl/WebGlCtxSubTexture.js +49 -0
  141. package/dist/src/core/renderers/webgl/WebGlCtxSubTexture.js.map +1 -0
  142. package/dist/src/core/renderers/webgl/WebGlCtxTexture.d.ts +67 -0
  143. package/dist/src/core/renderers/webgl/WebGlCtxTexture.js +259 -0
  144. package/dist/src/core/renderers/webgl/WebGlCtxTexture.js.map +1 -0
  145. package/dist/src/core/renderers/webgl/WebGlRenderer.d.ts +221 -0
  146. package/dist/src/core/renderers/webgl/WebGlRenderer.js +1015 -0
  147. package/dist/src/core/renderers/webgl/WebGlRenderer.js.map +1 -0
  148. package/dist/src/core/renderers/webgl/WebGlShaderNode.d.ts +213 -0
  149. package/dist/src/core/renderers/webgl/WebGlShaderNode.js +331 -0
  150. package/dist/src/core/renderers/webgl/WebGlShaderNode.js.map +1 -0
  151. package/dist/src/core/renderers/webgl/WebGlShaderProgram.d.ts +37 -0
  152. package/dist/src/core/renderers/webgl/WebGlShaderProgram.js +240 -0
  153. package/dist/src/core/renderers/webgl/WebGlShaderProgram.js.map +1 -0
  154. package/dist/src/core/renderers/webgl/internal/BufferCollection.d.ts +28 -0
  155. package/dist/src/core/renderers/webgl/internal/BufferCollection.js +39 -0
  156. package/dist/src/core/renderers/webgl/internal/BufferCollection.js.map +1 -0
  157. package/dist/src/core/renderers/webgl/internal/RendererUtils.d.ts +55 -0
  158. package/dist/src/core/renderers/webgl/internal/RendererUtils.js +88 -0
  159. package/dist/src/core/renderers/webgl/internal/RendererUtils.js.map +1 -0
  160. package/dist/src/core/renderers/webgl/internal/ShaderUtils.d.ts +74 -0
  161. package/dist/src/core/renderers/webgl/internal/ShaderUtils.js +83 -0
  162. package/dist/src/core/renderers/webgl/internal/ShaderUtils.js.map +1 -0
  163. package/dist/src/core/renderers/webgl/internal/WebGlUtils.d.ts +10 -0
  164. package/dist/src/core/renderers/webgl/internal/WebGlUtils.js +13 -0
  165. package/dist/src/core/renderers/webgl/internal/WebGlUtils.js.map +1 -0
  166. package/dist/src/core/shaders/canvas/Border.d.ts +15 -0
  167. package/dist/src/core/shaders/canvas/Border.js +83 -0
  168. package/dist/src/core/shaders/canvas/Border.js.map +1 -0
  169. package/dist/src/core/shaders/canvas/HolePunch.d.ts +7 -0
  170. package/dist/src/core/shaders/canvas/HolePunch.js +22 -0
  171. package/dist/src/core/shaders/canvas/HolePunch.js.map +1 -0
  172. package/dist/src/core/shaders/canvas/LinearGradient.d.ts +10 -0
  173. package/dist/src/core/shaders/canvas/LinearGradient.js +32 -0
  174. package/dist/src/core/shaders/canvas/LinearGradient.js.map +1 -0
  175. package/dist/src/core/shaders/canvas/RadialGradient.d.ts +11 -0
  176. package/dist/src/core/shaders/canvas/RadialGradient.js +54 -0
  177. package/dist/src/core/shaders/canvas/RadialGradient.js.map +1 -0
  178. package/dist/src/core/shaders/canvas/Rounded.d.ts +7 -0
  179. package/dist/src/core/shaders/canvas/Rounded.js +17 -0
  180. package/dist/src/core/shaders/canvas/Rounded.js.map +1 -0
  181. package/dist/src/core/shaders/canvas/RoundedWithBorder.d.ts +10 -0
  182. package/dist/src/core/shaders/canvas/RoundedWithBorder.js +57 -0
  183. package/dist/src/core/shaders/canvas/RoundedWithBorder.js.map +1 -0
  184. package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.d.ts +7 -0
  185. package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.js +61 -0
  186. package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.js.map +1 -0
  187. package/dist/src/core/shaders/canvas/RoundedWithShadow.d.ts +7 -0
  188. package/dist/src/core/shaders/canvas/RoundedWithShadow.js +26 -0
  189. package/dist/src/core/shaders/canvas/RoundedWithShadow.js.map +1 -0
  190. package/dist/src/core/shaders/canvas/Shadow.d.ts +8 -0
  191. package/dist/src/core/shaders/canvas/Shadow.js +15 -0
  192. package/dist/src/core/shaders/canvas/Shadow.js.map +1 -0
  193. package/dist/src/core/shaders/canvas/utils/render.d.ts +5 -0
  194. package/dist/src/core/shaders/canvas/utils/render.js +81 -0
  195. package/dist/src/core/shaders/canvas/utils/render.js.map +1 -0
  196. package/dist/src/core/shaders/templates/BorderTemplate.d.ts +47 -0
  197. package/dist/src/core/shaders/templates/BorderTemplate.js +77 -0
  198. package/dist/src/core/shaders/templates/BorderTemplate.js.map +1 -0
  199. package/dist/src/core/shaders/templates/HolePunchTemplate.d.ts +46 -0
  200. package/dist/src/core/shaders/templates/HolePunchTemplate.js +19 -0
  201. package/dist/src/core/shaders/templates/HolePunchTemplate.js.map +1 -0
  202. package/dist/src/core/shaders/templates/LinearGradientTemplate.d.ts +23 -0
  203. package/dist/src/core/shaders/templates/LinearGradientTemplate.js +31 -0
  204. package/dist/src/core/shaders/templates/LinearGradientTemplate.js.map +1 -0
  205. package/dist/src/core/shaders/templates/RadialGradientTemplate.d.ts +33 -0
  206. package/dist/src/core/shaders/templates/RadialGradientTemplate.js +33 -0
  207. package/dist/src/core/shaders/templates/RadialGradientTemplate.js.map +1 -0
  208. package/dist/src/core/shaders/templates/RoundedTemplate.d.ts +29 -0
  209. package/dist/src/core/shaders/templates/RoundedTemplate.js +51 -0
  210. package/dist/src/core/shaders/templates/RoundedTemplate.js.map +1 -0
  211. package/dist/src/core/shaders/templates/RoundedWithBorderAndShadowTemplate.d.ts +7 -0
  212. package/dist/src/core/shaders/templates/RoundedWithBorderAndShadowTemplate.js +8 -0
  213. package/dist/src/core/shaders/templates/RoundedWithBorderAndShadowTemplate.js.map +1 -0
  214. package/dist/src/core/shaders/templates/RoundedWithBorderTemplate.d.ts +8 -0
  215. package/dist/src/core/shaders/templates/RoundedWithBorderTemplate.js +9 -0
  216. package/dist/src/core/shaders/templates/RoundedWithBorderTemplate.js.map +1 -0
  217. package/dist/src/core/shaders/templates/RoundedWithShadowTemplate.d.ts +6 -0
  218. package/dist/src/core/shaders/templates/RoundedWithShadowTemplate.js +7 -0
  219. package/dist/src/core/shaders/templates/RoundedWithShadowTemplate.js.map +1 -0
  220. package/dist/src/core/shaders/templates/ShadowTemplate.d.ts +34 -0
  221. package/dist/src/core/shaders/templates/ShadowTemplate.js +50 -0
  222. package/dist/src/core/shaders/templates/ShadowTemplate.js.map +1 -0
  223. package/dist/src/core/shaders/utils.d.ts +5 -0
  224. package/dist/src/core/shaders/utils.js +25 -0
  225. package/dist/src/core/shaders/utils.js.map +1 -0
  226. package/dist/src/core/shaders/webgl/Border.d.ts +3 -0
  227. package/dist/src/core/shaders/webgl/Border.js +153 -0
  228. package/dist/src/core/shaders/webgl/Border.js.map +1 -0
  229. package/dist/src/core/shaders/webgl/Default.d.ts +2 -0
  230. package/dist/src/core/shaders/webgl/Default.js +51 -0
  231. package/dist/src/core/shaders/webgl/Default.js.map +1 -0
  232. package/dist/src/core/shaders/webgl/HolePunch.d.ts +3 -0
  233. package/dist/src/core/shaders/webgl/HolePunch.js +49 -0
  234. package/dist/src/core/shaders/webgl/HolePunch.js.map +1 -0
  235. package/dist/src/core/shaders/webgl/LinearGradient.d.ts +3 -0
  236. package/dist/src/core/shaders/webgl/LinearGradient.js +114 -0
  237. package/dist/src/core/shaders/webgl/LinearGradient.js.map +1 -0
  238. package/dist/src/core/shaders/webgl/RadialGradient.d.ts +3 -0
  239. package/dist/src/core/shaders/webgl/RadialGradient.js +81 -0
  240. package/dist/src/core/shaders/webgl/RadialGradient.js.map +1 -0
  241. package/dist/src/core/shaders/webgl/Rounded.d.ts +7 -0
  242. package/dist/src/core/shaders/webgl/Rounded.js +88 -0
  243. package/dist/src/core/shaders/webgl/Rounded.js.map +1 -0
  244. package/dist/src/core/shaders/webgl/RoundedWithBorder.d.ts +3 -0
  245. package/dist/src/core/shaders/webgl/RoundedWithBorder.js +202 -0
  246. package/dist/src/core/shaders/webgl/RoundedWithBorder.js.map +1 -0
  247. package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.d.ts +3 -0
  248. package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js +223 -0
  249. package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js.map +1 -0
  250. package/dist/src/core/shaders/webgl/RoundedWithShadow.d.ts +3 -0
  251. package/dist/src/core/shaders/webgl/RoundedWithShadow.js +123 -0
  252. package/dist/src/core/shaders/webgl/RoundedWithShadow.js.map +1 -0
  253. package/dist/src/core/shaders/webgl/SdfShader.d.ts +13 -0
  254. package/dist/src/core/shaders/webgl/SdfShader.js +72 -0
  255. package/dist/src/core/shaders/webgl/SdfShader.js.map +1 -0
  256. package/dist/src/core/shaders/webgl/Shadow.d.ts +3 -0
  257. package/dist/src/core/shaders/webgl/Shadow.js +115 -0
  258. package/dist/src/core/shaders/webgl/Shadow.js.map +1 -0
  259. package/dist/src/core/text-rendering/CanvasFontHandler.d.ts +59 -0
  260. package/dist/src/core/text-rendering/CanvasFontHandler.js +206 -0
  261. package/dist/src/core/text-rendering/CanvasFontHandler.js.map +1 -0
  262. package/dist/src/core/text-rendering/CanvasTextRenderer.d.ts +17 -0
  263. package/dist/src/core/text-rendering/CanvasTextRenderer.js +139 -0
  264. package/dist/src/core/text-rendering/CanvasTextRenderer.js.map +1 -0
  265. package/dist/src/core/text-rendering/SdfFontHandler.d.ts +167 -0
  266. package/dist/src/core/text-rendering/SdfFontHandler.js +371 -0
  267. package/dist/src/core/text-rendering/SdfFontHandler.js.map +1 -0
  268. package/dist/src/core/text-rendering/SdfTextRenderer.d.ts +17 -0
  269. package/dist/src/core/text-rendering/SdfTextRenderer.js +249 -0
  270. package/dist/src/core/text-rendering/SdfTextRenderer.js.map +1 -0
  271. package/dist/src/core/text-rendering/TextLayoutEngine.d.ts +18 -0
  272. package/dist/src/core/text-rendering/TextLayoutEngine.js +380 -0
  273. package/dist/src/core/text-rendering/TextLayoutEngine.js.map +1 -0
  274. package/dist/src/core/text-rendering/TextRenderer.d.ts +406 -0
  275. package/dist/src/core/text-rendering/TextRenderer.js +2 -0
  276. package/dist/src/core/text-rendering/TextRenderer.js.map +1 -0
  277. package/dist/src/core/text-rendering/Utils.d.ts +30 -0
  278. package/dist/src/core/text-rendering/Utils.js +66 -0
  279. package/dist/src/core/text-rendering/Utils.js.map +1 -0
  280. package/dist/src/core/textures/ColorTexture.d.ts +36 -0
  281. package/dist/src/core/textures/ColorTexture.js +57 -0
  282. package/dist/src/core/textures/ColorTexture.js.map +1 -0
  283. package/dist/src/core/textures/ImageTexture.d.ts +131 -0
  284. package/dist/src/core/textures/ImageTexture.js +211 -0
  285. package/dist/src/core/textures/ImageTexture.js.map +1 -0
  286. package/dist/src/core/textures/NoiseTexture.d.ts +43 -0
  287. package/dist/src/core/textures/NoiseTexture.js +50 -0
  288. package/dist/src/core/textures/NoiseTexture.js.map +1 -0
  289. package/dist/src/core/textures/RenderTexture.d.ts +29 -0
  290. package/dist/src/core/textures/RenderTexture.js +36 -0
  291. package/dist/src/core/textures/RenderTexture.js.map +1 -0
  292. package/dist/src/core/textures/SubTexture.d.ts +61 -0
  293. package/dist/src/core/textures/SubTexture.js +99 -0
  294. package/dist/src/core/textures/SubTexture.js.map +1 -0
  295. package/dist/src/core/textures/Texture.d.ts +275 -0
  296. package/dist/src/core/textures/Texture.js +326 -0
  297. package/dist/src/core/textures/Texture.js.map +1 -0
  298. package/dist/src/core/utils.d.ts +23 -0
  299. package/dist/src/core/utils.js +155 -0
  300. package/dist/src/core/utils.js.map +1 -0
  301. package/dist/src/main-api/INode.d.ts +65 -0
  302. package/dist/src/main-api/INode.js +2 -0
  303. package/dist/src/main-api/INode.js.map +1 -0
  304. package/dist/src/main-api/Inspector.d.ts +154 -0
  305. package/dist/src/main-api/Inspector.js +844 -0
  306. package/dist/src/main-api/Inspector.js.map +1 -0
  307. package/dist/src/main-api/Renderer.d.ts +629 -0
  308. package/dist/src/main-api/Renderer.js +471 -0
  309. package/dist/src/main-api/Renderer.js.map +1 -0
  310. package/dist/src/main-api/utils.d.ts +2 -0
  311. package/dist/src/main-api/utils.js +34 -0
  312. package/dist/src/main-api/utils.js.map +1 -0
  313. package/dist/src/utils.d.ts +123 -0
  314. package/dist/src/utils.js +234 -0
  315. package/dist/src/utils.js.map +1 -0
  316. package/dist/tsconfig.dist.tsbuildinfo +1 -0
  317. package/exports/canvas-shaders.ts +11 -0
  318. package/exports/canvas.ts +27 -0
  319. package/exports/index.ts +69 -0
  320. package/exports/inspector.ts +5 -0
  321. package/exports/utils.ts +32 -0
  322. package/exports/webgl-shaders.ts +12 -0
  323. package/exports/webgl.ts +33 -0
  324. package/package.json +99 -0
  325. package/src/common/CommonTypes.ts +145 -0
  326. package/src/common/EventEmitter.ts +58 -0
  327. package/src/common/IAnimationController.ts +65 -0
  328. package/src/common/IEventEmitter.ts +11 -0
  329. package/src/core/Autosizer.ts +205 -0
  330. package/src/core/CoreNode.test.ts +535 -0
  331. package/src/core/CoreNode.ts +2883 -0
  332. package/src/core/CoreShaderManager.ts +170 -0
  333. package/src/core/CoreTextNode.ts +573 -0
  334. package/src/core/CoreTextureManager.ts +552 -0
  335. package/src/core/Stage.ts +1037 -0
  336. package/src/core/TextureError.ts +46 -0
  337. package/src/core/TextureMemoryManager.ts +378 -0
  338. package/src/core/animations/AnimationManager.ts +178 -0
  339. package/src/core/animations/CoreAnimation.ts +138 -0
  340. package/src/core/lib/ContextSpy.ts +22 -0
  341. package/src/core/lib/ImageWorker.ts +292 -0
  342. package/src/core/lib/Matrix3d.ts +231 -0
  343. package/src/core/lib/RenderCoords.ts +55 -0
  344. package/src/core/lib/WebGlContextWrapper.ts +1448 -0
  345. package/src/core/lib/collectionUtils.ts +99 -0
  346. package/src/core/lib/colorCache.ts +20 -0
  347. package/src/core/lib/colorParser.ts +66 -0
  348. package/src/core/lib/textureCompression.ts +492 -0
  349. package/src/core/lib/textureSvg.ts +59 -0
  350. package/src/core/lib/utils.ts +400 -0
  351. package/src/core/lib/validateImageBitmap.ts +87 -0
  352. package/src/core/platforms/Platform.ts +64 -0
  353. package/src/core/platforms/web/WebPlatform.ts +132 -0
  354. package/src/core/renderers/CoreContextTexture.ts +25 -0
  355. package/src/core/renderers/CoreRenderOp.ts +3 -0
  356. package/src/core/renderers/CoreRenderer.ts +101 -0
  357. package/src/core/renderers/CoreShaderNode.ts +202 -0
  358. package/src/core/renderers/CoreShaderProgram.ts +4 -0
  359. package/src/core/renderers/canvas/CanvasRenderer.ts +274 -0
  360. package/src/core/renderers/canvas/CanvasShaderNode.ts +79 -0
  361. package/src/core/renderers/canvas/CanvasTexture.ts +141 -0
  362. package/src/core/renderers/webgl/SdfRenderOp.ts +103 -0
  363. package/src/core/renderers/webgl/WebGlCtxRenderTexture.ts +70 -0
  364. package/src/core/renderers/webgl/WebGlCtxSubTexture.ts +76 -0
  365. package/src/core/renderers/webgl/WebGlCtxTexture.ts +332 -0
  366. package/src/core/renderers/webgl/WebGlRenderer.ts +1323 -0
  367. package/src/core/renderers/webgl/WebGlShaderNode.ts +423 -0
  368. package/src/core/renderers/webgl/WebGlShaderProgram.ts +346 -0
  369. package/src/core/renderers/webgl/internal/BufferCollection.ts +46 -0
  370. package/src/core/renderers/webgl/internal/RendererUtils.ts +136 -0
  371. package/src/core/renderers/webgl/internal/ShaderUtils.ts +262 -0
  372. package/src/core/renderers/webgl/internal/WebGlUtils.ts +16 -0
  373. package/src/core/shaders/canvas/Border.ts +119 -0
  374. package/src/core/shaders/canvas/HolePunch.ts +38 -0
  375. package/src/core/shaders/canvas/LinearGradient.ts +54 -0
  376. package/src/core/shaders/canvas/RadialGradient.ts +82 -0
  377. package/src/core/shaders/canvas/Rounded.ts +38 -0
  378. package/src/core/shaders/canvas/RoundedWithBorder.ts +105 -0
  379. package/src/core/shaders/canvas/RoundedWithBorderAndShadow.ts +118 -0
  380. package/src/core/shaders/canvas/RoundedWithShadow.ts +56 -0
  381. package/src/core/shaders/canvas/Shadow.ts +35 -0
  382. package/src/core/shaders/canvas/utils/render.ts +143 -0
  383. package/src/core/shaders/templates/BorderTemplate.ts +128 -0
  384. package/src/core/shaders/templates/HolePunchTemplate.ts +65 -0
  385. package/src/core/shaders/templates/LinearGradientTemplate.ts +54 -0
  386. package/src/core/shaders/templates/RadialGradientTemplate.ts +66 -0
  387. package/src/core/shaders/templates/RoundedTemplate.ts +81 -0
  388. package/src/core/shaders/templates/RoundedWithBorderAndShadowTemplate.ts +21 -0
  389. package/src/core/shaders/templates/RoundedWithBorderTemplate.ts +23 -0
  390. package/src/core/shaders/templates/RoundedWithShadowTemplate.ts +18 -0
  391. package/src/core/shaders/templates/ShadowTemplate.ts +89 -0
  392. package/src/core/shaders/utils.ts +30 -0
  393. package/src/core/shaders/webgl/Border.ts +158 -0
  394. package/src/core/shaders/webgl/Default.ts +52 -0
  395. package/src/core/shaders/webgl/HolePunch.ts +58 -0
  396. package/src/core/shaders/webgl/LinearGradient.ts +119 -0
  397. package/src/core/shaders/webgl/RadialGradient.ts +91 -0
  398. package/src/core/shaders/webgl/Rounded.ts +97 -0
  399. package/src/core/shaders/webgl/RoundedWithBorder.ts +212 -0
  400. package/src/core/shaders/webgl/RoundedWithBorderAndShadow.ts +235 -0
  401. package/src/core/shaders/webgl/RoundedWithShadow.ts +132 -0
  402. package/src/core/shaders/webgl/SdfShader.ts +73 -0
  403. package/src/core/shaders/webgl/Shadow.ts +119 -0
  404. package/src/core/text-rendering/CanvasFontHandler.ts +285 -0
  405. package/src/core/text-rendering/CanvasTextRenderer.ts +236 -0
  406. package/src/core/text-rendering/SdfFontHandler.ts +566 -0
  407. package/src/core/text-rendering/SdfTextRenderer.ts +352 -0
  408. package/src/core/text-rendering/TextLayoutEngine.ts +672 -0
  409. package/src/core/text-rendering/TextRenderer.ts +449 -0
  410. package/src/core/text-rendering/Utils.ts +80 -0
  411. package/src/core/text-rendering/tests/TextLayoutEngine.test.ts +434 -0
  412. package/src/core/textures/ColorTexture.ts +85 -0
  413. package/src/core/textures/ImageTexture.ts +394 -0
  414. package/src/core/textures/NoiseTexture.ts +87 -0
  415. package/src/core/textures/RenderTexture.ts +68 -0
  416. package/src/core/textures/SubTexture.ts +165 -0
  417. package/src/core/textures/Texture.ts +505 -0
  418. package/src/core/utils.ts +210 -0
  419. package/src/env.d.ts +7 -0
  420. package/src/main-api/INode.ts +92 -0
  421. package/src/main-api/Inspector.ts +1267 -0
  422. package/src/main-api/Renderer.ts +1011 -0
  423. package/src/main-api/utils.ts +45 -0
  424. package/src/utils.ts +302 -0
@@ -0,0 +1,2883 @@
1
+ import {
2
+ assertTruthy,
3
+ getNewId,
4
+ premultiplyColorABGR,
5
+ USE_RTT,
6
+ ENABLE_AUTOSIZE,
7
+ EMIT_BOUNDS_EVENTS,
8
+ } from '../utils.js';
9
+ import type { TextureOptions } from './CoreTextureManager.js';
10
+ import type { WebGlRenderer } from './renderers/webgl/WebGlRenderer.js';
11
+ import type { WebGlCtxTexture } from './renderers/webgl/WebGlCtxTexture.js';
12
+ import type { BufferCollection } from './renderers/webgl/internal/BufferCollection.js';
13
+ import type { CoreRenderer } from './renderers/CoreRenderer.js';
14
+ import type { Stage } from './Stage.js';
15
+ import {
16
+ type Texture,
17
+ type TextureCoords,
18
+ type TextureFailedEventHandler,
19
+ type TextureFreedEventHandler,
20
+ type TextureLoadedEventHandler,
21
+ } from './textures/Texture.js';
22
+ import type {
23
+ Dimensions,
24
+ NodeTextureFailedPayload,
25
+ NodeTextureFreedPayload,
26
+ NodeTextureLoadedPayload,
27
+ NodeRenderablePayload,
28
+ } from '../common/CommonTypes.js';
29
+ import { EventEmitter } from '../common/EventEmitter.js';
30
+ import {
31
+ copyRect,
32
+ intersectRect,
33
+ type Bound,
34
+ type RectWithValid,
35
+ createBound,
36
+ boundInsideBound,
37
+ boundLargeThanBound,
38
+ createPreloadBounds,
39
+ } from './lib/utils.js';
40
+ import { Matrix3d } from './lib/Matrix3d.js';
41
+ import { RenderCoords } from './lib/RenderCoords.js';
42
+ import type { AnimationSettings } from './animations/CoreAnimation.js';
43
+ import type { AnimationConfig } from './animations/AnimationManager.js';
44
+ import type { IAnimationController } from '../common/IAnimationController.js';
45
+ import { createAnimation } from './animations/CoreAnimation.js';
46
+ import type { CoreShaderNode } from './renderers/CoreShaderNode.js';
47
+ import { AutosizeMode, Autosizer } from './Autosizer.js';
48
+ import { removeChild } from './lib/collectionUtils.js';
49
+
50
+ export enum CoreNodeRenderState {
51
+ Init = 0,
52
+ OutOfBounds = 2,
53
+ InBounds = 4,
54
+ InViewport = 8,
55
+ }
56
+
57
+ const NO_CLIPPING_RECT: RectWithValid = {
58
+ x: 0,
59
+ y: 0,
60
+ width: 0,
61
+ height: 0,
62
+ valid: false,
63
+ };
64
+
65
+ const CoreNodeRenderStateMap: Map<CoreNodeRenderState, string> = new Map();
66
+ CoreNodeRenderStateMap.set(CoreNodeRenderState.Init, 'init');
67
+ CoreNodeRenderStateMap.set(CoreNodeRenderState.OutOfBounds, 'outOfBounds');
68
+ CoreNodeRenderStateMap.set(CoreNodeRenderState.InBounds, 'inBounds');
69
+ CoreNodeRenderStateMap.set(CoreNodeRenderState.InViewport, 'inViewport');
70
+
71
+ export enum UpdateType {
72
+ /**
73
+ * Child updates
74
+ */
75
+ Children = 1,
76
+
77
+ /**
78
+ * localTransform
79
+ *
80
+ * @remarks
81
+ * CoreNode Properties Updated:
82
+ * - `localTransform`
83
+ */
84
+ Local = 2,
85
+
86
+ /**
87
+ * globalTransform
88
+ *
89
+ * * @remarks
90
+ * CoreNode Properties Updated:
91
+ * - `globalTransform`
92
+ * - `renderBounds`
93
+ * - `renderCoords`
94
+ */
95
+ Global = 4,
96
+
97
+ /**
98
+ * Clipping rect update
99
+ *
100
+ * @remarks
101
+ * CoreNode Properties Updated:
102
+ * - `clippingRect`
103
+ */
104
+ Clipping = 8,
105
+
106
+ /**
107
+ * Sort Z-Index Children update
108
+ *
109
+ * @remarks
110
+ * CoreNode Properties Updated:
111
+ * - `children` (sorts children by their `calcZIndex`)
112
+ */
113
+ SortZIndexChildren = 16,
114
+
115
+ /**
116
+ * Premultiplied Colors update
117
+ *
118
+ * @remarks
119
+ * CoreNode Properties Updated:
120
+ * - `premultipliedColorTl`
121
+ * - `premultipliedColorTr`
122
+ * - `premultipliedColorBl`
123
+ * - `premultipliedColorBr`
124
+ */
125
+ PremultipliedColors = 32,
126
+
127
+ /**
128
+ * World Alpha update
129
+ *
130
+ * @remarks
131
+ * CoreNode Properties Updated:
132
+ * - `worldAlpha` = `parent.worldAlpha` * `alpha`
133
+ */
134
+ WorldAlpha = 64,
135
+
136
+ /**
137
+ * Render State update
138
+ *
139
+ * @remarks
140
+ * CoreNode Properties Updated:
141
+ * - `renderState`
142
+ */
143
+ RenderState = 128,
144
+
145
+ /**
146
+ * Is Renderable update
147
+ *
148
+ * @remarks
149
+ * CoreNode Properties Updated:
150
+ * - `isRenderable`
151
+ */
152
+ IsRenderable = 256,
153
+
154
+ /**
155
+ * Render Texture update
156
+ */
157
+ RenderTexture = 512,
158
+
159
+ /**
160
+ * Track if parent has render texture
161
+ */
162
+ ParentRenderTexture = 1024,
163
+
164
+ /**
165
+ * Render Bounds update
166
+ */
167
+ RenderBounds = 2048,
168
+
169
+ /**
170
+ * RecalcUniforms
171
+ */
172
+ RecalcUniforms = 4096,
173
+
174
+ /**
175
+ * Autosize update
176
+ */
177
+ Autosize = 8192,
178
+ /**
179
+ * None
180
+ */
181
+ None = 0,
182
+
183
+ /**
184
+ * All
185
+ */
186
+ All = 16383,
187
+ }
188
+
189
+ /**
190
+ * A custom data map which can be stored on an CoreNode
191
+ *
192
+ * @remarks
193
+ * This is a map of key-value pairs that can be stored on an INode. It is used
194
+ * to store custom data that can be used by the application.
195
+ * The data stored can only be of type string, number or boolean.
196
+ */
197
+ export type CustomDataMap = {
198
+ [key: string]: string | number | boolean | undefined;
199
+ };
200
+
201
+ /**
202
+ * Writable properties of a Node.
203
+ */
204
+ export interface CoreNodeProps {
205
+ /**
206
+ * The x coordinate of the Node's Mount Point.
207
+ *
208
+ * @remarks
209
+ * See {@link mountX} and {@link mountY} for more information about setting
210
+ * the Mount Point.
211
+ *
212
+ * @default `0`
213
+ */
214
+ x: number;
215
+ /**
216
+ * The y coordinate of the Node's Mount Point.
217
+ *
218
+ * @remarks
219
+ * See {@link mountX} and {@link mountY} for more information about setting
220
+ * the Mount Point.
221
+ *
222
+ * @default `0`
223
+ */
224
+ y: number;
225
+ /**
226
+ * The width of the Node.
227
+ * @warning This will be deprecated in favor of `w` and `h` properties in the future.
228
+ *
229
+ * @default `0`
230
+ */
231
+ w: number;
232
+ /**
233
+ * The height of the Node.
234
+ * @warning This will be deprecated in favor of `w` and `h` properties in the future.
235
+ *
236
+ * @default `0`
237
+ */
238
+ h: number;
239
+ /**
240
+ * The alpha opacity of the Node.
241
+ *
242
+ * @remarks
243
+ * The alpha value is a number between 0 and 1, where 0 is fully transparent
244
+ * and 1 is fully opaque.
245
+ *
246
+ * @default `1`
247
+ */
248
+ alpha: number;
249
+ /**
250
+ * Autosize
251
+ *
252
+ * @remarks
253
+ * When enabled, the Node automatically resizes based on its content
254
+ *
255
+ * **Texture Autosize Mode:**
256
+ * - When the Node has a texture, it automatically resizes to match the
257
+ * texture's dimensions when the texture loads
258
+ * - This ensures images display at their natural size without manual sizing
259
+ * - Text Nodes always use this mode regardless of this setting
260
+ *
261
+ * **Children Autosize Mode:**
262
+ * - When the Node has no texture but contains children, it automatically
263
+ * resizes to encompass all children's bounds
264
+ * - Calculates the bounding box that contains all child positions, dimensions,
265
+ * and transforms (scale, rotation, mount/pivot points)
266
+ * - Creates container behavior where the parent grows to fit its content
267
+ * - Updates dynamically as children are added, removed, or transformed
268
+ *
269
+ * **Mode Selection Logic:**
270
+ * - Texture mode takes precedence over children mode
271
+ * - Mode switches automatically when texture is added/removed
272
+ * - If no texture and no children, autosize has no effect
273
+ *
274
+ * **Performance:**
275
+ * - Children mode uses efficient transform caching and differential updates
276
+ * - Only recalculates when child transforms actually change
277
+ * - Minimal memory allocation with factory function patterns
278
+ *
279
+ *
280
+ * @default `false`
281
+ */
282
+ autosize: boolean;
283
+ /**
284
+ * Margin around the Node's bounds for preloading
285
+ *
286
+ * @default `null`
287
+ */
288
+ boundsMargin: number | [number, number, number, number] | null;
289
+ /**
290
+ * Clipping Mode
291
+ *
292
+ * @remarks
293
+ * Enable Clipping Mode when you want to prevent the drawing of a Node and
294
+ * its descendants from overflowing outside of the Node's x/y/width/height
295
+ * bounds.
296
+ *
297
+ * For WebGL, clipping is implemented using the high-performance WebGL
298
+ * operation scissor. As a consequence, clipping does not work for
299
+ * non-rectangular areas. So, if the element is rotated
300
+ * (by itself or by any of its ancestors), clipping will not work as intended.
301
+ *
302
+ * TODO: Add support for non-rectangular clipping either automatically or
303
+ * via Render-To-Texture.
304
+ *
305
+ * @default `false`
306
+ */
307
+ clipping: boolean;
308
+ /**
309
+ * The color of the Node.
310
+ *
311
+ * @remarks
312
+ * The color value is a number in the format 0xRRGGBBAA, where RR is the red
313
+ * component, GG is the green component, BB is the blue component, and AA is
314
+ * the alpha component.
315
+ *
316
+ * Gradient colors may be set by setting the different color sub-properties:
317
+ * {@link colorTop}, {@link colorBottom}, {@link colorLeft}, {@link colorRight},
318
+ * {@link colorTl}, {@link colorTr}, {@link colorBr}, {@link colorBl} accordingly.
319
+ *
320
+ * @default `0xffffffff` (opaque white)
321
+ */
322
+ color: number;
323
+ /**
324
+ * The color of the top edge of the Node for gradient rendering.
325
+ *
326
+ * @remarks
327
+ * See {@link color} for more information about color values and gradient
328
+ * rendering.
329
+ */
330
+ colorTop: number;
331
+ /**
332
+ * The color of the bottom edge of the Node for gradient rendering.
333
+ *
334
+ * @remarks
335
+ * See {@link color} for more information about color values and gradient
336
+ * rendering.
337
+ */
338
+ colorBottom: number;
339
+ /**
340
+ * The color of the left edge of the Node for gradient rendering.
341
+ *
342
+ * @remarks
343
+ * See {@link color} for more information about color values and gradient
344
+ * rendering.
345
+ */
346
+ colorLeft: number;
347
+ /**
348
+ * The color of the right edge of the Node for gradient rendering.
349
+ *
350
+ * @remarks
351
+ * See {@link color} for more information about color values and gradient
352
+ * rendering.
353
+ */
354
+ colorRight: number;
355
+ /**
356
+ * The color of the top-left corner of the Node for gradient rendering.
357
+ *
358
+ * @remarks
359
+ * See {@link color} for more information about color values and gradient
360
+ * rendering.
361
+ */
362
+ colorTl: number;
363
+ /**
364
+ * The color of the top-right corner of the Node for gradient rendering.
365
+ *
366
+ * @remarks
367
+ * See {@link color} for more information about color values and gradient
368
+ * rendering.
369
+ */
370
+ colorTr: number;
371
+ /**
372
+ * The color of the bottom-right corner of the Node for gradient rendering.
373
+ *
374
+ * @remarks
375
+ * See {@link color} for more information about color values and gradient
376
+ * rendering.
377
+ */
378
+ colorBr: number;
379
+ /**
380
+ * The color of the bottom-left corner of the Node for gradient rendering.
381
+ *
382
+ * @remarks
383
+ * See {@link color} for more information about color values and gradient
384
+ * rendering.
385
+ */
386
+ colorBl: number;
387
+ /**
388
+ * The Node's parent Node.
389
+ *
390
+ * @remarks
391
+ * The value `null` indicates that the Node has no parent. This may either be
392
+ * because the Node is the root Node of the scene graph, or because the Node
393
+ * has been removed from the scene graph.
394
+ *
395
+ * In order to make sure that a Node can be rendered on the screen, it must
396
+ * be added to the scene graph by setting it's parent property to a Node that
397
+ * is already in the scene graph such as the root Node.
398
+ *
399
+ * @default `null`
400
+ */
401
+ parent: CoreNode | null;
402
+ /**
403
+ * The Node's z-index.
404
+ *
405
+ * @remarks
406
+ * Max z-index of children under the same parent determines which child
407
+ * is rendered on top. Higher z-index means the Node is rendered on top of
408
+ * children with lower z-index.
409
+ *
410
+ * Max value is 1000 and min value is -1000. Values outside of this range will be clamped.
411
+ */
412
+ zIndex: number;
413
+ /**
414
+ * The Node's Texture.
415
+ *
416
+ * @remarks
417
+ * The `texture` defines a rasterized image that is contained within the
418
+ * {@link width} and {@link height} dimensions of the Node. If null, the
419
+ * Node will use an opaque white {@link ColorTexture} when being drawn, which
420
+ * essentially enables colors (including gradients) to be drawn.
421
+ *
422
+ * If set, by default, the texture will be drawn, as is, stretched to the
423
+ * dimensions of the Node. This behavior can be modified by setting the TBD
424
+ * and TBD properties.
425
+ *
426
+ * To create a Texture in order to set it on this property, call
427
+ * {@link RendererMain.createTexture}.
428
+ *
429
+ * If the {@link src} is set on a Node, the Node will use the
430
+ * {@link ImageTexture} by default and the Node will simply load the image at
431
+ * the specified URL.
432
+ *
433
+ * Note: If this is a Text Node, the Texture will be managed by the Node's
434
+ * {@link TextRenderer} and should not be set explicitly.
435
+ */
436
+ texture: Texture | null;
437
+
438
+ /**
439
+ * Options to associate with the Node's Texture
440
+ */
441
+ textureOptions: TextureOptions;
442
+
443
+ /**
444
+ * The Node's shader
445
+ *
446
+ * @remarks
447
+ * The `shader` defines a {@link Shader} used to draw the Node. By default,
448
+ * the Default Shader is used which simply draws the defined {@link texture}
449
+ * or {@link color}(s) within the Node without any special effects.
450
+ *
451
+ * To create a Shader in order to set it on this property, call
452
+ * {@link RendererMain.createShader}.
453
+ *
454
+ * Note: If this is a Text Node, the Shader will be managed by the Node's
455
+ * {@link TextRenderer} and should not be set explicitly.
456
+ */
457
+ shader: CoreShaderNode<any> | null;
458
+ /**
459
+ * Image URL
460
+ *
461
+ * @remarks
462
+ * When set, the Node's {@link texture} is automatically set to an
463
+ * {@link ImageTexture} using the source image URL provided (with all other
464
+ * settings being defaults)
465
+ */
466
+ src: string | null;
467
+ /**
468
+ * Scale to render the Node at
469
+ *
470
+ * @remarks
471
+ * The scale value multiplies the provided {@link width} and {@link height}
472
+ * of the Node around the Node's Pivot Point (defined by the {@link pivot}
473
+ * props).
474
+ *
475
+ * Behind the scenes, setting this property sets both the {@link scaleX} and
476
+ * {@link scaleY} props to the same value.
477
+ *
478
+ * NOTE: When the scaleX and scaleY props are explicitly set to different values,
479
+ * this property returns `null`. Setting `null` on this property will have no
480
+ * effect.
481
+ *
482
+ * @default 1.0
483
+ */
484
+ scale: number | null;
485
+ /**
486
+ * Scale to render the Node at (X-Axis)
487
+ *
488
+ * @remarks
489
+ * The scaleX value multiplies the provided {@link width} of the Node around
490
+ * the Node's Pivot Point (defined by the {@link pivot} props).
491
+ *
492
+ * @default 1.0
493
+ */
494
+ scaleX: number;
495
+ /**
496
+ * Scale to render the Node at (Y-Axis)
497
+ *
498
+ * @remarks
499
+ * The scaleY value multiplies the provided {@link height} of the Node around
500
+ * the Node's Pivot Point (defined by the {@link pivot} props).
501
+ *
502
+ * @default 1.0
503
+ */
504
+ scaleY: number;
505
+ /**
506
+ * Combined position of the Node's Mount Point
507
+ *
508
+ * @remarks
509
+ * The value can be any number between `0.0` and `1.0`:
510
+ * - `0.0` defines the Mount Point at the top-left corner of the Node.
511
+ * - `0.5` defines it at the center of the Node.
512
+ * - `1.0` defines it at the bottom-right corner of the node.
513
+ *
514
+ * Use the {@link mountX} and {@link mountY} props seperately for more control
515
+ * of the Mount Point.
516
+ *
517
+ * When assigned, the same value is also passed to both the {@link mountX} and
518
+ * {@link mountY} props.
519
+ *
520
+ * @default 0 (top-left)
521
+ */
522
+ mount: number;
523
+ /**
524
+ * X position of the Node's Mount Point
525
+ *
526
+ * @remarks
527
+ * The value can be any number between `0.0` and `1.0`:
528
+ * - `0.0` defines the Mount Point's X position as the left-most edge of the
529
+ * Node
530
+ * - `0.5` defines it as the horizontal center of the Node
531
+ * - `1.0` defines it as the right-most edge of the Node.
532
+ *
533
+ * The combination of {@link mountX} and {@link mountY} define the Mount Point
534
+ *
535
+ * @default 0 (left-most edge)
536
+ */
537
+ mountX: number;
538
+ /**
539
+ * Y position of the Node's Mount Point
540
+ *
541
+ * @remarks
542
+ * The value can be any number between `0.0` and `1.0`:
543
+ * - `0.0` defines the Mount Point's Y position as the top-most edge of the
544
+ * Node
545
+ * - `0.5` defines it as the vertical center of the Node
546
+ * - `1.0` defines it as the bottom-most edge of the Node.
547
+ *
548
+ * The combination of {@link mountX} and {@link mountY} define the Mount Point
549
+ *
550
+ * @default 0 (top-most edge)
551
+ */
552
+ mountY: number;
553
+ /**
554
+ * Combined position of the Node's Pivot Point
555
+ *
556
+ * @remarks
557
+ * The value can be any number between `0.0` and `1.0`:
558
+ * - `0.0` defines the Pivot Point at the top-left corner of the Node.
559
+ * - `0.5` defines it at the center of the Node.
560
+ * - `1.0` defines it at the bottom-right corner of the node.
561
+ *
562
+ * Use the {@link pivotX} and {@link pivotY} props seperately for more control
563
+ * of the Pivot Point.
564
+ *
565
+ * When assigned, the same value is also passed to both the {@link pivotX} and
566
+ * {@link pivotY} props.
567
+ *
568
+ * @default 0.5 (center)
569
+ */
570
+ pivot: number;
571
+ /**
572
+ * X position of the Node's Pivot Point
573
+ *
574
+ * @remarks
575
+ * The value can be any number between `0.0` and `1.0`:
576
+ * - `0.0` defines the Pivot Point's X position as the left-most edge of the
577
+ * Node
578
+ * - `0.5` defines it as the horizontal center of the Node
579
+ * - `1.0` defines it as the right-most edge of the Node.
580
+ *
581
+ * The combination of {@link pivotX} and {@link pivotY} define the Pivot Point
582
+ *
583
+ * @default 0.5 (centered on x-axis)
584
+ */
585
+ pivotX: number;
586
+ /**
587
+ * Y position of the Node's Pivot Point
588
+ *
589
+ * @remarks
590
+ * The value can be any number between `0.0` and `1.0`:
591
+ * - `0.0` defines the Pivot Point's Y position as the top-most edge of the
592
+ * Node
593
+ * - `0.5` defines it as the vertical center of the Node
594
+ * - `1.0` defines it as the bottom-most edge of the Node.
595
+ *
596
+ * The combination of {@link pivotX} and {@link pivotY} define the Pivot Point
597
+ *
598
+ * @default 0.5 (centered on y-axis)
599
+ */
600
+ pivotY: number;
601
+ /**
602
+ * Rotation of the Node (in Radians)
603
+ *
604
+ * @remarks
605
+ * Sets the amount to rotate the Node by around it's Pivot Point (defined by
606
+ * the {@link pivot} props). Positive values rotate the Node clockwise, while
607
+ * negative values rotate it counter-clockwise.
608
+ *
609
+ * Example values:
610
+ * - `-Math.PI / 2`: 90 degree rotation counter-clockwise
611
+ * - `0`: No rotation
612
+ * - `Math.PI / 2`: 90 degree rotation clockwise
613
+ * - `Math.PI`: 180 degree rotation clockwise
614
+ * - `3 * Math.PI / 2`: 270 degree rotation clockwise
615
+ * - `2 * Math.PI`: 360 rotation clockwise
616
+ */
617
+ rotation: number;
618
+
619
+ /**
620
+ * Whether the Node is rendered to a texture
621
+ *
622
+ * @remarks
623
+ * TBD
624
+ *
625
+ * @default false
626
+ */
627
+ rtt: boolean;
628
+
629
+ /**
630
+ * Node data element for custom data storage (optional)
631
+ *
632
+ * @remarks
633
+ * This property is used to store custom data on the Node as a key/value data store.
634
+ * Data values are limited to string, numbers, booleans. Strings will be truncated
635
+ * to a 2048 character limit for performance reasons.
636
+ *
637
+ * This is not a data storage mechanism for large amounts of data please use a
638
+ * dedicated data storage mechanism for that.
639
+ *
640
+ * The custom data will be reflected in the inspector as part of `data-*` attributes
641
+ *
642
+ * @default `undefined`
643
+ */
644
+ data?: CustomDataMap;
645
+
646
+ /**
647
+ * Image Type to explicitly set the image type that is being loaded
648
+ *
649
+ * @remarks
650
+ * This property must be used with a `src` that points at an image. In some cases
651
+ * the extension doesn't provide a reliable representation of the image type. In such
652
+ * cases set the ImageType explicitly.
653
+ *
654
+ * `regular` is used for normal images such as png, jpg, etc
655
+ * `compressed` is used for ETC1/ETC2 compressed images with a PVR or KTX container
656
+ * `svg` is used for scalable vector graphics
657
+ *
658
+ * @default `undefined`
659
+ */
660
+ imageType?: 'regular' | 'compressed' | 'svg' | null;
661
+
662
+ /**
663
+ * She width of the rectangle from which the Image Texture will be extracted.
664
+ * This value can be negative. If not provided, the image's source natural
665
+ * width will be used.
666
+ */
667
+ srcWidth?: number;
668
+ /**
669
+ * The height of the rectangle from which the Image Texture will be extracted.
670
+ * This value can be negative. If not provided, the image's source natural
671
+ * height will be used.
672
+ */
673
+ srcHeight?: number;
674
+ /**
675
+ * The x coordinate of the reference point of the rectangle from which the Texture
676
+ * will be extracted. `width` and `height` are provided. And only works when
677
+ * createImageBitmap is available. Only works when createImageBitmap is supported on the browser.
678
+ */
679
+ srcX?: number;
680
+ /**
681
+ * The y coordinate of the reference point of the rectangle from which the Texture
682
+ * will be extracted. Only used when source `srcWidth` width and `srcHeight` height
683
+ * are provided. Only works when createImageBitmap is supported on the browser.
684
+ */
685
+ srcY?: number;
686
+ /**
687
+ * Mark the node as interactive so we can perform hit tests on it
688
+ * when pointer events are registered.
689
+ * @default false
690
+ */
691
+ interactive?: boolean;
692
+ /**
693
+ * preventDestroy flag prevents the node and its children from being destroyed
694
+ * when the parent is destroyed.
695
+ * @default false
696
+ */
697
+ preventDestroy?: boolean;
698
+ }
699
+
700
+ /**
701
+ * Grab all the number properties of type T
702
+ */
703
+ type NumberProps<T> = {
704
+ [Key in keyof T as NonNullable<T[Key]> extends number ? Key : never]: number;
705
+ };
706
+
707
+ /**
708
+ * Properties of a Node used by the animate() function
709
+ */
710
+ export interface CoreNodeAnimateProps extends NumberProps<CoreNodeProps> {
711
+ /**
712
+ * Shader properties to animate
713
+ */
714
+ shaderProps: Record<string, number>;
715
+ // TODO: textureProps: Record<string, number>;
716
+ }
717
+
718
+ /**
719
+ * A visual Node in the Renderer scene graph.
720
+ *
721
+ * @remarks
722
+ * CoreNode is an internally used class that represents a Renderer Node in the
723
+ * scene graph. See INode.ts for the public APIs exposed to Renderer users
724
+ * that include generic types for Shaders.
725
+ */
726
+ export class CoreNode extends EventEmitter {
727
+ readonly children: CoreNode[] = [];
728
+ protected _id: number = getNewId();
729
+ readonly props: CoreNodeProps;
730
+ public readonly isCoreNode = true as const;
731
+ private _animations: Record<
732
+ string,
733
+ { controller: AnimationConfig; settings: Partial<AnimationSettings> }
734
+ > = {};
735
+
736
+ // WebGL Render Op State
737
+ public renderOpBufferIdx: number = 0;
738
+ public numQuads: number = 0;
739
+ public renderOpTextures: WebGlCtxTexture[] = [];
740
+
741
+ /**
742
+ * Permanent index (in float32 units) into the renderer's quad buffer.
743
+ * -1 means this node has not yet been assigned a slot.
744
+ */
745
+ public quadBufferIndex: number = -1;
746
+
747
+ /**
748
+ * True when renderCoords, premultiplied colors, or textureCoords changed
749
+ * since the node's quad was last written to the GPU.
750
+ */
751
+ public isQuadDirty: boolean = true;
752
+
753
+ private hasShaderUpdater = false;
754
+ public hasShaderTimeFn = false;
755
+ private hasColorProps = false;
756
+ public textureLoaded = false;
757
+
758
+ public updateType = UpdateType.All;
759
+ public childUpdateType = UpdateType.None;
760
+
761
+ public globalTransform?: Matrix3d;
762
+ public localTransform?: Matrix3d;
763
+ public sceneGlobalTransform?: Matrix3d;
764
+ public renderCoords?: RenderCoords;
765
+ public sceneRenderCoords?: RenderCoords;
766
+ public renderBound?: Bound;
767
+ public strictBound?: Bound;
768
+ public preloadBound?: Bound;
769
+ public clippingRect: RectWithValid = {
770
+ x: 0,
771
+ y: 0,
772
+ width: 0,
773
+ height: 0,
774
+ valid: false,
775
+ };
776
+ public textureCoords?: TextureCoords;
777
+ public updateShaderUniforms: boolean = false;
778
+ public isRenderable = false;
779
+ public renderState: CoreNodeRenderState = CoreNodeRenderState.Init;
780
+ public isSimple = true;
781
+
782
+ public worldAlpha = 1;
783
+ public premultipliedColorTl = 0;
784
+ public premultipliedColorTr = 0;
785
+ public premultipliedColorBl = 0;
786
+ public premultipliedColorBr = 0;
787
+ public calcZIndex = 0;
788
+ public hasRTTupdates = false;
789
+ public parentHasRenderTexture = false;
790
+ public rttParent: CoreNode | null = null;
791
+ /**
792
+ * only used when rtt = true
793
+ */
794
+ public framebufferDimensions: Dimensions | null = null;
795
+
796
+ /**Autosize properties */
797
+ autosizer: Autosizer | null = null;
798
+ parentAutosizer: Autosizer | null = null;
799
+
800
+ public destroyed = false;
801
+
802
+ constructor(readonly stage: Stage, props: CoreNodeProps) {
803
+ super();
804
+
805
+ //inital update type
806
+ let initialUpdateType =
807
+ UpdateType.Local | UpdateType.RenderBounds | UpdateType.RenderState;
808
+
809
+ // Fast-path assign only known keys
810
+ const p = (this.props = {
811
+ x: props.x,
812
+ y: props.y,
813
+ w: props.w,
814
+ h: props.h,
815
+ alpha: props.alpha,
816
+ autosize: props.autosize,
817
+ clipping: props.clipping,
818
+ color: props.color,
819
+ colorTop: props.colorTop,
820
+ colorBottom: props.colorBottom,
821
+ colorLeft: props.colorLeft,
822
+ colorRight: props.colorRight,
823
+ colorTl: props.colorTl,
824
+ colorTr: props.colorTr,
825
+ colorBl: props.colorBl,
826
+ colorBr: props.colorBr,
827
+ scaleX: props.scaleX,
828
+ scaleY: props.scaleY,
829
+ rotation: props.rotation,
830
+ pivotX: props.pivotX,
831
+ pivotY: props.pivotY,
832
+ mountX: props.mountX,
833
+ mountY: props.mountY,
834
+ mount: props.mount,
835
+ pivot: props.pivot,
836
+ zIndex: props.zIndex,
837
+ textureOptions: props.textureOptions,
838
+ data: props.data,
839
+ imageType: props.imageType,
840
+ srcX: props.srcX,
841
+ srcY: props.srcY,
842
+ srcWidth: props.srcWidth,
843
+ srcHeight: props.srcHeight,
844
+ parent: props.parent,
845
+ texture: null,
846
+ shader: null,
847
+ src: null,
848
+ rtt: false,
849
+ boundsMargin: null,
850
+ scale: null,
851
+ interactive: props.interactive,
852
+ preventDestroy: props.preventDestroy,
853
+ });
854
+
855
+ //check if any color props are set for premultiplied color updates
856
+ if (
857
+ p.color > 0 ||
858
+ p.colorTop > 0 ||
859
+ p.colorBottom > 0 ||
860
+ p.colorLeft > 0 ||
861
+ p.colorRight > 0 ||
862
+ p.colorTl > 0 ||
863
+ p.colorTr > 0 ||
864
+ p.colorBl > 0 ||
865
+ p.colorBr > 0
866
+ ) {
867
+ this.hasColorProps = true;
868
+ initialUpdateType |= UpdateType.PremultipliedColors;
869
+ }
870
+
871
+ // Only set non-default values
872
+ if (p.zIndex !== 0) {
873
+ this.zIndex = p.zIndex;
874
+ }
875
+
876
+ if (props.parent !== null) {
877
+ props.parent.addChild(this);
878
+ }
879
+
880
+ // Assign props to instances
881
+ this.texture = props.texture;
882
+ this.shader = props.shader;
883
+ this.src = props.src;
884
+ this.rtt = props.rtt;
885
+ this.boundsMargin = props.boundsMargin;
886
+ this.interactive = props.interactive;
887
+
888
+ // Initialize autosize if enabled
889
+ if (p.autosize === true) {
890
+ this.autosizer = new Autosizer(this);
891
+ }
892
+
893
+ this.setUpdateType(initialUpdateType);
894
+
895
+ // if the default texture isn't loaded yet, wait for it to load
896
+ // this only happens when the node is created before the stage is ready
897
+ const dt = this.stage.defaultTexture;
898
+ if (dt !== null && dt.state !== 'loaded') {
899
+ dt.once('loaded', () => this.setUpdateType(UpdateType.IsRenderable));
900
+ }
901
+ this.updateIsSimple();
902
+ }
903
+
904
+ //#region Textures
905
+ loadTexture(): void {
906
+ if (this.props.texture === null) {
907
+ return;
908
+ }
909
+
910
+ // If texture is already loaded / failed, trigger loaded event manually
911
+ // so that users get a consistent event experience.
912
+ // We do this in a microtask to allow listeners to be attached in the same
913
+ // synchronous task after calling loadTexture()
914
+ queueMicrotask(this.loadTextureTask);
915
+ }
916
+
917
+ /**
918
+ * Task for queueMicrotask to loadTexture
919
+ *
920
+ * @remarks
921
+ * This method is called in a microtask to release the texture.
922
+ */
923
+ private loadTextureTask = (): void => {
924
+ const texture = this.props.texture as Texture;
925
+ //it is possible that texture is null here if user sets the texture to null right after loadTexture call
926
+ if (texture === null) {
927
+ return;
928
+ }
929
+ if (this.textureOptions.preload === true) {
930
+ this.stage.txManager.loadTexture(texture);
931
+ }
932
+
933
+ texture.preventCleanup = this.props.textureOptions?.preventCleanup ?? false;
934
+ texture.on('loaded', this.onTextureLoaded);
935
+ texture.on('failed', this.onTextureFailed);
936
+ texture.on('freed', this.onTextureFreed);
937
+
938
+ // If the parent is a render texture, the initial texture status
939
+ // will be set to freed until the texture is processed by the
940
+ // Render RTT nodes. So we only need to listen fo changes and
941
+ // no need to check the texture.state until we restructure how
942
+ // textures are being processed.
943
+ if (this.parentHasRenderTexture) {
944
+ this.notifyParentRTTOfUpdate();
945
+ return;
946
+ }
947
+
948
+ if (texture.state === 'loaded') {
949
+ this.onTextureLoaded(texture, texture.dimensions!);
950
+ } else if (texture.state === 'failed') {
951
+ this.onTextureFailed(texture, texture.error!);
952
+ } else if (texture.state === 'freed') {
953
+ this.onTextureFreed(texture);
954
+ }
955
+ };
956
+
957
+ unloadTexture(): void {
958
+ if (this.texture === null) {
959
+ return;
960
+ }
961
+
962
+ const texture = this.texture;
963
+ texture.off('loaded', this.onTextureLoaded);
964
+ texture.off('failed', this.onTextureFailed);
965
+ texture.off('freed', this.onTextureFreed);
966
+ texture.setRenderableOwner(this._id, false);
967
+ }
968
+
969
+ protected onTextureLoaded: TextureLoadedEventHandler = (_, dimensions) => {
970
+ if (this.autosizer !== null) {
971
+ this.autosizer.update();
972
+ }
973
+
974
+ this.textureLoaded = true;
975
+ this.setUpdateType(UpdateType.IsRenderable);
976
+
977
+ // Texture was loaded. In case the RAF loop has already stopped, we request
978
+ // a render to ensure the texture is rendered.
979
+ this.stage.requestRender();
980
+
981
+ // If parent has a render texture, flag that we need to update
982
+ if (this.parentHasRenderTexture) {
983
+ this.notifyParentRTTOfUpdate();
984
+ }
985
+
986
+ // ignore 1x1 pixel textures
987
+ if (dimensions.w > 1 && dimensions.h > 1) {
988
+ this.emit('loaded', {
989
+ type: 'texture',
990
+ dimensions,
991
+ } satisfies NodeTextureLoadedPayload);
992
+ }
993
+
994
+ if (
995
+ this.stage.calculateTextureCoord === true &&
996
+ this.props.textureOptions !== null
997
+ ) {
998
+ this.textureCoords = this.stage.renderer.getTextureCoords!(this);
999
+ }
1000
+
1001
+ // Trigger a local update if the texture is loaded and the resizeMode is 'contain'
1002
+ if (this.props.textureOptions?.resizeMode?.type === 'contain') {
1003
+ this.setUpdateType(UpdateType.Local);
1004
+ }
1005
+ };
1006
+
1007
+ private onTextureFailed: TextureFailedEventHandler = (_, error) => {
1008
+ // immediately set isRenderable to false, so that we handle the error
1009
+ // without waiting for the next frame loop
1010
+ this.textureLoaded = false;
1011
+ this.isRenderable = false;
1012
+ this.updateTextureOwnership(false);
1013
+ this.setUpdateType(UpdateType.IsRenderable);
1014
+
1015
+ // If parent has a render texture, flag that we need to update
1016
+ if (this.parentHasRenderTexture) {
1017
+ this.notifyParentRTTOfUpdate();
1018
+ }
1019
+
1020
+ if (
1021
+ this.texture !== null &&
1022
+ this.texture.retryCount > this.texture.maxRetryCount
1023
+ ) {
1024
+ this.emit('failed', {
1025
+ type: 'texture',
1026
+ error,
1027
+ } satisfies NodeTextureFailedPayload);
1028
+ }
1029
+ };
1030
+
1031
+ private onTextureFreed: TextureFreedEventHandler = () => {
1032
+ // immediately set isRenderable to false, so that we handle the error
1033
+ // without waiting for the next frame loop
1034
+ this.textureLoaded = false;
1035
+ this.isRenderable = false;
1036
+ this.updateTextureOwnership(false);
1037
+ this.setUpdateType(UpdateType.IsRenderable);
1038
+
1039
+ // If parent has a render texture, flag that we need to update
1040
+ if (this.parentHasRenderTexture) {
1041
+ this.notifyParentRTTOfUpdate();
1042
+ }
1043
+
1044
+ this.emit('freed', {
1045
+ type: 'texture',
1046
+ } satisfies NodeTextureFreedPayload);
1047
+ };
1048
+ //#endregion Textures
1049
+
1050
+ /**
1051
+ * Change types types is used to determine the scope of the changes being applied
1052
+ *
1053
+ * @remarks
1054
+ * See {@link UpdateType} for more information on each type
1055
+ *
1056
+ * @param type
1057
+ */
1058
+ setUpdateType(type: UpdateType): void {
1059
+ this.updateType |= type;
1060
+
1061
+ const parent = this.props.parent;
1062
+ if (!parent || parent.updateType & UpdateType.Children) return;
1063
+
1064
+ parent.setUpdateType(UpdateType.Children);
1065
+ }
1066
+
1067
+ updateLocalTransform() {
1068
+ const p = this.props;
1069
+ const { x, y } = p;
1070
+
1071
+ if (this.isSimple) {
1072
+ this.localTransform = Matrix3d.translate(x, y, this.localTransform);
1073
+ return;
1074
+ }
1075
+
1076
+ const { w, h } = p;
1077
+ const mountTranslateX = p.mountX * w;
1078
+ const mountTranslateY = p.mountY * h;
1079
+
1080
+ if (p.rotation !== 0 || p.scaleX !== 1 || p.scaleY !== 1) {
1081
+ const scaleRotate = Matrix3d.rotate(p.rotation, Matrix3d.temp).scale(
1082
+ p.scaleX,
1083
+ p.scaleY,
1084
+ );
1085
+ const pivotTranslateX = p.pivotX * w;
1086
+ const pivotTranslateY = p.pivotY * h;
1087
+
1088
+ this.localTransform = Matrix3d.translate(
1089
+ x - mountTranslateX + pivotTranslateX,
1090
+ y - mountTranslateY + pivotTranslateY,
1091
+ this.localTransform,
1092
+ )
1093
+ .multiply(scaleRotate)
1094
+ .translate(-pivotTranslateX, -pivotTranslateY);
1095
+ } else {
1096
+ this.localTransform = Matrix3d.translate(
1097
+ x - mountTranslateX,
1098
+ y - mountTranslateY,
1099
+ this.localTransform,
1100
+ );
1101
+ }
1102
+
1103
+ // Handle 'contain' resize mode
1104
+ const texture = p.texture;
1105
+ if (
1106
+ texture &&
1107
+ texture.dimensions &&
1108
+ p.textureOptions.resizeMode?.type === 'contain'
1109
+ ) {
1110
+ let resizeModeScaleX = 1;
1111
+ let resizeModeScaleY = 1;
1112
+ let extraX = 0;
1113
+ let extraY = 0;
1114
+ const { w: tw, h: th } = texture.dimensions;
1115
+ const txAspectRatio = tw / th;
1116
+ const nodeAspectRatio = w / h;
1117
+ if (txAspectRatio > nodeAspectRatio) {
1118
+ // Texture is wider than node
1119
+ // Center the node vertically (shift down by extraY)
1120
+ // Scale the node vertically to maintain original aspect ratio
1121
+ const scaleX = w / tw;
1122
+ const scaledTxHeight = th * scaleX;
1123
+ extraY = (h - scaledTxHeight) / 2;
1124
+ resizeModeScaleY = scaledTxHeight / h;
1125
+ } else {
1126
+ // Texture is taller than node (or equal)
1127
+ // Center the node horizontally (shift right by extraX)
1128
+ // Scale the node horizontally to maintain original aspect ratio
1129
+ const scaleY = h / th;
1130
+ const scaledTxWidth = tw * scaleY;
1131
+ extraX = (w - scaledTxWidth) / 2;
1132
+ resizeModeScaleX = scaledTxWidth / w;
1133
+ }
1134
+
1135
+ // Apply the extra translation and scale to the local transform
1136
+ this.localTransform
1137
+ .translate(extraX, extraY)
1138
+ .scale(resizeModeScaleX, resizeModeScaleY);
1139
+ }
1140
+ }
1141
+
1142
+ updateIsSimple() {
1143
+ const p = this.props;
1144
+ this.isSimple =
1145
+ p.rotation === 0 &&
1146
+ p.scaleX === 1 &&
1147
+ p.scaleY === 1 &&
1148
+ p.mountX === 0 &&
1149
+ p.mountY === 0 &&
1150
+ !(p.texture && p.textureOptions.resizeMode?.type === 'contain');
1151
+ }
1152
+
1153
+ /**
1154
+ * @todo: test for correct calculation flag
1155
+ * @param delta
1156
+ */
1157
+ update(delta: number, parentClippingRect: RectWithValid): void {
1158
+ const props = this.props;
1159
+ //parent can be forced to ! because the root node update loop uses updateRoot which implies that
1160
+ //all other loops using this update method have a parent
1161
+ const parent = props.parent!;
1162
+ const parentHasRenderTexture = this.parentHasRenderTexture;
1163
+ let newRenderState: CoreNodeRenderState | null = null;
1164
+ let updateType = this.updateType;
1165
+ let childUpdateType = this.childUpdateType;
1166
+
1167
+ //this needs to be handled before setting updateTypes are reset
1168
+ if (
1169
+ ENABLE_AUTOSIZE &&
1170
+ updateType & UpdateType.Autosize &&
1171
+ this.autosizer !== null
1172
+ ) {
1173
+ this.autosizer.update();
1174
+ }
1175
+
1176
+ // reset update type
1177
+ this.updateType = 0;
1178
+ this.childUpdateType = 0;
1179
+
1180
+ if (updateType & UpdateType.Local) {
1181
+ this.updateLocalTransform();
1182
+
1183
+ updateType |= UpdateType.Global;
1184
+ }
1185
+
1186
+ // Handle specific RTT updates at this node level
1187
+ if (USE_RTT && updateType & UpdateType.RenderTexture && this.rtt === true) {
1188
+ this.hasRTTupdates = true;
1189
+ }
1190
+
1191
+ if (updateType & UpdateType.Global) {
1192
+ if (
1193
+ USE_RTT &&
1194
+ this.parentHasRenderTexture === true &&
1195
+ parent.rtt === true
1196
+ ) {
1197
+ // we are at the start of the RTT chain, so we need to reset the globalTransform
1198
+ // for correct RTT rendering
1199
+ this.globalTransform = Matrix3d.identity(this.globalTransform);
1200
+
1201
+ // Maintain a full scene global transform for bounds detection
1202
+ const parentTransform =
1203
+ parent.globalTransform || Matrix3d.identity(Matrix3d.temp);
1204
+
1205
+ this.sceneGlobalTransform = Matrix3d.copy(
1206
+ parentTransform,
1207
+ this.sceneGlobalTransform,
1208
+ ).translateOrMultiply(this.localTransform!);
1209
+ } else if (
1210
+ USE_RTT &&
1211
+ this.parentHasRenderTexture === true &&
1212
+ parent.rtt === false
1213
+ ) {
1214
+ // we're part of an RTT chain but our parent is not the main RTT node
1215
+ // so we need to propogate the sceneGlobalTransform of the parent
1216
+ // to maintain a full scene global transform for bounds detection
1217
+ const parentSceneTransform =
1218
+ parent.sceneGlobalTransform || this.localTransform!;
1219
+
1220
+ this.sceneGlobalTransform = Matrix3d.copy(
1221
+ parentSceneTransform,
1222
+ this.sceneGlobalTransform,
1223
+ ).translateOrMultiply(this.localTransform!);
1224
+
1225
+ this.globalTransform = Matrix3d.copy(
1226
+ parent.globalTransform || this.localTransform!,
1227
+ this.globalTransform,
1228
+ );
1229
+ } else {
1230
+ this.globalTransform = Matrix3d.copy(
1231
+ parent.globalTransform || this.localTransform!,
1232
+ this.globalTransform,
1233
+ );
1234
+ }
1235
+
1236
+ if (this.isSimple) {
1237
+ this.globalTransform.translate(
1238
+ this.localTransform!.tx,
1239
+ this.localTransform!.ty,
1240
+ );
1241
+ } else {
1242
+ this.globalTransform.translateOrMultiply(this.localTransform!);
1243
+ }
1244
+ this.calculateRenderCoords();
1245
+ this.updateBoundingRect();
1246
+
1247
+ updateType |= UpdateType.RenderState | UpdateType.RecalcUniforms;
1248
+
1249
+ //only propagate children updates if not autosizing
1250
+ if ((updateType & UpdateType.Autosize) === 0) {
1251
+ updateType |= UpdateType.Children;
1252
+ childUpdateType |= UpdateType.Global;
1253
+ }
1254
+
1255
+ if (this.clipping === true) {
1256
+ updateType |= UpdateType.Clipping | UpdateType.RenderBounds;
1257
+ childUpdateType |= UpdateType.RenderBounds;
1258
+ }
1259
+ }
1260
+
1261
+ if (updateType & UpdateType.RenderBounds) {
1262
+ this.createRenderBounds();
1263
+
1264
+ updateType |= UpdateType.RenderState | UpdateType.Children;
1265
+ childUpdateType |= UpdateType.RenderBounds;
1266
+ }
1267
+
1268
+ if (updateType & UpdateType.RenderState) {
1269
+ newRenderState = this.checkRenderBounds();
1270
+ updateType |= UpdateType.IsRenderable;
1271
+
1272
+ // if we're not going out of bounds, update the render state
1273
+ // this is done so the update loop can finish before we mark a node
1274
+ // as out of bounds
1275
+ if (newRenderState !== CoreNodeRenderState.OutOfBounds) {
1276
+ this.updateRenderState(newRenderState);
1277
+ }
1278
+ }
1279
+
1280
+ if (updateType & UpdateType.WorldAlpha) {
1281
+ this.worldAlpha = parent.worldAlpha * this.props.alpha;
1282
+ updateType |=
1283
+ UpdateType.PremultipliedColors |
1284
+ UpdateType.Children |
1285
+ UpdateType.IsRenderable;
1286
+ childUpdateType |= UpdateType.WorldAlpha;
1287
+ }
1288
+
1289
+ if (updateType & UpdateType.IsRenderable) {
1290
+ this.updateIsRenderable();
1291
+ }
1292
+
1293
+ // Handle autosize updates when children transforms change
1294
+ if (
1295
+ ENABLE_AUTOSIZE &&
1296
+ updateType & UpdateType.Global &&
1297
+ this.isRenderable === true &&
1298
+ this.parentAutosizer !== null
1299
+ ) {
1300
+ this.parentAutosizer.patch(this.id);
1301
+ }
1302
+
1303
+ if (updateType & UpdateType.Clipping) {
1304
+ this.calculateClippingRect(parentClippingRect);
1305
+ updateType |= UpdateType.Children;
1306
+ childUpdateType |= UpdateType.Clipping | UpdateType.RenderBounds;
1307
+ }
1308
+
1309
+ if (updateType & UpdateType.PremultipliedColors) {
1310
+ const alpha = this.worldAlpha;
1311
+
1312
+ const tl = props.colorTl;
1313
+ const tr = props.colorTr;
1314
+ const bl = props.colorBl;
1315
+ const br = props.colorBr;
1316
+
1317
+ // Fast equality check (covers all 4 corners)
1318
+ const same = tl === tr && tl === bl && tl === br;
1319
+
1320
+ const merged = premultiplyColorABGR(tl, alpha);
1321
+
1322
+ this.premultipliedColorTl = merged;
1323
+
1324
+ if (same === true) {
1325
+ this.premultipliedColorTr =
1326
+ this.premultipliedColorBl =
1327
+ this.premultipliedColorBr =
1328
+ merged;
1329
+ } else {
1330
+ this.premultipliedColorTr = premultiplyColorABGR(tr, alpha);
1331
+ this.premultipliedColorBl = premultiplyColorABGR(bl, alpha);
1332
+ this.premultipliedColorBr = premultiplyColorABGR(br, alpha);
1333
+ }
1334
+ }
1335
+
1336
+ if (this.renderState === CoreNodeRenderState.OutOfBounds) {
1337
+ // Delay updating children until the node is in bounds
1338
+ this.updateType = updateType;
1339
+ this.childUpdateType = childUpdateType;
1340
+ return;
1341
+ }
1342
+
1343
+ if (
1344
+ updateType & UpdateType.RecalcUniforms &&
1345
+ this.hasShaderUpdater === true
1346
+ ) {
1347
+ this.updateShaderUniforms = true;
1348
+ }
1349
+
1350
+ if (this.isRenderable === true && this.updateShaderUniforms === true) {
1351
+ this.updateShaderUniforms = false;
1352
+ //this exists because the boolean hasShaderUpdater === true
1353
+ this.shader!.update!();
1354
+ }
1355
+
1356
+ if (updateType & UpdateType.Children && this.children.length > 0) {
1357
+ let childClippingRect = this.clippingRect;
1358
+
1359
+ if (USE_RTT && this.rtt === true) {
1360
+ childClippingRect = NO_CLIPPING_RECT;
1361
+ }
1362
+
1363
+ for (let i = 0, length = this.children.length; i < length; i++) {
1364
+ const child = this.children[i] as CoreNode;
1365
+
1366
+ if (childUpdateType !== 0) {
1367
+ child.updateType |= childUpdateType;
1368
+ }
1369
+
1370
+ if (child.updateType === 0) {
1371
+ continue;
1372
+ }
1373
+
1374
+ child.update(delta, childClippingRect);
1375
+ }
1376
+ }
1377
+
1378
+ // If the node has an RTT parent and requires a texture re-render, inform the RTT parent
1379
+ // if (this.parentHasRenderTexture && updateType & UpdateType.RenderTexture) {
1380
+ // @TODO have a more scoped down updateType for RTT updates
1381
+ if (USE_RTT === true && parentHasRenderTexture === true) {
1382
+ this.notifyParentRTTOfUpdate();
1383
+ }
1384
+
1385
+ //Resort children if needed
1386
+ if (updateType & UpdateType.SortZIndexChildren) {
1387
+ // reorder z-index
1388
+ this.sortChildren();
1389
+ }
1390
+
1391
+ // If we're out of bounds, apply the render state now
1392
+ // this is done so nodes can finish their entire update loop before
1393
+ // being marked as out of bounds
1394
+ if (newRenderState === CoreNodeRenderState.OutOfBounds) {
1395
+ this.updateRenderState(newRenderState);
1396
+ this.updateIsRenderable();
1397
+
1398
+ if (
1399
+ USE_RTT === true &&
1400
+ this.rtt === true &&
1401
+ newRenderState === CoreNodeRenderState.OutOfBounds
1402
+ ) {
1403
+ // notify children that we are going out of bounds
1404
+ // we have to do this now before we stop processing the render tree
1405
+ this.notifyChildrenRTTOfUpdate(newRenderState);
1406
+ }
1407
+ }
1408
+
1409
+ // Mark quad dirty only when visual data (transforms, colors) actually
1410
+ // changed, so the WebGL renderer only re-uploads modified slots.
1411
+ if (
1412
+ updateType &
1413
+ (UpdateType.Global |
1414
+ UpdateType.PremultipliedColors |
1415
+ UpdateType.WorldAlpha)
1416
+ ) {
1417
+ this.isQuadDirty = true;
1418
+ }
1419
+ }
1420
+
1421
+ private findParentRTTNode(): CoreNode | null {
1422
+ let rttNode: CoreNode | null = this.parent;
1423
+ while (rttNode && !rttNode.rtt) {
1424
+ rttNode = rttNode.parent;
1425
+ }
1426
+ return rttNode;
1427
+ }
1428
+
1429
+ private notifyChildrenRTTOfUpdate(renderState: CoreNodeRenderState) {
1430
+ for (const child of this.children) {
1431
+ // force child to update render state
1432
+ child.updateRenderState(renderState);
1433
+ child.updateIsRenderable();
1434
+ child.notifyChildrenRTTOfUpdate(renderState);
1435
+ }
1436
+ }
1437
+
1438
+ protected notifyParentRTTOfUpdate() {
1439
+ if (this.parent === null) {
1440
+ return;
1441
+ }
1442
+
1443
+ const rttNode = this.rttParent || this.findParentRTTNode();
1444
+ if (!rttNode) {
1445
+ return;
1446
+ }
1447
+
1448
+ // If an RTT node is found, mark it for re-rendering
1449
+ rttNode.hasRTTupdates = true;
1450
+ rttNode.setUpdateType(UpdateType.RenderTexture);
1451
+
1452
+ // if rttNode is nested, also make it update its RTT parent
1453
+ if (rttNode.parentHasRenderTexture === true) {
1454
+ rttNode.notifyParentRTTOfUpdate();
1455
+ }
1456
+ }
1457
+
1458
+ checkRenderBounds(): CoreNodeRenderState {
1459
+ if (boundInsideBound(this.renderBound!, this.strictBound!)) {
1460
+ return CoreNodeRenderState.InViewport;
1461
+ }
1462
+
1463
+ if (boundInsideBound(this.renderBound!, this.preloadBound!)) {
1464
+ return CoreNodeRenderState.InBounds;
1465
+ }
1466
+
1467
+ // check if we're larger then our parent, we're definitely in the viewport
1468
+ if (boundLargeThanBound(this.renderBound!, this.strictBound!)) {
1469
+ return CoreNodeRenderState.InViewport;
1470
+ }
1471
+
1472
+ // check if we dont have dimensions, take our parent's render state
1473
+ if (this.parent !== null && (this.props.w === 0 || this.props.h === 0)) {
1474
+ return this.parent.renderState;
1475
+ }
1476
+
1477
+ return CoreNodeRenderState.OutOfBounds;
1478
+ }
1479
+
1480
+ updateBoundingRect() {
1481
+ const transform = (this.sceneGlobalTransform ||
1482
+ this.globalTransform) as Matrix3d;
1483
+ const renderCoords = (this.sceneRenderCoords ||
1484
+ this.renderCoords) as RenderCoords;
1485
+
1486
+ if (transform.tb === 0 || transform.tc === 0) {
1487
+ this.renderBound = createBound(
1488
+ renderCoords.x1,
1489
+ renderCoords.y1,
1490
+ renderCoords.x3,
1491
+ renderCoords.y3,
1492
+ this.renderBound,
1493
+ );
1494
+ } else {
1495
+ const { x1, y1, x2, y2, x3, y3, x4, y4 } = renderCoords;
1496
+ this.renderBound = createBound(
1497
+ Math.min(x1, x2, x3, x4),
1498
+ Math.min(y1, y2, y3, y4),
1499
+ Math.max(x1, x2, x3, x4),
1500
+ Math.max(y1, y2, y3, y4),
1501
+ this.renderBound,
1502
+ );
1503
+ }
1504
+ }
1505
+
1506
+ createRenderBounds(): void {
1507
+ if (this.parent !== null && this.parent.strictBound !== undefined) {
1508
+ // we have a parent with a valid bound, copy it
1509
+ const parentBound = this.parent.strictBound;
1510
+ this.strictBound = createBound(
1511
+ parentBound.x1,
1512
+ parentBound.y1,
1513
+ parentBound.x2,
1514
+ parentBound.y2,
1515
+ this.strictBound,
1516
+ );
1517
+
1518
+ this.preloadBound = createPreloadBounds(
1519
+ this.strictBound,
1520
+ this.boundsMargin as [number, number, number, number],
1521
+ this.preloadBound,
1522
+ );
1523
+ } else {
1524
+ // no parent or parent does not have a bound, take the stage boundaries
1525
+ this.strictBound = this.stage.strictBound;
1526
+ this.preloadBound = this.stage.preloadBound;
1527
+ }
1528
+
1529
+ // if clipping is disabled, we're done
1530
+ if (this.props.clipping === false) {
1531
+ return;
1532
+ }
1533
+
1534
+ // only create local clipping bounds if node itself is in bounds
1535
+ // this can only be done if we have a render bound already
1536
+ if (this.renderBound === undefined) {
1537
+ return;
1538
+ }
1539
+
1540
+ // if we're out of bounds, we're done
1541
+ if (boundInsideBound(this.renderBound, this.strictBound) === false) {
1542
+ return;
1543
+ }
1544
+
1545
+ // clipping is enabled and we are in bounds create our own bounds
1546
+ const { x, y, w, h } = this.props;
1547
+
1548
+ // Pick the global transform if available, otherwise use the local transform
1549
+ // global transform is only available if the node in an RTT chain
1550
+ const { tx, ty } = this.sceneGlobalTransform || this.globalTransform || {};
1551
+ const _x = tx ?? x;
1552
+ const _y = ty ?? y;
1553
+ this.strictBound = createBound(_x, _y, _x + w, _y + h, this.strictBound);
1554
+
1555
+ this.preloadBound = createPreloadBounds(
1556
+ this.strictBound,
1557
+ this.boundsMargin as [number, number, number, number],
1558
+ this.preloadBound,
1559
+ );
1560
+ }
1561
+
1562
+ updateRenderState(renderState: CoreNodeRenderState) {
1563
+ if (renderState === this.renderState) {
1564
+ return;
1565
+ }
1566
+
1567
+ const previous = this.renderState;
1568
+ this.renderState = renderState;
1569
+
1570
+ // If node visibility changes, dirty the render list cache
1571
+ if (
1572
+ renderState === CoreNodeRenderState.OutOfBounds ||
1573
+ previous === CoreNodeRenderState.OutOfBounds
1574
+ ) {
1575
+ this.stage.requestRenderListUpdate();
1576
+ }
1577
+
1578
+ if (EMIT_BOUNDS_EVENTS) {
1579
+ const event = CoreNodeRenderStateMap.get(renderState);
1580
+ assertTruthy(event);
1581
+ this.emit(event, {
1582
+ previous,
1583
+ current: renderState,
1584
+ });
1585
+ }
1586
+ }
1587
+
1588
+ /**
1589
+ * Checks if the node is renderable based on world alpha, dimensions and out of bounds status.
1590
+ */
1591
+ checkBasicRenderability(): boolean {
1592
+ if (this.worldAlpha === 0 || this.isOutOfBounds() === true) {
1593
+ return false;
1594
+ } else {
1595
+ return true;
1596
+ }
1597
+ }
1598
+
1599
+ /**
1600
+ * Updates the `isRenderable` property based on various conditions.
1601
+ */
1602
+ updateIsRenderable() {
1603
+ let newIsRenderable = false;
1604
+ let needsTextureOwnership = false;
1605
+
1606
+ // If the node is out of bounds or has an alpha of 0, it is not renderable
1607
+ if (this.checkBasicRenderability() === false) {
1608
+ this.updateTextureOwnership(false);
1609
+ this.setRenderable(false);
1610
+ return;
1611
+ }
1612
+
1613
+ if (this.texture !== null) {
1614
+ // preemptive check for failed textures this will mark the current node as non-renderable
1615
+ // and will prevent further checks until the texture is reloaded or retry is reset on the texture
1616
+ if (this.texture.retryCount > this.texture.maxRetryCount) {
1617
+ // texture has failed to load, we cannot render
1618
+ this.updateTextureOwnership(false);
1619
+ this.setRenderable(false);
1620
+ return;
1621
+ }
1622
+
1623
+ needsTextureOwnership = true;
1624
+ // Use cached boolean instead of string comparison
1625
+ newIsRenderable = this.textureLoaded;
1626
+ } else if (
1627
+ // check shader
1628
+ (this.props.shader !== this.stage.renderer.getDefaultShaderNode() ||
1629
+ this.hasColorProps === true) &&
1630
+ // check dimensions
1631
+ this.hasDimensions() === true
1632
+ ) {
1633
+ // This mean we have dimensions and a color set, so we can render a ColorTexture
1634
+ newIsRenderable = true;
1635
+ }
1636
+
1637
+ this.updateTextureOwnership(needsTextureOwnership);
1638
+ this.setRenderable(newIsRenderable);
1639
+ }
1640
+
1641
+ /**
1642
+ * Sets the renderable state and triggers changes if necessary.
1643
+ * @param isRenderable - The new renderable state
1644
+ */
1645
+ setRenderable(isRenderable: boolean) {
1646
+ const previousIsRenderable = this.isRenderable;
1647
+ this.isRenderable = isRenderable;
1648
+
1649
+ // Emit event if renderable status has changed
1650
+ if (previousIsRenderable !== isRenderable) {
1651
+ this.stage.requestRenderListUpdate();
1652
+ if (EMIT_BOUNDS_EVENTS) {
1653
+ this.emit('renderable', {
1654
+ type: 'renderable',
1655
+ isRenderable,
1656
+ } satisfies NodeRenderablePayload);
1657
+ }
1658
+ }
1659
+ }
1660
+
1661
+ /**
1662
+ * Changes the renderable state of the node.
1663
+ */
1664
+ updateTextureOwnership(isRenderable: boolean) {
1665
+ this.texture?.setRenderableOwner(this._id, isRenderable);
1666
+ }
1667
+
1668
+ /**
1669
+ * Checks if the node is out of the viewport bounds.
1670
+ */
1671
+ isOutOfBounds(): boolean {
1672
+ return this.renderState <= CoreNodeRenderState.OutOfBounds;
1673
+ }
1674
+
1675
+ /**
1676
+ * Checks if the node has dimensions (width/height)
1677
+ */
1678
+ hasDimensions(): boolean {
1679
+ return this.props.w !== 0 && this.props.h !== 0;
1680
+ }
1681
+
1682
+ calculateRenderCoords() {
1683
+ const { w, h } = this.props;
1684
+
1685
+ const g = this.globalTransform!;
1686
+ const tx = g.tx,
1687
+ ty = g.ty,
1688
+ ta = g.ta,
1689
+ tb = g.tb,
1690
+ tc = g.tc,
1691
+ td = g.td;
1692
+ if (tb === 0 && tc === 0) {
1693
+ const minX = tx;
1694
+ const maxX = tx + w * ta;
1695
+ const minY = ty;
1696
+ const maxY = ty + h * td;
1697
+ this.renderCoords = RenderCoords.translate(
1698
+ //top-left
1699
+ minX,
1700
+ minY,
1701
+ //top-right
1702
+ maxX,
1703
+ minY,
1704
+ //bottom-right
1705
+ maxX,
1706
+ maxY,
1707
+ //bottom-left
1708
+ minX,
1709
+ maxY,
1710
+ this.renderCoords,
1711
+ );
1712
+ } else {
1713
+ this.renderCoords = RenderCoords.translate(
1714
+ //top-left
1715
+ tx,
1716
+ ty,
1717
+ //top-right
1718
+ tx + w * ta,
1719
+ ty + w * tc,
1720
+ //bottom-right
1721
+ tx + w * ta + h * tb,
1722
+ ty + w * tc + h * td,
1723
+ //bottom-left
1724
+ tx + h * tb,
1725
+ ty + h * td,
1726
+ this.renderCoords,
1727
+ );
1728
+ }
1729
+ if (!USE_RTT || this.sceneGlobalTransform === undefined) {
1730
+ return;
1731
+ }
1732
+
1733
+ const {
1734
+ tx: stx,
1735
+ ty: sty,
1736
+ ta: sta,
1737
+ tb: stb,
1738
+ tc: stc,
1739
+ td: std,
1740
+ } = this.sceneGlobalTransform;
1741
+ if (stb === 0 && stc === 0) {
1742
+ const minX = stx;
1743
+ const maxX = stx + w * sta;
1744
+ const minY = sty;
1745
+ const maxY = sty + h * std;
1746
+ this.sceneRenderCoords = RenderCoords.translate(
1747
+ //top-left
1748
+ minX,
1749
+ minY,
1750
+ //top-right
1751
+ maxX,
1752
+ minY,
1753
+ //bottom-right
1754
+ maxX,
1755
+ maxY,
1756
+ //bottom-left
1757
+ minX,
1758
+ maxY,
1759
+ this.sceneRenderCoords,
1760
+ );
1761
+ } else {
1762
+ this.sceneRenderCoords = RenderCoords.translate(
1763
+ //top-left
1764
+ stx,
1765
+ sty,
1766
+ //top-right
1767
+ stx + w * sta,
1768
+ sty + w * stc,
1769
+ //bottom-right
1770
+ stx + w * sta + h * stb,
1771
+ sty + w * stc + h * std,
1772
+ //bottom-left
1773
+ stx + h * stb,
1774
+ sty + h * std,
1775
+ this.sceneRenderCoords,
1776
+ );
1777
+ }
1778
+ }
1779
+
1780
+ /**
1781
+ * This function calculates the clipping rectangle for a node.
1782
+ *
1783
+ * The function then checks if the node is rotated. If the node requires clipping and is not rotated, a new clipping rectangle is created based on the node's global transform and dimensions.
1784
+ * If a parent clipping rectangle exists, it is intersected with the node's clipping rectangle (if it exists), or replaces the node's clipping rectangle.
1785
+ *
1786
+ * Finally, the node's parentClippingRect and clippingRect properties are updated.
1787
+ */
1788
+ calculateClippingRect(parentClippingRect: RectWithValid) {
1789
+ const { clippingRect, props, globalTransform: gt } = this;
1790
+ const { clipping } = props;
1791
+ const isRotated = gt!.tb !== 0 || gt!.tc !== 0;
1792
+
1793
+ if (clipping === true && isRotated === false) {
1794
+ clippingRect.x = gt!.tx;
1795
+ clippingRect.y = gt!.ty;
1796
+ clippingRect.width = this.props.w * gt!.ta;
1797
+ clippingRect.height = this.props.h * gt!.td;
1798
+ clippingRect.valid = true;
1799
+ } else {
1800
+ clippingRect.valid = false;
1801
+ }
1802
+
1803
+ if (parentClippingRect.valid === true && clippingRect.valid === true) {
1804
+ // Intersect parent clipping rect with node clipping rect
1805
+ intersectRect(parentClippingRect, clippingRect, clippingRect);
1806
+ } else if (parentClippingRect.valid === true) {
1807
+ // Copy parent clipping rect
1808
+ copyRect(parentClippingRect, clippingRect);
1809
+ clippingRect.valid = true;
1810
+ }
1811
+ }
1812
+
1813
+ /**
1814
+ * Destroy the node and cleanup all resources
1815
+ */
1816
+ destroy(isChild: boolean = false): void {
1817
+ if (this.destroyed === true || this.preventDestroy === true) {
1818
+ if (isChild && this.preventDestroy === true) {
1819
+ this.props.parent = null;
1820
+ }
1821
+ return;
1822
+ }
1823
+ this.destroyed = true;
1824
+
1825
+ // Detach from parent first to stop propagation of updates
1826
+ if (isChild === false) {
1827
+ const parent = this.parent;
1828
+ if (parent !== null) {
1829
+ parent.removeChild(this);
1830
+ }
1831
+ this.props.parent = null;
1832
+ this.stage.requestRender();
1833
+ }
1834
+
1835
+ this.removeAllListeners();
1836
+ this.unloadTexture();
1837
+ this.isRenderable = false;
1838
+
1839
+ if (this.hasShaderTimeFn === true) {
1840
+ this.stage.untrackTimedNode(this);
1841
+ }
1842
+
1843
+ if (USE_RTT && this.rtt === true) {
1844
+ this.stage.renderer.removeRTTNode(this);
1845
+ }
1846
+
1847
+ // Kill children
1848
+ for (let i = 0, n = this.children.length; i < n; i++) {
1849
+ this.children[i]!.destroy(true);
1850
+ }
1851
+ this.children.length = 0;
1852
+
1853
+ this.props.texture = null;
1854
+ }
1855
+
1856
+ renderQuads(renderer: CoreRenderer): void {
1857
+ if (USE_RTT && this.parentHasRenderTexture === true) {
1858
+ const rtt = renderer.renderToTextureActive;
1859
+ if (rtt === false || this.parentRenderTexture !== renderer.activeRttNode)
1860
+ return;
1861
+ }
1862
+ // There is a race condition where the texture can be null
1863
+ // with RTT nodes. Adding this defensively to avoid errors.
1864
+ // Also check if we have a valid texture or default texture to render
1865
+ if (USE_RTT && this.renderTexture!.state !== 'loaded') {
1866
+ return;
1867
+ }
1868
+
1869
+ renderer.addQuad(this);
1870
+ }
1871
+
1872
+ get renderTexture(): Texture | null {
1873
+ return this.props.texture || this.stage.defaultTexture;
1874
+ }
1875
+
1876
+ get renderTextureCoords(): TextureCoords | undefined {
1877
+ return this.textureCoords || this.stage.renderer.defaultTextureCoords;
1878
+ }
1879
+
1880
+ get quadBufferCollection(): BufferCollection {
1881
+ return (this.stage.renderer as WebGlRenderer).quadBufferCollection;
1882
+ }
1883
+
1884
+ get width(): number {
1885
+ return this.props.w;
1886
+ }
1887
+
1888
+ get height(): number {
1889
+ return this.props.h;
1890
+ }
1891
+
1892
+ get time(): number {
1893
+ if (this.hasShaderTimeFn === true) {
1894
+ return this.getTimerValue();
1895
+ }
1896
+ return 0;
1897
+ }
1898
+
1899
+ getTimerValue(): number {
1900
+ if (typeof this.shader!.time === 'function') {
1901
+ return this.shader!.time(this.stage);
1902
+ }
1903
+ return this.stage.elapsedTime;
1904
+ }
1905
+
1906
+ sortChildren() {
1907
+ this.children.sort((a, b) => a.props.zIndex - b.props.zIndex);
1908
+ this.stage.requestRenderListUpdate();
1909
+ }
1910
+
1911
+ removeChild(node: CoreNode, targetParent: CoreNode | null = null) {
1912
+ if (targetParent === null) {
1913
+ if (
1914
+ USE_RTT &&
1915
+ this.props.rtt === true &&
1916
+ this.parentHasRenderTexture === true
1917
+ ) {
1918
+ node.clearRTTInheritance();
1919
+ }
1920
+
1921
+ if (ENABLE_AUTOSIZE) {
1922
+ const autosizeTarget = this.autosizer || this.parentAutosizer;
1923
+ if (autosizeTarget !== null) {
1924
+ autosizeTarget.detach(node);
1925
+ }
1926
+ }
1927
+ }
1928
+ removeChild(node, this.children);
1929
+ this.stage.requestRenderListUpdate();
1930
+ }
1931
+
1932
+ addChild(node: CoreNode, previousParent: CoreNode | null = null) {
1933
+ const inRttCluster =
1934
+ USE_RTT &&
1935
+ (this.props.rtt === true || this.parentHasRenderTexture === true);
1936
+ const children = this.children;
1937
+ let attachToAutosizer = false;
1938
+ let autosizeTarget: Autosizer | null = null;
1939
+ if (ENABLE_AUTOSIZE) {
1940
+ autosizeTarget = this.autosizer || this.parentAutosizer;
1941
+ attachToAutosizer = autosizeTarget !== null;
1942
+ }
1943
+
1944
+ node.parentHasRenderTexture = inRttCluster;
1945
+ if (previousParent !== null) {
1946
+ const previousParentInRttCluster =
1947
+ USE_RTT &&
1948
+ (previousParent.props.rtt === true ||
1949
+ previousParent.parentHasRenderTexture === true);
1950
+ if (inRttCluster === false && previousParentInRttCluster === true) {
1951
+ // update child RTT status
1952
+ node.clearRTTInheritance();
1953
+ }
1954
+
1955
+ if (ENABLE_AUTOSIZE) {
1956
+ const previousAutosizer = node.autosizer || node.parentAutosizer;
1957
+ if (previousAutosizer !== null) {
1958
+ if (!autosizeTarget || previousAutosizer.id !== autosizeTarget.id) {
1959
+ previousAutosizer.detach(node);
1960
+ }
1961
+ attachToAutosizer = false;
1962
+ }
1963
+ }
1964
+ }
1965
+
1966
+ if (ENABLE_AUTOSIZE && attachToAutosizer === true && autosizeTarget) {
1967
+ //if this is true, then the autosizer really exists
1968
+ autosizeTarget.attach(node);
1969
+ }
1970
+
1971
+ if (inRttCluster === true) {
1972
+ node.markChildrenWithRTT(this);
1973
+ }
1974
+
1975
+ children.push(node);
1976
+
1977
+ // check if we need to sort
1978
+ const lastIndex = children.length - 1;
1979
+ let shouldSort = node.zIndex !== 0;
1980
+
1981
+ if (shouldSort === false && lastIndex > 0) {
1982
+ // If the new node has zIndex 0, we check if any existing children have (had) non-zero zIndex.
1983
+ // Since children are sorted, we only need to check the first and the last (before the new one).
1984
+ // The new node is at `lastIndex`. The previous last node is at `lastIndex - 1`.
1985
+ const first = children[0]!;
1986
+ const last = children[lastIndex - 1]!;
1987
+ shouldSort = first.zIndex !== 0 || last.zIndex !== 0;
1988
+ }
1989
+
1990
+ if (shouldSort) {
1991
+ this.setUpdateType(UpdateType.SortZIndexChildren);
1992
+ }
1993
+ this.setUpdateType(UpdateType.Children);
1994
+ this.stage.requestRenderListUpdate();
1995
+ }
1996
+
1997
+ //#region Properties
1998
+ get id(): number {
1999
+ return this._id;
2000
+ }
2001
+
2002
+ get data(): CustomDataMap | undefined {
2003
+ return this.props.data;
2004
+ }
2005
+
2006
+ set data(d: CustomDataMap | undefined) {
2007
+ this.props.data = d;
2008
+ }
2009
+
2010
+ get x(): number {
2011
+ return this.props.x;
2012
+ }
2013
+
2014
+ set x(value: number) {
2015
+ if (this.props.x !== value) {
2016
+ this.props.x = value;
2017
+ this.setUpdateType(UpdateType.Local);
2018
+ }
2019
+ }
2020
+
2021
+ get absX(): number {
2022
+ return (
2023
+ this.props.x +
2024
+ -this.props.w * this.props.mountX +
2025
+ (this.props.parent?.absX || this.props.parent?.globalTransform?.tx || 0)
2026
+ );
2027
+ }
2028
+
2029
+ get absY(): number {
2030
+ return (
2031
+ this.props.y +
2032
+ -this.props.h * this.props.mountY +
2033
+ (this.props.parent?.absY ?? 0)
2034
+ );
2035
+ }
2036
+
2037
+ get y(): number {
2038
+ return this.props.y;
2039
+ }
2040
+
2041
+ set y(value: number) {
2042
+ if (this.props.y !== value) {
2043
+ this.props.y = value;
2044
+ this.setUpdateType(UpdateType.Local);
2045
+ }
2046
+ }
2047
+
2048
+ get w(): number {
2049
+ return this.props.w;
2050
+ }
2051
+
2052
+ set w(value: number) {
2053
+ const props = this.props;
2054
+ if (props.w !== value) {
2055
+ props.w = value;
2056
+ let updateType = UpdateType.Local;
2057
+
2058
+ if (
2059
+ props.texture !== null &&
2060
+ this.stage.calculateTextureCoord === true &&
2061
+ props.textureOptions !== null
2062
+ ) {
2063
+ this.textureCoords = this.stage.renderer.getTextureCoords!(this);
2064
+ }
2065
+
2066
+ if (props.rtt === true) {
2067
+ this.framebufferDimensions!.w = value;
2068
+ this.texture = this.stage.txManager.createTexture(
2069
+ 'RenderTexture',
2070
+ this.framebufferDimensions!,
2071
+ );
2072
+ updateType |= UpdateType.RenderTexture;
2073
+ }
2074
+ this.setUpdateType(updateType);
2075
+ }
2076
+ }
2077
+
2078
+ get h(): number {
2079
+ return this.props.h;
2080
+ }
2081
+
2082
+ set h(value: number) {
2083
+ const props = this.props;
2084
+ if (props.h !== value) {
2085
+ props.h = value;
2086
+ let updateType = UpdateType.Local;
2087
+
2088
+ if (
2089
+ props.texture !== null &&
2090
+ this.stage.calculateTextureCoord === true &&
2091
+ props.textureOptions !== null
2092
+ ) {
2093
+ this.textureCoords = this.stage.renderer.getTextureCoords!(this);
2094
+ }
2095
+
2096
+ if (props.rtt === true) {
2097
+ this.framebufferDimensions!.h = value;
2098
+ this.texture = this.stage.txManager.createTexture(
2099
+ 'RenderTexture',
2100
+ this.framebufferDimensions!,
2101
+ );
2102
+ updateType |= UpdateType.RenderTexture;
2103
+ }
2104
+ this.setUpdateType(updateType);
2105
+ }
2106
+ }
2107
+
2108
+ get scale(): number {
2109
+ // The CoreNode `scale` property is only used by Animations.
2110
+ // Unlike INode, `null` should never be possibility for Animations.
2111
+ return this.scaleX;
2112
+ }
2113
+
2114
+ set scale(value: number) {
2115
+ // The CoreNode `scale` property is only used by Animations.
2116
+ // Unlike INode, `null` should never be possibility for Animations.
2117
+ this.scaleX = value;
2118
+ this.scaleY = value;
2119
+ this.updateIsSimple();
2120
+ }
2121
+
2122
+ get scaleX(): number {
2123
+ return this.props.scaleX;
2124
+ }
2125
+
2126
+ set scaleX(value: number) {
2127
+ if (this.props.scaleX !== value) {
2128
+ this.props.scaleX = value;
2129
+ this.setUpdateType(UpdateType.Local);
2130
+ this.updateIsSimple();
2131
+ }
2132
+ }
2133
+
2134
+ get scaleY(): number {
2135
+ return this.props.scaleY;
2136
+ }
2137
+
2138
+ set scaleY(value: number) {
2139
+ if (this.props.scaleY !== value) {
2140
+ this.props.scaleY = value;
2141
+ this.setUpdateType(UpdateType.Local);
2142
+ this.updateIsSimple();
2143
+ }
2144
+ }
2145
+
2146
+ get mount(): number {
2147
+ return this.props.mount;
2148
+ }
2149
+
2150
+ set mount(value: number) {
2151
+ if (this.props.mountX !== value || this.props.mountY !== value) {
2152
+ this.props.mountX = value;
2153
+ this.props.mountY = value;
2154
+ this.props.mount = value;
2155
+ this.setUpdateType(UpdateType.Local);
2156
+ this.updateIsSimple();
2157
+ }
2158
+ }
2159
+
2160
+ get mountX(): number {
2161
+ return this.props.mountX;
2162
+ }
2163
+
2164
+ set mountX(value: number) {
2165
+ if (this.props.mountX !== value) {
2166
+ this.props.mountX = value;
2167
+ this.setUpdateType(UpdateType.Local);
2168
+ this.updateIsSimple();
2169
+ }
2170
+ }
2171
+
2172
+ get mountY(): number {
2173
+ return this.props.mountY;
2174
+ }
2175
+
2176
+ set mountY(value: number) {
2177
+ if (this.props.mountY !== value) {
2178
+ this.props.mountY = value;
2179
+ this.setUpdateType(UpdateType.Local);
2180
+ this.updateIsSimple();
2181
+ }
2182
+ }
2183
+
2184
+ get pivot(): number {
2185
+ return this.props.pivot;
2186
+ }
2187
+
2188
+ set pivot(value: number) {
2189
+ if (this.props.pivotX !== value || this.props.pivotY !== value) {
2190
+ this.props.pivotX = value;
2191
+ this.props.pivotY = value;
2192
+ this.props.pivot = value;
2193
+ this.setUpdateType(UpdateType.Local);
2194
+ }
2195
+ }
2196
+
2197
+ get pivotX(): number {
2198
+ return this.props.pivotX;
2199
+ }
2200
+
2201
+ set pivotX(value: number) {
2202
+ if (this.props.pivotX !== value) {
2203
+ this.props.pivotX = value;
2204
+ this.setUpdateType(UpdateType.Local);
2205
+ }
2206
+ }
2207
+
2208
+ get pivotY(): number {
2209
+ return this.props.pivotY;
2210
+ }
2211
+
2212
+ set pivotY(value: number) {
2213
+ if (this.props.pivotY !== value) {
2214
+ this.props.pivotY = value;
2215
+ this.setUpdateType(UpdateType.Local);
2216
+ }
2217
+ }
2218
+
2219
+ get rotation(): number {
2220
+ return this.props.rotation;
2221
+ }
2222
+
2223
+ set rotation(value: number) {
2224
+ if (this.props.rotation !== value) {
2225
+ this.props.rotation = value;
2226
+ this.setUpdateType(UpdateType.Local);
2227
+ this.updateIsSimple();
2228
+ }
2229
+ }
2230
+
2231
+ get alpha(): number {
2232
+ return this.props.alpha;
2233
+ }
2234
+
2235
+ set alpha(value: number) {
2236
+ this.props.alpha = value;
2237
+ this.setUpdateType(
2238
+ UpdateType.PremultipliedColors |
2239
+ UpdateType.WorldAlpha |
2240
+ UpdateType.Children |
2241
+ UpdateType.IsRenderable,
2242
+ );
2243
+ this.childUpdateType |= UpdateType.WorldAlpha;
2244
+ }
2245
+
2246
+ get autosize(): boolean {
2247
+ return this.props.autosize;
2248
+ }
2249
+
2250
+ set autosize(value: boolean) {
2251
+ if (this.props.autosize === value) {
2252
+ return;
2253
+ }
2254
+
2255
+ this.props.autosize = value;
2256
+
2257
+ if (value === true && this.autosizer === null) {
2258
+ this.autosizer = new Autosizer(this);
2259
+ } else {
2260
+ this.autosizer = null;
2261
+ }
2262
+ }
2263
+
2264
+ get boundsMargin(): number | [number, number, number, number] | null {
2265
+ const props = this.props;
2266
+ if (props.boundsMargin !== null) {
2267
+ return props.boundsMargin;
2268
+ }
2269
+
2270
+ const parent = this.parent;
2271
+ if (parent !== null) {
2272
+ const margin = parent.boundsMargin;
2273
+ if (margin !== undefined) {
2274
+ return margin;
2275
+ }
2276
+ }
2277
+
2278
+ return this.stage.boundsMargin;
2279
+ }
2280
+
2281
+ set boundsMargin(value: number | [number, number, number, number] | null) {
2282
+ if (value === this.props.boundsMargin) {
2283
+ return;
2284
+ }
2285
+
2286
+ if (value === null) {
2287
+ this.props.boundsMargin = value;
2288
+ } else {
2289
+ const bm: [number, number, number, number] = Array.isArray(value)
2290
+ ? value
2291
+ : [value, value, value, value];
2292
+
2293
+ this.props.boundsMargin = bm;
2294
+ }
2295
+ this.setUpdateType(UpdateType.RenderBounds);
2296
+ }
2297
+
2298
+ get clipping(): boolean {
2299
+ return this.props.clipping;
2300
+ }
2301
+
2302
+ set clipping(value: boolean) {
2303
+ this.props.clipping = value;
2304
+ this.setUpdateType(
2305
+ UpdateType.Clipping | UpdateType.RenderBounds | UpdateType.Children,
2306
+ );
2307
+ this.childUpdateType |= UpdateType.Global | UpdateType.Clipping;
2308
+ }
2309
+
2310
+ get color(): number {
2311
+ return this.props.color;
2312
+ }
2313
+
2314
+ set color(value: number) {
2315
+ const p = this.props;
2316
+ if (p.color === value) return;
2317
+
2318
+ p.color = value;
2319
+
2320
+ const has = value > 0;
2321
+
2322
+ if (has !== this.hasColorProps) {
2323
+ this.setUpdateType(UpdateType.IsRenderable);
2324
+ }
2325
+ this.hasColorProps = has;
2326
+
2327
+ if (p.colorTop !== value) this.colorTop = value;
2328
+ if (p.colorBottom !== value) this.colorBottom = value;
2329
+ if (p.colorLeft !== value) this.colorLeft = value;
2330
+ if (p.colorRight !== value) this.colorRight = value;
2331
+
2332
+ this.setUpdateType(UpdateType.PremultipliedColors);
2333
+ }
2334
+
2335
+ get colorTop(): number {
2336
+ return this.props.colorTop;
2337
+ }
2338
+
2339
+ set colorTop(value: number) {
2340
+ if (this.props.colorTl !== value || this.props.colorTr !== value) {
2341
+ this.colorTl = value;
2342
+ this.colorTr = value;
2343
+ }
2344
+ this.props.colorTop = value;
2345
+ this.hasColorProps = value > 0;
2346
+ this.setUpdateType(
2347
+ UpdateType.PremultipliedColors | UpdateType.IsRenderable,
2348
+ );
2349
+ }
2350
+
2351
+ get colorBottom(): number {
2352
+ return this.props.colorBottom;
2353
+ }
2354
+
2355
+ set colorBottom(value: number) {
2356
+ if (this.props.colorBl !== value || this.props.colorBr !== value) {
2357
+ this.colorBl = value;
2358
+ this.colorBr = value;
2359
+ }
2360
+ this.props.colorBottom = value;
2361
+ this.hasColorProps = value > 0;
2362
+ this.setUpdateType(
2363
+ UpdateType.PremultipliedColors | UpdateType.IsRenderable,
2364
+ );
2365
+ }
2366
+
2367
+ get colorLeft(): number {
2368
+ return this.props.colorLeft;
2369
+ }
2370
+
2371
+ set colorLeft(value: number) {
2372
+ if (this.props.colorTl !== value || this.props.colorBl !== value) {
2373
+ this.colorTl = value;
2374
+ this.colorBl = value;
2375
+ }
2376
+ this.props.colorLeft = value;
2377
+ this.hasColorProps = value > 0;
2378
+ this.setUpdateType(
2379
+ UpdateType.PremultipliedColors | UpdateType.IsRenderable,
2380
+ );
2381
+ }
2382
+
2383
+ get colorRight(): number {
2384
+ return this.props.colorRight;
2385
+ }
2386
+
2387
+ set colorRight(value: number) {
2388
+ if (this.props.colorTr !== value || this.props.colorBr !== value) {
2389
+ this.colorTr = value;
2390
+ this.colorBr = value;
2391
+ }
2392
+ this.props.colorRight = value;
2393
+ this.hasColorProps = value > 0;
2394
+ this.setUpdateType(
2395
+ UpdateType.PremultipliedColors | UpdateType.IsRenderable,
2396
+ );
2397
+ }
2398
+
2399
+ get colorTl(): number {
2400
+ return this.props.colorTl;
2401
+ }
2402
+
2403
+ set colorTl(value: number) {
2404
+ this.props.colorTl = value;
2405
+ this.hasColorProps = value > 0;
2406
+ this.setUpdateType(
2407
+ UpdateType.PremultipliedColors | UpdateType.IsRenderable,
2408
+ );
2409
+ }
2410
+
2411
+ get colorTr(): number {
2412
+ return this.props.colorTr;
2413
+ }
2414
+
2415
+ set colorTr(value: number) {
2416
+ this.props.colorTr = value;
2417
+ this.hasColorProps = value > 0;
2418
+ this.setUpdateType(
2419
+ UpdateType.PremultipliedColors | UpdateType.IsRenderable,
2420
+ );
2421
+ }
2422
+
2423
+ get colorBl(): number {
2424
+ return this.props.colorBl;
2425
+ }
2426
+
2427
+ set colorBl(value: number) {
2428
+ this.props.colorBl = value;
2429
+ this.hasColorProps = value > 0;
2430
+ this.setUpdateType(
2431
+ UpdateType.PremultipliedColors | UpdateType.IsRenderable,
2432
+ );
2433
+ }
2434
+
2435
+ get colorBr(): number {
2436
+ return this.props.colorBr;
2437
+ }
2438
+
2439
+ set colorBr(value: number) {
2440
+ this.props.colorBr = value;
2441
+ this.hasColorProps = value > 0;
2442
+ this.setUpdateType(
2443
+ UpdateType.PremultipliedColors | UpdateType.IsRenderable,
2444
+ );
2445
+ }
2446
+
2447
+ get zIndex(): number {
2448
+ return this.props.zIndex;
2449
+ }
2450
+
2451
+ set zIndex(value: number) {
2452
+ let sanitizedValue = value;
2453
+ if (isNaN(sanitizedValue) || Number.isFinite(sanitizedValue) === false) {
2454
+ console.warn(
2455
+ `zIndex was set to an invalid value: ${value}, defaulting to 0`,
2456
+ );
2457
+ sanitizedValue = 0;
2458
+ }
2459
+
2460
+ //Clamp to safe integer range
2461
+ if (sanitizedValue > Number.MAX_SAFE_INTEGER) {
2462
+ sanitizedValue = 1000;
2463
+ } else if (sanitizedValue < Number.MIN_SAFE_INTEGER) {
2464
+ sanitizedValue = -1000;
2465
+ }
2466
+
2467
+ if (this.props.zIndex === sanitizedValue) {
2468
+ return;
2469
+ }
2470
+ this.props.zIndex = sanitizedValue;
2471
+ const parent = this.parent;
2472
+ if (parent !== null) {
2473
+ parent.setUpdateType(UpdateType.SortZIndexChildren);
2474
+ }
2475
+ }
2476
+
2477
+ get parent(): CoreNode | null {
2478
+ return this.props.parent;
2479
+ }
2480
+
2481
+ set parent(newParent: CoreNode | null) {
2482
+ const oldParent = this.props.parent;
2483
+ if (oldParent === newParent) {
2484
+ return;
2485
+ }
2486
+ this.props.parent = newParent;
2487
+ if (oldParent) {
2488
+ oldParent.removeChild(this, newParent);
2489
+ }
2490
+ if (newParent !== null) {
2491
+ newParent.addChild(this, oldParent);
2492
+ }
2493
+ //since this node has a new parent, recalc global and render bounds
2494
+ this.setUpdateType(UpdateType.Global | UpdateType.RenderBounds);
2495
+ }
2496
+
2497
+ get rtt(): boolean {
2498
+ return this.props.rtt;
2499
+ }
2500
+
2501
+ set rtt(value: boolean) {
2502
+ if (this.props.rtt === value) {
2503
+ return;
2504
+ }
2505
+ this.props.rtt = value;
2506
+
2507
+ if (value === true) {
2508
+ this.initRenderTexture();
2509
+ this.markChildrenWithRTT();
2510
+ } else {
2511
+ this.cleanupRenderTexture();
2512
+ }
2513
+
2514
+ this.setUpdateType(UpdateType.RenderTexture);
2515
+
2516
+ if (this.parentHasRenderTexture === true) {
2517
+ this.notifyParentRTTOfUpdate();
2518
+ }
2519
+ }
2520
+
2521
+ get preventDestroy(): boolean | undefined {
2522
+ return this.props.preventDestroy;
2523
+ }
2524
+
2525
+ set preventDestroy(value: boolean | undefined) {
2526
+ this.props.preventDestroy = value;
2527
+ }
2528
+
2529
+ private initRenderTexture() {
2530
+ this.framebufferDimensions = {
2531
+ w: this.props.w,
2532
+ h: this.props.h,
2533
+ };
2534
+ this.texture = this.stage.txManager.createTexture(
2535
+ 'RenderTexture',
2536
+ this.framebufferDimensions,
2537
+ );
2538
+ this.stage.renderer.renderToTexture(this);
2539
+ }
2540
+
2541
+ private cleanupRenderTexture() {
2542
+ this.unloadTexture();
2543
+ this.clearRTTInheritance();
2544
+
2545
+ this.hasRTTupdates = false;
2546
+ this.texture = null;
2547
+ this.framebufferDimensions = null;
2548
+ }
2549
+
2550
+ private markChildrenWithRTT(node: CoreNode | null = null) {
2551
+ const parent = node || this;
2552
+
2553
+ for (const child of parent.children) {
2554
+ child.setUpdateType(UpdateType.All);
2555
+ child.parentHasRenderTexture = true;
2556
+ child.markChildrenWithRTT();
2557
+ }
2558
+ }
2559
+
2560
+ // Apply RTT inheritance when a node has an RTT-enabled parent
2561
+ private applyRTTInheritance(parent: CoreNode) {
2562
+ if (parent.rtt) {
2563
+ // Only the RTT node should be added to `renderToTexture`
2564
+ parent.setUpdateType(UpdateType.RenderTexture);
2565
+ }
2566
+
2567
+ // Propagate `parentHasRenderTexture` downwards
2568
+ this.markChildrenWithRTT(parent);
2569
+ }
2570
+
2571
+ // Clear RTT inheritance when detaching from an RTT chain
2572
+ private clearRTTInheritance() {
2573
+ // if this node is RTT itself stop the propagation important for nested RTT nodes
2574
+ // for the initial RTT node this is already handled in `set rtt`
2575
+ if (this.rtt) {
2576
+ return;
2577
+ }
2578
+
2579
+ for (const child of this.children) {
2580
+ // force child to update everything as the RTT inheritance has changed
2581
+ child.parentHasRenderTexture = false;
2582
+ child.rttParent = null;
2583
+ child.setUpdateType(UpdateType.All);
2584
+ child.clearRTTInheritance();
2585
+ }
2586
+ }
2587
+
2588
+ get shader(): CoreShaderNode<any> | null {
2589
+ return this.props.shader;
2590
+ }
2591
+
2592
+ set shader(shader: CoreShaderNode<any> | null) {
2593
+ if (this.props.shader === shader) {
2594
+ return;
2595
+ }
2596
+ if (shader === null) {
2597
+ this.hasShaderUpdater = false;
2598
+ this.props.shader = this.stage.defShaderNode;
2599
+ this.setUpdateType(UpdateType.IsRenderable);
2600
+ return;
2601
+ }
2602
+ if (shader.shaderKey !== 'default') {
2603
+ this.hasShaderUpdater = shader.update !== undefined;
2604
+ this.hasShaderTimeFn = shader.time !== undefined;
2605
+ shader.attachNode(this);
2606
+ }
2607
+
2608
+ if (this.hasShaderTimeFn === true) {
2609
+ this.stage.trackTimedNode(this);
2610
+ } else {
2611
+ this.stage.untrackTimedNode(this);
2612
+ }
2613
+ this.props.shader = shader;
2614
+ this.setUpdateType(UpdateType.IsRenderable | UpdateType.RecalcUniforms);
2615
+ }
2616
+
2617
+ get src(): string | null {
2618
+ return this.props.src;
2619
+ }
2620
+
2621
+ set src(imageUrl: string | null) {
2622
+ if (this.props.src === imageUrl) {
2623
+ return;
2624
+ }
2625
+
2626
+ this.props.src = imageUrl;
2627
+
2628
+ if (!imageUrl) {
2629
+ this.texture = null;
2630
+ return;
2631
+ }
2632
+
2633
+ this.texture = this.stage.txManager.createTexture('ImageTexture', {
2634
+ src: imageUrl,
2635
+ w: this.props.w,
2636
+ h: this.props.h,
2637
+ type: this.props.imageType,
2638
+ sx: this.props.srcX,
2639
+ sy: this.props.srcY,
2640
+ sw: this.props.srcWidth,
2641
+ sh: this.props.srcHeight,
2642
+ });
2643
+ }
2644
+
2645
+ set imageType(type: 'regular' | 'compressed' | 'svg' | null) {
2646
+ if (this.props.imageType === type) {
2647
+ return;
2648
+ }
2649
+
2650
+ this.props.imageType = type;
2651
+ }
2652
+
2653
+ get imageType() {
2654
+ return this.props.imageType || null;
2655
+ }
2656
+
2657
+ get srcHeight(): number | undefined {
2658
+ return this.props.srcHeight;
2659
+ }
2660
+
2661
+ set srcHeight(value: number) {
2662
+ this.props.srcHeight = value;
2663
+ }
2664
+
2665
+ get srcWidth(): number | undefined {
2666
+ return this.props.srcWidth;
2667
+ }
2668
+
2669
+ set srcWidth(value: number) {
2670
+ this.props.srcWidth = value;
2671
+ }
2672
+
2673
+ get srcX(): number | undefined {
2674
+ return this.props.srcX;
2675
+ }
2676
+
2677
+ set srcX(value: number) {
2678
+ this.props.srcX = value;
2679
+ }
2680
+
2681
+ get srcY(): number | undefined {
2682
+ return this.props.srcY;
2683
+ }
2684
+
2685
+ set srcY(value: number) {
2686
+ this.props.srcY = value;
2687
+ }
2688
+
2689
+ /**
2690
+ * Returns the framebuffer dimensions of the RTT parent
2691
+ */
2692
+ get parentFramebufferDimensions(): Dimensions | null {
2693
+ if (this.rttParent !== null) {
2694
+ return this.rttParent.framebufferDimensions;
2695
+ }
2696
+ this.rttParent = this.findParentRTTNode();
2697
+ return this.rttParent ? this.rttParent.framebufferDimensions : null;
2698
+ }
2699
+
2700
+ /**
2701
+ * Returns the parent render texture node if it exists.
2702
+ */
2703
+ get parentRenderTexture(): CoreNode | null {
2704
+ let parent = this.parent;
2705
+ while (parent) {
2706
+ if (parent.rtt) {
2707
+ return parent;
2708
+ }
2709
+ parent = parent.parent;
2710
+ }
2711
+ return null;
2712
+ }
2713
+
2714
+ get texture(): Texture | null {
2715
+ return this.props.texture;
2716
+ }
2717
+
2718
+ set texture(value: Texture | null) {
2719
+ if (this.props.texture === value) {
2720
+ return;
2721
+ }
2722
+
2723
+ const oldTexture = this.props.texture;
2724
+ if (oldTexture) {
2725
+ this.unloadTexture();
2726
+ if (this.autosizer !== null && value === null) {
2727
+ this.autosizer.setMode(AutosizeMode.Children); // Set to children size mode
2728
+ }
2729
+ }
2730
+
2731
+ this.textureCoords = undefined;
2732
+ this.props.texture = value;
2733
+ this.textureLoaded = value !== null && value.state === 'loaded';
2734
+
2735
+ if (value !== null) {
2736
+ if (this.autosizer !== null) {
2737
+ this.autosizer.setMode(AutosizeMode.Texture); // Set to texture size mode
2738
+ }
2739
+ value.setRenderableOwner(this._id, this.isRenderable);
2740
+ this.loadTexture();
2741
+ }
2742
+
2743
+ this.setUpdateType(UpdateType.IsRenderable);
2744
+ this.updateIsSimple();
2745
+ }
2746
+
2747
+ set textureOptions(value: TextureOptions) {
2748
+ this.props.textureOptions = value;
2749
+ if (this.stage.calculateTextureCoord === true && value !== null) {
2750
+ this.textureCoords = this.stage.renderer.getTextureCoords!(this);
2751
+ }
2752
+ this.updateIsSimple();
2753
+ }
2754
+
2755
+ get textureOptions(): TextureOptions {
2756
+ return this.props.textureOptions;
2757
+ }
2758
+
2759
+ set interactive(value: boolean | undefined) {
2760
+ this.props.interactive = value;
2761
+ // Update Stage's interactive Set
2762
+ if (value === true) {
2763
+ this.stage.interactiveNodes.add(this);
2764
+ }
2765
+ }
2766
+
2767
+ get interactive(): boolean | undefined {
2768
+ return this.props.interactive;
2769
+ }
2770
+
2771
+ setRTTUpdates(type: number) {
2772
+ this.hasRTTupdates = true;
2773
+ this.parent?.setRTTUpdates(type);
2774
+ }
2775
+
2776
+ animate(
2777
+ props: Partial<CoreNodeAnimateProps>,
2778
+ settings: Partial<AnimationSettings>,
2779
+ ): IAnimationController {
2780
+ return createAnimation(this.stage.animationManager, this, props, settings);
2781
+ }
2782
+
2783
+ animateProp(
2784
+ name: string,
2785
+ value: number,
2786
+ settings: Partial<AnimationSettings>,
2787
+ ): IAnimationController {
2788
+ const existing = this._animations[name];
2789
+
2790
+ if (existing && existing.settings === settings) {
2791
+ const controller = existing.controller;
2792
+ const values = controller.props ? controller.props[name] : null;
2793
+
2794
+ if (values) {
2795
+ values.start = (this as any)[name] ?? 0;
2796
+ values.target = value;
2797
+ controller.progress = 0;
2798
+ return controller.start();
2799
+ }
2800
+ }
2801
+
2802
+ const animationProps: Partial<CoreNodeAnimateProps> = { [name]: value };
2803
+ const controller = createAnimation(
2804
+ this.stage.animationManager,
2805
+ this,
2806
+ animationProps,
2807
+ settings,
2808
+ );
2809
+ this._animations[name] = { controller, settings };
2810
+ return controller.start();
2811
+ }
2812
+
2813
+ flush() {
2814
+ // no-op
2815
+ }
2816
+
2817
+ /**
2818
+ * Add a texture to the current RenderOp.
2819
+ *
2820
+ * @param texture
2821
+ * @returns Assigned Texture Index of the texture in the render op
2822
+ */
2823
+ addTexture(texture: WebGlCtxTexture): number {
2824
+ const textures = this.renderOpTextures;
2825
+ const length = textures.length;
2826
+
2827
+ for (let i = 0; i < length; i++) {
2828
+ if (textures[i] === texture) {
2829
+ return i;
2830
+ }
2831
+ }
2832
+
2833
+ if (length >= 1) {
2834
+ return 0xffffffff;
2835
+ }
2836
+
2837
+ textures.push(texture);
2838
+ return length;
2839
+ }
2840
+
2841
+ draw(renderer: WebGlRenderer) {
2842
+ const { glw, options, stage } = renderer;
2843
+ const shader = this.props.shader as any;
2844
+
2845
+ stage.shManager.useShader(shader.program);
2846
+ shader.program.bindRenderOp(this);
2847
+
2848
+ // Clipping
2849
+ if (this.clippingRect.valid === true) {
2850
+ const pixelRatio =
2851
+ USE_RTT && this.parentHasRenderTexture ? 1 : stage.pixelRatio;
2852
+
2853
+ const clipX = Math.round(this.clippingRect.x * pixelRatio);
2854
+ const clipWidth = Math.round(this.clippingRect.width * pixelRatio);
2855
+ const clipHeight = Math.round(this.clippingRect.height * pixelRatio);
2856
+ let clipY = Math.round(
2857
+ options.canvas.height - clipHeight - this.clippingRect.y * pixelRatio,
2858
+ );
2859
+ // if parent has render texture, we need to adjust the scissor rect
2860
+ // to be relative to the parent's framebuffer
2861
+ if (USE_RTT && this.parentHasRenderTexture) {
2862
+ clipY = this.parentFramebufferDimensions
2863
+ ? this.parentFramebufferDimensions.h - this.props.h
2864
+ : 0;
2865
+ }
2866
+
2867
+ glw.setScissorTest(true);
2868
+ glw.scissor(clipX, clipY, clipWidth, clipHeight);
2869
+ } else {
2870
+ glw.setScissorTest(false);
2871
+ }
2872
+
2873
+ const quadIdx = (this.renderOpBufferIdx / 20) * 6 * 2;
2874
+ glw.drawElements(
2875
+ glw.TRIANGLES,
2876
+ 6 * this.numQuads,
2877
+ glw.UNSIGNED_SHORT,
2878
+ quadIdx,
2879
+ );
2880
+ }
2881
+
2882
+ //#endregion Properties
2883
+ }