@playcanvas/web-components 0.1.12 → 0.2.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 +1 -1
- package/dist/asset.d.ts +7 -7
- package/dist/components/camera-component.d.ts +8 -0
- package/dist/components/script-component.d.ts +30 -0
- package/dist/pwc.cjs +140 -68
- package/dist/pwc.cjs.map +1 -1
- package/dist/pwc.js +140 -68
- 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 +141 -69
- package/dist/pwc.mjs.map +1 -1
- package/package.json +9 -8
- package/src/asset.ts +14 -14
- package/src/components/camera-component.ts +8 -0
- package/src/components/script-component.ts +126 -59
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://github.com/playcanvas/web-components/blob/main/LICENSE)
|
|
6
6
|
[](https://github.com/playcanvas/web-components/actions/workflows/deploy.yml)
|
|
7
7
|
|
|
8
|
-
| [User Guide](https://developer.playcanvas.com/user-manual/engine/web-components) | [API Reference](https://api.playcanvas.com/modules/EngineWebComponents.html) | [Examples](https://playcanvas.github.io/web-components/examples) | [Forum](https://forum.playcanvas.com/) | [Discord](https://discord.gg/RSaMRzg) |
|
|
8
|
+
| [User Guide](https://developer.playcanvas.com/user-manual/engine/web-components) | [API Reference](https://api.playcanvas.com/modules/EngineWebComponents.html) | [Examples](https://playcanvas.github.io/web-components/examples) | [Blog](https://blog.playcanvas.com/) | [Forum](https://forum.playcanvas.com/) | [Discord](https://discord.gg/RSaMRzg) |
|
|
9
9
|
|
|
10
10
|
PlayCanvas Web Components are a set of custom HTML elements for building 3D interactive web apps. Using the declarative nature of HTML makes it both easy and fun to incorporate 3D into your website. Check out this simple example:
|
|
11
11
|
|
package/dist/asset.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { Asset } from 'playcanvas';
|
|
|
6
6
|
* {@link HTMLElement} interface.
|
|
7
7
|
*/
|
|
8
8
|
declare class AssetElement extends HTMLElement {
|
|
9
|
-
private
|
|
9
|
+
private _lazy;
|
|
10
10
|
/**
|
|
11
11
|
* The asset that is loaded.
|
|
12
12
|
*/
|
|
@@ -15,15 +15,15 @@ declare class AssetElement extends HTMLElement {
|
|
|
15
15
|
createAsset(): void;
|
|
16
16
|
destroyAsset(): void;
|
|
17
17
|
/**
|
|
18
|
-
* Sets the
|
|
19
|
-
* @param value - The
|
|
18
|
+
* Sets whether the asset should be loaded lazily.
|
|
19
|
+
* @param value - The lazy loading flag.
|
|
20
20
|
*/
|
|
21
|
-
set
|
|
21
|
+
set lazy(value: boolean);
|
|
22
22
|
/**
|
|
23
|
-
* Gets the
|
|
24
|
-
* @returns The
|
|
23
|
+
* Gets whether the asset should be loaded lazily.
|
|
24
|
+
* @returns The lazy loading flag.
|
|
25
25
|
*/
|
|
26
|
-
get
|
|
26
|
+
get lazy(): boolean;
|
|
27
27
|
static get(id: string): Asset | null | undefined;
|
|
28
28
|
static get observedAttributes(): string[];
|
|
29
29
|
attributeChangedCallback(name: string, _oldValue: string, _newValue: string): void;
|
|
@@ -50,7 +50,15 @@ declare class CameraComponentElement extends ComponentElement {
|
|
|
50
50
|
toneMapping: number | undefined;
|
|
51
51
|
};
|
|
52
52
|
get xrAvailable(): boolean | null | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* Starts the camera in XR mode.
|
|
55
|
+
* @param type - The type of XR mode to start.
|
|
56
|
+
* @param space - The space to start the camera in.
|
|
57
|
+
*/
|
|
53
58
|
startXr(type: 'immersive-ar' | 'immersive-vr', space: 'bounded-floor' | 'local' | 'local-floor' | 'unbounded' | 'viewer'): void;
|
|
59
|
+
/**
|
|
60
|
+
* Ends the camera's XR mode.
|
|
61
|
+
*/
|
|
54
62
|
endXr(): void;
|
|
55
63
|
/**
|
|
56
64
|
* Gets the underlying PlayCanvas camera component.
|
|
@@ -29,6 +29,36 @@ declare class ScriptComponentElement extends ComponentElement {
|
|
|
29
29
|
/** @ignore */
|
|
30
30
|
constructor();
|
|
31
31
|
initComponent(): void;
|
|
32
|
+
/**
|
|
33
|
+
* Recursively converts raw attribute data into proper PlayCanvas types. Supported conversions:
|
|
34
|
+
* - "asset:assetId" → resolves to an Asset instance
|
|
35
|
+
* - "entity:entityId" → resolves to an Entity instance
|
|
36
|
+
* - "vec2:1,2" → new Vec2(1,2)
|
|
37
|
+
* - "vec3:1,2,3" → new Vec3(1,2,3)
|
|
38
|
+
* - "vec4:1,2,3,4" → new Vec4(1,2,3,4)
|
|
39
|
+
* - "color:1,0.5,0.5,1" → new Color(1,0.5,0.5,1)
|
|
40
|
+
* @param item - The item to convert.
|
|
41
|
+
* @returns The converted item.
|
|
42
|
+
*/
|
|
43
|
+
private convertAttributes;
|
|
44
|
+
/**
|
|
45
|
+
* Preprocess the attributes object by converting its values.
|
|
46
|
+
* @param attrs - The attributes object to preprocess.
|
|
47
|
+
* @returns The preprocessed attributes object.
|
|
48
|
+
*/
|
|
49
|
+
private preprocessAttributes;
|
|
50
|
+
/**
|
|
51
|
+
* Recursively merge properties from source into target.
|
|
52
|
+
* @param target - The target object to merge into.
|
|
53
|
+
* @param source - The source object to merge from.
|
|
54
|
+
* @returns The merged object.
|
|
55
|
+
*/
|
|
56
|
+
private mergeDeep;
|
|
57
|
+
/**
|
|
58
|
+
* Update script attributes by merging preprocessed values into the script.
|
|
59
|
+
* @param script - The script to update.
|
|
60
|
+
* @param attributes - The attributes to merge into the script.
|
|
61
|
+
*/
|
|
32
62
|
private applyAttributes;
|
|
33
63
|
private handleScriptAttributesChange;
|
|
34
64
|
private handleScriptEnableChange;
|
package/dist/pwc.cjs
CHANGED
|
@@ -1003,7 +1003,7 @@ const extToType = new Map([
|
|
|
1003
1003
|
class AssetElement extends HTMLElement {
|
|
1004
1004
|
constructor() {
|
|
1005
1005
|
super(...arguments);
|
|
1006
|
-
this.
|
|
1006
|
+
this._lazy = false;
|
|
1007
1007
|
/**
|
|
1008
1008
|
* The asset that is loaded.
|
|
1009
1009
|
*/
|
|
@@ -1027,7 +1027,7 @@ class AssetElement extends HTMLElement {
|
|
|
1027
1027
|
return;
|
|
1028
1028
|
}
|
|
1029
1029
|
this.asset = new playcanvas.Asset(id, type, { url: src });
|
|
1030
|
-
this.asset.preload = this.
|
|
1030
|
+
this.asset.preload = !this._lazy;
|
|
1031
1031
|
}
|
|
1032
1032
|
destroyAsset() {
|
|
1033
1033
|
if (this.asset) {
|
|
@@ -1036,32 +1036,32 @@ class AssetElement extends HTMLElement {
|
|
|
1036
1036
|
}
|
|
1037
1037
|
}
|
|
1038
1038
|
/**
|
|
1039
|
-
* Sets the
|
|
1040
|
-
* @param value - The
|
|
1039
|
+
* Sets whether the asset should be loaded lazily.
|
|
1040
|
+
* @param value - The lazy loading flag.
|
|
1041
1041
|
*/
|
|
1042
|
-
set
|
|
1043
|
-
this.
|
|
1042
|
+
set lazy(value) {
|
|
1043
|
+
this._lazy = value;
|
|
1044
1044
|
if (this.asset) {
|
|
1045
|
-
this.asset.preload = value;
|
|
1045
|
+
this.asset.preload = !value;
|
|
1046
1046
|
}
|
|
1047
1047
|
}
|
|
1048
1048
|
/**
|
|
1049
|
-
* Gets the
|
|
1050
|
-
* @returns The
|
|
1049
|
+
* Gets whether the asset should be loaded lazily.
|
|
1050
|
+
* @returns The lazy loading flag.
|
|
1051
1051
|
*/
|
|
1052
|
-
get
|
|
1053
|
-
return this.
|
|
1052
|
+
get lazy() {
|
|
1053
|
+
return this._lazy;
|
|
1054
1054
|
}
|
|
1055
1055
|
static get(id) {
|
|
1056
1056
|
const assetElement = document.querySelector(`pc-asset[id="${id}"]`);
|
|
1057
1057
|
return assetElement === null || assetElement === undefined ? undefined : assetElement.asset;
|
|
1058
1058
|
}
|
|
1059
1059
|
static get observedAttributes() {
|
|
1060
|
-
return ['
|
|
1060
|
+
return ['lazy'];
|
|
1061
1061
|
}
|
|
1062
1062
|
attributeChangedCallback(name, _oldValue, _newValue) {
|
|
1063
|
-
if (name === '
|
|
1064
|
-
this.
|
|
1063
|
+
if (name === 'lazy') {
|
|
1064
|
+
this.lazy = this.hasAttribute('lazy');
|
|
1065
1065
|
}
|
|
1066
1066
|
}
|
|
1067
1067
|
}
|
|
@@ -1235,6 +1235,11 @@ class CameraComponentElement extends ComponentElement {
|
|
|
1235
1235
|
const xrManager = (_a = this.component) === null || _a === undefined ? undefined : _a.system.app.xr;
|
|
1236
1236
|
return xrManager && xrManager.supported && xrManager.isAvailable(playcanvas.XRTYPE_VR);
|
|
1237
1237
|
}
|
|
1238
|
+
/**
|
|
1239
|
+
* Starts the camera in XR mode.
|
|
1240
|
+
* @param type - The type of XR mode to start.
|
|
1241
|
+
* @param space - The space to start the camera in.
|
|
1242
|
+
*/
|
|
1238
1243
|
startXr(type, space) {
|
|
1239
1244
|
if (this.component && this.xrAvailable) {
|
|
1240
1245
|
this.component.startXr(type, space, {
|
|
@@ -1245,6 +1250,9 @@ class CameraComponentElement extends ComponentElement {
|
|
|
1245
1250
|
});
|
|
1246
1251
|
}
|
|
1247
1252
|
}
|
|
1253
|
+
/**
|
|
1254
|
+
* Ends the camera's XR mode.
|
|
1255
|
+
*/
|
|
1248
1256
|
endXr() {
|
|
1249
1257
|
if (this.component) {
|
|
1250
1258
|
this.component.endXr();
|
|
@@ -3120,62 +3128,116 @@ class ScriptComponentElement extends ComponentElement {
|
|
|
3120
3128
|
}
|
|
3121
3129
|
});
|
|
3122
3130
|
}
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3131
|
+
/**
|
|
3132
|
+
* Recursively converts raw attribute data into proper PlayCanvas types. Supported conversions:
|
|
3133
|
+
* - "asset:assetId" → resolves to an Asset instance
|
|
3134
|
+
* - "entity:entityId" → resolves to an Entity instance
|
|
3135
|
+
* - "vec2:1,2" → new Vec2(1,2)
|
|
3136
|
+
* - "vec3:1,2,3" → new Vec3(1,2,3)
|
|
3137
|
+
* - "vec4:1,2,3,4" → new Vec4(1,2,3,4)
|
|
3138
|
+
* - "color:1,0.5,0.5,1" → new Color(1,0.5,0.5,1)
|
|
3139
|
+
* @param item - The item to convert.
|
|
3140
|
+
* @returns The converted item.
|
|
3141
|
+
*/
|
|
3142
|
+
convertAttributes(item) {
|
|
3143
|
+
if (typeof item === 'string') {
|
|
3144
|
+
if (item.startsWith('asset:')) {
|
|
3145
|
+
const assetId = item.slice(6);
|
|
3146
|
+
const assetElement = document.querySelector(`pc-asset#${assetId}`);
|
|
3147
|
+
if (assetElement) {
|
|
3148
|
+
return assetElement.asset;
|
|
3135
3149
|
}
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
for (const itemKey in item) {
|
|
3143
|
-
applyValue(obj, itemKey, item[itemKey]);
|
|
3144
|
-
}
|
|
3145
|
-
return obj;
|
|
3146
|
-
});
|
|
3147
|
-
return;
|
|
3148
|
-
}
|
|
3149
|
-
// Handle vectors
|
|
3150
|
-
if (value.length === 2 && typeof value[0] === 'number') {
|
|
3151
|
-
target[key] = new playcanvas.Vec2(value[0], value[1]);
|
|
3152
|
-
return;
|
|
3153
|
-
}
|
|
3154
|
-
if (value.length === 3 && typeof value[0] === 'number') {
|
|
3155
|
-
target[key] = new playcanvas.Vec3(value[0], value[1], value[2]);
|
|
3156
|
-
return;
|
|
3157
|
-
}
|
|
3158
|
-
if (value.length === 4 && typeof value[0] === 'number') {
|
|
3159
|
-
target[key] = new playcanvas.Vec4(value[0], value[1], value[2], value[3]);
|
|
3160
|
-
return;
|
|
3161
|
-
}
|
|
3150
|
+
}
|
|
3151
|
+
if (item.startsWith('entity:')) {
|
|
3152
|
+
const entityId = item.slice(7);
|
|
3153
|
+
const entityElement = document.querySelector(`pc-entity[name="${entityId}"]`);
|
|
3154
|
+
if (entityElement) {
|
|
3155
|
+
return entityElement.entity;
|
|
3162
3156
|
}
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
for (const nestedKey in value) {
|
|
3169
|
-
applyValue(target[key], nestedKey, value[nestedKey]);
|
|
3170
|
-
}
|
|
3157
|
+
}
|
|
3158
|
+
if (item.startsWith('vec2:')) {
|
|
3159
|
+
const parts = item.slice(5).split(',').map(Number);
|
|
3160
|
+
if (parts.length === 2 && parts.every(v => !isNaN(v))) {
|
|
3161
|
+
return new playcanvas.Vec2(parts[0], parts[1]);
|
|
3171
3162
|
}
|
|
3172
|
-
|
|
3173
|
-
|
|
3163
|
+
}
|
|
3164
|
+
if (item.startsWith('vec3:')) {
|
|
3165
|
+
const parts = item.slice(5).split(',').map(Number);
|
|
3166
|
+
if (parts.length === 3 && parts.every(v => !isNaN(v))) {
|
|
3167
|
+
return new playcanvas.Vec3(parts[0], parts[1], parts[2]);
|
|
3168
|
+
}
|
|
3169
|
+
}
|
|
3170
|
+
if (item.startsWith('vec4:')) {
|
|
3171
|
+
const parts = item.slice(5).split(',').map(Number);
|
|
3172
|
+
if (parts.length === 4 && parts.every(v => !isNaN(v))) {
|
|
3173
|
+
return new playcanvas.Vec4(parts[0], parts[1], parts[2], parts[3]);
|
|
3174
|
+
}
|
|
3175
|
+
}
|
|
3176
|
+
if (item.startsWith('color:')) {
|
|
3177
|
+
const parts = item.slice(6).split(',').map(Number);
|
|
3178
|
+
if (parts.length === 4 && parts.every(v => !isNaN(v))) {
|
|
3179
|
+
return new playcanvas.Color(parts[0], parts[1], parts[2], parts[3]);
|
|
3174
3180
|
}
|
|
3175
|
-
};
|
|
3176
|
-
for (const key in attributesObject) {
|
|
3177
|
-
applyValue(script, key, attributesObject[key]);
|
|
3178
3181
|
}
|
|
3182
|
+
return item;
|
|
3183
|
+
}
|
|
3184
|
+
if (Array.isArray(item)) {
|
|
3185
|
+
// If it's an array of objects, convert each element individually.
|
|
3186
|
+
if (item.length > 0 && typeof item[0] === 'object') {
|
|
3187
|
+
return item.map((el) => this.convertAttributes(el));
|
|
3188
|
+
}
|
|
3189
|
+
// Otherwise, leave the numeric array unchanged but process each element.
|
|
3190
|
+
return item.map((el) => this.convertAttributes(el));
|
|
3191
|
+
}
|
|
3192
|
+
if (item && typeof item === 'object') {
|
|
3193
|
+
const result = {};
|
|
3194
|
+
for (const key in item) {
|
|
3195
|
+
result[key] = this.convertAttributes(item[key]);
|
|
3196
|
+
}
|
|
3197
|
+
return result;
|
|
3198
|
+
}
|
|
3199
|
+
return item;
|
|
3200
|
+
}
|
|
3201
|
+
/**
|
|
3202
|
+
* Preprocess the attributes object by converting its values.
|
|
3203
|
+
* @param attrs - The attributes object to preprocess.
|
|
3204
|
+
* @returns The preprocessed attributes object.
|
|
3205
|
+
*/
|
|
3206
|
+
preprocessAttributes(attrs) {
|
|
3207
|
+
return this.convertAttributes(attrs);
|
|
3208
|
+
}
|
|
3209
|
+
/**
|
|
3210
|
+
* Recursively merge properties from source into target.
|
|
3211
|
+
* @param target - The target object to merge into.
|
|
3212
|
+
* @param source - The source object to merge from.
|
|
3213
|
+
* @returns The merged object.
|
|
3214
|
+
*/
|
|
3215
|
+
mergeDeep(target, source) {
|
|
3216
|
+
for (const key in source) {
|
|
3217
|
+
if (source[key] &&
|
|
3218
|
+
typeof source[key] === 'object' &&
|
|
3219
|
+
!Array.isArray(source[key])) {
|
|
3220
|
+
if (!target[key] || typeof target[key] !== 'object') {
|
|
3221
|
+
target[key] = {};
|
|
3222
|
+
}
|
|
3223
|
+
this.mergeDeep(target[key], source[key]);
|
|
3224
|
+
}
|
|
3225
|
+
else {
|
|
3226
|
+
target[key] = source[key];
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3229
|
+
return target;
|
|
3230
|
+
}
|
|
3231
|
+
/**
|
|
3232
|
+
* Update script attributes by merging preprocessed values into the script.
|
|
3233
|
+
* @param script - The script to update.
|
|
3234
|
+
* @param attributes - The attributes to merge into the script.
|
|
3235
|
+
*/
|
|
3236
|
+
applyAttributes(script, attributes) {
|
|
3237
|
+
try {
|
|
3238
|
+
const attributesObject = attributes ? JSON.parse(attributes) : {};
|
|
3239
|
+
const converted = this.convertAttributes(attributesObject);
|
|
3240
|
+
this.mergeDeep(script, converted);
|
|
3179
3241
|
}
|
|
3180
3242
|
catch (error) {
|
|
3181
3243
|
console.error(`Error parsing attributes JSON string ${attributes}:`, error);
|
|
@@ -3204,10 +3266,20 @@ class ScriptComponentElement extends ComponentElement {
|
|
|
3204
3266
|
createScript(name, attributes) {
|
|
3205
3267
|
if (!this.component)
|
|
3206
3268
|
return null;
|
|
3207
|
-
|
|
3208
|
-
|
|
3269
|
+
let attributesObject = {};
|
|
3270
|
+
if (attributes) {
|
|
3271
|
+
try {
|
|
3272
|
+
attributesObject = JSON.parse(attributes);
|
|
3273
|
+
// Preprocess attributes: convert arrays or strings into vectors, colors, asset references, etc.
|
|
3274
|
+
attributesObject = this.preprocessAttributes(attributesObject);
|
|
3275
|
+
}
|
|
3276
|
+
catch (error) {
|
|
3277
|
+
console.error(`Error parsing attributes JSON string ${attributes}:`, error);
|
|
3278
|
+
}
|
|
3279
|
+
}
|
|
3280
|
+
return this.component.create(name, {
|
|
3281
|
+
properties: attributesObject
|
|
3209
3282
|
});
|
|
3210
|
-
return this.component.create(name);
|
|
3211
3283
|
}
|
|
3212
3284
|
destroyScript(name) {
|
|
3213
3285
|
if (!this.component)
|