@bloopjs/toodle 0.1.2 → 0.1.3

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 (49) hide show
  1. package/dist/Toodle.d.ts +1 -1
  2. package/dist/Toodle.d.ts.map +1 -1
  3. package/dist/backends/ITextShader.d.ts +15 -0
  4. package/dist/backends/ITextShader.d.ts.map +1 -0
  5. package/dist/backends/mod.d.ts +1 -0
  6. package/dist/backends/mod.d.ts.map +1 -1
  7. package/dist/backends/webgl2/WebGLTextShader.d.ts +20 -0
  8. package/dist/backends/webgl2/WebGLTextShader.d.ts.map +1 -0
  9. package/dist/backends/webgl2/mod.d.ts +1 -0
  10. package/dist/backends/webgl2/mod.d.ts.map +1 -1
  11. package/dist/{text → backends/webgpu}/FontPipeline.d.ts +1 -1
  12. package/dist/backends/webgpu/FontPipeline.d.ts.map +1 -0
  13. package/dist/{text/TextShader.d.ts → backends/webgpu/WebGPUTextShader.d.ts} +7 -7
  14. package/dist/backends/webgpu/WebGPUTextShader.d.ts.map +1 -0
  15. package/dist/backends/webgpu/mod.d.ts +2 -0
  16. package/dist/backends/webgpu/mod.d.ts.map +1 -1
  17. package/dist/backends/webgpu/wgsl/text.wgsl.d.ts.map +1 -0
  18. package/dist/mod.d.ts +1 -1
  19. package/dist/mod.d.ts.map +1 -1
  20. package/dist/mod.js +1795 -1777
  21. package/dist/mod.js.map +15 -14
  22. package/dist/{text → scene}/TextNode.d.ts +5 -5
  23. package/dist/scene/TextNode.d.ts.map +1 -0
  24. package/dist/scene/mod.d.ts +1 -0
  25. package/dist/scene/mod.d.ts.map +1 -1
  26. package/dist/text/mod.d.ts +1 -3
  27. package/dist/text/mod.d.ts.map +1 -1
  28. package/dist/textures/AssetManager.d.ts +9 -6
  29. package/dist/textures/AssetManager.d.ts.map +1 -1
  30. package/package.json +1 -1
  31. package/src/Toodle.ts +1 -1
  32. package/src/backends/ITextShader.ts +15 -0
  33. package/src/backends/mod.ts +1 -0
  34. package/src/backends/webgl2/WebGLTextShader.ts +35 -0
  35. package/src/backends/webgl2/mod.ts +1 -0
  36. package/src/{text → backends/webgpu}/FontPipeline.ts +2 -2
  37. package/src/{text/TextShader.ts → backends/webgpu/WebGPUTextShader.ts} +14 -10
  38. package/src/backends/webgpu/mod.ts +2 -0
  39. package/src/mod.ts +1 -1
  40. package/src/{text → scene}/TextNode.ts +6 -6
  41. package/src/scene/mod.ts +1 -0
  42. package/src/text/mod.ts +1 -4
  43. package/src/textures/AssetManager.ts +38 -31
  44. package/dist/text/FontPipeline.d.ts.map +0 -1
  45. package/dist/text/TextNode.d.ts.map +0 -1
  46. package/dist/text/TextShader.d.ts.map +0 -1
  47. package/dist/text/text.wgsl.d.ts.map +0 -1
  48. /package/dist/{text → backends/webgpu/wgsl}/text.wgsl.d.ts +0 -0
  49. /package/src/{text → backends/webgpu/wgsl}/text.wgsl.ts +0 -0
@@ -1,12 +1,12 @@
1
+ import type { ITextShader } from "../backends/ITextShader";
1
2
  import type { Color } from "../coreTypes/Color";
2
- import { type NodeOptions, SceneNode } from "../scene/SceneNode";
3
- import type { MsdfFont } from "./MsdfFont";
4
- import type { TextFormatting } from "./TextFormatting";
5
- import type { TextShader } from "./TextShader";
3
+ import type { MsdfFont } from "../text/MsdfFont";
4
+ import type { TextFormatting } from "../text/TextFormatting";
5
+ import { type NodeOptions, SceneNode } from "./SceneNode";
6
6
  export declare const DEFAULT_FONT_SIZE = 14;
