@lightningjs/renderer 3.0.0-beta1 → 3.0.0-beta10

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 (611) hide show
  1. package/COPYING +1 -0
  2. package/LICENSE +202 -202
  3. package/NOTICE +3 -3
  4. package/README.md +133 -147
  5. package/dist/exports/canvas.d.ts +1 -1
  6. package/dist/exports/canvas.js +1 -1
  7. package/dist/exports/canvas.js.map +1 -1
  8. package/dist/exports/index.d.ts +1 -5
  9. package/dist/exports/index.js +1 -5
  10. package/dist/exports/index.js.map +1 -1
  11. package/dist/exports/utils.d.ts +2 -1
  12. package/dist/exports/utils.js +2 -1
  13. package/dist/exports/utils.js.map +1 -1
  14. package/dist/exports/webgl.d.ts +2 -1
  15. package/dist/exports/webgl.js +2 -1
  16. package/dist/exports/webgl.js.map +1 -1
  17. package/dist/src/core/CoreNode.d.ts +45 -69
  18. package/dist/src/core/CoreNode.js +323 -305
  19. package/dist/src/core/CoreNode.js.map +1 -1
  20. package/dist/src/core/CoreShaderManager.d.ts +3 -5
  21. package/dist/src/core/CoreShaderManager.js.map +1 -1
  22. package/dist/src/core/CoreTextNode.d.ts +58 -87
  23. package/dist/src/core/CoreTextNode.js +243 -237
  24. package/dist/src/core/CoreTextNode.js.map +1 -1
  25. package/dist/src/core/CoreTextureManager.d.ts +9 -11
  26. package/dist/src/core/CoreTextureManager.js +80 -91
  27. package/dist/src/core/CoreTextureManager.js.map +1 -1
  28. package/dist/src/core/Stage.d.ts +75 -31
  29. package/dist/src/core/Stage.js +270 -136
  30. package/dist/src/core/Stage.js.map +1 -1
  31. package/dist/src/core/TextureMemoryManager.d.ts +10 -1
  32. package/dist/src/core/TextureMemoryManager.js +112 -78
  33. package/dist/src/core/TextureMemoryManager.js.map +1 -1
  34. package/dist/src/core/animations/CoreAnimation.js +5 -0
  35. package/dist/src/core/animations/CoreAnimation.js.map +1 -1
  36. package/dist/src/core/animations/CoreAnimationController.d.ts +1 -0
  37. package/dist/src/core/animations/CoreAnimationController.js +11 -4
  38. package/dist/src/core/animations/CoreAnimationController.js.map +1 -1
  39. package/dist/src/core/lib/ImageWorker.js +3 -2
  40. package/dist/src/core/lib/ImageWorker.js.map +1 -1
  41. package/dist/src/core/lib/RenderCoords.d.ts +9 -10
  42. package/dist/src/core/lib/RenderCoords.js +43 -55
  43. package/dist/src/core/lib/RenderCoords.js.map +1 -1
  44. package/dist/src/core/lib/WebGlContextWrapper.d.ts +51 -2
  45. package/dist/src/core/lib/WebGlContextWrapper.js +92 -22
  46. package/dist/src/core/lib/WebGlContextWrapper.js.map +1 -1
  47. package/dist/src/core/lib/colorCache.d.ts +1 -0
  48. package/dist/src/core/lib/colorCache.js +19 -0
  49. package/dist/src/core/lib/colorCache.js.map +1 -0
  50. package/dist/src/core/lib/colorParser.d.ts +21 -0
  51. package/dist/src/core/lib/colorParser.js +72 -0
  52. package/dist/src/core/lib/colorParser.js.map +1 -0
  53. package/dist/src/core/lib/utils.d.ts +3 -0
  54. package/dist/src/core/lib/utils.js +42 -0
  55. package/dist/src/core/lib/utils.js.map +1 -1
  56. package/dist/src/core/lib/validateImageBitmap.d.ts +2 -1
  57. package/dist/src/core/lib/validateImageBitmap.js +4 -4
  58. package/dist/src/core/lib/validateImageBitmap.js.map +1 -1
  59. package/dist/src/core/platforms/Platform.d.ts +37 -0
  60. package/dist/src/{main-api/IRenderDriver.js → core/platforms/Platform.js} +4 -2
  61. package/dist/src/core/platforms/Platform.js.map +1 -0
  62. package/dist/src/core/platforms/web/WebPlatform.d.ts +9 -0
  63. package/dist/src/core/platforms/web/WebPlatform.js +84 -0
  64. package/dist/src/core/platforms/web/WebPlatform.js.map +1 -0
  65. package/dist/src/core/renderers/CoreContextTexture.d.ts +1 -1
  66. package/dist/src/core/renderers/CoreRenderer.d.ts +5 -2
  67. package/dist/src/core/renderers/CoreRenderer.js.map +1 -1
  68. package/dist/src/core/renderers/CoreShaderNode.d.ts +3 -3
  69. package/dist/src/core/renderers/CoreShaderNode.js +8 -2
  70. package/dist/src/core/renderers/CoreShaderNode.js.map +1 -1
  71. package/dist/src/core/renderers/canvas/CanvasRenderer.d.ts +1 -2
  72. package/dist/src/core/renderers/canvas/CanvasRenderer.js +10 -21
  73. package/dist/src/core/renderers/canvas/CanvasRenderer.js.map +1 -1
  74. package/dist/src/core/renderers/canvas/CanvasShaderNode.js +3 -5
  75. package/dist/src/core/renderers/canvas/CanvasShaderNode.js.map +1 -1
  76. package/dist/src/core/renderers/canvas/CanvasTexture.d.ts +2 -2
  77. package/dist/src/core/renderers/canvas/CanvasTexture.js +11 -9
  78. package/dist/src/core/renderers/canvas/CanvasTexture.js.map +1 -1
  79. package/dist/src/core/renderers/webgl/WebGlCtxRenderTexture.js +3 -0
  80. package/dist/src/core/renderers/webgl/WebGlCtxRenderTexture.js.map +1 -1
  81. package/dist/src/core/renderers/webgl/WebGlCtxTexture.d.ts +5 -6
  82. package/dist/src/core/renderers/webgl/WebGlCtxTexture.js +30 -21
  83. package/dist/src/core/renderers/webgl/WebGlCtxTexture.js.map +1 -1
  84. package/dist/src/core/renderers/webgl/WebGlRenderOp.d.ts +10 -2
  85. package/dist/src/core/renderers/webgl/WebGlRenderOp.js +37 -19
  86. package/dist/src/core/renderers/webgl/WebGlRenderOp.js.map +1 -1
  87. package/dist/src/core/renderers/webgl/WebGlRenderer.d.ts +5 -3
  88. package/dist/src/core/renderers/webgl/WebGlRenderer.js +144 -117
  89. package/dist/src/core/renderers/webgl/WebGlRenderer.js.map +1 -1
  90. package/dist/src/core/renderers/webgl/WebGlShaderNode.d.ts +2 -1
  91. package/dist/src/core/renderers/webgl/WebGlShaderNode.js +1 -4
  92. package/dist/src/core/renderers/webgl/WebGlShaderNode.js.map +1 -1
  93. package/dist/src/core/renderers/webgl/WebGlShaderProgram.d.ts +5 -3
  94. package/dist/src/core/renderers/webgl/WebGlShaderProgram.js +55 -31
  95. package/dist/src/core/renderers/webgl/WebGlShaderProgram.js.map +1 -1
  96. package/dist/src/core/renderers/webgl/internal/ShaderUtils.js +35 -35
  97. package/dist/src/core/shaders/canvas/Border.js +1 -1
  98. package/dist/src/core/shaders/canvas/Border.js.map +1 -1
  99. package/dist/src/core/shaders/canvas/LinearGradient.js +5 -3
  100. package/dist/src/core/shaders/canvas/LinearGradient.js.map +1 -1
  101. package/dist/src/core/shaders/canvas/RadialGradient.js +13 -11
  102. package/dist/src/core/shaders/canvas/RadialGradient.js.map +1 -1
  103. package/dist/src/core/shaders/canvas/RoundedWithBorder.js +14 -6
  104. package/dist/src/core/shaders/canvas/RoundedWithBorder.js.map +1 -1
  105. package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.js +10 -8
  106. package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.js.map +1 -1
  107. package/dist/src/core/shaders/canvas/RoundedWithShadow.js +7 -5
  108. package/dist/src/core/shaders/canvas/RoundedWithShadow.js.map +1 -1
  109. package/dist/src/core/shaders/templates/BorderTemplate.d.ts +1 -1
  110. package/dist/src/core/shaders/templates/BorderTemplate.js +1 -1
  111. package/dist/src/core/shaders/templates/BorderTemplate.js.map +1 -1
  112. package/dist/src/core/shaders/templates/HolePunchTemplate.js +1 -1
  113. package/dist/src/core/shaders/templates/HolePunchTemplate.js.map +1 -1
  114. package/dist/src/core/shaders/templates/RoundedTemplate.js +1 -1
  115. package/dist/src/core/shaders/templates/RoundedTemplate.js.map +1 -1
  116. package/dist/src/core/shaders/templates/RoundedWithBorderAndShadowTemplate.d.ts +1 -1
  117. package/dist/src/core/shaders/templates/RoundedWithBorderTemplate.d.ts +1 -1
  118. package/dist/src/core/shaders/templates/RoundedWithShadowTemplate.d.ts +1 -1
  119. package/dist/src/core/shaders/templates/ShadowTemplate.d.ts +1 -1
  120. package/dist/src/core/shaders/{templates/shaderUtils.d.ts → utils.d.ts} +1 -1
  121. package/dist/src/core/shaders/{templates/shaderUtils.js → utils.js} +2 -2
  122. package/dist/src/core/shaders/utils.js.map +1 -0
  123. package/dist/src/core/shaders/webgl/Border.js +86 -63
  124. package/dist/src/core/shaders/webgl/Border.js.map +1 -1
  125. package/dist/src/core/shaders/webgl/Default.js +47 -47
  126. package/dist/src/core/shaders/webgl/DefaultBatched.js +61 -61
  127. package/dist/src/core/shaders/webgl/HolePunch.js +36 -35
  128. package/dist/src/core/shaders/webgl/HolePunch.js.map +1 -1
  129. package/dist/src/core/shaders/webgl/LinearGradient.js +41 -40
  130. package/dist/src/core/shaders/webgl/LinearGradient.js.map +1 -1
  131. package/dist/src/core/shaders/webgl/RadialGradient.js +39 -38
  132. package/dist/src/core/shaders/webgl/RadialGradient.js.map +1 -1
  133. package/dist/src/core/shaders/webgl/Rounded.js +71 -71
  134. package/dist/src/core/shaders/webgl/RoundedWithBorder.js +115 -72
  135. package/dist/src/core/shaders/webgl/RoundedWithBorder.js.map +1 -1
  136. package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js +138 -88
  137. package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js.map +1 -1
  138. package/dist/src/core/shaders/webgl/RoundedWithShadow.js +54 -54
  139. package/dist/src/core/shaders/webgl/SdfShader.js +63 -63
  140. package/dist/src/core/shaders/webgl/SdfShader.js.map +1 -1
  141. package/dist/src/core/shaders/webgl/Shadow.js +83 -83
  142. package/dist/src/core/text-rendering/CanvasFontHandler.d.ts +25 -0
  143. package/dist/src/core/text-rendering/CanvasFontHandler.js +130 -0
  144. package/dist/src/core/text-rendering/CanvasFontHandler.js.map +1 -0
  145. package/dist/src/core/text-rendering/CanvasTextRenderer.d.ts +22 -0
  146. package/dist/src/core/text-rendering/CanvasTextRenderer.js +366 -0
  147. package/dist/src/core/text-rendering/CanvasTextRenderer.js.map +1 -0
  148. package/dist/src/core/text-rendering/SdfFontHandler.d.ts +137 -0
  149. package/dist/src/core/text-rendering/SdfFontHandler.js +336 -0
  150. package/dist/src/core/text-rendering/SdfFontHandler.js.map +1 -0
  151. package/dist/src/core/text-rendering/SdfTextRenderer.d.ts +17 -0
  152. package/dist/src/core/text-rendering/SdfTextRenderer.js +355 -0
  153. package/dist/src/core/text-rendering/SdfTextRenderer.js.map +1 -0
  154. package/dist/src/core/text-rendering/TextRenderer.d.ts +349 -0
  155. package/dist/src/{main-api/ICoreDriver.js → core/text-rendering/TextRenderer.js} +1 -1
  156. package/dist/src/core/text-rendering/TextRenderer.js.map +1 -0
  157. package/dist/src/core/text-rendering/Utils.d.ts +71 -0
  158. package/dist/src/core/text-rendering/Utils.js +212 -0
  159. package/dist/src/core/text-rendering/Utils.js.map +1 -0
  160. package/dist/src/core/text-rendering/canvas/Settings.d.ts +64 -0
  161. package/dist/src/core/{renderers/CoreShader.js → text-rendering/canvas/Settings.js} +3 -11
  162. package/dist/src/core/text-rendering/canvas/Settings.js.map +1 -0
  163. package/dist/src/core/text-rendering/canvas/Utils.d.ts +20 -0
  164. package/dist/src/core/text-rendering/canvas/Utils.js +144 -0
  165. package/dist/src/core/text-rendering/canvas/Utils.js.map +1 -0
  166. package/dist/src/core/text-rendering/canvas/calculateRenderInfo.d.ts +60 -0
  167. package/dist/src/core/text-rendering/canvas/calculateRenderInfo.js +183 -0
  168. package/dist/src/core/text-rendering/canvas/calculateRenderInfo.js.map +1 -0
  169. package/dist/src/core/text-rendering/canvas/draw.d.ts +5 -0
  170. package/dist/src/core/text-rendering/canvas/draw.js +132 -0
  171. package/dist/src/core/text-rendering/canvas/draw.js.map +1 -0
  172. package/dist/src/core/text-rendering/renderers/CanvasTextRenderer.js +5 -0
  173. package/dist/src/core/text-rendering/renderers/CanvasTextRenderer.js.map +1 -1
  174. package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.d.ts +1 -1
  175. package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.js +50 -2
  176. package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.js.map +1 -1
  177. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js +9 -54
  178. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js.map +1 -1
  179. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.d.ts +1 -1
  180. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.js +66 -8
  181. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.js.map +1 -1
  182. package/dist/src/core/text-rendering/renderers/TextRenderer.d.ts +13 -0
  183. package/dist/src/core/text-rendering/renderers/TextRenderer.js +3 -0
  184. package/dist/src/core/text-rendering/renderers/TextRenderer.js.map +1 -1
  185. package/dist/src/core/text-rendering/sdf/Utils.d.ts +26 -0
  186. package/dist/src/core/text-rendering/sdf/Utils.js +304 -0
  187. package/dist/src/core/text-rendering/sdf/Utils.js.map +1 -0
  188. package/dist/src/core/text-rendering/sdf/index.d.ts +1 -0
  189. package/dist/src/{main-api/texture-usage-trackers/TextureUsageTracker.js → core/text-rendering/sdf/index.js} +3 -11
  190. package/dist/src/core/text-rendering/sdf/index.js.map +1 -0
  191. package/dist/src/core/textures/ImageTexture.d.ts +4 -3
  192. package/dist/src/core/textures/ImageTexture.js +36 -9
  193. package/dist/src/core/textures/ImageTexture.js.map +1 -1
  194. package/dist/src/core/textures/Texture.d.ts +21 -2
  195. package/dist/src/core/textures/Texture.js +37 -6
  196. package/dist/src/core/textures/Texture.js.map +1 -1
  197. package/dist/src/core/utils.d.ts +1 -1
  198. package/dist/src/main-api/INode.d.ts +2 -2
  199. package/dist/src/main-api/Inspector.d.ts +6 -1
  200. package/dist/src/main-api/Inspector.js +43 -7
  201. package/dist/src/main-api/Inspector.js.map +1 -1
  202. package/dist/src/main-api/Renderer.d.ts +122 -46
  203. package/dist/src/main-api/Renderer.js +174 -37
  204. package/dist/src/main-api/Renderer.js.map +1 -1
  205. package/dist/src/utils.d.ts +1 -6
  206. package/dist/src/utils.js +2 -9
  207. package/dist/src/utils.js.map +1 -1
  208. package/dist/tsconfig.dist.tsbuildinfo +1 -1
  209. package/exports/canvas-shaders.ts +28 -28
  210. package/exports/canvas.ts +45 -45
  211. package/exports/index.ts +82 -89
  212. package/exports/inspector.ts +24 -24
  213. package/exports/utils.ts +50 -44
  214. package/exports/webgl-shaders.ts +28 -28
  215. package/exports/webgl.ts +52 -50
  216. package/package.json +2 -4
  217. package/src/common/CommonTypes.ts +146 -146
  218. package/src/common/EventEmitter.ts +77 -77
  219. package/src/common/IAnimationController.ts +92 -92
  220. package/src/common/IEventEmitter.ts +28 -28
  221. package/src/core/CoreNode.test.ts +202 -203
  222. package/src/core/CoreNode.ts +2491 -2476
  223. package/src/core/CoreShaderManager.ts +188 -193
  224. package/src/core/CoreTextNode.ts +443 -448
  225. package/src/core/CoreTextureManager.ts +565 -597
  226. package/src/core/Stage.ts +906 -740
  227. package/src/core/TextureMemoryManager.ts +445 -395
  228. package/src/core/animations/AnimationManager.ts +38 -38
  229. package/src/core/animations/CoreAnimation.ts +291 -284
  230. package/src/core/animations/CoreAnimationController.ts +166 -157
  231. package/src/core/lib/ContextSpy.ts +41 -41
  232. package/src/core/lib/ImageWorker.ts +286 -279
  233. package/src/core/lib/Matrix3d.ts +244 -244
  234. package/src/core/lib/RenderCoords.ts +71 -86
  235. package/src/core/lib/WebGlContextWrapper.ts +1381 -1324
  236. package/src/core/lib/colorCache.ts +20 -0
  237. package/src/core/{renderers/canvas/internal/ColorUtils.ts → lib/colorParser.ts} +85 -85
  238. package/src/core/lib/textureCompression.ts +152 -152
  239. package/src/core/lib/textureSvg.ts +78 -78
  240. package/src/core/lib/utils.ts +412 -361
  241. package/src/core/lib/validateImageBitmap.ts +87 -76
  242. package/src/core/platforms/Platform.ts +77 -0
  243. package/src/core/platforms/web/WebPlatform.ts +121 -0
  244. package/src/core/renderers/CoreContextTexture.ts +43 -43
  245. package/src/core/renderers/CoreRenderOp.ts +22 -22
  246. package/src/core/renderers/CoreRenderer.ts +110 -107
  247. package/src/core/renderers/CoreShaderNode.ts +175 -171
  248. package/src/core/renderers/CoreShaderProgram.ts +23 -23
  249. package/src/core/renderers/canvas/CanvasRenderer.ts +283 -299
  250. package/src/core/renderers/canvas/CanvasShaderNode.ts +96 -99
  251. package/src/core/renderers/canvas/CanvasTexture.ts +156 -153
  252. package/src/core/renderers/webgl/WebGlCtxRenderTexture.ts +91 -86
  253. package/src/core/renderers/webgl/WebGlCtxSubTexture.ts +50 -50
  254. package/src/core/renderers/webgl/WebGlCtxTexture.ts +310 -301
  255. package/src/core/renderers/webgl/WebGlRenderOp.ts +167 -145
  256. package/src/core/renderers/webgl/WebGlRenderer.ts +747 -715
  257. package/src/core/renderers/webgl/WebGlShaderNode.ts +435 -433
  258. package/src/core/renderers/webgl/WebGlShaderProgram.ts +341 -310
  259. package/src/core/renderers/webgl/internal/BufferCollection.ts +54 -54
  260. package/src/core/renderers/webgl/internal/RendererUtils.ts +155 -155
  261. package/src/core/renderers/webgl/internal/ShaderUtils.ts +281 -281
  262. package/src/core/renderers/webgl/internal/WebGlUtils.ts +35 -35
  263. package/src/core/shaders/canvas/Border.ts +75 -78
  264. package/src/core/shaders/canvas/HolePunch.ts +62 -62
  265. package/src/core/shaders/canvas/LinearGradient.ts +71 -69
  266. package/src/core/shaders/canvas/RadialGradient.ts +99 -113
  267. package/src/core/shaders/canvas/Rounded.ts +55 -55
  268. package/src/core/shaders/canvas/RoundedWithBorder.ts +74 -68
  269. package/src/core/shaders/canvas/RoundedWithBorderAndShadow.ts +90 -88
  270. package/src/core/shaders/canvas/RoundedWithShadow.ts +70 -69
  271. package/src/core/shaders/canvas/Shadow.ts +52 -52
  272. package/src/core/shaders/canvas/utils/render.ts +151 -151
  273. package/src/core/shaders/templates/BorderTemplate.ts +115 -115
  274. package/src/core/shaders/templates/HolePunchTemplate.ts +82 -82
  275. package/src/core/shaders/templates/LinearGradientTemplate.ts +71 -71
  276. package/src/core/shaders/templates/RadialGradientTemplate.ts +81 -81
  277. package/src/core/shaders/templates/RoundedTemplate.ts +98 -98
  278. package/src/core/shaders/templates/RoundedWithBorderAndShadowTemplate.ts +38 -38
  279. package/src/core/shaders/templates/RoundedWithBorderTemplate.ts +35 -35
  280. package/src/core/shaders/templates/RoundedWithShadowTemplate.ts +35 -35
  281. package/src/core/shaders/templates/ShadowTemplate.ts +106 -106
  282. package/src/core/shaders/{templates/shaderUtils.ts → utils.ts} +46 -47
  283. package/src/core/shaders/webgl/Border.ts +116 -96
  284. package/src/core/shaders/webgl/Default.ts +89 -89
  285. package/src/core/shaders/webgl/DefaultBatched.ts +129 -129
  286. package/src/core/shaders/webgl/HolePunch.ts +75 -78
  287. package/src/core/shaders/webgl/LinearGradient.ts +82 -81
  288. package/src/core/shaders/webgl/RadialGradient.ts +85 -84
  289. package/src/core/shaders/webgl/Rounded.ts +117 -117
  290. package/src/core/shaders/webgl/RoundedWithBorder.ts +155 -114
  291. package/src/core/shaders/webgl/RoundedWithBorderAndShadow.ts +175 -133
  292. package/src/core/shaders/webgl/RoundedWithShadow.ts +98 -98
  293. package/src/core/shaders/webgl/SdfShader.ts +134 -137
  294. package/src/core/shaders/webgl/Shadow.ts +115 -115
  295. package/src/core/text-rendering/CanvasFontHandler.ts +176 -0
  296. package/src/core/text-rendering/CanvasTextRenderer.ts +622 -0
  297. package/src/core/text-rendering/SdfFontHandler.ts +517 -0
  298. package/src/core/text-rendering/SdfTextRenderer.ts +466 -0
  299. package/src/core/text-rendering/TextRenderer.ts +404 -0
  300. package/src/core/text-rendering/{TextTextureRendererUtils.ts → Utils.ts} +257 -263
  301. package/src/core/text-rendering/canvas/Settings.ts +99 -0
  302. package/src/core/text-rendering/canvas/Utils.test.ts +206 -0
  303. package/src/core/text-rendering/canvas/Utils.ts +178 -0
  304. package/src/core/text-rendering/canvas/calculateRenderInfo.ts +299 -0
  305. package/src/core/text-rendering/canvas/draw.ts +165 -0
  306. package/src/core/text-rendering/sdf/Utils.test.ts +402 -0
  307. package/src/core/text-rendering/sdf/Utils.ts +436 -0
  308. package/src/core/text-rendering/sdf/index.ts +20 -0
  309. package/src/core/textures/ColorTexture.ts +102 -102
  310. package/src/core/textures/ImageTexture.ts +418 -376
  311. package/src/core/textures/NoiseTexture.ts +104 -104
  312. package/src/core/textures/RenderTexture.ts +85 -85
  313. package/src/core/textures/SubTexture.ts +205 -205
  314. package/src/core/textures/Texture.ts +381 -337
  315. package/src/core/utils.ts +227 -227
  316. package/src/env.d.ts +7 -7
  317. package/src/main-api/INode.ts +100 -99
  318. package/src/main-api/Inspector.ts +567 -522
  319. package/src/main-api/Renderer.ts +873 -649
  320. package/src/main-api/utils.ts +45 -45
  321. package/src/utils.ts +267 -267
  322. package/dist/exports/core-api.d.ts +0 -74
  323. package/dist/exports/core-api.js +0 -96
  324. package/dist/exports/core-api.js.map +0 -1
  325. package/dist/exports/main-api.d.ts +0 -30
  326. package/dist/exports/main-api.js +0 -45
  327. package/dist/exports/main-api.js.map +0 -1
  328. package/dist/src/core/CoreExtension.d.ts +0 -12
  329. package/dist/src/core/CoreExtension.js +0 -29
  330. package/dist/src/core/CoreExtension.js.map +0 -1
  331. package/dist/src/core/CoreStuff.d.ts +0 -1
  332. package/dist/src/core/CoreStuff.js +0 -138
  333. package/dist/src/core/CoreStuff.js.map +0 -1
  334. package/dist/src/core/CoreTexturizer.d.ts +0 -14
  335. package/dist/src/core/CoreTexturizer.js +0 -47
  336. package/dist/src/core/CoreTexturizer.js.map +0 -1
  337. package/dist/src/core/LngNode.d.ts +0 -736
  338. package/dist/src/core/LngNode.js +0 -1174
  339. package/dist/src/core/LngNode.js.map +0 -1
  340. package/dist/src/core/Matrix2DContext.d.ts +0 -15
  341. package/dist/src/core/Matrix2DContext.js +0 -45
  342. package/dist/src/core/Matrix2DContext.js.map +0 -1
  343. package/dist/src/core/ShaderNode.d.ts +0 -10
  344. package/dist/src/core/ShaderNode.js +0 -30
  345. package/dist/src/core/ShaderNode.js.map +0 -1
  346. package/dist/src/core/TextNode.d.ts +0 -103
  347. package/dist/src/core/TextNode.js +0 -331
  348. package/dist/src/core/TextNode.js.map +0 -1
  349. package/dist/src/core/lib/Coords.d.ts +0 -14
  350. package/dist/src/core/lib/Coords.js +0 -55
  351. package/dist/src/core/lib/Coords.js.map +0 -1
  352. package/dist/src/core/lib/glm/common.d.ts +0 -162
  353. package/dist/src/core/lib/glm/common.js +0 -81
  354. package/dist/src/core/lib/glm/common.js.map +0 -1
  355. package/dist/src/core/lib/glm/index.d.ts +0 -11
  356. package/dist/src/core/lib/glm/index.js +0 -30
  357. package/dist/src/core/lib/glm/index.js.map +0 -1
  358. package/dist/src/core/lib/glm/mat2.d.ts +0 -219
  359. package/dist/src/core/lib/glm/mat2.js +0 -396
  360. package/dist/src/core/lib/glm/mat2.js.map +0 -1
  361. package/dist/src/core/lib/glm/mat2d.d.ts +0 -237
  362. package/dist/src/core/lib/glm/mat2d.js +0 -442
  363. package/dist/src/core/lib/glm/mat2d.js.map +0 -1
  364. package/dist/src/core/lib/glm/mat3.d.ts +0 -283
  365. package/dist/src/core/lib/glm/mat3.js +0 -680
  366. package/dist/src/core/lib/glm/mat3.js.map +0 -1
  367. package/dist/src/core/lib/glm/mat4.d.ts +0 -550
  368. package/dist/src/core/lib/glm/mat4.js +0 -1802
  369. package/dist/src/core/lib/glm/mat4.js.map +0 -1
  370. package/dist/src/core/lib/glm/quat.d.ts +0 -363
  371. package/dist/src/core/lib/glm/quat.js +0 -693
  372. package/dist/src/core/lib/glm/quat.js.map +0 -1
  373. package/dist/src/core/lib/glm/quat2.d.ts +0 -356
  374. package/dist/src/core/lib/glm/quat2.js +0 -754
  375. package/dist/src/core/lib/glm/quat2.js.map +0 -1
  376. package/dist/src/core/lib/glm/vec2.d.ts +0 -365
  377. package/dist/src/core/lib/glm/vec2.js +0 -569
  378. package/dist/src/core/lib/glm/vec2.js.map +0 -1
  379. package/dist/src/core/lib/glm/vec3.d.ts +0 -406
  380. package/dist/src/core/lib/glm/vec3.js +0 -720
  381. package/dist/src/core/lib/glm/vec3.js.map +0 -1
  382. package/dist/src/core/lib/glm/vec4.d.ts +0 -330
  383. package/dist/src/core/lib/glm/vec4.js +0 -608
  384. package/dist/src/core/lib/glm/vec4.js.map +0 -1
  385. package/dist/src/core/platform.d.ts +0 -10
  386. package/dist/src/core/platform.js +0 -56
  387. package/dist/src/core/platform.js.map +0 -1
  388. package/dist/src/core/renderers/CoreShader.d.ts +0 -9
  389. package/dist/src/core/renderers/CoreShader.js.map +0 -1
  390. package/dist/src/core/renderers/CoreShaderManager.d.ts +0 -19
  391. package/dist/src/core/renderers/CoreShaderManager.js +0 -33
  392. package/dist/src/core/renderers/CoreShaderManager.js.map +0 -1
  393. package/dist/src/core/renderers/canvas/CanvasCoreRenderer.d.ts +0 -33
  394. package/dist/src/core/renderers/canvas/CanvasCoreRenderer.js +0 -250
  395. package/dist/src/core/renderers/canvas/CanvasCoreRenderer.js.map +0 -1
  396. package/dist/src/core/renderers/canvas/CanvasCoreTexture.d.ts +0 -16
  397. package/dist/src/core/renderers/canvas/CanvasCoreTexture.js +0 -123
  398. package/dist/src/core/renderers/canvas/CanvasCoreTexture.js.map +0 -1
  399. package/dist/src/core/renderers/canvas/shaders/UnsupportedShader.d.ts +0 -10
  400. package/dist/src/core/renderers/canvas/shaders/UnsupportedShader.js +0 -43
  401. package/dist/src/core/renderers/canvas/shaders/UnsupportedShader.js.map +0 -1
  402. package/dist/src/core/renderers/webgl/WebGlCoreCtxRenderTexture.d.ts +0 -12
  403. package/dist/src/core/renderers/webgl/WebGlCoreCtxRenderTexture.js +0 -55
  404. package/dist/src/core/renderers/webgl/WebGlCoreCtxRenderTexture.js.map +0 -1
  405. package/dist/src/core/renderers/webgl/WebGlCoreCtxSubTexture.d.ts +0 -9
  406. package/dist/src/core/renderers/webgl/WebGlCoreCtxSubTexture.js +0 -38
  407. package/dist/src/core/renderers/webgl/WebGlCoreCtxSubTexture.js.map +0 -1
  408. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.d.ts +0 -57
  409. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js +0 -227
  410. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js.map +0 -1
  411. package/dist/src/core/renderers/webgl/WebGlCoreRenderOp.d.ts +0 -34
  412. package/dist/src/core/renderers/webgl/WebGlCoreRenderOp.js +0 -114
  413. package/dist/src/core/renderers/webgl/WebGlCoreRenderOp.js.map +0 -1
  414. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.d.ts +0 -133
  415. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.js +0 -613
  416. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.js.map +0 -1
  417. package/dist/src/core/renderers/webgl/WebGlCoreShader.d.ts +0 -83
  418. package/dist/src/core/renderers/webgl/WebGlCoreShader.js +0 -231
  419. package/dist/src/core/renderers/webgl/WebGlCoreShader.js.map +0 -1
  420. package/dist/src/core/renderers/webgl/WebGlCoreShaderManager.d.ts +0 -27
  421. package/dist/src/core/renderers/webgl/WebGlCoreShaderManager.js +0 -82
  422. package/dist/src/core/renderers/webgl/WebGlCoreShaderManager.js.map +0 -1
  423. package/dist/src/core/renderers/webgl/WebGlCoreShaderProgram.d.ts +0 -11
  424. package/dist/src/core/renderers/webgl/WebGlCoreShaderProgram.js +0 -34
  425. package/dist/src/core/renderers/webgl/WebGlCoreShaderProgram.js.map +0 -1
  426. package/dist/src/core/renderers/webgl/shaders/DefaultShader.d.ts +0 -9
  427. package/dist/src/core/renderers/webgl/shaders/DefaultShader.js +0 -87
  428. package/dist/src/core/renderers/webgl/shaders/DefaultShader.js.map +0 -1
  429. package/dist/src/core/renderers/webgl/shaders/DefaultShaderBatched.d.ts +0 -10
  430. package/dist/src/core/renderers/webgl/shaders/DefaultShaderBatched.js +0 -119
  431. package/dist/src/core/renderers/webgl/shaders/DefaultShaderBatched.js.map +0 -1
  432. package/dist/src/core/renderers/webgl/shaders/DynamicShader.d.ts +0 -29
  433. package/dist/src/core/renderers/webgl/shaders/DynamicShader.js +0 -413
  434. package/dist/src/core/renderers/webgl/shaders/DynamicShader.js.map +0 -1
  435. package/dist/src/core/renderers/webgl/shaders/RoundedRectangle.d.ts +0 -28
  436. package/dist/src/core/renderers/webgl/shaders/RoundedRectangle.js +0 -131
  437. package/dist/src/core/renderers/webgl/shaders/RoundedRectangle.js.map +0 -1
  438. package/dist/src/core/renderers/webgl/shaders/SdfShader.d.ts +0 -47
  439. package/dist/src/core/renderers/webgl/shaders/SdfShader.js +0 -160
  440. package/dist/src/core/renderers/webgl/shaders/SdfShader.js.map +0 -1
  441. package/dist/src/core/renderers/webgl/shaders/effects/BorderBottomEffect.d.ts +0 -31
  442. package/dist/src/core/renderers/webgl/shaders/effects/BorderBottomEffect.js +0 -71
  443. package/dist/src/core/renderers/webgl/shaders/effects/BorderBottomEffect.js.map +0 -1
  444. package/dist/src/core/renderers/webgl/shaders/effects/BorderEffect.d.ts +0 -30
  445. package/dist/src/core/renderers/webgl/shaders/effects/BorderEffect.js +0 -58
  446. package/dist/src/core/renderers/webgl/shaders/effects/BorderEffect.js.map +0 -1
  447. package/dist/src/core/renderers/webgl/shaders/effects/BorderLeftEffect.d.ts +0 -31
  448. package/dist/src/core/renderers/webgl/shaders/effects/BorderLeftEffect.js +0 -71
  449. package/dist/src/core/renderers/webgl/shaders/effects/BorderLeftEffect.js.map +0 -1
  450. package/dist/src/core/renderers/webgl/shaders/effects/BorderRightEffect.d.ts +0 -31
  451. package/dist/src/core/renderers/webgl/shaders/effects/BorderRightEffect.js +0 -71
  452. package/dist/src/core/renderers/webgl/shaders/effects/BorderRightEffect.js.map +0 -1
  453. package/dist/src/core/renderers/webgl/shaders/effects/BorderTopEffect.d.ts +0 -31
  454. package/dist/src/core/renderers/webgl/shaders/effects/BorderTopEffect.js +0 -71
  455. package/dist/src/core/renderers/webgl/shaders/effects/BorderTopEffect.js.map +0 -1
  456. package/dist/src/core/renderers/webgl/shaders/effects/EffectUtils.d.ts +0 -9
  457. package/dist/src/core/renderers/webgl/shaders/effects/EffectUtils.js +0 -136
  458. package/dist/src/core/renderers/webgl/shaders/effects/EffectUtils.js.map +0 -1
  459. package/dist/src/core/renderers/webgl/shaders/effects/FadeOutEffect.d.ts +0 -36
  460. package/dist/src/core/renderers/webgl/shaders/effects/FadeOutEffect.js +0 -85
  461. package/dist/src/core/renderers/webgl/shaders/effects/FadeOutEffect.js.map +0 -1
  462. package/dist/src/core/renderers/webgl/shaders/effects/GlitchEffect.d.ts +0 -45
  463. package/dist/src/core/renderers/webgl/shaders/effects/GlitchEffect.js +0 -104
  464. package/dist/src/core/renderers/webgl/shaders/effects/GlitchEffect.js.map +0 -1
  465. package/dist/src/core/renderers/webgl/shaders/effects/GrayscaleEffect.d.ts +0 -22
  466. package/dist/src/core/renderers/webgl/shaders/effects/GrayscaleEffect.js +0 -45
  467. package/dist/src/core/renderers/webgl/shaders/effects/GrayscaleEffect.js.map +0 -1
  468. package/dist/src/core/renderers/webgl/shaders/effects/HolePunchEffect.d.ts +0 -58
  469. package/dist/src/core/renderers/webgl/shaders/effects/HolePunchEffect.js +0 -80
  470. package/dist/src/core/renderers/webgl/shaders/effects/HolePunchEffect.js.map +0 -1
  471. package/dist/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.d.ts +0 -35
  472. package/dist/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.js +0 -129
  473. package/dist/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.js.map +0 -1
  474. package/dist/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.d.ts +0 -39
  475. package/dist/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.js +0 -116
  476. package/dist/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.js.map +0 -1
  477. package/dist/src/core/renderers/webgl/shaders/effects/RadialProgressEffect.d.ts +0 -61
  478. package/dist/src/core/renderers/webgl/shaders/effects/RadialProgressEffect.js +0 -127
  479. package/dist/src/core/renderers/webgl/shaders/effects/RadialProgressEffect.js.map +0 -1
  480. package/dist/src/core/renderers/webgl/shaders/effects/RadiusEffect.d.ts +0 -40
  481. package/dist/src/core/renderers/webgl/shaders/effects/RadiusEffect.js +0 -71
  482. package/dist/src/core/renderers/webgl/shaders/effects/RadiusEffect.js.map +0 -1
  483. package/dist/src/core/renderers/webgl/shaders/effects/ShaderEffect.d.ts +0 -115
  484. package/dist/src/core/renderers/webgl/shaders/effects/ShaderEffect.js +0 -61
  485. package/dist/src/core/renderers/webgl/shaders/effects/ShaderEffect.js.map +0 -1
  486. package/dist/src/core/scene/Scene.d.ts +0 -59
  487. package/dist/src/core/scene/Scene.js +0 -106
  488. package/dist/src/core/scene/Scene.js.map +0 -1
  489. package/dist/src/core/shaders/templates/shaderUtils.js.map +0 -1
  490. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/makeRenderWindow.d.ts +0 -20
  491. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/makeRenderWindow.js +0 -55
  492. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/makeRenderWindow.js.map +0 -1
  493. package/dist/src/main-api/DynamicShaderController.d.ts +0 -29
  494. package/dist/src/main-api/DynamicShaderController.js +0 -58
  495. package/dist/src/main-api/DynamicShaderController.js.map +0 -1
  496. package/dist/src/main-api/ICoreDriver.d.ts +0 -27
  497. package/dist/src/main-api/ICoreDriver.js.map +0 -1
  498. package/dist/src/main-api/IRenderDriver.d.ts +0 -20
  499. package/dist/src/main-api/IRenderDriver.js.map +0 -1
  500. package/dist/src/main-api/IShaderController.d.ts +0 -14
  501. package/dist/src/main-api/IShaderController.js +0 -30
  502. package/dist/src/main-api/IShaderController.js.map +0 -1
  503. package/dist/src/main-api/IShaderNode.d.ts +0 -17
  504. package/dist/src/main-api/IShaderNode.js +0 -19
  505. package/dist/src/main-api/IShaderNode.js.map +0 -1
  506. package/dist/src/main-api/RendererMain.d.ts +0 -375
  507. package/dist/src/main-api/RendererMain.js +0 -365
  508. package/dist/src/main-api/RendererMain.js.map +0 -1
  509. package/dist/src/main-api/ShaderController.d.ts +0 -31
  510. package/dist/src/main-api/ShaderController.js +0 -37
  511. package/dist/src/main-api/ShaderController.js.map +0 -1
  512. package/dist/src/main-api/texture-usage-trackers/FinalizationRegistryTextureUsageTracker.d.ts +0 -9
  513. package/dist/src/main-api/texture-usage-trackers/FinalizationRegistryTextureUsageTracker.js +0 -38
  514. package/dist/src/main-api/texture-usage-trackers/FinalizationRegistryTextureUsageTracker.js.map +0 -1
  515. package/dist/src/main-api/texture-usage-trackers/ManualCountTextureUsageTracker.d.ts +0 -56
  516. package/dist/src/main-api/texture-usage-trackers/ManualCountTextureUsageTracker.js +0 -101
  517. package/dist/src/main-api/texture-usage-trackers/ManualCountTextureUsageTracker.js.map +0 -1
  518. package/dist/src/main-api/texture-usage-trackers/TextureUsageTracker.d.ts +0 -32
  519. package/dist/src/main-api/texture-usage-trackers/TextureUsageTracker.js.map +0 -1
  520. package/dist/src/render-drivers/main/MainCoreDriver.d.ts +0 -24
  521. package/dist/src/render-drivers/main/MainCoreDriver.js +0 -118
  522. package/dist/src/render-drivers/main/MainCoreDriver.js.map +0 -1
  523. package/dist/src/render-drivers/main/MainOnlyNode.d.ts +0 -99
  524. package/dist/src/render-drivers/main/MainOnlyNode.js +0 -396
  525. package/dist/src/render-drivers/main/MainOnlyNode.js.map +0 -1
  526. package/dist/src/render-drivers/main/MainOnlyShaderController.d.ts +0 -6
  527. package/dist/src/render-drivers/main/MainOnlyShaderController.js +0 -15
  528. package/dist/src/render-drivers/main/MainOnlyShaderController.js.map +0 -1
  529. package/dist/src/render-drivers/main/MainOnlyShaderNode.d.ts +0 -7
  530. package/dist/src/render-drivers/main/MainOnlyShaderNode.js +0 -34
  531. package/dist/src/render-drivers/main/MainOnlyShaderNode.js.map +0 -1
  532. package/dist/src/render-drivers/main/MainOnlyTextNode.d.ts +0 -47
  533. package/dist/src/render-drivers/main/MainOnlyTextNode.js +0 -205
  534. package/dist/src/render-drivers/main/MainOnlyTextNode.js.map +0 -1
  535. package/dist/src/render-drivers/main/MainRenderDriver.d.ts +0 -17
  536. package/dist/src/render-drivers/main/MainRenderDriver.js +0 -88
  537. package/dist/src/render-drivers/main/MainRenderDriver.js.map +0 -1
  538. package/dist/src/render-drivers/threadx/NodeStruct.d.ts +0 -90
  539. package/dist/src/render-drivers/threadx/NodeStruct.js +0 -281
  540. package/dist/src/render-drivers/threadx/NodeStruct.js.map +0 -1
  541. package/dist/src/render-drivers/threadx/SharedNode.d.ts +0 -39
  542. package/dist/src/render-drivers/threadx/SharedNode.js +0 -60
  543. package/dist/src/render-drivers/threadx/SharedNode.js.map +0 -1
  544. package/dist/src/render-drivers/threadx/TextNodeStruct.d.ts +0 -44
  545. package/dist/src/render-drivers/threadx/TextNodeStruct.js +0 -201
  546. package/dist/src/render-drivers/threadx/TextNodeStruct.js.map +0 -1
  547. package/dist/src/render-drivers/threadx/ThreadXCoreDriver.d.ts +0 -28
  548. package/dist/src/render-drivers/threadx/ThreadXCoreDriver.js +0 -234
  549. package/dist/src/render-drivers/threadx/ThreadXCoreDriver.js.map +0 -1
  550. package/dist/src/render-drivers/threadx/ThreadXMainAnimationController.d.ts +0 -20
  551. package/dist/src/render-drivers/threadx/ThreadXMainAnimationController.js +0 -84
  552. package/dist/src/render-drivers/threadx/ThreadXMainAnimationController.js.map +0 -1
  553. package/dist/src/render-drivers/threadx/ThreadXMainNode.d.ts +0 -44
  554. package/dist/src/render-drivers/threadx/ThreadXMainNode.js +0 -154
  555. package/dist/src/render-drivers/threadx/ThreadXMainNode.js.map +0 -1
  556. package/dist/src/render-drivers/threadx/ThreadXMainShaderController.d.ts +0 -6
  557. package/dist/src/render-drivers/threadx/ThreadXMainShaderController.js +0 -16
  558. package/dist/src/render-drivers/threadx/ThreadXMainShaderController.js.map +0 -1
  559. package/dist/src/render-drivers/threadx/ThreadXMainShaderNode.d.ts +0 -7
  560. package/dist/src/render-drivers/threadx/ThreadXMainShaderNode.js +0 -15
  561. package/dist/src/render-drivers/threadx/ThreadXMainShaderNode.js.map +0 -1
  562. package/dist/src/render-drivers/threadx/ThreadXMainTextNode.d.ts +0 -28
  563. package/dist/src/render-drivers/threadx/ThreadXMainTextNode.js +0 -55
  564. package/dist/src/render-drivers/threadx/ThreadXMainTextNode.js.map +0 -1
  565. package/dist/src/render-drivers/threadx/ThreadXRenderDriver.d.ts +0 -21
  566. package/dist/src/render-drivers/threadx/ThreadXRenderDriver.js +0 -198
  567. package/dist/src/render-drivers/threadx/ThreadXRenderDriver.js.map +0 -1
  568. package/dist/src/render-drivers/threadx/ThreadXRendererMessage.d.ts +0 -70
  569. package/dist/src/render-drivers/threadx/ThreadXRendererMessage.js +0 -32
  570. package/dist/src/render-drivers/threadx/ThreadXRendererMessage.js.map +0 -1
  571. package/dist/src/render-drivers/threadx/worker/ThreadXRendererNode.d.ts +0 -19
  572. package/dist/src/render-drivers/threadx/worker/ThreadXRendererNode.js +0 -177
  573. package/dist/src/render-drivers/threadx/worker/ThreadXRendererNode.js.map +0 -1
  574. package/dist/src/render-drivers/threadx/worker/ThreadXRendererTextNode.d.ts +0 -27
  575. package/dist/src/render-drivers/threadx/worker/ThreadXRendererTextNode.js +0 -108
  576. package/dist/src/render-drivers/threadx/worker/ThreadXRendererTextNode.js.map +0 -1
  577. package/dist/src/render-drivers/threadx/worker/renderer.d.ts +0 -1
  578. package/dist/src/render-drivers/threadx/worker/renderer.js +0 -145
  579. package/dist/src/render-drivers/threadx/worker/renderer.js.map +0 -1
  580. package/dist/src/render-drivers/utils.d.ts +0 -12
  581. package/dist/src/render-drivers/utils.js +0 -69
  582. package/dist/src/render-drivers/utils.js.map +0 -1
  583. package/scripts/please-use-pnpm.js +0 -13
  584. package/src/core/platform.ts +0 -64
  585. package/src/core/renderers/canvas/internal/C2DShaderUtils.ts +0 -220
  586. package/src/core/text-rendering/TextRenderingUtils.ts +0 -36
  587. package/src/core/text-rendering/TrFontManager.ts +0 -183
  588. package/src/core/text-rendering/font-face-types/SdfTrFontFace/SdfTrFontFace.ts +0 -176
  589. package/src/core/text-rendering/font-face-types/SdfTrFontFace/internal/FontShaper.ts +0 -139
  590. package/src/core/text-rendering/font-face-types/SdfTrFontFace/internal/SdfFontShaper.test.ts +0 -173
  591. package/src/core/text-rendering/font-face-types/SdfTrFontFace/internal/SdfFontShaper.ts +0 -171
  592. package/src/core/text-rendering/font-face-types/TrFontFace.ts +0 -187
  593. package/src/core/text-rendering/font-face-types/WebTrFontFace.ts +0 -94
  594. package/src/core/text-rendering/font-face-types/utils.ts +0 -39
  595. package/src/core/text-rendering/renderers/CanvasTextRenderer.ts +0 -509
  596. package/src/core/text-rendering/renderers/LightningTextTextureRenderer.ts +0 -815
  597. package/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.ts +0 -841
  598. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/PeekableGenerator.test.ts +0 -48
  599. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/PeekableGenerator.ts +0 -66
  600. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/SpecialCodepoints.ts +0 -52
  601. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/constants.ts +0 -32
  602. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/getStartConditions.ts +0 -117
  603. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/getUnicodeCodepoints.test.ts +0 -133
  604. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/getUnicodeCodepoints.ts +0 -38
  605. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.ts +0 -408
  606. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/measureText.test.ts +0 -49
  607. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/measureText.ts +0 -52
  608. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/setRenderWindow.test.ts +0 -205
  609. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/setRenderWindow.ts +0 -93
  610. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/util.ts +0 -40
  611. package/src/core/text-rendering/renderers/TextRenderer.ts +0 -550
