Transform the dock settings GUI into a proper popup so you can live position the dock and make changes.
This commit is contained in:
@@ -0,0 +1,767 @@
|
||||
package net.minecraft.client.gui.screens.inventory;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.mojang.blaze3d.platform.InputConstants;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.ClickType;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.api.distmarker.OnlyIn;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public abstract class AbstractContainerScreen<T extends AbstractContainerMenu> extends Screen implements MenuAccess<T> {
|
||||
/**
|
||||
* The location of the inventory background texture
|
||||
*/
|
||||
public static final ResourceLocation INVENTORY_LOCATION = ResourceLocation.withDefaultNamespace("textures/gui/container/inventory.png");
|
||||
private static final float SNAPBACK_SPEED = 100.0F;
|
||||
private static final int QUICKDROP_DELAY = 500;
|
||||
public static final int SLOT_ITEM_BLIT_OFFSET = 100;
|
||||
private static final int HOVER_ITEM_BLIT_OFFSET = 200;
|
||||
/**
|
||||
* The X size of the inventory window in pixels.
|
||||
*/
|
||||
protected int imageWidth = 176;
|
||||
/**
|
||||
* The Y size of the inventory window in pixels.
|
||||
*/
|
||||
protected int imageHeight = 166;
|
||||
protected int titleLabelX;
|
||||
protected int titleLabelY;
|
||||
protected int inventoryLabelX;
|
||||
protected int inventoryLabelY;
|
||||
/**
|
||||
* A list of the players inventory slots
|
||||
*/
|
||||
protected final T menu;
|
||||
protected final Component playerInventoryTitle;
|
||||
/**
|
||||
* Holds the slot currently hovered
|
||||
*/
|
||||
@Nullable
|
||||
protected Slot hoveredSlot;
|
||||
/**
|
||||
* Used when touchscreen is enabled
|
||||
*/
|
||||
@Nullable
|
||||
private Slot clickedSlot;
|
||||
@Nullable
|
||||
private Slot snapbackEnd;
|
||||
@Nullable
|
||||
private Slot quickdropSlot;
|
||||
@Nullable
|
||||
private Slot lastClickSlot;
|
||||
/**
|
||||
* Starting X position for the Gui. Inconsistent use for Gui backgrounds.
|
||||
*/
|
||||
protected int leftPos;
|
||||
/**
|
||||
* Starting Y position for the Gui. Inconsistent use for Gui backgrounds.
|
||||
*/
|
||||
protected int topPos;
|
||||
/**
|
||||
* Used when touchscreen is enabled.
|
||||
*/
|
||||
private boolean isSplittingStack;
|
||||
/**
|
||||
* Used when touchscreen is enabled
|
||||
*/
|
||||
private ItemStack draggingItem = ItemStack.EMPTY;
|
||||
private int snapbackStartX;
|
||||
private int snapbackStartY;
|
||||
private long snapbackTime;
|
||||
/**
|
||||
* Used when touchscreen is enabled
|
||||
*/
|
||||
private ItemStack snapbackItem = ItemStack.EMPTY;
|
||||
private long quickdropTime;
|
||||
protected final Set<Slot> quickCraftSlots = Sets.newHashSet();
|
||||
protected boolean isQuickCrafting;
|
||||
private int quickCraftingType;
|
||||
private int quickCraftingButton;
|
||||
private boolean skipNextRelease;
|
||||
private int quickCraftingRemainder;
|
||||
private long lastClickTime;
|
||||
private int lastClickButton;
|
||||
private boolean doubleclick;
|
||||
private ItemStack lastQuickMoved = ItemStack.EMPTY;
|
||||
|
||||
public AbstractContainerScreen(T menu, Inventory playerInventory, Component title) {
|
||||
super(title);
|
||||
this.menu = menu;
|
||||
this.playerInventoryTitle = playerInventory.getDisplayName();
|
||||
this.skipNextRelease = true;
|
||||
this.titleLabelX = 8;
|
||||
this.titleLabelY = 6;
|
||||
this.inventoryLabelX = 8;
|
||||
this.inventoryLabelY = this.imageHeight - 94;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
this.leftPos = (this.width - this.imageWidth) / 2;
|
||||
this.topPos = (this.height - this.imageHeight) / 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the graphical user interface (GUI) element.
|
||||
*
|
||||
* @param guiGraphics the GuiGraphics object used for rendering.
|
||||
* @param mouseX the x-coordinate of the mouse cursor.
|
||||
* @param mouseY the y-coordinate of the mouse cursor.
|
||||
* @param partialTick the partial tick time.
|
||||
*/
|
||||
@Override
|
||||
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
|
||||
int i = this.leftPos;
|
||||
int j = this.topPos;
|
||||
// Neo: replicate the super method's implementation to insert the event between background and widgets
|
||||
this.renderBackground(guiGraphics, mouseX, mouseY, partialTick);
|
||||
net.neoforged.neoforge.common.NeoForge.EVENT_BUS.post(new net.neoforged.neoforge.client.event.ContainerScreenEvent.Render.Background(this, guiGraphics, mouseX, mouseY));
|
||||
for (net.minecraft.client.gui.components.Renderable renderable : this.renderables) {
|
||||
renderable.render(guiGraphics, mouseX, mouseY, partialTick);
|
||||
}
|
||||
RenderSystem.disableDepthTest();
|
||||
guiGraphics.pose().pushPose();
|
||||
guiGraphics.pose().translate((float)i, (float)j, 0.0F);
|
||||
this.hoveredSlot = null;
|
||||
|
||||
for (int k = 0; k < this.menu.slots.size(); k++) {
|
||||
Slot slot = this.menu.slots.get(k);
|
||||
if (slot.isActive()) {
|
||||
this.renderSlot(guiGraphics, slot);
|
||||
}
|
||||
|
||||
if (this.isHovering(slot, (double)mouseX, (double)mouseY) && slot.isActive()) {
|
||||
this.hoveredSlot = slot;
|
||||
this.renderSlotHighlight(guiGraphics, slot, mouseX, mouseY, partialTick);
|
||||
}
|
||||
}
|
||||
|
||||
this.renderLabels(guiGraphics, mouseX, mouseY);
|
||||
net.neoforged.neoforge.common.NeoForge.EVENT_BUS.post(new net.neoforged.neoforge.client.event.ContainerScreenEvent.Render.Foreground(this, guiGraphics, mouseX, mouseY));
|
||||
ItemStack itemstack = this.draggingItem.isEmpty() ? this.menu.getCarried() : this.draggingItem;
|
||||
if (!itemstack.isEmpty()) {
|
||||
int l1 = 8;
|
||||
int i2 = this.draggingItem.isEmpty() ? 8 : 16;
|
||||
String s = null;
|
||||
if (!this.draggingItem.isEmpty() && this.isSplittingStack) {
|
||||
itemstack = itemstack.copyWithCount(Mth.ceil((float)itemstack.getCount() / 2.0F));
|
||||
} else if (this.isQuickCrafting && this.quickCraftSlots.size() > 1) {
|
||||
itemstack = itemstack.copyWithCount(this.quickCraftingRemainder);
|
||||
if (itemstack.isEmpty()) {
|
||||
s = ChatFormatting.YELLOW + "0";
|
||||
}
|
||||
}
|
||||
|
||||
this.renderFloatingItem(guiGraphics, itemstack, mouseX - i - 8, mouseY - j - i2, s);
|
||||
}
|
||||
|
||||
if (!this.snapbackItem.isEmpty()) {
|
||||
float f = (float)(Util.getMillis() - this.snapbackTime) / 100.0F;
|
||||
if (f >= 1.0F) {
|
||||
f = 1.0F;
|
||||
this.snapbackItem = ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
int j2 = this.snapbackEnd.x - this.snapbackStartX;
|
||||
int k2 = this.snapbackEnd.y - this.snapbackStartY;
|
||||
int j1 = this.snapbackStartX + (int)((float)j2 * f);
|
||||
int k1 = this.snapbackStartY + (int)((float)k2 * f);
|
||||
this.renderFloatingItem(guiGraphics, this.snapbackItem, j1, k1, null);
|
||||
}
|
||||
|
||||
guiGraphics.pose().popPose();
|
||||
RenderSystem.enableDepthTest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderBackground(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
|
||||
this.renderTransparentBackground(guiGraphics);
|
||||
this.renderBg(guiGraphics, partialTick, mouseX, mouseY);
|
||||
}
|
||||
|
||||
public static void renderSlotHighlight(GuiGraphics guiGraphics, int x, int y, int blitOffset) {
|
||||
renderSlotHighlight(guiGraphics, x, y, blitOffset, -2130706433);
|
||||
}
|
||||
public static void renderSlotHighlight(GuiGraphics guiGraphics, int x, int y, int blitOffset, int color) {
|
||||
guiGraphics.fillGradient(RenderType.guiOverlay(), x, y, x + 16, y + 16, color, color, blitOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a highlight for the given slot to indicate the mouse is currently hovering over it.
|
||||
*/
|
||||
protected void renderSlotHighlight(GuiGraphics guiGraphics, Slot slot, int mouseX, int mouseY, float partialTick) {
|
||||
if (slot.isHighlightable()) {
|
||||
renderSlotHighlight(guiGraphics, slot.x, slot.y, 0, getSlotColor(slot.index));
|
||||
}
|
||||
}
|
||||
|
||||
protected void renderTooltip(GuiGraphics guiGraphics, int x, int y) {
|
||||
if (this.menu.getCarried().isEmpty() && this.hoveredSlot != null && this.hoveredSlot.hasItem()) {
|
||||
ItemStack itemstack = this.hoveredSlot.getItem();
|
||||
guiGraphics.renderTooltip(this.font, this.getTooltipFromContainerItem(itemstack), itemstack.getTooltipImage(), itemstack, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
protected List<Component> getTooltipFromContainerItem(ItemStack stack) {
|
||||
return getTooltipFromItem(this.minecraft, stack);
|
||||
}
|
||||
|
||||
private void renderFloatingItem(GuiGraphics guiGraphics, ItemStack stack, int x, int y, String text) {
|
||||
guiGraphics.pose().pushPose();
|
||||
guiGraphics.pose().translate(0.0F, 0.0F, 232.0F);
|
||||
guiGraphics.renderItem(stack, x, y);
|
||||
var font = net.neoforged.neoforge.client.extensions.common.IClientItemExtensions.of(stack).getFont(stack, net.neoforged.neoforge.client.extensions.common.IClientItemExtensions.FontContext.ITEM_COUNT);
|
||||
guiGraphics.renderItemDecorations(font == null ? this.font : font, stack, x, y - (this.draggingItem.isEmpty() ? 0 : 8), text);
|
||||
guiGraphics.pose().popPose();
|
||||
}
|
||||
|
||||
protected void renderLabels(GuiGraphics guiGraphics, int mouseX, int mouseY) {
|
||||
guiGraphics.drawString(this.font, this.title, this.titleLabelX, this.titleLabelY, 4210752, false);
|
||||
guiGraphics.drawString(this.font, this.playerInventoryTitle, this.inventoryLabelX, this.inventoryLabelY, 4210752, false);
|
||||
}
|
||||
|
||||
protected abstract void renderBg(GuiGraphics guiGraphics, float partialTick, int mouseX, int mouseY);
|
||||
|
||||
protected void renderSlot(GuiGraphics guiGraphics, Slot slot) {
|
||||
int i = slot.x;
|
||||
int j = slot.y;
|
||||
ItemStack itemstack = slot.getItem();
|
||||
boolean flag = false;
|
||||
boolean flag1 = slot == this.clickedSlot && !this.draggingItem.isEmpty() && !this.isSplittingStack;
|
||||
ItemStack itemstack1 = this.menu.getCarried();
|
||||
String s = null;
|
||||
if (slot == this.clickedSlot && !this.draggingItem.isEmpty() && this.isSplittingStack && !itemstack.isEmpty()) {
|
||||
itemstack = itemstack.copyWithCount(itemstack.getCount() / 2);
|
||||
} else if (this.isQuickCrafting && this.quickCraftSlots.contains(slot) && !itemstack1.isEmpty()) {
|
||||
if (this.quickCraftSlots.size() == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (AbstractContainerMenu.canItemQuickReplace(slot, itemstack1, true) && this.menu.canDragTo(slot)) {
|
||||
flag = true;
|
||||
int k = Math.min(itemstack1.getMaxStackSize(), slot.getMaxStackSize(itemstack1));
|
||||
int l = slot.getItem().isEmpty() ? 0 : slot.getItem().getCount();
|
||||
int i1 = AbstractContainerMenu.getQuickCraftPlaceCount(this.quickCraftSlots, this.quickCraftingType, itemstack1) + l;
|
||||
if (i1 > k) {
|
||||
i1 = k;
|
||||
s = ChatFormatting.YELLOW.toString() + k;
|
||||
}
|
||||
|
||||
itemstack = itemstack1.copyWithCount(i1);
|
||||
} else {
|
||||
this.quickCraftSlots.remove(slot);
|
||||
this.recalculateQuickCraftRemaining();
|
||||
}
|
||||
}
|
||||
|
||||
guiGraphics.pose().pushPose();
|
||||
guiGraphics.pose().translate(0.0F, 0.0F, 100.0F);
|
||||
if (itemstack.isEmpty() && slot.isActive()) {
|
||||
Pair<ResourceLocation, ResourceLocation> pair = slot.getNoItemIcon();
|
||||
if (pair != null) {
|
||||
TextureAtlasSprite textureatlassprite = this.minecraft.getTextureAtlas(pair.getFirst()).apply(pair.getSecond());
|
||||
guiGraphics.blit(i, j, 0, 16, 16, textureatlassprite);
|
||||
flag1 = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!flag1) {
|
||||
if (flag) {
|
||||
guiGraphics.fill(i, j, i + 16, j + 16, -2130706433);
|
||||
}
|
||||
|
||||
renderSlotContents(guiGraphics, itemstack, slot, s);
|
||||
}
|
||||
|
||||
guiGraphics.pose().popPose();
|
||||
}
|
||||
|
||||
protected void renderSlotContents(GuiGraphics guiGraphics, ItemStack itemstack, Slot slot, @Nullable String countString) {
|
||||
GuiGraphics p_281607_ = guiGraphics; Slot p_282613_ = slot; String s = countString; int i = slot.x; int j = slot.y;
|
||||
int j1 = p_282613_.x + p_282613_.y * this.imageWidth;
|
||||
if (p_282613_.isFake()) {
|
||||
p_281607_.renderFakeItem(itemstack, i, j, j1);
|
||||
} else {
|
||||
p_281607_.renderItem(itemstack, i, j, j1);
|
||||
}
|
||||
|
||||
p_281607_.renderItemDecorations(this.font, itemstack, i, j, s);
|
||||
}
|
||||
|
||||
private void recalculateQuickCraftRemaining() {
|
||||
ItemStack itemstack = this.menu.getCarried();
|
||||
if (!itemstack.isEmpty() && this.isQuickCrafting) {
|
||||
if (this.quickCraftingType == 2) {
|
||||
this.quickCraftingRemainder = itemstack.getMaxStackSize();
|
||||
} else {
|
||||
this.quickCraftingRemainder = itemstack.getCount();
|
||||
|
||||
for (Slot slot : this.quickCraftSlots) {
|
||||
ItemStack itemstack1 = slot.getItem();
|
||||
int i = itemstack1.isEmpty() ? 0 : itemstack1.getCount();
|
||||
int j = Math.min(itemstack.getMaxStackSize(), slot.getMaxStackSize(itemstack));
|
||||
int k = Math.min(AbstractContainerMenu.getQuickCraftPlaceCount(this.quickCraftSlots, this.quickCraftingType, itemstack) + i, j);
|
||||
this.quickCraftingRemainder -= k - i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Slot findSlot(double mouseX, double mouseY) {
|
||||
for (int i = 0; i < this.menu.slots.size(); i++) {
|
||||
Slot slot = this.menu.slots.get(i);
|
||||
if (this.isHovering(slot, mouseX, mouseY) && slot.isActive()) {
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a mouse button is clicked within the GUI element.
|
||||
* <p>
|
||||
* @return {@code true} if the event is consumed, {@code false} otherwise.
|
||||
*
|
||||
* @param mouseX the X coordinate of the mouse.
|
||||
* @param mouseY the Y coordinate of the mouse.
|
||||
* @param button the button that was clicked.
|
||||
*/
|
||||
@Override
|
||||
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||
if (super.mouseClicked(mouseX, mouseY, button)) {
|
||||
return true;
|
||||
} else {
|
||||
InputConstants.Key mouseKey = InputConstants.Type.MOUSE.getOrCreate(button);
|
||||
boolean flag = this.minecraft.options.keyPickItem.isActiveAndMatches(mouseKey);
|
||||
Slot slot = this.findSlot(mouseX, mouseY);
|
||||
long i = Util.getMillis();
|
||||
this.doubleclick = this.lastClickSlot == slot && i - this.lastClickTime < 250L && this.lastClickButton == button;
|
||||
this.skipNextRelease = false;
|
||||
if (button != 0 && button != 1 && !flag) {
|
||||
this.checkHotbarMouseClicked(button);
|
||||
} else {
|
||||
int j = this.leftPos;
|
||||
int k = this.topPos;
|
||||
boolean flag1 = this.hasClickedOutside(mouseX, mouseY, j, k, button);
|
||||
if (slot != null) flag1 = false; // Forge, prevent dropping of items through slots outside of GUI boundaries
|
||||
int l = -1;
|
||||
if (slot != null) {
|
||||
l = slot.index;
|
||||
}
|
||||
|
||||
if (flag1) {
|
||||
l = -999;
|
||||
}
|
||||
|
||||
if (this.minecraft.options.touchscreen().get() && flag1 && this.menu.getCarried().isEmpty()) {
|
||||
this.onClose();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (l != -1) {
|
||||
if (this.minecraft.options.touchscreen().get()) {
|
||||
if (slot != null && slot.hasItem()) {
|
||||
this.clickedSlot = slot;
|
||||
this.draggingItem = ItemStack.EMPTY;
|
||||
this.isSplittingStack = button == 1;
|
||||
} else {
|
||||
this.clickedSlot = null;
|
||||
}
|
||||
} else if (!this.isQuickCrafting) {
|
||||
if (this.menu.getCarried().isEmpty()) {
|
||||
if (this.minecraft.options.keyPickItem.isActiveAndMatches(mouseKey)) {
|
||||
this.slotClicked(slot, l, button, ClickType.CLONE);
|
||||
} else {
|
||||
boolean flag2 = l != -999
|
||||
&& (
|
||||
InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), 340)
|
||||
|| InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), 344)
|
||||
);
|
||||
ClickType clicktype = ClickType.PICKUP;
|
||||
if (flag2) {
|
||||
this.lastQuickMoved = slot != null && slot.hasItem() ? slot.getItem().copy() : ItemStack.EMPTY;
|
||||
clicktype = ClickType.QUICK_MOVE;
|
||||
} else if (l == -999) {
|
||||
clicktype = ClickType.THROW;
|
||||
}
|
||||
|
||||
this.slotClicked(slot, l, button, clicktype);
|
||||
}
|
||||
|
||||
this.skipNextRelease = true;
|
||||
} else {
|
||||
this.isQuickCrafting = true;
|
||||
this.quickCraftingButton = button;
|
||||
this.quickCraftSlots.clear();
|
||||
if (button == 0) {
|
||||
this.quickCraftingType = 0;
|
||||
} else if (button == 1) {
|
||||
this.quickCraftingType = 1;
|
||||
} else if (this.minecraft.options.keyPickItem.isActiveAndMatches(mouseKey)) {
|
||||
this.quickCraftingType = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.lastClickSlot = slot;
|
||||
this.lastClickTime = i;
|
||||
this.lastClickButton = button;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkHotbarMouseClicked(int keyCode) {
|
||||
if (this.hoveredSlot != null && this.menu.getCarried().isEmpty()) {
|
||||
if (this.minecraft.options.keySwapOffhand.matchesMouse(keyCode)) {
|
||||
this.slotClicked(this.hoveredSlot, this.hoveredSlot.index, 40, ClickType.SWAP);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 9; i++) {
|
||||
if (this.minecraft.options.keyHotbarSlots[i].matchesMouse(keyCode)) {
|
||||
this.slotClicked(this.hoveredSlot, this.hoveredSlot.index, i, ClickType.SWAP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean hasClickedOutside(double mouseX, double mouseY, int guiLeft, int guiTop, int mouseButton) {
|
||||
return mouseX < (double)guiLeft
|
||||
|| mouseY < (double)guiTop
|
||||
|| mouseX >= (double)(guiLeft + this.imageWidth)
|
||||
|| mouseY >= (double)(guiTop + this.imageHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the mouse is dragged within the GUI element.
|
||||
* <p>
|
||||
* @return {@code true} if the event is consumed, {@code false} otherwise.
|
||||
*
|
||||
* @param mouseX the X coordinate of the mouse.
|
||||
* @param mouseY the Y coordinate of the mouse.
|
||||
* @param button the button that is being dragged.
|
||||
* @param dragX the X distance of the drag.
|
||||
* @param dragY the Y distance of the drag.
|
||||
*/
|
||||
@Override
|
||||
public boolean mouseDragged(double mouseX, double mouseY, int button, double dragX, double dragY) {
|
||||
Slot slot = this.findSlot(mouseX, mouseY);
|
||||
ItemStack itemstack = this.menu.getCarried();
|
||||
if (this.clickedSlot != null && this.minecraft.options.touchscreen().get()) {
|
||||
if (button == 0 || button == 1) {
|
||||
if (this.draggingItem.isEmpty()) {
|
||||
if (slot != this.clickedSlot && !this.clickedSlot.getItem().isEmpty()) {
|
||||
this.draggingItem = this.clickedSlot.getItem().copy();
|
||||
}
|
||||
} else if (this.draggingItem.getCount() > 1 && slot != null && AbstractContainerMenu.canItemQuickReplace(slot, this.draggingItem, false)) {
|
||||
long i = Util.getMillis();
|
||||
if (this.quickdropSlot == slot) {
|
||||
if (i - this.quickdropTime > 500L) {
|
||||
this.slotClicked(this.clickedSlot, this.clickedSlot.index, 0, ClickType.PICKUP);
|
||||
this.slotClicked(slot, slot.index, 1, ClickType.PICKUP);
|
||||
this.slotClicked(this.clickedSlot, this.clickedSlot.index, 0, ClickType.PICKUP);
|
||||
this.quickdropTime = i + 750L;
|
||||
this.draggingItem.shrink(1);
|
||||
}
|
||||
} else {
|
||||
this.quickdropSlot = slot;
|
||||
this.quickdropTime = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (this.isQuickCrafting
|
||||
&& slot != null
|
||||
&& !itemstack.isEmpty()
|
||||
&& (itemstack.getCount() > this.quickCraftSlots.size() || this.quickCraftingType == 2)
|
||||
&& AbstractContainerMenu.canItemQuickReplace(slot, itemstack, true)
|
||||
&& slot.mayPlace(itemstack)
|
||||
&& this.menu.canDragTo(slot)) {
|
||||
this.quickCraftSlots.add(slot);
|
||||
this.recalculateQuickCraftRemaining();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a mouse button is released within the GUI element.
|
||||
* <p>
|
||||
* @return {@code true} if the event is consumed, {@code false} otherwise.
|
||||
*
|
||||
* @param mouseX the X coordinate of the mouse.
|
||||
* @param mouseY the Y coordinate of the mouse.
|
||||
* @param button the button that was released.
|
||||
*/
|
||||
@Override
|
||||
public boolean mouseReleased(double mouseX, double mouseY, int button) {
|
||||
super.mouseReleased(mouseX, mouseY, button); //Forge, Call parent to release buttons
|
||||
Slot slot = this.findSlot(mouseX, mouseY);
|
||||
int i = this.leftPos;
|
||||
int j = this.topPos;
|
||||
boolean flag = this.hasClickedOutside(mouseX, mouseY, i, j, button);
|
||||
if (slot != null) flag = false; // Forge, prevent dropping of items through slots outside of GUI boundaries
|
||||
InputConstants.Key mouseKey = InputConstants.Type.MOUSE.getOrCreate(button);
|
||||
int k = -1;
|
||||
if (slot != null) {
|
||||
k = slot.index;
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
k = -999;
|
||||
}
|
||||
|
||||
if (this.doubleclick && slot != null && button == 0 && this.menu.canTakeItemForPickAll(ItemStack.EMPTY, slot)) {
|
||||
if (hasShiftDown()) {
|
||||
if (!this.lastQuickMoved.isEmpty()) {
|
||||
for (Slot slot2 : this.menu.slots) {
|
||||
if (slot2 != null
|
||||
&& slot2.mayPickup(this.minecraft.player)
|
||||
&& slot2.hasItem()
|
||||
&& slot2.isSameInventory(slot)
|
||||
&& AbstractContainerMenu.canItemQuickReplace(slot2, this.lastQuickMoved, true)) {
|
||||
this.slotClicked(slot2, slot2.index, button, ClickType.QUICK_MOVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.slotClicked(slot, k, button, ClickType.PICKUP_ALL);
|
||||
}
|
||||
|
||||
this.doubleclick = false;
|
||||
this.lastClickTime = 0L;
|
||||
} else {
|
||||
if (this.isQuickCrafting && this.quickCraftingButton != button) {
|
||||
this.isQuickCrafting = false;
|
||||
this.quickCraftSlots.clear();
|
||||
this.skipNextRelease = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.skipNextRelease) {
|
||||
this.skipNextRelease = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.clickedSlot != null && this.minecraft.options.touchscreen().get()) {
|
||||
if (button == 0 || button == 1) {
|
||||
if (this.draggingItem.isEmpty() && slot != this.clickedSlot) {
|
||||
this.draggingItem = this.clickedSlot.getItem();
|
||||
}
|
||||
|
||||
boolean flag2 = AbstractContainerMenu.canItemQuickReplace(slot, this.draggingItem, false);
|
||||
if (k != -1 && !this.draggingItem.isEmpty() && flag2) {
|
||||
this.slotClicked(this.clickedSlot, this.clickedSlot.index, button, ClickType.PICKUP);
|
||||
this.slotClicked(slot, k, 0, ClickType.PICKUP);
|
||||
if (this.menu.getCarried().isEmpty()) {
|
||||
this.snapbackItem = ItemStack.EMPTY;
|
||||
} else {
|
||||
this.slotClicked(this.clickedSlot, this.clickedSlot.index, button, ClickType.PICKUP);
|
||||
this.snapbackStartX = Mth.floor(mouseX - (double)i);
|
||||
this.snapbackStartY = Mth.floor(mouseY - (double)j);
|
||||
this.snapbackEnd = this.clickedSlot;
|
||||
this.snapbackItem = this.draggingItem;
|
||||
this.snapbackTime = Util.getMillis();
|
||||
}
|
||||
} else if (!this.draggingItem.isEmpty()) {
|
||||
this.snapbackStartX = Mth.floor(mouseX - (double)i);
|
||||
this.snapbackStartY = Mth.floor(mouseY - (double)j);
|
||||
this.snapbackEnd = this.clickedSlot;
|
||||
this.snapbackItem = this.draggingItem;
|
||||
this.snapbackTime = Util.getMillis();
|
||||
}
|
||||
|
||||
this.clearDraggingState();
|
||||
}
|
||||
} else if (this.isQuickCrafting && !this.quickCraftSlots.isEmpty()) {
|
||||
this.slotClicked(null, -999, AbstractContainerMenu.getQuickcraftMask(0, this.quickCraftingType), ClickType.QUICK_CRAFT);
|
||||
|
||||
for (Slot slot1 : this.quickCraftSlots) {
|
||||
this.slotClicked(slot1, slot1.index, AbstractContainerMenu.getQuickcraftMask(1, this.quickCraftingType), ClickType.QUICK_CRAFT);
|
||||
}
|
||||
|
||||
this.slotClicked(null, -999, AbstractContainerMenu.getQuickcraftMask(2, this.quickCraftingType), ClickType.QUICK_CRAFT);
|
||||
} else if (!this.menu.getCarried().isEmpty()) {
|
||||
if (this.minecraft.options.keyPickItem.isActiveAndMatches(mouseKey)) {
|
||||
this.slotClicked(slot, k, button, ClickType.CLONE);
|
||||
} else {
|
||||
boolean flag1 = k != -999
|
||||
&& (
|
||||
InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), 340)
|
||||
|| InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), 344)
|
||||
);
|
||||
if (flag1) {
|
||||
this.lastQuickMoved = slot != null && slot.hasItem() ? slot.getItem().copy() : ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
this.slotClicked(slot, k, button, flag1 ? ClickType.QUICK_MOVE : ClickType.PICKUP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.menu.getCarried().isEmpty()) {
|
||||
this.lastClickTime = 0L;
|
||||
}
|
||||
|
||||
this.isQuickCrafting = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void clearDraggingState() {
|
||||
this.draggingItem = ItemStack.EMPTY;
|
||||
this.clickedSlot = null;
|
||||
}
|
||||
|
||||
private boolean isHovering(Slot slot, double mouseX, double mouseY) {
|
||||
return this.isHovering(slot.x, slot.y, 16, 16, mouseX, mouseY);
|
||||
}
|
||||
|
||||
protected boolean isHovering(int x, int y, int width, int height, double mouseX, double mouseY) {
|
||||
int i = this.leftPos;
|
||||
int j = this.topPos;
|
||||
mouseX -= (double)i;
|
||||
mouseY -= (double)j;
|
||||
return mouseX >= (double)(x - 1)
|
||||
&& mouseX < (double)(x + width + 1)
|
||||
&& mouseY >= (double)(y - 1)
|
||||
&& mouseY < (double)(y + height + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the mouse is clicked over a slot or outside the gui.
|
||||
*/
|
||||
protected void slotClicked(Slot slot, int slotId, int mouseButton, ClickType type) {
|
||||
if (slot != null) {
|
||||
slotId = slot.index;
|
||||
}
|
||||
|
||||
this.minecraft.gameMode.handleInventoryMouseClick(this.menu.containerId, slotId, mouseButton, type, this.minecraft.player);
|
||||
}
|
||||
|
||||
protected void handleSlotStateChanged(int slotId, int containerId, boolean newState) {
|
||||
this.minecraft.gameMode.handleSlotStateChanged(slotId, containerId, newState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a keyboard key is pressed within the GUI element.
|
||||
* <p>
|
||||
* @return {@code true} if the event is consumed, {@code false} otherwise.
|
||||
*
|
||||
* @param keyCode the key code of the pressed key.
|
||||
* @param scanCode the scan code of the pressed key.
|
||||
* @param modifiers the keyboard modifiers.
|
||||
*/
|
||||
@Override
|
||||
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||
InputConstants.Key mouseKey = InputConstants.getKey(keyCode, scanCode);
|
||||
if (super.keyPressed(keyCode, scanCode, modifiers)) {
|
||||
return true;
|
||||
} else if (this.minecraft.options.keyInventory.isActiveAndMatches(mouseKey)) {
|
||||
this.onClose();
|
||||
return true;
|
||||
} else {
|
||||
boolean handled = this.checkHotbarKeyPressed(keyCode, scanCode);// Forge MC-146650: Needs to return true when the key is handled
|
||||
if (this.hoveredSlot != null && this.hoveredSlot.hasItem()) {
|
||||
if (this.minecraft.options.keyPickItem.isActiveAndMatches(mouseKey)) {
|
||||
this.slotClicked(this.hoveredSlot, this.hoveredSlot.index, 0, ClickType.CLONE);
|
||||
handled = true;
|
||||
} else if (this.minecraft.options.keyDrop.isActiveAndMatches(mouseKey)) {
|
||||
this.slotClicked(this.hoveredSlot, this.hoveredSlot.index, hasControlDown() ? 1 : 0, ClickType.THROW);
|
||||
handled = true;
|
||||
}
|
||||
} else if (this.minecraft.options.keyDrop.isActiveAndMatches(mouseKey)) {
|
||||
handled = true; // Forge MC-146650: Emulate MC bug, so we don't drop from hotbar when pressing drop without hovering over a item.
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean checkHotbarKeyPressed(int keyCode, int scanCode) {
|
||||
if (this.menu.getCarried().isEmpty() && this.hoveredSlot != null) {
|
||||
if (this.minecraft.options.keySwapOffhand.isActiveAndMatches(InputConstants.getKey(keyCode, scanCode))) {
|
||||
this.slotClicked(this.hoveredSlot, this.hoveredSlot.index, 40, ClickType.SWAP);
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 9; i++) {
|
||||
if (this.minecraft.options.keyHotbarSlots[i].isActiveAndMatches(InputConstants.getKey(keyCode, scanCode))) {
|
||||
this.slotClicked(this.hoveredSlot, this.hoveredSlot.index, i, ClickType.SWAP);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed() {
|
||||
if (this.minecraft.player != null) {
|
||||
this.menu.removed(this.minecraft.player);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPauseScreen() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void tick() {
|
||||
super.tick();
|
||||
if (this.minecraft.player.isAlive() && !this.minecraft.player.isRemoved()) {
|
||||
this.containerTick();
|
||||
} else {
|
||||
this.minecraft.player.closeContainer();
|
||||
}
|
||||
}
|
||||
|
||||
protected void containerTick() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getMenu() {
|
||||
return this.menu;
|
||||
}
|
||||
|
||||
@org.jetbrains.annotations.Nullable
|
||||
public Slot getSlotUnderMouse() { return this.hoveredSlot; }
|
||||
public int getGuiLeft() { return leftPos; }
|
||||
public int getGuiTop() { return topPos; }
|
||||
public int getXSize() { return imageWidth; }
|
||||
public int getYSize() { return imageHeight; }
|
||||
|
||||
protected int slotColor = -2130706433;
|
||||
public int getSlotColor(int index) {
|
||||
return slotColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
this.minecraft.player.closeContainer();
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
1031
net/neoforged/neoforge/client/event/ScreenEvent.java
Normal file
1031
net/neoforged/neoforge/client/event/ScreenEvent.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 |
Reference in New Issue
Block a user