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