From 6c747e639c3e8524134aaf988b1b2e7ef6b11c78 Mon Sep 17 00:00:00 2001 From: Irtimaled Date: Thu, 21 May 2020 15:33:50 -0700 Subject: [PATCH] Fully support keyboard nav in gui --- .../bbor/client/gui/AbstractButton.java | 30 +-- .../bbor/client/gui/AbstractControl.java | 21 +-- .../bbor/client/gui/AbstractSlider.java | 67 ++++--- .../irtimaled/bbor/client/gui/BoolButton.java | 17 +- .../bbor/client/gui/ControlList.java | 172 +++++++++--------- .../bbor/client/gui/ControlListEntry.java | 23 ++- .../bbor/client/gui/ControlListSection.java | 90 +++++---- .../bbor/client/gui/CreateControl.java | 2 +- .../irtimaled/bbor/client/gui/IControl.java | 19 +- .../bbor/client/gui/IControlSet.java | 94 ++++++++++ .../bbor/client/gui/IFocusableControl.java | 6 + .../bbor/client/gui/IntSettingSlider.java | 28 ++- .../irtimaled/bbor/client/gui/ListHelper.java | 24 +++ .../irtimaled/bbor/client/gui/ListScreen.java | 30 ++- .../bbor/client/gui/LoadSavesScreen.java | 20 +- .../bbor/client/gui/MaxYSettingSlider.java | 8 +- .../bbor/client/gui/SearchField.java | 8 +- .../client/gui/SelectableControlList.java | 109 +++++++++++ .../bbor/client/gui/SettingsScreen.java | 85 ++++----- .../bbor/client/gui/WorldSaveRow.java | 35 ++-- .../mixin/client/gui/MixinGuiOptions.java | 4 +- 21 files changed, 574 insertions(+), 318 deletions(-) create mode 100644 src/main/java/com/irtimaled/bbor/client/gui/IControlSet.java create mode 100644 src/main/java/com/irtimaled/bbor/client/gui/IFocusableControl.java create mode 100644 src/main/java/com/irtimaled/bbor/client/gui/ListHelper.java create mode 100644 src/main/java/com/irtimaled/bbor/client/gui/SelectableControlList.java diff --git a/src/main/java/com/irtimaled/bbor/client/gui/AbstractButton.java b/src/main/java/com/irtimaled/bbor/client/gui/AbstractButton.java index 1ceed2e..5fd816a 100644 --- a/src/main/java/com/irtimaled/bbor/client/gui/AbstractButton.java +++ b/src/main/java/com/irtimaled/bbor/client/gui/AbstractButton.java @@ -1,30 +1,38 @@ package com.irtimaled.bbor.client.gui; +import net.minecraft.client.Minecraft; + abstract class AbstractButton extends AbstractControl { AbstractButton(int x, int y, int width, String name) { super(x, y, width, name); } - AbstractButton(int x, int y, int width, String name, boolean enabled) { - this(x, y, width, name); + AbstractButton(int width, String name, boolean enabled) { + this(0, 0, width, name); this.active = enabled; } - @Override - protected int getYImage(boolean p_getHoverState_1_) { - return getState(); - } - - protected int getState() { - return this.active ? this.isHovered ? 2 : 1 : 0; - } - @Override public void onClick(double mouseX, double mouseY) { super.onClick(mouseX, mouseY); onPressed(); } + @Override + public boolean keyPressed(int key, int scanCode, int modifiers) { + if (this.active && this.visible) { + if (key != 257 && key != 32 && key != 335) { + return false; + } else { + this.playDownSound(Minecraft.getInstance().getSoundHandler()); + this.onPressed(); + return true; + } + } else { + return false; + } + } + protected abstract void onPressed(); } diff --git a/src/main/java/com/irtimaled/bbor/client/gui/AbstractControl.java b/src/main/java/com/irtimaled/bbor/client/gui/AbstractControl.java index 839e280..6201d6f 100644 --- a/src/main/java/com/irtimaled/bbor/client/gui/AbstractControl.java +++ b/src/main/java/com/irtimaled/bbor/client/gui/AbstractControl.java @@ -19,22 +19,18 @@ abstract class AbstractControl extends Widget implements IControl { super.render(mouseX, mouseY, 0f); } - @Override public void setX(int x) { super.x = x; } - @Override public void setY(int y) { super.y = y; } - @Override public int getControlHeight() { return this.height + PADDING; } - @Override public int getControlWidth() { return this.width + PADDING; } @@ -48,24 +44,23 @@ abstract class AbstractControl extends Widget implements IControl { } @Override - public void setVisible(boolean visible) { - this.visible = visible; - } - - @Override - public boolean getVisible() { + public boolean isVisible() { return this.visible; } - @Override public void filter(String lowerValue) { String lowerString = this.getMessage().toLowerCase(); - this.setVisible(lowerValue.equals("") || + this.visible = lowerValue.equals("") || lowerString.startsWith(lowerValue) || - lowerString.contains(" " + lowerValue)); + lowerString.contains(" " + lowerValue); } void drawRectangle(int left, int top, int right, int bottom, Color color) { fill(left, top, right, bottom, color.getRGB()); } + + @Override + public void clearFocus() { + this.setFocused(false); + } } diff --git a/src/main/java/com/irtimaled/bbor/client/gui/AbstractSlider.java b/src/main/java/com/irtimaled/bbor/client/gui/AbstractSlider.java index d16d3ca..eaa5f60 100644 --- a/src/main/java/com/irtimaled/bbor/client/gui/AbstractSlider.java +++ b/src/main/java/com/irtimaled/bbor/client/gui/AbstractSlider.java @@ -1,43 +1,50 @@ package com.irtimaled.bbor.client.gui; +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.SoundHandler; import net.minecraft.util.math.MathHelper; import org.lwjgl.opengl.GL11; abstract class AbstractSlider extends AbstractControl { - double progress; - private boolean isDragging; + private final int optionCount; + private final int total; + int position = 0; - AbstractSlider(int x, int y, int width) { - super(x, y, width, ""); + AbstractSlider(int width, int optionCount) { + super(0, 0, width, ""); + this.optionCount = optionCount; + total = this.width - 8; } @Override protected void renderBackground(int mouseX, int mouseY) { this.minecraft.getTextureManager().bindTexture(WIDGETS_LOCATION); GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); - if(isDragging) { - changeProgress(mouseX); - } + int hoverState = super.getYImage(this.isHovered()); + this.blit(this.x + (int) getProgressPercentage(), this.y, 0, 46 + hoverState * 20, 4, this.height); + this.blit(this.x + (int) getProgressPercentage() + 4, this.y, 196, 46 + hoverState * 20, 4, 20); + } - int hoverState = super.getYImage(this.isHovered); - this.blit(this.x + (int) (this.progress * (double) (this.width - 8)), this.y, 0, 46 + hoverState * 20, 4, this.height); - this.blit(this.x + (int) (this.progress * (double) (this.width - 8)) + 4, this.y, 196, 46 + hoverState * 20, 4, 20); + private double getProgressPercentage() { + return (this.position / (double) this.optionCount) * (double) total; } - boolean setProgress(double progress) { - progress = MathHelper.clamp(progress, 0d, 1d); - if (this.progress == progress) return false; + private void changeProgress(double mouseX) { + double progress = (mouseX - (double) (this.x + 4)) / (double) total; + setPosition((int) (progress * optionCount)); + } - this.progress = progress; - return true; + protected int getPosition() { + return position; } - private void changeProgress(double mouseX) { - double progress = (mouseX - (double) (this.x + 4)) / (double) (this.width - 8); - if (setProgress(progress)) { - onProgressChanged(); - } - updateText(); + protected boolean setPosition(int position) { + position = MathHelper.clamp(position, 0, optionCount); + if (this.position == position) return false; + + this.position = position; + onProgressChanged(); + return true; } @Override @@ -53,15 +60,23 @@ abstract class AbstractSlider extends AbstractControl { @Override public void onClick(double mouseX, double mouseY) { changeProgress(mouseX); - isDragging = true; } + protected abstract void onProgressChanged(); + @Override - public void onRelease(double mouseX, double mouseY) { - this.isDragging = false; + public boolean keyPressed(int key, int scanCode, int modifiers) { + if (key != 262 && key != 263) return false; + int position = getPosition(); + return key == 263 ? setPosition(position - 1) : setPosition(position + 1); } - protected abstract void updateText(); + @Override + public void playDownSound(SoundHandler soundHandler) { + } - protected abstract void onProgressChanged(); + @Override + public void onRelease(double mouseX, double mouseY) { + super.playDownSound(Minecraft.getInstance().getSoundHandler()); + } } diff --git a/src/main/java/com/irtimaled/bbor/client/gui/BoolButton.java b/src/main/java/com/irtimaled/bbor/client/gui/BoolButton.java index f61e5db..f7a0ab1 100644 --- a/src/main/java/com/irtimaled/bbor/client/gui/BoolButton.java +++ b/src/main/java/com/irtimaled/bbor/client/gui/BoolButton.java @@ -4,28 +4,15 @@ import com.irtimaled.bbor.client.config.ColorHelper; import com.irtimaled.bbor.client.config.ConfigManager; public abstract class BoolButton extends AbstractButton { - private boolean value; - BoolButton(int width, String label, boolean enabled) { - super(0, 0, width, label, enabled); + super(width, label, enabled); } BoolButton(int width, String label) { super(0, 0, width, label); } - @Override - protected int getState() { - return active ? super.getState() : 0; - } - - protected boolean getValue() { - return this.value; - } - - protected void setValue(boolean value) { - this.value = value; - } + protected abstract boolean getValue(); @Override protected void renderBackground(int mouseX, int mouseY) { diff --git a/src/main/java/com/irtimaled/bbor/client/gui/ControlList.java b/src/main/java/com/irtimaled/bbor/client/gui/ControlList.java index 00f9d81..d15d971 100644 --- a/src/main/java/com/irtimaled/bbor/client/gui/ControlList.java +++ b/src/main/java/com/irtimaled/bbor/client/gui/ControlList.java @@ -4,34 +4,32 @@ import com.irtimaled.bbor.client.renderers.Renderer; import com.mojang.blaze3d.platform.GLX; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.AbstractGui; -import net.minecraft.client.gui.FocusableGui; -import net.minecraft.client.gui.IGuiEventListener; import net.minecraft.util.math.MathHelper; import org.lwjgl.opengl.GL11; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -public class ControlList extends FocusableGui { - private static final int CONTROLS_WIDTH = 310; +public class ControlList extends AbstractGui implements IControlSet { + public static final int CONTROLS_WIDTH = 310; + protected static final int PADDING = 8; + + protected final int listLeft; + protected final List entries = new ArrayList<>(); private final int scrollBarLeft; private final int listHeight; - private final int listLeft; - private final int listRight; private final Minecraft minecraft; - private final List entries = new ArrayList<>(); private final int width; private final int height; private final int top; private final int bottom; - private int contentHeight = 8; - private int selectedElement; + protected int contentHeight = PADDING; private double amountScrolled; private boolean clickedScrollbar; - private boolean showSelectionBox; private boolean transparentBackground; + private IControl focused; + private boolean isDragging; ControlList(int width, int height, int top, int bottom) { this.minecraft = Minecraft.getInstance(); @@ -42,12 +40,9 @@ public class ControlList extends FocusableGui { this.bottom = bottom; this.listHeight = bottom - top; this.listLeft = width / 2 - CONTROLS_WIDTH / 2; - this.listRight = this.listLeft + CONTROLS_WIDTH; - this.selectedElement = -1; } void add(ControlListEntry entry) { - entry.list = this; entry.index = entries.size(); addEntry(entry); } @@ -57,18 +52,18 @@ public class ControlList extends FocusableGui { this.contentHeight += entry.getControlHeight(); } - ControlListEntry getSelectedEntry() { - return this.selectedElement >= 0 && this.selectedElement < this.entries.size() ? this.entries.get(this.selectedElement) : null; - } - - void filter(String lowerValue) { + public void filter(String lowerValue) { int height = 0; - for (IControl entry : entries) { + + for (ControlListEntry entry : entries) { entry.filter(lowerValue); - if (entry.getVisible()) + if (entry.isVisible()) { height += entry.getControlHeight(); + } else if (entry == focused) { + focused = null; + } } - this.contentHeight = height + 8; + this.contentHeight = height + PADDING; } void close() { @@ -78,43 +73,47 @@ public class ControlList extends FocusableGui { @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { this.clickedScrollbar = button == 0 && mouseX >= (double) this.scrollBarLeft; - if (mouseY >= (double) this.top && mouseY <= (double) this.bottom) { - ControlListEntry entry = this.getEntryAt(mouseX, mouseY); - if (entry != null && entry.mouseClicked(mouseX, mouseY, button)) { - this.setDragging(true); - this.setSelectedIndex(entry.index); - return true; - } else { - return this.clickedScrollbar; - } - } else { - return false; - } + return isMouseOver(mouseX, mouseY) && + (IControlSet.super.mouseClicked(mouseX, mouseY, button) || + this.clickedScrollbar); } - void setSelectedIndex(int index) { - this.selectedElement = index; + @Override + public boolean isMouseOver(double mouseX, double mouseY) { + return mouseY >= (double) this.top && mouseY <= (double) this.bottom; } - private ControlListEntry getEntryAt(double mouseX, double mouseY) { - if (mouseX >= listLeft && mouseX <= listRight) { - for (ControlListEntry entry : entries) { - if (!entry.getVisible()) continue; + @Override + public boolean changeFocus(boolean moveForward) { + boolean newControlFocused = IControlSet.super.changeFocus(moveForward); + if (newControlFocused) { + this.ensureVisible((ControlListEntry) this.getFocused()); + } - int top = entry.getY(); - int bottom = top + entry.getControlHeight(); - if (mouseY >= top && mouseY <= bottom) - return entry; - } + return newControlFocused; + } + + private void ensureVisible(ControlListEntry control) { + int controlTop = control.getControlTop(); + int controlHeight = control.getControlHeight(); + int distanceAboveTop = this.top - controlTop; + if (distanceAboveTop > 0) { + this.amountScrolled -= Math.max(controlHeight, distanceAboveTop + PADDING); + return; + } + + int distanceBelowBottom = controlTop + controlHeight - this.bottom; + if (distanceBelowBottom > 0) { + this.amountScrolled += Math.max(controlHeight, distanceBelowBottom + PADDING); } - return null; } @Override public boolean mouseDragged(double mouseX, double mouseY, int button, double p_mouseDragged_6_, double p_mouseDragged_8_) { - if (super.mouseDragged(mouseX, mouseY, button, p_mouseDragged_6_, p_mouseDragged_8_)) { + if (IControlSet.super.mouseDragged(mouseX, mouseY, button, p_mouseDragged_6_, p_mouseDragged_8_)) { return true; - } else if (button == 0 && this.clickedScrollbar) { + } + if (button == 0 && this.clickedScrollbar) { if (mouseY < (double) this.top) { this.amountScrolled = 0.0D; } else if (mouseY > (double) this.bottom) { @@ -134,9 +133,8 @@ public class ControlList extends FocusableGui { } return true; - } else { - return false; } + return false; } private int getMaxScroll() { @@ -146,13 +144,7 @@ public class ControlList extends FocusableGui { private int getScrollBarHeight() { return MathHelper.clamp((int) ((float) (this.listHeight * this.listHeight) / (float) this.contentHeight), 32, - this.listHeight - 8); - } - - @Override - public boolean mouseReleased(double mouseX, double mouseY, int button) { - this.entries.forEach(entry -> entry.mouseReleased(mouseX, mouseY, button)); - return false; + this.listHeight - PADDING); } @Override @@ -168,7 +160,7 @@ public class ControlList extends FocusableGui { GL11.glDisable(GL11.GL_FOG); if (!transparentBackground) drawListBackground(); - int listTop = this.top + 8 - (int) this.amountScrolled; + int listTop = this.top + PADDING - (int) this.amountScrolled; drawEntries(mouseX, mouseY, listTop); @@ -207,37 +199,21 @@ public class ControlList extends FocusableGui { private void drawEntries(int mouseX, int mouseY, int top) { for (ControlListEntry entry : this.entries) { - if (!entry.getVisible()) continue; + if (!entry.isVisible()) continue; entry.setX(this.listLeft); entry.setY(top); int height = entry.getControlHeight(); - - if (this.showSelectionBox && this.selectedElement == entry.index) { - GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); - GL11.glDisable(GL11.GL_TEXTURE_2D); - Renderer.startTextured() - .setAlpha(255) - .setColor(128, 128, 128) - .addPoint((double) this.listLeft - 2, (double) (top + height) - 2, 0.0D, 0.0D, 1.0D) - .addPoint((double) this.listRight + 2, (double) (top + height) - 2, 0.0D, 1.0D, 1.0D) - .addPoint((double) this.listRight + 2, top - 2, 0.0D, 1.0D, 0.0D) - .addPoint((double) this.listLeft - 2, top - 2, 0.0D, 0.0D, 0.0D) - .setColor(0, 0, 0) - .addPoint(this.listLeft - 1, (double) (top + height) - 3, 0.0D, 0.0D, 1.0D) - .addPoint(this.listRight + 1, (double) (top + height) - 3, 0.0D, 1.0D, 1.0D) - .addPoint(this.listRight + 1, top - 1, 0.0D, 1.0D, 0.0D) - .addPoint(this.listLeft - 1, top - 1, 0.0D, 0.0D, 0.0D) - .render(); - GL11.glEnable(GL11.GL_TEXTURE_2D); - } - - entry.render(mouseX, mouseY); - top += entry.getControlHeight(); + drawEntry(mouseX, mouseY, top, entry, height); + top += height; } } + protected void drawEntry(int mouseX, int mouseY, int top, ControlListEntry entry, int height) { + entry.render(mouseX, mouseY); + } + private void overlayBackground(int top, int bottom) { this.minecraft.getTextureManager().bindTexture(AbstractGui.BACKGROUND_LOCATION); GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); @@ -302,21 +278,37 @@ public class ControlList extends FocusableGui { .render(); } - @Override - public List children() { - return Collections.emptyList(); - } - ControlList section(String title, CreateControl... createControls) { this.add(new ControlListSection(title, createControls)); return this; } - void showSelectionBox() { - this.showSelectionBox = true; - } - void setTransparentBackground() { this.transparentBackground = true; } + + @Override + public List controls() { + return entries; + } + + @Override + public IControl getFocused() { + return focused; + } + + @Override + public void setFocused(IControl control) { + this.focused = control; + } + + @Override + public boolean isDragging() { + return isDragging; + } + + @Override + public void setDragging(boolean dragging) { + this.isDragging = dragging; + } } diff --git a/src/main/java/com/irtimaled/bbor/client/gui/ControlListEntry.java b/src/main/java/com/irtimaled/bbor/client/gui/ControlListEntry.java index 1521bfe..231b097 100644 --- a/src/main/java/com/irtimaled/bbor/client/gui/ControlListEntry.java +++ b/src/main/java/com/irtimaled/bbor/client/gui/ControlListEntry.java @@ -2,15 +2,16 @@ package com.irtimaled.bbor.client.gui; public abstract class ControlListEntry implements IControl { int index; - ControlList list; private int x; private int y; private boolean visible = true; - public void close() { } + public void close() { + } - @Override - public int getControlHeight() { return 24; } + public int getControlHeight() { + return 24; + } public int getX() { return x; @@ -20,23 +21,29 @@ public abstract class ControlListEntry implements IControl { return y; } - @Override public void setX(int x) { this.x = x; } - @Override public void setY(int y) { this.y = y; } - @Override public void setVisible(boolean visible) { this.visible = visible; } @Override - public boolean getVisible() { + public boolean isVisible() { return visible; } + + public int getControlTop() { + return y; + } + + public void done() { + } + + public abstract void filter(String lowerValue); } diff --git a/src/main/java/com/irtimaled/bbor/client/gui/ControlListSection.java b/src/main/java/com/irtimaled/bbor/client/gui/ControlListSection.java index 4135bc9..dba872b 100644 --- a/src/main/java/com/irtimaled/bbor/client/gui/ControlListSection.java +++ b/src/main/java/com/irtimaled/bbor/client/gui/ControlListSection.java @@ -5,14 +5,15 @@ import net.minecraft.client.Minecraft; import java.util.ArrayList; import java.util.List; -public class ControlListSection extends ControlListEntry { +public class ControlListSection extends ControlListEntry implements IControlSet { private static final int TITLE_HEIGHT = 16; - private static final int CONTROLS_WIDTH = 310; private final String title; - private final List controls = new ArrayList<>(); + private final List controls = new ArrayList<>(); private final Minecraft minecraft = Minecraft.getInstance(); private final int titleHeight; private int height; + private IControl focused; + private boolean dragging; ControlListSection(String title, CreateControl... createControls) { this.title = title; @@ -20,12 +21,12 @@ public class ControlListSection extends ControlListEntry { this.height = titleHeight; int columnCount = columnCount(); - int controlWidth = (CONTROLS_WIDTH - ((columnCount - 1) * 4)) / columnCount; + int controlWidth = (ControlList.CONTROLS_WIDTH - ((columnCount - 1) * 4)) / columnCount; int column = 0; for (CreateControl createControl : createControls) { - IControl control = createControl.create(0, controlWidth); - if(control == null) continue; + AbstractControl control = createControl.create(controlWidth); + if (control == null) continue; this.controls.add(control); if (column == 0) { @@ -36,10 +37,11 @@ public class ControlListSection extends ControlListEntry { } private int columnCount() { - switch (minecraft.getLanguageManager().getCurrentLanguage().getCode()){ + switch (minecraft.getLanguageManager().getCurrentLanguage().getCode()) { case "en_au": case "en_us": - case "en_gb": return 3; + case "en_gb": + return 3; } return 2; } @@ -49,24 +51,24 @@ public class ControlListSection extends ControlListEntry { int x = this.getX(); int y = this.getY(); int top = y; - if(this.title != null) { + if (this.title != null) { this.minecraft.fontRenderer.drawString(this.title, x + 4, y + ((TITLE_HEIGHT - this.minecraft.fontRenderer.FONT_HEIGHT) / 1.5f), 16777215); top += titleHeight; } int left = 0; int height = 0; - for(IControl control : controls) { - if(!control.getVisible()) continue; + for (AbstractControl control : controls) { + if (!control.isVisible()) continue; control.setX(left + x); control.setY(top); control.render(mouseX, mouseY); - if(left == 0) { + if (left == 0) { height = control.getControlHeight(); } left += control.getControlWidth(); - if(left >= CONTROLS_WIDTH) { + if (left >= ControlList.CONTROLS_WIDTH) { left = 0; top += height; } @@ -74,49 +76,36 @@ public class ControlListSection extends ControlListEntry { } @Override - public int getControlHeight() { - return this.height; - } - - @Override - public int getControlWidth() { - return CONTROLS_WIDTH; + public void clearFocus() { + IControlSet.super.clearFocus(); } @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - for (IControl control : controls) { - if (control.getVisible() && control.mouseClicked(mouseX, mouseY, button)) { - return true; - } - } - return false; + public int getControlHeight() { + return this.height; } - @Override - public boolean mouseReleased(double mouseX, double mouseY, int button) { - boolean result = false; - for (IControl control : controls) { - if (control.mouseReleased(mouseX, mouseY, button)) result = true; - } - return result; + public int getControlWidth() { + return ControlList.CONTROLS_WIDTH; } - @Override public void filter(String lowerValue) { - if(matchesTitle(lowerValue)) lowerValue = ""; + if (matchesTitle(lowerValue)) lowerValue = ""; int height = 0; int left = 0; - for (IControl entry : controls) { + for (AbstractControl entry : controls) { entry.filter(lowerValue); - if (entry.getVisible()) { + if (entry.isVisible()) { if (left == 0) height += entry.getControlHeight(); left += entry.getControlWidth(); if (left >= getControlWidth()) { left = 0; } + } else if (entry == focused) { + entry.clearFocus(); + focused = null; } } this.height = height + titleHeight; @@ -130,4 +119,29 @@ public class ControlListSection extends ControlListEntry { return lowerString.startsWith(lowerValue) || lowerString.contains(" " + lowerValue); } + + @Override + public List controls() { + return this.controls; + } + + @Override + public IControl getFocused() { + return this.focused; + } + + @Override + public void setFocused(IControl focused) { + this.focused = focused; + } + + @Override + public boolean isDragging() { + return dragging; + } + + @Override + public void setDragging(boolean dragging) { + this.dragging = dragging; + } } diff --git a/src/main/java/com/irtimaled/bbor/client/gui/CreateControl.java b/src/main/java/com/irtimaled/bbor/client/gui/CreateControl.java index 7ea950f..b91c8db 100644 --- a/src/main/java/com/irtimaled/bbor/client/gui/CreateControl.java +++ b/src/main/java/com/irtimaled/bbor/client/gui/CreateControl.java @@ -2,5 +2,5 @@ package com.irtimaled.bbor.client.gui; @FunctionalInterface interface CreateControl { - IControl create(Integer x, Integer width); + AbstractControl create(Integer width); } diff --git a/src/main/java/com/irtimaled/bbor/client/gui/IControl.java b/src/main/java/com/irtimaled/bbor/client/gui/IControl.java index 17db2ba..871db38 100644 --- a/src/main/java/com/irtimaled/bbor/client/gui/IControl.java +++ b/src/main/java/com/irtimaled/bbor/client/gui/IControl.java @@ -2,23 +2,8 @@ package com.irtimaled.bbor.client.gui; import net.minecraft.client.gui.IGuiEventListener; -interface IControl extends IGuiEventListener { +interface IControl extends IFocusableControl, IGuiEventListener { void render(int mouseX, int mouseY); - void setX(int x); - - void setY(int y); - - int getControlWidth(); - - int getControlHeight(); - - boolean getVisible(); - - void setVisible(boolean visible); - - void filter(String lowerValue); - - default void close() { - } + boolean isVisible(); } diff --git a/src/main/java/com/irtimaled/bbor/client/gui/IControlSet.java b/src/main/java/com/irtimaled/bbor/client/gui/IControlSet.java new file mode 100644 index 0000000..86a9b37 --- /dev/null +++ b/src/main/java/com/irtimaled/bbor/client/gui/IControlSet.java @@ -0,0 +1,94 @@ +package com.irtimaled.bbor.client.gui; + +import net.minecraft.client.gui.IGuiEventListener; + +import java.util.List; + +public interface IControlSet extends IFocusableControl, IGuiEventListener { + List controls(); + + IControl getFocused(); + + void setFocused(IControl control); + + boolean isDragging(); + + void setDragging(boolean dragging); + + default boolean mouseClicked(double mouseX, double mouseY, int button) { + for (IControl control : this.controls()) { + if (control.isVisible() && control.mouseClicked(mouseX, mouseY, button)) { + IControl focused = getFocused(); + if (focused != null && focused != control) { + focused.clearFocus(); + } + this.setFocused(control); + if (button == 0) this.setDragging(true); + return true; + } + } + return false; + } + + default boolean mouseReleased(double mouseX, double mouseY, int button) { + this.setDragging(false); + IControl focused = this.getFocused(); + return focused != null && focused.mouseReleased(mouseX, mouseY, button); + } + + default boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { + IControl focused = this.getFocused(); + return focused != null && this.isDragging() && button == 0 && focused.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); + } + + default boolean mouseScrolled(double mouseX, double mouseY, double scrollAmount) { + IControl focused = this.getFocused(); + return focused != null && focused.mouseScrolled(mouseX, mouseY, scrollAmount); + } + + default boolean keyPressed(int key, int scanCode, int modifiers) { + IControl focused = this.getFocused(); + return focused != null && focused.keyPressed(key, scanCode, modifiers); + } + + default boolean keyReleased(int key, int scanCode, int modifiers) { + IControl focused = this.getFocused(); + return focused != null && focused.keyReleased(key, scanCode, modifiers); + } + + default boolean charTyped(char character, int modifiers) { + IControl focused = this.getFocused(); + return focused != null && focused.charTyped(character, modifiers); + } + + default boolean changeFocus(boolean moveForward) { + IControl focused = this.getFocused(); + if (focused != null && focused.changeFocus(moveForward)) { + return true; + } + + List controls = this.controls(); + int controlIndex = controls.indexOf(focused); + int newIndex; + if (focused != null && controlIndex >= 0) { + newIndex = controlIndex + (moveForward ? 1 : 0); + } else if (moveForward) { + newIndex = 0; + } else { + newIndex = controls.size(); + } + + if (ListHelper.findNextMatch(controls, newIndex, moveForward, + c -> c.changeFocus(moveForward), this::setFocused)) return true; + this.setFocused(null); + return false; + } + + default void clearFocus() { + IControl focused = getFocused(); + if (focused != null) { + setFocused(null); + focused.clearFocus(); + } + } +} diff --git a/src/main/java/com/irtimaled/bbor/client/gui/IFocusableControl.java b/src/main/java/com/irtimaled/bbor/client/gui/IFocusableControl.java new file mode 100644 index 0000000..ab58bc9 --- /dev/null +++ b/src/main/java/com/irtimaled/bbor/client/gui/IFocusableControl.java @@ -0,0 +1,6 @@ +package com.irtimaled.bbor.client.gui; + +public interface IFocusableControl { + default void clearFocus() { + } +} diff --git a/src/main/java/com/irtimaled/bbor/client/gui/IntSettingSlider.java b/src/main/java/com/irtimaled/bbor/client/gui/IntSettingSlider.java index 34fadec..e94cdeb 100644 --- a/src/main/java/com/irtimaled/bbor/client/gui/IntSettingSlider.java +++ b/src/main/java/com/irtimaled/bbor/client/gui/IntSettingSlider.java @@ -12,18 +12,20 @@ class IntSettingSlider extends AbstractSlider { final Setting setting; final int minValue; - final int range; IntSettingSlider(int width, int minValue, int maxValue, String format, Setting setting) { - super(0, 0, width); + super(width, maxValue - minValue); this.setting = setting; this.minValue = minValue; this.format = format; - this.range = maxValue - minValue; - this.setProgress(getSliderValue()); + setInitialPosition(); this.updateText(); } + protected void setInitialPosition() { + this.setPosition(this.setting.get() - this.minValue); + } + IntSettingSlider addDisplayValue(int value, String displayValue) { displayValues.put(value, displayValue); if (setting.get() == value) { @@ -32,26 +34,18 @@ class IntSettingSlider extends AbstractSlider { return this; } - private String getDisplayValue() { - Integer value = setting.get(); - return I18n.format(format, displayValues.getOrDefault(value, value.toString())); - } - protected Integer getSettingValue() { - return minValue + (int) (range * progress); + return minValue + getPosition(); } - protected double getSliderValue() { - return (setting.get() - minValue) / (double) range; - } - - @Override - protected void updateText() { - this.setMessage(this.getDisplayValue()); + private void updateText() { + Integer value = setting.get(); + this.setMessage(I18n.format(format, displayValues.getOrDefault(value, value.toString()))); } @Override protected void onProgressChanged() { this.setting.set(this.getSettingValue()); + updateText(); } } diff --git a/src/main/java/com/irtimaled/bbor/client/gui/ListHelper.java b/src/main/java/com/irtimaled/bbor/client/gui/ListHelper.java new file mode 100644 index 0000000..c9f0a3f --- /dev/null +++ b/src/main/java/com/irtimaled/bbor/client/gui/ListHelper.java @@ -0,0 +1,24 @@ +package com.irtimaled.bbor.client.gui; + +import java.util.List; +import java.util.ListIterator; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.function.Supplier; + +public class ListHelper { + public static boolean findNextMatch(List list, int index, boolean forward, Predicate match, Consumer consumer) { + ListIterator iterator = list.listIterator(index); + Supplier hasMore = forward ? iterator::hasNext : iterator::hasPrevious; + Supplier more = forward ? iterator::next : iterator::previous; + + while (hasMore.get()) { + T item = more.get(); + if (match.test(item)) { + consumer.accept(item); + return true; + } + } + return false; + } +} diff --git a/src/main/java/com/irtimaled/bbor/client/gui/ListScreen.java b/src/main/java/com/irtimaled/bbor/client/gui/ListScreen.java index 6b5dcf0..c8add06 100644 --- a/src/main/java/com/irtimaled/bbor/client/gui/ListScreen.java +++ b/src/main/java/com/irtimaled/bbor/client/gui/ListScreen.java @@ -1,6 +1,7 @@ package com.irtimaled.bbor.client.gui; import com.irtimaled.bbor.client.interop.ClientInterop; +import net.minecraft.client.gui.IGuiEventListener; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.resources.I18n; import net.minecraft.util.text.StringTextComponent; @@ -27,7 +28,7 @@ public abstract class ListScreen extends Screen { @Override protected void init() { - this.controlList = new ControlList(this.width, this.height, 48, this.height - 28); + this.controlList = this.buildList(48, this.height - 28); this.searchField = new SearchField(this.font, this.width / 2 - 100, 22, 200, 20, this.controlList); this.doneButton = new AbstractButton(this.width / 2 - 100, this.height - 24, 200, I18n.format("gui.done")) { @Override @@ -36,13 +37,12 @@ public abstract class ListScreen extends Screen { } }; - this.children.add(this.doneButton); - this.children.add(this.controlList); this.children.add(this.searchField); - this.setup(); + this.children.add(this.controlList); + this.children.add(this.doneButton); } - protected abstract void setup(); + protected abstract ControlList buildList(int top, int bottom); @Override public void render(int mouseX, int mouseY, float unknown) { @@ -82,11 +82,23 @@ public abstract class ListScreen extends Screen { this.controlList.close(); } - ControlList getControlList() { - return this.controlList; + protected void setCanExit(boolean canExit) { + this.doneButton.active = canExit; } - AbstractButton getDoneButton() { - return doneButton; + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + for (IGuiEventListener control : this.children()) { + if (control.mouseClicked(mouseX, mouseY, button)) { + IGuiEventListener focused = getFocused(); + if (focused instanceof IFocusableControl && focused != control) { + ((IFocusableControl) focused).clearFocus(); + } + this.setFocused(control); + if (button == 0) this.setDragging(true); + return true; + } + } + return false; } } diff --git a/src/main/java/com/irtimaled/bbor/client/gui/LoadSavesScreen.java b/src/main/java/com/irtimaled/bbor/client/gui/LoadSavesScreen.java index d26c679..90a4a01 100644 --- a/src/main/java/com/irtimaled/bbor/client/gui/LoadSavesScreen.java +++ b/src/main/java/com/irtimaled/bbor/client/gui/LoadSavesScreen.java @@ -8,33 +8,39 @@ import net.minecraft.world.storage.WorldSummary; import java.util.List; public class LoadSavesScreen extends ListScreen { + private SelectableControlList controlList; + public static void show() { ClientInterop.displayScreen(new LoadSavesScreen()); } @Override - protected void setup() { - ControlList controlList = this.getControlList(); - controlList.showSelectionBox(); + protected ControlList buildList(int top, int bottom) { + controlList = new SelectableControlList(this.width, this.height, top, bottom); try { final SaveFormat saveLoader = this.minecraft.getSaveLoader(); List saveList = saveLoader.getSaveList(); saveList.sort(null); - saveList.forEach(world -> controlList.add(new WorldSaveRow(world, saveLoader))); + saveList.forEach(world -> controlList.add(new WorldSaveRow(world, saveLoader, controlList::setSelectedEntry))); } catch (AnvilConverterException e) { e.printStackTrace(); } + return controlList; } @Override protected void onDoneClicked() { - ((WorldSaveRow) this.getControlList().getSelectedEntry()).loadWorld(); + getSelectedEntry().done(); } @Override public void render(int mouseX, int mouseY, float unknown) { - ControlListEntry selectedEntry = this.getControlList().getSelectedEntry(); - this.getDoneButton().active = selectedEntry != null && selectedEntry.getVisible(); + ControlListEntry selectedEntry = getSelectedEntry(); + this.setCanExit(selectedEntry != null && selectedEntry.isVisible()); super.render(mouseX, mouseY, unknown); } + + private ControlListEntry getSelectedEntry() { + return this.controlList.getSelectedEntry(); + } } diff --git a/src/main/java/com/irtimaled/bbor/client/gui/MaxYSettingSlider.java b/src/main/java/com/irtimaled/bbor/client/gui/MaxYSettingSlider.java index 7c6562e..4e3651a 100644 --- a/src/main/java/com/irtimaled/bbor/client/gui/MaxYSettingSlider.java +++ b/src/main/java/com/irtimaled/bbor/client/gui/MaxYSettingSlider.java @@ -9,7 +9,7 @@ class MaxYSettingSlider extends IntSettingSlider { MaxYSettingSlider(int width, int minValue, Setting setting) { super(width, minValue - 2, 127, I18n.format("bbor.options.maxY", "%s"), setting); this.actualMinValue = minValue; - this.setProgress(getSliderValue()); + this.setInitialPosition(); this.addDisplayValue(-1, I18n.format("bbor.options.maxY.activated")); this.addDisplayValue(0, I18n.format("bbor.options.maxY.player")); this.addDisplayValue(63, I18n.format("bbor.options.maxY.seaLevel")); @@ -24,11 +24,13 @@ class MaxYSettingSlider extends IntSettingSlider { } @Override - protected double getSliderValue() { + protected void setInitialPosition() { + if (actualMinValue != minValue + 2) return; + int value = setting.get(); if (value < actualMinValue) value = (value - 1) + actualMinValue; - return (value - minValue) / (double) range; + setPosition(value - minValue); } } diff --git a/src/main/java/com/irtimaled/bbor/client/gui/SearchField.java b/src/main/java/com/irtimaled/bbor/client/gui/SearchField.java index 4778f4d..d5fd4e2 100644 --- a/src/main/java/com/irtimaled/bbor/client/gui/SearchField.java +++ b/src/main/java/com/irtimaled/bbor/client/gui/SearchField.java @@ -3,7 +3,7 @@ package com.irtimaled.bbor.client.gui; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.widget.TextFieldWidget; -public class SearchField extends TextFieldWidget { +public class SearchField extends TextFieldWidget implements IControl { private final ControlList controlList; SearchField(FontRenderer fontRenderer, int left, int top, int width, int height, ControlList controlList) { @@ -13,19 +13,19 @@ public class SearchField extends TextFieldWidget { this.func_212954_a(text -> this.controlList.filter(removeLeadingSpaces(text.toLowerCase()))); this.setTextFormatter((text, id) -> removeLeadingSpaces(text)); this.setFocused(true); - this.setCanLoseFocus(false); } private String removeLeadingSpaces(String text) { return text.replaceFirst("^\\s++", ""); } + @Override public void render(int mouseX, int mouseY) { this.render(mouseX, mouseY, 0f); } @Override - public void setFocused(boolean ignored) { - super.setFocused(true); + public boolean isVisible() { + return super.getVisible(); } } diff --git a/src/main/java/com/irtimaled/bbor/client/gui/SelectableControlList.java b/src/main/java/com/irtimaled/bbor/client/gui/SelectableControlList.java new file mode 100644 index 0000000..0584a23 --- /dev/null +++ b/src/main/java/com/irtimaled/bbor/client/gui/SelectableControlList.java @@ -0,0 +1,109 @@ +package com.irtimaled.bbor.client.gui; + +import com.irtimaled.bbor.client.renderers.Renderer; +import org.lwjgl.opengl.GL11; + +public class SelectableControlList extends ControlList { + private final int listRight; + + private int selectedElement; + private boolean isFocused; + + SelectableControlList(int width, int height, int top, int bottom) { + super(width, height, top, bottom); + this.listRight = this.listLeft + CONTROLS_WIDTH; + this.selectedElement = -1; + } + + @Override + public void filter(String lowerValue) { + super.filter(lowerValue); + if (selectedElement >= 0) { + if (selectNextVisibleElement(true, selectedElement) || + selectNextVisibleElement(true, 0)) return; + selectedElement = -1; + } + } + + @Override + public boolean keyPressed(int key, int scanCode, int modifiers) { + if (key != 264 && key != 265 && key != 257) return false; + + if (key == 257) { + if (selectedElement >= 0) { + getSelectedEntry().done(); + return true; + } + return false; + } + + boolean moveForward = key == 264; + if (selectedElement >= 0) { + int newIndex = selectedElement + (moveForward ? 1 : 0); + if (selectNextVisibleElement(moveForward, newIndex)) return true; + } + if (selectNextVisibleElement(moveForward, moveForward ? 0 : entries.size())) return true; + + this.selectedElement = -1; + return false; + } + + private boolean selectNextVisibleElement(boolean moveForward, int index) { + return ListHelper.findNextMatch(entries, index, moveForward, ControlListEntry::isVisible, + entry -> this.selectedElement = entry.index); + } + + ControlListEntry getSelectedEntry() { + return this.selectedElement >= 0 && this.selectedElement < this.entries.size() ? + this.entries.get(this.selectedElement) : + null; + } + + void setSelectedEntry(ControlListEntry entry) { + if (entry != null) { + this.selectedElement = entry.index; + } else { + this.selectedElement = -1; + } + } + + @Override + public boolean changeFocus(boolean moveForward) { + if (contentHeight == PADDING) return false; + + isFocused = !isFocused; + if (getSelectedEntry() == null && this.entries.size() > 0) { + setSelectedEntry(this.entries.get(0)); + } + return isFocused; + } + + @Override + protected void drawEntry(int mouseX, int mouseY, int top, ControlListEntry entry, int height) { + if (this.selectedElement == entry.index) { + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + GL11.glDisable(GL11.GL_TEXTURE_2D); + int color = this.isFocused ? 255 : 128; + Renderer.startTextured() + .setAlpha(255) + .setColor(color, color, color) + .addPoint((double) this.listLeft - 2, (double) (top + height) - 2, 0.0D, 0.0D, 1.0D) + .addPoint((double) this.listRight + 2, (double) (top + height) - 2, 0.0D, 1.0D, 1.0D) + .addPoint((double) this.listRight + 2, top - 2, 0.0D, 1.0D, 0.0D) + .addPoint((double) this.listLeft - 2, top - 2, 0.0D, 0.0D, 0.0D) + .setColor(0, 0, 0) + .addPoint(this.listLeft - 1, (double) (top + height) - 3, 0.0D, 0.0D, 1.0D) + .addPoint(this.listRight + 1, (double) (top + height) - 3, 0.0D, 1.0D, 1.0D) + .addPoint(this.listRight + 1, top - 1, 0.0D, 1.0D, 0.0D) + .addPoint(this.listLeft - 1, top - 1, 0.0D, 0.0D, 0.0D) + .render(); + GL11.glEnable(GL11.GL_TEXTURE_2D); + } + super.drawEntry(mouseX, mouseY, top, entry, height); + } + + @Override + public void clearFocus() { + this.isFocused = false; + } +} diff --git a/src/main/java/com/irtimaled/bbor/client/gui/SettingsScreen.java b/src/main/java/com/irtimaled/bbor/client/gui/SettingsScreen.java index d8db265..cce48a2 100644 --- a/src/main/java/com/irtimaled/bbor/client/gui/SettingsScreen.java +++ b/src/main/java/com/irtimaled/bbor/client/gui/SettingsScreen.java @@ -28,14 +28,14 @@ public class SettingsScreen extends ListScreen { } @Override - protected void setup() { + protected ControlList buildList(int top, int bottom) { String version = SharedConstants.getVersion().getName(); - ControlList controlList = this.getControlList(); + ControlList controlList = new ControlList(this.width, this.height, top, bottom); if (this.minecraft.world != null) controlList.setTransparentBackground(); controlList .section(null, - (x, width) -> new BoolButton(width, I18n.format("bbor.options.active"), this.minecraft.world != null) { + width -> new BoolButton(width, I18n.format("bbor.options.active"), this.minecraft.world != null) { @Override public void onPressed() { ClientRenderer.toggleActive(); @@ -46,61 +46,62 @@ public class SettingsScreen extends ListScreen { return ClientRenderer.getActive(); } }, - (x, width) -> new BoolSettingButton(width, I18n.format("bbor.options.outerBoxOnly"), ConfigManager.outerBoxesOnly), - (x, width) -> new BoolSettingButton(width, I18n.format("bbor.options.fill"), ConfigManager.fill)) + width -> new BoolSettingButton(width, I18n.format("bbor.options.outerBoxOnly"), ConfigManager.outerBoxesOnly), + width -> new BoolSettingButton(width, I18n.format("bbor.options.fill"), ConfigManager.fill)) .section(I18n.format("bbor.features.spawnChunks"), - (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.features.spawnChunks"), BoundingBoxType.WorldSpawn), - (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.features.lazyChunks"), BoundingBoxType.LazySpawnChunks), - (x, width) -> new MaxYSettingSlider(width, 39, ConfigManager.worldSpawnMaxY)) + width -> new BoundingBoxTypeButton(width, I18n.format("bbor.features.spawnChunks"), BoundingBoxType.WorldSpawn), + width -> new BoundingBoxTypeButton(width, I18n.format("bbor.features.lazyChunks"), BoundingBoxType.LazySpawnChunks), + width -> new MaxYSettingSlider(width, 39, ConfigManager.worldSpawnMaxY)) .section(I18n.format("bbor.features.slimeChunks"), - (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.features.slimeChunks"), BoundingBoxType.SlimeChunks), - (x, width) -> new MaxYSettingSlider(width, 39, ConfigManager.slimeChunkMaxY)) + width -> new BoundingBoxTypeButton(width, I18n.format("bbor.features.slimeChunks"), BoundingBoxType.SlimeChunks), + width -> new MaxYSettingSlider(width, 39, ConfigManager.slimeChunkMaxY)) .section(I18n.format("bbor.features.biomeBorders"), - (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.features.biomeBorders"), BoundingBoxType.BiomeBorder), - (x, width) -> new MaxYSettingSlider(width, 1, ConfigManager.biomeBordersMaxY), - (x, width) -> new IntSettingSlider(width, 1, 3, "bbor.options.distance", ConfigManager.biomeBordersRenderDistance) + width -> new BoundingBoxTypeButton(width, I18n.format("bbor.features.biomeBorders"), BoundingBoxType.BiomeBorder), + width -> new MaxYSettingSlider(width, 1, ConfigManager.biomeBordersMaxY), + width -> new IntSettingSlider(width, 1, 3, "bbor.options.distance", ConfigManager.biomeBordersRenderDistance) .addDisplayValue(1, I18n.format("bbor.options.distance.nearest")) .addDisplayValue(2, I18n.format("bbor.options.distance.nearer")) .addDisplayValue(3, I18n.format("bbor.options.distance.normal"))) .section(I18n.format("bbor.features.mobSpawners"), - (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.features.mobSpawners"), BoundingBoxType.MobSpawner), - (x, width) -> new BoolSettingButton(width, I18n.format("bbor.features.mobSpawners.spawnArea"), ConfigManager.renderMobSpawnerSpawnArea), - (x, width) -> new BoolSettingButton(width, I18n.format("bbor.features.mobSpawners.activationLines"), ConfigManager.renderMobSpawnerActivationLines)) + width -> new BoundingBoxTypeButton(width, I18n.format("bbor.features.mobSpawners"), BoundingBoxType.MobSpawner), + width -> new BoolSettingButton(width, I18n.format("bbor.features.mobSpawners.spawnArea"), ConfigManager.renderMobSpawnerSpawnArea), + width -> new BoolSettingButton(width, I18n.format("bbor.features.mobSpawners.activationLines"), ConfigManager.renderMobSpawnerActivationLines)) .section(I18n.format("bbor.sections.beaconsAndConduits"), - (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.features.beacons"), BoundingBoxType.Beacon), - (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.features.conduits"), BoundingBoxType.Conduit), - (x, width) -> new BoolSettingButton(width, I18n.format("bbor.features.conduits.mobHarmArea"), ConfigManager.renderConduitMobHarmArea)) + width -> new BoundingBoxTypeButton(width, I18n.format("bbor.features.beacons"), BoundingBoxType.Beacon), + width -> new BoundingBoxTypeButton(width, I18n.format("bbor.features.conduits"), BoundingBoxType.Conduit), + width -> new BoolSettingButton(width, I18n.format("bbor.features.conduits.mobHarmArea"), ConfigManager.renderConduitMobHarmArea)) .section(I18n.format("bbor.features.spawnableBlocks"), - (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.features.spawnableBlocks"), BoundingBoxType.SpawnableBlocks), - (x, width) -> new IntSettingSlider(width, 1, 3, "bbor.options.distance.y", ConfigManager.spawnableBlocksRenderHeight) + width -> new BoundingBoxTypeButton(width, I18n.format("bbor.features.spawnableBlocks"), BoundingBoxType.SpawnableBlocks), + width -> new IntSettingSlider(width, 1, 3, "bbor.options.distance.y", ConfigManager.spawnableBlocksRenderHeight) .addDisplayValue(1, "2") .addDisplayValue(2, "4") .addDisplayValue(3, "8"), - (x, width) -> new IntSettingSlider(width, 1, 3, "bbor.options.distance.xz", ConfigManager.spawnableBlocksRenderWidth) + width -> new IntSettingSlider(width, 1, 3, "bbor.options.distance.xz", ConfigManager.spawnableBlocksRenderWidth) .addDisplayValue(1, "8") .addDisplayValue(2, "16") .addDisplayValue(3, "32")) .section(I18n.format("bbor.features.spawningSpheres"), - (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.features.spawningSpheres"), BoundingBoxType.AFKSphere), - (x, width) -> new BoolSettingButton(width, I18n.format("bbor.features.spawnableBlocks"), ConfigManager.renderAFKSpawnableBlocks)) + width -> new BoundingBoxTypeButton(width, I18n.format("bbor.features.spawningSpheres"), BoundingBoxType.AFKSphere), + width -> new BoolSettingButton(width, I18n.format("bbor.features.spawnableBlocks"), ConfigManager.renderAFKSpawnableBlocks)) .section(I18n.format("bbor.tabs.structures"), - (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.desertTemples"), BoundingBoxType.DesertTemple), - (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.jungleTemples"), BoundingBoxType.JungleTemple), - (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.witchHuts"), BoundingBoxType.WitchHut), - (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.mansions"), BoundingBoxType.Mansion), - (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.monuments"), BoundingBoxType.OceanMonument), - (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.igloos"), BoundingBoxType.Igloo), - (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.oceanRuins"), BoundingBoxType.OceanRuin), - (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.buriedTreasure"), BoundingBoxType.BuriedTreasure), - (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.shipwrecks"), BoundingBoxType.Shipwreck), - (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.strongholds"), BoundingBoxType.Stronghold), - (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.mineshafts"), BoundingBoxType.MineShaft), - (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.villages"), BoundingBoxType.Village), - (x, width) -> version.matches(pillagerOutpostVersionPattern) ? new BoundingBoxTypeButton(width, I18n.format("bbor.structures.pillagerOutposts"), BoundingBoxType.PillagerOutpost) : null, - (x, width) -> version.matches(bastionRemnantVersionPattern) ? new BoundingBoxTypeButton(width, I18n.format("bbor.structures.ruinedPortal"), BoundingBoxType.RuinedPortal) : null, - (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.fortresses"), BoundingBoxType.NetherFortress), - (x, width) -> version.matches(netherFossilVersionPattern) ? new BoundingBoxTypeButton(width, I18n.format("bbor.structures.netherFossils"), BoundingBoxType.NetherFossil) : null, - (x, width) -> version.matches(bastionRemnantVersionPattern) ? new BoundingBoxTypeButton(width, I18n.format("bbor.structures.bastionRemnants"), BoundingBoxType.BastionRemnant) : null, - (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.endCities"), BoundingBoxType.EndCity)); + width -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.desertTemples"), BoundingBoxType.DesertTemple), + width -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.jungleTemples"), BoundingBoxType.JungleTemple), + width -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.witchHuts"), BoundingBoxType.WitchHut), + width -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.mansions"), BoundingBoxType.Mansion), + width -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.monuments"), BoundingBoxType.OceanMonument), + width -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.igloos"), BoundingBoxType.Igloo), + width -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.oceanRuins"), BoundingBoxType.OceanRuin), + width -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.buriedTreasure"), BoundingBoxType.BuriedTreasure), + width -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.shipwrecks"), BoundingBoxType.Shipwreck), + width -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.strongholds"), BoundingBoxType.Stronghold), + width -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.mineshafts"), BoundingBoxType.MineShaft), + width -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.villages"), BoundingBoxType.Village), + width -> version.matches(pillagerOutpostVersionPattern) ? new BoundingBoxTypeButton(width, I18n.format("bbor.structures.pillagerOutposts"), BoundingBoxType.PillagerOutpost) : null, + width -> version.matches(bastionRemnantVersionPattern) ? new BoundingBoxTypeButton(width, I18n.format("bbor.structures.ruinedPortal"), BoundingBoxType.RuinedPortal) : null, + width -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.fortresses"), BoundingBoxType.NetherFortress), + width -> version.matches(netherFossilVersionPattern) ? new BoundingBoxTypeButton(width, I18n.format("bbor.structures.netherFossils"), BoundingBoxType.NetherFossil) : null, + width -> version.matches(bastionRemnantVersionPattern) ? new BoundingBoxTypeButton(width, I18n.format("bbor.structures.bastionRemnants"), BoundingBoxType.BastionRemnant) : null, + width -> new BoundingBoxTypeButton(width, I18n.format("bbor.structures.endCities"), BoundingBoxType.EndCity)); + return controlList; } } diff --git a/src/main/java/com/irtimaled/bbor/client/gui/WorldSaveRow.java b/src/main/java/com/irtimaled/bbor/client/gui/WorldSaveRow.java index 5dde418..f0268e4 100644 --- a/src/main/java/com/irtimaled/bbor/client/gui/WorldSaveRow.java +++ b/src/main/java/com/irtimaled/bbor/client/gui/WorldSaveRow.java @@ -21,6 +21,7 @@ import java.io.InputStream; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.function.Consumer; public class WorldSaveRow extends ControlListEntry implements Comparable { private static final Logger LOGGER = LogManager.getLogger(); @@ -30,15 +31,17 @@ public class WorldSaveRow extends ControlListEntry implements Comparable setSelectedEntry; private final ResourceLocation iconLocation; private final DynamicTexture icon; private File iconFile; private long lastClickTime; - WorldSaveRow(WorldSummary worldSummary, SaveFormat saveLoader) { + WorldSaveRow(WorldSummary worldSummary, SaveFormat saveLoader, Consumer setSelectedEntry) { this.worldSummary = worldSummary; this.saveLoader = saveLoader; + this.setSelectedEntry = setSelectedEntry; this.client = Minecraft.getInstance(); this.iconLocation = new ResourceLocation("worlds/" + Hashing.sha1().hashUnencodedChars(worldSummary.getFileName()) + "/icon"); this.iconFile = saveLoader.getFile(worldSummary.getFileName(), "icon.png"); @@ -49,24 +52,29 @@ public class WorldSaveRow extends ControlListEntry implements Comparable this.getX() && + mouseX < this.getX() + ControlList.CONTROLS_WIDTH && + mouseY > this.getY() && + mouseY < this.getY() + this.getControlHeight(); + } + @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - this.list.setSelectedIndex(this.index); + if (!isMouseOver(mouseX, mouseY)) return false; + + this.setSelectedEntry.accept(this); if (Util.milliTime() - this.lastClickTime < 250L) { - loadWorld(); - return true; + done(); } else { this.lastClickTime = Util.milliTime(); - return false; } + return true; } @Override - public boolean mouseReleased(double mouseX, double mouseY, int button) { - return false; - } - - void loadWorld() { + public void done() { String fileName = this.worldSummary.getFileName(); WorldInfo worldInfo = saveLoader.getWorldInfo(fileName); long seed = worldInfo.getSeed(); @@ -105,14 +113,9 @@ public class WorldSaveRow extends ControlListEntry implements Comparable= top && button.y < bottom) button.y -= 12; } - this.addButton(new SettingsScreenButton(this.width / 2 - 155, top + 84, 150, "BBOR", this)); + SettingsScreenButton button = new SettingsScreenButton(this.width / 2 - 155, top + 84, 150, "BBOR", this); + this.buttons.add(this.buttons.size() - 1, button); + this.children.add(this.children.size() - 1, button); } } -- 2.44.0