Added PathPreviewRenderer to draw a Preview of the current Camera Path into the World

Added KeyframesModifyEvent to be dispatched whenever the ReplayHandler's Keyframe List is changed
Refactored Event package
Reworked Settings GUI
This commit is contained in:
CrushedPixel
2015-06-15 11:32:34 +02:00
committed by johni0702
parent 6d4512e74b
commit 3df1bdcfc8
23 changed files with 447 additions and 126 deletions

View File

@@ -3,7 +3,7 @@ package eu.crushedpixel.replaymod;
import com.google.common.util.concurrent.ListenableFutureTask; import com.google.common.util.concurrent.ListenableFutureTask;
import eu.crushedpixel.replaymod.api.ApiClient; import eu.crushedpixel.replaymod.api.ApiClient;
import eu.crushedpixel.replaymod.chat.ChatMessageHandler; import eu.crushedpixel.replaymod.chat.ChatMessageHandler;
import eu.crushedpixel.replaymod.events.*; import eu.crushedpixel.replaymod.events.handlers.*;
import eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay; import eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay;
import eu.crushedpixel.replaymod.holders.KeyframeSet; import eu.crushedpixel.replaymod.holders.KeyframeSet;
import eu.crushedpixel.replaymod.localization.LocalizedResourcePack; import eu.crushedpixel.replaymod.localization.LocalizedResourcePack;
@@ -11,6 +11,8 @@ import eu.crushedpixel.replaymod.online.authentication.AuthenticationHandler;
import eu.crushedpixel.replaymod.recording.ConnectionEventHandler; import eu.crushedpixel.replaymod.recording.ConnectionEventHandler;
import eu.crushedpixel.replaymod.registry.*; import eu.crushedpixel.replaymod.registry.*;
import eu.crushedpixel.replaymod.renderer.InvisibilityRender; import eu.crushedpixel.replaymod.renderer.InvisibilityRender;
import eu.crushedpixel.replaymod.renderer.PathPreviewRenderer;
import eu.crushedpixel.replaymod.renderer.SafeEntityRenderer;
import eu.crushedpixel.replaymod.renderer.SpectatorRenderer; import eu.crushedpixel.replaymod.renderer.SpectatorRenderer;
import eu.crushedpixel.replaymod.replay.ReplayHandler; import eu.crushedpixel.replaymod.replay.ReplayHandler;
import eu.crushedpixel.replaymod.replay.ReplayProcess; import eu.crushedpixel.replaymod.replay.ReplayProcess;
@@ -69,6 +71,7 @@ public class ReplayMod {
public static RatedFileHandler ratedFileHandler; public static RatedFileHandler ratedFileHandler;
public static SpectatorRenderer spectatorRenderer; public static SpectatorRenderer spectatorRenderer;
public static TooltipRenderer tooltipRenderer; public static TooltipRenderer tooltipRenderer;
public static PathPreviewRenderer pathPreviewRenderer;
// The instance of your mod that Forge uses. // The instance of your mod that Forge uses.
@Instance(value = "ReplayModID") @Instance(value = "ReplayModID")
@@ -122,13 +125,17 @@ public class ReplayMod {
spectatorRenderer = new SpectatorRenderer(); spectatorRenderer = new SpectatorRenderer();
pathPreviewRenderer = new PathPreviewRenderer();
FMLCommonHandler.instance().bus().register(pathPreviewRenderer);
MinecraftForge.EVENT_BUS.register(pathPreviewRenderer);
KeybindRegistry.initialize(); KeybindRegistry.initialize();
// try { try {
// mc.entityRenderer = new SafeEntityRenderer(mc, mc.entityRenderer); mc.entityRenderer = new SafeEntityRenderer(mc, mc.entityRenderer);
// } catch(Exception e) { } catch(Exception e) {
// e.printStackTrace(); e.printStackTrace();
// } }
tooltipRenderer = new TooltipRenderer(); tooltipRenderer = new TooltipRenderer();

View File

@@ -0,0 +1,15 @@
package eu.crushedpixel.replaymod.events;
import eu.crushedpixel.replaymod.holders.Keyframe;
import net.minecraftforge.fml.common.eventhandler.Event;
import java.util.List;
public class KeyframesModifyEvent extends Event {
public List<Keyframe> keyframes;
public KeyframesModifyEvent(List<Keyframe> keyframes) {
this.keyframes = keyframes;
}
}

View File

@@ -1,4 +1,4 @@
package eu.crushedpixel.replaymod.events; package eu.crushedpixel.replaymod.events.handlers;
import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.ReplayMod;
import eu.crushedpixel.replaymod.gui.GuiConstants; import eu.crushedpixel.replaymod.gui.GuiConstants;

View File

@@ -1,4 +1,4 @@
package eu.crushedpixel.replaymod.events; package eu.crushedpixel.replaymod.events.handlers;
import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.ReplayMod;
import eu.crushedpixel.replaymod.entities.CameraEntity.MoveDirection; import eu.crushedpixel.replaymod.entities.CameraEntity.MoveDirection;

View File

@@ -1,4 +1,4 @@
package eu.crushedpixel.replaymod.events; package eu.crushedpixel.replaymod.events.handlers;
import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.ReplayMod;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;

View File

@@ -1,4 +1,4 @@
package eu.crushedpixel.replaymod.events; package eu.crushedpixel.replaymod.events.handlers;
import eu.crushedpixel.replaymod.entities.CameraEntity; import eu.crushedpixel.replaymod.entities.CameraEntity;
import eu.crushedpixel.replaymod.replay.ReplayHandler; import eu.crushedpixel.replaymod.replay.ReplayHandler;

View File

@@ -1,4 +1,4 @@
package eu.crushedpixel.replaymod.events; package eu.crushedpixel.replaymod.events.handlers;
import eu.crushedpixel.replaymod.recording.ConnectionEventHandler; import eu.crushedpixel.replaymod.recording.ConnectionEventHandler;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;

View File

@@ -1,4 +1,4 @@
package eu.crushedpixel.replaymod.events; package eu.crushedpixel.replaymod.events.handlers;
import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.ReplayMod;
import eu.crushedpixel.replaymod.chat.ChatMessageHandler; import eu.crushedpixel.replaymod.chat.ChatMessageHandler;

View File

@@ -1,6 +1,7 @@
package eu.crushedpixel.replaymod.gui; package eu.crushedpixel.replaymod.gui;
import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.ReplayMod;
import eu.crushedpixel.replaymod.events.KeyframesModifyEvent;
import eu.crushedpixel.replaymod.gui.elements.GuiArrowButton; import eu.crushedpixel.replaymod.gui.elements.GuiArrowButton;
import eu.crushedpixel.replaymod.gui.elements.GuiNumberInput; import eu.crushedpixel.replaymod.gui.elements.GuiNumberInput;
import eu.crushedpixel.replaymod.holders.*; import eu.crushedpixel.replaymod.holders.*;
@@ -10,6 +11,7 @@ import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.GuiTextField; import net.minecraft.client.gui.GuiTextField;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
import net.minecraftforge.fml.common.FMLCommonHandler;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;
import java.awt.*; import java.awt.*;
@@ -195,6 +197,7 @@ public class GuiEditKeyframe extends GuiScreen {
((MarkerKeyframe)keyframe).setName(markerNameInput.getText().trim()); ((MarkerKeyframe)keyframe).setName(markerNameInput.getText().trim());
} }
} }
FMLCommonHandler.instance().bus().post(new KeyframesModifyEvent(ReplayHandler.getKeyframes()));
Keyboard.enableRepeatEvents(false); Keyboard.enableRepeatEvents(false);
} }

