Skip to content

Commit 7bd00dd

Browse files
committed
JSON Exporter Re-write
1 parent 92508df commit 7bd00dd

File tree

3 files changed

+423
-127
lines changed

3 files changed

+423
-127
lines changed
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
type NodeType = 'bone' | 'camera' | 'locator'
2+
3+
interface ISerializedVariantModel {
4+
custom_model_data: number
5+
resource_location: string
6+
}
7+
8+
interface ISerializedVariant {
9+
name: string
10+
uuid: string
11+
models: Record<string, ISerializedVariantModel>
12+
affected_bones: string[]
13+
affected_bones_is_a_whitelist: boolean
14+
}
15+
16+
interface ISerializedAnimationFrame {
17+
nodes: ISerializedNodeAnimationFrameEntry[]
18+
time: number
19+
variant?: {
20+
uuid: string
21+
execute_condition?: string
22+
}
23+
commands?: {
24+
commands: string
25+
execute_condition?: string
26+
}
27+
}
28+
29+
interface ISerializedNodeAnimationFrameEntry {
30+
uuid: string
31+
matrix: number[]
32+
}
33+
34+
interface ISerealizedAnimation {
35+
frames: ISerializedAnimationFrame[]
36+
duration: number
37+
loop_mode: 'once' | 'hold' | 'loop'
38+
affected_bones: string[]
39+
affected_bones_is_a_whitelist: boolean
40+
}
41+
42+
interface ISerializedNode {
43+
type: NodeType
44+
name: string
45+
uuid: string
46+
custom_model_data: number
47+
resource_location: string
48+
}
49+
50+
interface ISerializedVariant {
51+
name: string
52+
uuid: string
53+
models: Record<string, ISerializedVariantModel>
54+
affected_bones: string[]
55+
affected_bones_is_a_whitelist: boolean
56+
}
57+
58+
export interface IJSONExport {
59+
project_settings: Record<string, any>
60+
exporter_settings: Record<string, any>
61+
rig: {
62+
default_pose: ISerializedNodeAnimationFrameEntry[]
63+
node_map: Record<string, ISerializedNode>
64+
}
65+
variants: Record<string, ISerializedVariant>
66+
animations: Record<string, ISerealizedAnimation>
67+
}
68+
69+
function serializeProjectSettings(): Record<string, any> {
70+
const project_settings = {}
71+
for (const [name, setting] of Object.entries(Project!.animated_java_settings)) {
72+
project_settings[name] = setting._save()
73+
}
74+
return project_settings
75+
}
76+
77+
function serializeExporterSettings(exporterSettings: Record<string, any>): Record<string, any> {
78+
const exporter_settings = {}
79+
for (const [name, setting] of Object.entries(exporterSettings)) {
80+
exporter_settings[name] = setting._save()
81+
}
82+
return exporter_settings
83+
}
84+
85+
function serializeNodeAnimationFrameEntry(
86+
node: AnimatedJava.IAnimationNode
87+
): ISerializedNodeAnimationFrameEntry {
88+
const { type, uuid, matrix } = node
89+
return {
90+
uuid,
91+
matrix: matrix.toArray(),
92+
}
93+
}
94+
95+
function serializeNodeMap(nodeMap: Record<string, any>): Record<string, ISerializedNode> {
96+
const serializedNodeMap: Record<string, ISerializedNode> = {}
97+
for (const uuid in nodeMap) {
98+
const node = nodeMap[uuid]
99+
const type = node.type
100+
const name = node.name
101+
const custom_model_data = node.customModelData
102+
const resource_location = node.resourceLocation
103+
104+
serializedNodeMap[uuid] = {
105+
type,
106+
name,
107+
uuid,
108+
custom_model_data,
109+
resource_location,
110+
}
111+
}
112+
return serializedNodeMap
113+
}
114+
115+
function serializeVariant(
116+
exportOptions: AnimatedJava.IAnimatedJavaExportData<unknown>,
117+
variant: AnimatedJava.Variant
118+
): ISerializedVariant {
119+
const name = variant.name
120+
const uuid = variant.uuid
121+
const models = {}
122+
const affected_bones = variant.affectedBones.map(v => v.value)
123+
const affected_bones_is_a_whitelist = variant.affectedBonesIsAWhitelist
124+
125+
for (const [uuid, model] of Object.entries(exportOptions.rig.variantModels[name])) {
126+
models[uuid] = {
127+
custom_model_data: model.customModelData,
128+
resource_location: model.resourceLocation,
129+
}
130+
}
131+
132+
return {
133+
name,
134+
uuid,
135+
models,
136+
affected_bones,
137+
affected_bones_is_a_whitelist,
138+
}
139+
}
140+
141+
function serializeAnimationFrame(
142+
frame: AnimatedJava.IRenderedAnimation['frames'][any]
143+
): ISerializedAnimationFrame {
144+
const nodes = frame.nodes.map(serializeNodeAnimationFrameEntry)
145+
const time = frame.time
146+
const variant = frame.variant
147+
const commands = frame.commands
148+
149+
return {
150+
nodes,
151+
time,
152+
variant,
153+
commands,
154+
}
155+
}
156+
157+
function serializeAnimation(animation: AnimatedJava.IRenderedAnimation): ISerealizedAnimation {
158+
const frames = animation.frames.map(serializeAnimationFrame)
159+
const duration = animation.duration
160+
const loop_mode = animation.loopMode
161+
const bbAnimation = Blockbench.Animation.all.find(
162+
v => v instanceof Blockbench.Animation && v.name === animation.name
163+
) as _Animation
164+
const affected_bones = bbAnimation.affected_bones.map(v => v.value)
165+
const affected_bones_is_a_whitelist = bbAnimation.affected_bones_is_a_whitelist
166+
167+
return {
168+
frames,
169+
duration,
170+
loop_mode,
171+
affected_bones,
172+
affected_bones_is_a_whitelist,
173+
}
174+
}
175+
176+
export function constructJSON(
177+
exportOptions: AnimatedJava.IAnimatedJavaExportData<unknown>
178+
): IJSONExport {
179+
const {} = AnimatedJava.API
180+
const project_settings = serializeProjectSettings()
181+
const exporter_settings = serializeExporterSettings(exportOptions.exporterSettings)
182+
const rig = {
183+
default_pose: exportOptions.rig.defaultPose.map(serializeNodeAnimationFrameEntry),
184+
node_map: serializeNodeMap(exportOptions.rig.nodeMap),
185+
}
186+
const variants = {}
187+
const animations = {}
188+
189+
for (const variant of Project!.animated_java_variants.variants) {
190+
if (variant.default) continue
191+
variants[variant.uuid] = serializeVariant(exportOptions, variant)
192+
}
193+
194+
for (const animation of exportOptions.renderedAnimations) {
195+
animations[animation.name] = serializeAnimation(animation)
196+
}
197+
198+
return {
199+
project_settings,
200+
exporter_settings,
201+
rig,
202+
variants,
203+
animations,
204+
}
205+
}

