@playcanvas/web-components 0.1.5 → 0.1.7

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.
package/dist/pwc.cjs CHANGED
@@ -47,14 +47,23 @@ class ModuleElement extends HTMLElement {
47
47
  const glue = this.getAttribute('glue');
48
48
  const wasm = this.getAttribute('wasm');
49
49
  const fallback = this.getAttribute('fallback');
50
- playcanvas.WasmModule.setConfig(name, {
51
- glueUrl: glue,
52
- wasmUrl: wasm,
53
- fallbackUrl: fallback
54
- });
55
- await new Promise((resolve) => {
56
- playcanvas.WasmModule.getInstance(name, () => resolve());
57
- });
50
+ if (name === 'Basis') {
51
+ playcanvas.basisInitialize({
52
+ glueUrl: glue,
53
+ wasmUrl: wasm,
54
+ fallbackUrl: fallback
55
+ });
56
+ }
57
+ else {
58
+ playcanvas.WasmModule.setConfig(name, {
59
+ glueUrl: glue,
60
+ wasmUrl: wasm,
61
+ fallbackUrl: fallback
62
+ });
63
+ await new Promise((resolve) => {
64
+ playcanvas.WasmModule.getInstance(name, () => resolve());
65
+ });
66
+ }
58
67
  }
59
68
  getLoadPromise() {
60
69
  return this.loadPromise;
@@ -75,6 +84,10 @@ class AppElement extends AsyncElement {
75
84
  * The canvas element.
76
85
  */
77
86
  this._canvas = null;
87
+ this._alpha = true;
88
+ this._antialias = true;
89
+ this._depth = true;
90
+ this._stencil = true;
78
91
  this._highResolution = false;
79
92
  /**
80
93
  * The PlayCanvas application instance.
@@ -94,11 +107,15 @@ class AppElement extends AsyncElement {
94
107
  // Initialize the PlayCanvas application
95
108
  this.app = new playcanvas.Application(this._canvas, {
96
109
  graphicsDeviceOptions: {
97
- devicePixelRatio: this._highResolution ? window.devicePixelRatio : 1
110
+ alpha: this._alpha,
111
+ antialias: this._antialias,
112
+ depth: this._depth,
113
+ stencil: this._stencil
98
114
  },
99
115
  keyboard: new playcanvas.Keyboard(window),
100
116
  mouse: new playcanvas.Mouse(this._canvas)
101
117
  });
118
+ this.app.graphicsDevice.maxPixelRatio = this._highResolution ? window.devicePixelRatio : 1;
102
119
  this.app.setCanvasFillMode(playcanvas.FILLMODE_FILL_WINDOW);
103
120
  this.app.setCanvasResolution(playcanvas.RESOLUTION_AUTO);
104
121
  // Get all pc-asset elements that are direct children of the pc-app element
@@ -143,6 +160,48 @@ class AppElement extends AsyncElement {
143
160
  this.app.resizeCanvas();
144
161
  }
145
162
  }
163
+ /**
164
+ * Sets the alpha flag.
165
+ * @param value - The alpha flag.
166
+ */
167
+ set alpha(value) {
168
+ this._alpha = value;
169
+ }
170
+ /**
171
+ * Gets the alpha flag.
172
+ * @returns The alpha flag.
173
+ */
174
+ get alpha() {
175
+ return this._alpha;
176
+ }
177
+ /**
178
+ * Sets the antialias flag.
179
+ * @param value - The antialias flag.
180
+ */
181
+ set antialias(value) {
182
+ this._antialias = value;
183
+ }
184
+ /**
185
+ * Gets the antialias flag.
186
+ * @returns The antialias flag.
187
+ */
188
+ get antialias() {
189
+ return this._antialias;
190
+ }
191
+ /**
192
+ * Sets the depth flag.
193
+ * @param value - The depth flag.
194
+ */
195
+ set depth(value) {
196
+ this._depth = value;
197
+ }
198
+ /**
199
+ * Gets the depth flag.
200
+ * @returns The depth flag.
201
+ */
202
+ get depth() {
203
+ return this._depth;
204
+ }
146
205
  /**
147
206
  * Sets the high resolution flag. When true, the application will render at the device's
148
207
  * physical resolution. When false, the application will render at CSS resolution.
@@ -161,19 +220,196 @@ class AppElement extends AsyncElement {
161
220
  get highResolution() {
162
221
  return this._highResolution;
163
222
  }
223
+ /**
224
+ * Sets the stencil flag.
225
+ * @param value - The stencil flag.
226
+ */
227
+ set stencil(value) {
228
+ this._stencil = value;
229
+ }
230
+ /**
231
+ * Gets the stencil flag.
232
+ * @returns The stencil flag.
233
+ */
234
+ get stencil() {
235
+ return this._stencil;
236
+ }
164
237
  static get observedAttributes() {
165
- return ['high-resolution'];
238
+ return ['alpha', 'antialias', 'depth', 'stencil', 'high-resolution'];
166
239
  }
167
- attributeChangedCallback(name, _oldValue, _newValue) {
240
+ attributeChangedCallback(name, _oldValue, newValue) {
168
241
  switch (name) {
242
+ case 'alpha':
243
+ this.alpha = newValue !== 'false';
244
+ break;
245
+ case 'antialias':
246
+ this.antialias = newValue !== 'false';
247
+ break;
248
+ case 'depth':
249
+ this.depth = newValue !== 'false';
250
+ break;
169
251
  case 'high-resolution':
170
- this.highResolution = this.hasAttribute(name);
252
+ this.highResolution = newValue !== 'false';
253
+ break;
254
+ case 'stencil':
255
+ this.stencil = newValue !== 'false';
171
256
  break;
172
257
  }
173
258
  }
174
259
  }
175
260
  customElements.define('pc-app', AppElement);
176
261
 
262
+ const CSS_COLORS = {
263
+ aliceblue: '#f0f8ff',
264
+ antiquewhite: '#faebd7',
265
+ aqua: '#00ffff',
266
+ aquamarine: '#7fffd4',
267
+ azure: '#f0ffff',
268
+ beige: '#f5f5dc',
269
+ bisque: '#ffe4c4',
270
+ black: '#000000',
271
+ blanchedalmond: '#ffebcd',
272
+ blue: '#0000ff',
273
+ blueviolet: '#8a2be2',
274
+ brown: '#a52a2a',
275
+ burlywood: '#deb887',
276
+ cadetblue: '#5f9ea0',
277
+ chartreuse: '#7fff00',
278
+ chocolate: '#d2691e',
279
+ coral: '#ff7f50',
280
+ cornflowerblue: '#6495ed',
281
+ cornsilk: '#fff8dc',
282
+ crimson: '#dc143c',
283
+ cyan: '#00ffff',
284
+ darkblue: '#00008b',
285
+ darkcyan: '#008b8b',
286
+ darkgoldenrod: '#b8860b',
287
+ darkgray: '#a9a9a9',
288
+ darkgreen: '#006400',
289
+ darkgrey: '#a9a9a9',
290
+ darkkhaki: '#bdb76b',
291
+ darkmagenta: '#8b008b',
292
+ darkolivegreen: '#556b2f',
293
+ darkorange: '#ff8c00',
294
+ darkorchid: '#9932cc',
295
+ darkred: '#8b0000',
296
+ darksalmon: '#e9967a',
297
+ darkseagreen: '#8fbc8f',
298
+ darkslateblue: '#483d8b',
299
+ darkslategray: '#2f4f4f',
300
+ darkslategrey: '#2f4f4f',
301
+ darkturquoise: '#00ced1',
302
+ darkviolet: '#9400d3',
303
+ deeppink: '#ff1493',
304
+ deepskyblue: '#00bfff',
305
+ dimgray: '#696969',
306
+ dimgrey: '#696969',
307
+ dodgerblue: '#1e90ff',
308
+ firebrick: '#b22222',
309
+ floralwhite: '#fffaf0',
310
+ forestgreen: '#228b22',
311
+ fuchsia: '#ff00ff',
312
+ gainsboro: '#dcdcdc',
313
+ ghostwhite: '#f8f8ff',
314
+ gold: '#ffd700',
315
+ goldenrod: '#daa520',
316
+ gray: '#808080',
317
+ green: '#008000',
318
+ greenyellow: '#adff2f',
319
+ grey: '#808080',
320
+ honeydew: '#f0fff0',
321
+ hotpink: '#ff69b4',
322
+ indianred: '#cd5c5c',
323
+ indigo: '#4b0082',
324
+ ivory: '#fffff0',
325
+ khaki: '#f0e68c',
326
+ lavender: '#e6e6fa',
327
+ lavenderblush: '#fff0f5',
328
+ lawngreen: '#7cfc00',
329
+ lemonchiffon: '#fffacd',
330
+ lightblue: '#add8e6',
331
+ lightcoral: '#f08080',
332
+ lightcyan: '#e0ffff',
333
+ lightgoldenrodyellow: '#fafad2',
334
+ lightgray: '#d3d3d3',
335
+ lightgreen: '#90ee90',
336
+ lightgrey: '#d3d3d3',
337
+ lightpink: '#ffb6c1',
338
+ lightsalmon: '#ffa07a',
339
+ lightseagreen: '#20b2aa',
340
+ lightskyblue: '#87cefa',
341
+ lightslategray: '#778899',
342
+ lightslategrey: '#778899',
343
+ lightsteelblue: '#b0c4de',
344
+ lightyellow: '#ffffe0',
345
+ lime: '#00ff00',
346
+ limegreen: '#32cd32',
347
+ linen: '#faf0e6',
348
+ magenta: '#ff00ff',
349
+ maroon: '#800000',
350
+ mediumaquamarine: '#66cdaa',
351
+ mediumblue: '#0000cd',
352
+ mediumorchid: '#ba55d3',
353
+ mediumpurple: '#9370db',
354
+ mediumseagreen: '#3cb371',
355
+ mediumslateblue: '#7b68ee',
356
+ mediumspringgreen: '#00fa9a',
357
+ mediumturquoise: '#48d1cc',
358
+ mediumvioletred: '#c71585',
359
+ midnightblue: '#191970',
360
+ mintcream: '#f5fffa',
361
+ mistyrose: '#ffe4e1',
362
+ moccasin: '#ffe4b5',
363
+ navajowhite: '#ffdead',
364
+ navy: '#000080',
365
+ oldlace: '#fdf5e6',
366
+ olive: '#808000',
367
+ olivedrab: '#6b8e23',
368
+ orange: '#ffa500',
369
+ orangered: '#ff4500',
370
+ orchid: '#da70d6',
371
+ palegoldenrod: '#eee8aa',
372
+ palegreen: '#98fb98',
373
+ paleturquoise: '#afeeee',
374
+ palevioletred: '#db7093',
375
+ papayawhip: '#ffefd5',
376
+ peachpuff: '#ffdab9',
377
+ peru: '#cd853f',
378
+ pink: '#ffc0cb',
379
+ plum: '#dda0dd',
380
+ powderblue: '#b0e0e6',
381
+ purple: '#800080',
382
+ rebeccapurple: '#663399',
383
+ red: '#ff0000',
384
+ rosybrown: '#bc8f8f',
385
+ royalblue: '#4169e1',
386
+ saddlebrown: '#8b4513',
387
+ salmon: '#fa8072',
388
+ sandybrown: '#f4a460',
389
+ seagreen: '#2e8b57',
390
+ seashell: '#fff5ee',
391
+ sienna: '#a0522d',
392
+ silver: '#c0c0c0',
393
+ skyblue: '#87ceeb',
394
+ slateblue: '#6a5acd',
395
+ slategray: '#708090',
396
+ slategrey: '#708090',
397
+ snow: '#fffafa',
398
+ springgreen: '#00ff7f',
399
+ steelblue: '#4682b4',
400
+ tan: '#d2b48c',
401
+ teal: '#008080',
402
+ thistle: '#d8bfd8',
403
+ tomato: '#ff6347',
404
+ turquoise: '#40e0d0',
405
+ violet: '#ee82ee',
406
+ wheat: '#f5deb3',
407
+ white: '#ffffff',
408
+ whitesmoke: '#f5f5f5',
409
+ yellow: '#ffff00',
410
+ yellowgreen: '#9acd32'
411
+ };
412
+
177
413
  /**
178
414
  * Parse a color string into a Color object. String can be in the format of '#rgb', '#rgba',
179
415
  * '#rrggbb', '#rrggbbaa', or a string of 3 or 4 comma-delimited numbers.
@@ -182,10 +418,15 @@ customElements.define('pc-app', AppElement);
182
418
  * @returns The parsed Color object.
183
419
  */
184
420
  const parseColor = (value) => {
421
+ // Check if it's a CSS color name first
422
+ const hexColor = CSS_COLORS[value.toLowerCase()];
423
+ if (hexColor) {
424
+ return new playcanvas.Color().fromString(hexColor);
425
+ }
185
426
  if (value.startsWith('#')) {
186
427
  return new playcanvas.Color().fromString(value);
187
428
  }
188
- const components = value.split(',').map(Number);
429
+ const components = value.split(' ').map(Number);
189
430
  return new playcanvas.Color(components);
190
431
  };
191
432
  /**
@@ -195,7 +436,7 @@ const parseColor = (value) => {
195
436
  * @returns The parsed Quat object.
196
437
  */
197
438
  const parseQuat = (value) => {
198
- const [x, y, z] = value.split(',').map(Number);
439
+ const [x, y, z] = value.split(' ').map(Number);
199
440
  const q = new playcanvas.Quat();
200
441
  q.setFromEulerAngles(x, y, z);
201
442
  return q;
@@ -207,7 +448,7 @@ const parseQuat = (value) => {
207
448
  * @returns The parsed Vec2 object.
208
449
  */
209
450
  const parseVec2 = (value) => {
210
- const components = value.split(',').map(Number);
451
+ const components = value.split(' ').map(Number);
211
452
  return new playcanvas.Vec2(components);
212
453
  };
213
454
  /**
@@ -217,7 +458,7 @@ const parseVec2 = (value) => {
217
458
  * @returns The parsed Vec3 object.
218
459
  */
219
460
  const parseVec3 = (value) => {
220
- const components = value.split(',').map(Number);
461
+ const components = value.split(' ').map(Number);
221
462
  return new playcanvas.Vec3(components);
222
463
  };
223
464
  /**
@@ -227,7 +468,7 @@ const parseVec3 = (value) => {
227
468
  * @returns The parsed Vec4 object.
228
469
  */
229
470
  const parseVec4 = (value) => {
230
- const components = value.split(',').map(Number);
471
+ const components = value.split(' ').map(Number);
231
472
  return new playcanvas.Vec4(components);
232
473
  };
233
474
 
@@ -2245,6 +2486,9 @@ class ScreenComponentElement extends ComponentElement {
2245
2486
  }
2246
2487
  customElements.define('pc-screen', ScreenComponentElement);
2247
2488
 
2489
+ const tmpV2 = new playcanvas.Vec2();
2490
+ const tmpV3 = new playcanvas.Vec3();
2491
+ const tmpV4 = new playcanvas.Vec4();
2248
2492
  /**
2249
2493
  * Represents a script component in the PlayCanvas engine.
2250
2494
  *
@@ -2274,9 +2518,39 @@ class ScriptComponentElement extends ComponentElement {
2274
2518
  }
2275
2519
  applyAttributes(script, attributes) {
2276
2520
  try {
2277
- // Parse the attributes string into an object and set them on the script
2278
2521
  const attributesObject = attributes ? JSON.parse(attributes) : {};
2279
- Object.assign(script, attributesObject);
2522
+ const applyValue = (target, key, value) => {
2523
+ // Handle vectors
2524
+ if (Array.isArray(value)) {
2525
+ if (target[key] instanceof playcanvas.Vec2) {
2526
+ target[key] = tmpV2.set(value[0], value[1]);
2527
+ return;
2528
+ }
2529
+ if (target[key] instanceof playcanvas.Vec3) {
2530
+ target[key] = tmpV3.set(value[0], value[1], value[2]);
2531
+ return;
2532
+ }
2533
+ if (target[key] instanceof playcanvas.Vec4) {
2534
+ target[key] = tmpV4.set(value[0], value[1], value[2], value[3]);
2535
+ return;
2536
+ }
2537
+ }
2538
+ // Handle nested objects
2539
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
2540
+ if (!target[key] || typeof target[key] !== 'object') {
2541
+ target[key] = {};
2542
+ }
2543
+ for (const nestedKey in value) {
2544
+ applyValue(target[key], nestedKey, value[nestedKey]);
2545
+ }
2546
+ }
2547
+ else {
2548
+ target[key] = value;
2549
+ }
2550
+ };
2551
+ for (const key in attributesObject) {
2552
+ applyValue(script, key, attributesObject[key]);
2553
+ }
2280
2554
  }
2281
2555
  catch (error) {
2282
2556
  console.error(`Error parsing attributes JSON string ${attributes}:`, error);
@@ -2440,14 +2714,22 @@ customElements.define('pc-script', ScriptElement);
2440
2714
  class SoundComponentElement extends ComponentElement {
2441
2715
  constructor() {
2442
2716
  super('sound');
2717
+ this._distanceModel = 'linear';
2718
+ this._maxDistance = 10000;
2443
2719
  this._pitch = 1;
2444
2720
  this._positional = false;
2721
+ this._refDistance = 1;
2722
+ this._rollOffFactor = 1;
2445
2723
  this._volume = 1;
2446
2724
  }
2447
2725
  getInitialComponentData() {
2448
2726
  return {
2727
+ distanceModel: this._distanceModel,
2728
+ maxDistance: this._maxDistance,
2449
2729
  pitch: this._pitch,
2450
2730
  positional: this._positional,
2731
+ refDistance: this._refDistance,
2732
+ rollOffFactor: this._rollOffFactor,
2451
2733
  volume: this._volume
2452
2734
  };
2453
2735
  }
@@ -2458,6 +2740,40 @@ class SoundComponentElement extends ComponentElement {
2458
2740
  get component() {
2459
2741
  return super.component;
2460
2742
  }
2743
+ /**
2744
+ * Sets which algorithm to use to reduce the volume of the sound as it moves away from the listener.
2745
+ * @param value - The distance model.
2746
+ */
2747
+ set distanceModel(value) {
2748
+ this._distanceModel = value;
2749
+ if (this.component) {
2750
+ this.component.distanceModel = value;
2751
+ }
2752
+ }
2753
+ /**
2754
+ * Gets which algorithm to use to reduce the volume of the sound as it moves away from the listener.
2755
+ * @returns The distance model.
2756
+ */
2757
+ get distanceModel() {
2758
+ return this._distanceModel;
2759
+ }
2760
+ /**
2761
+ * Sets the maximum distance from the listener at which audio falloff stops.
2762
+ * @param value - The max distance.
2763
+ */
2764
+ set maxDistance(value) {
2765
+ this._maxDistance = value;
2766
+ if (this.component) {
2767
+ this.component.maxDistance = value;
2768
+ }
2769
+ }
2770
+ /**
2771
+ * Gets the maximum distance from the listener at which audio falloff stops.
2772
+ * @returns The max distance.
2773
+ */
2774
+ get maxDistance() {
2775
+ return this._maxDistance;
2776
+ }
2461
2777
  /**
2462
2778
  * Sets the pitch of the sound.
2463
2779
  * @param value - The pitch.
@@ -2492,6 +2808,40 @@ class SoundComponentElement extends ComponentElement {
2492
2808
  get positional() {
2493
2809
  return this._positional;
2494
2810
  }
2811
+ /**
2812
+ * Sets the reference distance for reducing volume as the sound source moves further from the listener. Defaults to 1.
2813
+ * @param value - The ref distance.
2814
+ */
2815
+ set refDistance(value) {
2816
+ this._refDistance = value;
2817
+ if (this.component) {
2818
+ this.component.refDistance = value;
2819
+ }
2820
+ }
2821
+ /**
2822
+ * Gets the reference distance for reducing volume as the sound source moves further from the listener.
2823
+ * @returns The ref distance.
2824
+ */
2825
+ get refDistance() {
2826
+ return this._refDistance;
2827
+ }
2828
+ /**
2829
+ * Sets the factor used in the falloff equation. Defaults to 1.
2830
+ * @param value - The roll-off factor.
2831
+ */
2832
+ set rollOffFactor(value) {
2833
+ this._rollOffFactor = value;
2834
+ if (this.component) {
2835
+ this.component.rollOffFactor = value;
2836
+ }
2837
+ }
2838
+ /**
2839
+ * Gets the factor used in the falloff equation.
2840
+ * @returns The roll-off factor.
2841
+ */
2842
+ get rollOffFactor() {
2843
+ return this._rollOffFactor;
2844
+ }
2495
2845
  /**
2496
2846
  * Sets the volume of the sound.
2497
2847
  * @param value - The volume.
@@ -2510,17 +2860,38 @@ class SoundComponentElement extends ComponentElement {
2510
2860
  return this._volume;
2511
2861
  }
2512
2862
  static get observedAttributes() {
2513
- return [...super.observedAttributes, 'pitch', 'positional', 'volume'];
2863
+ return [
2864
+ ...super.observedAttributes,
2865
+ 'distance-model',
2866
+ 'max-distance',
2867
+ 'pitch',
2868
+ 'positional',
2869
+ 'ref-distance',
2870
+ 'roll-off-factor',
2871
+ 'volume'
2872
+ ];
2514
2873
  }
2515
2874
  attributeChangedCallback(name, _oldValue, newValue) {
2516
2875
  super.attributeChangedCallback(name, _oldValue, newValue);
2517
2876
  switch (name) {
2877
+ case 'distance-model':
2878
+ this.distanceModel = newValue;
2879
+ break;
2880
+ case 'max-distance':
2881
+ this.maxDistance = parseFloat(newValue);
2882
+ break;
2518
2883
  case 'pitch':
2519
2884
  this.pitch = parseFloat(newValue);
2520
2885
  break;
2521
2886
  case 'positional':
2522
2887
  this.positional = this.hasAttribute('positional');
2523
2888
  break;
2889
+ case 'ref-distance':
2890
+ this.refDistance = parseFloat(newValue);
2891
+ break;
2892
+ case 'roll-off-factor':
2893
+ this.rollOffFactor = parseFloat(newValue);
2894
+ break;
2524
2895
  case 'volume':
2525
2896
  this.volume = parseFloat(newValue);
2526
2897
  break;
@@ -2777,48 +3148,71 @@ class ModelElement extends AsyncElement {
2777
3148
  constructor() {
2778
3149
  super(...arguments);
2779
3150
  this._asset = '';
3151
+ this._entity = null;
2780
3152
  }
2781
- async connectedCallback() {
2782
- var _a;
2783
- await ((_a = this.closestApp) === null || _a === void 0 ? void 0 : _a.ready());
2784
- const asset = this.getAttribute('asset');
2785
- if (asset) {
2786
- this.asset = asset;
2787
- }
3153
+ connectedCallback() {
3154
+ this._loadModel();
2788
3155
  this._onReady();
2789
3156
  }
2790
- _loadModel() {
2791
- const asset = AssetElement.get(this._asset);
2792
- if (!asset) {
2793
- return;
2794
- }
2795
- const entity = asset.resource.instantiateRenderEntity();
2796
- if (asset.resource.animations.length > 0) {
2797
- entity.addComponent('anim');
2798
- entity.anim.assignAnimation('animation', asset.resource.animations[0].resource);
3157
+ disconnectedCallback() {
3158
+ this._unloadModel();
3159
+ }
3160
+ _instantiate(container) {
3161
+ this._entity = container.instantiateRenderEntity();
3162
+ // @ts-ignore
3163
+ if (container.animations.length > 0) {
3164
+ this._entity.addComponent('anim');
3165
+ // @ts-ignore
3166
+ this._entity.anim.assignAnimation('animation', container.animations[0].resource);
2799
3167
  }
2800
3168
  const parentEntityElement = this.closestEntity;
2801
3169
  if (parentEntityElement) {
2802
3170
  parentEntityElement.ready().then(() => {
2803
- parentEntityElement.entity.addChild(entity);
3171
+ parentEntityElement.entity.addChild(this._entity);
2804
3172
  });
2805
3173
  }
2806
3174
  else {
2807
3175
  const appElement = this.closestApp;
2808
3176
  if (appElement) {
2809
3177
  appElement.ready().then(() => {
2810
- appElement.app.root.addChild(entity);
3178
+ appElement.app.root.addChild(this._entity);
2811
3179
  });
2812
3180
  }
2813
3181
  }
2814
3182
  }
3183
+ async _loadModel() {
3184
+ var _a;
3185
+ this._unloadModel();
3186
+ const appElement = await ((_a = this.closestApp) === null || _a === void 0 ? void 0 : _a.ready());
3187
+ const app = appElement === null || appElement === void 0 ? void 0 : appElement.app;
3188
+ const asset = AssetElement.get(this._asset);
3189
+ if (!asset) {
3190
+ return;
3191
+ }
3192
+ if (asset.loaded) {
3193
+ this._instantiate(asset.resource);
3194
+ }
3195
+ else {
3196
+ asset.once('load', () => {
3197
+ this._instantiate(asset.resource);
3198
+ });
3199
+ app.assets.load(asset);
3200
+ }
3201
+ }
3202
+ _unloadModel() {
3203
+ var _a;
3204
+ (_a = this._entity) === null || _a === void 0 ? void 0 : _a.destroy();
3205
+ this._entity = null;
3206
+ }
2815
3207
  /**
2816
3208
  * Sets the asset ID of the model.
2817
3209
  * @param value - The asset ID.
2818
3210
  */
2819
3211
  set asset(value) {
2820
3212
  this._asset = value;
2821
- this._loadModel();
3213
+ if (this.isConnected) {
3214
+ this._loadModel();
3215
+ }
2822
3216
  }
2823
3217
  /**
2824
3218
  * Gets the source URL of the model.
@@ -3010,48 +3404,76 @@ class SkyElement extends AsyncElement {
3010
3404
  this._intensity = 1;
3011
3405
  this._rotation = new playcanvas.Vec3();
3012
3406
  this._level = 0;
3407
+ this._lighting = false;
3013
3408
  this._scale = new playcanvas.Vec3(100, 100, 100);
3014
3409
  this._type = 'infinite';
3410
+ this._scene = null;
3015
3411
  }
3016
- async connectedCallback() {
3017
- var _a;
3018
- await ((_a = this.closestApp) === null || _a === void 0 ? void 0 : _a.ready());
3019
- this.asset = this.getAttribute('asset') || '';
3412
+ connectedCallback() {
3413
+ this._loadSkybox();
3020
3414
  this._onReady();
3021
3415
  }
3022
- getScene() {
3023
- const app = this.closestApp.app;
3024
- if (!app) {
3025
- return;
3026
- }
3027
- return app.scene;
3416
+ disconnectedCallback() {
3417
+ this._unloadSkybox();
3028
3418
  }
3029
- initSkybox(source) {
3419
+ _generateSkybox(asset) {
3420
+ if (!this._scene)
3421
+ return;
3422
+ const source = asset.resource;
3030
3423
  source.anisotropy = 4;
3031
3424
  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;
3425
+ this._scene.skybox = skybox;
3426
+ if (this._lighting) {
3427
+ const lighting = playcanvas.EnvLighting.generateLightingSource(source);
3428
+ const envAtlas = playcanvas.EnvLighting.generateAtlas(lighting);
3429
+ this._scene.envAtlas = envAtlas;
3045
3430
  }
3431
+ const layer = this._scene.layers.getLayerById(playcanvas.LAYERID_SKYBOX);
3432
+ if (layer) {
3433
+ layer.enabled = this._type !== 'none';
3434
+ }
3435
+ this._scene.sky.type = this._type;
3436
+ this._scene.sky.node.setLocalScale(this._scale);
3437
+ this._scene.sky.center = this._center;
3438
+ }
3439
+ async _loadSkybox() {
3440
+ var _a;
3441
+ const appElement = await ((_a = this.closestApp) === null || _a === void 0 ? void 0 : _a.ready());
3442
+ const app = appElement === null || appElement === void 0 ? void 0 : appElement.app;
3443
+ if (!app) {
3444
+ return;
3445
+ }
3446
+ const asset = AssetElement.get(this._asset);
3447
+ if (!asset) {
3448
+ return;
3449
+ }
3450
+ this._scene = app.scene;
3451
+ if (asset.loaded) {
3452
+ this._generateSkybox(asset);
3453
+ }
3454
+ else {
3455
+ asset.once('load', () => {
3456
+ this._generateSkybox(asset);
3457
+ });
3458
+ app.assets.load(asset);
3459
+ }
3460
+ }
3461
+ _unloadSkybox() {
3462
+ var _a, _b;
3463
+ if (!this._scene)
3464
+ return;
3465
+ (_a = this._scene.skybox) === null || _a === void 0 ? void 0 : _a.destroy();
3466
+ // @ts-ignore
3467
+ this._scene.skybox = null;
3468
+ (_b = this._scene.envAtlas) === null || _b === void 0 ? void 0 : _b.destroy();
3469
+ // @ts-ignore
3470
+ this._scene.envAtlas = null;
3471
+ this._scene = null;
3046
3472
  }
3047
3473
  set asset(value) {
3048
3474
  this._asset = value;
3049
- const scene = this.getScene();
3050
- if (scene) {
3051
- const asset = AssetElement.get(value);
3052
- if (asset) {
3053
- this.initSkybox(asset.resource);
3054
- }
3475
+ if (this.isConnected) {
3476
+ this._loadSkybox();
3055
3477
  }
3056
3478
  }
3057
3479
  get asset() {
@@ -3059,9 +3481,8 @@ class SkyElement extends AsyncElement {
3059
3481
  }
3060
3482
  set center(value) {
3061
3483
  this._center = value;
3062
- const scene = this.getScene();
3063
- if (scene) {
3064
- scene.sky.center = this._center;
3484
+ if (this._scene) {
3485
+ this._scene.sky.center = this._center;
3065
3486
  }
3066
3487
  }
3067
3488
  get center() {
@@ -3069,19 +3490,32 @@ class SkyElement extends AsyncElement {
3069
3490
  }
3070
3491
  set intensity(value) {
3071
3492
  this._intensity = value;
3072
- const scene = this.getScene();
3073
- if (scene) {
3074
- scene.skyboxIntensity = this._intensity;
3493
+ if (this._scene) {
3494
+ this._scene.skyboxIntensity = this._intensity;
3075
3495
  }
3076
3496
  }
3077
3497
  get intensity() {
3078
3498
  return this._intensity;
3079
3499
  }
3500
+ set level(value) {
3501
+ this._level = value;
3502
+ if (this._scene) {
3503
+ this._scene.skyboxMip = this._level;
3504
+ }
3505
+ }
3506
+ get level() {
3507
+ return this._level;
3508
+ }
3509
+ set lighting(value) {
3510
+ this._lighting = value;
3511
+ }
3512
+ get lighting() {
3513
+ return this._lighting;
3514
+ }
3080
3515
  set rotation(value) {
3081
3516
  this._rotation = value;
3082
- const scene = this.getScene();
3083
- if (scene) {
3084
- scene.skyboxRotation = new playcanvas.Quat().setFromEulerAngles(value);
3517
+ if (this._scene) {
3518
+ this._scene.skyboxRotation = new playcanvas.Quat().setFromEulerAngles(value);
3085
3519
  }
3086
3520
  }
3087
3521
  get rotation() {
@@ -3089,30 +3523,18 @@ class SkyElement extends AsyncElement {
3089
3523
  }
3090
3524
  set scale(value) {
3091
3525
  this._scale = value;
3092
- const scene = this.getScene();
3093
- if (scene) {
3094
- scene.sky.node.setLocalScale(this._scale);
3526
+ if (this._scene) {
3527
+ this._scene.sky.node.setLocalScale(this._scale);
3095
3528
  }
3096
3529
  }
3097
3530
  get scale() {
3098
3531
  return this._scale;
3099
3532
  }
3100
- set level(value) {
3101
- this._level = value;
3102
- const scene = this.getScene();
3103
- if (scene) {
3104
- scene.skyboxMip = this._level;
3105
- }
3106
- }
3107
- get level() {
3108
- return this._level;
3109
- }
3110
3533
  set type(value) {
3111
3534
  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);
3535
+ if (this._scene) {
3536
+ this._scene.sky.type = this._type;
3537
+ const layer = this._scene.layers.getLayerById(playcanvas.LAYERID_SKYBOX);
3116
3538
  if (layer) {
3117
3539
  layer.enabled = this._type !== 'none';
3118
3540
  }
@@ -3122,7 +3544,7 @@ class SkyElement extends AsyncElement {
3122
3544
  return this._type;
3123
3545
  }
3124
3546
  static get observedAttributes() {
3125
- return ['asset', 'center', 'intensity', 'level', 'rotation', 'scale', 'type'];
3547
+ return ['asset', 'center', 'intensity', 'level', 'lighting', 'rotation', 'scale', 'type'];
3126
3548
  }
3127
3549
  attributeChangedCallback(name, _oldValue, newValue) {
3128
3550
  switch (name) {
@@ -3135,12 +3557,15 @@ class SkyElement extends AsyncElement {
3135
3557
  case 'intensity':
3136
3558
  this.intensity = parseFloat(newValue);
3137
3559
  break;
3138
- case 'rotation':
3139
- this.rotation = parseVec3(newValue);
3140
- break;
3141
3560
  case 'level':
3142
3561
  this.level = parseInt(newValue, 10);
3143
3562
  break;
3563
+ case 'lighting':
3564
+ this.lighting = this.hasAttribute(name);
3565
+ break;
3566
+ case 'rotation':
3567
+ this.rotation = parseVec3(newValue);
3568
+ break;
3144
3569
  case 'scale':
3145
3570
  this.scale = parseVec3(newValue);
3146
3571
  break;