Created
July 3, 2022 22:05
-
-
Save Commoble/ddb139a1e34bd1c78791569080741c02 to your computer and use it in GitHub Desktop.
Animation Codecs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package commoble.databuddy.codec; | |
import java.util.Map; | |
import com.google.common.collect.Lists; | |
import com.mojang.math.Vector3f; | |
import com.mojang.serialization.Codec; | |
import com.mojang.serialization.DataResult; | |
import com.mojang.serialization.codecs.RecordCodecBuilder; | |
import net.minecraft.client.animation.AnimationChannel; | |
import net.minecraft.client.animation.AnimationChannel.Interpolation; | |
import net.minecraft.client.animation.AnimationChannel.Interpolations; | |
import net.minecraft.client.animation.AnimationChannel.Target; | |
import net.minecraft.client.animation.AnimationChannel.Targets; | |
import net.minecraft.client.animation.AnimationDefinition; | |
import net.minecraft.client.animation.Keyframe; | |
import net.minecraft.util.StringRepresentable; | |
/** | |
* <p>Codecs for mojang's keyframe system. Json format of an AnimationDefinition by way of {@link #ANIMATION_DEFINITION}:</p> | |
* <pre> | |
* { | |
* "lengthInSeconds" : float, | |
* "looping": boolean (optional, defaults to false), | |
* "bone_animations": // map of named lists of animation channel objects | |
* { | |
* "name": | |
* [ | |
* { | |
* "target": "position" or "rotation" or "scale", | |
* "keyframes": // list of keyframe objects | |
* [ | |
* { | |
* "timestamp": float, | |
* "target": [x, y, z], // floats | |
* "interpolation": "linear" or "catmullrom" | |
* } | |
* ] | |
* } | |
* ] | |
* } | |
* } | |
* </pre> | |
* <p>Custom target types and interpolation types are not currently supported</p> | |
*/ | |
public class AnimationCodecs | |
{ | |
public static final Codec<Target> TARGET = TargetType.CODEC.flatComapMap(TargetType::target, target -> | |
{ | |
TargetType type = TargetType.BY_TARGET.get(target); | |
return type == null | |
? DataResult.error("Unknown target type (custom target types are not currently supported)") | |
: DataResult.success(type); | |
}); | |
public static final Codec<Interpolation> INTERPOLATION = InterpolationType.CODEC.flatComapMap(InterpolationType::interpolation, interpolation -> | |
{ | |
InterpolationType type = InterpolationType.BY_INTERPOLATION.get(interpolation); | |
return type == null | |
? DataResult.error("Unknown interpolation type (custom interpolation types are not currently supported)") | |
: DataResult.success(type); | |
}); | |
public static final Codec<Keyframe> KEYFRAME = RecordCodecBuilder.create(builder -> builder.group( | |
Codec.FLOAT.fieldOf("timestamp").forGetter(Keyframe::timestamp), | |
Vector3f.CODEC.fieldOf("target").forGetter(Keyframe::target), | |
INTERPOLATION.fieldOf("interpolation").forGetter(Keyframe::interpolation) | |
).apply(builder, Keyframe::new)); | |
public static final Codec<AnimationChannel> ANIMATION_CHANNEL = RecordCodecBuilder.create(builder -> builder.group( | |
TARGET.fieldOf("target").forGetter(AnimationChannel::target), | |
KEYFRAME.listOf().xmap(list -> list.toArray(Keyframe[]::new), arr -> Lists.newArrayList(arr)).fieldOf("keyframes").forGetter(AnimationChannel::keyframes) | |
).apply(builder, AnimationChannel::new)); | |
public static final Codec<AnimationDefinition> ANIMATION_DEFINITION = RecordCodecBuilder.create(builder -> builder.group( | |
Codec.FLOAT.fieldOf("length_in_seconds").forGetter(AnimationDefinition::lengthInSeconds), | |
Codec.BOOL.optionalFieldOf("looping", false).forGetter(AnimationDefinition::looping), | |
Codec.unboundedMap(Codec.STRING, ANIMATION_CHANNEL.listOf()).fieldOf("bone_animations").forGetter(AnimationDefinition::boneAnimations) | |
).apply(builder, AnimationDefinition::new)); | |
public static enum TargetType implements StringRepresentable | |
{ | |
POSITION("position", Targets.POSITION), | |
ROTATION("rotation", Targets.ROTATION), | |
SCALE("scale", Targets.SCALE); | |
public static final Map<Target, TargetType> BY_TARGET = Map.of( | |
Targets.POSITION, POSITION, | |
Targets.ROTATION, ROTATION, | |
Targets.SCALE, SCALE); | |
public static final Codec<TargetType> CODEC = StringRepresentable.fromEnum(() -> TargetType.values()); | |
private final String name; | |
private final Target target; | |
TargetType(String name, Target target) | |
{ | |
this.name = name; | |
this.target = target; | |
} | |
@Override | |
public String getSerializedName() | |
{ | |
return this.name; | |
} | |
public Target target() | |
{ | |
return this.target; | |
} | |
} | |
public static enum InterpolationType implements StringRepresentable | |
{ | |
LINEAR("linear", Interpolations.LINEAR), | |
CATMULLROM("catmullrom", Interpolations.CATMULLROM); | |
public static final Codec<InterpolationType> CODEC = StringRepresentable.fromEnum(() -> InterpolationType.values()); | |
public static final Map<Interpolation, InterpolationType> BY_INTERPOLATION = Map.of( | |
Interpolations.LINEAR, LINEAR, | |
Interpolations.CATMULLROM, CATMULLROM); | |
private final String name; | |
private final Interpolation interpolation; | |
InterpolationType(String name, Interpolation interpolation) | |
{ | |
this.name = name; | |
this.interpolation = interpolation; | |
} | |
@Override | |
public String getSerializedName() | |
{ | |
return this.name; | |
} | |
public Interpolation interpolation() | |
{ | |
return this.interpolation; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment