@playcanvas/web-components 0.1.2 → 0.1.4
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 +30 -6
- package/dist/asset.d.ts +1 -0
- package/dist/components/camera-component.d.ts +110 -2
- package/dist/components/collision-component.d.ts +9 -1
- package/dist/components/element-component.d.ts +0 -1
- package/dist/components/gsplat-component.d.ts +1 -2
- package/dist/components/render-component.d.ts +13 -1
- package/dist/components/screen-component.d.ts +44 -0
- package/dist/components/sound-slot.d.ts +0 -1
- package/dist/entity.d.ts +2 -0
- package/dist/index.d.ts +3 -1
- package/dist/material.d.ts +29 -0
- package/dist/model.d.ts +0 -1
- package/dist/pwc.cjs +562 -39
- package/dist/pwc.cjs.map +1 -1
- package/dist/pwc.js +562 -39
- 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 +562 -41
- package/dist/pwc.mjs.map +1 -1
- package/dist/sky.d.ts +0 -1
- package/dist/utils.d.ts +8 -1
- package/package.json +11 -11
- package/src/app.ts +7 -0
- package/src/asset.ts +5 -0
- package/src/components/camera-component.ts +248 -6
- package/src/components/collision-component.ts +37 -3
- package/src/components/element-component.ts +2 -7
- package/src/components/gsplat-component.ts +2 -7
- package/src/components/render-component.ts +38 -7
- package/src/components/screen-component.ts +153 -0
- package/src/components/sound-slot.ts +1 -6
- package/src/entity.ts +22 -2
- package/src/index.ts +4 -0
- package/src/material.ts +138 -0
- package/src/model.ts +1 -6
- package/src/sky.ts +1 -6
- package/src/utils.ts +14 -1
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { SCALEMODE_BLEND, SCALEMODE_NONE, ScreenComponent, Vec2 } from 'playcanvas';
|
|
2
|
+
|
|
3
|
+
import { ComponentElement } from './component';
|
|
4
|
+
import { parseVec2 } from '../utils';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Represents a screen component in the PlayCanvas engine.
|
|
8
|
+
*
|
|
9
|
+
* @category Components
|
|
10
|
+
*/
|
|
11
|
+
class ScreenComponentElement extends ComponentElement {
|
|
12
|
+
private _screenSpace = false;
|
|
13
|
+
|
|
14
|
+
private _resolution: Vec2 = new Vec2(640, 320);
|
|
15
|
+
|
|
16
|
+
private _referenceResolution: Vec2 = new Vec2(640, 320);
|
|
17
|
+
|
|
18
|
+
private _priority = 0;
|
|
19
|
+
|
|
20
|
+
private _blend = false;
|
|
21
|
+
|
|
22
|
+
private _scaleBlend = 0.5;
|
|
23
|
+
|
|
24
|
+
constructor() {
|
|
25
|
+
super('screen');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
getInitialComponentData() {
|
|
29
|
+
return {
|
|
30
|
+
priority: this._priority,
|
|
31
|
+
referenceResolution: this._referenceResolution,
|
|
32
|
+
resolution: this._resolution,
|
|
33
|
+
scaleBlend: this._scaleBlend,
|
|
34
|
+
scaleMode: this._blend ? SCALEMODE_BLEND : SCALEMODE_NONE,
|
|
35
|
+
screenSpace: this._screenSpace
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Gets the screen component.
|
|
41
|
+
* @returns The screen component.
|
|
42
|
+
*/
|
|
43
|
+
get component(): ScreenComponent | null {
|
|
44
|
+
return super.component as ScreenComponent | null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
set priority(value: number) {
|
|
48
|
+
this._priority = value;
|
|
49
|
+
if (this.component) {
|
|
50
|
+
this.component.priority = this._priority;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
get priority() {
|
|
55
|
+
return this._priority;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
set referenceResolution(value: Vec2) {
|
|
59
|
+
this._referenceResolution = value;
|
|
60
|
+
if (this.component) {
|
|
61
|
+
this.component.referenceResolution = this._referenceResolution;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get referenceResolution() {
|
|
66
|
+
return this._referenceResolution;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
set resolution(value: Vec2) {
|
|
70
|
+
this._resolution = value;
|
|
71
|
+
if (this.component) {
|
|
72
|
+
this.component.resolution = this._resolution;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
get resolution() {
|
|
77
|
+
return this._resolution;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
set scaleBlend(value: number) {
|
|
81
|
+
this._scaleBlend = value;
|
|
82
|
+
if (this.component) {
|
|
83
|
+
this.component.scaleBlend = this._scaleBlend;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
get scaleBlend() {
|
|
88
|
+
return this._scaleBlend;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
set blend(value: boolean) {
|
|
92
|
+
this._blend = value;
|
|
93
|
+
if (this.component) {
|
|
94
|
+
this.component.scaleMode = this._blend ? SCALEMODE_BLEND : SCALEMODE_NONE;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
get blend() {
|
|
99
|
+
return this._blend;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
set screenSpace(value: boolean) {
|
|
103
|
+
this._screenSpace = value;
|
|
104
|
+
if (this.component) {
|
|
105
|
+
this.component.screenSpace = this._screenSpace;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
get screenSpace() {
|
|
110
|
+
return this._screenSpace;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
static get observedAttributes() {
|
|
114
|
+
return [
|
|
115
|
+
...super.observedAttributes,
|
|
116
|
+
'blend',
|
|
117
|
+
'screen-space',
|
|
118
|
+
'resolution',
|
|
119
|
+
'reference-resolution',
|
|
120
|
+
'priority',
|
|
121
|
+
'scale-blend'
|
|
122
|
+
];
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
|
|
126
|
+
super.attributeChangedCallback(name, _oldValue, newValue);
|
|
127
|
+
|
|
128
|
+
switch (name) {
|
|
129
|
+
case 'priority':
|
|
130
|
+
this.priority = parseInt(newValue, 10);
|
|
131
|
+
break;
|
|
132
|
+
case 'reference-resolution':
|
|
133
|
+
this.referenceResolution = parseVec2(newValue);
|
|
134
|
+
break;
|
|
135
|
+
case 'resolution':
|
|
136
|
+
this.resolution = parseVec2(newValue);
|
|
137
|
+
break;
|
|
138
|
+
case 'scale-blend':
|
|
139
|
+
this.scaleBlend = parseFloat(newValue);
|
|
140
|
+
break;
|
|
141
|
+
case 'blend':
|
|
142
|
+
this.blend = this.hasAttribute('blend');
|
|
143
|
+
break;
|
|
144
|
+
case 'screen-space':
|
|
145
|
+
this.screenSpace = this.hasAttribute('screen-space');
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
customElements.define('pc-screen', ScreenComponentElement);
|
|
152
|
+
|
|
153
|
+
export { ScreenComponentElement };
|
|
@@ -31,11 +31,6 @@ class SoundSlotElement extends HTMLElement {
|
|
|
31
31
|
*/
|
|
32
32
|
soundSlot: SoundSlot | null = null;
|
|
33
33
|
|
|
34
|
-
getAsset() {
|
|
35
|
-
const assetElement = document.querySelector(`pc-asset[id="${this._asset}"]`) as AssetElement;
|
|
36
|
-
return assetElement!.asset;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
34
|
async connectedCallback() {
|
|
40
35
|
const appElement = this.closest('pc-app') as AppElement | null;
|
|
41
36
|
if (!appElement) {
|
|
@@ -83,7 +78,7 @@ class SoundSlotElement extends HTMLElement {
|
|
|
83
78
|
set asset(value: string) {
|
|
84
79
|
this._asset = value;
|
|
85
80
|
if (this.soundSlot) {
|
|
86
|
-
const id =
|
|
81
|
+
const id = AssetElement.get(value)?.id;
|
|
87
82
|
if (id) {
|
|
88
83
|
this.soundSlot.asset = id;
|
|
89
84
|
}
|
package/src/entity.ts
CHANGED
|
@@ -37,6 +37,12 @@ class EntityElement extends HTMLElement {
|
|
|
37
37
|
*/
|
|
38
38
|
private _tags: string[] = [];
|
|
39
39
|
|
|
40
|
+
private _resolveEntity!: (entity: Entity) => void;
|
|
41
|
+
|
|
42
|
+
private _entityReady = new Promise<Entity>((resolve) => {
|
|
43
|
+
this._resolveEntity = resolve;
|
|
44
|
+
});
|
|
45
|
+
|
|
40
46
|
/**
|
|
41
47
|
* The PlayCanvas entity instance.
|
|
42
48
|
*/
|
|
@@ -54,9 +60,12 @@ class EntityElement extends HTMLElement {
|
|
|
54
60
|
|
|
55
61
|
// Create a new entity
|
|
56
62
|
this.entity = new Entity(this._name, app);
|
|
63
|
+
this._resolveEntity(this.entity);
|
|
57
64
|
|
|
58
|
-
if (this.parentElement &&
|
|
59
|
-
|
|
65
|
+
if (this.parentElement &&
|
|
66
|
+
this.parentElement.tagName.toLowerCase() === 'pc-entity') {
|
|
67
|
+
const parentEntity = await (this.parentElement as EntityElement)._entityReady;
|
|
68
|
+
parentEntity.addChild(this.entity);
|
|
60
69
|
} else {
|
|
61
70
|
app.root.addChild(this.entity);
|
|
62
71
|
}
|
|
@@ -77,9 +86,20 @@ class EntityElement extends HTMLElement {
|
|
|
77
86
|
|
|
78
87
|
disconnectedCallback() {
|
|
79
88
|
if (this.entity) {
|
|
89
|
+
// Notify all children that their entities are about to become invalid
|
|
90
|
+
const children = this.querySelectorAll('pc-entity');
|
|
91
|
+
children.forEach((child) => {
|
|
92
|
+
(child as EntityElement).entity = null;
|
|
93
|
+
});
|
|
94
|
+
|
|
80
95
|
this.entity.destroy();
|
|
81
96
|
this.entity = null;
|
|
82
97
|
}
|
|
98
|
+
|
|
99
|
+
// Reset the promise for potential reconnection
|
|
100
|
+
this._entityReady = new Promise<Entity>((resolve) => {
|
|
101
|
+
this._resolveEntity = resolve;
|
|
102
|
+
});
|
|
83
103
|
}
|
|
84
104
|
|
|
85
105
|
/**
|
package/src/index.ts
CHANGED
|
@@ -14,10 +14,12 @@ import { GSplatComponentElement } from './components/gsplat-component';
|
|
|
14
14
|
import { LightComponentElement } from './components/light-component';
|
|
15
15
|
import { RenderComponentElement } from './components/render-component';
|
|
16
16
|
import { RigidBodyComponentElement } from './components/rigidbody-component';
|
|
17
|
+
import { ScreenComponentElement } from './components/screen-component';
|
|
17
18
|
import { ScriptComponentElement } from './components/script-component';
|
|
18
19
|
import { ScriptElement } from './components/script';
|
|
19
20
|
import { SoundComponentElement } from './components/sound-component';
|
|
20
21
|
import { SoundSlotElement } from './components/sound-slot';
|
|
22
|
+
import { MaterialElement } from './material';
|
|
21
23
|
import { ModelElement } from './model';
|
|
22
24
|
import { SceneElement } from './scene';
|
|
23
25
|
import { SkyElement } from './sky';
|
|
@@ -36,10 +38,12 @@ export {
|
|
|
36
38
|
ListenerComponentElement,
|
|
37
39
|
RenderComponentElement,
|
|
38
40
|
RigidBodyComponentElement,
|
|
41
|
+
ScreenComponentElement,
|
|
39
42
|
ScriptComponentElement,
|
|
40
43
|
ScriptElement,
|
|
41
44
|
SoundComponentElement,
|
|
42
45
|
SoundSlotElement,
|
|
46
|
+
MaterialElement,
|
|
43
47
|
ModelElement,
|
|
44
48
|
SceneElement,
|
|
45
49
|
SkyElement
|
package/src/material.ts
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { Color, StandardMaterial } from 'playcanvas';
|
|
2
|
+
|
|
3
|
+
import { AssetElement } from './asset';
|
|
4
|
+
import { parseColor } from './utils';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Represents a material in the PlayCanvas engine.
|
|
8
|
+
*/
|
|
9
|
+
class MaterialElement extends HTMLElement {
|
|
10
|
+
private _diffuse = new Color(1, 1, 1);
|
|
11
|
+
|
|
12
|
+
private _diffuseMap = '';
|
|
13
|
+
|
|
14
|
+
private _metalnessMap = '';
|
|
15
|
+
|
|
16
|
+
private _normalMap = '';
|
|
17
|
+
|
|
18
|
+
private _roughnessMap = '';
|
|
19
|
+
|
|
20
|
+
material: StandardMaterial | null = null;
|
|
21
|
+
|
|
22
|
+
createMaterial() {
|
|
23
|
+
this.material = new StandardMaterial();
|
|
24
|
+
this.material.glossInvert = true;
|
|
25
|
+
this.material.useMetalness = true;
|
|
26
|
+
this.material.diffuse = this._diffuse;
|
|
27
|
+
this.diffuseMap = this._diffuseMap;
|
|
28
|
+
this.metalnessMap = this._metalnessMap;
|
|
29
|
+
this.normalMap = this._normalMap;
|
|
30
|
+
this.roughnessMap = this._roughnessMap;
|
|
31
|
+
this.material.update();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
disconnectedCallback() {
|
|
35
|
+
if (this.material) {
|
|
36
|
+
this.material.destroy();
|
|
37
|
+
this.material = null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
setMap(map: string, property: 'diffuseMap' | 'metalnessMap' | 'normalMap' | 'glossMap') {
|
|
42
|
+
if (this.material) {
|
|
43
|
+
const asset = AssetElement.get(map);
|
|
44
|
+
if (asset) {
|
|
45
|
+
if (asset.loaded) {
|
|
46
|
+
this.material[property] = asset.resource;
|
|
47
|
+
this.material[property]!.anisotropy = 4;
|
|
48
|
+
} else {
|
|
49
|
+
asset.once('load', () => {
|
|
50
|
+
this.material![property] = asset.resource;
|
|
51
|
+
this.material![property]!.anisotropy = 4;
|
|
52
|
+
this.material!.update();
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
set diffuse(value: Color) {
|
|
60
|
+
this._diffuse = value;
|
|
61
|
+
if (this.material) {
|
|
62
|
+
this.material.diffuse = value;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
get diffuse(): Color {
|
|
67
|
+
return this._diffuse;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
set diffuseMap(value: string) {
|
|
71
|
+
this._diffuseMap = value;
|
|
72
|
+
this.setMap(value, 'diffuseMap');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
get diffuseMap() {
|
|
76
|
+
return this._diffuseMap;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
set metalnessMap(value: string) {
|
|
80
|
+
this._metalnessMap = value;
|
|
81
|
+
this.setMap(value, 'metalnessMap');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
get metalnessMap() {
|
|
85
|
+
return this._metalnessMap;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
set normalMap(value: string) {
|
|
89
|
+
this._normalMap = value;
|
|
90
|
+
this.setMap(value, 'normalMap');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
get normalMap() {
|
|
94
|
+
return this._normalMap;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
set roughnessMap(value: string) {
|
|
98
|
+
this._roughnessMap = value;
|
|
99
|
+
this.setMap(value, 'glossMap');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
get roughnessMap() {
|
|
103
|
+
return this._roughnessMap;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
static get(id: string) {
|
|
107
|
+
const materialElement = document.querySelector<MaterialElement>(`pc-material[id="${id}"]`);
|
|
108
|
+
return materialElement?.material;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
static get observedAttributes() {
|
|
112
|
+
return ['diffuse', 'diffuse-map', 'metalness-map', 'normal-map', 'roughness-map'];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
|
|
116
|
+
switch (name) {
|
|
117
|
+
case 'diffuse':
|
|
118
|
+
this.diffuse = parseColor(newValue);
|
|
119
|
+
break;
|
|
120
|
+
case 'diffuse-map':
|
|
121
|
+
this.diffuseMap = newValue;
|
|
122
|
+
break;
|
|
123
|
+
case 'metalness-map':
|
|
124
|
+
this.metalnessMap = newValue;
|
|
125
|
+
break;
|
|
126
|
+
case 'normal-map':
|
|
127
|
+
this.normalMap = newValue;
|
|
128
|
+
break;
|
|
129
|
+
case 'roughness-map':
|
|
130
|
+
this.roughnessMap = newValue;
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
customElements.define('pc-material', MaterialElement);
|
|
137
|
+
|
|
138
|
+
export { MaterialElement };
|
package/src/model.ts
CHANGED
|
@@ -24,13 +24,8 @@ class ModelElement extends HTMLElement {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
getAsset() {
|
|
28
|
-
const assetElement = document.querySelector(`pc-asset[id="${this._asset}"]`) as AssetElement;
|
|
29
|
-
return assetElement!.asset;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
27
|
_loadModel() {
|
|
33
|
-
const asset = this.
|
|
28
|
+
const asset = AssetElement.get(this._asset);
|
|
34
29
|
if (!asset) {
|
|
35
30
|
return;
|
|
36
31
|
}
|
package/src/sky.ts
CHANGED
|
@@ -31,11 +31,6 @@ class SkyElement extends HTMLElement {
|
|
|
31
31
|
this.solidColor = this.hasAttribute('solid-color');
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
getAsset() {
|
|
35
|
-
const assetElement = document.querySelector(`pc-asset[id="${this._asset}"]`) as AssetElement;
|
|
36
|
-
return assetElement!.asset;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
34
|
getScene() {
|
|
40
35
|
const appElement = this.closest('pc-app') as AppElement | null;
|
|
41
36
|
if (!appElement) {
|
|
@@ -52,7 +47,7 @@ class SkyElement extends HTMLElement {
|
|
|
52
47
|
this._asset = value;
|
|
53
48
|
const scene = this.getScene();
|
|
54
49
|
if (scene) {
|
|
55
|
-
const asset =
|
|
50
|
+
const asset = AssetElement.get(value);
|
|
56
51
|
if (asset) {
|
|
57
52
|
if (asset.resource) {
|
|
58
53
|
scene.envAtlas = asset.resource;
|
package/src/utils.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Color, Vec2, Vec3, Vec4 } from 'playcanvas';
|
|
1
|
+
import { Color, Quat, Vec2, Vec3, Vec4 } from 'playcanvas';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Parse a color string into a Color object. String can be in the format of '#rgb', '#rgba',
|
|
@@ -16,6 +16,19 @@ export const parseColor = (value: string): Color => {
|
|
|
16
16
|
return new Color(components);
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Parse an Euler angles string into a Quat object. String can be in the format of 'x,y,z'.
|
|
21
|
+
*
|
|
22
|
+
* @param value - The Euler angles string to parse.
|
|
23
|
+
* @returns The parsed Quat object.
|
|
24
|
+
*/
|
|
25
|
+
export const parseQuat = (value: string): Quat => {
|
|
26
|
+
const [x, y, z] = value.split(',').map(Number);
|
|
27
|
+
const q = new Quat();
|
|
28
|
+
q.setFromEulerAngles(x, y, z);
|
|
29
|
+
return q;
|
|
30
|
+
};
|
|
31
|
+
|
|
19
32
|
/**
|
|
20
33
|
* Parse a Vec2 string into a Vec2 object. String can be in the format of 'x,y'.
|
|
21
34
|
*
|