package de.hysky.skyblocker.config;
import de.hysky.skyblocker.utils.render.HudHelper;
import de.hysky.skyblocker.utils.render.gui.AbstractWidget;
import it.unimi.dsi.fastutil.ints.IntIntMutablePair;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.text.Text;
import java.awt.*;
import java.util.List;
/**
* A screen for configuring the positions of HUD widgets.
*
* Note: This is currently only used for title container. There is a new system for other HUD widgets, see {@link de.hysky.skyblocker.skyblock.tabhud.config.WidgetsConfigurationScreen}
*
* This class takes care of rendering the widgets, dragging them, and resetting their positions.
* Create one subclass for each collection of HUD widgets that are displayed at the same time.
* (i.e. one for dwarven mines, one for the end, etc.) See an implementation for an example.
*/
public abstract class HudConfigScreen extends Screen {
protected final Screen parent;
protected final List widgets;
private AbstractWidget draggingWidget;
private double mouseClickRelativeX;
private double mouseClickRelativeY;
/**
* Creates a new HudConfigScreen with the passed title, parent, and widget
*
* @param title the title of the screen
* @param parent the parent screen
* @param widget the widget to configure
*/
public HudConfigScreen(Text title, Screen parent, AbstractWidget widget) {
this(title, parent, List.of(widget));
}
/**
* Creates a new HudConfigScreen with the passed title, parent, and widgets
*
* @param title the title of the screen
* @param parent the parent screen
* @param widgets the widgets to configure
*/
public HudConfigScreen(Text title, Screen parent, List widgets) {
super(title);
this.parent = parent;
this.widgets = widgets;
}
@Override
protected void init() {
super.init();
// Reset positions here, so width and height are available.
resetPos();
}
@Override
public final void render(DrawContext context, int mouseX, int mouseY, float delta) {
super.render(context, mouseX, mouseY, delta);
renderWidget(context, widgets, delta);
context.drawCenteredTextWithShadow(textRenderer, "Right Click To Reset Position", width / 2, height / 2, Color.GRAY.getRGB());
}
/**
* Renders the widgets using the default {@link AbstractWidget#render(DrawContext, int, int, float)} method. Override to change the behavior.
*
* @param context the context to render in
* @param widgets the widgets to render
*/
protected void renderWidget(DrawContext context, List widgets, float delta) {
for (AbstractWidget widget : widgets) {
widget.render(context, -1, -1, delta);
}
}
@Override
public final boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
if (button == 0 && draggingWidget != null) {
draggingWidget.setX((int) Math.clamp(mouseX - mouseClickRelativeX, 0, this.width - draggingWidget.getWidth()) - getWidgetXOffset(draggingWidget));
draggingWidget.setY((int) Math.clamp(mouseY - mouseClickRelativeY, 0, this.height - draggingWidget.getHeight()));
}
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
}
@Override
public final boolean mouseClicked(double mouseX, double mouseY, int button) {
if (button == 0) {
for (AbstractWidget widget : widgets) {
if (HudHelper.pointIsInArea(mouseX, mouseY, widget.getX() + getWidgetXOffset(widget), widget.getY(), widget.getX() + getWidgetXOffset(widget) + widget.getWidth(), widget.getY() + widget.getHeight())) {
draggingWidget = widget;
mouseClickRelativeX = mouseX - widget.getX() - getWidgetXOffset(widget);
mouseClickRelativeY = mouseY - widget.getY();
break;
}
}
} else if (button == 1) {
resetPos();
}
return super.mouseClicked(mouseX, mouseY, button);
}
@Override
public final boolean mouseReleased(double mouseX, double mouseY, int button) {
draggingWidget = null;
return super.mouseReleased(mouseX, mouseY, button);
}
protected int getWidgetXOffset(AbstractWidget widget) {
return 0;
}
/**
* Resets the positions of the widgets to the positions in the config. Override to change the behavior.
*/
protected void resetPos() {
List configPositions = getConfigPos(SkyblockerConfigManager.get());
if (configPositions.size() != widgets.size()) {
throw new IllegalStateException("The number of positions (" + configPositions.size() + ") does not match the number of widgets (" + widgets.size() + ")");
}
for (int i = 0; i < widgets.size(); i++) {
AbstractWidget widget = widgets.get(i);
IntIntMutablePair configPos = configPositions.get(i);
widget.setX(configPos.leftInt());
widget.setY(configPos.rightInt());
}
}
/**
* Returns the positions of the widgets in the config
*
* @param config the config to get the positions from
* @return the positions of the widgets
*/
protected abstract List getConfigPos(SkyblockerConfig config);
@Override
public final void close() {
SkyblockerConfigManager.update(config -> savePos(config, widgets));
client.setScreen(parent);
}
/**
* Saves the passed positions to the config.
*
* NOTE: The config manager will save the config right after this method is called.
*
* @param configManager the config so you don't have to get it
* @param widgets the widgets to save
* @see SkyblockerConfigManager#update(java.util.function.Consumer)
*/
protected abstract void savePos(SkyblockerConfig configManager, List widgets);
}