From 644bebfd2b60d6d75e60dc4237f3ed0de215f992 Mon Sep 17 00:00:00 2001 From: Meekiavelique Date: Sun, 28 Jun 2026 11:56:39 +0200 Subject: [PATCH] Add matrix and decomposed transforms to baked plugin export frames --- schemas/plugin-blueprint.schema.json | 257 +++++++++++++++++---------- src/systems/pluginCompiler.ts | 30 ++++ 2 files changed, 190 insertions(+), 97 deletions(-) diff --git a/schemas/plugin-blueprint.schema.json b/schemas/plugin-blueprint.schema.json index 33804ef9..5098a687 100644 --- a/schemas/plugin-blueprint.schema.json +++ b/schemas/plugin-blueprint.schema.json @@ -680,6 +680,26 @@ "type": "object", "default": {}, "properties": { + "matrix": { + "type": "object", + "default": {}, + "description": "A collection of baked transformation matrix keyframes, identified by a floating-point timestamp.", + "patternProperties": { + "^\\d+\\.\\d+$": { + "$ref": "#/definitions/matrix_keyframe" + } + } + }, + "decomposed": { + "type": "object", + "default": {}, + "description": "A collection of baked decomposed transformation keyframes, identified by a floating-point timestamp.", + "patternProperties": { + "^\\d+\\.\\d+$": { + "$ref": "#/definitions/decomposed_keyframe" + } + } + }, "position": { "type": "object", "default": {}, @@ -762,110 +782,153 @@ "$ref": "#/definitions/molang_vector3" }, "interpolation": { + "$ref": "#/definitions/keyframe_interpolation" + } + } + }, + "matrix_keyframe": { + "type": "object", + "required": ["value", "interpolation"], + "description": "A baked transformation matrix keyframe, identified by a floating-point timestamp.", + "properties": { + "value": { + "$ref": "#/definitions/matrix" + }, + "interpolation": { + "$ref": "#/definitions/keyframe_interpolation" + } + } + }, + "decomposed_keyframe": { + "type": "object", + "required": ["value", "interpolation"], + "description": "A baked decomposed transformation keyframe, identified by a floating-point timestamp.", + "properties": { + "value": { "type": "object", - "oneOf": [ - { - "type": "object", - "required": ["type", "easing"], - "properties": { - "type": { - "const": "linear" - }, - "easing": { - "type": "string", - "enum": [ - "linear", - "step", - "ease_in_quad", - "ease_out_quad", - "ease_in_out_quad", - "ease_in_cubic", - "ease_out_cubic", - "ease_in_out_cubic", - "ease_in_quart", - "ease_out_quart", - "ease_in_out_quart", - "ease_in_quint", - "ease_out_quint", - "ease_in_out_quint", - "ease_in_sine", - "ease_out_sine", - "ease_in_out_sine", - "ease_in_expo", - "ease_out_expo", - "ease_in_out_expo", - "ease_in_circ", - "ease_out_circ", - "ease_in_out_circ", - "ease_in_back", - "ease_out_back", - "ease_in_out_back", - "ease_in_elastic", - "ease_out_elastic", - "ease_in_out_elastic", - "ease_in_bounce", - "ease_out_bounce", - "ease_in_out_bounce" - ] - }, - "easing_arguments": { - "type": "array", - "items": { - "type": "number" - }, - "default": [] - } - } - }, - { - "type": "object", - "required": [ - "type", - "left_handle_time", - "left_handle_value", - "right_handle_time", - "right_handle_value" - ], - "properties": { - "type": { - "const": "bezier" - }, - "left_handle_time": { - "$ref": "#/definitions/vector3" - }, - "left_handle_value": { - "$ref": "#/definitions/vector3" - }, - "right_handle_time": { - "$ref": "#/definitions/vector3" - }, - "right_handle_value": { - "$ref": "#/definitions/vector3" - } - } + "properties": { + "translation": { + "$ref": "#/definitions/vector3", + "default": [0.0, 0.0, 0.0] }, - { - "type": "object", - "required": ["type"], - "properties": { - "type": { - "const": "catmullrom" - } - } + "left_rotation": { + "$ref": "#/definitions/vector4", + "default": [0.0, 0.0, 0.0, 1.0] }, - { - "type": "object", - "required": ["type"], - "properties": { - "type": { - "const": "step" - } - } + "scale": { + "$ref": "#/definitions/vector3", + "default": [1.0, 1.0, 1.0] } - ] + } + }, + "interpolation": { + "$ref": "#/definitions/keyframe_interpolation" } } }, + "keyframe_interpolation": { + "type": "object", + "oneOf": [ + { + "type": "object", + "required": ["type", "easing"], + "properties": { + "type": { + "const": "linear" + }, + "easing": { + "type": "string", + "enum": [ + "linear", + "step", + "ease_in_quad", + "ease_out_quad", + "ease_in_out_quad", + "ease_in_cubic", + "ease_out_cubic", + "ease_in_out_cubic", + "ease_in_quart", + "ease_out_quart", + "ease_in_out_quart", + "ease_in_quint", + "ease_out_quint", + "ease_in_out_quint", + "ease_in_sine", + "ease_out_sine", + "ease_in_out_sine", + "ease_in_expo", + "ease_out_expo", + "ease_in_out_expo", + "ease_in_circ", + "ease_out_circ", + "ease_in_out_circ", + "ease_in_back", + "ease_out_back", + "ease_in_out_back", + "ease_in_elastic", + "ease_out_elastic", + "ease_in_out_elastic", + "ease_in_bounce", + "ease_out_bounce", + "ease_in_out_bounce" + ] + }, + "easing_arguments": { + "type": "array", + "items": { + "type": "number" + }, + "default": [] + } + } + }, + { + "type": "object", + "required": [ + "type", + "left_handle_time", + "left_handle_value", + "right_handle_time", + "right_handle_value" + ], + "properties": { + "type": { + "const": "bezier" + }, + "left_handle_time": { + "$ref": "#/definitions/vector3" + }, + "left_handle_value": { + "$ref": "#/definitions/vector3" + }, + "right_handle_time": { + "$ref": "#/definitions/vector3" + }, + "right_handle_value": { + "$ref": "#/definitions/vector3" + } + } + }, + { + "type": "object", + "required": ["type"], + "properties": { + "type": { + "const": "catmullrom" + } + } + }, + { + "type": "object", + "required": ["type"], + "properties": { + "type": { + "const": "step" + } + } + } + ] + }, "resource_location": { "type": "string", "pattern": "^[a-z0-9_\\-]+:[a-z0-9_\\-./]+$", diff --git a/src/systems/pluginCompiler.ts b/src/systems/pluginCompiler.ts index f286d2b9..270b2132 100644 --- a/src/systems/pluginCompiler.ts +++ b/src/systems/pluginCompiler.ts @@ -150,6 +150,20 @@ interface TransformationKeyframe { interpolation: TransformationKeyframeInterpolation } +interface MatrixKeyframe { + value: number[] + interpolation: TransformationKeyframeInterpolation +} + +interface DecomposedKeyframe { + value: { + translation: ArrayVector3 + left_rotation: ArrayVector4 + scale: ArrayVector3 + } + interpolation: TransformationKeyframeInterpolation +} + interface PluginAnimation { loop_mode: LoopMode length: number @@ -162,6 +176,8 @@ interface PluginAnimation { node_keyframes?: Record< string, { + matrix?: Record + decomposed?: Record position?: Record rotation?: Record scale?: Record @@ -637,10 +653,24 @@ function serializeBakedAnimation(options: { : { type: 'linear', easing: 'linear' } const channels = (node_keyframes[nodeId] ??= {}) + const matrix = (channels.matrix ??= {}) + const decomposed = (channels.decomposed ??= {}) const position = (channels.position ??= {}) const rotation = (channels.rotation ??= {}) const scale = (channels.scale ??= {}) + matrix[timeKey] = { + value: transform.matrix.elements.slice(), + interpolation, + } + decomposed[timeKey] = { + value: { + translation: transform.decomposed.translation.toArray() as ArrayVector3, + left_rotation: transform.decomposed.left_rotation.toArray() as ArrayVector4, + scale: transform.decomposed.scale.toArray() as ArrayVector3, + }, + interpolation, + } position[timeKey] = { value: transform.pos.map(toMolangNumber) as StringVector3, interpolation,