View File

@@ -1,9 +1,8 @@
package eu.crushedpixel.replaymod.gui; package eu.crushedpixel.replaymod.gui;
import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.gui.elements.GuiSettingsOnOffButton;
import eu.crushedpixel.replaymod.settings.ReplaySettings; import eu.crushedpixel.replaymod.gui.elements.GuiToggleButton;
import eu.crushedpixel.replaymod.settings.ReplaySettings.RecordingOptions; import eu.crushedpixel.replaymod.settings.ReplaySettings.RecordingOptions;
import eu.crushedpixel.replaymod.settings.ReplaySettings.RenderOptions;
import eu.crushedpixel.replaymod.settings.ReplaySettings.ReplayOptions; import eu.crushedpixel.replaymod.settings.ReplaySettings.ReplayOptions;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
@@ -16,20 +15,18 @@ import java.io.IOException;
public class GuiReplaySettings extends GuiScreen { public class GuiReplaySettings extends GuiScreen {
//TODO: Move to GuiConstants //TODO: Move to GuiConstants
private static final int QUALITY_SLIDER_ID = 9003;
private static final int RECORDSERVER_ID = 9004; private static final int RECORDSERVER_ID = 9004;
private static final int RECORDSP_ID = 9005; private static final int RECORDSP_ID = 9005;
private static final int SEND_CHAT = 9006; private static final int SEND_CHAT = 9006;
private static final int FORCE_LINEAR = 9007; private static final int FORCE_LINEAR = 9007;
private static final int ENABLE_LIGHTING = 9008; private static final int ENABLE_LIGHTING = 9008;
private static final int FRAMERATE_SLIDER_ID = 9009;
private static final int RESOURCEPACK_ID = 9010; private static final int RESOURCEPACK_ID = 9010;
private static final int WAITFORCHUNKS_ID = 9011;
private static final int INDICATOR_ID = 9012; private static final int INDICATOR_ID = 9012;
private static final int PATHPREVIEW_ID = 9013;
protected String screenTitle = I18n.format("replaymod.gui.settings.title"); protected String screenTitle = I18n.format("replaymod.gui.settings.title");
private GuiScreen parentGuiScreen; private GuiScreen parentGuiScreen;
private GuiButton recordServerButton, recordSPButton, sendChatButton, linearButton, lightingButton, private GuiToggleButton recordServerButton, recordSPButton, sendChatButton, linearButton, lightingButton,
resourcePackButton, waitForChunksButton, showIndicatorButton; resourcePackButton, showIndicatorButton, pathPreviewButton;
public GuiReplaySettings(GuiScreen parentGuiScreen) { public GuiReplaySettings(GuiScreen parentGuiScreen) {
this.parentGuiScreen = parentGuiScreen; this.parentGuiScreen = parentGuiScreen;
@@ -40,32 +37,31 @@ public class GuiReplaySettings extends GuiScreen {
this.buttonList.clear(); this.buttonList.clear();
this.buttonList.add(new GuiButton(200, this.width / 2 - 100, this.height - 27, I18n.format("gui.done"))); this.buttonList.add(new GuiButton(200, this.width / 2 - 100, this.height - 27, I18n.format("gui.done")));
ReplaySettings settings = ReplayMod.replaySettings;
int k = 0;
int i = 0; int i = 0;
for(RecordingOptions o : RecordingOptions.values()) { for(RecordingOptions o : RecordingOptions.values()) {
int xPos = this.width / 2 - 155 + i % 2 * 160;
int yPos = this.height / 6 + 24 * (i >> 1);
if(o == RecordingOptions.notifications) { if(o == RecordingOptions.notifications) {
this.buttonList.add(sendChatButton = new GuiButton(SEND_CHAT, sendChatButton = new GuiSettingsOnOffButton(SEND_CHAT, xPos, yPos, 150, 20, o);
this.width / 2 - 155 + i % 2 * 160, this.height / 6 + 24 * (i >> 1), 150, 20, this.buttonList.add(sendChatButton);
I18n.format("replaymod.gui.settings.notifications")+": " + onOff(settings.isShowNotifications())));
} else if(o == RecordingOptions.recordServer) { } else if(o == RecordingOptions.recordServer) {
this.buttonList.add(recordServerButton = new GuiButton(RECORDSERVER_ID, recordServerButton = new GuiSettingsOnOffButton(RECORDSERVER_ID, xPos, yPos, 150, 20, o);
this.width / 2 - 155 + i % 2 * 160, this.height / 6 + 24 * (i >> 1), 150, 20, this.buttonList.add(recordServerButton);
I18n.format("replaymod.gui.settings.recordserver")+": "
+ onOff(settings.isEnableRecordingServer())));
} else if(o == RecordingOptions.recordSingleplayer) { } else if(o == RecordingOptions.recordSingleplayer) {
this.buttonList.add(recordSPButton = new GuiButton(RECORDSP_ID, this.width / 2 - 155 + i % 2 * 160, recordSPButton = new GuiSettingsOnOffButton(RECORDSP_ID, xPos, yPos, 150, 20, o);
this.height / 6 + 24 * (i >> 1), 150, 20, I18n.format("replaymod.gui.settings.recordsingleplayer")+": " this.buttonList.add(recordSPButton);
+ onOff(settings.isEnableRecordingSingleplayer())));
} else if(o == RecordingOptions.indicator) { } else if(o == RecordingOptions.indicator) {
this.buttonList.add(showIndicatorButton = new GuiButton(INDICATOR_ID, this.width / 2 - 155 + i % 2 * 160, showIndicatorButton = new GuiSettingsOnOffButton(INDICATOR_ID, xPos, yPos, 150, 20, o);
this.height / 6 + 24 * (i >> 1), 150, 20, I18n.format("replaymod.gui.settings.indicator")+": "+ onOff(settings.showRecordingIndicator()))); this.buttonList.add(showIndicatorButton);
} }
++i; ++i;
++k;
} }
@@ -74,48 +70,34 @@ public class GuiReplaySettings extends GuiScreen {
} }
for(ReplayOptions o : ReplayOptions.values()) { for(ReplayOptions o : ReplayOptions.values()) {
int xPos = this.width / 2 - 155 + i % 2 * 160;
int yPos = this.height / 6 + 24 * (i >> 1);
if(o == ReplayOptions.lighting) { if(o == ReplayOptions.lighting) {
this.buttonList.add(lightingButton = new GuiButton(ENABLE_LIGHTING, this.width / 2 - 155 + i % 2 * 160, lightingButton = new GuiSettingsOnOffButton(ENABLE_LIGHTING, xPos, yPos, 150, 20, o);
this.height / 6 + 24 * (i >> 1), 150, 20, I18n.format("replaymod.gui.settings.lighting")+": " + onOff(settings.isLightingEnabled()))); this.buttonList.add(lightingButton);
} else if(o == ReplayOptions.linear) { } else if(o == ReplayOptions.linear) {
this.buttonList.add(linearButton = new GuiButton(FORCE_LINEAR, this.width / 2 - 155 + i % 2 * 160, linearButton = new GuiSettingsOnOffButton(FORCE_LINEAR, xPos, yPos, 150, 20, o,
this.height / 6 + 24 * (i >> 1), 150, 20, I18n.format("replaymod.gui.settings.interpolation")+": " + linearOnOff(settings.isLinearMovement()))); I18n.format("replaymod.gui.settings.interpolation.linear"), I18n.format("replaymod.gui.settings.interpolation.cubic"));
this.buttonList.add(linearButton);
} else if(o == ReplayOptions.useResources) { } else if(o == ReplayOptions.useResources) {
this.buttonList.add(resourcePackButton = new GuiButton(RESOURCEPACK_ID, this.width / 2 - 155 + i % 2 * 160, resourcePackButton = new GuiSettingsOnOffButton(RESOURCEPACK_ID, xPos, yPos, 150, 20, o);
this.height / 6 + 24 * (i >> 1), 150, 20, I18n.format("replaymod.gui.settings.resources")+": " + onOff(settings.getUseResourcePacks()))); this.buttonList.add(resourcePackButton);
} else if(o == ReplayOptions.previewPath) {
pathPreviewButton = new GuiSettingsOnOffButton(PATHPREVIEW_ID, xPos, yPos, 150, 20, o);
this.buttonList.add(pathPreviewButton);
} }
++i; ++i;
++k;
} }
if(i % 2 == 1) { if(i % 2 == 1) {
++i; ++i;
} }
for(RenderOptions o : RenderOptions.values()) {
if(o == RenderOptions.videoFramerate) {
this.buttonList.add(new GuiVideoFramerateSlider(FRAMERATE_SLIDER_ID,
this.width / 2 - 155 + i % 2 * 160, this.height / 6 + 24 * (i >> 1), settings.getVideoFramerate(), I18n.format("replaymod.gui.settings.framerate")));
} else if(o == RenderOptions.videoQuality) {
this.buttonList.add(new GuiVideoQualitySlider(QUALITY_SLIDER_ID,
this.width / 2 - 155 + i % 2 * 160, this.height / 6 + 24 * (i >> 1), (float) settings.getVideoQuality(), I18n.format("replaymod.gui.settings.quality")));
} else if(o == RenderOptions.waitForChunks) {
this.buttonList.add(waitForChunksButton = new GuiButton(WAITFORCHUNKS_ID, this.width / 2 - 155 + i % 2 * 160,
this.height / 6 + 24 * (i >> 1), 150, 20, I18n.format("replaymod.gui.settings.forcechunks")+": " + onOff(settings.getWaitForChunks())));
}
++i;
++k;
}
}
private String onOff(boolean on) {
return on ? I18n.format("options.on") : I18n.format("options.off");
}
private String linearOnOff(boolean on) {
return on ? I18n.format("replaymod.gui.settings.interpolation.linear") : I18n.format("replaymod.gui.settings.interpolation.cubic");
} }
@Override @Override
@@ -136,54 +118,10 @@ public class GuiReplaySettings extends GuiScreen {
case 200: case 200:
this.mc.displayGuiScreen(this.parentGuiScreen); this.mc.displayGuiScreen(this.parentGuiScreen);
break; break;
case RECORDSERVER_ID: }
boolean enabled = ReplayMod.replaySettings.isEnableRecordingServer();
enabled = !enabled; if(button instanceof GuiToggleButton) {
recordServerButton.displayString = I18n.format("replaymod.gui.settings.recordserver")+": " + onOff(enabled); ((GuiToggleButton) button).toggle();
ReplayMod.replaySettings.setEnableRecordingServer(enabled);
break;
case RECORDSP_ID:
enabled = ReplayMod.replaySettings.isEnableRecordingSingleplayer();
enabled = !enabled;
recordSPButton.displayString = I18n.format("replaymod.gui.settings.recordsingleplayer")+": " + onOff(enabled);
ReplayMod.replaySettings.setEnableRecordingSingleplayer(enabled);
break;
case SEND_CHAT:
enabled = ReplayMod.replaySettings.isShowNotifications();
enabled = !enabled;
sendChatButton.displayString = I18n.format("replaymod.gui.settings.notifications")+": " + onOff(enabled);
ReplayMod.replaySettings.setShowNotifications(enabled);
break;
case FORCE_LINEAR:
enabled = ReplayMod.replaySettings.isLinearMovement();
enabled = !enabled;
linearButton.displayString = I18n.format("replaymod.gui.settings.interpolation")+": " + linearOnOff(enabled);
ReplayMod.replaySettings.setLinearMovement(enabled);
break;
case ENABLE_LIGHTING:
enabled = ReplayMod.replaySettings.isLightingEnabled();
enabled = !enabled;
lightingButton.displayString = I18n.format("replaymod.gui.settings.lighting")+": " + onOff(enabled);
ReplayMod.replaySettings.setLightingEnabled(enabled);
break;
case RESOURCEPACK_ID:
enabled = ReplayMod.replaySettings.getUseResourcePacks();
enabled = !enabled;
resourcePackButton.displayString = I18n.format("replaymod.gui.settings.resources")+": " + onOff(enabled);
ReplayMod.replaySettings.setUseResourcePacks(enabled);
break;
case WAITFORCHUNKS_ID:
enabled = ReplayMod.replaySettings.getWaitForChunks();
enabled = !enabled;
waitForChunksButton.displayString = I18n.format("replaymod.gui.settings.forcechunks")+": " + onOff(enabled);
ReplayMod.replaySettings.setWaitForChunks(enabled);
break;
case INDICATOR_ID:
enabled = ReplayMod.replaySettings.showRecordingIndicator();
enabled = !enabled;
showIndicatorButton.displayString = I18n.format("replaymod.gui.settings.indicator")+": " + onOff(enabled);
ReplayMod.replaySettings.setEnableIndicator(enabled);
break;
} }
} }
} }

