445 lines
16 KiB
Java
445 lines
16 KiB
Java
package net.fretux.mindmotion.client;
|
|
|
|
import java.util.function.IntConsumer;
|
|
import net.fretux.mindmotion.ConfigMM;
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.client.gui.GuiGraphics;
|
|
import net.minecraft.client.gui.components.AbstractSliderButton;
|
|
import net.minecraft.client.gui.components.Button;
|
|
import net.minecraft.client.gui.screens.Screen;
|
|
import net.minecraft.network.chat.Component;
|
|
|
|
public class HudEditorScreen extends Screen {
|
|
private static final int MIN_BAR_WIDTH = 40;
|
|
private static final int MAX_BAR_WIDTH = 240;
|
|
private static final int MIN_BAR_HEIGHT = 4;
|
|
private static final int MAX_BAR_HEIGHT = 30;
|
|
private static final int MIN_OFFSET = -300;
|
|
private static final int MAX_OFFSET = 300;
|
|
private static final int DEFAULT_BAR_WIDTH = 102;
|
|
private static final int DEFAULT_BAR_HEIGHT = 9;
|
|
private static final int DEFAULT_OFFSET = 0;
|
|
private static final int BASE_TEMPO_X = 8;
|
|
private static final int BASE_Y_OFFSET = 48;
|
|
|
|
private final Screen previous;
|
|
|
|
private int barWidth;
|
|
private int barHeight;
|
|
private int tempoOffsetX;
|
|
private int tempoOffsetY;
|
|
private int sanityOffsetX;
|
|
private int sanityOffsetY;
|
|
|
|
private boolean draggingTempo;
|
|
private boolean draggingSanity;
|
|
private double dragStartX;
|
|
private double dragStartY;
|
|
private int dragStartTempoX;
|
|
private int dragStartTempoY;
|
|
private int dragStartSanityX;
|
|
private int dragStartSanityY;
|
|
|
|
private IntSlider barWidthSlider;
|
|
private IntSlider barHeightSlider;
|
|
private IntSlider tempoXSlider;
|
|
private IntSlider tempoYSlider;
|
|
private IntSlider sanityXSlider;
|
|
private IntSlider sanityYSlider;
|
|
|
|
public HudEditorScreen(Screen previous) {
|
|
super(Component.translatable("screen.mindmotion.hud_editor.title"));
|
|
this.previous = previous;
|
|
this.barWidth = ConfigMM.CLIENT.BAR_WIDTH.get();
|
|
this.barHeight = ConfigMM.CLIENT.BAR_HEIGHT.get();
|
|
this.tempoOffsetX = ConfigMM.CLIENT.TEMPO_BAR_X_OFFSET.get();
|
|
this.tempoOffsetY = ConfigMM.CLIENT.TEMPO_BAR_Y_OFFSET.get();
|
|
this.sanityOffsetX = ConfigMM.CLIENT.SANITY_BAR_X_OFFSET.get();
|
|
this.sanityOffsetY = ConfigMM.CLIENT.SANITY_BAR_Y_OFFSET.get();
|
|
}
|
|
|
|
@Override
|
|
protected void init() {
|
|
int leftX = this.width / 2 - 155;
|
|
int rightX = this.width / 2 + 5;
|
|
int sliderWidth = 150;
|
|
int y = 36;
|
|
int step = 24;
|
|
boolean tempoEnabled = ConfigMM.COMMON.ENABLE_TEMPO.get() && ClientData.TEMPO_ENABLED;
|
|
boolean sanityEnabled = ConfigMM.COMMON.ENABLE_SANITY.get() && ClientData.SANITY_ENABLED;
|
|
|
|
barWidthSlider = addRenderableWidget(new IntSlider(
|
|
leftX,
|
|
y,
|
|
sliderWidth,
|
|
20,
|
|
"screen.mindmotion.hud_editor.bar_width",
|
|
MIN_BAR_WIDTH,
|
|
MAX_BAR_WIDTH,
|
|
barWidth,
|
|
value -> setBarWidth(value, false)
|
|
));
|
|
barHeightSlider = addRenderableWidget(new IntSlider(
|
|
rightX,
|
|
y,
|
|
sliderWidth,
|
|
20,
|
|
"screen.mindmotion.hud_editor.bar_height",
|
|
MIN_BAR_HEIGHT,
|
|
MAX_BAR_HEIGHT,
|
|
barHeight,
|
|
value -> setBarHeight(value, false)
|
|
));
|
|
|
|
y += step;
|
|
if (tempoEnabled) {
|
|
tempoXSlider = addRenderableWidget(new IntSlider(
|
|
leftX,
|
|
y,
|
|
sliderWidth,
|
|
20,
|
|
"screen.mindmotion.hud_editor.tempo_x",
|
|
MIN_OFFSET,
|
|
MAX_OFFSET,
|
|
tempoOffsetX,
|
|
value -> setTempoOffsetX(value, false)
|
|
));
|
|
tempoYSlider = addRenderableWidget(new IntSlider(
|
|
rightX,
|
|
y,
|
|
sliderWidth,
|
|
20,
|
|
"screen.mindmotion.hud_editor.tempo_y",
|
|
MIN_OFFSET,
|
|
MAX_OFFSET,
|
|
tempoOffsetY,
|
|
value -> setTempoOffsetY(value, false)
|
|
));
|
|
y += step;
|
|
}
|
|
|
|
if (sanityEnabled) {
|
|
sanityXSlider = addRenderableWidget(new IntSlider(
|
|
leftX,
|
|
y,
|
|
sliderWidth,
|
|
20,
|
|
"screen.mindmotion.hud_editor.sanity_x",
|
|
MIN_OFFSET,
|
|
MAX_OFFSET,
|
|
sanityOffsetX,
|
|
value -> setSanityOffsetX(value, false)
|
|
));
|
|
sanityYSlider = addRenderableWidget(new IntSlider(
|
|
rightX,
|
|
y,
|
|
sliderWidth,
|
|
20,
|
|
"screen.mindmotion.hud_editor.sanity_y",
|
|
MIN_OFFSET,
|
|
MAX_OFFSET,
|
|
sanityOffsetY,
|
|
value -> setSanityOffsetY(value, false)
|
|
));
|
|
}
|
|
|
|
int buttonY = this.height - 28;
|
|
addRenderableWidget(Button.builder(
|
|
Component.translatable("screen.mindmotion.hud_editor.reset"),
|
|
button -> resetDefaults())
|
|
.bounds(leftX, buttonY, 150, 20)
|
|
.build());
|
|
|
|
addRenderableWidget(Button.builder(
|
|
Component.translatable("gui.done"),
|
|
button -> onClose())
|
|
.bounds(rightX, buttonY, 150, 20)
|
|
.build());
|
|
}
|
|
|
|
@Override
|
|
public void render(GuiGraphics gui, int mouseX, int mouseY, float partialTick) {
|
|
renderBackground(gui);
|
|
gui.drawCenteredString(this.font, this.title, this.width / 2, 12, 0xFFFFFF);
|
|
gui.drawCenteredString(
|
|
this.font,
|
|
Component.translatable("screen.mindmotion.hud_editor.instructions"),
|
|
this.width / 2,
|
|
22,
|
|
0xA0A0A0
|
|
);
|
|
renderPreview(gui);
|
|
super.render(gui, mouseX, mouseY, partialTick);
|
|
}
|
|
|
|
@Override
|
|
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
|
if (button == 0) {
|
|
BarPosition tempoBar = getTempoBarPosition();
|
|
if (isTempoEnabled() && isMouseOver(mouseX, mouseY, tempoBar)) {
|
|
draggingTempo = true;
|
|
dragStartX = mouseX;
|
|
dragStartY = mouseY;
|
|
dragStartTempoX = tempoOffsetX;
|
|
dragStartTempoY = tempoOffsetY;
|
|
return true;
|
|
}
|
|
BarPosition sanityBar = getSanityBarPosition();
|
|
if (isSanityEnabled() && isMouseOver(mouseX, mouseY, sanityBar)) {
|
|
draggingSanity = true;
|
|
dragStartX = mouseX;
|
|
dragStartY = mouseY;
|
|
dragStartSanityX = sanityOffsetX;
|
|
dragStartSanityY = sanityOffsetY;
|
|
return true;
|
|
}
|
|
}
|
|
return super.mouseClicked(mouseX, mouseY, button);
|
|
}
|
|
|
|
@Override
|
|
public boolean mouseDragged(double mouseX, double mouseY, int button, double dragX, double dragY) {
|
|
if (button == 0) {
|
|
if (draggingTempo) {
|
|
int newX = clamp(dragStartTempoX + (int) Math.round(mouseX - dragStartX), MIN_OFFSET, MAX_OFFSET);
|
|
int newY = clamp(dragStartTempoY + (int) Math.round(mouseY - dragStartY), MIN_OFFSET, MAX_OFFSET);
|
|
setTempoOffsetX(newX, true);
|
|
setTempoOffsetY(newY, true);
|
|
return true;
|
|
}
|
|
if (draggingSanity) {
|
|
int newX = clamp(dragStartSanityX + (int) Math.round(mouseX - dragStartX), MIN_OFFSET, MAX_OFFSET);
|
|
int newY = clamp(dragStartSanityY + (int) Math.round(mouseY - dragStartY), MIN_OFFSET, MAX_OFFSET);
|
|
setSanityOffsetX(newX, true);
|
|
setSanityOffsetY(newY, true);
|
|
return true;
|
|
}
|
|
}
|
|
return super.mouseDragged(mouseX, mouseY, button, dragX, dragY);
|
|
}
|
|
|
|
@Override
|
|
public boolean mouseReleased(double mouseX, double mouseY, int button) {
|
|
if (button == 0) {
|
|
draggingTempo = false;
|
|
draggingSanity = false;
|
|
}
|
|
return super.mouseReleased(mouseX, mouseY, button);
|
|
}
|
|
|
|
@Override
|
|
public void onClose() {
|
|
saveConfig();
|
|
Minecraft minecraft = Minecraft.getInstance();
|
|
minecraft.setScreen(previous);
|
|
}
|
|
|
|
private void renderPreview(GuiGraphics gui) {
|
|
BarPosition tempoBar = getTempoBarPosition();
|
|
BarPosition sanityBar = getSanityBarPosition();
|
|
if (isTempoEnabled()) {
|
|
drawRoundedBar(gui, tempoBar, 0xFF33AFFF, (int) (barWidth * 0.75f));
|
|
gui.drawString(this.font, Component.literal("Tempo"), tempoBar.x, tempoBar.y - 12, 0x66CCFF, false);
|
|
}
|
|
if (isSanityEnabled()) {
|
|
drawRoundedBar(gui, sanityBar, 0xFFFFFFFF, (int) (barWidth * 0.6f));
|
|
int sanityLabelWidth = this.font.width("Sanity");
|
|
gui.drawString(
|
|
this.font,
|
|
Component.literal("Sanity"),
|
|
sanityBar.x + barWidth - sanityLabelWidth,
|
|
sanityBar.y - 12,
|
|
0xFFFFFF,
|
|
false
|
|
);
|
|
}
|
|
}
|
|
|
|
private BarPosition getTempoBarPosition() {
|
|
int baseY = this.height - BASE_Y_OFFSET;
|
|
return new BarPosition(
|
|
BASE_TEMPO_X + tempoOffsetX,
|
|
baseY + tempoOffsetY,
|
|
barWidth,
|
|
barHeight
|
|
);
|
|
}
|
|
|
|
private BarPosition getSanityBarPosition() {
|
|
int baseY = this.height - BASE_Y_OFFSET;
|
|
int baseSanityX = this.width - barWidth - 8;
|
|
return new BarPosition(
|
|
baseSanityX + sanityOffsetX,
|
|
baseY + sanityOffsetY,
|
|
barWidth,
|
|
barHeight
|
|
);
|
|
}
|
|
|
|
private void setBarWidth(int value, boolean updateSlider) {
|
|
barWidth = clamp(value, MIN_BAR_WIDTH, MAX_BAR_WIDTH);
|
|
ConfigMM.CLIENT.BAR_WIDTH.set(barWidth);
|
|
if (updateSlider && barWidthSlider != null) {
|
|
barWidthSlider.setIntValue(barWidth);
|
|
}
|
|
}
|
|
|
|
private void setBarHeight(int value, boolean updateSlider) {
|
|
barHeight = clamp(value, MIN_BAR_HEIGHT, MAX_BAR_HEIGHT);
|
|
ConfigMM.CLIENT.BAR_HEIGHT.set(barHeight);
|
|
if (updateSlider && barHeightSlider != null) {
|
|
barHeightSlider.setIntValue(barHeight);
|
|
}
|
|
}
|
|
|
|
private void setTempoOffsetX(int value, boolean updateSlider) {
|
|
tempoOffsetX = clamp(value, MIN_OFFSET, MAX_OFFSET);
|
|
ConfigMM.CLIENT.TEMPO_BAR_X_OFFSET.set(tempoOffsetX);
|
|
if (updateSlider && tempoXSlider != null) {
|
|
tempoXSlider.setIntValue(tempoOffsetX);
|
|
}
|
|
}
|
|
|
|
private void setTempoOffsetY(int value, boolean updateSlider) {
|
|
tempoOffsetY = clamp(value, MIN_OFFSET, MAX_OFFSET);
|
|
ConfigMM.CLIENT.TEMPO_BAR_Y_OFFSET.set(tempoOffsetY);
|
|
if (updateSlider && tempoYSlider != null) {
|
|
tempoYSlider.setIntValue(tempoOffsetY);
|
|
}
|
|
}
|
|
|
|
private void setSanityOffsetX(int value, boolean updateSlider) {
|
|
sanityOffsetX = clamp(value, MIN_OFFSET, MAX_OFFSET);
|
|
ConfigMM.CLIENT.SANITY_BAR_X_OFFSET.set(sanityOffsetX);
|
|
if (updateSlider && sanityXSlider != null) {
|
|
sanityXSlider.setIntValue(sanityOffsetX);
|
|
}
|
|
}
|
|
|
|
private void setSanityOffsetY(int value, boolean updateSlider) {
|
|
sanityOffsetY = clamp(value, MIN_OFFSET, MAX_OFFSET);
|
|
ConfigMM.CLIENT.SANITY_BAR_Y_OFFSET.set(sanityOffsetY);
|
|
if (updateSlider && sanityYSlider != null) {
|
|
sanityYSlider.setIntValue(sanityOffsetY);
|
|
}
|
|
}
|
|
|
|
private void resetDefaults() {
|
|
setBarWidth(DEFAULT_BAR_WIDTH, true);
|
|
setBarHeight(DEFAULT_BAR_HEIGHT, true);
|
|
setTempoOffsetX(DEFAULT_OFFSET, true);
|
|
setTempoOffsetY(DEFAULT_OFFSET, true);
|
|
setSanityOffsetX(DEFAULT_OFFSET, true);
|
|
setSanityOffsetY(DEFAULT_OFFSET, true);
|
|
}
|
|
|
|
private void saveConfig() {
|
|
ConfigMM.CLIENT_SPEC.save();
|
|
}
|
|
|
|
private static boolean isTempoEnabled() {
|
|
return ConfigMM.COMMON.ENABLE_TEMPO.get() && ClientData.TEMPO_ENABLED;
|
|
}
|
|
|
|
private static boolean isSanityEnabled() {
|
|
return ConfigMM.COMMON.ENABLE_SANITY.get() && ClientData.SANITY_ENABLED;
|
|
}
|
|
|
|
private static int clamp(int value, int min, int max) {
|
|
return Math.min(Math.max(value, min), max);
|
|
}
|
|
|
|
private void drawRoundedBar(GuiGraphics gui, BarPosition pos, int color, int fillWidth) {
|
|
int bg = 0xCC000000;
|
|
drawRoundedRect(gui, pos.x, pos.y, pos.width, pos.height, bg);
|
|
int top = color;
|
|
int bottom = (color & 0x00FFFFFF) | 0xFF000000;
|
|
drawRoundedRect(gui, pos.x, pos.y, fillWidth, pos.height, top, bottom);
|
|
}
|
|
|
|
private void drawRoundedRect(GuiGraphics gui, int x, int y, int width, int height, int color) {
|
|
gui.fill(x + 1, y, x + width - 1, y + height, color);
|
|
gui.fill(x, y + 1, x + width, y + height - 1, color);
|
|
gui.fill(x + 1, y + 1, x + width - 1, y + height - 1, color);
|
|
}
|
|
|
|
private void drawRoundedRect(GuiGraphics gui, int x, int y, int width, int height, int topColor, int bottomColor) {
|
|
gui.fillGradient(x + 1, y, x + width - 1, y + height, topColor, bottomColor);
|
|
gui.fillGradient(x, y + 1, x + width, y + height - 1, topColor, bottomColor);
|
|
}
|
|
|
|
private static boolean isMouseOver(double mouseX, double mouseY, BarPosition pos) {
|
|
return mouseX >= pos.x
|
|
&& mouseX <= pos.x + pos.width
|
|
&& mouseY >= pos.y
|
|
&& mouseY <= pos.y + pos.height;
|
|
}
|
|
|
|
private static class BarPosition {
|
|
private final int x;
|
|
private final int y;
|
|
private final int width;
|
|
private final int height;
|
|
|
|
private BarPosition(int x, int y, int width, int height) {
|
|
this.x = x;
|
|
this.y = y;
|
|
this.width = width;
|
|
this.height = height;
|
|
}
|
|
}
|
|
|
|
private static class IntSlider extends AbstractSliderButton {
|
|
private final int min;
|
|
private final int max;
|
|
private final String translationKey;
|
|
private final IntConsumer onChange;
|
|
|
|
private IntSlider(
|
|
int x,
|
|
int y,
|
|
int width,
|
|
int height,
|
|
String translationKey,
|
|
int min,
|
|
int max,
|
|
int value,
|
|
IntConsumer onChange
|
|
) {
|
|
super(x, y, width, height, Component.translatable(translationKey, value), toSliderValue(value, min, max));
|
|
this.min = min;
|
|
this.max = max;
|
|
this.translationKey = translationKey;
|
|
this.onChange = onChange;
|
|
updateMessage();
|
|
}
|
|
|
|
@Override
|
|
protected void updateMessage() {
|
|
setMessage(Component.translatable(translationKey, getIntValue()));
|
|
}
|
|
|
|
@Override
|
|
protected void applyValue() {
|
|
onChange.accept(getIntValue());
|
|
}
|
|
|
|
private int getIntValue() {
|
|
double valueRange = max - min;
|
|
return (int) Math.round(min + (valueRange * this.value));
|
|
}
|
|
|
|
private void setIntValue(int value) {
|
|
this.value = toSliderValue(value, min, max);
|
|
updateMessage();
|
|
}
|
|
|
|
private static double toSliderValue(int value, int min, int max) {
|
|
if (max == min) {
|
|
return 0.0;
|
|
}
|
|
return (double) (value - min) / (double) (max - min);
|
|
}
|
|
}
|
|
}
|