exporters/jsonExporter/jsonExporter.ts

Lines changed: 5 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,6 @@
11
// @ts-ignore
22
import en from './lang/en.yaml'
3-
// TODO - Remake this exporter, it's a bit of a mess.
4-
interface ISerealizedAnimationNode {
5-
type: 'bone' | 'camera' | 'locator'
6-
name: string
7-
uuid: string
8-
node: undefined
9-
matrix: number[]
10-
interpolation?: 'instant' | 'default'
11-
}
12-
13-
function serializeFrame(frame: AnimatedJava.IRenderedFrame) {
14-
return {
15-
time: frame.time,
16-
nodes: frame.nodes.map(serializeAnimationNode),
17-
variant: frame.variant,
18-
commands: frame.commands,
19-
animationState: frame.animationState,
20-
}
21-
}
22-
23-
function serializeOutlinerNode(node: AnimatedJava.AnyRenderedNode) {
24-
switch (node.type) {
25-
case 'bone': {
26-
const {
27-
type,
28-
name,
29-
parent,
30-
customModelData,
31-
resourceLocation,
32-
scale,
33-
modelPath,
34-
node: outlinerNode,
35-
} = node
36-
return {
37-
type,
38-
name,
39-
uuid: outlinerNode.uuid,
40-
customModelData,
41-
resourceLocation,
42-
}
43-
}
44-
case 'camera': {
45-
const { type, name, parent, entity_type, nbt, node: outlinerNode } = node
46-
return {
47-
type,
48-
name,
49-
uuid: outlinerNode.uuid,
50-
entity_type,
51-
nbt,
52-
}
53-
}
54-
case 'locator': {
55-
const { type, name, parent, entity_type, nbt, node: outlinerNode } = node
56-
return {
57-
type,
58-
name,
59-
uuid: outlinerNode.uuid,
60-
entity_type,
61-
nbt,
62-
}
63-
}
64-
}
65-
}
66-
67-
function serializeAnimationNode(node: AnimatedJava.IAnimationNode): ISerealizedAnimationNode {
68-
const { type, name, uuid, matrix, pos, rot, scale, interpolation } = node
69-
return {
70-
type,
71-
name,
72-
uuid,
73-
node: undefined,
74-
matrix: matrix.toArray(),
75-
interpolation,
76-
}
77-
}
78-
79-
interface ISerealizedAnimation {
80-
frames: ISerealizedAnimationNode[]
81-
duration: number
82-
loopMode: 'loop' | 'once' | 'hold'
83-
}
84-
85-
function serializeAnimation(animation: AnimatedJava.IRenderedAnimation): any {
86-
return {
87-
...animation,
88-
frames: animation.frames.map(serializeFrame),
89-
}
90-
}
91-
92-
interface RawExportData {
93-
project_settings: Record<string, any>
94-
exporter_settings: Record<string, any>
95-
rig: {
96-
default_pose: ISerealizedAnimationNode[]
97-
node_map: any
98-
}
99-
animations: Record<string, ISerealizedAnimation>
100-
}
3+
import { constructJSON } from './jsonConstructor'
1014

