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