Skip to content

Commit 92508df

Browse files
committed
Clean up JSON Exporter data
1 parent c259e75 commit 92508df

File tree

4 files changed

+229
-111
lines changed

4 files changed

+229
-111
lines changed

exporters/jsonExporter/jsonExporter.ts

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@ interface ISerealizedAnimationNode {
77
uuid: string
88
node: undefined
99
matrix: number[]
10-
pos: [number, number, number]
11-
rot: [number, number, number, number]
12-
scale: [number, number, number]
1310
interpolation?: 'instant' | 'default'
1411
}
1512

@@ -38,33 +35,30 @@ function serializeOutlinerNode(node: AnimatedJava.AnyRenderedNode) {
3835
} = node
3936
return {
4037
type,
41-
parent,
4238
name,
4339
uuid: outlinerNode.uuid,
4440
customModelData,
4541
resourceLocation,
46-
scale,
47-
modelPath,
4842
}
4943
}
5044
case 'camera': {
51-
const { type, name, parent, teleported_entity_type, node: outlinerNode } = node
45+
const { type, name, parent, entity_type, nbt, node: outlinerNode } = node
5246
return {
5347
type,
54-
parent,
5548
name,
5649
uuid: outlinerNode.uuid,
57-
teleported_entity_type,
50+
entity_type,
51+
nbt,
5852
}
5953
}
6054
case 'locator': {
61-
const { type, name, parent, teleported_entity_type, node: outlinerNode } = node
55+
const { type, name, parent, entity_type, nbt, node: outlinerNode } = node
6256
return {
6357
type,
64-
parent,
6558
name,
6659
uuid: outlinerNode.uuid,
67-
teleported_entity_type,
60+
entity_type,
61+
nbt,
6862
}
6963
}
7064
}
@@ -78,9 +72,6 @@ function serializeAnimationNode(node: AnimatedJava.IAnimationNode): ISerealizedA
7872
uuid,
7973
node: undefined,
8074
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],
8475
interpolation,
8576
}
8677
}
@@ -103,7 +94,6 @@ interface RawExportData {
10394
exporter_settings: Record<string, any>
10495
rig: {
10596
default_pose: ISerealizedAnimationNode[]
106-
node_structure: AnimatedJava.INodeStructure
10797
node_map: any
10898
}
10999
animations: Record<string, ISerealizedAnimation>
@@ -166,7 +156,6 @@ export function loadExporter() {
166156
exporter_settings: {},
167157
rig: {
168158
default_pose: exportOptions.rig.defaultPose.map(serializeAnimationNode),
169-
node_structure: exportOptions.rig.nodeStructure,
170159
node_map: {},
171160
},
172161
animations: {},

src/minecraft/jsonText.ts

Lines changed: 178 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -41,60 +41,59 @@ const COLOR_MAP: Record<string, string> = {
4141
black: '#000000',
4242
}
4343

44-
type JsonTextComponent =
45-
| string
46-
| JsonTextArray
47-
| {
48-
text?: string
49-
font?: string
50-
color?: JsonTextColor
51-
extra?: JsonTextArray
52-
bold?: true | false
53-
italic?: true | false
54-
underlined?: true | false
55-
strikethrough?: true | false
56-
obfuscated?: true | false
57-
insertion?: string
58-
clickEvent?: {
59-
action:
60-
| 'open_url'
61-
| 'open_file'
62-
| 'run_command'
63-
| 'suggest_command'
64-
| 'change_page'
65-
| 'copy_to_clipboard'
66-
value: string
67-
}
68-
hoverEvent?: {
69-
action: 'show_text' | 'show_item' | 'show_entity'
70-
contents:
71-
| JsonTextComponent
72-
| {
73-
type: string
74-
id: string
75-
name?: string
76-
}
77-
| {
78-
id: string
79-
count?: number
80-
tag?: string
81-
}
82-
}
83-
tl?: string
84-
with?: JsonTextArray
85-
score?: {
86-
name: string
87-
objective: string
88-
value?: number
89-
}
90-
selector?: string
91-
separator?: string
92-
keybind?: string
93-
nbt?: string
94-
block?: string
95-
entity?: string
96-
storage?: string
97-
}
44+
type JsonTextObject = {
45+
text?: string
46+
font?: string
47+
color?: JsonTextColor
48+
extra?: JsonTextArray
49+
bold?: true | false
50+
italic?: true | false
51+
underlined?: true | false
52+
strikethrough?: true | false
53+
obfuscated?: true | false
54+
insertion?: string
55+
clickEvent?: {
56+
action:
57+
| 'open_url'
58+
| 'open_file'
59+
| 'run_command'
60+
| 'suggest_command'
61+
| 'change_page'
62+
| 'copy_to_clipboard'
63+
value: string
64+
}
65+
hoverEvent?: {
66+
action: 'show_text' | 'show_item' | 'show_entity'
67+
contents:
68+
| JsonTextComponent
69+
| {
70+
type: string
71+
id: string
72+
name?: string
73+
}
74+
| {
75+
id: string
76+
count?: number
77+
tag?: string
78+
}
79+
}
80+
tl?: string
81+
with?: JsonTextArray
82+
score?: {
83+
name: string
84+
objective: string
85+
value?: number
86+
}
87+
selector?: string
88+
separator?: string
89+
keybind?: string
90+
nbt?: string
91+
block?: string
92+
entity?: string
93+
storage?: string
94+
}
95+
96+
type JsonTextComponent = string | JsonTextArray | JsonTextObject
9897

9998
type JsonTextArray = JsonTextComponent[] | string[]
10099

@@ -112,30 +111,136 @@ export class JsonText {
112111
return this.text
113112
}
114113

115-
renderToCanvas(): CanvasFrame {
116-
const canvas = new CanvasFrame(1, 1)
114+
renderToCanvas(): TextCanvas {
115+
const textCanvas = new TextCanvas()
116+
117+
this._renderToCanvas(this.text, textCanvas)
118+
// textCanvas.canvas.width = textCanvas.width
119+
// textCanvas.canvas.height = textCanvas.height
120+
textCanvas.render()
121+
122+
return textCanvas
123+
}
124+
125+
private _renderToCanvas(comp: JsonTextComponent, textCanvas: TextCanvas) {
126+
if (comp instanceof Array) {
127+
console.log('array', comp)
128+
comp.forEach(c => this._renderToCanvas(c, textCanvas))
129+
} else if (typeof comp === 'string') {
130+
console.log('string', comp)
131+
} else {
132+
console.log('obj', comp)
133+
this._renderObj(comp, textCanvas)
134+
}
135+
}
136+
137+
private _renderObj(obj: JsonTextObject, textCanvas: TextCanvas) {
138+
const writeOptions: Record<string, any> = {}
139+
// canvas.ctx.font = FONT
140+
if (obj.color)
141+
writeOptions.fillStyle = obj.color[0] === '#' ? obj.color : COLOR_MAP[obj.color]
142+
143+
if (obj.bold) writeOptions.font = 'bold ' + FONT
144+
if (obj.italic) writeOptions.font = 'italic ' + FONT
145+
// if (obj.underlined) canvas.canvas.style.textDecoration = 'underline'
146+
// if (obj.strikethrough) canvas.canvas.style.textDecoration = 'line-through'
147+
// if (obj.obfuscated) canvas.canvas.style.textDecoration = 'blink'
148+
149+
if (obj.text) {
150+
textCanvas.write(obj.text, writeOptions)
151+
} else if (obj.score) {
152+
textCanvas.write(
153+
obj.score.value === undefined
154+
? `(${obj.score.name} ${obj.score.objective})`
155+
: obj.score.value.toString(),
156+
writeOptions
157+
)
158+
} else if (obj.nbt) {
159+
let text = `${obj.nbt}`
160+
if (obj.block) text += ` ${obj.block}`
161+
else if (obj.entity) text += ` ${obj.entity}`
162+
else if (obj.storage) text += ` ${obj.storage}`
163+
textCanvas.write(text, writeOptions)
164+
} else if (obj.selector) {
165+
textCanvas.write(`(${obj.selector})`, writeOptions)
166+
}
167+
}
168+
}
169+
170+
interface TextBit {
171+
canvas: CanvasFrame
172+
posX: number
173+
posY: number
174+
}
175+
176+
class TextCanvas {
177+
canvasFrame: CanvasFrame
178+
canvas: HTMLCanvasElement
179+
ctx: CanvasRenderingContext2D
180+
181+
private textBits: TextBit[] = []
182+
183+
currentX = 0
184+
currentY = 0
185+
186+
constructor() {
187+
this.canvasFrame = new CanvasFrame(1, 1)
188+
this.canvas = this.canvasFrame.canvas
189+
this.ctx = this.canvasFrame.ctx
190+
}
191+
192+
get width() {
193+
return this.canvas.width
194+
}
195+
196+
set width(width: number) {
197+
this.canvas.width = width
198+
}
199+
200+
get height() {
201+
return this.canvas.height
202+
}
203+
204+
set height(height: number) {
205+
this.canvas.height = height
206+
}
207+
208+
write(text: string, writeOptions: Record<string, any> = {}) {
209+
const measure = new CanvasFrame(1, 1)
210+
measure.ctx.font = FONT
211+
measure.ctx.filter = PIXEL_FILTER
212+
const metrics = measure.ctx.measureText(text)
213+
const width = Math.ceil(metrics.width)
214+
const height = Math.ceil(metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent)
215+
216+
const canvas = new CanvasFrame(width, height)
117217
canvas.ctx.font = FONT
118218
canvas.ctx.filter = PIXEL_FILTER
219+
canvas.ctx.fillStyle = '#ffffff'
220+
canvas.ctx.textBaseline = 'top'
119221

120-
function recurse(text: JsonTextComponent) {
121-
if (text instanceof Array) {
122-
text.forEach(recurse)
123-
} else if (typeof text === 'string') {
124-
//
125-
} else {
126-
canvas.ctx.fillStyle = text.color
127-
? text.color[0] === '#'
128-
? text.color
129-
: COLOR_MAP[text.color]
130-
: '#FFFFFF'
131-
}
132-
}
222+
Object.assign(canvas.ctx, writeOptions)
223+
224+
canvas.ctx.fillText(text, 0, 0)
133225

134-
recurse(this.text)
226+
this.textBits.push({ canvas, posX: this.currentX, posY: this.currentY })
135227

136-
// canvas.canvas.width = 0
137-
// canvas.canvas.height = 0
228+
this.currentX += width
229+
// this.currentY += height
230+
}
231+
232+
render() {
233+
console.log('rendering', this.textBits)
234+
235+
const totalWidth = this.textBits.reduce((acc, bit) => acc + bit.canvas.width, 0)
236+
const totalHeight = this.textBits.reduce((acc, bit) => Math.max(acc, bit.canvas.height), 0)
138237

139-
return canvas
238+
this.width = totalWidth
239+
this.height = totalHeight
240+
241+
for (const bit of this.textBits) {
242+
console.log('drawing', bit)
243+
this.ctx.drawImage(bit.canvas.canvas, bit.posX, bit.posY)
244+
}
140245
}
141246
}

0 commit comments

Comments
 (0)