1025
export function loadExporter() {
1036
const API = AnimatedJava.API
@@ -151,40 +54,15 @@ export function loadExporter() {
15154
async export(exportOptions) {
15255
console.log('Export Options:', exportOptions)
15356

154-
const data: RawExportData = {
155-
project_settings: {},
156-
exporter_settings: {},
157-
rig: {
158-
default_pose: exportOptions.rig.defaultPose.map(serializeAnimationNode),
159-
node_map: {},
160-
},
161-
animations: {},
162-
}
163-
164-
for (const [key, setting] of Object.entries(exportOptions.projectSettings)) {
165-
data.project_settings[key] = setting._save()
166-
}
167-
168-
for (const [key, setting] of Object.entries(exportOptions.exporterSettings)) {
169-
data.exporter_settings[key] = setting._save()
170-
}
171-
172-
for (const [uuid, node] of Object.entries(exportOptions.rig.nodeMap)) {
173-
if (!node.node.export) continue
174-
data.rig.node_map[uuid] = serializeOutlinerNode(node)
175-
}
176-
177-
for (const animation of exportOptions.renderedAnimations) {
178-
data.animations[animation.name] = serializeAnimation(animation)
179-
}
57+
const json = constructJSON(exportOptions)
18058

181-
console.log('Exported data:', data)
59+
console.log('Exported JSON:', json)
18260

18361
await fs.promises.writeFile(
18462
exportOptions.exporterSettings.output_file.value,
18563
exportOptions.ajSettings.minify_output.value
186-
? JSON.stringify(data)
187-
: JSON.stringify(data, null, '\t')
64+
? JSON.stringify(json)
65+
: JSON.stringify(json, null, '\t')
18866
)
18967
},
19068
})

0 commit comments

Comments
 (0)