@flighthq/scene2d-gl 0.2.1-next.840.857425c

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 (138) hide show
  1. package/dist/enableGlColorAdjustmentGuards.d.ts +4 -0
  2. package/dist/enableGlColorAdjustmentGuards.d.ts.map +1 -0
  3. package/dist/enableGlColorAdjustmentGuards.js +21 -0
  4. package/dist/enableGlColorAdjustmentGuards.js.map +1 -0
  5. package/dist/glBitmap.d.ts +4 -0
  6. package/dist/glBitmap.d.ts.map +1 -0
  7. package/dist/glBitmap.js +93 -0
  8. package/dist/glBitmap.js.map +1 -0
  9. package/dist/glCache.d.ts +30 -0
  10. package/dist/glCache.d.ts.map +1 -0
  11. package/dist/glCache.js +196 -0
  12. package/dist/glCache.js.map +1 -0
  13. package/dist/glClip.d.ts +3 -0
  14. package/dist/glClip.d.ts.map +1 -0
  15. package/dist/glClip.js +46 -0
  16. package/dist/glClip.js.map +1 -0
  17. package/dist/glClipContours.d.ts +4 -0
  18. package/dist/glClipContours.d.ts.map +1 -0
  19. package/dist/glClipContours.js +148 -0
  20. package/dist/glClipContours.js.map +1 -0
  21. package/dist/glClipRectangle.d.ts +4 -0
  22. package/dist/glClipRectangle.d.ts.map +1 -0
  23. package/dist/glClipRectangle.js +68 -0
  24. package/dist/glClipRectangle.js.map +1 -0
  25. package/dist/glColorAdjustment.d.ts +3 -0
  26. package/dist/glColorAdjustment.d.ts.map +1 -0
  27. package/dist/glColorAdjustment.js +361 -0
  28. package/dist/glColorAdjustment.js.map +1 -0
  29. package/dist/glDefaultMaterial.d.ts +4 -0
  30. package/dist/glDefaultMaterial.d.ts.map +1 -0
  31. package/dist/glDefaultMaterial.js +20 -0
  32. package/dist/glDefaultMaterial.js.map +1 -0
  33. package/dist/glNode2D.d.ts +5 -0
  34. package/dist/glNode2D.d.ts.map +1 -0
  35. package/dist/glNode2D.js +41 -0
  36. package/dist/glNode2D.js.map +1 -0
  37. package/dist/glNode2DRegistration.d.ts +25 -0
  38. package/dist/glNode2DRegistration.d.ts.map +1 -0
  39. package/dist/glNode2DRegistration.js +51 -0
  40. package/dist/glNode2DRegistration.js.map +1 -0
  41. package/dist/glParticleEmitter2D.d.ts +4 -0
  42. package/dist/glParticleEmitter2D.d.ts.map +1 -0
  43. package/dist/glParticleEmitter2D.js +263 -0
  44. package/dist/glParticleEmitter2D.js.map +1 -0
  45. package/dist/glQuadBatch.d.ts +3 -0
  46. package/dist/glQuadBatch.d.ts.map +1 -0
  47. package/dist/glQuadBatch.js +92 -0
  48. package/dist/glQuadBatch.js.map +1 -0
  49. package/dist/glRichText.d.ts +8 -0
  50. package/dist/glRichText.d.ts.map +1 -0
  51. package/dist/glRichText.js +161 -0
  52. package/dist/glRichText.js.map +1 -0
  53. package/dist/glScale9Mapper.d.ts +3 -0
  54. package/dist/glScale9Mapper.d.ts.map +1 -0
  55. package/dist/glScale9Mapper.js +37 -0
  56. package/dist/glScale9Mapper.js.map +1 -0
  57. package/dist/glScale9Shape.d.ts +9 -0
  58. package/dist/glScale9Shape.d.ts.map +1 -0
  59. package/dist/glScale9Shape.js +118 -0
  60. package/dist/glScale9Shape.js.map +1 -0
  61. package/dist/glShape.d.ts +4 -0
  62. package/dist/glShape.d.ts.map +1 -0
  63. package/dist/glShape.js +146 -0
  64. package/dist/glShape.js.map +1 -0
  65. package/dist/glShapeMesh.d.ts +5 -0
  66. package/dist/glShapeMesh.d.ts.map +1 -0
  67. package/dist/glShapeMesh.js +114 -0
  68. package/dist/glShapeMesh.js.map +1 -0
  69. package/dist/glSprite.d.ts +3 -0
  70. package/dist/glSprite.d.ts.map +1 -0
  71. package/dist/glSprite.js +28 -0
  72. package/dist/glSprite.js.map +1 -0
  73. package/dist/glSpriteBatch.d.ts +11 -0
  74. package/dist/glSpriteBatch.d.ts.map +1 -0
  75. package/dist/glSpriteBatch.js +277 -0
  76. package/dist/glSpriteBatch.js.map +1 -0
  77. package/dist/glSpriteRenderer.d.ts +3 -0
  78. package/dist/glSpriteRenderer.d.ts.map +1 -0
  79. package/dist/glSpriteRenderer.js +54 -0
  80. package/dist/glSpriteRenderer.js.map +1 -0
  81. package/dist/glTestHelper.d.ts +9 -0
  82. package/dist/glTestHelper.d.ts.map +1 -0
  83. package/dist/glTestHelper.js +17 -0
  84. package/dist/glTestHelper.js.map +1 -0
  85. package/dist/glTextInput.d.ts +4 -0
  86. package/dist/glTextInput.d.ts.map +1 -0
  87. package/dist/glTextInput.js +43 -0
  88. package/dist/glTextInput.js.map +1 -0
  89. package/dist/glTextLabel.d.ts +4 -0
  90. package/dist/glTextLabel.d.ts.map +1 -0
  91. package/dist/glTextLabel.js +141 -0
  92. package/dist/glTextLabel.js.map +1 -0
  93. package/dist/glTilemap.d.ts +3 -0
  94. package/dist/glTilemap.d.ts.map +1 -0
  95. package/dist/glTilemap.js +79 -0
  96. package/dist/glTilemap.js.map +1 -0
  97. package/dist/glVelocity.d.ts +22 -0
  98. package/dist/glVelocity.d.ts.map +1 -0
  99. package/dist/glVelocity.js +319 -0
  100. package/dist/glVelocity.js.map +1 -0
  101. package/dist/glVideo.d.ts +6 -0
  102. package/dist/glVideo.d.ts.map +1 -0
  103. package/dist/glVideo.js +62 -0
  104. package/dist/glVideo.js.map +1 -0
  105. package/dist/index.d.ts +27 -0
  106. package/dist/index.d.ts.map +1 -0
  107. package/dist/index.js +28 -0
  108. package/dist/index.js.map +1 -0
  109. package/dist/moduleMockTestHelper.d.ts +15 -0
  110. package/dist/moduleMockTestHelper.d.ts.map +1 -0
  111. package/dist/moduleMockTestHelper.js +25 -0
  112. package/dist/moduleMockTestHelper.js.map +1 -0
  113. package/package.json +60 -0
  114. package/src/enableGlColorAdjustmentGuards.test.ts +76 -0
  115. package/src/glBitmap.test.ts +136 -0
  116. package/src/glCache.test.ts +234 -0
  117. package/src/glClip.test.ts +101 -0
  118. package/src/glClipContours.test.ts +61 -0
  119. package/src/glClipRectangle.test.ts +47 -0
  120. package/src/glColorAdjustment.test.ts +166 -0
  121. package/src/glDefaultMaterial.test.ts +19 -0
  122. package/src/glNode2D.test.ts +85 -0
  123. package/src/glNode2DRegistration.test.ts +132 -0
  124. package/src/glParticleEmitter2D.test.ts +122 -0
  125. package/src/glQuadBatch.test.ts +132 -0
  126. package/src/glRichText.test.ts +140 -0
  127. package/src/glScale9Mapper.test.ts +20 -0
  128. package/src/glScale9Shape.test.ts +90 -0
  129. package/src/glShape.test.ts +116 -0
  130. package/src/glShapeMesh.test.ts +164 -0
  131. package/src/glSprite.test.ts +79 -0
  132. package/src/glSpriteBatch.test.ts +249 -0
  133. package/src/glSpriteRenderer.test.ts +89 -0
  134. package/src/glTextInput.test.ts +51 -0
  135. package/src/glTextLabel.test.ts +156 -0
  136. package/src/glTilemap.test.ts +127 -0
  137. package/src/glVelocity.test.ts +156 -0
  138. package/src/glVideo.test.ts +98 -0
