@playcanvas/web-components 0.11.1 → 0.13.0

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 (96) hide show
  1. package/README.md +1 -1
  2. package/dist/app.d.cts +246 -0
  3. package/dist/app.d.ts +38 -13
  4. package/dist/asset.d.cts +218 -0
  5. package/dist/asset.d.ts +145 -6
  6. package/dist/async-element.d.cts +103 -0
  7. package/dist/async-element.d.ts +11 -8
  8. package/dist/colors.d.cts +1 -0
  9. package/dist/components/button-component.d.cts +186 -0
  10. package/dist/components/button-component.d.ts +1 -1
  11. package/dist/components/camera-component.d.cts +253 -0
  12. package/dist/components/camera-component.d.ts +1 -1
  13. package/dist/components/collision-component.d.cts +73 -0
  14. package/dist/components/collision-component.d.ts +17 -1
  15. package/dist/components/component.d.cts +82 -0
  16. package/dist/components/component.d.ts +20 -1
  17. package/dist/components/element-component.d.cts +316 -0
  18. package/dist/components/element-component.d.ts +1 -1
  19. package/dist/components/gsplat-component.d.cts +108 -0
  20. package/dist/components/gsplat-component.d.ts +1 -1
  21. package/dist/components/layoutchild-component.d.cts +110 -0
  22. package/dist/components/layoutchild-component.d.ts +1 -1
  23. package/dist/components/layoutgroup-component.d.cts +136 -0
  24. package/dist/components/layoutgroup-component.d.ts +1 -1
  25. package/dist/components/light-component.d.cts +264 -0
  26. package/dist/components/light-component.d.ts +1 -1
  27. package/dist/components/listener-component.d.cts +20 -0
  28. package/dist/components/listener-component.d.ts +1 -1
  29. package/dist/components/particlesystem-component.d.cts +52 -0
  30. package/dist/components/particlesystem-component.d.ts +1 -1
  31. package/dist/components/render-component.d.cts +76 -0
  32. package/dist/components/render-component.d.ts +1 -1
  33. package/dist/components/rigidbody-component.d.cts +88 -0
  34. package/dist/components/rigidbody-component.d.ts +1 -1
  35. package/dist/components/screen-component.d.cts +70 -0
  36. package/dist/components/screen-component.d.ts +1 -1
  37. package/dist/components/script-component.d.cts +163 -0
  38. package/dist/components/script-component.d.ts +1 -1
  39. package/dist/components/script.d.cts +94 -0
  40. package/dist/components/script.d.ts +1 -1
  41. package/dist/components/scrollbar-component.d.cts +69 -0
  42. package/dist/components/scrollbar-component.d.ts +1 -1
  43. package/dist/components/scrollview-component.d.cts +178 -0
  44. package/dist/components/scrollview-component.d.ts +1 -1
  45. package/dist/components/sound-component.d.cts +108 -0
  46. package/dist/components/sound-component.d.ts +1 -1
  47. package/dist/components/sound-slot.d.cts +134 -0
  48. package/dist/components/sound-slot.d.ts +2 -2
  49. package/dist/custom-elements.json +1127 -179
  50. package/dist/entity-base.d.cts +67 -0
  51. package/dist/entity-base.d.ts +67 -0
  52. package/dist/entity.d.cts +131 -0
  53. package/dist/entity.d.ts +3 -38
  54. package/dist/index.d.cts +79 -0
  55. package/dist/index.d.ts +35 -32
  56. package/dist/loading-bar.d.cts +35 -0
  57. package/dist/material.d.cts +1011 -0
  58. package/dist/material.d.ts +2 -1
  59. package/dist/model.d.cts +72 -0
  60. package/dist/model.d.ts +27 -5
  61. package/dist/module.d.cts +29 -0
  62. package/dist/module.d.ts +16 -10
  63. package/dist/node.d.cts +253 -0
  64. package/dist/node.d.ts +253 -0
  65. package/dist/parse.d.cts +147 -0
  66. package/dist/pwc.cjs +1496 -200
  67. package/dist/pwc.cjs.map +1 -1
  68. package/dist/pwc.js +1497 -201
  69. package/dist/pwc.js.map +1 -1
  70. package/dist/pwc.min.js +1 -1
  71. package/dist/pwc.min.js.map +1 -1
  72. package/dist/pwc.min.mjs +1 -1
  73. package/dist/pwc.min.mjs.map +1 -1
  74. package/dist/pwc.mjs +1496 -202
  75. package/dist/pwc.mjs.map +1 -1
  76. package/dist/scene.d.cts +117 -0
  77. package/dist/scene.d.ts +1 -1
  78. package/dist/sky.d.cts +121 -0
  79. package/dist/sky.d.ts +1 -1
  80. package/dist/vscode.html-custom-data.json +127 -5
  81. package/dist/web-types.json +399 -59
  82. package/package.json +16 -7
  83. package/src/app.ts +137 -45
  84. package/src/asset.ts +439 -9
  85. package/src/async-element.ts +11 -8
  86. package/src/components/collision-component.ts +35 -0
  87. package/src/components/component.ts +93 -3
  88. package/src/entity-base.ts +136 -0
  89. package/src/entity.ts +23 -117
  90. package/src/index.ts +5 -0
  91. package/src/loading-bar.ts +2 -2
  92. package/src/material.ts +2 -2
  93. package/src/model.ts +79 -11
  94. package/src/module.ts +39 -20
  95. package/src/node.ts +715 -0
  96. package/src/sky.ts +0 -1