@@ -1,2476 +1,2491 @@
1
- /*
2
- * If not stated otherwise in this file or this component's LICENSE file the
3
- * following copyright and licenses apply:
4
- *
5
- * Copyright 2023 Comcast Cable Communications Management, LLC.
6
- *
7
- * Licensed under the Apache License, Version 2.0 (the License);
8
- * you may not use this file except in compliance with the License.
9
- * You may obtain a copy of the License at
10
- *
11
- * http://www.apache.org/licenses/LICENSE-2.0
12
- *
13
- * Unless required by applicable law or agreed to in writing, software
14
- * distributed under the License is distributed on an "AS IS" BASIS,
15
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- * See the License for the specific language governing permissions and
17
- * limitations under the License.
18
- */
19
-
20
- import {
21
- assertTruthy,
22
- getNewId,
23
- isProductionEnvironment,
24
- mergeColorAlphaPremultiplied,
25
- } from '../utils.js';
26
- import type { TextureOptions } from './CoreTextureManager.js';
27
- import type { CoreRenderer } from './renderers/CoreRenderer.js';
28
- import type { Stage } from './Stage.js';
29
- import {
30
- type Texture,
31
- type TextureFailedEventHandler,
32
- type TextureFreedEventHandler,
33
- type TextureLoadedEventHandler,
34
- } from './textures/Texture.js';
35
- import type {
36
- Dimensions,
37
- NodeTextureFailedPayload,
38
- NodeTextureFreedPayload,
39
- NodeTextureLoadedPayload,
40
- } from '../common/CommonTypes.js';
41
- import { EventEmitter } from '../common/EventEmitter.js';
42
- import {
43
- copyRect,
44
- intersectRect,
45
- type Bound,
46
- type RectWithValid,
47
- createBound,
48
- boundInsideBound,
49
- boundLargeThanBound,
50
- createPreloadBounds,
51
- } from './lib/utils.js';
52
- import { Matrix3d } from './lib/Matrix3d.js';
53
- import { RenderCoords } from './lib/RenderCoords.js';
54
- import type { AnimationSettings } from './animations/CoreAnimation.js';
55
- import type { IAnimationController } from '../common/IAnimationController.js';
56
- import { CoreAnimation } from './animations/CoreAnimation.js';
57
- import { CoreAnimationController } from './animations/CoreAnimationController.js';
58
- import type { CoreShaderNode } from './renderers/CoreShaderNode.js';
59
-
60
- export enum CoreNodeRenderState {
61
- Init = 0,
62
- OutOfBounds = 2,
63
- InBounds = 4,
64
- InViewport = 8,
65
- }
66
-
67
- const CoreNodeRenderStateMap: Map<CoreNodeRenderState, string> = new Map();
68
- CoreNodeRenderStateMap.set(CoreNodeRenderState.Init, 'init');
69
- CoreNodeRenderStateMap.set(CoreNodeRenderState.OutOfBounds, 'outOfBounds');
70
- CoreNodeRenderStateMap.set(CoreNodeRenderState.InBounds, 'inBounds');
71
- CoreNodeRenderStateMap.set(CoreNodeRenderState.InViewport, 'inViewport');
72
-
73
- export enum UpdateType {
74
- /**
75
- * Child updates
76
- */
77
- Children = 1,
78
-
79
- /**
80
- * Scale/Rotate transform update
81
- *
82
- * @remarks
83
- * CoreNode Properties Updated:
84
- * - `scaleRotateTransform`
85
- */
86
- ScaleRotate = 2,
87
-
88
- /**
89
- * Translate transform update (x/y/width/height/pivot/mount)
90
- *
91
- * @remarks
92
- * CoreNode Properties Updated:
93
- * - `localTransform`
94
- */
95
- Local = 4,
96
-
97
- /**
98
- * Global Transform update
99
- *
100
- * @remarks
101
- * CoreNode Properties Updated:
102
- * - `globalTransform`
103
- * - `renderCoords`
104
- * - `renderBound`
105
- */
106
- Global = 8,
107
-
108
- /**
109
- * Clipping rect update
110
- *
111
- * @remarks
112
- * CoreNode Properties Updated:
113
- * - `clippingRect`
114
- */
115
- Clipping = 16,
116
-
117
- /**
118
- * Calculated ZIndex update
119
- *
120
- * @remarks
121
- * CoreNode Properties Updated:
122
- * - `calcZIndex`
123
- */
124
- CalculatedZIndex = 32,
125
-
126
- /**
127
- * Z-Index Sorted Children update
128
- *
129
- * @remarks
130
- * CoreNode Properties Updated:
131
- * - `children` (sorts children by their `calcZIndex`)
132
- */
133
- ZIndexSortedChildren = 64,
134
-
135
- /**
136
- * Premultiplied Colors update
137
- *
138
- * @remarks
139
- * CoreNode Properties Updated:
140
- * - `premultipliedColorTl`
141
- * - `premultipliedColorTr`
142
- * - `premultipliedColorBl`
143
- * - `premultipliedColorBr`
144
- */
145
- PremultipliedColors = 128,
146
-
147
- /**
148
- * World Alpha update
149
- *
150
- * @remarks
151
- * CoreNode Properties Updated:
152
- * - `worldAlpha` = `parent.worldAlpha` * `alpha`
153
- */
154
- WorldAlpha = 256,
155
-
156
- /**
157
- * Render State update
158
- *
159
- * @remarks
160
- * CoreNode Properties Updated:
161
- * - `renderState`
162
- */
163
- RenderState = 512,
164
-
165
- /**
166
- * Is Renderable update
167
- *
168
- * @remarks
169
- * CoreNode Properties Updated:
170
- * - `isRenderable`
171
- */
172
- IsRenderable = 1024,
173
-
174
- /**
175
- * Render Texture update
176
- */
177
- RenderTexture = 2048,
178
-
179
- /**
180
- * Track if parent has render texture
181
- */
182
- ParentRenderTexture = 4096,
183
-
184
- /**
185
- * Render Bounds update
186
- */
187
- RenderBounds = 8192,
188
-
189
- /**
190
- * None
191
- */
192
- None = 0,
193
-
194
- /**
195
- * All
196
- */
197
- All = 14335,
198
-
199
- /**
200
- * RecalcUniforms
201
- */
202
- RecalcUniforms = 16384,
203
- }
204
-
205
- /**
206
- * A custom data map which can be stored on an CoreNode
207
- *
208
- * @remarks
209
- * This is a map of key-value pairs that can be stored on an INode. It is used
210
- * to store custom data that can be used by the application.
211
- * The data stored can only be of type string, number or boolean.
212
- */
213
- export type CustomDataMap = {
214
- [key: string]: string | number | boolean | undefined;
215
- };
216
-
217
- /**
218
- * Writable properties of a Node.
219
- */
220
- export interface CoreNodeProps {
221
- /**
222
- * The x coordinate of the Node's Mount Point.
223
- *
224
- * @remarks
225
- * See {@link mountX} and {@link mountY} for more information about setting
226
- * the Mount Point.
227
- *
228
- * @default `0`
229
- */
230
- x: number;
231
- /**
232
- * The y coordinate of the Node's Mount Point.
233
- *
234
- * @remarks
235
- * See {@link mountX} and {@link mountY} for more information about setting
236
- * the Mount Point.
237
- *
238
- * @default `0`
239
- */
240
- y: number;
241
- /**
242
- * The width of the Node.
243
- *
244
- * @default `0`
245
- */
246
- width: number;
247
- /**
248
- * The height of the Node.
249
- *
250
- * @default `0`
251
- */
252
- height: number;
253
- /**
254
- * The alpha opacity of the Node.
255
- *
256
- * @remarks
257
- * The alpha value is a number between 0 and 1, where 0 is fully transparent
258
- * and 1 is fully opaque.
259
- *
260
- * @default `1`
261
- */
262
- alpha: number;
263
- /**
264
- * Autosize mode
265
- *
266
- * @remarks
267
- * When enabled, when a texture is loaded into the Node, the Node will
268
- * automatically resize to the dimensions of the texture.
269
- *
270
- * Text Nodes are always autosized based on their text content regardless
271
- * of this mode setting.
272
- *
273
- * @default `false`
274
- */
275
- autosize: boolean;
276
- /**
277
- * Margin around the Node's bounds for preloading
278
- *
279
- * @default `null`
280
- */
281
- boundsMargin: number | [number, number, number, number] | null;
282
- /**
283
- * Clipping Mode
284
- *
285
- * @remarks
286
- * Enable Clipping Mode when you want to prevent the drawing of a Node and
287
- * its descendants from overflowing outside of the Node's x/y/width/height
288
- * bounds.
289
- *
290
- * For WebGL, clipping is implemented using the high-performance WebGL
291
- * operation scissor. As a consequence, clipping does not work for
292
- * non-rectangular areas. So, if the element is rotated
293
- * (by itself or by any of its ancestors), clipping will not work as intended.
294
- *
295
- * TODO: Add support for non-rectangular clipping either automatically or
296
- * via Render-To-Texture.
297
- *
298
- * @default `false`
299
- */
300
- clipping: boolean;
301
- /**
302
- * The color of the Node.
303
- *
304
- * @remarks
305
- * The color value is a number in the format 0xRRGGBBAA, where RR is the red
306
- * component, GG is the green component, BB is the blue component, and AA is
307
- * the alpha component.
308
- *
309
- * Gradient colors may be set by setting the different color sub-properties:
310
- * {@link colorTop}, {@link colorBottom}, {@link colorLeft}, {@link colorRight},
311
- * {@link colorTl}, {@link colorTr}, {@link colorBr}, {@link colorBl} accordingly.
312
- *
313
- * @default `0xffffffff` (opaque white)
314
- */
315
- color: number;
316
- /**
317
- * The color of the top edge of the Node for gradient rendering.
318
- *
319
- * @remarks
320
- * See {@link color} for more information about color values and gradient
321
- * rendering.
322
- */
323
- colorTop: number;
324
- /**
325
- * The color of the bottom edge of the Node for gradient rendering.
326
- *
327
- * @remarks
328
- * See {@link color} for more information about color values and gradient
329
- * rendering.
330
- */
331
- colorBottom: number;
332
- /**
333
- * The color of the left edge of the Node for gradient rendering.
334
- *
335
- * @remarks
336
- * See {@link color} for more information about color values and gradient
337
- * rendering.
338
- */
339
- colorLeft: number;
340
- /**
341
- * The color of the right edge of the Node for gradient rendering.
342
- *
343
- * @remarks
344
- * See {@link color} for more information about color values and gradient
345
- * rendering.
346
- */
347
- colorRight: number;
348
- /**
349
- * The color of the top-left corner of the Node for gradient rendering.
350
- *
351
- * @remarks
352
- * See {@link color} for more information about color values and gradient
353
- * rendering.
354
- */
355
- colorTl: number;
356
- /**
357
- * The color of the top-right corner of the Node for gradient rendering.
358
- *
359
- * @remarks
360
- * See {@link color} for more information about color values and gradient
361
- * rendering.
362
- */
363
- colorTr: number;
364
- /**
365
- * The color of the bottom-right corner of the Node for gradient rendering.
366
- *
367
- * @remarks
368
- * See {@link color} for more information about color values and gradient
369
- * rendering.
370
- */
371
- colorBr: number;
372
- /**
373
- * The color of the bottom-left corner of the Node for gradient rendering.
374
- *
375
- * @remarks
376
- * See {@link color} for more information about color values and gradient
377
- * rendering.
378
- */
379
- colorBl: number;
380
- /**
381
- * The Node's parent Node.
382
- *
383
- * @remarks
384
- * The value `null` indicates that the Node has no parent. This may either be
385
- * because the Node is the root Node of the scene graph, or because the Node
386
- * has been removed from the scene graph.
387
- *
388
- * In order to make sure that a Node can be rendered on the screen, it must
389
- * be added to the scene graph by setting it's parent property to a Node that
390
- * is already in the scene graph such as the root Node.
391
- *
392
- * @default `null`
393
- */
394
- parent: CoreNode | null;
395
- /**
396
- * The Node's z-index.
397
- *
398
- * @remarks
399
- * TBD
400
- */
401
- zIndex: number;
402
- /**
403
- * The Node's Texture.
404
- *
405
- * @remarks
406
- * The `texture` defines a rasterized image that is contained within the
407
- * {@link width} and {@link height} dimensions of the Node. If null, the
408
- * Node will use an opaque white {@link ColorTexture} when being drawn, which
409
- * essentially enables colors (including gradients) to be drawn.
410
- *
411
- * If set, by default, the texture will be drawn, as is, stretched to the
412
- * dimensions of the Node. This behavior can be modified by setting the TBD
413
- * and TBD properties.
414
- *
415
- * To create a Texture in order to set it on this property, call
416
- * {@link RendererMain.createTexture}.
417
- *
418
- * If the {@link src} is set on a Node, the Node will use the
419
- * {@link ImageTexture} by default and the Node will simply load the image at
420
- * the specified URL.
421
- *
422
- * Note: If this is a Text Node, the Texture will be managed by the Node's
423
- * {@link TextRenderer} and should not be set explicitly.
424
- */
425
- texture: Texture | null;
426
-
427
- /**
428
- * [Deprecated]: Prevents the texture from being cleaned up when the Node is removed
429
- *
430
- * @remarks
431
- * Please use the `preventCleanup` property on {@link TextureOptions} instead.
432
- *
433
- * @default false
434
- */
435
- preventCleanup: boolean;
436
- /**
437
- * Options to associate with the Node's Texture
438
- */
439
- textureOptions: TextureOptions;
440
-
441
- /**
442
- * The Node's shader
443
- *
444
- * @remarks
445
- * The `shader` defines a {@link Shader} used to draw the Node. By default,
446
- * the Default Shader is used which simply draws the defined {@link texture}
447
- * or {@link color}(s) within the Node without any special effects.
448
- *
449
- * To create a Shader in order to set it on this property, call
450
- * {@link RendererMain.createShader}.
451
- *
452
- * Note: If this is a Text Node, the Shader will be managed by the Node's
453
- * {@link TextRenderer} and should not be set explicitly.
454
- */
455
- shader: CoreShaderNode<any> | null;
456
- /**
457
- * Image URL
458
- *
459
- * @remarks
460
- * When set, the Node's {@link texture} is automatically set to an
461
- * {@link ImageTexture} using the source image URL provided (with all other
462
- * settings being defaults)
463
- */
464
- src: string | null;
465
- zIndexLocked: number;
466
- /**
467
- * Scale to render the Node at
468
- *
469
- * @remarks
470
- * The scale value multiplies the provided {@link width} and {@link height}
471
- * of the Node around the Node's Pivot Point (defined by the {@link pivot}
472
- * props).
473
- *
474
- * Behind the scenes, setting this property sets both the {@link scaleX} and
475
- * {@link scaleY} props to the same value.
476
- *
477
- * NOTE: When the scaleX and scaleY props are explicitly set to different values,
478
- * this property returns `null`. Setting `null` on this property will have no
479
- * effect.
480
- *
481
- * @default 1.0
482
- */
483
- scale: number | null;
484
- /**
485
- * Scale to render the Node at (X-Axis)
486
- *
487
- * @remarks
488
- * The scaleX value multiplies the provided {@link width} of the Node around
489
- * the Node's Pivot Point (defined by the {@link pivot} props).
490
- *
491
- * @default 1.0
492
- */
493
- scaleX: number;
494
- /**
495
- * Scale to render the Node at (Y-Axis)
496
- *
497
- * @remarks
498
- * The scaleY value multiplies the provided {@link height} of the Node around
499
- * the Node's Pivot Point (defined by the {@link pivot} props).
500
- *
501
- * @default 1.0
502
- */
503
- scaleY: number;
504
- /**
505
- * Combined position of the Node's Mount Point
506
- *
507
- * @remarks
508
- * The value can be any number between `0.0` and `1.0`:
509
- * - `0.0` defines the Mount Point at the top-left corner of the Node.
510
- * - `0.5` defines it at the center of the Node.
511
- * - `1.0` defines it at the bottom-right corner of the node.
512
- *
513
- * Use the {@link mountX} and {@link mountY} props seperately for more control
514
- * of the Mount Point.
515
- *
516
- * When assigned, the same value is also passed to both the {@link mountX} and
517
- * {@link mountY} props.
518
- *
519
- * @default 0 (top-left)
520
- */
521
- mount: number;
522
- /**
523
- * X position of the Node's Mount Point
524
- *
525
- * @remarks
526
- * The value can be any number between `0.0` and `1.0`:
527
- * - `0.0` defines the Mount Point's X position as the left-most edge of the
528
- * Node
529
- * - `0.5` defines it as the horizontal center of the Node
530
- * - `1.0` defines it as the right-most edge of the Node.
531
- *
532
- * The combination of {@link mountX} and {@link mountY} define the Mount Point
533
- *
534
- * @default 0 (left-most edge)
535
- */
536
- mountX: number;
537
- /**
538
- * Y position of the Node's Mount Point
539
- *
540
- * @remarks
541
- * The value can be any number between `0.0` and `1.0`:
542
- * - `0.0` defines the Mount Point's Y position as the top-most edge of the
543
- * Node
544
- * - `0.5` defines it as the vertical center of the Node
545
- * - `1.0` defines it as the bottom-most edge of the Node.
546
- *
547
- * The combination of {@link mountX} and {@link mountY} define the Mount Point
548
- *
549
- * @default 0 (top-most edge)
550
- */
551
- mountY: number;
552
- /**
553
- * Combined position of the Node's Pivot Point
554
- *
555
- * @remarks
556
- * The value can be any number between `0.0` and `1.0`:
557
- * - `0.0` defines the Pivot Point at the top-left corner of the Node.
558
- * - `0.5` defines it at the center of the Node.
559
- * - `1.0` defines it at the bottom-right corner of the node.
560
- *
561
- * Use the {@link pivotX} and {@link pivotY} props seperately for more control
562
- * of the Pivot Point.
563
- *
564
- * When assigned, the same value is also passed to both the {@link pivotX} and
565
- * {@link pivotY} props.
566
- *
567
- * @default 0.5 (center)
568
- */
569
- pivot: number;
570
- /**
571
- * X position of the Node's Pivot Point
572
- *
573
- * @remarks
574
- * The value can be any number between `0.0` and `1.0`:
575
- * - `0.0` defines the Pivot Point's X position as the left-most edge of the
576
- * Node
577
- * - `0.5` defines it as the horizontal center of the Node
578
- * - `1.0` defines it as the right-most edge of the Node.
579
- *
580
- * The combination of {@link pivotX} and {@link pivotY} define the Pivot Point
581
- *
582
- * @default 0.5 (centered on x-axis)
583
- */
584
- pivotX: number;
585
- /**
586
- * Y position of the Node's Pivot Point
587
- *
588
- * @remarks
589
- * The value can be any number between `0.0` and `1.0`:
590
- * - `0.0` defines the Pivot Point's Y position as the top-most edge of the
591
- * Node
592
- * - `0.5` defines it as the vertical center of the Node
593
- * - `1.0` defines it as the bottom-most edge of the Node.
594
- *
595
- * The combination of {@link pivotX} and {@link pivotY} define the Pivot Point
596
- *
597
- * @default 0.5 (centered on y-axis)
598
- */
599
- pivotY: number;
600
- /**
601
- * Rotation of the Node (in Radians)
602
- *
603
- * @remarks
604
- * Sets the amount to rotate the Node by around it's Pivot Point (defined by
605
- * the {@link pivot} props). Positive values rotate the Node clockwise, while
606
- * negative values rotate it counter-clockwise.
607
- *
608
- * Example values:
609
- * - `-Math.PI / 2`: 90 degree rotation counter-clockwise
610
- * - `0`: No rotation
611
- * - `Math.PI / 2`: 90 degree rotation clockwise
612
- * - `Math.PI`: 180 degree rotation clockwise
613
- * - `3 * Math.PI / 2`: 270 degree rotation clockwise
614
- * - `2 * Math.PI`: 360 rotation clockwise
615
- */
616
- rotation: number;
617
-
618
- /**
619
- * Whether the Node is rendered to a texture
620
- *
621
- * @remarks
622
- * TBD
623
- *
624
- * @default false
625
- */
626
- rtt: boolean;
627
-
628
- /**
629
- * Node data element for custom data storage (optional)
630
- *
631
- * @remarks
632
- * This property is used to store custom data on the Node as a key/value data store.
633
- * Data values are limited to string, numbers, booleans. Strings will be truncated
634
- * to a 2048 character limit for performance reasons.
635
- *
636
- * This is not a data storage mechanism for large amounts of data please use a
637
- * dedicated data storage mechanism for that.
638
- *
639
- * The custom data will be reflected in the inspector as part of `data-*` attributes
640
- *
641
- * @default `undefined`
642
- */
643
- data?: CustomDataMap;
644
-
645
- /**
646
- * Image Type to explicitly set the image type that is being loaded
647
- *
648
- * @remarks
649
- * This property must be used with a `src` that points at an image. In some cases
650
- * the extension doesn't provide a reliable representation of the image type. In such
651
- * cases set the ImageType explicitly.
652
- *
653
- * `regular` is used for normal images such as png, jpg, etc
654
- * `compressed` is used for ETC1/ETC2 compressed images with a PVR or KTX container
655
- * `svg` is used for scalable vector graphics
656
- *
657
- * @default `undefined`
658
- */
659
- imageType?: 'regular' | 'compressed' | 'svg' | null;
660
-
661
- /**
662
- * She width of the rectangle from which the Image Texture will be extracted.
663
- * This value can be negative. If not provided, the image's source natural
664
- * width will be used.
665
- */
666
- srcWidth?: number;
667
- /**
668
- * The height of the rectangle from which the Image Texture will be extracted.
669
- * This value can be negative. If not provided, the image's source natural
670
- * height will be used.
671
- */
672
- srcHeight?: number;
673
- /**
674
- * The x coordinate of the reference point of the rectangle from which the Texture
675
- * will be extracted. `width` and `height` are provided. And only works when
676
- * createImageBitmap is available. Only works when createImageBitmap is supported on the browser.
677
- */
678
- srcX?: number;
679
- /**
680
- * The y coordinate of the reference point of the rectangle from which the Texture
681
- * will be extracted. Only used when source `srcWidth` width and `srcHeight` height
682
- * are provided. Only works when createImageBitmap is supported on the browser.
683
- */
684
- srcY?: number;
685
- /**
686
- * By enabling Strict bounds the renderer will not process & render child nodes of a node that is out of the visible area
687
- *
688
- * @remarks
689
- * When enabled out of bound nodes, i.e. nodes that are out of the visible area, will
690
- * **NOT** have their children processed and renderer anymore. This means the children of a out of bound
691
- * node will not receive update processing such as positioning updates and will not be drawn on screen.
692
- * As such the rest of the branch of the update tree that sits below this node will not be processed anymore
693
- *
694
- * This is a big performance gain but may be disabled in cases where the width of the parent node is
695
- * unknown and the render must process the child nodes regardless of the viewport status of the parent node
696
- *
697
- * @default false
698
- */
699
- strictBounds: boolean;
700
- }
701
-
702
- /**
703
- * Grab all the number properties of type T
704
- */
705
- type NumberProps<T> = {
706
- [Key in keyof T as NonNullable<T[Key]> extends number ? Key : never]: number;
707
- };
708
-
709
- /**
710
- * Properties of a Node used by the animate() function
711
- */
712
- export interface CoreNodeAnimateProps extends NumberProps<CoreNodeProps> {
713
- /**
714
- * Shader properties to animate
715
- */
716
- shaderProps: Record<string, number>;
717
- // TODO: textureProps: Record<string, number>;
718
- }
719
-
720
- /**
721
- * A visual Node in the Renderer scene graph.
722
- *
723
- * @remarks
724
- * CoreNode is an internally used class that represents a Renderer Node in the
725
- * scene graph. See INode.ts for the public APIs exposed to Renderer users
726
- * that include generic types for Shaders.
727
- */
728
- export class CoreNode extends EventEmitter {
729
- readonly children: CoreNode[] = [];
730
- protected _id: number = getNewId();
731
- readonly props: CoreNodeProps;
732
-
733
- public updateType = UpdateType.All;
734
- public childUpdateType = UpdateType.None;
735
-
736
- public globalTransform?: Matrix3d;
737
- public scaleRotateTransform?: Matrix3d;
738
- public localTransform?: Matrix3d;
739
- public sceneGlobalTransform?: Matrix3d;
740
- public renderCoords?: RenderCoords;
741
- public sceneRenderCoords?: RenderCoords;
742
- public renderBound?: Bound;
743
- public strictBound?: Bound;
744
- public preloadBound?: Bound;
745
- public clippingRect: RectWithValid = {
746
- x: 0,
747
- y: 0,
748
- width: 0,
749
- height: 0,
750
- valid: false,
751
- };
752
- public isRenderable = false;
753
- public renderState: CoreNodeRenderState = CoreNodeRenderState.Init;
754
-
755
- public worldAlpha = 1;
756
- public premultipliedColorTl = 0;
757
- public premultipliedColorTr = 0;
758
- public premultipliedColorBl = 0;
759
- public premultipliedColorBr = 0;
760
- public calcZIndex = 0;
761
- public hasRTTupdates = false;
762
- public parentHasRenderTexture = false;
763
- public rttParent: CoreNode | null = null;
764
-
765
- constructor(readonly stage: Stage, props: CoreNodeProps) {
766
- super();
767
-
768
- this.props = Object.assign({}, props, {
769
- parent: null,
770
- texture: null,
771
- shader: null,
772
- src: null,
773
- rtt: false,
774
- });
775
-
776
- // Assign props to instance
777
- this.parent = props.parent;
778
- this.texture = props.texture;
779
- this.shader = props.shader;
780
- this.src = props.src;
781
- this.rtt = props.rtt;
782
-
783
- if (props.boundsMargin) {
784
- this.boundsMargin = Array.isArray(props.boundsMargin)
785
- ? props.boundsMargin
786
- : [
787
- props.boundsMargin,
788
- props.boundsMargin,
789
- props.boundsMargin,
790
- props.boundsMargin,
791
- ];
792
- }
793
-
794
- this.setUpdateType(
795
- UpdateType.ScaleRotate |
796
- UpdateType.Local |
797
- UpdateType.RenderBounds |
798
- UpdateType.RenderState,
799
- );
800
-
801
- if (isProductionEnvironment() === false && props.preventCleanup === true) {
802
- console.warn(
803
- 'CoreNode.preventCleanup: Is deprecated and will be removed in upcoming release, please use textureOptions.preventCleanup instead',
804
- );
805
- }
806
-
807
- // if the default texture isn't loaded yet, wait for it to load
808
- // this only happens when the node is created before the stage is ready
809
- if (
810
- this.stage.defaultTexture &&
811
- this.stage.defaultTexture.state !== 'loaded'
812
- ) {
813
- this.stage.defaultTexture.once('loaded', () => {
814
- this.setUpdateType(UpdateType.IsRenderable);
815
- });
816
- }
817
- }
818
-
819
- //#region Textures
820
- loadTexture(): void {
821
- const { texture } = this.props;
822
- assertTruthy(texture);
823
-
824
- // If texture is already loaded / failed, trigger loaded event manually
825
- // so that users get a consistent event experience.
826
- // We do this in a microtask to allow listeners to be attached in the same
827
- // synchronous task after calling loadTexture()
828
- queueMicrotask(() => {
829
- if (this.textureOptions.preload === true) {
830
- this.stage.txManager.loadTexture(texture);
831
- }
832
-
833
- texture.preventCleanup =
834
- this.props.textureOptions?.preventCleanup ?? false;
835
- texture.on('loaded', this.onTextureLoaded);
836
- texture.on('failed', this.onTextureFailed);
837
- texture.on('freed', this.onTextureFreed);
838
-
839
- // If the parent is a render texture, the initial texture status
840
- // will be set to freed until the texture is processed by the
841
- // Render RTT nodes. So we only need to listen fo changes and
842
- // no need to check the texture.state until we restructure how
843
- // textures are being processed.
844
- if (this.parentHasRenderTexture) {
845
- this.notifyParentRTTOfUpdate();
846
- return;
847
- }
848
-
849
- if (texture.state === 'loaded') {
850
- assertTruthy(texture.dimensions);
851
- this.onTextureLoaded(texture, texture.dimensions);
852
- } else if (texture.state === 'failed') {
853
- assertTruthy(texture.error);
854
- this.onTextureFailed(texture, texture.error);
855
- } else if (texture.state === 'freed') {
856
- this.onTextureFreed(texture);
857
- }
858
- });
859
- }
860
-
861
- unloadTexture(): void {
862
- if (this.texture !== null) {
863
- this.texture.off('loaded', this.onTextureLoaded);
864
- this.texture.off('failed', this.onTextureFailed);
865
- this.texture.off('freed', this.onTextureFreed);
866
- this.texture.setRenderableOwner(this, false);
867
- }
868
- }
869
-
870
- autosizeNode(dimensions: Dimensions) {
871
- if (this.autosize) {
872
- this.width = dimensions.width;
873
- this.height = dimensions.height;
874
- }
875
- }
876
-
877
- private onTextureLoaded: TextureLoadedEventHandler = (_, dimensions) => {
878
- this.autosizeNode(dimensions);
879
- this.setUpdateType(UpdateType.IsRenderable);
880
-
881
- // Texture was loaded. In case the RAF loop has already stopped, we request
882
- // a render to ensure the texture is rendered.
883
- this.stage.requestRender();
884
-
885
- // If parent has a render texture, flag that we need to update
886
- if (this.parentHasRenderTexture) {
887
- this.notifyParentRTTOfUpdate();
888
- }
889
-
890
- // ignore 1x1 pixel textures
891
- if (dimensions.width > 1 && dimensions.height > 1) {
892
- this.emit('loaded', {
893
- type: 'texture',
894
- dimensions,
895
- } satisfies NodeTextureLoadedPayload);
896
- }
897
-
898
- // Trigger a local update if the texture is loaded and the resizeMode is 'contain'
899
- if (this.props.textureOptions?.resizeMode?.type === 'contain') {
900
- this.setUpdateType(UpdateType.Local);
901
- }
902
- };
903
-
904
- private onTextureFailed: TextureFailedEventHandler = (_, error) => {
905
- this.setUpdateType(UpdateType.IsRenderable);
906
-
907
- // If parent has a render texture, flag that we need to update
908
- if (this.parentHasRenderTexture) {
909
- this.notifyParentRTTOfUpdate();
910
- }
911
-
912
- this.emit('failed', {
913
- type: 'texture',
914
- error,
915
- } satisfies NodeTextureFailedPayload);
916
- };
917
-
918
- private onTextureFreed: TextureFreedEventHandler = () => {
919
- this.setUpdateType(UpdateType.IsRenderable);
920
-
921
- // If parent has a render texture, flag that we need to update
922
- if (this.parentHasRenderTexture) {
923
- this.notifyParentRTTOfUpdate();
924
- }
925
-
926
- this.emit('freed', {
927
- type: 'texture',
928
- } satisfies NodeTextureFreedPayload);
929
- };
930
- //#endregion Textures
931
-
932
- /**
933
- * Change types types is used to determine the scope of the changes being applied
934
- *
935
- * @remarks
936
- * See {@link UpdateType} for more information on each type
937
- *
938
- * @param type
939
- */
940
- setUpdateType(type: UpdateType): void {
941
- this.updateType |= type;
942
-
943
- const parent = this.props.parent;
944
- if (!parent) return;
945
-
946
- if ((parent.updateType & UpdateType.Children) === 0) {
947
- // Inform the parent if it doesn’t already have a child update
948
- parent.setUpdateType(UpdateType.Children);
949
- }
950
- }
951
-
952
- sortChildren() {
953
- this.children.sort((a, b) => a.calcZIndex - b.calcZIndex);
954
- }
955
-
956
- updateScaleRotateTransform() {
957
- const { rotation, scaleX, scaleY } = this.props;
958
-
959
- // optimize simple translation cases
960
- if (rotation === 0 && scaleX === 1 && scaleY === 1) {
961
- this.scaleRotateTransform = undefined;
962
- return;
963
- }
964
-
965
- this.scaleRotateTransform = Matrix3d.rotate(
966
- rotation,
967
- this.scaleRotateTransform,
968
- ).scale(scaleX, scaleY);
969
- }
970
-
971
- updateLocalTransform() {
972
- const { x, y, width, height } = this.props;
973
- const mountTranslateX = this.props.mountX * width;
974
- const mountTranslateY = this.props.mountY * height;
975
-
976
- if (this.scaleRotateTransform) {
977
- const pivotTranslateX = this.props.pivotX * width;
978
- const pivotTranslateY = this.props.pivotY * height;
979
-
980
- this.localTransform = Matrix3d.translate(
981
- x - mountTranslateX + pivotTranslateX,
982
- y - mountTranslateY + pivotTranslateY,
983
- this.localTransform,
984
- )
985
- .multiply(this.scaleRotateTransform)
986
- .translate(-pivotTranslateX, -pivotTranslateY);
987
- } else {
988
- this.localTransform = Matrix3d.translate(
989
- x - mountTranslateX,
990
- y - mountTranslateY,
991
- this.localTransform,
992
- );
993
- }
994
-
995
- // Handle 'contain' resize mode
996
- const texture = this.props.texture;
997
- if (
998
- texture &&
999
- texture.dimensions &&
1000
- this.props.textureOptions?.resizeMode?.type === 'contain'
1001
- ) {
1002
- let resizeModeScaleX = 1;
1003
- let resizeModeScaleY = 1;
1004
- let extraX = 0;
1005
- let extraY = 0;
1006
- const { width: tw, height: th } = texture.dimensions;
1007
- const txAspectRatio = tw / th;
1008
- const nodeAspectRatio = width / height;
1009
- if (txAspectRatio > nodeAspectRatio) {
1010
- // Texture is wider than node
1011
- // Center the node vertically (shift down by extraY)
1012
- // Scale the node vertically to maintain original aspect ratio
1013
- const scaleX = width / tw;
1014
- const scaledTxHeight = th * scaleX;
1015
- extraY = (height - scaledTxHeight) / 2;
1016
- resizeModeScaleY = scaledTxHeight / height;
1017
- } else {
1018
- // Texture is taller than node (or equal)
1019
- // Center the node horizontally (shift right by extraX)
1020
- // Scale the node horizontally to maintain original aspect ratio
1021
- const scaleY = height / th;
1022
- const scaledTxWidth = tw * scaleY;
1023
- extraX = (width - scaledTxWidth) / 2;
1024
- resizeModeScaleX = scaledTxWidth / width;
1025
- }
1026
-
1027
- // Apply the extra translation and scale to the local transform
1028
- this.localTransform
1029
- .translate(extraX, extraY)
1030
- .scale(resizeModeScaleX, resizeModeScaleY);
1031
- }
1032
-
1033
- this.setUpdateType(UpdateType.Global);
1034
- }
1035
-
1036
- /**
1037
- * @todo: test for correct calculation flag
1038
- * @param delta
1039
- */
1040
- update(delta: number, parentClippingRect: RectWithValid): void {
1041
- if (this.updateType & UpdateType.ScaleRotate) {
1042
- this.updateScaleRotateTransform();
1043
- this.setUpdateType(UpdateType.Local);
1044
- }
1045
-
1046
- if (this.updateType & UpdateType.Local) {
1047
- this.updateLocalTransform();
1048
- this.setUpdateType(UpdateType.Global);
1049
- }
1050
-
1051
- const parent = this.props.parent;
1052
- let renderState: CoreNodeRenderState | null = null;
1053
-
1054
- // Handle specific RTT updates at this node level
1055
- if (this.updateType & UpdateType.RenderTexture && this.rtt) {
1056
- this.hasRTTupdates = true;
1057
- }
1058
-
1059
- if (this.updateType & UpdateType.Global) {
1060
- assertTruthy(this.localTransform);
1061
-
1062
- if (this.parentHasRenderTexture === true && parent?.rtt === true) {
1063
- // we are at the start of the RTT chain, so we need to reset the globalTransform
1064
- // for correct RTT rendering
1065
- this.globalTransform = Matrix3d.identity();
1066
-
1067
- // Maintain a full scene global transform for bounds detection
1068
- this.sceneGlobalTransform = Matrix3d.copy(
1069
- parent?.globalTransform || Matrix3d.identity(),
1070
- ).multiply(this.localTransform);
1071
- } else if (
1072
- this.parentHasRenderTexture === true &&
1073
- parent?.rtt === false
1074
- ) {
1075
- // we're part of an RTT chain but our parent is not the main RTT node
1076
- // so we need to propogate the sceneGlobalTransform of the parent
1077
- // to maintain a full scene global transform for bounds detection
1078
- this.sceneGlobalTransform = Matrix3d.copy(
1079
- parent?.sceneGlobalTransform || this.localTransform,
1080
- ).multiply(this.localTransform);
1081
-
1082
- this.globalTransform = Matrix3d.copy(
1083
- parent?.globalTransform || this.localTransform,
1084
- this.globalTransform,
1085
- );
1086
- } else {
1087
- this.globalTransform = Matrix3d.copy(
1088
- parent?.globalTransform || this.localTransform,
1089
- this.globalTransform,
1090
- );
1091
- }
1092
-
1093
- if (parent !== null) {
1094
- this.globalTransform.multiply(this.localTransform);
1095
- }
1096
- this.calculateRenderCoords();
1097
- this.updateBoundingRect();
1098
-
1099
- this.setUpdateType(
1100
- UpdateType.RenderState |
1101
- UpdateType.Children |
1102
- UpdateType.RecalcUniforms,
1103
- );
1104
- this.childUpdateType |= UpdateType.Global;
1105
-
1106
- if (this.clipping === true) {
1107
- this.setUpdateType(UpdateType.Clipping | UpdateType.RenderBounds);
1108
- this.childUpdateType |= UpdateType.RenderBounds;
1109
- }
1110
- }
1111
-
1112
- if (this.updateType & UpdateType.RenderBounds) {
1113
- this.createRenderBounds();
1114
- this.setUpdateType(UpdateType.RenderState);
1115
- this.setUpdateType(UpdateType.Children);
1116
-
1117
- this.childUpdateType |= UpdateType.RenderBounds;
1118
- }
1119
-
1120
- if (this.updateType & UpdateType.RenderState) {
1121
- renderState = this.checkRenderBounds();
1122
- this.setUpdateType(UpdateType.IsRenderable);
1123
-
1124
- // if we're not going out of bounds, update the render state
1125
- // this is done so the update loop can finish before we mark a node
1126
- // as out of bounds
1127
- if (renderState !== CoreNodeRenderState.OutOfBounds) {
1128
- this.updateRenderState(renderState);
1129
- }
1130
- }
1131
-
1132
- if (this.updateType & UpdateType.WorldAlpha) {
1133
- if (parent) {
1134
- this.worldAlpha = parent.worldAlpha * this.props.alpha;
1135
- } else {
1136
- this.worldAlpha = this.props.alpha;
1137
- }
1138
- this.setUpdateType(
1139
- UpdateType.Children |
1140
- UpdateType.PremultipliedColors |
1141
- UpdateType.IsRenderable,
1142
- );
1143
- this.childUpdateType |= UpdateType.WorldAlpha;
1144
- }
1145
-
1146
- if (this.updateType & UpdateType.IsRenderable) {
1147
- this.updateIsRenderable();
1148
- }
1149
-
1150
- if (this.updateType & UpdateType.Clipping) {
1151
- this.calculateClippingRect(parentClippingRect);
1152
- this.setUpdateType(UpdateType.Children);
1153
-
1154
- this.childUpdateType |= UpdateType.Clipping;
1155
- this.childUpdateType |= UpdateType.RenderBounds;
1156
- }
1157
-
1158
- if (this.updateType & UpdateType.PremultipliedColors) {
1159
- this.premultipliedColorTl = mergeColorAlphaPremultiplied(
1160
- this.props.colorTl,
1161
- this.worldAlpha,
1162
- true,
1163
- );
1164
-
1165
- // If all the colors are the same just sent them all to the same value
1166
- if (
1167
- this.props.colorTl === this.props.colorTr &&
1168
- this.props.colorBl === this.props.colorBr &&
1169
- this.props.colorTl === this.props.colorBl
1170
- ) {
1171
- this.premultipliedColorTr =
1172
- this.premultipliedColorBl =
1173
- this.premultipliedColorBr =
1174
- this.premultipliedColorTl;
1175
- } else {
1176
- this.premultipliedColorTr = mergeColorAlphaPremultiplied(
1177
- this.props.colorTr,
1178
- this.worldAlpha,
1179
- true,
1180
- );
1181
- this.premultipliedColorBl = mergeColorAlphaPremultiplied(
1182
- this.props.colorBl,
1183
- this.worldAlpha,
1184
- true,
1185
- );
1186
- this.premultipliedColorBr = mergeColorAlphaPremultiplied(
1187
- this.props.colorBr,
1188
- this.worldAlpha,
1189
- true,
1190
- );
1191
- }
1192
- }
1193
-
1194
- // No need to update zIndex if there is no parent
1195
- if (parent !== null && this.updateType & UpdateType.CalculatedZIndex) {
1196
- this.calculateZIndex();
1197
- // Tell parent to re-sort children
1198
- parent.setUpdateType(UpdateType.ZIndexSortedChildren);
1199
- }
1200
-
1201
- if (
1202
- this.props.strictBounds === true &&
1203
- this.renderState === CoreNodeRenderState.OutOfBounds
1204
- ) {
1205
- this.updateType &= ~UpdateType.RenderBounds; // remove render bounds update
1206
- return;
1207
- }
1208
-
1209
- if (
1210
- this.shader?.update !== undefined &&
1211
- (this.updateType & UpdateType.Local ||
1212
- this.updateType & UpdateType.RecalcUniforms)
1213
- ) {
1214
- this.shader.update();
1215
- }
1216
-
1217
- if (this.updateType & UpdateType.Children && this.children.length > 0) {
1218
- for (let i = 0, length = this.children.length; i < length; i++) {
1219
- const child = this.children[i] as CoreNode;
1220
-
1221
- child.setUpdateType(this.childUpdateType);
1222
-
1223
- if (child.updateType === 0) {
1224
- continue;
1225
- }
1226
-
1227
- let childClippingRect = this.clippingRect;
1228
- if (this.rtt === true) {
1229
- childClippingRect = {
1230
- x: 0,
1231
- y: 0,
1232
- width: 0,
1233
- height: 0,
1234
- valid: false,
1235
- };
1236
- }
1237
-
1238
- child.update(delta, childClippingRect);
1239
- }
1240
- }
1241
-
1242
- // If the node has an RTT parent and requires a texture re-render, inform the RTT parent
1243
- // if (this.parentHasRenderTexture && this.updateType & UpdateType.RenderTexture) {
1244
- // @TODO have a more scoped down updateType for RTT updates
1245
- if (this.parentHasRenderTexture && this.updateType > 0) {
1246
- this.notifyParentRTTOfUpdate();
1247
- }
1248
-
1249
- // Sorting children MUST happen after children have been updated so
1250
- // that they have the oppotunity to update their calculated zIndex.
1251
- if (this.updateType & UpdateType.ZIndexSortedChildren) {
1252
- // reorder z-index
1253
- this.sortChildren();
1254
- }
1255
-
1256
- // If we're out of bounds, apply the render state now
1257
- // this is done so nodes can finish their entire update loop before
1258
- // being marked as out of bounds
1259
- if (renderState === CoreNodeRenderState.OutOfBounds) {
1260
- this.updateRenderState(renderState);
1261
- this.updateIsRenderable();
1262
-
1263
- if (
1264
- this.rtt === true &&
1265
- renderState === CoreNodeRenderState.OutOfBounds
1266
- ) {
1267
- // notify children that we are going out of bounds
1268
- // we have to do this now before we stop processing the render tree
1269
- this.notifyChildrenRTTOfUpdate(renderState);
1270
- // this.childUpdateType |= UpdateType.RenderState;
1271
- }
1272
- }
1273
-
1274
- // reset update type
1275
- this.updateType = 0;
1276
- this.childUpdateType = 0;
1277
- }
1278
-
1279
- private findParentRTTNode(): CoreNode | null {
1280
- let rttNode: CoreNode | null = this.parent;
1281
- while (rttNode && !rttNode.rtt) {
1282
- rttNode = rttNode.parent;
1283
- }
1284
- return rttNode;
1285
- }
1286
-
1287
- private getRTTParentRenderState(): CoreNodeRenderState | null {
1288
- const rttNode = this.rttParent || this.findParentRTTNode();
1289
- if (!rttNode) {
1290
- return null;
1291
- }
1292
-
1293
- return rttNode.renderState;
1294
- }
1295
-
1296
- private notifyChildrenRTTOfUpdate(renderState: CoreNodeRenderState) {
1297
- for (const child of this.children) {
1298
- // force child to update render state
1299
- child.updateRenderState(renderState);
1300
- child.updateIsRenderable();
1301
- child.notifyChildrenRTTOfUpdate(renderState);
1302
- }
1303
- }
1304
-
1305
- private notifyParentRTTOfUpdate() {
1306
- if (this.parent === null) {
1307
- return;
1308
- }
1309
-
1310
- const rttNode = this.rttParent || this.findParentRTTNode();
1311
- if (!rttNode) {
1312
- return;
1313
- }
1314
-
1315
- // If an RTT node is found, mark it for re-rendering
1316
- rttNode.hasRTTupdates = true;
1317
- rttNode.setUpdateType(UpdateType.RenderTexture);
1318
-
1319
- // if rttNode is nested, also make it update its RTT parent
1320
- if (rttNode.parentHasRenderTexture === true) {
1321
- rttNode.notifyParentRTTOfUpdate();
1322
- }
1323
- }
1324
-
1325
- checkRenderBounds(): CoreNodeRenderState {
1326
- assertTruthy(this.renderBound);
1327
- assertTruthy(this.strictBound);
1328
- assertTruthy(this.preloadBound);
1329
-
1330
- if (boundInsideBound(this.renderBound, this.strictBound)) {
1331
- return CoreNodeRenderState.InViewport;
1332
- }
1333
-
1334
- if (boundInsideBound(this.renderBound, this.preloadBound)) {
1335
- return CoreNodeRenderState.InBounds;
1336
- }
1337
-
1338
- // check if we're larger then our parent, we're definitely in the viewport
1339
- if (boundLargeThanBound(this.renderBound, this.strictBound)) {
1340
- return CoreNodeRenderState.InViewport;
1341
- }
1342
-
1343
- // check if we dont have dimensions, take our parent's render state
1344
- if (
1345
- this.parent !== null &&
1346
- (this.props.width === 0 || this.props.height === 0)
1347
- ) {
1348
- return this.parent.renderState;
1349
- }
1350
-
1351
- return CoreNodeRenderState.OutOfBounds;
1352
- }
1353
-
1354
- updateBoundingRect() {
1355
- const transform = this.sceneGlobalTransform || this.globalTransform;
1356
- const renderCoords = this.sceneRenderCoords || this.renderCoords;
1357
-
1358
- assertTruthy(transform);
1359
- assertTruthy(renderCoords);
1360
-
1361
- const { tb, tc } = transform;
1362
- const { x1, y1, x3, y3 } = renderCoords;
1363
- if (tb === 0 || tc === 0) {
1364
- this.renderBound = createBound(x1, y1, x3, y3, this.renderBound);
1365
- } else {
1366
- const { x2, x4, y2, y4 } = renderCoords;
1367
- this.renderBound = createBound(
1368
- Math.min(x1, x2, x3, x4),
1369
- Math.min(y1, y2, y3, y4),
1370
- Math.max(x1, x2, x3, x4),
1371
- Math.max(y1, y2, y3, y4),
1372
- this.renderBound,
1373
- );
1374
- }
1375
- }
1376
-
1377
- createRenderBounds(): void {
1378
- assertTruthy(this.stage);
1379
-
1380
- if (this.parent !== null && this.parent.strictBound !== undefined) {
1381
- // we have a parent with a valid bound, copy it
1382
- const parentBound = this.parent.strictBound;
1383
- this.strictBound = createBound(
1384
- parentBound.x1,
1385
- parentBound.y1,
1386
- parentBound.x2,
1387
- parentBound.y2,
1388
- );
1389
-
1390
- this.preloadBound = createPreloadBounds(
1391
- this.strictBound,
1392
- this.boundsMargin as [number, number, number, number],
1393
- );
1394
- } else {
1395
- // no parent or parent does not have a bound, take the stage boundaries
1396
- this.strictBound = this.stage.strictBound;
1397
- this.preloadBound = this.stage.preloadBound;
1398
- }
1399
-
1400
- // if clipping is disabled, we're done
1401
- if (this.props.clipping === false) {
1402
- return;
1403
- }
1404
-
1405
- // only create local clipping bounds if node itself is in bounds
1406
- // this can only be done if we have a render bound already
1407
- if (this.renderBound === undefined) {
1408
- return;
1409
- }
1410
-
1411
- // if we're out of bounds, we're done
1412
- if (boundInsideBound(this.renderBound, this.strictBound) === false) {
1413
- return;
1414
- }
1415
-
1416
- // clipping is enabled and we are in bounds create our own bounds
1417
- const { x, y, width, height } = this.props;
1418
-
1419
- // Pick the global transform if available, otherwise use the local transform
1420
- // global transform is only available if the node in an RTT chain
1421
- const { tx, ty } = this.sceneGlobalTransform || this.globalTransform || {};
1422
- const _x = tx ?? x;
1423
- const _y = ty ?? y;
1424
- this.strictBound = createBound(
1425
- _x,
1426
- _y,
1427
- _x + width,
1428
- _y + height,
1429
- this.strictBound,
1430
- );
1431
-
1432
- this.preloadBound = createPreloadBounds(
1433
- this.strictBound,
1434
- this.boundsMargin as [number, number, number, number],
1435
- );
1436
- }
1437
-
1438
- updateRenderState(renderState: CoreNodeRenderState) {
1439
- if (renderState === this.renderState) {
1440
- return;
1441
- }
1442
-
1443
- const previous = this.renderState;
1444
- this.renderState = renderState;
1445
- const event = CoreNodeRenderStateMap.get(renderState);
1446
- assertTruthy(event);
1447
- this.emit(event, {
1448
- previous,
1449
- current: renderState,
1450
- });
1451
- }
1452
-
1453
- /**
1454
- * Updates the `isRenderable` property based on various conditions.
1455
- */
1456
- updateIsRenderable() {
1457
- let newIsRenderable = false;
1458
- let needsTextureOwnership = false;
1459
-
1460
- // If the node is out of bounds or has an alpha of 0, it is not renderable
1461
- if (this.checkBasicRenderability() === false) {
1462
- this.updateTextureOwnership(false);
1463
- this.setRenderable(false);
1464
- return;
1465
- }
1466
-
1467
- if (this.texture !== null) {
1468
- needsTextureOwnership = true;
1469
-
1470
- // we're only renderable if the texture state is loaded
1471
- newIsRenderable = this.texture.state === 'loaded';
1472
- } else if (
1473
- (this.hasShader() || this.hasColorProperties() === true) &&
1474
- this.hasDimensions() === true
1475
- ) {
1476
- // This mean we have dimensions and a color set, so we can render a ColorTexture
1477
- if (
1478
- this.stage.defaultTexture &&
1479
- this.stage.defaultTexture.state === 'loaded'
1480
- ) {
1481
- newIsRenderable = true;
1482
- }
1483
- }
1484
-
1485
- this.updateTextureOwnership(needsTextureOwnership);
1486
- this.setRenderable(newIsRenderable);
1487
- }
1488
-
1489
- /**
1490
- * Checks if the node is renderable based on world alpha, dimensions and out of bounds status.
1491
- */
1492
- checkBasicRenderability(): boolean {
1493
- if (this.worldAlpha === 0 || this.isOutOfBounds() === true) {
1494
- return false;
1495
- } else {
1496
- return true;
1497
- }
1498
- }
1499
-
1500
- /**
1501
- * Sets the renderable state and triggers changes if necessary.
1502
- * @param isRenderable - The new renderable state
1503
- */
1504
- setRenderable(isRenderable: boolean) {
1505
- this.isRenderable = isRenderable;
1506
- }
1507
-
1508
- /**
1509
- * Changes the renderable state of the node.
1510
- */
1511
- updateTextureOwnership(isRenderable: boolean) {
1512
- this.texture?.setRenderableOwner(this, isRenderable);
1513
- }
1514
-
1515
- /**
1516
- * Checks if the node is out of the viewport bounds.
1517
- */
1518
- isOutOfBounds(): boolean {
1519
- return this.renderState <= CoreNodeRenderState.OutOfBounds;
1520
- }
1521
-
1522
- /**
1523
- * Checks if the node has dimensions (width/height)
1524
- */
1525
- hasDimensions(): boolean {
1526
- return this.props.width !== 0 && this.props.height !== 0;
1527
- }
1528
-
1529
- /**
1530
- * Checks if the node has any color properties set.
1531
- */
1532
- hasColorProperties(): boolean {
1533
- return (
1534
- this.props.color !== 0 ||
1535
- this.props.colorTop !== 0 ||
1536
- this.props.colorBottom !== 0 ||
1537
- this.props.colorLeft !== 0 ||
1538
- this.props.colorRight !== 0 ||
1539
- this.props.colorTl !== 0 ||
1540
- this.props.colorTr !== 0 ||
1541
- this.props.colorBl !== 0 ||
1542
- this.props.colorBr !== 0
1543
- );
1544
- }
1545
-
1546
- hasShader(): boolean {
1547
- return this.props.shader !== null;
1548
- }
1549
-
1550
- calculateRenderCoords() {
1551
- const { width, height } = this;
1552
- const { tx, ty, ta, tb, tc, td } = this.globalTransform!;
1553
- if (tb === 0 && tc === 0) {
1554
- const minX = tx;
1555
- const maxX = tx + width * ta;
1556
- const minY = ty;
1557
- const maxY = ty + height * td;
1558
- this.renderCoords = RenderCoords.translate(
1559
- //top-left
1560
- minX,
1561
- minY,
1562
- //top-right
1563
- maxX,
1564
- minY,
1565
- //bottom-right
1566
- maxX,
1567
- maxY,
1568
- //bottom-left
1569
- minX,
1570
- maxY,
1571
- this.renderCoords,
1572
- );
1573
- } else {
1574
- this.renderCoords = RenderCoords.translate(
1575
- //top-left
1576
- tx,
1577
- ty,
1578
- //top-right
1579
- tx + width * ta,
1580
- ty + width * tc,
1581
- //bottom-right
1582
- tx + width * ta + height * tb,
1583
- ty + width * tc + height * td,
1584
- //bottom-left
1585
- tx + height * tb,
1586
- ty + height * td,
1587
- this.renderCoords,
1588
- );
1589
- }
1590
- if (this.sceneGlobalTransform === undefined) {
1591
- return;
1592
- }
1593
-
1594
- const {
1595
- tx: stx,
1596
- ty: sty,
1597
- ta: sta,
1598
- tb: stb,
1599
- tc: stc,
1600
- td: std,
1601
- } = this.sceneGlobalTransform;
1602
- if (stb === 0 && stc === 0) {
1603
- const minX = stx;
1604
- const maxX = stx + width * sta;
1605
- const minY = sty;
1606
- const maxY = sty + height * std;
1607
- this.sceneRenderCoords = RenderCoords.translate(
1608
- //top-left
1609
- minX,
1610
- minY,
1611
- //top-right
1612
- maxX,
1613
- minY,
1614
- //bottom-right
1615
- maxX,
1616
- maxY,
1617
- //bottom-left
1618
- minX,
1619
- maxY,
1620
- this.sceneRenderCoords,
1621
- );
1622
- } else {
1623
- this.sceneRenderCoords = RenderCoords.translate(
1624
- //top-left
1625
- stx,
1626
- sty,
1627
- //top-right
1628
- stx + width * sta,
1629
- sty + width * stc,
1630
- //bottom-right
1631
- stx + width * sta + height * stb,
1632
- sty + width * stc + height * std,
1633
- //bottom-left
1634
- stx + height * stb,
1635
- sty + height * std,
1636
- this.sceneRenderCoords,
1637
- );
1638
- }
1639
- }
1640
-
1641
- /**
1642
- * This function calculates the clipping rectangle for a node.
1643
- *
1644
- * 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.
1645
- * 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.
1646
- *
1647
- * Finally, the node's parentClippingRect and clippingRect properties are updated.
1648
- */
1649
- calculateClippingRect(parentClippingRect: RectWithValid) {
1650
- assertTruthy(this.globalTransform);
1651
- const { clippingRect, props, globalTransform: gt } = this;
1652
- const { clipping } = props;
1653
- const isRotated = gt.tb !== 0 || gt.tc !== 0;
1654
-
1655
- if (clipping === true && isRotated === false) {
1656
- clippingRect.x = gt.tx;
1657
- clippingRect.y = gt.ty;
1658
- clippingRect.width = this.width * gt.ta;
1659
- clippingRect.height = this.height * gt.td;
1660
- clippingRect.valid = true;
1661
- } else {
1662
- clippingRect.valid = false;
1663
- }
1664
-
1665
- if (parentClippingRect.valid === true && clippingRect.valid === true) {
1666
- // Intersect parent clipping rect with node clipping rect
1667
- intersectRect(parentClippingRect, clippingRect, clippingRect);
1668
- } else if (parentClippingRect.valid === true) {
1669
- // Copy parent clipping rect
1670
- copyRect(parentClippingRect, clippingRect);
1671
- clippingRect.valid = true;
1672
- }
1673
- }
1674
-
1675
- calculateZIndex(): void {
1676
- const props = this.props;
1677
- const z = props.zIndex || 0;
1678
- const p = props.parent?.zIndex || 0;
1679
-
1680
- let zIndex = z;
1681
- if (props.parent?.zIndexLocked) {
1682
- zIndex = z < p ? z : p;
1683
- }
1684
- this.calcZIndex = zIndex;
1685
- }
1686
-
1687
- /**
1688
- * Destroy the node and cleanup all resources
1689
- */
1690
- destroy(): void {
1691
- this.unloadTexture();
1692
-
1693
- this.clippingRect.valid = false;
1694
- this.isRenderable = false;
1695
-
1696
- this.renderCoords = undefined;
1697
- this.renderBound = undefined;
1698
- this.strictBound = undefined;
1699
- this.preloadBound = undefined;
1700
- this.globalTransform = undefined;
1701
- this.scaleRotateTransform = undefined;
1702
- this.localTransform = undefined;
1703
-
1704
- this.props.texture = null;
1705
- this.props.shader = this.stage.defShaderNode;
1706
-
1707
- while (this.children.length > 0) {
1708
- this.children[0]?.destroy();
1709
- }
1710
-
1711
- // This very action will also remove the node from the parent's children array
1712
- this.parent = null;
1713
-
1714
- if (this.rtt) {
1715
- this.stage.renderer.removeRTTNode(this);
1716
- }
1717
-
1718
- this.removeAllListeners();
1719
- }
1720
-
1721
- renderQuads(renderer: CoreRenderer): void {
1722
- // Prevent quad rendering if parent has a render texture
1723
- // and renderer is not currently rendering to a texture
1724
- if (this.parentHasRenderTexture) {
1725
- if (!renderer.renderToTextureActive) {
1726
- return;
1727
- }
1728
- // Prevent quad rendering if parent render texture is not the active render texture
1729
- if (this.parentRenderTexture !== renderer.activeRttNode) {
1730
- return;
1731
- }
1732
- }
1733
-
1734
- assertTruthy(this.globalTransform);
1735
- assertTruthy(this.renderCoords);
1736
-
1737
- // add to list of renderables to be sorted before rendering
1738
- renderer.addQuad({
1739
- width: this.props.width,
1740
- height: this.props.height,
1741
- colorTl: this.premultipliedColorTl,
1742
- colorTr: this.premultipliedColorTr,
1743
- colorBl: this.premultipliedColorBl,
1744
- colorBr: this.premultipliedColorBr,
1745
- // if we do not have a texture, use the default texture
1746
- // this assumes any renderable node is either a distinct texture or a ColorTexture
1747
- texture: this.texture || this.stage.defaultTexture,
1748
- textureOptions: this.textureOptions,
1749
- zIndex: this.zIndex,
1750
- shader: this.props.shader as CoreShaderNode<any>,
1751
- alpha: this.worldAlpha,
1752
- clippingRect: this.clippingRect,
1753
- tx: this.globalTransform.tx,
1754
- ty: this.globalTransform.ty,
1755
- ta: this.globalTransform.ta,
1756
- tb: this.globalTransform.tb,
1757
- tc: this.globalTransform.tc,
1758
- td: this.globalTransform.td,
1759
- renderCoords: this.renderCoords,
1760
- rtt: this.rtt,
1761
- parentHasRenderTexture: this.parentHasRenderTexture,
1762
- framebufferDimensions: this.framebufferDimensions,
1763
- });
1764
- }
1765
-
1766
- //#region Properties
1767
- get id(): number {
1768
- return this._id;
1769
- }
1770
-
1771
- get data(): CustomDataMap | undefined {
1772
- return this.props.data;
1773
- }
1774
-
1775
- set data(d: CustomDataMap | undefined) {
1776
- this.props.data = d;
1777
- }
1778
-
1779
- get x(): number {
1780
- return this.props.x;
1781
- }
1782
-
1783
- set x(value: number) {
1784
- if (this.props.x !== value) {
1785
- this.props.x = value;
1786
- this.setUpdateType(UpdateType.Local);
1787
- }
1788
- }
1789
-
1790
- get absX(): number {
1791
- return (
1792
- this.props.x +
1793
- -this.props.width * this.props.mountX +
1794
- (this.props.parent?.absX || this.props.parent?.globalTransform?.tx || 0)
1795
- );
1796
- }
1797
-
1798
- get absY(): number {
1799
- return (
1800
- this.props.y +
1801
- -this.props.height * this.props.mountY +
1802
- (this.props.parent?.absY ?? 0)
1803
- );
1804
- }
1805
-
1806
- get y(): number {
1807
- return this.props.y;
1808
- }
1809
-
1810
- set y(value: number) {
1811
- if (this.props.y !== value) {
1812
- this.props.y = value;
1813
- this.setUpdateType(UpdateType.Local);
1814
- }
1815
- }
1816
-
1817
- get width(): number {
1818
- return this.props.width;
1819
- }
1820
-
1821
- set width(value: number) {
1822
- if (this.props.width !== value) {
1823
- this.props.width = value;
1824
- this.setUpdateType(UpdateType.Local);
1825
-
1826
- if (this.props.rtt) {
1827
- this.texture = this.stage.txManager.createTexture('RenderTexture', {
1828
- width: this.width,
1829
- height: this.height,
1830
- });
1831
-
1832
- this.setUpdateType(UpdateType.RenderTexture);
1833
- }
1834
- }
1835
- }
1836
-
1837
- get height(): number {
1838
- return this.props.height;
1839
- }
1840
-
1841
- set height(value: number) {
1842
- if (this.props.height !== value) {
1843
- this.props.height = value;
1844
- this.setUpdateType(UpdateType.Local);
1845
-
1846
- if (this.props.rtt) {
1847
- this.texture = this.stage.txManager.createTexture('RenderTexture', {
1848
- width: this.width,
1849
- height: this.height,
1850
- });
1851
-
1852
- this.setUpdateType(UpdateType.RenderTexture);
1853
- }
1854
- }
1855
- }
1856
-
1857
- get scale(): number {
1858
- // The CoreNode `scale` property is only used by Animations.
1859
- // Unlike INode, `null` should never be possibility for Animations.
1860
- return this.scaleX;
1861
- }
1862
-
1863
- set scale(value: number) {
1864
- // The CoreNode `scale` property is only used by Animations.
1865
- // Unlike INode, `null` should never be possibility for Animations.
1866
- this.scaleX = value;
1867
- this.scaleY = value;
1868
- }
1869
-
1870
- get scaleX(): number {
1871
- return this.props.scaleX;
1872
- }
1873
-
1874
- set scaleX(value: number) {
1875
- if (this.props.scaleX !== value) {
1876
- this.props.scaleX = value;
1877
- this.setUpdateType(UpdateType.ScaleRotate);
1878
- }
1879
- }
1880
-
1881
- get scaleY(): number {
1882
- return this.props.scaleY;
1883
- }
1884
-
1885
- set scaleY(value: number) {
1886
- if (this.props.scaleY !== value) {
1887
- this.props.scaleY = value;
1888
- this.setUpdateType(UpdateType.ScaleRotate);
1889
- }
1890
- }
1891
-
1892
- get mount(): number {
1893
- return this.props.mount;
1894
- }
1895
-
1896
- set mount(value: number) {
1897
- if (this.props.mountX !== value || this.props.mountY !== value) {
1898
- this.props.mountX = value;
1899
- this.props.mountY = value;
1900
- this.props.mount = value;
1901
- this.setUpdateType(UpdateType.Local);
1902
- }
1903
- }
1904
-
1905
- get mountX(): number {
1906
- return this.props.mountX;
1907
- }
1908
-
1909
- set mountX(value: number) {
1910
- if (this.props.mountX !== value) {
1911
- this.props.mountX = value;
1912
- this.setUpdateType(UpdateType.Local);
1913
- }
1914
- }
1915
-
1916
- get mountY(): number {
1917
- return this.props.mountY;
1918
- }
1919
-
1920
- set mountY(value: number) {
1921
- if (this.props.mountY !== value) {
1922
- this.props.mountY = value;
1923
- this.setUpdateType(UpdateType.Local);
1924
- }
1925
- }
1926
-
1927
- get pivot(): number {
1928
- return this.props.pivot;
1929
- }
1930
-
1931
- set pivot(value: number) {
1932
- if (this.props.pivotX !== value || this.props.pivotY !== value) {
1933
- this.props.pivotX = value;
1934
- this.props.pivotY = value;
1935
- this.props.pivot = value;
1936
- this.setUpdateType(UpdateType.Local);
1937
- }
1938
- }
1939
-
1940
- get pivotX(): number {
1941
- return this.props.pivotX;
1942
- }
1943
-
1944
- set pivotX(value: number) {
1945
- if (this.props.pivotX !== value) {
1946
- this.props.pivotX = value;
1947
- this.setUpdateType(UpdateType.Local);
1948
- }
1949
- }
1950
-
1951
- get pivotY(): number {
1952
- return this.props.pivotY;
1953
- }
1954
-
1955
- set pivotY(value: number) {
1956
- if (this.props.pivotY !== value) {
1957
- this.props.pivotY = value;
1958
- this.setUpdateType(UpdateType.Local);
1959
- }
1960
- }
1961
-
1962
- get rotation(): number {
1963
- return this.props.rotation;
1964
- }
1965
-
1966
- set rotation(value: number) {
1967
- if (this.props.rotation !== value) {
1968
- this.props.rotation = value;
1969
- this.setUpdateType(UpdateType.ScaleRotate);
1970
- }
1971
- }
1972
-
1973
- get alpha(): number {
1974
- return this.props.alpha;
1975
- }
1976
-
1977
- set alpha(value: number) {
1978
- this.props.alpha = value;
1979
- this.setUpdateType(
1980
- UpdateType.PremultipliedColors |
1981
- UpdateType.WorldAlpha |
1982
- UpdateType.Children |
1983
- UpdateType.IsRenderable,
1984
- );
1985
- this.childUpdateType |= UpdateType.WorldAlpha;
1986
- }
1987
-
1988
- get autosize(): boolean {
1989
- return this.props.autosize;
1990
- }
1991
-
1992
- set autosize(value: boolean) {
1993
- this.props.autosize = value;
1994
- }
1995
-
1996
- get boundsMargin(): number | [number, number, number, number] | null {
1997
- return (
1998
- this.props.boundsMargin ??
1999
- this.parent?.boundsMargin ??
2000
- this.stage.boundsMargin
2001
- );
2002
- }
2003
-
2004
- set boundsMargin(value: number | [number, number, number, number] | null) {
2005
- if (value === this.props.boundsMargin) {
2006
- return;
2007
- }
2008
-
2009
- if (value === null) {
2010
- this.props.boundsMargin = value;
2011
- } else {
2012
- const bm: [number, number, number, number] = Array.isArray(value)
2013
- ? value
2014
- : [value, value, value, value];
2015
-
2016
- this.props.boundsMargin = bm;
2017
- }
2018
- this.setUpdateType(UpdateType.RenderBounds);
2019
- }
2020
-
2021
- get clipping(): boolean {
2022
- return this.props.clipping;
2023
- }
2024
-
2025
- set clipping(value: boolean) {
2026
- this.props.clipping = value;
2027
- this.setUpdateType(
2028
- UpdateType.Clipping | UpdateType.RenderBounds | UpdateType.Children,
2029
- );
2030
- this.childUpdateType |= UpdateType.Global | UpdateType.Clipping;
2031
- }
2032
-
2033
- get color(): number {
2034
- return this.props.color;
2035
- }
2036
-
2037
- set color(value: number) {
2038
- this.colorTop = value;
2039
- this.colorBottom = value;
2040
- this.colorLeft = value;
2041
- this.colorRight = value;
2042
- this.props.color = value;
2043
-
2044
- this.setUpdateType(UpdateType.PremultipliedColors);
2045
- }
2046
-
2047
- get colorTop(): number {
2048
- return this.props.colorTop;
2049
- }
2050
-
2051
- set colorTop(value: number) {
2052
- if (this.props.colorTl !== value || this.props.colorTr !== value) {
2053
- this.colorTl = value;
2054
- this.colorTr = value;
2055
- }
2056
- this.props.colorTop = value;
2057
- this.setUpdateType(UpdateType.PremultipliedColors);
2058
- }
2059
-
2060
- get colorBottom(): number {
2061
- return this.props.colorBottom;
2062
- }
2063
-
2064
- set colorBottom(value: number) {
2065
- if (this.props.colorBl !== value || this.props.colorBr !== value) {
2066
- this.colorBl = value;
2067
- this.colorBr = value;
2068
- }
2069
- this.props.colorBottom = value;
2070
- this.setUpdateType(UpdateType.PremultipliedColors);
2071
- }
2072
-
2073
- get colorLeft(): number {
2074
- return this.props.colorLeft;
2075
- }
2076
-
2077
- set colorLeft(value: number) {
2078
- if (this.props.colorTl !== value || this.props.colorBl !== value) {
2079
- this.colorTl = value;
2080
- this.colorBl = value;
2081
- }
2082
- this.props.colorLeft = value;
2083
- this.setUpdateType(UpdateType.PremultipliedColors);
2084
- }
2085
-
2086
- get colorRight(): number {
2087
- return this.props.colorRight;
2088
- }
2089
-
2090
- set colorRight(value: number) {
2091
- if (this.props.colorTr !== value || this.props.colorBr !== value) {
2092
- this.colorTr = value;
2093
- this.colorBr = value;
2094
- }
2095
- this.props.colorRight = value;
2096
- this.setUpdateType(UpdateType.PremultipliedColors);
2097
- }
2098
-
2099
- get colorTl(): number {
2100
- return this.props.colorTl;
2101
- }
2102
-
2103
- set colorTl(value: number) {
2104
- this.props.colorTl = value;
2105
- this.setUpdateType(UpdateType.PremultipliedColors);
2106
- }
2107
-
2108
- get colorTr(): number {
2109
- return this.props.colorTr;
2110
- }
2111
-
2112
- set colorTr(value: number) {
2113
- this.props.colorTr = value;
2114
- this.setUpdateType(UpdateType.PremultipliedColors);
2115
- }
2116
-
2117
- get colorBl(): number {
2118
- return this.props.colorBl;
2119
- }
2120
-
2121
- set colorBl(value: number) {
2122
- this.props.colorBl = value;
2123
- this.setUpdateType(UpdateType.PremultipliedColors);
2124
- }
2125
-
2126
- get colorBr(): number {
2127
- return this.props.colorBr;
2128
- }
2129
-
2130
- set colorBr(value: number) {
2131
- this.props.colorBr = value;
2132
- this.setUpdateType(UpdateType.PremultipliedColors);
2133
- }
2134
-
2135
- // we're only interested in parent zIndex to test
2136
- // if we should use node zIndex is higher then parent zIndex
2137
- get zIndexLocked(): number {
2138
- return this.props.zIndexLocked || 0;
2139
- }
2140
-
2141
- set zIndexLocked(value: number) {
2142
- this.props.zIndexLocked = value;
2143
- this.setUpdateType(UpdateType.CalculatedZIndex | UpdateType.Children);
2144
- for (let i = 0, length = this.children.length; i < length; i++) {
2145
- this.children[i]!.setUpdateType(UpdateType.CalculatedZIndex);
2146
- }
2147
- }
2148
-
2149
- get zIndex(): number {
2150
- return this.props.zIndex;
2151
- }
2152
-
2153
- set zIndex(value: number) {
2154
- this.props.zIndex = value;
2155
- this.setUpdateType(UpdateType.CalculatedZIndex | UpdateType.Children);
2156
- for (let i = 0, length = this.children.length; i < length; i++) {
2157
- this.children[i]!.setUpdateType(UpdateType.CalculatedZIndex);
2158
- }
2159
- }
2160
-
2161
- get parent(): CoreNode | null {
2162
- return this.props.parent;
2163
- }
2164
-
2165
- set parent(newParent: CoreNode | null) {
2166
- const oldParent = this.props.parent;
2167
- if (oldParent === newParent) {
2168
- return;
2169
- }
2170
- this.props.parent = newParent;
2171
- if (oldParent) {
2172
- const index = oldParent.children.indexOf(this);
2173
- assertTruthy(
2174
- index !== -1,
2175
- "CoreNode.parent: Node not found in old parent's children!",
2176
- );
2177
- oldParent.children.splice(index, 1);
2178
- oldParent.setUpdateType(
2179
- UpdateType.Children | UpdateType.ZIndexSortedChildren,
2180
- );
2181
- }
2182
- if (newParent) {
2183
- newParent.children.push(this);
2184
- // Since this node has a new parent, to be safe, have it do a full update.
2185
- this.setUpdateType(UpdateType.All);
2186
- // Tell parent that it's children need to be updated and sorted.
2187
- newParent.setUpdateType(
2188
- UpdateType.Children | UpdateType.ZIndexSortedChildren,
2189
- );
2190
-
2191
- // If the new parent has an RTT enabled, apply RTT inheritance
2192
- if (newParent.rtt || newParent.parentHasRenderTexture) {
2193
- this.applyRTTInheritance(newParent);
2194
- }
2195
- }
2196
- this.updateScaleRotateTransform();
2197
-
2198
- // fetch render bounds from parent
2199
- this.setUpdateType(UpdateType.RenderBounds | UpdateType.Children);
2200
- }
2201
-
2202
- get preventCleanup(): boolean {
2203
- return this.props.textureOptions.preventCleanup || false;
2204
- }
2205
-
2206
- set preventCleanup(value: boolean) {
2207
- if (isProductionEnvironment() === false) {
2208
- console.warn(
2209
- 'CoreNode.preventCleanup: Is deprecated and will be removed in upcoming release, please use textureOptions.preventCleanup instead',
2210
- );
2211
- }
2212
-
2213
- this.props.textureOptions.preventCleanup = value;
2214
- }
2215
-
2216
- get rtt(): boolean {
2217
- return this.props.rtt;
2218
- }
2219
-
2220
- set rtt(value: boolean) {
2221
- if (this.props.rtt === value) {
2222
- return;
2223
- }
2224
- this.props.rtt = value;
2225
-
2226
- if (value === true) {
2227
- this.initRenderTexture();
2228
- this.markChildrenWithRTT();
2229
- } else {
2230
- this.cleanupRenderTexture();
2231
- }
2232
-
2233
- this.setUpdateType(UpdateType.RenderTexture);
2234
-
2235
- if (this.parentHasRenderTexture === true) {
2236
- this.notifyParentRTTOfUpdate();
2237
- }
2238
- }
2239
- private initRenderTexture() {
2240
- this.texture = this.stage.txManager.createTexture('RenderTexture', {
2241
- width: this.width,
2242
- height: this.height,
2243
- });
2244
-
2245
- this.stage.renderer.renderToTexture(this);
2246
- }
2247
-
2248
- private cleanupRenderTexture() {
2249
- this.unloadTexture();
2250
- this.clearRTTInheritance();
2251
-
2252
- this.hasRTTupdates = false;
2253
- this.texture = null;
2254
- }
2255
-
2256
- private markChildrenWithRTT(node: CoreNode | null = null) {
2257
- const parent = node || this;
2258
-
2259
- for (const child of parent.children) {
2260
- child.setUpdateType(UpdateType.All);
2261
- child.parentHasRenderTexture = true;
2262
- child.markChildrenWithRTT();
2263
- }
2264
- }
2265
-
2266
- // Apply RTT inheritance when a node has an RTT-enabled parent
2267
- private applyRTTInheritance(parent: CoreNode) {
2268
- if (parent.rtt) {
2269
- // Only the RTT node should be added to `renderToTexture`
2270
- parent.setUpdateType(UpdateType.RenderTexture);
2271
- }
2272
-
2273
- // Propagate `parentHasRenderTexture` downwards
2274
- this.markChildrenWithRTT(parent);
2275
- }
2276
-
2277
- // Clear RTT inheritance when detaching from an RTT chain
2278
- private clearRTTInheritance() {
2279
- // if this node is RTT itself stop the propagation important for nested RTT nodes
2280
- // for the initial RTT node this is already handled in `set rtt`
2281
- if (this.rtt) {
2282
- return;
2283
- }
2284
-
2285
- for (const child of this.children) {
2286
- // force child to update everything as the RTT inheritance has changed
2287
- child.parentHasRenderTexture = false;
2288
- child.rttParent = null;
2289
- child.setUpdateType(UpdateType.All);
2290
- child.clearRTTInheritance();
2291
- }
2292
- }
2293
-
2294
- get shader(): CoreShaderNode<any> | null {
2295
- return this.props.shader;
2296
- }
2297
-
2298
- set shader(shader: CoreShaderNode<any> | null) {
2299
- if (this.props.shader === shader) {
2300
- return;
2301
- }
2302
- if (shader === null) {
2303
- this.props.shader = this.stage.defShaderNode;
2304
- this.setUpdateType(UpdateType.IsRenderable);
2305
- return;
2306
- }
2307
- shader.attachNode(this);
2308
- this.props.shader = shader;
2309
- this.setUpdateType(UpdateType.IsRenderable);
2310
- }
2311
-
2312
- get src(): string | null {
2313
- return this.props.src;
2314
- }
2315
-
2316
- set src(imageUrl: string | null) {
2317
- if (this.props.src === imageUrl) {
2318
- return;
2319
- }
2320
-
2321
- this.props.src = imageUrl;
2322
-
2323
- if (!imageUrl) {
2324
- this.texture = null;
2325
- return;
2326
- }
2327
-
2328
- this.texture = this.stage.txManager.createTexture('ImageTexture', {
2329
- src: imageUrl,
2330
- width: this.props.width,
2331
- height: this.props.height,
2332
- type: this.props.imageType,
2333
- sx: this.props.srcX,
2334
- sy: this.props.srcY,
2335
- sw: this.props.srcWidth,
2336
- sh: this.props.srcHeight,
2337
- });
2338
- }
2339
-
2340
- set imageType(type: 'regular' | 'compressed' | 'svg' | null) {
2341
- if (this.props.imageType === type) {
2342
- return;
2343
- }
2344
-
2345
- this.props.imageType = type;
2346
- }
2347
-
2348
- get imageType() {
2349
- return this.props.imageType || null;
2350
- }
2351
-
2352
- get srcHeight(): number | undefined {
2353
- return this.props.srcHeight;
2354
- }
2355
-
2356
- set srcHeight(value: number) {
2357
- this.props.srcHeight = value;
2358
- }
2359
-
2360
- get srcWidth(): number | undefined {
2361
- return this.props.srcWidth;
2362
- }
2363
-
2364
- set srcWidth(value: number) {
2365
- this.props.srcWidth = value;
2366
- }
2367
-
2368
- get srcX(): number | undefined {
2369
- return this.props.srcX;
2370
- }
2371
-
2372
- set srcX(value: number) {
2373
- this.props.srcX = value;
2374
- }
2375
-
2376
- get srcY(): number | undefined {
2377
- return this.props.srcY;
2378
- }
2379
-
2380
- set srcY(value: number) {
2381
- this.props.srcY = value;
2382
- }
2383
-
2384
- /**
2385
- * Returns the framebuffer dimensions of the node.
2386
- * If the node has a render texture, the dimensions are the same as the node's dimensions.
2387
- * If the node does not have a render texture, the dimensions are inherited from the parent.
2388
- * If the node parent has a render texture and the node is a render texture, the nodes dimensions are used.
2389
- */
2390
- get framebufferDimensions(): Dimensions {
2391
- if (this.parentHasRenderTexture && !this.rtt && this.parent) {
2392
- return this.parent.framebufferDimensions;
2393
- }
2394
- return { width: this.width, height: this.height };
2395
- }
2396
-
2397
- /**
2398
- * Returns the parent render texture node if it exists.
2399
- */
2400
- get parentRenderTexture(): CoreNode | null {
2401
- let parent = this.parent;
2402
- while (parent) {
2403
- if (parent.rtt) {
2404
- return parent;
2405
- }
2406
- parent = parent.parent;
2407
- }
2408
- return null;
2409
- }
2410
-
2411
- get texture(): Texture | null {
2412
- return this.props.texture;
2413
- }
2414
-
2415
- set texture(value: Texture | null) {
2416
- if (this.props.texture === value) {
2417
- return;
2418
- }
2419
-
2420
- const oldTexture = this.props.texture;
2421
- if (oldTexture) {
2422
- oldTexture.setRenderableOwner(this, false);
2423
- this.unloadTexture();
2424
- }
2425
-
2426
- this.props.texture = value;
2427
- if (value !== null) {
2428
- value.setRenderableOwner(this, this.isRenderable);
2429
- this.loadTexture();
2430
- }
2431
-
2432
- this.setUpdateType(UpdateType.IsRenderable);
2433
- }
2434
-
2435
- set textureOptions(value: TextureOptions) {
2436
- this.props.textureOptions = value;
2437
- }
2438
-
2439
- get textureOptions(): TextureOptions {
2440
- return this.props.textureOptions;
2441
- }
2442
-
2443
- get strictBounds(): boolean {
2444
- return this.props.strictBounds;
2445
- }
2446
-
2447
- set strictBounds(v) {
2448
- if (v === this.props.strictBounds) {
2449
- return;
2450
- }
2451
-
2452
- this.props.strictBounds = v;
2453
- this.setUpdateType(UpdateType.RenderBounds | UpdateType.Children);
2454
- this.childUpdateType |= UpdateType.RenderBounds | UpdateType.Children;
2455
- }
2456
-
2457
- animate(
2458
- props: Partial<CoreNodeAnimateProps>,
2459
- settings: Partial<AnimationSettings>,
2460
- ): IAnimationController {
2461
- const animation = new CoreAnimation(this, props, settings);
2462
-
2463
- const controller = new CoreAnimationController(
2464
- this.stage.animationManager,
2465
- animation,
2466
- );
2467
-
2468
- return controller;
2469
- }
2470
-
2471
- flush() {
2472
- // no-op
2473
- }
2474
-
2475
- //#endregion Properties
2476
- }
1
+ /*
2
+ * If not stated otherwise in this file or this component's LICENSE file the
3
+ * following copyright and licenses apply:
4
+ *
5
+ * Copyright 2023 Comcast Cable Communications Management, LLC.
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the License);
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+
20
+ import {
21
+ assertTruthy,
22
+ getNewId,
23
+ mergeColorAlphaPremultiplied,
24
+ } from '../utils.js';
25
+ import type { TextureOptions } from './CoreTextureManager.js';
26
+ import type { CoreRenderer } from './renderers/CoreRenderer.js';
27
+ import type { Stage } from './Stage.js';
28
+ import {
29
+ type Texture,
30
+ type TextureCoords,
31
+ type TextureFailedEventHandler,
32
+ type TextureFreedEventHandler,
33
+ type TextureLoadedEventHandler,
34
+ } from './textures/Texture.js';
35
+ import type {
36
+ Dimensions,
37
+ NodeTextureFailedPayload,
38
+ NodeTextureFreedPayload,
39
+ NodeTextureLoadedPayload,
40
+ } from '../common/CommonTypes.js';
41
+ import { EventEmitter } from '../common/EventEmitter.js';
42
+ import {
43
+ copyRect,
44
+ intersectRect,
45
+ type Bound,
46
+ type RectWithValid,
47
+ createBound,
48
+ boundInsideBound,
49
+ boundLargeThanBound,
50
+ createPreloadBounds,
51
+ } from './lib/utils.js';
52
+ import { Matrix3d } from './lib/Matrix3d.js';
53
+ import { RenderCoords } from './lib/RenderCoords.js';
54
+ import type { AnimationSettings } from './animations/CoreAnimation.js';
55
+ import type { IAnimationController } from '../common/IAnimationController.js';
56
+ import { CoreAnimation } from './animations/CoreAnimation.js';
57
+ import { CoreAnimationController } from './animations/CoreAnimationController.js';
58
+ import type { CoreShaderNode } from './renderers/CoreShaderNode.js';
59
+
60
+ export enum CoreNodeRenderState {
61
+ Init = 0,
62
+ OutOfBounds = 2,
63
+ InBounds = 4,
64
+ InViewport = 8,
65
+ }
66
+
67
+ const CoreNodeRenderStateMap: Map<CoreNodeRenderState, string> = new Map();
68
+ CoreNodeRenderStateMap.set(CoreNodeRenderState.Init, 'init');
69
+ CoreNodeRenderStateMap.set(CoreNodeRenderState.OutOfBounds, 'outOfBounds');
70
+ CoreNodeRenderStateMap.set(CoreNodeRenderState.InBounds, 'inBounds');
71
+ CoreNodeRenderStateMap.set(CoreNodeRenderState.InViewport, 'inViewport');
72
+
73
+ export enum UpdateType {
74
+ /**
75
+ * Child updates
76
+ */
77
+ Children = 1,
78
+
79
+ /**
80
+ * localTransform
81
+ *
82
+ * @remarks
83
+ * CoreNode Properties Updated:
84
+ * - `localTransform`
85
+ */
86
+ Local = 2,
87
+
88
+ /**
89
+ * globalTransform
90
+ *
91
+ * * @remarks
92
+ * CoreNode Properties Updated:
93
+ * - `globalTransform`
94
+ * - `renderBounds`
95
+ * - `renderCoords`
96
+ */
97
+ Global = 4,
98
+
99
+ /**
100
+ * Clipping rect update
101
+ *
102
+ * @remarks
103
+ * CoreNode Properties Updated:
104
+ * - `clippingRect`
105
+ */
106
+ Clipping = 8,
107
+
108
+ /**
109
+ * Calculated ZIndex update
110
+ *
111
+ * @remarks
112
+ * CoreNode Properties Updated:
113
+ * - `calcZIndex`
114
+ */
115
+ CalculatedZIndex = 16,
116
+
117
+ /**
118
+ * Z-Index Sorted Children update
119
+ *
120
+ * @remarks
121
+ * CoreNode Properties Updated:
122
+ * - `children` (sorts children by their `calcZIndex`)
123
+ */
124
+ ZIndexSortedChildren = 32,
125
+
126
+ /**
127
+ * Premultiplied Colors update
128
+ *
129
+ * @remarks
130
+ * CoreNode Properties Updated:
131
+ * - `premultipliedColorTl`
132
+ * - `premultipliedColorTr`
133
+ * - `premultipliedColorBl`
134
+ * - `premultipliedColorBr`
135
+ */
136
+ PremultipliedColors = 64,
137
+
138
+ /**
139
+ * World Alpha update
140
+ *
141
+ * @remarks
142
+ * CoreNode Properties Updated:
143
+ * - `worldAlpha` = `parent.worldAlpha` * `alpha`
144
+ */
145
+ WorldAlpha = 128,
146
+
147
+ /**
148
+ * Render State update
149
+ *
150
+ * @remarks
151
+ * CoreNode Properties Updated:
152
+ * - `renderState`
153
+ */
154
+ RenderState = 256,
155
+
156
+ /**
157
+ * Is Renderable update
158
+ *
159
+ * @remarks
160
+ * CoreNode Properties Updated:
161
+ * - `isRenderable`
162
+ */
163
+ IsRenderable = 512,
164
+
165
+ /**
166
+ * Render Texture update
167
+ */
168
+ RenderTexture = 1024,
169
+
170
+ /**
171
+ * Track if parent has render texture
172
+ */
173
+ ParentRenderTexture = 2048,
174
+
175
+ /**
176
+ * Render Bounds update
177
+ */
178
+ RenderBounds = 4096,
179
+
180
+ /**
181
+ * RecalcUniforms
182
+ */
183
+ RecalcUniforms = 8192,
184
+
185
+ /**
186
+ * None
187
+ */
188
+ None = 0,
189
+
190
+ /**
191
+ * All
192
+ */
193
+ All = 14335,
194
+ }
195
+
196
+ /**
197
+ * A custom data map which can be stored on an CoreNode
198
+ *
199
+ * @remarks
200
+ * This is a map of key-value pairs that can be stored on an INode. It is used
201
+ * to store custom data that can be used by the application.
202
+ * The data stored can only be of type string, number or boolean.
203
+ */
204
+ export type CustomDataMap = {
205
+ [key: string]: string | number | boolean | undefined;
206
+ };
207
+
208
+ /**
209
+ * Writable properties of a Node.
210
+ */
211
+ export interface CoreNodeProps {
212
+ /**
213
+ * The x coordinate of the Node's Mount Point.
214
+ *
215
+ * @remarks
216
+ * See {@link mountX} and {@link mountY} for more information about setting
217
+ * the Mount Point.
218
+ *
219
+ * @default `0`
220
+ */
221
+ x: number;
222
+ /**
223
+ * The y coordinate of the Node's Mount Point.
224
+ *
225
+ * @remarks
226
+ * See {@link mountX} and {@link mountY} for more information about setting
227
+ * the Mount Point.
228
+ *
229
+ * @default `0`
230
+ */
231
+ y: number;
232
+ /**
233
+ * The width of the Node.
234
+ *
235
+ * @default `0`
236
+ */
237
+ width: number;
238
+ /**
239
+ * The height of the Node.
240
+ *
241
+ * @default `0`
242
+ */
243
+ height: number;
244
+ /**
245
+ * The alpha opacity of the Node.
246
+ *
247
+ * @remarks
248
+ * The alpha value is a number between 0 and 1, where 0 is fully transparent
249
+ * and 1 is fully opaque.
250
+ *
251
+ * @default `1`
252
+ */
253
+ alpha: number;
254
+ /**
255
+ * Autosize mode
256
+ *
257
+ * @remarks
258
+ * When enabled, when a texture is loaded into the Node, the Node will
259
+ * automatically resize to the dimensions of the texture.
260
+ *
261
+ * Text Nodes are always autosized based on their text content regardless
262
+ * of this mode setting.
263
+ *
264
+ * @default `false`
265
+ */
266
+ autosize: boolean;
267
+ /**
268
+ * Margin around the Node's bounds for preloading
269
+ *
270
+ * @default `null`
271
+ */
272
+ boundsMargin: number | [number, number, number, number] | null;
273
+ /**
274
+ * Clipping Mode
275
+ *
276
+ * @remarks
277
+ * Enable Clipping Mode when you want to prevent the drawing of a Node and
278
+ * its descendants from overflowing outside of the Node's x/y/width/height
279
+ * bounds.
280
+ *
281
+ * For WebGL, clipping is implemented using the high-performance WebGL
282
+ * operation scissor. As a consequence, clipping does not work for
283
+ * non-rectangular areas. So, if the element is rotated
284
+ * (by itself or by any of its ancestors), clipping will not work as intended.
285
+ *
286
+ * TODO: Add support for non-rectangular clipping either automatically or
287
+ * via Render-To-Texture.
288
+ *
289
+ * @default `false`
290
+ */
291
+ clipping: boolean;
292
+ /**
293
+ * The color of the Node.
294
+ *
295
+ * @remarks
296
+ * The color value is a number in the format 0xRRGGBBAA, where RR is the red
297
+ * component, GG is the green component, BB is the blue component, and AA is
298
+ * the alpha component.
299
+ *
300
+ * Gradient colors may be set by setting the different color sub-properties:
301
+ * {@link colorTop}, {@link colorBottom}, {@link colorLeft}, {@link colorRight},
302
+ * {@link colorTl}, {@link colorTr}, {@link colorBr}, {@link colorBl} accordingly.
303
+ *
304
+ * @default `0xffffffff` (opaque white)
305
+ */
306
+ color: number;
307
+ /**
308
+ * The color of the top edge of the Node for gradient rendering.
309
+ *
310
+ * @remarks
311
+ * See {@link color} for more information about color values and gradient
312
+ * rendering.
313
+ */
314
+ colorTop: number;
315
+ /**
316
+ * The color of the bottom edge of the Node for gradient rendering.
317
+ *
318
+ * @remarks
319
+ * See {@link color} for more information about color values and gradient
320
+ * rendering.
321
+ */
322
+ colorBottom: number;
323
+ /**
324
+ * The color of the left 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
+ colorLeft: number;
331
+ /**
332
+ * The color of the right 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
+ colorRight: number;
339
+ /**
340
+ * The color of the top-left corner 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
+ colorTl: number;
347
+ /**
348
+ * The color of the top-right corner 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
+ colorTr: number;
355
+ /**
356
+ * The color of the bottom-right 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
+ colorBr: number;
363
+ /**
364
+ * The color of the bottom-left 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
+ colorBl: number;
371
+ /**
372
+ * The Node's parent Node.
373
+ *
374
+ * @remarks
375
+ * The value `null` indicates that the Node has no parent. This may either be
376
+ * because the Node is the root Node of the scene graph, or because the Node
377
+ * has been removed from the scene graph.
378
+ *
379
+ * In order to make sure that a Node can be rendered on the screen, it must
380
+ * be added to the scene graph by setting it's parent property to a Node that
381
+ * is already in the scene graph such as the root Node.
382
+ *
383
+ * @default `null`
384
+ */
385
+ parent: CoreNode | null;
386
+ /**
387
+ * The Node's z-index.
388
+ *
389
+ * @remarks
390
+ * TBD
391
+ */
392
+ zIndex: number;
393
+ /**
394
+ * The Node's Texture.
395
+ *
396
+ * @remarks
397
+ * The `texture` defines a rasterized image that is contained within the
398
+ * {@link width} and {@link height} dimensions of the Node. If null, the
399
+ * Node will use an opaque white {@link ColorTexture} when being drawn, which
400
+ * essentially enables colors (including gradients) to be drawn.
401
+ *
402
+ * If set, by default, the texture will be drawn, as is, stretched to the
403
+ * dimensions of the Node. This behavior can be modified by setting the TBD
404
+ * and TBD properties.
405
+ *
406
+ * To create a Texture in order to set it on this property, call
407
+ * {@link RendererMain.createTexture}.
408
+ *
409
+ * If the {@link src} is set on a Node, the Node will use the
410
+ * {@link ImageTexture} by default and the Node will simply load the image at
411
+ * the specified URL.
412
+ *
413
+ * Note: If this is a Text Node, the Texture will be managed by the Node's
414
+ * {@link TextRenderer} and should not be set explicitly.
415
+ */
416
+ texture: Texture | null;
417
+
418
+ /**
419
+ * Options to associate with the Node's Texture
420
+ */
421
+ textureOptions: TextureOptions;
422
+
423
+ /**
424
+ * The Node's shader
425
+ *
426
+ * @remarks
427
+ * The `shader` defines a {@link Shader} used to draw the Node. By default,
428
+ * the Default Shader is used which simply draws the defined {@link texture}
429
+ * or {@link color}(s) within the Node without any special effects.
430
+ *
431
+ * To create a Shader in order to set it on this property, call
432
+ * {@link RendererMain.createShader}.
433
+ *
434
+ * Note: If this is a Text Node, the Shader will be managed by the Node's
435
+ * {@link TextRenderer} and should not be set explicitly.
436
+ */
437
+ shader: CoreShaderNode<any> | null;
438
+ /**
439
+ * Image URL
440
+ *
441
+ * @remarks
442
+ * When set, the Node's {@link texture} is automatically set to an
443
+ * {@link ImageTexture} using the source image URL provided (with all other
444
+ * settings being defaults)
445
+ */
446
+ src: string | null;
447
+ zIndexLocked: number;
448
+ /**
449
+ * Scale to render the Node at
450
+ *
451
+ * @remarks
452
+ * The scale value multiplies the provided {@link width} and {@link height}
453
+ * of the Node around the Node's Pivot Point (defined by the {@link pivot}
454
+ * props).
455
+ *
456
+ * Behind the scenes, setting this property sets both the {@link scaleX} and
457
+ * {@link scaleY} props to the same value.
458
+ *
459
+ * NOTE: When the scaleX and scaleY props are explicitly set to different values,
460
+ * this property returns `null`. Setting `null` on this property will have no
461
+ * effect.
462
+ *
463
+ * @default 1.0
464
+ */
465
+ scale: number | null;
466
+ /**
467
+ * Scale to render the Node at (X-Axis)
468
+ *
469
+ * @remarks
470
+ * The scaleX value multiplies the provided {@link width} of the Node around
471
+ * the Node's Pivot Point (defined by the {@link pivot} props).
472
+ *
473
+ * @default 1.0
474
+ */
475
+ scaleX: number;
476
+ /**
477
+ * Scale to render the Node at (Y-Axis)
478
+ *
479
+ * @remarks
480
+ * The scaleY value multiplies the provided {@link height} of the Node around
481
+ * the Node's Pivot Point (defined by the {@link pivot} props).
482
+ *
483
+ * @default 1.0
484
+ */
485
+ scaleY: number;
486
+ /**
487
+ * Combined position of the Node's Mount Point
488
+ *
489
+ * @remarks
490
+ * The value can be any number between `0.0` and `1.0`:
491
+ * - `0.0` defines the Mount Point at the top-left corner of the Node.
492
+ * - `0.5` defines it at the center of the Node.
493
+ * - `1.0` defines it at the bottom-right corner of the node.
494
+ *
495
+ * Use the {@link mountX} and {@link mountY} props seperately for more control
496
+ * of the Mount Point.
497
+ *
498
+ * When assigned, the same value is also passed to both the {@link mountX} and
499
+ * {@link mountY} props.
500
+ *
501
+ * @default 0 (top-left)
502
+ */
503
+ mount: number;
504
+ /**
505
+ * X position of the Node's Mount Point
506
+ *
507
+ * @remarks
508
+ * The value can be any number between `0.0` and `1.0`:
509
+ * - `0.0` defines the Mount Point's X position as the left-most edge of the
510
+ * Node
511
+ * - `0.5` defines it as the horizontal center of the Node
512
+ * - `1.0` defines it as the right-most edge of the Node.
513
+ *
514
+ * The combination of {@link mountX} and {@link mountY} define the Mount Point
515
+ *
516
+ * @default 0 (left-most edge)
517
+ */
518
+ mountX: number;
519
+ /**
520
+ * Y position of the Node's Mount Point
521
+ *
522
+ * @remarks
523
+ * The value can be any number between `0.0` and `1.0`:
524
+ * - `0.0` defines the Mount Point's Y position as the top-most edge of the
525
+ * Node
526
+ * - `0.5` defines it as the vertical center of the Node
527
+ * - `1.0` defines it as the bottom-most edge of the Node.
528
+ *
529
+ * The combination of {@link mountX} and {@link mountY} define the Mount Point
530
+ *
531
+ * @default 0 (top-most edge)
532
+ */
533
+ mountY: number;
534
+ /**
535
+ * Combined position of the Node's Pivot Point
536
+ *
537
+ * @remarks
538
+ * The value can be any number between `0.0` and `1.0`:
539
+ * - `0.0` defines the Pivot Point at the top-left corner of the Node.
540
+ * - `0.5` defines it at the center of the Node.
541
+ * - `1.0` defines it at the bottom-right corner of the node.
542
+ *
543
+ * Use the {@link pivotX} and {@link pivotY} props seperately for more control
544
+ * of the Pivot Point.
545
+ *
546
+ * When assigned, the same value is also passed to both the {@link pivotX} and
547
+ * {@link pivotY} props.
548
+ *
549
+ * @default 0.5 (center)
550
+ */
551
+ pivot: number;
552
+ /**
553
+ * X position of the Node's Pivot Point
554
+ *
555
+ * @remarks
556
+ * The value can be any number between `0.0` and `1.0`:
557
+ * - `0.0` defines the Pivot Point's X position as the left-most edge of the
558
+ * Node
559
+ * - `0.5` defines it as the horizontal center of the Node
560
+ * - `1.0` defines it as the right-most edge of the Node.
561
+ *
562
+ * The combination of {@link pivotX} and {@link pivotY} define the Pivot Point
563
+ *
564
+ * @default 0.5 (centered on x-axis)
565
+ */
566
+ pivotX: number;
567
+ /**
568
+ * Y position of the Node's Pivot Point
569
+ *
570
+ * @remarks
571
+ * The value can be any number between `0.0` and `1.0`:
572
+ * - `0.0` defines the Pivot Point's Y position as the top-most edge of the
573
+ * Node
574
+ * - `0.5` defines it as the vertical center of the Node
575
+ * - `1.0` defines it as the bottom-most edge of the Node.
576
+ *
577
+ * The combination of {@link pivotX} and {@link pivotY} define the Pivot Point
578
+ *
579
+ * @default 0.5 (centered on y-axis)
580
+ */
581
+ pivotY: number;
582
+ /**
583
+ * Rotation of the Node (in Radians)
584
+ *
585
+ * @remarks
586
+ * Sets the amount to rotate the Node by around it's Pivot Point (defined by
587
+ * the {@link pivot} props). Positive values rotate the Node clockwise, while
588
+ * negative values rotate it counter-clockwise.
589
+ *
590
+ * Example values:
591
+ * - `-Math.PI / 2`: 90 degree rotation counter-clockwise
592
+ * - `0`: No rotation
593
+ * - `Math.PI / 2`: 90 degree rotation clockwise
594
+ * - `Math.PI`: 180 degree rotation clockwise
595
+ * - `3 * Math.PI / 2`: 270 degree rotation clockwise
596
+ * - `2 * Math.PI`: 360 rotation clockwise
597
+ */
598
+ rotation: number;
599
+
600
+ /**
601
+ * Whether the Node is rendered to a texture
602
+ *
603
+ * @remarks
604
+ * TBD
605
+ *
606
+ * @default false
607
+ */
608
+ rtt: boolean;
609
+
610
+ /**
611
+ * Node data element for custom data storage (optional)
612
+ *
613
+ * @remarks
614
+ * This property is used to store custom data on the Node as a key/value data store.
615
+ * Data values are limited to string, numbers, booleans. Strings will be truncated
616
+ * to a 2048 character limit for performance reasons.
617
+ *
618
+ * This is not a data storage mechanism for large amounts of data please use a
619
+ * dedicated data storage mechanism for that.
620
+ *
621
+ * The custom data will be reflected in the inspector as part of `data-*` attributes
622
+ *
623
+ * @default `undefined`
624
+ */
625
+ data?: CustomDataMap;
626
+
627
+ /**
628
+ * Image Type to explicitly set the image type that is being loaded
629
+ *
630
+ * @remarks
631
+ * This property must be used with a `src` that points at an image. In some cases
632
+ * the extension doesn't provide a reliable representation of the image type. In such
633
+ * cases set the ImageType explicitly.
634
+ *
635
+ * `regular` is used for normal images such as png, jpg, etc
636
+ * `compressed` is used for ETC1/ETC2 compressed images with a PVR or KTX container
637
+ * `svg` is used for scalable vector graphics
638
+ *
639
+ * @default `undefined`
640
+ */
641
+ imageType?: 'regular' | 'compressed' | 'svg' | null;
642
+
643
+ /**
644
+ * She width of the rectangle from which the Image Texture will be extracted.
645
+ * This value can be negative. If not provided, the image's source natural
646
+ * width will be used.
647
+ */
648
+ srcWidth?: number;
649
+ /**
650
+ * The height of the rectangle from which the Image Texture will be extracted.
651
+ * This value can be negative. If not provided, the image's source natural
652
+ * height will be used.
653
+ */
654
+ srcHeight?: number;
655
+ /**
656
+ * The x coordinate of the reference point of the rectangle from which the Texture
657
+ * will be extracted. `width` and `height` are provided. And only works when
658
+ * createImageBitmap is available. Only works when createImageBitmap is supported on the browser.
659
+ */
660
+ srcX?: number;
661
+ /**
662
+ * The y coordinate of the reference point of the rectangle from which the Texture
663
+ * will be extracted. Only used when source `srcWidth` width and `srcHeight` height
664
+ * are provided. Only works when createImageBitmap is supported on the browser.
665
+ */
666
+ srcY?: number;
667
+ /**
668
+ * Mark the node as interactive so we can perform hit tests on it
669
+ * when pointer events are registered.
670
+ * @default false
671
+ */
672
+ interactive?: boolean;
673
+ /**
674
+ * By enabling Strict bounds the renderer will not process & render child nodes of a node that is out of the visible area
675
+ *
676
+ * @remarks
677
+ * When enabled out of bound nodes, i.e. nodes that are out of the visible area, will
678
+ * **NOT** have their children processed and renderer anymore. This means the children of a out of bound
679
+ * node will not receive update processing such as positioning updates and will not be drawn on screen.
680
+ * As such the rest of the branch of the update tree that sits below this node will not be processed anymore
681
+ *
682
+ * This is a big performance gain but may be disabled in cases where the width of the parent node is
683
+ * unknown and the render must process the child nodes regardless of the viewport status of the parent node
684
+ *
685
+ * @default true
686
+ */
687
+ strictBounds: boolean;
688
+ }
689
+
690
+ /**
691
+ * Grab all the number properties of type T
692
+ */
693
+ type NumberProps<T> = {
694
+ [Key in keyof T as NonNullable<T[Key]> extends number ? Key : never]: number;
695
+ };
696
+
697
+ /**
698
+ * Properties of a Node used by the animate() function
699
+ */
700
+ export interface CoreNodeAnimateProps extends NumberProps<CoreNodeProps> {
701
+ /**
702
+ * Shader properties to animate
703
+ */
704
+ shaderProps: Record<string, number>;
705
+ // TODO: textureProps: Record<string, number>;
706
+ }
707
+
708
+ /**
709
+ * A visual Node in the Renderer scene graph.
710
+ *
711
+ * @remarks
712
+ * CoreNode is an internally used class that represents a Renderer Node in the
713
+ * scene graph. See INode.ts for the public APIs exposed to Renderer users
714
+ * that include generic types for Shaders.
715
+ */
716
+ export class CoreNode extends EventEmitter {
717
+ readonly children: CoreNode[] = [];
718
+ protected _id: number = getNewId();
719
+ readonly props: CoreNodeProps;
720
+
721
+ private hasShaderUpdater = false;
722
+ private hasColorProps = false;
723
+
724
+ public updateType = UpdateType.All;
725
+ public childUpdateType = UpdateType.None;
726
+
727
+ public globalTransform?: Matrix3d;
728
+ public localTransform?: Matrix3d;
729
+ public sceneGlobalTransform?: Matrix3d;
730
+ public renderCoords?: RenderCoords;
731
+ public sceneRenderCoords?: RenderCoords;
732
+ public renderBound?: Bound;
733
+ public strictBound?: Bound;
734
+ public preloadBound?: Bound;
735
+ public clippingRect: RectWithValid = {
736
+ x: 0,
737
+ y: 0,
738
+ width: 0,
739
+ height: 0,
740
+ valid: false,
741
+ };
742
+ public textureCoords?: TextureCoords;
743
+ public updateTextureCoords?: boolean = false;
744
+ public isRenderable = false;
745
+ public renderState: CoreNodeRenderState = CoreNodeRenderState.Init;
746
+
747
+ public worldAlpha = 1;
748
+ public premultipliedColorTl = 0;
749
+ public premultipliedColorTr = 0;
750
+ public premultipliedColorBl = 0;
751
+ public premultipliedColorBr = 0;
752
+ public calcZIndex = 0;
753
+ public hasRTTupdates = false;
754
+ public parentHasRenderTexture = false;
755
+ public rttParent: CoreNode | null = null;
756
+ /**
757
+ * only used when rtt = true
758
+ */
759
+ public framebufferDimensions: Dimensions | null = null;
760
+
761
+ public destroyed = false;
762
+
763
+ constructor(readonly stage: Stage, props: CoreNodeProps) {
764
+ super();
765
+
766
+ const p = (this.props = {} as CoreNodeProps);
767
+
768
+ // Fast-path assign only known keys
769
+ p.x = props.x;
770
+ p.y = props.y;
771
+ p.width = props.width;
772
+ p.height = props.height;
773
+ p.alpha = props.alpha;
774
+ p.autosize = props.autosize;
775
+ p.clipping = props.clipping;
776
+ p.color = props.color;
777
+
778
+ p.colorTop = props.colorTop;
779
+ p.colorBottom = props.colorBottom;
780
+ p.colorLeft = props.colorLeft;
781
+ p.colorRight = props.colorRight;
782
+ p.colorTl = props.colorTl;
783
+ p.colorTr = props.colorTr;
784
+ p.colorBl = props.colorBl;
785
+ p.colorBr = props.colorBr;
786
+
787
+ p.scaleX = props.scaleX;
788
+ p.scaleY = props.scaleY;
789
+ p.rotation = props.rotation;
790
+ p.pivotX = props.pivotX;
791
+ p.pivotY = props.pivotY;
792
+ p.mountX = props.mountX;
793
+ p.mountY = props.mountY;
794
+ p.mount = props.mount;
795
+ p.pivot = props.pivot;
796
+ p.strictBounds = props.strictBounds;
797
+
798
+ p.zIndex = props.zIndex;
799
+ p.zIndexLocked = props.zIndexLocked;
800
+ p.textureOptions = props.textureOptions;
801
+
802
+ p.data = props.data;
803
+ p.imageType = props.imageType;
804
+ p.srcX = props.srcX;
805
+ p.srcY = props.srcY;
806
+ p.srcWidth = props.srcWidth;
807
+ p.srcHeight = props.srcHeight;
808
+
809
+ p.parent = null;
810
+ p.texture = null;
811
+ p.shader = null;
812
+ p.src = null;
813
+ p.rtt = false;
814
+ p.boundsMargin = null;
815
+
816
+ // Assign props to instances
817
+ this.parent = props.parent;
818
+ this.texture = props.texture;
819
+ this.shader = props.shader;
820
+ this.src = props.src;
821
+ this.rtt = props.rtt;
822
+ this.boundsMargin = props.boundsMargin;
823
+ this.interactive = props.interactive;
824
+
825
+ this.setUpdateType(
826
+ UpdateType.Local | UpdateType.RenderBounds | UpdateType.RenderState,
827
+ );
828
+
829
+ // if the default texture isn't loaded yet, wait for it to load
830
+ // this only happens when the node is created before the stage is ready
831
+ const dt = this.stage.defaultTexture;
832
+ if (dt !== null && dt.state !== 'loaded') {
833
+ dt.once('loaded', () => this.setUpdateType(UpdateType.IsRenderable));
834
+ }
835
+ }
836
+
837
+ //#region Textures
838
+ loadTexture(): void {
839
+ const { texture } = this.props;
840
+ if (!texture) {
841
+ return;
842
+ }
843
+
844
+ // If texture is already loaded / failed, trigger loaded event manually
845
+ // so that users get a consistent event experience.
846
+ // We do this in a microtask to allow listeners to be attached in the same
847
+ // synchronous task after calling loadTexture()
848
+ queueMicrotask(() => {
849
+ if (this.textureOptions.preload === true) {
850
+ this.stage.txManager.loadTexture(texture);
851
+ }
852
+
853
+ texture.preventCleanup =
854
+ this.props.textureOptions?.preventCleanup ?? false;
855
+ texture.on('loaded', this.onTextureLoaded);
856
+ texture.on('failed', this.onTextureFailed);
857
+ texture.on('freed', this.onTextureFreed);
858
+
859
+ // If the parent is a render texture, the initial texture status
860
+ // will be set to freed until the texture is processed by the
861
+ // Render RTT nodes. So we only need to listen fo changes and
862
+ // no need to check the texture.state until we restructure how
863
+ // textures are being processed.
864
+ if (this.parentHasRenderTexture) {
865
+ this.notifyParentRTTOfUpdate();
866
+ return;
867
+ }
868
+
869
+ if (texture.state === 'loaded') {
870
+ this.onTextureLoaded(texture, texture.dimensions!);
871
+ } else if (texture.state === 'failed') {
872
+ this.onTextureFailed(texture, texture.error!);
873
+ } else if (texture.state === 'freed') {
874
+ this.onTextureFreed(texture);
875
+ }
876
+ });
877
+ }
878
+
879
+ unloadTexture(): void {
880
+ if (this.texture === null) {
881
+ return;
882
+ }
883
+
884
+ const texture = this.texture;
885
+ texture.off('loaded', this.onTextureLoaded);
886
+ texture.off('failed', this.onTextureFailed);
887
+ texture.off('freed', this.onTextureFreed);
888
+ texture.setRenderableOwner(this, false);
889
+ }
890
+
891
+ autosizeNode(dimensions: Dimensions) {
892
+ if (this.autosize) {
893
+ this.width = dimensions.width;
894
+ this.height = dimensions.height;
895
+ }
896
+ }
897
+
898
+ protected onTextureLoaded: TextureLoadedEventHandler = (_, dimensions) => {
899
+ this.autosizeNode(dimensions);
900
+ this.setUpdateType(UpdateType.IsRenderable);
901
+
902
+ // Texture was loaded. In case the RAF loop has already stopped, we request
903
+ // a render to ensure the texture is rendered.
904
+ this.stage.requestRender();
905
+
906
+ // If parent has a render texture, flag that we need to update
907
+ if (this.parentHasRenderTexture) {
908
+ this.notifyParentRTTOfUpdate();
909
+ }
910
+
911
+ // ignore 1x1 pixel textures
912
+ if (dimensions.width > 1 && dimensions.height > 1) {
913
+ this.emit('loaded', {
914
+ type: 'texture',
915
+ dimensions,
916
+ } satisfies NodeTextureLoadedPayload);
917
+ }
918
+
919
+ // Trigger a local update if the texture is loaded and the resizeMode is 'contain'
920
+ if (this.props.textureOptions?.resizeMode?.type === 'contain') {
921
+ this.setUpdateType(UpdateType.Local);
922
+ }
923
+ };
924
+
925
+ private onTextureFailed: TextureFailedEventHandler = (_, error) => {
926
+ // immediately set isRenderable to false, so that we handle the error
927
+ // without waiting for the next frame loop
928
+ this.isRenderable = false;
929
+ this.setUpdateType(UpdateType.IsRenderable);
930
+
931
+ // If parent has a render texture, flag that we need to update
932
+ if (this.parentHasRenderTexture) {
933
+ this.notifyParentRTTOfUpdate();
934
+ }
935
+
936
+ this.emit('failed', {
937
+ type: 'texture',
938
+ error,
939
+ } satisfies NodeTextureFailedPayload);
940
+ };
941
+
942
+ private onTextureFreed: TextureFreedEventHandler = () => {
943
+ // immediately set isRenderable to false, so that we handle the error
944
+ // without waiting for the next frame loop
945
+ this.isRenderable = false;
946
+ this.setUpdateType(UpdateType.IsRenderable);
947
+
948
+ // If parent has a render texture, flag that we need to update
949
+ if (this.parentHasRenderTexture) {
950
+ this.notifyParentRTTOfUpdate();
951
+ }
952
+
953
+ this.emit('freed', {
954
+ type: 'texture',
955
+ } satisfies NodeTextureFreedPayload);
956
+ };
957
+ //#endregion Textures
958
+
959
+ /**
960
+ * Change types types is used to determine the scope of the changes being applied
961
+ *
962
+ * @remarks
963
+ * See {@link UpdateType} for more information on each type
964
+ *
965
+ * @param type
966
+ */
967
+ setUpdateType(type: UpdateType): void {
968
+ this.updateType |= type;
969
+
970
+ const parent = this.props.parent;
971
+ if (!parent) return;
972
+
973
+ parent.setUpdateType(UpdateType.Children);
974
+ }
975
+
976
+ sortChildren() {
977
+ this.children.sort((a, b) => a.calcZIndex - b.calcZIndex);
978
+ }
979
+
980
+ updateLocalTransform() {
981
+ const p = this.props;
982
+ const { x, y, width, height } = p;
983
+ const mountTranslateX = p.mountX * width;
984
+ const mountTranslateY = p.mountY * height;
985
+
986
+ if (p.rotation !== 0 || p.scaleX !== 1 || p.scaleY !== 1) {
987
+ const pivotTranslateX = p.pivotX * width;
988
+ const pivotTranslateY = p.pivotY * height;
989
+
990
+ this.localTransform = Matrix3d.translate(
991
+ x - mountTranslateX + pivotTranslateX,
992
+ y - mountTranslateY + pivotTranslateY,
993
+ this.localTransform,
994
+ )
995
+ .rotate(p.rotation)
996
+ .scale(p.scaleX, p.scaleY)
997
+ .translate(-pivotTranslateX, -pivotTranslateY);
998
+ } else {
999
+ this.localTransform = Matrix3d.translate(
1000
+ x - mountTranslateX,
1001
+ y - mountTranslateY,
1002
+ this.localTransform,
1003
+ );
1004
+ }
1005
+
1006
+ // Handle 'contain' resize mode
1007
+ const texture = p.texture;
1008
+ if (
1009
+ texture &&
1010
+ texture.dimensions &&
1011
+ p.textureOptions.resizeMode?.type === 'contain'
1012
+ ) {
1013
+ let resizeModeScaleX = 1;
1014
+ let resizeModeScaleY = 1;
1015
+ let extraX = 0;
1016
+ let extraY = 0;
1017
+ const { width: tw, height: th } = texture.dimensions;
1018
+ const txAspectRatio = tw / th;
1019
+ const nodeAspectRatio = width / height;
1020
+ if (txAspectRatio > nodeAspectRatio) {
1021
+ // Texture is wider than node
1022
+ // Center the node vertically (shift down by extraY)
1023
+ // Scale the node vertically to maintain original aspect ratio
1024
+ const scaleX = width / tw;
1025
+ const scaledTxHeight = th * scaleX;
1026
+ extraY = (height - scaledTxHeight) / 2;
1027
+ resizeModeScaleY = scaledTxHeight / height;
1028
+ } else {
1029
+ // Texture is taller than node (or equal)
1030
+ // Center the node horizontally (shift right by extraX)
1031
+ // Scale the node horizontally to maintain original aspect ratio
1032
+ const scaleY = height / th;
1033
+ const scaledTxWidth = tw * scaleY;
1034
+ extraX = (width - scaledTxWidth) / 2;
1035
+ resizeModeScaleX = scaledTxWidth / width;
1036
+ }
1037
+
1038
+ // Apply the extra translation and scale to the local transform
1039
+ this.localTransform
1040
+ .translate(extraX, extraY)
1041
+ .scale(resizeModeScaleX, resizeModeScaleY);
1042
+ }
1043
+ }
1044
+
1045
+ /**
1046
+ * @todo: test for correct calculation flag
1047
+ * @param delta
1048
+ */
1049
+ update(delta: number, parentClippingRect: RectWithValid): void {
1050
+ if (this.updateType === UpdateType.None) {
1051
+ return;
1052
+ }
1053
+
1054
+ const props = this.props;
1055
+ const parent = props.parent;
1056
+ const parentHasRenderTexture = this.parentHasRenderTexture;
1057
+ const hasParent = props.parent !== null;
1058
+
1059
+ let renderState: CoreNodeRenderState | null = null;
1060
+
1061
+ let updateType = this.updateType;
1062
+ let childUpdateType = this.childUpdateType;
1063
+ let updateParent = false;
1064
+
1065
+ if (updateType & UpdateType.Local) {
1066
+ this.updateLocalTransform();
1067
+
1068
+ updateType |= UpdateType.Global;
1069
+ updateParent = hasParent;
1070
+ }
1071
+
1072
+ // Handle specific RTT updates at this node level
1073
+ if (updateType & UpdateType.RenderTexture && this.rtt === true) {
1074
+ this.hasRTTupdates = true;
1075
+ }
1076
+
1077
+ if (updateType & UpdateType.Global) {
1078
+ if (this.parentHasRenderTexture === true && parent?.rtt === true) {
1079
+ // we are at the start of the RTT chain, so we need to reset the globalTransform
1080
+ // for correct RTT rendering
1081
+ this.globalTransform = Matrix3d.identity();
1082
+
1083
+ // Maintain a full scene global transform for bounds detection
1084
+ this.sceneGlobalTransform = Matrix3d.copy(
1085
+ parent?.globalTransform || Matrix3d.identity(),
1086
+ ).multiply(this.localTransform!);
1087
+ } else if (
1088
+ this.parentHasRenderTexture === true &&
1089
+ parent?.rtt === false
1090
+ ) {
1091
+ // we're part of an RTT chain but our parent is not the main RTT node
1092
+ // so we need to propogate the sceneGlobalTransform of the parent
1093
+ // to maintain a full scene global transform for bounds detection
1094
+ this.sceneGlobalTransform = Matrix3d.copy(
1095
+ parent?.sceneGlobalTransform || this.localTransform!,
1096
+ ).multiply(this.localTransform!);
1097
+
1098
+ this.globalTransform = Matrix3d.copy(
1099
+ parent?.globalTransform || this.localTransform!,
1100
+ this.globalTransform,
1101
+ );
1102
+ } else {
1103
+ this.globalTransform = Matrix3d.copy(
1104
+ parent?.globalTransform || this.localTransform!,
1105
+ this.globalTransform,
1106
+ );
1107
+ }
1108
+
1109
+ if (parent !== null) {
1110
+ this.globalTransform.multiply(this.localTransform!);
1111
+ }
1112
+ this.calculateRenderCoords();
1113
+ this.updateBoundingRect();
1114
+
1115
+ updateType |=
1116
+ UpdateType.RenderState |
1117
+ UpdateType.Children |
1118
+ UpdateType.RecalcUniforms;
1119
+ updateParent = hasParent;
1120
+ childUpdateType |= UpdateType.Global;
1121
+
1122
+ if (this.clipping === true) {
1123
+ updateType |= UpdateType.Clipping | UpdateType.RenderBounds;
1124
+ updateParent = hasParent;
1125
+ childUpdateType |= UpdateType.RenderBounds;
1126
+ }
1127
+ }
1128
+
1129
+ if (updateType & UpdateType.RenderBounds) {
1130
+ this.createRenderBounds();
1131
+
1132
+ updateType |= UpdateType.RenderState | UpdateType.Children;
1133
+ updateParent = hasParent;
1134
+ childUpdateType |= UpdateType.RenderBounds;
1135
+ }
1136
+
1137
+ if (updateType & UpdateType.RenderState) {
1138
+ renderState = this.checkRenderBounds();
1139
+
1140
+ updateType |= UpdateType.IsRenderable;
1141
+ updateParent = hasParent;
1142
+
1143
+ // if we're not going out of bounds, update the render state
1144
+ // this is done so the update loop can finish before we mark a node
1145
+ // as out of bounds
1146
+ if (renderState !== CoreNodeRenderState.OutOfBounds) {
1147
+ this.updateRenderState(renderState);
1148
+ }
1149
+ }
1150
+
1151
+ if (updateType & UpdateType.WorldAlpha) {
1152
+ this.worldAlpha = ((parent && parent.worldAlpha) || 1) * props.alpha;
1153
+ updateType |=
1154
+ UpdateType.PremultipliedColors |
1155
+ UpdateType.Children |
1156
+ UpdateType.IsRenderable;
1157
+ updateParent = hasParent;
1158
+ childUpdateType |= UpdateType.WorldAlpha;
1159
+ }
1160
+
1161
+ if (updateType & UpdateType.IsRenderable) {
1162
+ this.updateIsRenderable();
1163
+ }
1164
+
1165
+ if (updateType & UpdateType.Clipping) {
1166
+ this.calculateClippingRect(parentClippingRect);
1167
+ updateType |= UpdateType.Children;
1168
+ updateParent = hasParent;
1169
+
1170
+ childUpdateType |= UpdateType.Clipping | UpdateType.RenderBounds;
1171
+ }
1172
+
1173
+ if (updateType & UpdateType.PremultipliedColors) {
1174
+ const alpha = this.worldAlpha;
1175
+
1176
+ const tl = props.colorTl;
1177
+ const tr = props.colorTr;
1178
+ const bl = props.colorBl;
1179
+ const br = props.colorBr;
1180
+
1181
+ // Fast equality check (covers all 4 corners)
1182
+ const same = tl === tr && tl === bl && tl === br;
1183
+
1184
+ const merged = mergeColorAlphaPremultiplied(tl, alpha, true);
1185
+
1186
+ this.premultipliedColorTl = merged;
1187
+
1188
+ if (same) {
1189
+ this.premultipliedColorTr =
1190
+ this.premultipliedColorBl =
1191
+ this.premultipliedColorBr =
1192
+ merged;
1193
+ } else {
1194
+ this.premultipliedColorTr = mergeColorAlphaPremultiplied(
1195
+ tr,
1196
+ alpha,
1197
+ true,
1198
+ );
1199
+ this.premultipliedColorBl = mergeColorAlphaPremultiplied(
1200
+ bl,
1201
+ alpha,
1202
+ true,
1203
+ );
1204
+ this.premultipliedColorBr = mergeColorAlphaPremultiplied(
1205
+ br,
1206
+ alpha,
1207
+ true,
1208
+ );
1209
+ }
1210
+ }
1211
+
1212
+ if (updateParent === true) {
1213
+ parent!.setUpdateType(UpdateType.Children);
1214
+ }
1215
+ // No need to update zIndex if there is no parent
1216
+ if (updateType & UpdateType.CalculatedZIndex && parent !== null) {
1217
+ this.calculateZIndex();
1218
+ // Tell parent to re-sort children
1219
+ parent.setUpdateType(UpdateType.ZIndexSortedChildren);
1220
+ }
1221
+
1222
+ if (
1223
+ props.strictBounds === true &&
1224
+ this.renderState === CoreNodeRenderState.OutOfBounds
1225
+ ) {
1226
+ updateType &= ~UpdateType.RenderBounds; // remove render bounds update
1227
+ return;
1228
+ }
1229
+
1230
+ if (
1231
+ updateType & UpdateType.RecalcUniforms &&
1232
+ this.hasShaderUpdater === true
1233
+ ) {
1234
+ //this exists because the boolean hasShaderUpdater === true
1235
+ this.shader!.update!();
1236
+ }
1237
+
1238
+ if (updateType & UpdateType.Children && this.children.length > 0) {
1239
+ for (let i = 0, length = this.children.length; i < length; i++) {
1240
+ const child = this.children[i] as CoreNode;
1241
+
1242
+ child.setUpdateType(childUpdateType);
1243
+
1244
+ if (child.updateType === 0) {
1245
+ continue;
1246
+ }
1247
+
1248
+ let childClippingRect = this.clippingRect;
1249
+ if (this.rtt === true) {
1250
+ childClippingRect = {
1251
+ x: 0,
1252
+ y: 0,
1253
+ width: 0,
1254
+ height: 0,
1255
+ valid: false,
1256
+ };
1257
+ }
1258
+
1259
+ child.update(delta, childClippingRect);
1260
+ }
1261
+ }
1262
+
1263
+ // If the node has an RTT parent and requires a texture re-render, inform the RTT parent
1264
+ // if (this.parentHasRenderTexture && updateType & UpdateType.RenderTexture) {
1265
+ // @TODO have a more scoped down updateType for RTT updates
1266
+ if (parentHasRenderTexture === true) {
1267
+ this.notifyParentRTTOfUpdate();
1268
+ }
1269
+
1270
+ // Sorting children MUST happen after children have been updated so
1271
+ // that they have the oppotunity to update their calculated zIndex.
1272
+ if (updateType & UpdateType.ZIndexSortedChildren) {
1273
+ // reorder z-index
1274
+ this.sortChildren();
1275
+ }
1276
+
1277
+ if (this.updateTextureCoords === true) {
1278
+ this.updateTextureCoords = false;
1279
+ this.textureCoords = this.stage.renderer.getTextureCoords!(this);
1280
+ }
1281
+
1282
+ // If we're out of bounds, apply the render state now
1283
+ // this is done so nodes can finish their entire update loop before
1284
+ // being marked as out of bounds
1285
+ if (renderState === CoreNodeRenderState.OutOfBounds) {
1286
+ this.updateRenderState(renderState);
1287
+ this.updateIsRenderable();
1288
+
1289
+ if (
1290
+ this.rtt === true &&
1291
+ renderState === CoreNodeRenderState.OutOfBounds
1292
+ ) {
1293
+ // notify children that we are going out of bounds
1294
+ // we have to do this now before we stop processing the render tree
1295
+ this.notifyChildrenRTTOfUpdate(renderState);
1296
+ }
1297
+ }
1298
+
1299
+ // reset update type
1300
+ this.updateType = 0;
1301
+ this.childUpdateType = 0;
1302
+ }
1303
+
1304
+ private findParentRTTNode(): CoreNode | null {
1305
+ let rttNode: CoreNode | null = this.parent;
1306
+ while (rttNode && !rttNode.rtt) {
1307
+ rttNode = rttNode.parent;
1308
+ }
1309
+ return rttNode;
1310
+ }
1311
+
1312
+ private notifyChildrenRTTOfUpdate(renderState: CoreNodeRenderState) {
1313
+ for (const child of this.children) {
1314
+ // force child to update render state
1315
+ child.updateRenderState(renderState);
1316
+ child.updateIsRenderable();
1317
+ child.notifyChildrenRTTOfUpdate(renderState);
1318
+ }
1319
+ }
1320
+
1321
+ protected notifyParentRTTOfUpdate() {
1322
+ if (this.parent === null) {
1323
+ return;
1324
+ }
1325
+
1326
+ const rttNode = this.rttParent || this.findParentRTTNode();
1327
+ if (!rttNode) {
1328
+ return;
1329
+ }
1330
+
1331
+ // If an RTT node is found, mark it for re-rendering
1332
+ rttNode.hasRTTupdates = true;
1333
+ rttNode.setUpdateType(UpdateType.RenderTexture);
1334
+
1335
+ // if rttNode is nested, also make it update its RTT parent
1336
+ if (rttNode.parentHasRenderTexture === true) {
1337
+ rttNode.notifyParentRTTOfUpdate();
1338
+ }
1339
+ }
1340
+
1341
+ checkRenderBounds(): CoreNodeRenderState {
1342
+ if (boundInsideBound(this.renderBound!, this.strictBound!)) {
1343
+ return CoreNodeRenderState.InViewport;
1344
+ }
1345
+
1346
+ if (boundInsideBound(this.renderBound!, this.preloadBound!)) {
1347
+ return CoreNodeRenderState.InBounds;
1348
+ }
1349
+
1350
+ // check if we're larger then our parent, we're definitely in the viewport
1351
+ if (boundLargeThanBound(this.renderBound!, this.strictBound!)) {
1352
+ return CoreNodeRenderState.InViewport;
1353
+ }
1354
+
1355
+ // check if we dont have dimensions, take our parent's render state
1356
+ if (
1357
+ this.parent !== null &&
1358
+ (this.props.width === 0 || this.props.height === 0)
1359
+ ) {
1360
+ return this.parent.renderState;
1361
+ }
1362
+
1363
+ return CoreNodeRenderState.OutOfBounds;
1364
+ }
1365
+
1366
+ updateBoundingRect() {
1367
+ const transform = (this.sceneGlobalTransform ||
1368
+ this.globalTransform) as Matrix3d;
1369
+ const renderCoords = (this.sceneRenderCoords ||
1370
+ this.renderCoords) as RenderCoords;
1371
+
1372
+ if (transform.tb === 0 || transform.tc === 0) {
1373
+ this.renderBound = createBound(
1374
+ renderCoords.x1,
1375
+ renderCoords.y1,
1376
+ renderCoords.x3,
1377
+ renderCoords.y3,
1378
+ this.renderBound,
1379
+ );
1380
+ } else {
1381
+ const { x1, y1, x2, y2, x3, y3, x4, y4 } = renderCoords;
1382
+ this.renderBound = createBound(
1383
+ Math.min(x1, x2, x3, x4),
1384
+ Math.min(y1, y2, y3, y4),
1385
+ Math.max(x1, x2, x3, x4),
1386
+ Math.max(y1, y2, y3, y4),
1387
+ this.renderBound,
1388
+ );
1389
+ }
1390
+ }
1391
+
1392
+ createRenderBounds(): void {
1393
+ if (this.parent !== null && this.parent.strictBound !== undefined) {
1394
+ // we have a parent with a valid bound, copy it
1395
+ const parentBound = this.parent.strictBound;
1396
+ this.strictBound = createBound(
1397
+ parentBound.x1,
1398
+ parentBound.y1,
1399
+ parentBound.x2,
1400
+ parentBound.y2,
1401
+ );
1402
+
1403
+ this.preloadBound = createPreloadBounds(
1404
+ this.strictBound,
1405
+ this.boundsMargin as [number, number, number, number],
1406
+ );
1407
+ } else {
1408
+ // no parent or parent does not have a bound, take the stage boundaries
1409
+ this.strictBound = this.stage.strictBound;
1410
+ this.preloadBound = this.stage.preloadBound;
1411
+ }
1412
+
1413
+ // if clipping is disabled, we're done
1414
+ if (this.props.clipping === false) {
1415
+ return;
1416
+ }
1417
+
1418
+ // only create local clipping bounds if node itself is in bounds
1419
+ // this can only be done if we have a render bound already
1420
+ if (this.renderBound === undefined) {
1421
+ return;
1422
+ }
1423
+
1424
+ // if we're out of bounds, we're done
1425
+ if (boundInsideBound(this.renderBound, this.strictBound) === false) {
1426
+ return;
1427
+ }
1428
+
1429
+ // clipping is enabled and we are in bounds create our own bounds
1430
+ const { x, y, width, height } = this.props;
1431
+
1432
+ // Pick the global transform if available, otherwise use the local transform
1433
+ // global transform is only available if the node in an RTT chain
1434
+ const { tx, ty } = this.sceneGlobalTransform || this.globalTransform || {};
1435
+ const _x = tx ?? x;
1436
+ const _y = ty ?? y;
1437
+ this.strictBound = createBound(
1438
+ _x,
1439
+ _y,
1440
+ _x + width,
1441
+ _y + height,
1442
+ this.strictBound,
1443
+ );
1444
+
1445
+ this.preloadBound = createPreloadBounds(
1446
+ this.strictBound,
1447
+ this.boundsMargin as [number, number, number, number],
1448
+ );
1449
+ }
1450
+
1451
+ updateRenderState(renderState: CoreNodeRenderState) {
1452
+ if (renderState === this.renderState) {
1453
+ return;
1454
+ }
1455
+
1456
+ const previous = this.renderState;
1457
+ this.renderState = renderState;
1458
+ const event = CoreNodeRenderStateMap.get(renderState);
1459
+ assertTruthy(event);
1460
+ this.emit(event, {
1461
+ previous,
1462
+ current: renderState,
1463
+ });
1464
+ }
1465
+
1466
+ /**
1467
+ * Updates the `isRenderable` property based on various conditions.
1468
+ */
1469
+ updateIsRenderable() {
1470
+ let newIsRenderable = false;
1471
+ let needsTextureOwnership = false;
1472
+
1473
+ // If the node is out of bounds or has an alpha of 0, it is not renderable
1474
+ if (
1475
+ this.worldAlpha === 0 ||
1476
+ this.renderState <= CoreNodeRenderState.OutOfBounds
1477
+ ) {
1478
+ this.updateTextureOwnership(false);
1479
+ this.setRenderable(false);
1480
+ return;
1481
+ }
1482
+
1483
+ if (this.texture !== null) {
1484
+ needsTextureOwnership = true;
1485
+
1486
+ // we're only renderable if the texture state is loaded
1487
+ newIsRenderable = this.texture.state === 'loaded';
1488
+ } else if (
1489
+ // check shader
1490
+ (this.props.shader !== null || this.hasColorProps === true) &&
1491
+ // check dimensions
1492
+ (this.props.width !== 0 && this.props.height !== 0) === true
1493
+ ) {
1494
+ // This mean we have dimensions and a color set, so we can render a ColorTexture
1495
+ if (
1496
+ this.stage.defaultTexture &&
1497
+ this.stage.defaultTexture.state === 'loaded'
1498
+ ) {
1499
+ newIsRenderable = true;
1500
+ }
1501
+ }
1502
+
1503
+ this.updateTextureOwnership(needsTextureOwnership);
1504
+ this.setRenderable(newIsRenderable);
1505
+ }
1506
+
1507
+ /**
1508
+ * Sets the renderable state and triggers changes if necessary.
1509
+ * @param isRenderable - The new renderable state
1510
+ */
1511
+ setRenderable(isRenderable: boolean) {
1512
+ this.isRenderable = isRenderable;
1513
+ if (
1514
+ isRenderable === true &&
1515
+ this.stage.calculateTextureCoord === true &&
1516
+ this.textureCoords === undefined
1517
+ ) {
1518
+ this.updateTextureCoords = true;
1519
+ }
1520
+ }
1521
+
1522
+ /**
1523
+ * Changes the renderable state of the node.
1524
+ */
1525
+ updateTextureOwnership(isRenderable: boolean) {
1526
+ this.texture?.setRenderableOwner(this, isRenderable);
1527
+ }
1528
+
1529
+ calculateRenderCoords() {
1530
+ const { width, height } = this;
1531
+
1532
+ const g = this.globalTransform!;
1533
+ const tx = g.tx,
1534
+ ty = g.ty,
1535
+ ta = g.ta,
1536
+ tb = g.tb,
1537
+ tc = g.tc,
1538
+ td = g.td;
1539
+ if (tb === 0 && tc === 0) {
1540
+ const minX = tx;
1541
+ const maxX = tx + width * ta;
1542
+ const minY = ty;
1543
+ const maxY = ty + height * td;
1544
+ this.renderCoords = RenderCoords.translate(
1545
+ //top-left
1546
+ minX,
1547
+ minY,
1548
+ //top-right
1549
+ maxX,
1550
+ minY,
1551
+ //bottom-right
1552
+ maxX,
1553
+ maxY,
1554
+ //bottom-left
1555
+ minX,
1556
+ maxY,
1557
+ this.renderCoords,
1558
+ );
1559
+ } else {
1560
+ this.renderCoords = RenderCoords.translate(
1561
+ //top-left
1562
+ tx,
1563
+ ty,
1564
+ //top-right
1565
+ tx + width * ta,
1566
+ ty + width * tc,
1567
+ //bottom-right
1568
+ tx + width * ta + height * tb,
1569
+ ty + width * tc + height * td,
1570
+ //bottom-left
1571
+ tx + height * tb,
1572
+ ty + height * td,
1573
+ this.renderCoords,
1574
+ );
1575
+ }
1576
+ if (this.sceneGlobalTransform === undefined) {
1577
+ return;
1578
+ }
1579
+
1580
+ const {
1581
+ tx: stx,
1582
+ ty: sty,
1583
+ ta: sta,
1584
+ tb: stb,
1585
+ tc: stc,
1586
+ td: std,
1587
+ } = this.sceneGlobalTransform;
1588
+ if (stb === 0 && stc === 0) {
1589
+ const minX = stx;
1590
+ const maxX = stx + width * sta;
1591
+ const minY = sty;
1592
+ const maxY = sty + height * std;
1593
+ this.sceneRenderCoords = RenderCoords.translate(
1594
+ //top-left
1595
+ minX,
1596
+ minY,
1597
+ //top-right
1598
+ maxX,
1599
+ minY,
1600
+ //bottom-right
1601
+ maxX,
1602
+ maxY,
1603
+ //bottom-left
1604
+ minX,
1605
+ maxY,
1606
+ this.sceneRenderCoords,
1607
+ );
1608
+ } else {
1609
+ this.sceneRenderCoords = RenderCoords.translate(
1610
+ //top-left
1611
+ stx,
1612
+ sty,
1613
+ //top-right
1614
+ stx + width * sta,
1615
+ sty + width * stc,
1616
+ //bottom-right
1617
+ stx + width * sta + height * stb,
1618
+ sty + width * stc + height * std,
1619
+ //bottom-left
1620
+ stx + height * stb,
1621
+ sty + height * std,
1622
+ this.sceneRenderCoords,
1623
+ );
1624
+ }
1625
+ }
1626
+
1627
+ /**
1628
+ * This function calculates the clipping rectangle for a node.
1629
+ *
1630
+ * 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.
1631
+ * 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.
1632
+ *
1633
+ * Finally, the node's parentClippingRect and clippingRect properties are updated.
1634
+ */
1635
+ calculateClippingRect(parentClippingRect: RectWithValid) {
1636
+ const { clippingRect, props, globalTransform: gt } = this;
1637
+ const { clipping } = props;
1638
+ const isRotated = gt!.tb !== 0 || gt!.tc !== 0;
1639
+
1640
+ if (clipping === true && isRotated === false) {
1641
+ clippingRect.x = gt!.tx;
1642
+ clippingRect.y = gt!.ty;
1643
+ clippingRect.width = this.width * gt!.ta;
1644
+ clippingRect.height = this.height * gt!.td;
1645
+ clippingRect.valid = true;
1646
+ } else {
1647
+ clippingRect.valid = false;
1648
+ }
1649
+
1650
+ if (parentClippingRect.valid === true && clippingRect.valid === true) {
1651
+ // Intersect parent clipping rect with node clipping rect
1652
+ intersectRect(parentClippingRect, clippingRect, clippingRect);
1653
+ } else if (parentClippingRect.valid === true) {
1654
+ // Copy parent clipping rect
1655
+ copyRect(parentClippingRect, clippingRect);
1656
+ clippingRect.valid = true;
1657
+ }
1658
+ }
1659
+
1660
+ calculateZIndex(): void {
1661
+ const props = this.props;
1662
+ const z = props.zIndex || 0;
1663
+ const p = props.parent?.zIndex || 0;
1664
+
1665
+ let zIndex = z;
1666
+ if (props.parent?.zIndexLocked) {
1667
+ zIndex = z < p ? z : p;
1668
+ }
1669
+ this.calcZIndex = zIndex;
1670
+ }
1671
+
1672
+ /**
1673
+ * Destroy the node and cleanup all resources
1674
+ */
1675
+ destroy(): void {
1676
+ if (this.destroyed === true) {
1677
+ return;
1678
+ }
1679
+
1680
+ this.removeAllListeners();
1681
+
1682
+ this.destroyed = true;
1683
+ this.unloadTexture();
1684
+ this.isRenderable = false;
1685
+
1686
+ // Kill children
1687
+ while (this.children.length > 0) {
1688
+ this.children[0]!.destroy();
1689
+ }
1690
+
1691
+ const parent = this.parent;
1692
+ if (parent !== null) {
1693
+ const index = parent.children.indexOf(this);
1694
+ parent.children.splice(index, 1);
1695
+ parent.setUpdateType(
1696
+ UpdateType.Children | UpdateType.ZIndexSortedChildren,
1697
+ );
1698
+ }
1699
+
1700
+ this.props.parent = null;
1701
+ this.props.texture = null;
1702
+
1703
+ if (this.rtt === true) {
1704
+ this.stage.renderer.removeRTTNode(this);
1705
+ }
1706
+ }
1707
+
1708
+ renderQuads(renderer: CoreRenderer): void {
1709
+ if (this.parentHasRenderTexture === true) {
1710
+ const rtt = renderer.renderToTextureActive;
1711
+ if (rtt === false || this.parentRenderTexture !== renderer.activeRttNode)
1712
+ return;
1713
+ }
1714
+
1715
+ const p = this.props;
1716
+ const t = this.globalTransform!;
1717
+ const coords = this.renderCoords;
1718
+ const texture = p.texture || this.stage.defaultTexture;
1719
+
1720
+ renderer.addQuad({
1721
+ width: p.width,
1722
+ height: p.height,
1723
+ colorTl: this.premultipliedColorTl,
1724
+ colorTr: this.premultipliedColorTr,
1725
+ colorBl: this.premultipliedColorBl,
1726
+ colorBr: this.premultipliedColorBr,
1727
+ texture,
1728
+ textureOptions: p.textureOptions,
1729
+ textureCoords: this.textureCoords,
1730
+ shader: p.shader as CoreShaderNode<any>,
1731
+ alpha: this.worldAlpha,
1732
+ clippingRect: this.clippingRect,
1733
+ tx: t.tx,
1734
+ ty: t.ty,
1735
+ ta: t.ta,
1736
+ tb: t.tb,
1737
+ tc: t.tc,
1738
+ td: t.td,
1739
+ renderCoords: coords,
1740
+ rtt: p.rtt,
1741
+ zIndex: this.calcZIndex,
1742
+ parentHasRenderTexture: this.parentHasRenderTexture,
1743
+ framebufferDimensions: this.parentHasRenderTexture
1744
+ ? this.parentFramebufferDimensions
1745
+ : null,
1746
+ });
1747
+ }
1748
+
1749
+ //#region Properties
1750
+ get id(): number {
1751
+ return this._id;
1752
+ }
1753
+
1754
+ get data(): CustomDataMap | undefined {
1755
+ return this.props.data;
1756
+ }
1757
+
1758
+ set data(d: CustomDataMap | undefined) {
1759
+ this.props.data = d;
1760
+ }
1761
+
1762
+ get x(): number {
1763
+ return this.props.x;
1764
+ }
1765
+
1766
+ set x(value: number) {
1767
+ if (this.props.x !== value) {
1768
+ this.props.x = value;
1769
+ this.setUpdateType(UpdateType.Local);
1770
+ }
1771
+ }
1772
+
1773
+ get absX(): number {
1774
+ return (
1775
+ this.props.x +
1776
+ -this.props.width * this.props.mountX +
1777
+ (this.props.parent?.absX || this.props.parent?.globalTransform?.tx || 0)
1778
+ );
1779
+ }
1780
+
1781
+ get absY(): number {
1782
+ return (
1783
+ this.props.y +
1784
+ -this.props.height * this.props.mountY +
1785
+ (this.props.parent?.absY ?? 0)
1786
+ );
1787
+ }
1788
+
1789
+ get y(): number {
1790
+ return this.props.y;
1791
+ }
1792
+
1793
+ set y(value: number) {
1794
+ if (this.props.y !== value) {
1795
+ this.props.y = value;
1796
+ this.setUpdateType(UpdateType.Local);
1797
+ }
1798
+ }
1799
+
1800
+ get width(): number {
1801
+ return this.props.width;
1802
+ }
1803
+
1804
+ set width(value: number) {
1805
+ if (this.props.width !== value) {
1806
+ this.textureCoords = undefined;
1807
+ this.props.width = value;
1808
+ this.setUpdateType(UpdateType.Local);
1809
+
1810
+ if (this.props.rtt === true) {
1811
+ this.framebufferDimensions!.width = value;
1812
+ this.texture = this.stage.txManager.createTexture(
1813
+ 'RenderTexture',
1814
+ this.framebufferDimensions!,
1815
+ );
1816
+
1817
+ this.setUpdateType(UpdateType.RenderTexture);
1818
+ }
1819
+ }
1820
+ }
1821
+
1822
+ get height(): number {
1823
+ return this.props.height;
1824
+ }
1825
+
1826
+ set height(value: number) {
1827
+ if (this.props.height !== value) {
1828
+ this.textureCoords = undefined;
1829
+ this.props.height = value;
1830
+ this.setUpdateType(UpdateType.Local);
1831
+
1832
+ if (this.props.rtt === true) {
1833
+ this.framebufferDimensions!.height = value;
1834
+ this.texture = this.stage.txManager.createTexture(
1835
+ 'RenderTexture',
1836
+ this.framebufferDimensions!,
1837
+ );
1838
+
1839
+ this.setUpdateType(UpdateType.RenderTexture);
1840
+ }
1841
+ }
1842
+ }
1843
+
1844
+ get scale(): number {
1845
+ // The CoreNode `scale` property is only used by Animations.
1846
+ // Unlike INode, `null` should never be possibility for Animations.
1847
+ return this.scaleX;
1848
+ }
1849
+
1850
+ set scale(value: number) {
1851
+ // The CoreNode `scale` property is only used by Animations.
1852
+ // Unlike INode, `null` should never be possibility for Animations.
1853
+ this.scaleX = value;
1854
+ this.scaleY = value;
1855
+ }
1856
+
1857
+ get scaleX(): number {
1858
+ return this.props.scaleX;
1859
+ }
1860
+
1861
+ set scaleX(value: number) {
1862
+ if (this.props.scaleX !== value) {
1863
+ this.props.scaleX = value;
1864
+ this.setUpdateType(UpdateType.Local);
1865
+ }
1866
+ }
1867
+
1868
+ get scaleY(): number {
1869
+ return this.props.scaleY;
1870
+ }
1871
+
1872
+ set scaleY(value: number) {
1873
+ if (this.props.scaleY !== value) {
1874
+ this.props.scaleY = value;
1875
+ this.setUpdateType(UpdateType.Local);
1876
+ }
1877
+ }
1878
+
1879
+ get mount(): number {
1880
+ return this.props.mount;
1881
+ }
1882
+
1883
+ set mount(value: number) {
1884
+ if (this.props.mountX !== value || this.props.mountY !== value) {
1885
+ this.props.mountX = value;
1886
+ this.props.mountY = value;
1887
+ this.props.mount = value;
1888
+ this.setUpdateType(UpdateType.Local);
1889
+ }
1890
+ }
1891
+
1892
+ get mountX(): number {
1893
+ return this.props.mountX;
1894
+ }
1895
+
1896
+ set mountX(value: number) {
1897
+ if (this.props.mountX !== value) {
1898
+ this.props.mountX = value;
1899
+ this.setUpdateType(UpdateType.Local);
1900
+ }
1901
+ }
1902
+
1903
+ get mountY(): number {
1904
+ return this.props.mountY;
1905
+ }
1906
+
1907
+ set mountY(value: number) {
1908
+ if (this.props.mountY !== value) {
1909
+ this.props.mountY = value;
1910
+ this.setUpdateType(UpdateType.Local);
1911
+ }
1912
+ }
1913
+
1914
+ get pivot(): number {
1915
+ return this.props.pivot;
1916
+ }
1917
+
1918
+ set pivot(value: number) {
1919
+ if (this.props.pivotX !== value || this.props.pivotY !== value) {
1920
+ this.props.pivotX = value;
1921
+ this.props.pivotY = value;
1922
+ this.props.pivot = value;
1923
+ this.setUpdateType(UpdateType.Local);
1924
+ }
1925
+ }
1926
+
1927
+ get pivotX(): number {
1928
+ return this.props.pivotX;
1929
+ }
1930
+
1931
+ set pivotX(value: number) {
1932
+ if (this.props.pivotX !== value) {
1933
+ this.props.pivotX = value;
1934
+ this.setUpdateType(UpdateType.Local);
1935
+ }
1936
+ }
1937
+
1938
+ get pivotY(): number {
1939
+ return this.props.pivotY;
1940
+ }
1941
+
1942
+ set pivotY(value: number) {
1943
+ if (this.props.pivotY !== value) {
1944
+ this.props.pivotY = value;
1945
+ this.setUpdateType(UpdateType.Local);
1946
+ }
1947
+ }
1948
+
1949
+ get rotation(): number {
1950
+ return this.props.rotation;
1951
+ }
1952
+
1953
+ set rotation(value: number) {
1954
+ if (this.props.rotation !== value) {
1955
+ this.props.rotation = value;
1956
+ this.setUpdateType(UpdateType.Local);
1957
+ }
1958
+ }
1959
+
1960
+ get alpha(): number {
1961
+ return this.props.alpha;
1962
+ }
1963
+
1964
+ set alpha(value: number) {
1965
+ this.props.alpha = value;
1966
+ this.setUpdateType(
1967
+ UpdateType.PremultipliedColors |
1968
+ UpdateType.WorldAlpha |
1969
+ UpdateType.Children |
1970
+ UpdateType.IsRenderable,
1971
+ );
1972
+ this.childUpdateType |= UpdateType.WorldAlpha;
1973
+ }
1974
+
1975
+ get autosize(): boolean {
1976
+ return this.props.autosize;
1977
+ }
1978
+
1979
+ set autosize(value: boolean) {
1980
+ this.props.autosize = value;
1981
+ }
1982
+
1983
+ get boundsMargin(): number | [number, number, number, number] | null {
1984
+ const props = this.props;
1985
+ if (props.boundsMargin !== null) {
1986
+ return props.boundsMargin;
1987
+ }
1988
+
1989
+ const parent = this.parent;
1990
+ if (parent !== null) {
1991
+ const margin = parent.boundsMargin;
1992
+ if (margin !== undefined) {
1993
+ return margin;
1994
+ }
1995
+ }
1996
+
1997
+ return this.stage.boundsMargin;
1998
+ }
1999
+
2000
+ set boundsMargin(value: number | [number, number, number, number] | null) {
2001
+ if (value === this.props.boundsMargin) {
2002
+ return;
2003
+ }
2004
+
2005
+ if (value === null) {
2006
+ this.props.boundsMargin = value;
2007
+ } else {
2008
+ const bm: [number, number, number, number] = Array.isArray(value)
2009
+ ? value
2010
+ : [value, value, value, value];
2011
+
2012
+ this.props.boundsMargin = bm;
2013
+ }
2014
+ this.setUpdateType(UpdateType.RenderBounds);
2015
+ }
2016
+
2017
+ get clipping(): boolean {
2018
+ return this.props.clipping;
2019
+ }
2020
+
2021
+ set clipping(value: boolean) {
2022
+ this.props.clipping = value;
2023
+ this.setUpdateType(
2024
+ UpdateType.Clipping | UpdateType.RenderBounds | UpdateType.Children,
2025
+ );
2026
+ this.childUpdateType |= UpdateType.Global | UpdateType.Clipping;
2027
+ }
2028
+
2029
+ get color(): number {
2030
+ return this.props.color;
2031
+ }
2032
+
2033
+ set color(value: number) {
2034
+ const p = this.props;
2035
+ if (p.color === value) return;
2036
+
2037
+ p.color = value;
2038
+
2039
+ const has = value > 0;
2040
+ this.hasColorProps = has;
2041
+
2042
+ if (p.colorTop !== value) this.colorTop = value;
2043
+ if (p.colorBottom !== value) this.colorBottom = value;
2044
+ if (p.colorLeft !== value) this.colorLeft = value;
2045
+ if (p.colorRight !== value) this.colorRight = value;
2046
+
2047
+ this.setUpdateType(UpdateType.PremultipliedColors);
2048
+ }
2049
+
2050
+ get colorTop(): number {
2051
+ return this.props.colorTop;
2052
+ }
2053
+
2054
+ set colorTop(value: number) {
2055
+ if (this.props.colorTl !== value || this.props.colorTr !== value) {
2056
+ this.colorTl = value;
2057
+ this.colorTr = value;
2058
+ }
2059
+ this.props.colorTop = value;
2060
+ this.hasColorProps = value > 0;
2061
+ this.setUpdateType(UpdateType.PremultipliedColors);
2062
+ }
2063
+
2064
+ get colorBottom(): number {
2065
+ return this.props.colorBottom;
2066
+ }
2067
+
2068
+ set colorBottom(value: number) {
2069
+ if (this.props.colorBl !== value || this.props.colorBr !== value) {
2070
+ this.colorBl = value;
2071
+ this.colorBr = value;
2072
+ }
2073
+ this.props.colorBottom = value;
2074
+ this.hasColorProps = value > 0;
2075
+ this.setUpdateType(UpdateType.PremultipliedColors);
2076
+ }
2077
+
2078
+ get colorLeft(): number {
2079
+ return this.props.colorLeft;
2080
+ }
2081
+
2082
+ set colorLeft(value: number) {
2083
+ if (this.props.colorTl !== value || this.props.colorBl !== value) {
2084
+ this.colorTl = value;
2085
+ this.colorBl = value;
2086
+ }
2087
+ this.props.colorLeft = value;
2088
+ this.hasColorProps = value > 0;
2089
+ this.setUpdateType(UpdateType.PremultipliedColors);
2090
+ }
2091
+
2092
+ get colorRight(): number {
2093
+ return this.props.colorRight;
2094
+ }
2095
+
2096
+ set colorRight(value: number) {
2097
+ if (this.props.colorTr !== value || this.props.colorBr !== value) {
2098
+ this.colorTr = value;
2099
+ this.colorBr = value;
2100
+ }
2101
+ this.props.colorRight = value;
2102
+ this.hasColorProps = value > 0;
2103
+ this.setUpdateType(UpdateType.PremultipliedColors);
2104
+ }
2105
+
2106
+ get colorTl(): number {
2107
+ return this.props.colorTl;
2108
+ }
2109
+
2110
+ set colorTl(value: number) {
2111
+ this.props.colorTl = value;
2112
+ this.hasColorProps = value > 0;
2113
+ this.setUpdateType(UpdateType.PremultipliedColors);
2114
+ }
2115
+
2116
+ get colorTr(): number {
2117
+ return this.props.colorTr;
2118
+ }
2119
+
2120
+ set colorTr(value: number) {
2121
+ this.props.colorTr = value;
2122
+ this.hasColorProps = value > 0;
2123
+ this.setUpdateType(UpdateType.PremultipliedColors);
2124
+ }
2125
+
2126
+ get colorBl(): number {
2127
+ return this.props.colorBl;
2128
+ }
2129
+
2130
+ set colorBl(value: number) {
2131
+ this.props.colorBl = value;
2132
+ this.hasColorProps = value > 0;
2133
+ this.setUpdateType(UpdateType.PremultipliedColors);
2134
+ }
2135
+
2136
+ get colorBr(): number {
2137
+ return this.props.colorBr;
2138
+ }
2139
+
2140
+ set colorBr(value: number) {
2141
+ this.props.colorBr = value;
2142
+ this.hasColorProps = value > 0;
2143
+ this.setUpdateType(UpdateType.PremultipliedColors);
2144
+ }
2145
+
2146
+ // we're only interested in parent zIndex to test
2147
+ // if we should use node zIndex is higher then parent zIndex
2148
+ get zIndexLocked(): number {
2149
+ return this.props.zIndexLocked || 0;
2150
+ }
2151
+
2152
+ set zIndexLocked(value: number) {
2153
+ this.props.zIndexLocked = value;
2154
+ this.setUpdateType(UpdateType.CalculatedZIndex | UpdateType.Children);
2155
+ for (let i = 0, length = this.children.length; i < length; i++) {
2156
+ this.children[i]!.setUpdateType(UpdateType.CalculatedZIndex);
2157
+ }
2158
+ }
2159
+
2160
+ get zIndex(): number {
2161
+ return this.props.zIndex;
2162
+ }
2163
+
2164
+ set zIndex(value: number) {
2165
+ this.props.zIndex = value;
2166
+ this.setUpdateType(UpdateType.CalculatedZIndex | UpdateType.Children);
2167
+ for (let i = 0, length = this.children.length; i < length; i++) {
2168
+ this.children[i]!.setUpdateType(UpdateType.CalculatedZIndex);
2169
+ }
2170
+ }
2171
+
2172
+ get parent(): CoreNode | null {
2173
+ return this.props.parent;
2174
+ }
2175
+
2176
+ set parent(newParent: CoreNode | null) {
2177
+ const oldParent = this.props.parent;
2178
+ if (oldParent === newParent) {
2179
+ return;
2180
+ }
2181
+ this.props.parent = newParent;
2182
+ if (oldParent) {
2183
+ const index = oldParent.children.indexOf(this);
2184
+ oldParent.children.splice(index, 1);
2185
+ oldParent.setUpdateType(
2186
+ UpdateType.Children | UpdateType.ZIndexSortedChildren,
2187
+ );
2188
+ }
2189
+ if (newParent) {
2190
+ newParent.children.push(this);
2191
+ // Since this node has a new parent, to be safe, have it do a full update.
2192
+ this.setUpdateType(UpdateType.All);
2193
+ // Tell parent that it's children need to be updated and sorted.
2194
+ newParent.setUpdateType(
2195
+ UpdateType.Children | UpdateType.ZIndexSortedChildren,
2196
+ );
2197
+
2198
+ // If the new parent has an RTT enabled, apply RTT inheritance
2199
+ if (newParent.rtt || newParent.parentHasRenderTexture) {
2200
+ this.applyRTTInheritance(newParent);
2201
+ }
2202
+ }
2203
+
2204
+ // fetch render bounds from parent
2205
+ this.setUpdateType(UpdateType.RenderBounds | UpdateType.Children);
2206
+ }
2207
+
2208
+ get rtt(): boolean {
2209
+ return this.props.rtt;
2210
+ }
2211
+
2212
+ set rtt(value: boolean) {
2213
+ if (this.props.rtt === value) {
2214
+ return;
2215
+ }
2216
+ this.props.rtt = value;
2217
+
2218
+ if (value === true) {
2219
+ this.initRenderTexture();
2220
+ this.markChildrenWithRTT();
2221
+ } else {
2222
+ this.cleanupRenderTexture();
2223
+ }
2224
+
2225
+ this.setUpdateType(UpdateType.RenderTexture);
2226
+
2227
+ if (this.parentHasRenderTexture === true) {
2228
+ this.notifyParentRTTOfUpdate();
2229
+ }
2230
+ }
2231
+ private initRenderTexture() {
2232
+ this.framebufferDimensions = {
2233
+ width: this.width,
2234
+ height: this.height,
2235
+ };
2236
+ this.texture = this.stage.txManager.createTexture(
2237
+ 'RenderTexture',
2238
+ this.framebufferDimensions,
2239
+ );
2240
+ this.stage.renderer.renderToTexture(this);
2241
+ }
2242
+
2243
+ private cleanupRenderTexture() {
2244
+ this.unloadTexture();
2245
+ this.clearRTTInheritance();
2246
+
2247
+ this.hasRTTupdates = false;
2248
+ this.texture = null;
2249
+ this.framebufferDimensions = null;
2250
+ }
2251
+
2252
+ private markChildrenWithRTT(node: CoreNode | null = null) {
2253
+ const parent = node || this;
2254
+
2255
+ for (const child of parent.children) {
2256
+ child.setUpdateType(UpdateType.All);
2257
+ child.parentHasRenderTexture = true;
2258
+ child.markChildrenWithRTT();
2259
+ }
2260
+ }
2261
+
2262
+ // Apply RTT inheritance when a node has an RTT-enabled parent
2263
+ private applyRTTInheritance(parent: CoreNode) {
2264
+ if (parent.rtt) {
2265
+ // Only the RTT node should be added to `renderToTexture`
2266
+ parent.setUpdateType(UpdateType.RenderTexture);
2267
+ }
2268
+
2269
+ // Propagate `parentHasRenderTexture` downwards
2270
+ this.markChildrenWithRTT(parent);
2271
+ }
2272
+
2273
+ // Clear RTT inheritance when detaching from an RTT chain
2274
+ private clearRTTInheritance() {
2275
+ // if this node is RTT itself stop the propagation important for nested RTT nodes
2276
+ // for the initial RTT node this is already handled in `set rtt`
2277
+ if (this.rtt) {
2278
+ return;
2279
+ }
2280
+
2281
+ for (const child of this.children) {
2282
+ // force child to update everything as the RTT inheritance has changed
2283
+ child.parentHasRenderTexture = false;
2284
+ child.rttParent = null;
2285
+ child.setUpdateType(UpdateType.All);
2286
+ child.clearRTTInheritance();
2287
+ }
2288
+ }
2289
+
2290
+ get shader(): CoreShaderNode<any> | null {
2291
+ return this.props.shader;
2292
+ }
2293
+
2294
+ set shader(shader: CoreShaderNode<any> | null) {
2295
+ if (this.props.shader === shader) {
2296
+ return;
2297
+ }
2298
+ if (shader === null) {
2299
+ this.hasShaderUpdater = false;
2300
+ this.props.shader = this.stage.defShaderNode;
2301
+ this.setUpdateType(UpdateType.IsRenderable);
2302
+ return;
2303
+ }
2304
+ if (shader.shaderKey !== 'default') {
2305
+ this.hasShaderUpdater = shader.update !== undefined;
2306
+ shader.attachNode(this);
2307
+ }
2308
+ this.props.shader = shader;
2309
+ this.setUpdateType(UpdateType.IsRenderable | UpdateType.RecalcUniforms);
2310
+ }
2311
+
2312
+ get src(): string | null {
2313
+ return this.props.src;
2314
+ }
2315
+
2316
+ set src(imageUrl: string | null) {
2317
+ if (this.props.src === imageUrl) {
2318
+ return;
2319
+ }
2320
+
2321
+ this.props.src = imageUrl;
2322
+
2323
+ if (!imageUrl) {
2324
+ this.texture = null;
2325
+ return;
2326
+ }
2327
+
2328
+ this.texture = this.stage.txManager.createTexture('ImageTexture', {
2329
+ src: imageUrl,
2330
+ width: this.props.width,
2331
+ height: this.props.height,
2332
+ type: this.props.imageType,
2333
+ sx: this.props.srcX,
2334
+ sy: this.props.srcY,
2335
+ sw: this.props.srcWidth,
2336
+ sh: this.props.srcHeight,
2337
+ });
2338
+ }
2339
+
2340
+ set imageType(type: 'regular' | 'compressed' | 'svg' | null) {
2341
+ if (this.props.imageType === type) {
2342
+ return;
2343
+ }
2344
+
2345
+ this.props.imageType = type;
2346
+ }
2347
+
2348
+ get imageType() {
2349
+ return this.props.imageType || null;
2350
+ }
2351
+
2352
+ get srcHeight(): number | undefined {
2353
+ return this.props.srcHeight;
2354
+ }
2355
+
2356
+ set srcHeight(value: number) {
2357
+ this.props.srcHeight = value;
2358
+ }
2359
+
2360
+ get srcWidth(): number | undefined {
2361
+ return this.props.srcWidth;
2362
+ }
2363
+
2364
+ set srcWidth(value: number) {
2365
+ this.props.srcWidth = value;
2366
+ }
2367
+
2368
+ get srcX(): number | undefined {
2369
+ return this.props.srcX;
2370
+ }
2371
+
2372
+ set srcX(value: number) {
2373
+ this.props.srcX = value;
2374
+ }
2375
+
2376
+ get srcY(): number | undefined {
2377
+ return this.props.srcY;
2378
+ }
2379
+
2380
+ set srcY(value: number) {
2381
+ this.props.srcY = value;
2382
+ }
2383
+
2384
+ /**
2385
+ * Returns the framebuffer dimensions of the RTT parent
2386
+ */
2387
+ get parentFramebufferDimensions(): Dimensions {
2388
+ if (this.rttParent !== null) {
2389
+ return this.rttParent.framebufferDimensions as Dimensions;
2390
+ }
2391
+ this.rttParent = this.findParentRTTNode() as CoreNode;
2392
+ return this.rttParent.framebufferDimensions as Dimensions;
2393
+ }
2394
+
2395
+ /**
2396
+ * Returns the parent render texture node if it exists.
2397
+ */
2398
+ get parentRenderTexture(): CoreNode | null {
2399
+ let parent = this.parent;
2400
+ while (parent) {
2401
+ if (parent.rtt) {
2402
+ return parent;
2403
+ }
2404
+ parent = parent.parent;
2405
+ }
2406
+ return null;
2407
+ }
2408
+
2409
+ get texture(): Texture | null {
2410
+ return this.props.texture;
2411
+ }
2412
+
2413
+ set texture(value: Texture | null) {
2414
+ if (this.props.texture === value) {
2415
+ return;
2416
+ }
2417
+
2418
+ const oldTexture = this.props.texture;
2419
+ if (oldTexture) {
2420
+ this.unloadTexture();
2421
+ }
2422
+
2423
+ this.textureCoords = undefined;
2424
+ this.props.texture = value;
2425
+ if (value !== null) {
2426
+ value.setRenderableOwner(this, this.isRenderable);
2427
+ this.loadTexture();
2428
+ }
2429
+
2430
+ this.setUpdateType(UpdateType.IsRenderable);
2431
+ }
2432
+
2433
+ set textureOptions(value: TextureOptions) {
2434
+ this.props.textureOptions = value;
2435
+ }
2436
+
2437
+ get textureOptions(): TextureOptions {
2438
+ return this.props.textureOptions;
2439
+ }
2440
+
2441
+ set interactive(value: boolean | undefined) {
2442
+ this.props.interactive = value;
2443
+ // Update Stage's interactive Set
2444
+ if (value === true) {
2445
+ this.stage.interactiveNodes.add(this);
2446
+ }
2447
+ }
2448
+
2449
+ get interactive(): boolean | undefined {
2450
+ return this.props.interactive;
2451
+ }
2452
+
2453
+ setRTTUpdates(type: number) {
2454
+ this.hasRTTupdates = true;
2455
+ this.parent?.setRTTUpdates(type);
2456
+ }
2457
+
2458
+ get strictBounds(): boolean {
2459
+ return this.props.strictBounds;
2460
+ }
2461
+
2462
+ set strictBounds(v) {
2463
+ if (v === this.props.strictBounds) {
2464
+ return;
2465
+ }
2466
+
2467
+ this.props.strictBounds = v;
2468
+ this.setUpdateType(UpdateType.RenderBounds | UpdateType.Children);
2469
+ this.childUpdateType |= UpdateType.RenderBounds | UpdateType.Children;
2470
+ }
2471
+
2472
+ animate(
2473
+ props: Partial<CoreNodeAnimateProps>,
2474
+ settings: Partial<AnimationSettings>,
2475
+ ): IAnimationController {
2476
+ const animation = new CoreAnimation(this, props, settings);
2477
+
2478
+ const controller = new CoreAnimationController(
2479
+ this.stage.animationManager,
2480
+ animation,
2481
+ );
2482
+
2483
+ return controller;
2484
+ }
2485
+
2486
+ flush() {
2487
+ // no-op
2488
+ }
2489
+
2490
+ //#endregion Properties
2491
+ }