@combos-fun/plugin-renderer-3d-model 0.0.39 → 0.0.41
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/agent-skill.md +42 -16
- package/combos-plugin.json +1 -1
- package/dist/plugin-renderer-3d-model.cjs.js +182 -3
- package/dist/plugin-renderer-3d-model.cjs.js.map +1 -1
- package/dist/plugin-renderer-3d-model.cjs.prod.js +1 -1
- package/dist/plugin-renderer-3d-model.d.ts +12 -1
- package/dist/plugin-renderer-3d-model.esm.js +184 -5
- package/dist/plugin-renderer-3d-model.esm.js.map +1 -1
- package/package.json +11 -6
package/agent-skill.md
CHANGED
|
@@ -1,26 +1,29 @@
|
|
|
1
1
|
# `@combos-fun/plugin-renderer-3d-model` — Agent notes
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Loads a named 3D model through the engine resource system and drives included animations with Three.js `AnimationMixer`. `resource` is an engine **name**, never a URL.
|
|
4
|
+
|
|
5
|
+
Formats: `.glb` / `.gltf` (Draco, KTX2, meshopt), `.fbx`, `.obj` (+ optional `src.mtl`), `.stl`, `.dae`, `.ply`. Prefer `.glb` when you control the export. DCC sources (`.blend` / `.max` / `.c4d` / `.ma`) are not runtime-loadable.
|
|
4
6
|
|
|
5
7
|
## When to read
|
|
6
8
|
|
|
7
|
-
Read for any 3D character / prop / scenery model:
|
|
9
|
+
Read for any 3D character / prop / scenery model: registering a model resource, choosing animation clips, scrubbing animation speed.
|
|
8
10
|
|
|
9
11
|
## Public API
|
|
10
12
|
|
|
11
13
|
```ts
|
|
12
14
|
import { Model3D, Model3DSystem, type Model3DParams } from '@combos-fun/plugin-renderer-3d-model';
|
|
15
|
+
import { resource, RESOURCE_TYPE } from '@combos-fun/engine';
|
|
13
16
|
```
|
|
14
17
|
|
|
15
|
-
`componentName = 'Model3D'`, `systemName = 'Model3DSystem'`.
|
|
18
|
+
`componentName = 'Model3D'`, `systemName = 'Model3DSystem'`. Importing this package registers `RESOURCE_TYPE.MODEL` (and the `GLB` alias) instance factories.
|
|
16
19
|
|
|
17
20
|
### `Model3DParams`
|
|
18
21
|
|
|
19
22
|
| Field | Type | Default | Notes |
|
|
20
23
|
|-------|------|---------|-------|
|
|
21
|
-
| `resource` | `string` | `''` |
|
|
24
|
+
| `resource` | `string` | `''` | Engine resource name (`RESOURCE_TYPE.MODEL`). Missing name throws; URLs are not accepted. |
|
|
22
25
|
| `autoPlay` | `boolean` | `true` | |
|
|
23
|
-
| `animationIndex` | `number` | `0` | Index into the
|
|
26
|
+
| `animationIndex` | `number` | `0` | Index into the model's `animations` array |
|
|
24
27
|
| `speed` | `number` | `1` | `AnimationMixer.timeScale` |
|
|
25
28
|
| `positionX` / `Y` / `Z` | `number` | `0` |
|
|
26
29
|
| `rotationX` / `Y` / `Z` | `number` | `0` |
|
|
@@ -28,35 +31,58 @@ import { Model3D, Model3DSystem, type Model3DParams } from '@combos-fun/plugin-r
|
|
|
28
31
|
|
|
29
32
|
Changing `animationIndex` or `speed` restarts the animation cleanly.
|
|
30
33
|
|
|
34
|
+
### Resource registration
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
resource.addResource([
|
|
38
|
+
{
|
|
39
|
+
name: 'hero',
|
|
40
|
+
type: RESOURCE_TYPE.MODEL,
|
|
41
|
+
src: { model: { type: 'glb', url: 'https://cdn.example/hero.glb' } },
|
|
42
|
+
preload: true,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: 'crate',
|
|
46
|
+
type: RESOURCE_TYPE.MODEL,
|
|
47
|
+
src: {
|
|
48
|
+
model: { type: 'obj', url: 'https://cdn.example/crate.obj' },
|
|
49
|
+
mtl: { type: 'mtl', url: 'https://cdn.example/crate.mtl' },
|
|
50
|
+
},
|
|
51
|
+
preload: true,
|
|
52
|
+
},
|
|
53
|
+
]);
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
CDN / http URLs belong in `src`, not on `Model3D.resource`. Sidecar files (gltf `.bin` / images, obj `.mtl`) should share the same directory as the main file, or be listed as extra `src` slots (`mtl`, `bin`).
|
|
57
|
+
|
|
31
58
|
## Required setup
|
|
32
59
|
|
|
33
|
-
`Renderer3DSystem` then `Model3DSystem`.
|
|
60
|
+
`Renderer3DSystem` then `Model3DSystem`. Gate `new Game(...)` on `resource.once(LOAD_EVENT.COMPLETE, ...)`.
|
|
34
61
|
|
|
35
62
|
## Runtime behaviour
|
|
36
63
|
|
|
37
|
-
- Loading is async. While the
|
|
38
|
-
|
|
39
|
-
-
|
|
40
|
-
|
|
41
|
-
- The `AnimationMixer` is owned by the system; switching
|
|
42
|
-
`animationIndex` calls `mixer.stopAllAction()` then plays the new clip.
|
|
64
|
+
- Loading is async. While the model is parsing, the GameObject has no visible mesh.
|
|
65
|
+
- The system uses `increaseAsyncId` / `validateAsyncId` to drop stale loads if the component is removed mid-fetch.
|
|
66
|
+
- Each GameObject gets a cloned scene (`SkeletonUtils.clone`) so two heroes can share one resource.
|
|
67
|
+
- The `AnimationMixer` is owned by `ThreeContext`; switching `animationIndex` calls `mixer.stopAllAction()` then plays the new clip.
|
|
43
68
|
|
|
44
69
|
## Common pitfalls
|
|
45
70
|
|
|
46
71
|
| Symptom | Fix |
|
|
47
72
|
|---------|-----|
|
|
73
|
+
| `Unknown resource` throw | Register the name with `resource.addResource` + `RESOURCE_TYPE.MODEL`; do not pass a URL to `Model3D.resource` |
|
|
48
74
|
| Model not visible | Loaded at origin; adjust `position*` or check camera distance (camera is at z=5 by default) |
|
|
49
75
|
| Wrong scale | Use `scaleX` / `Y` / `Z`; many GLBs export at meter scale |
|
|
50
|
-
| Animation doesn't play | `autoPlay: true` is the default — check `animationIndex` is within `animations.length` |
|
|
51
|
-
|
|
|
52
|
-
| 404 / CORS | Verify
|
|
76
|
+
| Animation doesn't play | `autoPlay: true` is the default — check `animationIndex` is within `animations.length` (OBJ/STL/PLY have none) |
|
|
77
|
+
| Draco / KTX2 glTF fails | Decoder WASM is fetched from Google Draco / unpkg three `basis/` — the page must allow that network |
|
|
78
|
+
| 404 / CORS | Verify `src.model.url` returns the file; check network tab |
|
|
53
79
|
|
|
54
80
|
## Minimal example
|
|
55
81
|
|
|
56
82
|
```ts
|
|
57
83
|
const hero = new GameObject('hero');
|
|
58
84
|
hero.addComponent(new Model3D({
|
|
59
|
-
resource: '
|
|
85
|
+
resource: 'hero',
|
|
60
86
|
autoPlay: true,
|
|
61
87
|
animationIndex: 0,
|
|
62
88
|
speed: 1,
|
package/combos-plugin.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"category": "rendering",
|
|
5
5
|
"dimension": "3d",
|
|
6
6
|
"isCore": false,
|
|
7
|
-
"keywords": ["3d", "model", "glb", "gltf", "animation", "mesh"],
|
|
7
|
+
"keywords": ["3d", "model", "glb", "gltf", "fbx", "obj", "stl", "dae", "ply", "animation", "mesh"],
|
|
8
8
|
"agentSkill": "./agent-skill.md",
|
|
9
9
|
"requires": ["@combos-fun/engine", "@combos-fun/plugin-renderer-3d"],
|
|
10
10
|
"exports": ["Model3D", "Model3DSystem"]
|
|
@@ -4,6 +4,18 @@ var tslib = require('tslib');
|
|
|
4
4
|
var engine = require('@combos-fun/engine');
|
|
5
5
|
var inspectorDecorator = require('@combos-fun/inspector-decorator');
|
|
6
6
|
var pluginRenderer3d = require('@combos-fun/plugin-renderer-3d');
|
|
7
|
+
var SkeletonUtils_js = require('three/addons/utils/SkeletonUtils.js');
|
|
8
|
+
var three = require('three');
|
|
9
|
+
var GLTFLoader_js = require('three/addons/loaders/GLTFLoader.js');
|
|
10
|
+
var DRACOLoader_js = require('three/addons/loaders/DRACOLoader.js');
|
|
11
|
+
var KTX2Loader_js = require('three/addons/loaders/KTX2Loader.js');
|
|
12
|
+
var FBXLoader_js = require('three/addons/loaders/FBXLoader.js');
|
|
13
|
+
var OBJLoader_js = require('three/addons/loaders/OBJLoader.js');
|
|
14
|
+
var MTLLoader_js = require('three/addons/loaders/MTLLoader.js');
|
|
15
|
+
var STLLoader_js = require('three/addons/loaders/STLLoader.js');
|
|
16
|
+
var ColladaLoader_js = require('three/addons/loaders/ColladaLoader.js');
|
|
17
|
+
var PLYLoader_js = require('three/addons/loaders/PLYLoader.js');
|
|
18
|
+
var meshopt_decoder_module_js = require('three/addons/libs/meshopt_decoder.module.js');
|
|
7
19
|
|
|
8
20
|
class Model3D extends engine.Component {
|
|
9
21
|
constructor() {
|
|
@@ -33,7 +45,7 @@ tslib.__decorate([
|
|
|
33
45
|
type: 'string',
|
|
34
46
|
group: 'Model3D',
|
|
35
47
|
label: 'resource',
|
|
36
|
-
description: '
|
|
48
|
+
description: 'Engine resource name registered with RESOURCE_TYPE.MODEL.',
|
|
37
49
|
editor: 'text',
|
|
38
50
|
})
|
|
39
51
|
], Model3D.prototype, "resource", void 0);
|
|
@@ -156,6 +168,163 @@ tslib.__decorate([
|
|
|
156
168
|
})
|
|
157
169
|
], Model3D.prototype, "scaleZ", void 0);
|
|
158
170
|
|
|
171
|
+
const THREE_ADDON_CDN = 'https://unpkg.com/three@0.172.0/examples/jsm/libs';
|
|
172
|
+
const DRACO_DECODER_PATH = 'https://www.gstatic.com/draco/versioned/decoders/1.5.7/';
|
|
173
|
+
const BASIS_TRANSCODER_PATH = `${THREE_ADDON_CDN}/basis/`;
|
|
174
|
+
let sharedDraco = null;
|
|
175
|
+
let sharedKtx2 = null;
|
|
176
|
+
let ktx2DetectedFor = null;
|
|
177
|
+
function dirOf(url) {
|
|
178
|
+
const clean = String(url || '').split('?')[0].split('#')[0];
|
|
179
|
+
const slash = clean.lastIndexOf('/');
|
|
180
|
+
return slash >= 0 ? clean.slice(0, slash + 1) : '';
|
|
181
|
+
}
|
|
182
|
+
function asText(data) {
|
|
183
|
+
if (typeof data === 'string')
|
|
184
|
+
return data;
|
|
185
|
+
if (data instanceof ArrayBuffer)
|
|
186
|
+
return new TextDecoder().decode(data);
|
|
187
|
+
if (ArrayBuffer.isView(data)) {
|
|
188
|
+
return new TextDecoder().decode(data);
|
|
189
|
+
}
|
|
190
|
+
if (data && typeof data === 'object')
|
|
191
|
+
return JSON.stringify(data);
|
|
192
|
+
throw new Error('expected text payload for this model format');
|
|
193
|
+
}
|
|
194
|
+
function asBuffer(data) {
|
|
195
|
+
if (data instanceof ArrayBuffer)
|
|
196
|
+
return data;
|
|
197
|
+
if (ArrayBuffer.isView(data)) {
|
|
198
|
+
const view = data;
|
|
199
|
+
return view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength);
|
|
200
|
+
}
|
|
201
|
+
throw new Error('expected binary payload for this model format');
|
|
202
|
+
}
|
|
203
|
+
function wrapGroup(object, animations = []) {
|
|
204
|
+
if (object instanceof three.Group) {
|
|
205
|
+
return { scene: object, animations };
|
|
206
|
+
}
|
|
207
|
+
const scene = new three.Group();
|
|
208
|
+
scene.add(object);
|
|
209
|
+
return { scene, animations };
|
|
210
|
+
}
|
|
211
|
+
function geometryToModel(geometry) {
|
|
212
|
+
geometry.computeVertexNormals?.();
|
|
213
|
+
const mesh = new three.Mesh(geometry, new three.MeshStandardMaterial({ color: 0x888888, metalness: 0.1, roughness: 0.8 }));
|
|
214
|
+
const scene = new three.Group();
|
|
215
|
+
scene.add(mesh);
|
|
216
|
+
return { scene, animations: [] };
|
|
217
|
+
}
|
|
218
|
+
function modelPayload(res) {
|
|
219
|
+
const slot = res.src?.model || res.src?.glb || res.src?.gltf;
|
|
220
|
+
const data = res.data?.model ?? res.data?.glb ?? res.data?.gltf;
|
|
221
|
+
if (data == null) {
|
|
222
|
+
throw new Error(`Resource "${res.name}" has no model data; use RESOURCE_TYPE.MODEL with src.model.url`);
|
|
223
|
+
}
|
|
224
|
+
const type = String(slot?.type || 'glb').toLowerCase();
|
|
225
|
+
return { data, type, path: dirOf(slot?.url || '') };
|
|
226
|
+
}
|
|
227
|
+
function ensureGltfExtras(loader, renderer) {
|
|
228
|
+
if (!sharedDraco) {
|
|
229
|
+
sharedDraco = new DRACOLoader_js.DRACOLoader();
|
|
230
|
+
sharedDraco.setDecoderPath(DRACO_DECODER_PATH);
|
|
231
|
+
}
|
|
232
|
+
loader.setDRACOLoader(sharedDraco);
|
|
233
|
+
if (!sharedKtx2) {
|
|
234
|
+
sharedKtx2 = new KTX2Loader_js.KTX2Loader();
|
|
235
|
+
sharedKtx2.setTranscoderPath(BASIS_TRANSCODER_PATH);
|
|
236
|
+
}
|
|
237
|
+
if (renderer && ktx2DetectedFor !== renderer) {
|
|
238
|
+
sharedKtx2.detectSupport(renderer);
|
|
239
|
+
ktx2DetectedFor = renderer;
|
|
240
|
+
}
|
|
241
|
+
loader.setKTX2Loader(sharedKtx2);
|
|
242
|
+
loader.setMeshoptDecoder(meshopt_decoder_module_js.MeshoptDecoder);
|
|
243
|
+
}
|
|
244
|
+
function parseGltf(data, path, renderer) {
|
|
245
|
+
const loader = new GLTFLoader_js.GLTFLoader();
|
|
246
|
+
ensureGltfExtras(loader, renderer);
|
|
247
|
+
const payload = typeof data === 'object' && data && !(data instanceof ArrayBuffer) && !ArrayBuffer.isView(data)
|
|
248
|
+
? JSON.stringify(data)
|
|
249
|
+
: data instanceof ArrayBuffer || ArrayBuffer.isView(data)
|
|
250
|
+
? asBuffer(data)
|
|
251
|
+
: asText(data);
|
|
252
|
+
return new Promise((resolve, reject) => {
|
|
253
|
+
loader.parse(payload, path, (gltf) => {
|
|
254
|
+
resolve(wrapGroup(gltf.scene, gltf.animations || []));
|
|
255
|
+
}, (err) => {
|
|
256
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
async function parseFbx(data, path) {
|
|
261
|
+
const loader = new FBXLoader_js.FBXLoader();
|
|
262
|
+
const object = loader.parse(asBuffer(data), path);
|
|
263
|
+
const animations = (object.animations || []);
|
|
264
|
+
return wrapGroup(object, animations);
|
|
265
|
+
}
|
|
266
|
+
async function parseObj(res, data, path) {
|
|
267
|
+
const objLoader = new OBJLoader_js.OBJLoader();
|
|
268
|
+
const mtlText = res.data?.mtl;
|
|
269
|
+
if (mtlText != null) {
|
|
270
|
+
const mtlLoader = new MTLLoader_js.MTLLoader();
|
|
271
|
+
const mtlPath = dirOf(res.src?.mtl?.url || '') || path;
|
|
272
|
+
const materials = mtlLoader.parse(asText(mtlText), mtlPath);
|
|
273
|
+
materials.preload();
|
|
274
|
+
objLoader.setMaterials(materials);
|
|
275
|
+
}
|
|
276
|
+
return wrapGroup(objLoader.parse(asText(data)));
|
|
277
|
+
}
|
|
278
|
+
async function parseCollada(data, path) {
|
|
279
|
+
const loader = new ColladaLoader_js.ColladaLoader();
|
|
280
|
+
const result = loader.parse(asText(data), path);
|
|
281
|
+
return wrapGroup(result.scene, result.animations || []);
|
|
282
|
+
}
|
|
283
|
+
async function parseModelResource(res, renderer) {
|
|
284
|
+
const { data, type, path } = modelPayload(res);
|
|
285
|
+
switch (type) {
|
|
286
|
+
case 'glb':
|
|
287
|
+
case 'gltf':
|
|
288
|
+
return parseGltf(data, path, renderer);
|
|
289
|
+
case 'fbx':
|
|
290
|
+
return parseFbx(data, path);
|
|
291
|
+
case 'obj':
|
|
292
|
+
return parseObj(res, data, path);
|
|
293
|
+
case 'stl':
|
|
294
|
+
return geometryToModel(new STLLoader_js.STLLoader().parse(asBuffer(data)));
|
|
295
|
+
case 'ply':
|
|
296
|
+
return geometryToModel(new PLYLoader_js.PLYLoader().parse(asBuffer(data)));
|
|
297
|
+
case 'dae':
|
|
298
|
+
case 'collada':
|
|
299
|
+
return parseCollada(data, path);
|
|
300
|
+
default:
|
|
301
|
+
throw new Error(`Unsupported 3D model type "${type}" for resource "${res.name}". ` +
|
|
302
|
+
'Use glb, gltf, fbx, obj, stl, dae, or ply.');
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
function createModelInstance(res) {
|
|
306
|
+
let cached = null;
|
|
307
|
+
return {
|
|
308
|
+
async parse(renderer) {
|
|
309
|
+
if (!cached) {
|
|
310
|
+
cached = await parseModelResource(res, renderer);
|
|
311
|
+
}
|
|
312
|
+
return cached;
|
|
313
|
+
},
|
|
314
|
+
dispose() {
|
|
315
|
+
cached = null;
|
|
316
|
+
},
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
engine.resource.registerInstance(engine.RESOURCE_TYPE.MODEL, (res) => createModelInstance(res));
|
|
320
|
+
engine.resource.registerInstance(engine.RESOURCE_TYPE.GLB, (res) => createModelInstance(res));
|
|
321
|
+
engine.resource.registerDestroy(engine.RESOURCE_TYPE.MODEL, ({ instance }) => {
|
|
322
|
+
instance?.dispose?.();
|
|
323
|
+
});
|
|
324
|
+
engine.resource.registerDestroy(engine.RESOURCE_TYPE.GLB, ({ instance }) => {
|
|
325
|
+
instance?.dispose?.();
|
|
326
|
+
});
|
|
327
|
+
|
|
159
328
|
let Model3DSystem = class Model3DSystem extends pluginRenderer3d.Renderer3D {
|
|
160
329
|
constructor() {
|
|
161
330
|
super(...arguments);
|
|
@@ -196,7 +365,7 @@ let Model3DSystem = class Model3DSystem extends pluginRenderer3d.Renderer3D {
|
|
|
196
365
|
if (!component.resource)
|
|
197
366
|
return;
|
|
198
367
|
const asyncId = this.increaseAsyncId(gameObject.id);
|
|
199
|
-
await this.
|
|
368
|
+
await this.attachNamedModel(gameObject.id, component.resource);
|
|
200
369
|
if (!this.validateAsyncId(gameObject.id, asyncId))
|
|
201
370
|
return;
|
|
202
371
|
if (component.autoPlay) {
|
|
@@ -211,7 +380,7 @@ let Model3DSystem = class Model3DSystem extends pluginRenderer3d.Renderer3D {
|
|
|
211
380
|
if (!component.resource)
|
|
212
381
|
return;
|
|
213
382
|
const asyncId = this.increaseAsyncId(changed.gameObject.id);
|
|
214
|
-
await this.
|
|
383
|
+
await this.attachNamedModel(changed.gameObject.id, component.resource);
|
|
215
384
|
if (!this.validateAsyncId(changed.gameObject.id, asyncId))
|
|
216
385
|
return;
|
|
217
386
|
if (component.autoPlay) {
|
|
@@ -222,6 +391,16 @@ let Model3DSystem = class Model3DSystem extends pluginRenderer3d.Renderer3D {
|
|
|
222
391
|
this.threeContext.playAnimation(changed.gameObject.id, component.animationIndex, component.speed);
|
|
223
392
|
}
|
|
224
393
|
}
|
|
394
|
+
async attachNamedModel(id, name) {
|
|
395
|
+
const res = await pluginRenderer3d.requireNamedResource(name);
|
|
396
|
+
const instance = res.instance;
|
|
397
|
+
if (!instance || typeof instance.parse !== 'function') {
|
|
398
|
+
throw new Error(`Resource "${name}" is not a MODEL instance; register RESOURCE_TYPE.MODEL and import Model3DSystem`);
|
|
399
|
+
}
|
|
400
|
+
const parsed = await instance.parse(this.threeContext.renderer);
|
|
401
|
+
const clone = SkeletonUtils_js.clone(parsed.scene);
|
|
402
|
+
this.threeContext.attachParsedModel(id, clone, parsed.animations);
|
|
403
|
+
}
|
|
225
404
|
};
|
|
226
405
|
Model3DSystem = tslib.__decorate([
|
|
227
406
|
engine.decorators.componentObserver({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-renderer-3d-model.cjs.js","sources":["../lib/component.ts","../lib/system.ts"],"sourcesContent":["import { Component } from '@combos-fun/engine';\nimport { Field } from '@combos-fun/inspector-decorator';\n\nexport interface Model3DParams {\n resource?: string;\n autoPlay?: boolean;\n animationIndex?: number;\n speed?: number;\n positionX?: number;\n positionY?: number;\n positionZ?: number;\n rotationX?: number;\n rotationY?: number;\n rotationZ?: number;\n scaleX?: number;\n scaleY?: number;\n scaleZ?: number;\n}\n\nexport default class Model3D extends Component<Model3DParams> {\n static componentName: string = 'Model3D';\n\n @Field({\n\n type: 'string',\n\n group: 'Model3D',\n\n label: 'resource',\n\n description: 'Resource id from the asset registry.',\n\n editor: 'text',\n\n })\n\n resource: string = '';\n @Field({\n type: 'boolean',\n group: 'Model3D',\n label: 'autoPlay',\n description: 'Start playing automatically when loaded.',\n editor: 'toggle',\n })\n autoPlay: boolean = true;\n @Field({\n type: 'number',\n group: 'Model3D',\n label: 'animationIndex',\n description: 'Animation clip index.',\n editor: 'number-stepper',\n })\n animationIndex: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'speed',\n description: 'Playback speed.',\n editor: 'number-stepper',\n })\n speed: number = 1;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'positionX',\n description: 'Local X position.',\n editor: 'number-stepper',\n })\n positionX: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'positionY',\n description: 'Local Y position.',\n editor: 'number-stepper',\n })\n positionY: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'positionZ',\n description: 'Local Z position.',\n editor: 'number-stepper',\n })\n positionZ: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Model3D',\n label: 'rotationX',\n description: 'Rotation around X in radians.',\n editor: 'number-stepper',\n })\n rotationX: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Model3D',\n label: 'rotationY',\n description: 'Rotation around Y in radians.',\n editor: 'number-stepper',\n })\n rotationY: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Model3D',\n label: 'rotationZ',\n description: 'Rotation around Z in radians.',\n editor: 'number-stepper',\n })\n rotationZ: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'scaleX',\n description: 'Scale on X.',\n editor: 'number-stepper',\n })\n scaleX: number = 1;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'scaleY',\n description: 'Scale on Y.',\n editor: 'number-stepper',\n })\n scaleY: number = 1;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'scaleZ',\n description: 'Scale on Z.',\n editor: 'number-stepper',\n })\n scaleZ: number = 1;\n\n init(obj?: Model3DParams) {\n if (obj) Object.assign(this, obj);\n }\n}\n","import { decorators, ComponentChanged, OBSERVER_TYPE, GameObject } from '@combos-fun/engine';\nimport { Renderer3D, Renderer3DSystem } from '@combos-fun/plugin-renderer-3d';\nimport Model3D from './component';\n\n@decorators.componentObserver({\n Model3D: [\n 'resource',\n 'positionX', 'positionY', 'positionZ',\n 'rotationX', 'rotationY', 'rotationZ',\n 'scaleX', 'scaleY', 'scaleZ',\n 'speed', 'animationIndex',\n ],\n})\nexport default class Model3DSystem extends Renderer3D {\n static systemName = 'Model3DSystem';\n name: string = 'Model3DSystem';\n\n init() {\n const renderer3DSystem = this.game.getSystem(Renderer3DSystem) as Renderer3DSystem;\n renderer3DSystem.rendererManager.register(this);\n }\n\n componentChanged(changed: ComponentChanged) {\n if (changed.componentName !== 'Model3D') return;\n\n const component = changed.component as Model3D;\n\n if (changed.type === OBSERVER_TYPE.ADD) {\n this.handleAdd(changed.gameObject, component);\n } else if (changed.type === OBSERVER_TYPE.CHANGE) {\n this.handleChange(changed);\n } else if (changed.type === OBSERVER_TYPE.REMOVE) {\n this.increaseAsyncId(changed.gameObject.id);\n this.threeContext.removeModel(changed.gameObject.id);\n }\n }\n\n rendererUpdate(gameObject: GameObject) {\n const component = gameObject.getComponent(Model3D) as Model3D;\n if (!component) return;\n\n const model = this.threeContext.models.get(gameObject.id);\n if (!model) return;\n\n model.position.set(component.positionX, component.positionY, component.positionZ);\n model.rotation.set(component.rotationX, component.rotationY, component.rotationZ);\n model.scale.set(component.scaleX, component.scaleY, component.scaleZ);\n }\n\n private async handleAdd(gameObject: GameObject, component: Model3D) {\n if (!component.resource) return;\n\n const asyncId = this.increaseAsyncId(gameObject.id);\n await this.threeContext.loadGLB(gameObject.id, component.resource);\n if (!this.validateAsyncId(gameObject.id, asyncId)) return;\n\n if (component.autoPlay) {\n this.threeContext.playAnimation(\n gameObject.id,\n component.animationIndex,\n component.speed,\n );\n }\n }\n\n private async handleChange(changed: ComponentChanged) {\n const component = changed.component as Model3D;\n const changedProp = changed.prop?.prop?.[0];\n\n if (changedProp === 'resource') {\n this.threeContext.removeModel(changed.gameObject.id);\n if (!component.resource) return;\n\n const asyncId = this.increaseAsyncId(changed.gameObject.id);\n await this.threeContext.loadGLB(changed.gameObject.id, component.resource);\n if (!this.validateAsyncId(changed.gameObject.id, asyncId)) return;\n\n if (component.autoPlay) {\n this.threeContext.playAnimation(\n changed.gameObject.id,\n component.animationIndex,\n component.speed,\n );\n }\n }\n\n if (changedProp === 'speed' || changedProp === 'animationIndex') {\n this.threeContext.playAnimation(\n changed.gameObject.id,\n component.animationIndex,\n component.speed,\n );\n }\n }\n}\n"],"names":["Component","__decorate","Field","Renderer3D","Renderer3DSystem","OBSERVER_TYPE","decorators"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugin-renderer-3d-model.cjs.js","sources":["../lib/component.ts","../lib/parseModel.ts","../lib/system.ts"],"sourcesContent":["import { Component } from '@combos-fun/engine';\nimport { Field } from '@combos-fun/inspector-decorator';\n\nexport interface Model3DParams {\n resource?: string;\n autoPlay?: boolean;\n animationIndex?: number;\n speed?: number;\n positionX?: number;\n positionY?: number;\n positionZ?: number;\n rotationX?: number;\n rotationY?: number;\n rotationZ?: number;\n scaleX?: number;\n scaleY?: number;\n scaleZ?: number;\n}\n\nexport default class Model3D extends Component<Model3DParams> {\n static componentName: string = 'Model3D';\n\n @Field({\n\n type: 'string',\n\n group: 'Model3D',\n\n label: 'resource',\n\n description: 'Engine resource name registered with RESOURCE_TYPE.MODEL.',\n\n editor: 'text',\n\n })\n\n resource: string = '';\n @Field({\n type: 'boolean',\n group: 'Model3D',\n label: 'autoPlay',\n description: 'Start playing automatically when loaded.',\n editor: 'toggle',\n })\n autoPlay: boolean = true;\n @Field({\n type: 'number',\n group: 'Model3D',\n label: 'animationIndex',\n description: 'Animation clip index.',\n editor: 'number-stepper',\n })\n animationIndex: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'speed',\n description: 'Playback speed.',\n editor: 'number-stepper',\n })\n speed: number = 1;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'positionX',\n description: 'Local X position.',\n editor: 'number-stepper',\n })\n positionX: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'positionY',\n description: 'Local Y position.',\n editor: 'number-stepper',\n })\n positionY: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'positionZ',\n description: 'Local Z position.',\n editor: 'number-stepper',\n })\n positionZ: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Model3D',\n label: 'rotationX',\n description: 'Rotation around X in radians.',\n editor: 'number-stepper',\n })\n rotationX: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Model3D',\n label: 'rotationY',\n description: 'Rotation around Y in radians.',\n editor: 'number-stepper',\n })\n rotationY: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Model3D',\n label: 'rotationZ',\n description: 'Rotation around Z in radians.',\n editor: 'number-stepper',\n })\n rotationZ: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'scaleX',\n description: 'Scale on X.',\n editor: 'number-stepper',\n })\n scaleX: number = 1;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'scaleY',\n description: 'Scale on Y.',\n editor: 'number-stepper',\n })\n scaleY: number = 1;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'scaleZ',\n description: 'Scale on Z.',\n editor: 'number-stepper',\n })\n scaleZ: number = 1;\n\n init(obj?: Model3DParams) {\n if (obj) Object.assign(this, obj);\n }\n}\n","import { resource, RESOURCE_TYPE } from '@combos-fun/engine';\nimport type { ResourceStruct } from '@combos-fun/engine';\nimport {\n AnimationClip,\n BufferGeometry,\n Group,\n Mesh,\n MeshStandardMaterial,\n Object3D,\n} from 'three';\nimport type { WebGLRenderer } from 'three';\nimport { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';\nimport { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';\nimport { KTX2Loader } from 'three/addons/loaders/KTX2Loader.js';\nimport { FBXLoader } from 'three/addons/loaders/FBXLoader.js';\nimport { OBJLoader } from 'three/addons/loaders/OBJLoader.js';\nimport { MTLLoader } from 'three/addons/loaders/MTLLoader.js';\nimport { STLLoader } from 'three/addons/loaders/STLLoader.js';\nimport { ColladaLoader } from 'three/addons/loaders/ColladaLoader.js';\nimport { PLYLoader } from 'three/addons/loaders/PLYLoader.js';\nimport { MeshoptDecoder } from 'three/addons/libs/meshopt_decoder.module.js';\n\nexport interface ParsedModel {\n scene: Group;\n animations: AnimationClip[];\n}\n\nexport interface ModelResourceInstance {\n parse(renderer?: WebGLRenderer): Promise<ParsedModel>;\n dispose(): void;\n}\n\nconst THREE_ADDON_CDN = 'https://unpkg.com/three@0.172.0/examples/jsm/libs';\nconst DRACO_DECODER_PATH = 'https://www.gstatic.com/draco/versioned/decoders/1.5.7/';\nconst BASIS_TRANSCODER_PATH = `${THREE_ADDON_CDN}/basis/`;\n\nlet sharedDraco: DRACOLoader | null = null;\nlet sharedKtx2: KTX2Loader | null = null;\nlet ktx2DetectedFor: WebGLRenderer | null = null;\n\nfunction dirOf(url: string): string {\n const clean = String(url || '').split('?')[0].split('#')[0];\n const slash = clean.lastIndexOf('/');\n return slash >= 0 ? clean.slice(0, slash + 1) : '';\n}\n\nfunction asText(data: unknown): string {\n if (typeof data === 'string') return data;\n if (data instanceof ArrayBuffer) return new TextDecoder().decode(data);\n if (ArrayBuffer.isView(data)) {\n return new TextDecoder().decode(data as ArrayBufferView);\n }\n if (data && typeof data === 'object') return JSON.stringify(data);\n throw new Error('expected text payload for this model format');\n}\n\nfunction asBuffer(data: unknown): ArrayBuffer {\n if (data instanceof ArrayBuffer) return data;\n if (ArrayBuffer.isView(data)) {\n const view = data as ArrayBufferView;\n return view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength);\n }\n throw new Error('expected binary payload for this model format');\n}\n\nfunction wrapGroup(object: Object3D, animations: AnimationClip[] = []): ParsedModel {\n if (object instanceof Group) {\n return { scene: object, animations };\n }\n const scene = new Group();\n scene.add(object);\n return { scene, animations };\n}\n\nfunction geometryToModel(geometry: BufferGeometry): ParsedModel {\n geometry.computeVertexNormals?.();\n const mesh = new Mesh(\n geometry,\n new MeshStandardMaterial({ color: 0x888888, metalness: 0.1, roughness: 0.8 }),\n );\n const scene = new Group();\n scene.add(mesh);\n return { scene, animations: [] };\n}\n\nfunction modelPayload(res: ResourceStruct): { data: unknown; type: string; path: string } {\n const slot = res.src?.model || res.src?.glb || res.src?.gltf;\n const data = res.data?.model ?? res.data?.glb ?? res.data?.gltf;\n if (data == null) {\n throw new Error(\n `Resource \"${res.name}\" has no model data; use RESOURCE_TYPE.MODEL with src.model.url`,\n );\n }\n const type = String(slot?.type || 'glb').toLowerCase();\n return { data, type, path: dirOf(slot?.url || '') };\n}\n\nfunction ensureGltfExtras(loader: GLTFLoader, renderer?: WebGLRenderer) {\n if (!sharedDraco) {\n sharedDraco = new DRACOLoader();\n sharedDraco.setDecoderPath(DRACO_DECODER_PATH);\n }\n loader.setDRACOLoader(sharedDraco);\n\n if (!sharedKtx2) {\n sharedKtx2 = new KTX2Loader();\n sharedKtx2.setTranscoderPath(BASIS_TRANSCODER_PATH);\n }\n if (renderer && ktx2DetectedFor !== renderer) {\n sharedKtx2.detectSupport(renderer);\n ktx2DetectedFor = renderer;\n }\n loader.setKTX2Loader(sharedKtx2);\n loader.setMeshoptDecoder(MeshoptDecoder);\n}\n\nfunction parseGltf(\n data: unknown,\n path: string,\n renderer?: WebGLRenderer,\n): Promise<ParsedModel> {\n const loader = new GLTFLoader();\n ensureGltfExtras(loader, renderer);\n const payload =\n typeof data === 'object' && data && !(data instanceof ArrayBuffer) && !ArrayBuffer.isView(data)\n ? JSON.stringify(data)\n : data instanceof ArrayBuffer || ArrayBuffer.isView(data)\n ? asBuffer(data)\n : asText(data);\n\n return new Promise((resolve, reject) => {\n loader.parse(\n payload as ArrayBuffer | string,\n path,\n (gltf) => {\n resolve(wrapGroup(gltf.scene, gltf.animations || []));\n },\n (err) => {\n reject(err instanceof Error ? err : new Error(String(err)));\n },\n );\n });\n}\n\nasync function parseFbx(data: unknown, path: string): Promise<ParsedModel> {\n const loader = new FBXLoader();\n const object = loader.parse(asBuffer(data), path);\n const animations = (object.animations || []) as AnimationClip[];\n return wrapGroup(object, animations);\n}\n\nasync function parseObj(res: ResourceStruct, data: unknown, path: string): Promise<ParsedModel> {\n const objLoader = new OBJLoader();\n const mtlText = res.data?.mtl;\n if (mtlText != null) {\n const mtlLoader = new MTLLoader();\n const mtlPath = dirOf(res.src?.mtl?.url || '') || path;\n const materials = mtlLoader.parse(asText(mtlText), mtlPath);\n materials.preload();\n objLoader.setMaterials(materials);\n }\n return wrapGroup(objLoader.parse(asText(data)));\n}\n\nasync function parseCollada(data: unknown, path: string): Promise<ParsedModel> {\n const loader = new ColladaLoader();\n const result = loader.parse(asText(data), path);\n return wrapGroup(result.scene, result.animations || []);\n}\n\nexport async function parseModelResource(\n res: ResourceStruct,\n renderer?: WebGLRenderer,\n): Promise<ParsedModel> {\n const { data, type, path } = modelPayload(res);\n switch (type) {\n case 'glb':\n case 'gltf':\n return parseGltf(data, path, renderer);\n case 'fbx':\n return parseFbx(data, path);\n case 'obj':\n return parseObj(res, data, path);\n case 'stl':\n return geometryToModel(new STLLoader().parse(asBuffer(data)));\n case 'ply':\n return geometryToModel(new PLYLoader().parse(asBuffer(data)));\n case 'dae':\n case 'collada':\n return parseCollada(data, path);\n default:\n throw new Error(\n `Unsupported 3D model type \"${type}\" for resource \"${res.name}\". ` +\n 'Use glb, gltf, fbx, obj, stl, dae, or ply.',\n );\n }\n}\n\nfunction createModelInstance(res: ResourceStruct): ModelResourceInstance {\n let cached: ParsedModel | null = null;\n return {\n async parse(renderer?: WebGLRenderer) {\n if (!cached) {\n cached = await parseModelResource(res, renderer);\n }\n return cached;\n },\n dispose() {\n cached = null;\n },\n };\n}\n\nresource.registerInstance(RESOURCE_TYPE.MODEL, (res) => createModelInstance(res));\nresource.registerInstance(RESOURCE_TYPE.GLB, (res) => createModelInstance(res));\nresource.registerDestroy(RESOURCE_TYPE.MODEL, ({ instance }) => {\n instance?.dispose?.();\n});\nresource.registerDestroy(RESOURCE_TYPE.GLB, ({ instance }) => {\n instance?.dispose?.();\n});\n","import { decorators, ComponentChanged, OBSERVER_TYPE, GameObject } from '@combos-fun/engine';\nimport {\n Renderer3D,\n Renderer3DSystem,\n requireNamedResource,\n} from '@combos-fun/plugin-renderer-3d';\nimport { Group } from 'three';\nimport { clone as cloneSkinned } from 'three/addons/utils/SkeletonUtils.js';\nimport Model3D from './component';\nimport './parseModel';\nimport type { ModelResourceInstance } from './parseModel';\n\n@decorators.componentObserver({\n Model3D: [\n 'resource',\n 'positionX', 'positionY', 'positionZ',\n 'rotationX', 'rotationY', 'rotationZ',\n 'scaleX', 'scaleY', 'scaleZ',\n 'speed', 'animationIndex',\n ],\n})\nexport default class Model3DSystem extends Renderer3D {\n static systemName = 'Model3DSystem';\n name: string = 'Model3DSystem';\n\n init() {\n const renderer3DSystem = this.game.getSystem(Renderer3DSystem) as Renderer3DSystem;\n renderer3DSystem.rendererManager.register(this);\n }\n\n componentChanged(changed: ComponentChanged) {\n if (changed.componentName !== 'Model3D') return;\n\n const component = changed.component as Model3D;\n\n if (changed.type === OBSERVER_TYPE.ADD) {\n this.handleAdd(changed.gameObject, component);\n } else if (changed.type === OBSERVER_TYPE.CHANGE) {\n this.handleChange(changed);\n } else if (changed.type === OBSERVER_TYPE.REMOVE) {\n this.increaseAsyncId(changed.gameObject.id);\n this.threeContext.removeModel(changed.gameObject.id);\n }\n }\n\n rendererUpdate(gameObject: GameObject) {\n const component = gameObject.getComponent(Model3D) as Model3D;\n if (!component) return;\n\n const model = this.threeContext.models.get(gameObject.id);\n if (!model) return;\n\n model.position.set(component.positionX, component.positionY, component.positionZ);\n model.rotation.set(component.rotationX, component.rotationY, component.rotationZ);\n model.scale.set(component.scaleX, component.scaleY, component.scaleZ);\n }\n\n private async handleAdd(gameObject: GameObject, component: Model3D) {\n if (!component.resource) return;\n\n const asyncId = this.increaseAsyncId(gameObject.id);\n await this.attachNamedModel(gameObject.id, component.resource);\n if (!this.validateAsyncId(gameObject.id, asyncId)) return;\n\n if (component.autoPlay) {\n this.threeContext.playAnimation(\n gameObject.id,\n component.animationIndex,\n component.speed,\n );\n }\n }\n\n private async handleChange(changed: ComponentChanged) {\n const component = changed.component as Model3D;\n const changedProp = changed.prop?.prop?.[0];\n\n if (changedProp === 'resource') {\n this.threeContext.removeModel(changed.gameObject.id);\n if (!component.resource) return;\n\n const asyncId = this.increaseAsyncId(changed.gameObject.id);\n await this.attachNamedModel(changed.gameObject.id, component.resource);\n if (!this.validateAsyncId(changed.gameObject.id, asyncId)) return;\n\n if (component.autoPlay) {\n this.threeContext.playAnimation(\n changed.gameObject.id,\n component.animationIndex,\n component.speed,\n );\n }\n }\n\n if (changedProp === 'speed' || changedProp === 'animationIndex') {\n this.threeContext.playAnimation(\n changed.gameObject.id,\n component.animationIndex,\n component.speed,\n );\n }\n }\n\n private async attachNamedModel(id: number, name: string) {\n const res = await requireNamedResource(name);\n const instance = res.instance as ModelResourceInstance | undefined;\n if (!instance || typeof instance.parse !== 'function') {\n throw new Error(\n `Resource \"${name}\" is not a MODEL instance; register RESOURCE_TYPE.MODEL and import Model3DSystem`,\n );\n }\n const parsed = await instance.parse(this.threeContext.renderer);\n const clone = cloneSkinned(parsed.scene) as Group;\n this.threeContext.attachParsedModel(id, clone, parsed.animations);\n }\n}\n"],"names":["Component","__decorate","Field","Group","Mesh","MeshStandardMaterial","DRACOLoader","KTX2Loader","MeshoptDecoder","GLTFLoader","FBXLoader","OBJLoader","MTLLoader","ColladaLoader","STLLoader","PLYLoader","resource","RESOURCE_TYPE","Renderer3D","Renderer3DSystem","OBSERVER_TYPE","requireNamedResource","cloneSkinned","decorators"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("tslib"),t=require("@combos-fun/engine"),
|
|
1
|
+
"use strict";var e=require("tslib"),t=require("@combos-fun/engine"),r=require("@combos-fun/inspector-decorator"),o=require("@combos-fun/plugin-renderer-3d"),n=require("three/addons/utils/SkeletonUtils.js"),s=require("three"),i=require("three/addons/loaders/GLTFLoader.js"),a=require("three/addons/loaders/DRACOLoader.js"),d=require("three/addons/loaders/KTX2Loader.js"),c=require("three/addons/loaders/FBXLoader.js"),p=require("three/addons/loaders/OBJLoader.js"),l=require("three/addons/loaders/MTLLoader.js"),u=require("three/addons/loaders/STLLoader.js"),m=require("three/addons/loaders/ColladaLoader.js"),h=require("three/addons/loaders/PLYLoader.js"),y=require("three/addons/libs/meshopt_decoder.module.js");class f extends t.Component{constructor(){super(...arguments),this.resource="",this.autoPlay=!0,this.animationIndex=0,this.speed=1,this.positionX=0,this.positionY=0,this.positionZ=0,this.rotationX=0,this.rotationY=0,this.rotationZ=0,this.scaleX=1,this.scaleY=1,this.scaleZ=1}static{this.componentName="Model3D"}init(e){e&&Object.assign(this,e)}}e.__decorate([r.Field({type:"string",group:"Model3D",label:"resource",description:"Engine resource name registered with RESOURCE_TYPE.MODEL.",editor:"text"})],f.prototype,"resource",void 0),e.__decorate([r.Field({type:"boolean",group:"Model3D",label:"autoPlay",description:"Start playing automatically when loaded.",editor:"toggle"})],f.prototype,"autoPlay",void 0),e.__decorate([r.Field({type:"number",group:"Model3D",label:"animationIndex",description:"Animation clip index.",editor:"number-stepper"})],f.prototype,"animationIndex",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Model3D",label:"speed",description:"Playback speed.",editor:"number-stepper"})],f.prototype,"speed",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Model3D",label:"positionX",description:"Local X position.",editor:"number-stepper"})],f.prototype,"positionX",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Model3D",label:"positionY",description:"Local Y position.",editor:"number-stepper"})],f.prototype,"positionY",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Model3D",label:"positionZ",description:"Local Z position.",editor:"number-stepper"})],f.prototype,"positionZ",void 0),e.__decorate([r.Field({type:"number",step:.01,group:"Model3D",label:"rotationX",description:"Rotation around X in radians.",editor:"number-stepper"})],f.prototype,"rotationX",void 0),e.__decorate([r.Field({type:"number",step:.01,group:"Model3D",label:"rotationY",description:"Rotation around Y in radians.",editor:"number-stepper"})],f.prototype,"rotationY",void 0),e.__decorate([r.Field({type:"number",step:.01,group:"Model3D",label:"rotationZ",description:"Rotation around Z in radians.",editor:"number-stepper"})],f.prototype,"rotationZ",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Model3D",label:"scaleX",description:"Scale on X.",editor:"number-stepper"})],f.prototype,"scaleX",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Model3D",label:"scaleY",description:"Scale on Y.",editor:"number-stepper"})],f.prototype,"scaleY",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Model3D",label:"scaleZ",description:"Scale on Z.",editor:"number-stepper"})],f.prototype,"scaleZ",void 0);let b=null,g=null,E=null;function w(e){const t=String(e||"").split("?")[0].split("#")[0],r=t.lastIndexOf("/");return r>=0?t.slice(0,r+1):""}function M(e){if("string"==typeof e)return e;if(e instanceof ArrayBuffer)return(new TextDecoder).decode(e);if(ArrayBuffer.isView(e))return(new TextDecoder).decode(e);if(e&&"object"==typeof e)return JSON.stringify(e);throw new Error("expected text payload for this model format")}function D(e){if(e instanceof ArrayBuffer)return e;if(ArrayBuffer.isView(e)){const t=e;return t.buffer.slice(t.byteOffset,t.byteOffset+t.byteLength)}throw new Error("expected binary payload for this model format")}function L(e,t=[]){if(e instanceof s.Group)return{scene:e,animations:t};const r=new s.Group;return r.add(e),{scene:r,animations:t}}function _(e){e.computeVertexNormals?.();const t=new s.Mesh(e,new s.MeshStandardMaterial({color:8947848,metalness:.1,roughness:.8})),r=new s.Group;return r.add(t),{scene:r,animations:[]}}function O(e,t,r){const o=new i.GLTFLoader;!function(e,t){b||(b=new a.DRACOLoader,b.setDecoderPath("https://www.gstatic.com/draco/versioned/decoders/1.5.7/")),e.setDRACOLoader(b),g||(g=new d.KTX2Loader,g.setTranscoderPath("https://unpkg.com/three@0.172.0/examples/jsm/libs/basis/")),t&&E!==t&&(g.detectSupport(t),E=t),e.setKTX2Loader(g),e.setMeshoptDecoder(y.MeshoptDecoder)}(o,r);const n="object"!=typeof e||!e||e instanceof ArrayBuffer||ArrayBuffer.isView(e)?e instanceof ArrayBuffer||ArrayBuffer.isView(e)?D(e):M(e):JSON.stringify(e);return new Promise((e,r)=>{o.parse(n,t,t=>{e(L(t.scene,t.animations||[]))},e=>{r(e instanceof Error?e:new Error(String(e)))})})}async function x(e,t){const{data:r,type:o,path:n}=function(e){const t=e.src?.model||e.src?.glb||e.src?.gltf,r=e.data?.model??e.data?.glb??e.data?.gltf;if(null==r)throw new Error(`Resource "${e.name}" has no model data; use RESOURCE_TYPE.MODEL with src.model.url`);return{data:r,type:String(t?.type||"glb").toLowerCase(),path:w(t?.url||"")}}(e);switch(o){case"glb":case"gltf":return O(r,n,t);case"fbx":return async function(e,t){const r=(new c.FBXLoader).parse(D(e),t);return L(r,r.animations||[])}(r,n);case"obj":return async function(e,t,r){const o=new p.OBJLoader,n=e.data?.mtl;if(null!=n){const t=new l.MTLLoader,s=w(e.src?.mtl?.url||"")||r,i=t.parse(M(n),s);i.preload(),o.setMaterials(i)}return L(o.parse(M(t)))}(e,r,n);case"stl":return _((new u.STLLoader).parse(D(r)));case"ply":return _((new h.PLYLoader).parse(D(r)));case"dae":case"collada":return async function(e,t){const r=(new m.ColladaLoader).parse(M(e),t);return L(r.scene,r.animations||[])}(r,n);default:throw new Error(`Unsupported 3D model type "${o}" for resource "${e.name}". Use glb, gltf, fbx, obj, stl, dae, or ply.`)}}function R(e){let t=null;return{parse:async r=>(t||(t=await x(e,r)),t),dispose(){t=null}}}t.resource.registerInstance(t.RESOURCE_TYPE.MODEL,e=>R(e)),t.resource.registerInstance(t.RESOURCE_TYPE.GLB,e=>R(e)),t.resource.registerDestroy(t.RESOURCE_TYPE.MODEL,({instance:e})=>{e?.dispose?.()}),t.resource.registerDestroy(t.RESOURCE_TYPE.GLB,({instance:e})=>{e?.dispose?.()});let S=class extends o.Renderer3D{constructor(){super(...arguments),this.name="Model3DSystem"}static{this.systemName="Model3DSystem"}init(){this.game.getSystem(o.Renderer3DSystem).rendererManager.register(this)}componentChanged(e){if("Model3D"!==e.componentName)return;const r=e.component;e.type===t.OBSERVER_TYPE.ADD?this.handleAdd(e.gameObject,r):e.type===t.OBSERVER_TYPE.CHANGE?this.handleChange(e):e.type===t.OBSERVER_TYPE.REMOVE&&(this.increaseAsyncId(e.gameObject.id),this.threeContext.removeModel(e.gameObject.id))}rendererUpdate(e){const t=e.getComponent(f);if(!t)return;const r=this.threeContext.models.get(e.id);r&&(r.position.set(t.positionX,t.positionY,t.positionZ),r.rotation.set(t.rotationX,t.rotationY,t.rotationZ),r.scale.set(t.scaleX,t.scaleY,t.scaleZ))}async handleAdd(e,t){if(!t.resource)return;const r=this.increaseAsyncId(e.id);await this.attachNamedModel(e.id,t.resource),this.validateAsyncId(e.id,r)&&t.autoPlay&&this.threeContext.playAnimation(e.id,t.animationIndex,t.speed)}async handleChange(e){const t=e.component,r=e.prop?.prop?.[0];if("resource"===r){if(this.threeContext.removeModel(e.gameObject.id),!t.resource)return;const r=this.increaseAsyncId(e.gameObject.id);if(await this.attachNamedModel(e.gameObject.id,t.resource),!this.validateAsyncId(e.gameObject.id,r))return;t.autoPlay&&this.threeContext.playAnimation(e.gameObject.id,t.animationIndex,t.speed)}"speed"!==r&&"animationIndex"!==r||this.threeContext.playAnimation(e.gameObject.id,t.animationIndex,t.speed)}async attachNamedModel(e,t){const r=(await o.requireNamedResource(t)).instance;if(!r||"function"!=typeof r.parse)throw new Error(`Resource "${t}" is not a MODEL instance; register RESOURCE_TYPE.MODEL and import Model3DSystem`);const s=await r.parse(this.threeContext.renderer),i=n.clone(s.scene);this.threeContext.attachParsedModel(e,i,s.animations)}};S=e.__decorate([t.decorators.componentObserver({Model3D:["resource","positionX","positionY","positionZ","rotationX","rotationY","rotationZ","scaleX","scaleY","scaleZ","speed","animationIndex"]})],S);var Y=S;exports.Model3D=f,exports.Model3DSystem=Y;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Component, ComponentChanged, GameObject } from '@combos-fun/engine';
|
|
2
|
+
import { WebGLRenderer, Group, AnimationClip } from 'three';
|
|
2
3
|
import { Renderer3D } from '@combos-fun/plugin-renderer-3d';
|
|
3
4
|
|
|
4
5
|
interface Model3DParams {
|
|
@@ -34,6 +35,15 @@ declare class Model3D extends Component<Model3DParams> {
|
|
|
34
35
|
init(obj?: Model3DParams): void;
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
interface ParsedModel {
|
|
39
|
+
scene: Group;
|
|
40
|
+
animations: AnimationClip[];
|
|
41
|
+
}
|
|
42
|
+
interface ModelResourceInstance {
|
|
43
|
+
parse(renderer?: WebGLRenderer): Promise<ParsedModel>;
|
|
44
|
+
dispose(): void;
|
|
45
|
+
}
|
|
46
|
+
|
|
37
47
|
declare class Model3DSystem extends Renderer3D {
|
|
38
48
|
static systemName: string;
|
|
39
49
|
name: string;
|
|
@@ -42,7 +52,8 @@ declare class Model3DSystem extends Renderer3D {
|
|
|
42
52
|
rendererUpdate(gameObject: GameObject): void;
|
|
43
53
|
private handleAdd;
|
|
44
54
|
private handleChange;
|
|
55
|
+
private attachNamedModel;
|
|
45
56
|
}
|
|
46
57
|
|
|
47
58
|
export { Model3D, Model3DSystem };
|
|
48
|
-
export type { Model3DParams };
|
|
59
|
+
export type { Model3DParams, ModelResourceInstance, ParsedModel };
|
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
import { __decorate } from 'tslib';
|
|
2
|
-
import { Component, OBSERVER_TYPE, decorators } from '@combos-fun/engine';
|
|
2
|
+
import { Component, resource, RESOURCE_TYPE, OBSERVER_TYPE, decorators } from '@combos-fun/engine';
|
|
3
3
|
import { Field } from '@combos-fun/inspector-decorator';
|
|
4
|
-
import { Renderer3D, Renderer3DSystem } from '@combos-fun/plugin-renderer-3d';
|
|
4
|
+
import { Renderer3D, Renderer3DSystem, requireNamedResource } from '@combos-fun/plugin-renderer-3d';
|
|
5
|
+
import { clone } from 'three/addons/utils/SkeletonUtils.js';
|
|
6
|
+
import { Mesh, MeshStandardMaterial, Group } from 'three';
|
|
7
|
+
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
|
|
8
|
+
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';
|
|
9
|
+
import { KTX2Loader } from 'three/addons/loaders/KTX2Loader.js';
|
|
10
|
+
import { FBXLoader } from 'three/addons/loaders/FBXLoader.js';
|
|
11
|
+
import { OBJLoader } from 'three/addons/loaders/OBJLoader.js';
|
|
12
|
+
import { MTLLoader } from 'three/addons/loaders/MTLLoader.js';
|
|
13
|
+
import { STLLoader } from 'three/addons/loaders/STLLoader.js';
|
|
14
|
+
import { ColladaLoader } from 'three/addons/loaders/ColladaLoader.js';
|
|
15
|
+
import { PLYLoader } from 'three/addons/loaders/PLYLoader.js';
|
|
16
|
+
import { MeshoptDecoder } from 'three/addons/libs/meshopt_decoder.module.js';
|
|
5
17
|
|
|
6
18
|
class Model3D extends Component {
|
|
7
19
|
constructor() {
|
|
@@ -31,7 +43,7 @@ __decorate([
|
|
|
31
43
|
type: 'string',
|
|
32
44
|
group: 'Model3D',
|
|
33
45
|
label: 'resource',
|
|
34
|
-
description: '
|
|
46
|
+
description: 'Engine resource name registered with RESOURCE_TYPE.MODEL.',
|
|
35
47
|
editor: 'text',
|
|
36
48
|
})
|
|
37
49
|
], Model3D.prototype, "resource", void 0);
|
|
@@ -154,6 +166,163 @@ __decorate([
|
|
|
154
166
|
})
|
|
155
167
|
], Model3D.prototype, "scaleZ", void 0);
|
|
156
168
|
|
|
169
|
+
const THREE_ADDON_CDN = 'https://unpkg.com/three@0.172.0/examples/jsm/libs';
|
|
170
|
+
const DRACO_DECODER_PATH = 'https://www.gstatic.com/draco/versioned/decoders/1.5.7/';
|
|
171
|
+
const BASIS_TRANSCODER_PATH = `${THREE_ADDON_CDN}/basis/`;
|
|
172
|
+
let sharedDraco = null;
|
|
173
|
+
let sharedKtx2 = null;
|
|
174
|
+
let ktx2DetectedFor = null;
|
|
175
|
+
function dirOf(url) {
|
|
176
|
+
const clean = String(url || '').split('?')[0].split('#')[0];
|
|
177
|
+
const slash = clean.lastIndexOf('/');
|
|
178
|
+
return slash >= 0 ? clean.slice(0, slash + 1) : '';
|
|
179
|
+
}
|
|
180
|
+
function asText(data) {
|
|
181
|
+
if (typeof data === 'string')
|
|
182
|
+
return data;
|
|
183
|
+
if (data instanceof ArrayBuffer)
|
|
184
|
+
return new TextDecoder().decode(data);
|
|
185
|
+
if (ArrayBuffer.isView(data)) {
|
|
186
|
+
return new TextDecoder().decode(data);
|
|
187
|
+
}
|
|
188
|
+
if (data && typeof data === 'object')
|
|
189
|
+
return JSON.stringify(data);
|
|
190
|
+
throw new Error('expected text payload for this model format');
|
|
191
|
+
}
|
|
192
|
+
function asBuffer(data) {
|
|
193
|
+
if (data instanceof ArrayBuffer)
|
|
194
|
+
return data;
|
|
195
|
+
if (ArrayBuffer.isView(data)) {
|
|
196
|
+
const view = data;
|
|
197
|
+
return view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength);
|
|
198
|
+
}
|
|
199
|
+
throw new Error('expected binary payload for this model format');
|
|
200
|
+
}
|
|
201
|
+
function wrapGroup(object, animations = []) {
|
|
202
|
+
if (object instanceof Group) {
|
|
203
|
+
return { scene: object, animations };
|
|
204
|
+
}
|
|
205
|
+
const scene = new Group();
|
|
206
|
+
scene.add(object);
|
|
207
|
+
return { scene, animations };
|
|
208
|
+
}
|
|
209
|
+
function geometryToModel(geometry) {
|
|
210
|
+
geometry.computeVertexNormals?.();
|
|
211
|
+
const mesh = new Mesh(geometry, new MeshStandardMaterial({ color: 0x888888, metalness: 0.1, roughness: 0.8 }));
|
|
212
|
+
const scene = new Group();
|
|
213
|
+
scene.add(mesh);
|
|
214
|
+
return { scene, animations: [] };
|
|
215
|
+
}
|
|
216
|
+
function modelPayload(res) {
|
|
217
|
+
const slot = res.src?.model || res.src?.glb || res.src?.gltf;
|
|
218
|
+
const data = res.data?.model ?? res.data?.glb ?? res.data?.gltf;
|
|
219
|
+
if (data == null) {
|
|
220
|
+
throw new Error(`Resource "${res.name}" has no model data; use RESOURCE_TYPE.MODEL with src.model.url`);
|
|
221
|
+
}
|
|
222
|
+
const type = String(slot?.type || 'glb').toLowerCase();
|
|
223
|
+
return { data, type, path: dirOf(slot?.url || '') };
|
|
224
|
+
}
|
|
225
|
+
function ensureGltfExtras(loader, renderer) {
|
|
226
|
+
if (!sharedDraco) {
|
|
227
|
+
sharedDraco = new DRACOLoader();
|
|
228
|
+
sharedDraco.setDecoderPath(DRACO_DECODER_PATH);
|
|
229
|
+
}
|
|
230
|
+
loader.setDRACOLoader(sharedDraco);
|
|
231
|
+
if (!sharedKtx2) {
|
|
232
|
+
sharedKtx2 = new KTX2Loader();
|
|
233
|
+
sharedKtx2.setTranscoderPath(BASIS_TRANSCODER_PATH);
|
|
234
|
+
}
|
|
235
|
+
if (renderer && ktx2DetectedFor !== renderer) {
|
|
236
|
+
sharedKtx2.detectSupport(renderer);
|
|
237
|
+
ktx2DetectedFor = renderer;
|
|
238
|
+
}
|
|
239
|
+
loader.setKTX2Loader(sharedKtx2);
|
|
240
|
+
loader.setMeshoptDecoder(MeshoptDecoder);
|
|
241
|
+
}
|
|
242
|
+
function parseGltf(data, path, renderer) {
|
|
243
|
+
const loader = new GLTFLoader();
|
|
244
|
+
ensureGltfExtras(loader, renderer);
|
|
245
|
+
const payload = typeof data === 'object' && data && !(data instanceof ArrayBuffer) && !ArrayBuffer.isView(data)
|
|
246
|
+
? JSON.stringify(data)
|
|
247
|
+
: data instanceof ArrayBuffer || ArrayBuffer.isView(data)
|
|
248
|
+
? asBuffer(data)
|
|
249
|
+
: asText(data);
|
|
250
|
+
return new Promise((resolve, reject) => {
|
|
251
|
+
loader.parse(payload, path, (gltf) => {
|
|
252
|
+
resolve(wrapGroup(gltf.scene, gltf.animations || []));
|
|
253
|
+
}, (err) => {
|
|
254
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
async function parseFbx(data, path) {
|
|
259
|
+
const loader = new FBXLoader();
|
|
260
|
+
const object = loader.parse(asBuffer(data), path);
|
|
261
|
+
const animations = (object.animations || []);
|
|
262
|
+
return wrapGroup(object, animations);
|
|
263
|
+
}
|
|
264
|
+
async function parseObj(res, data, path) {
|
|
265
|
+
const objLoader = new OBJLoader();
|
|
266
|
+
const mtlText = res.data?.mtl;
|
|
267
|
+
if (mtlText != null) {
|
|
268
|
+
const mtlLoader = new MTLLoader();
|
|
269
|
+
const mtlPath = dirOf(res.src?.mtl?.url || '') || path;
|
|
270
|
+
const materials = mtlLoader.parse(asText(mtlText), mtlPath);
|
|
271
|
+
materials.preload();
|
|
272
|
+
objLoader.setMaterials(materials);
|
|
273
|
+
}
|
|
274
|
+
return wrapGroup(objLoader.parse(asText(data)));
|
|
275
|
+
}
|
|
276
|
+
async function parseCollada(data, path) {
|
|
277
|
+
const loader = new ColladaLoader();
|
|
278
|
+
const result = loader.parse(asText(data), path);
|
|
279
|
+
return wrapGroup(result.scene, result.animations || []);
|
|
280
|
+
}
|
|
281
|
+
async function parseModelResource(res, renderer) {
|
|
282
|
+
const { data, type, path } = modelPayload(res);
|
|
283
|
+
switch (type) {
|
|
284
|
+
case 'glb':
|
|
285
|
+
case 'gltf':
|
|
286
|
+
return parseGltf(data, path, renderer);
|
|
287
|
+
case 'fbx':
|
|
288
|
+
return parseFbx(data, path);
|
|
289
|
+
case 'obj':
|
|
290
|
+
return parseObj(res, data, path);
|
|
291
|
+
case 'stl':
|
|
292
|
+
return geometryToModel(new STLLoader().parse(asBuffer(data)));
|
|
293
|
+
case 'ply':
|
|
294
|
+
return geometryToModel(new PLYLoader().parse(asBuffer(data)));
|
|
295
|
+
case 'dae':
|
|
296
|
+
case 'collada':
|
|
297
|
+
return parseCollada(data, path);
|
|
298
|
+
default:
|
|
299
|
+
throw new Error(`Unsupported 3D model type "${type}" for resource "${res.name}". ` +
|
|
300
|
+
'Use glb, gltf, fbx, obj, stl, dae, or ply.');
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
function createModelInstance(res) {
|
|
304
|
+
let cached = null;
|
|
305
|
+
return {
|
|
306
|
+
async parse(renderer) {
|
|
307
|
+
if (!cached) {
|
|
308
|
+
cached = await parseModelResource(res, renderer);
|
|
309
|
+
}
|
|
310
|
+
return cached;
|
|
311
|
+
},
|
|
312
|
+
dispose() {
|
|
313
|
+
cached = null;
|
|
314
|
+
},
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
resource.registerInstance(RESOURCE_TYPE.MODEL, (res) => createModelInstance(res));
|
|
318
|
+
resource.registerInstance(RESOURCE_TYPE.GLB, (res) => createModelInstance(res));
|
|
319
|
+
resource.registerDestroy(RESOURCE_TYPE.MODEL, ({ instance }) => {
|
|
320
|
+
instance?.dispose?.();
|
|
321
|
+
});
|
|
322
|
+
resource.registerDestroy(RESOURCE_TYPE.GLB, ({ instance }) => {
|
|
323
|
+
instance?.dispose?.();
|
|
324
|
+
});
|
|
325
|
+
|
|
157
326
|
let Model3DSystem = class Model3DSystem extends Renderer3D {
|
|
158
327
|
constructor() {
|
|
159
328
|
super(...arguments);
|
|
@@ -194,7 +363,7 @@ let Model3DSystem = class Model3DSystem extends Renderer3D {
|
|
|
194
363
|
if (!component.resource)
|
|
195
364
|
return;
|
|
196
365
|
const asyncId = this.increaseAsyncId(gameObject.id);
|
|
197
|
-
await this.
|
|
366
|
+
await this.attachNamedModel(gameObject.id, component.resource);
|
|
198
367
|
if (!this.validateAsyncId(gameObject.id, asyncId))
|
|
199
368
|
return;
|
|
200
369
|
if (component.autoPlay) {
|
|
@@ -209,7 +378,7 @@ let Model3DSystem = class Model3DSystem extends Renderer3D {
|
|
|
209
378
|
if (!component.resource)
|
|
210
379
|
return;
|
|
211
380
|
const asyncId = this.increaseAsyncId(changed.gameObject.id);
|
|
212
|
-
await this.
|
|
381
|
+
await this.attachNamedModel(changed.gameObject.id, component.resource);
|
|
213
382
|
if (!this.validateAsyncId(changed.gameObject.id, asyncId))
|
|
214
383
|
return;
|
|
215
384
|
if (component.autoPlay) {
|
|
@@ -220,6 +389,16 @@ let Model3DSystem = class Model3DSystem extends Renderer3D {
|
|
|
220
389
|
this.threeContext.playAnimation(changed.gameObject.id, component.animationIndex, component.speed);
|
|
221
390
|
}
|
|
222
391
|
}
|
|
392
|
+
async attachNamedModel(id, name) {
|
|
393
|
+
const res = await requireNamedResource(name);
|
|
394
|
+
const instance = res.instance;
|
|
395
|
+
if (!instance || typeof instance.parse !== 'function') {
|
|
396
|
+
throw new Error(`Resource "${name}" is not a MODEL instance; register RESOURCE_TYPE.MODEL and import Model3DSystem`);
|
|
397
|
+
}
|
|
398
|
+
const parsed = await instance.parse(this.threeContext.renderer);
|
|
399
|
+
const clone$1 = clone(parsed.scene);
|
|
400
|
+
this.threeContext.attachParsedModel(id, clone$1, parsed.animations);
|
|
401
|
+
}
|
|
223
402
|
};
|
|
224
403
|
Model3DSystem = __decorate([
|
|
225
404
|
decorators.componentObserver({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-renderer-3d-model.esm.js","sources":["../lib/component.ts","../lib/system.ts"],"sourcesContent":["import { Component } from '@combos-fun/engine';\nimport { Field } from '@combos-fun/inspector-decorator';\n\nexport interface Model3DParams {\n resource?: string;\n autoPlay?: boolean;\n animationIndex?: number;\n speed?: number;\n positionX?: number;\n positionY?: number;\n positionZ?: number;\n rotationX?: number;\n rotationY?: number;\n rotationZ?: number;\n scaleX?: number;\n scaleY?: number;\n scaleZ?: number;\n}\n\nexport default class Model3D extends Component<Model3DParams> {\n static componentName: string = 'Model3D';\n\n @Field({\n\n type: 'string',\n\n group: 'Model3D',\n\n label: 'resource',\n\n description: 'Resource id from the asset registry.',\n\n editor: 'text',\n\n })\n\n resource: string = '';\n @Field({\n type: 'boolean',\n group: 'Model3D',\n label: 'autoPlay',\n description: 'Start playing automatically when loaded.',\n editor: 'toggle',\n })\n autoPlay: boolean = true;\n @Field({\n type: 'number',\n group: 'Model3D',\n label: 'animationIndex',\n description: 'Animation clip index.',\n editor: 'number-stepper',\n })\n animationIndex: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'speed',\n description: 'Playback speed.',\n editor: 'number-stepper',\n })\n speed: number = 1;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'positionX',\n description: 'Local X position.',\n editor: 'number-stepper',\n })\n positionX: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'positionY',\n description: 'Local Y position.',\n editor: 'number-stepper',\n })\n positionY: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'positionZ',\n description: 'Local Z position.',\n editor: 'number-stepper',\n })\n positionZ: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Model3D',\n label: 'rotationX',\n description: 'Rotation around X in radians.',\n editor: 'number-stepper',\n })\n rotationX: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Model3D',\n label: 'rotationY',\n description: 'Rotation around Y in radians.',\n editor: 'number-stepper',\n })\n rotationY: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Model3D',\n label: 'rotationZ',\n description: 'Rotation around Z in radians.',\n editor: 'number-stepper',\n })\n rotationZ: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'scaleX',\n description: 'Scale on X.',\n editor: 'number-stepper',\n })\n scaleX: number = 1;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'scaleY',\n description: 'Scale on Y.',\n editor: 'number-stepper',\n })\n scaleY: number = 1;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'scaleZ',\n description: 'Scale on Z.',\n editor: 'number-stepper',\n })\n scaleZ: number = 1;\n\n init(obj?: Model3DParams) {\n if (obj) Object.assign(this, obj);\n }\n}\n","import { decorators, ComponentChanged, OBSERVER_TYPE, GameObject } from '@combos-fun/engine';\nimport { Renderer3D, Renderer3DSystem } from '@combos-fun/plugin-renderer-3d';\nimport Model3D from './component';\n\n@decorators.componentObserver({\n Model3D: [\n 'resource',\n 'positionX', 'positionY', 'positionZ',\n 'rotationX', 'rotationY', 'rotationZ',\n 'scaleX', 'scaleY', 'scaleZ',\n 'speed', 'animationIndex',\n ],\n})\nexport default class Model3DSystem extends Renderer3D {\n static systemName = 'Model3DSystem';\n name: string = 'Model3DSystem';\n\n init() {\n const renderer3DSystem = this.game.getSystem(Renderer3DSystem) as Renderer3DSystem;\n renderer3DSystem.rendererManager.register(this);\n }\n\n componentChanged(changed: ComponentChanged) {\n if (changed.componentName !== 'Model3D') return;\n\n const component = changed.component as Model3D;\n\n if (changed.type === OBSERVER_TYPE.ADD) {\n this.handleAdd(changed.gameObject, component);\n } else if (changed.type === OBSERVER_TYPE.CHANGE) {\n this.handleChange(changed);\n } else if (changed.type === OBSERVER_TYPE.REMOVE) {\n this.increaseAsyncId(changed.gameObject.id);\n this.threeContext.removeModel(changed.gameObject.id);\n }\n }\n\n rendererUpdate(gameObject: GameObject) {\n const component = gameObject.getComponent(Model3D) as Model3D;\n if (!component) return;\n\n const model = this.threeContext.models.get(gameObject.id);\n if (!model) return;\n\n model.position.set(component.positionX, component.positionY, component.positionZ);\n model.rotation.set(component.rotationX, component.rotationY, component.rotationZ);\n model.scale.set(component.scaleX, component.scaleY, component.scaleZ);\n }\n\n private async handleAdd(gameObject: GameObject, component: Model3D) {\n if (!component.resource) return;\n\n const asyncId = this.increaseAsyncId(gameObject.id);\n await this.threeContext.loadGLB(gameObject.id, component.resource);\n if (!this.validateAsyncId(gameObject.id, asyncId)) return;\n\n if (component.autoPlay) {\n this.threeContext.playAnimation(\n gameObject.id,\n component.animationIndex,\n component.speed,\n );\n }\n }\n\n private async handleChange(changed: ComponentChanged) {\n const component = changed.component as Model3D;\n const changedProp = changed.prop?.prop?.[0];\n\n if (changedProp === 'resource') {\n this.threeContext.removeModel(changed.gameObject.id);\n if (!component.resource) return;\n\n const asyncId = this.increaseAsyncId(changed.gameObject.id);\n await this.threeContext.loadGLB(changed.gameObject.id, component.resource);\n if (!this.validateAsyncId(changed.gameObject.id, asyncId)) return;\n\n if (component.autoPlay) {\n this.threeContext.playAnimation(\n changed.gameObject.id,\n component.animationIndex,\n component.speed,\n );\n }\n }\n\n if (changedProp === 'speed' || changedProp === 'animationIndex') {\n this.threeContext.playAnimation(\n changed.gameObject.id,\n component.animationIndex,\n component.speed,\n );\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugin-renderer-3d-model.esm.js","sources":["../lib/component.ts","../lib/parseModel.ts","../lib/system.ts"],"sourcesContent":["import { Component } from '@combos-fun/engine';\nimport { Field } from '@combos-fun/inspector-decorator';\n\nexport interface Model3DParams {\n resource?: string;\n autoPlay?: boolean;\n animationIndex?: number;\n speed?: number;\n positionX?: number;\n positionY?: number;\n positionZ?: number;\n rotationX?: number;\n rotationY?: number;\n rotationZ?: number;\n scaleX?: number;\n scaleY?: number;\n scaleZ?: number;\n}\n\nexport default class Model3D extends Component<Model3DParams> {\n static componentName: string = 'Model3D';\n\n @Field({\n\n type: 'string',\n\n group: 'Model3D',\n\n label: 'resource',\n\n description: 'Engine resource name registered with RESOURCE_TYPE.MODEL.',\n\n editor: 'text',\n\n })\n\n resource: string = '';\n @Field({\n type: 'boolean',\n group: 'Model3D',\n label: 'autoPlay',\n description: 'Start playing automatically when loaded.',\n editor: 'toggle',\n })\n autoPlay: boolean = true;\n @Field({\n type: 'number',\n group: 'Model3D',\n label: 'animationIndex',\n description: 'Animation clip index.',\n editor: 'number-stepper',\n })\n animationIndex: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'speed',\n description: 'Playback speed.',\n editor: 'number-stepper',\n })\n speed: number = 1;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'positionX',\n description: 'Local X position.',\n editor: 'number-stepper',\n })\n positionX: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'positionY',\n description: 'Local Y position.',\n editor: 'number-stepper',\n })\n positionY: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'positionZ',\n description: 'Local Z position.',\n editor: 'number-stepper',\n })\n positionZ: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Model3D',\n label: 'rotationX',\n description: 'Rotation around X in radians.',\n editor: 'number-stepper',\n })\n rotationX: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Model3D',\n label: 'rotationY',\n description: 'Rotation around Y in radians.',\n editor: 'number-stepper',\n })\n rotationY: number = 0;\n @Field({\n type: 'number',\n step: 0.01,\n group: 'Model3D',\n label: 'rotationZ',\n description: 'Rotation around Z in radians.',\n editor: 'number-stepper',\n })\n rotationZ: number = 0;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'scaleX',\n description: 'Scale on X.',\n editor: 'number-stepper',\n })\n scaleX: number = 1;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'scaleY',\n description: 'Scale on Y.',\n editor: 'number-stepper',\n })\n scaleY: number = 1;\n @Field({\n type: 'number',\n step: 0.1,\n group: 'Model3D',\n label: 'scaleZ',\n description: 'Scale on Z.',\n editor: 'number-stepper',\n })\n scaleZ: number = 1;\n\n init(obj?: Model3DParams) {\n if (obj) Object.assign(this, obj);\n }\n}\n","import { resource, RESOURCE_TYPE } from '@combos-fun/engine';\nimport type { ResourceStruct } from '@combos-fun/engine';\nimport {\n AnimationClip,\n BufferGeometry,\n Group,\n Mesh,\n MeshStandardMaterial,\n Object3D,\n} from 'three';\nimport type { WebGLRenderer } from 'three';\nimport { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';\nimport { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';\nimport { KTX2Loader } from 'three/addons/loaders/KTX2Loader.js';\nimport { FBXLoader } from 'three/addons/loaders/FBXLoader.js';\nimport { OBJLoader } from 'three/addons/loaders/OBJLoader.js';\nimport { MTLLoader } from 'three/addons/loaders/MTLLoader.js';\nimport { STLLoader } from 'three/addons/loaders/STLLoader.js';\nimport { ColladaLoader } from 'three/addons/loaders/ColladaLoader.js';\nimport { PLYLoader } from 'three/addons/loaders/PLYLoader.js';\nimport { MeshoptDecoder } from 'three/addons/libs/meshopt_decoder.module.js';\n\nexport interface ParsedModel {\n scene: Group;\n animations: AnimationClip[];\n}\n\nexport interface ModelResourceInstance {\n parse(renderer?: WebGLRenderer): Promise<ParsedModel>;\n dispose(): void;\n}\n\nconst THREE_ADDON_CDN = 'https://unpkg.com/three@0.172.0/examples/jsm/libs';\nconst DRACO_DECODER_PATH = 'https://www.gstatic.com/draco/versioned/decoders/1.5.7/';\nconst BASIS_TRANSCODER_PATH = `${THREE_ADDON_CDN}/basis/`;\n\nlet sharedDraco: DRACOLoader | null = null;\nlet sharedKtx2: KTX2Loader | null = null;\nlet ktx2DetectedFor: WebGLRenderer | null = null;\n\nfunction dirOf(url: string): string {\n const clean = String(url || '').split('?')[0].split('#')[0];\n const slash = clean.lastIndexOf('/');\n return slash >= 0 ? clean.slice(0, slash + 1) : '';\n}\n\nfunction asText(data: unknown): string {\n if (typeof data === 'string') return data;\n if (data instanceof ArrayBuffer) return new TextDecoder().decode(data);\n if (ArrayBuffer.isView(data)) {\n return new TextDecoder().decode(data as ArrayBufferView);\n }\n if (data && typeof data === 'object') return JSON.stringify(data);\n throw new Error('expected text payload for this model format');\n}\n\nfunction asBuffer(data: unknown): ArrayBuffer {\n if (data instanceof ArrayBuffer) return data;\n if (ArrayBuffer.isView(data)) {\n const view = data as ArrayBufferView;\n return view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength);\n }\n throw new Error('expected binary payload for this model format');\n}\n\nfunction wrapGroup(object: Object3D, animations: AnimationClip[] = []): ParsedModel {\n if (object instanceof Group) {\n return { scene: object, animations };\n }\n const scene = new Group();\n scene.add(object);\n return { scene, animations };\n}\n\nfunction geometryToModel(geometry: BufferGeometry): ParsedModel {\n geometry.computeVertexNormals?.();\n const mesh = new Mesh(\n geometry,\n new MeshStandardMaterial({ color: 0x888888, metalness: 0.1, roughness: 0.8 }),\n );\n const scene = new Group();\n scene.add(mesh);\n return { scene, animations: [] };\n}\n\nfunction modelPayload(res: ResourceStruct): { data: unknown; type: string; path: string } {\n const slot = res.src?.model || res.src?.glb || res.src?.gltf;\n const data = res.data?.model ?? res.data?.glb ?? res.data?.gltf;\n if (data == null) {\n throw new Error(\n `Resource \"${res.name}\" has no model data; use RESOURCE_TYPE.MODEL with src.model.url`,\n );\n }\n const type = String(slot?.type || 'glb').toLowerCase();\n return { data, type, path: dirOf(slot?.url || '') };\n}\n\nfunction ensureGltfExtras(loader: GLTFLoader, renderer?: WebGLRenderer) {\n if (!sharedDraco) {\n sharedDraco = new DRACOLoader();\n sharedDraco.setDecoderPath(DRACO_DECODER_PATH);\n }\n loader.setDRACOLoader(sharedDraco);\n\n if (!sharedKtx2) {\n sharedKtx2 = new KTX2Loader();\n sharedKtx2.setTranscoderPath(BASIS_TRANSCODER_PATH);\n }\n if (renderer && ktx2DetectedFor !== renderer) {\n sharedKtx2.detectSupport(renderer);\n ktx2DetectedFor = renderer;\n }\n loader.setKTX2Loader(sharedKtx2);\n loader.setMeshoptDecoder(MeshoptDecoder);\n}\n\nfunction parseGltf(\n data: unknown,\n path: string,\n renderer?: WebGLRenderer,\n): Promise<ParsedModel> {\n const loader = new GLTFLoader();\n ensureGltfExtras(loader, renderer);\n const payload =\n typeof data === 'object' && data && !(data instanceof ArrayBuffer) && !ArrayBuffer.isView(data)\n ? JSON.stringify(data)\n : data instanceof ArrayBuffer || ArrayBuffer.isView(data)\n ? asBuffer(data)\n : asText(data);\n\n return new Promise((resolve, reject) => {\n loader.parse(\n payload as ArrayBuffer | string,\n path,\n (gltf) => {\n resolve(wrapGroup(gltf.scene, gltf.animations || []));\n },\n (err) => {\n reject(err instanceof Error ? err : new Error(String(err)));\n },\n );\n });\n}\n\nasync function parseFbx(data: unknown, path: string): Promise<ParsedModel> {\n const loader = new FBXLoader();\n const object = loader.parse(asBuffer(data), path);\n const animations = (object.animations || []) as AnimationClip[];\n return wrapGroup(object, animations);\n}\n\nasync function parseObj(res: ResourceStruct, data: unknown, path: string): Promise<ParsedModel> {\n const objLoader = new OBJLoader();\n const mtlText = res.data?.mtl;\n if (mtlText != null) {\n const mtlLoader = new MTLLoader();\n const mtlPath = dirOf(res.src?.mtl?.url || '') || path;\n const materials = mtlLoader.parse(asText(mtlText), mtlPath);\n materials.preload();\n objLoader.setMaterials(materials);\n }\n return wrapGroup(objLoader.parse(asText(data)));\n}\n\nasync function parseCollada(data: unknown, path: string): Promise<ParsedModel> {\n const loader = new ColladaLoader();\n const result = loader.parse(asText(data), path);\n return wrapGroup(result.scene, result.animations || []);\n}\n\nexport async function parseModelResource(\n res: ResourceStruct,\n renderer?: WebGLRenderer,\n): Promise<ParsedModel> {\n const { data, type, path } = modelPayload(res);\n switch (type) {\n case 'glb':\n case 'gltf':\n return parseGltf(data, path, renderer);\n case 'fbx':\n return parseFbx(data, path);\n case 'obj':\n return parseObj(res, data, path);\n case 'stl':\n return geometryToModel(new STLLoader().parse(asBuffer(data)));\n case 'ply':\n return geometryToModel(new PLYLoader().parse(asBuffer(data)));\n case 'dae':\n case 'collada':\n return parseCollada(data, path);\n default:\n throw new Error(\n `Unsupported 3D model type \"${type}\" for resource \"${res.name}\". ` +\n 'Use glb, gltf, fbx, obj, stl, dae, or ply.',\n );\n }\n}\n\nfunction createModelInstance(res: ResourceStruct): ModelResourceInstance {\n let cached: ParsedModel | null = null;\n return {\n async parse(renderer?: WebGLRenderer) {\n if (!cached) {\n cached = await parseModelResource(res, renderer);\n }\n return cached;\n },\n dispose() {\n cached = null;\n },\n };\n}\n\nresource.registerInstance(RESOURCE_TYPE.MODEL, (res) => createModelInstance(res));\nresource.registerInstance(RESOURCE_TYPE.GLB, (res) => createModelInstance(res));\nresource.registerDestroy(RESOURCE_TYPE.MODEL, ({ instance }) => {\n instance?.dispose?.();\n});\nresource.registerDestroy(RESOURCE_TYPE.GLB, ({ instance }) => {\n instance?.dispose?.();\n});\n","import { decorators, ComponentChanged, OBSERVER_TYPE, GameObject } from '@combos-fun/engine';\nimport {\n Renderer3D,\n Renderer3DSystem,\n requireNamedResource,\n} from '@combos-fun/plugin-renderer-3d';\nimport { Group } from 'three';\nimport { clone as cloneSkinned } from 'three/addons/utils/SkeletonUtils.js';\nimport Model3D from './component';\nimport './parseModel';\nimport type { ModelResourceInstance } from './parseModel';\n\n@decorators.componentObserver({\n Model3D: [\n 'resource',\n 'positionX', 'positionY', 'positionZ',\n 'rotationX', 'rotationY', 'rotationZ',\n 'scaleX', 'scaleY', 'scaleZ',\n 'speed', 'animationIndex',\n ],\n})\nexport default class Model3DSystem extends Renderer3D {\n static systemName = 'Model3DSystem';\n name: string = 'Model3DSystem';\n\n init() {\n const renderer3DSystem = this.game.getSystem(Renderer3DSystem) as Renderer3DSystem;\n renderer3DSystem.rendererManager.register(this);\n }\n\n componentChanged(changed: ComponentChanged) {\n if (changed.componentName !== 'Model3D') return;\n\n const component = changed.component as Model3D;\n\n if (changed.type === OBSERVER_TYPE.ADD) {\n this.handleAdd(changed.gameObject, component);\n } else if (changed.type === OBSERVER_TYPE.CHANGE) {\n this.handleChange(changed);\n } else if (changed.type === OBSERVER_TYPE.REMOVE) {\n this.increaseAsyncId(changed.gameObject.id);\n this.threeContext.removeModel(changed.gameObject.id);\n }\n }\n\n rendererUpdate(gameObject: GameObject) {\n const component = gameObject.getComponent(Model3D) as Model3D;\n if (!component) return;\n\n const model = this.threeContext.models.get(gameObject.id);\n if (!model) return;\n\n model.position.set(component.positionX, component.positionY, component.positionZ);\n model.rotation.set(component.rotationX, component.rotationY, component.rotationZ);\n model.scale.set(component.scaleX, component.scaleY, component.scaleZ);\n }\n\n private async handleAdd(gameObject: GameObject, component: Model3D) {\n if (!component.resource) return;\n\n const asyncId = this.increaseAsyncId(gameObject.id);\n await this.attachNamedModel(gameObject.id, component.resource);\n if (!this.validateAsyncId(gameObject.id, asyncId)) return;\n\n if (component.autoPlay) {\n this.threeContext.playAnimation(\n gameObject.id,\n component.animationIndex,\n component.speed,\n );\n }\n }\n\n private async handleChange(changed: ComponentChanged) {\n const component = changed.component as Model3D;\n const changedProp = changed.prop?.prop?.[0];\n\n if (changedProp === 'resource') {\n this.threeContext.removeModel(changed.gameObject.id);\n if (!component.resource) return;\n\n const asyncId = this.increaseAsyncId(changed.gameObject.id);\n await this.attachNamedModel(changed.gameObject.id, component.resource);\n if (!this.validateAsyncId(changed.gameObject.id, asyncId)) return;\n\n if (component.autoPlay) {\n this.threeContext.playAnimation(\n changed.gameObject.id,\n component.animationIndex,\n component.speed,\n );\n }\n }\n\n if (changedProp === 'speed' || changedProp === 'animationIndex') {\n this.threeContext.playAnimation(\n changed.gameObject.id,\n component.animationIndex,\n component.speed,\n );\n }\n }\n\n private async attachNamedModel(id: number, name: string) {\n const res = await requireNamedResource(name);\n const instance = res.instance as ModelResourceInstance | undefined;\n if (!instance || typeof instance.parse !== 'function') {\n throw new Error(\n `Resource \"${name}\" is not a MODEL instance; register RESOURCE_TYPE.MODEL and import Model3DSystem`,\n );\n }\n const parsed = await instance.parse(this.threeContext.renderer);\n const clone = cloneSkinned(parsed.scene) as Group;\n this.threeContext.attachParsedModel(id, clone, parsed.animations);\n }\n}\n"],"names":["clone","cloneSkinned"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@combos-fun/plugin-renderer-3d-model",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.0.41",
|
|
4
|
+
"description": "Named 3D model loader (glTF/GLB, FBX, OBJ, STL, Collada, PLY) and animator",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "dist/plugin-renderer-3d-model.esm.js",
|
|
7
7
|
"bundle": "CombosFun.plugin.renderer.3d.model",
|
|
@@ -26,10 +26,10 @@
|
|
|
26
26
|
"pluginManifest": "./combos-plugin.json"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"
|
|
30
|
-
"@combos-fun/inspector-decorator": "0.0.
|
|
31
|
-
"@combos-fun/
|
|
32
|
-
"
|
|
29
|
+
"three": "^0.172.0",
|
|
30
|
+
"@combos-fun/inspector-decorator": "0.0.41",
|
|
31
|
+
"@combos-fun/engine": "0.0.41",
|
|
32
|
+
"@combos-fun/plugin-renderer-3d": "0.0.41"
|
|
33
33
|
},
|
|
34
34
|
"keywords": [
|
|
35
35
|
"combos-fun",
|
|
@@ -37,6 +37,11 @@
|
|
|
37
37
|
"model",
|
|
38
38
|
"glb",
|
|
39
39
|
"gltf",
|
|
40
|
+
"fbx",
|
|
41
|
+
"obj",
|
|
42
|
+
"stl",
|
|
43
|
+
"dae",
|
|
44
|
+
"ply",
|
|
40
45
|
"animation",
|
|
41
46
|
"mesh"
|
|
42
47
|
],
|