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
This commit is contained in:
CrushedPixel
2015-07-14 13:48:48 +02:00
parent 3e77e72f5a
commit d057553223
6 changed files with 26 additions and 24 deletions

View File

@@ -83,18 +83,18 @@ public class GuiEditKeyframe extends GuiScreen {
KeyframeList<Marker> 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);

View File

@@ -65,9 +65,10 @@ public class KeyframeList<K extends KeyframeValue> extends ArrayList<Keyframe<K>
/**
* 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 <b>realTime</b>
* @return The first Keyframe prior to the given value
*/
public Keyframe<K> getPreviousKeyframe(int realTime) {
public Keyframe<K> getPreviousKeyframe(int realTime, boolean inclusive) {
if(this.isEmpty()) return null;
Keyframe<K> backup = null;
@@ -76,7 +77,7 @@ public class KeyframeList<K extends KeyframeValue> extends ArrayList<Keyframe<K>
for(Keyframe<K> 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<K extends KeyframeValue> extends ArrayList<Keyframe<K>
/**
* 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 <b>realTime</b>
* @return The first Keyframe after the given value
*/
public Keyframe<K> getNextKeyframe(int realTime) {
public Keyframe<K> getNextKeyframe(int realTime, boolean inclusive) {
if(this.isEmpty()) return null;
Keyframe<K> backup = null;
for(Keyframe<K> 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<K extends KeyframeValue> extends ArrayList<Keyframe<K>
* @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<K extends KeyframeValue> extends ArrayList<Keyframe<K>
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);

View File

@@ -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;

View File

@@ -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();
}

View File

@@ -206,8 +206,8 @@ public class ReplayProcess {
int curRealReplayTime = (int) (lastRealReplayTime + timeStep);
Keyframe<AdvancedPosition> lastPos = ReplayHandler.getPositionKeyframes().getPreviousKeyframe(curRealReplayTime);
Keyframe<AdvancedPosition> nextPos = ReplayHandler.getPositionKeyframes().getNextKeyframe(curRealReplayTime);
Keyframe<AdvancedPosition> lastPos = ReplayHandler.getPositionKeyframes().getPreviousKeyframe(curRealReplayTime, true);
Keyframe<AdvancedPosition> nextPos = ReplayHandler.getPositionKeyframes().getNextKeyframe(curRealReplayTime, true);
boolean spectating = false;
@@ -239,8 +239,8 @@ public class ReplayProcess {
}
}
Keyframe<TimestampValue> lastTime = ReplayHandler.getTimeKeyframes().getPreviousKeyframe(curRealReplayTime);
Keyframe<TimestampValue> nextTime = ReplayHandler.getTimeKeyframes().getNextKeyframe(curRealReplayTime);
Keyframe<TimestampValue> lastTime = ReplayHandler.getTimeKeyframes().getPreviousKeyframe(curRealReplayTime, true);
Keyframe<TimestampValue> nextTime = ReplayHandler.getTimeKeyframes().getNextKeyframe(curRealReplayTime, true);
int lastTimeStamp = 0;
int nextTimeStamp = 0;

View File

@@ -217,16 +217,16 @@ public class VideoRenderer {
int posCount = ReplayHandler.getPositionKeyframes().size();
AdvancedPosition pos = new AdvancedPosition();
Keyframe<AdvancedPosition> lastPos = positionKeyframes.getPreviousKeyframe(videoTime);
Keyframe<AdvancedPosition> lastPos = positionKeyframes.getPreviousKeyframe(videoTime, true);
Keyframe<AdvancedPosition> nextPos = null;
if (movement == null || lastPos == null) {
// Stay at one position, no movement
Keyframe<AdvancedPosition> keyframe = positionKeyframes.getNextKeyframe(-1);
Keyframe<AdvancedPosition> 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<TimestampValue> lastTime = timeKeyframes.getPreviousKeyframe(videoTime);
Keyframe<TimestampValue> nextTime = timeKeyframes.getNextKeyframe(videoTime);
Keyframe<TimestampValue> lastTime = timeKeyframes.getPreviousKeyframe(videoTime, false);
Keyframe<TimestampValue> nextTime = timeKeyframes.getNextKeyframe(videoTime, false);
int lastTimeStamp = 0;
int nextTimeStamp = 0;