From d057553223da1a7c951c648f532f4530e31b82f9 Mon Sep 17 00:00:00 2001 From: CrushedPixel Date: Tue, 14 Jul 2015 13:48:48 +0200 Subject: [PATCH] Added "inclusive" parameter to getPreviousKeyframe() and getNextKeyframe() in KeyframeList to define whether the next/previous keyframe may have the same timestamp as the realTime parameter Fixed a bug in KeyframeList#getPositionOnPath where a non-inclusive getPreviousKeyframe call resulted in an incorrect position value --- .../replaymod/gui/GuiEditKeyframe.java | 12 ++++++------ .../replaymod/interpolation/KeyframeList.java | 16 +++++++++------- .../replaymod/renderer/PathPreviewRenderer.java | 2 +- .../replaymod/replay/ReplayHandler.java | 2 +- .../replaymod/replay/ReplayProcess.java | 8 ++++---- .../replaymod/video/VideoRenderer.java | 10 +++++----- 6 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiEditKeyframe.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiEditKeyframe.java index 9a071214..bc43e8b0 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiEditKeyframe.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiEditKeyframe.java @@ -83,18 +83,18 @@ public class GuiEditKeyframe extends GuiScreen { KeyframeList markerKeyframes = ReplayHandler.getMarkerKeyframes(); if(keyframeType == KeyframeType.POSITION) { - previous = positionKeyframes.getPreviousKeyframe(keyframe.getRealTimestamp() - 1); - next = positionKeyframes.getNextKeyframe(keyframe.getRealTimestamp() + 1); + previous = positionKeyframes.getPreviousKeyframe(keyframe.getRealTimestamp(), false); + next = positionKeyframes.getNextKeyframe(keyframe.getRealTimestamp(), false); screenTitle = I18n.format("replaymod.gui.editkeyframe.title.pos"); } else if(keyframeType == KeyframeType.TIME) { - previous = timeKeyframes.getPreviousKeyframe(keyframe.getRealTimestamp() - 1); - next = timeKeyframes.getNextKeyframe(keyframe.getRealTimestamp() + 1); + previous = timeKeyframes.getPreviousKeyframe(keyframe.getRealTimestamp(), false); + next = timeKeyframes.getNextKeyframe(keyframe.getRealTimestamp(), false); screenTitle = I18n.format("replaymod.gui.editkeyframe.title.time"); } else if(keyframeType == KeyframeType.MARKER) { - previous = markerKeyframes.getPreviousKeyframe(keyframe.getRealTimestamp() - 1); - next = markerKeyframes.getNextKeyframe(keyframe.getRealTimestamp() + 1); + previous = markerKeyframes.getPreviousKeyframe(keyframe.getRealTimestamp(), false); + next = markerKeyframes.getNextKeyframe(keyframe.getRealTimestamp(), false); } ReplayMod.replaySender.setReplaySpeed(0); diff --git a/src/main/java/eu/crushedpixel/replaymod/interpolation/KeyframeList.java b/src/main/java/eu/crushedpixel/replaymod/interpolation/KeyframeList.java index d9ca259b..2c2d5743 100644 --- a/src/main/java/eu/crushedpixel/replaymod/interpolation/KeyframeList.java +++ b/src/main/java/eu/crushedpixel/replaymod/interpolation/KeyframeList.java @@ -65,9 +65,10 @@ public class KeyframeList extends ArrayList /** * Returns the first Keyframe that comes before a given value. * @param realTime The value to use + * @param inclusive Whether the previous Keyframe might have the same timestamp as realTime * @return The first Keyframe prior to the given value */ - public Keyframe getPreviousKeyframe(int realTime) { + public Keyframe getPreviousKeyframe(int realTime, boolean inclusive) { if(this.isEmpty()) return null; Keyframe backup = null; @@ -76,7 +77,7 @@ public class KeyframeList extends ArrayList for(Keyframe kf : this) { - if(kf.getRealTimestamp() < realTime) { + if((inclusive && kf.getRealTimestamp() <= realTime) || (!inclusive && kf.getRealTimestamp() < realTime)) { found.add(kf); } else if(kf.getRealTimestamp() == realTime) { backup = kf; @@ -93,16 +94,17 @@ public class KeyframeList extends ArrayList /** * Returns the first Keyframe that comes after a given value. * @param realTime The value to use + * @param inclusive Whether the next Keyframe might have the same timestamp as realTime * @return The first Keyframe after the given value */ - public Keyframe getNextKeyframe(int realTime) { + public Keyframe getNextKeyframe(int realTime, boolean inclusive) { if(this.isEmpty()) return null; Keyframe backup = null; for(Keyframe kf : this) { - if(kf.getRealTimestamp() > realTime) { + if((inclusive && kf.getRealTimestamp() >= realTime) || (!inclusive && kf.getRealTimestamp() > realTime)) { return kf; //first found element is next } else if(kf.getRealTimestamp() == realTime) { backup = kf; @@ -179,8 +181,8 @@ public class KeyframeList extends ArrayList * @return A value between 0 and 1 */ private float getPositionOnPath(int timestamp) { - Keyframe previousKeyframe = getPreviousKeyframe(timestamp); - Keyframe nextKeyframe = getNextKeyframe(timestamp); + Keyframe previousKeyframe = getPreviousKeyframe(timestamp, true); + Keyframe nextKeyframe = getNextKeyframe(timestamp, true); int previousTimestamp = 0; int nextTimestamp = 0; @@ -203,7 +205,7 @@ public class KeyframeList extends ArrayList int currentPos = timestamp - previousTimestamp; float currentStepPercentage = (float) currentPos / (float) currentPosDiff; - if(Float.isInfinite(currentStepPercentage)) currentStepPercentage = 0; + if(Float.isInfinite(currentStepPercentage) || Float.isNaN(currentStepPercentage)) currentStepPercentage = 0; float value = (indexOf(previousKeyframe) + currentStepPercentage) / (float)(size() - 1); diff --git a/src/main/java/eu/crushedpixel/replaymod/renderer/PathPreviewRenderer.java b/src/main/java/eu/crushedpixel/replaymod/renderer/PathPreviewRenderer.java index f116c7bc..e1eefd3e 100644 --- a/src/main/java/eu/crushedpixel/replaymod/renderer/PathPreviewRenderer.java +++ b/src/main/java/eu/crushedpixel/replaymod/renderer/PathPreviewRenderer.java @@ -36,7 +36,7 @@ public class PathPreviewRenderer { @SubscribeEvent public void renderCameraPath(RenderWorldLastEvent event) { if(!ReplayHandler.isInReplay() || ReplayHandler.isInPath() || !ReplayMod.replaySettings.showPathPreview() || mc.gameSettings.hideGUI) return; - + Entity entity = ReplayHandler.getCameraEntity(); if(entity == null) return; diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java index bb3126d0..8ee230a8 100755 --- a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java @@ -539,7 +539,7 @@ public class ReplayHandler { //if shift is down, it will refer to the previous Time Keyframe instead of the last one if(shiftMode) { int realTime = getRealTimelineCursor(); - keyframe = timeKeyframes.getPreviousKeyframe(realTime); + keyframe = timeKeyframes.getPreviousKeyframe(realTime, false); } else { keyframe = timeKeyframes.last(); } diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayProcess.java b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayProcess.java index 4ab18c57..f9a91c2d 100755 --- a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayProcess.java +++ b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayProcess.java @@ -206,8 +206,8 @@ public class ReplayProcess { int curRealReplayTime = (int) (lastRealReplayTime + timeStep); - Keyframe lastPos = ReplayHandler.getPositionKeyframes().getPreviousKeyframe(curRealReplayTime); - Keyframe nextPos = ReplayHandler.getPositionKeyframes().getNextKeyframe(curRealReplayTime); + Keyframe lastPos = ReplayHandler.getPositionKeyframes().getPreviousKeyframe(curRealReplayTime, true); + Keyframe nextPos = ReplayHandler.getPositionKeyframes().getNextKeyframe(curRealReplayTime, true); boolean spectating = false; @@ -239,8 +239,8 @@ public class ReplayProcess { } } - Keyframe lastTime = ReplayHandler.getTimeKeyframes().getPreviousKeyframe(curRealReplayTime); - Keyframe nextTime = ReplayHandler.getTimeKeyframes().getNextKeyframe(curRealReplayTime); + Keyframe lastTime = ReplayHandler.getTimeKeyframes().getPreviousKeyframe(curRealReplayTime, true); + Keyframe nextTime = ReplayHandler.getTimeKeyframes().getNextKeyframe(curRealReplayTime, true); int lastTimeStamp = 0; int nextTimeStamp = 0; diff --git a/src/main/java/eu/crushedpixel/replaymod/video/VideoRenderer.java b/src/main/java/eu/crushedpixel/replaymod/video/VideoRenderer.java index f23c400e..79d5d5ca 100644 --- a/src/main/java/eu/crushedpixel/replaymod/video/VideoRenderer.java +++ b/src/main/java/eu/crushedpixel/replaymod/video/VideoRenderer.java @@ -217,16 +217,16 @@ public class VideoRenderer { int posCount = ReplayHandler.getPositionKeyframes().size(); AdvancedPosition pos = new AdvancedPosition(); - Keyframe lastPos = positionKeyframes.getPreviousKeyframe(videoTime); + Keyframe lastPos = positionKeyframes.getPreviousKeyframe(videoTime, true); Keyframe nextPos = null; if (movement == null || lastPos == null) { // Stay at one position, no movement - Keyframe keyframe = positionKeyframes.getNextKeyframe(-1); + Keyframe keyframe = positionKeyframes.getNextKeyframe(-1, true); assert keyframe != null; pos = keyframe.getValue(); } else { // Position interpolation - nextPos = positionKeyframes.getNextKeyframe(videoTime); + nextPos = positionKeyframes.getNextKeyframe(videoTime, true); int lastPosStamp = lastPos.getRealTimestamp(); int nextPosStamp = (nextPos == null ? lastPos : nextPos).getRealTimestamp(); @@ -275,8 +275,8 @@ public class VideoRenderer { // WARNING: The rest of this method contains some magic for which Marius is responsible // Time interpolation - Keyframe lastTime = timeKeyframes.getPreviousKeyframe(videoTime); - Keyframe nextTime = timeKeyframes.getNextKeyframe(videoTime); + Keyframe lastTime = timeKeyframes.getPreviousKeyframe(videoTime, false); + Keyframe nextTime = timeKeyframes.getNextKeyframe(videoTime, false); int lastTimeStamp = 0; int nextTimeStamp = 0;