View File

@@ -0,0 +1,24 @@
package eu.crushedpixel.replaymod.gui.elements;
import net.minecraft.client.resources.I18n;
public class GuiOnOffButton extends GuiToggleButton {
private static final String[] values = new String[] {I18n.format("options.on"), I18n.format("options.off")};
public GuiOnOffButton(int buttonId, int x, int y, String buttonText) {
super(buttonId, x, y, buttonText, values);
}
public GuiOnOffButton(int buttonId, int x, int y, int width, int height, String buttonText) {
super(buttonId, x, y, width, height, buttonText, values);
}
public GuiOnOffButton(int buttonId, int x, int y, int width, int height, String buttonText, String onValue, String offValue) {
super(buttonId, x, y, width, height, buttonText, new String[] {onValue, offValue});
}
public boolean isOn() {
return getValue() == 0;
}
}

View File

@@ -0,0 +1,39 @@
package eu.crushedpixel.replaymod.gui.elements;
import eu.crushedpixel.replaymod.ReplayMod;
import eu.crushedpixel.replaymod.settings.ReplaySettings;
public class GuiSettingsOnOffButton extends GuiOnOffButton {
private ReplaySettings.ValueEnum toChange;
public GuiSettingsOnOffButton(int buttonId, int x, int y, int width, int height, ReplaySettings.ValueEnum toChange) {
super(buttonId, x, y, width, height, toChange.getName()+": ");
this.toChange = toChange;
if(toChange.getValue() instanceof Boolean) {
this.setValue((Boolean) toChange.getValue() == true ? 0 : 1);
}
}
public GuiSettingsOnOffButton(int buttonId, int x, int y, int width, int height, ReplaySettings.ValueEnum toChange, String onValue, String offValue) {
super(buttonId, x, y, width, height, toChange.getName()+": ", onValue, offValue);
this.toChange = toChange;
if(toChange.getValue() instanceof Boolean) {
this.setValue((Boolean) toChange.getValue() == true ? 0 : 1);
}
}
@Override
public void toggle() {
super.toggle();
toChange.setValue(isOn());
ReplayMod.replaySettings.rewriteSettings();
}
@Override
public void setValue(int value) {
super.setValue(value);
toChange.setValue(isOn());
ReplayMod.replaySettings.rewriteSettings();
}
}

