@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
|
@@ -1,8 +1,18 @@
|
|
|
1
|
-
import { PROJECTION_ORTHOGRAPHIC, PROJECTION_PERSPECTIVE,
|
|
1
|
+
import { CameraComponent, Color, Vec4, GAMMA_NONE, GAMMA_SRGB, PROJECTION_ORTHOGRAPHIC, PROJECTION_PERSPECTIVE, TONEMAP_LINEAR, TONEMAP_FILMIC, TONEMAP_NEUTRAL, TONEMAP_ACES2, TONEMAP_ACES, TONEMAP_HEJL, TONEMAP_NONE, XRTYPE_VR } from 'playcanvas';
|
|
2
2
|
|
|
3
3
|
import { ComponentElement } from './component';
|
|
4
4
|
import { parseColor, parseVec4 } from '../utils';
|
|
5
5
|
|
|
6
|
+
const tonemaps = new Map([
|
|
7
|
+
['none', TONEMAP_NONE],
|
|
8
|
+
['linear', TONEMAP_LINEAR],
|
|
9
|
+
['filmic', TONEMAP_FILMIC],
|
|
10
|
+
['hejl', TONEMAP_HEJL],
|
|
11
|
+
['aces', TONEMAP_ACES],
|
|
12
|
+
['aces2', TONEMAP_ACES2],
|
|
13
|
+
['neutral', TONEMAP_NEUTRAL]
|
|
14
|
+
]);
|
|
15
|
+
|
|
6
16
|
/**
|
|
7
17
|
* The CameraComponentElement interface provides properties and methods for manipulating
|
|
8
18
|
* `<pc-camera>` elements. The CameraComponentElement interface also inherits the properties and
|
|
@@ -29,6 +39,8 @@ class CameraComponentElement extends ComponentElement {
|
|
|
29
39
|
|
|
30
40
|
private _frustumCulling = true;
|
|
31
41
|
|
|
42
|
+
private _gamma: 'none' | 'srgb' = 'srgb';
|
|
43
|
+
|
|
32
44
|
private _nearClip = 0.1;
|
|
33
45
|
|
|
34
46
|
private _orthographic = false;
|
|
@@ -41,6 +53,8 @@ class CameraComponentElement extends ComponentElement {
|
|
|
41
53
|
|
|
42
54
|
private _scissorRect = new Vec4(0, 0, 1, 1);
|
|
43
55
|
|
|
56
|
+
private _tonemap: 'none' | 'linear' | 'filmic' | 'hejl' | 'aces' | 'aces2' | 'neutral' = 'none';
|
|
57
|
+
|
|
44
58
|
/** @ignore */
|
|
45
59
|
constructor() {
|
|
46
60
|
super('camera');
|
|
@@ -57,12 +71,14 @@ class CameraComponentElement extends ComponentElement {
|
|
|
57
71
|
flipFaces: this._flipFaces,
|
|
58
72
|
fov: this._fov,
|
|
59
73
|
frustumCulling: this._frustumCulling,
|
|
74
|
+
gammaCorrection: this._gamma === 'srgb' ? GAMMA_SRGB : GAMMA_NONE,
|
|
60
75
|
nearClip: this._nearClip,
|
|
61
76
|
orthographic: this._orthographic,
|
|
62
77
|
orthoHeight: this._orthoHeight,
|
|
63
78
|
priority: this._priority,
|
|
64
79
|
rect: this._rect,
|
|
65
|
-
scissorRect: this._scissorRect
|
|
80
|
+
scissorRect: this._scissorRect,
|
|
81
|
+
toneMapping: tonemaps.get(this._tonemap)
|
|
66
82
|
};
|
|
67
83
|
}
|
|
68
84
|
|
|
@@ -266,6 +282,25 @@ class CameraComponentElement extends ComponentElement {
|
|
|
266
282
|
return this._frustumCulling;
|
|
267
283
|
}
|
|
268
284
|
|
|
285
|
+
/**
|
|
286
|
+
* Sets the gamma correction of the camera.
|
|
287
|
+
* @param value - The gamma correction.
|
|
288
|
+
*/
|
|
289
|
+
set gamma(value: 'none' | 'srgb') {
|
|
290
|
+
this._gamma = value;
|
|
291
|
+
if (this.component) {
|
|
292
|
+
this.component.gammaCorrection = value === 'srgb' ? GAMMA_SRGB : GAMMA_NONE;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Gets the gamma correction of the camera.
|
|
298
|
+
* @returns The gamma correction.
|
|
299
|
+
*/
|
|
300
|
+
get gamma(): 'none' | 'srgb' {
|
|
301
|
+
return this._gamma;
|
|
302
|
+
}
|
|
303
|
+
|
|
269
304
|
/**
|
|
270
305
|
* Sets the near clip distance of the camera.
|
|
271
306
|
* @param value - The near clip distance.
|
|
@@ -380,6 +415,25 @@ class CameraComponentElement extends ComponentElement {
|
|
|
380
415
|
return this._scissorRect;
|
|
381
416
|
}
|
|
382
417
|
|
|
418
|
+
/**
|
|
419
|
+
* Sets the tone mapping of the camera.
|
|
420
|
+
* @param value - The tone mapping.
|
|
421
|
+
*/
|
|
422
|
+
set tonemap(value: 'none' | 'linear' | 'filmic' | 'hejl' | 'aces' | 'aces2' | 'neutral') {
|
|
423
|
+
this._tonemap = value;
|
|
424
|
+
if (this.component) {
|
|
425
|
+
this.component.toneMapping = tonemaps.get(value) ?? TONEMAP_NONE;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Gets the tone mapping of the camera.
|
|
431
|
+
* @returns The tone mapping.
|
|
432
|
+
*/
|
|
433
|
+
get tonemap(): 'none' | 'linear' | 'filmic' | 'hejl' | 'aces' | 'aces2' | 'neutral' {
|
|
434
|
+
return this._tonemap;
|
|
435
|
+
}
|
|
436
|
+
|
|
383
437
|
static get observedAttributes() {
|
|
384
438
|
return [
|
|
385
439
|
...super.observedAttributes,
|
|
@@ -392,12 +446,14 @@ class CameraComponentElement extends ComponentElement {
|
|
|
392
446
|
'flip-faces',
|
|
393
447
|
'fov',
|
|
394
448
|
'frustum-culling',
|
|
449
|
+
'gamma',
|
|
395
450
|
'near-clip',
|
|
396
451
|
'orthographic',
|
|
397
452
|
'ortho-height',
|
|
398
453
|
'priority',
|
|
399
454
|
'rect',
|
|
400
|
-
'scissor-rect'
|
|
455
|
+
'scissor-rect',
|
|
456
|
+
'tonemap'
|
|
401
457
|
];
|
|
402
458
|
}
|
|
403
459
|
|
|
@@ -432,6 +488,9 @@ class CameraComponentElement extends ComponentElement {
|
|
|
432
488
|
case 'frustum-culling':
|
|
433
489
|
this.frustumCulling = newValue !== 'false';
|
|
434
490
|
break;
|
|
491
|
+
case 'gamma':
|
|
492
|
+
this.gamma = newValue as 'none' | 'srgb';
|
|
493
|
+
break;
|
|
435
494
|
case 'near-clip':
|
|
436
495
|
this.nearClip = parseFloat(newValue);
|
|
437
496
|
break;
|
|
@@ -450,6 +509,9 @@ class CameraComponentElement extends ComponentElement {
|
|
|
450
509
|
case 'scissor-rect':
|
|
451
510
|
this.scissorRect = parseVec4(newValue);
|
|
452
511
|
break;
|
|
512
|
+
case 'tonemap':
|
|
513
|
+
this.tonemap = newValue as 'none' | 'linear' | 'filmic' | 'hejl' | 'aces' | 'aces2' | 'neutral';
|
|
514
|
+
break;
|
|
453
515
|
}
|
|
454
516
|
}
|
|
455
517
|
}
|
|
@@ -1,8 +1,20 @@
|
|
|
1
|
-
import { Color, LightComponent } from 'playcanvas';
|
|
1
|
+
import { Color, LightComponent, SHADOW_PCF1_16F, SHADOW_PCF1_32F, SHADOW_PCF3_16F, SHADOW_PCF3_32F, SHADOW_PCF5_16F, SHADOW_PCF5_32F, SHADOW_PCSS_32F, SHADOW_VSM_16F, SHADOW_VSM_32F } from 'playcanvas';
|
|
2
2
|
|
|
3
3
|
import { ComponentElement } from './component';
|
|
4
4
|
import { parseColor } from '../utils';
|
|
5
5
|
|
|
6
|
+
const shadowTypes = new Map([
|
|
7
|
+
['pcf1-16f', SHADOW_PCF1_16F],
|
|
8
|
+
['pcf1-32f', SHADOW_PCF1_32F],
|
|
9
|
+
['pcf3-16f', SHADOW_PCF3_16F],
|
|
10
|
+
['pcf3-32f', SHADOW_PCF3_32F],
|
|
11
|
+
['pcf5-16f', SHADOW_PCF5_16F],
|
|
12
|
+
['pcf5-32f', SHADOW_PCF5_32F],
|
|
13
|
+
['vsm-16f', SHADOW_VSM_16F],
|
|
14
|
+
['vsm-32f', SHADOW_VSM_32F],
|
|
15
|
+
['pcss-32f', SHADOW_PCSS_32F]
|
|
16
|
+
]);
|
|
17
|
+
|
|
6
18
|
/**
|
|
7
19
|
* The LightComponentElement interface provides properties and methods for manipulating
|
|
8
20
|
* `<pc-light>` elements. The LightComponentElement interface also inherits the properties and
|
|
@@ -29,10 +41,16 @@ class LightComponentElement extends ComponentElement {
|
|
|
29
41
|
|
|
30
42
|
private _shadowDistance = 16;
|
|
31
43
|
|
|
44
|
+
private _shadowIntensity = 1;
|
|
45
|
+
|
|
32
46
|
private _shadowResolution = 1024;
|
|
33
47
|
|
|
48
|
+
private _shadowType: 'pcf1-16f' | 'pcf1-32f' | 'pcf3-16f' | 'pcf3-32f' | 'pcf5-16f' | 'pcf5-32f' | 'vsm-16f' | 'vsm-32f' | 'pcss-32f' = 'pcf3-32f';
|
|
49
|
+
|
|
34
50
|
private _type = 'directional';
|
|
35
51
|
|
|
52
|
+
private _vsmBias = 0.01;
|
|
53
|
+
|
|
36
54
|
/** @ignore */
|
|
37
55
|
constructor() {
|
|
38
56
|
super('light');
|
|
@@ -49,8 +67,11 @@ class LightComponentElement extends ComponentElement {
|
|
|
49
67
|
range: this._range,
|
|
50
68
|
shadowBias: this._shadowBias,
|
|
51
69
|
shadowDistance: this._shadowDistance,
|
|
70
|
+
shadowIntensity: this._shadowIntensity,
|
|
52
71
|
shadowResolution: this._shadowResolution,
|
|
53
|
-
|
|
72
|
+
shadowType: shadowTypes.get(this._shadowType),
|
|
73
|
+
type: this._type,
|
|
74
|
+
vsmBias: this._vsmBias
|
|
54
75
|
};
|
|
55
76
|
}
|
|
56
77
|
|
|
@@ -233,6 +254,25 @@ class LightComponentElement extends ComponentElement {
|
|
|
233
254
|
return this._shadowDistance;
|
|
234
255
|
}
|
|
235
256
|
|
|
257
|
+
/**
|
|
258
|
+
* Sets the shadow intensity of the light.
|
|
259
|
+
* @param value - The shadow intensity.
|
|
260
|
+
*/
|
|
261
|
+
set shadowIntensity(value: number) {
|
|
262
|
+
this._shadowIntensity = value;
|
|
263
|
+
if (this.component) {
|
|
264
|
+
this.component.shadowIntensity = value;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Gets the shadow intensity of the light.
|
|
270
|
+
* @returns The shadow intensity.
|
|
271
|
+
*/
|
|
272
|
+
get shadowIntensity() {
|
|
273
|
+
return this._shadowIntensity;
|
|
274
|
+
}
|
|
275
|
+
|
|
236
276
|
/**
|
|
237
277
|
* Sets the shadow resolution of the light.
|
|
238
278
|
* @param value - The shadow resolution.
|
|
@@ -252,6 +292,35 @@ class LightComponentElement extends ComponentElement {
|
|
|
252
292
|
return this._shadowResolution;
|
|
253
293
|
}
|
|
254
294
|
|
|
295
|
+
/**
|
|
296
|
+
* Sets the shadow type of the light.
|
|
297
|
+
* @param value - The shadow type. Can be:
|
|
298
|
+
*
|
|
299
|
+
* - `pcf1-16f` - 1-tap percentage-closer filtered shadow map with 16-bit depth.
|
|
300
|
+
* - `pcf1-32f` - 1-tap percentage-closer filtered shadow map with 32-bit depth.
|
|
301
|
+
* - `pcf3-16f` - 3-tap percentage-closer filtered shadow map with 16-bit depth.
|
|
302
|
+
* - `pcf3-32f` - 3-tap percentage-closer filtered shadow map with 32-bit depth.
|
|
303
|
+
* - `pcf5-16f` - 5-tap percentage-closer filtered shadow map with 16-bit depth.
|
|
304
|
+
* - `pcf5-32f` - 5-tap percentage-closer filtered shadow map with 32-bit depth.
|
|
305
|
+
* - `vsm-16f` - Variance shadow map with 16-bit depth.
|
|
306
|
+
* - `vsm-32f` - Variance shadow map with 32-bit depth.
|
|
307
|
+
* - `pcss-32f` - Percentage-closer soft shadow with 32-bit depth.
|
|
308
|
+
*/
|
|
309
|
+
set shadowType(value: 'pcf1-16f' | 'pcf1-32f' | 'pcf3-16f' | 'pcf3-32f' | 'pcf5-16f' | 'pcf5-32f' | 'vsm-16f' | 'vsm-32f' | 'pcss-32f') {
|
|
310
|
+
this._shadowType = value;
|
|
311
|
+
if (this.component) {
|
|
312
|
+
this.component.shadowType = shadowTypes.get(value) ?? SHADOW_PCF3_32F;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Gets the shadow type of the light.
|
|
318
|
+
* @returns The shadow type.
|
|
319
|
+
*/
|
|
320
|
+
get shadowType() {
|
|
321
|
+
return this._shadowType;
|
|
322
|
+
}
|
|
323
|
+
|
|
255
324
|
/**
|
|
256
325
|
* Sets the type of the light.
|
|
257
326
|
* @param value - The type.
|
|
@@ -276,6 +345,25 @@ class LightComponentElement extends ComponentElement {
|
|
|
276
345
|
return this._type;
|
|
277
346
|
}
|
|
278
347
|
|
|
348
|
+
/**
|
|
349
|
+
* Sets the VSM bias of the light.
|
|
350
|
+
* @param value - The VSM bias.
|
|
351
|
+
*/
|
|
352
|
+
set vsmBias(value: number) {
|
|
353
|
+
this._vsmBias = value;
|
|
354
|
+
if (this.component) {
|
|
355
|
+
this.component.vsmBias = value;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Gets the VSM bias of the light.
|
|
361
|
+
* @returns The VSM bias.
|
|
362
|
+
*/
|
|
363
|
+
get vsmBias() {
|
|
364
|
+
return this._vsmBias;
|
|
365
|
+
}
|
|
366
|
+
|
|
279
367
|
static get observedAttributes() {
|
|
280
368
|
return [
|
|
281
369
|
...super.observedAttributes,
|
|
@@ -288,8 +376,11 @@ class LightComponentElement extends ComponentElement {
|
|
|
288
376
|
'range',
|
|
289
377
|
'shadow-bias',
|
|
290
378
|
'shadow-distance',
|
|
379
|
+
'shadow-intensity',
|
|
291
380
|
'shadow-resolution',
|
|
292
|
-
'type'
|
|
381
|
+
'shadow-type',
|
|
382
|
+
'type',
|
|
383
|
+
'vsm-bias'
|
|
293
384
|
];
|
|
294
385
|
}
|
|
295
386
|
|
|
@@ -327,9 +418,18 @@ class LightComponentElement extends ComponentElement {
|
|
|
327
418
|
case 'shadow-resolution':
|
|
328
419
|
this.shadowResolution = Number(newValue);
|
|
329
420
|
break;
|
|
421
|
+
case 'shadow-intensity':
|
|
422
|
+
this.shadowIntensity = Number(newValue);
|
|
423
|
+
break;
|
|
424
|
+
case 'shadow-type':
|
|
425
|
+
this.shadowType = newValue as 'pcf1-16f' | 'pcf1-32f' | 'pcf3-16f' | 'pcf3-32f' | 'pcf5-16f' | 'pcf5-32f' | 'vsm-16f' | 'vsm-32f' | 'pcss-32f';
|
|
426
|
+
break;
|
|
330
427
|
case 'type':
|
|
331
428
|
this.type = newValue;
|
|
332
429
|
break;
|
|
430
|
+
case 'vsm-bias':
|
|
431
|
+
this.vsmBias = Number(newValue);
|
|
432
|
+
break;
|
|
333
433
|
}
|
|
334
434
|
}
|
|
335
435
|
}
|
|
@@ -4,10 +4,6 @@ import { ComponentElement } from './component';
|
|
|
4
4
|
import { ScriptElement } from './script';
|
|
5
5
|
import { AssetElement } from '../asset';
|
|
6
6
|
|
|
7
|
-
const tmpV2 = new Vec2();
|
|
8
|
-
const tmpV3 = new Vec3();
|
|
9
|
-
const tmpV4 = new Vec4();
|
|
10
|
-
|
|
11
7
|
// Add these interfaces at the top of the file, after the imports
|
|
12
8
|
interface ScriptAttributesChangeEvent extends CustomEvent {
|
|
13
9
|
detail: { attributes: any };
|
|
@@ -76,23 +72,36 @@ class ScriptComponentElement extends ComponentElement {
|
|
|
76
72
|
}
|
|
77
73
|
}
|
|
78
74
|
|
|
79
|
-
// Handle
|
|
80
|
-
if (Array.isArray(value)) {
|
|
81
|
-
|
|
82
|
-
|
|
75
|
+
// Handle arrays
|
|
76
|
+
if (value && typeof value === 'object' && Array.isArray(value)) {
|
|
77
|
+
// If it's an array of objects, recursively apply to each object
|
|
78
|
+
if (value.length > 0 && typeof value[0] === 'object') {
|
|
79
|
+
target[key] = value.map((item) => {
|
|
80
|
+
const obj = {};
|
|
81
|
+
for (const itemKey in item) {
|
|
82
|
+
applyValue(obj, itemKey, item[itemKey]);
|
|
83
|
+
}
|
|
84
|
+
return obj;
|
|
85
|
+
});
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Handle vectors
|
|
90
|
+
if (value.length === 2 && typeof value[0] === 'number') {
|
|
91
|
+
target[key] = new Vec2(value[0], value[1]);
|
|
83
92
|
return;
|
|
84
93
|
}
|
|
85
|
-
if (
|
|
86
|
-
target[key] =
|
|
94
|
+
if (value.length === 3 && typeof value[0] === 'number') {
|
|
95
|
+
target[key] = new Vec3(value[0], value[1], value[2]);
|
|
87
96
|
return;
|
|
88
97
|
}
|
|
89
|
-
if (
|
|
90
|
-
target[key] =
|
|
98
|
+
if (value.length === 4 && typeof value[0] === 'number') {
|
|
99
|
+
target[key] = new Vec4(value[0], value[1], value[2], value[3]);
|
|
91
100
|
return;
|
|
92
101
|
}
|
|
93
102
|
}
|
|
94
103
|
|
|
95
|
-
// Handle nested objects
|
|
104
|
+
// Handle nested objects (non-array)
|
|
96
105
|
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
97
106
|
if (!target[key] || typeof target[key] !== 'object') {
|
|
98
107
|
target[key] = {};
|
package/src/entity.ts
CHANGED
|
@@ -39,6 +39,11 @@ class EntityElement extends AsyncElement {
|
|
|
39
39
|
*/
|
|
40
40
|
private _tags: string[] = [];
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* The pointer event listeners for the entity.
|
|
44
|
+
*/
|
|
45
|
+
private _listeners: { [key: string]: EventListener[] } = {};
|
|
46
|
+
|
|
42
47
|
/**
|
|
43
48
|
* The PlayCanvas entity instance.
|
|
44
49
|
*/
|
|
@@ -72,6 +77,31 @@ class EntityElement extends AsyncElement {
|
|
|
72
77
|
if (tags) {
|
|
73
78
|
this.entity.tags.add(tags.split(',').map(tag => tag.trim()));
|
|
74
79
|
}
|
|
80
|
+
|
|
81
|
+
// Handle pointer events
|
|
82
|
+
const pointerEvents = [
|
|
83
|
+
'onpointerenter',
|
|
84
|
+
'onpointerleave',
|
|
85
|
+
'onpointerdown',
|
|
86
|
+
'onpointerup',
|
|
87
|
+
'onpointermove'
|
|
88
|
+
];
|
|
89
|
+
|
|
90
|
+
pointerEvents.forEach((eventName) => {
|
|
91
|
+
const handler = this.getAttribute(eventName);
|
|
92
|
+
if (handler) {
|
|
93
|
+
const eventType = eventName.substring(2); // remove 'on' prefix
|
|
94
|
+
const eventHandler = (event: Event) => {
|
|
95
|
+
try {
|
|
96
|
+
/* eslint-disable-next-line no-new-func */
|
|
97
|
+
new Function('event', handler).call(this, event);
|
|
98
|
+
} catch (e) {
|
|
99
|
+
console.error('Error in event handler:', e);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
this.addEventListener(eventType, eventHandler);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
75
105
|
}
|
|
76
106
|
|
|
77
107
|
buildHierarchy(app: Application) {
|
|
@@ -240,7 +270,19 @@ class EntityElement extends AsyncElement {
|
|
|
240
270
|
}
|
|
241
271
|
|
|
242
272
|
static get observedAttributes() {
|
|
243
|
-
return [
|
|
273
|
+
return [
|
|
274
|
+
'enabled',
|
|
275
|
+
'name',
|
|
276
|
+
'position',
|
|
277
|
+
'rotation',
|
|
278
|
+
'scale',
|
|
279
|
+
'tags',
|
|
280
|
+
'onpointerenter',
|
|
281
|
+
'onpointerleave',
|
|
282
|
+
'onpointerdown',
|
|
283
|
+
'onpointerup',
|
|
284
|
+
'onpointermove'
|
|
285
|
+
];
|
|
244
286
|
}
|
|
245
287
|
|
|
246
288
|
attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
|
|
@@ -263,7 +305,52 @@ class EntityElement extends AsyncElement {
|
|
|
263
305
|
case 'tags':
|
|
264
306
|
this.tags = newValue.split(',').map(tag => tag.trim());
|
|
265
307
|
break;
|
|
308
|
+
case 'onpointerenter':
|
|
309
|
+
case 'onpointerleave':
|
|
310
|
+
case 'onpointerdown':
|
|
311
|
+
case 'onpointerup':
|
|
312
|
+
case 'onpointermove':
|
|
313
|
+
if (newValue) {
|
|
314
|
+
const eventName = name.substring(2);
|
|
315
|
+
// Use Function.prototype.bind to avoid new Function
|
|
316
|
+
const handler = (event: Event) => {
|
|
317
|
+
try {
|
|
318
|
+
const handlerStr = this.getAttribute(eventName) || '';
|
|
319
|
+
/* eslint-disable-next-line no-new-func */
|
|
320
|
+
new Function('event', handlerStr).call(this, event);
|
|
321
|
+
} catch (e) {
|
|
322
|
+
console.error('Error in event handler:', e);
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
this.addEventListener(eventName, handler);
|
|
326
|
+
}
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions) {
|
|
332
|
+
if (!this._listeners[type]) {
|
|
333
|
+
this._listeners[type] = [];
|
|
266
334
|
}
|
|
335
|
+
this._listeners[type].push(listener);
|
|
336
|
+
super.addEventListener(type, listener, options);
|
|
337
|
+
if (type.startsWith('pointer')) {
|
|
338
|
+
this.dispatchEvent(new CustomEvent(`${type}:connect`, { bubbles: true }));
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions) {
|
|
343
|
+
if (this._listeners[type]) {
|
|
344
|
+
this._listeners[type] = this._listeners[type].filter(l => l !== listener);
|
|
345
|
+
}
|
|
346
|
+
super.removeEventListener(type, listener, options);
|
|
347
|
+
if (type.startsWith('pointer')) {
|
|
348
|
+
this.dispatchEvent(new CustomEvent(`${type}:disconnect`, { bubbles: true }));
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
hasListeners(type: string): boolean {
|
|
353
|
+
return Boolean(this._listeners[type]?.length);
|
|
267
354
|
}
|
|
268
355
|
}
|
|
269
356
|
|
package/src/fog.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { Color } from 'playcanvas';
|
|
2
|
+
|
|
3
|
+
import { parseColor } from './utils';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The FogElement interface provides properties and methods for manipulating
|
|
7
|
+
* `<pc-fog>` elements. The FogElement interface also inherits the properties and
|
|
8
|
+
* methods of the {@link HTMLElement} interface.
|
|
9
|
+
*/
|
|
10
|
+
class FogElement extends HTMLElement {
|
|
11
|
+
private _color = new Color(0.5, 0.5, 0.5);
|
|
12
|
+
|
|
13
|
+
private _density = 0.001;
|
|
14
|
+
|
|
15
|
+
private _end = 100;
|
|
16
|
+
|
|
17
|
+
private _start = 0;
|
|
18
|
+
|
|
19
|
+
private _type: 'linear' | 'exp' | 'exp2' = 'linear';
|
|
20
|
+
|
|
21
|
+
private dispatchFogUpdate() {
|
|
22
|
+
const event = new CustomEvent('fogupdate', {
|
|
23
|
+
bubbles: true,
|
|
24
|
+
detail: {
|
|
25
|
+
color: this._color,
|
|
26
|
+
density: this._density,
|
|
27
|
+
end: this._end,
|
|
28
|
+
start: this._start,
|
|
29
|
+
type: this._type
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
this.dispatchEvent(event);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
set color(value: Color) {
|
|
36
|
+
this._color = value;
|
|
37
|
+
this.dispatchFogUpdate();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get color(): Color {
|
|
41
|
+
return this._color;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
set density(value: number) {
|
|
45
|
+
this._density = value;
|
|
46
|
+
this.dispatchFogUpdate();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
get density(): number {
|
|
50
|
+
return this._density;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
set end(value: number) {
|
|
54
|
+
this._end = value;
|
|
55
|
+
this.dispatchFogUpdate();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
get end(): number {
|
|
59
|
+
return this._end;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
set start(value: number) {
|
|
63
|
+
this._start = value;
|
|
64
|
+
this.dispatchFogUpdate();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
get start(): number {
|
|
68
|
+
return this._start;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
set type(value: 'linear' | 'exp' | 'exp2') {
|
|
72
|
+
this._type = value;
|
|
73
|
+
this.dispatchFogUpdate();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
get type(): 'linear' | 'exp' | 'exp2' {
|
|
77
|
+
return this._type;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
static get observedAttributes() {
|
|
81
|
+
return [
|
|
82
|
+
'color',
|
|
83
|
+
'density',
|
|
84
|
+
'end',
|
|
85
|
+
'start',
|
|
86
|
+
'type'
|
|
87
|
+
];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
|
|
91
|
+
switch (name) {
|
|
92
|
+
case 'color':
|
|
93
|
+
this.color = parseColor(newValue);
|
|
94
|
+
break;
|
|
95
|
+
case 'density':
|
|
96
|
+
this.density = parseFloat(newValue);
|
|
97
|
+
break;
|
|
98
|
+
case 'end':
|
|
99
|
+
this.end = parseFloat(newValue);
|
|
100
|
+
break;
|
|
101
|
+
case 'start':
|
|
102
|
+
this.start = parseFloat(newValue);
|
|
103
|
+
break;
|
|
104
|
+
case 'type':
|
|
105
|
+
if (newValue === 'linear' || newValue === 'exp' || newValue === 'exp2') {
|
|
106
|
+
this.type = newValue;
|
|
107
|
+
}
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
constructor() {
|
|
113
|
+
super();
|
|
114
|
+
// Dispatch initial fog state
|
|
115
|
+
this.dispatchFogUpdate();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
customElements.define('pc-fog', FogElement);
|
|
120
|
+
|
|
121
|
+
export { FogElement };
|
package/src/material.ts
CHANGED
|
@@ -23,8 +23,8 @@ class MaterialElement extends HTMLElement {
|
|
|
23
23
|
|
|
24
24
|
createMaterial() {
|
|
25
25
|
this.material = new StandardMaterial();
|
|
26
|
-
this.material.glossInvert =
|
|
27
|
-
this.material.useMetalness =
|
|
26
|
+
this.material.glossInvert = false;
|
|
27
|
+
this.material.useMetalness = false;
|
|
28
28
|
this.material.diffuse = this._diffuse;
|
|
29
29
|
this.diffuseMap = this._diffuseMap;
|
|
30
30
|
this.metalnessMap = this._metalnessMap;
|