package/src/model.ts CHANGED
@@ -8,6 +8,21 @@ import { AsyncElement } from './async-element';
8
8
  * {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-model/ | `<pc-model>`} elements.
9
9
  * The ModelElement interface also inherits the properties and methods of the
10
10
  * {@link HTMLElement} interface.
11
+ *
12
+ * The element becomes ready once its container asset has loaded and the instantiated hierarchy has
13
+ * been added to the scene — `entity` is non-null by then. A failed load also settles readiness,
14
+ * with `entity` remaining `null`: readiness means the load settled, not that it succeeded — listen
15
+ * for `error`, or check `entity`, to tell the outcomes apart. Changing `asset` re-arms readiness
16
+ * and instantiates anew, so a `ready()` obtained after the change resolves against the new
17
+ * hierarchy. A `pc-model` outside a `pc-app`, or referencing an unknown asset id, warns and never
18
+ * becomes ready.
19
+ *
20
+ * @fires {Event} load - Fired each time a container asset finishes instantiating, including
21
+ * re-instantiation after `asset` changes. Does not bubble — listen on this element, or use a
22
+ * capture-phase listener on an ancestor.
23
+ * @fires {ErrorEvent} error - Fired when the container asset fails to load, with the engine's
24
+ * error in `message`. Does not bubble. The element still becomes ready — readiness means the load
25
+ * settled, not that it succeeded.
11
26
  */
12
27
  class ModelElement extends AsyncElement {
13
28
  private _asset = '';
@@ -23,12 +38,14 @@ class ModelElement extends AsyncElement {
23
38
  private _loadGeneration = 0;
24
39
 
25
40
  /**
26
- * The pending asset-load subscription of the current load, if it is waiting for its asset.
27
- * Held so that whatever supersedes the load can detach the handler from the asset, rather
28
- * than leave it registered until the asset loads (or forever, if it never does).
41
+ * The pending asset subscriptions of the current load, if it is waiting for its asset. Held
42
+ * so that whatever supersedes the load can detach the handlers from the asset, rather than
43
+ * leave them registered until the asset settles (or forever, if it never does).
29
44
  */
30
45
  private _loadHandle: EventHandle | null = null;
31
46
 
47
+ private _errorHandle: EventHandle | null = null;
48
+
32
49
  /**
33
50
  * The root entity of the instantiated model. `null` until the container asset has loaded
34
51
  * and been instantiated, and again once the element has been removed from the document.
@@ -39,20 +56,39 @@ class ModelElement extends AsyncElement {
39
56
  }
40
57
 
41
58
  connectedCallback() {
59
+ // A model outside an application is inert and never becomes ready, so awaiting it hangs.
60
+ // Warn rather than fail silently, naming the parent it requires, as every other misplaced
61
+ // element does.
62
+ if (!this.closestApp) {
63
+ const label = this._asset ? ` '${this._asset}'` : '';
64
+ console.warn(`pc-model${label} must be a descendant of pc-app - model not created`);
65
+ return;
66
+ }
42
67
  this._loadModel();
43
- this._onReady();
44
68
  }
45
69
 
46
70
  disconnectedCallback() {
47
71
  this._loadGeneration++;
48
- this._detachLoadHandler();
72
+ this._detachLoadHandlers();
49
73
  this._unloadModel();
50
74
  this._resetReady();
51
75
  }
52
76
 
53
- private _detachLoadHandler() {
77
+ private _detachLoadHandlers() {
54
78
  this._loadHandle?.off();
55
79
  this._loadHandle = null;
80
+ this._errorHandle?.off();
81
+ this._errorHandle = null;
82
+ }
83
+
84
+ /**
85
+ * Resolves readiness and dispatches the `load` event. Called once the instantiated hierarchy
86
+ * has been parented — readiness means "in the scene graph", matching `pc-entity`, so a ready
87
+ * model's entity always has world transforms.
88
+ */
89
+ private _announceLoad() {
90
+ this._onReady();
91
+ this.dispatchEvent(new Event('load'));
56
92
  }
57
93
 
58
94
  private _instantiate(container: ContainerResource) {
@@ -78,6 +114,7 @@ class ModelElement extends AsyncElement {
78
114
  return;
79
115
  }
80
116
  parentEntityElement.entity!.addChild(entity);
117
+ this._announceLoad();
81
118
  });
82
119
  } else {
83
120
  const appElement = this.closestApp;
@@ -87,6 +124,7 @@ class ModelElement extends AsyncElement {
87
124
  return;
88
125
  }
89
126
  appElement.app!.root.addChild(entity);
127
+ this._announceLoad();
90
128
  });
91
129
  }
92
130
  }
@@ -97,19 +135,35 @@ class ModelElement extends AsyncElement {
97
135
 
98
136
  // Supersede any load already in flight - only the newest load may instantiate
99
137
  const generation = ++this._loadGeneration;
100
- this._detachLoadHandler();
138
+ this._detachLoadHandlers();
101
139
 
102
- const appElement = await this.closestApp?.ready();
140
+ // Re-arm readiness so a waiter obtained after an asset change resolves against the new
141
+ // hierarchy. A no-op on first connection, where readiness is still pending.
142
+ this._resetReady();
143
+
144
+ const appElement = this.closestApp;
145
+ if (!appElement) {
146
+ // Outside pc-app; connectedCallback already warned. Reached through the asset setter.
147
+ return;
148
+ }
149
+
150
+ await appElement.ready();
103
151
 
104
152
  // The element may have been removed, or another load started, while we waited
105
153
  if (generation !== this._loadGeneration) {
106
154
  return;
107
155
  }
108
156
 
109
- const app = appElement?.app;
157
+ const app = appElement.app;
110
158
 
111
159
  const asset = AssetElement.get(this._asset);
112
160
  if (!asset) {
161
+ // An empty id is a legitimate transient (the asset may be assigned later); a
162
+ // non-empty one that resolves to nothing is a dead end - say so rather than staying
163
+ // silently pending.
164
+ if (this._asset) {
165
+ console.warn(`pc-model could not find asset '${this._asset}' - model not created`);
166
+ }
113
167
  return;
114
168
  }
115
169
 
@@ -118,14 +172,28 @@ class ModelElement extends AsyncElement {
118
172
  } else {
119
173
  // The generation is re-checked even though a superseded handler is detached: the
120
174
  // detach relies on how the engine's event emitter treats removal, while the check
121
- // holds on its own.
175
+ // holds on its own. Whichever of load/error fires first detaches the other.
122
176
  this._loadHandle = asset.once('load', () => {
123
- this._loadHandle = null;
177
+ this._detachLoadHandlers();
124
178
  if (generation !== this._loadGeneration) {
125
179
  return;
126
180
  }
127
181
  this._instantiate(asset.resource as ContainerResource);
128
182
  });
183
+ this._errorHandle = asset.once('error', (err: string | Error) => {
184
+ this._detachLoadHandlers();
185
+ if (generation !== this._loadGeneration) {
186
+ return;
187
+ }
188
+ // A failed load settles readiness with a null entity, mirroring pc-asset:
189
+ // readiness means the load settled, not that it succeeded.
190
+ this.dispatchEvent(
191
+ new ErrorEvent('error', {
192
+ message: err instanceof Error ? err.message : String(err)
193
+ })
194
+ );
195
+ this._onReady();
196
+ });
129
197
  app!.assets.load(asset);
130
198
  }
131
199
  }
