@playcanvas/web-components 0.8.2 → 0.10.0
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 +18 -0
- package/dist/app.d.ts +13 -4
- package/dist/asset.d.ts +33 -3
- package/dist/async-element.d.ts +54 -4
- package/dist/components/button-component.d.ts +11 -5
- package/dist/components/camera-component.d.ts +10 -5
- package/dist/components/collision-component.d.ts +10 -5
- package/dist/components/component.d.ts +8 -2
- package/dist/components/element-component.d.ts +18 -13
- package/dist/components/gsplat-component.d.ts +7 -2
- package/dist/components/layoutchild-component.d.ts +7 -2
- package/dist/components/layoutgroup-component.d.ts +22 -16
- package/dist/components/light-component.d.ts +13 -7
- package/dist/components/listener-component.d.ts +6 -1
- package/dist/components/particlesystem-component.d.ts +7 -2
- package/dist/components/render-component.d.ts +14 -5
- package/dist/components/rigidbody-component.d.ts +10 -5
- package/dist/components/screen-component.d.ts +7 -2
- package/dist/components/script-component.d.ts +116 -16
- package/dist/components/script.d.ts +79 -8
- package/dist/components/scrollbar-component.d.ts +11 -5
- package/dist/components/scrollview-component.d.ts +18 -11
- package/dist/components/sound-component.d.ts +7 -2
- package/dist/components/sound-slot.d.ts +17 -4
- package/dist/custom-elements.json +16231 -0
- package/dist/entity.d.ts +45 -3
- package/dist/index.d.ts +3 -2
- package/dist/material.d.ts +976 -4
- package/dist/model.d.ts +6 -1
- package/dist/module.d.ts +15 -0
- package/dist/parse.d.ts +144 -0
- package/dist/pwc.cjs +5735 -2923
- package/dist/pwc.cjs.map +1 -1
- package/dist/pwc.js +5735 -2923
- 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.min.mjs +2 -0
- package/dist/pwc.min.mjs.map +1 -0
- package/dist/pwc.mjs +5736 -2925
- package/dist/pwc.mjs.map +1 -1
- package/dist/scene.d.ts +15 -6
- package/dist/sky.d.ts +7 -1
- package/dist/vscode.html-custom-data.json +1795 -0
- package/dist/web-types.json +3592 -0
- package/package.json +32 -14
- package/src/app.ts +42 -15
- package/src/asset.ts +78 -8
- package/src/async-element.ts +89 -5
- package/src/components/button-component.ts +31 -24
- package/src/components/camera-component.ts +30 -24
- package/src/components/collision-component.ts +20 -14
- package/src/components/component.ts +33 -14
- package/src/components/element-component.ts +62 -56
- package/src/components/gsplat-component.ts +16 -9
- package/src/components/layoutchild-component.ts +17 -10
- package/src/components/layoutgroup-component.ts +39 -32
- package/src/components/light-component.ts +34 -32
- package/src/components/listener-component.ts +8 -2
- package/src/components/particlesystem-component.ts +10 -4
- package/src/components/render-component.ts +28 -12
- package/src/components/rigidbody-component.ts +22 -16
- package/src/components/screen-component.ts +16 -10
- package/src/components/script-component.ts +512 -125
- package/src/components/script.ts +123 -16
- package/src/components/scrollbar-component.ts +21 -14
- package/src/components/scrollview-component.ts +42 -34
- package/src/components/sound-component.ts +17 -10
- package/src/components/sound-slot.ts +50 -19
- package/src/entity.ts +84 -76
- package/src/index.ts +5 -2
- package/src/material.ts +2432 -62
- package/src/model.ts +8 -2
- package/src/module.ts +16 -0
- package/src/parse.ts +298 -0
- package/src/scene.ts +26 -13
- package/src/sky.ts +36 -18
- package/dist/utils.d.ts +0 -56
- package/src/utils.ts +0 -119
package/src/model.ts
CHANGED
|
@@ -97,10 +97,10 @@ class ModelElement extends AsyncElement {
|
|
|
97
97
|
return ['asset'];
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
|
|
100
|
+
attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null) {
|
|
101
101
|
switch (name) {
|
|
102
102
|
case 'asset':
|
|
103
|
-
this.asset = newValue;
|
|
103
|
+
this.asset = newValue ?? '';
|
|
104
104
|
break;
|
|
105
105
|
}
|
|
106
106
|
}
|
|
@@ -108,4 +108,10 @@ class ModelElement extends AsyncElement {
|
|
|
108
108
|
|
|
109
109
|
customElements.define('pc-model', ModelElement);
|
|
110
110
|
|
|
111
|
+
declare global {
|
|
112
|
+
interface HTMLElementTagNameMap {
|
|
113
|
+
'pc-model': ModelElement;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
111
117
|
export { ModelElement };
|
package/src/module.ts
CHANGED
|
@@ -5,6 +5,16 @@ import { basisInitialize, WasmModule } from 'playcanvas';
|
|
|
5
5
|
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-module/ | `<pc-module>`} elements.
|
|
6
6
|
* The ModuleElement interface also inherits the properties and methods of the
|
|
7
7
|
* {@link HTMLElement} interface.
|
|
8
|
+
*
|
|
9
|
+
* Note that these attributes are read once when the element is created, so changing them later
|
|
10
|
+
* has no effect.
|
|
11
|
+
*
|
|
12
|
+
* @attribute {string} name - The name of the WebAssembly module to configure, e.g. `Basis` or
|
|
13
|
+
* `Ammo`.
|
|
14
|
+
* @attribute {string} glue - The URL of the module's glue script.
|
|
15
|
+
* @attribute {string} wasm - The URL of the module's WebAssembly binary.
|
|
16
|
+
* @attribute {string} fallback - The URL of the module's asm.js fallback script, used when
|
|
17
|
+
* WebAssembly is unavailable.
|
|
8
18
|
*/
|
|
9
19
|
class ModuleElement extends HTMLElement {
|
|
10
20
|
private loadPromise: Promise<void>;
|
|
@@ -40,4 +50,10 @@ class ModuleElement extends HTMLElement {
|
|
|
40
50
|
|
|
41
51
|
customElements.define('pc-module', ModuleElement);
|
|
42
52
|
|
|
53
|
+
declare global {
|
|
54
|
+
interface HTMLElementTagNameMap {
|
|
55
|
+
'pc-module': ModuleElement;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
43
59
|
export { ModuleElement };
|
package/src/parse.ts
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts HTML attribute values into the values the engine expects. Every element's
|
|
3
|
+
* `attributeChangedCallback` funnels through this module.
|
|
4
|
+
*
|
|
5
|
+
* The parsers share one contract:
|
|
6
|
+
*
|
|
7
|
+
* - A `null` value means the attribute is absent or was removed, and yields the supplied default.
|
|
8
|
+
* - A malformed value yields the same default and logs exactly one `console.warn` naming the
|
|
9
|
+
* attribute, so misuse is reported rather than thrown — nothing here throws or rejects.
|
|
10
|
+
* - A math-type default is cloned on the way out, which is what makes it safe to pass the engine's
|
|
11
|
+
* shared frozen constants (`Vec3.ZERO`, `Color.WHITE`) as defaults.
|
|
12
|
+
* - `parseBool` and `parseTags` take no attribute name, because every value is valid for them and
|
|
13
|
+
* so they never warn.
|
|
14
|
+
*
|
|
15
|
+
* `getEntity` is the exception: it resolves a reference to a live entity rather than parsing a
|
|
16
|
+
* literal, and returns `null` instead of falling back to a default.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { Color, Entity, Quat, Vec2, Vec3, Vec4 } from 'playcanvas';
|
|
20
|
+
|
|
21
|
+
import { CSS_COLORS } from './colors';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Splits an attribute value into exactly `count` numeric components. Returns `null` when the
|
|
25
|
+
* value does not consist of exactly `count` whitespace-separated finite numbers.
|
|
26
|
+
*
|
|
27
|
+
* @param value - The value to split.
|
|
28
|
+
* @param count - The required number of components.
|
|
29
|
+
* @returns The parsed components, or `null`.
|
|
30
|
+
* @ignore
|
|
31
|
+
*/
|
|
32
|
+
export const parseComponents = (value: string, count: number): number[] | null => {
|
|
33
|
+
const components = value.trim().split(/\s+/).map(Number);
|
|
34
|
+
if (components.length !== count || components.some(component => !Number.isFinite(component))) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
return components;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Clones a math-type default so parsed results never alias the caller's default instance. This
|
|
42
|
+
* is what makes it safe to pass the engine's shared frozen constants (e.g. `Vec3.ZERO`,
|
|
43
|
+
* `Color.WHITE`) as defaults.
|
|
44
|
+
*
|
|
45
|
+
* @param value - The default value to clone (`null` is passed through).
|
|
46
|
+
* @returns The cloned value.
|
|
47
|
+
*/
|
|
48
|
+
const cloneDefault = <T extends Color | Quat | Vec2 | Vec3 | Vec4 | null>(value: T): T => {
|
|
49
|
+
return (value === null ? null : value.clone()) as T;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Parse a boolean attribute value. The same rules apply to every boolean attribute:
|
|
54
|
+
*
|
|
55
|
+
* - Attribute absent (or removed): the supplied default is used.
|
|
56
|
+
* - Attribute set to the string 'false': `false`.
|
|
57
|
+
* - Attribute present with any other value, including the empty string of a bare boolean
|
|
58
|
+
* attribute (e.g. `<pc-light cast-shadows>`): `true`.
|
|
59
|
+
*
|
|
60
|
+
* @param value - The attribute value to parse (`null` when the attribute is absent).
|
|
61
|
+
* @param defaultValue - The value to use when the attribute is absent or removed.
|
|
62
|
+
* @returns The parsed boolean.
|
|
63
|
+
*/
|
|
64
|
+
export const parseBool = (value: string | null, defaultValue: boolean): boolean => {
|
|
65
|
+
return value === null ? defaultValue : value !== 'false';
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Parse a color attribute value. The expected format is a CSS color name (e.g. 'rebeccapurple'),
|
|
70
|
+
* a hex color (e.g. '#ff0000' or '#f00'), or 3 or 4 space-separated numbers in the range 0 to 1
|
|
71
|
+
* (e.g. '1 0.5 0.5' or '1 0.5 0.5 0.5'). Returns `defaultValue` (cloned, when it is a color)
|
|
72
|
+
* when the attribute is absent (`null`), or when the value is malformed — the latter also logs
|
|
73
|
+
* a warning.
|
|
74
|
+
*
|
|
75
|
+
* @param value - The attribute value to parse (`null` when the attribute is absent).
|
|
76
|
+
* @param defaultValue - The value to use when the attribute is absent or invalid.
|
|
77
|
+
* @param attribute - The attribute name, used in the warning message.
|
|
78
|
+
* @returns The parsed Color object.
|
|
79
|
+
*/
|
|
80
|
+
export const parseColor = <T extends Color | null>(value: string | null, defaultValue: T, attribute: string): Color | T => {
|
|
81
|
+
if (value === null) {
|
|
82
|
+
return cloneDefault(defaultValue);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// A CSS color name (e.g. 'rebeccapurple')
|
|
86
|
+
const hexColor = CSS_COLORS[value.toLowerCase()];
|
|
87
|
+
if (hexColor) {
|
|
88
|
+
return new Color().fromString(hexColor);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// A hex color (e.g. '#ff0000'), expanding short forms (e.g. '#f00') for Color.fromString
|
|
92
|
+
if (/^#(?:[0-9a-f]{3}|[0-9a-f]{4}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(value)) {
|
|
93
|
+
let hex = value.slice(1);
|
|
94
|
+
if (hex.length === 3 || hex.length === 4) {
|
|
95
|
+
hex = hex.split('').map(char => char + char).join('');
|
|
96
|
+
}
|
|
97
|
+
return new Color().fromString(`#${hex}`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// 3 or 4 space-separated components (e.g. '1 0.5 0.5')
|
|
101
|
+
const components = parseComponents(value, 4) ?? parseComponents(value, 3);
|
|
102
|
+
if (components) {
|
|
103
|
+
return new Color(components);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
console.warn(`Invalid value '${value}' for attribute '${attribute}'. Expected a CSS color name, a hex color or 3 or 4 space-separated numbers. Using '${defaultValue}'.`);
|
|
107
|
+
return cloneDefault(defaultValue);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Resolves an enum attribute value against its set of valid names. Returns the value when it is
|
|
112
|
+
* one of the valid names. Returns `defaultValue` when the attribute is absent (`null`), or when
|
|
113
|
+
* the value is invalid — the latter also logs a warning listing the valid names.
|
|
114
|
+
*
|
|
115
|
+
* @param value - The attribute value to parse (`null` when the attribute is absent).
|
|
116
|
+
* @param valid - The valid names: an array, or a map whose keys are the valid names.
|
|
117
|
+
* @param defaultValue - The value to use when the attribute is absent or invalid.
|
|
118
|
+
* @param attribute - The attribute name, used in the warning message.
|
|
119
|
+
* @returns The resolved enum name.
|
|
120
|
+
*/
|
|
121
|
+
export const parseEnum = <T extends string>(
|
|
122
|
+
value: string | null,
|
|
123
|
+
valid: readonly T[] | ReadonlyMap<T, number>,
|
|
124
|
+
defaultValue: T,
|
|
125
|
+
attribute: string
|
|
126
|
+
): T => {
|
|
127
|
+
if (value === null) {
|
|
128
|
+
return defaultValue;
|
|
129
|
+
}
|
|
130
|
+
const names = Array.isArray(valid) ? valid : [...(valid as ReadonlyMap<T, number>).keys()];
|
|
131
|
+
if (names.includes(value as T)) {
|
|
132
|
+
return value as T;
|
|
133
|
+
}
|
|
134
|
+
console.warn(`Invalid value '${value}' for attribute '${attribute}'. Valid values: ${names.join(', ')}. Using '${defaultValue}'.`);
|
|
135
|
+
return defaultValue;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Parses a number attribute value. Returns the parsed number when the value is a finite number.
|
|
140
|
+
* Returns `defaultValue` when the attribute is absent (`null`), or when the value is not a
|
|
141
|
+
* finite number — the latter also logs a warning.
|
|
142
|
+
*
|
|
143
|
+
* @param value - The attribute value to parse (`null` when the attribute is absent).
|
|
144
|
+
* @param defaultValue - The value to use when the attribute is absent or invalid.
|
|
145
|
+
* @param attribute - The attribute name, used in the warning message.
|
|
146
|
+
* @returns The parsed number.
|
|
147
|
+
*/
|
|
148
|
+
export const parseNumber = <T extends number | null>(value: string | null, defaultValue: T, attribute: string): number | T => {
|
|
149
|
+
if (value === null) {
|
|
150
|
+
return defaultValue;
|
|
151
|
+
}
|
|
152
|
+
const number = value.trim() === '' ? NaN : Number(value);
|
|
153
|
+
if (!Number.isFinite(number)) {
|
|
154
|
+
console.warn(`Invalid value '${value}' for attribute '${attribute}'. Expected a finite number. Using '${defaultValue}'.`);
|
|
155
|
+
return defaultValue;
|
|
156
|
+
}
|
|
157
|
+
return number;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Parse an Euler-angles attribute value into a quaternion. The expected format is 3
|
|
162
|
+
* space-separated angles in degrees (e.g. '0 90 0'). Returns `defaultValue` (cloned, when it is
|
|
163
|
+
* a quaternion) when the attribute is absent (`null`), or when the value is malformed — the
|
|
164
|
+
* latter also logs a warning.
|
|
165
|
+
*
|
|
166
|
+
* @param value - The attribute value to parse (`null` when the attribute is absent).
|
|
167
|
+
* @param defaultValue - The value to use when the attribute is absent or invalid.
|
|
168
|
+
* @param attribute - The attribute name, used in the warning message.
|
|
169
|
+
* @returns The parsed Quat object.
|
|
170
|
+
*/
|
|
171
|
+
export const parseQuat = <T extends Quat | null>(value: string | null, defaultValue: T, attribute: string): Quat | T => {
|
|
172
|
+
if (value === null) {
|
|
173
|
+
return cloneDefault(defaultValue);
|
|
174
|
+
}
|
|
175
|
+
const components = parseComponents(value, 3);
|
|
176
|
+
if (!components) {
|
|
177
|
+
console.warn(`Invalid value '${value}' for attribute '${attribute}'. Expected 3 space-separated numbers. Using '${defaultValue}'.`);
|
|
178
|
+
return cloneDefault(defaultValue);
|
|
179
|
+
}
|
|
180
|
+
return new Quat().setFromEulerAngles(components[0], components[1], components[2]);
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Parse a tags attribute value. The expected format is a comma-separated list of tag names
|
|
185
|
+
* (e.g. 'enemy, flying'). Surrounding whitespace is trimmed from each name and empty names are
|
|
186
|
+
* discarded, so a trailing comma or a doubled separator does not produce a blank tag. Returns a
|
|
187
|
+
* copy of `defaultValue` when the attribute is absent or removed (`null`).
|
|
188
|
+
*
|
|
189
|
+
* Every value is valid, so this never warns.
|
|
190
|
+
*
|
|
191
|
+
* @param value - The attribute value to parse (`null` when the attribute is absent).
|
|
192
|
+
* @param defaultValue - The value to use when the attribute is absent or removed.
|
|
193
|
+
* @returns The parsed tag names.
|
|
194
|
+
*/
|
|
195
|
+
export const parseTags = (value: string | null, defaultValue: string[] = []): string[] => {
|
|
196
|
+
if (value === null) {
|
|
197
|
+
// Copied for the same reason cloneDefault exists: a parsed result must never alias the
|
|
198
|
+
// caller's default, or a later mutation would write back through it.
|
|
199
|
+
return [...defaultValue];
|
|
200
|
+
}
|
|
201
|
+
return value.split(',').map(tag => tag.trim()).filter(tag => tag !== '');
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Parse a Vec2 attribute value. The expected format is 2 space-separated numbers (e.g. '1 2').
|
|
206
|
+
* Returns `defaultValue` (cloned, when it is a vector) when the attribute is absent (`null`),
|
|
207
|
+
* or when the value is malformed — the latter also logs a warning.
|
|
208
|
+
*
|
|
209
|
+
* @param value - The attribute value to parse (`null` when the attribute is absent).
|
|
210
|
+
* @param defaultValue - The value to use when the attribute is absent or invalid.
|
|
211
|
+
* @param attribute - The attribute name, used in the warning message.
|
|
212
|
+
* @returns The parsed Vec2 object.
|
|
213
|
+
*/
|
|
214
|
+
export const parseVec2 = <T extends Vec2 | null>(value: string | null, defaultValue: T, attribute: string): Vec2 | T => {
|
|
215
|
+
if (value === null) {
|
|
216
|
+
return cloneDefault(defaultValue);
|
|
217
|
+
}
|
|
218
|
+
const components = parseComponents(value, 2);
|
|
219
|
+
if (!components) {
|
|
220
|
+
console.warn(`Invalid value '${value}' for attribute '${attribute}'. Expected 2 space-separated numbers. Using '${defaultValue}'.`);
|
|
221
|
+
return cloneDefault(defaultValue);
|
|
222
|
+
}
|
|
223
|
+
return new Vec2(components);
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Parse a Vec3 attribute value. The expected format is 3 space-separated numbers (e.g. '1 2 3').
|
|
228
|
+
* Returns `defaultValue` (cloned, when it is a vector) when the attribute is absent (`null`),
|
|
229
|
+
* or when the value is malformed — the latter also logs a warning.
|
|
230
|
+
*
|
|
231
|
+
* @param value - The attribute value to parse (`null` when the attribute is absent).
|
|
232
|
+
* @param defaultValue - The value to use when the attribute is absent or invalid.
|
|
233
|
+
* @param attribute - The attribute name, used in the warning message.
|
|
234
|
+
* @returns The parsed Vec3 object.
|
|
235
|
+
*/
|
|
236
|
+
export const parseVec3 = <T extends Vec3 | null>(value: string | null, defaultValue: T, attribute: string): Vec3 | T => {
|
|
237
|
+
if (value === null) {
|
|
238
|
+
return cloneDefault(defaultValue);
|
|
239
|
+
}
|
|
240
|
+
const components = parseComponents(value, 3);
|
|
241
|
+
if (!components) {
|
|
242
|
+
console.warn(`Invalid value '${value}' for attribute '${attribute}'. Expected 3 space-separated numbers. Using '${defaultValue}'.`);
|
|
243
|
+
return cloneDefault(defaultValue);
|
|
244
|
+
}
|
|
245
|
+
return new Vec3(components);
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Parse a Vec4 attribute value. The expected format is 4 space-separated numbers
|
|
250
|
+
* (e.g. '1 2 3 4'). Returns `defaultValue` (cloned, when it is a vector) when the attribute is
|
|
251
|
+
* absent (`null`), or when the value is malformed — the latter also logs a warning.
|
|
252
|
+
*
|
|
253
|
+
* @param value - The attribute value to parse (`null` when the attribute is absent).
|
|
254
|
+
* @param defaultValue - The value to use when the attribute is absent or invalid.
|
|
255
|
+
* @param attribute - The attribute name, used in the warning message.
|
|
256
|
+
* @returns The parsed Vec4 object.
|
|
257
|
+
*/
|
|
258
|
+
export const parseVec4 = <T extends Vec4 | null>(value: string | null, defaultValue: T, attribute: string): Vec4 | T => {
|
|
259
|
+
if (value === null) {
|
|
260
|
+
return cloneDefault(defaultValue);
|
|
261
|
+
}
|
|
262
|
+
const components = parseComponents(value, 4);
|
|
263
|
+
if (!components) {
|
|
264
|
+
console.warn(`Invalid value '${value}' for attribute '${attribute}'. Expected 4 space-separated numbers. Using '${defaultValue}'.`);
|
|
265
|
+
return cloneDefault(defaultValue);
|
|
266
|
+
}
|
|
267
|
+
return new Vec4(components);
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Resolves a reference string to the {@link Entity} backing a `<pc-entity>` element. The reference
|
|
272
|
+
* can be a CSS selector (e.g. `#my-id`, `pc-entity[name="Foo"]`), a bare element id, or a bare
|
|
273
|
+
* entity name. Returns `null` if no matching element (or backing entity) is found.
|
|
274
|
+
*
|
|
275
|
+
* @param ref - The reference string to resolve.
|
|
276
|
+
* @returns The resolved entity, or `null`.
|
|
277
|
+
*/
|
|
278
|
+
export const getEntity = (ref: string): Entity | null => {
|
|
279
|
+
if (!ref) {
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
let element: Element | null = null;
|
|
284
|
+
|
|
285
|
+
// Try the reference as a CSS selector. An invalid selector (e.g. a bare name containing
|
|
286
|
+
// spaces) throws, in which case we fall back to id/name lookups below.
|
|
287
|
+
try {
|
|
288
|
+
element = document.querySelector(ref);
|
|
289
|
+
} catch {
|
|
290
|
+
element = null;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (!element) {
|
|
294
|
+
element = document.getElementById(ref) ?? document.querySelector(`pc-entity[name="${ref}"]`);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return (element as { entity?: Entity } | null)?.entity ?? null;
|
|
298
|
+
};
|
package/src/scene.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Color, Scene, Vec3 } from 'playcanvas';
|
|
|
2
2
|
|
|
3
3
|
import { AppElement } from './app';
|
|
4
4
|
import { AsyncElement } from './async-element';
|
|
5
|
-
import { parseColor, parseVec3 } from './
|
|
5
|
+
import { parseColor, parseEnum, parseNumber, parseVec3 } from './parse';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* The SceneElement interface provides properties and methods for manipulating
|
|
@@ -14,7 +14,7 @@ class SceneElement extends AsyncElement {
|
|
|
14
14
|
/**
|
|
15
15
|
* The fog type of the scene.
|
|
16
16
|
*/
|
|
17
|
-
private _fog
|
|
17
|
+
private _fog: 'none' | 'linear' | 'exp' | 'exp2' = 'none';
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* The color of the fog.
|
|
@@ -41,15 +41,21 @@ class SceneElement extends AsyncElement {
|
|
|
41
41
|
*/
|
|
42
42
|
private _gravity = new Vec3(0, -9.81, 0);
|
|
43
43
|
|
|
44
|
+
private _scene: Scene | null = null;
|
|
45
|
+
|
|
44
46
|
/**
|
|
45
|
-
* The PlayCanvas scene instance.
|
|
47
|
+
* The PlayCanvas scene instance. Available once the element is ready — await
|
|
48
|
+
* {@link whenReady} or the element's `ready()` promise before accessing it.
|
|
49
|
+
* @returns The scene instance.
|
|
46
50
|
*/
|
|
47
|
-
scene: Scene
|
|
51
|
+
get scene(): Scene {
|
|
52
|
+
return this._scene!;
|
|
53
|
+
}
|
|
48
54
|
|
|
49
55
|
async connectedCallback() {
|
|
50
56
|
await this.closestApp?.ready();
|
|
51
57
|
|
|
52
|
-
this.
|
|
58
|
+
this._scene = this.closestApp!.app!.scene;
|
|
53
59
|
this.updateSceneSettings();
|
|
54
60
|
|
|
55
61
|
this._onReady();
|
|
@@ -69,7 +75,8 @@ class SceneElement extends AsyncElement {
|
|
|
69
75
|
}
|
|
70
76
|
|
|
71
77
|
/**
|
|
72
|
-
* Sets the fog type of the scene.
|
|
78
|
+
* Sets the fog type of the scene. Can be `none`, `linear`, `exp` or `exp2`. Defaults to
|
|
79
|
+
* `none`.
|
|
73
80
|
* @param value - The fog type.
|
|
74
81
|
*/
|
|
75
82
|
set fog(value) {
|
|
@@ -187,25 +194,25 @@ class SceneElement extends AsyncElement {
|
|
|
187
194
|
return ['fog', 'fog-color', 'fog-density', 'fog-start', 'fog-end', 'gravity'];
|
|
188
195
|
}
|
|
189
196
|
|
|
190
|
-
attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
|
|
197
|
+
attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null) {
|
|
191
198
|
switch (name) {
|
|
192
199
|
case 'fog':
|
|
193
|
-
this.fog = newValue;
|
|
200
|
+
this.fog = parseEnum(newValue, ['none', 'linear', 'exp', 'exp2'], 'none', name);
|
|
194
201
|
break;
|
|
195
202
|
case 'fog-color':
|
|
196
|
-
this.fogColor = parseColor(newValue);
|
|
203
|
+
this.fogColor = parseColor(newValue, Color.WHITE, name);
|
|
197
204
|
break;
|
|
198
205
|
case 'fog-density':
|
|
199
|
-
this.fogDensity =
|
|
206
|
+
this.fogDensity = parseNumber(newValue, 0, name);
|
|
200
207
|
break;
|
|
201
208
|
case 'fog-start':
|
|
202
|
-
this.fogStart =
|
|
209
|
+
this.fogStart = parseNumber(newValue, 0, name);
|
|
203
210
|
break;
|
|
204
211
|
case 'fog-end':
|
|
205
|
-
this.fogEnd =
|
|
212
|
+
this.fogEnd = parseNumber(newValue, 1000, name);
|
|
206
213
|
break;
|
|
207
214
|
case 'gravity':
|
|
208
|
-
this.gravity = parseVec3(newValue);
|
|
215
|
+
this.gravity = parseVec3(newValue, new Vec3(0, -9.81, 0), name);
|
|
209
216
|
break;
|
|
210
217
|
// ... handle other attributes as well
|
|
211
218
|
}
|
|
@@ -214,4 +221,10 @@ class SceneElement extends AsyncElement {
|
|
|
214
221
|
|
|
215
222
|
customElements.define('pc-scene', SceneElement);
|
|
216
223
|
|
|
224
|
+
declare global {
|
|
225
|
+
interface HTMLElementTagNameMap {
|
|
226
|
+
'pc-scene': SceneElement;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
217
230
|
export { SceneElement };
|
package/src/sky.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Asset, EnvLighting, LAYERID_SKYBOX, Quat, Scene, Texture, Vec3 } from 'playcanvas';
|
|
2
2
|
|
|
3
|
+
import { AppElement } from './app';
|
|
3
4
|
import { AssetElement } from './asset';
|
|
4
5
|
import { AsyncElement } from './async-element';
|
|
5
|
-
import { parseVec3 } from './
|
|
6
|
+
import { parseBool, parseEnum, parseNumber, parseVec3 } from './parse';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* The SkyElement interface provides properties and methods for manipulating
|
|
@@ -28,6 +29,8 @@ class SkyElement extends AsyncElement {
|
|
|
28
29
|
|
|
29
30
|
private _scene: Scene | null = null;
|
|
30
31
|
|
|
32
|
+
private _appElement: AppElement | null = null;
|
|
33
|
+
|
|
31
34
|
connectedCallback() {
|
|
32
35
|
this._loadSkybox();
|
|
33
36
|
this._onReady();
|
|
@@ -35,6 +38,7 @@ class SkyElement extends AsyncElement {
|
|
|
35
38
|
|
|
36
39
|
disconnectedCallback() {
|
|
37
40
|
this._unloadSkybox();
|
|
41
|
+
this._appElement = null;
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
private _generateSkybox(asset: Asset) {
|
|
@@ -67,10 +71,12 @@ class SkyElement extends AsyncElement {
|
|
|
67
71
|
private async _loadSkybox() {
|
|
68
72
|
const appElement = await this.closestApp?.ready();
|
|
69
73
|
const app = appElement?.app;
|
|
70
|
-
if (!app) {
|
|
74
|
+
if (!appElement || !app) {
|
|
71
75
|
return;
|
|
72
76
|
}
|
|
73
77
|
|
|
78
|
+
this._appElement = appElement;
|
|
79
|
+
|
|
74
80
|
const asset = AssetElement.get(this._asset);
|
|
75
81
|
if (!asset) {
|
|
76
82
|
return;
|
|
@@ -89,16 +95,22 @@ class SkyElement extends AsyncElement {
|
|
|
89
95
|
}
|
|
90
96
|
|
|
91
97
|
private _unloadSkybox() {
|
|
92
|
-
|
|
98
|
+
const scene = this._scene;
|
|
99
|
+
if (!scene) return;
|
|
100
|
+
|
|
101
|
+
this._scene = null;
|
|
102
|
+
|
|
103
|
+
// If the owning application has already been destroyed (removing a <pc-app>
|
|
104
|
+
// disconnects it before its children), the scene, graphics device and skybox
|
|
105
|
+
// textures have all been destroyed along with it — nothing left to clean up.
|
|
106
|
+
if (!this._appElement?.app) return;
|
|
93
107
|
|
|
94
|
-
|
|
108
|
+
scene.skybox?.destroy();
|
|
95
109
|
// @ts-ignore
|
|
96
|
-
|
|
97
|
-
|
|
110
|
+
scene.skybox = null;
|
|
111
|
+
scene.envAtlas?.destroy();
|
|
98
112
|
// @ts-ignore
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
this._scene = null;
|
|
113
|
+
scene.envAtlas = null;
|
|
102
114
|
}
|
|
103
115
|
|
|
104
116
|
/**
|
|
@@ -258,31 +270,31 @@ class SkyElement extends AsyncElement {
|
|
|
258
270
|
return ['asset', 'center', 'intensity', 'level', 'lighting', 'rotation', 'scale', 'type'];
|
|
259
271
|
}
|
|
260
272
|
|
|
261
|
-
attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
|
|
273
|
+
attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null) {
|
|
262
274
|
switch (name) {
|
|
263
275
|
case 'asset':
|
|
264
|
-
this.asset = newValue;
|
|
276
|
+
this.asset = newValue ?? '';
|
|
265
277
|
break;
|
|
266
278
|
case 'center':
|
|
267
|
-
this.center = parseVec3(newValue);
|
|
279
|
+
this.center = parseVec3(newValue, new Vec3(0, 0.01, 0), name);
|
|
268
280
|
break;
|
|
269
281
|
case 'intensity':
|
|
270
|
-
this.intensity =
|
|
282
|
+
this.intensity = parseNumber(newValue, 1, name);
|
|
271
283
|
break;
|
|
272
284
|
case 'level':
|
|
273
|
-
this.level =
|
|
285
|
+
this.level = parseNumber(newValue, 0, name);
|
|
274
286
|
break;
|
|
275
287
|
case 'lighting':
|
|
276
|
-
this.lighting =
|
|
288
|
+
this.lighting = parseBool(newValue, false);
|
|
277
289
|
break;
|
|
278
290
|
case 'rotation':
|
|
279
|
-
this.rotation = parseVec3(newValue);
|
|
291
|
+
this.rotation = parseVec3(newValue, Vec3.ZERO, name);
|
|
280
292
|
break;
|
|
281
293
|
case 'scale':
|
|
282
|
-
this.scale = parseVec3(newValue);
|
|
294
|
+
this.scale = parseVec3(newValue, new Vec3(100, 100, 100), name);
|
|
283
295
|
break;
|
|
284
296
|
case 'type':
|
|
285
|
-
this.type = newValue
|
|
297
|
+
this.type = parseEnum(newValue, ['box', 'dome', 'infinite', 'none'], 'infinite', name);
|
|
286
298
|
break;
|
|
287
299
|
}
|
|
288
300
|
}
|
|
@@ -290,4 +302,10 @@ class SkyElement extends AsyncElement {
|
|
|
290
302
|
|
|
291
303
|
customElements.define('pc-sky', SkyElement);
|
|
292
304
|
|
|
305
|
+
declare global {
|
|
306
|
+
interface HTMLElementTagNameMap {
|
|
307
|
+
'pc-sky': SkyElement;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
293
311
|
export { SkyElement };
|
package/dist/utils.d.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { Color, Entity, Quat, Vec2, Vec3, Vec4 } from 'playcanvas';
|
|
2
|
-
/**
|
|
3
|
-
* Parse a color string into a Color object. String can be in the format of '#rgb', '#rgba',
|
|
4
|
-
* '#rrggbb', '#rrggbbaa', or a string of 3 or 4 comma-delimited numbers.
|
|
5
|
-
*
|
|
6
|
-
* @param value - The color string to parse.
|
|
7
|
-
* @returns The parsed Color object.
|
|
8
|
-
*/
|
|
9
|
-
export declare const parseColor: (value: string) => Color;
|
|
10
|
-
/**
|
|
11
|
-
* Parse an Euler angles string into a Quat object. String can be in the format of 'x,y,z'.
|
|
12
|
-
*
|
|
13
|
-
* @param value - The Euler angles string to parse.
|
|
14
|
-
* @returns The parsed Quat object.
|
|
15
|
-
*/
|
|
16
|
-
export declare const parseQuat: (value: string) => Quat;
|
|
17
|
-
/**
|
|
18
|
-
* Parse a Vec2 string into a Vec2 object. String can be in the format of 'x,y'.
|
|
19
|
-
*
|
|
20
|
-
* @param value - The Vec2 string to parse.
|
|
21
|
-
* @returns The parsed Vec2 object.
|
|
22
|
-
*/
|
|
23
|
-
export declare const parseVec2: (value: string) => Vec2;
|
|
24
|
-
/**
|
|
25
|
-
* Parse a Vec3 string into a Vec3 object. String can be in the format of 'x,y,z'.
|
|
26
|
-
*
|
|
27
|
-
* @param value - The Vec3 string to parse.
|
|
28
|
-
* @returns The parsed Vec3 object.
|
|
29
|
-
*/
|
|
30
|
-
export declare const parseVec3: (value: string) => Vec3;
|
|
31
|
-
/**
|
|
32
|
-
* Parse a Vec4 string into a Vec4 object. String can be in the format of 'x,y,z,w'.
|
|
33
|
-
*
|
|
34
|
-
* @param value - The Vec4 string to parse.
|
|
35
|
-
* @returns The parsed Vec4 object.
|
|
36
|
-
*/
|
|
37
|
-
export declare const parseVec4: (value: string) => Vec4;
|
|
38
|
-
/**
|
|
39
|
-
* Resolves an enum value supplied as either a named string (looked up in `map`) or a numeric
|
|
40
|
-
* string. Falls back to `defaultValue` when the value is neither a known name nor a finite number.
|
|
41
|
-
*
|
|
42
|
-
* @param value - The attribute value to parse.
|
|
43
|
-
* @param map - A map of named values to their numeric enum equivalents.
|
|
44
|
-
* @param defaultValue - The value to return when parsing fails.
|
|
45
|
-
* @returns The resolved numeric enum value.
|
|
46
|
-
*/
|
|
47
|
-
export declare const parseEnum: (value: string, map: Map<string, number>, defaultValue: number) => number;
|
|
48
|
-
/**
|
|
49
|
-
* Resolves a reference string to the {@link Entity} backing a `<pc-entity>` element. The reference
|
|
50
|
-
* can be a CSS selector (e.g. `#my-id`, `pc-entity[name="Foo"]`), a bare element id, or a bare
|
|
51
|
-
* entity name. Returns `null` if no matching element (or backing entity) is found.
|
|
52
|
-
*
|
|
53
|
-
* @param ref - The reference string to resolve.
|
|
54
|
-
* @returns The resolved entity, or `null`.
|
|
55
|
-
*/
|
|
56
|
-
export declare const getEntity: (ref: string) => Entity | null;
|