730 lines
28 KiB
Java
Executable File
730 lines
28 KiB
Java
Executable File
package eu.crushedpixel.replaymod.events;
|
|
|
|
import eu.crushedpixel.replaymod.ReplayMod;
|
|
import eu.crushedpixel.replaymod.entities.CameraEntity;
|
|
import eu.crushedpixel.replaymod.gui.*;
|
|
import eu.crushedpixel.replaymod.holders.Keyframe;
|
|
import eu.crushedpixel.replaymod.holders.Position;
|
|
import eu.crushedpixel.replaymod.holders.PositionKeyframe;
|
|
import eu.crushedpixel.replaymod.holders.TimeKeyframe;
|
|
import eu.crushedpixel.replaymod.recording.ConnectionEventHandler;
|
|
import eu.crushedpixel.replaymod.registry.ReplayGuiRegistry;
|
|
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
|
import eu.crushedpixel.replaymod.replay.ReplayProcess;
|
|
import eu.crushedpixel.replaymod.utils.MouseUtils;
|
|
import eu.crushedpixel.replaymod.video.VideoWriter;
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.client.gui.Gui;
|
|
import net.minecraft.client.gui.GuiChat;
|
|
import net.minecraft.client.gui.ScaledResolution;
|
|
import net.minecraft.client.gui.inventory.GuiInventory;
|
|
import net.minecraft.client.renderer.GlStateManager;
|
|
import net.minecraft.client.resources.I18n;
|
|
import net.minecraft.entity.Entity;
|
|
import net.minecraft.util.ResourceLocation;
|
|
import net.minecraftforge.client.event.RenderGameOverlayEvent;
|
|
import net.minecraftforge.fml.client.FMLClientHandler;
|
|
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
|
import org.lwjgl.input.Mouse;
|
|
import org.lwjgl.opengl.GL11;
|
|
|
|
import java.awt.*;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
public class GuiReplayOverlay extends Gui {
|
|
|
|
private final Minecraft mc = Minecraft.getMinecraft();
|
|
int sl_begin_x = 0;
|
|
int sl_end_x = 63;
|
|
int sl_y = 40;
|
|
int plus_x = 0;
|
|
int plus_y = 0;
|
|
int minus_x = 0;
|
|
int minus_y = 9;
|
|
int slider_begin_x = 1;
|
|
int slider_begin_width = 1;
|
|
int slider_end_x = 62;
|
|
int slider_end_width = 1;
|
|
int slider_y = 50;
|
|
int slider_height = 7;
|
|
private int sliderX = 35;
|
|
private int sliderY = 10;
|
|
private int timelineX = sliderX + 100 + 5;
|
|
private int realTimelineX = 10 + 4 * 25;
|
|
private int realTimelineY = 33 + 10;
|
|
private int ppButtonX = 10;
|
|
private int ppButtonY = 10;
|
|
private int r_ppButtonX = 10;
|
|
private int r_ppButtonY = realTimelineY + 1;
|
|
private int exportButtonX = 35;
|
|
private int exportButtonY = realTimelineY + 1;
|
|
private int place_ButtonX = 60;
|
|
private int place_ButtonY = realTimelineY + 1;
|
|
private int time_ButtonX = 85;
|
|
private int time_ButtonY = realTimelineY + 1;
|
|
private ResourceLocation replay_gui = new ResourceLocation("replaymod", "replay_gui.png");
|
|
private ResourceLocation extended_gui = new ResourceLocation("replaymod", "extended_gui.png");
|
|
private ResourceLocation timeline_icons = new ResourceLocation("replaymod", "timeline_icons.png");
|
|
private GuiReplaySpeedSlider speedSlider;
|
|
private boolean mouseDown = false;
|
|
private int tl_begin_x = 0;
|
|
private int tl_begin_width = 4;
|
|
private int tl_end_x = 60;
|
|
private int tl_end_width = 4;
|
|
private int tl_middle_x = 4;
|
|
private int tl_y = 40;
|
|
private float zoom_scale = 0.1f; //can see 1/10th of the timeline
|
|
private float pos_left = 0f; //left border of timeline is at 0%
|
|
private long timelineLength = 10 * 60 * 1000; //10 min of timeline
|
|
private float zoom_steps = 0.05f;
|
|
private boolean wasSliding = false;
|
|
private boolean mouseDwn = false;
|
|
|
|
public void resetUI(boolean slider) throws Exception {
|
|
if(FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) {
|
|
mc.displayGuiScreen(null);
|
|
}
|
|
ReplayHandler.setRealTimelineCursor(0);
|
|
if(slider)
|
|
speedSlider = new GuiReplaySpeedSlider(1, sliderX, sliderY, I18n.format("replaymod.gui.speed"));
|
|
}
|
|
|
|
@SubscribeEvent
|
|
public void onRenderGui(RenderGameOverlayEvent event) {
|
|
if(ReplayProcess.isVideoRecording() && ReplayHandler.isInPath() && !(mc.currentScreen instanceof GuiCancelRender)) {
|
|
if(event.isCancelable()) event.setCanceled(true);
|
|
}
|
|
}
|
|
|
|
|
|
@SubscribeEvent
|
|
public void onRenderTabList(RenderGameOverlayEvent.Pre event) { //cancelling tab list rendering and rendering help instead
|
|
if(ReplayHandler.isInReplay() && event.type == RenderGameOverlayEvent.ElementType.PLAYER_LIST) {
|
|
event.setCanceled(true);
|
|
}
|
|
}
|
|
|
|
@SubscribeEvent
|
|
public void renderRecordingIndicator(RenderGameOverlayEvent.Text event) {
|
|
if(!ReplayHandler.isInReplay() && ReplayMod.replaySettings.showRecordingIndicator() && ConnectionEventHandler.isRecording()) {
|
|
this.drawString(mc.fontRendererObj, I18n.format("replaymod.gui.recording").toUpperCase(), 30, 18 - (mc.fontRendererObj.FONT_HEIGHT / 2), Color.WHITE.getRGB());
|
|
mc.renderEngine.bindTexture(replay_gui);
|
|
GlStateManager.resetColor();
|
|
GlStateManager.enableAlpha();
|
|
this.drawModalRectWithCustomSizedTexture(10, 10, 40, 21, 16, 16, 64, 64);
|
|
}
|
|
}
|
|
|
|
@SubscribeEvent
|
|
public void onRenderGui(RenderGameOverlayEvent.Post event) throws IllegalArgumentException, IllegalAccessException {
|
|
|
|
if(!ReplayHandler.isInReplay() || FMLClientHandler.instance().isGUIOpen(GuiSpectateSelection.class)
|
|
|| VideoWriter.isRecording() || FMLClientHandler.instance().isGUIOpen(GuiKeyframeRepository.class)) {
|
|
return;
|
|
}
|
|
|
|
if(!ReplayGuiRegistry.hidden) ReplayGuiRegistry.hide();
|
|
|
|
if(FMLClientHandler.instance().isGUIOpen(GuiChat.class) || FMLClientHandler.instance().isGUIOpen(GuiInventory.class)) {
|
|
mc.displayGuiScreen(new GuiMouseInput());
|
|
}
|
|
|
|
GL11.glEnable(GL11.GL_BLEND);
|
|
|
|
Point mousePoint = MouseUtils.getMousePos();
|
|
final int mouseX = (int) mousePoint.getX();
|
|
final int mouseY = (int) mousePoint.getY();
|
|
|
|
Point scaled = MouseUtils.getScaledDimensions();
|
|
final int width = (int) scaled.getX();
|
|
final int height = (int) scaled.getY();
|
|
|
|
//Draw Timeline
|
|
drawTimeline(timelineX, width - 14, 9);
|
|
drawRealTimeline(realTimelineX, width - 14 - 11, realTimelineY, mouseX, mouseY);
|
|
|
|
//Play/Pause button
|
|
int x = 0;
|
|
int y = 0;
|
|
|
|
boolean play = !ReplayMod.replaySender.paused();
|
|
boolean hover = false;
|
|
|
|
if(FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) {
|
|
if(mouseX >= ppButtonX && mouseX <= ppButtonX + 20
|
|
&& mouseY >= ppButtonY && mouseY <= ppButtonY + 20) {
|
|
hover = true;
|
|
}
|
|
}
|
|
|
|
if(play) {
|
|
y = 20;
|
|
}
|
|
if(hover) {
|
|
x = 20;
|
|
}
|
|
|
|
mc.renderEngine.bindTexture(replay_gui);
|
|
|
|
GlStateManager.resetColor();
|
|
this.drawModalRectWithCustomSizedTexture(ppButtonX, ppButtonY, x, y, 20, 20, 64, 64);
|
|
|
|
//When hurrying, no Timeline jumping etc. is possible
|
|
if(Mouse.isButtonDown(0) && FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class) && !ReplayMod.replaySender.isHurrying()) { //clicking the Button
|
|
speedSlider.mousePressed(mc, mouseX, mouseY);
|
|
if(!mouseDown) {
|
|
mouseDown = true;
|
|
if(hover) {
|
|
boolean paused = !ReplayMod.replaySender.paused();
|
|
if(paused) {
|
|
ReplayMod.replaySender.setReplaySpeed(0);
|
|
} else {
|
|
ReplayMod.replaySender.setReplaySpeed(speedSlider.getSliderValue());
|
|
}
|
|
|
|
} else if(mouseX >= exportButtonX && mouseX <= exportButtonX + 20 && mouseY >= exportButtonY && exportButtonY <= exportButtonY + 20) {
|
|
ReplayHandler.startPath(true);
|
|
}
|
|
|
|
if(mouseX >= timelineX + 4 && mouseX <= width - 18 && mouseY >= 11 && mouseY <= 29) {
|
|
double tot = (width - 18) - (timelineX + 4);
|
|
double perc = (mouseX - (timelineX + 4)) / tot;
|
|
double time = perc * (double) ReplayMod.replaySender.replayLength();
|
|
|
|
if(time < ReplayMod.replaySender.currentTimeStamp()) {
|
|
mc.displayGuiScreen(null);
|
|
}
|
|
|
|
CameraEntity cam = ReplayHandler.getCameraEntity();
|
|
if(cam != null) {
|
|
ReplayHandler.setLastPosition(new Position(cam.posX, cam.posY, cam.posZ, cam.rotationPitch, cam.rotationYaw));
|
|
} else {
|
|
ReplayHandler.setLastPosition(null);
|
|
}
|
|
|
|
if((int) time != ReplayMod.replaySender.getDesiredTimestamp())
|
|
ReplayMod.replaySender.jumpToTime((int) time);
|
|
}
|
|
}
|
|
|
|
} else {
|
|
try {
|
|
speedSlider.mouseReleased(mouseX, mouseY);
|
|
mouseDown = false;
|
|
} catch(Exception e) {
|
|
}
|
|
}
|
|
|
|
hover = false;
|
|
x = 0;
|
|
y = 18;
|
|
|
|
if(FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) {
|
|
if(mouseX >= exportButtonX && mouseX <= exportButtonX + 20
|
|
&& mouseY >= exportButtonY && mouseY <= exportButtonY + 20) {
|
|
hover = true;
|
|
}
|
|
}
|
|
|
|
if(hover) {
|
|
x = 20;
|
|
}
|
|
|
|
mc.renderEngine.bindTexture(timeline_icons);
|
|
|
|
GlStateManager.resetColor();
|
|
this.drawModalRectWithCustomSizedTexture(exportButtonX, exportButtonY, x, y, 20, 20, 64, 64);
|
|
|
|
//GlStateManager.resetColor();
|
|
|
|
//Place Keyframe Button
|
|
hover = false;
|
|
x = 0;
|
|
y = 0;
|
|
|
|
if(FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) {
|
|
if(mouseX >= place_ButtonX && mouseX <= place_ButtonX + 20
|
|
&& mouseY >= place_ButtonY && mouseY <= place_ButtonY + 20) {
|
|
hover = true;
|
|
}
|
|
}
|
|
|
|
if(hover) {
|
|
x = 20;
|
|
}
|
|
|
|
if(ReplayHandler.getSelected() != null && ReplayHandler.getSelected() instanceof PositionKeyframe) {
|
|
y += 20;
|
|
}
|
|
|
|
mc.renderEngine.bindTexture(extended_gui);
|
|
|
|
if(hover && Mouse.isButtonDown(0) && isClick() && FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)
|
|
&& !ReplayHandler.isInPath()) {
|
|
if(ReplayHandler.getSelected() == null || !(ReplayHandler.getSelected() instanceof PositionKeyframe)) {
|
|
addPlaceKeyframe();
|
|
} else {
|
|
ReplayHandler.removeKeyframe(ReplayHandler.getSelected());
|
|
}
|
|
}
|
|
|
|
GlStateManager.resetColor();
|
|
this.drawModalRectWithCustomSizedTexture(place_ButtonX, place_ButtonY, x, y, 20, 20, 64, 64);
|
|
|
|
|
|
//Time Keyframe Button
|
|
hover = false;
|
|
x = 0;
|
|
y = 40;
|
|
|
|
boolean timeSelected = false;
|
|
if(ReplayHandler.getSelected() != null && ReplayHandler.getSelected() instanceof TimeKeyframe) {
|
|
timeSelected = true;
|
|
x = 40;
|
|
y = 0;
|
|
}
|
|
|
|
if(FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) {
|
|
if(mouseX >= time_ButtonX && mouseX <= time_ButtonX + 20
|
|
&& mouseY >= time_ButtonY && mouseY <= time_ButtonY + 20) {
|
|
hover = true;
|
|
}
|
|
}
|
|
|
|
if(hover) {
|
|
if(timeSelected) {
|
|
y = 20;
|
|
} else {
|
|
x = 20;
|
|
}
|
|
}
|
|
|
|
mc.renderEngine.bindTexture(extended_gui);
|
|
|
|
if(hover && Mouse.isButtonDown(0) && isClick() && FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) {
|
|
if(ReplayHandler.getSelected() == null || !(ReplayHandler.getSelected() instanceof TimeKeyframe) && !ReplayHandler.isInPath()) {
|
|
addTimeKeyframe();
|
|
} else {
|
|
ReplayHandler.removeKeyframe(ReplayHandler.getSelected());
|
|
}
|
|
}
|
|
|
|
GlStateManager.resetColor();
|
|
this.drawModalRectWithCustomSizedTexture(time_ButtonX, time_ButtonY, x, y, 20, 20, 64, 64);
|
|
|
|
if(mouseX >= (timelineX + 4) && mouseX <= width - 18 && mouseY >= 11 && mouseY <= 29) {
|
|
double tot = (width - 18) - (timelineX + 4);
|
|
double perc = (mouseX - (timelineX + 4)) / tot;
|
|
long time = Math.round(perc * (double) ReplayMod.replaySender.replayLength());
|
|
|
|
String timestamp = (String.format("%02d:%02ds",
|
|
TimeUnit.MILLISECONDS.toMinutes(time),
|
|
TimeUnit.MILLISECONDS.toSeconds(time) -
|
|
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(time))
|
|
));
|
|
|
|
this.drawCenteredString(mc.fontRendererObj, timestamp, mouseX, mouseY + 5, Color.WHITE.getRGB());
|
|
}
|
|
|
|
if(mc.inGameHasFocus) {
|
|
Mouse.setCursorPosition(width / 2, height / 2);
|
|
}
|
|
|
|
try {
|
|
speedSlider.drawButton(mc, mouseX, mouseY);
|
|
} catch(Exception e) {
|
|
}
|
|
|
|
GlStateManager.resetColor();
|
|
|
|
Entity player = ReplayHandler.getCameraEntity();
|
|
if(player != null) {
|
|
player.setVelocity(0, 0, 0);
|
|
}
|
|
|
|
if(!Mouse.isButtonDown(0)) isClick();
|
|
}
|
|
|
|
private void drawTimeline(int minX, int maxX, int y) {
|
|
int zero = minX + tl_begin_width;
|
|
int full = maxX - tl_end_width;
|
|
|
|
GlStateManager.resetColor();
|
|
mc.renderEngine.bindTexture(replay_gui);
|
|
this.drawModalRectWithCustomSizedTexture(minX, y, tl_begin_x, tl_y, tl_begin_width, 22, 64, 64);
|
|
|
|
for(int i = minX + tl_begin_width; i < maxX - tl_end_width; i += tl_end_x - tl_begin_width) {
|
|
this.drawModalRectWithCustomSizedTexture(i, y, tl_begin_x + tl_begin_width
|
|
, tl_y, Math.min(tl_end_x - tl_begin_width, maxX - tl_end_width - i)
|
|
, 22, 64, 64);
|
|
}
|
|
|
|
this.drawModalRectWithCustomSizedTexture(maxX - tl_end_width, y, tl_end_x, tl_y, tl_end_width, 22, 64, 64);
|
|
|
|
//Cursor
|
|
double width = full - zero;
|
|
double perc = (double) ReplayMod.replaySender.currentTimeStamp() / (double) ReplayMod.replaySender.replayLength();
|
|
|
|
int cursorX = (int) Math.round(zero + (perc * width));
|
|
this.drawModalRectWithCustomSizedTexture(cursorX - 3, y + 3, 44, 0, 8, 16, 64, 64);
|
|
}
|
|
|
|
private void drawRealTimeline(int minX, int maxX, int y, int mouseX, int mouseY) {
|
|
int zero = minX + tl_begin_width;
|
|
int full = maxX - tl_end_width;
|
|
|
|
//the real timeline
|
|
GlStateManager.resetColor();
|
|
mc.renderEngine.bindTexture(replay_gui);
|
|
this.drawModalRectWithCustomSizedTexture(minX, y, tl_begin_x, tl_y, tl_begin_width, 22, 64, 64);
|
|
|
|
for(int i = minX + tl_begin_width; i < maxX - tl_end_width; i += tl_end_x - tl_begin_width) {
|
|
this.drawModalRectWithCustomSizedTexture(i, y, tl_begin_x + tl_begin_width
|
|
, tl_y, Math.min(tl_end_x - tl_begin_width, maxX - tl_end_width - i)
|
|
, 22, 64, 64);
|
|
}
|
|
|
|
this.drawModalRectWithCustomSizedTexture(maxX - tl_end_width, y, tl_end_x, tl_y, tl_end_width, 22, 64, 64);
|
|
|
|
//Time Slider
|
|
int yo = y + 22 + 1;
|
|
GlStateManager.resetColor();
|
|
mc.renderEngine.bindTexture(timeline_icons);
|
|
this.drawModalRectWithCustomSizedTexture(minX, yo, sl_begin_x, sl_y, 2, 9, 64, 64);
|
|
|
|
for(int i = minX + 2; i < maxX - 1; i += sl_end_x - 2) {
|
|
this.drawModalRectWithCustomSizedTexture(i, yo, 2, sl_y,
|
|
Math.min(sl_end_x - 2, maxX - 1 - i), 9, 64, 64);
|
|
}
|
|
|
|
this.drawModalRectWithCustomSizedTexture(maxX - 1, yo, sl_end_x, sl_y, 1, 9, 64, 64);
|
|
|
|
//Timeline Pos Slider
|
|
int sl_y = yo + 1;
|
|
int minPos = minX + 1;
|
|
int maxPos = maxX - 2;
|
|
int tlWidth = maxPos - minPos;
|
|
|
|
int slider_min = minPos + Math.round(pos_left * tlWidth);
|
|
int slider_width = Math.round(zoom_scale * tlWidth);
|
|
|
|
int sl_max = slider_min + slider_width;
|
|
|
|
this.drawModalRectWithCustomSizedTexture(slider_min, sl_y, slider_begin_x, slider_y, slider_begin_width, slider_height, 64, 64);
|
|
|
|
for(int i = slider_min + slider_begin_width; i < sl_max - slider_end_width; i += slider_end_x - slider_begin_width - slider_begin_x) {
|
|
this.drawModalRectWithCustomSizedTexture(i, sl_y, slider_begin_x + slider_begin_width, slider_y,
|
|
Math.min(slider_end_x - slider_end_width - slider_begin_x, sl_max - slider_end_width - i), slider_height, 64, 64);
|
|
}
|
|
|
|
this.drawModalRectWithCustomSizedTexture(sl_max - slider_end_width, sl_y, slider_end_x, slider_y,
|
|
slider_end_width, slider_height, 64, 64);
|
|
|
|
//Slider dragging
|
|
if(Mouse.isButtonDown(0) && FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class) && (mouseX >= slider_min && mouseX <= sl_max && mouseY >= sl_y && mouseY <= sl_y + slider_height || wasSliding)) {
|
|
wasSliding = true;
|
|
float dx = ((float) Mouse.getDX() * (float) new ScaledResolution(mc, mc.displayWidth, mc.displayHeight).getScaledWidth() / mc.displayWidth);
|
|
this.pos_left = Math.min(1f - this.zoom_scale, Math.max(0f, this.pos_left + (dx / (float) tlWidth)));
|
|
}
|
|
|
|
if(!Mouse.isButtonDown(0)) {
|
|
wasSliding = false;
|
|
}
|
|
|
|
//Timeline Buttons
|
|
//+- Buttons
|
|
boolean hover = false;
|
|
int px = plus_x;
|
|
if(FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) {
|
|
if(mouseX >= maxX + 2 && mouseX <= maxX + 2 + 9
|
|
&& mouseY >= y + 1 && mouseY <= y + 1 + 9) {
|
|
hover = true;
|
|
}
|
|
}
|
|
|
|
if(hover) {
|
|
px += 9;
|
|
}
|
|
|
|
this.drawModalRectWithCustomSizedTexture(maxX + 2, y + 1, px, plus_y, 9, 9, 64, 64);
|
|
|
|
if(hover && Mouse.isButtonDown(0) && FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) {
|
|
zoomIn();
|
|
}
|
|
|
|
hover = false;
|
|
int mx = minus_x;
|
|
|
|
if(FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) {
|
|
if(mouseX >= maxX + 2 && mouseX <= maxX + 2 + 9
|
|
&& mouseY >= y + 9 + 3 && mouseY <= y + 9 + 3 + 9) {
|
|
hover = true;
|
|
}
|
|
}
|
|
|
|
if(hover) {
|
|
mx += 9;
|
|
}
|
|
|
|
this.drawModalRectWithCustomSizedTexture(maxX + 2, y + 9 + 3, mx, minus_y, 9, 9, 64, 64);
|
|
|
|
if(hover && Mouse.isButtonDown(0) && FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) {
|
|
zoomOut();
|
|
}
|
|
|
|
//show Time String
|
|
if(mouseX >= zero && mouseX <= full && mouseY >= y && mouseY <= y + 22) {
|
|
long tot = Math.round((double) timelineLength * zoom_scale);
|
|
double perc = (mouseX - (realTimelineX + 4)) / (double) (full - zero);
|
|
|
|
long time = Math.round(this.pos_left * (double) timelineLength) + Math.round(perc * (double) tot);
|
|
|
|
String timestamp = (String.format("%02d:%02ds",
|
|
TimeUnit.MILLISECONDS.toMinutes(time),
|
|
TimeUnit.MILLISECONDS.toSeconds(time) -
|
|
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(time))
|
|
));
|
|
this.drawCenteredString(mc.fontRendererObj, timestamp, mouseX, mouseY + 5, Color.WHITE.getRGB());
|
|
}
|
|
|
|
//draw Markers on timeline
|
|
MarkerType mt = MarkerType.getMarkerType(zoom_scale, timelineLength);
|
|
|
|
//every x seconds, draw small marker
|
|
long left_real = Math.round(pos_left * (double) timelineLength);
|
|
long right_real = left_real + (Math.round(zoom_scale * timelineLength));
|
|
long tot = Math.round((double) timelineLength * zoom_scale);
|
|
|
|
for(int s = 0; s <= timelineLength; s += mt.getSmallDistance()) {
|
|
if(s > right_real) break;
|
|
if(s >= left_real) {
|
|
//calculate absolute position on screen
|
|
long relative = (s) - (left_real);
|
|
double perc = ((double) relative / (double) tot);
|
|
|
|
long real_width = full - zero;
|
|
long rel_x = Math.round(perc * (double) real_width);
|
|
|
|
long real_x = zero + rel_x;
|
|
|
|
this.drawVerticalLine((int) real_x, y + 19 - 3, y + 19, Color.WHITE.getRGB());
|
|
}
|
|
}
|
|
|
|
//every x seconds, draw big marker
|
|
for(int s = 0; s <= timelineLength; s += mt.getDistance()) {
|
|
if(s > right_real) break;
|
|
if(s >= left_real) {
|
|
//calculate absolute position on screen
|
|
long relative = s - (left_real);
|
|
double perc = ((double) relative / (double) tot);
|
|
|
|
long real_width = full - zero;
|
|
long rel_x = Math.round(perc * (double) real_width);
|
|
|
|
long real_x = zero + rel_x;
|
|
|
|
this.drawVerticalLine((int) real_x, y + 19 - 7, y + 19, Color.LIGHT_GRAY.getRGB());
|
|
|
|
//write text
|
|
int time = s;
|
|
String timestamp = (String.format("%02d:%02d",
|
|
TimeUnit.MILLISECONDS.toMinutes(time),
|
|
TimeUnit.MILLISECONDS.toSeconds(time) -
|
|
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(time))
|
|
));
|
|
|
|
this.drawCenteredString(mc.fontRendererObj, timestamp, (int) real_x, y - 8, Color.WHITE.getRGB());
|
|
}
|
|
}
|
|
|
|
//handle Mouse clicks on realTimeLine
|
|
if(Mouse.isButtonDown(0) && FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class) && !wasSliding && mouseX >= minX + tl_begin_width && mouseX <= maxX - tl_end_width &&
|
|
mouseY >= y && mouseY <= y + 22) {
|
|
|
|
//calculate real time and set cursor accordingly
|
|
int width = (maxX - tl_end_width) - (minX + tl_begin_width);
|
|
int rel_x = mouseX - (minX + tl_begin_width);
|
|
|
|
float rel_pos = (float) rel_x / (float) width;
|
|
|
|
float abs_width = (zoom_scale * (float) timelineLength);
|
|
int real_pos = Math.round(left_real + ((rel_pos) * abs_width));
|
|
|
|
ReplayHandler.setRealTimelineCursor(real_pos);
|
|
|
|
//Keyframe click handling here
|
|
if(isClick()) {
|
|
//tolerance is 2 pixels multiplied with the timespan of one pixel
|
|
int tolerance = 2 * Math.round(abs_width / (float) width);
|
|
|
|
if(mouseY >= y + 9) {
|
|
TimeKeyframe close = ReplayHandler.getClosestTimeKeyframeForRealTime(ReplayHandler.getRealTimelineCursor(), tolerance);
|
|
ReplayHandler.selectKeyframe(close); //can be null, deselects keyframe
|
|
} else {
|
|
PositionKeyframe close = ReplayHandler.getClosestPlaceKeyframeForRealTime(ReplayHandler.getRealTimelineCursor(), tolerance);
|
|
ReplayHandler.selectKeyframe(close); //can be null, deselects keyframe
|
|
}
|
|
}
|
|
}
|
|
|
|
//Draw Realtime Cursor
|
|
if(ReplayHandler.getRealTimelineCursor() >= left_real && ReplayHandler.getRealTimelineCursor() <= right_real) {
|
|
long rel_pos = ReplayHandler.getRealTimelineCursor() - left_real;
|
|
long rel_width = right_real - left_real;
|
|
double perc = (double) rel_pos / (double) rel_width;
|
|
|
|
int real_width = (maxX - tl_end_width) - (minX + tl_begin_width);
|
|
double rel_x = (float) real_width * perc;
|
|
|
|
int real_x = (int) Math.round((minX + tl_begin_width) + rel_x);
|
|
mc.renderEngine.bindTexture(this.replay_gui);
|
|
|
|
GL11.glEnable(GL11.GL_BLEND);
|
|
this.drawModalRectWithCustomSizedTexture(real_x - 3, y + 3, 44, 0, 8, 16, 64, 64);
|
|
//this.drawModalRectWithCustomSizedTexture(real_x, sl_y, u, v, width, height, textureWidth, textureHeight)
|
|
}
|
|
|
|
|
|
//Draw Keyframe logos
|
|
mc.renderEngine.bindTexture(timeline_icons);
|
|
for(Keyframe kf : ReplayHandler.getKeyframes()) {
|
|
if(kf.getRealTimestamp() > right_real) break;
|
|
if(kf.getRealTimestamp() >= left_real) {
|
|
int dx = 18;
|
|
int dy = 0;
|
|
|
|
int ry = y + 3;
|
|
|
|
if(kf instanceof TimeKeyframe) {
|
|
dy = 5;
|
|
ry += 5;
|
|
}
|
|
if(ReplayHandler.isSelected(kf)) {
|
|
dx += 5;
|
|
}
|
|
|
|
long relative = kf.getRealTimestamp() - (left_real);
|
|
double perc = ((double) relative / (double) tot);
|
|
|
|
long real_width = full - zero;
|
|
long rel_x = Math.round(perc * (double) real_width);
|
|
|
|
long real_x = zero + rel_x - 2;
|
|
|
|
this.drawModalRectWithCustomSizedTexture((int) real_x, ry, dx, dy, 5, 5, 64, 64);
|
|
}
|
|
}
|
|
|
|
//Draw Play/Pause Button
|
|
//Play/Pause button
|
|
|
|
int dx = 0;
|
|
int dy = 0;
|
|
|
|
boolean play = ReplayHandler.isInPath();
|
|
hover = false;
|
|
|
|
if(FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) {
|
|
if(mouseX >= r_ppButtonX && mouseX <= r_ppButtonX + 20
|
|
&& mouseY >= r_ppButtonY && mouseY <= r_ppButtonY + 20) {
|
|
hover = true;
|
|
}
|
|
}
|
|
|
|
if(play) {
|
|
dy = 20;
|
|
}
|
|
if(hover) {
|
|
dx = 20;
|
|
}
|
|
|
|
mc.renderEngine.bindTexture(replay_gui);
|
|
|
|
GlStateManager.resetColor();
|
|
this.drawModalRectWithCustomSizedTexture(r_ppButtonX, r_ppButtonY, dx, dy, 20, 20, 64, 64);
|
|
|
|
//Handling the click on the Replay starter
|
|
if(hover && Mouse.isButtonDown(0) && isClick() && FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) {
|
|
if(ReplayHandler.isInPath()) {
|
|
ReplayHandler.interruptReplay();
|
|
} else {
|
|
ReplayHandler.startPath(false);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
private void addPlaceKeyframe() {
|
|
Entity cam = mc.getRenderViewEntity();
|
|
if(cam == null) return;
|
|
ReplayHandler.addKeyframe(new PositionKeyframe(ReplayHandler.getRealTimelineCursor(), new Position(cam.posX, cam.posY, cam.posZ, cam.rotationPitch, cam.rotationYaw, ReplayHandler.getCameraTilt())));
|
|
}
|
|
|
|
private void addTimeKeyframe() {
|
|
ReplayHandler.addKeyframe(new TimeKeyframe(ReplayHandler.getRealTimelineCursor(), ReplayMod.replaySender.currentTimeStamp()));
|
|
}
|
|
|
|
private void zoomIn() {
|
|
if(!isClick()) return;
|
|
this.zoom_scale = Math.max(0.025f, zoom_scale - zoom_steps);
|
|
}
|
|
|
|
private void zoomOut() {
|
|
if(!isClick()) return;
|
|
this.zoom_scale = Math.min(1f, zoom_scale + zoom_steps);
|
|
this.pos_left = Math.min(pos_left, 1f - zoom_scale);
|
|
}
|
|
|
|
private boolean isClick() {
|
|
if(Mouse.isButtonDown(0)) {
|
|
boolean bef = mouseDwn;
|
|
mouseDwn = true;
|
|
return !bef;
|
|
} else {
|
|
mouseDwn = false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private enum MarkerType {
|
|
|
|
ONE_S(1 * 1000, 100),
|
|
FIVE_S(5 * 1000, 1 * 1000),
|
|
QUARTER_M(15 * 1000, 3 * 1000),
|
|
HALF_M(30 * 1000, 5 * 1000),
|
|
ONE_M(60 * 1000, 10 * 1000),
|
|
FIVE_M(5 * 60 * 1000, 50 * 1000);
|
|
|
|
int minimum;
|
|
int small_min;
|
|
int maximum = 10;
|
|
|
|
MarkerType(int minimum, int small_min) {
|
|
this.minimum = minimum;
|
|
this.small_min = small_min;
|
|
}
|
|
|
|
public static MarkerType getMarkerType(float scale, long totalLength) {
|
|
long visible = Math.round((double) totalLength * scale);
|
|
long seconds = visible;
|
|
|
|
for(MarkerType mt : values()) {
|
|
if(seconds / mt.getDistance() <= 10) {
|
|
return mt;
|
|
}
|
|
}
|
|
|
|
return FIVE_M;
|
|
}
|
|
|
|
int getDistance() {
|
|
return minimum;
|
|
}
|
|
|
|
int getSmallDistance() {
|
|
return small_min;
|
|
}
|
|
}
|
|
}
|