Allowed GuiTimeline instances to have any height (instead of fixed 22px height) and updated draw() method accordingly

Added HSV noise to GuiTimeline's textures to somewhat hide the repeating body texture
Implemented GuiTimeline in GuiObjectManager's GuiObjectKeyframeTimeline
Added asInt() method to TimestampValue, to avoid int casts of value field
This commit is contained in:
CrushedPixel
2015-07-10 03:36:57 +02:00
parent 5828b04596
commit 30ebfe96bd
7 changed files with 146 additions and 109 deletions

View File

@@ -3,12 +3,12 @@ package eu.crushedpixel.replaymod.gui;
import eu.crushedpixel.replaymod.assets.CustomImageObject;
import eu.crushedpixel.replaymod.assets.ReplayAsset;
import eu.crushedpixel.replaymod.gui.elements.*;
import eu.crushedpixel.replaymod.gui.elements.listeners.SelectionListener;
import eu.crushedpixel.replaymod.gui.elements.timelines.GuiTimeline;
import eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay;
import eu.crushedpixel.replaymod.interpolation.KeyframeList;
import eu.crushedpixel.replaymod.replay.ReplayHandler;
import eu.crushedpixel.replaymod.utils.MouseUtils;
import lombok.Getter;
import lombok.Setter;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.renderer.GlStateManager;
@@ -44,7 +44,7 @@ public class GuiObjectManager extends GuiScreen {
private GuiTexturedButton zoomInButton, zoomOutButton;
private ComposedElement anchorInputs, positionInputs, scaleInputs, orientationInputs, opacityInputs, numberInputs;
private ComposedElement allElements;
private ComposedElement disableElements, allElements;
private static final int KEYFRAME_BUTTON_X = 80;
private static final int KEYFRAME_BUTTON_Y = 40;
@@ -57,11 +57,11 @@ public class GuiObjectManager extends GuiScreen {
private GuiTexturedButton normal = new GuiTexturedButton(0, x, y, 20, 20,
GuiReplayOverlay.replay_gui, KEYFRAME_BUTTON_X, KEYFRAME_BUTTON_Y,
GuiReplayOverlay.TEXTURE_SIZE, GuiReplayOverlay.TEXTURE_SIZE, new Runnable() {
@Override
public void run() {
addKeyframe(line);
}
},
@Override
public void run() {
addKeyframe(line);
}
},
null);
private GuiTexturedButton selected = new GuiTexturedButton(0, x, y, 20, 20,
@@ -84,6 +84,12 @@ public class GuiObjectManager extends GuiScreen {
return normal;
}
}
@Override
public void setEnabled(boolean enabled) {
selected.setEnabled(enabled);
normal.setEnabled(enabled);
}
};
}
@@ -128,7 +134,7 @@ public class GuiObjectManager extends GuiScreen {
objectList = new GuiEntryList<CustomImageObject>(fontRendererObj, 0, 0, 0, 0);
objectList.setEmptyMessage(I18n.format("replaymod.gui.objects.empty"));
addButton = new GuiAdvancedButton(0, 0, 0, 20, I18n.format("replaymod.gui.add"), new Runnable() {
@Override
public void run() {
@@ -147,6 +153,18 @@ public class GuiObjectManager extends GuiScreen {
nameInput.hint = I18n.format("replaymod.gui.objects.properties.name");
keyframeLists = new KeyframeList[5];
objectList.addSelectionListener(new SelectionListener() {
@Override
public void onSelectionChanged(int selectionIndex) {
CustomImageObject selectedObject = objectList.getElement(selectionIndex);
if(selectedObject != null) {
disableElements.setEnabled(true);
} else {
disableElements.setEnabled(false);
}
}
});
}
String[] labelStrings = new String[] {
@@ -165,6 +183,7 @@ public class GuiObjectManager extends GuiScreen {
}
}
disableElements = new ComposedElement();
allElements = new ComposedElement();
int inputWidth = 40;
@@ -194,30 +213,34 @@ public class GuiObjectManager extends GuiScreen {
child.addPart(button);
child.addPart(label);
allElements.addPart(child);
disableElements.addPart(child);
}
int timelineX = anchorZInput.xPosition + anchorZInput.width + 5;
int timelineY = anchorZInput.yPosition;
int timelineX = anchorZInput.xPosition + anchorZInput.width + 5 - 1;
int timelineY = anchorZInput.yPosition - 1;
int timelineWidth = this.width-10-timelineX;
int timelineHeight = this.height-10-10-timelineY;
int timelineWidth = this.width-10-timelineX + 2;
int timelineHeight = this.height-10-10-timelineY + 2;
objectKeyframeTimeline = new GuiObjectKeyframeTimeline(timelineX, timelineY, timelineWidth, timelineHeight, keyframeLists);
allElements.addPart(objectKeyframeTimeline);
disableElements.addPart(objectKeyframeTimeline);
timelineScrollbar = new GuiScrollbar(timelineX, this.height-15, timelineWidth-19) {
timelineScrollbar = new GuiScrollbar(timelineX, this.height-15, timelineWidth-21) {
@Override
public void dragged() {
objectKeyframeTimeline.setLeftPosition((float)sliderPosition);
objectKeyframeTimeline.timeStart = (float)sliderPosition;
}
};
allElements.addPart(timelineScrollbar);
timelineScrollbar.size = objectKeyframeTimeline.zoom;
timelineScrollbar.sliderPosition = objectKeyframeTimeline.timeStart;
disableElements.addPart(timelineScrollbar);
zoomInButton = GuiReplayOverlay.texturedButton(width - 28, this.height-15, 40, 20, 9, new Runnable() {
@Override
public void run() {
objectKeyframeTimeline.setZoomScale(Math.max(0.025f, objectKeyframeTimeline.getZoomScale() - ZOOM_STEPS));
objectKeyframeTimeline.zoom = Math.max(0.025f, objectKeyframeTimeline.zoom - ZOOM_STEPS);
}
}, "replaymod.gui.ingame.menu.zoomin");
@@ -225,13 +248,13 @@ public class GuiObjectManager extends GuiScreen {
@Override
public void run() {
objectKeyframeTimeline.setZoomScale(Math.min(1f, objectKeyframeTimeline.getZoomScale() + ZOOM_STEPS));
objectKeyframeTimeline.setLeftPosition(Math.min(objectKeyframeTimeline.getLeftPos(), 1f - objectKeyframeTimeline.getZoomScale()));
objectKeyframeTimeline.zoom = Math.min(1f, objectKeyframeTimeline.zoom + ZOOM_STEPS);
objectKeyframeTimeline.timeStart = Math.min(objectKeyframeTimeline.timeStart, 1f - objectKeyframeTimeline.zoom);
}
}, "replaymod.gui.ingame.menu.zoomout");
allElements.addPart(zoomInButton);
allElements.addPart(zoomOutButton);
disableElements.addPart(zoomInButton);
disableElements.addPart(zoomOutButton);
objectList.xPosition = 11;
objectList.yPosition = 11;
@@ -246,7 +269,7 @@ public class GuiObjectManager extends GuiScreen {
nameInput.yPosition = objectList.yPosition;
nameInput.width = objectList.width;
allElements.addPart(nameInput);
disableElements.addPart(nameInput);
dropdownLabel.positionX = (width/2)+5;
int strWidth = fontRendererObj.getStringWidth(I18n.format("replaymod.gui.assets.filechooser")+": ");
@@ -256,8 +279,8 @@ public class GuiObjectManager extends GuiScreen {
dropdownLabel.positionY = assetDropdown.yPosition + 6;
assetDropdown.width = (objectList.width-strWidth-5);
allElements.addPart(dropdownLabel);
allElements.addPart(assetDropdown);
disableElements.addPart(dropdownLabel);
disableElements.addPart(assetDropdown);
addButton.xPosition = nameInput.xPosition;
addButton.width = removeButton.width = nameInput.width/2 - 2;
@@ -267,6 +290,10 @@ public class GuiObjectManager extends GuiScreen {
allElements.addPart(addButton);
allElements.addPart(removeButton);
allElements.addPart(disableElements);
objectList.setSelectionIndex(objectList.getSelectionIndex()); // trigger an event for the SelectionListener
initialized = true;
}
@@ -313,93 +340,50 @@ public class GuiObjectManager extends GuiScreen {
super.mouseReleased(mouseX, mouseY, mouseButton);
}
public class GuiObjectKeyframeTimeline implements GuiElement {
public class GuiObjectKeyframeTimeline extends GuiTimeline {
private KeyframeList[] keyframeLists;
public int x, y, width, height;
@Getter @Setter
private int timestamp;
@Getter @Setter
private float zoomScale;
@Getter @Setter
private float leftPos;
private int timelineLength = 10 * 60 * 1000;
private boolean dragging = false;
public GuiObjectKeyframeTimeline(int x, int y, int width, int height, KeyframeList... keyframeLists) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
super(x, y, width, height);
this.keyframeLists = keyframeLists;
}
public void setLeftPosition(float leftPos) {
this.leftPos = leftPos;
}
private boolean enabled = true;
@Override
public void draw(Minecraft mc, int mouseX, int mouseY) {
drawRect(this.x - 1, this.y - 1, this.x + this.width + 1, this.y + this.height + 1, -6250336);
drawRect(this.x, this.y, this.x + this.width, this.y + this.height, -16777216);
int count = keyframeLists.length;
int i = 0;
for(KeyframeList list : keyframeLists) {
int yPos = (int)(((float)i/count)*(height+2));
int h = (int)(1f/count)*(height+2);
if(i < count)
drawHorizontalLine(x, x+width, y+yPos+h-1, -6250336);
i++;
}
}
@Override
public void drawOverlay(Minecraft mc, int mouseX, int mouseY) {
}
@Override
public boolean isHovering(int mouseX, int mouseY) {
return false;
this.zoom = 0.1;
this.timelineLength = 10 * 60 * 1000;
this.showMarkers = true;
}
@Override
public void mouseClick(Minecraft mc, int mouseX, int mouseY, int button) {
if(!enabled) return;
super.mouseClick(mc, mouseX, mouseY, button);
int time = (int) getTimeAt(mouseX, mouseY);
if(time != -1) {
cursorPosition = time;
dragging = true;
}
}
@Override
public void mouseDrag(Minecraft mc, int mouseX, int mouseY, int button) {
if(!enabled) return;
super.mouseDrag(mc, mouseX, mouseY, button);
if(dragging) {
int time = (int) getTimeAt(mouseX, mouseY);
if(time != -1) cursorPosition = time;
}
}
@Override
public void mouseRelease(Minecraft mc, int mouseX, int mouseY, int button) {
}
@Override
public void buttonPressed(Minecraft mc, int mouseX, int mouseY, char key, int keyCode) {
}
@Override
public void tick(Minecraft mc) {
}
@Override
public void setEnabled(boolean enabled) {
this.enabled = enabled;
if(!enabled) return;
super.mouseRelease(mc, mouseX, mouseY, button);
this.dragging = false;
}
}
}

View File

@@ -23,9 +23,9 @@ public class GuiKeyframeTimeline extends GuiTimeline {
private boolean timeKeyframes;
private boolean placeKeyframes;
public GuiKeyframeTimeline(int positionX, int positionY, int width, boolean showMarkers,
public GuiKeyframeTimeline(int positionX, int positionY, int width, int height, boolean showMarkers,
boolean showPlaceKeyframes, boolean showTimeKeyframes) {
super(positionX, positionY, width);
super(positionX, positionY, width, height);
this.showMarkers = showMarkers;
this.timeKeyframes = showTimeKeyframes;
this.placeKeyframes = showPlaceKeyframes;

View File

@@ -18,8 +18,8 @@ public class GuiMarkerTimeline extends GuiTimeline {
private long clickTime;
private boolean dragging;
public GuiMarkerTimeline(int positionX, int positionY, int width, boolean showMarkers) {
super(positionX, positionY, width);
public GuiMarkerTimeline(int positionX, int positionY, int width, int height, boolean showMarkers) {
super(positionX, positionY, width, height);
this.showMarkers = showMarkers;
}

View File

@@ -16,10 +16,10 @@ import static org.lwjgl.opengl.GL11.glEnable;
public class GuiTimeline extends Gui implements GuiElement {
protected static final int TEXTURE_WIDTH = 64;
protected static final int TEXTURE_HEIGHT = 22;
protected static final int BORDER_TOP = 4;
protected static final int BORDER_BOTTOM = 3;
protected static final int HEIGHT = 22;
protected static final int TEXTURE_X = 64;
protected static final int TEXTURE_Y = 106;
@@ -57,13 +57,15 @@ public class GuiTimeline extends Gui implements GuiElement {
protected final int positionX;
protected final int positionY;
protected final int width;
protected final int height;
protected boolean enabled = true;
public GuiTimeline(int positionX, int positionY, int width) {
public GuiTimeline(int positionX, int positionY, int width, int height) {
this.positionX = positionX;
this.positionY = positionY;
this.width = width;
this.height = height;
}
/**
@@ -76,7 +78,7 @@ public class GuiTimeline extends Gui implements GuiElement {
int left = positionX + BORDER_LEFT;
int right = positionX + width - BORDER_RIGHT;
int bodyWidth = width - BORDER_LEFT - BORDER_RIGHT;
if (mouseX >= left && mouseX <= right && mouseY >= positionY && mouseY <= positionY + HEIGHT) {
if (mouseX >= left && mouseX <= right && mouseY >= positionY && mouseY <= positionY + height) {
double segmentLength = timelineLength * zoom;
double segmentTime = segmentLength * (mouseX - left) / bodyWidth;
return Math.round(timeStart * timelineLength + segmentTime);
@@ -96,14 +98,48 @@ public class GuiTimeline extends Gui implements GuiElement {
int BORDER_LEFT = GuiTimeline.BORDER_LEFT + 1;
int BODY_WIDTH = GuiTimeline.BODY_WIDTH - 1;
// Left border
rect(positionX, positionY, TEXTURE_X, TEXTURE_Y, BORDER_LEFT, HEIGHT);
// Body
for (int i = bodyLeft; i < bodyRight; i += BODY_WIDTH) {
rect(i, positionY, TEXTURE_X + BORDER_LEFT, TEXTURE_Y, Math.min(BODY_WIDTH, bodyRight - i), HEIGHT);
/*
// Upper left border
rect(positionX, positionY, TEXTURE_X, TEXTURE_Y, BORDER_LEFT, BORDER_TOP);
// Lower left border
rect(positionX, positionY+height-BORDER_BOTTOM, TEXTURE_X, TEXTURE_Y+TEXTURE_HEIGHT-BORDER_BOTTOM, BORDER_LEFT, BORDER_BOTTOM);
*/
boolean leftRightDrawn = false;
for (int i = positionX; i < bodyRight; i += BODY_WIDTH) {
int textureX = leftRightDrawn ? TEXTURE_X+BORDER_LEFT : TEXTURE_X;
// Upper border
rect(i, positionY, textureX, TEXTURE_Y, Math.min(BODY_WIDTH, bodyRight - i), BORDER_TOP);
int remaining = height-BORDER_TOP-BORDER_BOTTOM;
int y = positionY + BORDER_TOP;
while(remaining > 0) {
int toDraw = Math.min(remaining, TEXTURE_HEIGHT - BORDER_TOP - BORDER_BOTTOM);
rect(i, y, textureX, TEXTURE_Y+BORDER_TOP, Math.min(BODY_WIDTH, bodyRight - i), Math.min(TEXTURE_HEIGHT-BORDER_TOP-BORDER_BOTTOM, toDraw));
// Right border
if(!leftRightDrawn) {
rect(bodyLeft+bodyWidth, y, TEXTURE_X+TEXTURE_WIDTH-BORDER_RIGHT, TEXTURE_Y+BORDER_TOP, BORDER_RIGHT, Math.min(TEXTURE_HEIGHT-BORDER_TOP-BORDER_BOTTOM, toDraw));
}
y += toDraw;
remaining -= toDraw;
}
// Lower border
rect(i, positionY+height-BORDER_BOTTOM, textureX, TEXTURE_Y+TEXTURE_HEIGHT-BORDER_BOTTOM, Math.min(BODY_WIDTH, bodyRight - i), BORDER_BOTTOM);
leftRightDrawn = true;
}
// Right border
rect(bodyRight, positionY, TEXTURE_X + BORDER_LEFT + BODY_WIDTH, TEXTURE_Y, BORDER_RIGHT, HEIGHT);
// Upper right corner
rect(bodyLeft+bodyWidth, positionY, TEXTURE_X+TEXTURE_WIDTH-BORDER_RIGHT, TEXTURE_Y, BORDER_RIGHT, BORDER_TOP);
// Lower right corner
rect(bodyLeft+bodyWidth, positionY+height-BORDER_BOTTOM, TEXTURE_X+TEXTURE_WIDTH-BORDER_RIGHT, TEXTURE_Y+TEXTURE_HEIGHT-BORDER_BOTTOM, BORDER_RIGHT, BORDER_BOTTOM);
}
long leftTime = Math.round(timeStart * timelineLength);
@@ -111,7 +147,7 @@ public class GuiTimeline extends Gui implements GuiElement {
// Draw markers
if (showMarkers) {
int markerY = positionY + HEIGHT - BORDER_BOTTOM;
int markerY = positionY + height - BORDER_BOTTOM;
MarkerType mt = MarkerType.getMarkerType(zoom, timelineLength);
// Small markers
@@ -152,7 +188,20 @@ public class GuiTimeline extends Gui implements GuiElement {
double fractionOfSegment = positionInSegment / (zoom * timelineLength);
int cursorX = (int) (positionX + BORDER_LEFT + fractionOfSegment * bodyWidth);
rect(cursorX - 2, positionY + BORDER_TOP, 84, 20, 5, 16);
rect(cursorX - 2, positionY + BORDER_TOP-1, 84, 20, 5, 4);
int remaining = height-BORDER_TOP-BORDER_BOTTOM-3;
int y = positionY + BORDER_TOP-1 + 4;
while(remaining > 0) {
int toDraw = Math.min(remaining, 11);
rect(cursorX - 2, y, 84, 24, 5, toDraw);
y += toDraw;
remaining -= toDraw;
}
}
}

View File

@@ -234,9 +234,9 @@ public class GuiReplayOverlay extends Gui {
}, "replaymod.gui.ingame.menu.zoomout");
private final GuiMarkerTimeline timeline = new GuiMarkerTimeline(TIMELINE_X, TOP_ROW - 1, WIDTH - 14 - TIMELINE_X, false);
private final GuiMarkerTimeline timeline = new GuiMarkerTimeline(TIMELINE_X, TOP_ROW - 1, WIDTH - 14 - TIMELINE_X, 22, false);
private final GuiKeyframeTimeline timelineReal = new GuiKeyframeTimeline(TIMELINE_REAL_X, BOTTOM_ROW - 1, TIMELINE_REAL_WIDTH, true, true, true);
private final GuiKeyframeTimeline timelineReal = new GuiKeyframeTimeline(TIMELINE_REAL_X, BOTTOM_ROW - 1, TIMELINE_REAL_WIDTH, 22, true, true, true);
{
timelineReal.timelineLength = 10 * 60 * 1000;
}

View File

@@ -12,6 +12,10 @@ public class TimestampValue implements KeyframeValue {
@Interpolate
public double value;
public int asInt() {
return (int)value;
}
@Override
public TimestampValue newInstance() {
return new TimestampValue();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB