@lightningjs/renderer 3.0.0-beta20 → 3.0.0-beta21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/dist/src/core/CoreNode.d.ts +53 -7
  2. package/dist/src/core/CoreNode.js +175 -65
  3. package/dist/src/core/CoreNode.js.map +1 -1
  4. package/dist/src/core/CoreTextNode.d.ts +1 -1
  5. package/dist/src/core/CoreTextNode.js +3 -5
  6. package/dist/src/core/CoreTextNode.js.map +1 -1
  7. package/dist/src/core/CoreTextureManager.js +1 -1
  8. package/dist/src/core/CoreTextureManager.js.map +1 -1
  9. package/dist/src/core/Stage.d.ts +2 -1
  10. package/dist/src/core/Stage.js +9 -7
  11. package/dist/src/core/Stage.js.map +1 -1
  12. package/dist/src/core/TextureMemoryManager.d.ts +1 -1
  13. package/dist/src/core/TextureMemoryManager.js +3 -3
  14. package/dist/src/core/TextureMemoryManager.js.map +1 -1
  15. package/dist/src/core/animations/Animation.d.ts +21 -0
  16. package/dist/src/core/animations/Animation.js +194 -0
  17. package/dist/src/core/animations/Animation.js.map +1 -0
  18. package/dist/src/core/animations/Playback.d.ts +64 -0
  19. package/dist/src/core/animations/Playback.js +169 -0
  20. package/dist/src/core/animations/Playback.js.map +1 -0
  21. package/dist/src/core/animations/Transition.d.ts +27 -0
  22. package/dist/src/core/animations/Transition.js +52 -0
  23. package/dist/src/core/animations/Transition.js.map +1 -0
  24. package/dist/src/core/animations/utils.d.ts +2 -0
  25. package/dist/src/core/animations/utils.js +136 -0
  26. package/dist/src/core/animations/utils.js.map +1 -0
  27. package/dist/src/core/lib/ImageWorker.d.ts +2 -2
  28. package/dist/src/core/lib/ImageWorker.js +30 -11
  29. package/dist/src/core/lib/ImageWorker.js.map +1 -1
  30. package/dist/src/core/lib/WebGlContextWrapper.js +1 -1
  31. package/dist/src/core/lib/WebGlContextWrapper.js.map +1 -1
  32. package/dist/src/core/lib/utils.d.ts +6 -2
  33. package/dist/src/core/lib/utils.js +21 -21
  34. package/dist/src/core/lib/utils.js.map +1 -1
  35. package/dist/src/core/renderers/CoreRenderer.d.ts +1 -31
  36. package/dist/src/core/renderers/CoreRenderer.js.map +1 -1
  37. package/dist/src/core/renderers/CoreShaderNode.d.ts +4 -0
  38. package/dist/src/core/renderers/CoreShaderNode.js +15 -0
  39. package/dist/src/core/renderers/CoreShaderNode.js.map +1 -1
  40. package/dist/src/core/renderers/canvas/CanvasRenderer.d.ts +3 -3
  41. package/dist/src/core/renderers/canvas/CanvasRenderer.js +38 -33
  42. package/dist/src/core/renderers/canvas/CanvasRenderer.js.map +1 -1
  43. package/dist/src/core/renderers/canvas/CanvasShaderNode.d.ts +1 -2
  44. package/dist/src/core/renderers/canvas/CanvasShaderNode.js.map +1 -1
  45. package/dist/src/core/renderers/webgl/SdfRenderOp.d.ts +33 -0
  46. package/dist/src/core/renderers/webgl/SdfRenderOp.js +97 -0
  47. package/dist/src/core/renderers/webgl/SdfRenderOp.js.map +1 -0
  48. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js +1 -1
  49. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js.map +1 -1
  50. package/dist/src/core/renderers/webgl/WebGlCtxTexture.js +12 -8
  51. package/dist/src/core/renderers/webgl/WebGlCtxTexture.js.map +1 -1
  52. package/dist/src/core/renderers/webgl/WebGlRenderOp.d.ts +2 -3
  53. package/dist/src/core/renderers/webgl/WebGlRenderOp.js +1 -3
  54. package/dist/src/core/renderers/webgl/WebGlRenderOp.js.map +1 -1
  55. package/dist/src/core/renderers/webgl/WebGlRenderer.d.ts +6 -18
  56. package/dist/src/core/renderers/webgl/WebGlRenderer.js +48 -61
  57. package/dist/src/core/renderers/webgl/WebGlRenderer.js.map +1 -1
  58. package/dist/src/core/renderers/webgl/WebGlShaderNode.d.ts +2 -4
  59. package/dist/src/core/renderers/webgl/WebGlShaderNode.js.map +1 -1
  60. package/dist/src/core/renderers/webgl/WebGlShaderProgram.d.ts +3 -4
  61. package/dist/src/core/renderers/webgl/WebGlShaderProgram.js +40 -29
  62. package/dist/src/core/renderers/webgl/WebGlShaderProgram.js.map +1 -1
  63. package/dist/src/core/shaders/canvas/Border.d.ts +8 -2
  64. package/dist/src/core/shaders/canvas/Border.js +62 -23
  65. package/dist/src/core/shaders/canvas/Border.js.map +1 -1
  66. package/dist/src/core/shaders/canvas/HolePunch.js +2 -1
  67. package/dist/src/core/shaders/canvas/HolePunch.js.map +1 -1
  68. package/dist/src/core/shaders/canvas/LinearGradient.js +5 -3
  69. package/dist/src/core/shaders/canvas/LinearGradient.js.map +1 -1
  70. package/dist/src/core/shaders/canvas/RadialGradient.js +7 -5
  71. package/dist/src/core/shaders/canvas/RadialGradient.js.map +1 -1
  72. package/dist/src/core/shaders/canvas/Rounded.js +2 -2
  73. package/dist/src/core/shaders/canvas/Rounded.js.map +1 -1
  74. package/dist/src/core/shaders/canvas/RoundedWithBorder.d.ts +6 -3
  75. package/dist/src/core/shaders/canvas/RoundedWithBorder.js +39 -9
  76. package/dist/src/core/shaders/canvas/RoundedWithBorder.js.map +1 -1
  77. package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.d.ts +2 -3
  78. package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.js +44 -7
  79. package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.js.map +1 -1
  80. package/dist/src/core/shaders/canvas/RoundedWithShadow.js +5 -4
  81. package/dist/src/core/shaders/canvas/RoundedWithShadow.js.map +1 -1
  82. package/dist/src/core/shaders/canvas/Shadow.js +4 -2
  83. package/dist/src/core/shaders/canvas/Shadow.js.map +1 -1
  84. package/dist/src/core/shaders/canvas/utils/render.d.ts +1 -1
  85. package/dist/src/core/shaders/canvas/utils/render.js +31 -18
  86. package/dist/src/core/shaders/canvas/utils/render.js.map +1 -1
  87. package/dist/src/core/shaders/templates/BorderTemplate.d.ts +10 -0
  88. package/dist/src/core/shaders/templates/BorderTemplate.js +20 -0
  89. package/dist/src/core/shaders/templates/BorderTemplate.js.map +1 -1
  90. package/dist/src/core/shaders/webgl/Border.js +72 -14
  91. package/dist/src/core/shaders/webgl/Border.js.map +1 -1
  92. package/dist/src/core/shaders/webgl/RoundedWithBorder.js +101 -31
  93. package/dist/src/core/shaders/webgl/RoundedWithBorder.js.map +1 -1
  94. package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js +102 -38
  95. package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js.map +1 -1
  96. package/dist/src/core/shaders/webgl/RoundedWithShadow.js +5 -4
  97. package/dist/src/core/shaders/webgl/RoundedWithShadow.js.map +1 -1
  98. package/dist/src/core/shaders/webgl/SdfShadowShader.d.ts +9 -0
  99. package/dist/src/core/shaders/webgl/SdfShadowShader.js +100 -0
  100. package/dist/src/core/shaders/webgl/SdfShadowShader.js.map +1 -0
  101. package/dist/src/core/shaders/webgl/Shadow.js +12 -6
  102. package/dist/src/core/shaders/webgl/Shadow.js.map +1 -1
  103. package/dist/src/core/text-rendering/SdfTextRenderer.js +12 -20
  104. package/dist/src/core/text-rendering/SdfTextRenderer.js.map +1 -1
  105. package/dist/src/core/utils.d.ts +1 -1
  106. package/dist/src/main-api/Inspector.d.ts +1 -1
  107. package/dist/src/main-api/Inspector.js +4 -1
  108. package/dist/src/main-api/Inspector.js.map +1 -1
  109. package/dist/src/main-api/Renderer.d.ts +10 -0
  110. package/dist/src/main-api/Renderer.js +2 -0
  111. package/dist/src/main-api/Renderer.js.map +1 -1
  112. package/dist/tsconfig.dist.tsbuildinfo +1 -1
  113. package/package.json +1 -1
  114. package/src/core/Autosizer.ts +224 -0
  115. package/src/core/CoreNode.test.ts +116 -2
  116. package/src/core/CoreNode.ts +247 -78
  117. package/src/core/CoreTextNode.ts +3 -5
  118. package/src/core/CoreTextureManager.ts +1 -1
  119. package/src/core/Stage.ts +10 -7
  120. package/src/core/TextureMemoryManager.ts +3 -3
  121. package/src/core/lib/ImageWorker.ts +36 -11
  122. package/src/core/lib/WebGlContextWrapper.ts +1 -1
  123. package/src/core/lib/utils.ts +28 -25
  124. package/src/core/renderers/CoreRenderer.ts +1 -32
  125. package/src/core/renderers/CoreShaderNode.ts +20 -0
  126. package/src/core/renderers/canvas/CanvasRenderer.ts +43 -51
  127. package/src/core/renderers/canvas/CanvasShaderNode.ts +1 -2
  128. package/src/core/renderers/webgl/SdfRenderOp.ts +105 -0
  129. package/src/core/renderers/webgl/WebGlCtxTexture.ts +16 -9
  130. package/src/core/renderers/webgl/WebGlRenderer.ts +56 -78
  131. package/src/core/renderers/webgl/WebGlShaderNode.ts +2 -7
  132. package/src/core/renderers/webgl/WebGlShaderProgram.ts +48 -38
  133. package/src/core/shaders/canvas/Border.ts +86 -29
  134. package/src/core/shaders/canvas/HolePunch.ts +2 -1
  135. package/src/core/shaders/canvas/LinearGradient.ts +8 -6
  136. package/src/core/shaders/canvas/RadialGradient.ts +7 -10
  137. package/src/core/shaders/canvas/Rounded.ts +5 -5
  138. package/src/core/shaders/canvas/RoundedWithBorder.ts +68 -18
  139. package/src/core/shaders/canvas/RoundedWithBorderAndShadow.ts +71 -23
  140. package/src/core/shaders/canvas/RoundedWithShadow.ts +6 -5
  141. package/src/core/shaders/canvas/Shadow.ts +7 -5
  142. package/src/core/shaders/canvas/utils/render.ts +45 -36
  143. package/src/core/shaders/templates/BorderTemplate.ts +30 -0
  144. package/src/core/shaders/webgl/Border.ts +72 -15
  145. package/src/core/shaders/webgl/RoundedWithBorder.ts +101 -31
  146. package/src/core/shaders/webgl/RoundedWithBorderAndShadow.ts +102 -38
  147. package/src/core/shaders/webgl/RoundedWithShadow.ts +5 -4
  148. package/src/core/shaders/webgl/Shadow.ts +12 -6
  149. package/src/core/text-rendering/SdfTextRenderer.ts +18 -21
  150. package/src/main-api/Inspector.ts +6 -3
  151. package/src/main-api/Renderer.ts +13 -0
  152. package/src/core/renderers/webgl/WebGlRenderOp.ts +0 -170
