From be4ee42dcbedc8ead1b49a723a53f45887757a37 Mon Sep 17 00:00:00 2001 From: johni0702 Date: Sun, 14 Jun 2015 14:13:03 +0200 Subject: [PATCH] Add GuiTextArea Reorder and add description to GuiUpload --- .../api/replay/holders/Category.java | 9 + .../replaymod/gui/GuiRenderSettings.java | 4 +- .../replaymod/gui/GuiReplaySpeedSlider.java | 10 + .../gui/elements/ComposedElement.java | 14 + .../gui/elements/DelegatingElement.java | 10 + .../gui/elements/GuiAdvancedButton.java | 66 ++ .../gui/elements/GuiAdvancedCheckBox.java | 53 ++ .../gui/elements/GuiAdvancedTextField.java | 86 +++ .../replaymod/gui/elements/GuiElement.java | 4 + .../replaymod/gui/elements/GuiScrollbar.java | 10 + .../replaymod/gui/elements/GuiString.java | 75 +++ .../replaymod/gui/elements/GuiTextArea.java | 615 ++++++++++++++++++ .../gui/elements/GuiTexturedButton.java | 10 + .../replaymod/gui/elements/GuiTimeline.java | 10 + .../gui/elements/GuiToggleButton.java | 13 +- .../replaymod/gui/online/GuiUploadFile.java | 223 ++++--- .../replaymod/registry/KeybindRegistry.java | 9 + .../assets/replaymod/lang/en_US.lang | 1 + 18 files changed, 1112 insertions(+), 110 deletions(-) create mode 100644 src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiAdvancedButton.java create mode 100644 src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiAdvancedCheckBox.java create mode 100644 src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiAdvancedTextField.java create mode 100644 src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiString.java create mode 100644 src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiTextArea.java diff --git a/src/main/java/eu/crushedpixel/replaymod/api/replay/holders/Category.java b/src/main/java/eu/crushedpixel/replaymod/api/replay/holders/Category.java index 51d04754..265e672e 100755 --- a/src/main/java/eu/crushedpixel/replaymod/api/replay/holders/Category.java +++ b/src/main/java/eu/crushedpixel/replaymod/api/replay/holders/Category.java @@ -41,4 +41,13 @@ public enum Category { } return this; } + + public static String[] stringValues() { + String[] values = new String[Category.values().length]; + int i = 0; + for (Category c : Category.values()) { + values[i++] = c.toNiceString(); + } + return values; + } } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiRenderSettings.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiRenderSettings.java index a30a6005..de86b2e7 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiRenderSettings.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiRenderSettings.java @@ -340,9 +340,7 @@ public class GuiRenderSettings extends GuiScreen { if(button instanceof GuiCheckBox) ((GuiCheckBox)button).setIsChecked(!((GuiCheckBox)button).isChecked()); - if(button instanceof GuiToggleButton) { - ((GuiToggleButton)button).toggle(); - } else if(button instanceof GuiColorPicker) { + if(button instanceof GuiColorPicker) { ((GuiColorPicker)button).pickerToggled(); } else { if(button.id == GuiConstants.RENDER_SETTINGS_ENABLE_GREENSCREEN) { diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySpeedSlider.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySpeedSlider.java index 39a568e4..294f105d 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySpeedSlider.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySpeedSlider.java @@ -204,4 +204,14 @@ public class GuiReplaySpeedSlider extends GuiButton implements GuiElement { public void mouseRelease(Minecraft mc, int mouseX, int mouseY, int button) { mouseReleased(mouseX, mouseY); } + + @Override + public void buttonPressed(Minecraft mc, int mouseX, int mouseY, char key, int keyCode) { + + } + + @Override + public void tick(Minecraft mc) { + + } } \ No newline at end of file diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/ComposedElement.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/ComposedElement.java index d3a82d4e..62a9326a 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/elements/ComposedElement.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/ComposedElement.java @@ -53,4 +53,18 @@ public class ComposedElement implements GuiElement { part.mouseRelease(mc, mouseX, mouseY, button); } } + + @Override + public void buttonPressed(Minecraft mc, int mouseX, int mouseY, char key, int keyCode) { + for (GuiElement part : parts) { + part.buttonPressed(mc, mouseX, mouseY, key, keyCode); + } + } + + @Override + public void tick(Minecraft mc) { + for (GuiElement part : parts) { + part.tick(mc); + } + } } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/DelegatingElement.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/DelegatingElement.java index 7bc83e7d..1c46b4f5 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/elements/DelegatingElement.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/DelegatingElement.java @@ -43,4 +43,14 @@ public abstract class DelegatingElement implements GuiElement { public void mouseRelease(Minecraft mc, int mouseX, int mouseY, int button) { delegate().mouseRelease(mc, mouseX, mouseY, button); } + + @Override + public void buttonPressed(Minecraft mc, int mouseX, int mouseY, char key, int keyCode) { + delegate().buttonPressed(mc, mouseX, mouseY, key, keyCode); + } + + @Override + public void tick(Minecraft mc) { + delegate().tick(mc); + } } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiAdvancedButton.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiAdvancedButton.java new file mode 100644 index 00000000..6d8c00f8 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiAdvancedButton.java @@ -0,0 +1,66 @@ +package eu.crushedpixel.replaymod.gui.elements; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; + +public class GuiAdvancedButton extends GuiButton implements GuiElement { + + public GuiAdvancedButton(int x, int y, String buttonText) { + this(0, x, y, buttonText); + } + + public GuiAdvancedButton(int x, int y, int widthIn, int heightIn, String buttonText) { + this(0, x, y, widthIn, heightIn, buttonText); + } + + public GuiAdvancedButton(int id, int x, int y, String buttonText) { + super(id, x, y, buttonText); + } + + public GuiAdvancedButton(int id, int x, int y, int widthIn, int heightIn, String buttonText) { + super(id, x, y, widthIn, heightIn, buttonText); + } + + @Override + public void draw(Minecraft mc, int mouseX, int mouseY) { + drawButton(mc, mouseX, mouseY); + } + + @Override + public void drawOverlay(Minecraft mc, int mouseX, int mouseY) { + + } + + @Override + public boolean isHovering(int mouseX, int mouseY) { + return mouseX >= xPosition + && mouseY >= yPosition + && mouseX < xPosition + width + && mouseY < yPosition + height; + } + + @Override + public void mouseClick(Minecraft mc, int mouseX, int mouseY, int button) { + mousePressed(mc, mouseX, mouseY); + } + + @Override + public void mouseDrag(Minecraft mc, int mouseX, int mouseY, int button) { + + } + + @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) { + + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiAdvancedCheckBox.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiAdvancedCheckBox.java new file mode 100644 index 00000000..7e20b138 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiAdvancedCheckBox.java @@ -0,0 +1,53 @@ +package eu.crushedpixel.replaymod.gui.elements; + +import net.minecraft.client.Minecraft; +import net.minecraftforge.fml.client.config.GuiCheckBox; + +public class GuiAdvancedCheckBox extends GuiCheckBox implements GuiElement { + public GuiAdvancedCheckBox(int xPos, int yPos, String displayString, boolean isChecked) { + super(0, xPos, yPos, displayString, isChecked); + } + + @Override + public void draw(Minecraft mc, int mouseX, int mouseY) { + drawButton(mc, mouseX, mouseY); + } + + @Override + public void drawOverlay(Minecraft mc, int mouseX, int mouseY) { + + } + + @Override + public boolean isHovering(int mouseX, int mouseY) { + return mouseX >= xPosition + && mouseY >= yPosition + && mouseX < xPosition + width + && mouseY < yPosition + height; + } + + @Override + public void mouseClick(Minecraft mc, int mouseX, int mouseY, int button) { + mousePressed(mc, mouseX, mouseY); + } + + @Override + public void mouseDrag(Minecraft mc, int mouseX, int mouseY, int button) { + + } + + @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) { + + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiAdvancedTextField.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiAdvancedTextField.java new file mode 100644 index 00000000..59a5c638 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiAdvancedTextField.java @@ -0,0 +1,86 @@ +package eu.crushedpixel.replaymod.gui.elements; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiTextField; + +import java.awt.*; + +public class GuiAdvancedTextField extends GuiTextField implements GuiElement { + public String hint; + public int hintTextColor = Color.DARK_GRAY.getRGB(); + + private boolean isEnabled = true; + private int disabledTextColor; + + public GuiAdvancedTextField(FontRenderer fontRenderer, int x, int y, int width, int height) { + super(0, fontRenderer, x, y, width, height); + } + + @Override + public void setEnabled(boolean isEnabled) { + this.isEnabled = isEnabled; + super.setEnabled(isEnabled); + } + + @Override + public void setDisabledTextColour(int disabledTextColor) { + this.disabledTextColor = disabledTextColor; + super.setDisabledTextColour(disabledTextColor); + } + + @Override + public void draw(Minecraft mc, int mouseX, int mouseY) { + if (text.isEmpty() && !isFocused()) { + super.setEnabled(false); + super.setDisabledTextColour(hintTextColor); + text = hint; + + drawTextBox(); + + text = ""; + super.setDisabledTextColour(disabledTextColor); + super.setEnabled(isEnabled); + } else { + drawTextBox(); + } + } + + @Override + public void drawOverlay(Minecraft mc, int mouseX, int mouseY) { + + } + + @Override + public boolean isHovering(int mouseX, int mouseY) { + return mouseX >= xPosition + && mouseY >= yPosition + && mouseX < xPosition + width + && mouseY < yPosition + height; + } + + @Override + public void mouseClick(Minecraft mc, int mouseX, int mouseY, int button) { + mouseClicked(mouseX, mouseY, button); + } + + @Override + public void mouseDrag(Minecraft mc, int mouseX, int mouseY, int button) { + + } + + @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) { + textboxKeyTyped(key, keyCode); + } + + @Override + public void tick(Minecraft mc) { + updateCursorCounter(); + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiElement.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiElement.java index 44980e38..e5ed0af0 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiElement.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiElement.java @@ -13,4 +13,8 @@ public interface GuiElement { void mouseDrag(Minecraft mc, int mouseX, int mouseY, int button); void mouseRelease(Minecraft mc, int mouseX, int mouseY, int button); + void buttonPressed(Minecraft mc, int mouseX, int mouseY, char key, int keyCode); + + void tick(Minecraft mc); + } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiScrollbar.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiScrollbar.java index 654abbcf..a41313f5 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiScrollbar.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiScrollbar.java @@ -79,6 +79,16 @@ public class GuiScrollbar extends Gui implements GuiElement { draggingStart = -1; } + @Override + public void buttonPressed(Minecraft mc, int mouseX, int mouseY, char key, int keyCode) { + + } + + @Override + public void tick(Minecraft mc) { + + } + @Override public void draw(Minecraft mc, int mouseX, int mouseY) { GlStateManager.resetColor(); diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiString.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiString.java new file mode 100644 index 00000000..fc5ef248 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiString.java @@ -0,0 +1,75 @@ +package eu.crushedpixel.replaymod.gui.elements; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; + +import java.awt.*; +import java.util.concurrent.Callable; + +public class GuiString extends Gui implements GuiElement { + public int positionX, positionY; + public Color color; + public Callable getContent; + + public GuiString(int positionX, int positionY, Color color, final String content) { + this(positionX, positionY, color, new Callable() { + @Override + public String call() throws Exception { + return content; + } + }); + } + + public GuiString(int positionX, int positionY, Color color, Callable getContent) { + this.positionX = positionX; + this.positionY = positionY; + this.color = color; + this.getContent = getContent; + } + + @Override + public void draw(Minecraft mc, int mouseX, int mouseY) { + String text; + try { + text = getContent.call(); + } catch (Exception e) { + throw new RuntimeException(e); + } + drawString(mc.fontRendererObj, text, positionX, positionY, color.getRGB()); + } + + @Override + public void drawOverlay(Minecraft mc, int mouseX, int mouseY) { + + } + + @Override + public boolean isHovering(int mouseX, int mouseY) { + return false; + } + + @Override + public void mouseClick(Minecraft mc, int mouseX, int mouseY, int button) { + + } + + @Override + public void mouseDrag(Minecraft mc, int mouseX, int mouseY, int button) { + + } + + @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) { + + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiTextArea.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiTextArea.java new file mode 100644 index 00000000..63b75036 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiTextArea.java @@ -0,0 +1,615 @@ +/* + * Copyright (c) 2015 johni0702 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package eu.crushedpixel.replaymod.gui.elements; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.util.ChatAllowedCharacters; +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.GL11; + +import java.util.Arrays; + +import static net.minecraft.client.renderer.GlStateManager.*; +import static net.minecraft.util.MathHelper.clamp_int; + +public class GuiTextArea extends Gui implements GuiElement { + + // Constants + protected static final int BORDER = 4; + private static int LINE_SPACING = 2; + + // General + protected final FontRenderer fontRenderer; + protected final int guiId; + public boolean enabled = true; + public boolean alwaysFocused; + + // Geometry + public int positionX; + public int positionY; + private int width; + private int height; + + // Content + private final int maxTextWidth; + private final int maxTextHeight; + + private String[] text = {""}; + private boolean isFocused; + private int cursorX; + private int cursorY; + private int selectionX; + private int selectionY; + + // Rendering + private int currentXOffset; + private int currentYOffset; + private int blinkCursorTick; + public int textColorEnabled = 0xE0E0E0; + public int textColorDisabled = 0x707070; + + + public GuiTextArea(FontRenderer fontRenderer, int positionX, int positionY, int width, int height, + int maxTextWidth, int maxTextHeight) { + this(0, fontRenderer, positionX, positionY, width, height, maxTextWidth, maxTextHeight); + } + + public GuiTextArea(int guiId, FontRenderer fontRenderer, int positionX, int positionY, int width, int height, + int maxTextWidth, int maxTextHeight) { + this.guiId = guiId; + this.fontRenderer = fontRenderer; + this.positionX = positionX; + this.positionY = positionY; + this.width = width; + this.height = height; + this.maxTextWidth = maxTextWidth; + this.maxTextHeight = maxTextHeight; + } + + public void setText(String[] lines) { + if (lines.length > maxTextHeight) { + lines = Arrays.copyOf(lines, maxTextHeight); + } + this.text = lines; + for (int i = 0; i < lines.length; i++) { + if (lines[i].length() > maxTextWidth) { + lines[i] = lines[i].substring(0, maxTextWidth); + } + } + } + + public String[] getText() { + return this.text; + } + + public String getText(int fromX, int fromY, int toX, int toY) { + StringBuilder sb = new StringBuilder(); + if (fromY == toY) { + sb.append(text[fromY].substring(fromX, toX)); + } else { + sb.append(text[fromY].substring(fromX)).append('\n'); + for (int y = fromY + 1; y < toY; y++) { + sb.append(text[y]).append('\n'); + } + sb.append(text[toY].substring(0, toX)); + } + return sb.toString(); + } + + private void deleteText(int fromX, int fromY, int toX, int toY) { + String[] newText = new String[text.length - (toY - fromY)]; + if (fromY > 0) { + System.arraycopy(text, 0, newText, 0, fromY); + } + + newText[fromY] = text[fromY].substring(0, fromX) + text[toY].substring(toX); + + if (toY + 1 < text.length) { + System.arraycopy(text, toY + 1, newText, fromY + 1, text.length - toY - 1); + } + text = newText; + } + + public int getSelectionFromX() { + if (cursorY == selectionY) { + return cursorX > selectionX ? selectionX : cursorX; + } + return cursorY > selectionY ? selectionX : cursorX; + } + + public int getSelectionToX() { + if (cursorY == selectionY) { + return cursorX > selectionX ? cursorX : selectionX; + } + return cursorY > selectionY ? cursorX : selectionX; + } + + public int getSelectionFromY() { + return cursorY > selectionY ? selectionY : cursorY; + } + + public int getSelectionToY() { + return cursorY > selectionY ? cursorY : selectionY; + } + + public String getSelectedText() { + if (cursorX == selectionX && cursorY == selectionY) { + return ""; + } + int fromX = getSelectionFromX(); + int fromY = getSelectionFromY(); + int toX = getSelectionToX(); + int toY = getSelectionToY(); + return getText(fromX, fromY, toX, toY); + } + + public void deleteSelectedText() { + if (cursorX == selectionX && cursorY == selectionY) { + return; + } + int fromX = getSelectionFromX(); + int fromY = getSelectionFromY(); + int toX = getSelectionToX(); + int toY = getSelectionToY(); + deleteText(fromX, fromY, toX, toY); + cursorX = selectionX = fromX; + cursorY = selectionY = fromY; + updateCurrentXOffset(); + updateCurrentYOffset(); + } + + private void updateCurrentXOffset() { + currentXOffset = Math.min(currentXOffset, cursorX); + String line = text[cursorY].substring(currentXOffset, cursorX); + int currentWidth = fontRenderer.getStringWidth(line); + if (currentWidth > width - BORDER * 2) { + currentXOffset = cursorX - fontRenderer.trimStringToWidth(line, width - BORDER * 2, true).length(); + } + } + + private void updateCurrentYOffset() { + currentYOffset = Math.min(currentYOffset, cursorY); + int lineHeight = fontRenderer.FONT_HEIGHT + LINE_SPACING; + int contentHeight = height - BORDER * 2; + int maxLines = contentHeight / lineHeight; + if (cursorY - currentYOffset >= maxLines) { + currentYOffset = cursorY - maxLines + 1; + } + } + + public String cutSelectedText() { + String selection = getSelectedText(); + deleteSelectedText(); + return selection; + } + + public void writeText(String append) { + for (char c : append.toCharArray()) { + writeChar(c); + } + } + + public void writeChar(char c) { + if (!ChatAllowedCharacters.isAllowedCharacter(c) && c != '\n') { + return; + } + + deleteSelectedText(); + + if (c == '\n') { + if (text.length >= maxTextHeight) { + return; + } + String[] newText = new String[text.length + 1]; + if (cursorY > 0) { + System.arraycopy(text, 0, newText, 0, cursorY); + } + + newText[cursorY] = text[cursorY].substring(0, cursorX); + newText[cursorY + 1] = text[cursorY].substring(cursorX); + + if (cursorY + 1 < text.length) { + System.arraycopy(text, cursorY + 1, newText, cursorY + 1, text.length - cursorY - 1); + } + text = newText; + selectionX = cursorX = 0; + selectionY = ++cursorY; + updateCurrentYOffset(); + } else { + String line = text[cursorY]; + if (line.length() >= maxTextWidth) { + return; + } + + line = line.substring(0, cursorX) + c + line.substring(cursorX); + text[cursorY] = line; + selectionX = ++cursorX; + } + updateCurrentXOffset(); + } + + private void deleteNextChar() { + String line = text[cursorY]; + if (cursorX < line.length()) { + line = line.substring(0, cursorX) + line.substring(cursorX + 1); + text[cursorY] = line; + } else if (cursorY + 1 < text.length) { + deleteText(cursorX, cursorY, 0, cursorY + 1); + } + } + + private int getNextWordLength() { + int length = 0; + String line = text[cursorY]; + boolean inWord = true; + for (int i = cursorX; i < line.length(); i++) { + if (inWord) { + if (line.charAt(i) == ' ') { + inWord = false; + } + } else { + if (line.charAt(i) != ' ') { + return length; + } + } + length++; + } + return length; + } + + private void deleteNextWord() { + int worldLength = getNextWordLength(); + if (worldLength == 0) { + deleteNextChar(); + } else { + deleteText(cursorX, cursorY, cursorX + worldLength, cursorY); + } + } + + private void deletePreviousChar() { + if (cursorX > 0) { + String line = text[cursorY]; + line = line.substring(0, cursorX - 1) + line.substring(cursorX); + selectionX = --cursorX; + text[cursorY] = line; + } else if (cursorY > 0) { + int fromX = text[cursorY - 1].length(); + deleteText(fromX, cursorY - 1, cursorX, cursorY); + selectionX = cursorX = fromX; + selectionY = --cursorY; + } + updateCurrentXOffset(); + } + + private int getPreviousWordLength() { + int length = 0; + String line = text[cursorY]; + boolean inWord = false; + for (int i = cursorX - 1; i >= 0; i--) { + if (inWord) { + if (line.charAt(i) == ' ') { + return length; + } + } else { + if (line.charAt(i) != ' ') { + inWord = true; + } + } + length++; + } + return length; + } + + private void deletePreviousWord() { + int worldLength = getPreviousWordLength(); + if (worldLength == 0) { + deletePreviousChar(); + } else { + deleteText(cursorX, cursorY, cursorX - worldLength, cursorY); + selectionX = cursorX -= worldLength; + updateCurrentXOffset(); + } + } + + + + public void setCursorPosition(int x, int y) { + selectionY = cursorY = clamp_int(y, 0, text.length - 1); + selectionX = cursorX = clamp_int(x, 0, text[cursorY].length()); + updateCurrentXOffset(); + updateCurrentYOffset(); + } + + public void setFocused(boolean isFocused) { + isFocused |= alwaysFocused; + if (isFocused && !this.isFocused) { + this.blinkCursorTick = 0; // Restart blinking to indicate successful focus + } + + this.isFocused = isFocused; + } + + public boolean isFocused() { + return isFocused || alwaysFocused; + } + + @Override + public void draw(Minecraft mc, int mouseX, int mouseY) { + // Draw black rect once pixel smaller than gray rect + drawRect(positionX, positionY, positionX + width, positionY + height, 0xffa0a0a0); + drawRect(positionX + 1, positionY + 1, positionX + width - 1, positionY + height - 1, 0xff000000); + + int textColor = this.enabled ? textColorEnabled : textColorDisabled; + + int lineHeight = fontRenderer.FONT_HEIGHT + LINE_SPACING; + int contentHeight = height - BORDER * 2; + int maxLines = contentHeight / lineHeight; + int contentWidth = width - BORDER * 2; + + // Draw lines + for (int i = 0; i < maxLines && i + currentYOffset < text.length; i++) { + int lineY = i + currentYOffset; + String line = text[lineY]; + int leftTrimmed = 0; + if (lineY == cursorY) { + line = line.substring(currentXOffset); + leftTrimmed = currentXOffset; + } + line = fontRenderer.trimStringToWidth(line, contentWidth); + + // Draw line + int posY = positionY + BORDER + i * lineHeight; + int lineEnd = fontRenderer.drawStringWithShadow(line, positionX + BORDER, posY, textColor); + + // Draw selection + int fromX = getSelectionFromX(); + int fromY = getSelectionFromY(); + int toX = getSelectionToX(); + int toY = getSelectionToY(); + if (lineY > fromY && lineY < toY) { // Whole line selected + invertColors(lineEnd, posY - 1 + lineHeight, positionX + BORDER, posY - 1); + } else if (lineY == fromY && lineY == toY) { // Part of line selected + String leftStr = line.substring(0, clamp_int(fromX - leftTrimmed, 0, line.length())); + String rightStr = line.substring(clamp_int(toX - leftTrimmed, 0, line.length())); + int left = positionX + BORDER + fontRenderer.getStringWidth(leftStr); + int right = lineEnd - fontRenderer.getStringWidth(rightStr) - 1; + invertColors(right, posY - 1 + lineHeight, left, posY - 1); + } else if (lineY == fromY) { // End of line selected + String rightStr = line.substring(clamp_int(fromX - leftTrimmed, 0, line.length())); + invertColors(lineEnd, posY - 1 + lineHeight, lineEnd - fontRenderer.getStringWidth(rightStr), posY - 1); + } else if (lineY == toY) { // Beginning of line selected + String leftStr = line.substring(0, clamp_int(toX - leftTrimmed, 0, line.length())); + int right = positionX + BORDER + fontRenderer.getStringWidth(leftStr); + invertColors(right, posY - 1 + lineHeight, positionX + BORDER, posY - 1); + } + + // Draw cursor + if (lineY == cursorY && blinkCursorTick / 6 % 2 == 0 && isFocused) { + String beforeCursor = line.substring(0, cursorX - leftTrimmed); + int posX = positionX + BORDER + fontRenderer.getStringWidth(beforeCursor); + if (cursorX == text[lineY].length()) { + fontRenderer.drawStringWithShadow("_", posX, posY, 0xfff0f0f0); + } else { + drawRect(posX, posY - 1, posX + 1, posY + 1 + fontRenderer.FONT_HEIGHT, 0xfff0f0f0); + } + } + } + } + + private void invertColors(int right, int bottom, int left, int top) { + color(0, 0, 255, 255); + disableTexture2D(); + enableColorLogic(); + colorLogicOp(GL11.GL_OR_REVERSE); + + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer renderer = tessellator.getWorldRenderer(); + renderer.startDrawingQuads(); + renderer.addVertex(right, top, 0); + renderer.addVertex(left, top, 0); + renderer.addVertex(left, bottom, 0); + renderer.addVertex(right, bottom, 0); + tessellator.draw(); + + disableColorLogic(); + enableTexture2D(); + } + + @Override + public void drawOverlay(Minecraft mc, int mouseX, int mouseY) { + + } + + @Override + public boolean isHovering(int mouseX, int mouseY) { + return mouseX >= positionX + && mouseY >= positionY + && mouseX < positionX + width + && mouseY < positionY + height; + } + + @Override + public void mouseClick(Minecraft mc, int mouseX, int mouseY, int button) { + boolean hovering = isHovering(mouseX, mouseY); + + if (hovering && isFocused() && button == 0) { + mouseX -= positionX + BORDER; + mouseY -= positionY + BORDER; + int textY = clamp_int(mouseY / (fontRenderer.FONT_HEIGHT + LINE_SPACING) + currentYOffset, 0, text.length - 1); + if (cursorY != textY) { + currentXOffset = 0; + } + String line = text[textY].substring(currentXOffset); + int textX = fontRenderer.trimStringToWidth(line, mouseX).length() + currentXOffset; + setCursorPosition(textX, textY); + } + + setFocused(hovering); + } + + @Override + public void mouseDrag(Minecraft mc, int mouseX, int mouseY, int button) { + + } + + @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) { + if (!this.isFocused) { + return; + } + + if (GuiScreen.isCtrlKeyDown()) { + switch (keyCode) { + case Keyboard.KEY_A: // Select all + cursorX = cursorY = 0; + selectionY = text.length - 1; + selectionX = text[selectionY].length(); + updateCurrentXOffset(); + updateCurrentYOffset(); + return; + case Keyboard.KEY_C: // Copy + GuiScreen.setClipboardString(getSelectedText()); + return; + case Keyboard.KEY_V: // Paste + if (enabled) { + writeText(GuiScreen.getClipboardString()); + } + return; + case Keyboard.KEY_X: // Cut + if (enabled) { + GuiScreen.setClipboardString(cutSelectedText()); + } + return; + } + } + + boolean words = GuiScreen.isCtrlKeyDown(); + boolean select = GuiScreen.isShiftKeyDown(); + switch (keyCode) { + case Keyboard.KEY_HOME: + cursorX = 0; + break; + case Keyboard.KEY_END: + cursorX = text[cursorY].length(); + break; + case Keyboard.KEY_LEFT: + if (cursorX == 0) { + if (cursorY > 0) { + cursorY--; + cursorX = text[cursorY].length(); + } + } else { + if (words) { + cursorX -= getPreviousWordLength(); + } else { + cursorX--; + } + } + break; + case Keyboard.KEY_RIGHT: + if (cursorX == text[cursorY].length()) { + if (cursorY < text.length - 1) { + cursorY++; + cursorX = 0; + } + } else { + if (words) { + cursorX += getNextWordLength(); + } else { + cursorX++; + } + } + break; + case Keyboard.KEY_UP: + if (cursorY > 0) { + cursorY--; + cursorX = Math.min(cursorX, text[cursorY].length()); + } + break; + case Keyboard.KEY_DOWN: + if (cursorY + 1 < text.length) { + cursorY++; + cursorX = Math.min(cursorX, text[cursorY].length()); + } + break; + case Keyboard.KEY_BACK: + if (enabled) { + if (getSelectedText().length() > 0) { + deleteSelectedText(); + } else if (words) { + deletePreviousWord(); + } else { + deletePreviousChar(); + } + } + return; + case Keyboard.KEY_DELETE: + if (enabled) { + if (getSelectedText().length() > 0) { + deleteSelectedText(); + } else if (words) { + deleteNextWord(); + } else { + deleteNextChar(); + } + } + return; + default: + if (enabled) { + if (key == '\r') { + key = '\n'; + } + writeChar(key); + } + return; + } + + updateCurrentXOffset(); + updateCurrentYOffset(); + + if (!select) { + selectionX = cursorX; + selectionY = cursorY; + } + } + + @Override + public void tick(Minecraft mc) { + blinkCursorTick++; + } + + public void setWidth(int width) { + this.width = width; + updateCurrentXOffset(); + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiTexturedButton.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiTexturedButton.java index ba47b1a1..02343e4f 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiTexturedButton.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiTexturedButton.java @@ -85,6 +85,16 @@ public class GuiTexturedButton extends GuiButton implements GuiElement { } + @Override + public void buttonPressed(Minecraft mc, int mouseX, int mouseY, char key, int keyCode) { + + } + + @Override + public void tick(Minecraft mc) { + + } + public void performAction() { action.run(); } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiTimeline.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiTimeline.java index a602398e..399c5155 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiTimeline.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiTimeline.java @@ -189,6 +189,16 @@ public class GuiTimeline extends Gui implements GuiElement { } + @Override + public void buttonPressed(Minecraft mc, int mouseX, int mouseY, char key, int keyCode) { + + } + + @Override + public void tick(Minecraft mc) { + + } + protected void rect(int x, int y, int u, int v, int width, int height) { Minecraft.getMinecraft().renderEngine.bindTexture(replay_gui); glEnable(GL_BLEND); diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiToggleButton.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiToggleButton.java index 3c14af22..ca66d04e 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiToggleButton.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiToggleButton.java @@ -1,8 +1,8 @@ package eu.crushedpixel.replaymod.gui.elements; -import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.Minecraft; -public class GuiToggleButton extends GuiButton { +public class GuiToggleButton extends GuiAdvancedButton { private String baseText; private String[] values; @@ -20,6 +20,15 @@ public class GuiToggleButton extends GuiButton { this.displayString = baseText+values[value]; } + @Override + public boolean mousePressed(Minecraft mc, int mouseX, int mouseY) { + boolean success = super.mousePressed(mc, mouseX, mouseY); + if (success) { + toggle(); + } + return success; + } + public void toggle() { value++; if(value >= values.length) value = 0; diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiUploadFile.java b/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiUploadFile.java index 8ef43444..1f81882c 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiUploadFile.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiUploadFile.java @@ -4,12 +4,14 @@ import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.api.replay.FileUploader; import eu.crushedpixel.replaymod.api.replay.holders.Category; import eu.crushedpixel.replaymod.gui.GuiConstants; -import eu.crushedpixel.replaymod.gui.elements.GuiProgressBar; +import eu.crushedpixel.replaymod.gui.elements.*; import eu.crushedpixel.replaymod.gui.replayviewer.GuiReplayViewer; import eu.crushedpixel.replaymod.online.authentication.AuthenticationHandler; import eu.crushedpixel.replaymod.recording.ReplayMetaData; +import eu.crushedpixel.replaymod.registry.KeybindRegistry; import eu.crushedpixel.replaymod.registry.ResourceHelper; import eu.crushedpixel.replaymod.utils.ImageUtils; +import eu.crushedpixel.replaymod.utils.MouseUtils; import eu.crushedpixel.replaymod.utils.ReplayFile; import eu.crushedpixel.replaymod.utils.ReplayFileIO; import net.minecraft.client.Minecraft; @@ -19,8 +21,8 @@ import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiTextField; import net.minecraft.client.renderer.texture.DynamicTexture; import net.minecraft.client.resources.I18n; +import net.minecraft.client.settings.GameSettings; import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fml.client.config.GuiCheckBox; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.apache.logging.log4j.LogManager; @@ -33,9 +35,10 @@ import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.Callable; import java.util.regex.Pattern; public class GuiUploadFile extends GuiScreen { @@ -48,20 +51,30 @@ public class GuiUploadFile extends GuiScreen { private final ResourceLocation textureResource; private DynamicTexture dynTex = null; - private GuiTextField fileTitleInput, fileTitlePlaceholder, tagInput, messageTextField, tagPlaceholder; - private GuiCheckBox hideServerIP; - private GuiButton categoryButton, startUploadButton, cancelUploadButton, backButton; + private boolean initialized; + + private int columnWidth, columnLeft, columnMiddle, columnRight; + + private GuiAdvancedTextField name, tags; + private GuiToggleButton category; + private GuiString serverIP, duration; + private GuiAdvancedCheckBox hideServerIP; + private GuiTextArea description; + + private ComposedElement content; + + private GuiTextField messageTextField; + private GuiButton startUploadButton, cancelUploadButton, backButton; private GuiProgressBar progressBar; private File replayFile; private ReplayMetaData metaData; private BufferedImage thumb; + private boolean hasThumbnail; private FileUploader uploader = new FileUploader(); - private Category category = Category.MINIGAME; - private GuiReplayViewer parent; private boolean lockUploadButton = false; @@ -86,6 +99,7 @@ public class GuiUploadFile extends GuiScreen { BufferedImage img = archive.thumb().get(); if(img != null) { thumb = ImageUtils.scaleImage(img, new Dimension(1280, 720)); + hasThumbnail = true; } archive.close(); @@ -131,43 +145,77 @@ public class GuiUploadFile extends GuiScreen { return; } - if(fileTitleInput == null) { - fileTitleInput = new GuiTextField(GuiConstants.UPLOAD_NAME_INPUT, fontRendererObj, (this.width / 2) + 20 + 10, 21, Math.min(200, this.width - 20 - 260), 20); - String fname = FilenameUtils.getBaseName(replayFile.getAbsolutePath()); - fileTitleInput.setText(fname); - fileTitleInput.setMaxStringLength(30); - } else { - fileTitleInput.xPosition = (this.width / 2) + 20 + 10; - fileTitleInput.width = Math.min(200, this.width - 20 - 260); - } + if (!initialized) { + initialized = true; - if(fileTitlePlaceholder == null) { - fileTitlePlaceholder = new GuiTextField(GuiConstants.UPLOAD_NAME_PLACEHOLDER, fontRendererObj, fileTitleInput.xPosition, fileTitleInput.yPosition, fileTitleInput.width, 20); - fileTitlePlaceholder.setTextColor(Color.DARK_GRAY.getRGB()); - fileTitlePlaceholder.setText(I18n.format("replaymod.gui.upload.namehint")); - } else { - fileTitlePlaceholder.xPosition = fileTitleInput.xPosition; - fileTitlePlaceholder.width = fileTitleInput.width; - } + int y = 20; - if(hideServerIP == null) { - hideServerIP = new GuiCheckBox(GuiConstants.UPLOAD_HIDE_SERVER_IP, 0, 80, I18n.format("replaymod.gui.upload.hideip"), false); + name = new GuiAdvancedTextField(fontRendererObj, 0, y, 0, 20); + name.hint = I18n.format("replaymod.gui.upload.namehint"); + name.text = FilenameUtils.getBaseName(replayFile.getAbsolutePath()); + name.setMaxStringLength(30); + y+=25; + + int secs = metaData.getDuration() / 1000; + String durationString = I18n.format("replaymod.gui.duration") + String.format(": %02dm%02ds", secs / 60, secs % 60); + duration = new GuiString(0, y, Color.WHITE, durationString); + y+=15; + + hideServerIP = new GuiAdvancedCheckBox(0, y, I18n.format("replaymod.gui.upload.hideip"), false); hideServerIP.enabled = !metaData.isSingleplayer(); + y+=15; + + serverIP = new GuiString(0, y, Color.GRAY, new Callable() { + @Override + public String call() throws Exception { + if (hideServerIP.isChecked()){ + return I18n.format("replaymod.gui.iphidden"); + } else { + return metaData.getServerName(); + } + } + }); + y+=15; + + category = new GuiToggleButton(0, 0, y, I18n.format("replaymod.category") + ": ", Category.stringValues()); + y+=25; + + tags = new GuiAdvancedTextField(fontRendererObj, 0, y, 0, 20); + tags.setMaxStringLength(30); + tags.hint = I18n.format("replaymod.gui.upload.tagshint"); + y+=20; + + description = new GuiTextArea(fontRendererObj, 0, name.yPosition, 0, y - name.yPosition, 30, 15); } - if(hideServerIP.enabled) { - hideServerIP.xPosition = (this.width / 2) + 20 + 9; - buttonList.add(hideServerIP); - } + columnWidth = Math.min(200, (width - 60) / 3); + columnLeft = width / 2 - columnWidth / 2 * 3 - 10; + columnMiddle = width / 2 - columnWidth / 2; + columnRight = width / 2 + columnWidth / 2 + 10; - if(categoryButton == null) { - categoryButton = new GuiButton(GuiConstants.UPLOAD_CATEGORY_BUTTON, (this.width / 2) + 20 + 10 - 1, 95, I18n.format("replaymod.category")+": " + category.toNiceString()); - categoryButton.width = Math.min(202, this.width - 20 - 260 + 2); - } else { - categoryButton.xPosition = (this.width / 2) + 20 + 10 - 1; - } + name.xPosition = columnLeft; + name.width = columnWidth; - buttonList.add(categoryButton); + duration.positionX = columnLeft; + hideServerIP.xPosition = columnLeft - 1; + serverIP.positionX = columnLeft; + + category.xPosition = columnLeft - 1; + category.width = columnWidth + 2; + + tags.xPosition = columnLeft; + tags.width = columnWidth; + + description.positionX = columnMiddle; + description.setWidth(columnWidth); + + List elements = new ArrayList(Arrays.asList( + name, category, tags, description, serverIP, duration + )); + if (!metaData.isSingleplayer()) { + elements.add(hideServerIP); + } + content = new ComposedElement(elements.toArray(new GuiElement[elements.size()])); if(startUploadButton == null) { List bottomBar = new ArrayList(); @@ -228,23 +276,6 @@ public class GuiUploadFile extends GuiScreen { messageTextField.width = width - 40; } - if(tagInput == null) { - tagInput = new GuiTextField(GuiConstants.UPLOAD_TAG_INPUT, fontRendererObj, (this.width / 2) + 20 + 10, categoryButton.yPosition + 20 + 5, Math.min(200, this.width - 20 - 260), 20); - tagInput.setMaxStringLength(30); - } else { - tagInput.xPosition = (this.width / 2) + 20 + 10; - tagInput.width = Math.min(200, this.width - 20 - 260); - } - - if(tagPlaceholder == null) { - tagPlaceholder = new GuiTextField(GuiConstants.UPLOAD_TAG_PLACEHOLDER, fontRendererObj, (this.width / 2) + 20 + 10, tagInput.yPosition, Math.min(200, this.width - 20 - 260), 20); - tagPlaceholder.setTextColor(Color.DARK_GRAY.getRGB()); - tagPlaceholder.setText(I18n.format("replaymod.gui.upload.tagshint")); - } else { - tagPlaceholder.xPosition = (this.width / 2) + 20 + 10; - tagPlaceholder.width = Math.min(200, this.width - 20 - 260); - } - if(progressBar == null) { progressBar = new GuiProgressBar(19, height - 52, width - (2*19), 15); } else { @@ -257,18 +288,15 @@ public class GuiUploadFile extends GuiScreen { @Override protected void actionPerformed(GuiButton button) throws IOException { if(!button.enabled) return; - if(button.id == GuiConstants.UPLOAD_CATEGORY_BUTTON) { - category = category.next(); - categoryButton.displayString = I18n.format("replaymod.category")+": " + category.toNiceString(); - } else if(button.id == GuiConstants.UPLOAD_BACK_BUTTON) { + if(button.id == GuiConstants.UPLOAD_BACK_BUTTON) { mc.displayGuiScreen(parent); } else if(button.id == GuiConstants.UPLOAD_START_BUTTON) { - final String name = fileTitleInput.getText().trim(); + final String name = this.name.getText().trim(); new Thread(new Runnable() { @Override public void run() { try { - String tagsRaw = tagInput.getText(); + String tagsRaw = tags.getText(); String[] split = tagsRaw.split(","); List tags = new ArrayList(); for(String str : split) { @@ -277,6 +305,7 @@ public class GuiUploadFile extends GuiScreen { } } + Category category = Category.values()[GuiUploadFile.this.category.getValue()]; if(hideServerIP.isChecked()) { File tmp = File.createTempFile("replay_hidden_ip", "mcpr"); File tmpMeta = File.createTempFile("metadata", "json"); @@ -316,16 +345,6 @@ public class GuiUploadFile extends GuiScreen { public void drawScreen(int mouseX, int mouseY, float partialTicks) { this.drawDefaultBackground(); - String durationString = I18n.format("replaymod.gui.duration") + ": " + String.format("%02dm%02ds", - TimeUnit.MILLISECONDS.toMinutes(metaData.getDuration()), - TimeUnit.MILLISECONDS.toSeconds(metaData.getDuration()) - - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(metaData.getDuration())) - ); - - drawString(fontRendererObj, durationString, (this.width / 2) + 20 + 10, 50, Color.WHITE.getRGB()); - drawString(fontRendererObj, hideServerIP.isChecked() ? I18n.format("replaymod.gui.iphidden") : metaData.getServerName(), - (this.width / 2) + 20 + 10, 65, Color.GRAY.getRGB()); - drawCenteredString(fontRendererObj, I18n.format("replaymod.gui.upload.title"), this.width / 2, 5, Color.WHITE.getRGB()); //Draw thumbnail @@ -338,42 +357,37 @@ public class GuiUploadFile extends GuiScreen { } mc.getTextureManager().bindTexture(textureResource); //Will be freed by the ResourceHelper - int wid = (this.width) / 2; - int hei = Math.round(wid * (720f / 1280f)); - Gui.drawScaledCustomSizeModalRect(19, 20, 0, 0, 1280, 720, wid, hei, 1280, 720); - } + int height = columnWidth * 720 / 1280; + Gui.drawScaledCustomSizeModalRect(columnRight, 20, 0, 0, 1280, 720, columnWidth, height, 1280, 720); - if(fileTitleInput.getText().length() > 0 || fileTitleInput.isFocused()) { - fileTitleInput.drawTextBox(); - } else { - fileTitlePlaceholder.drawTextBox(); + if (!hasThumbnail) { + String str = I18n.format("replaymod.gui.upload.nothumbnail", + GameSettings.getKeyDisplayString(KeybindRegistry.getKeyBinding(KeybindRegistry.KEY_THUMBNAIL).getKeyCode())); + int y = 20 + height + 10; + fontRendererObj.drawSplitString(str, columnRight, y, columnWidth, Color.RED.getRGB()); + } } messageTextField.drawTextBox(); - if(tagInput.getText().length() > 0 || tagInput.isFocused()) { - tagInput.drawTextBox(); - } else { - tagPlaceholder.drawTextBox(); - } - super.drawScreen(mouseX, mouseY, partialTicks); progressBar.setProgress(uploader.getUploadProgress()); progressBar.drawProgressBar(); + + content.draw(mc, mouseX, mouseY); + content.drawOverlay(mc, mouseX, mouseY); } @Override public void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { super.mouseClicked(mouseX, mouseY, mouseButton); - fileTitleInput.mouseClicked(mouseX, mouseY, mouseButton); - tagInput.mouseClicked(mouseX, mouseY, mouseButton); + content.mouseClick(mc, mouseX, mouseY, mouseButton); } @Override public void updateScreen() { - fileTitleInput.updateCursorCounter(); - tagInput.updateCursorCounter(); + content.tick(mc); } @Override @@ -385,11 +399,8 @@ public class GuiUploadFile extends GuiScreen { @Override protected void keyTyped(char typedChar, int keyCode) throws IOException { - if(fileTitleInput.isFocused()) { - fileTitleInput.textboxKeyTyped(typedChar, keyCode); - } else if(tagInput.isFocused()) { - tagInput.textboxKeyTyped(typedChar, keyCode); - } + org.lwjgl.util.Point mouse = MouseUtils.getMousePos(); + content.buttonPressed(mc, mouse.getX(), mouse.getY(), typedChar, keyCode); if(uploader.isUploading()) { startUploadButton.enabled = false; @@ -400,17 +411,17 @@ public class GuiUploadFile extends GuiScreen { private void validateStartButton() { boolean enabled = true; - if(fileTitleInput.getText().trim().length() < 5 || fileTitleInput.getText().trim().length() > 30) { + if(name.getText().trim().length() < 5 || name.getText().trim().length() > 30) { enabled = false; - } else if(titlePattern.matcher(fileTitleInput.getText()).find()) { + } else if(titlePattern.matcher(name.getText()).find()) { enabled = false; - fileTitleInput.setTextColor(Color.RED.getRGB()); - } else if(tagsPattern.matcher(tagInput.getText()).find()) { + name.setTextColor(Color.RED.getRGB()); + } else if(tagsPattern.matcher(tags.getText()).find()) { enabled = false; - tagInput.setTextColor(Color.RED.getRGB()); + tags.setTextColor(Color.RED.getRGB()); } else { - fileTitleInput.setTextColor(Color.WHITE.getRGB()); - tagInput.setTextColor(Color.WHITE.getRGB()); + name.setTextColor(Color.WHITE.getRGB()); + tags.setTextColor(Color.WHITE.getRGB()); } if(lockUploadButton) enabled = false; @@ -422,8 +433,9 @@ public class GuiUploadFile extends GuiScreen { startUploadButton.enabled = false; cancelUploadButton.enabled = true; backButton.enabled = false; - categoryButton.enabled = false; - fileTitleInput.setEnabled(false); + category.enabled = false; + name.setEnabled(false); + description.enabled = false; messageTextField.setText(I18n.format("replaymod.gui.upload.uploading")); messageTextField.setTextColor(Color.WHITE.getRGB()); } @@ -432,8 +444,9 @@ public class GuiUploadFile extends GuiScreen { validateStartButton(); cancelUploadButton.enabled = false; backButton.enabled = true; - categoryButton.enabled = true; - fileTitleInput.setEnabled(true); + category.enabled = true; + name.setEnabled(true); + description.enabled = true; if(success) { messageTextField.setText(I18n.format("replaymod.gui.upload.success")); messageTextField.setTextColor(Color.GREEN.getRGB()); diff --git a/src/main/java/eu/crushedpixel/replaymod/registry/KeybindRegistry.java b/src/main/java/eu/crushedpixel/replaymod/registry/KeybindRegistry.java index 6a03be28..8d8377ed 100755 --- a/src/main/java/eu/crushedpixel/replaymod/registry/KeybindRegistry.java +++ b/src/main/java/eu/crushedpixel/replaymod/registry/KeybindRegistry.java @@ -42,4 +42,13 @@ public class KeybindRegistry { mc.gameSettings.loadOptions(); } + + public static KeyBinding getKeyBinding(String binding) { + for (KeyBinding keyBinding : mc.gameSettings.keyBindings) { + if (binding.equals(keyBinding.getKeyDescription())) { + return keyBinding; + } + } + return null; + } } diff --git a/src/main/resources/assets/replaymod/lang/en_US.lang b/src/main/resources/assets/replaymod/lang/en_US.lang index 4ab7d841..03d82d55 100644 --- a/src/main/resources/assets/replaymod/lang/en_US.lang +++ b/src/main/resources/assets/replaymod/lang/en_US.lang @@ -163,6 +163,7 @@ replaymod.gui.upload.uploading=Uploading... replaymod.gui.upload.success=File has been successfully uploaded replaymod.gui.upload.canceled=Upload has been canceled replaymod.gui.upload.hideip=Hide Server IP +replaymod.gui.upload.nothumbnail=Missing Thumbnail. Please create a Thumbnail in the Replay using the %1$s key. #Replay Editor replaymod.gui.editor.replayfile=Replay File