package/src/module.ts CHANGED
@@ -1,13 +1,21 @@
1
1
  import { basisInitialize, WasmModule } from 'playcanvas';
2
2
 
3
+ import { AsyncElement } from './async-element';
4
+
3
5
  /**
4
6
  * The ModuleElement interface provides properties and methods for manipulating
5
- * {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-module/ | `<pc-module>`} elements.
6
- * The ModuleElement interface also inherits the properties and methods of the
7
- * {@link HTMLElement} interface.
7
+ * {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-module/ | `<pc-module>`}
8
+ * elements. The ModuleElement interface also inherits the properties and methods of the
9
+ * {@link AsyncElement} interface.
10
+ *
11
+ * The attributes are read once, when the module starts loading - on the element's first
12
+ * connection, or earlier if a containing `<pc-app>` boots first and collects it - so changing
13
+ * them later has no effect. The element becomes ready once the module has loaded. WebAssembly
14
+ * modules configure engine-global state that never unloads, so readiness is not re-armed by
15
+ * removing the element, and a re-inserted element does not load again.
8
16
  *
9
- * Note that these attributes are read once when the element is created, so changing them later
10
- * has no effect.
17
+ * A `<pc-module>` without a `name` warns and never becomes ready; a containing `<pc-app>` still
18
+ * boots.
11
19
  *
12
20
  * @attribute {string} name - The name of the WebAssembly module to configure, e.g. `Basis` or
13
21
  * `Ammo`.
@@ -16,21 +24,25 @@ import { basisInitialize, WasmModule } from 'playcanvas';
16
24
  * @attribute {string} fallback - The URL of the module's asm.js fallback script, used when
17
25
  * WebAssembly is unavailable.
18
26
  */
19
- class ModuleElement extends HTMLElement {
20
- private loadPromise: Promise<void>;
27
+ class ModuleElement extends AsyncElement {
28
+ private _loadPromise: Promise<void> | null = null;
21
29
 
22
- /** @ignore */
23
- constructor() {
24
- super();
25
- this.loadPromise = this.loadModule();
30
+ connectedCallback() {
31
+ this._getLoadPromise();
26
32
  }
27
33
 
28
- private async loadModule(): Promise<void> {
29
- const name = this.getAttribute('name')!;
30
- const glueUrl = this.getAttribute('glue')!;
31
- const wasmUrl = this.getAttribute('wasm')!;
32
- const fallbackUrl = this.getAttribute('fallback')!;
33
- const config = { glueUrl, wasmUrl, fallbackUrl };
34
+ private async _loadModule(): Promise<void> {
35
+ const name = this.getAttribute('name');
36
+ if (!name) {
37
+ console.warn("pc-module requires a 'name' attribute - no module was configured");
38
+ return;
39
+ }
40
+
41
+ const config = {
42
+ glueUrl: this.getAttribute('glue') ?? undefined,
43
+ wasmUrl: this.getAttribute('wasm') ?? undefined,
44
+ fallbackUrl: this.getAttribute('fallback') ?? undefined
45
+ };
34
46
 
35
47
  if (name === 'Basis') {
36
48
  basisInitialize(config);
@@ -41,17 +53,24 @@ class ModuleElement extends HTMLElement {
41
53
  WasmModule.getInstance(name, () => resolve());
42
54
  });
43
55
  }
56
+
57
+ this._onReady();
44
58
  }
45
59
 
46
60
  /**
47
- * Returns the promise that settles when the module has loaded. Awaited by the containing
48
- * `<pc-app>` element before it creates its graphics device.
61
+ * Returns the promise that settles when the module has loaded, starting the load if it has
62
+ * not already started - a containing `<pc-app>` boots in document order, so it may collect
63
+ * this element before the element's own connectedCallback has run. A missing `name` resolves
64
+ * the promise without configuring anything, so a misconfigured module never blocks the app.
49
65
  *
50
66
  * @returns The load promise.
51
67
  * @internal
52
68
  */
53
69
  _getLoadPromise(): Promise<void> {
54
- return this.loadPromise;
70
+ if (!this._loadPromise) {
71
+ this._loadPromise = this._loadModule();
72
+ }
73
+ return this._loadPromise;
55
74
  }
56
75
  }
57
76