@playcanvas/web-components 0.1.9 → 0.1.11

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.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { basisInitialize, 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';
1
+ import { basisInitialize, WasmModule, Application, Keyboard, Mouse, FILLMODE_FILL_WINDOW, RESOLUTION_AUTO, Picker, Color, Quat, Vec2, Vec3, Vec4, Entity, Asset, GAMMA_SRGB, GAMMA_NONE, XRTYPE_VR, PROJECTION_ORTHOGRAPHIC, PROJECTION_PERSPECTIVE, TONEMAP_NONE, TONEMAP_LINEAR, TONEMAP_FILMIC, TONEMAP_HEJL, TONEMAP_ACES, TONEMAP_ACES2, TONEMAP_NEUTRAL, SHADOW_PCF3_32F, SHADOW_PCF1_16F, SHADOW_PCF1_32F, SHADOW_PCF3_16F, SHADOW_PCF5_16F, SHADOW_PCF5_32F, SHADOW_VSM_16F, SHADOW_VSM_32F, SHADOW_PCSS_32F, StandardMaterial, SCALEMODE_BLEND, SCALEMODE_NONE, EnvLighting, LAYERID_SKYBOX } from 'playcanvas';
2
2
 
3
3
  /**
4
4
  * Base class for all PlayCanvas Web Components that initialize asynchronously.
@@ -13,11 +13,11 @@ class AsyncElement extends HTMLElement {
13
13
  }
14
14
  get closestApp() {
15
15
  var _a;
16
- return (_a = this.parentElement) === null || _a === void 0 ? void 0 : _a.closest('pc-app');
16
+ return (_a = this.parentElement) === null || _a === undefined ? undefined : _a.closest('pc-app');
17
17
  }
18
18
  get closestEntity() {
19
19
  var _a;
20
- return (_a = this.parentElement) === null || _a === void 0 ? void 0 : _a.closest('pc-entity');
20
+ return (_a = this.parentElement) === null || _a === undefined ? undefined : _a.closest('pc-entity');
21
21
  }
22
22
  /**
23
23
  * Called when the element is fully initialized and ready.
@@ -97,6 +97,20 @@ class AppElement extends AsyncElement {
97
97
  this._stencil = true;
98
98
  this._highResolution = false;
99
99
  this._hierarchyReady = false;
100
+ this._picker = null;
101
+ this._hasPointerListeners = {
102
+ pointerenter: false,
103
+ pointerleave: false,
104
+ pointerdown: false,
105
+ pointerup: false,
106
+ pointermove: false
107
+ };
108
+ this._hoveredEntity = null;
109
+ this._pointerHandlers = {
110
+ pointermove: null,
111
+ pointerdown: null,
112
+ pointerup: null
113
+ };
100
114
  /**
101
115
  * The PlayCanvas application instance.
102
116
  */
@@ -126,6 +140,7 @@ class AppElement extends AsyncElement {
126
140
  this.app.graphicsDevice.maxPixelRatio = this._highResolution ? window.devicePixelRatio : 1;
127
141
  this.app.setCanvasFillMode(FILLMODE_FILL_WINDOW);
128
142
  this.app.setCanvasResolution(RESOLUTION_AUTO);
143
+ this._pickerCreate();
129
144
  // Get all pc-asset elements that are direct children of the pc-app element
130
145
  const assetElements = this.querySelectorAll(':scope > pc-asset');
131
146
  Array.from(assetElements).forEach((assetElement) => {
@@ -160,6 +175,7 @@ class AppElement extends AsyncElement {
160
175
  });
161
176
  }
162
177
  disconnectedCallback() {
178
+ this._pickerDestroy();
163
179
  // Clean up the application
164
180
  if (this.app) {
165
181
  this.app.destroy();
@@ -178,6 +194,139 @@ class AppElement extends AsyncElement {
178
194
  this.app.resizeCanvas();
179
195
  }
180
196
  }
197
+ _pickerCreate() {
198
+ const { width, height } = this.app.graphicsDevice;
199
+ this._picker = new Picker(this.app, width, height);
200
+ // Create bound handlers but don't attach them yet
201
+ this._pointerHandlers.pointermove = this._onPointerMove.bind(this);
202
+ this._pointerHandlers.pointerdown = this._onPointerDown.bind(this);
203
+ this._pointerHandlers.pointerup = this._onPointerUp.bind(this);
204
+ // Listen for pointer listeners being added/removed
205
+ ['pointermove', 'pointerdown', 'pointerup', 'pointerenter', 'pointerleave'].forEach((type) => {
206
+ this.addEventListener(`${type}:connect`, () => this._onPointerListenerAdded(type));
207
+ this.addEventListener(`${type}:disconnect`, () => this._onPointerListenerRemoved(type));
208
+ });
209
+ }
210
+ _pickerDestroy() {
211
+ if (this._canvas) {
212
+ Object.entries(this._pointerHandlers).forEach(([type, handler]) => {
213
+ if (handler) {
214
+ this._canvas.removeEventListener(type, handler);
215
+ }
216
+ });
217
+ }
218
+ this._picker = null;
219
+ this._pointerHandlers = {
220
+ pointermove: null,
221
+ pointerdown: null,
222
+ pointerup: null
223
+ };
224
+ }
225
+ _onPointerMove(event) {
226
+ if (!this._picker || !this.app)
227
+ return;
228
+ const camera = this.app.root.findComponent('camera');
229
+ if (!camera)
230
+ return;
231
+ const canvasRect = this._canvas.getBoundingClientRect();
232
+ const x = event.clientX - canvasRect.left;
233
+ const y = event.clientY - canvasRect.top;
234
+ this._picker.prepare(camera, this.app.scene);
235
+ const selection = this._picker.getSelection(x, y);
236
+ // Get the currently hovered entity by walking up the hierarchy
237
+ let newHoverEntity = null;
238
+ if (selection.length > 0) {
239
+ let node = selection[0].node;
240
+ while (node && !newHoverEntity) {
241
+ const entityElement = this.querySelector(`pc-entity[name="${node.name}"]`);
242
+ if (entityElement) {
243
+ newHoverEntity = entityElement;
244
+ }
245
+ node = node.parent;
246
+ }
247
+ }
248
+ // Handle enter/leave events
249
+ if (this._hoveredEntity !== newHoverEntity) {
250
+ if (this._hoveredEntity && this._hoveredEntity.hasListeners('pointerleave')) {
251
+ this._hoveredEntity.dispatchEvent(new PointerEvent('pointerleave', event));
252
+ }
253
+ if (newHoverEntity && newHoverEntity.hasListeners('pointerenter')) {
254
+ newHoverEntity.dispatchEvent(new PointerEvent('pointerenter', event));
255
+ }
256
+ }
257
+ // Update hover state
258
+ this._hoveredEntity = newHoverEntity;
259
+ // Handle pointermove event
260
+ if (newHoverEntity && newHoverEntity.hasListeners('pointermove')) {
261
+ newHoverEntity.dispatchEvent(new PointerEvent('pointermove', event));
262
+ }
263
+ }
264
+ _onPointerDown(event) {
265
+ if (!this._picker || !this.app)
266
+ return;
267
+ const camera = this.app.root.findComponent('camera');
268
+ if (!camera)
269
+ return;
270
+ const canvasRect = this._canvas.getBoundingClientRect();
271
+ const x = event.clientX - canvasRect.left;
272
+ const y = event.clientY - canvasRect.top;
273
+ this._picker.prepare(camera, this.app.scene);
274
+ const selection = this._picker.getSelection(x, y);
275
+ if (selection.length > 0) {
276
+ let node = selection[0].node;
277
+ while (node) {
278
+ const entityElement = this.querySelector(`pc-entity[name="${node.name}"]`);
279
+ if (entityElement && entityElement.hasListeners('pointerdown')) {
280
+ entityElement.dispatchEvent(new PointerEvent('pointerdown', event));
281
+ break;
282
+ }
283
+ node = node.parent;
284
+ }
285
+ }
286
+ }
287
+ _onPointerUp(event) {
288
+ if (!this._picker || !this.app)
289
+ return;
290
+ const camera = this.app.root.findComponent('camera');
291
+ if (!camera)
292
+ return;
293
+ const canvasRect = this._canvas.getBoundingClientRect();
294
+ const x = event.clientX - canvasRect.left;
295
+ const y = event.clientY - canvasRect.top;
296
+ this._picker.prepare(camera, this.app.scene);
297
+ const selection = this._picker.getSelection(x, y);
298
+ if (selection.length > 0) {
299
+ const entityElement = this.querySelector(`pc-entity[name="${selection[0].node.name}"]`);
300
+ if (entityElement && entityElement.hasListeners('pointerup')) {
301
+ entityElement.dispatchEvent(new PointerEvent('pointerup', event));
302
+ }
303
+ }
304
+ }
305
+ _onPointerListenerAdded(type) {
306
+ if (!this._hasPointerListeners[type] && this._canvas) {
307
+ this._hasPointerListeners[type] = true;
308
+ // For enter/leave events, we need the move handler
309
+ const handler = (type === 'pointerenter' || type === 'pointerleave') ?
310
+ this._pointerHandlers.pointermove :
311
+ this._pointerHandlers[type];
312
+ if (handler) {
313
+ this._canvas.addEventListener(type === 'pointerenter' || type === 'pointerleave' ? 'pointermove' : type, handler);
314
+ }
315
+ }
316
+ }
317
+ _onPointerListenerRemoved(type) {
318
+ const hasListeners = Array.from(this.querySelectorAll('pc-entity'))
319
+ .some(entity => entity.hasListeners(type));
320
+ if (!hasListeners && this._canvas) {
321
+ this._hasPointerListeners[type] = false;
322
+ const handler = (type === 'pointerenter' || type === 'pointerleave') ?
323
+ this._pointerHandlers.pointermove :
324
+ this._pointerHandlers[type];
325
+ if (handler) {
326
+ this._canvas.removeEventListener(type === 'pointerenter' || type === 'pointerleave' ? 'pointermove' : type, handler);
327
+ }
328
+ }
329
+ }
181
330
  /**
182
331
  * Sets the alpha flag.
183
332
  * @param value - The alpha flag.
@@ -530,6 +679,10 @@ class EntityElement extends AsyncElement {
530
679
  * The tags of the entity.
531
680
  */
532
681
  this._tags = [];
682
+ /**
683
+ * The pointer event listeners for the entity.
684
+ */
685
+ this._listeners = {};
533
686
  /**
534
687
  * The PlayCanvas entity instance.
535
688
  */
@@ -558,12 +711,36 @@ class EntityElement extends AsyncElement {
558
711
  if (tags) {
559
712
  this.entity.tags.add(tags.split(',').map(tag => tag.trim()));
560
713
  }
714
+ // Handle pointer events
715
+ const pointerEvents = [
716
+ 'onpointerenter',
717
+ 'onpointerleave',
718
+ 'onpointerdown',
719
+ 'onpointerup',
720
+ 'onpointermove'
721
+ ];
722
+ pointerEvents.forEach((eventName) => {
723
+ const handler = this.getAttribute(eventName);
724
+ if (handler) {
725
+ const eventType = eventName.substring(2); // remove 'on' prefix
726
+ const eventHandler = (event) => {
727
+ try {
728
+ /* eslint-disable-next-line no-new-func */
729
+ new Function('event', handler).call(this, event);
730
+ }
731
+ catch (e) {
732
+ console.error('Error in event handler:', e);
733
+ }
734
+ };
735
+ this.addEventListener(eventType, eventHandler);
736
+ }
737
+ });
561
738
  }
562
739
  buildHierarchy(app) {
563
740
  if (!this.entity)
564
741
  return;
565
742
  const closestEntity = this.closestEntity;
566
- if (closestEntity === null || closestEntity === void 0 ? void 0 : closestEntity.entity) {
743
+ if (closestEntity === null || closestEntity === undefined ? undefined : closestEntity.entity) {
567
744
  closestEntity.entity.addChild(this.entity);
568
745
  }
569
746
  else {
@@ -707,7 +884,19 @@ class EntityElement extends AsyncElement {
707
884
  return this._tags;
708
885
  }
709
886
  static get observedAttributes() {
710
- return ['enabled', 'name', 'position', 'rotation', 'scale', 'tags'];
887
+ return [
888
+ 'enabled',
889
+ 'name',
890
+ 'position',
891
+ 'rotation',
892
+ 'scale',
893
+ 'tags',
894
+ 'onpointerenter',
895
+ 'onpointerleave',
896
+ 'onpointerdown',
897
+ 'onpointerup',
898
+ 'onpointermove'
899
+ ];
711
900
  }
712
901
  attributeChangedCallback(name, _oldValue, newValue) {
713
902
  switch (name) {
@@ -729,7 +918,51 @@ class EntityElement extends AsyncElement {
729
918
  case 'tags':
730
919
  this.tags = newValue.split(',').map(tag => tag.trim());
731
920
  break;
921
+ case 'onpointerenter':
922
+ case 'onpointerleave':
923
+ case 'onpointerdown':
924
+ case 'onpointerup':
925
+ case 'onpointermove':
926
+ if (newValue) {
927
+ const eventName = name.substring(2);
928
+ // Use Function.prototype.bind to avoid new Function
929
+ const handler = (event) => {
930
+ try {
931
+ const handlerStr = this.getAttribute(eventName) || '';
932
+ /* eslint-disable-next-line no-new-func */
933
+ new Function('event', handlerStr).call(this, event);
934
+ }
935
+ catch (e) {
936
+ console.error('Error in event handler:', e);
937
+ }
938
+ };
939
+ this.addEventListener(eventName, handler);
940
+ }
941
+ break;
942
+ }
943
+ }
944
+ addEventListener(type, listener, options) {
945
+ if (!this._listeners[type]) {
946
+ this._listeners[type] = [];
947
+ }
948
+ this._listeners[type].push(listener);
949
+ super.addEventListener(type, listener, options);
950
+ if (type.startsWith('pointer')) {
951
+ this.dispatchEvent(new CustomEvent(`${type}:connect`, { bubbles: true }));
952
+ }
953
+ }
954
+ removeEventListener(type, listener, options) {
955
+ if (this._listeners[type]) {
956
+ this._listeners[type] = this._listeners[type].filter(l => l !== listener);
732
957
  }
958
+ super.removeEventListener(type, listener, options);
959
+ if (type.startsWith('pointer')) {
960
+ this.dispatchEvent(new CustomEvent(`${type}:disconnect`, { bubbles: true }));
961
+ }
962
+ }
963
+ hasListeners(type) {
964
+ var _a;
965
+ return Boolean((_a = this._listeners[type]) === null || _a === undefined ? undefined : _a.length);
733
966
  }
734
967
  }
735
968
  customElements.define('pc-entity', EntityElement);
@@ -778,7 +1011,7 @@ class AssetElement extends HTMLElement {
778
1011
  // If no type is specified, try to infer it from the file extension.
779
1012
  if (!type) {
780
1013
  const ext = src.split('.').pop();
781
- type = (_a = extToType.get(ext || '')) !== null && _a !== void 0 ? _a : null;
1014
+ type = (_a = extToType.get(ext || '')) !== null && _a !== undefined ? _a : null;
782
1015
  }
783
1016
  if (!type) {
784
1017
  console.warn(`Unsupported asset type: ${src}`);
@@ -812,7 +1045,7 @@ class AssetElement extends HTMLElement {
812
1045
  }
813
1046
  static get(id) {
814
1047
  const assetElement = document.querySelector(`pc-asset[id="${id}"]`);
815
- return assetElement === null || assetElement === void 0 ? void 0 : assetElement.asset;
1048
+ return assetElement === null || assetElement === undefined ? undefined : assetElement.asset;
816
1049
  }
817
1050
  static get observedAttributes() {
818
1051
  return ['preload'];
@@ -859,7 +1092,7 @@ class ComponentElement extends AsyncElement {
859
1092
  initComponent() { }
860
1093
  async connectedCallback() {
861
1094
  var _a;
862
- await ((_a = this.closestApp) === null || _a === void 0 ? void 0 : _a.ready());
1095
+ await ((_a = this.closestApp) === null || _a === undefined ? undefined : _a.ready());
863
1096
  await this.addComponent();
864
1097
  this.initComponent();
865
1098
  this._onReady();
@@ -925,6 +1158,15 @@ class ListenerComponentElement extends ComponentElement {
925
1158
  }
926
1159
  customElements.define('pc-listener', ListenerComponentElement);
927
1160
 
1161
+ const tonemaps = new Map([
1162
+ ['none', TONEMAP_NONE],
1163
+ ['linear', TONEMAP_LINEAR],
1164
+ ['filmic', TONEMAP_FILMIC],
1165
+ ['hejl', TONEMAP_HEJL],
1166
+ ['aces', TONEMAP_ACES],
1167
+ ['aces2', TONEMAP_ACES2],
1168
+ ['neutral', TONEMAP_NEUTRAL]
1169
+ ]);
928
1170
  /**
929
1171
  * The CameraComponentElement interface provides properties and methods for manipulating
930
1172
  * `<pc-camera>` elements. The CameraComponentElement interface also inherits the properties and
@@ -945,12 +1187,15 @@ class CameraComponentElement extends ComponentElement {
945
1187
  this._flipFaces = false;
946
1188
  this._fov = 45;
947
1189
  this._frustumCulling = true;
1190
+ this._gamma = 'srgb';
1191
+ this._horizontalFov = false;
948
1192
  this._nearClip = 0.1;
949
1193
  this._orthographic = false;
950
1194
  this._orthoHeight = 10;
951
1195
  this._priority = 0;
952
1196
  this._rect = new Vec4(0, 0, 1, 1);
953
1197
  this._scissorRect = new Vec4(0, 0, 1, 1);
1198
+ this._tonemap = 'none';
954
1199
  }
955
1200
  getInitialComponentData() {
956
1201
  return {
@@ -963,17 +1208,20 @@ class CameraComponentElement extends ComponentElement {
963
1208
  flipFaces: this._flipFaces,
964
1209
  fov: this._fov,
965
1210
  frustumCulling: this._frustumCulling,
1211
+ gammaCorrection: this._gamma === 'srgb' ? GAMMA_SRGB : GAMMA_NONE,
1212
+ horizontalFov: this._horizontalFov,
966
1213
  nearClip: this._nearClip,
967
1214
  orthographic: this._orthographic,
968
1215
  orthoHeight: this._orthoHeight,
969
1216
  priority: this._priority,
970
1217
  rect: this._rect,
971
- scissorRect: this._scissorRect
1218
+ scissorRect: this._scissorRect,
1219
+ toneMapping: tonemaps.get(this._tonemap)
972
1220
  };
973
1221
  }
974
1222
  get xrAvailable() {
975
1223
  var _a;
976
- const xrManager = (_a = this.component) === null || _a === void 0 ? void 0 : _a.system.app.xr;
1224
+ const xrManager = (_a = this.component) === null || _a === undefined ? undefined : _a.system.app.xr;
977
1225
  return xrManager && xrManager.supported && xrManager.isAvailable(XRTYPE_VR);
978
1226
  }
979
1227
  startXr(type, space) {
@@ -1151,6 +1399,41 @@ class CameraComponentElement extends ComponentElement {
1151
1399
  get frustumCulling() {
1152
1400
  return this._frustumCulling;
1153
1401
  }
1402
+ /**
1403
+ * Sets the gamma correction of the camera.
1404
+ * @param value - The gamma correction.
1405
+ */
1406
+ set gamma(value) {
1407
+ this._gamma = value;
1408
+ if (this.component) {
1409
+ this.component.gammaCorrection = value === 'srgb' ? GAMMA_SRGB : GAMMA_NONE;
1410
+ }
1411
+ }
1412
+ /**
1413
+ * Gets the gamma correction of the camera.
1414
+ * @returns The gamma correction.
1415
+ */
1416
+ get gamma() {
1417
+ return this._gamma;
1418
+ }
1419
+ /**
1420
+ * Sets whether the camera's field of view (fov) is horizontal or vertical. Defaults to false
1421
+ * (meaning it is vertical be default).
1422
+ * @param value - Whether the camera's field of view is horizontal.
1423
+ */
1424
+ set horizontalFov(value) {
1425
+ this._horizontalFov = value;
1426
+ if (this.component) {
1427
+ this.component.horizontalFov = value;
1428
+ }
1429
+ }
1430
+ /**
1431
+ * Gets whether the camera's field of view (fov) is horizontal or vertical.
1432
+ * @returns Whether the camera's field of view is horizontal.
1433
+ */
1434
+ get horizontalFov() {
1435
+ return this._horizontalFov;
1436
+ }
1154
1437
  /**
1155
1438
  * Sets the near clip distance of the camera.
1156
1439
  * @param value - The near clip distance.
@@ -1253,6 +1536,24 @@ class CameraComponentElement extends ComponentElement {
1253
1536
  get scissorRect() {
1254
1537
  return this._scissorRect;
1255
1538
  }
1539
+ /**
1540
+ * Sets the tone mapping of the camera.
1541
+ * @param value - The tone mapping.
1542
+ */
1543
+ set tonemap(value) {
1544
+ var _a;
1545
+ this._tonemap = value;
1546
+ if (this.component) {
1547
+ this.component.toneMapping = (_a = tonemaps.get(value)) !== null && _a !== undefined ? _a : TONEMAP_NONE;
1548
+ }
1549
+ }
1550
+ /**
1551
+ * Gets the tone mapping of the camera.
1552
+ * @returns The tone mapping.
1553
+ */
1554
+ get tonemap() {
1555
+ return this._tonemap;
1556
+ }
1256
1557
  static get observedAttributes() {
1257
1558
  return [
1258
1559
  ...super.observedAttributes,
@@ -1265,12 +1566,15 @@ class CameraComponentElement extends ComponentElement {
1265
1566
  'flip-faces',
1266
1567
  'fov',
1267
1568
  'frustum-culling',
1569
+ 'gamma',
1570
+ 'horizontal-fov',
1268
1571
  'near-clip',
1269
1572
  'orthographic',
1270
1573
  'ortho-height',
1271
1574
  'priority',
1272
1575
  'rect',
1273
- 'scissor-rect'
1576
+ 'scissor-rect',
1577
+ 'tonemap'
1274
1578
  ];
1275
1579
  }
1276
1580
  attributeChangedCallback(name, _oldValue, newValue) {
@@ -1303,6 +1607,12 @@ class CameraComponentElement extends ComponentElement {
1303
1607
  case 'frustum-culling':
1304
1608
  this.frustumCulling = newValue !== 'false';
1305
1609
  break;
1610
+ case 'gamma':
1611
+ this.gamma = newValue;
1612
+ break;
1613
+ case 'horizontal-fov':
1614
+ this.horizontalFov = this.hasAttribute('horizontal-fov');
1615
+ break;
1306
1616
  case 'near-clip':
1307
1617
  this.nearClip = parseFloat(newValue);
1308
1618
  break;
@@ -1321,6 +1631,9 @@ class CameraComponentElement extends ComponentElement {
1321
1631
  case 'scissor-rect':
1322
1632
  this.scissorRect = parseVec4(newValue);
1323
1633
  break;
1634
+ case 'tonemap':
1635
+ this.tonemap = newValue;
1636
+ break;
1324
1637
  }
1325
1638
  }
1326
1639
  }
@@ -1734,6 +2047,17 @@ class GSplatComponentElement extends ComponentElement {
1734
2047
  }
1735
2048
  customElements.define('pc-splat', GSplatComponentElement);
1736
2049
 
2050
+ const shadowTypes = new Map([
2051
+ ['pcf1-16f', SHADOW_PCF1_16F],
2052
+ ['pcf1-32f', SHADOW_PCF1_32F],
2053
+ ['pcf3-16f', SHADOW_PCF3_16F],
2054
+ ['pcf3-32f', SHADOW_PCF3_32F],
2055
+ ['pcf5-16f', SHADOW_PCF5_16F],
2056
+ ['pcf5-32f', SHADOW_PCF5_32F],
2057
+ ['vsm-16f', SHADOW_VSM_16F],
2058
+ ['vsm-32f', SHADOW_VSM_32F],
2059
+ ['pcss-32f', SHADOW_PCSS_32F]
2060
+ ]);
1737
2061
  /**
1738
2062
  * The LightComponentElement interface provides properties and methods for manipulating
1739
2063
  * `<pc-light>` elements. The LightComponentElement interface also inherits the properties and
@@ -1754,8 +2078,11 @@ class LightComponentElement extends ComponentElement {
1754
2078
  this._range = 10;
1755
2079
  this._shadowBias = 0.2;
1756
2080
  this._shadowDistance = 16;
2081
+ this._shadowIntensity = 1;
1757
2082
  this._shadowResolution = 1024;
2083
+ this._shadowType = 'pcf3-32f';
1758
2084
  this._type = 'directional';
2085
+ this._vsmBias = 0.01;
1759
2086
  }
1760
2087
  getInitialComponentData() {
1761
2088
  return {
@@ -1768,8 +2095,11 @@ class LightComponentElement extends ComponentElement {
1768
2095
  range: this._range,
1769
2096
  shadowBias: this._shadowBias,
1770
2097
  shadowDistance: this._shadowDistance,
2098
+ shadowIntensity: this._shadowIntensity,
1771
2099
  shadowResolution: this._shadowResolution,
1772
- type: this._type
2100
+ shadowType: shadowTypes.get(this._shadowType),
2101
+ type: this._type,
2102
+ vsmBias: this._vsmBias
1773
2103
  };
1774
2104
  }
1775
2105
  /**
@@ -1932,6 +2262,23 @@ class LightComponentElement extends ComponentElement {
1932
2262
  get shadowDistance() {
1933
2263
  return this._shadowDistance;
1934
2264
  }
2265
+ /**
2266
+ * Sets the shadow intensity of the light.
2267
+ * @param value - The shadow intensity.
2268
+ */
2269
+ set shadowIntensity(value) {
2270
+ this._shadowIntensity = value;
2271
+ if (this.component) {
2272
+ this.component.shadowIntensity = value;
2273
+ }
2274
+ }
2275
+ /**
2276
+ * Gets the shadow intensity of the light.
2277
+ * @returns The shadow intensity.
2278
+ */
2279
+ get shadowIntensity() {
2280
+ return this._shadowIntensity;
2281
+ }
1935
2282
  /**
1936
2283
  * Sets the shadow resolution of the light.
1937
2284
  * @param value - The shadow resolution.
@@ -1949,6 +2296,34 @@ class LightComponentElement extends ComponentElement {
1949
2296
  get shadowResolution() {
1950
2297
  return this._shadowResolution;
1951
2298
  }
2299
+ /**
2300
+ * Sets the shadow type of the light.
2301
+ * @param value - The shadow type. Can be:
2302
+ *
2303
+ * - `pcf1-16f` - 1-tap percentage-closer filtered shadow map with 16-bit depth.
2304
+ * - `pcf1-32f` - 1-tap percentage-closer filtered shadow map with 32-bit depth.
2305
+ * - `pcf3-16f` - 3-tap percentage-closer filtered shadow map with 16-bit depth.
2306
+ * - `pcf3-32f` - 3-tap percentage-closer filtered shadow map with 32-bit depth.
2307
+ * - `pcf5-16f` - 5-tap percentage-closer filtered shadow map with 16-bit depth.
2308
+ * - `pcf5-32f` - 5-tap percentage-closer filtered shadow map with 32-bit depth.
2309
+ * - `vsm-16f` - Variance shadow map with 16-bit depth.
2310
+ * - `vsm-32f` - Variance shadow map with 32-bit depth.
2311
+ * - `pcss-32f` - Percentage-closer soft shadow with 32-bit depth.
2312
+ */
2313
+ set shadowType(value) {
2314
+ var _a;
2315
+ this._shadowType = value;
2316
+ if (this.component) {
2317
+ this.component.shadowType = (_a = shadowTypes.get(value)) !== null && _a !== undefined ? _a : SHADOW_PCF3_32F;
2318
+ }
2319
+ }
2320
+ /**
2321
+ * Gets the shadow type of the light.
2322
+ * @returns The shadow type.
2323
+ */
2324
+ get shadowType() {
2325
+ return this._shadowType;
2326
+ }
1952
2327
  /**
1953
2328
  * Sets the type of the light.
1954
2329
  * @param value - The type.
@@ -1970,6 +2345,23 @@ class LightComponentElement extends ComponentElement {
1970
2345
  get type() {
1971
2346
  return this._type;
1972
2347
  }
2348
+ /**
2349
+ * Sets the VSM bias of the light.
2350
+ * @param value - The VSM bias.
2351
+ */
2352
+ set vsmBias(value) {
2353
+ this._vsmBias = value;
2354
+ if (this.component) {
2355
+ this.component.vsmBias = value;
2356
+ }
2357
+ }
2358
+ /**
2359
+ * Gets the VSM bias of the light.
2360
+ * @returns The VSM bias.
2361
+ */
2362
+ get vsmBias() {
2363
+ return this._vsmBias;
2364
+ }
1973
2365
  static get observedAttributes() {
1974
2366
  return [
1975
2367
  ...super.observedAttributes,
@@ -1982,8 +2374,11 @@ class LightComponentElement extends ComponentElement {
1982
2374
  'range',
1983
2375
  'shadow-bias',
1984
2376
  'shadow-distance',
2377
+ 'shadow-intensity',
1985
2378
  'shadow-resolution',
1986
- 'type'
2379
+ 'shadow-type',
2380
+ 'type',
2381
+ 'vsm-bias'
1987
2382
  ];
1988
2383
  }
1989
2384
  attributeChangedCallback(name, _oldValue, newValue) {
@@ -2019,9 +2414,18 @@ class LightComponentElement extends ComponentElement {
2019
2414
  case 'shadow-resolution':
2020
2415
  this.shadowResolution = Number(newValue);
2021
2416
  break;
2417
+ case 'shadow-intensity':
2418
+ this.shadowIntensity = Number(newValue);
2419
+ break;
2420
+ case 'shadow-type':
2421
+ this.shadowType = newValue;
2422
+ break;
2022
2423
  case 'type':
2023
2424
  this.type = newValue;
2024
2425
  break;
2426
+ case 'vsm-bias':
2427
+ this.vsmBias = Number(newValue);
2428
+ break;
2025
2429
  }
2026
2430
  }
2027
2431
  }
@@ -2044,8 +2448,8 @@ class MaterialElement extends HTMLElement {
2044
2448
  }
2045
2449
  createMaterial() {
2046
2450
  this.material = new StandardMaterial();
2047
- this.material.glossInvert = true;
2048
- this.material.useMetalness = true;
2451
+ this.material.glossInvert = false;
2452
+ this.material.useMetalness = false;
2049
2453
  this.material.diffuse = this._diffuse;
2050
2454
  this.diffuseMap = this._diffuseMap;
2051
2455
  this.metalnessMap = this._metalnessMap;
@@ -2116,7 +2520,7 @@ class MaterialElement extends HTMLElement {
2116
2520
  }
2117
2521
  static get(id) {
2118
2522
  const materialElement = document.querySelector(`pc-material[id="${id}"]`);
2119
- return materialElement === null || materialElement === void 0 ? void 0 : materialElement.material;
2523
+ return materialElement === null || materialElement === undefined ? undefined : materialElement.material;
2120
2524
  }
2121
2525
  static get observedAttributes() {
2122
2526
  return ['diffuse', 'diffuse-map', 'metalness-map', 'normal-map', 'roughness-map'];
@@ -2578,9 +2982,6 @@ class ScreenComponentElement extends ComponentElement {
2578
2982
  }
2579
2983
  customElements.define('pc-screen', ScreenComponentElement);
2580
2984
 
2581
- const tmpV2 = new Vec2();
2582
- const tmpV3 = new Vec3();
2583
- const tmpV4 = new Vec4();
2584
2985
  /**
2585
2986
  * The ScriptComponentElement interface provides properties and methods for manipulating
2586
2987
  * `<pc-scripts>` elements. The ScriptComponentElement interface also inherits the properties and
@@ -2624,22 +3025,34 @@ class ScriptComponentElement extends ComponentElement {
2624
3025
  return;
2625
3026
  }
2626
3027
  }
2627
- // Handle vectors
2628
- if (Array.isArray(value)) {
2629
- if (target[key] instanceof Vec2) {
2630
- target[key] = tmpV2.set(value[0], value[1]);
3028
+ // Handle arrays
3029
+ if (value && typeof value === 'object' && Array.isArray(value)) {
3030
+ // If it's an array of objects, recursively apply to each object
3031
+ if (value.length > 0 && typeof value[0] === 'object') {
3032
+ target[key] = value.map((item) => {
3033
+ const obj = {};
3034
+ for (const itemKey in item) {
3035
+ applyValue(obj, itemKey, item[itemKey]);
3036
+ }
3037
+ return obj;
3038
+ });
3039
+ return;
3040
+ }
3041
+ // Handle vectors
3042
+ if (value.length === 2 && typeof value[0] === 'number') {
3043
+ target[key] = new Vec2(value[0], value[1]);
2631
3044
  return;
2632
3045
  }
2633
- if (target[key] instanceof Vec3) {
2634
- target[key] = tmpV3.set(value[0], value[1], value[2]);
3046
+ if (value.length === 3 && typeof value[0] === 'number') {
3047
+ target[key] = new Vec3(value[0], value[1], value[2]);
2635
3048
  return;
2636
3049
  }
2637
- if (target[key] instanceof Vec4) {
2638
- target[key] = tmpV4.set(value[0], value[1], value[2], value[3]);
3050
+ if (value.length === 4 && typeof value[0] === 'number') {
3051
+ target[key] = new Vec4(value[0], value[1], value[2], value[3]);
2639
3052
  return;
2640
3053
  }
2641
3054
  }
2642
- // Handle nested objects
3055
+ // Handle nested objects (non-array)
2643
3056
  if (value && typeof value === 'object' && !Array.isArray(value)) {
2644
3057
  if (!target[key] || typeof target[key] !== 'object') {
2645
3058
  target[key] = {};
@@ -2719,7 +3132,7 @@ class ScriptComponentElement extends ComponentElement {
2719
3132
  disconnectedCallback() {
2720
3133
  var _a;
2721
3134
  this.observer.disconnect();
2722
- (_a = super.disconnectedCallback) === null || _a === void 0 ? void 0 : _a.call(this);
3135
+ (_a = super.disconnectedCallback) === null || _a === undefined ? undefined : _a.call(this);
2723
3136
  }
2724
3137
  /**
2725
3138
  * Gets the script component.
@@ -3033,7 +3446,7 @@ class SoundSlotElement extends AsyncElement {
3033
3446
  }
3034
3447
  async connectedCallback() {
3035
3448
  var _a;
3036
- await ((_a = this.soundElement) === null || _a === void 0 ? void 0 : _a.ready());
3449
+ await ((_a = this.soundElement) === null || _a === undefined ? undefined : _a.ready());
3037
3450
  const options = {
3038
3451
  autoPlay: this._autoPlay,
3039
3452
  loop: this._loop,
@@ -3069,7 +3482,7 @@ class SoundSlotElement extends AsyncElement {
3069
3482
  var _a;
3070
3483
  this._asset = value;
3071
3484
  if (this.soundSlot) {
3072
- const id = (_a = AssetElement.get(value)) === null || _a === void 0 ? void 0 : _a.id;
3485
+ const id = (_a = AssetElement.get(value)) === null || _a === undefined ? undefined : _a.id;
3073
3486
  if (id) {
3074
3487
  this.soundSlot.asset = id;
3075
3488
  }
@@ -3296,8 +3709,8 @@ class ModelElement extends AsyncElement {
3296
3709
  async _loadModel() {
3297
3710
  var _a;
3298
3711
  this._unloadModel();
3299
- const appElement = await ((_a = this.closestApp) === null || _a === void 0 ? void 0 : _a.ready());
3300
- const app = appElement === null || appElement === void 0 ? void 0 : appElement.app;
3712
+ const appElement = await ((_a = this.closestApp) === null || _a === undefined ? undefined : _a.ready());
3713
+ const app = appElement === null || appElement === undefined ? undefined : appElement.app;
3301
3714
  const asset = AssetElement.get(this._asset);
3302
3715
  if (!asset) {
3303
3716
  return;
@@ -3314,7 +3727,7 @@ class ModelElement extends AsyncElement {
3314
3727
  }
3315
3728
  _unloadModel() {
3316
3729
  var _a;
3317
- (_a = this._entity) === null || _a === void 0 ? void 0 : _a.destroy();
3730
+ (_a = this._entity) === null || _a === undefined ? undefined : _a.destroy();
3318
3731
  this._entity = null;
3319
3732
  }
3320
3733
  /**
@@ -3382,7 +3795,7 @@ class SceneElement extends AsyncElement {
3382
3795
  }
3383
3796
  async connectedCallback() {
3384
3797
  var _a;
3385
- await ((_a = this.closestApp) === null || _a === void 0 ? void 0 : _a.ready());
3798
+ await ((_a = this.closestApp) === null || _a === undefined ? undefined : _a.ready());
3386
3799
  this.scene = this.closestApp.app.scene;
3387
3800
  this.updateSceneSettings();
3388
3801
  this._onReady();
@@ -3556,8 +3969,8 @@ class SkyElement extends AsyncElement {
3556
3969
  }
3557
3970
  async _loadSkybox() {
3558
3971
  var _a;
3559
- const appElement = await ((_a = this.closestApp) === null || _a === void 0 ? void 0 : _a.ready());
3560
- const app = appElement === null || appElement === void 0 ? void 0 : appElement.app;
3972
+ const appElement = await ((_a = this.closestApp) === null || _a === undefined ? undefined : _a.ready());
3973
+ const app = appElement === null || appElement === undefined ? undefined : appElement.app;
3561
3974
  if (!app) {
3562
3975
  return;
3563
3976
  }
@@ -3580,10 +3993,10 @@ class SkyElement extends AsyncElement {
3580
3993
  var _a, _b;
3581
3994
  if (!this._scene)
3582
3995
  return;
3583
- (_a = this._scene.skybox) === null || _a === void 0 ? void 0 : _a.destroy();
3996
+ (_a = this._scene.skybox) === null || _a === undefined ? undefined : _a.destroy();
3584
3997
  // @ts-ignore
3585
3998
  this._scene.skybox = null;
3586
- (_b = this._scene.envAtlas) === null || _b === void 0 ? void 0 : _b.destroy();
3999
+ (_b = this._scene.envAtlas) === null || _b === undefined ? undefined : _b.destroy();
3587
4000
  // @ts-ignore
3588
4001
  this._scene.envAtlas = null;
3589
4002
  this._scene = null;