{
	"$schema": "https://json-schema.org/draft/2020-12/schema",
	"$id": "https://schema.stfform.at/stf.animation.schema.json",
	"title": "STF Animation",
	"description": "An animation relative to a prefab.",
	"stfImplementations": {
		"blender": {
			"representingType": "bpy.types.Action setup with Slot Link",
			"link": "https://codeberg.org/stf_format/stf_blender/src/branch/master/stfblender/stf_resources/stf/stf_animation/stf_animation.py"
		},
		"godot": {
			"representingType": "Animation",
			"link": "https://codeberg.org/stf_format/stf_godot/src/branch/master/addons/stf_godot/resources/stf/STF_Animation.gd"
		},
		"unity": {
			"representingType": "AnimationClip",
			"link": "https://codeberg.org/stf_format/stf_unity/src/branch/master/Runtime/Resources/Resources_STF/STF_Animation.cs",
			"extra_links": {
				"Default Processor": "https://codeberg.org/stf_format/stf_unity/src/branch/master/Runtime/Processors/Processors_STF/STF_Animation_Processor.cs"
			}
		}
	},
	"allOf": [{ "$ref": "https://schema.stfform.at/stf.schema.json#/$defs/stf_data_resource" }],
	"properties": {
		"type": {
			"const": "stf.animation"
		},
		"loop": {
			"enum": ["loop", "none"],
			"default": "none",
			"description": "Whether to loop the animation and how."
		},
		"fps": {
			"type": "number"
		},
		"range": {
			"type": "array",
			"items": {
				"type": "number"
			},
			"minItems": 2,
			"maxItems": 2
		},
		"tracks": {
			"type": "array",
			"items": {
				"type": "object",
				"title": "Animation Track",
				"$ref": "#/$defs/animation_track"
			},
			"stfExpand": true
		},
		"tracks_baked": {
			"type": "array",
			"items": {
				"type": "object",
				"title": "Baked Animation Track",
				"$ref": "#/$defs/animation_track"
			},
			"description": "Tracks that are the result of a baking operation.",
			"stfExpand": true
		}
	},
	"required": [
		"type",
		"fps",
		"range",
		"tracks"
	],
	"additionalProperties": false,

	"$defs": {
		"animation_track": {
			"title": "Animation Track",
			"type": "object",
			"properties": {
				"target": {
					"$ref": "https://schema.stfform.at/stf.schema.json#resource_id_path",
					"description": "STF path to the target property. Must start with a Resource-ID."
				},
				"timepoints": {
					"type": "array",
					"items": {
						"type": "number"
					},
					"description": "The timepoints at which this track has keyframes. Must be sorted from earliest to latest."
				},
				"interpolation": {
					"enum": ["bezier", "constant", "linear", "quadratic", "cubic"],
					"description": "Fallback interpolation type for the entire track."
				},
				"subtracks": {
					"type": "array",
					"items": {
						"type": ["object", "null"],
						"title": "Subtrack",
						"properties": {
							"keyframes": {
								"type": "array",
								"title": "Keyframe",
								"oneOf": [
									{
										"prefixItems": [
											{
												"title": "source_of_truth",
												"type": "boolean",
												"description": "Whether this keyframe is a source of truth, as in not baked or generated."
											},
											{
												"title": "value",
												"type": "number",
												"description": "The keyframes **value**."
											},
											{
												"title": "interpolation",
												"enum": ["constant", "linear", "quadratic", "cubic"],
												"description": "Interpolation type for this keyframe. Depending on this, the keyframe array may contain further items."
											}
										],
										"items": {
											"title": "in_tangent",
											"type": "array",
											"items": {
												"type": "number"
											},
											"minItems": 2,
											"maxItems": 2,
											"description": "In-tangent x and y offset. In case the previous keyframe has an out-tangent, this keyframes in-tangent is added at the last position in the keyframe-array."
										}
									},
									{
										"prefixItems": [
											{
												"title": "source_of_truth",
												"type": "boolean",
												"description": "Whether this keyframe is a source of truth, as in not baked or generated."
											},
											{
												"title": "value",
												"type": "number",
												"description": "The keyframes **value**."
											},
											{
												"title": "interpolation",
												"enum": ["bezier"],
												"description": "Interpolation type for this keyframe. Depending on this, the keyframe array may contain further items."
											},
											{
												"title": "tangent_type",
												"enum": ["split", "aligned", "auto"]
											},
											{
												"title": "out_tangent",
												"type": "array",
												"items": {
													"type": "number"
												},
												"minItems": 2,
												"maxItems": 2,
												"description": "Out-tangent x and y offset"
											}
										],
										"items": {
											"title": "in_tangent",
											"type": "array",
											"items": {
												"type": "number"
											},
											"minItems": 2,
											"maxItems": 2,
											"description": "In-tangent x and y offset. In case the previous keyframe has an out-tangent, this keyframes in-tangent is added at the last position in the keyframe-array."
										}
									}
								],
								"minItems": 0,
								"maxItems": 1,
								"unevaluatedItems": false,
								"description": "In case the previous keyframe has an out-tangent, this keyframes in-tangent is added at the last position in the keyframe-array.",
								"stfExpand": true
							},
							"baked": {
								"$ref": "https://schema.stfform.at/stf.schema.json#buffer_ref",
								"description": "Buffer reference. Baked keyframe values for each frame within the animations `range`."
							}
						},
						"required": [
							"keyframes"
						]
					},
					"description": "In case a vector with 3 components is animated, each of the vectors component will have its own subtrack. In case a subtrack is not to be animated, it can be `null`",
					"stfExpand": true
				},
				"track_baked": {
					"type": "boolean",
					"default": false,
					"description": "Indicates whether the entire tracks is generated by a baking operation."
				},
				"reset_animation": {
					"$ref": "https://schema.stfform.at/stf.schema.json#resource_ref",
					"description": "Resource reference to a reset animation."
				},
				"is_reset_animation": {
					"type": "boolean",
					"default": false,
					"description": "Whether this animation is a reset-animation."
				}
			},
			"required": [
				"target",
				"timepoints",
				"subtracks"
			]
		}
	},

	"examples": [
		{
			"type": "stf.animation",
			"name": "Test Animation",
			"loop": "none",
			"fps": 24,
			"range": [
				1.0,
				5.0
			],
			"reset_animation": 0,
			"tracks": [
				{
					"target": [
						"bbff51e8-b34d-4ec4-aca4-3fcecad73309",
						"instance",
						"blendshape",
						"MouthEdgesOpen",
						"value"
					],
					"timepoints": [
						1.0,
						5.0
					],
					"subtracks": [
						{
							"keyframes": [
								[
									true,
									0.0,
									"bezier",
									"auto",
									[
										1.3333334922790527,
										0.0
									]
								],
								[
									true,
									1.0,
									"bezier",
									"auto",
									[
										1.3333334922790527,
										0.0
									],
									[
										-1.3333334922790527,
										0.0
									]
								]
							],
							"baked": 0
						}
					],
					"interpolation": "bezier",
					"track_baked": false
				},
				{
					"target": [
						"e6ae2ed1-fc53-43ee-ac53-05bf296d5fc1",
						"instance",
						"29c1fb4e-37f7-46d5-b07e-526934455996",
						"r"
					],
					"timepoints": [
						1.0,
						5.0
					],
					"subtracks": [
						{
							"keyframes": [
								[
									true,
									0.8330915570259094,
									"bezier",
									"auto",
									[
										1.3333334922790527,
										0.0
									]
								],
								[
									true,
									0.8460156917572021,
									"bezier",
									"auto",
									[
										1.3333334922790527,
										0.0
									],
									[
										-1.3333334922790527,
										0.0
									]
								]
							],
							"baked": 6
						},
						{
							"keyframes": [
								[
									true,
									4.20605830192368e-16,
									"bezier",
									"auto",
									[
										1.3333334922790527,
										0.0
									]
								],
								[
									true,
									4.3544335926898076e-16,
									"bezier",
									"auto",
									[
										1.3333334922790527,
										0.0
									],
									[
										-1.3333334922790527,
										0.0
									]
								]
							],
							"baked": 7
						},
						{
							"keyframes": [
								[
									true,
									-1.713443229014921e-16,
									"bezier",
									"auto",
									[
										1.3333334922790527,
										0.0
									]
								],
								[
									true,
									-1.7949213134447822e-16,
									"bezier",
									"auto",
									[
										1.3333334922790527,
										0.0
									],
									[
										-1.3333334922790527,
										0.0
									]
								]
							],
							"baked": 8
						},
						{
							"keyframes": [
								[
									true,
									0.5531351566314697,
									"bezier",
									"auto",
									[
										1.3333334922790527,
										0.0
									]
								],
								[
									true,
									0.5331581234931946,
									"bezier",
									"auto",
									[
										1.3333334922790527,
										0.0
									],
									[
										-1.3333334922790527,
										0.0
									]
								]
							],
							"baked": 9
						}
					],
					"interpolation": "bezier",
					"track_baked": false
				}
			],
			"referenced_buffers": [
				"d8127b86-db5a-4914-b04b-8303058abbcf",
				"65d2a116-3534-418d-a60d-8fbf63e086d0",
				"62291a71-9c14-4fee-811b-406abf5dadec",
				"87638823-adb0-4822-ad66-9cabdf0e0de4",
				"e17a8389-5517-4c33-a5d7-17d93f0d00b4",
				"a893069d-0b84-44e4-846c-24d59ece8fac",
				"4c462ff6-8fd6-4c62-b668-ac87e700c9df",
				"265c2f68-85fb-4f73-8643-8f419f5b9c62",
				"2ccf7b4a-1a7f-4f9f-b729-751b9539eaf6",
				"c7859f35-1c2e-46af-a50e-e52df147b53f"
			],
			"referenced_resources": [
				"49ebe3d6-b733-4556-91ce-5adc6779f0b3"
			]
		}
	]
}