Reworked ReplayProcess to get rid of own Interpolation instances (as these can be handled by the KeyframeLists)
Camera Paths are now started from the current cursor position, using Ctrl-click the path always starts from the beginning
This commit is contained in:
@@ -350,7 +350,7 @@ public class ReplayMod {
|
|||||||
|
|
||||||
System.out.println("Rendering started...");
|
System.out.println("Rendering started...");
|
||||||
try {
|
try {
|
||||||
ReplayProcess.startReplayProcess(options);
|
ReplayProcess.startReplayProcess(options, true);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
t.printStackTrace();
|
t.printStackTrace();
|
||||||
FMLCommonHandler.instance().exitJava(1, false);
|
FMLCommonHandler.instance().exitJava(1, false);
|
||||||
|
|||||||
@@ -457,7 +457,7 @@ public class GuiRenderSettings extends GuiScreen implements GuiReplayOverlay.NoO
|
|||||||
if(FMLClientHandler.instance().hasOptifine()) {
|
if(FMLClientHandler.instance().hasOptifine()) {
|
||||||
mc.displayGuiScreen(new GuiErrorScreen(I18n.format("replaymod.gui.rendering.error.title"), I18n.format("replaymod.gui.rendering.error.optifine")));
|
mc.displayGuiScreen(new GuiErrorScreen(I18n.format("replaymod.gui.rendering.error.title"), I18n.format("replaymod.gui.rendering.error.optifine")));
|
||||||
} else {
|
} else {
|
||||||
ReplayHandler.startPath(options);
|
ReplayHandler.startPath(options, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ public class GuiReplayOverlay extends Gui {
|
|||||||
private final GuiElement buttonPlay = texturedButton(BUTTON_PLAY_PATH_X, BOTTOM_ROW, 0, 0, 20, new Runnable() {
|
private final GuiElement buttonPlay = texturedButton(BUTTON_PLAY_PATH_X, BOTTOM_ROW, 0, 0, 20, new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
ReplayHandler.startPath(null);
|
ReplayHandler.startPath(null, GuiScreen.isCtrlKeyDown());
|
||||||
|
|
||||||
}
|
}
|
||||||
}, "replaymod.gui.ingame.menu.playpath");
|
}, "replaymod.gui.ingame.menu.playpath");
|
||||||
|
|||||||
@@ -165,10 +165,10 @@ public class ReplayHandler {
|
|||||||
return currentEntity;
|
return currentEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void startPath(RenderOptions renderOptions) {
|
public static void startPath(RenderOptions renderOptions, boolean fromStart) {
|
||||||
if(!ReplayHandler.isInPath()) {
|
if(!ReplayHandler.isInPath()) {
|
||||||
try {
|
try {
|
||||||
ReplayProcess.startReplayProcess(renderOptions);
|
ReplayProcess.startReplayProcess(renderOptions, fromStart);
|
||||||
} catch (ReportedException e) {
|
} catch (ReportedException e) {
|
||||||
// We have to manually unwrap OOM errors as Minecraft doesn't handle them when they're wrapped
|
// We have to manually unwrap OOM errors as Minecraft doesn't handle them when they're wrapped
|
||||||
Throwable prevCause = null;
|
Throwable prevCause = null;
|
||||||
|
|||||||
@@ -5,9 +5,7 @@ import eu.crushedpixel.replaymod.chat.ChatMessageHandler.ChatMessageType;
|
|||||||
import eu.crushedpixel.replaymod.holders.AdvancedPosition;
|
import eu.crushedpixel.replaymod.holders.AdvancedPosition;
|
||||||
import eu.crushedpixel.replaymod.holders.Keyframe;
|
import eu.crushedpixel.replaymod.holders.Keyframe;
|
||||||
import eu.crushedpixel.replaymod.holders.TimestampValue;
|
import eu.crushedpixel.replaymod.holders.TimestampValue;
|
||||||
import eu.crushedpixel.replaymod.interpolation.AdvancedPositionLinearInterpolation;
|
import eu.crushedpixel.replaymod.interpolation.KeyframeList;
|
||||||
import eu.crushedpixel.replaymod.interpolation.AdvancedPositionSplineInterpolation;
|
|
||||||
import eu.crushedpixel.replaymod.interpolation.GenericLinearInterpolation;
|
|
||||||
import eu.crushedpixel.replaymod.settings.RenderOptions;
|
import eu.crushedpixel.replaymod.settings.RenderOptions;
|
||||||
import eu.crushedpixel.replaymod.timer.EnchantmentTimer;
|
import eu.crushedpixel.replaymod.timer.EnchantmentTimer;
|
||||||
import eu.crushedpixel.replaymod.timer.ReplayTimer;
|
import eu.crushedpixel.replaymod.timer.ReplayTimer;
|
||||||
@@ -32,14 +30,10 @@ public class ReplayProcess {
|
|||||||
|
|
||||||
private static boolean linear = false;
|
private static boolean linear = false;
|
||||||
|
|
||||||
private static AdvancedPositionSplineInterpolation motionSpline = null;
|
private static int initialTimestamp = 0;
|
||||||
private static AdvancedPositionLinearInterpolation motionLinear = null;
|
|
||||||
private static GenericLinearInterpolation<TimestampValue> timeLinear = null;
|
|
||||||
|
|
||||||
private static double previousReplaySpeed = 0;
|
private static double previousReplaySpeed = 0;
|
||||||
|
|
||||||
private static boolean calculated = false;
|
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private static VideoRenderer videoRenderer = null;
|
private static VideoRenderer videoRenderer = null;
|
||||||
|
|
||||||
@@ -54,10 +48,6 @@ public class ReplayProcess {
|
|||||||
private static void resetProcess() {
|
private static void resetProcess() {
|
||||||
firstTime = true;
|
firstTime = true;
|
||||||
|
|
||||||
motionSpline = null;
|
|
||||||
motionLinear = null;
|
|
||||||
timeLinear = null;
|
|
||||||
calculated = false;
|
|
||||||
requestFinish = false;
|
requestFinish = false;
|
||||||
|
|
||||||
lastRealTime = System.currentTimeMillis();
|
lastRealTime = System.currentTimeMillis();
|
||||||
@@ -69,7 +59,7 @@ public class ReplayProcess {
|
|||||||
EnchantmentTimer.resetRecordingTime();
|
EnchantmentTimer.resetRecordingTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void startReplayProcess(RenderOptions renderOptions) {
|
public static void startReplayProcess(RenderOptions renderOptions, boolean fromStart) {
|
||||||
mc.displayGuiScreen(null);
|
mc.displayGuiScreen(null);
|
||||||
|
|
||||||
ReplayHandler.selectKeyframe(null);
|
ReplayHandler.selectKeyframe(null);
|
||||||
@@ -89,20 +79,21 @@ public class ReplayProcess {
|
|||||||
ReplayHandler.setInPath(true);
|
ReplayHandler.setInPath(true);
|
||||||
ReplayMod.replaySender.setAsyncMode(false);
|
ReplayMod.replaySender.setAsyncMode(false);
|
||||||
|
|
||||||
|
//default camera path, no rendering
|
||||||
if (renderOptions == null) {
|
if (renderOptions == null) {
|
||||||
//gets first Value and sets Replay Time to it
|
initialTimestamp = fromStart ? 0 : ReplayHandler.getRealTimelineCursor();
|
||||||
Keyframe<TimestampValue> tf = ReplayHandler.getTimeKeyframes().first();
|
lastRealReplayTime = initialTimestamp;
|
||||||
if (tf != null) {
|
|
||||||
int ts = (int)tf.getValue().value;
|
int ts = ReplayHandler.getTimeKeyframes().getInterpolatedValueForTimestamp(initialTimestamp, true).asInt();
|
||||||
if (ts < ReplayMod.replaySender.currentTimeStamp()) {
|
if (ts < ReplayMod.replaySender.currentTimeStamp()) {
|
||||||
mc.displayGuiScreen(null);
|
mc.displayGuiScreen(null);
|
||||||
}
|
|
||||||
ReplayMod.replaySender.sendPacketsTill(ts);
|
|
||||||
}
|
}
|
||||||
|
ReplayMod.replaySender.sendPacketsTill(ts);
|
||||||
|
|
||||||
ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.pathstarted", ChatMessageType.INFORMATION);
|
ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.pathstarted", ChatMessageType.INFORMATION);
|
||||||
mc.timer.timerSpeed = 1;
|
mc.timer.timerSpeed = 1;
|
||||||
} else {
|
} else {
|
||||||
|
initialTimestamp = 0;
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
try {
|
try {
|
||||||
isVideoRecording = true;
|
isVideoRecording = true;
|
||||||
@@ -148,11 +139,17 @@ public class ReplayProcess {
|
|||||||
//are called if the Timer speed is set to 0, leading to this method never being
|
//are called if the Timer speed is set to 0, leading to this method never being
|
||||||
//called from the RenderWorldLastEvent handlers.
|
//called from the RenderWorldLastEvent handlers.
|
||||||
public static void tickReplay(boolean justCheck) {
|
public static void tickReplay(boolean justCheck) {
|
||||||
|
final long curTime = System.currentTimeMillis();
|
||||||
|
KeyframeList<AdvancedPosition> positionKeyframes = ReplayHandler.getPositionKeyframes();
|
||||||
|
KeyframeList<TimestampValue> timeKeyframes = ReplayHandler.getTimeKeyframes();
|
||||||
|
|
||||||
|
int curRealReplayTime;
|
||||||
|
|
||||||
if (isVideoRecording) {
|
if (isVideoRecording) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(ReplayMod.replaySender.isHurrying()) {
|
if(ReplayMod.replaySender.isHurrying()) {
|
||||||
lastRealTime = System.currentTimeMillis();
|
lastRealTime = curTime;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,55 +158,23 @@ public class ReplayProcess {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastRealTime = System.currentTimeMillis();
|
lastRealTime = curTime;
|
||||||
lastRealReplayTime = 0;
|
|
||||||
|
|
||||||
firstTime = false;
|
firstTime = false;
|
||||||
mc.timer.renderPartialTicks = 100;
|
mc.timer.renderPartialTicks = 100;
|
||||||
mc.timer.elapsedPartialTicks = 100;
|
mc.timer.elapsedPartialTicks = 100;
|
||||||
mc.timer.elapsedTicks = 100;
|
mc.timer.elapsedTicks = 100;
|
||||||
|
|
||||||
|
curRealReplayTime = lastRealReplayTime = initialTimestamp;
|
||||||
|
} else {
|
||||||
|
long timeStep = curTime - lastRealTime;
|
||||||
|
curRealReplayTime = (int) (lastRealReplayTime + timeStep);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(justCheck) return;
|
if(justCheck) return;
|
||||||
|
|
||||||
int posCount = ReplayHandler.getPositionKeyframes().size();
|
Keyframe<AdvancedPosition> lastPos = positionKeyframes.getPreviousKeyframe(curRealReplayTime, true);
|
||||||
int timeCount = ReplayHandler.getTimeKeyframes().size();
|
Keyframe<AdvancedPosition> nextPos = positionKeyframes.getNextKeyframe(curRealReplayTime, true);
|
||||||
|
|
||||||
if(!linear && motionSpline == null) {
|
|
||||||
//set up spline path
|
|
||||||
motionSpline = new AdvancedPositionSplineInterpolation();
|
|
||||||
for(Keyframe<AdvancedPosition> kf : ReplayHandler.getPositionKeyframes()) {
|
|
||||||
motionSpline.addPoint(kf.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(linear && motionLinear == null) {
|
|
||||||
//set up linear path
|
|
||||||
motionLinear = new AdvancedPositionLinearInterpolation();
|
|
||||||
for(Keyframe<AdvancedPosition> kf : ReplayHandler.getPositionKeyframes()) {
|
|
||||||
motionLinear.addPoint(kf.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(timeLinear == null) {
|
|
||||||
timeLinear = new GenericLinearInterpolation<TimestampValue>();
|
|
||||||
for(Keyframe<TimestampValue> kf : ReplayHandler.getTimeKeyframes()) {
|
|
||||||
timeLinear.addPoint(kf.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!calculated) {
|
|
||||||
calculated = true;
|
|
||||||
if(posCount > 1 && motionSpline != null)
|
|
||||||
motionSpline.prepare();
|
|
||||||
}
|
|
||||||
|
|
||||||
long curTime = System.currentTimeMillis();
|
|
||||||
long timeStep = curTime - lastRealTime;
|
|
||||||
|
|
||||||
int curRealReplayTime = (int) (lastRealReplayTime + timeStep);
|
|
||||||
|
|
||||||
Keyframe<AdvancedPosition> lastPos = ReplayHandler.getPositionKeyframes().getPreviousKeyframe(curRealReplayTime, true);
|
|
||||||
Keyframe<AdvancedPosition> nextPos = ReplayHandler.getPositionKeyframes().getNextKeyframe(curRealReplayTime, true);
|
|
||||||
|
|
||||||
boolean spectating = false;
|
boolean spectating = false;
|
||||||
|
|
||||||
@@ -224,89 +189,41 @@ public class ReplayProcess {
|
|||||||
|
|
||||||
ReplayHandler.setRealTimelineCursor(curRealReplayTime);
|
ReplayHandler.setRealTimelineCursor(curRealReplayTime);
|
||||||
|
|
||||||
int lastPosStamp = 0;
|
Keyframe<TimestampValue> lastTime = timeKeyframes.getPreviousKeyframe(curRealReplayTime, true);
|
||||||
int nextPosStamp = 0;
|
Keyframe<TimestampValue> nextTime = timeKeyframes.getNextKeyframe(curRealReplayTime, true);
|
||||||
|
|
||||||
if(nextPos != null || lastPos != null) {
|
int lastTimeStamp;
|
||||||
if(nextPos != null) {
|
int nextTimeStamp;
|
||||||
nextPosStamp = nextPos.getRealTimestamp();
|
|
||||||
} else {
|
|
||||||
nextPosStamp = lastPos.getRealTimestamp();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(lastPos != null) {
|
|
||||||
lastPosStamp = lastPos.getRealTimestamp();
|
|
||||||
} else {
|
|
||||||
lastPosStamp = nextPos.getRealTimestamp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Keyframe<TimestampValue> lastTime = ReplayHandler.getTimeKeyframes().getPreviousKeyframe(curRealReplayTime, true);
|
|
||||||
Keyframe<TimestampValue> nextTime = ReplayHandler.getTimeKeyframes().getNextKeyframe(curRealReplayTime, true);
|
|
||||||
|
|
||||||
int lastTimeStamp = 0;
|
|
||||||
int nextTimeStamp = 0;
|
|
||||||
|
|
||||||
double curSpeed = 0;
|
double curSpeed = 0;
|
||||||
|
|
||||||
if(timeCount > 1 && (nextTime != null || lastTime != null)) {
|
if(nextTime != null && lastTime != null && nextTime.getRealTimestamp() == lastTime.getRealTimestamp()) {
|
||||||
|
curSpeed = 0;
|
||||||
if(nextTime != null && lastTime != null && nextTime.getRealTimestamp() == lastTime.getRealTimestamp()) {
|
} else {
|
||||||
curSpeed = 0;
|
if(nextTime != null) {
|
||||||
|
nextTimeStamp = nextTime.getRealTimestamp();
|
||||||
} else {
|
} else {
|
||||||
if(nextTime != null) {
|
nextTimeStamp = lastTime.getRealTimestamp();
|
||||||
nextTimeStamp = nextTime.getRealTimestamp();
|
}
|
||||||
} else {
|
|
||||||
nextTimeStamp = lastTime.getRealTimestamp();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(lastTime != null) {
|
if(lastTime != null) {
|
||||||
lastTimeStamp = lastTime.getRealTimestamp();
|
lastTimeStamp = lastTime.getRealTimestamp();
|
||||||
} else {
|
} else {
|
||||||
lastTimeStamp = nextTime.getRealTimestamp();
|
lastTimeStamp = nextTime.getRealTimestamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!(nextTime == null || lastTime == null)) {
|
if(!(nextTime == null || lastTime == null)) {
|
||||||
curSpeed = ((double) (((int)nextTime.getValue().value - (int)lastTime.getValue().value))) / ((double) ((nextTimeStamp - lastTimeStamp)));
|
curSpeed = ((double) (((int)nextTime.getValue().value - (int)lastTime.getValue().value))) / ((double) ((nextTimeStamp - lastTimeStamp)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lastTimeStamp == nextTimeStamp) {
|
if(lastTimeStamp == nextTimeStamp) {
|
||||||
curSpeed = 0f;
|
curSpeed = 0f;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int currentPosDiff = nextPosStamp - lastPosStamp;
|
|
||||||
int currentPos = curRealReplayTime - lastPosStamp;
|
|
||||||
|
|
||||||
float currentPosStepPerc = (float) currentPos / (float) currentPosDiff; //The percentage of the travelled path between the current positions
|
|
||||||
if(Float.isInfinite(currentPosStepPerc)) currentPosStepPerc = 0;
|
|
||||||
|
|
||||||
int currentTimeDiff = nextTimeStamp - lastTimeStamp;
|
|
||||||
int currentTime = curRealReplayTime - lastTimeStamp;
|
|
||||||
|
|
||||||
float currentTimeStepPerc = (float) currentTime / (float) currentTimeDiff; //The percentage of the travelled path between the current timestamps
|
|
||||||
if(Float.isInfinite(currentTimeStepPerc)) currentTimeStepPerc = 0;
|
|
||||||
|
|
||||||
float splinePos = ((float) ReplayHandler.getPositionKeyframes().indexOf(lastPos) + currentPosStepPerc) / (float) (posCount - 1);
|
|
||||||
float timePos = ((float) ReplayHandler.getTimeKeyframes().indexOf(lastTime) + currentTimeStepPerc) / (float) (timeCount - 1);
|
|
||||||
|
|
||||||
if(!spectating) {
|
if(!spectating) {
|
||||||
ReplayHandler.spectateCamera();
|
ReplayHandler.spectateCamera();
|
||||||
AdvancedPosition pos = new AdvancedPosition();
|
AdvancedPosition pos = positionKeyframes.getInterpolatedValueForTimestamp(curRealReplayTime, linear);
|
||||||
if(posCount > 1) {
|
|
||||||
if(!linear) {
|
|
||||||
motionSpline.applyPoint(Math.max(0, Math.min(1, splinePos)), pos);
|
|
||||||
} else {
|
|
||||||
motionLinear.applyPoint(Math.max(0, Math.min(1, splinePos)), pos);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(posCount == 1) {
|
|
||||||
Keyframe<AdvancedPosition> keyframe = ReplayHandler.getPositionKeyframes().first();
|
|
||||||
assert keyframe != null;
|
|
||||||
pos = keyframe.getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(pos != null) {
|
if(pos != null) {
|
||||||
ReplayHandler.setCameraTilt((float)pos.getRoll());
|
ReplayHandler.setCameraTilt((float)pos.getRoll());
|
||||||
@@ -316,17 +233,11 @@ public class ReplayProcess {
|
|||||||
ReplayHandler.spectateEntity(mc.theWorld.getEntityByID(lastPos.getValue().getSpectatedEntityID()));
|
ReplayHandler.spectateEntity(mc.theWorld.getEntityByID(lastPos.getValue().getSpectatedEntityID()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Integer curTimestamp = null;
|
Integer curTimestamp = timeKeyframes.getInterpolatedValueForTimestamp(curRealReplayTime, true).asInt();
|
||||||
if(timeLinear != null && timeCount > 1) {
|
|
||||||
TimestampValue timestampValue = new TimestampValue();
|
|
||||||
timeLinear.applyPoint(Math.max(0, Math.min(1, timePos)), timestampValue);
|
|
||||||
curTimestamp = (int) timestampValue.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!isVideoRecording()) ReplayMod.replaySender.setReplaySpeed(curSpeed);
|
if(!isVideoRecording()) ReplayMod.replaySender.setReplaySpeed(curSpeed);
|
||||||
|
|
||||||
if(curTimestamp != null)
|
ReplayMod.replaySender.sendPacketsTill(curTimestamp);
|
||||||
ReplayMod.replaySender.sendPacketsTill(curTimestamp);
|
|
||||||
|
|
||||||
lastRealReplayTime = curRealReplayTime;
|
lastRealReplayTime = curRealReplayTime;
|
||||||
lastRealTime = curTime;
|
lastRealTime = curTime;
|
||||||
@@ -336,7 +247,8 @@ public class ReplayProcess {
|
|||||||
requestFinish = false;
|
requestFinish = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((splinePos >= 1 || posCount <= 1) && (timePos >= 1 || timeCount <= 1)) {
|
if(curRealReplayTime > timeKeyframes.last().getRealTimestamp()
|
||||||
|
&& curRealReplayTime > positionKeyframes.last().getRealTimestamp()) {
|
||||||
requestFinish = true;
|
requestFinish = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user