Skip to content

Commit ffe0372

Browse files
committed
🚧Implement #242 & #240
- Reduced complexity of keyframe data.
1 parent d610ebc commit ffe0372

File tree

3 files changed

+205
-104
lines changed

3 files changed

+205
-104
lines changed

schemas/pluginJson.schema.json

Lines changed: 104 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,12 @@
222222
},
223223
"vec2": { "type": "array", "items": { "type": "number" }, "minItems": 2, "maxItems": 2 },
224224
"vec3": { "type": "array", "items": { "type": "number" }, "minItems": 3, "maxItems": 3 },
225+
"vec3String": {
226+
"type": "array",
227+
"items": { "type": "string" },
228+
"minItems": 3,
229+
"maxItems": 3
230+
},
225231
"vec4": { "type": "array", "items": { "type": "number" }, "minItems": 4, "maxItems": 4 },
226232
"vanillaModel": {
227233
"type": "object",
@@ -652,73 +658,72 @@
652658
},
653659
"keyframe": {
654660
"type": "object",
655-
"required": ["time", "uuid", "channel", "data_points", "interpolation", "easing"],
661+
"required": ["time", "channel"],
656662
"properties": {
657663
"time": { "type": "number" },
658-
"uuid": { "type": "string" },
659-
"channel": { "type": "string" },
660-
"data_points": {
661-
"type": "array",
662-
"items": { "$ref": "#/definitions/keyframeDataPoint" }
663-
},
664-
"interpolation": {
665-
"type": "string",
666-
"enum": ["linear", "bezier", "catmullrom", "step"]
664+
"channel": { "type": "string" }
665+
},
666+
"oneOf": [
667+
{
668+
"required": ["value", "interpolation"],
669+
"properties": {
670+
"channel": { "enum": ["position", "rotation", "scale"] },
671+
"value": { "$ref": "#/definitions/vec3String" },
672+
"post": { "$ref": "#/definitions/vec3String" },
673+
"interpolation": {
674+
"oneOf": [
675+
{
676+
"type": "object",
677+
"properties": {
678+
"type": { "const": "linear" },
679+
"easing": { "$ref": "#/definitions/easing" },
680+
"easingArgs": {
681+
"type": "array",
682+
"items": { "type": "number" }
683+
}
684+
}
685+
},
686+
{
687+
"type": "object",
688+
"properties": {
689+
"type": { "const": "bezier" }
690+
}
691+
},
692+
{
693+
"type": "object",
694+
"properties": {
695+
"type": { "const": "catmullrom" }
696+
}
697+
},
698+
{
699+
"type": "object",
700+
"properties": {
701+
"type": { "const": "step" }
702+
}
703+
}
704+
]
705+
}
706+
}
667707
},
668-
"easing": {
669-
"type": "string",
670-
"enum": [
671-
"linear",
672-
"step",
673-
"easeInQuad",
674-
"easeOutQuad",
675-
"easeInOutQuad",
676-
"easeInCubic",
677-
"easeOutCubic",
678-
"easeInOutCubic",
679-
"easeInQuart",
680-
"easeOutQuart",
681-
"easeInOutQuart",
682-
"easeInQuint",
683-
"easeOutQuint",
684-
"easeInOutQuint",
685-
"easeInSine",
686-
"easeOutSine",
687-
"easeInOutSine",
688-
"easeInExpo",
689-
"easeOutExpo",
690-
"easeInOutExpo",
691-
"easeInCirc",
692-
"easeOutCirc",
693-
"easeInOutCirc",
694-
"easeInBack",
695-
"easeOutBack",
696-
"easeInOutBack",
697-
"easeInElastic",
698-
"easeOutElastic",
699-
"easeInOutElastic",
700-
"easeInBounce",
701-
"easeOutBounce",
702-
"easeInOutBounce"
703-
]
708+
{
709+
"required": ["variant"],
710+
"properties": {
711+
"channel": { "const": "variant" },
712+
"variant": { "type": "string" },
713+
"execute_condition": { "type": "string" }
714+
}
704715
},
705-
"easingArgs": {
706-
"type": "array",
707-
"items": { "type": "number" }
716+
{
717+
"required": ["commands"],
718+
"properties": {
719+
"channel": { "const": "commands" },
720+
"commands": { "type": "string" },
721+
"execute_condition": { "type": "string" },
722+
"repeat": { "type": "boolean" },
723+
"repeat_frequency": { "type": "number", "min": 1 }
724+
}
708725
}
709-
}
710-
},
711-
"keyframeDataPoint": {
712-
"type": "object",
713-
"properties": {
714-
"x": { "type": "string" },
715-
"y": { "type": "string" },
716-
"z": { "type": "string" },
717-
"commands": { "type": "string" },
718-
"execute_condition": { "type": "string" },
719-
"repeat": { "type": "boolean" },
720-
"repeat_frequency": { "type": "number", "min": 1 }
721-
}
726+
]
722727
},
723728
"variant": {
724729
"type": "object",
@@ -754,6 +759,43 @@
754759
"description": "Whether or not this variant is the default variant."
755760
}
756761
}
762+
},
763+
"easing": {
764+
"type": "string",
765+
"enum": [
766+
"linear",
767+
"step",
768+
"easeInQuad",
769+
"easeOutQuad",
770+
"easeInOutQuad",
771+
"easeInCubic",
772+
"easeOutCubic",
773+
"easeInOutCubic",
774+
"easeInQuart",
775+
"easeOutQuart",
776+
"easeInOutQuart",
777+
"easeInQuint",
778+
"easeOutQuint",
779+
"easeInOutQuint",
780+
"easeInSine",
781+
"easeOutSine",
782+
"easeInOutSine",
783+
"easeInExpo",
784+
"easeOutExpo",
785+
"easeInOutExpo",
786+
"easeInCirc",
787+
"easeOutCirc",
788+
"easeInOutCirc",
789+
"easeInBack",
790+
"easeOutBack",
791+
"easeInOutBack",
792+
"easeInElastic",
793+
"easeOutElastic",
794+
"easeInOutElastic",
795+
"easeInBounce",
796+
"easeOutBounce",
797+
"easeInOutBounce"
798+
]
757799
}
758800
}
759801
}

