@playcanvas/web-components 0.1.6 → 0.1.8
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 +22 -22
- package/dist/colors.d.ts +1 -0
- package/dist/components/light-component.d.ts +12 -0
- package/dist/model.d.ts +6 -2
- package/dist/pwc.cjs +358 -97
- package/dist/pwc.cjs.map +1 -1
- package/dist/pwc.js +358 -97
- 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 +359 -98
- package/dist/pwc.mjs.map +1 -1
- package/dist/sky.d.ts +12 -6
- package/package.json +12 -10
- package/src/colors.ts +150 -0
- package/src/components/light-component.ts +26 -0
- package/src/components/script-component.ts +40 -13
- package/src/entity.ts +2 -0
- package/src/model.ts +47 -19
- package/src/sky.ts +103 -64
- package/src/utils.ts +13 -5
|
@@ -2,6 +2,7 @@ import { ScriptComponent, Script, Vec2, Vec3, Vec4 } from 'playcanvas';
|
|
|
2
2
|
|
|
3
3
|
import { ComponentElement } from './component';
|
|
4
4
|
import { ScriptElement } from './script';
|
|
5
|
+
import { AssetElement } from '../asset';
|
|
5
6
|
|
|
6
7
|
const tmpV2 = new Vec2();
|
|
7
8
|
const tmpV3 = new Vec3();
|
|
@@ -59,24 +60,50 @@ class ScriptComponentElement extends ComponentElement {
|
|
|
59
60
|
|
|
60
61
|
private applyAttributes(script: any, attributes: string | null) {
|
|
61
62
|
try {
|
|
62
|
-
// Parse the attributes string into an object and set them on the script
|
|
63
63
|
const attributesObject = attributes ? JSON.parse(attributes) : {};
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
|
|
65
|
+
const applyValue = (target: any, key: string, value: any) => {
|
|
66
|
+
// Handle asset references
|
|
67
|
+
if (typeof value === 'string' && value.startsWith('asset:')) {
|
|
68
|
+
const assetId = value.slice(6);
|
|
69
|
+
const assetElement = document.querySelector(`pc-asset#${assetId}`) as AssetElement;
|
|
70
|
+
if (assetElement) {
|
|
71
|
+
target[key] = assetElement.asset;
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
69
74
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
75
|
+
|
|
76
|
+
// Handle vectors
|
|
77
|
+
if (Array.isArray(value)) {
|
|
78
|
+
if (target[key] instanceof Vec2) {
|
|
79
|
+
target[key] = tmpV2.set(value[0], value[1]);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (target[key] instanceof Vec3) {
|
|
83
|
+
target[key] = tmpV3.set(value[0], value[1], value[2]);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (target[key] instanceof Vec4) {
|
|
87
|
+
target[key] = tmpV4.set(value[0], value[1], value[2], value[3]);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
73
90
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
91
|
+
|
|
92
|
+
// Handle nested objects
|
|
93
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
94
|
+
if (!target[key] || typeof target[key] !== 'object') {
|
|
95
|
+
target[key] = {};
|
|
96
|
+
}
|
|
97
|
+
for (const nestedKey in value) {
|
|
98
|
+
applyValue(target[key], nestedKey, value[nestedKey]);
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
target[key] = value;
|
|
77
102
|
}
|
|
103
|
+
};
|
|
78
104
|
|
|
79
|
-
|
|
105
|
+
for (const key in attributesObject) {
|
|
106
|
+
applyValue(script, key, attributesObject[key]);
|
|
80
107
|
}
|
|
81
108
|
} catch (error) {
|
|
82
109
|
console.error(`Error parsing attributes JSON string ${attributes}:`, error);
|
package/src/entity.ts
CHANGED
|
@@ -55,12 +55,14 @@ class EntityElement extends AsyncElement {
|
|
|
55
55
|
this.entity = new Entity(this._name, app);
|
|
56
56
|
|
|
57
57
|
// Initialize from attributes
|
|
58
|
+
const enabledAttr = this.getAttribute('enabled');
|
|
58
59
|
const nameAttr = this.getAttribute('name');
|
|
59
60
|
const positionAttr = this.getAttribute('position');
|
|
60
61
|
const rotationAttr = this.getAttribute('rotation');
|
|
61
62
|
const scaleAttr = this.getAttribute('scale');
|
|
62
63
|
const tagsAttr = this.getAttribute('tags');
|
|
63
64
|
|
|
65
|
+
if (enabledAttr) this.enabled = enabledAttr !== 'false';
|
|
64
66
|
if (nameAttr) this.name = nameAttr;
|
|
65
67
|
if (positionAttr) this.position = parseVec3(positionAttr);
|
|
66
68
|
if (rotationAttr) this.rotation = parseVec3(rotationAttr);
|
package/src/model.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ContainerResource, Entity } from 'playcanvas';
|
|
2
|
+
|
|
1
3
|
import { AssetElement } from './asset';
|
|
2
4
|
import { AsyncElement } from './async-element';
|
|
3
5
|
|
|
@@ -7,51 +9,77 @@ import { AsyncElement } from './async-element';
|
|
|
7
9
|
class ModelElement extends AsyncElement {
|
|
8
10
|
private _asset: string = '';
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
await this.closestApp?.ready();
|
|
12
|
-
|
|
13
|
-
const asset = this.getAttribute('asset');
|
|
14
|
-
if (asset) {
|
|
15
|
-
this.asset = asset;
|
|
16
|
-
}
|
|
12
|
+
private _entity: Entity | null = null;
|
|
17
13
|
|
|
14
|
+
connectedCallback() {
|
|
15
|
+
this._loadModel();
|
|
18
16
|
this._onReady();
|
|
19
17
|
}
|
|
20
18
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
disconnectedCallback() {
|
|
20
|
+
this._unloadModel();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private _instantiate(container: ContainerResource) {
|
|
24
|
+
this._entity = container.instantiateRenderEntity();
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
// @ts-ignore
|
|
27
|
+
if (container.animations.length > 0) {
|
|
28
|
+
this._entity.addComponent('anim');
|
|
29
|
+
// @ts-ignore
|
|
30
|
+
this._entity.anim.assignAnimation('animation', container.animations[0].resource);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
const parentEntityElement = this.closestEntity;
|
|
34
34
|
if (parentEntityElement) {
|
|
35
35
|
parentEntityElement.ready().then(() => {
|
|
36
|
-
parentEntityElement.entity!.addChild(
|
|
36
|
+
parentEntityElement.entity!.addChild(this._entity!);
|
|
37
37
|
});
|
|
38
38
|
} else {
|
|
39
39
|
const appElement = this.closestApp;
|
|
40
40
|
if (appElement) {
|
|
41
41
|
appElement.ready().then(() => {
|
|
42
|
-
appElement.app!.root.addChild(
|
|
42
|
+
appElement.app!.root.addChild(this._entity!);
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
private async _loadModel() {
|
|
49
|
+
this._unloadModel();
|
|
50
|
+
|
|
51
|
+
const appElement = await this.closestApp?.ready();
|
|
52
|
+
const app = appElement?.app;
|
|
53
|
+
|
|
54
|
+
const asset = AssetElement.get(this._asset);
|
|
55
|
+
if (!asset) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (asset.loaded) {
|
|
60
|
+
this._instantiate(asset.resource);
|
|
61
|
+
} else {
|
|
62
|
+
asset.once('load', () => {
|
|
63
|
+
this._instantiate(asset.resource);
|
|
64
|
+
});
|
|
65
|
+
app!.assets.load(asset);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private _unloadModel() {
|
|
70
|
+
this._entity?.destroy();
|
|
71
|
+
this._entity = null;
|
|
72
|
+
}
|
|
73
|
+
|
|
48
74
|
/**
|
|
49
75
|
* Sets the asset ID of the model.
|
|
50
76
|
* @param value - The asset ID.
|
|
51
77
|
*/
|
|
52
78
|
set asset(value: string) {
|
|
53
79
|
this._asset = value;
|
|
54
|
-
this.
|
|
80
|
+
if (this.isConnected) {
|
|
81
|
+
this._loadModel();
|
|
82
|
+
}
|
|
55
83
|
}
|
|
56
84
|
|
|
57
85
|
/**
|
package/src/sky.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EnvLighting, LAYERID_SKYBOX, Quat, Texture, Vec3 } from 'playcanvas';
|
|
1
|
+
import { Asset, EnvLighting, LAYERID_SKYBOX, Quat, Scene, Texture, Vec3 } from 'playcanvas';
|
|
2
2
|
|
|
3
3
|
import { AssetElement } from './asset';
|
|
4
4
|
import { AsyncElement } from './async-element';
|
|
@@ -18,56 +18,90 @@ class SkyElement extends AsyncElement {
|
|
|
18
18
|
|
|
19
19
|
private _level = 0;
|
|
20
20
|
|
|
21
|
+
private _lighting = false;
|
|
22
|
+
|
|
21
23
|
private _scale = new Vec3(100, 100, 100);
|
|
22
24
|
|
|
23
25
|
private _type: 'box' | 'dome' | 'infinite' | 'none' = 'infinite';
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
await this.closestApp?.ready();
|
|
27
|
-
|
|
28
|
-
this.asset = this.getAttribute('asset') || '';
|
|
27
|
+
private _scene: Scene | null = null;
|
|
29
28
|
|
|
29
|
+
connectedCallback() {
|
|
30
|
+
this._loadSkybox();
|
|
30
31
|
this._onReady();
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
disconnectedCallback() {
|
|
35
|
+
this._unloadSkybox();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
private _generateSkybox(asset: Asset) {
|
|
39
|
+
if (!this._scene) return;
|
|
40
|
+
|
|
41
|
+
const source = asset.resource as Texture;
|
|
42
|
+
|
|
43
|
+
const skybox = EnvLighting.generateSkyboxCubemap(source);
|
|
44
|
+
skybox.anisotropy = 4;
|
|
45
|
+
this._scene.skybox = skybox;
|
|
46
|
+
|
|
47
|
+
if (this._lighting) {
|
|
48
|
+
const lighting = EnvLighting.generateLightingSource(source);
|
|
49
|
+
const envAtlas = EnvLighting.generateAtlas(lighting);
|
|
50
|
+
this._scene.envAtlas = envAtlas;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const layer = this._scene.layers.getLayerById(LAYERID_SKYBOX);
|
|
54
|
+
if (layer) {
|
|
55
|
+
layer.enabled = this._type !== 'none';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
this._scene.sky.type = this._type;
|
|
59
|
+
this._scene.sky.node.setLocalScale(this._scale);
|
|
60
|
+
this._scene.sky.center = this._center;
|
|
61
|
+
this._scene.skyboxIntensity = this._intensity;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private async _loadSkybox() {
|
|
65
|
+
const appElement = await this.closestApp?.ready();
|
|
66
|
+
const app = appElement?.app;
|
|
35
67
|
if (!app) {
|
|
36
68
|
return;
|
|
37
69
|
}
|
|
38
|
-
return app.scene;
|
|
39
|
-
}
|
|
40
70
|
|
|
41
|
-
|
|
42
|
-
|
|
71
|
+
const asset = AssetElement.get(this._asset);
|
|
72
|
+
if (!asset) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
43
75
|
|
|
44
|
-
|
|
45
|
-
const lighting = EnvLighting.generateLightingSource(source);
|
|
46
|
-
const envAtlas = EnvLighting.generateAtlas(lighting);
|
|
47
|
-
const app = this.closestApp!.app;
|
|
48
|
-
if (app) {
|
|
49
|
-
app.scene.envAtlas = envAtlas;
|
|
50
|
-
app.scene.skybox = skybox;
|
|
51
|
-
|
|
52
|
-
const layer = app.scene.layers.getLayerById(LAYERID_SKYBOX);
|
|
53
|
-
if (layer) {
|
|
54
|
-
layer.enabled = this._type !== 'none';
|
|
55
|
-
}
|
|
76
|
+
this._scene = app.scene;
|
|
56
77
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
78
|
+
if (asset.loaded) {
|
|
79
|
+
this._generateSkybox(asset);
|
|
80
|
+
} else {
|
|
81
|
+
asset.once('load', () => {
|
|
82
|
+
this._generateSkybox(asset);
|
|
83
|
+
});
|
|
84
|
+
app.assets.load(asset);
|
|
60
85
|
}
|
|
61
86
|
}
|
|
62
87
|
|
|
88
|
+
private _unloadSkybox() {
|
|
89
|
+
if (!this._scene) return;
|
|
90
|
+
|
|
91
|
+
this._scene.skybox?.destroy();
|
|
92
|
+
// @ts-ignore
|
|
93
|
+
this._scene.skybox = null;
|
|
94
|
+
this._scene.envAtlas?.destroy();
|
|
95
|
+
// @ts-ignore
|
|
96
|
+
this._scene.envAtlas = null;
|
|
97
|
+
|
|
98
|
+
this._scene = null;
|
|
99
|
+
}
|
|
100
|
+
|
|
63
101
|
set asset(value: string) {
|
|
64
102
|
this._asset = value;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const asset = AssetElement.get(value);
|
|
68
|
-
if (asset) {
|
|
69
|
-
this.initSkybox(asset.resource);
|
|
70
|
-
}
|
|
103
|
+
if (this.isConnected) {
|
|
104
|
+
this._loadSkybox();
|
|
71
105
|
}
|
|
72
106
|
}
|
|
73
107
|
|
|
@@ -77,9 +111,8 @@ class SkyElement extends AsyncElement {
|
|
|
77
111
|
|
|
78
112
|
set center(value: Vec3) {
|
|
79
113
|
this._center = value;
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
scene.sky.center = this._center;
|
|
114
|
+
if (this._scene) {
|
|
115
|
+
this._scene.sky.center = this._center;
|
|
83
116
|
}
|
|
84
117
|
}
|
|
85
118
|
|
|
@@ -89,9 +122,8 @@ class SkyElement extends AsyncElement {
|
|
|
89
122
|
|
|
90
123
|
set intensity(value: number) {
|
|
91
124
|
this._intensity = value;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
scene.skyboxIntensity = this._intensity;
|
|
125
|
+
if (this._scene) {
|
|
126
|
+
this._scene.skyboxIntensity = this._intensity;
|
|
95
127
|
}
|
|
96
128
|
}
|
|
97
129
|
|
|
@@ -99,11 +131,29 @@ class SkyElement extends AsyncElement {
|
|
|
99
131
|
return this._intensity;
|
|
100
132
|
}
|
|
101
133
|
|
|
134
|
+
set level(value: number) {
|
|
135
|
+
this._level = value;
|
|
136
|
+
if (this._scene) {
|
|
137
|
+
this._scene.skyboxMip = this._level;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
get level() {
|
|
142
|
+
return this._level;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
set lighting(value: boolean) {
|
|
146
|
+
this._lighting = value;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
get lighting() {
|
|
150
|
+
return this._lighting;
|
|
151
|
+
}
|
|
152
|
+
|
|
102
153
|
set rotation(value: Vec3) {
|
|
103
154
|
this._rotation = value;
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
scene.skyboxRotation = new Quat().setFromEulerAngles(value);
|
|
155
|
+
if (this._scene) {
|
|
156
|
+
this._scene.skyboxRotation = new Quat().setFromEulerAngles(value);
|
|
107
157
|
}
|
|
108
158
|
}
|
|
109
159
|
|
|
@@ -113,9 +163,8 @@ class SkyElement extends AsyncElement {
|
|
|
113
163
|
|
|
114
164
|
set scale(value: Vec3) {
|
|
115
165
|
this._scale = value;
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
scene.sky.node.setLocalScale(this._scale);
|
|
166
|
+
if (this._scene) {
|
|
167
|
+
this._scene.sky.node.setLocalScale(this._scale);
|
|
119
168
|
}
|
|
120
169
|
}
|
|
121
170
|
|
|
@@ -123,24 +172,11 @@ class SkyElement extends AsyncElement {
|
|
|
123
172
|
return this._scale;
|
|
124
173
|
}
|
|
125
174
|
|
|
126
|
-
set level(value: number) {
|
|
127
|
-
this._level = value;
|
|
128
|
-
const scene = this.getScene();
|
|
129
|
-
if (scene) {
|
|
130
|
-
scene.skyboxMip = this._level;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
get level() {
|
|
135
|
-
return this._level;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
175
|
set type(value: 'box' | 'dome' | 'infinite' | 'none') {
|
|
139
176
|
this._type = value;
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const layer = scene.layers.getLayerById(LAYERID_SKYBOX);
|
|
177
|
+
if (this._scene) {
|
|
178
|
+
this._scene.sky.type = this._type;
|
|
179
|
+
const layer = this._scene.layers.getLayerById(LAYERID_SKYBOX);
|
|
144
180
|
if (layer) {
|
|
145
181
|
layer.enabled = this._type !== 'none';
|
|
146
182
|
}
|
|
@@ -152,7 +188,7 @@ class SkyElement extends AsyncElement {
|
|
|
152
188
|
}
|
|
153
189
|
|
|
154
190
|
static get observedAttributes() {
|
|
155
|
-
return ['asset', 'center', 'intensity', 'level', 'rotation', 'scale', 'type'];
|
|
191
|
+
return ['asset', 'center', 'intensity', 'level', 'lighting', 'rotation', 'scale', 'type'];
|
|
156
192
|
}
|
|
157
193
|
|
|
158
194
|
attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
|
|
@@ -166,12 +202,15 @@ class SkyElement extends AsyncElement {
|
|
|
166
202
|
case 'intensity':
|
|
167
203
|
this.intensity = parseFloat(newValue);
|
|
168
204
|
break;
|
|
169
|
-
case 'rotation':
|
|
170
|
-
this.rotation = parseVec3(newValue);
|
|
171
|
-
break;
|
|
172
205
|
case 'level':
|
|
173
206
|
this.level = parseInt(newValue, 10);
|
|
174
207
|
break;
|
|
208
|
+
case 'lighting':
|
|
209
|
+
this.lighting = this.hasAttribute(name);
|
|
210
|
+
break;
|
|
211
|
+
case 'rotation':
|
|
212
|
+
this.rotation = parseVec3(newValue);
|
|
213
|
+
break;
|
|
175
214
|
case 'scale':
|
|
176
215
|
this.scale = parseVec3(newValue);
|
|
177
216
|
break;
|
package/src/utils.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Color, Quat, Vec2, Vec3, Vec4 } from 'playcanvas';
|
|
2
2
|
|
|
3
|
+
import { CSS_COLORS } from './colors';
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
6
|
* Parse a color string into a Color object. String can be in the format of '#rgb', '#rgba',
|
|
5
7
|
* '#rrggbb', '#rrggbbaa', or a string of 3 or 4 comma-delimited numbers.
|
|
@@ -8,11 +10,17 @@ import { Color, Quat, Vec2, Vec3, Vec4 } from 'playcanvas';
|
|
|
8
10
|
* @returns The parsed Color object.
|
|
9
11
|
*/
|
|
10
12
|
export const parseColor = (value: string): Color => {
|
|
13
|
+
// Check if it's a CSS color name first
|
|
14
|
+
const hexColor = CSS_COLORS[value.toLowerCase()];
|
|
15
|
+
if (hexColor) {
|
|
16
|
+
return new Color().fromString(hexColor);
|
|
17
|
+
}
|
|
18
|
+
|
|
11
19
|
if (value.startsWith('#')) {
|
|
12
20
|
return new Color().fromString(value);
|
|
13
21
|
}
|
|
14
22
|
|
|
15
|
-
const components = value.split('
|
|
23
|
+
const components = value.split(' ').map(Number);
|
|
16
24
|
return new Color(components);
|
|
17
25
|
};
|
|
18
26
|
|
|
@@ -23,7 +31,7 @@ export const parseColor = (value: string): Color => {
|
|
|
23
31
|
* @returns The parsed Quat object.
|
|
24
32
|
*/
|
|
25
33
|
export const parseQuat = (value: string): Quat => {
|
|
26
|
-
const [x, y, z] = value.split('
|
|
34
|
+
const [x, y, z] = value.split(' ').map(Number);
|
|
27
35
|
const q = new Quat();
|
|
28
36
|
q.setFromEulerAngles(x, y, z);
|
|
29
37
|
return q;
|
|
@@ -36,7 +44,7 @@ export const parseQuat = (value: string): Quat => {
|
|
|
36
44
|
* @returns The parsed Vec2 object.
|
|
37
45
|
*/
|
|
38
46
|
export const parseVec2 = (value: string): Vec2 => {
|
|
39
|
-
const components = value.split('
|
|
47
|
+
const components = value.split(' ').map(Number);
|
|
40
48
|
return new Vec2(components);
|
|
41
49
|
};
|
|
42
50
|
|
|
@@ -47,7 +55,7 @@ export const parseVec2 = (value: string): Vec2 => {
|
|
|
47
55
|
* @returns The parsed Vec3 object.
|
|
48
56
|
*/
|
|
49
57
|
export const parseVec3 = (value: string): Vec3 => {
|
|
50
|
-
const components = value.split('
|
|
58
|
+
const components = value.split(' ').map(Number);
|
|
51
59
|
return new Vec3(components);
|
|
52
60
|
};
|
|
53
61
|
|
|
@@ -58,6 +66,6 @@ export const parseVec3 = (value: string): Vec3 => {
|
|
|
58
66
|
* @returns The parsed Vec4 object.
|
|
59
67
|
*/
|
|
60
68
|
export const parseVec4 = (value: string): Vec4 => {
|
|
61
|
-
const components = value.split('
|
|
69
|
+
const components = value.split(' ').map(Number);
|
|
62
70
|
return new Vec4(components);
|
|
63
71
|
};
|