-
Notifications
You must be signed in to change notification settings - Fork 26
/
modelLoader.ts
84 lines (69 loc) · 2.83 KB
/
modelLoader.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import { Resource, ResourceLocation } from './resourcePack'
import { ResourceLoader } from './resourceManager'
import { BlockModel } from './format'
/**
* The model loader load the resource
*/
export class ModelLoader {
static findRealTexturePath(model: BlockModel.Resolved, variantKey: string) {
let texturePath = model.textures[variantKey] as string
while (texturePath.startsWith('#')) {
const next = model.textures[texturePath.substring(1, texturePath.length)]
if (!next) { return undefined }
texturePath = next
}
return texturePath
}
/**
* All required texture raw resources
*/
readonly textures: Record<string, Resource> = {}
/**
* All the resolved model
*/
readonly models: Record<string, BlockModel.Resolved> = {}
/**
* @param loader The resource loader
*/
constructor(readonly loader: ResourceLoader) { }
/**
* Load a model by search its parent. It will throw an error if the model is not found.
*/
async loadModel(modelPath: string, folder = 'block'): Promise<BlockModel.Resolved> {
const path = ResourceLocation.deconstruct(modelPath, folder)
const resourceLocation = ResourceLocation.ofModelPath(path)
const cacheName = resourceLocation.toString()
if (this.models[cacheName] !== undefined) {
return this.models[cacheName]
}
const resource = await this.loader.get(resourceLocation)
if (!resource) { throw new Error(`Model ${modelPath} (${resourceLocation}) not found`) }
const baseModel = JSON.parse(await resource.read('utf-8')) as BlockModel
if (!baseModel.textures) { baseModel.textures = {} }
if (baseModel.parent) {
const parentModel = await this.loadModel(baseModel.parent, '')
if (!parentModel) { throw new Error(`Missing parent model ${baseModel.parent} for ${resource.location}`) }
if (!baseModel.elements) { baseModel.elements = parentModel.elements }
if (!baseModel.ambientocclusion) { baseModel.ambientocclusion = parentModel.ambientocclusion }
if (!baseModel.display) { baseModel.display = parentModel.display }
if (!baseModel.overrides) { baseModel.overrides = parentModel.overrides }
if (parentModel.textures) { Object.assign(baseModel.textures, parentModel.textures) }
}
baseModel.ambientocclusion = baseModel.ambientocclusion || false
baseModel.overrides = baseModel.overrides || []
delete baseModel.parent
const model: BlockModel.Resolved = baseModel as any
const reg = this.textures
for (const variant of Object.keys(model.textures)) {
const texPath = ModelLoader.findRealTexturePath(model, variant)
if (texPath) {
const load = await this.loader.get(ResourceLocation.ofTexturePath(texPath))
if (load) {
reg[texPath] = load
}
}
}
this.models[cacheName] = model
return model
}
}