@@ -23,6 +23,9 @@ import {
23
23
  mergeColorAlphaPremultiplied,
24
24
  } from '../utils.js';
25
25
  import type { TextureOptions } from './CoreTextureManager.js';
26
+ import type { WebGlRenderer } from './renderers/webgl/WebGlRenderer.js';
27
+ import type { WebGlCtxTexture } from './renderers/webgl/WebGlCtxTexture.js';
28
+ import type { BufferCollection } from './renderers/webgl/internal/BufferCollection.js';
26
29
  import type { CoreRenderer } from './renderers/CoreRenderer.js';
27
30
  import type { Stage } from './Stage.js';
28
31
  import {
@@ -57,6 +60,7 @@ import type { IAnimationController } from '../common/IAnimationController.js';
57
60
  import { CoreAnimation } from './animations/CoreAnimation.js';
58
61
  import { CoreAnimationController } from './animations/CoreAnimationController.js';
59
62
  import type { CoreShaderNode } from './renderers/CoreShaderNode.js';
63
+ import { AutosizeMode, Autosizer } from './Autosizer.js';
60
64
  import {
61
65
  bucketSortByZIndex,
62
66
  incrementalRepositionByZIndex,
@@ -73,8 +77,8 @@ export enum CoreNodeRenderState {
73
77
  const NO_CLIPPING_RECT: RectWithValid = {
74
78
  x: 0,
75
79
  y: 0,
76
- width: 0,
77
- height: 0,
80
+ w: 0,
81
+ h: 0,
78
82
  valid: false,
79
83
  };
80
84
 
@@ -187,6 +191,10 @@ export enum UpdateType {
187
191
  */
188
192
  RecalcUniforms = 4096,
189
193
 
194
+ /**
195
+ * Autosize update
196
+ */
197
+ Autosize = 8192,
190
198
  /**
191
199
  * None
192
200
  */
@@ -195,7 +203,7 @@ export enum UpdateType {
195
203
  /**
196
204
  * All
197
205
  */
198
- All = 7167,
206
+ All = 16383,
199
207
  }
200
208
 
201
209
  /**
@@ -259,14 +267,35 @@ export interface CoreNodeProps {
259
267
  */
260
268
  alpha: number;
261
269
  /**
262
- * Autosize mode
270
+ * Autosize
263
271
  *
264
272
  * @remarks
265
- * When enabled, when a texture is loaded into the Node, the Node will
266
- * automatically resize to the dimensions of the texture.
273
+ * When enabled, the Node automatically resizes based on its content
274
+ *
275
+ * **Texture Autosize Mode:**
276
+ * - When the Node has a texture, it automatically resizes to match the
277
+ * texture's dimensions when the texture loads
278
+ * - This ensures images display at their natural size without manual sizing
279
+ * - Text Nodes always use this mode regardless of this setting
280
+ *
281
+ * **Children Autosize Mode:**
282
+ * - When the Node has no texture but contains children, it automatically
283
+ * resizes to encompass all children's bounds
284
+ * - Calculates the bounding box that contains all child positions, dimensions,
285
+ * and transforms (scale, rotation, mount/pivot points)
286
+ * - Creates container behavior where the parent grows to fit its content
287
+ * - Updates dynamically as children are added, removed, or transformed
288
+ *
289
+ * **Mode Selection Logic:**
290
+ * - Texture mode takes precedence over children mode
291
+ * - Mode switches automatically when texture is added/removed
292
+ * - If no texture and no children, autosize has no effect
293
+ *
294
+ * **Performance:**
295
+ * - Children mode uses efficient transform caching and differential updates
296
+ * - Only recalculates when child transforms actually change
297
+ * - Minimal memory allocation with factory function patterns
267
298
  *
268
- * Text Nodes are always autosized based on their text content regardless
269
- * of this mode setting.
270
299
  *
271
300
  * @default `false`
272
301
  */
@@ -712,6 +741,12 @@ export class CoreNode extends EventEmitter {
712
741
  readonly children: CoreNode[] = [];
713
742
  protected _id: number = getNewId();
714
743
  readonly props: CoreNodeProps;
744
+ public readonly isCoreNode = true as const;
745
+
746
+ // WebGL Render Op State
747
+ public renderOpBufferIdx: number = 0;
748
+ public numQuads: number = 0;
749
+ public renderOpTextures: WebGlCtxTexture[] = [];
715
750
 
716
751
  private hasShaderUpdater = false;
717
752
  public hasShaderTimeFn = false;
@@ -736,8 +771,8 @@ export class CoreNode extends EventEmitter {
736
771
  public clippingRect: RectWithValid = {
737
772
  x: 0,
738
773
  y: 0,
739
- width: 0,
740
- height: 0,
774
+ w: 0,
775
+ h: 0,
741
776
  valid: false,
742
777
  };
743
778
  public textureCoords?: TextureCoords;
@@ -759,11 +794,19 @@ export class CoreNode extends EventEmitter {
759
794
  */
760
795
  public framebufferDimensions: Dimensions | null = null;
761
796
 
797
+ /**Autosize properties */
798
+ autosizer: Autosizer | null = null;
799
+ parentAutosizer: Autosizer | null = null;
800
+
762
801
  public destroyed = false;
763
802
 
764
803
  constructor(readonly stage: Stage, props: CoreNodeProps) {
765
804
  super();
766
805
  const p = (this.props = {} as CoreNodeProps);
806
+
807
+ // Initialize the renderOpTextures array with a capacity of 16 (typical max textures)
808
+ this.renderOpTextures = [];
809
+
767
810
  //inital update type
768
811
  let initialUpdateType =
769
812
  UpdateType.Local | UpdateType.RenderBounds | UpdateType.RenderState;
@@ -822,6 +865,7 @@ export class CoreNode extends EventEmitter {
822
865
  p.srcY = props.srcY;
823
866
  p.srcWidth = props.srcWidth;
824
867
  p.srcHeight = props.srcHeight;
868
+ p.autosize = props.autosize;
825
869
 
826
870
  p.parent = props.parent;
827
871
  p.texture = null;
@@ -847,6 +891,11 @@ export class CoreNode extends EventEmitter {
847
891
  this.boundsMargin = props.boundsMargin;
848
892
  this.interactive = props.interactive;
849
893
 
894
+ // Initialize autosize if enabled
895
+ if (p.autosize === true) {
896
+ this.autosizer = new Autosizer(this);
897
+ }
898
+
850
899
  this.setUpdateType(initialUpdateType);
851
900
 
852
901
  // if the default texture isn't loaded yet, wait for it to load
@@ -877,7 +926,11 @@ export class CoreNode extends EventEmitter {
877
926
  * This method is called in a microtask to release the texture.
878
927
  */
879
928
  private loadTextureTask = (): void => {
880
- const texture = this.texture as Texture;
929
+ const texture = this.props.texture as Texture;
930
+ //it is possible that texture is null here if user sets the texture to null right after loadTexture call
931
+ if (texture === null) {
932
+ return;
933
+ }
881
934
  if (this.textureOptions.preload === true) {
882
935
  this.stage.txManager.loadTexture(texture);
883
936
  }
@@ -919,9 +972,8 @@ export class CoreNode extends EventEmitter {
919
972
  }
920
973
 
921
974
  protected onTextureLoaded: TextureLoadedEventHandler = (_, dimensions) => {
922
- if (this.autosize === true) {
923
- this.w = dimensions.w;
924
- this.h = dimensions.h;
975
+ if (this.autosizer !== null) {
976
+ this.autosizer.update();
925
977
  }
926
978
 
927
979
  this.setUpdateType(UpdateType.IsRenderable);
@@ -1094,6 +1146,12 @@ export class CoreNode extends EventEmitter {
1094
1146
  let updateType = this.updateType;
1095
1147
  let childUpdateType = this.childUpdateType;
1096
1148
  let updateParent = false;
1149
+
1150
+ //this needs to be handled before setting updateTypes are reset
1151
+ if (updateType & UpdateType.Autosize && this.autosizer !== null) {
1152
+ this.autosizer.update();
1153
+ }
1154
+
1097
1155
  // reset update type
1098
1156
  this.updateType = 0;
1099
1157
  this.childUpdateType = 0;
@@ -1148,12 +1206,14 @@ export class CoreNode extends EventEmitter {
1148
1206
  this.calculateRenderCoords();
1149
1207
  this.updateBoundingRect();
1150
1208
 
1151
- updateType |=
1152
- UpdateType.RenderState |
1153
- UpdateType.Children |
1154
- UpdateType.RecalcUniforms;
1209
+ updateType |= UpdateType.RenderState | UpdateType.RecalcUniforms;
1155
1210
  updateParent = hasParent;
1156
- childUpdateType |= UpdateType.Global;
1211
+
1212
+ //only propagate children updates if not autosizing
1213
+ if ((updateType & UpdateType.Autosize) === 0) {
1214
+ updateType |= UpdateType.Children;
1215
+ childUpdateType |= UpdateType.Global;
1216
+ }
1157
1217
 
1158
1218
  if (this.clipping === true) {
1159
1219
  updateType |= UpdateType.Clipping | UpdateType.RenderBounds;
@@ -1198,6 +1258,15 @@ export class CoreNode extends EventEmitter {
1198
1258
  this.updateIsRenderable();
1199
1259
  }
1200
1260
 
1261
+ // Handle autosize updates when children transforms change
1262
+ if (
1263
+ updateType & UpdateType.Global &&
1264
+ this.isRenderable === true &&
1265
+ this.parentAutosizer !== null
1266
+ ) {
1267
+ this.parentAutosizer.patch(this.id);
1268
+ }
1269
+
1201
1270
  if (updateType & UpdateType.Clipping) {
1202
1271
  this.calculateClippingRect(parentClippingRect);
1203
1272
  updateType |= UpdateType.Children;
@@ -1684,8 +1753,8 @@ export class CoreNode extends EventEmitter {
1684
1753
  if (clipping === true && isRotated === false) {
1685
1754
  clippingRect.x = gt!.tx;
1686
1755
  clippingRect.y = gt!.ty;
1687
- clippingRect.width = this.props.w * gt!.ta;
1688
- clippingRect.height = this.props.h * gt!.td;
1756
+ clippingRect.w = this.props.w * gt!.ta;
1757
+ clippingRect.h = this.props.h * gt!.td;
1689
1758
  clippingRect.valid = true;
1690
1759
  } else {
1691
1760
  clippingRect.valid = false;
@@ -1744,47 +1813,27 @@ export class CoreNode extends EventEmitter {
1744
1813
  return;
1745
1814
  }
1746
1815
 
1747
- const p = this.props;
1748
- const t = this.globalTransform!;
1749
- const coords = this.renderCoords;
1750
- const texture = p.texture || this.stage.defaultTexture;
1751
- const textureCoords =
1752
- this.textureCoords || this.stage.renderer.defaultTextureCoords;
1816
+ const texture = this.props.texture || this.stage.defaultTexture;
1753
1817
 
1754
1818
  // There is a race condition where the texture can be null
1755
1819
  // with RTT nodes. Adding this defensively to avoid errors.
1756
- if (texture && texture.state !== 'loaded') {
1820
+ // Also check if we have a valid texture or default texture to render
1821
+ if (!texture || texture.state !== 'loaded') {
1757
1822
  return;
1758
1823
  }
1759
1824
 
1760
- renderer.addQuad({
1761
- width: p.w,
1762
- height: p.h,
1763
- colorTl: this.premultipliedColorTl,
1764
- colorTr: this.premultipliedColorTr,
1765
- colorBl: this.premultipliedColorBl,
1766
- colorBr: this.premultipliedColorBr,
1767
- texture,
1768
- textureOptions: p.textureOptions,
1769
- textureCoords: textureCoords,
1770
- shader: p.shader as CoreShaderNode<any>,
1771
- alpha: this.worldAlpha,
1772
- clippingRect: this.clippingRect,
1773
- tx: t.tx,
1774
- ty: t.ty,
1775
- ta: t.ta,
1776
- tb: t.tb,
1777
- tc: t.tc,
1778
- td: t.td,
1779
- renderCoords: coords,
1780
- rtt: p.rtt,
1781
- zIndex: this.calcZIndex,
1782
- parentHasRenderTexture: this.parentHasRenderTexture,
1783
- framebufferDimensions: this.parentHasRenderTexture
1784
- ? this.parentFramebufferDimensions
1785
- : null,
1786
- time: this.hasShaderTimeFn === true ? this.getTimerValue() : null,
1787
- });
1825
+ renderer.addQuad(this);
1826
+ }
1827
+
1828
+ get quadBufferCollection(): BufferCollection {
1829
+ return (this.stage.renderer as WebGlRenderer).quadBufferCollection;
1830
+ }
1831
+
1832
+ get time(): number {
1833
+ if (this.hasShaderTimeFn === true) {
1834
+ return this.getTimerValue();
1835
+ }
1836
+ return 0;
1788
1837
  }
1789
1838
 
1790
1839
  getTimerValue(): number {
@@ -1838,12 +1887,14 @@ export class CoreNode extends EventEmitter {
1838
1887
  }
1839
1888
 
1840
1889
  removeChild(node: CoreNode, targetParent: CoreNode | null = null) {
1841
- if (
1842
- targetParent === null &&
1843
- this.props.rtt === true &&
1844
- this.parentHasRenderTexture === true
1845
- ) {
1846
- node.clearRTTInheritance();
1890
+ if (targetParent === null) {
1891
+ if (this.props.rtt === true && this.parentHasRenderTexture === true) {
1892
+ node.clearRTTInheritance();
1893
+ }
1894
+ const autosizeTarget = this.autosizer || this.parentAutosizer;
1895
+ if (autosizeTarget !== null) {
1896
+ autosizeTarget.detach(node);
1897
+ }
1847
1898
  }
1848
1899
  removeChild(node, this.children);
1849
1900
  }
@@ -1855,6 +1906,8 @@ export class CoreNode extends EventEmitter {
1855
1906
  const min = this.zIndexMin;
1856
1907
  const max = this.zIndexMax;
1857
1908
  const zIndex = node.zIndex;
1909
+ const autosizeTarget = this.autosizer || this.parentAutosizer;
1910
+ let attachToAutosizer = autosizeTarget !== null;
1858
1911
 
1859
1912
  node.parentHasRenderTexture = inRttCluster;
1860
1913
  if (previousParent !== null) {
@@ -1865,6 +1918,22 @@ export class CoreNode extends EventEmitter {
1865
1918
  // update child RTT status
1866
1919
  node.clearRTTInheritance();
1867
1920
  }
1921
+ const previousAutosizer = node.autosizer || node.parentAutosizer;
1922
+
1923
+ if (previousAutosizer !== null) {
1924
+ if (
1925
+ autosizeTarget === null ||
1926
+ previousAutosizer.id !== autosizeTarget.id
1927
+ ) {
1928
+ previousAutosizer.detach(node);
1929
+ }
1930
+ attachToAutosizer = false;
1931
+ }
1932
+ }
1933
+
1934
+ if (attachToAutosizer === true) {
1935
+ //if this is true, then the autosizer really exists
1936
+ autosizeTarget!.attach(node);
1868
1937
  }
1869
1938
 
1870
1939
  if (inRttCluster === true) {
@@ -1936,19 +2005,28 @@ export class CoreNode extends EventEmitter {
1936
2005
  }
1937
2006
 
1938
2007
  set w(value: number) {
1939
- if (this.props.w !== value) {
1940
- this.props.w = value;
1941
- this.setUpdateType(UpdateType.Local);
2008
+ const props = this.props;
2009
+ if (props.w !== value) {
2010
+ props.w = value;
2011
+ let updateType = UpdateType.Local;
2012
+
2013
+ if (
2014
+ props.texture !== null &&
2015
+ this.stage.calculateTextureCoord === true &&
2016
+ props.textureOptions !== null
2017
+ ) {
2018
+ this.textureCoords = this.stage.renderer.getTextureCoords!(this);
2019
+ }
1942
2020
 
1943
- if (this.props.rtt === true) {
2021
+ if (props.rtt === true) {
1944
2022
  this.framebufferDimensions!.w = value;
1945
2023
  this.texture = this.stage.txManager.createTexture(
1946
2024
  'RenderTexture',
1947
2025
  this.framebufferDimensions!,
1948
2026
  );
1949
-
1950
- this.setUpdateType(UpdateType.RenderTexture);
2027
+ updateType |= UpdateType.RenderTexture;
1951
2028
  }
2029
+ this.setUpdateType(updateType);
1952
2030
  }
1953
2031
  }
1954
2032
 
@@ -1957,19 +2035,28 @@ export class CoreNode extends EventEmitter {
1957
2035
  }
1958
2036
 
1959
2037
  set h(value: number) {
1960
- if (this.props.h !== value) {
1961
- this.props.h = value;
1962
- this.setUpdateType(UpdateType.Local);
2038
+ const props = this.props;
2039
+ if (props.h !== value) {
2040
+ props.h = value;
2041
+ let updateType = UpdateType.Local;
2042
+
2043
+ if (
2044
+ props.texture !== null &&
2045
+ this.stage.calculateTextureCoord === true &&
2046
+ props.textureOptions !== null
2047
+ ) {
2048
+ this.textureCoords = this.stage.renderer.getTextureCoords!(this);
2049
+ }
1963
2050
 
1964
- if (this.props.rtt === true) {
2051
+ if (props.rtt === true) {
1965
2052
  this.framebufferDimensions!.h = value;
1966
2053
  this.texture = this.stage.txManager.createTexture(
1967
2054
  'RenderTexture',
1968
2055
  this.framebufferDimensions!,
1969
2056
  );
1970
-
1971
- this.setUpdateType(UpdateType.RenderTexture);
2057
+ updateType |= UpdateType.RenderTexture;
1972
2058
  }
2059
+ this.setUpdateType(updateType);
1973
2060
  }
1974
2061
  }
1975
2062
 
@@ -2109,7 +2196,17 @@ export class CoreNode extends EventEmitter {
2109
2196
  }
2110
2197
 
2111
2198
  set autosize(value: boolean) {
2199
+ if (this.props.autosize === value) {
2200
+ return;
2201
+ }
2202
+
2112
2203
  this.props.autosize = value;
2204
+
2205
+ if (value === true && this.autosizer === null) {
2206
+ this.autosizer = new Autosizer(this);
2207
+ } else {
2208
+ this.autosizer = null;
2209
+ }
2113
2210
  }
2114
2211
 
2115
2212
  get boundsMargin(): number | [number, number, number, number] | null {
@@ -2517,12 +2614,12 @@ export class CoreNode extends EventEmitter {
2517
2614
  /**
2518
2615
  * Returns the framebuffer dimensions of the RTT parent
2519
2616
  */
2520
- get parentFramebufferDimensions(): Dimensions {
2617
+ get parentFramebufferDimensions(): Dimensions | null {
2521
2618
  if (this.rttParent !== null) {
2522
- return this.rttParent.framebufferDimensions as Dimensions;
2619
+ return this.rttParent.framebufferDimensions;
2523
2620
  }
2524
- this.rttParent = this.findParentRTTNode() as CoreNode;
2525
- return this.rttParent.framebufferDimensions as Dimensions;
2621
+ this.rttParent = this.findParentRTTNode();
2622
+ return this.rttParent ? this.rttParent.framebufferDimensions : null;
2526
2623
  }
2527
2624
 
2528
2625
  /**
@@ -2551,11 +2648,17 @@ export class CoreNode extends EventEmitter {
2551
2648
  const oldTexture = this.props.texture;
2552
2649
  if (oldTexture) {
2553
2650
  this.unloadTexture();
2651
+ if (this.autosizer !== null && value === null) {
2652
+ this.autosizer.setMode(AutosizeMode.Children); // Set to children size mode
2653
+ }
2554
2654
  }
2555
2655
 
2556
2656
  this.textureCoords = undefined;
2557
2657
  this.props.texture = value;
2558
2658
  if (value !== null) {
2659
+ if (this.autosizer !== null) {
2660
+ this.autosizer.setMode(AutosizeMode.Texture); // Set to texture size mode
2661
+ }
2559
2662
  value.setRenderableOwner(this._id, this.isRenderable);
2560
2663
  this.loadTexture();
2561
2664
  }
@@ -2609,5 +2712,71 @@ export class CoreNode extends EventEmitter {
2609
2712
  // no-op
2610
2713
  }
2611
2714
 
2715
+ /**
2716
+ * Add a texture to the current RenderOp.
2717
+ *
2718
+ * @param texture
2719
+ * @returns Assigned Texture Index of the texture in the render op
2720
+ */
2721
+ addTexture(texture: WebGlCtxTexture): number {
2722
+ const textures = this.renderOpTextures;
2723
+ const length = textures.length;
2724
+
2725
+ for (let i = 0; i < length; i++) {
2726
+ if (textures[i] === texture) {
2727
+ return i;
2728
+ }
2729
+ }
2730
+
2731
+ if (length >= 1) {
2732
+ return 0xffffffff;
2733
+ }
2734
+
2735
+ textures.push(texture);
2736
+ return length;
2737
+ }
2738
+
2739
+ draw(renderer: WebGlRenderer) {
2740
+ const { glw, options, stage } = renderer;
2741
+ const shader = this.props.shader as any;
2742
+
2743
+ stage.shManager.useShader(shader.program);
2744
+ shader.program.bindRenderOp(this);
2745
+
2746
+ // Clipping
2747
+ if (this.clippingRect.valid === true) {
2748
+ const pixelRatio = this.parentHasRenderTexture ? 1 : stage.pixelRatio;
2749
+
2750
+ const clipX = Math.round(this.clippingRect.x * pixelRatio);
2751
+ const clipWidth = Math.round(this.clippingRect.w * pixelRatio);
2752
+ const clipHeight = Math.round(this.clippingRect.h * pixelRatio);
2753
+ let clipY = Math.round(
2754
+ options.canvas.height - clipHeight - this.clippingRect.y * pixelRatio,
2755
+ );
2756
+ // if parent has render texture, we need to adjust the scissor rect
2757
+ // to be relative to the parent's framebuffer
2758
+ if (this.parentHasRenderTexture) {
2759
+ const parentFramebufferDimensions = this.parentFramebufferDimensions;
2760
+ clipY =
2761
+ parentFramebufferDimensions !== null
2762
+ ? parentFramebufferDimensions.h - this.props.h
2763
+ : 0;
2764
+ }
2765
+
2766
+ glw.setScissorTest(true);
2767
+ glw.scissor(clipX, clipY, clipWidth, clipHeight);
2768
+ } else {
2769
+ glw.setScissorTest(false);
2770
+ }
2771
+
2772
+ const quadIdx = (this.renderOpBufferIdx / 32) * 6 * 2;
2773
+ glw.drawElements(
2774
+ glw.TRIANGLES,
2775
+ 6 * this.numQuads,
2776
+ glw.UNSIGNED_SHORT,
2777
+ quadIdx,
2778
+ );
2779
+ }
2780
+
2612
2781
  //#endregion Properties
2613
2782
  }
@@ -52,7 +52,7 @@ export enum TextConstraint {
52
52
  'none' = 0,
53
53
  'width' = 1,
54
54
  'height' = 2,
55
- 'both' = 4,
55
+ 'both' = 3,
56
56
  }
57
57
 
58
58
  export class CoreTextNode extends CoreNode implements CoreTextNodeProps {
@@ -359,8 +359,7 @@ export class CoreTextNode extends CoreNode implements CoreTextNodeProps {
359
359
  }
360
360
 
361
361
  override set w(value: number) {
362
- // dont allow direct setting of width on text nodes, handled by text layout generation
363
- console.warn('Cannot directly set w on CoreTextNode');
362
+ this.maxWidth = value;
364
363
  }
365
364
 
366
365
  override get w(): number {
@@ -368,8 +367,7 @@ export class CoreTextNode extends CoreNode implements CoreTextNodeProps {
368
367
  }
369
368
 
370
369
  override set h(value: number) {
371
- // dont allow direct setting of height on text nodes, handled by text layout generation
372
- console.warn('Cannot directly set h on CoreTextNode');
370
+ this.maxHeight = value;
373
371
  }
374
372
 
375
373
  override get h(): number {
@@ -505,7 +505,7 @@ export class CoreTextureManager extends EventEmitter {
505
505
  }
506
506
 
507
507
  public hasUpdates(): boolean {
508
- return this.uploadTextureQueue.length > 0;
508
+ return this.uploadTextureQueue.length > 0 || this.priorityQueue.length > 0;
509
509
  }
510
510
 
511
511
  /**
package/src/core/Stage.ts CHANGED
@@ -69,6 +69,7 @@ export type StageOptions = Omit<
69
69
  platform: Platform | WebPlatform;
70
70
  inspector: boolean;
71
71
  maxRetryCount: number;
72
+ enableClear: boolean;
72
73
  };
73
74
 
74
75
  export type StageFpsUpdateHandler = (
@@ -471,11 +472,13 @@ export class Stage {
471
472
 
472
473
  // Process some textures asynchronously but don't block the frame
473
474
  // Use a background task to prevent frame drops
474
- this.txManager
475
- .processSome(this.options.textureProcessingTimeLimit)
476
- .catch((err) => {
477
- console.error('Error processing textures:', err);
478
- });
475
+ if (this.txManager.hasUpdates() === true) {
476
+ this.txManager
477
+ .processSome(this.options.textureProcessingTimeLimit)
478
+ .catch((err) => {
479
+ console.error('Error processing textures:', err);
480
+ });
481
+ }
479
482
 
480
483
  // Reset render operations and clear the canvas
481
484
  renderer.reset();
@@ -888,8 +891,8 @@ export class Stage {
888
891
  * @remarks
889
892
  * This method is used to cleanup orphaned textures that are no longer in use.
890
893
  */
891
- cleanup() {
892
- this.txMemManager.cleanup();
894
+ cleanup(full: boolean = false) {
895
+ this.txMemManager.cleanup(full);
893
896
  }
894
897
 
895
898
  set clearColor(value: number) {
@@ -253,7 +253,7 @@ export class TextureMemoryManager {
253
253
  texture.memUsed = 0;
254
254
  }
255
255
 
256
- cleanup() {
256
+ cleanup(full: boolean = false) {
257
257
  const critical = this.criticalCleanupRequested;
258
258
  this.lastCleanupTime = this.frameTime;
259
259
 
@@ -266,7 +266,7 @@ export class TextureMemoryManager {
266
266
 
267
267
  if (this.debugLogging === true) {
268
268
  console.log(
269
- `[TextureMemoryManager] Cleaning up textures. Critical: ${critical}.`,
269
+ `[TextureMemoryManager] Cleaning up textures. Critical: ${critical}. Full: ${full}`,
270
270
  );
271
271
  }
272
272
 
@@ -279,7 +279,7 @@ export class TextureMemoryManager {
279
279
 
280
280
  for (let i = 0; i < this.loadedTextures.length; i++) {
281
281
  // Early exit: target memory reached
282
- if (currentMemUsed < memTarget) {
282
+ if (full === false && currentMemUsed < memTarget) {
283
283
  break;
284
284
  }
285
285