7
7
  export declare class TextNode extends SceneNode {
8
8
  #private;
9
- constructor(shader: TextShader, text: string, opts?: TextOptions);
9
+ constructor(shader: ITextShader, text: string, opts?: TextOptions);
10
10
  get text(): string;
11
11
  get formatting(): TextFormatting;
12
12
  get font(): MsdfFont;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TextNode.d.ts","sourceRoot":"","sources":["../../src/scene/TextNode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,KAAK,WAAW,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE1D,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC,qBAAa,QAAS,SAAQ,SAAS;;gBAKzB,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,WAAgB;IAgCrE,IAAI,IAAI,IAYO,MAAM,CAVpB;IAED,IAAI,UAAU,IAyBa,cAAc,CAvBxC;IAED,IAAI,IAAI,aAEP;IAED,IAAI,IAAI,CAAC,IAAI,EAAE,MAAM,EAMpB;IAED,IAAI,IAAI,IAIO,KAAK,CAFnB;IAED,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAGnB;IAED,IAAI,UAAU,CAAC,UAAU,EAAE,cAAc,EAGxC;CACF;AAED,MAAM,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,GAAG,cAAc,CAAC"}
@@ -2,4 +2,5 @@ export * from "./Camera";
2
2
  export * from "./QuadNode";
3
3
  export * from "./RenderComponent";
4
4
  export * from "./SceneNode";
5
+ export * from "./TextNode";
5
6
  //# sourceMappingURL=mod.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/scene/mod.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/scene/mod.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"}
@@ -1,4 +1,2 @@
1
- export type { TextOptions } from "./TextNode";
2
- export { TextNode } from "./TextNode";
3
- export { TextShader } from "./TextShader";
1
+ export { WebGPUTextShader as TextShader } from "../backends/webgpu/WebGPUTextShader";
4
2
  //# sourceMappingURL=mod.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/text/mod.ts"],"names":[],"mappings":"AAKA,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/text/mod.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,IAAI,UAAU,EAAE,MAAM,qCAAqC,CAAC"}
@@ -1,9 +1,9 @@
1
1
  import type { IRenderBackend } from "../backends/IRenderBackend";
2
+ import type { ITextShader } from "../backends/ITextShader";
2
3
  import type { Size } from "../coreTypes/Size";
3
4
  import type { Vec2 } from "../coreTypes/Vec2";
4
5
  import { QuadNode } from "../scene/QuadNode";
5
6
  import type { SceneNode } from "../scene/SceneNode";
6
- import { TextShader } from "../text/TextShader";
7
7
  import { Bundles } from "./Bundles";
8
8
  import type { AtlasBundleOpts, AtlasCoords, CpuTextureAtlas, TextureBundleOpts } from "./types";
9
9
  export type TextureId = string;
@@ -119,16 +119,19 @@ export declare class AssetManager {
119
119
  */
120
120
  unloadBundle(bundleId: BundleId): Promise<void>;
121
121
  /**
122
- * Load a font to the gpu
122
+ * Load a font for text rendering (WebGPU) or measurement only (WebGL).
123
123
  *
124
124
  * @param id - The id of the font to load
125
- * @param url - The url of the font to load
126
- * @param fallbackCharacter - The character to use as a fallback if the font does not contain a character to be rendererd
125
+ * @param url - The url of the font JSON to load
126
+ * @param fallbackCharacter - The character to use as a fallback if the font does not contain a character to be rendered
127
127
  *
128
- * @throws Error if using WebGL backend (fonts not supported in WebGL mode)
128
+ * @remarks
129
+ * On WebGPU backend, loads the full font for rendering.
130
+ * On WebGL backend, loads the font for text measurement only. Attempting to
131
+ * render text on WebGL will throw an error.
129
132
  */
130
133
  loadFont(id: string, url: URL, fallbackCharacter?: string): Promise<string>;
131
- getFont(id: string): TextShader;
134
+ getFont(id: string): ITextShader;
132
135
  validateTextureReference(node: SceneNode | QuadNode): void;
133
136
  /**
134
137
  * Advanced and niche features
@@ -1 +1 @@
1
- {"version":3,"file":"AssetManager.d.ts","sourceRoot":"","sources":["../../src/textures/AssetManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAGjE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAE9C,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAGpD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EACV,eAAe,EACf,WAAW,EACX,eAAe,EACf,iBAAiB,EAElB,MAAM,SAAS,CAAC;AAGjB,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC;AAC/B,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAC9B,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC;AAE5B,MAAM,MAAM,mBAAmB,GAAG;IAChC,oGAAoG;IACpG,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,sDAAsD;IACtD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,qBAAa,YAAY;;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;gBAOd,OAAO,EAAE,cAAc,EAAE,OAAO,GAAE,mBAAwB;IAsBtE;;OAEG;IACH,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED;;;OAGG;IACH,IAAI,YAAY,IAAI,UAAU,CAE7B;IAED;;OAEG;IACH,IAAI,SAAS,IAAI,IAAI,CAGpB;IAED;;;;;OAKG;IACH,OAAO,CAAC,EAAE,EAAE,SAAS,GAAG,IAAI;IAU5B;;;;;OAKG;IACH,cAAc,CAAC,EAAE,EAAE,SAAS,GAAG,IAAI;IAYnC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,EAAE,SAAS,GAAG,OAAO;IAUjC;;OAEG;IACH,IAAI,QAAQ,uCAEX;IAED;;OAEG;IACH,IAAI,UAAU,aAEb;IAED;;;;;;;;;;;;;;;;OAgBG;IACG,YAAY,CAAC,IAAI,EAAE,iBAAiB,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtE;;;;;;;;;;;OAWG;IACG,WAAW,CACf,EAAE,EAAE,SAAS,EACb,GAAG,EAAE,GAAG,GAAG,WAAW,EACtB,OAAO,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC;;;;IA+CtC;;;;;;;;OAQG;IACG,cAAc,CAClB,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,iBAAiB,GAAG,eAAe,GACxC,OAAO,CAAC,QAAQ,CAAC;IAcpB;;;;OAIG;IACG,UAAU,CAAC,QAAQ,EAAE,QAAQ;IAsBnC;;;;;OAKG;IACG,YAAY,CAAC,QAAQ,EAAE,QAAQ;IAkBrC;;;;;;;;OAQG;IACG,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,iBAAiB,SAAM;IAgC5D,OAAO,CAAC,EAAE,EAAE,MAAM;IASlB,wBAAwB,CAAC,IAAI,EAAE,SAAS,GAAG,QAAQ;IAoGnD;;OAEG;IACH,KAAK;sCAEyB,MAAM,EAAE;kCAKZ,MAAM,EAAE;QAIhC;;;;;;;WAOG;6BACkB,SAAS,UAAU,WAAW;QAInD;;;;;WAKG;6BACkB,SAAS,KAAG,WAAW,EAAE;QAI9C;;;;;WAKG;+BACoB,SAAS,KAAG,IAAI;QAIvC;;;;WAIG;;YAKC;;;eAGG;;YAEH;;eAEG;;YAEH;;eAEG;;;QAKP;;;WAGG;;QAaH;;;;;WAKG;2BACsB,eAAe;QAYxC;;;;WAIG;kCAC6B,MAAM;MAItC;IAqCF;;OAEG;IACH,OAAO;CAGR"}
1
+ {"version":3,"file":"AssetManager.d.ts","sourceRoot":"","sources":["../../src/textures/AssetManager.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bloopjs/toodle",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
package/src/Toodle.ts CHANGED
@@ -21,8 +21,8 @@ import { Camera } from "./scene/Camera";
21
21
  import { JumboQuadNode, type JumboQuadOptions } from "./scene/JumboQuadNode";
22
22
  import { QuadNode, type QuadOptions } from "./scene/QuadNode";
23
23
  import { type NodeOptions, SceneNode } from "./scene/SceneNode";
24
+ import { TextNode, type TextOptions } from "./scene/TextNode";
24
25
  import type { Resolution } from "./screen/resolution";
25
- import { TextNode, type TextOptions } from "./text/TextNode";
26
26
  import { AssetManager, type TextureId } from "./textures/AssetManager";
27
27
  import { Pool } from "./utils/mod";
28
28
 
@@ -0,0 +1,15 @@
1
+ import type { MsdfFont } from "../text/MsdfFont";
2
+ import type { IBackendShader } from "./IBackendShader";
3
+
4
+ /**
5
+ * Backend-agnostic text shader interface.
6
+ *
7
+ * Extends IBackendShader with text-specific properties.
8
+ * Each backend provides its own implementation.
9
+ */
10
+ export interface ITextShader extends IBackendShader {
11
+ /** The font used by this text shader */
12
+ readonly font: MsdfFont;
13
+ /** Maximum number of characters that can be rendered per text node */
14
+ readonly maxCharCount: number;
15
+ }
@@ -13,6 +13,7 @@ export type {
13
13
  BlendOperation,
14
14
  IRenderBackend,
15
15
  } from "./IRenderBackend";
16
+ export type { ITextShader } from "./ITextShader";
16
17
  export type {
17
18
  ITextureAtlas,
18
19
  TextureAtlasFormat,
@@ -0,0 +1,35 @@
1
+ import type { EngineUniform } from "../../coreTypes/EngineUniform";
2
+ import type { SceneNode } from "../../scene/SceneNode";
3
+ import type { MsdfFont } from "../../text/MsdfFont";
4
+ import type { ITextShader } from "../ITextShader";
5
+
6
+ /**
7
+ * WebGL text shader that supports font loading for measurement but not rendering.
8
+ *
9
+ * This allows text measurement (via MsdfFont) on WebGL backend, but throws
10
+ * an error if text rendering is attempted. For text rendering, use the WebGPU backend.
11
+ */
12
+ export class WebGLTextShader implements ITextShader {
13
+ readonly label = "text";
14
+ readonly font: MsdfFont;
15
+ readonly maxCharCount: number;
16
+
17
+ constructor(font: MsdfFont, maxCharCount: number) {
18
+ this.font = font;
19
+ this.maxCharCount = maxCharCount;
20
+ }
21
+
22
+ startFrame(_uniform: EngineUniform): void {
23
+ // No-op for measurement-only shader
24
+ }
25
+
26
+ processBatch(_nodes: SceneNode[]): number {
27
+ throw new Error(
28
+ "Text rendering is not supported in WebGL mode. Use WebGPU backend for text rendering.",
29
+ );
30
+ }
31
+
32
+ endFrame(): void {
33
+ // No-op for measurement-only shader
34
+ }
35
+ }
@@ -1,2 +1,3 @@
1
1
  export { WebGLBackend, type WebGLBackendOptions } from "./WebGLBackend";
2
2
  export { WebGLQuadShader } from "./WebGLQuadShader";
3
+ export { WebGLTextShader } from "./WebGLTextShader";
@@ -1,5 +1,5 @@
1
- import type { MsdfFont } from "./MsdfFont";
2
- import msdfShader from "./text.wgsl";
1
+ import type { MsdfFont } from "../../text/MsdfFont";
2
+ import msdfShader from "./wgsl/text.wgsl";
3
3
 
4
4
  /**
5
5
  * A webgpu pipeline for rendering blocks of text with a given font.
@@ -1,13 +1,17 @@
1
1
  import { WgslReflect } from "wgsl_reflect";
2
- import type { IBackendShader } from "../backends/IBackendShader";
3
- import type { WebGPUBackend } from "../backends/webgpu/WebGPUBackend";
4
- import type { EngineUniform } from "../coreTypes/EngineUniform";
5
- import type { SceneNode } from "../scene/SceneNode";
2
+ import type { EngineUniform } from "../../coreTypes/EngineUniform";
3
+ import type { SceneNode } from "../../scene/SceneNode";
4
+ import { DEFAULT_FONT_SIZE, TextNode } from "../../scene/TextNode";
5
+ import type { MsdfFont } from "../../text/MsdfFont";
6
+ import {
7
+ findLargestFontSize,
8
+ measureText,
9
+ shapeText,
10
+ } from "../../text/shaping";
11
+ import type { ITextShader } from "../ITextShader";
6
12
  import type { FontPipeline } from "./FontPipeline";
7
- import type { MsdfFont } from "./MsdfFont";
8
- import { findLargestFontSize, measureText, shapeText } from "./shaping";
9
- import { DEFAULT_FONT_SIZE, TextNode } from "./TextNode";
10
- import msdfShader from "./text.wgsl";
13
+ import type { WebGPUBackend } from "./WebGPUBackend";
14
+ import msdfShader from "./wgsl/text.wgsl";
11
15
 
12
16
  const deets = new WgslReflect(msdfShader);
13
17
  const struct = deets.structs.find((s) => s.name === "TextBlockDescriptor");
@@ -16,7 +20,7 @@ if (!struct) {
16
20
  }
17
21
  const textDescriptorInstanceSize = struct.size;
18
22
 
19
- export class TextShader implements IBackendShader {
23
+ export class WebGPUTextShader implements ITextShader {
20
24
  readonly label = "text";
21
25
 
22
26
  #backend: WebGPUBackend;
@@ -130,7 +134,7 @@ export class TextShader implements IBackendShader {
130
134
  if (!(node instanceof TextNode)) {
131
135
  console.error(node);
132
136
  throw new Error(
133
- `Tried to use TextShader on something that isn't a TextNode: ${node}`,
137
+ `Tried to use WebGPUTextShader on something that isn't a TextNode: ${node}`,
134
138
  );
135
139
  }
136
140
  const text = node.text;
@@ -1,2 +1,4 @@
1
+ export { FontPipeline } from "./FontPipeline";
1
2
  export { WebGPUBackend, type WebGPUBackendOptions } from "./WebGPUBackend";
2
3
  export { WebGPUQuadShader } from "./WebGPUQuadShader";
4
+ export { WebGPUTextShader } from "./WebGPUTextShader";
package/src/mod.ts CHANGED
@@ -4,7 +4,7 @@ export type * from "./coreTypes/mod";
4
4
 
5
5
  export type * from "./scene/QuadNode";
6
6
  export type * from "./scene/SceneNode";
7
- export type * from "./text/TextNode";
7
+ export type * from "./scene/TextNode";
8
8
  export type * from "./backends/IBackendShader";
9
9
  export type * from "./backends/IRenderBackend";
10
10
 
@@ -1,9 +1,9 @@
1
+ import type { ITextShader } from "../backends/ITextShader";
1
2
  import type { Color } from "../coreTypes/Color";
2
- import { type NodeOptions, SceneNode } from "../scene/SceneNode";
3
- import type { MsdfFont } from "./MsdfFont";
4
- import { measureText } from "./shaping";
5
- import type { TextFormatting } from "./TextFormatting";
6
- import type { TextShader } from "./TextShader";
3
+ import type { MsdfFont } from "../text/MsdfFont";
4
+ import { measureText } from "../text/shaping";
5
+ import type { TextFormatting } from "../text/TextFormatting";
6
+ import { type NodeOptions, SceneNode } from "./SceneNode";
7
7
 
8
8
  export const DEFAULT_FONT_SIZE = 14;
9
9
 
@@ -12,7 +12,7 @@ export class TextNode extends SceneNode {
12
12
  #formatting: TextFormatting;
13
13
  #font: MsdfFont;
14
14
 
15
- constructor(shader: TextShader, text: string, opts: TextOptions = {}) {
15
+ constructor(shader: ITextShader, text: string, opts: TextOptions = {}) {
16
16
  const { width, height } = measureText(shader.font, text, opts.wordWrap);
17
17
 
18
18
  if (text.length > shader.maxCharCount) {
package/src/scene/mod.ts CHANGED
@@ -2,3 +2,4 @@ export * from "./Camera";
2
2
  export * from "./QuadNode";
3
3
  export * from "./RenderComponent";
4
4
  export * from "./SceneNode";
5
+ export * from "./TextNode";
package/src/text/mod.ts CHANGED
@@ -2,7 +2,4 @@
2
2
  // https://tchayen.com/drawing-text-in-webgpu-using-just-the-font-file
3
3
  // https://github.com/Chlumsky/msdfgen/issues/22#issuecomment-234958005
4
4
  // https://github.com/pixijs/pixijs/blob/dev/src/scene/text-bitmap/utils/getBitmapTextLayout.ts#L20
5
-
6
- export type { TextOptions } from "./TextNode";
7
- export { TextNode } from "./TextNode";
8
- export { TextShader } from "./TextShader";
5
+ export { WebGPUTextShader as TextShader } from "../backends/webgpu/WebGPUTextShader";
@@ -1,14 +1,16 @@
1
1
  import type { IRenderBackend } from "../backends/IRenderBackend";
2
+ import type { ITextShader } from "../backends/ITextShader";
3
+ import { WebGLTextShader } from "../backends/webgl2/WebGLTextShader";
4
+ import { FontPipeline } from "../backends/webgpu/FontPipeline";
2
5
  import { TextureComputeShader } from "../backends/webgpu/TextureComputeShader";
3
6
  import type { WebGPUBackend } from "../backends/webgpu/WebGPUBackend";
7
+ import { WebGPUTextShader } from "../backends/webgpu/WebGPUTextShader";
4
8
  import type { Size } from "../coreTypes/Size";
5
9
  import type { Vec2 } from "../coreTypes/Vec2";
6
10
  import { JumboQuadNode } from "../scene/JumboQuadNode";
7
11
  import { QuadNode } from "../scene/QuadNode";
8
12
  import type { SceneNode } from "../scene/SceneNode";
9
- import { FontPipeline } from "../text/FontPipeline";
10
13
  import { MsdfFont } from "../text/MsdfFont";
11
- import { TextShader } from "../text/TextShader";
12
14
  import { Bundles } from "./Bundles";
13
15
  import type {
14
16
  AtlasBundleOpts,
@@ -34,7 +36,7 @@ export class AssetManager {
34
36
  readonly bundles: Bundles;
35
37
  #backend: IRenderBackend;
36
38
  #atlasId: string;
37
- #fonts: Map<string, TextShader> = new Map();
39
+ #fonts: Map<string, ITextShader> = new Map();
38
40
  #cropComputeShader: TextureComputeShader | null = null;
39
41
  #availableIndices: Set<number> = new Set();
40
42
 
@@ -310,43 +312,48 @@ export class AssetManager {
310
312
  }
311
313
 
312
314
  /**
313
- * Load a font to the gpu
315
+ * Load a font for text rendering (WebGPU) or measurement only (WebGL).
314
316
  *
315
317
  * @param id - The id of the font to load
316
- * @param url - The url of the font to load
317
- * @param fallbackCharacter - The character to use as a fallback if the font does not contain a character to be rendererd
318
+ * @param url - The url of the font JSON to load
319
+ * @param fallbackCharacter - The character to use as a fallback if the font does not contain a character to be rendered
318
320
  *
319
- * @throws Error if using WebGL backend (fonts not supported in WebGL mode)
321
+ * @remarks
322
+ * On WebGPU backend, loads the full font for rendering.
323
+ * On WebGL backend, loads the font for text measurement only. Attempting to
324
+ * render text on WebGL will throw an error.
320
325
  */
321
326
  async loadFont(id: string, url: URL, fallbackCharacter = "_") {
322
- if (this.#backend.type !== "webgpu") {
323
- throw new Error(
324
- "loadFont is only supported with WebGPU backend. Text rendering is not available in WebGL mode.",
325
- );
326
- }
327
-
328
- const webgpuBackend = this.#backend as WebGPUBackend;
329
- const device = webgpuBackend.device;
330
- const presentationFormat = webgpuBackend.presentationFormat;
331
327
  const limits = this.#backend.limits;
332
-
333
328
  const font = await MsdfFont.create(id, url);
334
329
  font.fallbackCharacter = fallbackCharacter;
335
- const fontPipeline = await FontPipeline.create(
336
- device,
337
- font,
338
- presentationFormat,
339
- limits.maxTextLength,
340
- );
341
330
 
342
- const textShader = new TextShader(
343
- this.#backend as WebGPUBackend,
344
- fontPipeline,
345
- font,
346
- presentationFormat,
347
- limits.instanceCount,
348
- );
349
- this.#fonts.set(id, textShader);
331
+ if (this.#backend.type === "webgpu") {
332
+ const webgpuBackend = this.#backend as WebGPUBackend;
333
+ const device = webgpuBackend.device;
334
+ const presentationFormat = webgpuBackend.presentationFormat;
335
+
336
+ const fontPipeline = await FontPipeline.create(
337
+ device,
338
+ font,
339
+ presentationFormat,
340
+ limits.maxTextLength,
341
+ );
342
+
343
+ const textShader = new WebGPUTextShader(
344
+ webgpuBackend,
345
+ fontPipeline,
346
+ font,
347
+ presentationFormat,
348
+ limits.instanceCount,
349
+ );
350
+ this.#fonts.set(id, textShader);
351
+ } else {
352
+ // WebGL: font loaded for measurement, but rendering will throw
353
+ const textShader = new WebGLTextShader(font, limits.maxTextLength);
354
+ this.#fonts.set(id, textShader);
355
+ }
356
+
350
357
  return id;
351
358
  }
352
359
 
@@ -1 +0,0 @@
1
- {"version":3,"file":"FontPipeline.d.ts","sourceRoot":"","sources":["../../src/text/FontPipeline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG3C;;GAEG;AACH,qBAAa,YAAY;IAEd,QAAQ,EAAE,iBAAiB;IAC3B,IAAI,EAAE,QAAQ;IACd,aAAa,EAAE,YAAY;IAC3B,YAAY,EAAE,MAAM;gBAHpB,QAAQ,EAAE,iBAAiB,EAC3B,IAAI,EAAE,QAAQ,EACd,aAAa,EAAE,YAAY,EAC3B,YAAY,EAAE,MAAM;WAGhB,MAAM,CACjB,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,QAAQ,EACd,WAAW,EAAE,gBAAgB,EAC7B,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,YAAY,CAAC;CAuEzB;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,gBAAgB,EAC7B,KAAK,EAAE,MAAM,8BA4Cd"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"TextNode.d.ts","sourceRoot":"","sources":["../../src/text/TextNode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,KAAK,WAAW,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC,qBAAa,QAAS,SAAQ,SAAS;;gBAKzB,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,WAAgB;IAgCpE,IAAI,IAAI,IAYO,MAAM,CAVpB;IAED,IAAI,UAAU,IAyBa,cAAc,CAvBxC;IAED,IAAI,IAAI,aAEP;IAED,IAAI,IAAI,CAAC,IAAI,EAAE,MAAM,EAMpB;IAED,IAAI,IAAI,IAIO,KAAK,CAFnB;IAED,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAGnB;IAED,IAAI,UAAU,CAAC,UAAU,EAAE,cAAc,EAGxC;CACF;AAED,MAAM,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,GAAG,cAAc,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"TextShader.d.ts","sourceRoot":"","sources":["../../src/text/TextShader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAY3C,qBAAa,UAAW,YAAW,cAAc;;IAC/C,QAAQ,CAAC,KAAK,UAAU;gBAgBtB,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,YAAY,EACtB,IAAI,EAAE,QAAQ,EACd,YAAY,EAAE,gBAAgB,EAC9B,aAAa,EAAE,MAAM;IAqEvB,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAWxC,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM;IAkGxC,QAAQ,IAAI,IAAI;IAIhB,IAAI,IAAI,aAEP;IAED,IAAI,YAAY,WAEf;CACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"text.wgsl.d.ts","sourceRoot":"","sources":["../../src/text/text.wgsl.ts"],"names":[],"mappings":";AAAA,wBAoJE"}
File without changes