@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/README.md +2 -2
- package/dist/app.d.ts +11 -0
- package/dist/components/camera-component.d.ts +24 -0
- package/dist/components/light-component.d.ts +46 -0
- package/dist/components/sound-component.d.ts +1 -1
- package/dist/entity.d.ts +7 -0
- package/dist/fog.d.ts +28 -0
- package/dist/pwc.cjs +408 -19
- package/dist/pwc.cjs.map +1 -1
- package/dist/pwc.js +408 -19
- package/dist/pwc.js.map +1 -1
- package/dist/pwc.min.js +1 -1
- package/dist/pwc.min.js.map +1 -1
- package/dist/pwc.mjs +409 -20
- package/dist/pwc.mjs.map +1 -1
- package/package.json +5 -4
- package/src/app.ts +180 -1
- package/src/components/camera-component.ts +65 -3
- package/src/components/light-component.ts +103 -3
- package/src/components/script-component.ts +22 -13
- package/src/entity.ts +88 -1
- package/src/fog.ts +121 -0
- package/src/material.ts +2 -2
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.
|
|
@@ -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,6 +711,30 @@ 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)
|
|
@@ -707,7 +884,19 @@ class EntityElement extends AsyncElement {
|
|
|
707
884
|
return this._tags;
|
|
708
885
|
}
|
|
709
886
|
static get observedAttributes() {
|
|
710
|
-
return [
|
|
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] = [];
|
|
732
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);
|
|
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 === void 0 ? void 0 : _a.length);
|
|
733
966
|
}
|
|
734
967
|
}
|
|
735
968
|
customElements.define('pc-entity', EntityElement);
|
|
@@ -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,14 @@ class CameraComponentElement extends ComponentElement {
|
|
|
945
1187
|
this._flipFaces = false;
|
|
946
1188
|
this._fov = 45;
|
|
947
1189
|
this._frustumCulling = true;
|
|
1190
|
+
this._gamma = 'srgb';
|
|
948
1191
|
this._nearClip = 0.1;
|
|
949
1192
|
this._orthographic = false;
|
|
950
1193
|
this._orthoHeight = 10;
|
|
951
1194
|
this._priority = 0;
|
|
952
1195
|
this._rect = new Vec4(0, 0, 1, 1);
|
|
953
1196
|
this._scissorRect = new Vec4(0, 0, 1, 1);
|
|
1197
|
+
this._tonemap = 'none';
|
|
954
1198
|
}
|
|
955
1199
|
getInitialComponentData() {
|
|
956
1200
|
return {
|
|
@@ -963,12 +1207,14 @@ class CameraComponentElement extends ComponentElement {
|
|
|
963
1207
|
flipFaces: this._flipFaces,
|
|
964
1208
|
fov: this._fov,
|
|
965
1209
|
frustumCulling: this._frustumCulling,
|
|
1210
|
+
gammaCorrection: this._gamma === 'srgb' ? GAMMA_SRGB : GAMMA_NONE,
|
|
966
1211
|
nearClip: this._nearClip,
|
|
967
1212
|
orthographic: this._orthographic,
|
|
968
1213
|
orthoHeight: this._orthoHeight,
|
|
969
1214
|
priority: this._priority,
|
|
970
1215
|
rect: this._rect,
|
|
971
|
-
scissorRect: this._scissorRect
|
|
1216
|
+
scissorRect: this._scissorRect,
|
|
1217
|
+
toneMapping: tonemaps.get(this._tonemap)
|
|
972
1218
|
};
|
|
973
1219
|
}
|
|
974
1220
|
get xrAvailable() {
|
|
@@ -1151,6 +1397,23 @@ class CameraComponentElement extends ComponentElement {
|
|
|
1151
1397
|
get frustumCulling() {
|
|
1152
1398
|
return this._frustumCulling;
|
|
1153
1399
|
}
|
|
1400
|
+
/**
|
|
1401
|
+
* Sets the gamma correction of the camera.
|
|
1402
|
+
* @param value - The gamma correction.
|
|
1403
|
+
*/
|
|
1404
|
+
set gamma(value) {
|
|
1405
|
+
this._gamma = value;
|
|
1406
|
+
if (this.component) {
|
|
1407
|
+
this.component.gammaCorrection = value === 'srgb' ? GAMMA_SRGB : GAMMA_NONE;
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
/**
|
|
1411
|
+
* Gets the gamma correction of the camera.
|
|
1412
|
+
* @returns The gamma correction.
|
|
1413
|
+
*/
|
|
1414
|
+
get gamma() {
|
|
1415
|
+
return this._gamma;
|
|
1416
|
+
}
|
|
1154
1417
|
/**
|
|
1155
1418
|
* Sets the near clip distance of the camera.
|
|
1156
1419
|
* @param value - The near clip distance.
|
|
@@ -1253,6 +1516,24 @@ class CameraComponentElement extends ComponentElement {
|
|
|
1253
1516
|
get scissorRect() {
|
|
1254
1517
|
return this._scissorRect;
|
|
1255
1518
|
}
|
|
1519
|
+
/**
|
|
1520
|
+
* Sets the tone mapping of the camera.
|
|
1521
|
+
* @param value - The tone mapping.
|
|
1522
|
+
*/
|
|
1523
|
+
set tonemap(value) {
|
|
1524
|
+
var _a;
|
|
1525
|
+
this._tonemap = value;
|
|
1526
|
+
if (this.component) {
|
|
1527
|
+
this.component.toneMapping = (_a = tonemaps.get(value)) !== null && _a !== void 0 ? _a : TONEMAP_NONE;
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
/**
|
|
1531
|
+
* Gets the tone mapping of the camera.
|
|
1532
|
+
* @returns The tone mapping.
|
|
1533
|
+
*/
|
|
1534
|
+
get tonemap() {
|
|
1535
|
+
return this._tonemap;
|
|
1536
|
+
}
|
|
1256
1537
|
static get observedAttributes() {
|
|
1257
1538
|
return [
|
|
1258
1539
|
...super.observedAttributes,
|
|
@@ -1265,12 +1546,14 @@ class CameraComponentElement extends ComponentElement {
|
|
|
1265
1546
|
'flip-faces',
|
|
1266
1547
|
'fov',
|
|
1267
1548
|
'frustum-culling',
|
|
1549
|
+
'gamma',
|
|
1268
1550
|
'near-clip',
|
|
1269
1551
|
'orthographic',
|
|
1270
1552
|
'ortho-height',
|
|
1271
1553
|
'priority',
|
|
1272
1554
|
'rect',
|
|
1273
|
-
'scissor-rect'
|
|
1555
|
+
'scissor-rect',
|
|
1556
|
+
'tonemap'
|
|
1274
1557
|
];
|
|
1275
1558
|
}
|
|
1276
1559
|
attributeChangedCallback(name, _oldValue, newValue) {
|
|
@@ -1303,6 +1586,9 @@ class CameraComponentElement extends ComponentElement {
|
|
|
1303
1586
|
case 'frustum-culling':
|
|
1304
1587
|
this.frustumCulling = newValue !== 'false';
|
|
1305
1588
|
break;
|
|
1589
|
+
case 'gamma':
|
|
1590
|
+
this.gamma = newValue;
|
|
1591
|
+
break;
|
|
1306
1592
|
case 'near-clip':
|
|
1307
1593
|
this.nearClip = parseFloat(newValue);
|
|
1308
1594
|
break;
|
|
@@ -1321,6 +1607,9 @@ class CameraComponentElement extends ComponentElement {
|
|
|
1321
1607
|
case 'scissor-rect':
|
|
1322
1608
|
this.scissorRect = parseVec4(newValue);
|
|
1323
1609
|
break;
|
|
1610
|
+
case 'tonemap':
|
|
1611
|
+
this.tonemap = newValue;
|
|
1612
|
+
break;
|
|
1324
1613
|
}
|
|
1325
1614
|
}
|
|
1326
1615
|
}
|
|
@@ -1734,6 +2023,17 @@ class GSplatComponentElement extends ComponentElement {
|
|
|
1734
2023
|
}
|
|
1735
2024
|
customElements.define('pc-splat', GSplatComponentElement);
|
|
1736
2025
|
|
|
2026
|
+
const shadowTypes = new Map([
|
|
2027
|
+
['pcf1-16f', SHADOW_PCF1_16F],
|
|
2028
|
+
['pcf1-32f', SHADOW_PCF1_32F],
|
|
2029
|
+
['pcf3-16f', SHADOW_PCF3_16F],
|
|
2030
|
+
['pcf3-32f', SHADOW_PCF3_32F],
|
|
2031
|
+
['pcf5-16f', SHADOW_PCF5_16F],
|
|
2032
|
+
['pcf5-32f', SHADOW_PCF5_32F],
|
|
2033
|
+
['vsm-16f', SHADOW_VSM_16F],
|
|
2034
|
+
['vsm-32f', SHADOW_VSM_32F],
|
|
2035
|
+
['pcss-32f', SHADOW_PCSS_32F]
|
|
2036
|
+
]);
|
|
1737
2037
|
/**
|
|
1738
2038
|
* The LightComponentElement interface provides properties and methods for manipulating
|
|
1739
2039
|
* `<pc-light>` elements. The LightComponentElement interface also inherits the properties and
|
|
@@ -1754,8 +2054,11 @@ class LightComponentElement extends ComponentElement {
|
|
|
1754
2054
|
this._range = 10;
|
|
1755
2055
|
this._shadowBias = 0.2;
|
|
1756
2056
|
this._shadowDistance = 16;
|
|
2057
|
+
this._shadowIntensity = 1;
|
|
1757
2058
|
this._shadowResolution = 1024;
|
|
2059
|
+
this._shadowType = 'pcf3-32f';
|
|
1758
2060
|
this._type = 'directional';
|
|
2061
|
+
this._vsmBias = 0.01;
|
|
1759
2062
|
}
|
|
1760
2063
|
getInitialComponentData() {
|
|
1761
2064
|
return {
|
|
@@ -1768,8 +2071,11 @@ class LightComponentElement extends ComponentElement {
|
|
|
1768
2071
|
range: this._range,
|
|
1769
2072
|
shadowBias: this._shadowBias,
|
|
1770
2073
|
shadowDistance: this._shadowDistance,
|
|
2074
|
+
shadowIntensity: this._shadowIntensity,
|
|
1771
2075
|
shadowResolution: this._shadowResolution,
|
|
1772
|
-
|
|
2076
|
+
shadowType: shadowTypes.get(this._shadowType),
|
|
2077
|
+
type: this._type,
|
|
2078
|
+
vsmBias: this._vsmBias
|
|
1773
2079
|
};
|
|
1774
2080
|
}
|
|
1775
2081
|
/**
|
|
@@ -1932,6 +2238,23 @@ class LightComponentElement extends ComponentElement {
|
|
|
1932
2238
|
get shadowDistance() {
|
|
1933
2239
|
return this._shadowDistance;
|
|
1934
2240
|
}
|
|
2241
|
+
/**
|
|
2242
|
+
* Sets the shadow intensity of the light.
|
|
2243
|
+
* @param value - The shadow intensity.
|
|
2244
|
+
*/
|
|
2245
|
+
set shadowIntensity(value) {
|
|
2246
|
+
this._shadowIntensity = value;
|
|
2247
|
+
if (this.component) {
|
|
2248
|
+
this.component.shadowIntensity = value;
|
|
2249
|
+
}
|
|
2250
|
+
}
|
|
2251
|
+
/**
|
|
2252
|
+
* Gets the shadow intensity of the light.
|
|
2253
|
+
* @returns The shadow intensity.
|
|
2254
|
+
*/
|
|
2255
|
+
get shadowIntensity() {
|
|
2256
|
+
return this._shadowIntensity;
|
|
2257
|
+
}
|
|
1935
2258
|
/**
|
|
1936
2259
|
* Sets the shadow resolution of the light.
|
|
1937
2260
|
* @param value - The shadow resolution.
|
|
@@ -1949,6 +2272,34 @@ class LightComponentElement extends ComponentElement {
|
|
|
1949
2272
|
get shadowResolution() {
|
|
1950
2273
|
return this._shadowResolution;
|
|
1951
2274
|
}
|
|
2275
|
+
/**
|
|
2276
|
+
* Sets the shadow type of the light.
|
|
2277
|
+
* @param value - The shadow type. Can be:
|
|
2278
|
+
*
|
|
2279
|
+
* - `pcf1-16f` - 1-tap percentage-closer filtered shadow map with 16-bit depth.
|
|
2280
|
+
* - `pcf1-32f` - 1-tap percentage-closer filtered shadow map with 32-bit depth.
|
|
2281
|
+
* - `pcf3-16f` - 3-tap percentage-closer filtered shadow map with 16-bit depth.
|
|
2282
|
+
* - `pcf3-32f` - 3-tap percentage-closer filtered shadow map with 32-bit depth.
|
|
2283
|
+
* - `pcf5-16f` - 5-tap percentage-closer filtered shadow map with 16-bit depth.
|
|
2284
|
+
* - `pcf5-32f` - 5-tap percentage-closer filtered shadow map with 32-bit depth.
|
|
2285
|
+
* - `vsm-16f` - Variance shadow map with 16-bit depth.
|
|
2286
|
+
* - `vsm-32f` - Variance shadow map with 32-bit depth.
|
|
2287
|
+
* - `pcss-32f` - Percentage-closer soft shadow with 32-bit depth.
|
|
2288
|
+
*/
|
|
2289
|
+
set shadowType(value) {
|
|
2290
|
+
var _a;
|
|
2291
|
+
this._shadowType = value;
|
|
2292
|
+
if (this.component) {
|
|
2293
|
+
this.component.shadowType = (_a = shadowTypes.get(value)) !== null && _a !== void 0 ? _a : SHADOW_PCF3_32F;
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
/**
|
|
2297
|
+
* Gets the shadow type of the light.
|
|
2298
|
+
* @returns The shadow type.
|
|
2299
|
+
*/
|
|
2300
|
+
get shadowType() {
|
|
2301
|
+
return this._shadowType;
|
|
2302
|
+
}
|
|
1952
2303
|
/**
|
|
1953
2304
|
* Sets the type of the light.
|
|
1954
2305
|
* @param value - The type.
|
|
@@ -1970,6 +2321,23 @@ class LightComponentElement extends ComponentElement {
|
|
|
1970
2321
|
get type() {
|
|
1971
2322
|
return this._type;
|
|
1972
2323
|
}
|
|
2324
|
+
/**
|
|
2325
|
+
* Sets the VSM bias of the light.
|
|
2326
|
+
* @param value - The VSM bias.
|
|
2327
|
+
*/
|
|
2328
|
+
set vsmBias(value) {
|
|
2329
|
+
this._vsmBias = value;
|
|
2330
|
+
if (this.component) {
|
|
2331
|
+
this.component.vsmBias = value;
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
/**
|
|
2335
|
+
* Gets the VSM bias of the light.
|
|
2336
|
+
* @returns The VSM bias.
|
|
2337
|
+
*/
|
|
2338
|
+
get vsmBias() {
|
|
2339
|
+
return this._vsmBias;
|
|
2340
|
+
}
|
|
1973
2341
|
static get observedAttributes() {
|
|
1974
2342
|
return [
|
|
1975
2343
|
...super.observedAttributes,
|
|
@@ -1982,8 +2350,11 @@ class LightComponentElement extends ComponentElement {
|
|
|
1982
2350
|
'range',
|
|
1983
2351
|
'shadow-bias',
|
|
1984
2352
|
'shadow-distance',
|
|
2353
|
+
'shadow-intensity',
|
|
1985
2354
|
'shadow-resolution',
|
|
1986
|
-
'type'
|
|
2355
|
+
'shadow-type',
|
|
2356
|
+
'type',
|
|
2357
|
+
'vsm-bias'
|
|
1987
2358
|
];
|
|
1988
2359
|
}
|
|
1989
2360
|
attributeChangedCallback(name, _oldValue, newValue) {
|
|
@@ -2019,9 +2390,18 @@ class LightComponentElement extends ComponentElement {
|
|
|
2019
2390
|
case 'shadow-resolution':
|
|
2020
2391
|
this.shadowResolution = Number(newValue);
|
|
2021
2392
|
break;
|
|
2393
|
+
case 'shadow-intensity':
|
|
2394
|
+
this.shadowIntensity = Number(newValue);
|
|
2395
|
+
break;
|
|
2396
|
+
case 'shadow-type':
|
|
2397
|
+
this.shadowType = newValue;
|
|
2398
|
+
break;
|
|
2022
2399
|
case 'type':
|
|
2023
2400
|
this.type = newValue;
|
|
2024
2401
|
break;
|
|
2402
|
+
case 'vsm-bias':
|
|
2403
|
+
this.vsmBias = Number(newValue);
|
|
2404
|
+
break;
|
|
2025
2405
|
}
|
|
2026
2406
|
}
|
|
2027
2407
|
}
|
|
@@ -2044,8 +2424,8 @@ class MaterialElement extends HTMLElement {
|
|
|
2044
2424
|
}
|
|
2045
2425
|
createMaterial() {
|
|
2046
2426
|
this.material = new StandardMaterial();
|
|
2047
|
-
this.material.glossInvert =
|
|
2048
|
-
this.material.useMetalness =
|
|
2427
|
+
this.material.glossInvert = false;
|
|
2428
|
+
this.material.useMetalness = false;
|
|
2049
2429
|
this.material.diffuse = this._diffuse;
|
|
2050
2430
|
this.diffuseMap = this._diffuseMap;
|
|
2051
2431
|
this.metalnessMap = this._metalnessMap;
|
|
@@ -2578,9 +2958,6 @@ class ScreenComponentElement extends ComponentElement {
|
|
|
2578
2958
|
}
|
|
2579
2959
|
customElements.define('pc-screen', ScreenComponentElement);
|
|
2580
2960
|
|
|
2581
|
-
const tmpV2 = new Vec2();
|
|
2582
|
-
const tmpV3 = new Vec3();
|
|
2583
|
-
const tmpV4 = new Vec4();
|
|
2584
2961
|
/**
|
|
2585
2962
|
* The ScriptComponentElement interface provides properties and methods for manipulating
|
|
2586
2963
|
* `<pc-scripts>` elements. The ScriptComponentElement interface also inherits the properties and
|
|
@@ -2624,22 +3001,34 @@ class ScriptComponentElement extends ComponentElement {
|
|
|
2624
3001
|
return;
|
|
2625
3002
|
}
|
|
2626
3003
|
}
|
|
2627
|
-
// Handle
|
|
2628
|
-
if (Array.isArray(value)) {
|
|
2629
|
-
|
|
2630
|
-
|
|
3004
|
+
// Handle arrays
|
|
3005
|
+
if (value && typeof value === 'object' && Array.isArray(value)) {
|
|
3006
|
+
// If it's an array of objects, recursively apply to each object
|
|
3007
|
+
if (value.length > 0 && typeof value[0] === 'object') {
|
|
3008
|
+
target[key] = value.map((item) => {
|
|
3009
|
+
const obj = {};
|
|
3010
|
+
for (const itemKey in item) {
|
|
3011
|
+
applyValue(obj, itemKey, item[itemKey]);
|
|
3012
|
+
}
|
|
3013
|
+
return obj;
|
|
3014
|
+
});
|
|
3015
|
+
return;
|
|
3016
|
+
}
|
|
3017
|
+
// Handle vectors
|
|
3018
|
+
if (value.length === 2 && typeof value[0] === 'number') {
|
|
3019
|
+
target[key] = new Vec2(value[0], value[1]);
|
|
2631
3020
|
return;
|
|
2632
3021
|
}
|
|
2633
|
-
if (
|
|
2634
|
-
target[key] =
|
|
3022
|
+
if (value.length === 3 && typeof value[0] === 'number') {
|
|
3023
|
+
target[key] = new Vec3(value[0], value[1], value[2]);
|
|
2635
3024
|
return;
|
|
2636
3025
|
}
|
|
2637
|
-
if (
|
|
2638
|
-
target[key] =
|
|
3026
|
+
if (value.length === 4 && typeof value[0] === 'number') {
|
|
3027
|
+
target[key] = new Vec4(value[0], value[1], value[2], value[3]);
|
|
2639
3028
|
return;
|
|
2640
3029
|
}
|
|
2641
3030
|
}
|
|
2642
|
-
// Handle nested objects
|
|
3031
|
+
// Handle nested objects (non-array)
|
|
2643
3032
|
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
2644
3033
|
if (!target[key] || typeof target[key] !== 'object') {
|
|
2645
3034
|
target[key] = {};
|