KeyframeTrackSampler.java

net.minecraft.util.KeyframeTrackSampler

信息

  • 全限定名:net.minecraft.util.KeyframeTrackSampler
  • 类型:public class
  • 包:net.minecraft.util
  • 源码路径:src/main/java/net/minecraft/util/KeyframeTrackSampler.java
  • 起始行号:L8
  • 职责:

    TODO

字段/常量

  • periodTicks

    • 类型: Optional<Integer>
    • 修饰符: private final
    • 源码定位: L9
    • 说明:

      TODO

  • lerp

    • 类型: LerpFunction<T>
    • 修饰符: private final
    • 源码定位: L10
    • 说明:

      TODO

  • segments

    • 类型: List<KeyframeTrackSampler.Segment<T>>
    • 修饰符: private final
    • 源码定位: L11
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.util.KeyframeTrackSampler.Segment
    • 类型: record
    • 修饰符: private
    • 源码定位: L80
    • 说明:

      TODO

构造器

KeyframeTrackSampler(KeyframeTrack<T> track, Optional<Integer> periodTicks, LerpFunction<T> lerp) @ L13

  • 构造器名:KeyframeTrackSampler
  • 源码定位:L13
  • 修饰符:package-private

参数:

  • track: KeyframeTrack
  • periodTicks: Optional
  • lerp: LerpFunction

说明:

TODO

方法

下面的方法块按源码顺序生成。

private static <T> List<KeyframeTrackSampler.Segment<T>> bakeSegments(KeyframeTrack<T> track, Optional<Integer> periodTicks) @ L19

  • 方法名:bakeSegments
  • 源码定位:L19
  • 返回类型: List<KeyframeTrackSampler.Segment>
  • 修饰符:private static

参数:

  • track: KeyframeTrack
  • periodTicks: Optional

说明:

TODO

private static <T> void addSegmentsFromKeyframes(KeyframeTrack<T> track, List<Keyframe<T>> keyframes, List<KeyframeTrackSampler.Segment<T>> output) @ L44

  • 方法名:addSegmentsFromKeyframes
  • 源码定位:L44
  • 返回类型: void
  • 修饰符:private static

参数:

  • track: KeyframeTrack
  • keyframes: List<Keyframe>
  • output: List<KeyframeTrackSampler.Segment>

说明:

TODO

public T sample(long ticks) @ L52

  • 方法名:sample
  • 源码定位:L52
  • 返回类型:T
  • 修饰符:public

参数:

  • ticks: long

说明:

TODO

private KeyframeTrackSampler.Segment<T> getSegmentAt(long currentTicks) @ L66

  • 方法名:getSegmentAt
  • 源码定位:L66
  • 返回类型:KeyframeTrackSampler.Segment
  • 修饰符:private

参数:

  • currentTicks: long

说明:

TODO

private long loopTicks(long ticks) @ L76

  • 方法名:loopTicks
  • 源码定位:L76
  • 返回类型:long
  • 修饰符:private

参数:

  • ticks: long

说明:

TODO

代码

public class KeyframeTrackSampler<T> {
    private final Optional<Integer> periodTicks;
    private final LerpFunction<T> lerp;
    private final List<KeyframeTrackSampler.Segment<T>> segments;
 
    KeyframeTrackSampler(KeyframeTrack<T> track, Optional<Integer> periodTicks, LerpFunction<T> lerp) {
        this.periodTicks = periodTicks;
        this.lerp = lerp;
        this.segments = bakeSegments(track, periodTicks);
    }
 
    private static <T> List<KeyframeTrackSampler.Segment<T>> bakeSegments(KeyframeTrack<T> track, Optional<Integer> periodTicks) {
        List<Keyframe<T>> keyframes = track.keyframes();
        if (keyframes.size() == 1) {
            T value = keyframes.getFirst().value();
            return List.of(new KeyframeTrackSampler.Segment<>(EasingType.CONSTANT, value, 0, value, 0));
        } else {
            List<KeyframeTrackSampler.Segment<T>> segments = new ArrayList<>();
            if (periodTicks.isPresent()) {
                Keyframe<T> firstKeyframe = keyframes.getFirst();
                Keyframe<T> lastKeyframe = keyframes.getLast();
                segments.add(
                    new KeyframeTrackSampler.Segment<>(track, lastKeyframe, lastKeyframe.ticks() - periodTicks.get(), firstKeyframe, firstKeyframe.ticks())
                );
                addSegmentsFromKeyframes(track, keyframes, segments);
                segments.add(
                    new KeyframeTrackSampler.Segment<>(track, lastKeyframe, lastKeyframe.ticks(), firstKeyframe, firstKeyframe.ticks() + periodTicks.get())
                );
            } else {
                addSegmentsFromKeyframes(track, keyframes, segments);
            }
 
            return List.copyOf(segments);
        }
    }
 
    private static <T> void addSegmentsFromKeyframes(KeyframeTrack<T> track, List<Keyframe<T>> keyframes, List<KeyframeTrackSampler.Segment<T>> output) {
        for (int i = 0; i < keyframes.size() - 1; i++) {
            Keyframe<T> keyframe = keyframes.get(i);
            Keyframe<T> nextKeyframe = keyframes.get(i + 1);
            output.add(new KeyframeTrackSampler.Segment<>(track, keyframe, keyframe.ticks(), nextKeyframe, nextKeyframe.ticks()));
        }
    }
 
    public T sample(long ticks) {
        long sampleTicks = this.loopTicks(ticks);
        KeyframeTrackSampler.Segment<T> segment = this.getSegmentAt(sampleTicks);
        if (sampleTicks <= segment.fromTicks) {
            return segment.fromValue;
        } else if (sampleTicks >= segment.toTicks) {
            return segment.toValue;
        } else {
            float alpha = (float)(sampleTicks - segment.fromTicks) / (segment.toTicks - segment.fromTicks);
            float easedAlpha = segment.easing.apply(alpha);
            return this.lerp.apply(easedAlpha, segment.fromValue, segment.toValue);
        }
    }
 
    private KeyframeTrackSampler.Segment<T> getSegmentAt(long currentTicks) {
        for (KeyframeTrackSampler.Segment<T> segment : this.segments) {
            if (currentTicks < segment.toTicks) {
                return segment;
            }
        }
 
        return this.segments.getLast();
    }
 
    private long loopTicks(long ticks) {
        return this.periodTicks.isPresent() ? Math.floorMod(ticks, this.periodTicks.get()) : ticks;
    }
 
    private record Segment<T>(EasingType easing, T fromValue, int fromTicks, T toValue, int toTicks) {
        public Segment(KeyframeTrack<T> track, Keyframe<T> from, int fromTicks, Keyframe<T> to, int toTicks) {
            this(track.easingType(), from.value(), fromTicks, to.value(), toTicks);
        }
    }
}

引用的其他类