@@ -0,0 +1,51 @@
1
+ import { registerRenderer } from '@flighthq/render';
2
+ import { BitmapKind, DisplayObjectKind, ParticleEmitter2DKind, QuadBatchKind, RenderCacheKind, RichTextKind, Scale9ShapeKind, ShapeKind, SpriteKind, TextLabelKind, TilemapKind, VideoKind, } from '@flighthq/types';
3
+ import { defaultGlBitmapRenderer } from './glBitmap';
4
+ import { defaultGlRenderCacheRenderer } from './glCache';
5
+ import { defaultGlScene2DRenderer } from './glNode2D';
6
+ import { defaultGlParticleEmitter2DRenderer } from './glParticleEmitter2D';
7
+ import { defaultGlQuadBatchRenderer } from './glQuadBatch';
8
+ import { defaultGlRichTextRenderer } from './glRichText';
9
+ import { defaultGlScale9ShapeRenderer } from './glScale9Shape';
10
+ import { defaultGlShapeRenderer } from './glShape';
11
+ import { defaultGlSpriteRenderer } from './glSpriteRenderer';
12
+ import { defaultGlTextLabelRenderer } from './glTextLabel';
13
+ import { defaultGlTilemapRenderer } from './glTilemap';
14
+ import { defaultGlVideoRenderer } from './glVideo';
15
+ /**
16
+ * Registers every built-in GL display-object renderer against its kind in `state`.
17
+ *
18
+ * This is the convenience path — the tree-shakable golden path is registering each
19
+ * `default*Renderer` descriptor individually via `registerRenderer`. Call this when you
20
+ * want all renderers registered in one step and do not need to tree-shake individual leaf
21
+ * types. The default material must be separately registered via `registerDefaultGlMaterial`.
22
+ *
23
+ * Registered renderers:
24
+ * - `BitmapKind` → `defaultGlBitmapRenderer`
25
+ * - `DisplayObjectKind` → `defaultGlScene2DRenderer`
26
+ * - `ParticleEmitter2DKind`→ `defaultGlParticleEmitter2DRenderer`
27
+ * - `QuadBatchKind` → `defaultGlQuadBatchRenderer`
28
+ * - `RenderCacheKind` → `defaultGlRenderCacheRenderer`
29
+ * - `RichTextKind` → `defaultGlRichTextRenderer`
30
+ * - `Scale9ShapeKind` → `defaultGlScale9ShapeRenderer`
31
+ * - `ShapeKind` → `defaultGlShapeRenderer`
32
+ * - `SpriteKind` → `defaultGlSpriteRenderer`
33
+ * - `TextLabelKind` → `defaultGlTextLabelRenderer`
34
+ * - `TilemapKind` → `defaultGlTilemapRenderer`
35
+ * - `VideoKind` → `defaultGlVideoRenderer`
36
+ */
37
+ export function registerGlScene2DRenderers(state) {
38
+ registerRenderer(state, BitmapKind, defaultGlBitmapRenderer);
39
+ registerRenderer(state, DisplayObjectKind, defaultGlScene2DRenderer);
40
+ registerRenderer(state, ParticleEmitter2DKind, defaultGlParticleEmitter2DRenderer);
41
+ registerRenderer(state, QuadBatchKind, defaultGlQuadBatchRenderer);
42
+ registerRenderer(state, RenderCacheKind, defaultGlRenderCacheRenderer);
43
+ registerRenderer(state, RichTextKind, defaultGlRichTextRenderer);
44
+ registerRenderer(state, Scale9ShapeKind, defaultGlScale9ShapeRenderer);
45
+ registerRenderer(state, ShapeKind, defaultGlShapeRenderer);
46
+ registerRenderer(state, SpriteKind, defaultGlSpriteRenderer);
47
+ registerRenderer(state, TextLabelKind, defaultGlTextLabelRenderer);
48
+ registerRenderer(state, TilemapKind, defaultGlTilemapRenderer);
49
+ registerRenderer(state, VideoKind, defaultGlVideoRenderer);
50
+ }
51
+ //# sourceMappingURL=glNode2DRegistration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glNode2DRegistration.js","sourceRoot":"","sources":["../src/glNode2DRegistration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,EACb,eAAe,EACf,YAAY,EACZ,eAAe,EACf,SAAS,EACT,UAAU,EACV,aAAa,EACb,WAAW,EACX,SAAS,GACV,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,4BAA4B,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,kCAAkC,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,4BAA4B,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,0BAA0B,CAAC,KAAoB;IAC7D,gBAAgB,CAAC,KAAK,EAAE,UAAU,EAAE,uBAAuB,CAAC,CAAC;IAC7D,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,EAAE,wBAAwB,CAAC,CAAC;IACrE,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,EAAE,kCAAkC,CAAC,CAAC;IACnF,gBAAgB,CAAC,KAAK,EAAE,aAAa,EAAE,0BAA0B,CAAC,CAAC;IACnE,gBAAgB,CAAC,KAAK,EAAE,eAAe,EAAE,4BAA4B,CAAC,CAAC;IACvE,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,yBAAyB,CAAC,CAAC;IACjE,gBAAgB,CAAC,KAAK,EAAE,eAAe,EAAE,4BAA4B,CAAC,CAAC;IACvE,gBAAgB,CAAC,KAAK,EAAE,SAAS,EAAE,sBAAsB,CAAC,CAAC;IAC3D,gBAAgB,CAAC,KAAK,EAAE,UAAU,EAAE,uBAAuB,CAAC,CAAC;IAC7D,gBAAgB,CAAC,KAAK,EAAE,aAAa,EAAE,0BAA0B,CAAC,CAAC;IACnE,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,wBAAwB,CAAC,CAAC;IAC/D,gBAAgB,CAAC,KAAK,EAAE,SAAS,EAAE,sBAAsB,CAAC,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { GlRenderState, RenderProxy2D, SpriteRenderer } from '@flighthq/types';
2
+ export declare function drawGlParticleEmitter2D(state: GlRenderState, renderProxy: RenderProxy2D): void;
3
+ export declare const defaultGlParticleEmitter2DRenderer: SpriteRenderer;
4
+ //# sourceMappingURL=glParticleEmitter2D.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glParticleEmitter2D.d.ts","sourceRoot":"","sources":["../src/glParticleEmitter2D.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAqB,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AA0HvG,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,GAAG,IAAI,CA2J9F;AAED,eAAO,MAAM,kCAAkC,EAAE,cAMhD,CAAC"}
@@ -0,0 +1,263 @@
1
+ import { hasImageResourcePixels } from '@flighthq/image';
2
+ import { noopRendererData } from '@flighthq/render';
3
+ import { bindGlImageResourceTexture } from '@flighthq/render-gl';
4
+ import { createGlProgram } from '@flighthq/render-gl';
5
+ import { getGlRenderStateRuntime } from '@flighthq/render-gl';
6
+ import { flushGlSpriteBatch } from './glSpriteBatch';
7
+ // Per-instance layout (14 floats = 56 bytes):
8
+ // [0] px float
9
+ // [1] py float
10
+ // [2] cosScale float
11
+ // [3] sinScale float
12
+ // [4] r float
13
+ // [5] g float
14
+ // [6] b float
15
+ // [7] alpha float
16
+ // [8] u0 float
17
+ // [9] v0 float
18
+ // [10] u1 float
19
+ // [11] v1 float
20
+ // [12] width float
21
+ // [13] height float
22
+ const INSTANCE_FLOATS = 14;
23
+ const INSTANCE_STRIDE = INSTANCE_FLOATS * 4; // bytes
24
+ const PARTICLE_VS = `#version 300 es
25
+ precision mediump float;
26
+
27
+ in vec2 a_corner;
28
+
29
+ layout(location = 1) in vec2 a_pos;
30
+ layout(location = 2) in float a_cosScale;
31
+ layout(location = 3) in float a_sinScale;
32
+ layout(location = 4) in vec4 a_color;
33
+ layout(location = 5) in vec4 a_uvRect;
34
+ layout(location = 6) in vec2 a_size;
35
+
36
+ uniform mat3 u_world;
37
+
38
+ out vec2 v_uv;
39
+ out vec4 v_color;
40
+
41
+ void main() {
42
+ float lx = a_corner.x * a_size.x;
43
+ float ly = a_corner.y * a_size.y;
44
+ float rx = a_cosScale * lx - a_sinScale * ly + a_pos.x;
45
+ float ry = a_sinScale * lx + a_cosScale * ly + a_pos.y;
46
+ vec3 clip = u_world * vec3(rx, ry, 1.0);
47
+ gl_Position = vec4(clip.xy, 0.0, 1.0);
48
+ v_uv = mix(a_uvRect.xy, a_uvRect.zw, a_corner);
49
+ v_color = a_color;
50
+ }`;
51
+ // Premultiplied-alpha tint: tex.rgb is already multiplied by tex.a, so the
52
+ // correct tinted premultiplied output is (tex.rgb * color.rgb * alpha, tex.a * alpha).
53
+ const PARTICLE_FS = `#version 300 es
54
+ precision mediump float;
55
+
56
+ in vec2 v_uv;
57
+ in vec4 v_color;
58
+
59
+ uniform sampler2D u_texture;
60
+ uniform bool u_straightTextureAlpha;
61
+
62
+ out vec4 fragColor;
63
+
64
+ void main() {
65
+ vec4 tex = texture(u_texture, v_uv);
66
+ if (u_straightTextureAlpha) tex.rgb *= tex.a;
67
+ fragColor = vec4(tex.rgb * v_color.rgb, tex.a) * v_color.a;
68
+ if (fragColor.a <= 0.0) discard;
69
+ }`;
70
+ function compileParticleShader(gl) {
71
+ const program = createGlProgram(gl, PARTICLE_VS, PARTICLE_FS, 'Particle emitter');
72
+ return {
73
+ program,
74
+ locCorner: gl.getAttribLocation(program, 'a_corner'),
75
+ locPos: 1, // layout(location = 1)
76
+ locCosScale: 2,
77
+ locSinScale: 3,
78
+ locColor: 4,
79
+ locUvRect: 5,
80
+ locSize: 6,
81
+ locWorldMatrix: gl.getUniformLocation(program, 'u_world'),
82
+ locTexture: gl.getUniformLocation(program, 'u_texture'),
83
+ locStraightTextureAlpha: gl.getUniformLocation(program, 'u_straightTextureAlpha'),
84
+ };
85
+ }
86
+ function ensureParticleShader(state) {
87
+ const runtime = getGlRenderStateRuntime(state);
88
+ if (runtime.particleShader)
89
+ return runtime.particleShader;
90
+ const gl = state.gl;
91
+ runtime.particleShader = compileParticleShader(gl);
92
+ // Static corner buffer: (0,0),(1,0),(1,1),(0,1)
93
+ const cornerData = new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]);
94
+ const cornerBuf = gl.createBuffer();
95
+ gl.bindBuffer(gl.ARRAY_BUFFER, cornerBuf);
96
+ gl.bufferData(gl.ARRAY_BUFFER, cornerData, gl.STATIC_DRAW);
97
+ runtime.particleCornerBuffer = cornerBuf;
98
+ // Dynamic instance buffer — starts empty, grows as needed
99
+ runtime.particleInstanceBuffer = gl.createBuffer();
100
+ runtime.particleInstanceData = new Float32Array(0);
101
+ return runtime.particleShader;
102
+ }
103
+ function ensureInstanceCapacity(state, count) {
104
+ const runtime = getGlRenderStateRuntime(state);
105
+ const gl = state.gl;
106
+ const needed = count * INSTANCE_FLOATS;
107
+ if ((runtime.particleInstanceData?.length ?? 0) >= needed)
108
+ return;
109
+ // Double capacity each time.
110
+ const newSize = Math.max(needed, (runtime.particleInstanceData?.length ?? 0) * 2);
111
+ runtime.particleInstanceData = new Float32Array(newSize);
112
+ // Resize GPU buffer to match.
113
+ gl.bindBuffer(gl.ARRAY_BUFFER, runtime.particleInstanceBuffer);
114
+ gl.bufferData(gl.ARRAY_BUFFER, newSize * 4, gl.DYNAMIC_DRAW);
115
+ }
116
+ export function drawGlParticleEmitter2D(state, renderProxy) {
117
+ const runtime = getGlRenderStateRuntime(state);
118
+ const source = renderProxy.source;
119
+ const { atlas, alphas, colors, ids, particleCount, transforms } = source.data;
120
+ if (atlas === null || atlas.image === null || !hasImageResourcePixels(atlas.image) || particleCount === 0)
121
+ return;
122
+ const shader = ensureParticleShader(state);
123
+ ensureInstanceCapacity(state, particleCount);
124
+ state.applyBlendMode?.(state, renderProxy.blendMode);
125
+ bindGlImageResourceTexture(state, atlas.image);
126
+ const gl = state.gl;
127
+ const regions = atlas.regions;
128
+ const numRegions = regions.length;
129
+ const nodeAlpha = renderProxy.alpha;
130
+ const t = renderProxy.transform2D;
131
+ const viewport = runtime.renderTargetViewport ?? state.canvas;
132
+ const iw = 1 / (atlas.image.width || 1);
133
+ const ih = 1 / (atlas.image.height || 1);
134
+ const instanceData = runtime.particleInstanceData;
135
+ // Build per-instance CPU buffer.
136
+ let base = 0;
137
+ let drawCount = 0;
138
+ for (let i = 0; i < particleCount; i++) {
139
+ const id = ids[i];
140
+ if (id < 0 || id >= numRegions)
141
+ continue;
142
+ const region = regions[id];
143
+ if (region.width <= 0 || region.height <= 0)
144
+ continue;
145
+ const tt = i * 4;
146
+ const px = transforms[tt];
147
+ const py = transforms[tt + 1];
148
+ const rotation = transforms[tt + 2];
149
+ const scale = transforms[tt + 3];
150
+ const cosR = Math.cos(rotation) * scale;
151
+ const sinR = Math.sin(rotation) * scale;
152
+ // Fold the emitter node transform into cosScale/sinScale and pos.
153
+ // particle local → emitter world (then clip via u_world).
154
+ // Full composition would need to pass the raw particle params and apply
155
+ // the node transform in the shader via u_world. We do exactly that:
156
+ // u_world encodes (t × viewport projection), so we pass raw local coords.
157
+ const ct = i * 3;
158
+ const hasColors = colors != null && colors.length > ct + 2;
159
+ const r = hasColors ? colors[ct] : 1;
160
+ const g = hasColors ? colors[ct + 1] : 1;
161
+ const b = hasColors ? colors[ct + 2] : 1;
162
+ instanceData[base] = px;
163
+ instanceData[base + 1] = py;
164
+ instanceData[base + 2] = cosR;
165
+ instanceData[base + 3] = sinR;
166
+ instanceData[base + 4] = r;
167
+ instanceData[base + 5] = g;
168
+ instanceData[base + 6] = b;
169
+ instanceData[base + 7] = nodeAlpha * alphas[i];
170
+ instanceData[base + 8] = region.x * iw;
171
+ instanceData[base + 9] = region.y * ih;
172
+ instanceData[base + 10] = (region.x + region.width) * iw;
173
+ instanceData[base + 11] = (region.y + region.height) * ih;
174
+ instanceData[base + 12] = region.width;
175
+ instanceData[base + 13] = region.height;
176
+ base += INSTANCE_FLOATS;
177
+ drawCount++;
178
+ }
179
+ if (drawCount === 0)
180
+ return;
181
+ // Upload instance data.
182
+ gl.bindBuffer(gl.ARRAY_BUFFER, runtime.particleInstanceBuffer);
183
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, instanceData, 0, drawCount * INSTANCE_FLOATS);
184
+ // Activate particle shader program.
185
+ if (runtime.currentProgram !== shader.program) {
186
+ gl.useProgram(shader.program);
187
+ runtime.currentProgram = shader.program;
188
+ }
189
+ // Compute and upload the emitter node → clip-space world matrix.
190
+ // In world-space mode particle positions ARE already in world (pixel) space,
191
+ // so we skip the node transform and map directly through the viewport.
192
+ const clipW = 2 / viewport.width;
193
+ const clipH = 2 / viewport.height;
194
+ const m = runtime.matrixArray;
195
+ if (source.data.worldSpace) {
196
+ m[0] = clipW;
197
+ m[1] = 0;
198
+ m[2] = 0;
199
+ m[3] = 0;
200
+ m[4] = -clipH;
201
+ m[5] = 0;
202
+ m[6] = -1;
203
+ m[7] = 1;
204
+ m[8] = 1;
205
+ }
206
+ else {
207
+ m[0] = t.a * clipW;
208
+ m[1] = -t.b * clipH;
209
+ m[2] = 0;
210
+ m[3] = t.c * clipW;
211
+ m[4] = -t.d * clipH;
212
+ m[5] = 0;
213
+ m[6] = t.tx * clipW - 1;
214
+ m[7] = -t.ty * clipH + 1;
215
+ m[8] = 1;
216
+ }
217
+ gl.uniformMatrix3fv(shader.locWorldMatrix, false, m);
218
+ gl.uniform1i(shader.locTexture, 0);
219
+ gl.uniform1i(shader.locStraightTextureAlpha, runtime.currentTextureStraightAlpha ? 1 : 0);
220
+ // Per-vertex: corner buffer.
221
+ gl.bindBuffer(gl.ARRAY_BUFFER, runtime.particleCornerBuffer);
222
+ gl.enableVertexAttribArray(shader.locCorner);
223
+ gl.vertexAttribPointer(shader.locCorner, 2, gl.FLOAT, false, 8, 0);
224
+ gl.vertexAttribDivisor(shader.locCorner, 0);
225
+ // Per-instance: instance buffer.
226
+ gl.bindBuffer(gl.ARRAY_BUFFER, runtime.particleInstanceBuffer);
227
+ gl.enableVertexAttribArray(shader.locPos);
228
+ gl.vertexAttribPointer(shader.locPos, 2, gl.FLOAT, false, INSTANCE_STRIDE, 0);
229
+ gl.vertexAttribDivisor(shader.locPos, 1);
230
+ gl.enableVertexAttribArray(shader.locCosScale);
231
+ gl.vertexAttribPointer(shader.locCosScale, 1, gl.FLOAT, false, INSTANCE_STRIDE, 8);
232
+ gl.vertexAttribDivisor(shader.locCosScale, 1);
233
+ gl.enableVertexAttribArray(shader.locSinScale);
234
+ gl.vertexAttribPointer(shader.locSinScale, 1, gl.FLOAT, false, INSTANCE_STRIDE, 12);
235
+ gl.vertexAttribDivisor(shader.locSinScale, 1);
236
+ gl.enableVertexAttribArray(shader.locColor);
237
+ gl.vertexAttribPointer(shader.locColor, 4, gl.FLOAT, false, INSTANCE_STRIDE, 16);
238
+ gl.vertexAttribDivisor(shader.locColor, 1);
239
+ gl.enableVertexAttribArray(shader.locUvRect);
240
+ gl.vertexAttribPointer(shader.locUvRect, 4, gl.FLOAT, false, INSTANCE_STRIDE, 32);
241
+ gl.vertexAttribDivisor(shader.locUvRect, 1);
242
+ gl.enableVertexAttribArray(shader.locSize);
243
+ gl.vertexAttribPointer(shader.locSize, 2, gl.FLOAT, false, INSTANCE_STRIDE, 48);
244
+ gl.vertexAttribDivisor(shader.locSize, 1);
245
+ // Single draw call for all particles.
246
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, runtime.quadIndexBuffer);
247
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0, drawCount);
248
+ // Reset divisors so other renderers are not affected.
249
+ gl.vertexAttribDivisor(shader.locPos, 0);
250
+ gl.vertexAttribDivisor(shader.locCosScale, 0);
251
+ gl.vertexAttribDivisor(shader.locSinScale, 0);
252
+ gl.vertexAttribDivisor(shader.locColor, 0);
253
+ gl.vertexAttribDivisor(shader.locUvRect, 0);
254
+ gl.vertexAttribDivisor(shader.locSize, 0);
255
+ }
256
+ export const defaultGlParticleEmitter2DRenderer = {
257
+ createData: noopRendererData,
258
+ submit(state, node) {
259
+ flushGlSpriteBatch(state);
260
+ drawGlParticleEmitter2D(state, node);
261
+ },
262
+ };
263
+ //# sourceMappingURL=glParticleEmitter2D.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glParticleEmitter2D.js","sourceRoot":"","sources":["../src/glParticleEmitter2D.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { SpriteRenderer } from '@flighthq/types';
2
+ export declare const defaultGlQuadBatchRenderer: SpriteRenderer;
3
+ //# sourceMappingURL=glQuadBatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glQuadBatch.d.ts","sourceRoot":"","sources":["../src/glQuadBatch.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAA2D,cAAc,EAAE,MAAM,iBAAiB,CAAC;AA6G/G,eAAO,MAAM,0BAA0B,EAAE,cAIxC,CAAC"}
@@ -0,0 +1,92 @@
1
+ import { hasImageResourcePixels } from '@flighthq/image';
2
+ import { noopRendererData } from '@flighthq/render';
3
+ import { resolveGlMaterialRenderer } from '@flighthq/render-gl';
4
+ import { getGlRenderStateRuntime } from '@flighthq/render-gl';
5
+ import { BatchFormat } from '@flighthq/types';
6
+ import { ensureGlQuadBatchShader, packGlSpriteBatchMaterialInstance, prepareGlSpriteBatchWrite, recordGlSpriteBatchColorTransform, } from './glSpriteBatch';
7
+ // Per-instance layout (13 floats = 52 bytes, world-space transforms + per-instance alpha):
8
+ // [0-3] a, b, c, d — world-space 2D matrix
9
+ // [4-5] tx, ty — world-space translation
10
+ // [6-7] width, height — region size in pixels
11
+ // [8-11] u0,v0,u1,v1 — atlas UV rect
12
+ // [12] alpha — per-instance alpha
13
+ const INSTANCE_FLOATS = 13;
14
+ function submitGlQuadBatch(state, quadBatch) {
15
+ const runtime = getGlRenderStateRuntime(state);
16
+ const source = quadBatch.source;
17
+ const data = source.data;
18
+ const { atlas, instanceCount, ids, transforms } = data;
19
+ if (atlas === null || atlas.image === null || !hasImageResourcePixels(atlas.image) || instanceCount === 0)
20
+ return;
21
+ ensureGlQuadBatchShader(state);
22
+ const material = quadBatch.material;
23
+ const materialRenderer = resolveGlMaterialRenderer(state, material);
24
+ if (materialRenderer === null)
25
+ return;
26
+ const nodeMaterialData = quadBatch.materialData;
27
+ // Per-quad color transforms, overriding the node-level tint for the quads that carry one.
28
+ const perQuadColorTransform = data.materialData;
29
+ const nodeColorTransform = quadBatch.colorTransform;
30
+ const startCount = runtime.spriteBatchCount;
31
+ const base = prepareGlSpriteBatchWrite(state, atlas.image, quadBatch.blendMode, material, materialRenderer, instanceCount);
32
+ const regions = atlas.regions;
33
+ const numRegions = regions.length;
34
+ const iw = 1 / (atlas.image.width || 1);
35
+ const ih = 1 / (atlas.image.height || 1);
36
+ const instanceData = runtime.spriteBatchInstanceData;
37
+ const isVector2 = data.transformType === 'vector2';
38
+ const pt = quadBatch.transform2D;
39
+ const pa = pt.a, pb = pt.b, pc = pt.c, pd = pt.d, ptx = pt.tx, pty = pt.ty;
40
+ const alpha = quadBatch.alpha;
41
+ let writeBase = base;
42
+ let drawCount = 0;
43
+ for (let i = 0; i < instanceCount; i++) {
44
+ const id = ids[i];
45
+ if (id < 0 || id >= numRegions)
46
+ continue;
47
+ const region = regions[id];
48
+ if (region.width <= 0 || region.height <= 0)
49
+ continue;
50
+ if (isVector2) {
51
+ const dx = transforms[i * 2], dy = transforms[i * 2 + 1];
52
+ instanceData[writeBase] = pa;
53
+ instanceData[writeBase + 1] = pb;
54
+ instanceData[writeBase + 2] = pc;
55
+ instanceData[writeBase + 3] = pd;
56
+ instanceData[writeBase + 4] = pa * dx + pc * dy + ptx;
57
+ instanceData[writeBase + 5] = pb * dx + pd * dy + pty;
58
+ }
59
+ else {
60
+ const offset = i * 6;
61
+ const la = transforms[offset], lb = transforms[offset + 1];
62
+ const lc = transforms[offset + 2], ld = transforms[offset + 3];
63
+ const ltx = transforms[offset + 4], lty = transforms[offset + 5];
64
+ instanceData[writeBase] = pa * la + pc * lb;
65
+ instanceData[writeBase + 1] = pb * la + pd * lb;
66
+ instanceData[writeBase + 2] = pa * lc + pc * ld;
67
+ instanceData[writeBase + 3] = pb * lc + pd * ld;
68
+ instanceData[writeBase + 4] = pa * ltx + pc * lty + ptx;
69
+ instanceData[writeBase + 5] = pb * ltx + pd * lty + pty;
70
+ }
71
+ instanceData[writeBase + 6] = region.width;
72
+ instanceData[writeBase + 7] = region.height;
73
+ instanceData[writeBase + 8] = region.x * iw;
74
+ instanceData[writeBase + 9] = region.y * ih;
75
+ instanceData[writeBase + 10] = (region.x + region.width) * iw;
76
+ instanceData[writeBase + 11] = (region.y + region.height) * ih;
77
+ instanceData[writeBase + 12] = alpha;
78
+ packGlSpriteBatchMaterialInstance(state, nodeMaterialData, startCount + drawCount);
79
+ // Per-quad tint overrides the node-level tint (null → the node's, itself possibly null → untinted).
80
+ const colorTransform = perQuadColorTransform?.[i] ?? nodeColorTransform;
81
+ recordGlSpriteBatchColorTransform(state, colorTransform, startCount + drawCount);
82
+ writeBase += INSTANCE_FLOATS;
83
+ drawCount++;
84
+ }
85
+ runtime.spriteBatchCount += drawCount;
86
+ }
87
+ export const defaultGlQuadBatchRenderer = {
88
+ format: BatchFormat.Quad,
89
+ createData: noopRendererData,
90
+ submit: submitGlQuadBatch,
91
+ };
92
+ //# sourceMappingURL=glQuadBatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glQuadBatch.js","sourceRoot":"","sources":["../src/glQuadBatch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { Scene2DRenderer, GlRenderState, GlRichTextOverlay, Renderable, RendererData, RenderProxy2D } from '@flighthq/types';
2
+ export declare function createGlRichTextData(_state: GlRenderState, _source: Renderable): RendererData;
3
+ export declare function destroyGlRichTextData(state: GlRenderState, data: RendererData): void;
4
+ export declare function drawGlRichText(state: GlRenderState, renderProxy: RenderProxy2D): void;
5
+ export declare function drawGlRichTextWithOverlay(state: GlRenderState, renderProxy: RenderProxy2D, overlay?: GlRichTextOverlay): void;
6
+ export declare function registerGlTextInputOverlay(overlay: GlRichTextOverlay): void;
7
+ export declare const defaultGlRichTextRenderer: Scene2DRenderer;
8
+ //# sourceMappingURL=glRichText.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glRichText.d.ts","sourceRoot":"","sources":["../src/glRichText.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,aAAa,EAKd,MAAM,iBAAiB,CAAC;AAczB,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,GAAG,YAAY,CAE7F;AAGD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CAGpF;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,GAAG,IAAI,CASrF;AAED,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,aAAa,EACpB,WAAW,EAAE,aAAa,EAC1B,OAAO,CAAC,EAAE,iBAAiB,GAC1B,IAAI,CAqDN;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAE3E;AAED,eAAO,MAAM,yBAAyB,EAAE,eAIvC,CAAC"}
@@ -0,0 +1,161 @@
1
+ import { computeRgbHexString } from '@flighthq/color';
2
+ import { createGlTexture, drawGlQuad, updateGlTexture, useGlProgram } from '@flighthq/render-gl';
3
+ import { resolveGlShader } from '@flighthq/render-gl';
4
+ import { computeTextFormatFontString } from '@flighthq/text';
5
+ import { getRichTextPasswordCharacter, getRichTextRuntime } from '@flighthq/text';
6
+ import { computeRichTextContent, computeTextBoundsHeight, computeTextBoundsOffsetX, computeTextBoundsWidth, computeTextLayout, getRichTextContent, getRichTextScrollYOffset, getTextLayoutResult, } from '@flighthq/textlayout';
7
+ import { flushGlSpriteBatch } from './glSpriteBatch';
8
+ let _offscreenCanvas = null;
9
+ let _offscreenCtx = null;
10
+ let _webglTextInputOverlay = null;
11
+ export function createGlRichTextData(_state, _source) {
12
+ return { texture: null };
13
+ }
14
+ // Frees the GPU texture this rich text node owns when it is torn down via disposeScene2DRender.
15
+ export function destroyGlRichTextData(state, data) {
16
+ const { texture } = data;
17
+ if (texture !== null)
18
+ state.gl.deleteTexture(texture);
19
+ }
20
+ export function drawGlRichText(state, renderProxy) {
21
+ // The editable-input overlay rasterizes onto the offscreen field texture, so it is passed into the
22
+ // rasterization pass — only when the input slot is present. registerGlTextInputOverlay
23
+ // (enableGlTextInput) installs it; a static RichText leaves the slot null and pulls no text-input code.
24
+ const overlay = _webglTextInputOverlay !== null && getRichTextRuntime(renderProxy.source).input !== null
25
+ ? _webglTextInputOverlay
26
+ : undefined;
27
+ drawGlRichTextWithOverlay(state, renderProxy, overlay);
28
+ }
29
+ export function drawGlRichTextWithOverlay(state, renderProxy, overlay) {
30
+ flushGlSpriteBatch(state);
31
+ const source = renderProxy.source;
32
+ const data = source.data;
33
+ const richTextRuntime = getRichTextRuntime(source);
34
+ const content = getRichTextContent(richTextRuntime);
35
+ computeRichTextContent(content, data, getRichTextPasswordCharacter(source));
36
+ if (content.text.length === 0 && !data.background && !data.border)
37
+ return;
38
+ const result = layoutRichText(source, richTextRuntime, content.text, content.formatRanges);
39
+ const fieldW = Math.ceil(computeTextBoundsWidth(data, result));
40
+ const fieldH = Math.ceil(computeTextBoundsHeight(data, result));
41
+ if (fieldW <= 0 || fieldH <= 0)
42
+ return;
43
+ const pixelRatio = state.pixelRatio;
44
+ const offCtx = getOffscreenCanvas(fieldW, fieldH, pixelRatio);
45
+ offCtx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
46
+ offCtx.clearRect(0, 0, fieldW, fieldH);
47
+ if (data.background) {
48
+ offCtx.fillStyle = computeRgbHexString(data.backgroundColor);
49
+ offCtx.fillRect(0, 0, fieldW, fieldH);
50
+ }
51
+ if (data.border) {
52
+ offCtx.strokeStyle = computeRgbHexString(data.borderColor);
53
+ offCtx.lineWidth = 1;
54
+ offCtx.strokeRect(0, 0, fieldW, fieldH);
55
+ }
56
+ if (content.text.length > 0) {
57
+ drawRichTextToCanvas(offCtx, source, result, fieldW, fieldH, content.text);
58
+ }
59
+ overlay?.(offCtx, source, result, fieldW, fieldH, content.text);
60
+ const shader = resolveGlShader(state, renderProxy);
61
+ useGlProgram(state, shader);
62
+ if (renderProxy.rendererData === null)
63
+ return;
64
+ const richTextData = renderProxy.rendererData;
65
+ let texture = richTextData.texture;
66
+ if (texture === null) {
67
+ texture = createGlTexture(state);
68
+ richTextData.texture = texture;
69
+ }
70
+ updateGlTexture(state, texture, _offscreenCanvas);
71
+ shader.bind(state.gl, state, renderProxy);
72
+ // Anchor the field box for autoSize 'right'/'center' so the rendered quad lines up with the local
73
+ // bounds (computeRichTextLocalBoundsRectangle applies the same offset). Zero for 'none'/'left'.
74
+ const offsetX = computeTextBoundsOffsetX(data, result);
75
+ drawGlQuad(state, offsetX, 0, offsetX + fieldW, fieldH, 0, 0, 1, 1);
76
+ }
77
+ export function registerGlTextInputOverlay(overlay) {
78
+ _webglTextInputOverlay = overlay;
79
+ }
80
+ export const defaultGlRichTextRenderer = {
81
+ createData: createGlRichTextData,
82
+ destroyData: destroyGlRichTextData,
83
+ submit: drawGlRichText,
84
+ };
85
+ function drawRichTextToCanvas(context, source, result, fieldW, fieldH, text) {
86
+ const data = source.data;
87
+ const firstVisibleLine = data.scrollV - 1;
88
+ const scrollYOffset = firstVisibleLine > 0 ? getRichTextScrollYOffset(result.lineHeights, firstVisibleLine) : 0;
89
+ const scrollXOffset = data.scrollH;
90
+ context.save();
91
+ context.beginPath();
92
+ context.rect(0, 0, fieldW, fieldH);
93
+ context.clip();
94
+ context.textBaseline = 'alphabetic';
95
+ context.textAlign = 'start';
96
+ for (const group of result.groups) {
97
+ if (group.lineIndex < firstVisibleLine)
98
+ continue;
99
+ context.font = computeTextFormatFontString(group.format);
100
+ context.fillStyle = computeRgbHexString(group.format.color ?? data.textColor);
101
+ const slice = text.substring(group.startIndex, group.endIndex);
102
+ const x = group.offsetX - scrollXOffset;
103
+ const y = group.offsetY + group.ascent - scrollYOffset;
104
+ context.fillText(slice, x, y);
105
+ if (group.format.underline || group.format.strikethrough) {
106
+ context.strokeStyle = computeRgbHexString(group.format.color ?? data.textColor);
107
+ context.lineWidth = Math.max(1, (group.format.size ?? 12) / 16);
108
+ if (group.format.underline) {
109
+ const lineY = y + group.descent;
110
+ context.beginPath();
111
+ context.moveTo(x, lineY);
112
+ context.lineTo(x + group.width, lineY);
113
+ context.stroke();
114
+ }
115
+ // Strikethrough sits ~35% of the ascent above the baseline — through the middle of the glyphs,
116
+ // matching scene2d-canvas's canvasRichText.
117
+ if (group.format.strikethrough) {
118
+ const lineY = y - group.ascent * 0.35;
119
+ context.beginPath();
120
+ context.moveTo(x, lineY);
121
+ context.lineTo(x + group.width, lineY);
122
+ context.stroke();
123
+ }
124
+ }
125
+ }
126
+ context.restore();
127
+ }
128
+ function layoutRichText(source, richTextRuntime, text, formatRanges) {
129
+ const data = source.data;
130
+ const measure = (value, format) => {
131
+ const context = getOffscreenCanvas(1, 1);
132
+ context.font = computeTextFormatFontString(format);
133
+ return context.measureText(value).width;
134
+ };
135
+ const result = getTextLayoutResult(richTextRuntime);
136
+ computeTextLayout(result, {
137
+ text,
138
+ formatRanges,
139
+ width: data.width,
140
+ height: data.height,
141
+ measure,
142
+ multiline: data.multiline,
143
+ verticalAlign: data.autoSize === 'none' ? data.verticalAlign : 'top',
144
+ wordWrap: data.wordWrap,
145
+ });
146
+ return result;
147
+ }
148
+ function getOffscreenCanvas(width, height, pixelRatio = 1) {
149
+ if (!_offscreenCanvas) {
150
+ _offscreenCanvas = document.createElement('canvas');
151
+ _offscreenCtx = _offscreenCanvas.getContext('2d');
152
+ }
153
+ const pw = Math.ceil(width * pixelRatio);
154
+ const ph = Math.ceil(height * pixelRatio);
155
+ if (_offscreenCanvas.width !== pw)
156
+ _offscreenCanvas.width = pw;
157
+ if (_offscreenCanvas.height !== ph)
158
+ _offscreenCanvas.height = ph;
159
+ return _offscreenCtx;
160
+ }
161
+ //# sourceMappingURL=glRichText.js.map