src/systems/jsonCompiler.ts

Lines changed: 100 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44

55
import type { IBlueprintBoneConfigJSON, IBlueprintVariantJSON } from '../blueprintFormat'
66
import { type defaultValues } from '../blueprintSettings'
7+
import {
8+
getKeyframeCommands,
9+
getKeyframeExecuteCondition,
10+
getKeyframeRepeat,
11+
getKeyframeRepeatFrequency,
12+
getKeyframeVariant,
13+
} from '../mods/customKeyframesMod'
714
import { EasingKey } from '../util/easing'
815
import { resolvePath } from '../util/fileUtil'
916
import { detectCircularReferences, scrubUndefined } from '../util/misc'
@@ -46,20 +53,38 @@ type ExportedBakedAnimation = Omit<IRenderedAnimation, 'uuid' | 'frames' | 'incl
4653
frames: ExportedAnimationFrame[]
4754
includedNodes: string[]
4855
}
49-
type ExportedAnimator = Array<{
50-
uuid: string
56+
type ExportedKeyframe = {
5157
time: number
5258
channel: string
53-
data_points: KeyframeDataPoint[]
54-
interpolation: 'linear' | 'bezier' | 'catmullrom' | 'step'
55-
bezier_linked?: boolean
56-
bezier_left_time?: ArrayVector3
57-
bezier_left_value?: ArrayVector3
58-
bezier_right_time?: ArrayVector3
59-
bezier_right_value?: ArrayVector3
60-
easing: EasingKey
61-
easingArgs?: number[]
62-
}>
59+
value?: [string, string, string]
60+
post?: [string, string, string]
61+
interpolation?:
62+
| {
63+
type: 'linear'
64+
easing: EasingKey
65+
easingArgs?: number[]
66+
}
67+
| {
68+
type: 'bezier'
69+
bezier_linked?: boolean
70+
bezier_left_time?: ArrayVector3
71+
bezier_left_value?: ArrayVector3
72+
bezier_right_time?: ArrayVector3
73+
bezier_right_value?: ArrayVector3
74+
}
75+
| {
76+
type: 'catmullrom'
77+
}
78+
| {
79+
type: 'step'
80+
}
81+
commands?: string
82+
variant?: string
83+
execute_condition?: string
84+
repeat?: boolean
85+
repeat_frequency?: number
86+
}
87+
type ExportedAnimator = ExportedKeyframe[]
6388
type ExportedDynamicAnimation = {
6489
name: string
6590
loop_mode: 'once' | 'hold' | 'loop'
@@ -113,6 +138,67 @@ export interface IExportedJSON {
113138
animations: Record<string, ExportedBakedAnimation> | Record<string, ExportedDynamicAnimation>
114139
}
115140

141+
function serailizeKeyframe(kf: _Keyframe): ExportedKeyframe {
142+
const json = {
143+
time: kf.time,
144+
channel: kf.channel,
145+
commands: getKeyframeCommands(kf),
146+
variant: getKeyframeVariant(kf),
147+
execute_condition: getKeyframeExecuteCondition(kf),
148+
repeat: getKeyframeRepeat(kf),
149+
repeat_frequency: getKeyframeRepeatFrequency(kf),
150+
} as ExportedKeyframe
151+
152+
switch (json.channel) {
153+
case 'variant':
154+
case 'commands':
155+
break
156+
default: {
157+
json.value = [
158+
kf.get('x', 0).toString(),
159+
kf.get('y', 0).toString(),
160+
kf.get('z', 0).toString(),
161+
]
162+
json.interpolation = { type: kf.interpolation } as any
163+
}
164+
}
165+
166+
if (json.interpolation) {
167+
switch (json.interpolation.type) {
168+
case 'linear': {
169+
json.interpolation.easing = kf.easing!
170+
if (kf.easingArgs?.length) json.interpolation.easingArgs = kf.easingArgs
171+
break
172+
}
173+
case 'bezier': {
174+
json.interpolation.bezier_linked = kf.bezier_linked
175+
json.interpolation.bezier_left_time = kf.bezier_left_time.slice() as ArrayVector3
176+
json.interpolation.bezier_left_value = kf.bezier_left_value.slice() as ArrayVector3
177+
json.interpolation.bezier_right_time = kf.bezier_right_time.slice() as ArrayVector3
178+
json.interpolation.bezier_right_value =
179+
kf.bezier_right_value.slice() as ArrayVector3
180+
break
181+
}
182+
case 'catmullrom': {
183+
break
184+
}
185+
case 'step': {
186+
break
187+
}
188+
}
189+
}
190+
191+
if (kf.data_points.length === 2) {
192+
json.post = [
193+
kf.get('x', 1).toString(),
194+
kf.get('y', 1).toString(),
195+
kf.get('z', 1).toString(),
196+
]
197+
}
198+
199+
return json
200+
}
201+
116202
export function exportJSON(options: {
117203
rig: IRenderedRig
118204
animations: IRenderedAnimation[]
@@ -195,36 +281,9 @@ export function exportJSON(options: {
195281
animators: {},
196282
}
197283
for (const [uuid, animator] of Object.entries(animation.animators)) {
198-
const keyframes = animator.keyframes.map(kf => {
199-
const keyframeJSON: any = kf.getUndoCopy(true)
200-
delete keyframeJSON.color
201-
if (
202-
Array.isArray(keyframeJSON.easingArgs) &&
203-
keyframeJSON.easingArgs.length === 0
204-
) {
205-
delete keyframeJSON.easingArgs
206-
}
207-
if (keyframeJSON.data_points?.length) {
208-
const isCustomChannel = ['commands', 'variant'].includes(kf.channel)
209-
for (const dp of keyframeJSON.data_points) {
210-
if (isCustomChannel) {
211-
delete dp.x
212-
delete dp.y
213-
delete dp.z
214-
continue
215-
}
216-
if (dp.x !== undefined) dp.x = String(dp.x)
217-
if (dp.y !== undefined) dp.y = String(dp.y)
218-
if (dp.z !== undefined) dp.z = String(dp.z)
219-
}
220-
}
221-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
222-
return keyframeJSON
223-
})
224284
// Only include animators with keyframes
225-
if (keyframes.length > 0) {
226-
animJSON.animators[uuid] = keyframes
227-
}
285+
if (animator.keyframes.length === 0) continue
286+
animJSON.animators[uuid] = animator.keyframes.map(serailizeKeyframe)
228287
}
229288
json.animations[animation.uuid] = animJSON
230289
}

test_blueprints/armor_stand.ajblueprint

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3033,7 +3033,7 @@
30333033
"override": false,
30343034
"length": 0.8,
30353035
"snapping": 20,
3036-
"selected": false,
3036+
"selected": true,
30373037
"saved": false,
30383038
"path": "",
30393039
"anim_time_update": "",

0 commit comments

Comments
 (0)