@playcanvas/web-components 0.1.3 → 0.1.5

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 (43) hide show
  1. package/README.md +12 -24
  2. package/dist/app.d.ts +11 -4
  3. package/dist/asset.d.ts +0 -1
  4. package/dist/async-element.d.ts +23 -0
  5. package/dist/components/camera-component.d.ts +3 -0
  6. package/dist/components/collision-component.d.ts +9 -1
  7. package/dist/components/component.d.ts +4 -2
  8. package/dist/components/element-component.d.ts +1 -1
  9. package/dist/components/render-component.d.ts +2 -2
  10. package/dist/components/script-component.d.ts +1 -1
  11. package/dist/components/sound-slot.d.ts +2 -1
  12. package/dist/entity.d.ts +2 -1
  13. package/dist/index.d.ts +10 -1
  14. package/dist/model.d.ts +2 -1
  15. package/dist/pwc.cjs +259 -119
  16. package/dist/pwc.cjs.map +1 -1
  17. package/dist/pwc.js +259 -119
  18. package/dist/pwc.js.map +1 -1
  19. package/dist/pwc.min.js +1 -1
  20. package/dist/pwc.min.js.map +1 -1
  21. package/dist/pwc.mjs +260 -121
  22. package/dist/pwc.mjs.map +1 -1
  23. package/dist/scene.d.ts +2 -1
  24. package/dist/sky.d.ts +15 -6
  25. package/dist/utils.d.ts +8 -1
  26. package/package.json +13 -12
  27. package/src/app.ts +13 -16
  28. package/src/asset.ts +1 -3
  29. package/src/async-element.ts +45 -0
  30. package/src/components/camera-component.ts +23 -2
  31. package/src/components/collision-component.ts +37 -3
  32. package/src/components/component.ts +15 -26
  33. package/src/components/element-component.ts +15 -4
  34. package/src/components/render-component.ts +1 -6
  35. package/src/components/screen-component.ts +1 -1
  36. package/src/components/script-component.ts +1 -3
  37. package/src/components/sound-slot.ts +7 -10
  38. package/src/entity.ts +25 -15
  39. package/src/index.ts +11 -0
  40. package/src/model.ts +20 -15
  41. package/src/scene.ts +6 -11
  42. package/src/sky.ts +82 -40
  43. package/src/utils.ts +14 -1
package/dist/pwc.mjs CHANGED
@@ -1,4 +1,39 @@
1
- import { WasmModule, Application, Keyboard, Mouse, FILLMODE_FILL_WINDOW, RESOLUTION_AUTO, Color, Vec2, Vec3, Vec4, Entity, Asset, PROJECTION_ORTHOGRAPHIC, PROJECTION_PERSPECTIVE, StandardMaterial, SCALEMODE_BLEND, SCALEMODE_NONE, Quat, LAYERID_SKYBOX } from 'playcanvas';
1
+ import { WasmModule, Application, Keyboard, Mouse, FILLMODE_FILL_WINDOW, RESOLUTION_AUTO, Color, Quat, Vec2, Vec3, Vec4, Entity, Asset, XRTYPE_VR, PROJECTION_ORTHOGRAPHIC, PROJECTION_PERSPECTIVE, StandardMaterial, SCALEMODE_BLEND, SCALEMODE_NONE, EnvLighting, LAYERID_SKYBOX } from 'playcanvas';
2
+
3
+ /**
4
+ * Base class for all PlayCanvas web components that initialize asynchronously.
5
+ */
6
+ class AsyncElement extends HTMLElement {
7
+ constructor() {
8
+ super();
9
+ this._readyPromise = new Promise((resolve) => {
10
+ this._readyResolve = resolve;
11
+ });
12
+ }
13
+ get closestApp() {
14
+ var _a;
15
+ return (_a = this.parentElement) === null || _a === void 0 ? void 0 : _a.closest('pc-app');
16
+ }
17
+ get closestEntity() {
18
+ var _a;
19
+ return (_a = this.parentElement) === null || _a === void 0 ? void 0 : _a.closest('pc-entity');
20
+ }
21
+ /**
22
+ * Called when the element is fully initialized and ready.
23
+ * Subclasses should call this when they're ready.
24
+ */
25
+ _onReady() {
26
+ this._readyResolve();
27
+ this.dispatchEvent(new CustomEvent('ready'));
28
+ }
29
+ /**
30
+ * Returns a promise that resolves with this element when it's ready.
31
+ * @returns A promise that resolves with this element when it's ready.
32
+ */
33
+ ready() {
34
+ return this._readyPromise.then(() => this);
35
+ }
36
+ }
2
37
 
