@playcanvas/web-components 0.1.9 → 0.1.10

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
@@ -99,6 +99,20 @@ class AppElement extends AsyncElement {
99
99
  this._stencil = true;
100
100
  this._highResolution = false;
101
101
  this._hierarchyReady = false;
102
+ this._picker = null;
103
+ this._hasPointerListeners = {
104
+ pointerenter: false,
105
+ pointerleave: false,
106
+ pointerdown: false,
107
+ pointerup: false,
108
+ pointermove: false
109
+ };
110
+ this._hoveredEntity = null;
111
+ this._pointerHandlers = {
112
+ pointermove: null,
113
+ pointerdown: null,
114
+ pointerup: null
115
+ };
102
116
  /**
103
117
  * The PlayCanvas application instance.
104
118
  */
@@ -128,6 +142,7 @@ class AppElement extends AsyncElement {
128
142
  this.app.graphicsDevice.maxPixelRatio = this._highResolution ? window.devicePixelRatio : 1;
129
143
  this.app.setCanvasFillMode(playcanvas.FILLMODE_FILL_WINDOW);
130
144
  this.app.setCanvasResolution(playcanvas.RESOLUTION_AUTO);
145
+ this._pickerCreate();
131
146
  // Get all pc-asset elements that are direct children of the pc-app element
132
147
  const assetElements = this.querySelectorAll(':scope > pc-asset');
133
148
  Array.from(assetElements).forEach((assetElement) => {
@@ -162,6 +177,7 @@ class AppElement extends AsyncElement {
162
177
  });
163
178
  }
164
179
  disconnectedCallback() {
180
+ this._pickerDestroy();
165
181
  // Clean up the application
166
182
  if (this.app) {
167
183
  this.app.destroy();
@@ -180,6 +196,139 @@ class AppElement extends AsyncElement {
180
196
  this.app.resizeCanvas();
181
197
  }
182
198
  }
199
+ _pickerCreate() {
200
+ const { width, height } = this.app.graphicsDevice;
201
+ this._picker = new playcanvas.Picker(this.app, width, height);
202
+ // Create bound handlers but don't attach them yet
203
+ this._pointerHandlers.pointermove = this._onPointerMove.bind(this);
204
+ this._pointerHandlers.pointerdown = this._onPointerDown.bind(this);
205
+ this._pointerHandlers.pointerup = this._onPointerUp.bind(this);
206
+ // Listen for pointer listeners being added/removed
207
+ ['pointermove', 'pointerdown', 'pointerup', 'pointerenter', 'pointerleave'].forEach((type) => {
208
+ this.addEventListener(`${type}:connect`, () => this._onPointerListenerAdded(type));
209
+ this.addEventListener(`${type}:disconnect`, () => this._onPointerListenerRemoved(type));
210
+ });
211
+ }
212
+ _pickerDestroy() {
213
+ if (this._canvas) {
214
+ Object.entries(this._pointerHandlers).forEach(([type, handler]) => {
215
+ if (handler) {
216
+ this._canvas.removeEventListener(type, handler);
217
+ }
218
+ });
219
+ }
220
+ this._picker = null;
221
+ this._pointerHandlers = {
222
+ pointermove: null,
223
+ pointerdown: null,
224
+ pointerup: null
225
+ };
226
+ }
227
+ _onPointerMove(event) {
228
+ if (!this._picker || !this.app)
229
+ return;
230
+ const camera = this.app.root.findComponent('camera');
231
+ if (!camera)
232
+ return;
233
+ const canvasRect = this._canvas.getBoundingClientRect();
234
+ const x = event.clientX - canvasRect.left;
235
+ const y = event.clientY - canvasRect.top;
236
+ this._picker.prepare(camera, this.app.scene);
237
+ const selection = this._picker.getSelection(x, y);
238
+ // Get the currently hovered entity by walking up the hierarchy
239
+ let newHoverEntity = null;
240
+ if (selection.length > 0) {
241
+ let node = selection[0].node;
242
+ while (node && !newHoverEntity) {
243
+ const entityElement = this.querySelector(`pc-entity[name="${node.name}"]`);
244
+ if (entityElement) {
245
+ newHoverEntity = entityElement;
246
+ }
247
+ node = node.parent;
248
+ }
249
+ }
250
+ // Handle enter/leave events
251
+ if (this._hoveredEntity !== newHoverEntity) {
252
+ if (this._hoveredEntity && this._hoveredEntity.hasListeners('pointerleave')) {
253
+ this._hoveredEntity.dispatchEvent(new PointerEvent('pointerleave', event));
254
+ }
255
+ if (newHoverEntity && newHoverEntity.hasListeners('pointerenter')) {
256
+ newHoverEntity.dispatchEvent(new PointerEvent('pointerenter', event));
257
+ }
258
+ }
259
+ // Update hover state
260
+ this._hoveredEntity = newHoverEntity;
261
+ // Handle pointermove event
262
+ if (newHoverEntity && newHoverEntity.hasListeners('pointermove')) {
263
+ newHoverEntity.dispatchEvent(new PointerEvent('pointermove', event));
264
+ }
265
+ }
266
+ _onPointerDown(event) {
267
+ if (!this._picker || !this.app)
268
+ return;
269
+ const camera = this.app.root.findComponent('camera');
270
+ if (!camera)
271
+ return;
272
+ const canvasRect = this._canvas.getBoundingClientRect();
273
+ const x = event.clientX - canvasRect.left;
274
+ const y = event.clientY - canvasRect.top;
275
+ this._picker.prepare(camera, this.app.scene);
276
+ const selection = this._picker.getSelection(x, y);
277
+ if (selection.length > 0) {
278
+ let node = selection[0].node;
279
+ while (node) {
280
+ const entityElement = this.querySelector(`pc-entity[name="${node.name}"]`);
281
+ if (entityElement && entityElement.hasListeners('pointerdown')) {
282
+ entityElement.dispatchEvent(new PointerEvent('pointerdown', event));
283
+ break;
284
+ }
285
+ node = node.parent;
286
+ }
287
+ }
288
+ }
289
+ _onPointerUp(event) {
290
+ if (!this._picker || !this.app)
291
+ return;
292
+ const camera = this.app.root.findComponent('camera');
293
+ if (!camera)
294
+ return;
295
+ const canvasRect = this._canvas.getBoundingClientRect();
296
+ const x = event.clientX - canvasRect.left;
297
+ const y = event.clientY - canvasRect.top;
298
+ this._picker.prepare(camera, this.app.scene);
299
+ const selection = this._picker.getSelection(x, y);
300
+ if (selection.length > 0) {
301
+ const entityElement = this.querySelector(`pc-entity[name="${selection[0].node.name}"]`);
302
+ if (entityElement && entityElement.hasListeners('pointerup')) {
303
+ entityElement.dispatchEvent(new PointerEvent('pointerup', event));
304
+ }
305
+ }
306
+ }
307
+ _onPointerListenerAdded(type) {
308
+ if (!this._hasPointerListeners[type] && this._canvas) {
309
+ this._hasPointerListeners[type] = true;
310
+ // For enter/leave events, we need the move handler
311
+ const handler = (type === 'pointerenter' || type === 'pointerleave') ?
312
+ this._pointerHandlers.pointermove :
313
+ this._pointerHandlers[type];
314
+ if (handler) {
315
+ this._canvas.addEventListener(type === 'pointerenter' || type === 'pointerleave' ? 'pointermove' : type, handler);
316
+ }
317
+ }
318
+ }
319
+ _onPointerListenerRemoved(type) {
320
+ const hasListeners = Array.from(this.querySelectorAll('pc-entity'))
321
+ .some(entity => entity.hasListeners(type));
322
+ if (!hasListeners && this._canvas) {
323
+ this._hasPointerListeners[type] = false;
324
+ const handler = (type === 'pointerenter' || type === 'pointerleave') ?
325
+ this._pointerHandlers.pointermove :
326
+ this._pointerHandlers[type];
327
+ if (handler) {
328
+ this._canvas.removeEventListener(type === 'pointerenter' || type === 'pointerleave' ? 'pointermove' : type, handler);
329
+ }
330
+ }
331
+ }
183
332
  /**
184
333
  * Sets the alpha flag.
185
334
  * @param value - The alpha flag.
@@ -532,6 +681,10 @@ class EntityElement extends AsyncElement {
532
681
  * The tags of the entity.
533
682
  */
534
683
  this._tags = [];
684
+ /**
685
+ * The pointer event listeners for the entity.
686
+ */
687
+ this._listeners = {};
535
688
  /**
536
689
  * The PlayCanvas entity instance.
537
690
  */
@@ -560,6 +713,30 @@ class EntityElement extends AsyncElement {
560
713
  if (tags) {
561
714
  this.entity.tags.add(tags.split(',').map(tag => tag.trim()));
562
715
  }
716
+ // Handle pointer events
717
+ const pointerEvents = [
718
+ 'onpointerenter',
719
+ 'onpointerleave',
720
+ 'onpointerdown',
721
+ 'onpointerup',
722
+ 'onpointermove'
723
+ ];
724
+ pointerEvents.forEach((eventName) => {
725
+ const handler = this.getAttribute(eventName);
726
+ if (handler) {
727
+ const eventType = eventName.substring(2); // remove 'on' prefix
728
+ const eventHandler = (event) => {
729
+ try {
730
+ /* eslint-disable-next-line no-new-func */
731
+ new Function('event', handler).call(this, event);
732
+ }
733
+ catch (e) {
734
+ console.error('Error in event handler:', e);
735
+ }
736
+ };
737
+ this.addEventListener(eventType, eventHandler);
738
+ }
739
+ });
563
740
  }
564
741
  buildHierarchy(app) {
565
742
  if (!this.entity)
@@ -709,7 +886,19 @@ class EntityElement extends AsyncElement {
709
886
  return this._tags;
710
887
  }
711
888
  static get observedAttributes() {
712
- return ['enabled', 'name', 'position', 'rotation', 'scale', 'tags'];
889
+ return [
890
+ 'enabled',
891
+ 'name',
892
+ 'position',
893
+ 'rotation',
894
+ 'scale',
895
+ 'tags',
896
+ 'onpointerenter',
897
+ 'onpointerleave',
898
+ 'onpointerdown',
899
+ 'onpointerup',
900
+ 'onpointermove'
901
+ ];
713
902
  }
714
903
  attributeChangedCallback(name, _oldValue, newValue) {
715
904
  switch (name) {
@@ -731,7 +920,51 @@ class EntityElement extends AsyncElement {
731
920
  case 'tags':
732
921
  this.tags = newValue.split(',').map(tag => tag.trim());
733
922
  break;
923
+ case 'onpointerenter':
924
+ case 'onpointerleave':
925
+ case 'onpointerdown':
926
+ case 'onpointerup':
927
+ case 'onpointermove':
928
+ if (newValue) {
929
+ const eventName = name.substring(2);
930
+ // Use Function.prototype.bind to avoid new Function
931
+ const handler = (event) => {
932
+ try {
933
+ const handlerStr = this.getAttribute(eventName) || '';
934
+ /* eslint-disable-next-line no-new-func */
935
+ new Function('event', handlerStr).call(this, event);
936
+ }
937
+ catch (e) {
938
+ console.error('Error in event handler:', e);
939
+ }
940
+ };
941
+ this.addEventListener(eventName, handler);
942
+ }
943
+ break;
944
+ }
945
+ }
946
+ addEventListener(type, listener, options) {
947
+ if (!this._listeners[type]) {
948
+ this._listeners[type] = [];
734
949
  }
950
+ this._listeners[type].push(listener);
951
+ super.addEventListener(type, listener, options);
952
+ if (type.startsWith('pointer')) {
953
+ this.dispatchEvent(new CustomEvent(`${type}:connect`, { bubbles: true }));
954
+ }
955
+ }
956
+ removeEventListener(type, listener, options) {
957
+ if (this._listeners[type]) {
958
+ this._listeners[type] = this._listeners[type].filter(l => l !== listener);
959
+ }
960
+ super.removeEventListener(type, listener, options);
961
+ if (type.startsWith('pointer')) {
962
+ this.dispatchEvent(new CustomEvent(`${type}:disconnect`, { bubbles: true }));
963
+ }
964
+ }
965
+ hasListeners(type) {
966
+ var _a;
967
+ return Boolean((_a = this._listeners[type]) === null || _a === void 0 ? void 0 : _a.length);
735
968
  }
736
969
  }
737
970
  customElements.define('pc-entity', EntityElement);
@@ -927,6 +1160,15 @@ class ListenerComponentElement extends ComponentElement {
927
1160
  }
928
1161
  customElements.define('pc-listener', ListenerComponentElement);
929
1162
 
1163
+ const tonemaps = new Map([
1164
+ ['none', playcanvas.TONEMAP_NONE],
1165
+ ['linear', playcanvas.TONEMAP_LINEAR],
1166
+ ['filmic', playcanvas.TONEMAP_FILMIC],
1167
+ ['hejl', playcanvas.TONEMAP_HEJL],
1168
+ ['aces', playcanvas.TONEMAP_ACES],
1169
+ ['aces2', playcanvas.TONEMAP_ACES2],
1170
+ ['neutral', playcanvas.TONEMAP_NEUTRAL]
1171
+ ]);
930
1172
  /**
931
1173
  * The CameraComponentElement interface provides properties and methods for manipulating
932
1174
  * `<pc-camera>` elements. The CameraComponentElement interface also inherits the properties and
@@ -947,12 +1189,14 @@ class CameraComponentElement extends ComponentElement {
947
1189
  this._flipFaces = false;
948
1190
  this._fov = 45;
949
1191
  this._frustumCulling = true;
1192
+ this._gamma = 'srgb';
950
1193
  this._nearClip = 0.1;
951
1194
  this._orthographic = false;
952
1195
  this._orthoHeight = 10;
953
1196
  this._priority = 0;
954
1197
  this._rect = new playcanvas.Vec4(0, 0, 1, 1);
955
1198
  this._scissorRect = new playcanvas.Vec4(0, 0, 1, 1);
1199
+ this._tonemap = 'none';
956
1200
  }
957
1201
  getInitialComponentData() {
958
1202
  return {
@@ -965,12 +1209,14 @@ class CameraComponentElement extends ComponentElement {
965
1209
  flipFaces: this._flipFaces,
966
1210
  fov: this._fov,
967
1211
  frustumCulling: this._frustumCulling,
1212
+ gammaCorrection: this._gamma === 'srgb' ? playcanvas.GAMMA_SRGB : playcanvas.GAMMA_NONE,
968
1213
  nearClip: this._nearClip,
969
1214
  orthographic: this._orthographic,
970
1215
  orthoHeight: this._orthoHeight,
971
1216
  priority: this._priority,
972
1217
  rect: this._rect,
973
- scissorRect: this._scissorRect
1218
+ scissorRect: this._scissorRect,
1219
+ toneMapping: tonemaps.get(this._tonemap)
974
1220
  };
975
1221
  }
976
1222
  get xrAvailable() {
@@ -1153,6 +1399,23 @@ class CameraComponentElement extends ComponentElement {
1153
1399
  get frustumCulling() {
1154
1400
  return this._frustumCulling;
1155
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' ? playcanvas.GAMMA_SRGB : playcanvas.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
+ }
1156
1419
  /**
1157
1420
  * Sets the near clip distance of the camera.
1158
1421
  * @param value - The near clip distance.
@@ -1255,6 +1518,24 @@ class CameraComponentElement extends ComponentElement {
1255
1518
  get scissorRect() {
1256
1519
  return this._scissorRect;
1257
1520
  }
1521
+ /**
1522
+ * Sets the tone mapping of the camera.
1523
+ * @param value - The tone mapping.
1524
+ */
1525
+ set tonemap(value) {
1526
+ var _a;
1527
+ this._tonemap = value;
1528
+ if (this.component) {
1529
+ this.component.toneMapping = (_a = tonemaps.get(value)) !== null && _a !== void 0 ? _a : playcanvas.TONEMAP_NONE;
1530
+ }
1531
+ }
1532
+ /**
1533
+ * Gets the tone mapping of the camera.
1534
+ * @returns The tone mapping.
1535
+ */
1536
+ get tonemap() {
1537
+ return this._tonemap;
1538
+ }
1258
1539
  static get observedAttributes() {
1259
1540
  return [
1260
1541
  ...super.observedAttributes,
@@ -1267,12 +1548,14 @@ class CameraComponentElement extends ComponentElement {
1267
1548
  'flip-faces',
1268
1549
  'fov',
1269
1550
  'frustum-culling',
1551
+ 'gamma',
1270
1552
  'near-clip',
1271
1553
  'orthographic',
1272
1554
  'ortho-height',
1273
1555
  'priority',
1274
1556
  'rect',
1275
- 'scissor-rect'
1557
+ 'scissor-rect',
1558
+ 'tonemap'
1276
1559
  ];
1277
1560
  }
1278
1561
  attributeChangedCallback(name, _oldValue, newValue) {
@@ -1305,6 +1588,9 @@ class CameraComponentElement extends ComponentElement {
1305
1588
  case 'frustum-culling':
1306
1589
  this.frustumCulling = newValue !== 'false';
1307
1590
  break;
1591
+ case 'gamma':
1592
+ this.gamma = newValue;
1593
+ break;
1308
1594
  case 'near-clip':
1309
1595
  this.nearClip = parseFloat(newValue);
1310
1596
  break;
@@ -1323,6 +1609,9 @@ class CameraComponentElement extends ComponentElement {
1323
1609
  case 'scissor-rect':
1324
1610
  this.scissorRect = parseVec4(newValue);
1325
1611
  break;
1612
+ case 'tonemap':
1613
+ this.tonemap = newValue;
1614
+ break;
1326
1615
  }
1327
1616
  }
1328
1617
  }
@@ -1736,6 +2025,17 @@ class GSplatComponentElement extends ComponentElement {
1736
2025
  }
1737
2026
  customElements.define('pc-splat', GSplatComponentElement);
1738
2027
 
2028
+ const shadowTypes = new Map([
2029
+ ['pcf1-16f', playcanvas.SHADOW_PCF1_16F],
2030
+ ['pcf1-32f', playcanvas.SHADOW_PCF1_32F],
2031
+ ['pcf3-16f', playcanvas.SHADOW_PCF3_16F],
2032
+ ['pcf3-32f', playcanvas.SHADOW_PCF3_32F],
2033
+ ['pcf5-16f', playcanvas.SHADOW_PCF5_16F],
2034
+ ['pcf5-32f', playcanvas.SHADOW_PCF5_32F],
2035
+ ['vsm-16f', playcanvas.SHADOW_VSM_16F],
2036
+ ['vsm-32f', playcanvas.SHADOW_VSM_32F],
2037
+ ['pcss-32f', playcanvas.SHADOW_PCSS_32F]
2038
+ ]);
1739
2039
  /**
1740
2040
  * The LightComponentElement interface provides properties and methods for manipulating
1741
2041
  * `<pc-light>` elements. The LightComponentElement interface also inherits the properties and
@@ -1756,8 +2056,11 @@ class LightComponentElement extends ComponentElement {
1756
2056
  this._range = 10;
1757
2057
  this._shadowBias = 0.2;
1758
2058
  this._shadowDistance = 16;
2059
+ this._shadowIntensity = 1;
1759
2060
  this._shadowResolution = 1024;
2061
+ this._shadowType = 'pcf3-32f';
1760
2062
  this._type = 'directional';
2063
+ this._vsmBias = 0.01;
1761
2064
  }
1762
2065
  getInitialComponentData() {
1763
2066
  return {
@@ -1770,8 +2073,11 @@ class LightComponentElement extends ComponentElement {
1770
2073
  range: this._range,
1771
2074
  shadowBias: this._shadowBias,
1772
2075
  shadowDistance: this._shadowDistance,
2076
+ shadowIntensity: this._shadowIntensity,
1773
2077
  shadowResolution: this._shadowResolution,
1774
- type: this._type
2078
+ shadowType: shadowTypes.get(this._shadowType),
2079
+ type: this._type,
2080
+ vsmBias: this._vsmBias
1775
2081
  };
1776
2082
  }
1777
2083
  /**
@@ -1934,6 +2240,23 @@ class LightComponentElement extends ComponentElement {
1934
2240
  get shadowDistance() {
1935
2241
  return this._shadowDistance;
1936
2242
  }
2243
+ /**
2244
+ * Sets the shadow intensity of the light.
2245
+ * @param value - The shadow intensity.
2246
+ */
2247
+ set shadowIntensity(value) {
2248
+ this._shadowIntensity = value;
2249
+ if (this.component) {
2250
+ this.component.shadowIntensity = value;
2251
+ }
2252
+ }
2253
+ /**
2254
+ * Gets the shadow intensity of the light.
2255
+ * @returns The shadow intensity.
2256
+ */
2257
+ get shadowIntensity() {
2258
+ return this._shadowIntensity;
2259
+ }
1937
2260
  /**
1938
2261
  * Sets the shadow resolution of the light.
1939
2262
  * @param value - The shadow resolution.
@@ -1951,6 +2274,34 @@ class LightComponentElement extends ComponentElement {
1951
2274
  get shadowResolution() {
1952
2275
  return this._shadowResolution;
1953
2276
  }
2277
+ /**
2278
+ * Sets the shadow type of the light.
2279
+ * @param value - The shadow type. Can be:
2280
+ *
2281
+ * - `pcf1-16f` - 1-tap percentage-closer filtered shadow map with 16-bit depth.
2282
+ * - `pcf1-32f` - 1-tap percentage-closer filtered shadow map with 32-bit depth.
2283
+ * - `pcf3-16f` - 3-tap percentage-closer filtered shadow map with 16-bit depth.
2284
+ * - `pcf3-32f` - 3-tap percentage-closer filtered shadow map with 32-bit depth.
2285
+ * - `pcf5-16f` - 5-tap percentage-closer filtered shadow map with 16-bit depth.
2286
+ * - `pcf5-32f` - 5-tap percentage-closer filtered shadow map with 32-bit depth.
2287
+ * - `vsm-16f` - Variance shadow map with 16-bit depth.
2288
+ * - `vsm-32f` - Variance shadow map with 32-bit depth.
2289
+ * - `pcss-32f` - Percentage-closer soft shadow with 32-bit depth.
2290
+ */
2291
+ set shadowType(value) {
2292
+ var _a;
2293
+ this._shadowType = value;
2294
+ if (this.component) {
2295
+ this.component.shadowType = (_a = shadowTypes.get(value)) !== null && _a !== void 0 ? _a : playcanvas.SHADOW_PCF3_32F;
2296
+ }
2297
+ }
2298
+ /**
2299
+ * Gets the shadow type of the light.
2300
+ * @returns The shadow type.
2301
+ */
2302
+ get shadowType() {
2303
+ return this._shadowType;
2304
+ }
1954
2305
  /**
1955
2306
  * Sets the type of the light.
1956
2307
  * @param value - The type.
@@ -1972,6 +2323,23 @@ class LightComponentElement extends ComponentElement {
1972
2323
  get type() {
1973
2324
  return this._type;
1974
2325
  }
2326
+ /**
2327
+ * Sets the VSM bias of the light.
2328
+ * @param value - The VSM bias.
2329
+ */
2330
+ set vsmBias(value) {
2331
+ this._vsmBias = value;
2332
+ if (this.component) {
2333
+ this.component.vsmBias = value;
2334
+ }
2335
+ }
2336
+ /**
2337
+ * Gets the VSM bias of the light.
2338
+ * @returns The VSM bias.
2339
+ */
2340
+ get vsmBias() {
2341
+ return this._vsmBias;
2342
+ }
1975
2343
  static get observedAttributes() {
1976
2344
  return [
1977
2345
  ...super.observedAttributes,
@@ -1984,8 +2352,11 @@ class LightComponentElement extends ComponentElement {
1984
2352
  'range',
1985
2353
  'shadow-bias',
1986
2354
  'shadow-distance',
2355
+ 'shadow-intensity',
1987
2356
  'shadow-resolution',
1988
- 'type'
2357
+ 'shadow-type',
2358
+ 'type',
2359
+ 'vsm-bias'
1989
2360
  ];
1990
2361
  }
1991
2362
  attributeChangedCallback(name, _oldValue, newValue) {
@@ -2021,9 +2392,18 @@ class LightComponentElement extends ComponentElement {
2021
2392
  case 'shadow-resolution':
2022
2393
  this.shadowResolution = Number(newValue);
2023
2394
  break;
2395
+ case 'shadow-intensity':
2396
+ this.shadowIntensity = Number(newValue);
2397
+ break;
2398
+ case 'shadow-type':
2399
+ this.shadowType = newValue;
2400
+ break;
2024
2401
  case 'type':
2025
2402
  this.type = newValue;
2026
2403
  break;
2404
+ case 'vsm-bias':
2405
+ this.vsmBias = Number(newValue);
2406
+ break;
2027
2407
  }
2028
2408
  }
2029
2409
  }
@@ -2046,8 +2426,8 @@ class MaterialElement extends HTMLElement {
2046
2426
  }
2047
2427
  createMaterial() {
2048
2428
  this.material = new playcanvas.StandardMaterial();
2049
- this.material.glossInvert = true;
2050
- this.material.useMetalness = true;
2429
+ this.material.glossInvert = false;
2430
+ this.material.useMetalness = false;
2051
2431
  this.material.diffuse = this._diffuse;
2052
2432
  this.diffuseMap = this._diffuseMap;
2053
2433
  this.metalnessMap = this._metalnessMap;
@@ -2580,9 +2960,6 @@ class ScreenComponentElement extends ComponentElement {
2580
2960
  }
2581
2961
  customElements.define('pc-screen', ScreenComponentElement);
2582
2962
 
2583
- const tmpV2 = new playcanvas.Vec2();
2584
- const tmpV3 = new playcanvas.Vec3();
2585
- const tmpV4 = new playcanvas.Vec4();
2586
2963
  /**
2587
2964
  * The ScriptComponentElement interface provides properties and methods for manipulating
2588
2965
  * `<pc-scripts>` elements. The ScriptComponentElement interface also inherits the properties and
@@ -2626,22 +3003,34 @@ class ScriptComponentElement extends ComponentElement {
2626
3003
  return;
2627
3004
  }
2628
3005
  }
2629
- // Handle vectors
2630
- if (Array.isArray(value)) {
2631
- if (target[key] instanceof playcanvas.Vec2) {
2632
- target[key] = tmpV2.set(value[0], value[1]);
3006
+ // Handle arrays
3007
+ if (value && typeof value === 'object' && Array.isArray(value)) {
3008
+ // If it's an array of objects, recursively apply to each object
3009
+ if (value.length > 0 && typeof value[0] === 'object') {
3010
+ target[key] = value.map((item) => {
3011
+ const obj = {};
3012
+ for (const itemKey in item) {
3013
+ applyValue(obj, itemKey, item[itemKey]);
3014
+ }
3015
+ return obj;
3016
+ });
3017
+ return;
3018
+ }
3019
+ // Handle vectors
3020
+ if (value.length === 2 && typeof value[0] === 'number') {
3021
+ target[key] = new playcanvas.Vec2(value[0], value[1]);
2633
3022
  return;
2634
3023
  }
2635
- if (target[key] instanceof playcanvas.Vec3) {
2636
- target[key] = tmpV3.set(value[0], value[1], value[2]);
3024
+ if (value.length === 3 && typeof value[0] === 'number') {
3025
+ target[key] = new playcanvas.Vec3(value[0], value[1], value[2]);
2637
3026
  return;
2638
3027
  }
2639
- if (target[key] instanceof playcanvas.Vec4) {
2640
- target[key] = tmpV4.set(value[0], value[1], value[2], value[3]);
3028
+ if (value.length === 4 && typeof value[0] === 'number') {
3029
+ target[key] = new playcanvas.Vec4(value[0], value[1], value[2], value[3]);
2641
3030
  return;
2642
3031
  }
2643
3032
  }
2644
- // Handle nested objects
3033
+ // Handle nested objects (non-array)
2645
3034
  if (value && typeof value === 'object' && !Array.isArray(value)) {
2646
3035
  if (!target[key] || typeof target[key] !== 'object') {
2647
3036
  target[key] = {};