View File

@@ -20,6 +20,12 @@ public class GuiToggleButton extends GuiAdvancedButton {
this.displayString = baseText+values[value]; this.displayString = baseText+values[value];
} }
public GuiToggleButton(int buttonId, int x, int y, int width, int height, String buttonText, String[] values) {
this(buttonId, x, y, buttonText, values);
this.width = width;
this.height = height;
}
@Override @Override
public boolean mousePressed(Minecraft mc, int mouseX, int mouseY) { public boolean mousePressed(Minecraft mc, int mouseX, int mouseY) {
boolean success = super.mousePressed(mc, mouseX, mouseY); boolean success = super.mousePressed(mc, mouseX, mouseY);
@@ -41,6 +47,7 @@ public class GuiToggleButton extends GuiAdvancedButton {
public void setValue(int value) { public void setValue(int value) {
this.value = value; this.value = value;
this.displayString = baseText+values[value];
} }

View File

@@ -180,7 +180,7 @@ public class GuiReplayOverlay extends Gui {
@Override @Override
public GuiElement delegate() { public GuiElement delegate() {
boolean selected = ReplayHandler.getSelectedKeyframe() instanceof PositionKeyframe; boolean selected = ReplayHandler.getSelectedKeyframe() instanceof PositionKeyframe;
boolean camera = true; boolean camera;
if(selected) { if(selected) {
camera = ((PositionKeyframe)ReplayHandler.getSelectedKeyframe()).getSpectatedEntityID() == null; camera = ((PositionKeyframe)ReplayHandler.getSelectedKeyframe()).getSpectatedEntityID() == null;
} else { } else {

View File

@@ -82,6 +82,14 @@ public class Position {
public void setRoll(float roll) { this.roll = roll; } public void setRoll(float roll) { this.roll = roll; }
public double distanceTo(double x, double y, double z) {
return distanceTo(new Position(x, y, z, 0, 0));
}
public double distanceTo(Position p2) {
return Math.sqrt(Math.pow((p2.getX() - getX()), 2) + Math.pow((p2.getY() - getY()), 2) + Math.pow((p2.getZ() - getZ()), 2));
}
@Override @Override
public String toString() { public String toString() {
return "X=" + x + ", Y=" + y + ", Z=" + z + ", Yaw=" + yaw + ", Pitch=" + pitch + ", Roll="+roll; return "X=" + x + ", Y=" + y + ", Z=" + z + ", Yaw=" + yaw + ", Pitch=" + pitch + ", Roll="+roll;

View File

@@ -0,0 +1,231 @@
package eu.crushedpixel.replaymod.renderer;
import eu.crushedpixel.replaymod.ReplayMod;
import eu.crushedpixel.replaymod.events.KeyframesModifyEvent;
import eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay;
import eu.crushedpixel.replaymod.holders.Keyframe;
import eu.crushedpixel.replaymod.holders.Position;
import eu.crushedpixel.replaymod.holders.PositionKeyframe;
import eu.crushedpixel.replaymod.interpolation.SplinePoint;
import eu.crushedpixel.replaymod.replay.ReplayHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.entity.Entity;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import org.lwjgl.opengl.GL11;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class PathPreviewRenderer {
private static final Minecraft mc = Minecraft.getMinecraft();
private SplinePoint spline = new SplinePoint();
private DistanceComparator distanceComparator = new DistanceComparator();
private List<PositionKeyframe> keyframes = new ArrayList<PositionKeyframe>();
@SubscribeEvent
public void renderCameraPath(RenderWorldLastEvent event) {
if(!ReplayHandler.isInReplay() || ReplayHandler.isInPath() || !ReplayMod.replaySettings.showPathPreview()) return;
Entity entity = ReplayHandler.getCameraEntity();
if(entity == null) return;
double doubleX = entity.posX;
double doubleY = entity.posY;
double doubleZ = entity.posZ;
GlStateManager.pushAttrib();
GlStateManager.pushMatrix();
GlStateManager.disableLighting();
GlStateManager.enableBlend();
GlStateManager.disableTexture2D();
if(spline.getPoints().size() > 1) {
Position prev = null;
if(ReplayMod.replaySettings.isLinearMovement()) {
for(int i = 0; i < spline.getPoints().size(); i++) {
Position point = spline.getPoints().get(i);
if(prev != null) {
drawConnection(doubleX, doubleY, doubleZ, prev, point, Color.RED.getRGB());
}
prev = point;
}
} else {
float max = spline.getPoints().size() * 50;
for(int i = 0; i < max; i++) {
Position point = spline.getPoint(i / max);
if(prev != null) {
drawConnection(doubleX, doubleY, doubleZ, prev, point, Color.RED.getRGB());
}
prev = point;
}
}
}
distanceComparator.setPlayerPos(doubleX, doubleY + 1.4, doubleZ);
Collections.sort(keyframes, distanceComparator);
for(PositionKeyframe kf : keyframes) {
drawPoint(doubleX, doubleY, doubleZ, kf);
}
GlStateManager.enableTexture2D();
GlStateManager.enableLighting();
GlStateManager.disableBlend();
GlStateManager.popAttrib();
GlStateManager.popMatrix();
}
@SubscribeEvent
public void recalcSpline(KeyframesModifyEvent event) {
keyframes = new ArrayList<PositionKeyframe>();
spline = new SplinePoint();
for(Keyframe kf : event.keyframes) {
if(kf instanceof PositionKeyframe) {
PositionKeyframe pkf = (PositionKeyframe)kf;
Position pos = pkf.getPosition();
spline.addPoint(pos);
keyframes.add(pkf);
}
}
if(spline.getPoints().size() > 1) {
spline.prepare();
}
}
private class DistanceComparator implements Comparator<PositionKeyframe> {
private double playerX, playerY, playerZ;
public void setPlayerPos(double playerX, double playerY, double playerZ) {
this.playerX = playerX;
this.playerY = playerY;
this.playerZ = playerZ;
}
@Override
public int compare(PositionKeyframe o1, PositionKeyframe o2) {
return -(new Double(o1.getPosition().distanceTo(playerX, playerY, playerZ)).compareTo(o2.getPosition().distanceTo(playerX, playerY, playerZ)));
}
@Override
public boolean equals(Object obj) {
return false;
}
}
private void drawConnection(double playerX, double playerY, double playerZ, Position pos1, Position pos2, int color) {
Tessellator tessellator = Tessellator.getInstance();
WorldRenderer renderer = tessellator.getWorldRenderer();
GL11.glLineWidth(3.0F);
double x = pos1.getX() - playerX;
double y = pos1.getY() - playerY;
double z = pos1.getZ() - playerZ;
renderer.setTranslation(x, y+1.4, z);
renderer.startDrawing(1);
renderer.setColorRGBA_I(color, 50);
renderer.addVertex(pos2.getX() - pos1.getX(), pos2.getY() - pos1.getY(), pos2.getZ() - pos1.getZ());
renderer.addVertex(0, 0, 0);
tessellator.draw();
renderer.setTranslation(0, 0, 0);
}
private void drawPoint(double playerX, double playerY, double playerZ, PositionKeyframe kf) {
GlStateManager.pushMatrix();
GlStateManager.enableTexture2D();
GlStateManager.enableLighting();
GlStateManager.disableLighting();
GlStateManager.enableAlpha();
GlStateManager.enableBlend();
Tessellator tessellator = Tessellator.getInstance();
WorldRenderer renderer = tessellator.getWorldRenderer();
mc.renderEngine.bindTexture(GuiReplayOverlay.replay_gui);
Position pos1 = kf.getPosition();
double x = pos1.getX() - playerX;
double y = pos1.getY() - playerY;
double z = pos1.getZ() - playerZ;
GlStateManager.translate(x, y+1.4, z);
float pitch = mc.getRenderManager().playerViewX;
float yaw = mc.getRenderManager().playerViewY;
GL11.glNormal3f(0, 1, 0);
GlStateManager.rotate(-yaw, 0, 1, 0);
GlStateManager.rotate(pitch, 1, 0, 0);
renderer.setColorRGBA_F(1, 1, 1, 0.5f);
renderer.startDrawingQuads();
float posX = 80/128f;
float posY = 0;
float size = 10/128f;
if(kf.equals(ReplayHandler.getSelectedKeyframe())) {
posY += size;
}
if(kf.getSpectatedEntityID() != null) {
posX += size;
}
renderer.addVertexWithUV(-0.5, 0.5, 0, posX+size, posY);
renderer.addVertexWithUV(0.5, 0.5, 0, posX+size, posY+size);
renderer.addVertexWithUV(-0.5, -0.5, 0, posX, posY);
renderer.addVertexWithUV(0.5, -0.5, 0, posX, posY+size);
renderer.addVertexWithUV(0.5, -0.5, 0, posX+size, posY);
renderer.addVertexWithUV(-0.5, -0.5, 0, posX, posY);
renderer.addVertexWithUV(0.5, 0.5, 0, posX+size, posY+size);
renderer.addVertexWithUV(-0.5, 0.5, 0, posX, posY + size);
tessellator.draw();
renderer.setTranslation(0, 0, 0);
GlStateManager.disableAlpha();
GlStateManager.disableTexture2D();
GlStateManager.disableBlend();
GlStateManager.enableLighting();
GlStateManager.popMatrix();
}
}

View File

@@ -14,6 +14,7 @@ public class SafeEntityRenderer extends EntityRenderer {
try { try {
super.updateCameraAndRender(partialTicks); super.updateCameraAndRender(partialTicks);
} catch(Exception e) { } catch(Exception e) {
e.printStackTrace();
} //This is plain easier than doing proper error prevention. } //This is plain easier than doing proper error prevention.
//If Johni reads this, don't think I'm a bad programmer... Just a lazy one :P //If Johni reads this, don't think I'm a bad programmer... Just a lazy one :P
} }

View File

@@ -3,6 +3,7 @@ package eu.crushedpixel.replaymod.replay;
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile;
import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.ReplayMod;
import eu.crushedpixel.replaymod.entities.CameraEntity; import eu.crushedpixel.replaymod.entities.CameraEntity;
import eu.crushedpixel.replaymod.events.KeyframesModifyEvent;
import eu.crushedpixel.replaymod.holders.*; import eu.crushedpixel.replaymod.holders.*;
import eu.crushedpixel.replaymod.registry.PlayerHandler; import eu.crushedpixel.replaymod.registry.PlayerHandler;
import eu.crushedpixel.replaymod.settings.RenderOptions; import eu.crushedpixel.replaymod.settings.RenderOptions;
@@ -92,6 +93,8 @@ public class ReplayHandler {
e.printStackTrace(); e.printStackTrace();
} }
} }
FMLCommonHandler.instance().bus().post(new KeyframesModifyEvent(keyframes));
} }
public static void useKeyframePresetFromRepository(int index) { public static void useKeyframePresetFromRepository(int index) {
@@ -104,6 +107,8 @@ public class ReplayHandler {
} }
if(!(selectedKeyframe instanceof MarkerKeyframe)) selectedKeyframe = null; if(!(selectedKeyframe instanceof MarkerKeyframe)) selectedKeyframe = null;
FMLCommonHandler.instance().bus().post(new KeyframesModifyEvent(keyframes));
} }
public static void spectateEntity(Entity e) { public static void spectateEntity(Entity e) {
@@ -214,6 +219,8 @@ public class ReplayHandler {
a = b; a = b;
} }
} }
FMLCommonHandler.instance().bus().post(new KeyframesModifyEvent(keyframes));
} }
public static void removeKeyframe(Keyframe keyframe) { public static void removeKeyframe(Keyframe keyframe) {
@@ -223,6 +230,8 @@ public class ReplayHandler {
} else { } else {
sortKeyframes(); sortKeyframes();
} }
FMLCommonHandler.instance().bus().post(new KeyframesModifyEvent(keyframes));
} }
public static int getKeyframeIndex(TimeKeyframe timeKeyframe) { public static int getKeyframeIndex(TimeKeyframe timeKeyframe) {
@@ -430,6 +439,8 @@ public class ReplayHandler {
} else { } else {
selectKeyframe(null); selectKeyframe(null);
} }
FMLCommonHandler.instance().bus().post(new KeyframesModifyEvent(keyframes));
} }
public static boolean isSelected(Keyframe kf) { public static boolean isSelected(Keyframe kf) {

View File

@@ -5,7 +5,7 @@ import com.google.common.io.Files;
import com.google.common.util.concurrent.ListenableFutureTask; import com.google.common.util.concurrent.ListenableFutureTask;
import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.ReplayMod;
import eu.crushedpixel.replaymod.entities.CameraEntity; import eu.crushedpixel.replaymod.entities.CameraEntity;
import eu.crushedpixel.replaymod.events.RecordingHandler; import eu.crushedpixel.replaymod.events.handlers.RecordingHandler;
import eu.crushedpixel.replaymod.holders.PacketData; import eu.crushedpixel.replaymod.holders.PacketData;
import eu.crushedpixel.replaymod.holders.Position; import eu.crushedpixel.replaymod.holders.Position;
import eu.crushedpixel.replaymod.timer.MCTimerHandler; import eu.crushedpixel.replaymod.timer.MCTimerHandler;

View File

@@ -2,6 +2,7 @@ package eu.crushedpixel.replaymod.settings;
import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.ReplayMod;
import eu.crushedpixel.replaymod.registry.LightingHandler; import eu.crushedpixel.replaymod.registry.LightingHandler;
import net.minecraft.client.resources.I18n;
import net.minecraftforge.common.config.Configuration; import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property; import net.minecraftforge.common.config.Property;
@@ -149,6 +150,13 @@ public class ReplaySettings {
rewriteSettings(); rewriteSettings();
} }
public boolean showPathPreview() { return (Boolean) ReplayOptions.previewPath.getValue(); };
public void setShowPathPreview(boolean show) {
ReplayOptions.previewPath.setValue(show);
rewriteSettings();
}
public void rewriteSettings() { public void rewriteSettings() {
ReplayMod.instance.config.load(); ReplayMod.instance.config.load();
@@ -218,12 +226,17 @@ public class ReplaySettings {
} }
public enum RecordingOptions implements ValueEnum { public enum RecordingOptions implements ValueEnum {
recordServer(true), recordSingleplayer(true), notifications(true), indicator(true); recordServer(true, "replaymod.gui.settings.recordserver"),
recordSingleplayer(true, "replaymod.gui.settings.recordsingleplayer"),
notifications(true, "replaymod.gui.settings.notifications"),
indicator(true, "replaymod.gui.settings.indicator");
private Object value; private Object value;
private String name;
RecordingOptions(Object value) { RecordingOptions(Object value, String name) {
this.value = value; this.value = value;
this.name = name;
} }
public Object getValue() { public Object getValue() {
@@ -233,15 +246,22 @@ public class ReplaySettings {
public void setValue(Object value) { public void setValue(Object value) {
this.value = value; this.value = value;
} }
public String getName() { return I18n.format(name); };
} }
public enum ReplayOptions implements ValueEnum { public enum ReplayOptions implements ValueEnum {
linear(false), lighting(false), useResources(true); linear(false, "replaymod.gui.settings.interpolation"),
lighting(false, "replaymod.gui.settings.lighting"),
useResources(true, "replaymod.gui.settings.resources"),
previewPath(true, "replaymod.gui.settings.pathpreview");
private Object value; private Object value;
private String name;
ReplayOptions(Object value) { ReplayOptions(Object value, String name) {
this.value = value; this.value = value;
this.name = name;
} }
public Object getValue() { public Object getValue() {
@@ -251,15 +271,21 @@ public class ReplaySettings {
public void setValue(Object value) { public void setValue(Object value) {
this.value = value; this.value = value;
} }
public String getName() { return I18n.format(name); };
} }
public enum RenderOptions implements ValueEnum { public enum RenderOptions implements ValueEnum {
videoQuality(0.5f), videoFramerate(30), waitForChunks(true); videoQuality(0.5f, "replaymod.gui.settings.quality"),
videoFramerate(30, "replaymod.gui.settings.framerate"),
waitForChunks(true, "replaymod.gui.settings.forcechunks");
private Object value; private Object value;
private String name;
RenderOptions(Object value) { RenderOptions(Object value, String name) {
this.value = value; this.value = value;
this.name = name;
} }
public Object getValue() { public Object getValue() {
@@ -269,15 +295,21 @@ public class ReplaySettings {
public void setValue(Object value) { public void setValue(Object value) {
this.value = value; this.value = value;
} }
public String getName() { return I18n.format(name); };
} }
public enum AdvancedOptions implements ValueEnum { public enum AdvancedOptions implements ValueEnum {
recordingPath("./replay_recordings/"), renderPath("./replay_videos/"), downloadPath("./replay_downloads"); recordingPath("./replay_recordings/", ""),
renderPath("./replay_videos/", ""),
downloadPath("./replay_downloads", "");
private Object value; private Object value;
private String name;
AdvancedOptions(Object value) { AdvancedOptions(Object value, String name) {
this.value = value; this.value = value;
this.name = name;
} }
public Object getValue() { public Object getValue() {
@@ -287,11 +319,15 @@ public class ReplaySettings {
public void setValue(Object value) { public void setValue(Object value) {
this.value = value; this.value = value;
} }
public String getName() { return I18n.format(name); };
} }
public interface ValueEnum { public interface ValueEnum {
Object getValue(); Object getValue();
void setValue(Object value); void setValue(Object value);
String getName();
} }
} }

View File

@@ -2,7 +2,7 @@ package eu.crushedpixel.replaymod.video;
import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.ReplayMod;
import eu.crushedpixel.replaymod.chat.ChatMessageHandler.ChatMessageType; import eu.crushedpixel.replaymod.chat.ChatMessageHandler.ChatMessageType;
import eu.crushedpixel.replaymod.events.TickAndRenderListener; import eu.crushedpixel.replaymod.events.handlers.TickAndRenderListener;
import eu.crushedpixel.replaymod.replay.ReplayHandler; import eu.crushedpixel.replaymod.replay.ReplayHandler;
import eu.crushedpixel.replaymod.utils.ImageUtils; import eu.crushedpixel.replaymod.utils.ImageUtils;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;

View File

@@ -210,6 +210,7 @@ replaymod.gui.settings.lighting=Ambient Lighting
replaymod.gui.settings.forcechunks=Force Render Chunks replaymod.gui.settings.forcechunks=Force Render Chunks
replaymod.gui.settings.resources=Server Resource Packs replaymod.gui.settings.resources=Server Resource Packs
replaymod.gui.settings.interpolation=Path Interpolation replaymod.gui.settings.interpolation=Path Interpolation
replaymod.gui.settings.pathpreview=Show Path Preview
replaymod.gui.settings.videoquality.draft=Draft replaymod.gui.settings.videoquality.draft=Draft
replaymod.gui.settings.videoquality.normal=Normal replaymod.gui.settings.videoquality.normal=Normal

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB