|
4 | 4 |
|
5 | 5 | import type { IBlueprintBoneConfigJSON, IBlueprintVariantJSON } from '../blueprintFormat' |
6 | 6 | import { type defaultValues } from '../blueprintSettings' |
| 7 | +import { |
| 8 | + getKeyframeCommands, |
| 9 | + getKeyframeExecuteCondition, |
| 10 | + getKeyframeRepeat, |
| 11 | + getKeyframeRepeatFrequency, |
| 12 | + getKeyframeVariant, |
| 13 | +} from '../mods/customKeyframesMod' |
7 | 14 | import { EasingKey } from '../util/easing' |
8 | 15 | import { resolvePath } from '../util/fileUtil' |
9 | 16 | import { detectCircularReferences, scrubUndefined } from '../util/misc' |
@@ -46,20 +53,38 @@ type ExportedBakedAnimation = Omit<IRenderedAnimation, 'uuid' | 'frames' | 'incl |
46 | 53 | frames: ExportedAnimationFrame[] |
47 | 54 | includedNodes: string[] |
48 | 55 | } |
49 | | -type ExportedAnimator = Array<{ |
50 | | - uuid: string |
| 56 | +type ExportedKeyframe = { |
51 | 57 | time: number |
52 | 58 | 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[] |
63 | 88 | type ExportedDynamicAnimation = { |
64 | 89 | name: string |
65 | 90 | loop_mode: 'once' | 'hold' | 'loop' |
@@ -113,6 +138,67 @@ export interface IExportedJSON { |
113 | 138 | animations: Record<string, ExportedBakedAnimation> | Record<string, ExportedDynamicAnimation> |
114 | 139 | } |
115 | 140 |
|
| 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 | + |
116 | 202 | export function exportJSON(options: { |
117 | 203 | rig: IRenderedRig |
118 | 204 | animations: IRenderedAnimation[] |
@@ -195,36 +281,9 @@ export function exportJSON(options: { |
195 | 281 | animators: {}, |
196 | 282 | } |
197 | 283 | 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 | | - }) |
224 | 284 | // 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) |
228 | 287 | } |
229 | 288 | json.animations[animation.uuid] = animJSON |
230 | 289 | } |
|
0 commit comments