Skip to content

Commit 5b47ad0

Browse files
committed
JSON Exporter
1 parent dbbf9a5 commit 5b47ad0

File tree

10 files changed

+15265
-47
lines changed

10 files changed

+15265
-47
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Animated Java Raw Exporter - An exporter plugin for the Animated Java Blockbench Plugin
1+
Animated Java JSON Exporter - An exporter plugin for the Animated Java Blockbench Plugin
22
Copyright (C) 2023 Titus Evans
33

44
This program is free software: you can redistribute it and/or modify
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { loadExporter } from './rawExporter'
1+
import { loadExporter } from './jsonExporter'
22

33
requestAnimationFrame(function repeat() {
44
if (AnimatedJava?.loaded) loadExporter()
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
// @ts-ignore
2+
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+
pos: [number, number, number]
11+
rot: [number, number, number, number]
12+
scale: [number, number, number]
13+
interpolation?: 'instant' | 'default'
14+
}
15+
16+
function serializeFrame(frame: AnimatedJava.IRenderedFrame) {
17+
return {
18+
time: frame.time,
19+
nodes: frame.nodes.map(serializeAnimationNode),
20+
variant: frame.variant,
21+
commands: frame.commands,
22+
animationState: frame.animationState,
23+
}
24+
}
25+
26+
function serializeOutlinerNode(node: AnimatedJava.AnyRenderedNode) {
27+
switch (node.type) {
28+
case 'bone': {
29+
const {
30+
type,
31+
name,
32+
parent,
33+
customModelData,
34+
resourceLocation,
35+
scale,
36+
modelPath,
37+
node: outlinerNode,
38+
} = node
39+
return {
40+
type,
41+
parent,
42+
name,
43+
uuid: outlinerNode.uuid,
44+
customModelData,
45+
resourceLocation,
46+
scale,
47+
modelPath,
48+
}
49+
}
50+
case 'camera': {
51+
const { type, name, parent, teleported_entity_type, node: outlinerNode } = node
52+
return {
53+
type,
54+
parent,
55+
name,
56+
uuid: outlinerNode.uuid,
57+
teleported_entity_type,
58+
}
59+
}
60+
case 'locator': {
61+
const { type, name, parent, teleported_entity_type, node: outlinerNode } = node
62+
return {
63+
type,
64+
parent,
65+
name,
66+
uuid: outlinerNode.uuid,
67+
teleported_entity_type,
68+
}
69+
}
70+
}
71+
}
72+
73+
function serializeAnimationNode(node: AnimatedJava.IAnimationNode): ISerealizedAnimationNode {
74+
const { type, name, uuid, matrix, pos, rot, scale, interpolation } = node
75+
return {
76+
type,
77+
name,
78+
uuid,
79+
node: undefined,
80+
matrix: matrix.toArray(),
81+
pos: [pos.x, pos.y, pos.z],
82+
rot: [rot.x, rot.y, rot.z, rot.w],
83+
scale: [scale.x, scale.y, scale.z],
84+
interpolation,
85+
}
86+
}
87+
88+
interface ISerealizedAnimation {
89+
frames: ISerealizedAnimationNode[]
90+
duration: number
91+
loopMode: 'loop' | 'once' | 'hold'
92+
}
93+
94+
function serializeAnimation(animation: AnimatedJava.IRenderedAnimation): any {
95+
return {
96+
...animation,
97+
frames: animation.frames.map(serializeFrame),
98+
}
99+
}
100+
101+
interface RawExportData {
102+
project_settings: Record<string, any>
103+
exporter_settings: Record<string, any>
104+
rig: {
105+
default_pose: ISerealizedAnimationNode[]
106+
node_structure: AnimatedJava.INodeStructure
107+
node_map: any
108+
}
109+
animations: Record<string, ISerealizedAnimation>
110+
}
111+
112+
export function loadExporter() {
113+
const API = AnimatedJava.API
114+
115+
API.addTranslations('en', en as Record<string, string>)
116+
117+
const TRANSLATIONS = {
118+
output_file: {
119+
error: {
120+
empty: API.translate(
121+
'animated_java.exporters.json_exporter.settings.output_file.error.empty'
122+
),
123+
},
124+
},
125+
}
126+
127+
new API.Exporter({
128+
id: 'animated_java:json_exporter',
129+
name: API.translate('animated_java.exporters.json_exporter.name'),
130+
description: API.translate('animated_java.exporters.json_exporter.description'),
131+
getSettings() {
132+
return {
133+
output_file: new API.Settings.FileSetting(
134+
{
135+
id: 'animated_java:json_exporter/output_file',
136+
displayName: API.translate(
137+
'animated_java.exporters.json_exporter.settings.output_file'
138+
),
139+
description: API.translate(
140+
'animated_java.exporters.json_exporter.settings.output_file.description'
141+
).split('\n'),
142+
defaultValue: '',
143+
},
144+
function onUpdate(setting) {
145+
if (!setting.value) {
146+
setting.infoPopup = API.createInfo(
147+
'error',
148+
TRANSLATIONS.output_file.error.empty
149+
)
150+
}
151+
}
152+
),
153+
}
154+
},
155+
settingsStructure: [
156+
{
157+
type: 'setting',
158+
settingId: 'animated_java:json_exporter/output_file',
159+
},
160+
],
161+
async export(exportOptions) {
162+
console.log('Export Options:', exportOptions)
163+
164+
const data: RawExportData = {
165+
project_settings: {},
166+
exporter_settings: {},
167+
rig: {
168+
default_pose: exportOptions.rig.defaultPose.map(serializeAnimationNode),
169+
node_structure: exportOptions.rig.nodeStructure,
170+
node_map: {},
171+
},
172+
animations: {},
173+
}
174+
175+
for (const [key, setting] of Object.entries(exportOptions.projectSettings)) {
176+
data.project_settings[key] = setting._save()
177+
}
178+
179+
for (const [key, setting] of Object.entries(exportOptions.exporterSettings)) {
180+
data.exporter_settings[key] = setting._save()
181+
}
182+
183+
for (const [uuid, node] of Object.entries(exportOptions.rig.nodeMap)) {
184+
if (!node.node.export) continue
185+
data.rig.node_map[uuid] = serializeOutlinerNode(node)
186+
}
187+
188+
for (const animation of exportOptions.renderedAnimations) {
189+
data.animations[animation.name] = serializeAnimation(animation)
190+
}
191+
192+
console.log('Exported data:', data)
193+
194+
await fs.promises.writeFile(
195+
exportOptions.exporterSettings.output_file.value,
196+
exportOptions.ajSettings.minify_output.value
197+
? JSON.stringify(data)
198+
: JSON.stringify(data, null, '\t')
199+
)
200+
},
201+
})
202+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# JSON Exporter
2+
animated_java.exporters.json_exporter.name: JSON Exporter
3+
animated_java.exporters.json_exporter.description: Exports an Animated Java Rig as a JSON file for use in plugins or mods.
4+
5+
# Settings
6+
animated_java.exporters.json_exporter.settings.output_file: Output File
7+
animated_java.exporters.json_exporter.settings.output_file.description: The file to export to.
8+
animated_java.exporters.json_exporter.settings.output_file.error.empty: |-
9+
The output file cannot be empty.

exporters/rawExporter/lang/en.yaml

Lines changed: 0 additions & 2 deletions
This file was deleted.

exporters/rawExporter/rawExporter.ts

Lines changed: 0 additions & 38 deletions
This file was deleted.

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,4 @@ BBPlugin.register(PACKAGE.name, {
133133
})
134134

135135
import('../exporters/datapackExporter')
136-
import('../exporters/rawExporter')
136+
import('../exporters/jsonExporter')

0 commit comments

Comments
 (0)