@lightningjs/renderer 2.9.0 → 2.9.1

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 (218) hide show
  1. package/COPYING +1 -0
  2. package/LICENSE +202 -202
  3. package/NOTICE +3 -3
  4. package/README.md +147 -147
  5. package/dist/src/core/CoreNode.js +1 -1
  6. package/dist/src/core/CoreNode.js.map +1 -1
  7. package/dist/src/core/renderers/webgl/shaders/DefaultShader.js +45 -45
  8. package/dist/src/core/renderers/webgl/shaders/DefaultShaderBatched.js +61 -61
  9. package/dist/src/core/renderers/webgl/shaders/DynamicShader.js +93 -93
  10. package/dist/src/core/renderers/webgl/shaders/RoundedRectangle.js +63 -63
  11. package/dist/src/core/renderers/webgl/shaders/SdfShader.js +62 -62
  12. package/dist/src/core/renderers/webgl/shaders/effects/BorderBottomEffect.js +15 -15
  13. package/dist/src/core/renderers/webgl/shaders/effects/BorderEffect.js +6 -6
  14. package/dist/src/core/renderers/webgl/shaders/effects/BorderLeftEffect.js +15 -15
  15. package/dist/src/core/renderers/webgl/shaders/effects/BorderRightEffect.js +15 -15
  16. package/dist/src/core/renderers/webgl/shaders/effects/BorderTopEffect.js +15 -15
  17. package/dist/src/core/renderers/webgl/shaders/effects/FadeOutEffect.js +42 -42
  18. package/dist/src/core/renderers/webgl/shaders/effects/GlitchEffect.js +44 -44
  19. package/dist/src/core/renderers/webgl/shaders/effects/GrayscaleEffect.js +3 -3
  20. package/dist/src/core/renderers/webgl/shaders/effects/HolePunchEffect.js +22 -22
  21. package/dist/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.js +28 -28
  22. package/dist/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.js +10 -10
  23. package/dist/src/core/renderers/webgl/shaders/effects/RadialProgressEffect.js +37 -37
  24. package/dist/src/core/renderers/webgl/shaders/effects/RadiusEffect.js +19 -19
  25. package/dist/src/core/text-rendering/font-face-types/WebTrFontFace.js +7 -3
  26. package/dist/src/core/text-rendering/font-face-types/WebTrFontFace.js.map +1 -1
  27. package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.js +7 -0
  28. package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.js.map +1 -1
  29. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.js +5 -1
  30. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.js.map +1 -1
  31. package/dist/src/core/textures/ImageTexture.js +1 -1
  32. package/dist/src/core/textures/SubTexture.d.ts +1 -0
  33. package/dist/src/core/textures/SubTexture.js +7 -0
  34. package/dist/src/core/textures/SubTexture.js.map +1 -1
  35. package/dist/src/core/textures/Texture.d.ts +9 -0
  36. package/dist/src/core/textures/Texture.js +23 -13
  37. package/dist/src/core/textures/Texture.js.map +1 -1
  38. package/dist/tsconfig.dist.tsbuildinfo +1 -1
  39. package/exports/canvas.ts +39 -39
  40. package/exports/index.ts +89 -89
  41. package/exports/inspector.ts +24 -24
  42. package/exports/utils.ts +44 -44
  43. package/exports/webgl.ts +38 -38
  44. package/package.json +1 -1
  45. package/scripts/please-use-pnpm.js +13 -13
  46. package/src/common/CommonTypes.ts +139 -139
  47. package/src/common/EventEmitter.ts +77 -77
  48. package/src/common/IAnimationController.ts +92 -92
  49. package/src/common/IEventEmitter.ts +28 -28
  50. package/src/core/CoreNode.test.ts +199 -199
  51. package/src/core/CoreNode.ts +2335 -2335
  52. package/src/core/CoreShaderManager.ts +292 -292
  53. package/src/core/CoreTextNode.ts +455 -455
  54. package/src/core/CoreTextureManager.ts +548 -548
  55. package/src/core/Stage.ts +700 -700
  56. package/src/core/TextureMemoryManager.ts +277 -277
  57. package/src/core/animations/AnimationManager.ts +38 -38
  58. package/src/core/animations/CoreAnimation.ts +340 -340
  59. package/src/core/animations/CoreAnimationController.ts +157 -157
  60. package/src/core/lib/ContextSpy.ts +41 -41
  61. package/src/core/lib/ImageWorker.ts +270 -270
  62. package/src/core/lib/Matrix3d.ts +244 -244
  63. package/src/core/lib/RenderCoords.ts +86 -86
  64. package/src/core/lib/WebGlContextWrapper.ts +1322 -1322
  65. package/src/core/lib/textureCompression.ts +152 -152
  66. package/src/core/lib/textureSvg.ts +78 -78
  67. package/src/core/lib/utils.ts +306 -306
  68. package/src/core/platform.ts +61 -61
  69. package/src/core/renderers/CoreContextTexture.ts +43 -43
  70. package/src/core/renderers/CoreRenderOp.ts +22 -22
  71. package/src/core/renderers/CoreRenderer.ts +114 -114
  72. package/src/core/renderers/CoreShader.ts +41 -41
  73. package/src/core/renderers/canvas/CanvasCoreRenderer.ts +364 -364
  74. package/src/core/renderers/canvas/CanvasCoreTexture.ts +150 -150
  75. package/src/core/renderers/canvas/internal/C2DShaderUtils.ts +231 -231
  76. package/src/core/renderers/canvas/internal/ColorUtils.ts +69 -69
  77. package/src/core/renderers/canvas/shaders/UnsupportedShader.ts +48 -48
  78. package/src/core/renderers/webgl/WebGlCoreCtxRenderTexture.ts +79 -79
  79. package/src/core/renderers/webgl/WebGlCoreCtxSubTexture.ts +50 -50
  80. package/src/core/renderers/webgl/WebGlCoreCtxTexture.ts +298 -298
  81. package/src/core/renderers/webgl/WebGlCoreRenderOp.ts +125 -125
  82. package/src/core/renderers/webgl/WebGlCoreRenderer.ts +805 -805
  83. package/src/core/renderers/webgl/WebGlCoreShader.ts +362 -362
  84. package/src/core/renderers/webgl/internal/BufferCollection.ts +54 -54
  85. package/src/core/renderers/webgl/internal/RendererUtils.ts +155 -155
  86. package/src/core/renderers/webgl/internal/ShaderUtils.ts +143 -143
  87. package/src/core/renderers/webgl/internal/WebGlUtils.ts +35 -35
  88. package/src/core/renderers/webgl/shaders/DefaultShader.ts +93 -93
  89. package/src/core/renderers/webgl/shaders/DefaultShaderBatched.ts +132 -132
  90. package/src/core/renderers/webgl/shaders/DynamicShader.ts +580 -580
  91. package/src/core/renderers/webgl/shaders/RoundedRectangle.ts +167 -167
  92. package/src/core/renderers/webgl/shaders/SdfShader.ts +204 -204
  93. package/src/core/renderers/webgl/shaders/effects/BorderBottomEffect.ts +101 -101
  94. package/src/core/renderers/webgl/shaders/effects/BorderEffect.ts +87 -87
  95. package/src/core/renderers/webgl/shaders/effects/BorderLeftEffect.ts +101 -101
  96. package/src/core/renderers/webgl/shaders/effects/BorderRightEffect.ts +101 -101
  97. package/src/core/renderers/webgl/shaders/effects/BorderTopEffect.ts +101 -101
  98. package/src/core/renderers/webgl/shaders/effects/EffectUtils.ts +159 -159
  99. package/src/core/renderers/webgl/shaders/effects/FadeOutEffect.ts +127 -127
  100. package/src/core/renderers/webgl/shaders/effects/GlitchEffect.ts +148 -148
  101. package/src/core/renderers/webgl/shaders/effects/GrayscaleEffect.ts +67 -67
  102. package/src/core/renderers/webgl/shaders/effects/HolePunchEffect.ts +157 -157
  103. package/src/core/renderers/webgl/shaders/effects/LinearGradientEffect.ts +171 -171
  104. package/src/core/renderers/webgl/shaders/effects/RadialGradientEffect.ts +168 -168
  105. package/src/core/renderers/webgl/shaders/effects/RadialProgressEffect.ts +187 -187
  106. package/src/core/renderers/webgl/shaders/effects/RadiusEffect.ts +110 -110
  107. package/src/core/renderers/webgl/shaders/effects/ShaderEffect.ts +196 -196
  108. package/src/core/text-rendering/TextRenderingUtils.ts +36 -36
  109. package/src/core/text-rendering/TextTextureRendererUtils.ts +263 -263
  110. package/src/core/text-rendering/TrFontManager.ts +183 -183
  111. package/src/core/text-rendering/font-face-types/SdfTrFontFace/SdfTrFontFace.ts +176 -176
  112. package/src/core/text-rendering/font-face-types/SdfTrFontFace/internal/FontShaper.ts +139 -139
  113. package/src/core/text-rendering/font-face-types/SdfTrFontFace/internal/SdfFontShaper.test.ts +173 -173
  114. package/src/core/text-rendering/font-face-types/SdfTrFontFace/internal/SdfFontShaper.ts +171 -171
  115. package/src/core/text-rendering/font-face-types/TrFontFace.ts +187 -187
  116. package/src/core/text-rendering/font-face-types/WebTrFontFace.ts +94 -89
  117. package/src/core/text-rendering/renderers/CanvasTextRenderer.ts +509 -509
  118. package/src/core/text-rendering/renderers/LightningTextTextureRenderer.ts +808 -798
  119. package/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.ts +853 -853
  120. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/PeekableGenerator.test.ts +48 -48
  121. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/PeekableGenerator.ts +66 -66
  122. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/SpecialCodepoints.ts +52 -52
  123. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/constants.ts +32 -32
  124. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/getStartConditions.ts +117 -117
  125. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/getUnicodeCodepoints.test.ts +133 -133
  126. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/getUnicodeCodepoints.ts +38 -38
  127. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.ts +408 -403
  128. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/measureText.test.ts +49 -49
  129. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/measureText.ts +52 -52
  130. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/setRenderWindow.test.ts +205 -205
  131. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/setRenderWindow.ts +93 -93
  132. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/util.ts +40 -40
  133. package/src/core/text-rendering/renderers/TextRenderer.ts +557 -557
  134. package/src/core/textures/ColorTexture.ts +102 -102
  135. package/src/core/textures/ImageTexture.ts +378 -378
  136. package/src/core/textures/NoiseTexture.ts +104 -104
  137. package/src/core/textures/RenderTexture.ts +85 -85
  138. package/src/core/textures/SubTexture.ts +179 -171
  139. package/src/core/textures/Texture.ts +435 -423
  140. package/src/core/utils.ts +227 -227
  141. package/src/env.d.ts +7 -7
  142. package/src/main-api/DynamicShaderController.ts +104 -104
  143. package/src/main-api/INode.ts +101 -101
  144. package/src/main-api/Inspector.ts +505 -505
  145. package/src/main-api/Renderer.ts +693 -693
  146. package/src/main-api/ShaderController.ts +80 -80
  147. package/src/main-api/utils.ts +45 -45
  148. package/src/utils.ts +248 -248
  149. package/dist/exports/core-api.d.ts +0 -74
  150. package/dist/exports/core-api.js +0 -96
  151. package/dist/exports/core-api.js.map +0 -1
  152. package/dist/exports/main-api.d.ts +0 -30
  153. package/dist/exports/main-api.js +0 -45
  154. package/dist/exports/main-api.js.map +0 -1
  155. package/dist/src/core/CoreExtension.d.ts +0 -12
  156. package/dist/src/core/CoreExtension.js +0 -29
  157. package/dist/src/core/CoreExtension.js.map +0 -1
  158. package/dist/src/main-api/ICoreDriver.d.ts +0 -24
  159. package/dist/src/main-api/ICoreDriver.js +0 -20
  160. package/dist/src/main-api/ICoreDriver.js.map +0 -1
  161. package/dist/src/main-api/RendererMain.d.ts +0 -378
  162. package/dist/src/main-api/RendererMain.js +0 -367
  163. package/dist/src/main-api/RendererMain.js.map +0 -1
  164. package/dist/src/main-api/texture-usage-trackers/FinalizationRegistryTextureUsageTracker.d.ts +0 -9
  165. package/dist/src/main-api/texture-usage-trackers/FinalizationRegistryTextureUsageTracker.js +0 -38
  166. package/dist/src/main-api/texture-usage-trackers/FinalizationRegistryTextureUsageTracker.js.map +0 -1
  167. package/dist/src/main-api/texture-usage-trackers/ManualCountTextureUsageTracker.d.ts +0 -56
  168. package/dist/src/main-api/texture-usage-trackers/ManualCountTextureUsageTracker.js +0 -101
  169. package/dist/src/main-api/texture-usage-trackers/ManualCountTextureUsageTracker.js.map +0 -1
  170. package/dist/src/main-api/texture-usage-trackers/TextureUsageTracker.d.ts +0 -32
  171. package/dist/src/main-api/texture-usage-trackers/TextureUsageTracker.js +0 -28
  172. package/dist/src/main-api/texture-usage-trackers/TextureUsageTracker.js.map +0 -1
  173. package/dist/src/render-drivers/main/MainCoreDriver.d.ts +0 -21
  174. package/dist/src/render-drivers/main/MainCoreDriver.js +0 -115
  175. package/dist/src/render-drivers/main/MainCoreDriver.js.map +0 -1
  176. package/dist/src/render-drivers/main/MainOnlyNode.d.ts +0 -101
  177. package/dist/src/render-drivers/main/MainOnlyNode.js +0 -425
  178. package/dist/src/render-drivers/main/MainOnlyNode.js.map +0 -1
  179. package/dist/src/render-drivers/main/MainOnlyTextNode.d.ts +0 -47
  180. package/dist/src/render-drivers/main/MainOnlyTextNode.js +0 -204
  181. package/dist/src/render-drivers/main/MainOnlyTextNode.js.map +0 -1
  182. package/dist/src/render-drivers/threadx/NodeStruct.d.ts +0 -93
  183. package/dist/src/render-drivers/threadx/NodeStruct.js +0 -290
  184. package/dist/src/render-drivers/threadx/NodeStruct.js.map +0 -1
  185. package/dist/src/render-drivers/threadx/SharedNode.d.ts +0 -40
  186. package/dist/src/render-drivers/threadx/SharedNode.js +0 -61
  187. package/dist/src/render-drivers/threadx/SharedNode.js.map +0 -1
  188. package/dist/src/render-drivers/threadx/TextNodeStruct.d.ts +0 -44
  189. package/dist/src/render-drivers/threadx/TextNodeStruct.js +0 -203
  190. package/dist/src/render-drivers/threadx/TextNodeStruct.js.map +0 -1
  191. package/dist/src/render-drivers/threadx/ThreadXCoreDriver.d.ts +0 -25
  192. package/dist/src/render-drivers/threadx/ThreadXCoreDriver.js +0 -232
  193. package/dist/src/render-drivers/threadx/ThreadXCoreDriver.js.map +0 -1
  194. package/dist/src/render-drivers/threadx/ThreadXMainAnimationController.d.ts +0 -24
  195. package/dist/src/render-drivers/threadx/ThreadXMainAnimationController.js +0 -113
  196. package/dist/src/render-drivers/threadx/ThreadXMainAnimationController.js.map +0 -1
  197. package/dist/src/render-drivers/threadx/ThreadXMainNode.d.ts +0 -46
  198. package/dist/src/render-drivers/threadx/ThreadXMainNode.js +0 -160
  199. package/dist/src/render-drivers/threadx/ThreadXMainNode.js.map +0 -1
  200. package/dist/src/render-drivers/threadx/ThreadXMainTextNode.d.ts +0 -28
  201. package/dist/src/render-drivers/threadx/ThreadXMainTextNode.js +0 -55
  202. package/dist/src/render-drivers/threadx/ThreadXMainTextNode.js.map +0 -1
  203. package/dist/src/render-drivers/threadx/ThreadXRendererMessage.d.ts +0 -70
  204. package/dist/src/render-drivers/threadx/ThreadXRendererMessage.js +0 -32
  205. package/dist/src/render-drivers/threadx/ThreadXRendererMessage.js.map +0 -1
  206. package/dist/src/render-drivers/threadx/worker/ThreadXRendererNode.d.ts +0 -19
  207. package/dist/src/render-drivers/threadx/worker/ThreadXRendererNode.js +0 -184
  208. package/dist/src/render-drivers/threadx/worker/ThreadXRendererNode.js.map +0 -1
  209. package/dist/src/render-drivers/threadx/worker/ThreadXRendererTextNode.d.ts +0 -27
  210. package/dist/src/render-drivers/threadx/worker/ThreadXRendererTextNode.js +0 -109
  211. package/dist/src/render-drivers/threadx/worker/ThreadXRendererTextNode.js.map +0 -1
  212. package/dist/src/render-drivers/threadx/worker/renderer.d.ts +0 -1
  213. package/dist/src/render-drivers/threadx/worker/renderer.js +0 -147
  214. package/dist/src/render-drivers/threadx/worker/renderer.js.map +0 -1
  215. package/dist/src/render-drivers/utils.d.ts +0 -12
  216. package/dist/src/render-drivers/utils.js +0 -74
  217. package/dist/src/render-drivers/utils.js.map +0 -1
  218. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -1,693 +1,693 @@
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
- /* eslint-disable @typescript-eslint/no-unused-vars */
21
- import type { EffectMap, ShaderMap } from '../core/CoreShaderManager.js';
22
- import type { ExtractProps, TextureMap } from '../core/CoreTextureManager.js';
23
- import { EventEmitter } from '../common/EventEmitter.js';
24
- import { assertTruthy, isProductionEnvironment } from '../utils.js';
25
- import { Stage } from '../core/Stage.js';
26
- import { CoreNode, type CoreNodeProps } from '../core/CoreNode.js';
27
- import { type CoreTextNodeProps } from '../core/CoreTextNode.js';
28
- import type {
29
- BaseShaderController,
30
- ShaderController,
31
- } from './ShaderController.js';
32
- import type { INode, INodeProps, ITextNode, ITextNodeProps } from './INode.js';
33
- import type {
34
- DynamicEffects,
35
- DynamicShaderController,
36
- } from './DynamicShaderController.js';
37
- import type {
38
- EffectDesc,
39
- EffectDescUnion,
40
- } from '../core/renderers/webgl/shaders/effects/ShaderEffect.js';
41
- import type { TextureMemoryManagerSettings } from '../core/TextureMemoryManager.js';
42
- import type { CanvasTextRenderer } from '../core/text-rendering/renderers/CanvasTextRenderer.js';
43
- import type { SdfTextRenderer } from '../core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js';
44
- import type { WebGlCoreRenderer } from '../core/renderers/webgl/WebGlCoreRenderer.js';
45
- import type { CanvasCoreRenderer } from '../core/renderers/canvas/CanvasCoreRenderer.js';
46
- import type { Inspector } from './Inspector.js';
47
-
48
- /**
49
- * An immutable reference to a specific Shader type
50
- *
51
- * @remarks
52
- * See {@link ShaderRef} for more details.
53
- */
54
- export interface SpecificShaderRef<ShType extends keyof ShaderMap> {
55
- readonly descType: 'shader';
56
- readonly shType: ShType;
57
- readonly props: ExtractProps<ShaderMap[ShType]>;
58
- }
59
-
60
- type MapShaderRefs<ShType extends keyof ShaderMap> =
61
- ShType extends keyof ShaderMap ? SpecificShaderRef<ShType> : never;
62
-
63
- /**
64
- * An immutable reference to a Shader
65
- *
66
- * @remarks
67
- * This structure should only be created by the RendererMain's `createShader`
68
- * method. The structure is immutable and should not be modified once created.
69
- *
70
- * A `ShaderRef` exists in the Main API Space and is used to point to an actual
71
- * `Shader` instance in the Core API Space. The `ShaderRef` is used to
72
- * communicate with the Core API Space to create, load, and destroy the
73
- * `Shader` instance.
74
- *
75
- * This type is technically a discriminated union of all possible shader types.
76
- * If you'd like to represent a specific shader type, you can use the
77
- * `SpecificShaderRef` generic type.
78
- */
79
- export type ShaderRef = MapShaderRefs<keyof ShaderMap>;
80
-
81
- /**
82
- * Configuration settings for {@link RendererMain}
83
- */
84
- export interface RendererMainSettings {
85
- /**
86
- * Authored logical pixel width of the application
87
- *
88
- * @defaultValue `1920`
89
- */
90
- appWidth?: number;
91
-
92
- /**
93
- * Authored logical pixel height of the application
94
- *
95
- * @defaultValue `1080`
96
- */
97
- appHeight?: number;
98
-
99
- /**
100
- * Texture Memory Manager Settings
101
- */
102
- textureMemory?: Partial<TextureMemoryManagerSettings>;
103
-
104
- /**
105
- * Bounds margin to extend the boundary in which a Node is added as Quad.
106
- */
107
- boundsMargin?: number | [number, number, number, number];
108
-
109
- /**
110
- * Factor to convert app-authored logical coorindates to device logical coordinates
111
- *
112
- * @remarks
113
- * This value allows auto-scaling to support larger/small resolutions than the
114
- * app was authored for.
115
- *
116
- * If the app was authored for 1920x1080 and this value is 2, the app's canvas
117
- * will be rendered at 3840x2160 logical pixels.
118
- *
119
- * Likewise, if the app was authored for 1920x1080 and this value is 0.66667,
120
- * the app's canvas will be rendered at 1280x720 logical pixels.
121
- *
122
- * @defaultValue `1`
123
- */
124
- deviceLogicalPixelRatio?: number;
125
-
126
- /**
127
- * Factor to convert device logical coordinates to device physical coordinates
128
- *
129
- * @remarks
130
- * This value allows auto-scaling to support devices with different pixel densities.
131
- *
132
- * This controls the number of physical pixels that are used to render each logical
133
- * pixel. For example, if the device has a pixel density of 2, each logical pixel
134
- * will be rendered using 2x2 physical pixels.
135
- *
136
- * By default, it will be set to `window.devicePixelRatio` which is the pixel
137
- * density of the device the app is running on reported by the browser.
138
- *
139
- * @defaultValue `window.devicePixelRatio`
140
- */
141
- devicePhysicalPixelRatio?: number;
142
-
143
- /**
144
- * RGBA encoded number of the background to use
145
- *
146
- * @defaultValue `0x00000000`
147
- */
148
- clearColor?: number;
149
-
150
- /**
151
- * Interval in milliseconds to receive FPS updates
152
- *
153
- * @remarks
154
- * If set to `0`, FPS updates will be disabled.
155
- *
156
- * @defaultValue `0` (disabled)
157
- */
158
- fpsUpdateInterval?: number;
159
-
160
- /**
161
- * Include context call (i.e. WebGL) information in FPS updates
162
- *
163
- * @remarks
164
- * When enabled the number of calls to each context method over the
165
- * `fpsUpdateInterval` will be included in the FPS update payload's
166
- * `contextSpyData` property.
167
- *
168
- * Enabling the context spy has a serious impact on performance so only use it
169
- * when you need to extract context call information.
170
- *
171
- * @defaultValue `false` (disabled)
172
- */
173
- enableContextSpy?: boolean;
174
-
175
- /**
176
- * Number or Image Workers to use
177
- *
178
- * @remarks
179
- * On devices with multiple cores, this can be used to improve image loading
180
- * as well as reduce the impact of image loading on the main thread.
181
- * Set to 0 to disable image workers.
182
- *
183
- * @defaultValue `2`
184
- */
185
- numImageWorkers?: number;
186
-
187
- /**
188
- * DOM Inspector
189
- *
190
- * @remarks
191
- * The inspector will replicate the state of the Nodes created
192
- * in the renderer and allow inspection of the state of the nodes.
193
- *
194
- */
195
- inspector?: typeof Inspector | false;
196
-
197
- /**
198
- * Renderer Engine
199
- *
200
- * @remarks
201
- * The renderer engine to use. Spawns a WebGL or Canvas renderer.
202
- * WebGL is more performant and supports more features. Canvas is
203
- * supported on most platforms.
204
- *
205
- * Note: When using CanvasCoreRenderer you can only use
206
- * CanvasTextRenderer. The WebGLCoreRenderer supports
207
- * both CanvasTextRenderer and SdfTextRenderer for Text Rendering.
208
- *
209
- */
210
- renderEngine: typeof CanvasCoreRenderer | typeof WebGlCoreRenderer;
211
-
212
- /**
213
- * Quad buffer size in bytes
214
- *
215
- * @defaultValue 4 * 1024 * 1024
216
- */
217
- quadBufferSize?: number;
218
-
219
- /**
220
- * Font Engines
221
- *
222
- * @remarks
223
- * The font engines to use for text rendering. CanvasTextRenderer is supported
224
- * on all platforms. SdfTextRenderer is a more performant renderer.
225
- * When using `renderEngine=CanvasCoreRenderer` you can only use `CanvasTextRenderer`.
226
- * The `renderEngine=WebGLCoreRenderer` supports both `CanvasTextRenderer` and `SdfTextRenderer`.
227
- *
228
- * This setting is used to enable tree shaking of unused font engines. Please
229
- * import your font engine(s) as follows:
230
- * ```
231
- * import { CanvasTextRenderer } from '@lightning/renderer/canvas';
232
- * import { SdfTextRenderer } from '@lightning/renderer/webgl';
233
- * ```
234
- *
235
- * If both CanvasTextRenderer and SdfTextRenderer are provided, the first renderer
236
- * provided will be asked first if it can render the font. If it cannot render the
237
- * font, the next renderer will be asked. If no renderer can render the font, the
238
- * text will not be rendered.
239
- *
240
- * **Note** that if you have fonts available in both engines the second font engine
241
- * will not be used. This is because the first font engine will always be asked first.
242
- *
243
- * @defaultValue '[]'
244
- *
245
- *
246
- */
247
- fontEngines: (typeof SdfTextRenderer | typeof CanvasTextRenderer)[];
248
-
249
- /**
250
- * Force WebGL2
251
- *
252
- * @remarks
253
- * Force the renderer to use WebGL2. This can be used to force the renderer to
254
- * use WebGL2 even if the browser supports WebGL1.
255
- *
256
- * @defaultValue `false`
257
- */
258
- forceWebGL2?: boolean;
259
-
260
- /**
261
- * Enable strictBounds
262
- *
263
- * @remarks
264
- * Enable strict bounds for the renderer. This will ensure that the renderer
265
- * will not render outside the bounds of the canvas.
266
- *
267
- * @defaultValue `true`
268
- */
269
- strictBounds?: boolean;
270
-
271
- /**
272
- * Texture Processing Limit
273
- *
274
- * @remarks
275
- * The maximum number of textures to process in a single frame. This is used to
276
- * prevent the renderer from processing too many textures in a single frame.
277
- *
278
- * @defaultValue `0`
279
- */
280
- textureProcessingLimit?: number;
281
-
282
- /**
283
- * Canvas object to use for rendering
284
- *
285
- * @remarks
286
- * This is used to render the scene graph. If not provided, a new canvas
287
- * element will be created and appended to the target element.
288
- */
289
- canvas?: HTMLCanvasElement;
290
- }
291
-
292
- /**
293
- * The Renderer Main API
294
- *
295
- * @remarks
296
- * This is the primary class used to configure and operate the Renderer.
297
- *
298
- * It is used to create and destroy Nodes, as well as Texture and Shader
299
- * references.
300
- *
301
- * Example:
302
- * ```ts
303
- * import { RendererMain, MainCoreDriver } from '@lightningjs/renderer';
304
- *
305
- * // Initialize the Renderer
306
- * const renderer = new RendererMain(
307
- * {
308
- * appWidth: 1920,
309
- * appHeight: 1080
310
- * },
311
- * 'app',
312
- * new MainCoreDriver(),
313
- * );
314
- * ```
315
- *
316
- * ## Events
317
- * - `fpsUpdate`
318
- * - Emitted every `fpsUpdateInterval` milliseconds with the current FPS
319
- * - `frameTick`
320
- * - Emitted every frame tick
321
- * - `idle`
322
- * - Emitted when the renderer is idle (no changes to the scene
323
- * graph/animations running)
324
- * - `criticalCleanup`
325
- * - Emitted when the Texture Memory Manager Cleanup process is triggered
326
- * - Payload: { memUsed: number, criticalThreshold: number }
327
- * - `memUsed` - The amount of memory (in bytes) used by textures before the
328
- * cleanup process
329
- * - `criticalThreshold` - The critical threshold (in bytes)
330
- * - `criticalCleanupFailed`
331
- * - Emitted when the Texture Memory Manager Cleanup process is unable to free
332
- * up enough texture memory to reach below the critical threshold.
333
- * This can happen when there is not enough non-renderable textures to
334
- * free up.
335
- * - Payload (object with keys):
336
- * - `memUsed` - The amount of memory (in bytes) used by textures after
337
- * the cleanup process
338
- * - `criticalThreshold` - The critical threshold (in bytes)
339
- */
340
- export class RendererMain extends EventEmitter {
341
- readonly root: INode<ShaderController<'DefaultShader'>>;
342
- readonly canvas: HTMLCanvasElement;
343
- readonly settings: Readonly<Required<RendererMainSettings>>;
344
- readonly stage: Stage;
345
- private inspector: Inspector | null = null;
346
-
347
- /**
348
- * Constructs a new Renderer instance
349
- *
350
- * @param settings Renderer settings
351
- * @param target Element ID or HTMLElement to insert the canvas into
352
- * @param driver Core Driver to use
353
- */
354
- constructor(settings: RendererMainSettings, target: string | HTMLElement) {
355
- super();
356
- const resolvedTxSettings: TextureMemoryManagerSettings = {
357
- criticalThreshold: settings.textureMemory?.criticalThreshold || 124e6,
358
- targetThresholdLevel: settings.textureMemory?.targetThresholdLevel || 0.5,
359
- cleanupInterval: settings.textureMemory?.cleanupInterval || 30000,
360
- debugLogging: settings.textureMemory?.debugLogging || false,
361
- };
362
- const resolvedSettings: Required<RendererMainSettings> = {
363
- appWidth: settings.appWidth || 1920,
364
- appHeight: settings.appHeight || 1080,
365
- textureMemory: resolvedTxSettings,
366
- boundsMargin: settings.boundsMargin || 0,
367
- deviceLogicalPixelRatio: settings.deviceLogicalPixelRatio || 1,
368
- devicePhysicalPixelRatio:
369
- settings.devicePhysicalPixelRatio || window.devicePixelRatio,
370
- clearColor: settings.clearColor ?? 0x00000000,
371
- fpsUpdateInterval: settings.fpsUpdateInterval || 0,
372
- numImageWorkers:
373
- settings.numImageWorkers !== undefined ? settings.numImageWorkers : 2,
374
- enableContextSpy: settings.enableContextSpy ?? false,
375
- forceWebGL2: settings.forceWebGL2 ?? false,
376
- inspector: settings.inspector ?? false,
377
- renderEngine: settings.renderEngine,
378
- quadBufferSize: settings.quadBufferSize ?? 4 * 1024 * 1024,
379
- fontEngines: settings.fontEngines,
380
- strictBounds: settings.strictBounds ?? true,
381
- textureProcessingLimit: settings.textureProcessingLimit || 0,
382
- canvas: settings.canvas || document.createElement('canvas'),
383
- };
384
- this.settings = resolvedSettings;
385
-
386
- const {
387
- appWidth,
388
- appHeight,
389
- deviceLogicalPixelRatio,
390
- devicePhysicalPixelRatio,
391
- inspector,
392
- canvas,
393
- } = resolvedSettings;
394
-
395
- const deviceLogicalWidth = appWidth * deviceLogicalPixelRatio;
396
- const deviceLogicalHeight = appHeight * deviceLogicalPixelRatio;
397
-
398
- this.canvas = canvas;
399
- canvas.width = deviceLogicalWidth * devicePhysicalPixelRatio;
400
- canvas.height = deviceLogicalHeight * devicePhysicalPixelRatio;
401
-
402
- canvas.style.width = `${deviceLogicalWidth}px`;
403
- canvas.style.height = `${deviceLogicalHeight}px`;
404
-
405
- // Initialize the stage
406
- this.stage = new Stage({
407
- appWidth: this.settings.appWidth,
408
- appHeight: this.settings.appHeight,
409
- boundsMargin: this.settings.boundsMargin,
410
- clearColor: this.settings.clearColor,
411
- canvas: this.canvas,
412
- deviceLogicalPixelRatio: this.settings.deviceLogicalPixelRatio,
413
- devicePhysicalPixelRatio: this.settings.devicePhysicalPixelRatio,
414
- enableContextSpy: this.settings.enableContextSpy,
415
- forceWebGL2: this.settings.forceWebGL2,
416
- fpsUpdateInterval: this.settings.fpsUpdateInterval,
417
- numImageWorkers: this.settings.numImageWorkers,
418
- renderEngine: this.settings.renderEngine,
419
- textureMemory: resolvedTxSettings,
420
- eventBus: this,
421
- quadBufferSize: this.settings.quadBufferSize,
422
- fontEngines: this.settings.fontEngines,
423
- inspector: this.settings.inspector !== null,
424
- strictBounds: this.settings.strictBounds,
425
- textureProcessingLimit: this.settings.textureProcessingLimit,
426
- });
427
-
428
- // Extract the root node
429
- this.root = this.stage.root as unknown as INode<
430
- ShaderController<'DefaultShader'>
431
- >;
432
-
433
- // Get the target element and attach the canvas to it
434
- let targetEl: HTMLElement | null;
435
- if (typeof target === 'string') {
436
- targetEl = document.getElementById(target);
437
- } else {
438
- targetEl = target;
439
- }
440
-
441
- if (!targetEl) {
442
- throw new Error('Could not find target element');
443
- }
444
-
445
- targetEl.appendChild(canvas);
446
-
447
- // Initialize inspector (if enabled)
448
- if (inspector && !isProductionEnvironment()) {
449
- this.inspector = new inspector(canvas, resolvedSettings);
450
- }
451
- }
452
-
453
- /**
454
- * Create a new scene graph node
455
- *
456
- * @remarks
457
- * A node is the main graphical building block of the Renderer scene graph. It
458
- * can be a container for other nodes, or it can be a leaf node that renders a
459
- * solid color, gradient, image, or specific texture, using a specific shader.
460
- *
461
- * To create a text node, see {@link createTextNode}.
462
- *
463
- * See {@link CoreNode} for more details.
464
- *
465
- * @param props
466
- * @returns
467
- */
468
- createNode<
469
- ShCtr extends BaseShaderController = ShaderController<'DefaultShader'>,
470
- >(props: Partial<INodeProps<ShCtr>>): INode<ShCtr> {
471
- const node = this.stage.createNode(props as Partial<CoreNodeProps>);
472
-
473
- if (this.inspector) {
474
- return this.inspector.createNode(node) as unknown as INode<ShCtr>;
475
- }
476
-
477
- // FIXME onDestroy event? node.once('beforeDestroy'
478
- // FIXME onCreate event?
479
- return node as unknown as INode<ShCtr>;
480
- }
481
-
482
- /**
483
- * Create a new scene graph text node
484
- *
485
- * @remarks
486
- * A text node is the second graphical building block of the Renderer scene
487
- * graph. It renders text using a specific text renderer that is automatically
488
- * chosen based on the font requested and what type of fonts are installed
489
- * into an app.
490
- *
491
- * See {@link ITextNode} for more details.
492
- *
493
- * @param props
494
- * @returns
495
- */
496
- createTextNode(props: Partial<ITextNodeProps>): ITextNode {
497
- const textNode = this.stage.createTextNode(props as CoreTextNodeProps);
498
-
499
- if (this.inspector) {
500
- return this.inspector.createTextNode(textNode);
501
- }
502
-
503
- return textNode as unknown as ITextNode;
504
- }
505
-
506
- /**
507
- * Destroy a node
508
- *
509
- * @remarks
510
- * This method destroys a node
511
- *
512
- * @param node
513
- * @returns
514
- */
515
- destroyNode(node: INode) {
516
- if (this.inspector) {
517
- this.inspector.destroyNode(node.id);
518
- }
519
-
520
- return node.destroy();
521
- }
522
-
523
- /**
524
- * Create a new texture reference
525
- *
526
- * @remarks
527
- * This method creates a new reference to a texture. The texture is not
528
- * loaded until it is used on a node.
529
- *
530
- * It can be assigned to a node's `texture` property, or it can be used
531
- * when creating a SubTexture.
532
- *
533
- * @param textureType
534
- * @param props
535
- * @param options
536
- * @returns
537
- */
538
- createTexture<TxType extends keyof TextureMap>(
539
- textureType: TxType,
540
- props: ExtractProps<TextureMap[TxType]>,
541
- ): InstanceType<TextureMap[TxType]> {
542
- return this.stage.txManager.createTexture(textureType, props);
543
- }
544
-
545
- /**
546
- * Create a new shader controller for a shader type
547
- *
548
- * @remarks
549
- * This method creates a new Shader Controller for a specific shader type.
550
- *
551
- * If the shader has not been loaded yet, it will be loaded. Otherwise, the
552
- * existing shader will be reused.
553
- *
554
- * It can be assigned to a Node's `shader` property.
555
- *
556
- * @param shaderType
557
- * @param props
558
- * @returns
559
- */
560
- createShader<ShType extends keyof ShaderMap>(
561
- shaderType: ShType,
562
- props?: ExtractProps<ShaderMap[ShType]>,
563
- ): ShaderController<ShType> {
564
- return this.stage.shManager.loadShader(shaderType, props);
565
- }
566
-
567
- /**
568
- * Create a new Dynamic Shader controller
569
- *
570
- * @remarks
571
- * A Dynamic Shader is a shader that can be composed of an array of mulitple
572
- * effects. Each effect can be animated or changed after creation (provided
573
- * the effect is given a name).
574
- *
575
- * Example:
576
- * ```ts
577
- * renderer.createNode({
578
- * shader: renderer.createDynamicShader([
579
- * renderer.createEffect('radius', {
580
- * radius: 0
581
- * }, 'effect1'),
582
- * renderer.createEffect('border', {
583
- * color: 0xff00ffff,
584
- * width: 10,
585
- * }, 'effect2'),
586
- * ]),
587
- * });
588
- * ```
589
- *
590
- * @param effects
591
- * @returns
592
- */
593
- createDynamicShader<
594
- T extends DynamicEffects<[...{ name?: string; type: keyof EffectMap }[]]>,
595
- >(effects: [...T]): DynamicShaderController<T> {
596
- return this.stage.shManager.loadDynamicShader({
597
- effects: effects as EffectDescUnion[],
598
- });
599
- }
600
-
601
- /**
602
- * Create an effect to be used in a Dynamic Shader
603
- *
604
- * @remark
605
- * The {name} parameter is optional but required if you want to animate the effect
606
- * or change the effect's properties after creation.
607
- *
608
- * See {@link createDynamicShader} for an example.
609
- *
610
- * @param type
611
- * @param props
612
- * @param name
613
- * @returns
614
- */
615
- createEffect<
616
- Type extends keyof EffectMap,
617
- Name extends string | undefined = undefined,
618
- >(
619
- type: Type,
620
- props: EffectDesc<{ name: Name; type: Type }>['props'],
621
- name?: Name,
622
- ): EffectDesc<{ name: Name; type: Type }> {
623
- return {
624
- name,
625
- type,
626
- props,
627
- };
628
- }
629
-
630
- /**
631
- * Get a Node by its ID
632
- *
633
- * @param id
634
- * @returns
635
- */
636
- getNodeById(id: number): CoreNode | null {
637
- const root = this.stage?.root;
638
- if (!root) {
639
- return null;
640
- }
641
-
642
- const findNode = (node: CoreNode): CoreNode | null => {
643
- if (node.id === id) {
644
- return node;
645
- }
646
-
647
- for (const child of node.children) {
648
- const found = findNode(child);
649
- if (found) {
650
- return found;
651
- }
652
- }
653
-
654
- return null;
655
- };
656
-
657
- return findNode(root);
658
- }
659
-
660
- toggleFreeze() {
661
- throw new Error('Not implemented');
662
- }
663
-
664
- advanceFrame() {
665
- throw new Error('Not implemented');
666
- }
667
-
668
- getBufferInfo() {
669
- return this.stage.renderer.getBufferInfo();
670
- }
671
-
672
- /**
673
- * Re-render the current frame without advancing any running animations.
674
- *
675
- * @remarks
676
- * Any state changes will be reflected in the re-rendered frame. Useful for
677
- * debugging.
678
- *
679
- * May not do anything if the render loop is running on a separate worker.
680
- */
681
- rerender() {
682
- this.stage.requestRender();
683
- }
684
-
685
- /**
686
- * Sets the clear color for the stage.
687
- *
688
- * @param color - The color to set as the clear color.
689
- */
690
- setClearColor(color: number) {
691
- this.stage.setClearColor(color);
692
- }
693
- }
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
+ /* eslint-disable @typescript-eslint/no-unused-vars */
21
+ import type { EffectMap, ShaderMap } from '../core/CoreShaderManager.js';
22
+ import type { ExtractProps, TextureMap } from '../core/CoreTextureManager.js';
23
+ import { EventEmitter } from '../common/EventEmitter.js';
24
+ import { assertTruthy, isProductionEnvironment } from '../utils.js';
25
+ import { Stage } from '../core/Stage.js';
26
+ import { CoreNode, type CoreNodeProps } from '../core/CoreNode.js';
27
+ import { type CoreTextNodeProps } from '../core/CoreTextNode.js';
28
+ import type {
29
+ BaseShaderController,
30
+ ShaderController,
31
+ } from './ShaderController.js';
32
+ import type { INode, INodeProps, ITextNode, ITextNodeProps } from './INode.js';
33
+ import type {
34
+ DynamicEffects,
35
+ DynamicShaderController,
36
+ } from './DynamicShaderController.js';
37
+ import type {
38
+ EffectDesc,
39
+ EffectDescUnion,
40
+ } from '../core/renderers/webgl/shaders/effects/ShaderEffect.js';
41
+ import type { TextureMemoryManagerSettings } from '../core/TextureMemoryManager.js';
42
+ import type { CanvasTextRenderer } from '../core/text-rendering/renderers/CanvasTextRenderer.js';
43
+ import type { SdfTextRenderer } from '../core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js';
44
+ import type { WebGlCoreRenderer } from '../core/renderers/webgl/WebGlCoreRenderer.js';
45
+ import type { CanvasCoreRenderer } from '../core/renderers/canvas/CanvasCoreRenderer.js';
46
+ import type { Inspector } from './Inspector.js';
47
+
48
+ /**
49
+ * An immutable reference to a specific Shader type
50
+ *
51
+ * @remarks
52
+ * See {@link ShaderRef} for more details.
53
+ */
54
+ export interface SpecificShaderRef<ShType extends keyof ShaderMap> {
55
+ readonly descType: 'shader';
56
+ readonly shType: ShType;
57
+ readonly props: ExtractProps<ShaderMap[ShType]>;
58
+ }
59
+
60
+ type MapShaderRefs<ShType extends keyof ShaderMap> =
61
+ ShType extends keyof ShaderMap ? SpecificShaderRef<ShType> : never;
62
+
63
+ /**
64
+ * An immutable reference to a Shader
65
+ *
66
+ * @remarks
67
+ * This structure should only be created by the RendererMain's `createShader`
68
+ * method. The structure is immutable and should not be modified once created.
69
+ *
70
+ * A `ShaderRef` exists in the Main API Space and is used to point to an actual
71
+ * `Shader` instance in the Core API Space. The `ShaderRef` is used to
72
+ * communicate with the Core API Space to create, load, and destroy the
73
+ * `Shader` instance.
74
+ *
75
+ * This type is technically a discriminated union of all possible shader types.
76
+ * If you'd like to represent a specific shader type, you can use the
77
+ * `SpecificShaderRef` generic type.
78
+ */
79
+ export type ShaderRef = MapShaderRefs<keyof ShaderMap>;
80
+
81
+ /**
82
+ * Configuration settings for {@link RendererMain}
83
+ */
84
+ export interface RendererMainSettings {
85
+ /**
86
+ * Authored logical pixel width of the application
87
+ *
88
+ * @defaultValue `1920`
89
+ */
90
+ appWidth?: number;
91
+
92
+ /**
93
+ * Authored logical pixel height of the application
94
+ *
95
+ * @defaultValue `1080`
96
+ */
97
+ appHeight?: number;
98
+
99
+ /**
100
+ * Texture Memory Manager Settings
101
+ */
102
+ textureMemory?: Partial<TextureMemoryManagerSettings>;
103
+
104
+ /**
105
+ * Bounds margin to extend the boundary in which a Node is added as Quad.
106
+ */
107
+ boundsMargin?: number | [number, number, number, number];
108
+
109
+ /**
110
+ * Factor to convert app-authored logical coorindates to device logical coordinates
111
+ *
112
+ * @remarks
113
+ * This value allows auto-scaling to support larger/small resolutions than the
114
+ * app was authored for.
115
+ *
116
+ * If the app was authored for 1920x1080 and this value is 2, the app's canvas
117
+ * will be rendered at 3840x2160 logical pixels.
118
+ *
119
+ * Likewise, if the app was authored for 1920x1080 and this value is 0.66667,
120
+ * the app's canvas will be rendered at 1280x720 logical pixels.
121
+ *
122
+ * @defaultValue `1`
123
+ */
124
+ deviceLogicalPixelRatio?: number;
125
+
126
+ /**
127
+ * Factor to convert device logical coordinates to device physical coordinates
128
+ *
129
+ * @remarks
130
+ * This value allows auto-scaling to support devices with different pixel densities.
131
+ *
132
+ * This controls the number of physical pixels that are used to render each logical
133
+ * pixel. For example, if the device has a pixel density of 2, each logical pixel
134
+ * will be rendered using 2x2 physical pixels.
135
+ *
136
+ * By default, it will be set to `window.devicePixelRatio` which is the pixel
137
+ * density of the device the app is running on reported by the browser.
138
+ *
139
+ * @defaultValue `window.devicePixelRatio`
140
+ */
141
+ devicePhysicalPixelRatio?: number;
142
+
143
+ /**
144
+ * RGBA encoded number of the background to use
145
+ *
146
+ * @defaultValue `0x00000000`
147
+ */
148
+ clearColor?: number;
149
+
150
+ /**
151
+ * Interval in milliseconds to receive FPS updates
152
+ *
153
+ * @remarks
154
+ * If set to `0`, FPS updates will be disabled.
155
+ *
156
+ * @defaultValue `0` (disabled)
157
+ */
158
+ fpsUpdateInterval?: number;
159
+
160
+ /**
161
+ * Include context call (i.e. WebGL) information in FPS updates
162
+ *
163
+ * @remarks
164
+ * When enabled the number of calls to each context method over the
165
+ * `fpsUpdateInterval` will be included in the FPS update payload's
166
+ * `contextSpyData` property.
167
+ *
168
+ * Enabling the context spy has a serious impact on performance so only use it
169
+ * when you need to extract context call information.
170
+ *
171
+ * @defaultValue `false` (disabled)
172
+ */
173
+ enableContextSpy?: boolean;
174
+
175
+ /**
176
+ * Number or Image Workers to use
177
+ *
178
+ * @remarks
179
+ * On devices with multiple cores, this can be used to improve image loading
180
+ * as well as reduce the impact of image loading on the main thread.
181
+ * Set to 0 to disable image workers.
182
+ *
183
+ * @defaultValue `2`
184
+ */
185
+ numImageWorkers?: number;
186
+
187
+ /**
188
+ * DOM Inspector
189
+ *
190
+ * @remarks
191
+ * The inspector will replicate the state of the Nodes created
192
+ * in the renderer and allow inspection of the state of the nodes.
193
+ *
194
+ */
195
+ inspector?: typeof Inspector | false;
196
+
197
+ /**
198
+ * Renderer Engine
199
+ *
200
+ * @remarks
201
+ * The renderer engine to use. Spawns a WebGL or Canvas renderer.
202
+ * WebGL is more performant and supports more features. Canvas is
203
+ * supported on most platforms.
204
+ *
205
+ * Note: When using CanvasCoreRenderer you can only use
206
+ * CanvasTextRenderer. The WebGLCoreRenderer supports
207
+ * both CanvasTextRenderer and SdfTextRenderer for Text Rendering.
208
+ *
209
+ */
210
+ renderEngine: typeof CanvasCoreRenderer | typeof WebGlCoreRenderer;
211
+
212
+ /**
213
+ * Quad buffer size in bytes
214
+ *
215
+ * @defaultValue 4 * 1024 * 1024
216
+ */
217
+ quadBufferSize?: number;
218
+
219
+ /**
220
+ * Font Engines
221
+ *
222
+ * @remarks
223
+ * The font engines to use for text rendering. CanvasTextRenderer is supported
224
+ * on all platforms. SdfTextRenderer is a more performant renderer.
225
+ * When using `renderEngine=CanvasCoreRenderer` you can only use `CanvasTextRenderer`.
226
+ * The `renderEngine=WebGLCoreRenderer` supports both `CanvasTextRenderer` and `SdfTextRenderer`.
227
+ *
228
+ * This setting is used to enable tree shaking of unused font engines. Please
229
+ * import your font engine(s) as follows:
230
+ * ```
231
+ * import { CanvasTextRenderer } from '@lightning/renderer/canvas';
232
+ * import { SdfTextRenderer } from '@lightning/renderer/webgl';
233
+ * ```
234
+ *
235
+ * If both CanvasTextRenderer and SdfTextRenderer are provided, the first renderer
236
+ * provided will be asked first if it can render the font. If it cannot render the
237
+ * font, the next renderer will be asked. If no renderer can render the font, the
238
+ * text will not be rendered.
239
+ *
240
+ * **Note** that if you have fonts available in both engines the second font engine
241
+ * will not be used. This is because the first font engine will always be asked first.
242
+ *
243
+ * @defaultValue '[]'
244
+ *
245
+ *
246
+ */
247
+ fontEngines: (typeof SdfTextRenderer | typeof CanvasTextRenderer)[];
248
+
249
+ /**
250
+ * Force WebGL2
251
+ *
252
+ * @remarks
253
+ * Force the renderer to use WebGL2. This can be used to force the renderer to
254
+ * use WebGL2 even if the browser supports WebGL1.
255
+ *
256
+ * @defaultValue `false`
257
+ */
258
+ forceWebGL2?: boolean;
259
+
260
+ /**
261
+ * Enable strictBounds
262
+ *
263
+ * @remarks
264
+ * Enable strict bounds for the renderer. This will ensure that the renderer
265
+ * will not render outside the bounds of the canvas.
266
+ *
267
+ * @defaultValue `true`
268
+ */
269
+ strictBounds?: boolean;
270
+
271
+ /**
272
+ * Texture Processing Limit
273
+ *
274
+ * @remarks
275
+ * The maximum number of textures to process in a single frame. This is used to
276
+ * prevent the renderer from processing too many textures in a single frame.
277
+ *
278
+ * @defaultValue `0`
279
+ */
280
+ textureProcessingLimit?: number;
281
+
282
+ /**
283
+ * Canvas object to use for rendering
284
+ *
285
+ * @remarks
286
+ * This is used to render the scene graph. If not provided, a new canvas
287
+ * element will be created and appended to the target element.
288
+ */
289
+ canvas?: HTMLCanvasElement;
290
+ }
291
+
292
+ /**
293
+ * The Renderer Main API
294
+ *
295
+ * @remarks
296
+ * This is the primary class used to configure and operate the Renderer.
297
+ *
298
+ * It is used to create and destroy Nodes, as well as Texture and Shader
299
+ * references.
300
+ *
301
+ * Example:
302
+ * ```ts
303
+ * import { RendererMain, MainCoreDriver } from '@lightningjs/renderer';
304
+ *
305
+ * // Initialize the Renderer
306
+ * const renderer = new RendererMain(
307
+ * {
308
+ * appWidth: 1920,
309
+ * appHeight: 1080
310
+ * },
311
+ * 'app',
312
+ * new MainCoreDriver(),
313
+ * );
314
+ * ```
315
+ *
316
+ * ## Events
317
+ * - `fpsUpdate`
318
+ * - Emitted every `fpsUpdateInterval` milliseconds with the current FPS
319
+ * - `frameTick`
320
+ * - Emitted every frame tick
321
+ * - `idle`
322
+ * - Emitted when the renderer is idle (no changes to the scene
323
+ * graph/animations running)
324
+ * - `criticalCleanup`
325
+ * - Emitted when the Texture Memory Manager Cleanup process is triggered
326
+ * - Payload: { memUsed: number, criticalThreshold: number }
327
+ * - `memUsed` - The amount of memory (in bytes) used by textures before the
328
+ * cleanup process
329
+ * - `criticalThreshold` - The critical threshold (in bytes)
330
+ * - `criticalCleanupFailed`
331
+ * - Emitted when the Texture Memory Manager Cleanup process is unable to free
332
+ * up enough texture memory to reach below the critical threshold.
333
+ * This can happen when there is not enough non-renderable textures to
334
+ * free up.
335
+ * - Payload (object with keys):
336
+ * - `memUsed` - The amount of memory (in bytes) used by textures after
337
+ * the cleanup process
338
+ * - `criticalThreshold` - The critical threshold (in bytes)
339
+ */
340
+ export class RendererMain extends EventEmitter {
341
+ readonly root: INode<ShaderController<'DefaultShader'>>;
342
+ readonly canvas: HTMLCanvasElement;
343
+ readonly settings: Readonly<Required<RendererMainSettings>>;
344
+ readonly stage: Stage;
345
+ private inspector: Inspector | null = null;
346
+
347
+ /**
348
+ * Constructs a new Renderer instance
349
+ *
350
+ * @param settings Renderer settings
351
+ * @param target Element ID or HTMLElement to insert the canvas into
352
+ * @param driver Core Driver to use
353
+ */
354
+ constructor(settings: RendererMainSettings, target: string | HTMLElement) {
355
+ super();
356
+ const resolvedTxSettings: TextureMemoryManagerSettings = {
357
+ criticalThreshold: settings.textureMemory?.criticalThreshold || 124e6,
358
+ targetThresholdLevel: settings.textureMemory?.targetThresholdLevel || 0.5,
359
+ cleanupInterval: settings.textureMemory?.cleanupInterval || 30000,
360
+ debugLogging: settings.textureMemory?.debugLogging || false,
361
+ };
362
+ const resolvedSettings: Required<RendererMainSettings> = {
363
+ appWidth: settings.appWidth || 1920,
364
+ appHeight: settings.appHeight || 1080,
365
+ textureMemory: resolvedTxSettings,
366
+ boundsMargin: settings.boundsMargin || 0,
367
+ deviceLogicalPixelRatio: settings.deviceLogicalPixelRatio || 1,
368
+ devicePhysicalPixelRatio:
369
+ settings.devicePhysicalPixelRatio || window.devicePixelRatio,
370
+ clearColor: settings.clearColor ?? 0x00000000,
371
+ fpsUpdateInterval: settings.fpsUpdateInterval || 0,
372
+ numImageWorkers:
373
+ settings.numImageWorkers !== undefined ? settings.numImageWorkers : 2,
374
+ enableContextSpy: settings.enableContextSpy ?? false,
375
+ forceWebGL2: settings.forceWebGL2 ?? false,
376
+ inspector: settings.inspector ?? false,
377
+ renderEngine: settings.renderEngine,
378
+ quadBufferSize: settings.quadBufferSize ?? 4 * 1024 * 1024,
379
+ fontEngines: settings.fontEngines,
380
+ strictBounds: settings.strictBounds ?? true,
381
+ textureProcessingLimit: settings.textureProcessingLimit || 0,
382
+ canvas: settings.canvas || document.createElement('canvas'),
383
+ };
384
+ this.settings = resolvedSettings;
385
+
386
+ const {
387
+ appWidth,
388
+ appHeight,
389
+ deviceLogicalPixelRatio,
390
+ devicePhysicalPixelRatio,
391
+ inspector,
392
+ canvas,
393
+ } = resolvedSettings;
394
+
395
+ const deviceLogicalWidth = appWidth * deviceLogicalPixelRatio;
396
+ const deviceLogicalHeight = appHeight * deviceLogicalPixelRatio;
397
+
398
+ this.canvas = canvas;
399
+ canvas.width = deviceLogicalWidth * devicePhysicalPixelRatio;
400
+ canvas.height = deviceLogicalHeight * devicePhysicalPixelRatio;
401
+
402
+ canvas.style.width = `${deviceLogicalWidth}px`;
403
+ canvas.style.height = `${deviceLogicalHeight}px`;
404
+
405
+ // Initialize the stage
406
+ this.stage = new Stage({
407
+ appWidth: this.settings.appWidth,
408
+ appHeight: this.settings.appHeight,
409
+ boundsMargin: this.settings.boundsMargin,
410
+ clearColor: this.settings.clearColor,
411
+ canvas: this.canvas,
412
+ deviceLogicalPixelRatio: this.settings.deviceLogicalPixelRatio,
413
+ devicePhysicalPixelRatio: this.settings.devicePhysicalPixelRatio,
414
+ enableContextSpy: this.settings.enableContextSpy,
415
+ forceWebGL2: this.settings.forceWebGL2,
416
+ fpsUpdateInterval: this.settings.fpsUpdateInterval,
417
+ numImageWorkers: this.settings.numImageWorkers,
418
+ renderEngine: this.settings.renderEngine,
419
+ textureMemory: resolvedTxSettings,
420
+ eventBus: this,
421
+ quadBufferSize: this.settings.quadBufferSize,
422
+ fontEngines: this.settings.fontEngines,
423
+ inspector: this.settings.inspector !== null,
424
+ strictBounds: this.settings.strictBounds,
425
+ textureProcessingLimit: this.settings.textureProcessingLimit,
426
+ });
427
+
428
+ // Extract the root node
429
+ this.root = this.stage.root as unknown as INode<
430
+ ShaderController<'DefaultShader'>
431
+ >;
432
+
433
+ // Get the target element and attach the canvas to it
434
+ let targetEl: HTMLElement | null;
435
+ if (typeof target === 'string') {
436
+ targetEl = document.getElementById(target);
437
+ } else {
438
+ targetEl = target;
439
+ }
440
+
441
+ if (!targetEl) {
442
+ throw new Error('Could not find target element');
443
+ }
444
+
445
+ targetEl.appendChild(canvas);
446
+
447
+ // Initialize inspector (if enabled)
448
+ if (inspector && !isProductionEnvironment()) {
449
+ this.inspector = new inspector(canvas, resolvedSettings);
450
+ }
451
+ }
452
+
453
+ /**
454
+ * Create a new scene graph node
455
+ *
456
+ * @remarks
457
+ * A node is the main graphical building block of the Renderer scene graph. It
458
+ * can be a container for other nodes, or it can be a leaf node that renders a
459
+ * solid color, gradient, image, or specific texture, using a specific shader.
460
+ *
461
+ * To create a text node, see {@link createTextNode}.
462
+ *
463
+ * See {@link CoreNode} for more details.
464
+ *
465
+ * @param props
466
+ * @returns
467
+ */
468
+ createNode<
469
+ ShCtr extends BaseShaderController = ShaderController<'DefaultShader'>,
470
+ >(props: Partial<INodeProps<ShCtr>>): INode<ShCtr> {
471
+ const node = this.stage.createNode(props as Partial<CoreNodeProps>);
472
+
473
+ if (this.inspector) {
474
+ return this.inspector.createNode(node) as unknown as INode<ShCtr>;
475
+ }
476
+
477
+ // FIXME onDestroy event? node.once('beforeDestroy'
478
+ // FIXME onCreate event?
479
+ return node as unknown as INode<ShCtr>;
480
+ }
481
+
482
+ /**
483
+ * Create a new scene graph text node
484
+ *
485
+ * @remarks
486
+ * A text node is the second graphical building block of the Renderer scene
487
+ * graph. It renders text using a specific text renderer that is automatically
488
+ * chosen based on the font requested and what type of fonts are installed
489
+ * into an app.
490
+ *
491
+ * See {@link ITextNode} for more details.
492
+ *
493
+ * @param props
494
+ * @returns
495
+ */
496
+ createTextNode(props: Partial<ITextNodeProps>): ITextNode {
497
+ const textNode = this.stage.createTextNode(props as CoreTextNodeProps);
498
+
499
+ if (this.inspector) {
500
+ return this.inspector.createTextNode(textNode);
501
+ }
502
+
503
+ return textNode as unknown as ITextNode;
504
+ }
505
+
506
+ /**
507
+ * Destroy a node
508
+ *
509
+ * @remarks
510
+ * This method destroys a node
511
+ *
512
+ * @param node
513
+ * @returns
514
+ */
515
+ destroyNode(node: INode) {
516
+ if (this.inspector) {
517
+ this.inspector.destroyNode(node.id);
518
+ }
519
+
520
+ return node.destroy();
521
+ }
522
+
523
+ /**
524
+ * Create a new texture reference
525
+ *
526
+ * @remarks
527
+ * This method creates a new reference to a texture. The texture is not
528
+ * loaded until it is used on a node.
529
+ *
530
+ * It can be assigned to a node's `texture` property, or it can be used
531
+ * when creating a SubTexture.
532
+ *
533
+ * @param textureType
534
+ * @param props
535
+ * @param options
536
+ * @returns
537
+ */
538
+ createTexture<TxType extends keyof TextureMap>(
539
+ textureType: TxType,
540
+ props: ExtractProps<TextureMap[TxType]>,
541
+ ): InstanceType<TextureMap[TxType]> {
542
+ return this.stage.txManager.createTexture(textureType, props);
543
+ }
544
+
545
+ /**
546
+ * Create a new shader controller for a shader type
547
+ *
548
+ * @remarks
549
+ * This method creates a new Shader Controller for a specific shader type.
550
+ *
551
+ * If the shader has not been loaded yet, it will be loaded. Otherwise, the
552
+ * existing shader will be reused.
553
+ *
554
+ * It can be assigned to a Node's `shader` property.
555
+ *
556
+ * @param shaderType
557
+ * @param props
558
+ * @returns
559
+ */
560
+ createShader<ShType extends keyof ShaderMap>(
561
+ shaderType: ShType,
562
+ props?: ExtractProps<ShaderMap[ShType]>,
563
+ ): ShaderController<ShType> {
564
+ return this.stage.shManager.loadShader(shaderType, props);
565
+ }
566
+
567
+ /**
568
+ * Create a new Dynamic Shader controller
569
+ *
570
+ * @remarks
571
+ * A Dynamic Shader is a shader that can be composed of an array of mulitple
572
+ * effects. Each effect can be animated or changed after creation (provided
573
+ * the effect is given a name).
574
+ *
575
+ * Example:
576
+ * ```ts
577
+ * renderer.createNode({
578
+ * shader: renderer.createDynamicShader([
579
+ * renderer.createEffect('radius', {
580
+ * radius: 0
581
+ * }, 'effect1'),
582
+ * renderer.createEffect('border', {
583
+ * color: 0xff00ffff,
584
+ * width: 10,
585
+ * }, 'effect2'),
586
+ * ]),
587
+ * });
588
+ * ```
589
+ *
590
+ * @param effects
591
+ * @returns
592
+ */
593
+ createDynamicShader<
594
+ T extends DynamicEffects<[...{ name?: string; type: keyof EffectMap }[]]>,
595
+ >(effects: [...T]): DynamicShaderController<T> {
596
+ return this.stage.shManager.loadDynamicShader({
597
+ effects: effects as EffectDescUnion[],
598
+ });
599
+ }
600
+
601
+ /**
602
+ * Create an effect to be used in a Dynamic Shader
603
+ *
604
+ * @remark
605
+ * The {name} parameter is optional but required if you want to animate the effect
606
+ * or change the effect's properties after creation.
607
+ *
608
+ * See {@link createDynamicShader} for an example.
609
+ *
610
+ * @param type
611
+ * @param props
612
+ * @param name
613
+ * @returns
614
+ */
615
+ createEffect<
616
+ Type extends keyof EffectMap,
617
+ Name extends string | undefined = undefined,
618
+ >(
619
+ type: Type,
620
+ props: EffectDesc<{ name: Name; type: Type }>['props'],
621
+ name?: Name,
622
+ ): EffectDesc<{ name: Name; type: Type }> {
623
+ return {
624
+ name,
625
+ type,
626
+ props,
627
+ };
628
+ }
629
+
630
+ /**
631
+ * Get a Node by its ID
632
+ *
633
+ * @param id
634
+ * @returns
635
+ */
636
+ getNodeById(id: number): CoreNode | null {
637
+ const root = this.stage?.root;
638
+ if (!root) {
639
+ return null;
640
+ }
641
+
642
+ const findNode = (node: CoreNode): CoreNode | null => {
643
+ if (node.id === id) {
644
+ return node;
645
+ }
646
+
647
+ for (const child of node.children) {
648
+ const found = findNode(child);
649
+ if (found) {
650
+ return found;
651
+ }
652
+ }
653
+
654
+ return null;
655
+ };
656
+
657
+ return findNode(root);
658
+ }
659
+
660
+ toggleFreeze() {
661
+ throw new Error('Not implemented');
662
+ }
663
+
664
+ advanceFrame() {
665
+ throw new Error('Not implemented');
666
+ }
667
+
668
+ getBufferInfo() {
669
+ return this.stage.renderer.getBufferInfo();
670
+ }
671
+
672
+ /**
673
+ * Re-render the current frame without advancing any running animations.
674
+ *
675
+ * @remarks
676
+ * Any state changes will be reflected in the re-rendered frame. Useful for
677
+ * debugging.
678
+ *
679
+ * May not do anything if the render loop is running on a separate worker.
680
+ */
681
+ rerender() {
682
+ this.stage.requestRender();
683
+ }
684
+
685
+ /**
686
+ * Sets the clear color for the stage.
687
+ *
688
+ * @param color - The color to set as the clear color.
689
+ */
690
+ setClearColor(color: number) {
691
+ this.stage.setClearColor(color);
692
+ }
693
+ }