3
38
  class ModuleElement extends HTMLElement {
4
39
  constructor() {
@@ -28,7 +63,7 @@ customElements.define('pc-module', ModuleElement);
28
63
  /**
29
64
  * The main application element.
30
65
  */
31
- class AppElement extends HTMLElement {
66
+ class AppElement extends AsyncElement {
32
67
  /**
33
68
  * Creates a new AppElement.
34
69
  */
@@ -45,9 +80,6 @@ class AppElement extends HTMLElement {
45
80
  this.app = null;
46
81
  // Bind methods to maintain 'this' context
47
82
  this._onWindowResize = this._onWindowResize.bind(this);
48
- this.appReadyPromise = new Promise((resolve) => {
49
- this.appReadyResolve = resolve;
50
- });
51
83
  }
52
84
  async connectedCallback() {
53
85
  // Get all pc-module elements that are direct children of the pc-app element
@@ -87,7 +119,7 @@ class AppElement extends HTMLElement {
87
119
  this.app.start();
88
120
  // Handle window resize to keep the canvas responsive
89
121
  window.addEventListener('resize', this._onWindowResize);
90
- this.appReadyResolve(this.app);
122
+ this._onReady();
91
123
  });
92
124
  }
93
125
  disconnectedCallback() {
@@ -104,21 +136,26 @@ class AppElement extends HTMLElement {
104
136
  this._canvas = null;
105
137
  }
106
138
  }
107
- async getApplication() {
108
- await this.appReadyPromise;
109
- return this.app;
110
- }
111
139
  _onWindowResize() {
112
140
  if (this.app) {
113
141
  this.app.resizeCanvas();
114
142
  }
115
143
  }
144
+ /**
145
+ * Sets the high resolution flag. When true, the application will render at the device's
146
+ * physical resolution. When false, the application will render at CSS resolution.
147
+ * @param value - The high resolution flag.
148
+ */
116
149
  set highResolution(value) {
117
150
  this._highResolution = value;
118
151
  if (this.app) {
119
152
  this.app.graphicsDevice.maxPixelRatio = value ? window.devicePixelRatio : 1;
120
153
  }
121
154
  }
155
+ /**
156
+ * Gets the high resolution flag.
157
+ * @returns The high resolution flag.
158
+ */
122
159
  get highResolution() {
123
160
  return this._highResolution;
124
161
  }
@@ -149,6 +186,18 @@ const parseColor = (value) => {
149
186
  const components = value.split(',').map(Number);
150
187
  return new Color(components);
151
188
  };
189
+ /**
190
+ * Parse an Euler angles string into a Quat object. String can be in the format of 'x,y,z'.
191
+ *
192
+ * @param value - The Euler angles string to parse.
193
+ * @returns The parsed Quat object.
194
+ */
195
+ const parseQuat = (value) => {
196
+ const [x, y, z] = value.split(',').map(Number);
197
+ const q = new Quat();
198
+ q.setFromEulerAngles(x, y, z);
199
+ return q;
200
+ };
152
201
  /**
153
202
  * Parse a Vec2 string into a Vec2 object. String can be in the format of 'x,y'.
154
203
  *
@@ -183,7 +232,7 @@ const parseVec4 = (value) => {
183
232
  /**
184
233
  * Represents an entity in the PlayCanvas engine.
185
234
  */
186
- class EntityElement extends HTMLElement {
235
+ class EntityElement extends AsyncElement {
187
236
  constructor() {
188
237
  super(...arguments);
189
238
  /**
@@ -216,21 +265,14 @@ class EntityElement extends HTMLElement {
216
265
  this.entity = null;
217
266
  }
218
267
  async connectedCallback() {
219
- // Get the application
220
- const appElement = this.closest('pc-app');
221
- if (!appElement) {
222
- console.warn(`${this.tagName} must be a child of pc-app`);
268
+ const closestApp = this.closestApp;
269
+ if (!closestApp)
223
270
  return;
224
- }
225
- const app = await appElement.getApplication();
271
+ // Wait for the app to complete initialization
272
+ await closestApp.ready();
273
+ const app = closestApp.app;
226
274
  // Create a new entity
227
275
  this.entity = new Entity(this._name, app);
228
- if (this.parentElement && this.parentElement.tagName.toLowerCase() === 'pc-entity' && this.parentElement.entity) {
229
- this.parentElement.entity.addChild(this.entity);
230
- }
231
- else {
232
- app.root.addChild(this.entity);
233
- }
234
276
  // Initialize from attributes
235
277
  const nameAttr = this.getAttribute('name');
236
278
  const positionAttr = this.getAttribute('position');
@@ -247,9 +289,25 @@ class EntityElement extends HTMLElement {
247
289
  this.scale = parseVec3(scaleAttr);
248
290
  if (tagsAttr)
249
291
  this.tags = tagsAttr.split(',').map(tag => tag.trim());
292
+ const closestEntity = this.closestEntity;
293
+ if (closestEntity) {
294
+ closestEntity.ready().then(() => {
295
+ closestEntity.entity.addChild(this.entity);
296
+ this._onReady();
297
+ });
298
+ }
299
+ else {
300
+ app.root.addChild(this.entity);
301
+ this._onReady();
302
+ }
250
303
  }
251
304
  disconnectedCallback() {
252
305
  if (this.entity) {
306
+ // Notify all children that their entities are about to become invalid
307
+ const children = this.querySelectorAll('pc-entity');
308
+ children.forEach((child) => {
309
+ child.entity = null;
310
+ });
253
311
  this.entity.destroy();
254
312
  this.entity = null;
255
313
  }
@@ -391,6 +449,7 @@ const extToType = new Map([
391
449
  ['frag', 'shader'],
392
450
  ['glb', 'container'],
393
451
  ['glsl', 'shader'],
452
+ ['hdr', 'texture'],
394
453
  ['html', 'html'],
395
454
  ['jpg', 'texture'],
396
455
  ['js', 'script'],
@@ -415,8 +474,6 @@ class AssetElement extends HTMLElement {
415
474
  */
416
475
  this.asset = null;
417
476
  }
418
- async connectedCallback() {
419
- }
420
477
  disconnectedCallback() {
421
478
  this.destroyAsset();
422
479
  }
@@ -480,7 +537,7 @@ customElements.define('pc-asset', AssetElement);
480
537
  *
481
538
  * @category Components
482
539
  */
483
- class ComponentElement extends HTMLElement {
540
+ class ComponentElement extends AsyncElement {
484
541
  /**
485
542
  * Constructor for the ComponentElement.
486
543
  * @param componentName - The name of the component.
@@ -495,27 +552,23 @@ class ComponentElement extends HTMLElement {
495
552
  getInitialComponentData() {
496
553
  return {};
497
554
  }
498
- async connectedCallback() {
499
- const appElement = this.closest('pc-app');
500
- if (!appElement) {
501
- console.error(`${this.tagName.toLowerCase()} should be a descendant of pc-app`);
502
- return;
503
- }
504
- await appElement.getApplication();
505
- this.addComponent();
506
- }
507
- addComponent() {
508
- // Access the parent pc-entity's 'entity' property
509
- const entityElement = this.closest('pc-entity');
510
- if (!entityElement) {
511
- console.error(`${this.tagName.toLowerCase()} should be a child of pc-entity`);
512
- return;
513
- }
514
- if (entityElement && entityElement.entity) {
555
+ async addComponent() {
556
+ const entityElement = this.closestEntity;
557
+ if (entityElement) {
558
+ await entityElement.ready();
515
559
  // Add the component to the entity
516
- this._component = entityElement.entity.addComponent(this._componentName, this.getInitialComponentData());
560
+ const data = this.getInitialComponentData();
561
+ this._component = entityElement.entity.addComponent(this._componentName, data);
517
562
  }
518
563
  }
564
+ initComponent() { }
565
+ async connectedCallback() {
566
+ var _a;
567
+ await ((_a = this.closestApp) === null || _a === void 0 ? void 0 : _a.ready());
568
+ await this.addComponent();
569
+ this.initComponent();
570
+ this._onReady();
571
+ }
519
572
  disconnectedCallback() {
520
573
  // Remove the component when the element is disconnected
521
574
  if (this.component && this.component.entity) {
@@ -620,6 +673,26 @@ class CameraComponentElement extends ComponentElement {
620
673
  scissorRect: this._scissorRect
621
674
  };
622
675
  }
676
+ get xrAvailable() {
677
+ var _a;
678
+ const xrManager = (_a = this.component) === null || _a === void 0 ? void 0 : _a.system.app.xr;
679
+ return xrManager && xrManager.supported && xrManager.isAvailable(XRTYPE_VR);
680
+ }
681
+ startXr(type, space) {
682
+ if (this.component && this.xrAvailable) {
683
+ this.component.startXr(type, space, {
684
+ callback: (err) => {
685
+ if (err)
686
+ console.error(`WebXR Immersive VR failed to start: ${err.message}`);
687
+ }
688
+ });
689
+ }
690
+ }
691
+ endXr() {
692
+ if (this.component) {
693
+ this.component.endXr();
694
+ }
695
+ }
623
696
  /**
624
697
  * Gets the camera component.
625
698
  * @returns The camera component.
@@ -966,19 +1039,23 @@ class CollisionComponentElement extends ComponentElement {
966
1039
  */
967
1040
  constructor() {
968
1041
  super('collision');
1042
+ this._angularOffset = new Quat();
969
1043
  this._axis = 1;
970
1044
  this._convexHull = false;
971
1045
  this._halfExtents = new Vec3(0.5, 0.5, 0.5);
972
1046
  this._height = 2;
1047
+ this._linearOffset = new Vec3();
973
1048
  this._radius = 0.5;
974
1049
  this._type = 'box';
975
1050
  }
976
1051
  getInitialComponentData() {
977
1052
  return {
978
1053
  axis: this._axis,
1054
+ angularOffset: this._angularOffset,
979
1055
  convexHull: this._convexHull,
980
1056
  halfExtents: this._halfExtents,
981
1057
  height: this._height,
1058
+ linearOffset: this._linearOffset,
982
1059
  radius: this._radius,
983
1060
  type: this._type
984
1061
  };
@@ -990,6 +1067,15 @@ class CollisionComponentElement extends ComponentElement {
990
1067
  get component() {
991
1068
  return super.component;
992
1069
  }
1070
+ set angularOffset(value) {
1071
+ this._angularOffset = value;
1072
+ if (this.component) {
1073
+ this.component.angularOffset = value;
1074
+ }
1075
+ }
1076
+ get angularOffset() {
1077
+ return this._angularOffset;
1078
+ }
993
1079
  set axis(value) {
994
1080
  this._axis = value;
995
1081
  if (this.component) {
@@ -1026,6 +1112,15 @@ class CollisionComponentElement extends ComponentElement {
1026
1112
  get height() {
1027
1113
  return this._height;
1028
1114
  }
1115
+ set linearOffset(value) {
1116
+ this._linearOffset = value;
1117
+ if (this.component) {
1118
+ this.component.linearOffset = value;
1119
+ }
1120
+ }
1121
+ get linearOffset() {
1122
+ return this._linearOffset;
1123
+ }
1029
1124
  set radius(value) {
1030
1125
  this._radius = value;
1031
1126
  if (this.component) {
@@ -1045,11 +1140,14 @@ class CollisionComponentElement extends ComponentElement {
1045
1140
  return this._type;
1046
1141
  }
1047
1142
  static get observedAttributes() {
1048
- return [...super.observedAttributes, 'axis', 'convex-hull', 'half-extents', 'height', 'radius', 'type'];
1143
+ return [...super.observedAttributes, 'angular-offset', 'axis', 'convex-hull', 'half-extents', 'height', 'linear-offset', 'radius', 'type'];
1049
1144
  }
1050
1145
  attributeChangedCallback(name, _oldValue, newValue) {
1051
1146
  super.attributeChangedCallback(name, _oldValue, newValue);
1052
1147
  switch (name) {
1148
+ case 'angular-offset':
1149
+ this.angularOffset = parseQuat(newValue);
1150
+ break;
1053
1151
  case 'axis':
1054
1152
  this.axis = parseInt(newValue, 10);
1055
1153
  break;
@@ -1062,6 +1160,9 @@ class CollisionComponentElement extends ComponentElement {
1062
1160
  case 'height':
1063
1161
  this.height = parseFloat(newValue);
1064
1162
  break;
1163
+ case 'linear-offset':
1164
+ this.linearOffset = parseVec3(newValue);
1165
+ break;
1065
1166
  case 'radius':
1066
1167
  this.radius = parseFloat(newValue);
1067
1168
  break;
@@ -1093,8 +1194,7 @@ class ElementComponentElement extends ComponentElement {
1093
1194
  this._width = 0;
1094
1195
  this._wrapLines = false;
1095
1196
  }
1096
- async connectedCallback() {
1097
- await super.connectedCallback();
1197
+ initComponent() {
1098
1198
  this.component._text._material.useFog = true;
1099
1199
  }
1100
1200
  getInitialComponentData() {
@@ -1228,7 +1328,20 @@ class ElementComponentElement extends ComponentElement {
1228
1328
  return this._wrapLines;
1229
1329
  }
1230
1330
  static get observedAttributes() {
1231
- return [...super.observedAttributes, 'anchor', 'asset', 'auto-width', 'color', 'font-size', 'line-height', 'pivot', 'text', 'type', 'width', 'wrap-lines'];
1331
+ return [
1332
+ ...super.observedAttributes,
1333
+ 'anchor',
1334
+ 'asset',
1335
+ 'auto-width',
1336
+ 'color',
1337
+ 'font-size',
1338
+ 'line-height',
1339
+ 'pivot',
1340
+ 'text',
1341
+ 'type',
1342
+ 'width',
1343
+ 'wrap-lines'
1344
+ ];
1232
1345
  }
1233
1346
  attributeChangedCallback(name, _oldValue, newValue) {
1234
1347
  super.attributeChangedCallback(name, _oldValue, newValue);
@@ -1714,14 +1827,11 @@ class RenderComponentElement extends ComponentElement {
1714
1827
  this._receiveShadows = true;
1715
1828
  this._type = 'asset';
1716
1829
  }
1717
- async connectedCallback() {
1718
- await super.connectedCallback();
1719
- this.material = this._material;
1720
- }
1721
1830
  getInitialComponentData() {
1722
1831
  return {
1723
1832
  type: this._type,
1724
1833
  castShadows: this._castShadows,
1834
+ material: MaterialElement.get(this._material),
1725
1835
  receiveShadows: this._receiveShadows
1726
1836
  };
1727
1837
  }
@@ -2111,7 +2221,7 @@ class ScreenComponentElement extends ComponentElement {
2111
2221
  super.attributeChangedCallback(name, _oldValue, newValue);
2112
2222
  switch (name) {
2113
2223
  case 'priority':
2114
- this.priority = parseInt(newValue);
2224
+ this.priority = parseInt(newValue, 10);
2115
2225
  break;
2116
2226
  case 'reference-resolution':
2117
2227
  this.referenceResolution = parseVec2(newValue);
@@ -2150,8 +2260,7 @@ class ScriptComponentElement extends ComponentElement {
2150
2260
  this.addEventListener('scriptattributeschange', this.handleScriptAttributesChange.bind(this));
2151
2261
  this.addEventListener('scriptenablechange', this.handleScriptEnableChange.bind(this));
2152
2262
  }
2153
- async connectedCallback() {
2154
- await super.connectedCallback();
2263
+ initComponent() {
2155
2264
  // Handle initial script elements
2156
2265
  this.querySelectorAll(':scope > pc-script').forEach((scriptElement) => {
2157
2266
  const scriptName = scriptElement.getAttribute('name');
@@ -2421,7 +2530,7 @@ customElements.define('pc-sounds', SoundComponentElement);
2421
2530
  /**
2422
2531
  * Represents a sound slot in the PlayCanvas engine.
2423
2532
  */
2424
- class SoundSlotElement extends HTMLElement {
2533
+ class SoundSlotElement extends AsyncElement {
2425
2534
  constructor() {
2426
2535
  super(...arguments);
2427
2536
  this._asset = '';
@@ -2439,12 +2548,8 @@ class SoundSlotElement extends HTMLElement {
2439
2548
  this.soundSlot = null;
2440
2549
  }
2441
2550
  async connectedCallback() {
2442
- const appElement = this.closest('pc-app');
2443
- if (!appElement) {
2444
- console.error(`${this.tagName.toLowerCase()} should be a descendant of pc-app`);
2445
- return;
2446
- }
2447
- await appElement.getApplication();
2551
+ var _a;
2552
+ await ((_a = this.soundElement) === null || _a === void 0 ? void 0 : _a.ready());
2448
2553
  const options = {
2449
2554
  autoPlay: this._autoPlay,
2450
2555
  loop: this._loop,
@@ -2459,6 +2564,7 @@ class SoundSlotElement extends HTMLElement {
2459
2564
  this.soundSlot = this.soundElement.component.addSlot(this._name, options);
2460
2565
  this.asset = this._asset;
2461
2566
  this.soundSlot.play();
2567
+ this._onReady();
2462
2568
  }
2463
2569
  disconnectedCallback() {
2464
2570
  this.soundElement.component.removeSlot(this._name);
@@ -2665,23 +2771,19 @@ customElements.define('pc-sound', SoundSlotElement);
2665
2771
  /**
2666
2772
  * Represents a model in the PlayCanvas engine.
2667
2773
  */
2668
- class ModelElement extends HTMLElement {
2774
+ class ModelElement extends AsyncElement {
2669
2775
  constructor() {
2670
2776
  super(...arguments);
2671
2777
  this._asset = '';
2672
2778
  }
2673
2779
  async connectedCallback() {
2674
- // Get the application
2675
- const appElement = this.closest('pc-app');
2676
- if (!appElement) {
2677
- console.warn(`${this.tagName} must be a child of pc-app`);
2678
- return;
2679
- }
2680
- await appElement.getApplication();
2780
+ var _a;
2781
+ await ((_a = this.closestApp) === null || _a === void 0 ? void 0 : _a.ready());
2681
2782
  const asset = this.getAttribute('asset');
2682
2783
  if (asset) {
2683
2784
  this.asset = asset;
2684
2785
  }
2786
+ this._onReady();
2685
2787
  }
2686
2788
  _loadModel() {
2687
2789
  const asset = AssetElement.get(this._asset);
@@ -2689,13 +2791,23 @@ class ModelElement extends HTMLElement {
2689
2791
  return;
2690
2792
  }
2691
2793
  const entity = asset.resource.instantiateRenderEntity();
2692
- const parentEntityElement = this.closest('pc-entity');
2794
+ if (asset.resource.animations.length > 0) {
2795
+ entity.addComponent('anim');
2796
+ entity.anim.assignAnimation('animation', asset.resource.animations[0].resource);
2797
+ }
2798
+ const parentEntityElement = this.closestEntity;
2693
2799
  if (parentEntityElement) {
2694
- parentEntityElement.entity.addChild(entity);
2800
+ parentEntityElement.ready().then(() => {
2801
+ parentEntityElement.entity.addChild(entity);
2802
+ });
2695
2803
  }
2696
2804
  else {
2697
- const appElement = this.closest('pc-app');
2698
- appElement.app.root.addChild(entity);
2805
+ const appElement = this.closestApp;
2806
+ if (appElement) {
2807
+ appElement.ready().then(() => {
2808
+ appElement.app.root.addChild(entity);
2809
+ });
2810
+ }
2699
2811
  }
2700
2812
  }
2701
2813
  /**
@@ -2729,7 +2841,7 @@ customElements.define('pc-model', ModelElement);
2729
2841
  /**
2730
2842
  * Represents a scene in the PlayCanvas engine.
2731
2843
  */
2732
- class SceneElement extends HTMLElement {
2844
+ class SceneElement extends AsyncElement {
2733
2845
  constructor() {
2734
2846
  super(...arguments);
2735
2847
  /**
@@ -2758,15 +2870,11 @@ class SceneElement extends HTMLElement {
2758
2870
  this.scene = null;
2759
2871
  }
2760
2872
  async connectedCallback() {
2761
- // Get the application
2762
- const appElement = this.closest('pc-app');
2763
- if (!appElement) {
2764
- console.warn(`${this.tagName} must be a child of pc-app`);
2765
- return;
2766
- }
2767
- const app = await appElement.getApplication();
2768
- this.scene = app.scene;
2873
+ var _a;
2874
+ await ((_a = this.closestApp) === null || _a === void 0 ? void 0 : _a.ready());
2875
+ this.scene = this.closestApp.app.scene;
2769
2876
  this.updateSceneSettings();
2877
+ this._onReady();
2770
2878
  }
2771
2879
  updateSceneSettings() {
2772
2880
  if (this.scene) {
@@ -2892,57 +3000,71 @@ customElements.define('pc-scene', SceneElement);
2892
3000
  /**
2893
3001
  * Represents a sky in the PlayCanvas engine.
2894
3002
  */
2895
- class SkyElement extends HTMLElement {
3003
+ class SkyElement extends AsyncElement {
2896
3004
  constructor() {
2897
3005
  super(...arguments);
2898
3006
  this._asset = '';
3007
+ this._center = new Vec3(0, 0.01, 0);
2899
3008
  this._intensity = 1;
2900
- this._rotation = [0, 0, 0];
3009
+ this._rotation = new Vec3();
2901
3010
  this._level = 0;
2902
- this._solidColor = false;
3011
+ this._scale = new Vec3(100, 100, 100);
3012
+ this._type = 'infinite';
2903
3013
  }
2904
3014
  async connectedCallback() {
2905
- // Get the application
2906
- const appElement = this.closest('pc-app');
2907
- if (!appElement) {
2908
- console.warn(`${this.tagName} must be a child of pc-app`);
2909
- return;
2910
- }
2911
- await appElement.getApplication();
3015
+ var _a;
3016
+ await ((_a = this.closestApp) === null || _a === void 0 ? void 0 : _a.ready());
2912
3017
  this.asset = this.getAttribute('asset') || '';
2913
- this.solidColor = this.hasAttribute('solid-color');
3018
+ this._onReady();
2914
3019
  }
2915
3020
  getScene() {
2916
- const appElement = this.closest('pc-app');
2917
- if (!appElement) {
2918
- return;
2919
- }
2920
- const app = appElement.app;
3021
+ const app = this.closestApp.app;
2921
3022
  if (!app) {
2922
3023
  return;
2923
3024
  }
2924
3025
  return app.scene;
2925
3026
  }
3027
+ initSkybox(source) {
3028
+ source.anisotropy = 4;
3029
+ const skybox = EnvLighting.generateSkyboxCubemap(source);
3030
+ const lighting = EnvLighting.generateLightingSource(source);
3031
+ const envAtlas = EnvLighting.generateAtlas(lighting);
3032
+ const app = this.closestApp.app;
3033
+ if (app) {
3034
+ app.scene.envAtlas = envAtlas;
3035
+ app.scene.skybox = skybox;
3036
+ const layer = app.scene.layers.getLayerById(LAYERID_SKYBOX);
3037
+ if (layer) {
3038
+ layer.enabled = this._type !== 'none';
3039
+ }
3040
+ app.scene.sky.type = this._type;
3041
+ app.scene.sky.node.setLocalScale(this._scale);
3042
+ app.scene.sky.center = this._center;
3043
+ }
3044
+ }
2926
3045
  set asset(value) {
2927
3046
  this._asset = value;
2928
3047
  const scene = this.getScene();
2929
3048
  if (scene) {
2930
3049
  const asset = AssetElement.get(value);
2931
3050
  if (asset) {
2932
- if (asset.resource) {
2933
- scene.envAtlas = asset.resource;
2934
- }
2935
- else {
2936
- asset.once('load', () => {
2937
- scene.envAtlas = asset.resource;
2938
- });
2939
- }
3051
+ this.initSkybox(asset.resource);
2940
3052
  }
2941
3053
  }
2942
3054
  }
2943
3055
  get asset() {
2944
3056
  return this._asset;
2945
3057
  }
3058
+ set center(value) {
3059
+ this._center = value;
3060
+ const scene = this.getScene();
3061
+ if (scene) {
3062
+ scene.sky.center = this._center;
3063
+ }
3064
+ }
3065
+ get center() {
3066
+ return this._center;
3067
+ }
2946
3068
  set intensity(value) {
2947
3069
  this._intensity = value;
2948
3070
  const scene = this.getScene();
@@ -2957,24 +3079,21 @@ class SkyElement extends HTMLElement {
2957
3079
  this._rotation = value;
2958
3080
  const scene = this.getScene();
2959
3081
  if (scene) {
2960
- scene.skyboxRotation = new Quat().setFromEulerAngles(this._rotation[0], this._rotation[1], this._rotation[2]);
3082
+ scene.skyboxRotation = new Quat().setFromEulerAngles(value);
2961
3083
  }
2962
3084
  }
2963
3085
  get rotation() {
2964
3086
  return this._rotation;
2965
3087
  }
2966
- set solidColor(value) {
2967
- this._solidColor = value;
3088
+ set scale(value) {
3089
+ this._scale = value;
2968
3090
  const scene = this.getScene();
2969
3091
  if (scene) {
2970
- const layer = scene.layers.getLayerById(LAYERID_SKYBOX);
2971
- if (layer) {
2972
- layer.enabled = !this._solidColor;
2973
- }
3092
+ scene.sky.node.setLocalScale(this._scale);
2974
3093
  }
2975
3094
  }
2976
- get solidColor() {
2977
- return this._solidColor;
3095
+ get scale() {
3096
+ return this._scale;
2978
3097
  }
2979
3098
  set level(value) {
2980
3099
  this._level = value;
@@ -2986,30 +3105,50 @@ class SkyElement extends HTMLElement {
2986
3105
  get level() {
2987
3106
  return this._level;
2988
3107
  }
3108
+ set type(value) {
3109
+ this._type = value;
3110
+ const scene = this.getScene();
3111
+ if (scene) {
3112
+ scene.sky.type = this._type;
3113
+ const layer = scene.layers.getLayerById(LAYERID_SKYBOX);
3114
+ if (layer) {
3115
+ layer.enabled = this._type !== 'none';
3116
+ }
3117
+ }
3118
+ }
3119
+ get type() {
3120
+ return this._type;
3121
+ }
2989
3122
  static get observedAttributes() {
2990
- return ['asset', 'intensity', 'level', 'rotation', 'solid-color'];
3123
+ return ['asset', 'center', 'intensity', 'level', 'rotation', 'scale', 'type'];
2991
3124
  }
2992
3125
  attributeChangedCallback(name, _oldValue, newValue) {
2993
3126
  switch (name) {
2994
3127
  case 'asset':
2995
3128
  this.asset = newValue;
2996
3129
  break;
3130
+ case 'center':
3131
+ this.center = parseVec3(newValue);
3132
+ break;
2997
3133
  case 'intensity':
2998
3134
  this.intensity = parseFloat(newValue);
2999
3135
  break;
3000
3136
  case 'rotation':
3001
- this.rotation = newValue.split(',').map(Number);
3137
+ this.rotation = parseVec3(newValue);
3002
3138
  break;
3003
3139
  case 'level':
3004
3140
  this.level = parseInt(newValue, 10);
3005
3141
  break;
3006
- case 'solid-color':
3007
- this.solidColor = this.hasAttribute('solid-color');
3142
+ case 'scale':
3143
+ this.scale = parseVec3(newValue);
3144
+ break;
3145
+ case 'type':
3146
+ this.type = newValue;
3008
3147
  break;
3009
3148
  }
3010
3149
  }
3011
3150
  }
3012
3151
  customElements.define('pc-sky', SkyElement);
3013
3152
 
3014
- export { AppElement, AssetElement, CameraComponentElement, CollisionComponentElement, ComponentElement, ElementComponentElement, EntityElement, GSplatComponentElement, LightComponentElement, ListenerComponentElement, MaterialElement, ModelElement, ModuleElement, RenderComponentElement, RigidBodyComponentElement, SceneElement, ScreenComponentElement, ScriptComponentElement, ScriptElement, SkyElement, SoundComponentElement, SoundSlotElement };
3153
+ export { AppElement, AssetElement, AsyncElement, CameraComponentElement, CollisionComponentElement, ComponentElement, ElementComponentElement, EntityElement, GSplatComponentElement, LightComponentElement, ListenerComponentElement, MaterialElement, ModelElement, ModuleElement, RenderComponentElement, RigidBodyComponentElement, SceneElement, ScreenComponentElement, ScriptComponentElement, ScriptElement, SkyElement, SoundComponentElement, SoundSlotElement };
3015
3154
  //# sourceMappingURL=pwc.mjs.map