1 | import { ResourceLocation } from "@xmcl/resourcepack";
|
2 | import { System } from "@xmcl/system";
|
3 |
|
4 |
|
5 |
|
6 | export class ModelLoader {
|
7 | |
8 |
|
9 |
|
10 | constructor(manager) {
|
11 | this.manager = manager;
|
12 | |
13 |
|
14 |
|
15 | this.textures = {};
|
16 | |
17 |
|
18 |
|
19 | this.models = {};
|
20 | }
|
21 | static findRealTexturePath(model, variantKey) {
|
22 | let texturePath = model.textures[variantKey];
|
23 | while (texturePath.startsWith("#")) {
|
24 | const next = model.textures[texturePath.substring(1, texturePath.length)];
|
25 | if (!next) {
|
26 | return undefined;
|
27 | }
|
28 | texturePath = next;
|
29 | }
|
30 | return texturePath;
|
31 | }
|
32 | |
33 |
|
34 |
|
35 | async loadModel(modelPath) {
|
36 | const res = await this.manager.load(ResourceLocation.ofModelPath(modelPath));
|
37 | if (!res) {
|
38 | throw new Error(`Model ${modelPath} (${ResourceLocation.ofModelPath(modelPath)}) not found`);
|
39 | }
|
40 | const raw = JSON.parse(System.bufferToText(res.content));
|
41 | if (!raw.textures) {
|
42 | raw.textures = {};
|
43 | }
|
44 | if (raw.parent) {
|
45 | const parentModel = await this.loadModel(raw.parent);
|
46 | if (!parentModel) {
|
47 | throw new Error(`Missing parent model ${raw.parent} for ${location.toString()}`);
|
48 | }
|
49 | if (!raw.elements) {
|
50 | raw.elements = parentModel.elements;
|
51 | }
|
52 | if (!raw.ambientocclusion) {
|
53 | raw.ambientocclusion = parentModel.ambientocclusion;
|
54 | }
|
55 | if (!raw.display) {
|
56 | raw.display = parentModel.display;
|
57 | }
|
58 | if (!raw.overrides) {
|
59 | raw.overrides = parentModel.overrides;
|
60 | }
|
61 | if (parentModel.textures) {
|
62 | Object.assign(raw.textures, parentModel.textures);
|
63 | }
|
64 | }
|
65 | raw.ambientocclusion = raw.ambientocclusion || false;
|
66 | raw.overrides = raw.overrides || [];
|
67 | delete raw.parent;
|
68 | const model = raw;
|
69 | this.models[modelPath] = model;
|
70 | const reg = this.textures;
|
71 | for (const variant of Object.keys(model.textures)) {
|
72 | const texPath = ModelLoader.findRealTexturePath(model, variant);
|
73 | if (texPath) {
|
74 | const load = await this.manager.load(ResourceLocation.ofTexturePath(texPath));
|
75 | if (load) {
|
76 | reg[texPath] = load;
|
77 | }
|
78 | }
|
79 | }
|
80 | return model;
|
81 | }
|
82 | }
|