aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/SyncedGuiDescription.java52
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/client/BackgroundPainter.java44
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/client/CottonClientScreen.java75
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/client/CottonHud.java57
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/client/CottonInventoryScreen.java73
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/client/LibGui.java20
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/client/LightweightGuiDescription.java2
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/client/NinePatch.java135
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/client/ScreenDrawing.java219
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/client/TextHoverRendererScreen.java11
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/client/modmenu/package-info.java4
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/impl/CottonScreenImpl.java24
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/impl/MouseInputHandler.java112
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/impl/access/ScreenAccessor.java16
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/impl/access/package-info.java3
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/impl/client/LibGuiClient.java (renamed from src/main/java/io/github/cottonmc/cotton/gui/client/LibGuiClient.java)6
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/impl/client/LibGuiConfig.java (renamed from src/main/java/io/github/cottonmc/cotton/gui/client/LibGuiConfig.java)2
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/impl/client/NinePatchInternals.java103
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/impl/client/modmenu/ConfigGui.java (renamed from src/main/java/io/github/cottonmc/cotton/gui/client/modmenu/ConfigGui.java)4
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/impl/client/modmenu/ModMenuSupport.java (renamed from src/main/java/io/github/cottonmc/cotton/gui/client/modmenu/ModMenuSupport.java)2
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/impl/client/modmenu/WKirbSprite.java (renamed from src/main/java/io/github/cottonmc/cotton/gui/client/modmenu/WKirbSprite.java)10
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/impl/client/modmenu/package-info.java7
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/impl/client/package-info.java9
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/impl/package-info.java3
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/TooltipBuilder.java117
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WAbstractSlider.java19
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WBar.java20
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java8
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WCardPanel.java10
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WClippedPanel.java2
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WDynamicLabel.java4
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java2
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java18
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WLabeledSlider.java25
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WPanel.java76
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WScrollBar.java49
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WSlider.java22
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WSprite.java15
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WTabPanel.java191
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WText.java20
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WTextField.java220
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WTiledSprite.java4
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WToggleButton.java12
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java57
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/data/InputResult.java12
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/data/Tab.java189
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/icon/TextureIcon.java2
-rw-r--r--src/main/resources/fabric.mod.json4
-rw-r--r--src/main/resources/mixins.libgui.accessors.json1
49 files changed, 1058 insertions, 1034 deletions
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/SyncedGuiDescription.java b/src/main/java/io/github/cottonmc/cotton/gui/SyncedGuiDescription.java
index ce0dd4b..fae723e 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/SyncedGuiDescription.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/SyncedGuiDescription.java
@@ -26,7 +26,7 @@ import net.minecraft.server.world.ServerWorld;
import net.minecraft.world.World;
import io.github.cottonmc.cotton.gui.client.BackgroundPainter;
-import io.github.cottonmc.cotton.gui.client.LibGuiClient;
+import io.github.cottonmc.cotton.gui.client.LibGui;
import io.github.cottonmc.cotton.gui.networking.NetworkSide;
import io.github.cottonmc.cotton.gui.widget.WGridPanel;
import io.github.cottonmc.cotton.gui.widget.WLabel;
@@ -80,7 +80,7 @@ public class SyncedGuiDescription extends ScreenHandler implements GuiDescriptio
}
public int getTitleColor() {
- return (world.isClient && LibGuiClient.config.darkMode) ? darkTitleColor : titleColor;
+ return (world.isClient && LibGui.isDarkMode()) ? darkTitleColor : titleColor;
}
public SyncedGuiDescription setRootPanel(WPanel panel) {
@@ -164,7 +164,7 @@ public class SyncedGuiDescription extends ScreenHandler implements GuiDescriptio
/** WILL MODIFY toInsert! Returns true if anything was inserted. */
private boolean insertIntoExisting(ItemStack toInsert, Slot slot, PlayerEntity player) {
ItemStack curSlotStack = slot.getStack();
- if (!curSlotStack.isEmpty() && canStacksCombine(toInsert, curSlotStack) && slot.canInsert(toInsert)) {
+ if (!curSlotStack.isEmpty() && ItemStack.canCombine(toInsert, curSlotStack) && slot.canInsert(toInsert)) {
int combinedAmount = curSlotStack.getCount() + toInsert.getCount();
int maxAmount = Math.min(toInsert.getMaxCount(), slot.getMaxItemCount());
if (combinedAmount <= maxAmount) {
@@ -299,52 +299,6 @@ public class SyncedGuiDescription extends ScreenHandler implements GuiDescriptio
}
@Nullable
- public WWidget doMouseUp(int x, int y, int state) {
- if (rootPanel!=null) return rootPanel.onMouseUp(x, y, state);
- return null;
- }
-
- @Nullable
- public WWidget doMouseDown(int x, int y, int button) {
- if (rootPanel!=null) return rootPanel.onMouseDown(x, y, button);
- return null;
- }
-
- public void doMouseDrag(int x, int y, int button, double deltaX, double deltaY) {
- if (rootPanel!=null) rootPanel.onMouseDrag(x, y, button, deltaX, deltaY);
- }
-
- public void doClick(int x, int y, int button) {
- if (focus!=null) {
- int wx = focus.getAbsoluteX();
- int wy = focus.getAbsoluteY();
-
- if (x>=wx && x<wx+focus.getWidth() && y>=wy && y<wy+focus.getHeight()) {
- //Do nothing, focus will get the click soon
- } else {
- //Invalidate the component first
- WWidget lastFocus = focus;
- focus = null;
- lastFocus.onFocusLost();
- }
- }
-
- //if (rootPanel!=null) rootPanel.onClick(x, y, button);
- }
-
- public void doCharType(char ch) {
- if (focus!=null) focus.onCharTyped(ch);
- }
-
- //public void doKeyPress(int key) {
- // if (focus!=null) focus.onKeyPressed(key);
- //}
-
- //public void doKeyRelease(int key) {
- // if (focus!=null) focus.onKeyReleased(key);
- //}
-
- @Nullable
@Override
public PropertyDelegate getPropertyDelegate() {
return propertyDelegate;
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/BackgroundPainter.java b/src/main/java/io/github/cottonmc/cotton/gui/client/BackgroundPainter.java
index f00bf80..13ca534 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/client/BackgroundPainter.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/client/BackgroundPainter.java
@@ -1,5 +1,6 @@
package io.github.cottonmc.cotton.gui.client;
+import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Identifier;
import io.github.cottonmc.cotton.gui.widget.WItemSlot;
@@ -13,11 +14,12 @@ import io.github.cottonmc.cotton.gui.widget.WWidget;
public interface BackgroundPainter {
/**
* Paint the specified panel to the screen.
+ * @param matrices The rendering matrix stack
* @param left The absolute position of the left of the panel, in gui-screen coordinates
* @param top The absolute position of the top of the panel, in gui-screen coordinates
* @param panel The panel being painted
*/
- public void paintBackground(int left, int top, WWidget panel);
+ public void paintBackground(MatrixStack matrices, int left, int top, WWidget panel);
/**
* The {@code VANILLA} background painter draws a vanilla-like gui panel using {@linkplain NinePatch nine-patch textures}.
@@ -40,9 +42,9 @@ public interface BackgroundPainter {
/**
* The {@code SLOT} background painter draws item slots or slot-like widgets.
*/
- public static BackgroundPainter SLOT = (left, top, panel) -> {
+ public static BackgroundPainter SLOT = (matrices, left, top, panel) -> {
if (!(panel instanceof WItemSlot)) {
- ScreenDrawing.drawBeveledPanel(left-1, top-1, panel.getWidth()+2, panel.getHeight()+2, 0xB8000000, 0x4C000000, 0xB8FFFFFF);
+ ScreenDrawing.drawBeveledPanel(matrices, left-1, top-1, panel.getWidth()+2, panel.getHeight()+2, 0xB8000000, 0x4C000000, 0xB8FFFFFF);
} else {
WItemSlot slot = (WItemSlot)panel;
for(int x = 0; x < slot.getWidth()/18; ++x) {
@@ -53,26 +55,26 @@ public interface BackgroundPainter {
//this will cause a slightly discolored bottom border on vanilla backgrounds but it's necessary for color support, it shouldn't be *too* visible unless you're looking for it
int hi = 0xB8FFFFFF;
if (slot.isBigSlot()) {
- ScreenDrawing.drawBeveledPanel((x * 18) + left - 4, (y * 18) + top - 4, 26, 26,
+ ScreenDrawing.drawBeveledPanel(matrices, (x * 18) + left - 4, (y * 18) + top - 4, 26, 26,
lo, bg, hi);
if (slot.getFocusedSlot() == index) {
int sx = (x * 18) + left - 4;
int sy = (y * 18) + top - 4;
- ScreenDrawing.coloredRect(sx, sy, 26, 1, 0xFF_FFFFA0);
- ScreenDrawing.coloredRect(sx, sy + 1, 1, 26 - 1, 0xFF_FFFFA0);
- ScreenDrawing.coloredRect(sx + 26 - 1, sy + 1, 1, 26 - 1, 0xFF_FFFFA0);
- ScreenDrawing.coloredRect(sx + 1, sy + 26 - 1, 26 - 1, 1, 0xFF_FFFFA0);
+ ScreenDrawing.coloredRect(matrices, sx, sy, 26, 1, 0xFF_FFFFA0);
+ ScreenDrawing.coloredRect(matrices, sx, sy + 1, 1, 26 - 1, 0xFF_FFFFA0);
+ ScreenDrawing.coloredRect(matrices, sx + 26 - 1, sy + 1, 1, 26 - 1, 0xFF_FFFFA0);
+ ScreenDrawing.coloredRect(matrices, sx + 1, sy + 26 - 1, 26 - 1, 1, 0xFF_FFFFA0);
}
} else {
- ScreenDrawing.drawBeveledPanel((x * 18) + left, (y * 18) + top, 16+2, 16+2,
+ ScreenDrawing.drawBeveledPanel(matrices, (x * 18) + left, (y * 18) + top, 16+2, 16+2,
lo, bg, hi);
if (slot.getFocusedSlot() == index) {
int sx = (x * 18) + left;
int sy = (y * 18) + top;
- ScreenDrawing.coloredRect(sx, sy, 18, 1, 0xFF_FFFFA0);
- ScreenDrawing.coloredRect(sx, sy + 1, 1, 18 - 1, 0xFF_FFFFA0);
- ScreenDrawing.coloredRect(sx + 18 - 1, sy + 1, 1, 18 - 1, 0xFF_FFFFA0);
- ScreenDrawing.coloredRect(sx + 1, sy + 18 - 1, 18 - 1, 1, 0xFF_FFFFA0);
+ ScreenDrawing.coloredRect(matrices, sx, sy, 18, 1, 0xFF_FFFFA0);
+ ScreenDrawing.coloredRect(matrices, sx, sy + 1, 1, 18 - 1, 0xFF_FFFFA0);
+ ScreenDrawing.coloredRect(matrices, sx + 18 - 1, sy + 1, 1, 18 - 1, 0xFF_FFFFA0);
+ ScreenDrawing.coloredRect(matrices, sx + 1, sy + 18 - 1, 18 - 1, 1, 0xFF_FFFFA0);
}
}
}
@@ -85,11 +87,11 @@ public interface BackgroundPainter {
*
* @param panelColor the panel background color
* @return a colorful gui panel painter
- * @see ScreenDrawing#drawGuiPanel(int, int, int, int, int)
+ * @see ScreenDrawing#drawGuiPanel(MatrixStack, int, int, int, int, int)
*/
public static BackgroundPainter createColorful(int panelColor) {
- return (left, top, panel) -> {
- ScreenDrawing.drawGuiPanel(left-8, top-8, panel.getWidth()+16, panel.getHeight()+16, panelColor);
+ return (matrices, left, top, panel) -> {
+ ScreenDrawing.drawGuiPanel(matrices, left-8, top-8, panel.getWidth()+16, panel.getHeight()+16, panelColor);
};
}
@@ -101,11 +103,11 @@ public interface BackgroundPainter {
* @return a colorful gui panel painter
*/
public static BackgroundPainter createColorful(int panelColor, float contrast) {
- return (left, top, panel) -> {
+ return (matrices, left, top, panel) -> {
int shadowColor = ScreenDrawing.multiplyColor(panelColor, 1.0f - contrast);
int hilightColor = ScreenDrawing.multiplyColor(panelColor, 1.0f + contrast);
- ScreenDrawing.drawGuiPanel(left-8, top-8, panel.getWidth()+16, panel.getHeight()+16, shadowColor, panelColor, hilightColor, 0xFF000000);
+ ScreenDrawing.drawGuiPanel(matrices, left-8, top-8, panel.getWidth()+16, panel.getHeight()+16, shadowColor, panelColor, hilightColor, 0xFF000000);
};
}
@@ -146,9 +148,9 @@ public interface BackgroundPainter {
* @since 1.5.0
*/
public static BackgroundPainter createLightDarkVariants(BackgroundPainter light, BackgroundPainter dark) {
- return (left, top, panel) -> {
- if (LibGuiClient.config.darkMode) dark.paintBackground(left, top, panel);
- else light.paintBackground(left, top, panel);
+ return (matrices, left, top, panel) -> {
+ if (LibGui.isDarkMode()) dark.paintBackground(matrices, left, top, panel);
+ else light.paintBackground(matrices, left, top, panel);
};
}
}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/CottonClientScreen.java b/src/main/java/io/github/cottonmc/cotton/gui/client/CottonClientScreen.java
index 055262e..cdb65af 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/client/CottonClientScreen.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/client/CottonClientScreen.java
@@ -7,11 +7,14 @@ import net.minecraft.text.Style;
import net.minecraft.text.Text;
import io.github.cottonmc.cotton.gui.GuiDescription;
+import io.github.cottonmc.cotton.gui.impl.CottonScreenImpl;
+import io.github.cottonmc.cotton.gui.impl.MouseInputHandler;
import io.github.cottonmc.cotton.gui.widget.WPanel;
import io.github.cottonmc.cotton.gui.widget.WWidget;
+import org.jetbrains.annotations.Nullable;
import org.lwjgl.opengl.GL11;
-public class CottonClientScreen extends Screen implements TextHoverRendererScreen {
+public class CottonClientScreen extends Screen implements CottonScreenImpl {
protected GuiDescription description;
protected int left = 0;
protected int top = 0;
@@ -63,6 +66,17 @@ public class CottonClientScreen extends Screen implements TextHoverRendererScree
this.client.keyboard.setRepeatEvents(false);
}
+ @Nullable
+ @Override
+ public WWidget getLastResponder() {
+ return lastResponder;
+ }
+
+ @Override
+ public void setLastResponder(@Nullable WWidget lastResponder) {
+ this.lastResponder = lastResponder;
+ }
+
/**
* Repositions the root panel.
*
@@ -157,68 +171,46 @@ public class CottonClientScreen extends Screen implements TextHoverRendererScree
}
}
- boolean result = super.mouseClicked(mouseX, mouseY, mouseButton);
+ super.mouseClicked(mouseX, mouseY, mouseButton);
int containerX = (int)mouseX-left;
int containerY = (int)mouseY-top;
- if (containerX<0 || containerY<0 || containerX>=width || containerY>=height) return result;
- if (lastResponder==null) {
- lastResponder = description.getRootPanel().hit(containerX, containerY);
- if (lastResponder!=null) lastResponder.onMouseDown(containerX-lastResponder.getAbsoluteX(), containerY-lastResponder.getAbsoluteY(), mouseButton);
- } else {
- //This is a drag instead
- }
- return result;
-
+ if (containerX<0 || containerY<0 || containerX>=width || containerY>=height) return true;
+ MouseInputHandler.onMouseDown(description, this, containerX, containerY, mouseButton);
+
+ return true;
}
@Override
public boolean mouseReleased(double mouseX, double mouseY, int mouseButton) {
if (description.getRootPanel()==null) return super.mouseReleased(mouseX, mouseY, mouseButton);
- boolean result = super.mouseReleased(mouseX, mouseY, mouseButton);
+ super.mouseReleased(mouseX, mouseY, mouseButton);
int containerX = (int)mouseX-left;
int containerY = (int)mouseY-top;
-
- if (lastResponder!=null) {
- lastResponder.onMouseUp(containerX-lastResponder.getAbsoluteX(), containerY-lastResponder.getAbsoluteY(), mouseButton);
- if (containerX>=0 && containerY>=0 && containerX<width && containerY<height) {
- lastResponder.onClick(containerX-lastResponder.getAbsoluteX(), containerY-lastResponder.getAbsoluteY(), mouseButton);
- }
- } else {
- description.getRootPanel().onMouseUp(containerX, containerY, mouseButton);
- }
-
- lastResponder = null;
- return result;
+ MouseInputHandler.onMouseUp(description, this, containerX, containerY, mouseButton);
+
+ return true;
}
@Override
public boolean mouseDragged(double mouseX, double mouseY, int mouseButton, double deltaX, double deltaY) {
if (description.getRootPanel()==null) return super.mouseDragged(mouseX, mouseY, mouseButton, deltaX, deltaY);
- boolean result = super.mouseDragged(mouseX, mouseY, mouseButton, deltaX, deltaY);
+ super.mouseDragged(mouseX, mouseY, mouseButton, deltaX, deltaY);
int containerX = (int)mouseX-left;
int containerY = (int)mouseY-top;
-
- if (lastResponder!=null) {
- lastResponder.onMouseDrag(containerX-lastResponder.getAbsoluteX(), containerY-lastResponder.getAbsoluteY(), mouseButton, deltaX, deltaY);
- return result;
- } else {
- if (containerX<0 || containerY<0 || containerX>=width || containerY>=height) return result;
- description.getRootPanel().onMouseDrag(containerX, containerY, mouseButton, deltaX, deltaY);
- }
- return result;
+ MouseInputHandler.onMouseDrag(description, this, containerX, containerY, mouseButton, deltaX, deltaY);
+
+ return true;
}
@Override
public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
if (description.getRootPanel()==null) return super.mouseScrolled(mouseX, mouseY, amount);
- WPanel root = description.getRootPanel();
int containerX = (int)mouseX-left;
int containerY = (int)mouseY-top;
-
- WWidget child = root.hit(containerX, containerY);
- child.onMouseScroll(containerX - child.getAbsoluteX(), containerY - child.getAbsoluteY(), amount);
+ MouseInputHandler.onMouseScroll(description, containerX, containerY, amount);
+
return true;
}
@@ -226,12 +218,9 @@ public class CottonClientScreen extends Screen implements TextHoverRendererScree
public void mouseMoved(double mouseX, double mouseY) {
if (description.getRootPanel()==null) return;
- WPanel root = description.getRootPanel();
int containerX = (int)mouseX-left;
int containerY = (int)mouseY-top;
-
- WWidget child = root.hit(containerX, containerY);
- child.onMouseMove(containerX - child.getAbsoluteX(), containerY - child.getAbsoluteY());
+ MouseInputHandler.onMouseMove(description, containerX, containerY);
}
@Override
@@ -262,7 +251,7 @@ public class CottonClientScreen extends Screen implements TextHoverRendererScree
//}
@Override
- public void renderTextHover(MatrixStack matrices, Style textStyle, int x, int y) {
+ public void renderTextHover(MatrixStack matrices, @Nullable Style textStyle, int x, int y) {
renderTextHoverEffect(matrices, textStyle, x, y);
}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/CottonHud.java b/src/main/java/io/github/cottonmc/cotton/gui/client/CottonHud.java
index 79111d2..f69bb65 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/client/CottonHud.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/client/CottonHud.java
@@ -6,7 +6,6 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.util.Window;
-import net.minecraft.client.util.math.MatrixStack;
import io.github.cottonmc.cotton.gui.widget.WWidget;
@@ -19,27 +18,40 @@ import java.util.Set;
* Manages widgets that are painted on the in-game HUD.
*/
@Environment(EnvType.CLIENT)
-public enum CottonHud implements HudRenderCallback {
- INSTANCE; // TODO (4.0): Migrate from singleton to static methods
+public final class CottonHud {
+ private CottonHud() {}
+
+ private static final Set<WWidget> widgets = new HashSet<>();
+ private static final Map<WWidget, Positioner> positioners = new HashMap<>();
static {
- HudRenderCallback.EVENT.register(INSTANCE);
+ HudRenderCallback.EVENT.register((matrices, tickDelta) -> {
+ Window window = MinecraftClient.getInstance().getWindow();
+ int hudWidth = window.getScaledWidth();
+ int hudHeight = window.getScaledHeight();
+ for (WWidget widget : widgets) {
+ Positioner positioner = positioners.get(widget);
+ if (positioner != null) {
+ positioner.reposition(widget, hudWidth, hudHeight);
+ }
+
+ widget.paint(matrices, widget.getX(), widget.getY(), -1, -1);
+ }
+ });
+
ClientTickEvents.END_CLIENT_TICK.register(client -> {
- for (WWidget widget : INSTANCE.widgets) {
+ for (WWidget widget : widgets) {
widget.tick();
}
});
}
- private final Set<WWidget> widgets = new HashSet<>();
- private final Map<WWidget, Positioner> positioners = new HashMap<>();
-
/**
* Adds a new widget to the HUD.
*
* @param widget the widget
*/
- public void add(WWidget widget) {
+ public static void add(WWidget widget) {
widgets.add(widget);
}
@@ -51,7 +63,7 @@ public enum CottonHud implements HudRenderCallback {
* @param y the y offset
* @see Positioner#of documentation about the offsets
*/
- public void add(WWidget widget, int x, int y) {
+ public static void add(WWidget widget, int x, int y) {
add(widget, Positioner.of(x, y));
}
@@ -65,7 +77,7 @@ public enum CottonHud implements HudRenderCallback {
* @param height the height of the widget
* @see Positioner#of documentation about the offsets
*/
- public void add(WWidget widget, int x, int y, int width, int height) {
+ public static void add(WWidget widget, int x, int y, int width, int height) {
add(widget, Positioner.of(x, y));
widget.setSize(width, height);
}
@@ -76,7 +88,7 @@ public enum CottonHud implements HudRenderCallback {
* @param widget the widget
* @param positioner the positioner
*/
- public void add(WWidget widget, Positioner positioner) {
+ public static void add(WWidget widget, Positioner positioner) {
widgets.add(widget);
setPositioner(widget, positioner);
}
@@ -89,7 +101,7 @@ public enum CottonHud implements HudRenderCallback {
* @param width the width of the widget
* @param height the height of the widget
*/
- public void add(WWidget widget, Positioner positioner, int width, int height) {
+ public static void add(WWidget widget, Positioner positioner, int width, int height) {
widgets.add(widget);
widget.setSize(width, height);
setPositioner(widget, positioner);
@@ -101,7 +113,7 @@ public enum CottonHud implements HudRenderCallback {
* @param widget the widget
* @param positioner the positioner
*/
- public void setPositioner(WWidget widget, Positioner positioner) {
+ public static void setPositioner(WWidget widget, Positioner positioner) {
positioners.put(widget, positioner);
}
@@ -110,25 +122,10 @@ public enum CottonHud implements HudRenderCallback {
*
* @param widget the widget
*/
- public void remove(WWidget widget) {
+ public static void remove(WWidget widget) {
widgets.remove(widget);
}
- @Override
- public void onHudRender(MatrixStack matrices, float tickDelta) {
- Window window = MinecraftClient.getInstance().getWindow();
- int hudWidth = window.getScaledWidth();
- int hudHeight = window.getScaledHeight();
- for (WWidget widget : widgets) {
- Positioner positioner = positioners.get(widget);
- if (positioner != null) {
- positioner.reposition(widget, hudWidth, hudHeight);
- }
-
- widget.paint(matrices, widget.getX(), widget.getY(), -1, -1);
- }
- }
-
/**
* Positioners can be used to change the position of a widget based on the window dimensions.
*/
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/CottonInventoryScreen.java b/src/main/java/io/github/cottonmc/cotton/gui/client/CottonInventoryScreen.java
index 5b36a66..f6c1429 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/client/CottonInventoryScreen.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/client/CottonInventoryScreen.java
@@ -9,8 +9,11 @@ import net.minecraft.text.Style;
import net.minecraft.text.Text;
import io.github.cottonmc.cotton.gui.SyncedGuiDescription;
+import io.github.cottonmc.cotton.gui.impl.CottonScreenImpl;
+import io.github.cottonmc.cotton.gui.impl.MouseInputHandler;
import io.github.cottonmc.cotton.gui.widget.WPanel;
import io.github.cottonmc.cotton.gui.widget.WWidget;
+import org.jetbrains.annotations.Nullable;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.opengl.GL11;
@@ -19,7 +22,7 @@ import org.lwjgl.opengl.GL11;
*
* @param <T> the description type
*/
-public class CottonInventoryScreen<T extends SyncedGuiDescription> extends HandledScreen<T> implements TextHoverRendererScreen {
+public class CottonInventoryScreen<T extends SyncedGuiDescription> extends HandledScreen<T> implements CottonScreenImpl {
protected SyncedGuiDescription description;
protected WWidget lastResponder = null;
@@ -41,7 +44,7 @@ public class CottonInventoryScreen<T extends SyncedGuiDescription> extends Handl
* @param title the screen title
*/
public CottonInventoryScreen(T description, PlayerEntity player, Text title) {
- super(description, player.inventory, title);
+ super(description, player.getInventory(), title);
this.description = description;
width = 18*9;
height = 18*9;
@@ -77,6 +80,17 @@ public class CottonInventoryScreen<T extends SyncedGuiDescription> extends Handl
this.client.keyboard.setRepeatEvents(false);
}
+ @Nullable
+ @Override
+ public WWidget getLastResponder() {
+ return lastResponder;
+ }
+
+ @Override
+ public void setLastResponder(@Nullable WWidget lastResponder) {
+ this.lastResponder = lastResponder;
+ }
+
/**
* Clears the heavyweight peers of this screen's GUI description.
*/
@@ -177,60 +191,40 @@ public class CottonInventoryScreen<T extends SyncedGuiDescription> extends Handl
int containerX = (int)mouseX-x;
int containerY = (int)mouseY-y;
if (containerX<0 || containerY<0 || containerX>=width || containerY>=height) return result;
- if (lastResponder==null) {
- lastResponder = description.doMouseDown(containerX, containerY, mouseButton);
- } else {
- //This is a drag instead
- }
- return result;
+ MouseInputHandler.onMouseDown(description, this, containerX, containerY, mouseButton);
+
+ return true;
}
@Override
public boolean mouseReleased(double mouseX, double mouseY, int mouseButton) { //Testing shows that STATE IS ACTUALLY BUTTON
- boolean result = super.mouseReleased(mouseX, mouseY, mouseButton);
+ super.mouseReleased(mouseX, mouseY, mouseButton);
int containerX = (int)mouseX-x;
int containerY = (int)mouseY-y;
-
- if (lastResponder!=null) {
- lastResponder.onMouseUp(containerX-lastResponder.getAbsoluteX(), containerY-lastResponder.getAbsoluteY(), mouseButton);
- if (containerX>=0 && containerY>=0 && containerX<width && containerY<height) {
- lastResponder.onClick(containerX-lastResponder.getAbsoluteX(), containerY-lastResponder.getAbsoluteY(), mouseButton);
- }
- } else {
- description.doMouseUp(containerX, containerY, mouseButton);
- }
-
- lastResponder = null;
- return result;
+ MouseInputHandler.onMouseUp(description, this, containerX, containerY, mouseButton);
+
+ return true;
}
@Override
public boolean mouseDragged(double mouseX, double mouseY, int mouseButton, double deltaX, double deltaY) {
- boolean result = super.mouseDragged(mouseX, mouseY, mouseButton, deltaX, deltaY);
+ super.mouseDragged(mouseX, mouseY, mouseButton, deltaX, deltaY);
int containerX = (int)mouseX-x;
int containerY = (int)mouseY-y;
-
- if (lastResponder!=null) {
- lastResponder.onMouseDrag(containerX-lastResponder.getAbsoluteX(), containerY-lastResponder.getAbsoluteY(), mouseButton, deltaX, deltaY);
- return result;
- } else {
- if (containerX<0 || containerY<0 || containerX>=width || containerY>=height) return result;
- description.doMouseDrag(containerX, containerY, mouseButton, deltaX, deltaY);
- }
- return result;
+ MouseInputHandler.onMouseDrag(description, this, containerX, containerY, mouseButton, deltaX, deltaY);
+
+ return true;
}
@Override
public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
if (description.getRootPanel()==null) return super.mouseScrolled(mouseX, mouseY, amount);
-
- WPanel root = description.getRootPanel();
+
int containerX = (int)mouseX-x;
int containerY = (int)mouseY-y;
-
- WWidget child = root.hit(containerX, containerY);
- child.onMouseScroll(containerX - child.getAbsoluteX(), containerY - child.getAbsoluteY(), amount);
+ MouseInputHandler.onMouseScroll(description, containerX, containerY, amount);
+
return true;
}
@@ -238,12 +232,9 @@ public class CottonInventoryScreen<T extends SyncedGuiDescription> extends Handl
public void mouseMoved(double mouseX, double mouseY) {
if (description.getRootPanel()==null) return;
- WPanel root = description.getRootPanel();
int containerX = (int)mouseX-x;
int containerY = (int)mouseY-y;
-
- WWidget child = root.hit(containerX, containerY);
- child.onMouseMove(containerX - child.getAbsoluteX(), containerY - child.getAbsoluteY());
+ MouseInputHandler.onMouseMove(description, containerX, containerY);
}
@Override
@@ -305,7 +296,7 @@ public class CottonInventoryScreen<T extends SyncedGuiDescription> extends Handl
}
@Override
- public void renderTextHover(MatrixStack matrices, Style textStyle, int x, int y) {
+ public void renderTextHover(MatrixStack matrices, @Nullable Style textStyle, int x, int y) {
renderTextHoverEffect(matrices, textStyle, x, y);
}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/LibGui.java b/src/main/java/io/github/cottonmc/cotton/gui/client/LibGui.java
new file mode 100644
index 0000000..b55c0fe
--- /dev/null
+++ b/src/main/java/io/github/cottonmc/cotton/gui/client/LibGui.java
@@ -0,0 +1,20 @@
+package io.github.cottonmc.cotton.gui.client;
+
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
+
+import io.github.cottonmc.cotton.gui.impl.client.LibGuiClient;
+
+/**
+ * Provides access to global LibGui data such as the dark mode state.
+ *
+ * @since 4.0.0
+ */
+@Environment(EnvType.CLIENT)
+public final class LibGui {
+ private LibGui() {}
+
+ public static boolean isDarkMode() {
+ return LibGuiClient.config.darkMode;
+ }
+}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/LightweightGuiDescription.java b/src/main/java/io/github/cottonmc/cotton/gui/client/LightweightGuiDescription.java
index 41b8d49..54ae02f 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/client/LightweightGuiDescription.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/client/LightweightGuiDescription.java
@@ -32,7 +32,7 @@ public class LightweightGuiDescription implements GuiDescription {
@Override
public int getTitleColor() {
- return (LibGuiClient.config.darkMode) ? darkmodeTitleColor : titleColor;
+ return (LibGui.isDarkMode()) ? darkmodeTitleColor : titleColor;
}
@Override
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/NinePatch.java b/src/main/java/io/github/cottonmc/cotton/gui/client/NinePatch.java
index 9057739..8059b35 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/client/NinePatch.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/client/NinePatch.java
@@ -2,24 +2,14 @@ package io.github.cottonmc.cotton.gui.client;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
-import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
-import net.minecraft.resource.Resource;
-import net.minecraft.resource.ResourceManager;
-import net.minecraft.resource.SinglePreparationResourceReloadListener;
+import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
-import net.minecraft.util.profiler.Profiler;
+import io.github.cottonmc.cotton.gui.impl.client.NinePatchInternals;
import io.github.cottonmc.cotton.gui.widget.WWidget;
import org.jetbrains.annotations.Nullable;
-import java.io.InputStream;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-
/**
* The nine-patch background painter paints rectangles using a nine-patch texture.
*
@@ -167,7 +157,7 @@ public class NinePatch implements BackgroundPainter {
}
@Override
- public void paintBackground(int left, int top, WWidget panel) {
+ public void paintBackground(MatrixStack matrices, int left, int top, WWidget panel) {
int width = panel.getWidth() + leftPadding + rightPadding;
int height = panel.getHeight() + topPadding + bottomPadding;
left = left - leftPadding;
@@ -178,12 +168,12 @@ public class NinePatch implements BackgroundPainter {
int y2 = top + height - cornerSize;
float uv1 = cornerUv;
float uv2 = 1.0f - cornerUv;
- Mode mode = this.mode != null ? this.mode : MetadataLoader.INSTANCE.getProperties(texture).getMode();
+ Mode mode = this.mode != null ? this.mode : NinePatchInternals.MetadataLoader.INSTANCE.getProperties(texture).getMode();
- ScreenDrawing.texturedRect(left, top, cornerSize, cornerSize, texture, 0, 0, uv1, uv1, 0xFF_FFFFFF);
- ScreenDrawing.texturedRect(x2, top, cornerSize, cornerSize, texture, uv2, 0, 1, uv1, 0xFF_FFFFFF);
- ScreenDrawing.texturedRect(left, y2, cornerSize, cornerSize, texture, 0, uv2, uv1, 1, 0xFF_FFFFFF);
- ScreenDrawing.texturedRect(x2, y2, cornerSize, cornerSize, texture, uv2, uv2, 1, 1, 0xFF_FFFFFF);
+ ScreenDrawing.texturedRect(matrices, left, top, cornerSize, cornerSize, texture, 0, 0, uv1, uv1, 0xFF_FFFFFF);
+ ScreenDrawing.texturedRect(matrices, x2, top, cornerSize, cornerSize, texture, uv2, 0, 1, uv1, 0xFF_FFFFFF);
+ ScreenDrawing.texturedRect(matrices, left, y2, cornerSize, cornerSize, texture, 0, uv2, uv1, 1, 0xFF_FFFFFF);
+ ScreenDrawing.texturedRect(matrices, x2, y2, cornerSize, cornerSize, texture, uv2, uv2, 1, 1, 0xFF_FFFFFF);
if (mode == Mode.TILING) {
int tileSize = (int) (cornerSize / cornerUv - 2 * cornerSize);
@@ -196,8 +186,8 @@ public class NinePatch implements BackgroundPainter {
int tileWidth = Math.min(widthLeft, tileSize);
float uo = (tileSize - tileWidth) * px; // Used to remove unnecessary pixels on the X axis
- ScreenDrawing.texturedRect(x1 + i * tileSize, top, tileWidth, cornerSize, texture, uv1, 0, uv2 - uo, uv1, 0xFF_FFFFFF);
- ScreenDrawing.texturedRect(x1 + i * tileSize, y2, tileWidth, cornerSize, texture, uv1, uv2, uv2 - uo, 1, 0xFF_FFFFFF);
+ ScreenDrawing.texturedRect(matrices, x1 + i * tileSize, top, tileWidth, cornerSize, texture, uv1, 0, uv2 - uo, uv1, 0xFF_FFFFFF);
+ ScreenDrawing.texturedRect(matrices, x1 + i * tileSize, y2, tileWidth, cornerSize, texture, uv1, uv2, uv2 - uo, 1, 0xFF_FFFFFF);
// Reset the height left each time the Y is looped
heightLeft = height - 2 * cornerSize;
@@ -206,21 +196,21 @@ public class NinePatch implements BackgroundPainter {
int tileHeight = Math.min(heightLeft, tileSize);
float vo = (tileSize - tileHeight) * px; // Used to remove unnecessary pixels on the Y axis
- ScreenDrawing.texturedRect(left, y1 + j * tileSize, cornerSize, tileHeight, texture, 0, uv1, uv1, uv2 - vo, 0xFF_FFFFFF);
- ScreenDrawing.texturedRect(x2, y1 + j * tileSize, cornerSize, tileHeight, texture, uv2, uv1, 1, uv2 - vo, 0xFF_FFFFFF);
+ ScreenDrawing.texturedRect(matrices, left, y1 + j * tileSize, cornerSize, tileHeight, texture, 0, uv1, uv1, uv2 - vo, 0xFF_FFFFFF);
+ ScreenDrawing.texturedRect(matrices, x2, y1 + j * tileSize, cornerSize, tileHeight, texture, uv2, uv1, 1, uv2 - vo, 0xFF_FFFFFF);
- ScreenDrawing.texturedRect(x1 + i * tileSize, y1 + j * tileSize, tileWidth, tileHeight, texture, uv1, uv1, uv2 - uo, uv2 - vo, 0xFF_FFFFFF);
+ ScreenDrawing.texturedRect(matrices, x1 + i * tileSize, y1 + j * tileSize, tileWidth, tileHeight, texture, uv1, uv1, uv2 - uo, uv2 - vo, 0xFF_FFFFFF);
heightLeft -= tileSize;
}
widthLeft -= tileSize;
}
} else {
- ScreenDrawing.texturedRect(x1, top, width - 2 * cornerSize, cornerSize, texture, uv1, 0, uv2, uv1, 0xFF_FFFFFF);
- ScreenDrawing.texturedRect(left, y1, cornerSize, height - 2 * cornerSize, texture, 0, uv1, uv1, uv2, 0xFF_FFFFFF);
- ScreenDrawing.texturedRect(x1, y2, width - 2 * cornerSize, cornerSize, texture, uv1, uv2, uv2, 1, 0xFF_FFFFFF);
- ScreenDrawing.texturedRect(x2, y1, cornerSize, height - 2 * cornerSize, texture, uv2, uv1, 1, uv2, 0xFF_FFFFFF);
+ ScreenDrawing.texturedRect(matrices, x1, top, width - 2 * cornerSize, cornerSize, texture, uv1, 0, uv2, uv1, 0xFF_FFFFFF);
+ ScreenDrawing.texturedRect(matrices, left, y1, cornerSize, height - 2 * cornerSize, texture, 0, uv1, uv1, uv2, 0xFF_FFFFFF);
+ ScreenDrawing.texturedRect(matrices, x1, y2, width - 2 * cornerSize, cornerSize, texture, uv1, uv2, uv2, 1, 0xFF_FFFFFF);
+ ScreenDrawing.texturedRect(matrices, x2, y1, cornerSize, height - 2 * cornerSize, texture, uv2, uv1, 1, uv2, 0xFF_FFFFFF);
- ScreenDrawing.texturedRect(x1, y1, width - 2 * cornerSize, height - 2 * cornerSize, texture, uv1, uv1, uv2, uv2, 0xFF_FFFFFF);
+ ScreenDrawing.texturedRect(matrices, x1, y1, width - 2 * cornerSize, height - 2 * cornerSize, texture, uv1, uv1, uv2, uv2, 0xFF_FFFFFF);
}
}
@@ -239,8 +229,15 @@ public class NinePatch implements BackgroundPainter {
*/
TILING;
+ /**
+ * Deserializes a nine-patch mode from a string.
+ *
+ * @param str the mode string
+ * @return the mode, or null if the string is invalid
+ * @since 4.0.0
+ */
@Nullable
- static Mode fromString(String str) {
+ public static Mode fromString(String str) {
if (str == null) return null;
if (str.equalsIgnoreCase("stretching")) return STRETCHING;
@@ -249,84 +246,4 @@ public class NinePatch implements BackgroundPainter {
return null;
}
}
-
- public static class TextureProperties {
- public static final TextureProperties DEFAULT = new TextureProperties(Mode.STRETCHING);
-
- private final Mode mode;
-
- public TextureProperties(Mode mode) {
- this.mode = mode;
- }
-
- public Mode getMode() {
- return mode;
- }
- }
-
- public static class MetadataLoader extends SinglePreparationResourceReloadListener<Map<Identifier, Properties>> implements IdentifiableResourceReloadListener {
- public static final MetadataLoader INSTANCE = new MetadataLoader();
-
- private static final Identifier ID = new Identifier("libgui", "9patch_metadata");
- private static final String SUFFIX = ".9patch";
-
- private Map<Identifier, TextureProperties> properties = Collections.emptyMap();
-
- public TextureProperties getProperties(Identifier texture) {
- return properties.getOrDefault(texture, TextureProperties.DEFAULT);
- }
-
- @Override
- public Identifier getFabricId() {
- return ID;
- }
-
- @Override
- protected Map<Identifier, Properties> prepare(ResourceManager manager, Profiler profiler) {
- Collection<Identifier> ids = manager.findResources("textures", s -> s.endsWith(SUFFIX));
- Map<Identifier, Properties> result = new HashMap<>();
-
- for (Identifier input : ids) {
- try (Resource resource = manager.getResource(input);
- InputStream stream = resource.getInputStream()) {
- Properties props = new Properties();
- props.load(stream);
- Identifier textureId = new Identifier(input.getNamespace(), input.getPath().substring(0, input.getPath().length() - SUFFIX.length()));
- result.put(textureId, props);
- } catch (Exception e) {
- LibGuiClient.logger.error("Error while loading metadata file {}, skipping...", input, e);
- }
- }
-
- return result;
- }
-
- @Override
- protected void apply(Map<Identifier, Properties> meta, ResourceManager manager, Profiler profiler) {
- properties = new HashMap<>();
- for (Map.Entry<Identifier, Properties> entry : meta.entrySet()) {
- Identifier id = entry.getKey();
- Properties props = entry.getValue();
-
- Mode mode = TextureProperties.DEFAULT.getMode();
-// float cornerUv = TextureProperties.DEFAULT.getCornerUv();
-
- if (props.containsKey("mode")) {
- String modeStr = props.getProperty("mode");
- mode = Mode.fromString(modeStr);
- if (mode == null) {
- LibGuiClient.logger.error("Invalid mode '{}' in nine-patch metadata file for texture {}", modeStr, id);
- continue;
- }
- }
-
-// if (props.containsKey("cornerUv")) {
-// cornerUv = Float.parseFloat(props.getProperty("cornerUv"));
-// }
-
- TextureProperties texProperties = new TextureProperties(mode);
- properties.put(id, texProperties);
- }
- }
- }
}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/ScreenDrawing.java b/src/main/java/io/github/cottonmc/cotton/gui/client/ScreenDrawing.java
index f31a046..f121c47 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/client/ScreenDrawing.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/client/ScreenDrawing.java
@@ -5,24 +5,33 @@ import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
+import net.minecraft.client.render.VertexFormat;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.OrderedText;
+import net.minecraft.text.Style;
import net.minecraft.util.Identifier;
+import net.minecraft.util.math.Matrix4f;
+import io.github.cottonmc.cotton.gui.impl.CottonScreenImpl;
import io.github.cottonmc.cotton.gui.widget.data.HorizontalAlignment;
import io.github.cottonmc.cotton.gui.widget.data.Texture;
-import org.lwjgl.opengl.GL11;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.jetbrains.annotations.Nullable;
/**
* {@code ScreenDrawing} contains utility methods for drawing contents on a screen.
*/
public class ScreenDrawing {
+ private static final Logger LOGGER = LogManager.getLogger();
+
private ScreenDrawing() {}
/**
* Draws a textured rectangle.
*
+ * @param matrices the rendering matrix stack
* @param x the x coordinate of the box on-screen
* @param y the y coordinate of the box on-screen
* @param width the width of the box on-screen
@@ -30,13 +39,14 @@ public class ScreenDrawing {
* @param texture the Identifier for the texture
* @param color a color to tint the texture. This can be transparent! Use 0xFF_FFFFFF if you don't want a color tint
*/
- public static void texturedRect(int x, int y, int width, int height, Identifier texture, int color) {
- texturedRect(x, y, width, height, texture, 0, 0, 1, 1, color, 1.0f);
+ public static void texturedRect(MatrixStack matrices, int x, int y, int width, int height, Identifier texture, int color) {
+ texturedRect(matrices, x, y, width, height, texture, 0, 0, 1, 1, color, 1.0f);
}
/**
* Draws a textured rectangle.
*
+ * @param matrices the rendering matrix stack
* @param x the x coordinate of the box on-screen
* @param y the y coordinate of the box on-screen
* @param width the width of the box on-screen
@@ -46,13 +56,14 @@ public class ScreenDrawing {
* @param opacity opacity of the drawn texture. (0f is fully opaque and 1f is fully visible)
* @since 2.0.0
*/
- public static void texturedRect(int x, int y, int width, int height, Identifier texture, int color, float opacity) {
- texturedRect(x, y, width, height, texture, 0, 0, 1, 1, color, opacity);
+ public static void texturedRect(MatrixStack matrices, int x, int y, int width, int height, Identifier texture, int color, float opacity) {
+ texturedRect(matrices, x, y, width, height, texture, 0, 0, 1, 1, color, opacity);
}
/**
* Draws a textured rectangle.
*
+ * @param matrices the rendering matrix stack
* @param x the x coordinate of the box on-screen
* @param y the y coordinate of the box on-screen
* @param width the width of the box on-screen
@@ -64,13 +75,14 @@ public class ScreenDrawing {
* @param v2 the bottom edge of the texture
* @param color a color to tint the texture. This can be transparent! Use 0xFF_FFFFFF if you don't want a color tint
*/
- public static void texturedRect(int x, int y, int width, int height, Identifier texture, float u1, float v1, float u2, float v2, int color) {
- texturedRect(x, y, width, height, texture, u1, v1, u2, v2, color, 1.0f);
+ public static void texturedRect(MatrixStack matrices, int x, int y, int width, int height, Identifier texture, float u1, float v1, float u2, float v2, int color) {
+ texturedRect(matrices, x, y, width, height, texture, u1, v1, u2, v2, color, 1.0f);
}
/**
* Draws a textured rectangle.
*
+ * @param matrices the rendering matrix stack
* @param x the x coordinate of the box on-screen
* @param y the y coordinate of the box on-screen
* @param width the width of the box on-screen
@@ -79,13 +91,14 @@ public class ScreenDrawing {
* @param color a color to tint the texture. This can be transparent! Use 0xFF_FFFFFF if you don't want a color tint
* @since 3.0.0
*/
- public static void texturedRect(int x, int y, int width, int height, Texture texture, int color) {
- texturedRect(x, y, width, height, texture, color, 1.0f);
+ public static void texturedRect(MatrixStack matrices, int x, int y, int width, int height, Texture texture, int color) {
+ texturedRect(matrices, x, y, width, height, texture, color, 1.0f);
}
/**
* Draws a textured rectangle.
*
+ * @param matrices the rendering matrix stack
* @param x the x coordinate of the box on-screen
* @param y the y coordinate of the box on-screen
* @param width the width of the box on-screen
@@ -95,13 +108,14 @@ public class ScreenDrawing {
* @param opacity opacity of the drawn texture. (0f is fully opaque and 1f is fully visible)
* @since 3.0.0
*/
- public static void texturedRect(int x, int y, int width, int height, Texture texture, int color, float opacity) {
- texturedRect(x, y, width, height, texture.image, texture.u1, texture.v1, texture.u2, texture.v2, color, opacity);
+ public static void texturedRect(MatrixStack matrices, int x, int y, int width, int height, Texture texture, int color, float opacity) {
+ texturedRect(matrices, x, y, width, height, texture.image, texture.u1, texture.v1, texture.u2, texture.v2, color, opacity);
}
/**
* Draws a textured rectangle.
*
+ * @param matrices the rendering matrix stack
* @param x the x coordinate of the box on-screen
* @param y the y coordinate of the box on-screen
* @param width the width of the box on-screen
@@ -115,7 +129,7 @@ public class ScreenDrawing {
* @param opacity opacity of the drawn texture. (0f is fully opaque and 1f is fully visible)
* @since 2.0.0
*/
- public static void texturedRect(int x, int y, int width, int height, Identifier texture, float u1, float v1, float u2, float v2, int color, float opacity) {
+ public static void texturedRect(MatrixStack matrices, int x, int y, int width, int height, Identifier texture, float u1, float v1, float u2, float v2, int color, float opacity) {
MinecraftClient.getInstance().getTextureManager().bindTexture(texture);
//float scale = 0.00390625F;
@@ -128,14 +142,15 @@ public class ScreenDrawing {
float b = (color & 255) / 255.0F;
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder buffer = tessellator.getBuffer();
+ Matrix4f model = matrices.peek().getModel();
RenderSystem.enableBlend();
//GlStateManager.disableTexture2D();
RenderSystem.blendFuncSeparate(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SrcFactor.ONE, GlStateManager.DstFactor.ZERO);
- buffer.begin(GL11.GL_QUADS, VertexFormats.POSITION_COLOR_TEXTURE); //I thought GL_QUADS was deprecated but okay, sure.
- buffer.vertex(x, y + height, 0).color(r, g, b, opacity).texture(u1, v2).next();
- buffer.vertex(x + width, y + height, 0).color(r, g, b, opacity).texture(u2, v2).next();
- buffer.vertex(x + width, y, 0).color(r, g, b, opacity).texture(u2, v1).next();
- buffer.vertex(x, y, 0).color(r, g, b, opacity).texture(u1, v1).next();
+ buffer.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR_TEXTURE); //I thought GL_QUADS was deprecated but okay, sure.
+ buffer.vertex(model, x, y + height, 0).color(r, g, b, opacity).texture(u1, v2).next();
+ buffer.vertex(model, x + width, y + height, 0).color(r, g, b, opacity).texture(u2, v2).next();
+ buffer.vertex(model, x + width, y, 0).color(r, g, b, opacity).texture(u2, v1).next();
+ buffer.vertex(model, x, y, 0).color(r, g, b, opacity).texture(u1, v1).next();
tessellator.draw();
//GlStateManager.enableTexture2D();
RenderSystem.disableBlend();
@@ -145,6 +160,8 @@ public class ScreenDrawing {
* Draws a textured rectangle with UV values based on the width and height.
*
* <p>If the texture is 256x256, this draws the texture at one pixel per texel.
+ *
+ * @param matrices the rendering matrix stack
* @param x the x coordinate of the box on-screen
* @param y the y coordinate of the box on-screen
* @param width the width of the box on-screen
@@ -154,9 +171,9 @@ public class ScreenDrawing {
* @param textureY the y offset into the texture
* @param color a color to tint the texture. This can be transparent! Use 0xFF_FFFFFF if you don't want a color tint
*/
- public static void texturedGuiRect(int x, int y, int width, int height, Identifier texture, int textureX, int textureY, int color) {
+ public static void texturedGuiRect(MatrixStack matrices, int x, int y, int width, int height, Identifier texture, int textureX, int textureY, int color) {
float px = 1/256f;
- texturedRect(x, y, width, height, texture, textureX*px, textureY*px, (textureX+width)*px, (textureY+height)*px, color);
+ texturedRect(matrices, x, y, width, height, texture, textureX*px, textureY*px, (textureX+width)*px, (textureY+height)*px, color);
}
/**
@@ -164,21 +181,22 @@ public class ScreenDrawing {
*
* <p>If the texture is 256x256, this draws the texture at one pixel per texel.
*
- * @param left the x coordinate of the box on-screen
- * @param top the y coordinate of the box on-screen
- * @param width the width of the box on-screen
- * @param height the height of the box on-screen
- * @param texture the Identifier for the texture
- * @param color a color to tint the texture. This can be transparent! Use 0xFF_FFFFFF if you don't want a color tint
+ * @param matrices the rendering matrix stack
+ * @param left the x coordinate of the box on-screen
+ * @param top the y coordinate of the box on-screen
+ * @param width the width of the box on-screen
+ * @param height the height of the box on-screen
+ * @param texture the Identifier for the texture
+ * @param color a color to tint the texture. This can be transparent! Use 0xFF_FFFFFF if you don't want a color tint
*/
- public static void texturedGuiRect(int left, int top, int width, int height, Identifier texture, int color) {
- texturedGuiRect(left, top, width, height, texture, 0, 0, color);
+ public static void texturedGuiRect(MatrixStack matrices, int left, int top, int width, int height, Identifier texture, int color) {
+ texturedGuiRect(matrices, left, top, width, height, texture, 0, 0, color);
}
/**
* Draws an untextured rectangle of the specified RGB color.
*/
- public static void coloredRect(int left, int top, int width, int height, int color) {
+ public static void coloredRect(MatrixStack matrices, int left, int top, int width, int height, int color) {
if (width <= 0) width = 1;
if (height <= 0) height = 1;
@@ -188,33 +206,20 @@ public class ScreenDrawing {
float b = (color & 255) / 255.0F;
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder buffer = tessellator.getBuffer();
+ Matrix4f model = matrices.peek().getModel();
RenderSystem.enableBlend();
RenderSystem.disableTexture();
RenderSystem.blendFuncSeparate(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SrcFactor.ONE, GlStateManager.DstFactor.ZERO);
- buffer.begin(GL11.GL_QUADS, VertexFormats.POSITION_COLOR); //I thought GL_QUADS was deprecated but okay, sure.
- buffer.vertex(left, top + height, 0.0D).color(r, g, b, a).next();
- buffer.vertex(left + width, top + height, 0.0D).color(r, g, b, a).next();
- buffer.vertex(left + width, top, 0.0D).color(r, g, b, a).next();
- buffer.vertex(left, top, 0.0D).color(r, g, b, a).next();
+ buffer.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR); //I thought GL_QUADS was deprecated but okay, sure.
+ buffer.vertex(model, left, top + height, 0).color(r, g, b, a).next();
+ buffer.vertex(model, left + width, top + height, 0).color(r, g, b, a).next();
+ buffer.vertex(model, left + width, top, 0).color(r, g, b, a).next();
+ buffer.vertex(model, left, top, 0).color(r, g, b, a).next();
tessellator.draw();
RenderSystem.enableTexture();
RenderSystem.disableBlend();
}
- public static void maskedRect(Identifier mask, Identifier texture, int left, int top, int width, int height) {
-
-
- texturedRect(left, top, width, height, mask, 0, 0, 1, 1, 0xFFFFFFFF); //TODO: 7 Z
-
- RenderSystem.enableDepthTest();
- RenderSystem.depthFunc(GL11.GL_EQUAL);
-
- texturedRect(left, top, width, height, texture, 0, 0, 1, 1, 0xFFFFFFFF); //, 7);
-
- RenderSystem.depthFunc(GL11.GL_LESS);
- RenderSystem.disableDepthTest();
- }
-
/**
* Draws a rectangle for a Fluid, because fluids are tough.
*/
@@ -256,82 +261,86 @@ public class ScreenDrawing {
/**
* Draws a beveled, round rectangle that is substantially similar to default Minecraft UI panels.
*
- * @param x the X position of the panel
- * @param y the Y position of the panel
- * @param width the width of the panel
- * @param height the height of the panel
+ * @param matrices the rendering matrix stack
+ * @param x the X position of the panel
+ * @param y the Y position of the panel
+ * @param width the width of the panel
+ * @param height the height of the panel
*/
- public static void drawGuiPanel(int x, int y, int width, int height) {
- if (LibGuiClient.config.darkMode) drawGuiPanel(x, y, width, height, 0xFF0B0B0B, 0xFF2F2F2F, 0xFF414141, 0xFF000000);
- else drawGuiPanel(x, y, width, height, 0xFF555555, 0xFFC6C6C6, 0xFFFFFFFF, 0xFF000000);
+ public static void drawGuiPanel(MatrixStack matrices, int x, int y, int width, int height) {
+ if (LibGui.isDarkMode()) drawGuiPanel(matrices, x, y, width, height, 0xFF0B0B0B, 0xFF2F2F2F, 0xFF414141, 0xFF000000);
+ else drawGuiPanel(matrices, x, y, width, height, 0xFF555555, 0xFFC6C6C6, 0xFFFFFFFF, 0xFF000000);
}
/**
* Draws a beveled, round, and colored rectangle that is substantially similar to default Minecraft UI panels.
*
+ * @param matrices the rendering matrix stack
* @param x the X position of the panel
* @param y the Y position of the panel
* @param width the width of the panel
* @param height the height of the panel
* @param panelColor the panel ARGB color
*/
- public static void drawGuiPanel(int x, int y, int width, int height, int panelColor) {
+ public static void drawGuiPanel(MatrixStack matrices, int x, int y, int width, int height, int panelColor) {
int shadowColor = multiplyColor(panelColor, 0.50f);
int hilightColor = multiplyColor(panelColor, 1.25f);
- drawGuiPanel(x, y, width, height, shadowColor, panelColor, hilightColor, 0xFF000000);
+ drawGuiPanel(matrices, x, y, width, height, shadowColor, panelColor, hilightColor, 0xFF000000);
}
/**
* Draws a beveled, round rectangle with custom edge colors that is substantially similar to default Minecraft UI panels.
*
- * @param x the X position of the panel
- * @param y the Y position of the panel
- * @param width the width of the panel
- * @param height the height of the panel
- * @param shadow the bottom/right shadow ARGB color
- * @param panel the center ARGB color
- * @param hilight the top/left hilight ARGB color
- * @param outline the outline ARGB color
+ * @param matrices the rendering matrix stack
+ * @param x the X position of the panel
+ * @param y the Y position of the panel
+ * @param width the width of the panel
+ * @param height the height of the panel
+ * @param shadow the bottom/right shadow ARGB color
+ * @param panel the center ARGB color
+ * @param hilight the top/left hilight ARGB color
+ * @param outline the outline ARGB color
*/
- public static void drawGuiPanel(int x, int y, int width, int height, int shadow, int panel, int hilight, int outline) {
- coloredRect(x + 3, y + 3, width - 6, height - 6, panel); //Main panel area
-
- coloredRect(x + 2, y + 1, width - 4, 2, hilight); //Top hilight
- coloredRect(x + 2, y + height - 3, width - 4, 2, shadow); //Bottom shadow
- coloredRect(x + 1, y + 2, 2, height - 4, hilight); //Left hilight
- coloredRect(x + width - 3, y + 2, 2, height - 4, shadow); //Right shadow
- coloredRect(x + width - 3, y + 2, 1, 1, panel); //Topright non-hilight/non-shadow transition pixel
- coloredRect(x + 2, y + height - 3, 1, 1, panel); //Bottomleft non-hilight/non-shadow transition pixel
- coloredRect(x + 3, y + 3, 1, 1, hilight); //Topleft round hilight pixel
- coloredRect(x + width - 4, y + height - 4, 1, 1, shadow); //Bottomright round shadow pixel
-
- coloredRect(x + 2, y, width - 4, 1, outline); //Top outline
- coloredRect(x, y + 2, 1, height - 4, outline); //Left outline
- coloredRect(x + width - 1, y + 2, 1, height - 4, outline); //Right outline
- coloredRect(x + 2, y + height - 1, width - 4, 1, outline); //Bottom outline
- coloredRect(x + 1, y + 1, 1, 1, outline); //Topleft round pixel
- coloredRect(x + 1, y + height - 2, 1, 1, outline); //Bottomleft round pixel
- coloredRect(x + width - 2, y + 1, 1, 1, outline); //Topright round pixel
- coloredRect(x + width - 2, y + height - 2, 1, 1, outline); //Bottomright round pixel
+ public static void drawGuiPanel(MatrixStack matrices, int x, int y, int width, int height, int shadow, int panel, int hilight, int outline) {
+ coloredRect(matrices, x + 3, y + 3, width - 6, height - 6, panel); //Main panel area
+
+ coloredRect(matrices, x + 2, y + 1, width - 4, 2, hilight); //Top hilight
+ coloredRect(matrices, x + 2, y + height - 3, width - 4, 2, shadow); //Bottom shadow
+ coloredRect(matrices, x + 1, y + 2, 2, height - 4, hilight); //Left hilight
+ coloredRect(matrices, x + width - 3, y + 2, 2, height - 4, shadow); //Right shadow
+ coloredRect(matrices, x + width - 3, y + 2, 1, 1, panel); //Topright non-hilight/non-shadow transition pixel
+ coloredRect(matrices, x + 2, y + height - 3, 1, 1, panel); //Bottomleft non-hilight/non-shadow transition pixel
+ coloredRect(matrices, x + 3, y + 3, 1, 1, hilight); //Topleft round hilight pixel
+ coloredRect(matrices, x + width - 4, y + height - 4, 1, 1, shadow); //Bottomright round shadow pixel
+
+ coloredRect(matrices, x + 2, y, width - 4, 1, outline); //Top outline
+ coloredRect(matrices, x, y + 2, 1, height - 4, outline); //Left outline
+ coloredRect(matrices, x + width - 1, y + 2, 1, height - 4, outline); //Right outline
+ coloredRect(matrices, x + 2, y + height - 1, width - 4, 1, outline); //Bottom outline
+ coloredRect(matrices, x + 1, y + 1, 1, 1, outline); //Topleft round pixel
+ coloredRect(matrices, x + 1, y + height - 2, 1, 1, outline); //Bottomleft round pixel
+ coloredRect(matrices, x + width - 2, y + 1, 1, 1, outline); //Topright round pixel
+ coloredRect(matrices, x + width - 2, y + height - 2, 1, 1, outline); //Bottomright round pixel
}
/**
* Draws a default-sized recessed itemslot panel
*/
- public static void drawBeveledPanel(int x, int y) {
- drawBeveledPanel(x, y, 18, 18, 0xFF373737, 0xFF8b8b8b, 0xFFFFFFFF);
+ public static void drawBeveledPanel(MatrixStack matrices, int x, int y) {
+ drawBeveledPanel(matrices, x, y, 18, 18, 0xFF373737, 0xFF8b8b8b, 0xFFFFFFFF);
}
/**
* Draws a default-color recessed itemslot panel of variable size
*/
- public static void drawBeveledPanel(int x, int y, int width, int height) {
- drawBeveledPanel(x, y, width, height, 0xFF373737, 0xFF8b8b8b, 0xFFFFFFFF);
+ public static void drawBeveledPanel(MatrixStack matrices, int x, int y, int width, int height) {
+ drawBeveledPanel(matrices, x, y, width, height, 0xFF373737, 0xFF8b8b8b, 0xFFFFFFFF);
}
/**
* Draws a generalized-case beveled panel. Can be inset or outset depending on arguments.
+ * @param matrices the rendering matrix stack
* @param x x coordinate of the topleft corner
* @param y y coordinate of the topleft corner
* @param width width of the panel
@@ -340,12 +349,12 @@ public class ScreenDrawing {
* @param panel color of the panel area
* @param bottomright color of the bottom/right bevel
*/
- public static void drawBeveledPanel(int x, int y, int width, int height, int topleft, int panel, int bottomright) {
- coloredRect(x, y, width, height, panel); //Center panel
- coloredRect(x, y, width - 1, 1, topleft); //Top shadow
- coloredRect(x, y + 1, 1, height - 2, topleft); //Left shadow
- coloredRect(x + width - 1, y + 1, 1, height - 1, bottomright); //Right hilight
- coloredRect(x + 1, y + height - 1, width - 1, 1, bottomright); //Bottom hilight
+ public static void drawBeveledPanel(MatrixStack matrices, int x, int y, int width, int height, int topleft, int panel, int bottomright) {
+ coloredRect(matrices, x, y, width, height, panel); //Center panel
+ coloredRect(matrices, x, y, width - 1, 1, topleft); //Top shadow
+ coloredRect(matrices, x, y + 1, 1, height - 2, topleft); //Left shadow
+ coloredRect(matrices, x + width - 1, y + 1, 1, height - 1, bottomright); //Right hilight
+ coloredRect(matrices, x + 1, y + height - 1, width - 1, 1, bottomright); //Bottom hilight
}
/**
@@ -503,6 +512,28 @@ public class ScreenDrawing {
MinecraftClient.getInstance().textRenderer.draw(matrices, text, x, y, color);
}
+ /**
+ * Draws the text hover effects for a text style.
+ *
+ * <p>This method should only be called from a widget in a screen.
+ * For example, there will be nothing drawn in HUDs.
+ *
+ * @param matrices the rendering matrix stack
+ * @param textStyle the text style
+ * @param x the X position
+ * @param y the Y position
+ * @since 4.0.0
+ */
+ public static void drawTextHover(MatrixStack matrices, @Nullable Style textStyle, int x, int y) {
+ CottonScreenImpl screen = (CottonScreenImpl) MinecraftClient.getInstance().currentScreen;
+
+ if (screen != null) {
+ screen.renderTextHover(matrices, textStyle, x, y);
+ } else {
+ LOGGER.warn("Rendering text hover effects outside of a screen!");
+ }
+ }
+
public static int colorAtOpacity(int opaque, float opacity) {
if (opacity<0.0f) opacity=0.0f;
if (opacity>1.0f) opacity=1.0f;
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/TextHoverRendererScreen.java b/src/main/java/io/github/cottonmc/cotton/gui/client/TextHoverRendererScreen.java
deleted file mode 100644
index d6b4ca1..0000000
--- a/src/main/java/io/github/cottonmc/cotton/gui/client/TextHoverRendererScreen.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package io.github.cottonmc.cotton.gui.client;
-
-import net.minecraft.client.util.math.MatrixStack;
-import net.minecraft.text.Style;
-
-/**
- * Implemented by LibGui screens to access {@code Screen.renderTextHoverEffect()}.
- */
-public interface TextHoverRendererScreen {
- void renderTextHover(MatrixStack matrices, Style textStyle, int x, int y);
-}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/modmenu/package-info.java b/src/main/java/io/github/cottonmc/cotton/gui/client/modmenu/package-info.java
deleted file mode 100644
index ad040bf..0000000
--- a/src/main/java/io/github/cottonmc/cotton/gui/client/modmenu/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * Mod Menu support for LibGui.
- */
-package io.github.cottonmc.cotton.gui.client.modmenu;
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/impl/CottonScreenImpl.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/CottonScreenImpl.java
new file mode 100644
index 0000000..69a6f77
--- /dev/null
+++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/CottonScreenImpl.java
@@ -0,0 +1,24 @@
+package io.github.cottonmc.cotton.gui.impl;
+
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.text.Style;
+
+import io.github.cottonmc.cotton.gui.widget.WWidget;
+import org.jetbrains.annotations.Nullable;
+
+@Environment(EnvType.CLIENT)
+public interface CottonScreenImpl {
+ default Screen asScreen() {
+ return (Screen) this;
+ }
+
+ @Nullable
+ WWidget getLastResponder();
+
+ void setLastResponder(@Nullable WWidget lastResponder);
+
+ void renderTextHover(MatrixStack matrices, @Nullable Style textStyle, int x, int y);
+}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/impl/MouseInputHandler.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/MouseInputHandler.java
new file mode 100644
index 0000000..747bae8
--- /dev/null
+++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/MouseInputHandler.java
@@ -0,0 +1,112 @@
+package io.github.cottonmc.cotton.gui.impl;
+
+import io.github.cottonmc.cotton.gui.GuiDescription;
+import io.github.cottonmc.cotton.gui.widget.WWidget;
+import io.github.cottonmc.cotton.gui.widget.data.InputResult;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.function.Function;
+
+/**
+ * The implementation for mouse inputs.
+ */
+public final class MouseInputHandler {
+ public static void onMouseDown(GuiDescription description, CottonScreenImpl screen, int containerX, int containerY, int mouseButton) {
+ if (screen.getLastResponder() == null) {
+ WWidget lastResponder = description.getRootPanel().hit(containerX, containerY);
+ screen.setLastResponder(lastResponder);
+ if (lastResponder != null) {
+ runTree(
+ lastResponder,
+ widget -> widget.onMouseDown(containerX - widget.getAbsoluteX(), containerY - widget.getAbsoluteY(), mouseButton)
+ );
+ }
+ } else {
+ // This is a drag instead
+ }
+ }
+
+ public static void onMouseUp(GuiDescription description, CottonScreenImpl screen, int containerX, int containerY, int mouseButton) {
+ WWidget lastResponder = screen.getLastResponder();
+
+ if (lastResponder != null) {
+ int width = screen.asScreen().width;
+ int height = screen.asScreen().height;
+
+ runTree(
+ lastResponder,
+ widget -> widget.onMouseUp(containerX - widget.getAbsoluteX(), containerY - widget.getAbsoluteY(), mouseButton)
+ );
+
+ if (containerX >= 0 && containerY >= 0 && containerX < width && containerY < height) {
+ runTree(
+ lastResponder,
+ widget -> widget.onClick(containerX - widget.getAbsoluteX(), containerY - widget.getAbsoluteY(), mouseButton)
+ );
+ }
+ } else {
+ runTree(
+ description.getRootPanel().hit(containerX, containerY),
+ widget -> widget.onMouseUp(containerX - widget.getAbsoluteX(), containerY - widget.getAbsoluteY(), mouseButton)
+ );
+ }
+
+ screen.setLastResponder(null);
+ }
+
+ public static void onMouseDrag(GuiDescription description, CottonScreenImpl screen, int containerX, int containerY, int mouseButton, double deltaX, double deltaY) {
+ WWidget lastResponder = screen.getLastResponder();
+
+ if (lastResponder != null) {
+ lastResponder.onMouseDrag(containerX - lastResponder.getAbsoluteX(), containerY - lastResponder.getAbsoluteY(), mouseButton, deltaX, deltaY);
+ } else {
+ int width = screen.asScreen().width;
+ int height = screen.asScreen().height;
+
+ if (containerX < 0 || containerY < 0 || containerX >= width || containerY >= height) return;
+
+ runTree(
+ description.getRootPanel().hit(containerX, containerY),
+ widget -> widget.onMouseDrag(containerX - widget.getAbsoluteX(), containerY - widget.getAbsoluteY(), mouseButton, deltaX, deltaY)
+ );
+ }
+ }
+
+ public static void onMouseScroll(GuiDescription description, int containerX, int containerY, double amount) {
+ runTree(
+ description.getRootPanel().hit(containerX, containerY),
+ widget -> widget.onMouseScroll(containerX - widget.getAbsoluteX(), containerY - widget.getAbsoluteY(), amount)
+ );
+ }
+
+ public static void onMouseMove(GuiDescription description, int containerX, int containerY) {
+ runTree(
+ description.getRootPanel().hit(containerX, containerY),
+ widget -> widget.onMouseMove(containerX - widget.getAbsoluteX(), containerY - widget.getAbsoluteY())
+ );
+ }
+
+ /**
+ * Traverses the {@code function} up the widget tree until it finds a {@link InputResult#PROCESSED} result.
+ *
+ * @param bottom the starting point for the traversal
+ * @param function the function to run
+ * @return the first widget to return {@link InputResult#PROCESSED}, or null if none found.
+ */
+ @Nullable
+ private static WWidget runTree(WWidget bottom, Function<WWidget, InputResult> function) {
+ WWidget current = bottom;
+
+ while (current != null) {
+ InputResult result = function.apply(current);
+
+ if (result == InputResult.PROCESSED) {
+ break;
+ } else {
+ current = current.getParent();
+ }
+ }
+
+ return current;
+ }
+}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/impl/access/ScreenAccessor.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/access/ScreenAccessor.java
new file mode 100644
index 0000000..33add9f
--- /dev/null
+++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/access/ScreenAccessor.java
@@ -0,0 +1,16 @@
+package io.github.cottonmc.cotton.gui.impl.access;
+
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.tooltip.TooltipComponent;
+import net.minecraft.client.util.math.MatrixStack;
+
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Invoker;
+
+import java.util.List;
+
+@Mixin(Screen.class)
+public interface ScreenAccessor {
+ @Invoker
+ void callRenderTooltipFromComponents(MatrixStack matrices, List<TooltipComponent> components, int x, int y);
+}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/impl/access/package-info.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/access/package-info.java
index 8f391fd..b98a6b8 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/impl/access/package-info.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/access/package-info.java
@@ -1,4 +1,7 @@
/**
* Internal implementation classes.
*/
+@ApiStatus.Internal
package io.github.cottonmc.cotton.gui.impl.access;
+
+import org.jetbrains.annotations.ApiStatus;
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/LibGuiClient.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/LibGuiClient.java
index 80fa414..ccb4a0a 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/client/LibGuiClient.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/LibGuiClient.java
@@ -1,4 +1,4 @@
-package io.github.cottonmc.cotton.gui.client;
+package io.github.cottonmc.cotton.gui.impl.client;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
@@ -9,8 +9,8 @@ import net.minecraft.resource.ResourceType;
import blue.endless.jankson.Jankson;
import blue.endless.jankson.JsonElement;
import blue.endless.jankson.JsonObject;
-import io.github.cottonmc.cotton.gui.impl.ScreenNetworkingImpl;
import io.github.cottonmc.jankson.JanksonFactory;
+import io.github.cottonmc.cotton.gui.impl.ScreenNetworkingImpl;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -29,7 +29,7 @@ public class LibGuiClient implements ClientModInitializer {
public void onInitializeClient() {
config = loadConfig();
- ResourceManagerHelper.get(ResourceType.CLIENT_RESOURCES).registerReloadListener(NinePatch.MetadataLoader.INSTANCE);
+ ResourceManagerHelper.get(ResourceType.CLIENT_RESOURCES).registerReloadListener(NinePatchInternals.MetadataLoader.INSTANCE);
ClientPlayNetworking.registerGlobalReceiver(ScreenNetworkingImpl.SCREEN_MESSAGE_S2C, (client, networkHandler, buf, responseSender) -> {
ScreenNetworkingImpl.handle(client, client.player, buf);
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/LibGuiConfig.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/LibGuiConfig.java
index b971e31..b1985af 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/client/LibGuiConfig.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/LibGuiConfig.java
@@ -1,4 +1,4 @@
-package io.github.cottonmc.cotton.gui.client;
+package io.github.cottonmc.cotton.gui.impl.client;
import blue.endless.jankson.Comment;
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/impl/client/NinePatchInternals.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/NinePatchInternals.java
new file mode 100644
index 0000000..4113825
--- /dev/null
+++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/NinePatchInternals.java
@@ -0,0 +1,103 @@
+package io.github.cottonmc.cotton.gui.impl.client;
+
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
+import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
+import net.minecraft.resource.Resource;
+import net.minecraft.resource.ResourceManager;
+import net.minecraft.resource.SinglePreparationResourceReloadListener;
+import net.minecraft.util.Identifier;
+import net.minecraft.util.profiler.Profiler;
+
+import io.github.cottonmc.cotton.gui.client.NinePatch;
+
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+@Environment(EnvType.CLIENT)
+public final class NinePatchInternals {
+ @Environment(EnvType.CLIENT)
+ public static final class MetadataLoader extends SinglePreparationResourceReloadListener<Map<Identifier, Properties>> implements IdentifiableResourceReloadListener {
+ public static final MetadataLoader INSTANCE = new MetadataLoader();
+
+ private static final Identifier ID = new Identifier("libgui", "9patch_metadata");
+ private static final String SUFFIX = ".9patch";
+
+ private Map<Identifier, TextureProperties> properties = Collections.emptyMap();
+
+ public TextureProperties getProperties(Identifier texture) {
+ return properties.getOrDefault(texture, TextureProperties.DEFAULT);
+ }
+
+ @Override
+ public Identifier getFabricId() {
+ return ID;
+ }
+
+ @Override
+ protected Map<Identifier, Properties> prepare(ResourceManager manager, Profiler profiler) {
+ Collection<Identifier> ids = manager.findResources("textures", s -> s.endsWith(SUFFIX));
+ Map<Identifier, Properties> result = new HashMap<>();
+
+ for (Identifier input : ids) {
+ try (Resource resource = manager.getResource(input);
+ InputStream stream = resource.getInputStream()) {
+ Properties props = new Properties();
+ props.load(stream);
+ Identifier textureId = new Identifier(input.getNamespace(), input.getPath().substring(0, input.getPath().length() - SUFFIX.length()));
+ result.put(textureId, props);
+ } catch (Exception e) {
+ LibGuiClient.logger.error("Error while loading metadata file {}, skipping...", input, e);
+ }
+ }
+
+ return result;
+ }
+
+ @Override
+ protected void apply(Map<Identifier, Properties> meta, ResourceManager manager, Profiler profiler) {
+ properties = new HashMap<>();
+ for (Map.Entry<Identifier, Properties> entry : meta.entrySet()) {
+ Identifier id = entry.getKey();
+ Properties props = entry.getValue();
+
+ NinePatch.Mode mode = TextureProperties.DEFAULT.getMode();
+ // float cornerUv = TextureProperties.DEFAULT.getCornerUv();
+
+ if (props.containsKey("mode")) {
+ String modeStr = props.getProperty("mode");
+ mode = NinePatch.Mode.fromString(modeStr);
+ if (mode == null) {
+ LibGuiClient.logger.error("Invalid mode '{}' in nine-patch metadata file for texture {}", modeStr, id);
+ continue;
+ }
+ }
+
+ // if (props.containsKey("cornerUv")) {
+ // cornerUv = Float.parseFloat(props.getProperty("cornerUv"));
+ // }
+
+ TextureProperties texProperties = new TextureProperties(mode);
+ properties.put(id, texProperties);
+ }
+ }
+ }
+
+ public static class TextureProperties {
+ public static final TextureProperties DEFAULT = new TextureProperties(NinePatch.Mode.STRETCHING);
+
+ private final NinePatch.Mode mode;
+
+ public TextureProperties(NinePatch.Mode mode) {
+ this.mode = mode;
+ }
+
+ public NinePatch.Mode getMode() {
+ return mode;
+ }
+ }
+}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/modmenu/ConfigGui.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/modmenu/ConfigGui.java
index cd3fe0a..5f3d4fa 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/client/modmenu/ConfigGui.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/modmenu/ConfigGui.java
@@ -1,12 +1,12 @@
-package io.github.cottonmc.cotton.gui.client.modmenu;
+package io.github.cottonmc.cotton.gui.impl.client.modmenu;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.text.TranslatableText;
import io.github.cottonmc.cotton.gui.client.BackgroundPainter;
-import io.github.cottonmc.cotton.gui.client.LibGuiClient;
import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription;
+import io.github.cottonmc.cotton.gui.impl.client.LibGuiClient;
import io.github.cottonmc.cotton.gui.widget.WButton;
import io.github.cottonmc.cotton.gui.widget.WGridPanel;
import io.github.cottonmc.cotton.gui.widget.WTextField;
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/modmenu/ModMenuSupport.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/modmenu/ModMenuSupport.java
index ccdff93..82fead4 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/client/modmenu/ModMenuSupport.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/modmenu/ModMenuSupport.java
@@ -1,4 +1,4 @@
-package io.github.cottonmc.cotton.gui.client.modmenu;
+package io.github.cottonmc.cotton.gui.impl.client.modmenu;
import net.minecraft.text.TranslatableText;
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/modmenu/WKirbSprite.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/modmenu/WKirbSprite.java
index 74d5357..74f0f1a 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/client/modmenu/WKirbSprite.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/modmenu/WKirbSprite.java
@@ -1,11 +1,11 @@
-package io.github.cottonmc.cotton.gui.client.modmenu;
+package io.github.cottonmc.cotton.gui.impl.client.modmenu;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Identifier;
-import io.github.cottonmc.cotton.gui.client.LibGuiClient;
+import io.github.cottonmc.cotton.gui.client.LibGui;
import io.github.cottonmc.cotton.gui.client.ScreenDrawing;
import io.github.cottonmc.cotton.gui.widget.WWidget;
@@ -30,7 +30,7 @@ public class WKirbSprite extends WWidget {
private long lastFrame;
public WKirbSprite() {
- state = (LibGuiClient.config.darkMode) ? State.ASLEEP : State.AWAKE;
+ state = (LibGui.isDarkMode()) ? State.ASLEEP : State.AWAKE;
}
public void schedule(int[] frames) {
@@ -60,7 +60,7 @@ public class WKirbSprite extends WWidget {
if (pendingFrames.isEmpty()) {
- if (LibGuiClient.config.darkMode) {
+ if (LibGui.isDarkMode()) {
switch(state) {
case AWAKE:
state = State.FALLING_ASLEEP;
@@ -96,7 +96,7 @@ public class WKirbSprite extends WWidget {
}
float offset = KIRB_WIDTH * currentFrame;
- ScreenDrawing.texturedRect(x, y+8, 32, 32, KIRB, offset, 0, offset+KIRB_WIDTH, 1, 0xFFFFFFFF);
+ ScreenDrawing.texturedRect(matrices, x, y+8, 32, 32, KIRB, offset, 0, offset+KIRB_WIDTH, 1, 0xFFFFFFFF);
long elapsed = now - lastFrame;
currentFrameTime += elapsed;
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/impl/client/modmenu/package-info.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/modmenu/package-info.java
new file mode 100644
index 0000000..283aa50
--- /dev/null
+++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/modmenu/package-info.java
@@ -0,0 +1,7 @@
+/**
+ * Mod Menu support for LibGui.
+ */
+@ApiStatus.Internal
+package io.github.cottonmc.cotton.gui.impl.client.modmenu;
+
+import org.jetbrains.annotations.ApiStatus;
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/impl/client/package-info.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/package-info.java
new file mode 100644
index 0000000..c27d30e
--- /dev/null
+++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/package-info.java
@@ -0,0 +1,9 @@
+/**
+ * Internal implementation classes.
+ *
+ * @since 4.0.0
+ */
+@ApiStatus.Internal // I hope this scares people off
+package io.github.cottonmc.cotton.gui.impl.client;
+
+import org.jetbrains.annotations.ApiStatus;
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/impl/package-info.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/package-info.java
index 678ba6f..298c2fc 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/impl/package-info.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/package-info.java
@@ -3,4 +3,7 @@
*
* @since 2.0.0
*/
+@ApiStatus.Internal
package io.github.cottonmc.cotton.gui.impl;
+
+import org.jetbrains.annotations.ApiStatus;
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/TooltipBuilder.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/TooltipBuilder.java
index f99df0a..86b8016 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/TooltipBuilder.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/TooltipBuilder.java
@@ -2,12 +2,19 @@ package io.github.cottonmc.cotton.gui.widget;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
+import net.minecraft.client.font.TextRenderer;
+import net.minecraft.client.gui.tooltip.TooltipComponent;
+import net.minecraft.client.item.TooltipData;
+import net.minecraft.client.render.item.ItemRenderer;
+import net.minecraft.client.texture.TextureManager;
+import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.OrderedText;
import net.minecraft.text.Text;
import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
/**
* A builder for widget tooltips.
@@ -16,10 +23,10 @@ import java.util.List;
*/
@Environment(EnvType.CLIENT)
public final class TooltipBuilder {
- final List<OrderedText> lines = new ArrayList<>();
+ final List<TooltipComponent> components = new ArrayList<>();
int size() {
- return lines.size();
+ return components.size();
}
/**
@@ -27,10 +34,12 @@ public final class TooltipBuilder {
*
* @param lines the lines
* @return this builder
+ * @throws NullPointerException if the lines are null
*/
public TooltipBuilder add(Text... lines) {
+ Objects.requireNonNull(lines, "lines");
for (Text line : lines) {
- this.lines.add(line.asOrderedText());
+ components.add(TooltipComponent.of(line.asOrderedText()));
}
return this;
@@ -41,10 +50,108 @@ public final class TooltipBuilder {
*
* @param lines the lines
* @return this builder
+ * @throws NullPointerException if the lines are null
*/
public TooltipBuilder add(OrderedText... lines) {
- Collections.addAll(this.lines, lines);
+ Objects.requireNonNull(lines, "lines");
+ for (OrderedText line : lines) {
+ components.add(TooltipComponent.of(line));
+ }
+
+ return this;
+ }
+
+ /**
+ * Adds the components to this builder.
+ *
+ * @param components the components
+ * @return this builder
+ * @throws NullPointerException if the components are null
+ * @since 4.0.0
+ */
+ public TooltipBuilder add(TooltipComponent... components) {
+ Objects.requireNonNull(components, "components");
+ this.components.addAll(Arrays.asList(components));
+
+ return this;
+ }
+
+ /**
+ * Adds a tooltip component created from tooltip data to this builder.
+ *
+ * @param tooltipData the data
+ * @return this builder
+ * @throws NullPointerException if the data is null
+ * @since 4.0.0
+ */
+ public TooltipBuilder add(TooltipData tooltipData) {
+ Objects.requireNonNull(tooltipData, "tooltipData");
+ components.add(TooltipComponent.of(tooltipData));
return this;
}
+
+ /**
+ * Adds the widget to this builder.
+ *
+ * <p>Tooltip widgets should usually be cached inside the widget they are created in.
+ *
+ * @param widget the widget
+ * @return this builder
+ * @throws NullPointerException if the widget is null
+ * @since 4.0.0
+ */
+ public TooltipBuilder add(WWidget widget) {
+ Objects.requireNonNull(widget, "widget");
+ components.add(new WidgetTooltipComponent(widget));
+
+ return this;
+ }
+
+ /**
+ * Adds the widget to this builder and resizes it if resizeable.
+ *
+ * <p>Tooltip widgets should usually be cached inside the widget they are created in.
+ *
+ * @param widget the widget
+ * @param width the new width
+ * @param height the new height
+ * @return this builder
+ * @throws NullPointerException if the widget is null
+ * @since 4.0.0
+ */
+ public TooltipBuilder add(WWidget widget, int width, int height) {
+ Objects.requireNonNull(widget, "widget");
+ components.add(new WidgetTooltipComponent(widget));
+
+ if (widget.canResize()) {
+ widget.setSize(width, height);
+ }
+
+ return this;
+ }
+
+ private static class WidgetTooltipComponent implements TooltipComponent {
+ private final WWidget widget;
+
+ WidgetTooltipComponent(WWidget widget) {
+ this.widget = widget;
+ }
+
+ @Override
+ public int getWidth(TextRenderer textRenderer) {
+ return widget.getWidth();
+ }
+
+ @Override
+ public int getHeight() {
+ return widget.getHeight();
+ }
+
+ @Override
+ public void drawItems(TextRenderer textRenderer, int x, int y, MatrixStack matrices, ItemRenderer itemRenderer, int z, TextureManager textureManager) {
+ widget.paint(matrices, x, y, /* mouse coords: nowhere in sight */ -x, -y);
+ widget.tick(); // Screens are ticked every time they're rendered, so why not tooltip widgets?
+ }
+ }
}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WAbstractSlider.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WAbstractSlider.java
index 6c422bc..b5eda0a 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WAbstractSlider.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WAbstractSlider.java
@@ -5,6 +5,7 @@ import net.fabricmc.api.Environment;
import net.minecraft.util.math.MathHelper;
import io.github.cottonmc.cotton.gui.widget.data.Axis;
+import io.github.cottonmc.cotton.gui.widget.data.InputResult;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.glfw.GLFW;
@@ -108,28 +109,31 @@ public abstract class WAbstractSlider extends WWidget {
@Environment(EnvType.CLIENT)
@Override
- public WWidget onMouseDown(int x, int y, int button) {
+ public InputResult onMouseDown(int x, int y, int button) {
// Check if cursor is inside or <=2px away from track
if (isMouseInsideBounds(x, y)) {
requestFocus();
+ return InputResult.PROCESSED;
}
- return super.onMouseDown(x, y, button);
+ return InputResult.IGNORED;
}
@Environment(EnvType.CLIENT)
@Override
- public void onMouseDrag(int x, int y, int button) {
+ public InputResult onMouseDrag(int x, int y, int button, double deltaX, double deltaY) {
if (isFocused()) {
dragging = true;
moveSlider(x, y);
}
+ return InputResult.PROCESSED;
}
@Environment(EnvType.CLIENT)
@Override
- public void onClick(int x, int y, int button) {
+ public InputResult onClick(int x, int y, int button) {
moveSlider(x, y);
if (draggingFinishedListener != null) draggingFinishedListener.accept(value);
+ return InputResult.PROCESSED;
}
private void moveSlider(int x, int y) {
@@ -160,15 +164,15 @@ public abstract class WAbstractSlider extends WWidget {
@Environment(EnvType.CLIENT)
@Override
- public WWidget onMouseUp(int x, int y, int button) {
+ public InputResult onMouseUp(int x, int y, int button) {
dragging = false;
if (draggingFinishedListener != null) draggingFinishedListener.accept(value);
- return super.onMouseUp(x, y, button);
+ return InputResult.PROCESSED;
}
@Environment(EnvType.CLIENT)
@Override
- public void onMouseScroll(int x, int y, double amount) {
+ public InputResult onMouseScroll(int x, int y, double amount) {
if (direction == Direction.LEFT || direction == Direction.DOWN) {
amount = -amount;
}
@@ -180,6 +184,7 @@ public abstract class WAbstractSlider extends WWidget {
onValueChanged(value);
pendingDraggingFinishedFromScrolling = true;
}
+ return InputResult.PROCESSED;
}
@Environment(EnvType.CLIENT)
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WBar.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WBar.java
index 13cf16b..1aea8ec 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WBar.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WBar.java
@@ -113,9 +113,9 @@ public class WBar extends WWidget {
@Override
public void paint(MatrixStack matrices, int x, int y, int mouseX, int mouseY) {
if (bg!=null) {
- ScreenDrawing.texturedRect(x, y, getWidth(), getHeight(), bg, 0xFFFFFFFF);
+ ScreenDrawing.texturedRect(matrices, x, y, getWidth(), getHeight(), bg, 0xFFFFFFFF);
} else {
- ScreenDrawing.coloredRect(x, y, getWidth(), getHeight(), ScreenDrawing.colorAtOpacity(0x000000, 0.25f));
+ ScreenDrawing.coloredRect(matrices, x, y, getWidth(), getHeight(), ScreenDrawing.colorAtOpacity(0x000000, 0.25f));
}
float percent = properties.get(field) / (float) properties.get(max);
@@ -135,25 +135,25 @@ public class WBar extends WWidget {
int top = y + getHeight();
top -= barSize;
if (bar!=null) {
- ScreenDrawing.texturedRect(left, top, getWidth(), barSize, bar.image, bar.u1, MathHelper.lerp(percent, bar.v2, bar.v1), bar.u2, bar.v2, 0xFFFFFFFF);
+ ScreenDrawing.texturedRect(matrices, left, top, getWidth(), barSize, bar.image, bar.u1, MathHelper.lerp(percent, bar.v2, bar.v1), bar.u2, bar.v2, 0xFFFFFFFF);
} else {
- ScreenDrawing.coloredRect(left, top, getWidth(), barSize, ScreenDrawing.colorAtOpacity(0xFFFFFF, 0.5f));
+ ScreenDrawing.coloredRect(matrices, left, top, getWidth(), barSize, ScreenDrawing.colorAtOpacity(0xFFFFFF, 0.5f));
}
break;
}
case RIGHT: {
if (bar!=null) {
- ScreenDrawing.texturedRect(x, y, barSize, getHeight(), bar.image, bar.u1, bar.v1, MathHelper.lerp(percent, bar.u1, bar.u2), bar.v2, 0xFFFFFFFF);
+ ScreenDrawing.texturedRect(matrices, x, y, barSize, getHeight(), bar.image, bar.u1, bar.v1, MathHelper.lerp(percent, bar.u1, bar.u2), bar.v2, 0xFFFFFFFF);
} else {
- ScreenDrawing.coloredRect(x, y, barSize, getHeight(), ScreenDrawing.colorAtOpacity(0xFFFFFF, 0.5f));
+ ScreenDrawing.coloredRect(matrices, x, y, barSize, getHeight(), ScreenDrawing.colorAtOpacity(0xFFFFFF, 0.5f));
}
break;
}
case DOWN: {
if (bar!=null) {
- ScreenDrawing.texturedRect(x, y, getWidth(), barSize, bar.image, bar.u1, bar.v1, bar.u2, MathHelper.lerp(percent, bar.v1, bar.v2), 0xFFFFFFFF);
+ ScreenDrawing.texturedRect(matrices, x, y, getWidth(), barSize, bar.image, bar.u1, bar.v1, bar.u2, MathHelper.lerp(percent, bar.v1, bar.v2), 0xFFFFFFFF);
} else {
- ScreenDrawing.coloredRect(x, y, getWidth(), barSize, ScreenDrawing.colorAtOpacity(0xFFFFFF, 0.5f));
+ ScreenDrawing.coloredRect(matrices, x, y, getWidth(), barSize, ScreenDrawing.colorAtOpacity(0xFFFFFF, 0.5f));
}
break;
}
@@ -162,9 +162,9 @@ public class WBar extends WWidget {
int top = y;
left -= barSize;
if (bar!=null) {
- ScreenDrawing.texturedRect(left, top, barSize, getHeight(), bar.image, MathHelper.lerp(percent, bar.u2, bar.u1), bar.v1, bar.u2, bar.v2, 0xFFFFFFFF);
+ ScreenDrawing.texturedRect(matrices, left, top, barSize, getHeight(), bar.image, MathHelper.lerp(percent, bar.u2, bar.u1), bar.v1, bar.u2, bar.v2, 0xFFFFFFFF);
} else {
- ScreenDrawing.coloredRect(left, top, barSize, getHeight(), ScreenDrawing.colorAtOpacity(0xFFFFFF, 0.5f));
+ ScreenDrawing.coloredRect(matrices, left, top, barSize, getHeight(), ScreenDrawing.colorAtOpacity(0xFFFFFF, 0.5f));
}
break;
}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java
index 65dde6f..a8db003 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java
@@ -11,6 +11,7 @@ import net.minecraft.text.Text;
import io.github.cottonmc.cotton.gui.client.ScreenDrawing;
import io.github.cottonmc.cotton.gui.widget.data.HorizontalAlignment;
+import io.github.cottonmc.cotton.gui.widget.data.InputResult;
import io.github.cottonmc.cotton.gui.widget.icon.Icon;
import org.jetbrains.annotations.Nullable;
@@ -93,8 +94,8 @@ public class WButton extends WWidget {
float buttonEndLeft = (200-(getWidth()/2)) * px;
- ScreenDrawing.texturedRect(x, y, getWidth()/2, 20, AbstractButtonWidget.WIDGETS_LOCATION, buttonLeft, buttonTop, buttonLeft+buttonWidth, buttonTop+buttonHeight, 0xFFFFFFFF);
- ScreenDrawing.texturedRect(x+(getWidth()/2), y, getWidth()/2, 20, AbstractButtonWidget.WIDGETS_LOCATION, buttonEndLeft, buttonTop, 200*px, buttonTop+buttonHeight, 0xFFFFFFFF);
+ ScreenDrawing.texturedRect(matrices, x, y, getWidth()/2, 20, AbstractButtonWidget.WIDGETS_LOCATION, buttonLeft, buttonTop, buttonLeft+buttonWidth, buttonTop+buttonHeight, 0xFFFFFFFF);
+ ScreenDrawing.texturedRect(matrices, x+(getWidth()/2), y, getWidth()/2, 20, AbstractButtonWidget.WIDGETS_LOCATION, buttonEndLeft, buttonTop, 200*px, buttonTop+buttonHeight, 0xFFFFFFFF);
if (icon != null) {
icon.paint(matrices, x + 1, y + 1, 16);
@@ -120,7 +121,7 @@ public class WButton extends WWidget {
@Environment(EnvType.CLIENT)
@Override
- public void onClick(int x, int y, int button) {
+ public InputResult onClick(int x, int y, int button) {
super.onClick(x, y, button);
if (enabled && isWithinBounds(x, y)) {
@@ -128,6 +129,7 @@ public class WButton extends WWidget {
if (onClick!=null) onClick.run();
}
+ return InputResult.PROCESSED;
}
@Environment(EnvType.CLIENT)
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WCardPanel.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WCardPanel.java
index 3d1da6a..8caad27 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WCardPanel.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WCardPanel.java
@@ -178,16 +178,6 @@ public class WCardPanel extends WPanel {
card.validate(c);
if (getSelectedCard() != card) card.onHidden();
}
-
- if (c != null) createPeers(c);
- }
-
- @SuppressWarnings("deprecation")
- @Override
- public void createPeers(GuiDescription c) {
- for (WWidget card : cards) {
- card.createPeers(c);
- }
}
@Environment(EnvType.CLIENT)
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WClippedPanel.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WClippedPanel.java
index 6daf600..a594fc2 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WClippedPanel.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WClippedPanel.java
@@ -13,7 +13,7 @@ public class WClippedPanel extends WPanel {
@Environment(EnvType.CLIENT)
@Override
public void paint(MatrixStack matrices, int x, int y, int mouseX, int mouseY) {
- if (getBackgroundPainter()!=null) getBackgroundPainter().paintBackground(x, y, this);
+ if (getBackgroundPainter()!=null) getBackgroundPainter().paintBackground(matrices, x, y, this);
Scissors.push(x, y, width, height);
for(WWidget child : children) {
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WDynamicLabel.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WDynamicLabel.java
index 0412b83..6099022 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WDynamicLabel.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WDynamicLabel.java
@@ -4,7 +4,7 @@ import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.util.math.MatrixStack;
-import io.github.cottonmc.cotton.gui.client.LibGuiClient;
+import io.github.cottonmc.cotton.gui.client.LibGui;
import io.github.cottonmc.cotton.gui.client.ScreenDrawing;
import io.github.cottonmc.cotton.gui.widget.data.HorizontalAlignment;
@@ -40,7 +40,7 @@ public class WDynamicLabel extends WWidget {
@Override
public void paint(MatrixStack matrices, int x, int y, int mouseX, int mouseY) {
String tr = text.get();
- ScreenDrawing.drawString(matrices, tr, alignment, x, y, this.getWidth(), LibGuiClient.config.darkMode ? darkmodeColor : color);
+ ScreenDrawing.drawString(matrices, tr, alignment, x, y, this.getWidth(), LibGui.isDarkMode() ? darkmodeColor : color);
}
@Override
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java
index 45fc896..1667bee 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java
@@ -328,7 +328,7 @@ public class WItemSlot extends WWidget {
@Override
public void paint(MatrixStack matrices, int x, int y, int mouseX, int mouseY) {
if (backgroundPainter != null) {
- backgroundPainter.paintBackground(x, y, this);
+ backgroundPainter.paintBackground(matrices, x, y, this);
}
}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java
index 0bdf81a..2943f1b 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java
@@ -10,10 +10,10 @@ import net.minecraft.text.LiteralText;
import net.minecraft.text.Style;
import net.minecraft.text.Text;
-import io.github.cottonmc.cotton.gui.client.LibGuiClient;
+import io.github.cottonmc.cotton.gui.client.LibGui;
import io.github.cottonmc.cotton.gui.client.ScreenDrawing;
-import io.github.cottonmc.cotton.gui.client.TextHoverRendererScreen;
import io.github.cottonmc.cotton.gui.widget.data.HorizontalAlignment;
+import io.github.cottonmc.cotton.gui.widget.data.InputResult;
import io.github.cottonmc.cotton.gui.widget.data.VerticalAlignment;
import org.jetbrains.annotations.Nullable;
@@ -33,7 +33,7 @@ public class WLabel extends WWidget {
public static final int DEFAULT_TEXT_COLOR = 0x404040;
/**
- * The default text color for {@linkplain io.github.cottonmc.cotton.gui.client.LibGuiConfig#darkMode dark mode} labels.
+ * The default text color for {@linkplain LibGui#isDarkMode() dark mode} labels.
*/
public static final int DEFAULT_DARKMODE_TEXT_COLOR = 0xbcbcbc;
@@ -98,20 +98,15 @@ public class WLabel extends WWidget {
break;
}
- ScreenDrawing.drawString(matrices, text.asOrderedText(), horizontalAlignment, x, y + yOffset, this.getWidth(), LibGuiClient.config.darkMode ? darkmodeColor : color);
+ ScreenDrawing.drawString(matrices, text.asOrderedText(), horizontalAlignment, x, y + yOffset, this.getWidth(), LibGui.isDarkMode() ? darkmodeColor : color);
Style hoveredTextStyle = getTextStyleAt(mouseX, mouseY);
- if (hoveredTextStyle != null) {
- Screen screen = MinecraftClient.getInstance().currentScreen;
- if (screen instanceof TextHoverRendererScreen) {
- ((TextHoverRendererScreen) screen).renderTextHover(matrices, hoveredTextStyle, x + mouseX, y + mouseY);
- }
- }
+ ScreenDrawing.drawTextHover(matrices, hoveredTextStyle, x + mouseX, y + mouseY);
}
@Environment(EnvType.CLIENT)
@Override
- public void onClick(int x, int y, int button) {
+ public InputResult onClick(int x, int y, int button) {
Style hoveredTextStyle = getTextStyleAt(x, y);
if (hoveredTextStyle != null) {
Screen screen = MinecraftClient.getInstance().currentScreen;
@@ -119,6 +114,7 @@ public class WLabel extends WWidget {
screen.handleTextClick(hoveredTextStyle);
}
}
+ return InputResult.PROCESSED;
}
/**
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabeledSlider.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabeledSlider.java
index 0c1a510..57cc8e6 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabeledSlider.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabeledSlider.java
@@ -1,11 +1,11 @@
package io.github.cottonmc.cotton.gui.widget;
-import com.mojang.blaze3d.systems.RenderSystem;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gui.widget.AbstractButtonWidget;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.Text;
+import net.minecraft.util.math.Vec3f;
import io.github.cottonmc.cotton.gui.client.ScreenDrawing;
import io.github.cottonmc.cotton.gui.widget.data.Axis;
@@ -155,7 +155,6 @@ public class WLabeledSlider extends WAbstractSlider {
return x >= 0 && x <= width && y >= 0 && y <= height;
}
- @SuppressWarnings("deprecation")
@Environment(EnvType.CLIENT)
@Override
public void paint(MatrixStack matrices, int x, int y, int mouseX, int mouseY) {
@@ -166,13 +165,13 @@ public class WLabeledSlider extends WAbstractSlider {
: (direction == Direction.UP ? height - mouseY : mouseY);
int rotMouseY = axis == Axis.HORIZONTAL ? mouseY : mouseX;
- RenderSystem.pushMatrix();
- RenderSystem.translatef(x, y, 0);
+ matrices.push();
+ matrices.translate(x, y, 0);
if (axis == Axis.VERTICAL) {
- RenderSystem.translatef(0, height, 0);
- RenderSystem.rotatef(270, 0, 0, 1);
+ matrices.translate(0, height, 0);
+ matrices.multiply(Vec3f.POSITIVE_Z.getDegreesQuaternion(270));
}
- drawButton(0, 0, 0, aWidth);
+ drawButton(matrices, 0, 0, 0, aWidth);
// 1: regular, 2: hovered, 0: disabled/dragging
int thumbX = Math.round(coordToValueRatio * (value - min));
@@ -182,23 +181,23 @@ public class WLabeledSlider extends WAbstractSlider {
boolean hovering = rotMouseX >= thumbX && rotMouseX <= thumbX + thumbWidth && rotMouseY >= thumbY && rotMouseY <= thumbY + thumbHeight;
int thumbState = dragging || hovering ? 2 : 1;
- drawButton(thumbX, thumbY, thumbState, thumbWidth);
+ drawButton(matrices, thumbX, thumbY, thumbState, thumbWidth);
if (thumbState == 1 && isFocused()) {
float px = 1 / 32f;
- ScreenDrawing.texturedRect(thumbX, thumbY, thumbWidth, thumbHeight, WSlider.LIGHT_TEXTURE, 24*px, 0*px, 32*px, 20*px, 0xFFFFFFFF);
+ ScreenDrawing.texturedRect(matrices, thumbX, thumbY, thumbWidth, thumbHeight, WSlider.LIGHT_TEXTURE, 24*px, 0*px, 32*px, 20*px, 0xFFFFFFFF);
}
if (label != null) {
int color = isMouseInsideBounds(mouseX, mouseY) ? 0xFFFFA0 : 0xE0E0E0;
ScreenDrawing.drawStringWithShadow(matrices, label.asOrderedText(), labelAlignment, 2, aHeight / 2 - 4, aWidth - 4, color);
}
- RenderSystem.popMatrix();
+ matrices.pop();
}
// state = 1: regular, 2: hovered, 0: disabled/dragging
@Environment(EnvType.CLIENT)
- private void drawButton(int x, int y, int state, int width) {
+ private void drawButton(MatrixStack matrices, int x, int y, int state, int width) {
float px = 1 / 256f;
float buttonLeft = 0 * px;
float buttonTop = (46 + (state * 20)) * px;
@@ -208,8 +207,8 @@ public class WLabeledSlider extends WAbstractSlider {
float buttonHeight = 20 * px;
float buttonEndLeft = (200 - halfWidth) * px;
- ScreenDrawing.texturedRect(x, y, halfWidth, 20, AbstractButtonWidget.WIDGETS_LOCATION, buttonLeft, buttonTop, buttonLeft + buttonWidth, buttonTop + buttonHeight, 0xFFFFFFFF);
- ScreenDrawing.texturedRect(x + halfWidth, y, halfWidth, 20, AbstractButtonWidget.WIDGETS_LOCATION, buttonEndLeft, buttonTop, 200 * px, buttonTop + buttonHeight, 0xFFFFFFFF);
+ ScreenDrawing.texturedRect(matrices, x, y, halfWidth, 20, AbstractButtonWidget.WIDGETS_LOCATION, buttonLeft, buttonTop, buttonLeft + buttonWidth, buttonTop + buttonHeight, 0xFFFFFFFF);
+ ScreenDrawing.texturedRect(matrices, x + halfWidth, y, halfWidth, 20, AbstractButtonWidget.WIDGETS_LOCATION, buttonEndLeft, buttonTop, 200 * px, buttonTop + buttonHeight, 0xFFFFFFFF);
}
/**
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WPanel.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WPanel.java
index 90ef5d6..51a10ce 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WPanel.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WPanel.java
@@ -26,15 +26,6 @@ public abstract class WPanel extends WWidget {
@Environment(EnvType.CLIENT)
private BackgroundPainter backgroundPainter = null;
- @SuppressWarnings("deprecation")
- @Override
- public void createPeers(GuiDescription c) {
- super.createPeers(c);
- for(WWidget child : children) {
- child.createPeers(c);
- }
- }
-
/**
* Removes the widget from this panel.
*
@@ -92,70 +83,6 @@ public abstract class WPanel extends WWidget {
this.setSize(Math.max(this.getWidth(), pushRight), Math.max(this.getHeight(), pushDown));
}
- @Environment(EnvType.CLIENT)
- @Override
- public WWidget onMouseUp(int x, int y, int button) {
- if (children.isEmpty()) return super.onMouseUp(x, y, button);
- for(int i=children.size()-1; i>=0; i--) { //Backwards so topmost widgets get priority
- WWidget child = children.get(i);
- if ( x>=child.getX() &&
- y>=child.getY() &&
- x<child.getX()+child.getWidth() &&
- y<child.getY()+child.getHeight()) {
- return child.onMouseUp(x-child.getX(), y-child.getY(), button);
- }
- }
- return super.onMouseUp(x, y, button);
- }
-
- @Environment(EnvType.CLIENT)
- @Override
- public WWidget onMouseDown(int x, int y, int button) {
- if (children.isEmpty()) return super.onMouseDown(x, y, button);
- for(int i=children.size()-1; i>=0; i--) { //Backwards so topmost widgets get priority
- WWidget child = children.get(i);
- if ( x>=child.getX() &&
- y>=child.getY() &&
- x<child.getX()+child.getWidth() &&
- y<child.getY()+child.getHeight()) {
- return child.onMouseDown(x-child.getX(), y-child.getY(), button);
- }
- }
- return super.onMouseDown(x, y, button);
- }
-
- @Environment(EnvType.CLIENT)
- @Override
- public void onMouseDrag(int x, int y, int button) {
- if (children.isEmpty()) return;
- for(int i=children.size()-1; i>=0; i--) { //Backwards so topmost widgets get priority
- WWidget child = children.get(i);
- if ( x>=child.getX() &&
- y>=child.getY() &&
- x<child.getX()+child.getWidth() &&
- y<child.getY()+child.getHeight()) {
- child.onMouseDrag(x-child.getX(), y-child.getY(), button);
- return; //Only send the message to the first valid recipient
- }
- }
- super.onMouseDrag(x, y, button);
- }
- /*
- @Override
- public void onClick(int x, int y, int button) {
- if (children.isEmpty()) return;
- for(int i=children.size()-1; i>=0; i--) { //Backwards so topmost widgets get priority
- WWidget child = children.get(i);
- if ( x>=child.getX() &&
- y>=child.getY() &&
- x<child.getX()+child.getWidth() &&
- y<child.getY()+child.getHeight()) {
- child.onClick(x-child.getX(), y-child.getY(), button);
- return; //Only send the message to the first valid recipient
- }
- }
- }*/
-
/**
* Finds the most specific child node at this location.
*/
@@ -188,13 +115,12 @@ public abstract class WPanel extends WWidget {
for (WWidget child : children) {
child.validate(c);
}
- if (c!=null) createPeers(c);
}
@Environment(EnvType.CLIENT)
@Override
public void paint(MatrixStack matrices, int x, int y, int mouseX, int mouseY) {
- if (backgroundPainter!=null) backgroundPainter.paintBackground(x, y, this);
+ if (backgroundPainter!=null) backgroundPainter.paintBackground(matrices, x, y, this);
for(WWidget child : children) {
child.paint(matrices, x + child.getX(), y + child.getY(), mouseX-child.getX(), mouseY-child.getY());
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WScrollBar.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WScrollBar.java
index 500f312..ea23953 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WScrollBar.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WScrollBar.java
@@ -4,9 +4,10 @@ import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.util.math.MatrixStack;
-import io.github.cottonmc.cotton.gui.client.LibGuiClient;
+import io.github.cottonmc.cotton.gui.client.LibGui;
import io.github.cottonmc.cotton.gui.client.ScreenDrawing;
import io.github.cottonmc.cotton.gui.widget.data.Axis;
+import io.github.cottonmc.cotton.gui.widget.data.InputResult;
public class WScrollBar extends WWidget {
protected Axis axis = Axis.HORIZONTAL;
@@ -36,10 +37,10 @@ public class WScrollBar extends WWidget {
@Environment(EnvType.CLIENT)
@Override
public void paint(MatrixStack matrices, int x, int y, int mouseX, int mouseY) {
- if (LibGuiClient.config.darkMode) {
- ScreenDrawing.drawBeveledPanel(x, y, width, height, 0xFF_212121, 0xFF_2F2F2F, 0xFF_5D5D5D);
+ if (LibGui.isDarkMode()) {
+ ScreenDrawing.drawBeveledPanel(matrices, x, y, width, height, 0xFF_212121, 0xFF_2F2F2F, 0xFF_5D5D5D);
} else {
- ScreenDrawing.drawBeveledPanel(x, y, width, height, 0xFF_373737, 0xFF_8B8B8B, 0xFF_FFFFFF);
+ ScreenDrawing.drawBeveledPanel(matrices, x, y, width, height, 0xFF_373737, 0xFF_8B8B8B, 0xFF_FFFFFF);
}
if (maxValue<=0) return;
@@ -47,7 +48,7 @@ public class WScrollBar extends WWidget {
int top, middle, bottom;
if (sliding) {
- if (LibGuiClient.config.darkMode) {
+ if (LibGui.isDarkMode()) {
top = 0xFF_6C6C6C;
middle = 0xFF_2F2F2F;
bottom = 0xFF_212121;
@@ -57,7 +58,7 @@ public class WScrollBar extends WWidget {
bottom = 0xFF_555555;
}
} else if (isWithinBounds(mouseX, mouseY)) {
- if (LibGuiClient.config.darkMode) {
+ if (LibGui.isDarkMode()) {
top = 0xFF_5F6A9D;
middle = 0xFF_323F6E;
bottom = 0xFF_0B204A;
@@ -67,7 +68,7 @@ public class WScrollBar extends WWidget {
bottom = 0xFF_343E75;
}
} else {
- if (LibGuiClient.config.darkMode) {
+ if (LibGui.isDarkMode()) {
top = 0xFF_6C6C6C;
middle = 0xFF_414141;
bottom = 0xFF_212121;
@@ -79,16 +80,16 @@ public class WScrollBar extends WWidget {
}
if (axis==Axis.HORIZONTAL) {
- ScreenDrawing.drawBeveledPanel(x+1+getHandlePosition(), y+1, getHandleSize(), height-2, top, middle, bottom);
+ ScreenDrawing.drawBeveledPanel(matrices, x+1+getHandlePosition(), y+1, getHandleSize(), height-2, top, middle, bottom);
if (isFocused()) {
- drawBeveledOutline(x+1+getHandlePosition(), y+1, getHandleSize(), height-2, 0xFF_FFFFA7, 0xFF_8C8F39);
+ drawBeveledOutline(matrices, x+1+getHandlePosition(), y+1, getHandleSize(), height-2, 0xFF_FFFFA7, 0xFF_8C8F39);
}
} else {
- ScreenDrawing.drawBeveledPanel(x+1, y+1+getHandlePosition(), width-2, getHandleSize(), top, middle, bottom);
+ ScreenDrawing.drawBeveledPanel(matrices, x+1, y+1+getHandlePosition(), width-2, getHandleSize(), top, middle, bottom);
if (isFocused()) {
- drawBeveledOutline(x+1, y+1+getHandlePosition(), width-2, getHandleSize(), 0xFF_FFFFA7, 0xFF_8C8F39);
+ drawBeveledOutline(matrices, x+1, y+1+getHandlePosition(), width-2, getHandleSize(), 0xFF_FFFFA7, 0xFF_8C8F39);
}
}
}
@@ -103,11 +104,12 @@ public class WScrollBar extends WWidget {
return true;
}
- private static void drawBeveledOutline(int x, int y, int width, int height, int topleft, int bottomright) {
- ScreenDrawing.coloredRect(x, y, width, 1, topleft); //Top shadow
- ScreenDrawing.coloredRect(x, y + 1, 1, height - 1, topleft); //Left shadow
- ScreenDrawing.coloredRect(x + width - 1, y + 1, 1, height - 1, bottomright); //Right hilight
- ScreenDrawing.coloredRect(x + 1, y + height - 1, width - 1, 1, bottomright); //Bottom hilight
+ @Environment(EnvType.CLIENT)
+ private static void drawBeveledOutline(MatrixStack matrices, int x, int y, int width, int height, int topleft, int bottomright) {
+ ScreenDrawing.coloredRect(matrices, x, y, width, 1, topleft); //Top shadow
+ ScreenDrawing.coloredRect(matrices, x, y + 1, 1, height - 1, topleft); //Left shadow
+ ScreenDrawing.coloredRect(matrices, x + width - 1, y + 1, 1, height - 1, bottomright); //Right hilight
+ ScreenDrawing.coloredRect(matrices, x + 1, y + height - 1, width - 1, 1, bottomright); //Bottom hilight
}
/**
@@ -166,7 +168,7 @@ public class WScrollBar extends WWidget {
}
@Override
- public WWidget onMouseDown(int x, int y, int button) {
+ public InputResult onMouseDown(int x, int y, int button) {
//TODO: Clicking before or after the handle should jump instead of scrolling
requestFocus();
@@ -178,23 +180,25 @@ public class WScrollBar extends WWidget {
anchorValue = value;
}
sliding = true;
- return this;
+
+ return InputResult.PROCESSED;
}
@Environment(EnvType.CLIENT)
@Override
- public void onMouseDrag(int x, int y, int button) {
+ public InputResult onMouseDrag(int x, int y, int button, double deltaX, double deltaY) {
adjustSlider(x, y);
+ return InputResult.PROCESSED;
}
@Environment(EnvType.CLIENT)
@Override
- public WWidget onMouseUp(int x, int y, int button) {
+ public InputResult onMouseUp(int x, int y, int button) {
//TODO: Clicking before or after the handle should jump instead of scrolling
anchor = -1;
anchorValue = -1;
sliding = false;
- return this;
+ return InputResult.PROCESSED;
}
@Override
@@ -216,8 +220,9 @@ public class WScrollBar extends WWidget {
@Environment(EnvType.CLIENT)
@Override
- public void onMouseScroll(int x, int y, double amount) {
+ public InputResult onMouseScroll(int x, int y, double amount) {
setValue(getValue() + (int) -amount);
+ return InputResult.PROCESSED;
}
public int getValue() {
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WSlider.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WSlider.java
index 0e78333..a63c9cb 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WSlider.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WSlider.java
@@ -6,7 +6,7 @@ import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Identifier;
import io.github.cottonmc.cotton.gui.client.BackgroundPainter;
-import io.github.cottonmc.cotton.gui.client.LibGuiClient;
+import io.github.cottonmc.cotton.gui.client.LibGui;
import io.github.cottonmc.cotton.gui.client.ScreenDrawing;
import io.github.cottonmc.cotton.gui.widget.data.Axis;
import org.jetbrains.annotations.Nullable;
@@ -50,14 +50,14 @@ public class WSlider extends WAbstractSlider {
@Override
public void paint(MatrixStack matrices, int x, int y, int mouseX, int mouseY) {
if (backgroundPainter != null) {
- backgroundPainter.paintBackground(x, y, this);
+ backgroundPainter.paintBackground(matrices, x, y, this);
} else {
float px = 1 / 32f;
// thumbX/Y: thumb position in widget-space
int thumbX, thumbY;
// thumbXOffset: thumb texture x offset in pixels
int thumbXOffset;
- Identifier texture = LibGuiClient.config.darkMode ? DARK_TEXTURE : LIGHT_TEXTURE;
+ Identifier texture = LibGui.isDarkMode() ? DARK_TEXTURE : LIGHT_TEXTURE;
if (axis == Axis.VERTICAL) {
int trackX = x + width / 2 - TRACK_WIDTH / 2;
@@ -67,9 +67,9 @@ public class WSlider extends WAbstractSlider {
: Math.round(coordToValueRatio * (value - min));
thumbXOffset = 0;
- ScreenDrawing.texturedRect(trackX, y + 1, TRACK_WIDTH, 1, texture, 16*px, 0*px, 22*px, 1*px, 0xFFFFFFFF);
- ScreenDrawing.texturedRect(trackX, y + 2, TRACK_WIDTH, height - 2, texture, 16*px, 1*px, 22*px, 2*px, 0xFFFFFFFF);
- ScreenDrawing.texturedRect(trackX, y + height, TRACK_WIDTH, 1, texture, 16*px, 2*px, 22*px, 3*px, 0xFFFFFFFF);
+ ScreenDrawing.texturedRect(matrices, trackX, y + 1, TRACK_WIDTH, 1, texture, 16*px, 0*px, 22*px, 1*px, 0xFFFFFFFF);
+ ScreenDrawing.texturedRect(matrices, trackX, y + 2, TRACK_WIDTH, height - 2, texture, 16*px, 1*px, 22*px, 2*px, 0xFFFFFFFF);
+ ScreenDrawing.texturedRect(matrices, trackX, y + height, TRACK_WIDTH, 1, texture, 16*px, 2*px, 22*px, 3*px, 0xFFFFFFFF);
} else {
int trackY = y + height / 2 - TRACK_WIDTH / 2;
thumbX = direction == Direction.LEFT
@@ -78,18 +78,18 @@ public class WSlider extends WAbstractSlider {
thumbY = height / 2 - THUMB_SIZE / 2;
thumbXOffset = 8;
- ScreenDrawing.texturedRect(x, trackY, 1, TRACK_WIDTH, texture, 16*px, 3*px, 17*px, 9*px, 0xFFFFFFFF);
- ScreenDrawing.texturedRect(x + 1, trackY, width - 2, TRACK_WIDTH, texture, 17*px, 3*px, 18*px, 9*px, 0xFFFFFFFF);
- ScreenDrawing.texturedRect(x + width - 1, trackY, 1, TRACK_WIDTH, texture, 18*px, 3*px, 19*px, 9*px, 0xFFFFFFFF);
+ ScreenDrawing.texturedRect(matrices, x, trackY, 1, TRACK_WIDTH, texture, 16*px, 3*px, 17*px, 9*px, 0xFFFFFFFF);
+ ScreenDrawing.texturedRect(matrices, x + 1, trackY, width - 2, TRACK_WIDTH, texture, 17*px, 3*px, 18*px, 9*px, 0xFFFFFFFF);
+ ScreenDrawing.texturedRect(matrices, x + width - 1, trackY, 1, TRACK_WIDTH, texture, 18*px, 3*px, 19*px, 9*px, 0xFFFFFFFF);
}
// thumbState values:
// 0: default, 1: dragging, 2: hovered
int thumbState = dragging ? 1 : (mouseX >= thumbX && mouseX <= thumbX + THUMB_SIZE && mouseY >= thumbY && mouseY <= thumbY + THUMB_SIZE ? 2 : 0);
- ScreenDrawing.texturedRect(x + thumbX, y + thumbY, THUMB_SIZE, THUMB_SIZE, texture, thumbXOffset*px, 0*px + thumbState * 8*px, (thumbXOffset + 8)*px, 8*px + thumbState * 8*px, 0xFFFFFFFF);
+ ScreenDrawing.texturedRect(matrices, x + thumbX, y + thumbY, THUMB_SIZE, THUMB_SIZE, texture, thumbXOffset*px, 0*px + thumbState * 8*px, (thumbXOffset + 8)*px, 8*px + thumbState * 8*px, 0xFFFFFFFF);
if (thumbState == 0 && isFocused()) {
- ScreenDrawing.texturedRect(x + thumbX, y + thumbY, THUMB_SIZE, THUMB_SIZE, texture, 0*px, 24*px, 8*px, 32*px, 0xFFFFFFFF);
+ ScreenDrawing.texturedRect(matrices, x + thumbX, y + thumbY, THUMB_SIZE, THUMB_SIZE, texture, 0*px, 24*px, 8*px, 32*px, 0xFFFFFFFF);
}
}
}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WSprite.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WSprite.java
index 632ca6c..a17ed42 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WSprite.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WSprite.java
@@ -184,7 +184,7 @@ public class WSprite extends WWidget {
@Override
public void paint(MatrixStack matrices, int x, int y, int mouseX, int mouseY) {
if (singleImage) {
- paintFrame(x, y, frames[0]);
+ paintFrame(matrices, x, y, frames[0]);
} else {
//grab the system time at the very start of the frame.
long now = System.nanoTime() / 1_000_000L;
@@ -194,7 +194,7 @@ public class WSprite extends WWidget {
if (!inBounds) currentFrame = 0;
//assemble and draw the frame calculated last iteration.
Texture currentFrameTex = frames[currentFrame];
- paintFrame(x, y, currentFrameTex);
+ paintFrame(matrices, x, y, currentFrameTex);
//calculate how much time has elapsed since the last animation change, and change the frame if necessary.
long elapsed = now - lastFrame;
@@ -216,12 +216,13 @@ public class WSprite extends WWidget {
/**
* Paints a single frame for this sprite.
*
- * @param x the X coordinate to draw it at
- * @param y the Y coordinate to draw it at
- * @param texture the texture to draw
+ * @param matrices the rendering matrix stack
+ * @param x the X coordinate to draw it at
+ * @param y the Y coordinate to draw it at
+ * @param texture the texture to draw
*/
@Environment(EnvType.CLIENT)
- protected void paintFrame(int x, int y, Texture texture) {
- ScreenDrawing.texturedRect(x, y, getWidth(), getHeight(), texture, tint);
+ protected void paintFrame(MatrixStack matrices, int x, int y, Texture texture) {
+ ScreenDrawing.texturedRect(matrices, x, y, getWidth(), getHeight(), texture, tint);
}
}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WTabPanel.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WTabPanel.java
index efb71d5..ae23842 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WTabPanel.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WTabPanel.java
@@ -11,18 +11,16 @@ import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import io.github.cottonmc.cotton.gui.client.BackgroundPainter;
-import io.github.cottonmc.cotton.gui.client.LibGuiClient;
+import io.github.cottonmc.cotton.gui.client.LibGui;
import io.github.cottonmc.cotton.gui.client.ScreenDrawing;
import io.github.cottonmc.cotton.gui.widget.data.Axis;
import io.github.cottonmc.cotton.gui.widget.data.HorizontalAlignment;
+import io.github.cottonmc.cotton.gui.widget.data.InputResult;
+import io.github.cottonmc.cotton.gui.widget.data.Tab;
import io.github.cottonmc.cotton.gui.widget.icon.Icon;
-import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
import java.util.List;
-import java.util.Objects;
import java.util.function.Consumer;
// TODO: Different tab positions
@@ -99,178 +97,6 @@ public class WTabPanel extends WPanel {
mainPanel.setBackgroundPainter(BackgroundPainter.VANILLA);
}
- /**
- * The data of a tab.
- */
- public static class Tab {
- @Nullable
- private final Text title;
- @Nullable
- private final Icon icon;
- private final WWidget widget;
- @Nullable
- private final Consumer<TooltipBuilder> tooltip;
-
- /**
- * Constructs a tab.
- *
- * @param title the tab title
- * @param icon the tab icon
- * @param widget the widget contained in the tab
- * @param tooltip the tab tooltip
- * @throws IllegalArgumentException if both the title and the icon are null
- * @throws NullPointerException if the widget is null
- * @deprecated Use {@link Builder} instead.
- */
- @Deprecated
- public Tab(@Nullable Text title, @Nullable Icon icon, WWidget widget, @Nullable Consumer<TooltipBuilder> tooltip) {
- if (title == null && icon == null) {
- throw new IllegalArgumentException("A tab must have a title or an icon");
- }
-
- this.title = title;
- this.icon = icon;
- this.widget = Objects.requireNonNull(widget, "widget");
- this.tooltip = tooltip;
- }
-
- /**
- * Gets the title of this tab.
- *
- * @return the title, or null if there's no title
- */
- @Nullable
- public Text getTitle() {
- return title;
- }
-
- /**
- * Gets the icon of this tab.
- *
- * @return the icon, or null if there's no title
- */
- @Nullable
- public Icon getIcon() {
- return icon;
- }
-
- /**
- * Gets the contained widget of this tab.
- *
- * @return the contained widget
- */
- public WWidget getWidget() {
- return widget;
- }
-
- /**
- * Adds this widget's tooltip to the {@code tooltip} builder.
- *
- * @param tooltip the tooltip builder
- */
- @Environment(EnvType.CLIENT)
- public void addTooltip(TooltipBuilder tooltip) {
- if (this.tooltip != null) {
- this.tooltip.accept(tooltip);
- }
- }
-
- /**
- * A builder for tab data.
- */
- public static final class Builder {
- @Nullable
- private Text title;
- @Nullable
- private Icon icon;
- private final WWidget widget;
- private final List<Text> tooltip = new ArrayList<>();
-
- /**
- * Constructs a new tab data builder.
- *
- * @param widget the contained widget
- * @throws NullPointerException if the widget is null
- */
- public Builder(WWidget widget) {
- this.widget = Objects.requireNonNull(widget, "widget");
- }
-
- /**
- * Sets the tab title.
- *
- * @param title the new title
- * @return this builder
- * @throws NullPointerException if the title is null
- */
- public Builder title(Text title) {
- this.title = Objects.requireNonNull(title, "title");
- return this;
- }
-
- /**
- * Sets the tab icon.
- *
- * @param icon the new icon
- * @return this builder
- * @throws NullPointerException if the icon is null
- */
- public Builder icon(Icon icon) {
- this.icon = Objects.requireNonNull(icon, "icon");
- return this;
- }
-
- /**
- * Adds lines to the tab's tooltip.
- *
- * @param lines the added lines
- * @return this builder
- * @throws NullPointerException if the line array is null
- */
- public Builder tooltip(Text... lines) {
- Objects.requireNonNull(lines, "lines");
- Collections.addAll(tooltip, lines);
-
- return this;
- }
-
- /**
- * Adds lines to the tab's tooltip.
- *
- * @param lines the added lines
- * @return this builder
- * @throws NullPointerException if the line collection is null
- */
- public Builder tooltip(Collection<? extends Text> lines) {
- Objects.requireNonNull(lines, "lines");
- tooltip.addAll(lines);
- return this;
- }
-
- /**
- * Builds a tab from this builder.
- *
- * @return the built tab
- */
- public Tab build() {
- Consumer<TooltipBuilder> tooltip = null;
-
- if (!this.tooltip.isEmpty()) {
- //noinspection Convert2Lambda
- tooltip = new Consumer<TooltipBuilder>() {
- @Environment(EnvType.CLIENT)
- @Override
- public void accept(TooltipBuilder builder) {
- builder.add(Tab.Builder.this.tooltip.toArray(new Text[0]));
- }
- };
- }
-
- return new Tab(title, icon, widget, tooltip);
- }
- }
- }
-
private final class WTab extends WWidget {
private final Tab data;
boolean selected = false;
@@ -286,9 +112,7 @@ public class WTabPanel extends WPanel {
@Environment(EnvType.CLIENT)
@Override
- public void onClick(int x, int y, int button) {
- super.onClick(x, y, button);
-
+ public InputResult onClick(int x, int y, int button) {
MinecraftClient.getInstance().getSoundManager().play(PositionedSoundInstance.master(SoundEvents.UI_BUTTON_CLICK, 1.0F));
for (WTab tab : tabWidgets) {
@@ -297,6 +121,7 @@ public class WTabPanel extends WPanel {
mainPanel.setSelectedCard(data.getWidget());
WTabPanel.this.layout();
+ return InputResult.PROCESSED;
}
@Environment(EnvType.CLIENT)
@@ -324,9 +149,9 @@ public class WTabPanel extends WPanel {
}
}
- (selected ? Painters.SELECTED_TAB : Painters.UNSELECTED_TAB).paintBackground(x, y, this);
+ (selected ? Painters.SELECTED_TAB : Painters.UNSELECTED_TAB).paintBackground(matrices, x, y, this);
if (isFocused()) {
- (selected ? Painters.SELECTED_TAB_FOCUS_BORDER : Painters.UNSELECTED_TAB_FOCUS_BORDER).paintBackground(x, y, this);
+ (selected ? Painters.SELECTED_TAB_FOCUS_BORDER : Painters.UNSELECTED_TAB_FOCUS_BORDER).paintBackground(matrices, x, y, this);
}
int iconX = 6;
@@ -338,7 +163,7 @@ public class WTabPanel extends WPanel {
HorizontalAlignment align = (icon != null) ? HorizontalAlignment.LEFT : HorizontalAlignment.CENTER;
int color;
- if (LibGuiClient.config.darkMode) {
+ if (LibGui.isDarkMode()) {
color = WLabel.DEFAULT_DARKMODE_TEXT_COLOR;
} else {
color = selected ? WLabel.DEFAULT_TEXT_COLOR : 0xEEEEEE;
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WText.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WText.java
index 953f995..6f8afca 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WText.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WText.java
@@ -4,16 +4,15 @@ import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
-import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.OrderedText;
import net.minecraft.text.Style;
import net.minecraft.text.Text;
-import io.github.cottonmc.cotton.gui.client.LibGuiClient;
+import io.github.cottonmc.cotton.gui.client.LibGui;
import io.github.cottonmc.cotton.gui.client.ScreenDrawing;
-import io.github.cottonmc.cotton.gui.client.TextHoverRendererScreen;
import io.github.cottonmc.cotton.gui.widget.data.HorizontalAlignment;
+import io.github.cottonmc.cotton.gui.widget.data.InputResult;
import io.github.cottonmc.cotton.gui.widget.data.VerticalAlignment;
import org.jetbrains.annotations.Nullable;
@@ -109,29 +108,26 @@ public class WText extends WWidget {
for (int i = 0; i < wrappedLines.size(); i++) {
OrderedText line = wrappedLines.get(i);
- int c = LibGuiClient.config.darkMode ? darkmodeColor : color;
+ int c = LibGui.isDarkMode() ? darkmodeColor : color;
ScreenDrawing.drawString(matrices, line, horizontalAlignment, x, y + yOffset + i * font.fontHeight, width, c);
}
Style hoveredTextStyle = getTextStyleAt(mouseX, mouseY);
- if (hoveredTextStyle != null) {
- Screen screen = MinecraftClient.getInstance().currentScreen;
- if (screen instanceof TextHoverRendererScreen) {
- ((TextHoverRendererScreen) screen).renderTextHover(matrices, hoveredTextStyle, x + mouseX, y + mouseY);
- }
- }
+ ScreenDrawing.drawTextHover(matrices, hoveredTextStyle, x + mouseX, y + mouseY);
}
@Environment(EnvType.CLIENT)
@Override
- public void onClick(int x, int y, int button) {
- if (button != 0) return; // only left clicks
+ public InputResult onClick(int x, int y, int button) {
+ if (button != 0) return InputResult.IGNORED; // only left clicks
Style hoveredTextStyle = getTextStyleAt(x, y);
if (hoveredTextStyle != null) {
MinecraftClient.getInstance().currentScreen.handleTextClick(hoveredTextStyle);
}
+
+ return InputResult.PROCESSED;
}
/**
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WTextField.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WTextField.java
index 8ff03cf..ead273b 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WTextField.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WTextField.java
@@ -9,17 +9,19 @@ import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
+import net.minecraft.client.render.VertexFormat;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import net.minecraft.util.math.MathHelper;
+import net.minecraft.util.math.Matrix4f;
import io.github.cottonmc.cotton.gui.client.BackgroundPainter;
import io.github.cottonmc.cotton.gui.client.ScreenDrawing;
+import io.github.cottonmc.cotton.gui.widget.data.InputResult;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.glfw.GLFW;
-import org.lwjgl.opengl.GL11;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -86,78 +88,6 @@ public class WTextField extends WWidget {
public void setSize(int x, int y) {
super.setSize(x, 20);
}
-
- /*
- public String getSelectedText() {
- int start = this.cursorMax < this.cursorMin ? this.cursorMax : this.cursorMin;
- int end = this.cursorMax < this.cursorMin ? this.cursorMin : this.cursorMax;
- return this.text.substring(start, end);
- }*/
-
- /*
- //This would seem to insert or paste text in the vanilla control
- public void addText(String string_1) {
- String string_2 = "";
- String string_3 = SharedConstants.stripInvalidChars(string_1);
- int int_1 = this.cursorMax < this.cursorMin ? this.cursorMax : this.cursorMin;
- int int_2 = this.cursorMax < this.cursorMin ? this.cursorMin : this.cursorMax;
- int int_3 = this.maxLength - this.text.length() - (int_1 - int_2);
- if (!this.text.isEmpty()) {
- string_2 = string_2 + this.text.substring(0, int_1);
- }
-
- int int_5;
- if (int_3 < string_3.length()) {
- string_2 = string_2 + string_3.substring(0, int_3);
- int_5 = int_3;
- } else {
- string_2 = string_2 + string_3;
- int_5 = string_3.length();
- }
-
- if (!this.text.isEmpty() && int_2 < this.text.length()) {
- string_2 = string_2 + this.text.substring(int_2);
- }
-
- if (this.textPredicate.test(string_2)) {
- this.text = string_2;
- this.setCursor(int_1 + int_5);
- this.method_1884(this.cursorMax);
- this.onChanged(this.text);
- }
- }*/
-
- /*
-
- //this would seem to delete text. if int_1 is negative, deletes from the end?
- public void method_1878(int int_1) {
- if (!this.text.isEmpty()) {
- if (this.cursorMin != this.cursorMax) {
- this.addText("");
- } else {
- boolean boolean_1 = int_1 < 0;
- int int_2 = boolean_1 ? this.cursorMax + int_1 : this.cursorMax;
- int int_3 = boolean_1 ? this.cursorMax : this.cursorMax + int_1;
- String string_1 = "";
- if (int_2 >= 0) {
- string_1 = this.text.substring(0, int_2);
- }
-
- if (int_3 < this.text.length()) {
- string_1 = string_1 + this.text.substring(int_3);
- }
-
- if (this.textPredicate.test(string_1)) {
- this.text = string_1;
- if (boolean_1) {
- this.moveCursor(int_1);
- }
-
- this.onChanged(this.text);
- }
- }
- }
- }*/
public void setCursorPos(int location) {
this.cursor = MathHelper.clamp(location, 0, this.text.length());
@@ -190,132 +120,14 @@ public class WTextField extends WWidget {
public boolean isEditable() {
return this.editable;
}
-
- /*
- public boolean keyPressed(int int_1, int int_2, int int_3) {
- if (!this.method_20315()) {
- return false;
- } else {
- this.field_17037 = Screen.hasShiftDown();
- if (Screen.isSelectAll(int_1)) {
- this.method_1872();
- this.method_1884(0);
- return true;
- } else if (Screen.isCopy(int_1)) {
- MinecraftClient.getInstance().keyboard.setClipboard(this.getSelectedText());
- return true;
- } else if (Screen.isPaste(int_1)) {
- if (this.editable) {
- this.addText(MinecraftClient.getInstance().keyboard.getClipboard());
- }
-
- return true;
- } else if (Screen.isCut(int_1)) {
- MinecraftClient.getInstance().keyboard.setClipboard(this.getSelectedText());
- if (this.editable) {
- this.addText("");
- }
-
- return true;
- } else {
- switch(int_1) {
- case 259:
- if (this.editable) {
- this.method_16873(-1);
- }
-
- return true;
- case 260:
- case 264:
- case 265:
- case 266:
- case 267:
- default:
- return false;
- case 261:
- if (this.editable) {
- this.method_16873(1);
- }
-
- return true;
- case 262:
- if (Screen.hasControlDown()) {
- this.method_1883(this.method_1853(1));
- } else {
- this.moveCursor(1);
- }
-
- return true;
- case 263:
- if (Screen.hasControlDown()) {
- this.method_1883(this.method_1853(-1));
- } else {
- this.moveCursor(-1);
- }
-
- return true;
- case 268:
- this.method_1870();
- return true;
- case 269:
- this.method_1872();
- return true;
- }
- }
- }
- }*/
-
- /*
- public boolean charTyped(char char_1, int int_1) {
- if (!this.method_20315()) {
- return false;
- } else if (SharedConstants.isValidChar(char_1)) {
- if (this.editable) {
- this.addText(Character.toString(char_1));
- }
-
- return true;
- } else {
- return false;
- }
- }*/
- /*
- @Override
- public void onClick(int x, int y, int button) {
-
- }
-
- public boolean mouseClicked(double double_1, double double_2, int int_1) {
- if (!this.isVisible()) {
- return false;
- } else {
- boolean boolean_1 = double_1 >= (double)this.x && double_1 < (double)(this.x + this.width) && double_2 >= (double)this.y && double_2 < (double)(this.y + this.height);
- if (this.field_2096) {
- this.method_1876(boolean_1);
- }
-
- if (this.isFocused() && boolean_1 && int_1 == 0) {
- int int_2 = MathHelper.floor(double_1) - this.x;
- if (this.focused) {
- int_2 -= 4;
- }
-
- String string_1 = this.textRenderer.trimToWidth(this.text.substring(this.field_2103), this.method_1859());
- this.method_1883(this.textRenderer.trimToWidth(string_1, int_2).length() + this.field_2103);
- return true;
- } else {
- return false;
- }
- }
- }*/
@Environment(EnvType.CLIENT)
protected void renderTextField(MatrixStack matrices, int x, int y) {
if (this.font==null) this.font = MinecraftClient.getInstance().textRenderer;
int borderColor = (this.isFocused()) ? 0xFF_FFFFA0 : 0xFF_A0A0A0;
- ScreenDrawing.coloredRect(x-1, y-1, width+2, height+2, borderColor);
- ScreenDrawing.coloredRect(x, y, width, height, 0xFF000000);
+ ScreenDrawing.coloredRect(matrices, x-1, y-1, width+2, height+2, borderColor);
+ ScreenDrawing.coloredRect(matrices, x, y, width, height, 0xFF000000);
int textColor = this.editable ? this.enabledColor : this.uneditableColor;
@@ -369,7 +181,7 @@ public class WTextField extends WWidget {
//} else {
// caretLoc = textX+caretLoc-1;
//}
- ScreenDrawing.coloredRect(preCursorAdvance-1, textY-2, 1, 12, 0xFFD0D0D0);
+ ScreenDrawing.coloredRect(matrices, preCursorAdvance-1, textY-2, 1, 12, 0xFFD0D0D0);
//if (boolean_3) {
// int var10001 = int_7 - 1;
// var10002 = int_9 + 1;
@@ -390,7 +202,7 @@ public class WTextField extends WWidget {
b = a;
a = tmp;
}
- invertedRect(textX+a-1, textY-1, Math.min(b-a, width - OFFSET_X_TEXT), 12);
+ invertedRect(matrices, textX+a-1, textY-1, Math.min(b-a, width - OFFSET_X_TEXT), 12);
// int int_10 = int_6 + MinecraftClient.getInstance().textRenderer.getStringWidth(trimText.substring(0, adjustedCursor));
// var10002 = int_7 - 1;
// var10003 = int_10 - 1;
@@ -400,18 +212,18 @@ public class WTextField extends WWidget {
}
@Environment(EnvType.CLIENT)
- private void invertedRect(int x, int y, int width, int height) {
+ private void invertedRect(MatrixStack matrices, int x, int y, int width, int height) {
Tessellator tessellator_1 = Tessellator.getInstance();
BufferBuilder bufferBuilder_1 = tessellator_1.getBuffer();
- RenderSystem.color4f(0.0F, 0.0F, 255.0F, 255.0F);
+ Matrix4f model = matrices.peek().getModel();
RenderSystem.disableTexture();
RenderSystem.enableColorLogicOp();
RenderSystem.logicOp(GlStateManager.LogicOp.OR_REVERSE);
- bufferBuilder_1.begin(GL11.GL_QUADS, VertexFormats.POSITION);
- bufferBuilder_1.vertex(x, y+height, 0.0D).next();
- bufferBuilder_1.vertex(x+width, y+height, 0.0D).next();
- bufferBuilder_1.vertex(x+width, y, 0.0D).next();
- bufferBuilder_1.vertex(x, y, 0.0D).next();
+ bufferBuilder_1.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR);
+ bufferBuilder_1.vertex(model, x, y+height, 0).color(0, 0, 255, 255).next();
+ bufferBuilder_1.vertex(model, x+width, y+height, 0).color(0, 0, 255, 255).next();
+ bufferBuilder_1.vertex(model, x+width, y, 0).color(0, 0, 255, 255).next();
+ bufferBuilder_1.vertex(model, x, y, 0).color(0, 0, 255, 255).next();
tessellator_1.draw();
RenderSystem.disableColorLogicOp();
RenderSystem.enableTexture();
@@ -538,9 +350,10 @@ public class WTextField extends WWidget {
@Environment(EnvType.CLIENT)
@Override
- public void onClick(int x, int y, int button) {
+ public InputResult onClick(int x, int y, int button) {
requestFocus();
cursor = getCaretPos(this.text, x-OFFSET_X_TEXT);
+ return InputResult.PROCESSED;
}
@Environment(EnvType.CLIENT)
@@ -655,6 +468,7 @@ public class WTextField extends WWidget {
}
} else {
if (modifiers==GLFW.GLFW_MOD_SHIFT) {
+ // TODO: Add Ctrl word selection support
if (ch==GLFW.GLFW_KEY_LEFT) {
if (select==-1) select = cursor;
if (cursor>0) cursor--;
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WTiledSprite.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WTiledSprite.java
index 5750636..0ab9d7c 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WTiledSprite.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WTiledSprite.java
@@ -2,6 +2,7 @@ package io.github.cottonmc.cotton.gui.widget;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
+import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Identifier;
import io.github.cottonmc.cotton.gui.client.ScreenDrawing;
@@ -129,13 +130,14 @@ public class WTiledSprite extends WSprite {
@Environment(EnvType.CLIENT)
@Override
- public void paintFrame(int x, int y, Texture texture) {
+ public void paintFrame(MatrixStack matrices, int x, int y, Texture texture) {
// Y Direction (down)
for (int tileYOffset = 0; tileYOffset < height; tileYOffset += tileHeight) {
// X Direction (right)
for (int tileXOffset = 0; tileXOffset < width; tileXOffset += tileWidth) {
// draw the texture
ScreenDrawing.texturedRect(
+ matrices,
// at the correct position using tileXOffset and tileYOffset
x + tileXOffset, y + tileYOffset,
// but using the set tileWidth and tileHeight instead of the full height and
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WToggleButton.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WToggleButton.java
index 1142928..355572e 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WToggleButton.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WToggleButton.java
@@ -9,8 +9,9 @@ import net.minecraft.sound.SoundEvents;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
-import io.github.cottonmc.cotton.gui.client.LibGuiClient;
+import io.github.cottonmc.cotton.gui.client.LibGui;
import io.github.cottonmc.cotton.gui.client.ScreenDrawing;
+import io.github.cottonmc.cotton.gui.widget.data.InputResult;
import io.github.cottonmc.cotton.gui.widget.data.Texture;
import org.jetbrains.annotations.Nullable;
@@ -101,13 +102,13 @@ public class WToggleButton extends WWidget {
@Environment(EnvType.CLIENT)
@Override
public void paint(MatrixStack matrices, int x, int y, int mouseX, int mouseY) {
- ScreenDrawing.texturedRect(x, y, 18, 18, isOn ? onImage : offImage, 0xFFFFFFFF);
+ ScreenDrawing.texturedRect(matrices, x, y, 18, 18, isOn ? onImage : offImage, 0xFFFFFFFF);
if (isFocused()) {
- ScreenDrawing.texturedRect(x, y, 18, 18, focusImage, 0xFFFFFFFF);
+ ScreenDrawing.texturedRect(matrices, x, y, 18, 18, focusImage, 0xFFFFFFFF);
}
if (label!=null) {
- ScreenDrawing.drawString(matrices, label.asOrderedText(), x + 22, y+6, LibGuiClient.config.darkMode ? darkmodeColor : color);
+ ScreenDrawing.drawString(matrices, label.asOrderedText(), x + 22, y+6, LibGui.isDarkMode() ? darkmodeColor : color);
}
}
@@ -123,13 +124,14 @@ public class WToggleButton extends WWidget {
@Environment(EnvType.CLIENT)
@Override
- public void onClick(int x, int y, int button) {
+ public InputResult onClick(int x, int y, int button) {
super.onClick(x, y, button);
MinecraftClient.getInstance().getSoundManager().play(PositionedSoundInstance.master(SoundEvents.UI_BUTTON_CLICK, 1.0F));
this.isOn = !this.isOn;
onToggle(this.isOn);
+ return InputResult.PROCESSED;
}
@Override
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java
index cd3c31b..f78723b 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java
@@ -3,11 +3,12 @@ package io.github.cottonmc.cotton.gui.widget;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.util.math.MatrixStack;
import com.google.common.annotations.Beta;
import io.github.cottonmc.cotton.gui.GuiDescription;
+import io.github.cottonmc.cotton.gui.impl.access.ScreenAccessor;
+import io.github.cottonmc.cotton.gui.widget.data.InputResult;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable;
@@ -153,17 +154,16 @@ public class WWidget {
* @param x The X coordinate of the event, in widget-space (0 is the left edge of this widget)
* @param y The Y coordinate of the event, in widget-space (0 is the top edge of this widget)
* @param button The mouse button that was used. Button numbering is consistent with LWJGL Mouse (0=left, 1=right, 2=mousewheel click)
+ * @return {@link InputResult#PROCESSED} if the event is handled, {@link InputResult#IGNORED} otherwise.
*/
@Environment(EnvType.CLIENT)
- public WWidget onMouseDown(int x, int y, int button) {
- return this;
+ public InputResult onMouseDown(int x, int y, int button) {
+ return InputResult.IGNORED;
}
/**
* Notifies this widget that the mouse has been moved while pressed and inside its bounds.
*
- * <p>The default implementation calls {@link #onMouseDrag(int, int, int)} for backwards compatibility.
- *
* @param x The X coordinate of the event, in widget-space (0 is the left edge of this widget)
* @param y The Y coordinate of the event, in widget-space (0 is the top edge of this widget)
* @param button The mouse button that was used. Button numbering is consistent with LWJGL Mouse (0=left, 1=right, 2=mousewheel click)
@@ -171,20 +171,11 @@ public class WWidget {
* @param deltaY The amount of dragging on the Y axis
*
* @since 1.5.0
+ * @return {@link InputResult#PROCESSED} if the event is handled, {@link InputResult#IGNORED} otherwise.
*/
@Environment(EnvType.CLIENT)
- public void onMouseDrag(int x, int y, int button, double deltaX, double deltaY) {
- onMouseDrag(x, y, button);
- }
-
- /**
- * Notifies this widget that the mouse has been moved while pressed and inside its bounds
- * @param x The X coordinate of the event, in widget-space (0 is the left edge of this widget)
- * @param y The Y coordinate of the event, in widget-space (0 is the top edge of this widget)
- * @param button The mouse button that was used. Button numbering is consistent with LWJGL Mouse (0=left, 1=right, 2=mousewheel click)
- */
- @Environment(EnvType.CLIENT)
- public void onMouseDrag(int x, int y, int button) {
+ public InputResult onMouseDrag(int x, int y, int button, double deltaX, double deltaY) {
+ return InputResult.IGNORED;
}
/**
@@ -192,10 +183,11 @@ public class WWidget {
* @param x The X coordinate of the event, in widget-space (0 is the left edge of this widget)
* @param y The Y coordinate of the event, in widget-space (0 is the top edge of this widget)
* @param button The mouse button that was used. Button numbering is consistent with LWJGL Mouse (0=left, 1=right, 2=mousewheel click)
+ * @return {@link InputResult#PROCESSED} if the event is handled, {@link InputResult#IGNORED} otherwise.
*/
@Environment(EnvType.CLIENT)
- public WWidget onMouseUp(int x, int y, int button) {
- return this;
+ public InputResult onMouseUp(int x, int y, int button) {
+ return InputResult.IGNORED;
}
/**
@@ -203,9 +195,11 @@ public class WWidget {
* @param x The X coordinate of the event, in widget-space (0 is the left edge of this widget)
* @param y The Y coordinate of the event, in widget-space (0 is the top edge of this widget)
* @param button The mouse button that was used. Button numbering is consistent with LWJGL Mouse (0=left, 1=right, 2=mousewheel click)
+ * @return {@link InputResult#PROCESSED} if the event is handled, {@link InputResult#IGNORED} otherwise.
*/
@Environment(EnvType.CLIENT)
- public void onClick(int x, int y, int button) {
+ public InputResult onClick(int x, int y, int button) {
+ return InputResult.IGNORED;
}
/**
@@ -213,9 +207,11 @@ public class WWidget {
* @param x The X coordinate of the event, in widget-space (0 is the left edge of this widget)
* @param y The Y coordinate of the event, in widget-space (0 is the top edge of this widget)
* @param amount The scrolled amount. Positive values are up and negative values are down.
+ * @return {@link InputResult#PROCESSED} if the event is handled, {@link InputResult#IGNORED} otherwise.
*/
@Environment(EnvType.CLIENT)
- public void onMouseScroll(int x, int y, double amount) {
+ public InputResult onMouseScroll(int x, int y, double amount) {
+ return InputResult.IGNORED;
}
/**
@@ -224,9 +220,11 @@ public class WWidget {
* @param x The X coordinate of the event, in widget-space (0 is the left edge of this widget)
* @param y The Y coordinate of the event, in widget-space (0 is the top edge of this widget)
* @since 1.5.0
+ * @return {@link InputResult#PROCESSED} if the event is handled, {@link InputResult#IGNORED} otherwise.
*/
@Environment(EnvType.CLIENT)
- public void onMouseMove(int x, int y) {
+ public InputResult onMouseMove(int x, int y) {
+ return InputResult.IGNORED;
}
/**
@@ -305,15 +303,6 @@ public class WWidget {
}
/**
- * Creates "heavyweight" component peers
- * @param c the top-level Container that will hold the peers
- * @deprecated All widget peers should be added in {@link #validate(GuiDescription)}.
- */
- @Deprecated
- public void createPeers(GuiDescription c) {
- }
-
- /**
* Paints this widget.
*
* @param matrices the rendering matrix stack
@@ -356,8 +345,8 @@ public class WWidget {
if (builder.size() == 0) return;
- Screen screen = MinecraftClient.getInstance().currentScreen;
- screen.renderOrderedTooltip(matrices, builder.lines, tX+x, tY+y);
+ ScreenAccessor screen = (ScreenAccessor) MinecraftClient.getInstance().currentScreen;
+ screen.callRenderTooltipFromComponents(matrices, builder.components, tX+x, tY+y);
}
/**
@@ -370,7 +359,7 @@ public class WWidget {
if (host != null) {
this.host = host;
} else {
- LOGGER.warn("Validating {} with a null host", this);
+ LOGGER.warn("Validating {} with a null host", this);
}
}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/data/InputResult.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/data/InputResult.java
new file mode 100644
index 0000000..991cfd3
--- /dev/null
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/data/InputResult.java
@@ -0,0 +1,12 @@
+package io.github.cottonmc.cotton.gui.widget.data;
+
+/**
+ * Specifies whether an input event was ignored or processed.
+ * Used for mouse input events.
+ *
+ * @since 4.0.0
+ */
+public enum InputResult {
+ PROCESSED,
+ IGNORED;
+}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/data/Tab.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/data/Tab.java
new file mode 100644
index 0000000..05f6933
--- /dev/null
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/data/Tab.java
@@ -0,0 +1,189 @@
+package io.github.cottonmc.cotton.gui.widget.data;
+
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
+import net.minecraft.text.Text;
+
+import io.github.cottonmc.cotton.gui.widget.TooltipBuilder;
+import io.github.cottonmc.cotton.gui.widget.WWidget;
+import io.github.cottonmc.cotton.gui.widget.icon.Icon;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Consumer;
+
+/**
+ * The data of a tab.
+ *
+ * @see io.github.cottonmc.cotton.gui.widget.WTabPanel
+ */
+public final class Tab {
+ @Nullable
+ private final Text title;
+ @Nullable
+ private final Icon icon;
+ private final WWidget widget;
+ @Nullable
+ private final Consumer<TooltipBuilder> tooltip;
+
+ /**
+ * Constructs a tab.
+ *
+ * @param title the tab title
+ * @param icon the tab icon
+ * @param widget the widget contained in the tab
+ * @param tooltip the tab tooltip
+ * @throws IllegalArgumentException if both the title and the icon are null
+ * @throws NullPointerException if the widget is null
+ */
+ private Tab(@Nullable Text title, @Nullable Icon icon, WWidget widget, @Nullable Consumer<TooltipBuilder> tooltip) {
+ if (title == null && icon == null) {
+ throw new IllegalArgumentException("A tab must have a title or an icon");
+ }
+
+ this.title = title;
+ this.icon = icon;
+ this.widget = Objects.requireNonNull(widget, "widget");
+ this.tooltip = tooltip;
+ }
+
+ /**
+ * Gets the title of this tab.
+ *
+ * @return the title, or null if there's no title
+ */
+ @Nullable
+ public Text getTitle() {
+ return title;
+ }
+
+ /**
+ * Gets the icon of this tab.
+ *
+ * @return the icon, or null if there's no title
+ */
+ @Nullable
+ public Icon getIcon() {
+ return icon;
+ }
+
+ /**
+ * Gets the contained widget of this tab.
+ *
+ * @return the contained widget
+ */
+ public WWidget getWidget() {
+ return widget;
+ }
+
+ /**
+ * Adds this widget's tooltip to the {@code tooltip} builder.
+ *
+ * @param tooltip the tooltip builder
+ */
+ @Environment(EnvType.CLIENT)
+ public void addTooltip(TooltipBuilder tooltip) {
+ if (this.tooltip != null) {
+ this.tooltip.accept(tooltip);
+ }
+ }
+
+ /**
+ * A builder for tab data.
+ */
+ public static final class Builder {
+ @Nullable
+ private Text title;
+ @Nullable
+ private Icon icon;
+ private final WWidget widget;
+ private final List<Text> tooltip = new ArrayList<>();
+
+ /**
+ * Constructs a new tab data builder.
+ *
+ * @param widget the contained widget
+ * @throws NullPointerException if the widget is null
+ */
+ public Builder(WWidget widget) {
+ this.widget = Objects.requireNonNull(widget, "widget");
+ }
+
+ /**
+ * Sets the tab title.
+ *
+ * @param title the new title
+ * @return this builder
+ * @throws NullPointerException if the title is null
+ */
+ public Builder title(Text title) {
+ this.title = Objects.requireNonNull(title, "title");
+ return this;
+ }
+
+ /**
+ * Sets the tab icon.
+ *
+ * @param icon the new icon
+ * @return this builder
+ * @throws NullPointerException if the icon is null
+ */
+ public Builder icon(Icon icon) {
+ this.icon = Objects.requireNonNull(icon, "icon");
+ return this;
+ }
+
+ /**
+ * Adds lines to the tab's tooltip.
+ *
+ * @param lines the added lines
+ * @return this builder
+ * @throws NullPointerException if the line array is null
+ */
+ public Builder tooltip(Text... lines) {
+ Objects.requireNonNull(lines, "lines");
+ Collections.addAll(tooltip, lines);
+
+ return this;
+ }
+
+ /**
+ * Adds lines to the tab's tooltip.
+ *
+ * @param lines the added lines
+ * @return this builder
+ * @throws NullPointerException if the line collection is null
+ */
+ public Builder tooltip(Collection<? extends Text> lines) {
+ Objects.requireNonNull(lines, "lines");
+ tooltip.addAll(lines);
+ return this;
+ }
+
+ /**
+ * Builds a tab from this builder.
+ *
+ * @return the built tab
+ */
+ public Tab build() {
+ Consumer<TooltipBuilder> tooltip = null;
+
+ if (!this.tooltip.isEmpty()) {
+ //noinspection Convert2Lambda
+ tooltip = new Consumer<TooltipBuilder>() {
+ @Environment(EnvType.CLIENT)
+ @Override
+ public void accept(TooltipBuilder builder) {
+ builder.add(Builder.this.tooltip.toArray(new Text[0]));
+ }
+ };
+ }
+
+ return new Tab(title, icon, widget, tooltip);
+ }
+ }
+}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/icon/TextureIcon.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/icon/TextureIcon.java
index 18cf4c3..acc3ce5 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/icon/TextureIcon.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/icon/TextureIcon.java
@@ -80,6 +80,6 @@ public class TextureIcon implements Icon {
@Environment(EnvType.CLIENT)
@Override
public void paint(MatrixStack matrices, int x, int y, int size) {
- ScreenDrawing.texturedRect(x, y, size, size, texture, color, opacity);
+ ScreenDrawing.texturedRect(matrices, x, y, size, size, texture, color, opacity);
}
}
diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json
index b540edf..ca3cde8 100644
--- a/src/main/resources/fabric.mod.json
+++ b/src/main/resources/fabric.mod.json
@@ -19,8 +19,8 @@
"environment": "*",
"entrypoints": {
"main": ["io.github.cottonmc.cotton.gui.impl.LibGuiCommon"],
- "client": ["io.github.cottonmc.cotton.gui.client.LibGuiClient"],
- "modmenu": ["io.github.cottonmc.cotton.gui.client.modmenu.ModMenuSupport"]
+ "client": ["io.github.cottonmc.cotton.gui.impl.client.LibGuiClient"],
+ "modmenu": ["io.github.cottonmc.cotton.gui.impl.client.modmenu.ModMenuSupport"]
},
"mixins": [
"mixins.libgui.accessors.json"
diff --git a/src/main/resources/mixins.libgui.accessors.json b/src/main/resources/mixins.libgui.accessors.json
index 9ec55f2..03d0946 100644
--- a/src/main/resources/mixins.libgui.accessors.json
+++ b/src/main/resources/mixins.libgui.accessors.json
@@ -5,6 +5,7 @@
"required": true,
"mixins": [
+ "ScreenAccessor",
"SlotAccessor"
],