@playcanvas/web-components 0.1.0 → 0.1.1
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 +3 -3
- package/dist/pwc.cjs +1 -1
- package/dist/pwc.cjs.map +1 -1
- package/dist/pwc.js +1 -1
- 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 +1 -1
- package/dist/pwc.mjs.map +1 -1
- package/package.json +3 -2
- package/src/app.ts +138 -0
- package/src/asset.ts +99 -0
- package/src/components/camera-component.ts +196 -0
- package/src/components/collision-component.ts +148 -0
- package/src/components/component.ts +106 -0
- package/src/components/element-component.ts +252 -0
- package/src/components/gsplat-component.ts +66 -0
- package/src/components/light-component.ts +313 -0
- package/src/components/listener-component.ts +26 -0
- package/src/components/render-component.ts +117 -0
- package/src/components/rigidbody-component.ts +226 -0
- package/src/components/script-component.ts +26 -0
- package/src/components/script.ts +130 -0
- package/src/components/sound-component.ts +117 -0
- package/src/components/sound-slot.ts +289 -0
- package/src/entity.ts +230 -0
- package/src/index.ts +46 -0
- package/src/model.ts +80 -0
- package/src/module.ts +35 -0
- package/src/scene.ts +188 -0
- package/src/sky.ts +150 -0
- package/src/utils.ts +50 -0
package/src/app.ts
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { Application, FILLMODE_FILL_WINDOW, Keyboard, Mouse, RESOLUTION_AUTO } from 'playcanvas';
|
|
2
|
+
|
|
3
|
+
import { AssetElement } from './asset';
|
|
4
|
+
import { ModuleElement } from './module';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The main application element.
|
|
8
|
+
*/
|
|
9
|
+
class AppElement extends HTMLElement {
|
|
10
|
+
/**
|
|
11
|
+
* The canvas element.
|
|
12
|
+
*/
|
|
13
|
+
private _canvas: HTMLCanvasElement | null = null;
|
|
14
|
+
|
|
15
|
+
private appReadyPromise: Promise<Application>;
|
|
16
|
+
|
|
17
|
+
private appReadyResolve!: (app: Application) => void;
|
|
18
|
+
|
|
19
|
+
private _highResolution = false;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The PlayCanvas application instance.
|
|
23
|
+
*/
|
|
24
|
+
app: Application | null = null;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Creates a new AppElement.
|
|
28
|
+
*/
|
|
29
|
+
constructor() {
|
|
30
|
+
super();
|
|
31
|
+
|
|
32
|
+
// Bind methods to maintain 'this' context
|
|
33
|
+
this._onWindowResize = this._onWindowResize.bind(this);
|
|
34
|
+
|
|
35
|
+
this.appReadyPromise = new Promise<Application>((resolve) => {
|
|
36
|
+
this.appReadyResolve = resolve;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async connectedCallback() {
|
|
41
|
+
// Get all pc-module elements that are direct children of the pc-app element
|
|
42
|
+
const moduleElements = this.querySelectorAll<ModuleElement>(':scope > pc-module');
|
|
43
|
+
|
|
44
|
+
// Wait for all modules to load
|
|
45
|
+
await Promise.all(Array.from(moduleElements).map(module => module.getLoadPromise()));
|
|
46
|
+
|
|
47
|
+
// Create and append the canvas to the element
|
|
48
|
+
this._canvas = document.createElement('canvas');
|
|
49
|
+
this.appendChild(this._canvas);
|
|
50
|
+
|
|
51
|
+
// Initialize the PlayCanvas application
|
|
52
|
+
this.app = new Application(this._canvas, {
|
|
53
|
+
graphicsDeviceOptions: {
|
|
54
|
+
devicePixelRatio: this._highResolution ? window.devicePixelRatio : 1
|
|
55
|
+
},
|
|
56
|
+
keyboard: new Keyboard(window),
|
|
57
|
+
mouse: new Mouse(this._canvas)
|
|
58
|
+
});
|
|
59
|
+
this.app.setCanvasFillMode(FILLMODE_FILL_WINDOW);
|
|
60
|
+
this.app.setCanvasResolution(RESOLUTION_AUTO);
|
|
61
|
+
|
|
62
|
+
// Get all pc-asset elements that are direct children of the pc-app element
|
|
63
|
+
const assetElements = this.querySelectorAll<AssetElement>(':scope > pc-asset');
|
|
64
|
+
Array.from(assetElements).forEach((assetElement) => {
|
|
65
|
+
assetElement.createAsset();
|
|
66
|
+
const asset = assetElement.asset;
|
|
67
|
+
if (asset) {
|
|
68
|
+
this.app!.assets.add(asset);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Load assets before starting the application
|
|
73
|
+
this.app.preload(() => {
|
|
74
|
+
// Start the application
|
|
75
|
+
this.app!.start();
|
|
76
|
+
|
|
77
|
+
// Handle window resize to keep the canvas responsive
|
|
78
|
+
window.addEventListener('resize', this._onWindowResize);
|
|
79
|
+
|
|
80
|
+
this.appReadyResolve(this.app!);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
disconnectedCallback() {
|
|
85
|
+
// Clean up the application
|
|
86
|
+
if (this.app) {
|
|
87
|
+
this.app.destroy();
|
|
88
|
+
this.app = null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Remove event listeners
|
|
92
|
+
window.removeEventListener('resize', this._onWindowResize);
|
|
93
|
+
|
|
94
|
+
// Remove the canvas
|
|
95
|
+
if (this._canvas && this.contains(this._canvas)) {
|
|
96
|
+
this.removeChild(this._canvas);
|
|
97
|
+
this._canvas = null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async getApplication(): Promise<Application> {
|
|
102
|
+
await this.appReadyPromise;
|
|
103
|
+
return this.app!;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
_onWindowResize() {
|
|
107
|
+
if (this.app) {
|
|
108
|
+
this.app.resizeCanvas();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
set highResolution(value: boolean) {
|
|
113
|
+
this._highResolution = value;
|
|
114
|
+
if (this.app) {
|
|
115
|
+
this.app.graphicsDevice.maxPixelRatio = value ? window.devicePixelRatio : 1;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
get highResolution() {
|
|
120
|
+
return this._highResolution;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
static get observedAttributes() {
|
|
124
|
+
return ['high-resolution'];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
attributeChangedCallback(name: string, _oldValue: string, _newValue: string) {
|
|
128
|
+
switch (name) {
|
|
129
|
+
case 'high-resolution':
|
|
130
|
+
this.highResolution = this.hasAttribute(name);
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
customElements.define('pc-app', AppElement);
|
|
137
|
+
|
|
138
|
+
export { AppElement };
|
package/src/asset.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Asset } from 'playcanvas';
|
|
2
|
+
|
|
3
|
+
const extToType = new Map([
|
|
4
|
+
['bin', 'binary'],
|
|
5
|
+
['css', 'css'],
|
|
6
|
+
['frag', 'shader'],
|
|
7
|
+
['glb', 'container'],
|
|
8
|
+
['glsl', 'shader'],
|
|
9
|
+
['html', 'html'],
|
|
10
|
+
['jpg', 'texture'],
|
|
11
|
+
['js', 'script'],
|
|
12
|
+
['json', 'json'],
|
|
13
|
+
['mp3', 'audio'],
|
|
14
|
+
['mjs', 'script'],
|
|
15
|
+
['ply', 'gsplat'],
|
|
16
|
+
['png', 'texture'],
|
|
17
|
+
['txt', 'text'],
|
|
18
|
+
['vert', 'shader'],
|
|
19
|
+
['webp', 'texture']
|
|
20
|
+
]);
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Loads an asset into the PlayCanvas engine.
|
|
24
|
+
*/
|
|
25
|
+
class AssetElement extends HTMLElement {
|
|
26
|
+
private _preload: boolean = false;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The asset that is loaded.
|
|
30
|
+
*/
|
|
31
|
+
asset: Asset | null = null;
|
|
32
|
+
|
|
33
|
+
async connectedCallback() {
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
disconnectedCallback() {
|
|
37
|
+
this.destroyAsset();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
createAsset() {
|
|
41
|
+
const id = this.getAttribute('id') || '';
|
|
42
|
+
const src = this.getAttribute('src') || '';
|
|
43
|
+
let type = this.getAttribute('type');
|
|
44
|
+
|
|
45
|
+
// If no type is specified, try to infer it from the file extension.
|
|
46
|
+
if (!type) {
|
|
47
|
+
const ext = src.split('.').pop();
|
|
48
|
+
type = extToType.get(ext || '') ?? null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (!type) {
|
|
52
|
+
console.warn(`Unsupported asset type: ${src}`);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
this.asset = new Asset(id, type, { url: src });
|
|
57
|
+
this.asset.preload = this.preload;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
destroyAsset() {
|
|
61
|
+
if (this.asset) {
|
|
62
|
+
this.asset.unload();
|
|
63
|
+
this.asset = null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Sets the preload flag of the asset.
|
|
69
|
+
* @param value - The preload flag.
|
|
70
|
+
*/
|
|
71
|
+
set preload(value: boolean) {
|
|
72
|
+
this._preload = value;
|
|
73
|
+
if (this.asset) {
|
|
74
|
+
this.asset.preload = value;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Gets the preload flag of the asset.
|
|
80
|
+
* @returns The preload flag.
|
|
81
|
+
*/
|
|
82
|
+
get preload() {
|
|
83
|
+
return this._preload;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
static get observedAttributes() {
|
|
87
|
+
return ['preload'];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
attributeChangedCallback(name: string, _oldValue: string, _newValue: string) {
|
|
91
|
+
if (name === 'preload') {
|
|
92
|
+
this.preload = this.hasAttribute('preload');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
customElements.define('pc-asset', AssetElement);
|
|
98
|
+
|
|
99
|
+
export { AssetElement };
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { PROJECTION_ORTHOGRAPHIC, PROJECTION_PERSPECTIVE, CameraComponent, Color } from 'playcanvas';
|
|
2
|
+
|
|
3
|
+
import { ComponentElement } from './component';
|
|
4
|
+
import { parseColor } from '../utils';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Represents a camera component in the PlayCanvas engine.
|
|
8
|
+
*
|
|
9
|
+
* @category Components
|
|
10
|
+
*/
|
|
11
|
+
class CameraComponentElement extends ComponentElement {
|
|
12
|
+
private _clearColor = new Color(1, 1, 1, 1);
|
|
13
|
+
|
|
14
|
+
private _farClip = 1000;
|
|
15
|
+
|
|
16
|
+
private _fov = 45;
|
|
17
|
+
|
|
18
|
+
private _nearClip = 0.1;
|
|
19
|
+
|
|
20
|
+
private _orthographic = false;
|
|
21
|
+
|
|
22
|
+
private _orthoHeight = 10;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Creates a new CameraComponentElement.
|
|
26
|
+
*/
|
|
27
|
+
constructor() {
|
|
28
|
+
super('camera');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
getInitialComponentData() {
|
|
32
|
+
return {
|
|
33
|
+
clearColor: this._clearColor,
|
|
34
|
+
farClip: this._farClip,
|
|
35
|
+
fov: this._fov,
|
|
36
|
+
nearClip: this._nearClip,
|
|
37
|
+
projection: this._orthographic ? PROJECTION_ORTHOGRAPHIC : PROJECTION_PERSPECTIVE,
|
|
38
|
+
orthoHeight: this._orthoHeight
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Gets the camera component.
|
|
44
|
+
* @returns The camera component.
|
|
45
|
+
*/
|
|
46
|
+
get component(): CameraComponent | null {
|
|
47
|
+
return super.component as CameraComponent | null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Sets the clear color of the camera.
|
|
52
|
+
* @param value - The clear color.
|
|
53
|
+
*/
|
|
54
|
+
set clearColor(value) {
|
|
55
|
+
this._clearColor = value;
|
|
56
|
+
if (this.component) {
|
|
57
|
+
this.component.clearColor = value;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Gets the clear color of the camera.
|
|
63
|
+
* @returns The clear color.
|
|
64
|
+
*/
|
|
65
|
+
get clearColor(): Color {
|
|
66
|
+
return this._clearColor;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Sets the far clip distance of the camera.
|
|
71
|
+
* @param value - The far clip distance.
|
|
72
|
+
*/
|
|
73
|
+
set farClip(value: number) {
|
|
74
|
+
this._farClip = value;
|
|
75
|
+
if (this.component) {
|
|
76
|
+
this.component.farClip = value;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Gets the far clip distance of the camera.
|
|
82
|
+
* @returns The far clip distance.
|
|
83
|
+
*/
|
|
84
|
+
get farClip(): number {
|
|
85
|
+
return this._farClip;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Sets the field of view of the camera.
|
|
90
|
+
* @param value - The field of view.
|
|
91
|
+
*/
|
|
92
|
+
set fov(value: number) {
|
|
93
|
+
this._fov = value;
|
|
94
|
+
if (this.component) {
|
|
95
|
+
this.component.fov = value;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Gets the field of view of the camera.
|
|
101
|
+
* @returns The field of view.
|
|
102
|
+
*/
|
|
103
|
+
get fov(): number {
|
|
104
|
+
return this._fov;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Sets the near clip distance of the camera.
|
|
109
|
+
* @param value - The near clip distance.
|
|
110
|
+
*/
|
|
111
|
+
set nearClip(value: number) {
|
|
112
|
+
this._nearClip = value;
|
|
113
|
+
if (this.component) {
|
|
114
|
+
this.component.nearClip = value;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Gets the near clip distance of the camera.
|
|
120
|
+
* @returns The near clip distance.
|
|
121
|
+
*/
|
|
122
|
+
get nearClip(): number {
|
|
123
|
+
return this._nearClip;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Sets the orthographic projection of the camera.
|
|
128
|
+
* @param value - The orthographic projection.
|
|
129
|
+
*/
|
|
130
|
+
set orthographic(value) {
|
|
131
|
+
this._orthographic = value;
|
|
132
|
+
if (this.component) {
|
|
133
|
+
this.component.projection = value ? PROJECTION_ORTHOGRAPHIC : PROJECTION_PERSPECTIVE;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Gets the orthographic projection of the camera.
|
|
139
|
+
* @returns The orthographic projection.
|
|
140
|
+
*/
|
|
141
|
+
get orthographic(): boolean {
|
|
142
|
+
return this._orthographic;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Sets the orthographic height of the camera.
|
|
147
|
+
* @param value - The orthographic height.
|
|
148
|
+
*/
|
|
149
|
+
set orthoHeight(value: number) {
|
|
150
|
+
this._orthoHeight = value;
|
|
151
|
+
if (this.component) {
|
|
152
|
+
this.component.orthoHeight = value;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Gets the orthographic height of the camera.
|
|
158
|
+
* @returns The orthographic height.
|
|
159
|
+
*/
|
|
160
|
+
get orthoHeight() {
|
|
161
|
+
return this._orthoHeight;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
static get observedAttributes() {
|
|
165
|
+
return [...super.observedAttributes, 'clear-color', 'near-clip', 'far-clip', 'fov', 'orthographic', 'ortho-height'];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
|
|
169
|
+
super.attributeChangedCallback(name, _oldValue, newValue);
|
|
170
|
+
|
|
171
|
+
switch (name) {
|
|
172
|
+
case 'clear-color':
|
|
173
|
+
this.clearColor = parseColor(newValue);
|
|
174
|
+
break;
|
|
175
|
+
case 'far-clip':
|
|
176
|
+
this.farClip = parseFloat(newValue);
|
|
177
|
+
break;
|
|
178
|
+
case 'fov':
|
|
179
|
+
this.fov = parseFloat(newValue);
|
|
180
|
+
break;
|
|
181
|
+
case 'near-clip':
|
|
182
|
+
this.nearClip = parseFloat(newValue);
|
|
183
|
+
break;
|
|
184
|
+
case 'orthographic':
|
|
185
|
+
this.orthographic = this.hasAttribute('orthographic');
|
|
186
|
+
break;
|
|
187
|
+
case 'ortho-height':
|
|
188
|
+
this.orthoHeight = parseFloat(newValue);
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
customElements.define('pc-camera', CameraComponentElement);
|
|
195
|
+
|
|
196
|
+
export { CameraComponentElement };
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { CollisionComponent, Vec3 } from 'playcanvas';
|
|
2
|
+
|
|
3
|
+
import { ComponentElement } from './component';
|
|
4
|
+
import { parseVec3 } from '../utils';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Represents a collision component in the PlayCanvas engine.
|
|
8
|
+
*
|
|
9
|
+
* @category Components
|
|
10
|
+
*/
|
|
11
|
+
class CollisionComponentElement extends ComponentElement {
|
|
12
|
+
private _axis: number = 1;
|
|
13
|
+
|
|
14
|
+
private _convexHull: boolean = false;
|
|
15
|
+
|
|
16
|
+
private _halfExtents: Vec3 = new Vec3(0.5, 0.5, 0.5);
|
|
17
|
+
|
|
18
|
+
private _height: number = 2;
|
|
19
|
+
|
|
20
|
+
private _radius: number = 0.5;
|
|
21
|
+
|
|
22
|
+
private _type: string = 'box';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Creates a new CollisionComponentElement.
|
|
26
|
+
*/
|
|
27
|
+
constructor() {
|
|
28
|
+
super('collision');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
getInitialComponentData() {
|
|
32
|
+
return {
|
|
33
|
+
axis: this._axis,
|
|
34
|
+
convexHull: this._convexHull,
|
|
35
|
+
halfExtents: this._halfExtents,
|
|
36
|
+
height: this._height,
|
|
37
|
+
radius: this._radius,
|
|
38
|
+
type: this._type
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Gets the collision component.
|
|
44
|
+
* @returns The collision component.
|
|
45
|
+
*/
|
|
46
|
+
get component(): CollisionComponent | null {
|
|
47
|
+
return super.component as CollisionComponent | null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
set axis(value: number) {
|
|
51
|
+
this._axis = value;
|
|
52
|
+
if (this.component) {
|
|
53
|
+
this.component.axis = value;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
get axis() {
|
|
58
|
+
return this._axis;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
set convexHull(value: boolean) {
|
|
62
|
+
this._convexHull = value;
|
|
63
|
+
if (this.component) {
|
|
64
|
+
this.component.convexHull = value;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
get convexHull() {
|
|
69
|
+
return this._convexHull;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
set halfExtents(value: Vec3) {
|
|
73
|
+
this._halfExtents = value;
|
|
74
|
+
if (this.component) {
|
|
75
|
+
this.component.halfExtents = value;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
get halfExtents() {
|
|
80
|
+
return this._halfExtents;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
set height(value: number) {
|
|
84
|
+
this._height = value;
|
|
85
|
+
if (this.component) {
|
|
86
|
+
this.component.height = value;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
get height() {
|
|
91
|
+
return this._height;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
set radius(value: number) {
|
|
95
|
+
this._radius = value;
|
|
96
|
+
if (this.component) {
|
|
97
|
+
this.component.radius = value;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
get radius() {
|
|
102
|
+
return this._radius;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
set type(value: string) {
|
|
106
|
+
this._type = value;
|
|
107
|
+
if (this.component) {
|
|
108
|
+
this.component.type = value;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
get type() {
|
|
113
|
+
return this._type;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
static get observedAttributes() {
|
|
117
|
+
return [...super.observedAttributes, 'axis', 'convex-hull', 'half-extents', 'height', 'radius', 'type'];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
|
|
121
|
+
super.attributeChangedCallback(name, _oldValue, newValue);
|
|
122
|
+
|
|
123
|
+
switch (name) {
|
|
124
|
+
case 'axis':
|
|
125
|
+
this.axis = parseInt(newValue, 10);
|
|
126
|
+
break;
|
|
127
|
+
case 'convex-hull':
|
|
128
|
+
this.convexHull = this.hasAttribute('convex-hull');
|
|
129
|
+
break;
|
|
130
|
+
case 'half-extents':
|
|
131
|
+
this.halfExtents = parseVec3(newValue);
|
|
132
|
+
break;
|
|
133
|
+
case 'height':
|
|
134
|
+
this.height = parseFloat(newValue);
|
|
135
|
+
break;
|
|
136
|
+
case 'radius':
|
|
137
|
+
this.radius = parseFloat(newValue);
|
|
138
|
+
break;
|
|
139
|
+
case 'type':
|
|
140
|
+
this.type = newValue;
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
customElements.define('pc-collision', CollisionComponentElement);
|
|
147
|
+
|
|
148
|
+
export { CollisionComponentElement };
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { Component } from 'playcanvas';
|
|
2
|
+
|
|
3
|
+
import { AppElement } from '../app';
|
|
4
|
+
import { EntityElement } from '../entity';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Represents a component in the PlayCanvas engine.
|
|
8
|
+
*
|
|
9
|
+
* @category Components
|
|
10
|
+
*/
|
|
11
|
+
class ComponentElement extends HTMLElement {
|
|
12
|
+
private _componentName: string;
|
|
13
|
+
|
|
14
|
+
private _enabled = true;
|
|
15
|
+
|
|
16
|
+
private _component: Component | null = null;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Constructor for the ComponentElement.
|
|
20
|
+
* @param componentName - The name of the component.
|
|
21
|
+
*/
|
|
22
|
+
constructor(componentName: string) {
|
|
23
|
+
super();
|
|
24
|
+
|
|
25
|
+
this._componentName = componentName;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Method to be overridden by subclasses to provide initial component data
|
|
29
|
+
getInitialComponentData() {
|
|
30
|
+
return {};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async connectedCallback() {
|
|
34
|
+
const appElement = this.closest('pc-app') as AppElement | null;
|
|
35
|
+
if (!appElement) {
|
|
36
|
+
console.error(`${this.tagName.toLowerCase()} should be a descendant of pc-app`);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
await appElement.getApplication();
|
|
41
|
+
|
|
42
|
+
this.addComponent();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
addComponent() {
|
|
46
|
+
// Access the parent pc-entity's 'entity' property
|
|
47
|
+
const entityElement = this.closest('pc-entity') as EntityElement | null;
|
|
48
|
+
if (!entityElement) {
|
|
49
|
+
console.error(`${this.tagName.toLowerCase()} should be a child of pc-entity`);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (entityElement && entityElement.entity) {
|
|
54
|
+
// Add the component to the entity
|
|
55
|
+
this._component = entityElement.entity.addComponent(
|
|
56
|
+
this._componentName,
|
|
57
|
+
this.getInitialComponentData()
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
disconnectedCallback() {
|
|
63
|
+
// Remove the component when the element is disconnected
|
|
64
|
+
if (this.component && this.component.entity) {
|
|
65
|
+
this._component!.entity.removeComponent(this._componentName);
|
|
66
|
+
this._component = null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
get component(): Component | null {
|
|
71
|
+
return this._component;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Sets the enabled state of the component.
|
|
76
|
+
* @param value - The enabled state of the component.
|
|
77
|
+
*/
|
|
78
|
+
set enabled(value: boolean) {
|
|
79
|
+
this._enabled = value;
|
|
80
|
+
if (this.component) {
|
|
81
|
+
this.component.enabled = value;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Gets the enabled state of the component.
|
|
87
|
+
* @returns The enabled state of the component.
|
|
88
|
+
*/
|
|
89
|
+
get enabled() {
|
|
90
|
+
return this._enabled;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
static get observedAttributes() {
|
|
94
|
+
return ['enabled'];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
|
|
98
|
+
switch (name) {
|
|
99
|
+
case 'enabled':
|
|
100
|
+
this.enabled = newValue !== 'false';
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export { ComponentElement };
|