Transform the dock settings GUI into a proper popup so you can live position the dock and make changes.

This commit is contained in:
trunksbomb
2026-03-23 02:45:01 -04:00
parent 966e199a23
commit e201c8c674
6 changed files with 2245 additions and 21 deletions

View File

@@ -33,6 +33,7 @@ public class BagTabsClient {
modEventBus.addListener(BagTabsClient::registerScreens);
modEventBus.addListener(BagTabsClient::registerItemColors);
modEventBus.addListener(BagTabsClient::registerKeyMappings);
NeoForge.EVENT_BUS.addListener(BagTabsClient::renderTabsPre);
NeoForge.EVENT_BUS.addListener(BagTabsClient::renderTabs);
NeoForge.EVENT_BUS.addListener(BagTabsClient::clickTabs);
NeoForge.EVENT_BUS.addListener(BagTabsClient::dragTabs);
@@ -56,6 +57,10 @@ public class BagTabsClient {
event.register(OPEN_LAST_BAG);
}
private static void renderTabsPre(ScreenEvent.Render.Pre event) {
BagTabOverlay.renderPre(event);
}
private static void renderTabs(ScreenEvent.Render.Post event) {
BagTabOverlay.render(event);
}

View File

@@ -48,6 +48,7 @@ public final class BagTabOverlay {
private static final ResourceLocation GEAR_ICON_TEXTURE = BagTabs.id("textures/gui/dock_gear.png");
private static final ResourceLocation PREV_ICON_TEXTURE = BagTabs.id("textures/gui/dock_prev.png");
private static final ResourceLocation NEXT_ICON_TEXTURE = BagTabs.id("textures/gui/dock_next.png");
private static final ResourceLocation POPUP_TEXTURE = BagTabs.id("textures/gui/dock_config_popup.png");
private static final int BASE_TAB_WIDTH = 22;
private static final int BASE_TAB_HEIGHT = 22;
private static final int BASE_COMPACT_TAB_WIDTH = 22;
@@ -55,6 +56,9 @@ public final class BagTabOverlay {
private static final int BASE_DOCK_WIDTH = 18;
private static final int BASE_DOCK_HEIGHT = 22;
private static final int BASE_DOCK_ICON_SIZE = 32;
private static final int POPUP_WIDTH = 140;
private static final int POPUP_HEIGHT = 160;
private static final int POPUP_TITLE_HEIGHT = 16;
private static final int TAB_GAP = 0;
private static final int TAB_Y_OFFSET = -3;
private static final int TAB_X_OFFSET = -6;
@@ -69,10 +73,38 @@ public final class BagTabOverlay {
private static long nextAutoScrollAt;
private static String lastOpenedBagKey;
private static int lastOpenedBagSlot = -1;
private static ConfigPopupState configPopup;
private static boolean suppressUnderlyingHoverRender;
private static int overlayMouseX = Integer.MIN_VALUE;
private static int overlayMouseY = Integer.MIN_VALUE;
private BagTabOverlay() {
}
public static void renderPre(ScreenEvent.Render.Pre event) {
if (suppressUnderlyingHoverRender) {
return;
}
if (!(event.getScreen() instanceof AbstractContainerScreen<?> screen) || !supportsTabs(screen)) {
return;
}
if (!isConfigPopupOpenFor(screen) || !isPointInsideConfigPopup(event.getMouseX(), event.getMouseY())) {
return;
}
suppressUnderlyingHoverRender = true;
overlayMouseX = event.getMouseX();
overlayMouseY = event.getMouseY();
event.setCanceled(true);
try {
screen.render(event.getGuiGraphics(), -10_000, -10_000, event.getPartialTick());
} finally {
suppressUnderlyingHoverRender = false;
overlayMouseX = Integer.MIN_VALUE;
overlayMouseY = Integer.MIN_VALUE;
}
}
public static void render(ScreenEvent.Render.Post event) {
expirePendingCursorRestore();
if (!(event.getScreen() instanceof AbstractContainerScreen<?> screen) || !supportsTabs(screen)) {
@@ -89,8 +121,8 @@ public final class BagTabOverlay {
}
GuiGraphics g = event.getGuiGraphics();
int mouseX = event.getMouseX();
int mouseY = event.getMouseY();
int mouseX = effectiveMouseX(event.getMouseX());
int mouseY = effectiveMouseY(event.getMouseY());
ItemStack carried = screen.getMenu().getCarried();
refreshInsertTargets(screen, carried);
@@ -133,10 +165,18 @@ public final class BagTabOverlay {
g.pose().popPose();
}
if (isConfigPopupOpenFor(screen)) {
renderConfigPopup(g, screen, mouseX, mouseY);
}
if (dragState != null) {
return;
}
if (isConfigPopupOpenFor(screen) && isPointInsideConfigPopup(mouseX, mouseY)) {
return;
}
DockIcon hovered = strip.control().hoveredIcon(mouseX, mouseY);
if (hovered != null) {
g.renderTooltip(Minecraft.getInstance().font, List.of(getDockTooltip(hovered).getVisualOrderText()), mouseX, mouseY);
@@ -168,6 +208,10 @@ public final class BagTabOverlay {
}
TabStrip strip = getTabStrip(screen, player);
if (handleConfigPopupClick(screen, event.getMouseX(), event.getMouseY(), event.getButton())) {
event.setCanceled(true);
return;
}
if (event.getButton() == 0) {
DockIcon clicked = strip.control().hoveredIcon(event.getMouseX(), event.getMouseY());
if (clicked == DockIcon.LOCK) {
@@ -179,7 +223,7 @@ public final class BagTabOverlay {
return;
}
if (clicked == DockIcon.CONFIG) {
Minecraft.getInstance().setScreen(new DockConfigScreen(screen));
toggleConfigPopup(screen);
Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F));
event.setCanceled(true);
return;
@@ -237,6 +281,11 @@ public final class BagTabOverlay {
return;
}
if (handleConfigPopupDrag(screen, event.getMouseX(), event.getMouseY())) {
event.setCanceled(true);
return;
}
TabStrip strip = getTabStrip(screen, player);
List<RenderedTab> tabs = strip.tabs();
if (pendingClick != null && pendingClick.pinned()) {
@@ -266,6 +315,11 @@ public final class BagTabOverlay {
return;
}
if (isConfigPopupOpenFor(screen) && isPointInsideConfigPopup(event.getMouseX(), event.getMouseY())) {
event.setCanceled(true);
return;
}
TabStrip strip = getTabStrip(screen, player);
if (strip.scrollControl() == null || !isScrollHoverTarget(strip, event.getMouseX(), event.getMouseY())) {
return;
@@ -292,6 +346,11 @@ public final class BagTabOverlay {
return;
}
if (handleConfigPopupRelease(screen, event.getButton())) {
event.setCanceled(true);
return;
}
ItemStack carried = screen.getMenu().getCarried();
if (carried.isEmpty()) {
TabStrip strip = getTabStrip(screen, player);
@@ -607,6 +666,244 @@ public final class BagTabOverlay {
return false;
}
private static void toggleConfigPopup(AbstractContainerScreen<?> screen) {
if (isConfigPopupOpenFor(screen)) {
configPopup = null;
return;
}
String screenKey = getScreenKey(screen);
int popupX = clamp((screen.width - POPUP_WIDTH) / 2, 4, Math.max(4, screen.width - POPUP_WIDTH - 4));
int popupY = clamp((screen.height - POPUP_HEIGHT) / 2, 4, Math.max(4, screen.height - POPUP_HEIGHT - 4));
configPopup = new ConfigPopupState(
screenKey,
DockConfigManager.hasOverride(screenKey),
DockConfigManager.getEditableSettings(screenKey, DockConfigManager.hasOverride(screenKey)).copy(),
popupX,
popupY,
false,
0,
0
);
}
private static boolean isConfigPopupOpenFor(AbstractContainerScreen<?> screen) {
return configPopup != null && configPopup.screenKey().equals(getScreenKey(screen));
}
private static boolean handleConfigPopupClick(AbstractContainerScreen<?> screen, double mouseX, double mouseY, int button) {
if (!isConfigPopupOpenFor(screen)) {
return false;
}
if (!isPointInsideConfigPopup(mouseX, mouseY)) {
return false;
}
if (button == 0 && isPointInsideConfigPopupTitle(mouseX, mouseY)) {
configPopup = configPopup.withDragging(true, (int) mouseX - configPopup.x(), (int) mouseY - configPopup.y());
return true;
}
PopupElement element = getPopupElementAt(mouseX, mouseY);
if (element == null) {
return true;
}
if (button == 1 && element == PopupElement.SIDE) {
mutateConfigPopup(settings -> settings.withDockSide(settings.dockSide().previous()));
Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F));
return true;
}
if (button != 0) {
return true;
}
switch (element) {
case TARGET -> {
saveConfigPopup();
boolean editOverride = !configPopup.editOverride();
DockConfigManager.DockSettings settings = DockConfigManager.getEditableSettings(configPopup.screenKey(), editOverride).copy();
configPopup = configPopup.withMode(editOverride, settings);
}
case SIDE -> mutateConfigPopup(settings -> settings.withDockSide(settings.dockSide().next()));
case X_MINUS -> mutateConfigPopup(settings -> settings.withXOffset(settings.xOffset() - getOffsetStep()));
case X_PLUS -> mutateConfigPopup(settings -> settings.withXOffset(settings.xOffset() + getOffsetStep()));
case Y_MINUS -> mutateConfigPopup(settings -> settings.withYOffset(settings.yOffset() - getOffsetStep()));
case Y_PLUS -> mutateConfigPopup(settings -> settings.withYOffset(settings.yOffset() + getOffsetStep()));
case MAX_MINUS -> mutateConfigPopup(settings -> settings.withMaxTabs(settings.maxTabs() - 1));
case MAX_PLUS -> mutateConfigPopup(settings -> settings.withMaxTabs(settings.maxTabs() + 1));
case COMPACT -> mutateConfigPopup(settings -> settings.withCompact(!settings.compact()));
case RESET -> {
DockConfigManager.clearOverride(configPopup.screenKey());
configPopup = configPopup.withMode(false, DockConfigManager.getEditableSettings(configPopup.screenKey(), false).copy());
}
case DONE -> {
saveConfigPopup();
configPopup = null;
}
}
Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F));
return true;
}
private static boolean handleConfigPopupDrag(AbstractContainerScreen<?> screen, double mouseX, double mouseY) {
if (!isConfigPopupOpenFor(screen) || !configPopup.dragging()) {
return false;
}
int x = clamp((int) mouseX - configPopup.dragOffsetX(), 4, Math.max(4, screen.width - POPUP_WIDTH - 4));
int y = clamp((int) mouseY - configPopup.dragOffsetY(), 4, Math.max(4, screen.height - POPUP_HEIGHT - 4));
configPopup = configPopup.withPosition(x, y);
return true;
}
private static boolean handleConfigPopupRelease(AbstractContainerScreen<?> screen, int button) {
if (!isConfigPopupOpenFor(screen) || button != 0 || !configPopup.dragging()) {
return false;
}
configPopup = configPopup.withDragging(false, 0, 0);
return true;
}
private static void renderConfigPopup(GuiGraphics g, AbstractContainerScreen<?> screen, int mouseX, int mouseY) {
if (!isConfigPopupOpenFor(screen)) {
return;
}
int x = configPopup.x();
int y = configPopup.y();
g.pose().pushPose();
g.pose().translate(0.0F, 0.0F, 300.0F);
g.blit(POPUP_TEXTURE, x, y, 0, 0, POPUP_WIDTH, POPUP_HEIGHT, POPUP_WIDTH, POPUP_HEIGHT);
g.drawCenteredString(Minecraft.getInstance().font, BagTabs.translation("dock.title"), x + (POPUP_WIDTH / 2), y + 4, 0xFFFFFF);
renderPopupButton(g, PopupElement.TARGET, getPopupButtonText(PopupElement.TARGET), mouseX, mouseY, false);
renderPopupButton(g, PopupElement.SIDE, getPopupButtonText(PopupElement.SIDE), mouseX, mouseY, false);
renderPopupButton(g, PopupElement.X_MINUS, Component.literal("-"), mouseX, mouseY, false);
renderPopupButton(g, PopupElement.X_PLUS, Component.literal("+"), mouseX, mouseY, false);
renderPopupButton(g, PopupElement.Y_MINUS, Component.literal("-"), mouseX, mouseY, false);
renderPopupButton(g, PopupElement.Y_PLUS, Component.literal("+"), mouseX, mouseY, false);
renderPopupButton(g, PopupElement.MAX_MINUS, Component.literal("-"), mouseX, mouseY, false);
renderPopupButton(g, PopupElement.MAX_PLUS, Component.literal("+"), mouseX, mouseY, false);
renderPopupButton(g, PopupElement.COMPACT, getPopupButtonText(PopupElement.COMPACT), mouseX, mouseY, false);
renderPopupButton(g, PopupElement.RESET, BagTabs.translation("dock.reset"), mouseX, mouseY, !(configPopup.editOverride() || DockConfigManager.hasOverride(configPopup.screenKey())));
renderPopupButton(g, PopupElement.DONE, BagTabs.translation("dock.done"), mouseX, mouseY, false);
int centerX = x + (POPUP_WIDTH / 2);
int labelTop = y + 24;
g.drawCenteredString(Minecraft.getInstance().font, Component.literal("X: " + configPopup.settings().xOffset()), centerX, labelTop + 42, 0xFFFFFF);
g.drawCenteredString(Minecraft.getInstance().font, Component.literal("Y: " + configPopup.settings().yOffset()), centerX, labelTop + 64, 0xFFFFFF);
g.drawCenteredString(Minecraft.getInstance().font, Component.literal("Tabs: " + configPopup.settings().maxTabs()), centerX, labelTop + 86, 0xFFFFFF);
PopupElement hovered = getPopupElementAt(mouseX, mouseY);
if (hovered == PopupElement.X_MINUS || hovered == PopupElement.X_PLUS || hovered == PopupElement.Y_MINUS || hovered == PopupElement.Y_PLUS) {
g.renderTooltip(Minecraft.getInstance().font, List.of(BagTabs.translation("dock.offset_steps").getVisualOrderText()), mouseX, mouseY);
}
g.pose().popPose();
}
private static void renderPopupButton(GuiGraphics g, PopupElement element, Component message, int mouseX, int mouseY, boolean disabled) {
Rect rect = getPopupRect(element);
int fill = disabled ? 0xFF3A3A3A : isPointInsideRect(mouseX, mouseY, rect) ? 0xFF7A7A7A : 0xFF5A5A5A;
int text = disabled ? 0xFF808080 : 0xFFFFFFFF;
g.fill(rect.x(), rect.y(), rect.right(), rect.bottom(), fill);
g.fill(rect.x(), rect.y(), rect.right(), rect.y() + 1, 0xFF000000);
g.fill(rect.x(), rect.bottom() - 1, rect.right(), rect.bottom(), 0xFF000000);
g.fill(rect.x(), rect.y(), rect.x() + 1, rect.bottom(), 0xFF000000);
g.fill(rect.right() - 1, rect.y(), rect.right(), rect.bottom(), 0xFF000000);
Minecraft minecraft = Minecraft.getInstance();
int availableWidth = rect.width() - 6;
int textWidth = minecraft.font.width(message);
float scale = textWidth <= availableWidth ? 1.0F : Math.max(0.45F, availableWidth / (float) textWidth);
float scaledWidth = textWidth * scale;
float textX = rect.x() + ((rect.width() - scaledWidth) / 2.0F);
float textY = rect.y() + ((rect.height() - (minecraft.font.lineHeight * scale)) / 2.0F);
g.pose().pushPose();
g.pose().translate(textX, textY, 0.0F);
g.pose().scale(scale, scale, 1.0F);
g.drawString(minecraft.font, message, 0, 0, text, false);
g.pose().popPose();
}
private static Component getPopupButtonText(PopupElement element) {
return switch (element) {
case TARGET -> configPopup.editOverride()
? BagTabs.translation("dock.target.override")
: BagTabs.translation("dock.target.global");
case SIDE -> BagTabs.translation("dock.side." + configPopup.settings().dockSide().name().toLowerCase());
case COMPACT -> BagTabs.translation(configPopup.settings().compact() ? "dock.compact.on" : "dock.compact.off");
default -> Component.empty();
};
}
private static Rect getPopupRect(PopupElement element) {
int left = configPopup.x() + 6;
int top = configPopup.y() + 24;
return switch (element) {
case TARGET -> new Rect(left, top, 128, 14);
case SIDE -> new Rect(left, top + 18, 128, 14);
case X_MINUS -> new Rect(left, top + 40, 14, 14);
case X_PLUS -> new Rect(left + 114, top + 40, 14, 14);
case Y_MINUS -> new Rect(left, top + 62, 14, 14);
case Y_PLUS -> new Rect(left + 114, top + 62, 14, 14);
case MAX_MINUS -> new Rect(left, top + 84, 14, 14);
case MAX_PLUS -> new Rect(left + 114, top + 84, 14, 14);
case COMPACT -> new Rect(left, top + 100, 128, 14);
case RESET -> new Rect(left, top + 120, 61, 14);
case DONE -> new Rect(left + 67, top + 120, 61, 14);
};
}
private static PopupElement getPopupElementAt(double mouseX, double mouseY) {
if (configPopup == null) {
return null;
}
for (PopupElement element : PopupElement.values()) {
if (isPointInsideRect(mouseX, mouseY, getPopupRect(element))) {
return element;
}
}
return null;
}
private static boolean isPointInsideConfigPopup(double mouseX, double mouseY) {
return configPopup != null && mouseX >= configPopup.x() && mouseX < configPopup.x() + POPUP_WIDTH && mouseY >= configPopup.y() && mouseY < configPopup.y() + POPUP_HEIGHT;
}
private static boolean isPointInsideConfigPopupTitle(double mouseX, double mouseY) {
return configPopup != null
&& mouseX >= configPopup.x() + 2
&& mouseX < configPopup.x() + POPUP_WIDTH - 2
&& mouseY >= configPopup.y() + 2
&& mouseY < configPopup.y() + POPUP_TITLE_HEIGHT;
}
private static boolean isPointInsideRect(double mouseX, double mouseY, Rect rect) {
return mouseX >= rect.x() && mouseX < rect.right() && mouseY >= rect.y() && mouseY < rect.bottom();
}
private static int getOffsetStep() {
boolean shift = Screen.hasShiftDown();
boolean control = Screen.hasControlDown();
if (shift && control) {
return 100;
}
if (control) {
return 25;
}
if (shift) {
return 5;
}
return 1;
}
private static void mutateConfigPopup(java.util.function.UnaryOperator<DockConfigManager.DockSettings> mutator) {
if (configPopup == null) {
return;
}
configPopup = configPopup.withSettings(mutator.apply(configPopup.settings()));
saveConfigPopup();
}
private static void saveConfigPopup() {
if (configPopup != null) {
DockConfigManager.setEditableSettings(configPopup.screenKey(), configPopup.editOverride(), configPopup.settings());
}
}
private static void rememberOpenedBag(BagEntry entry) {
lastOpenedBagSlot = entry.slot();
lastOpenedBagKey = entry.identity() == null ? null : entry.identity().key();
@@ -1146,6 +1443,14 @@ public final class BagTabOverlay {
return screen.getClass().getName();
}
private static int effectiveMouseX(int fallback) {
return overlayMouseX == Integer.MIN_VALUE ? fallback : overlayMouseX;
}
private static int effectiveMouseY(int fallback) {
return overlayMouseY == Integer.MIN_VALUE ? fallback : overlayMouseY;
}
private static int clamp(int value, int min, int max) {
return Math.max(min, Math.min(max, value));
}
@@ -1257,6 +1562,34 @@ public final class BagTabOverlay {
private record DockLayout(int firstTabX, int firstTabY, int tabWidth, int tabHeight, int controlX, int controlY, int controlWidth, int controlHeight, float scale, DockConfigManager.DockSide dockSide, boolean vertical, int maxTabs, boolean floating, boolean compact) {
}
private record ConfigPopupState(String screenKey, boolean editOverride, DockConfigManager.DockSettings settings, int x, int y, boolean dragging, int dragOffsetX, int dragOffsetY) {
private ConfigPopupState withMode(boolean nextEditOverride, DockConfigManager.DockSettings nextSettings) {
return new ConfigPopupState(this.screenKey, nextEditOverride, nextSettings, this.x, this.y, false, 0, 0);
}
private ConfigPopupState withSettings(DockConfigManager.DockSettings nextSettings) {
return new ConfigPopupState(this.screenKey, this.editOverride, nextSettings, this.x, this.y, this.dragging, this.dragOffsetX, this.dragOffsetY);
}
private ConfigPopupState withPosition(int nextX, int nextY) {
return new ConfigPopupState(this.screenKey, this.editOverride, this.settings, nextX, nextY, this.dragging, this.dragOffsetX, this.dragOffsetY);
}
private ConfigPopupState withDragging(boolean nextDragging, int nextDragOffsetX, int nextDragOffsetY) {
return new ConfigPopupState(this.screenKey, this.editOverride, this.settings, this.x, this.y, nextDragging, nextDragOffsetX, nextDragOffsetY);
}
}
private record Rect(int x, int y, int width, int height) {
private int right() {
return this.x + this.width;
}
private int bottom() {
return this.y + this.height;
}
}
private record PendingCursorRestore(double guiX, double guiY, long expiresAt) {
}
@@ -1354,4 +1687,18 @@ public final class BagTabOverlay {
PREV,
NEXT
}
private enum PopupElement {
TARGET,
SIDE,
X_MINUS,
X_PLUS,
Y_MINUS,
Y_PLUS,
MAX_MINUS,
MAX_PLUS,
COMPACT,
RESET,
DONE
}
}

View File

@@ -9,10 +9,18 @@ import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;
public class DockConfigScreen extends Screen {
private static final int PANEL_WIDTH = 196;
private static final int PANEL_HEIGHT = 234;
private static final int TITLE_BAR_HEIGHT = 18;
private final Screen parent;
private final String screenKey;
private boolean editOverride;
private DockConfigManager.DockSettings dockSettings;
private int panelX;
private int panelY;
private boolean draggingPanel;
private int dragOffsetX;
private int dragOffsetY;
private Button targetButton;
private Button sideButton;
@@ -24,6 +32,7 @@ public class DockConfigScreen extends Screen {
private Button maxTabsPlusButton;
private Button compactButton;
private Button resetButton;
private Button doneButton;
public DockConfigScreen(Screen parent) {
super(BagTabs.translation("dock.title"));
@@ -35,52 +44,54 @@ public class DockConfigScreen extends Screen {
@Override
protected void init() {
int centerX = this.width / 2;
int top = this.height / 2 - 70;
if (this.panelX == 0 && this.panelY == 0) {
this.panelX = (this.width - PANEL_WIDTH) / 2;
this.panelY = (this.height - PANEL_HEIGHT) / 2;
}
this.targetButton = this.addRenderableWidget(Button.builder(Component.empty(), button -> {
saveCurrent();
this.editOverride = !this.editOverride;
this.dockSettings = DockConfigManager.getEditableSettings(this.screenKey, this.editOverride).copy();
syncLabels();
}).bounds(centerX - 90, top, 180, 20).build());
}).bounds(0, 0, 180, 20).build());
this.sideButton = this.addRenderableWidget(Button.builder(Component.empty(), button -> {
this.dockSettings = this.dockSettings.withDockSide(this.dockSettings.dockSide().next());
saveCurrent();
syncLabels();
}).bounds(centerX - 90, top + 26, 180, 20).build());
}).bounds(0, 0, 180, 20).build());
this.xMinusButton = this.addRenderableWidget(Button.builder(Component.literal("-"), button -> adjustX(-getOffsetStep()))
.bounds(centerX - 90, top + 56, 20, 20).build());
.bounds(0, 0, 20, 20).build());
this.xPlusButton = this.addRenderableWidget(Button.builder(Component.literal("+"), button -> adjustX(getOffsetStep()))
.bounds(centerX + 70, top + 56, 20, 20).build());
.bounds(0, 0, 20, 20).build());
this.yMinusButton = this.addRenderableWidget(Button.builder(Component.literal("-"), button -> adjustY(-getOffsetStep()))
.bounds(centerX - 90, top + 82, 20, 20).build());
.bounds(0, 0, 20, 20).build());
this.yPlusButton = this.addRenderableWidget(Button.builder(Component.literal("+"), button -> adjustY(getOffsetStep()))
.bounds(centerX + 70, top + 82, 20, 20).build());
.bounds(0, 0, 20, 20).build());
this.maxTabsMinusButton = this.addRenderableWidget(Button.builder(Component.literal("-"), button -> adjustMaxTabs(-1))
.bounds(centerX - 90, top + 108, 20, 20).build());
.bounds(0, 0, 20, 20).build());
this.maxTabsPlusButton = this.addRenderableWidget(Button.builder(Component.literal("+"), button -> adjustMaxTabs(1))
.bounds(centerX + 70, top + 108, 20, 20).build());
.bounds(0, 0, 20, 20).build());
this.compactButton = this.addRenderableWidget(Button.builder(Component.empty(), button -> {
this.dockSettings = this.dockSettings.withCompact(!this.dockSettings.compact());
saveCurrent();
syncLabels();
}).bounds(centerX - 90, top + 134, 180, 20).build());
}).bounds(0, 0, 180, 20).build());
this.resetButton = this.addRenderableWidget(Button.builder(BagTabs.translation("dock.reset"), button -> {
DockConfigManager.clearOverride(this.screenKey);
this.editOverride = false;
this.dockSettings = DockConfigManager.getEditableSettings(this.screenKey, false).copy();
syncLabels();
}).bounds(centerX - 90, top + 160, 180, 20).build());
}).bounds(0, 0, 180, 20).build());
this.addRenderableWidget(Button.builder(BagTabs.translation("dock.done"), button -> onClose())
.bounds(centerX - 90, top + 186, 180, 20).build());
this.doneButton = this.addRenderableWidget(Button.builder(BagTabs.translation("dock.done"), button -> onClose())
.bounds(0, 0, 180, 20).build());
syncLabels();
Tooltip offsetTooltip = Tooltip.create(BagTabs.translation("dock.offset_steps"));
@@ -88,16 +99,22 @@ public class DockConfigScreen extends Screen {
this.xPlusButton.setTooltip(offsetTooltip);
this.yMinusButton.setTooltip(offsetTooltip);
this.yPlusButton.setTooltip(offsetTooltip);
updateWidgetPositions();
}
@Override
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
this.renderBackground(guiGraphics, mouseX, mouseY, partialTick);
this.parent.render(guiGraphics, mouseX, mouseY, partialTick);
guiGraphics.fill(0, 0, this.width, this.height, 0x5A000000);
guiGraphics.fill(this.panelX, this.panelY, this.panelX + PANEL_WIDTH, this.panelY + PANEL_HEIGHT, 0xE03A3A3A);
guiGraphics.fill(this.panelX + 1, this.panelY + 1, this.panelX + PANEL_WIDTH - 1, this.panelY + PANEL_HEIGHT - 1, 0xE01E1E1E);
guiGraphics.fill(this.panelX + 2, this.panelY + 2, this.panelX + PANEL_WIDTH - 2, this.panelY + TITLE_BAR_HEIGHT, 0xFF5A5A5A);
guiGraphics.fill(this.panelX + 2, this.panelY + TITLE_BAR_HEIGHT, this.panelX + PANEL_WIDTH - 2, this.panelY + TITLE_BAR_HEIGHT + 1, 0xFF000000);
super.render(guiGraphics, mouseX, mouseY, partialTick);
int centerX = this.width / 2;
int top = this.height / 2 - 70;
guiGraphics.drawCenteredString(this.font, this.title, centerX, top - 18, 0xFFFFFF);
int centerX = this.panelX + (PANEL_WIDTH / 2);
int top = this.panelY + 12;
guiGraphics.drawCenteredString(this.font, this.title, centerX, this.panelY + 6, 0xFFFFFF);
guiGraphics.drawCenteredString(this.font, Component.literal("X Offset: " + this.dockSettings.xOffset()), centerX, top + 62, 0xFFFFFF);
guiGraphics.drawCenteredString(this.font, Component.literal("Y Offset: " + this.dockSettings.yOffset()), centerX, top + 88, 0xFFFFFF);
guiGraphics.drawCenteredString(this.font, Component.literal("Max Tabs: " + this.dockSettings.maxTabs()), centerX, top + 114, 0xFFFFFF);
@@ -109,8 +126,19 @@ public class DockConfigScreen extends Screen {
Minecraft.getInstance().setScreen(this.parent);
}
@Override
public boolean isPauseScreen() {
return false;
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
if (button == 0 && isOverTitleBar(mouseX, mouseY)) {
this.draggingPanel = true;
this.dragOffsetX = (int) mouseX - this.panelX;
this.dragOffsetY = (int) mouseY - this.panelY;
return true;
}
if (button == 1 && this.sideButton != null && this.sideButton.isMouseOver(mouseX, mouseY)) {
this.dockSettings = this.dockSettings.withDockSide(this.dockSettings.dockSide().previous());
saveCurrent();
@@ -120,6 +148,25 @@ public class DockConfigScreen extends Screen {
return super.mouseClicked(mouseX, mouseY, button);
}
@Override
public boolean mouseDragged(double mouseX, double mouseY, int button, double dragX, double dragY) {
if (button == 0 && this.draggingPanel) {
this.panelX = clamp((int) mouseX - this.dragOffsetX, 4, this.width - PANEL_WIDTH - 4);
this.panelY = clamp((int) mouseY - this.dragOffsetY, 4, this.height - PANEL_HEIGHT - 4);
updateWidgetPositions();
return true;
}
return super.mouseDragged(mouseX, mouseY, button, dragX, dragY);
}
@Override
public boolean mouseReleased(double mouseX, double mouseY, int button) {
if (button == 0) {
this.draggingPanel = false;
}
return super.mouseReleased(mouseX, mouseY, button);
}
private void adjustX(int delta) {
this.dockSettings = this.dockSettings.withXOffset(this.dockSettings.xOffset() + delta);
saveCurrent();
@@ -165,4 +212,31 @@ public class DockConfigScreen extends Screen {
private void saveCurrent() {
DockConfigManager.setEditableSettings(this.screenKey, this.editOverride, this.dockSettings);
}
private void updateWidgetPositions() {
int left = this.panelX + 8;
int top = this.panelY + 26;
this.targetButton.setPosition(left, top);
this.sideButton.setPosition(left, top + 26);
this.xMinusButton.setPosition(left, top + 56);
this.xPlusButton.setPosition(left + 160, top + 56);
this.yMinusButton.setPosition(left, top + 82);
this.yPlusButton.setPosition(left + 160, top + 82);
this.maxTabsMinusButton.setPosition(left, top + 108);
this.maxTabsPlusButton.setPosition(left + 160, top + 108);
this.compactButton.setPosition(left, top + 134);
this.resetButton.setPosition(left, top + 160);
this.doneButton.setPosition(left, top + 186);
}
private boolean isOverTitleBar(double mouseX, double mouseY) {
return mouseX >= this.panelX + 2
&& mouseX < this.panelX + PANEL_WIDTH - 2
&& mouseY >= this.panelY + 2
&& mouseY < this.panelY + TITLE_BAR_HEIGHT;
}
private int clamp(int value, int min, int max) {
return Math.max(min, Math.min(max, value));
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 B