Made calculation of Markers on GuiTimeline dynamic
Changed Real Timeline's Length to 30 minutes (request by multiple users)
This commit is contained in:
@@ -115,7 +115,7 @@ public abstract class GuiEditKeyframe<T extends KeyframeValue> extends GuiScreen
|
||||
|
||||
//Real Time Input
|
||||
int timestamp = keyframe.getRealTimestamp();
|
||||
min = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 30, 0d, 9d, (double)TimestampUtils.timestampToWholeMinutes(timestamp), false, "", 1);
|
||||
min = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 30, 0d, 29d, (double)TimestampUtils.timestampToWholeMinutes(timestamp), false, "", 1);
|
||||
sec = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 25, 0d, 59d, (double)TimestampUtils.getSecondsFromTimestamp(timestamp), false, "", 1);
|
||||
ms = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 35, 0d, 999d, (double)TimestampUtils.getMillisecondsFromTimestamp(timestamp), false, "", 1);
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ public class GuiScrollbar extends Gui implements GuiElement {
|
||||
|
||||
int backgroundBodyWidth = width - BORDER_LEFT - BORDER_RIGHT;
|
||||
int bodyLeft = positionX + SLIDER_BORDER_LEFT;
|
||||
int bodyRight = positionX + (int) Math.round(backgroundBodyWidth * size) - SLIDER_BORDER_RIGHT;
|
||||
int bodyRight = positionX + Math.max(1, (int) Math.round(backgroundBodyWidth * size) - SLIDER_BORDER_RIGHT);
|
||||
|
||||
// Left border
|
||||
rect(positionX, positionY, SLIDER_TEXTURE_X, SLIDER_TEXTURE_Y, SLIDER_BORDER_LEFT, SLIDER_HEIGHT);
|
||||
@@ -172,7 +172,7 @@ public class GuiScrollbar extends Gui implements GuiElement {
|
||||
public boolean isHovering(int mouseX, int mouseY) {
|
||||
int offsetX = getSliderOffsetX();
|
||||
int minX = positionX + offsetX;
|
||||
int maxX = positionX + offsetX + (int) (width * size);
|
||||
int maxX = positionX + offsetX + Math.max(3, (int) (width * size));
|
||||
int minY = positionY + BORDER_TOP;
|
||||
int maxY = minY + SLIDER_HEIGHT;
|
||||
return mouseX >= minX && mouseY >= minY && mouseX < maxX && mouseY < maxY;
|
||||
|
||||
@@ -2,6 +2,9 @@ package eu.crushedpixel.replaymod.gui.elements.timelines;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.gui.elements.GuiElement;
|
||||
import eu.crushedpixel.replaymod.utils.RoundUtils;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Gui;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
@@ -47,6 +50,27 @@ public class GuiTimeline extends Gui implements GuiElement {
|
||||
*/
|
||||
public double zoom = 1;
|
||||
|
||||
/**
|
||||
* The smallest value <code>zoom</code> might have.
|
||||
*/
|
||||
public double minZoom = 0.005;
|
||||
|
||||
/**
|
||||
* The step size of zooming in/out
|
||||
*/
|
||||
public double zoomStep = 0.05;
|
||||
|
||||
/**
|
||||
* Where the more detailed part of the timeline begins
|
||||
*/
|
||||
|
||||
public double detailedZoom = 0.05;
|
||||
|
||||
/**
|
||||
* The step size for the more detailed part of the timeline
|
||||
*/
|
||||
public double smallZoomStep = 0.005;
|
||||
|
||||
/**
|
||||
* Whether to draw markers on the timeline in regular time intervals.
|
||||
* This draws the time at big markers above the timeline. Therefore extra space in negative y direction
|
||||
@@ -154,7 +178,7 @@ public class GuiTimeline extends Gui implements GuiElement {
|
||||
// Draw markers
|
||||
if (showMarkers) {
|
||||
int markerY = positionY + height - BORDER_BOTTOM;
|
||||
MarkerType mt = MarkerType.getMarkerType(zoom, timelineLength);
|
||||
Markers mt = Markers.getMarkers(zoom, timelineLength, bodyWidth);
|
||||
|
||||
// Small markers
|
||||
for (int s = 0; s <= timelineLength; s += mt.smallDistance) {
|
||||
@@ -178,7 +202,7 @@ public class GuiTimeline extends Gui implements GuiElement {
|
||||
|
||||
// Write time above the timeline
|
||||
long sec = Math.round(s / 1000.0);
|
||||
String timestamp = String.format("%02d:%02ds", sec / 60, sec % 60);
|
||||
String timestamp = String.format("%02d:%02d", sec / 60, sec % 60);
|
||||
drawCenteredString(mc.fontRendererObj, timestamp, markerX, positionY - 8, 0xffffffff);
|
||||
}
|
||||
}
|
||||
@@ -217,7 +241,7 @@ public class GuiTimeline extends Gui implements GuiElement {
|
||||
long mouseTime = getTimeAt(mouseX, mouseY);
|
||||
if (mouseTime != -1) {
|
||||
long sec = mouseTime / 1000;
|
||||
String timestamp = String.format("%02d:%02ds", sec / 60, sec % 60);
|
||||
String timestamp = String.format("%02d:%02d", sec / 60, sec % 60);
|
||||
ReplayMod.tooltipRenderer.drawTooltip(mouseX, mouseY, timestamp, null, Color.WHITE);
|
||||
}
|
||||
}
|
||||
@@ -262,34 +286,52 @@ public class GuiTimeline extends Gui implements GuiElement {
|
||||
drawModalRectWithCustomSizedTexture(x, y, u, v, width, height, TEXTURE_SIZE, TEXTURE_SIZE);
|
||||
}
|
||||
|
||||
|
||||
private enum MarkerType {
|
||||
|
||||
ONE_S(1000, 100),
|
||||
FIVE_S(5 * 1000, 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 distance;
|
||||
int smallDistance;
|
||||
|
||||
MarkerType(int minimum, int smallDistance) {
|
||||
this.distance = minimum;
|
||||
this.smallDistance = smallDistance;
|
||||
public void zoomIn() {
|
||||
if(zoom-zoomStep < detailedZoom) {
|
||||
zoom = Math.max(minZoom, zoom - smallZoomStep);
|
||||
timeStart = Math.min(timeStart, 1f - smallZoomStep);
|
||||
} else {
|
||||
zoom = Math.max(minZoom, zoom - zoomStep);
|
||||
timeStart = Math.min(timeStart, 1f - zoomStep);
|
||||
}
|
||||
}
|
||||
|
||||
public static MarkerType getMarkerType(double scale, long totalLength) {
|
||||
long seconds = Math.round(totalLength * scale);
|
||||
public void zoomOut() {
|
||||
if(zoom+smallZoomStep <= detailedZoom) {
|
||||
zoom = Math.min(1, zoom+smallZoomStep);
|
||||
} else {
|
||||
zoom = Math.min(1, zoom+zoomStep);
|
||||
}
|
||||
}
|
||||
|
||||
for(MarkerType mt : values()) {
|
||||
if(seconds / mt.distance <= 10) {
|
||||
return mt;
|
||||
}
|
||||
}
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public static class Markers {
|
||||
|
||||
return FIVE_M;
|
||||
static final int S = 1000;
|
||||
static final int M = 60*1000;
|
||||
|
||||
static final int[] snapNumbers = new int[]{S, 2*S, 5*S, 10*S, 15*S, 20*S, 30*S, M, 2*M,
|
||||
5*M, 10*M, 15*M, 30*M};
|
||||
|
||||
static final int MARKER_DISTANCE = 35;
|
||||
|
||||
int smallDistance;
|
||||
int distance;
|
||||
|
||||
public static Markers getMarkers(double scale, long totalLength, int pixelWidth) {
|
||||
|
||||
//amount of seconds visible on timeline
|
||||
int visible = (int)(scale*totalLength);
|
||||
|
||||
int bigMarkerCount = pixelWidth/MARKER_DISTANCE;
|
||||
|
||||
int bigMarkerDistance = visible / bigMarkerCount;
|
||||
int snap = RoundUtils.getClosestInt(bigMarkerDistance, snapNumbers);
|
||||
|
||||
bigMarkerDistance = RoundUtils.roundToMultiple(bigMarkerDistance, snap);
|
||||
|
||||
return new Markers(bigMarkerDistance/4, bigMarkerDistance);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,9 +48,8 @@ public class GuiReplayOverlay extends Gui {
|
||||
private static final Minecraft mc = Minecraft.getMinecraft();
|
||||
public static final ResourceLocation replay_gui = new ResourceLocation("replaymod", "replay_gui.png");
|
||||
public static final int TEXTURE_SIZE = 128;
|
||||
private static final float ZOOM_STEPS = 0.05f;
|
||||
|
||||
public static final int KEYFRAME_TIMELINE_LENGTH = 10 * 60 * 1000;
|
||||
public static final int KEYFRAME_TIMELINE_LENGTH = 30 * 60 * 1000;
|
||||
|
||||
public static GuiTexturedButton texturedButton(int x, int y, int u, int v, int size, Runnable action, String hoverText) {
|
||||
return new GuiTexturedButton(0, x, y, size, size, replay_gui, u, v, TEXTURE_SIZE, TEXTURE_SIZE, action, I18n.format(hoverText));
|
||||
@@ -228,7 +227,7 @@ public class GuiReplayOverlay extends Gui {
|
||||
private final GuiElement buttonZoomIn = texturedButton(WIDTH - 14 - 9, BOTTOM_ROW, 40, 20, 9, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
zoom_scale = Math.max(0.025f, zoom_scale - ZOOM_STEPS);
|
||||
timelineReal.zoomIn();
|
||||
}
|
||||
}, "replaymod.gui.ingame.menu.zoomin");
|
||||
|
||||
@@ -236,8 +235,7 @@ public class GuiReplayOverlay extends Gui {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
zoom_scale = Math.min(1f, zoom_scale + ZOOM_STEPS);
|
||||
pos_left = Math.min(pos_left, 1f - zoom_scale);
|
||||
timelineReal.zoomOut();
|
||||
}
|
||||
}, "replaymod.gui.ingame.menu.zoomout");
|
||||
|
||||
@@ -252,7 +250,7 @@ public class GuiReplayOverlay extends Gui {
|
||||
private final GuiScrollbar scrollbar = new GuiScrollbar(TIMELINE_REAL_X, BOTTOM_ROW + 22, TIMELINE_REAL_WIDTH) {
|
||||
@Override
|
||||
public void dragged() {
|
||||
pos_left = scrollbar.sliderPosition;
|
||||
timelineReal.timeStart = scrollbar.sliderPosition;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -350,9 +348,6 @@ public class GuiReplayOverlay extends Gui {
|
||||
private final GuiElement content = new ComposedElement(buttonPlayPause, buttonExport, buttonPlace, buttonTime,
|
||||
buttonPlayPausePath, buttonZoomIn, buttonZoomOut, timeline, timelineReal, scrollbar, speedSlider, toolbar);
|
||||
|
||||
private float zoom_scale = 0.1f; //can see 1/10th of the timeline
|
||||
private double pos_left = 0f; //left border of timeline is at 0%
|
||||
|
||||
public boolean isVisible() {
|
||||
return ReplayHandler.isInReplay();
|
||||
}
|
||||
@@ -365,8 +360,8 @@ public class GuiReplayOverlay extends Gui {
|
||||
if(FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) {
|
||||
mc.displayGuiScreen(null);
|
||||
}
|
||||
zoom_scale = 0.1f;
|
||||
pos_left = 0;
|
||||
timelineReal.zoom = 0.1f;
|
||||
timelineReal.timeStart = 0;
|
||||
if (slider) {
|
||||
ReplayHandler.setRealTimelineCursor(0);
|
||||
speedSlider.reset();
|
||||
@@ -386,8 +381,8 @@ public class GuiReplayOverlay extends Gui {
|
||||
private void checkResize() {
|
||||
if (displayWidth != mc.displayWidth || displayHeight != mc.displayHeight) {
|
||||
GuiReplayOverlay other = new GuiReplayOverlay();
|
||||
other.zoom_scale = this.zoom_scale;
|
||||
other.pos_left = this.pos_left;
|
||||
other.timelineReal.zoom = this.timelineReal.zoom;
|
||||
other.timelineReal.timeStart = this.timelineReal.timeStart;
|
||||
other.speedSlider.copyValueFrom(this.speedSlider);
|
||||
|
||||
this.unregister();
|
||||
@@ -560,15 +555,13 @@ public class GuiReplayOverlay extends Gui {
|
||||
}
|
||||
|
||||
// Setup scrollbar and timelines
|
||||
scrollbar.size = zoom_scale;
|
||||
scrollbar.sliderPosition = pos_left;
|
||||
scrollbar.size = timelineReal.zoom;
|
||||
scrollbar.sliderPosition = timelineReal.timeStart;
|
||||
|
||||
timeline.cursorPosition = ReplayMod.replaySender.currentTimeStamp();
|
||||
timeline.timelineLength = ReplayMod.replaySender.replayLength();
|
||||
|
||||
timelineReal.cursorPosition = ReplayHandler.getRealTimelineCursor();
|
||||
timelineReal.zoom = zoom_scale;
|
||||
timelineReal.timeStart = pos_left;
|
||||
|
||||
// Draw all elements
|
||||
content.draw(mc, mouseX, mouseY);
|
||||
|
||||
@@ -4,6 +4,10 @@ import java.text.DecimalFormat;
|
||||
|
||||
public class RoundUtils {
|
||||
|
||||
public static int roundToMultiple(int value, int snap) {
|
||||
return Math.max(snap, (int)Math.round((float)value/snap) * snap);
|
||||
}
|
||||
|
||||
public static double round2Decimals(double val) {
|
||||
return round(val, 2);
|
||||
}
|
||||
@@ -20,4 +24,20 @@ public class RoundUtils {
|
||||
return Double.valueOf(df.format(value));
|
||||
}
|
||||
|
||||
public static int getClosestInt(int base, int[] snap) {
|
||||
int min = Integer.MAX_VALUE;
|
||||
int closest = base;
|
||||
|
||||
for (int v : snap) {
|
||||
final int diff = Math.abs(v - base);
|
||||
|
||||
if (diff < min) {
|
||||
min = diff;
|
||||
closest = v;
|
||||
}
|
||||
}
|
||||
|
||||
return closest;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user