11package doggytalents .client .entity .model .animation ;
22
33import java .util .ArrayList ;
4- import java .util .Arrays ;
54import java .util .HashMap ;
65import java .util .List ;
76import java .util .Map ;
8- import java .util .stream .Collectors ;
97
108import org .joml .Vector3f ;
119
1210import com .google .common .collect .ImmutableBiMap ;
11+ import com .google .common .collect .ImmutableMap ;
1312import com .mojang .serialization .Codec ;
1413import com .mojang .serialization .codecs .RecordCodecBuilder ;
1514
1615import net .minecraft .client .animation .AnimationChannel ;
1716import net .minecraft .client .animation .AnimationDefinition ;
1817import net .minecraft .client .animation .Keyframe ;
18+ import net .minecraft .client .animation .KeyframeAnimations ;
1919import net .minecraft .util .ExtraCodecs ;
20+ import net .minecraft .util .Mth ;
2021
2122public class DTNAnimationCodec {
2223
@@ -51,7 +52,7 @@ public class DTNAnimationCodec {
5152 builder -> builder .group (
5253 Codec .FLOAT .fieldOf ("length" )
5354 .forGetter (AnimationDefinition ::lengthInSeconds ),
54- Codec .BOOL .fieldOf ("loop" )
55+ Codec .BOOL .optionalFieldOf ("loop" , false )
5556 .forGetter (AnimationDefinition ::looping ),
5657 channelWithPartCodec ().listOf ().xmap (
5758 DTNAnimationCodec ::channelWithPartListToMap ,
@@ -89,7 +90,8 @@ private static List<ChannelWithPart> channelWithPartListFromMap(
8990 private static final ImmutableBiMap <String , AnimationChannel .Target >
9091 CHANNEL_TYPE_BY_ID = ImmutableBiMap .of (
9192 "position" , AnimationChannel .Targets .POSITION ,
92- "rotation" , AnimationChannel .Targets .ROTATION
93+ "rotation" , AnimationChannel .Targets .ROTATION ,
94+ "scale" , AnimationChannel .Targets .SCALE
9395 );
9496 private static final AnimationChannel .Target getChannelTypeFromId (String id ) {
9597 return CHANNEL_TYPE_BY_ID .get (id );
@@ -100,41 +102,80 @@ private static final String getIdFromChannelType(AnimationChannel.Target interp)
100102 private record ChannelWithPart (String part , AnimationChannel channel ) {
101103 public AnimationChannel .Target type () { return channel .target (); }
102104 public List <Keyframe > keyframesForEncode () {
103- return fixChannelWhenEncode (channel );
105+ return processChannelWhenEncode (channel );
104106 }
105107 public static ChannelWithPart of (String part , AnimationChannel .Target type ,
106108 List <Keyframe > keyframes ) {
107109 return new ChannelWithPart (part ,
108- fixChannelWhenDecode (type , keyframes ));
110+ processChannelWhenDecode (type , keyframes ));
109111 }
110112 }
111- private static AnimationChannel fixChannelWhenDecode (
112- AnimationChannel .Target type , List <Keyframe > keyframes ) {
113+ private static record KeyframeProcessor (
114+ KeyframeValueFunction whenDecode , KeyframeValueFunction whenEncode
115+ ) {
116+ public static KeyframeProcessor of (KeyframeValueFunction whenDecode ,
117+ KeyframeValueFunction whenEncode ) {
118+ return new KeyframeProcessor (whenDecode , whenEncode );
119+ }
120+ }
121+ private static final ImmutableMap <AnimationChannel .Target , KeyframeProcessor >
122+ KEYFRAME_PROCESSORS = ImmutableMap .of (
123+
124+ AnimationChannel .Targets .POSITION ,
125+ KeyframeProcessor .of (KeyframeAnimations ::posVec , KeyframeAnimations ::posVec ),
126+
127+ AnimationChannel .Targets .ROTATION ,
128+ KeyframeProcessor .of (KeyframeAnimations ::degreeVec , DTNAnimationCodec ::invertedRotationVec ),
129+
130+ AnimationChannel .Targets .SCALE ,
131+ KeyframeProcessor .of (KeyframeAnimations ::scaleVec , DTNAnimationCodec ::invertedScaleVec )
113132
114- if (type != AnimationChannel .Targets .ROTATION )
115- return new AnimationChannel (type , keyframes .toArray (Keyframe []::new ));
116-
117- var new_keyframes = keyframes .stream ()
118- .map (kf -> {
119- var old_value = kf .target ();
120- var new_value = new Vector3f (-old_value .x (), -old_value .y (), old_value .z ());
121- return new Keyframe (kf .timestamp (), new_value , kf .interpolation ());
122- })
123- .toArray (Keyframe []::new );
124- return new AnimationChannel (type , new_keyframes );
125- }
126- private static List <Keyframe > fixChannelWhenEncode (AnimationChannel channel ) {
133+ );
134+ private static AnimationChannel processChannelWhenDecode (
135+ AnimationChannel .Target type , List <Keyframe > rawKeyframes ) {
136+
137+ final var keyframe_processor = KEYFRAME_PROCESSORS .get (type );
138+ final boolean fix_rotation = type == AnimationChannel .Targets .ROTATION ;
139+
140+ var keyframes = new ArrayList <Keyframe >(rawKeyframes .size ());
141+ for (var raw_keyframe : rawKeyframes ) {
142+ var value = raw_keyframe .target ();
143+
144+ value = keyframe_processor .whenDecode ()
145+ .apply (value .x , value .y , value .z );
146+
147+ if (fix_rotation )
148+ value = new Vector3f (-value .x , -value .y , value .z );
149+
150+ var keyframe =
151+ new Keyframe (raw_keyframe .timestamp (), value , raw_keyframe .interpolation ());
152+ keyframes .add (keyframe );
153+ }
154+ return new AnimationChannel (type , keyframes .toArray (Keyframe []::new ));
155+ }
156+ private static List <Keyframe > processChannelWhenEncode (AnimationChannel channel ) {
127157 var type = channel .target ();
128- if (type != AnimationChannel .Targets .ROTATION )
129- return Arrays .asList (channel .keyframes ());
130-
131- return Arrays .stream (channel .keyframes ())
132- .map (kf -> {
133- var old_value = kf .target ();
134- var new_value = new Vector3f (-old_value .x (), -old_value .y (), old_value .z ());
135- return new Keyframe (kf .timestamp (), new_value , kf .interpolation ());
136- })
137- .collect (Collectors .toList ());
158+ final var keyframe_processor = KEYFRAME_PROCESSORS .get (type );
159+ final boolean fix_rotation = type == AnimationChannel .Targets .ROTATION ;
160+
161+ var keyframes = channel .keyframes ();
162+ var raw_keyframes = new ArrayList <Keyframe >(keyframes .length );
163+ for (var keyframe : keyframes ) {
164+ var value = keyframe .target ();
165+
166+ if (fix_rotation )
167+ value = new Vector3f (-value .x , -value .y , value .z );
168+
169+ value = keyframe_processor .whenEncode ()
170+ .apply (value .x , value .y , value .z );
171+
172+ value = sanitizeWhenEncode (value );
173+
174+ var raw_keyframe =
175+ new Keyframe (keyframe .timestamp (), value , keyframe .interpolation ());
176+ raw_keyframes .add (raw_keyframe );
177+ }
178+ return raw_keyframes ;
138179 }
139180 private static Codec <ChannelWithPart > channelWithPartCodec () {
140181 return RecordCodecBuilder .create (
@@ -148,7 +189,7 @@ private static Codec<ChannelWithPart> channelWithPartCodec() {
148189 )
149190 .fieldOf ("type" )
150191 .forGetter (ChannelWithPart ::type ),
151- keyframeCodec ().listOf ()
192+ rawKeyframeCodec ().listOf ()
152193 .fieldOf ("keyframes" )
153194 .forGetter (ChannelWithPart ::keyframesForEncode )
154195 )
@@ -167,7 +208,8 @@ private static final AnimationChannel.Interpolation getInterpFromId(String id) {
167208 private static final String getIdFromInterp (AnimationChannel .Interpolation interp ) {
168209 return INTERP_BY_ID .inverse ().get (interp );
169210 }
170- private static Codec <Keyframe > keyframeCodec () {
211+
212+ private static Codec <Keyframe > rawKeyframeCodec () {
171213 return RecordCodecBuilder .create (
172214 builder -> builder .group (
173215 Codec .FLOAT .fieldOf ("at" )
@@ -182,4 +224,36 @@ private static Codec<Keyframe> keyframeCodec() {
182224 .apply (builder , Keyframe ::new )
183225 );
184226 }
227+
228+ public static Vector3f invertedRotationVec (float x , float y , float z ) {
229+ return new Vector3f (x , y , z ).mul (Mth .RAD_TO_DEG );
230+ }
231+ public static Vector3f invertedScaleVec (float x , float y , float z ) {
232+ return new Vector3f (x , y , z ).add (1 , 1 , 1 );
233+ }
234+ private static Vector3f sanitizeWhenEncode (Vector3f vec ) {
235+ vec = zeroSanitize (vec );
236+ vec = round (vec );
237+ return vec ;
238+ }
239+ private static Vector3f zeroSanitize (Vector3f vec ) {
240+ return new Vector3f (
241+ Mth .equal (vec .x (), 0 ) ? 0 : vec .x (),
242+ Mth .equal (vec .y (), 0 ) ? 0 : vec .y (),
243+ Mth .equal (vec .z (), 0 ) ? 0 : vec .z ()
244+ );
245+ }
246+ private static Vector3f round (Vector3f vec ) {
247+ final float rounding_mul = 100f ;
248+ return new Vector3f (
249+ Math .round (vec .x * rounding_mul )/rounding_mul ,
250+ Math .round (vec .y * rounding_mul )/rounding_mul ,
251+ Math .round (vec .z * rounding_mul )/rounding_mul
252+ );
253+ }
254+
255+ @ FunctionalInterface
256+ private static interface KeyframeValueFunction {
257+ public Vector3f apply (float x , float y , float z );
258+ }
185259}
0 commit comments