@lightningjs/renderer 3.0.0-beta21 → 3.0.0-beta23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -0
- package/dist/exports/index.d.ts +1 -0
- package/dist/exports/index.js +1 -0
- package/dist/exports/index.js.map +1 -1
- package/dist/exports/platform.d.ts +7 -0
- package/dist/exports/platform.js +27 -0
- package/dist/exports/platform.js.map +1 -0
- package/dist/src/common/CommonTypes.d.ts +2 -1
- package/dist/src/core/AutosizeManager.d.ts +29 -0
- package/dist/src/core/AutosizeManager.js +169 -0
- package/dist/src/core/AutosizeManager.js.map +1 -0
- package/dist/src/core/CoreNode.js +10 -14
- package/dist/src/core/CoreNode.js.map +1 -1
- package/dist/src/core/CoreTextureManager.d.ts +0 -13
- package/dist/src/core/CoreTextureManager.js +4 -78
- package/dist/src/core/CoreTextureManager.js.map +1 -1
- package/dist/src/core/Stage.js +2 -12
- package/dist/src/core/Stage.js.map +1 -1
- package/dist/src/core/animations/CoreAnimationController.d.ts +1 -1
- package/dist/src/core/animations/CoreAnimationController.js +4 -2
- package/dist/src/core/animations/CoreAnimationController.js.map +1 -1
- package/dist/src/core/lib/collectionUtils.js +3 -2
- package/dist/src/core/lib/collectionUtils.js.map +1 -1
- package/dist/src/core/lib/utils.d.ts +0 -5
- package/dist/src/core/lib/utils.js +0 -63
- package/dist/src/core/lib/utils.js.map +1 -1
- package/dist/src/core/platforms/GlContextWrapper.d.ts +136 -0
- package/dist/src/core/platforms/GlContextWrapper.js +32 -0
- package/dist/src/core/platforms/GlContextWrapper.js.map +1 -0
- package/dist/src/core/platforms/Platform.d.ts +74 -13
- package/dist/src/core/platforms/Platform.js +18 -0
- package/dist/src/core/platforms/Platform.js.map +1 -1
- package/dist/src/core/platforms/web/WebGlContextWrapper.d.ts +776 -0
- package/dist/src/core/platforms/web/WebGlContextWrapper.js +1208 -0
- package/dist/src/core/platforms/web/WebGlContextWrapper.js.map +1 -0
- package/dist/src/core/platforms/web/WebPlatform.d.ts +13 -2
- package/dist/src/core/platforms/web/WebPlatform.js +109 -8
- package/dist/src/core/platforms/web/WebPlatform.js.map +1 -1
- package/dist/src/core/platforms/web/WebPlatformChrome50.d.ts +17 -0
- package/dist/src/core/platforms/web/WebPlatformChrome50.js +50 -0
- package/dist/src/core/platforms/web/WebPlatformChrome50.js.map +1 -0
- package/dist/src/core/platforms/web/WebPlatformLegacy.d.ts +18 -0
- package/dist/src/core/platforms/web/WebPlatformLegacy.js +99 -0
- package/dist/src/core/platforms/web/WebPlatformLegacy.js.map +1 -0
- package/dist/src/core/platforms/web/WebPlatformNext.d.ts +21 -0
- package/dist/src/core/platforms/web/WebPlatformNext.js +52 -0
- package/dist/src/core/platforms/web/WebPlatformNext.js.map +1 -0
- package/dist/src/core/platforms/web/lib/ImageWorker.d.ts +15 -0
- package/dist/src/core/platforms/web/lib/ImageWorker.js +189 -0
- package/dist/src/core/platforms/web/lib/ImageWorker.js.map +1 -0
- package/dist/src/core/platforms/web/lib/createImageBitmap.d.ts +1 -0
- package/dist/src/core/platforms/web/lib/createImageBitmap.js +27 -0
- package/dist/src/core/platforms/web/lib/createImageBitmap.js.map +1 -0
- package/dist/src/core/platforms/web/lib/textureCompression.d.ts +26 -0
- package/dist/src/core/platforms/web/lib/textureCompression.js +301 -0
- package/dist/src/core/platforms/web/lib/textureCompression.js.map +1 -0
- package/dist/src/core/platforms/web/lib/textureSvg.d.ts +7 -0
- package/dist/src/core/platforms/web/lib/textureSvg.js +51 -0
- package/dist/src/core/platforms/web/lib/textureSvg.js.map +1 -0
- package/dist/src/core/platforms/web/lib/utils.d.ts +5 -0
- package/dist/src/core/platforms/web/lib/utils.js +86 -0
- package/dist/src/core/platforms/web/lib/utils.js.map +1 -0
- package/dist/src/core/renderers/CoreRenderer.d.ts +1 -9
- package/dist/src/core/renderers/CoreRenderer.js +2 -4
- package/dist/src/core/renderers/CoreRenderer.js.map +1 -1
- package/dist/src/core/renderers/canvas/CanvasRenderer.d.ts +3 -2
- package/dist/src/core/renderers/canvas/CanvasRenderer.js +4 -3
- package/dist/src/core/renderers/canvas/CanvasRenderer.js.map +1 -1
- package/dist/src/core/renderers/webgl/SdfRenderOp.js +3 -2
- package/dist/src/core/renderers/webgl/SdfRenderOp.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlCtxRenderTexture.d.ts +2 -2
- package/dist/src/core/renderers/webgl/WebGlCtxRenderTexture.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlCtxSubTexture.d.ts +2 -2
- package/dist/src/core/renderers/webgl/WebGlCtxSubTexture.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlCtxTexture.d.ts +3 -3
- package/dist/src/core/renderers/webgl/WebGlCtxTexture.js +1 -2
- package/dist/src/core/renderers/webgl/WebGlCtxTexture.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlRenderOp.d.ts +3 -2
- package/dist/src/core/renderers/webgl/WebGlRenderOp.js +3 -1
- package/dist/src/core/renderers/webgl/WebGlRenderOp.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlRenderer.d.ts +5 -5
- package/dist/src/core/renderers/webgl/WebGlRenderer.js +7 -8
- package/dist/src/core/renderers/webgl/WebGlRenderer.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlShaderNode.d.ts +2 -2
- package/dist/src/core/renderers/webgl/WebGlShaderProgram.d.ts +2 -2
- package/dist/src/core/renderers/webgl/WebGlShaderProgram.js.map +1 -1
- package/dist/src/core/renderers/webgl/internal/RendererUtils.d.ts +4 -4
- package/dist/src/core/renderers/webgl/internal/RendererUtils.js.map +1 -1
- package/dist/src/core/renderers/webgl/internal/ShaderUtils.d.ts +3 -3
- package/dist/src/core/renderers/webgl/internal/ShaderUtils.js.map +1 -1
- package/dist/src/core/shaders/webgl/Border.js +13 -17
- package/dist/src/core/shaders/webgl/Border.js.map +1 -1
- package/dist/src/core/shaders/webgl/RoundedWithBorder.js +12 -21
- package/dist/src/core/shaders/webgl/RoundedWithBorder.js.map +1 -1
- package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js +10 -12
- package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js.map +1 -1
- package/dist/src/core/text-rendering/CanvasFont.d.ts +14 -0
- package/dist/src/core/text-rendering/CanvasFont.js +111 -0
- package/dist/src/core/text-rendering/CanvasFont.js.map +1 -0
- package/dist/src/core/text-rendering/CoreFont.d.ts +33 -0
- package/dist/src/core/text-rendering/CoreFont.js +48 -0
- package/dist/src/core/text-rendering/CoreFont.js.map +1 -0
- package/dist/src/core/text-rendering/FontManager.d.ts +11 -0
- package/dist/src/core/text-rendering/FontManager.js +42 -0
- package/dist/src/core/text-rendering/FontManager.js.map +1 -0
- package/dist/src/core/text-rendering/SdfFont.d.ts +29 -0
- package/dist/src/core/text-rendering/SdfFont.js +142 -0
- package/dist/src/core/text-rendering/SdfFont.js.map +1 -0
- package/dist/src/core/textures/ImageTexture.d.ts +24 -11
- package/dist/src/core/textures/ImageTexture.js +32 -95
- package/dist/src/core/textures/ImageTexture.js.map +1 -1
- package/dist/src/core/textures/Texture.d.ts +5 -4
- package/dist/src/core/textures/Texture.js.map +1 -1
- package/dist/src/core/utils.d.ts +1 -1
- package/dist/src/main-api/Inspector.d.ts +4 -0
- package/dist/src/main-api/Inspector.js +160 -0
- package/dist/src/main-api/Inspector.js.map +1 -1
- package/dist/src/main-api/Renderer.js +18 -21
- package/dist/src/main-api/Renderer.js.map +1 -1
- package/dist/src/utils.d.ts +0 -2
- package/dist/src/utils.js +0 -36
- package/dist/src/utils.js.map +1 -1
- package/dist/tsconfig.dist.tsbuildinfo +1 -1
- package/exports/index.ts +5 -0
- package/exports/platform.ts +31 -0
- package/package.json +3 -2
- package/src/common/CommonTypes.ts +2 -1
- package/src/core/CoreNode.ts +11 -15
- package/src/core/CoreTextureManager.ts +10 -103
- package/src/core/Stage.ts +1 -14
- package/src/core/animations/CoreAnimationController.ts +5 -2
- package/src/core/lib/collectionUtils.ts +3 -2
- package/src/core/lib/utils.ts +0 -78
- package/src/core/platforms/GlContextWrapper.ts +291 -0
- package/src/core/platforms/Platform.ts +121 -28
- package/src/core/{lib → platforms/web}/WebGlContextWrapper.ts +129 -4
- package/src/core/platforms/web/WebPlatform.ts +171 -22
- package/src/core/platforms/web/WebPlatformChrome50.ts +57 -0
- package/src/core/platforms/web/WebPlatformLegacy.ts +140 -0
- package/src/core/platforms/web/WebPlatformNext.ts +57 -0
- package/src/core/{lib → platforms/web/lib}/ImageWorker.ts +10 -74
- package/src/core/platforms/web/lib/createImageBitmap.ts +40 -0
- package/src/core/{lib → platforms/web/lib}/textureCompression.ts +19 -138
- package/src/core/{lib → platforms/web/lib}/textureSvg.ts +3 -15
- package/src/core/platforms/web/lib/utils.ts +105 -0
- package/src/core/renderers/CoreRenderer.ts +2 -11
- package/src/core/renderers/canvas/CanvasRenderer.ts +6 -4
- package/src/core/renderers/webgl/SdfRenderOp.ts +3 -2
- package/src/core/renderers/webgl/WebGlCtxRenderTexture.ts +2 -2
- package/src/core/renderers/webgl/WebGlCtxSubTexture.ts +2 -2
- package/src/core/renderers/webgl/WebGlCtxTexture.ts +3 -4
- package/src/core/renderers/webgl/WebGlRenderer.ts +12 -19
- package/src/core/renderers/webgl/WebGlShaderNode.ts +2 -2
- package/src/core/renderers/webgl/WebGlShaderProgram.ts +2 -2
- package/src/core/renderers/webgl/internal/RendererUtils.ts +4 -8
- package/src/core/renderers/webgl/internal/ShaderUtils.ts +3 -3
- package/src/core/shaders/webgl/Border.ts +13 -17
- package/src/core/shaders/webgl/RoundedWithBorder.ts +12 -21
- package/src/core/shaders/webgl/RoundedWithBorderAndShadow.ts +10 -12
- package/src/core/textures/ImageTexture.ts +42 -161
- package/src/core/textures/Texture.ts +11 -7
- package/src/main-api/Inspector.ts +215 -0
- package/src/main-api/Renderer.ts +24 -22
- package/src/utils.ts +0 -47
- package/src/core/lib/validateImageBitmap.ts +0 -87
|
@@ -23,6 +23,7 @@ import type { Dimensions } from '../../common/CommonTypes.js';
|
|
|
23
23
|
import { EventEmitter } from '../../common/EventEmitter.js';
|
|
24
24
|
import type { CoreContextTexture } from '../renderers/CoreContextTexture.js';
|
|
25
25
|
import type { Bound } from '../lib/utils.js';
|
|
26
|
+
import type { TextureError } from '../TextureError.js';
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
29
|
* Event handler for when a Texture is freed
|
|
@@ -59,7 +60,7 @@ export interface CompressedData {
|
|
|
59
60
|
/**
|
|
60
61
|
* Supported container types ('pvr' or 'ktx').
|
|
61
62
|
*/
|
|
62
|
-
type: '
|
|
63
|
+
type: 'PVR' | 'KTX' | 'ASTC';
|
|
63
64
|
|
|
64
65
|
/**
|
|
65
66
|
* The width of the compressed texture in pixels. Defaults to 0.
|
|
@@ -86,7 +87,10 @@ export interface CompressedData {
|
|
|
86
87
|
/**
|
|
87
88
|
* Event handler for when a Texture fails to load
|
|
88
89
|
*/
|
|
89
|
-
export type TextureFailedEventHandler = (
|
|
90
|
+
export type TextureFailedEventHandler = (
|
|
91
|
+
target: any,
|
|
92
|
+
error: TextureError,
|
|
93
|
+
) => void;
|
|
90
94
|
|
|
91
95
|
/**
|
|
92
96
|
* TextureData that is used to populate a CoreContextTexture
|
|
@@ -151,7 +155,7 @@ export abstract class Texture extends EventEmitter {
|
|
|
151
155
|
* `null`.
|
|
152
156
|
*/
|
|
153
157
|
private _dimensions: Dimensions | null = null;
|
|
154
|
-
private _error:
|
|
158
|
+
private _error: TextureError | null = null;
|
|
155
159
|
|
|
156
160
|
// aggregate state
|
|
157
161
|
public state: TextureState = 'initial';
|
|
@@ -205,7 +209,7 @@ export abstract class Texture extends EventEmitter {
|
|
|
205
209
|
return this._dimensions;
|
|
206
210
|
}
|
|
207
211
|
|
|
208
|
-
get error():
|
|
212
|
+
get error(): TextureError | null {
|
|
209
213
|
return this._error;
|
|
210
214
|
}
|
|
211
215
|
|
|
@@ -393,13 +397,13 @@ export abstract class Texture extends EventEmitter {
|
|
|
393
397
|
|
|
394
398
|
public setState(
|
|
395
399
|
state: TextureState,
|
|
396
|
-
errorOrDimensions?:
|
|
400
|
+
errorOrDimensions?: TextureError | Dimensions,
|
|
397
401
|
): void {
|
|
398
402
|
if (this.state === state) {
|
|
399
403
|
return;
|
|
400
404
|
}
|
|
401
405
|
|
|
402
|
-
let payload:
|
|
406
|
+
let payload: TextureError | Dimensions | null = null;
|
|
403
407
|
if (state === 'loaded') {
|
|
404
408
|
if (
|
|
405
409
|
errorOrDimensions !== undefined &&
|
|
@@ -413,7 +417,7 @@ export abstract class Texture extends EventEmitter {
|
|
|
413
417
|
|
|
414
418
|
payload = this._dimensions;
|
|
415
419
|
} else if (state === 'failed') {
|
|
416
|
-
this._error = errorOrDimensions as
|
|
420
|
+
this._error = errorOrDimensions as TextureError;
|
|
417
421
|
payload = this._error;
|
|
418
422
|
|
|
419
423
|
// increment the retry count for the texture
|
|
@@ -11,6 +11,8 @@ import type {
|
|
|
11
11
|
} from '../common/IAnimationController.js';
|
|
12
12
|
import { isProductionEnvironment } from '../utils.js';
|
|
13
13
|
import { CoreTextNode, type CoreTextNodeProps } from '../core/CoreTextNode.js';
|
|
14
|
+
import type { Texture } from '../core/textures/Texture.js';
|
|
15
|
+
import { TextureType } from '../core/textures/Texture.js';
|
|
14
16
|
|
|
15
17
|
/**
|
|
16
18
|
* Inspector Options
|
|
@@ -204,6 +206,22 @@ const gradientColorPropertyMap = [
|
|
|
204
206
|
'colorBr',
|
|
205
207
|
];
|
|
206
208
|
|
|
209
|
+
const textureTypeNames: Record<number, string> = {
|
|
210
|
+
[TextureType.generic]: 'generic',
|
|
211
|
+
[TextureType.color]: 'color',
|
|
212
|
+
[TextureType.image]: 'image',
|
|
213
|
+
[TextureType.noise]: 'noise',
|
|
214
|
+
[TextureType.renderToTexture]: 'renderToTexture',
|
|
215
|
+
[TextureType.subTexture]: 'subTexture',
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
interface TextureMetrics {
|
|
219
|
+
previousState: string;
|
|
220
|
+
loadedCount: number;
|
|
221
|
+
failedCount: number;
|
|
222
|
+
freedCount: number;
|
|
223
|
+
}
|
|
224
|
+
|
|
207
225
|
const knownProperties = new Set<string>([
|
|
208
226
|
...Object.keys(stylePropertyMap),
|
|
209
227
|
...Object.keys(domPropertyMap),
|
|
@@ -223,6 +241,7 @@ export class Inspector {
|
|
|
223
241
|
private width = 1920;
|
|
224
242
|
private scaleX = 1;
|
|
225
243
|
private scaleY = 1;
|
|
244
|
+
private textureMetrics = new Map<Texture, TextureMetrics>();
|
|
226
245
|
|
|
227
246
|
// Performance monitoring for frequent setter calls
|
|
228
247
|
private static setterCallCount = new Map<
|
|
@@ -788,6 +807,94 @@ export class Inspector {
|
|
|
788
807
|
node: CoreNode | CoreTextNode,
|
|
789
808
|
div: HTMLElement,
|
|
790
809
|
): CoreNode | CoreTextNode {
|
|
810
|
+
// Store texture event listeners for cleanup
|
|
811
|
+
const textureListeners = new Map<
|
|
812
|
+
Texture,
|
|
813
|
+
{
|
|
814
|
+
onLoaded: () => void;
|
|
815
|
+
onFailed: () => void;
|
|
816
|
+
onFreed: () => void;
|
|
817
|
+
}
|
|
818
|
+
>();
|
|
819
|
+
|
|
820
|
+
const coreNodeListeners = new Map<
|
|
821
|
+
CoreNode,
|
|
822
|
+
{
|
|
823
|
+
onLoaded: () => void;
|
|
824
|
+
}
|
|
825
|
+
>();
|
|
826
|
+
|
|
827
|
+
const setupCoreNodeListeners = (coreNode: CoreNode) => {
|
|
828
|
+
const onLoaded = () => {
|
|
829
|
+
this.updateTextNodeDimensions(div, coreNode as CoreTextNode);
|
|
830
|
+
};
|
|
831
|
+
coreNode.on('loaded', onLoaded);
|
|
832
|
+
coreNodeListeners.set(coreNode, { onLoaded });
|
|
833
|
+
};
|
|
834
|
+
|
|
835
|
+
// Helper function to setup texture event listeners
|
|
836
|
+
const setupTextureListeners = (texture: Texture | null) => {
|
|
837
|
+
// Clean up existing listeners first
|
|
838
|
+
textureListeners.forEach((listeners, oldTexture) => {
|
|
839
|
+
oldTexture.off('loaded', listeners.onLoaded);
|
|
840
|
+
oldTexture.off('failed', listeners.onFailed);
|
|
841
|
+
oldTexture.off('freed', listeners.onFreed);
|
|
842
|
+
});
|
|
843
|
+
textureListeners.clear();
|
|
844
|
+
|
|
845
|
+
// Setup new listeners if texture exists
|
|
846
|
+
if (texture) {
|
|
847
|
+
// Initialize metrics if not exists
|
|
848
|
+
if (!this.textureMetrics.has(texture)) {
|
|
849
|
+
this.textureMetrics.set(texture, {
|
|
850
|
+
previousState: texture.state,
|
|
851
|
+
loadedCount: 0,
|
|
852
|
+
failedCount: 0,
|
|
853
|
+
freedCount: 0,
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
const onLoaded = () => {
|
|
858
|
+
const metrics = this.textureMetrics.get(texture);
|
|
859
|
+
if (metrics) {
|
|
860
|
+
metrics.previousState =
|
|
861
|
+
metrics.previousState !== texture.state
|
|
862
|
+
? metrics.previousState
|
|
863
|
+
: 'loading';
|
|
864
|
+
metrics.loadedCount++;
|
|
865
|
+
}
|
|
866
|
+
this.updateTextureAttributes(div, texture);
|
|
867
|
+
};
|
|
868
|
+
const onFailed = () => {
|
|
869
|
+
const metrics = this.textureMetrics.get(texture);
|
|
870
|
+
if (metrics) {
|
|
871
|
+
metrics.previousState =
|
|
872
|
+
metrics.previousState !== texture.state
|
|
873
|
+
? metrics.previousState
|
|
874
|
+
: 'loading';
|
|
875
|
+
metrics.failedCount++;
|
|
876
|
+
}
|
|
877
|
+
this.updateTextureAttributes(div, texture);
|
|
878
|
+
};
|
|
879
|
+
const onFreed = () => {
|
|
880
|
+
const metrics = this.textureMetrics.get(texture);
|
|
881
|
+
if (metrics) {
|
|
882
|
+
metrics.previousState =
|
|
883
|
+
metrics.previousState !== texture.state
|
|
884
|
+
? metrics.previousState
|
|
885
|
+
: texture.state;
|
|
886
|
+
metrics.freedCount++;
|
|
887
|
+
}
|
|
888
|
+
this.updateTextureAttributes(div, texture);
|
|
889
|
+
};
|
|
890
|
+
|
|
891
|
+
texture.on('loaded', onLoaded);
|
|
892
|
+
texture.on('failed', onFailed);
|
|
893
|
+
texture.on('freed', onFreed);
|
|
894
|
+
|
|
895
|
+
textureListeners.set(texture, { onLoaded, onFailed, onFreed });
|
|
896
|
+
}
|
|
897
|
+
};
|
|
791
898
|
// Define traps for each property in knownProperties
|
|
792
899
|
knownProperties.forEach((property) => {
|
|
793
900
|
let originalProp = Object.getOwnPropertyDescriptor(node, property);
|
|
@@ -802,6 +909,10 @@ export class Inspector {
|
|
|
802
909
|
return;
|
|
803
910
|
}
|
|
804
911
|
|
|
912
|
+
if (property === 'text') {
|
|
913
|
+
setupCoreNodeListeners(node);
|
|
914
|
+
}
|
|
915
|
+
|
|
805
916
|
Object.defineProperty(node, property, {
|
|
806
917
|
get() {
|
|
807
918
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
@@ -818,6 +929,15 @@ export class Inspector {
|
|
|
818
929
|
value,
|
|
819
930
|
node.props,
|
|
820
931
|
);
|
|
932
|
+
|
|
933
|
+
// Setup texture event listeners if this is a texture property
|
|
934
|
+
if (property === 'texture') {
|
|
935
|
+
const textureValue =
|
|
936
|
+
value && typeof value === 'object' && 'state' in value
|
|
937
|
+
? (value as Texture)
|
|
938
|
+
: null;
|
|
939
|
+
setupTextureListeners(textureValue);
|
|
940
|
+
}
|
|
821
941
|
},
|
|
822
942
|
configurable: true,
|
|
823
943
|
enumerable: true,
|
|
@@ -827,6 +947,21 @@ export class Inspector {
|
|
|
827
947
|
const originalDestroy = node.destroy;
|
|
828
948
|
Object.defineProperty(node, 'destroy', {
|
|
829
949
|
value: () => {
|
|
950
|
+
// Clean up texture event listeners and metrics
|
|
951
|
+
textureListeners.forEach((listeners, texture) => {
|
|
952
|
+
texture.off('loaded', listeners.onLoaded);
|
|
953
|
+
texture.off('failed', listeners.onFailed);
|
|
954
|
+
texture.off('freed', listeners.onFreed);
|
|
955
|
+
// Clean up metrics for this texture
|
|
956
|
+
this.textureMetrics.delete(texture);
|
|
957
|
+
});
|
|
958
|
+
textureListeners.clear();
|
|
959
|
+
|
|
960
|
+
coreNodeListeners.forEach((listeners, coreNode) => {
|
|
961
|
+
coreNode.off('loaded', listeners.onLoaded);
|
|
962
|
+
});
|
|
963
|
+
coreNodeListeners.clear();
|
|
964
|
+
|
|
830
965
|
this.destroyNode(node.id);
|
|
831
966
|
originalDestroy.call(node);
|
|
832
967
|
},
|
|
@@ -856,6 +991,86 @@ export class Inspector {
|
|
|
856
991
|
return node;
|
|
857
992
|
}
|
|
858
993
|
|
|
994
|
+
updateTextNodeDimensions(div: HTMLElement, node: CoreTextNode) {
|
|
995
|
+
const textMetrics = node.renderInfo;
|
|
996
|
+
if (textMetrics) {
|
|
997
|
+
div.style.width = `${textMetrics.width}px`;
|
|
998
|
+
div.style.height = `${textMetrics.height}px`;
|
|
999
|
+
} else {
|
|
1000
|
+
div.style.removeProperty('width');
|
|
1001
|
+
div.style.removeProperty('height');
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
updateTextureAttributes(div: HTMLElement, texture: Texture) {
|
|
1006
|
+
// Update texture state
|
|
1007
|
+
div.setAttribute('data-texture-state', texture.state);
|
|
1008
|
+
|
|
1009
|
+
// Update texture type
|
|
1010
|
+
div.setAttribute(
|
|
1011
|
+
'data-texture-type',
|
|
1012
|
+
textureTypeNames[texture.type] || 'unknown',
|
|
1013
|
+
);
|
|
1014
|
+
|
|
1015
|
+
// Update texture dimensions if available
|
|
1016
|
+
if (texture.dimensions) {
|
|
1017
|
+
div.setAttribute('data-texture-width', String(texture.dimensions.w));
|
|
1018
|
+
div.setAttribute('data-texture-height', String(texture.dimensions.h));
|
|
1019
|
+
} else {
|
|
1020
|
+
div.removeAttribute('data-texture-width');
|
|
1021
|
+
div.removeAttribute('data-texture-height');
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
// Update renderable owners count
|
|
1025
|
+
div.setAttribute(
|
|
1026
|
+
'data-texture-owners',
|
|
1027
|
+
String(texture.renderableOwners.length),
|
|
1028
|
+
);
|
|
1029
|
+
|
|
1030
|
+
// Update retry count
|
|
1031
|
+
div.setAttribute('data-texture-retry-count', String(texture.retryCount));
|
|
1032
|
+
|
|
1033
|
+
// Update max retry count if available
|
|
1034
|
+
if (texture.maxRetryCount !== null) {
|
|
1035
|
+
div.setAttribute(
|
|
1036
|
+
'data-texture-max-retry-count',
|
|
1037
|
+
String(texture.maxRetryCount),
|
|
1038
|
+
);
|
|
1039
|
+
} else {
|
|
1040
|
+
div.removeAttribute('data-texture-max-retry-count');
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
// Update metrics if available
|
|
1044
|
+
const metrics = this.textureMetrics.get(texture);
|
|
1045
|
+
if (metrics) {
|
|
1046
|
+
div.setAttribute('data-texture-previous-state', metrics.previousState);
|
|
1047
|
+
div.setAttribute(
|
|
1048
|
+
'data-texture-loaded-count',
|
|
1049
|
+
String(metrics.loadedCount),
|
|
1050
|
+
);
|
|
1051
|
+
div.setAttribute(
|
|
1052
|
+
'data-texture-failed-count',
|
|
1053
|
+
String(metrics.failedCount),
|
|
1054
|
+
);
|
|
1055
|
+
div.setAttribute('data-texture-freed-count', String(metrics.freedCount));
|
|
1056
|
+
} else {
|
|
1057
|
+
div.removeAttribute('data-texture-previous-state');
|
|
1058
|
+
div.removeAttribute('data-texture-loaded-count');
|
|
1059
|
+
div.removeAttribute('data-texture-failed-count');
|
|
1060
|
+
div.removeAttribute('data-texture-freed-count');
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
// Update error information if present
|
|
1064
|
+
if (texture.error) {
|
|
1065
|
+
div.setAttribute(
|
|
1066
|
+
'data-texture-error',
|
|
1067
|
+
texture.error.code || texture.error.message,
|
|
1068
|
+
);
|
|
1069
|
+
} else {
|
|
1070
|
+
div.removeAttribute('data-texture-error');
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
|
|
859
1074
|
public destroy() {
|
|
860
1075
|
// Stop animation stats timer
|
|
861
1076
|
this.stopAnimationStatsTimer();
|
package/src/main-api/Renderer.ts
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
import type { ExtractProps, TextureMap } from '../core/CoreTextureManager.js';
|
|
21
21
|
import { EventEmitter } from '../common/EventEmitter.js';
|
|
22
|
-
import { isProductionEnvironment } from '../utils.js';
|
|
22
|
+
import { assertTruthy, isProductionEnvironment } from '../utils.js';
|
|
23
23
|
import { Stage, type StageOptions } from '../core/Stage.js';
|
|
24
24
|
import { CoreNode, type CoreNodeProps } from '../core/CoreNode.js';
|
|
25
25
|
import { type CoreTextNodeProps } from '../core/CoreTextNode.js';
|
|
@@ -550,7 +550,7 @@ export class RendererMain extends EventEmitter {
|
|
|
550
550
|
textureProcessingTimeLimit: settings.textureProcessingTimeLimit || 42,
|
|
551
551
|
canvas: settings.canvas,
|
|
552
552
|
createImageBitmapSupport: settings.createImageBitmapSupport || 'full',
|
|
553
|
-
platform: settings.platform ||
|
|
553
|
+
platform: settings.platform || WebPlatform,
|
|
554
554
|
maxRetryCount: settings.maxRetryCount ?? 5,
|
|
555
555
|
};
|
|
556
556
|
|
|
@@ -562,29 +562,28 @@ export class RendererMain extends EventEmitter {
|
|
|
562
562
|
inspector,
|
|
563
563
|
} = settings as RendererMainSettings;
|
|
564
564
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
settings.platform.prototype instanceof Platform === true
|
|
570
|
-
) {
|
|
571
|
-
// @ts-ignore - if Platform is a valid class, it will be used
|
|
572
|
-
platform = new settings.platform();
|
|
573
|
-
} else {
|
|
574
|
-
platform = new WebPlatform();
|
|
575
|
-
}
|
|
565
|
+
assertTruthy(
|
|
566
|
+
settings.platform,
|
|
567
|
+
'A platform implementation must be provided in settings.platform',
|
|
568
|
+
);
|
|
576
569
|
|
|
577
|
-
|
|
570
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
|
|
571
|
+
const platform = new (settings.platform as any)({
|
|
572
|
+
numImageWorkers: settings.numImageWorkers,
|
|
573
|
+
forceWebGL2: settings.forceWebGL2,
|
|
574
|
+
canvas: settings.canvas,
|
|
575
|
+
});
|
|
578
576
|
|
|
579
577
|
const deviceLogicalWidth = appWidth * deviceLogicalPixelRatio;
|
|
580
578
|
const deviceLogicalHeight = appHeight * deviceLogicalPixelRatio;
|
|
581
579
|
|
|
582
|
-
|
|
583
|
-
canvas
|
|
584
|
-
canvas.
|
|
580
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unsafe-member-access
|
|
581
|
+
this.canvas = platform.canvas! as HTMLCanvasElement;
|
|
582
|
+
this.canvas.width = deviceLogicalWidth * devicePhysicalPixelRatio;
|
|
583
|
+
this.canvas.height = deviceLogicalHeight * devicePhysicalPixelRatio;
|
|
585
584
|
|
|
586
|
-
canvas.style.width = `${deviceLogicalWidth}px`;
|
|
587
|
-
canvas.style.height = `${deviceLogicalHeight}px`;
|
|
585
|
+
this.canvas.style.width = `${deviceLogicalWidth}px`;
|
|
586
|
+
this.canvas.style.height = `${deviceLogicalHeight}px`;
|
|
588
587
|
|
|
589
588
|
// Initialize the stage
|
|
590
589
|
this.stage = new Stage({
|
|
@@ -629,8 +628,8 @@ export class RendererMain extends EventEmitter {
|
|
|
629
628
|
throw new Error('Could not find target element');
|
|
630
629
|
}
|
|
631
630
|
|
|
632
|
-
targetEl.appendChild(canvas);
|
|
633
|
-
} else if (settings.canvas !== canvas) {
|
|
631
|
+
targetEl.appendChild(this.canvas);
|
|
632
|
+
} else if (settings.canvas !== this.canvas) {
|
|
634
633
|
throw new Error(
|
|
635
634
|
'New canvas element could not be appended to undefined target',
|
|
636
635
|
);
|
|
@@ -638,7 +637,10 @@ export class RendererMain extends EventEmitter {
|
|
|
638
637
|
|
|
639
638
|
// Initialize inspector (if enabled)
|
|
640
639
|
if (inspector && isProductionEnvironment === false) {
|
|
641
|
-
this.inspector = new inspector(
|
|
640
|
+
this.inspector = new inspector(
|
|
641
|
+
this.canvas,
|
|
642
|
+
settings as RendererMainSettings,
|
|
643
|
+
);
|
|
642
644
|
}
|
|
643
645
|
}
|
|
644
646
|
|
package/src/utils.ts
CHANGED
|
@@ -17,53 +17,6 @@
|
|
|
17
17
|
* limitations under the License.
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import type { ContextSpy } from './core/lib/ContextSpy.js';
|
|
21
|
-
|
|
22
|
-
export function createWebGLContext(
|
|
23
|
-
canvas: HTMLCanvasElement | OffscreenCanvas,
|
|
24
|
-
forceWebGL2 = false,
|
|
25
|
-
contextSpy: ContextSpy | null,
|
|
26
|
-
): WebGLRenderingContext {
|
|
27
|
-
const config: WebGLContextAttributes = {
|
|
28
|
-
alpha: true,
|
|
29
|
-
antialias: false,
|
|
30
|
-
depth: false,
|
|
31
|
-
stencil: true,
|
|
32
|
-
desynchronized: false,
|
|
33
|
-
// Disabled because it prevents Visual Regression Tests from working
|
|
34
|
-
// failIfMajorPerformanceCaveat: true,
|
|
35
|
-
powerPreference: 'high-performance',
|
|
36
|
-
premultipliedAlpha: true,
|
|
37
|
-
preserveDrawingBuffer: false,
|
|
38
|
-
};
|
|
39
|
-
const gl =
|
|
40
|
-
// TODO: Remove this assertion once this issue is fixed in TypeScript
|
|
41
|
-
// https://github.com/microsoft/TypeScript/issues/53614
|
|
42
|
-
(canvas.getContext(forceWebGL2 ? 'webgl2' : 'webgl', config) ||
|
|
43
|
-
canvas.getContext(
|
|
44
|
-
'experimental-webgl' as 'webgl',
|
|
45
|
-
config,
|
|
46
|
-
)) as unknown as WebGLRenderingContext | null;
|
|
47
|
-
if (!gl) {
|
|
48
|
-
throw new Error('Unable to create WebGL context');
|
|
49
|
-
}
|
|
50
|
-
if (contextSpy) {
|
|
51
|
-
// Proxy the GL context to log all GL calls
|
|
52
|
-
return new Proxy(gl, {
|
|
53
|
-
get(target, prop) {
|
|
54
|
-
const value = target[prop as never] as unknown;
|
|
55
|
-
if (typeof value === 'function') {
|
|
56
|
-
contextSpy.increment(String(prop));
|
|
57
|
-
return value.bind(target);
|
|
58
|
-
}
|
|
59
|
-
return value;
|
|
60
|
-
},
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return gl;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
20
|
/**
|
|
68
21
|
* Checks if we're in a development environment or not.
|
|
69
22
|
*
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import type { Platform } from '../platforms/Platform.js';
|
|
2
|
-
|
|
3
|
-
export interface CreateImageBitmapSupport {
|
|
4
|
-
basic: boolean; // Supports createImageBitmap(image)
|
|
5
|
-
options: boolean; // Supports createImageBitmap(image, options)
|
|
6
|
-
full: boolean; // Supports createImageBitmap(image, sx, sy, sw, sh, options)
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export async function validateCreateImageBitmap(
|
|
10
|
-
platform: Platform,
|
|
11
|
-
): Promise<CreateImageBitmapSupport> {
|
|
12
|
-
// Test if createImageBitmap is supported using a simple 1x1 PNG image
|
|
13
|
-
// prettier-ignore
|
|
14
|
-
const pngBinaryData = new Uint8Array([
|
|
15
|
-
0x89, 0x50, 0x4e, 0x47,
|
|
16
|
-
0x0d, 0x0a, 0x1a, 0x0a, // PNG signature
|
|
17
|
-
0x00, 0x00, 0x00, 0x0d, // IHDR chunk length
|
|
18
|
-
0x49, 0x48, 0x44, 0x52, // "IHDR" chunk type
|
|
19
|
-
0x00, 0x00, 0x00, 0x01, // Width: 1
|
|
20
|
-
0x00, 0x00, 0x00, 0x01, // Height: 1
|
|
21
|
-
0x01, // Bit depth: 1
|
|
22
|
-
0x03, // Color type: Indexed
|
|
23
|
-
0x00, // Compression method: Deflate
|
|
24
|
-
0x00, // Filter method: None
|
|
25
|
-
0x00, // Interlace method: None
|
|
26
|
-
0x25, 0xdb, 0x56, 0xca, // CRC for IHDR
|
|
27
|
-
0x00, 0x00, 0x00, 0x03, // PLTE chunk length
|
|
28
|
-
0x50, 0x4c, 0x54, 0x45, // "PLTE" chunk type
|
|
29
|
-
0x00, 0x00, 0x00, // Palette entry: Black
|
|
30
|
-
0xa7, 0x7a, 0x3d, 0xda, // CRC for PLTE
|
|
31
|
-
0x00, 0x00, 0x00, 0x01, // tRNS chunk length
|
|
32
|
-
0x74, 0x52, 0x4e, 0x53, // "tRNS" chunk type
|
|
33
|
-
0x00, // Transparency for black: Fully transparent
|
|
34
|
-
0x40, 0xe6, 0xd8, 0x66, // CRC for tRNS
|
|
35
|
-
0x00, 0x00, 0x00, 0x0a, // IDAT chunk length
|
|
36
|
-
0x49, 0x44, 0x41, 0x54, // "IDAT" chunk type
|
|
37
|
-
0x08, 0xd7, // Deflate header
|
|
38
|
-
0x63, 0x60, 0x00, 0x00,
|
|
39
|
-
0x00, 0x02, 0x00, 0x01, // Zlib-compressed data
|
|
40
|
-
0xe2, 0x21, 0xbc, 0x33, // CRC for IDAT
|
|
41
|
-
0x00, 0x00, 0x00, 0x00, // IEND chunk length
|
|
42
|
-
0x49, 0x45, 0x4e, 0x44, // "IEND" chunk type
|
|
43
|
-
0xae, 0x42, 0x60, 0x82, // CRC for IEND
|
|
44
|
-
]);
|
|
45
|
-
|
|
46
|
-
const support: CreateImageBitmapSupport = {
|
|
47
|
-
basic: false,
|
|
48
|
-
options: false,
|
|
49
|
-
full: false,
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
// Test basic createImageBitmap support
|
|
53
|
-
const blob = new Blob([pngBinaryData], { type: 'image/png' });
|
|
54
|
-
const bitmap = await platform.createImageBitmap(blob);
|
|
55
|
-
bitmap.close?.();
|
|
56
|
-
support.basic = true;
|
|
57
|
-
|
|
58
|
-
// Test createImageBitmap with options support
|
|
59
|
-
try {
|
|
60
|
-
const options = { premultiplyAlpha: 'none' as const };
|
|
61
|
-
const bitmapWithOptions = await platform.createImageBitmap(blob, options);
|
|
62
|
-
bitmapWithOptions.close?.();
|
|
63
|
-
support.options = true;
|
|
64
|
-
} catch (e) {
|
|
65
|
-
/* ignore */
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Test createImageBitmap with full options support
|
|
69
|
-
try {
|
|
70
|
-
const bitmapWithFullOptions = await platform.createImageBitmap(
|
|
71
|
-
blob,
|
|
72
|
-
0,
|
|
73
|
-
0,
|
|
74
|
-
1,
|
|
75
|
-
1,
|
|
76
|
-
{
|
|
77
|
-
premultiplyAlpha: 'none',
|
|
78
|
-
},
|
|
79
|
-
);
|
|
80
|
-
bitmapWithFullOptions.close?.();
|
|
81
|
-
support.full = true;
|
|
82
|
-
} catch (e) {
|
|
83
|
-
/* ignore */
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return support;
|
|
87
|
-
}
|