Added Quests and Real Settings (yay)
This commit is contained in:
@@ -18,6 +18,9 @@ public class Config {
|
||||
public int fpsY = 1;
|
||||
public String lastModule = "FPS";
|
||||
|
||||
public int keyX = 1;
|
||||
public int keyY = 1;
|
||||
|
||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||
private static final Path PATH = FabricLoader.getInstance()
|
||||
.getConfigDir()
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
package de.fullrisk.citrusDev.UI;
|
||||
|
||||
import io.wispforest.owo.ui.component.LabelComponent;
|
||||
import io.wispforest.owo.ui.component.UIComponents;
|
||||
import io.wispforest.owo.ui.container.FlowLayout;
|
||||
import io.wispforest.owo.ui.container.UIContainers;
|
||||
import io.wispforest.owo.ui.core.*;
|
||||
import io.wispforest.owo.ui.hud.Hud;
|
||||
import net.minecraft.client.KeyMapping;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import de.fullrisk.citrusDev.Config;
|
||||
|
||||
public class Module_KeyStrokes {
|
||||
|
||||
private static FlowLayout keyContainer;
|
||||
private static FlowLayout topRow;
|
||||
private static FlowLayout bottomRow;
|
||||
|
||||
private static FlowLayout wBox, aBox, sBox, dBox;
|
||||
private static LabelComponent wLabel, aLabel, sLabel, dLabel;
|
||||
|
||||
static boolean toggle = true;
|
||||
private static boolean shown = false;
|
||||
public static boolean isEnabled() {
|
||||
return toggle;
|
||||
}
|
||||
|
||||
public static void setEnabled(boolean value) {
|
||||
toggle = value;
|
||||
}
|
||||
|
||||
private static final Config CONFIG = Config.get();
|
||||
|
||||
private static final Surface GLASS_PANEL = Surface.blur(5f, 15f)
|
||||
.and(Surface.flat(0x40FFFFFF));
|
||||
|
||||
private static final int KEY_SIZE = 16;
|
||||
private static final int PRESSED_COLOR = 0xFF64de4b;
|
||||
private static final int IDLE_COLOR = 0x40FFFFFF;
|
||||
|
||||
public static void setPosition(int x, int y) {
|
||||
if (keyContainer != null) {
|
||||
keyContainer.positioning(Positioning.relative(x, y));
|
||||
}
|
||||
CONFIG.keyX = x;
|
||||
CONFIG.keyY = y;
|
||||
CONFIG.save();
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
Hud.add(Identifier.fromNamespaceAndPath("citrus-dev", "keystrokes_display"), () -> {
|
||||
if (keyContainer == null) {
|
||||
wLabel = UIComponents.label(Component.literal("W"));
|
||||
aLabel = UIComponents.label(Component.literal("A"));
|
||||
sLabel = UIComponents.label(Component.literal("S"));
|
||||
dLabel = UIComponents.label(Component.literal("D"));
|
||||
|
||||
wBox = makeKeyBox(wLabel);
|
||||
aBox = makeKeyBox(aLabel);
|
||||
sBox = makeKeyBox(sLabel);
|
||||
dBox = makeKeyBox(dLabel);
|
||||
|
||||
topRow = UIContainers.horizontalFlow(Sizing.content(), Sizing.content());
|
||||
topRow.gap(2);
|
||||
topRow.horizontalAlignment(HorizontalAlignment.CENTER);
|
||||
topRow.child(UIContainers.horizontalFlow(Sizing.fixed(KEY_SIZE), Sizing.fixed(KEY_SIZE))); // spacer
|
||||
topRow.child(wBox);
|
||||
topRow.child(UIContainers.horizontalFlow(Sizing.fixed(KEY_SIZE), Sizing.fixed(KEY_SIZE))); // spacer
|
||||
|
||||
bottomRow = UIContainers.horizontalFlow(Sizing.content(), Sizing.content());
|
||||
bottomRow.gap(2);
|
||||
bottomRow.horizontalAlignment(HorizontalAlignment.CENTER);
|
||||
bottomRow.child(aBox);
|
||||
bottomRow.child(sBox);
|
||||
bottomRow.child(dBox);
|
||||
|
||||
keyContainer = UIContainers.verticalFlow(Sizing.content(), Sizing.content());
|
||||
keyContainer.gap(2);
|
||||
keyContainer.verticalAlignment(VerticalAlignment.CENTER);
|
||||
keyContainer.horizontalAlignment(HorizontalAlignment.CENTER);
|
||||
keyContainer.padding(Insets.of(0));
|
||||
|
||||
keyContainer.positioning(Positioning.relative(CONFIG.keyX, CONFIG.keyY));
|
||||
}
|
||||
return keyContainer;
|
||||
});
|
||||
}
|
||||
|
||||
private static FlowLayout makeKeyBox(LabelComponent label) {
|
||||
FlowLayout box = UIContainers.verticalFlow(Sizing.fixed(KEY_SIZE), Sizing.fixed(KEY_SIZE));
|
||||
box.horizontalAlignment(HorizontalAlignment.CENTER);
|
||||
box.verticalAlignment(VerticalAlignment.CENTER);
|
||||
box.surface(Surface.flat(IDLE_COLOR));
|
||||
box.child(label);
|
||||
return box;
|
||||
}
|
||||
|
||||
public static void tick() {
|
||||
if (keyContainer == null) return;
|
||||
|
||||
if (toggle && !shown) {
|
||||
keyContainer.clearChildren(); // <-- safety net against duplicate adds
|
||||
keyContainer.surface(GLASS_PANEL);
|
||||
keyContainer.padding(Insets.of(Config.get().fpsP));
|
||||
keyContainer.child(topRow);
|
||||
keyContainer.child(bottomRow);
|
||||
shown = true;
|
||||
} else if (!toggle && shown) {
|
||||
keyContainer.clearChildren();
|
||||
keyContainer.surface(Surface.flat(0));
|
||||
keyContainer.padding(Insets.of(0));
|
||||
shown = false;
|
||||
}
|
||||
|
||||
if (!toggle) return;
|
||||
|
||||
Minecraft client = Minecraft.getInstance();
|
||||
KeyMapping up = client.options.keyUp;
|
||||
KeyMapping left = client.options.keyLeft;
|
||||
KeyMapping down = client.options.keyDown;
|
||||
KeyMapping right = client.options.keyRight;
|
||||
|
||||
wBox.surface(Surface.flat(up.isDown() ? PRESSED_COLOR : IDLE_COLOR));
|
||||
aBox.surface(Surface.flat(left.isDown() ? PRESSED_COLOR : IDLE_COLOR));
|
||||
sBox.surface(Surface.flat(down.isDown() ? PRESSED_COLOR : IDLE_COLOR));
|
||||
dBox.surface(Surface.flat(right.isDown() ? PRESSED_COLOR : IDLE_COLOR));
|
||||
}
|
||||
}
|
||||
@@ -56,6 +56,7 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
|
||||
private FlowLayout content;
|
||||
private final String initialModule;
|
||||
|
||||
|
||||
public MyScreen() {
|
||||
this(null);
|
||||
}
|
||||
@@ -130,8 +131,8 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
|
||||
|
||||
rootComponent.child(panel);
|
||||
|
||||
if ("FPS".equals(initialModule)) {
|
||||
openModuleSettings("FPS", fpsModuleSettings());
|
||||
if (initialModule != null) {
|
||||
openModuleByKey(initialModule);
|
||||
} else {
|
||||
buildGeneralPanel(content);
|
||||
}
|
||||
@@ -249,72 +250,51 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
|
||||
}
|
||||
|
||||
private void buildGeneralPanel(FlowLayout content) {
|
||||
FlowLayout iconButton = UIContainers.horizontalFlow(Sizing.content(), Sizing.content());
|
||||
iconButton.gap(8);
|
||||
iconButton.verticalAlignment(VerticalAlignment.TOP);
|
||||
iconButton.horizontalAlignment(HorizontalAlignment.CENTER);
|
||||
iconButton.padding(Insets.of(6));
|
||||
iconButton.horizontalSizing(Sizing.fixed(0));
|
||||
iconButton.verticalSizing(Sizing.fixed(0));
|
||||
iconButton.surface(toggle ? GLASS_PANEL : DISABLED);
|
||||
iconButton.child(UIComponents.texture(
|
||||
FlowLayout fpsRow = ModuleRow.build(
|
||||
GLASS_PANEL, DISABLED, FLAT,
|
||||
Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/block_culling_file.png"),
|
||||
0, 0, 18, 12, 18, 12
|
||||
)).horizontalAlignment(HorizontalAlignment.LEFT)
|
||||
.verticalAlignment(VerticalAlignment.CENTER);
|
||||
|
||||
FlowLayout textStack = UIContainers.verticalFlow(Sizing.content(), Sizing.content());
|
||||
textStack.gap(2);
|
||||
textStack.horizontalAlignment(HorizontalAlignment.LEFT);
|
||||
textStack.verticalAlignment(VerticalAlignment.CENTER);
|
||||
|
||||
var fpsLabel = UIComponents.label(
|
||||
Component.literal("FPS")
|
||||
.withStyle(style -> style.withFont(new FontDescription.Resource(MC_FIVE)))
|
||||
).color(Color.ofRgb(toggle ? 0xffffff : 0x797b86));
|
||||
|
||||
textStack.child(fpsLabel);
|
||||
|
||||
textStack.child(UIComponents.label(
|
||||
Component.literal("Displays your FPS"))
|
||||
.color(Color.ofRgb(0xa3a3ac))
|
||||
.maxWidth(130)
|
||||
);
|
||||
|
||||
iconButton.child(textStack);
|
||||
iconButton.child(UIComponents.spacer());
|
||||
|
||||
FlowLayout settingsButton = SettingsControls.makeSmallButton(
|
||||
FLAT,
|
||||
18, 12,
|
||||
MC_FIVE,
|
||||
"FPS",
|
||||
"Displays your FPS",
|
||||
new ModuleRow.ToggleState() {
|
||||
public boolean get() { return toggle; }
|
||||
public void set(boolean value) { toggle = value; }
|
||||
},
|
||||
Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/settings.png"),
|
||||
() -> {
|
||||
Config.get().lastModule = "FPS";
|
||||
Config.get().save();
|
||||
|
||||
openModuleSettings("FPS", fpsModuleSettings());
|
||||
}
|
||||
},
|
||||
"Module Enabled", "FPS counter is now active",
|
||||
"Module Disabled", "FPS counter is now inactive"
|
||||
);
|
||||
iconButton.child(settingsButton);
|
||||
|
||||
iconButton.mouseEnter().subscribe(() -> iconButton.surface(toggle ? GLASS_PANEL : DISABLED));
|
||||
iconButton.mouseLeave().subscribe(() -> iconButton.surface(toggle ? GLASS_PANEL : DISABLED));
|
||||
|
||||
iconButton.mouseDown().subscribe((click, doubled) -> {
|
||||
toggle = !toggle;
|
||||
fpsLabel.color(Color.ofRgb(toggle ? 0xffffff : 0x797b86));
|
||||
iconButton.surface(toggle ? GLASS_PANEL : DISABLED);
|
||||
CitrusToast.show("Module Enabled", "FPS counter is now active");
|
||||
|
||||
Minecraft.getInstance().getSoundManager().play(
|
||||
SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK.value(), 2.0F, 2)
|
||||
FlowLayout keyStrokesRow = ModuleRow.build(
|
||||
GLASS_PANEL, DISABLED, FLAT,
|
||||
Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/block_culling_file.png"),
|
||||
18, 12,
|
||||
MC_FIVE,
|
||||
"Keystrokes",
|
||||
"Current Key Presses",
|
||||
new ModuleRow.ToggleState() {
|
||||
public boolean get() { return Module_KeyStrokes.isEnabled(); }
|
||||
public void set(boolean value) { Module_KeyStrokes.setEnabled(value); }
|
||||
},
|
||||
Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/settings.png"),
|
||||
() -> {
|
||||
Config.get().lastModule = "Key";
|
||||
Config.get().save();
|
||||
openModuleSettings("Key", keyStrokesSettings());
|
||||
},
|
||||
"Module Enabled", "Keystrokes is now active",
|
||||
"Module Disabled", "KeyStrokes is now inactive"
|
||||
);
|
||||
return true;
|
||||
});
|
||||
content.child(keyStrokesRow);
|
||||
content.child(fpsRow);
|
||||
|
||||
iconButton.horizontalSizing().animate(150, Easing.CUBIC, Sizing.fixed(200)).forwards();
|
||||
iconButton.verticalSizing().animate(150, Easing.CUBIC, Sizing.fixed(35)).forwards();
|
||||
|
||||
content.child(iconButton);
|
||||
}
|
||||
|
||||
|
||||
@@ -366,6 +346,14 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
|
||||
content.child(scrollArea);
|
||||
}
|
||||
|
||||
private void openModuleByKey(String key) {
|
||||
switch (key) {
|
||||
case "FPS" -> openModuleSettings("FPS", fpsModuleSettings());
|
||||
case "Key" -> openModuleSettings("Keystrokes", keyStrokesSettings());
|
||||
default -> buildGeneralPanel(content);
|
||||
}
|
||||
}
|
||||
|
||||
private FlowLayout makeSettingRow(SettingRow setting) {
|
||||
FlowLayout row = UIContainers.horizontalFlow(Sizing.fixed(CONTENT_WIDTH - 8), Sizing.fixed(16));
|
||||
row.verticalAlignment(VerticalAlignment.CENTER);
|
||||
@@ -398,12 +386,48 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
|
||||
value -> Module_FPS.fpsContainer.gap((int) value)
|
||||
);
|
||||
|
||||
int currentIndex = positionIndex(Config.get().fpsX, Config.get().fpsY);
|
||||
|
||||
return List.of(
|
||||
new SettingRow("Position", SettingsControls.makeCyclingButton(GLASS_PANEL, positionStates)),
|
||||
new SettingRow("Position", SettingsControls.makeCyclingButton(GLASS_PANEL, positionStates, currentIndex)),
|
||||
new SettingRow("Size", sizeSlider)
|
||||
);
|
||||
}
|
||||
|
||||
private List<SettingRow> keyStrokesSettings() {
|
||||
List<SettingsControls.ButtonState> positionStates = List.of(
|
||||
new SettingsControls.ButtonState("L-TOP", () -> Module_KeyStrokes.setPosition(1, 1)),
|
||||
new SettingsControls.ButtonState("R-TOP", () -> Module_KeyStrokes.setPosition(99, 1)),
|
||||
new SettingsControls.ButtonState("R-BOTTOM", () -> Module_KeyStrokes.setPosition(99, 99)),
|
||||
new SettingsControls.ButtonState("L-BOTTOM", () -> Module_KeyStrokes.setPosition(1, 99))
|
||||
);
|
||||
|
||||
FlowLayout sizeSlider = SettingsControls.makeSlider(
|
||||
FLAT,
|
||||
80,
|
||||
0.0, 20.0,
|
||||
4.0,
|
||||
value -> (int) value + "px",
|
||||
value -> {} // fixed: was Module_FPS.fpsContainer.gap(...)
|
||||
);
|
||||
|
||||
int currentIndex = positionIndex(Config.get().keyX, Config.get().keyY);
|
||||
|
||||
return List.of(
|
||||
new SettingRow("Position", SettingsControls.makeCyclingButton(GLASS_PANEL, positionStates, currentIndex)),
|
||||
new SettingRow("Size", sizeSlider)
|
||||
);
|
||||
}
|
||||
|
||||
private int positionIndex(int x, int y) {
|
||||
boolean right = x > 50;
|
||||
boolean bottom = y > 50;
|
||||
if (!right && !bottom) return 0; // L-TOP
|
||||
if (right && !bottom) return 1; // R-TOP
|
||||
if (right && bottom) return 2; // R-BOTTOM
|
||||
return 3; // L-BOTTOM
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPauseScreen() {
|
||||
return false;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package de.fullrisk.citrusDev.UI;
|
||||
|
||||
import io.wispforest.owo.ui.component.LabelComponent;
|
||||
import io.wispforest.owo.ui.component.UIComponents;
|
||||
import io.wispforest.owo.ui.container.FlowLayout;
|
||||
import io.wispforest.owo.ui.container.UIContainers;
|
||||
@@ -7,12 +8,15 @@ import io.wispforest.owo.ui.core.*;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.FontDescription;
|
||||
import de.fullrisk.citrusDev.client.PlaytimeTracker;
|
||||
import de.fullrisk.citrusDev.UIHelper.CitrusToast;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class QuestsPanel {
|
||||
|
||||
private static final int ACCENT = 0xbaff86;
|
||||
private static final int ACCENT = 0x64de4b;
|
||||
|
||||
private record QuestData(String title, String description, int requiredPlaytime) {
|
||||
boolean isUnlocked() {
|
||||
@@ -20,7 +24,50 @@ public class QuestsPanel {
|
||||
}
|
||||
}
|
||||
|
||||
public static void build(FlowLayout content, int contentWidth, int contentHeight) {
|
||||
public static class Handle {
|
||||
private final LabelComponent playtimeLabel;
|
||||
private final LabelComponent percentLabel;
|
||||
private final FlowLayout barFill;
|
||||
private final int barWidth;
|
||||
private final List<QuestData> quests;
|
||||
private final Set<String> notifiedTitles = new HashSet<>();
|
||||
|
||||
private Handle(LabelComponent playtimeLabel, LabelComponent percentLabel, FlowLayout barFill, int barWidth, List<QuestData> quests) {
|
||||
this.playtimeLabel = playtimeLabel;
|
||||
this.percentLabel = percentLabel;
|
||||
this.barFill = barFill;
|
||||
this.barWidth = barWidth;
|
||||
this.quests = quests;
|
||||
|
||||
// seed with whatever's already unlocked on open, so we don't spam
|
||||
// toasts for quests the player unlocked before opening this screen
|
||||
for (QuestData quest : quests) {
|
||||
if (quest.isUnlocked()) {
|
||||
notifiedTitles.add(quest.title());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
int playtime = PlaytimeTracker.getCurrentPlaytimeSeconds();
|
||||
int maxPlaytime = 360;
|
||||
int progress = Math.min(playtime * 100 / maxPlaytime, 100);
|
||||
|
||||
playtimeLabel.text(Component.literal(formatPlaytime(playtime)));
|
||||
percentLabel.text(Component.literal(progress + "%"));
|
||||
|
||||
int fillWidth = Math.max(barWidth * progress / 100, progress > 0 ? 2 : 0);
|
||||
barFill.horizontalSizing(Sizing.fixed(fillWidth));
|
||||
|
||||
for (QuestData quest : quests) {
|
||||
if (quest.isUnlocked() && notifiedTitles.add(quest.title())) {
|
||||
CitrusToast.show("Quest Unlocked", quest.title());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Handle build(FlowLayout content, int contentWidth, int contentHeight) {
|
||||
List<QuestData> quests = quests();
|
||||
int playtime = PlaytimeTracker.getCurrentPlaytimeSeconds();
|
||||
int maxPlaytime = 360;
|
||||
@@ -28,7 +75,6 @@ public class QuestsPanel {
|
||||
int barWidth = contentWidth - 8;
|
||||
long unlockedCount = quests.stream().filter(QuestData::isUnlocked).count();
|
||||
|
||||
// --- status row: playtime + percentage ---
|
||||
FlowLayout statusBar = UIContainers.horizontalFlow(Sizing.fixed(barWidth), Sizing.fixed(20));
|
||||
statusBar.gap(4);
|
||||
statusBar.padding(Insets.of(4));
|
||||
@@ -36,15 +82,17 @@ public class QuestsPanel {
|
||||
statusBar.horizontalAlignment(HorizontalAlignment.LEFT);
|
||||
statusBar.surface(MyScreen.GLASS_PANEL);
|
||||
|
||||
statusBar.child(UIComponents.label(Component.literal("Playtime: " + formatPlaytime(playtime)))
|
||||
.color(Color.ofRgb(0xFFFFFF)));
|
||||
LabelComponent playtimeLabel = UIComponents.label(Component.literal(formatPlaytime(playtime)));
|
||||
playtimeLabel.color(Color.ofRgb(0xFFFFFF));
|
||||
statusBar.child(playtimeLabel);
|
||||
statusBar.child(UIComponents.spacer());
|
||||
statusBar.child(UIComponents.label(Component.literal(progress + "%"))
|
||||
.color(Color.ofRgb(ACCENT)));
|
||||
|
||||
LabelComponent percentLabel = UIComponents.label(Component.literal(progress + "%"));
|
||||
percentLabel.color(Color.ofRgb(ACCENT));
|
||||
statusBar.child(percentLabel);
|
||||
|
||||
content.child(statusBar);
|
||||
|
||||
// --- progress bar ---
|
||||
FlowLayout barBg = UIContainers.horizontalFlow(Sizing.fixed(barWidth), Sizing.fixed(6));
|
||||
barBg.surface(Surface.flat(0x30FFFFFF).and(Surface.outline(0x30FFFFFF)));
|
||||
barBg.horizontalAlignment(HorizontalAlignment.LEFT);
|
||||
@@ -58,7 +106,6 @@ public class QuestsPanel {
|
||||
|
||||
content.child(barBg);
|
||||
|
||||
// --- unlocked count summary ---
|
||||
FlowLayout summaryRow = UIContainers.horizontalFlow(Sizing.fixed(barWidth), Sizing.content());
|
||||
summaryRow.padding(Insets.of(3, 0, 2, 2));
|
||||
|
||||
@@ -69,7 +116,6 @@ public class QuestsPanel {
|
||||
|
||||
content.child(summaryRow);
|
||||
|
||||
// --- quest list (scrollable) ---
|
||||
FlowLayout questList = UIContainers.verticalFlow(Sizing.fixed(barWidth), Sizing.content());
|
||||
questList.gap(3);
|
||||
questList.padding(Insets.of(2, 0, 2, 2));
|
||||
@@ -78,7 +124,7 @@ public class QuestsPanel {
|
||||
questList.child(buildQuestEntry(quest, contentWidth));
|
||||
}
|
||||
|
||||
int usedHeight = 20 + 6 + 18 + 6; // statusBar + barBg + summaryRow + gaps
|
||||
int usedHeight = 20 + 6 + 18 + 6;
|
||||
int scrollHeight = contentHeight - usedHeight;
|
||||
|
||||
var scrollArea = UIContainers.verticalScroll(
|
||||
@@ -87,6 +133,8 @@ public class QuestsPanel {
|
||||
questList
|
||||
);
|
||||
content.child(scrollArea);
|
||||
|
||||
return new Handle(playtimeLabel, percentLabel, barFill, barWidth, quests);
|
||||
}
|
||||
|
||||
private static String formatPlaytime(int seconds) {
|
||||
@@ -130,7 +178,7 @@ public class QuestsPanel {
|
||||
: Surface.flat(0x40FFFFFF));
|
||||
iconBox.horizontalAlignment(HorizontalAlignment.CENTER);
|
||||
iconBox.verticalAlignment(VerticalAlignment.CENTER);
|
||||
iconBox.child(UIComponents.label(Component.literal(unlocked ? "✓" : ""))
|
||||
iconBox.child(UIComponents.label(Component.literal(""))
|
||||
.color(Color.ofRgb(0x1c1c1c)));
|
||||
row.child(iconBox);
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
package de.fullrisk.citrusDev.UIHelper;
|
||||
|
||||
import io.wispforest.owo.ui.component.UIComponents;
|
||||
import io.wispforest.owo.ui.container.FlowLayout;
|
||||
import io.wispforest.owo.ui.container.UIContainers;
|
||||
import io.wispforest.owo.ui.core.*;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.FontDescription;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
|
||||
public class ModuleRow {
|
||||
|
||||
/** Bridge to whatever boolean field actually holds the module's on/off state. */
|
||||
public interface ToggleState {
|
||||
boolean get();
|
||||
void set(boolean value);
|
||||
}
|
||||
|
||||
public static FlowLayout build(
|
||||
Surface enabledSurface,
|
||||
Surface disabledSurface,
|
||||
Surface flatSurface,
|
||||
Identifier icon,
|
||||
int iconWidth,
|
||||
int iconHeight,
|
||||
Identifier titleFont,
|
||||
String title,
|
||||
String description,
|
||||
ToggleState state,
|
||||
Identifier settingsIcon,
|
||||
Runnable onSettingsClick,
|
||||
String enabledToastTitle,
|
||||
String enabledToastMessage,
|
||||
String disabledToastTitle,
|
||||
String disabledToastMessage
|
||||
) {
|
||||
FlowLayout row = UIContainers.horizontalFlow(Sizing.content(), Sizing.content());
|
||||
row.gap(8);
|
||||
row.verticalAlignment(VerticalAlignment.TOP);
|
||||
row.horizontalAlignment(HorizontalAlignment.CENTER);
|
||||
row.padding(Insets.of(6));
|
||||
row.horizontalSizing(Sizing.fixed(0));
|
||||
row.verticalSizing(Sizing.fixed(0));
|
||||
row.surface(state.get() ? enabledSurface : disabledSurface);
|
||||
|
||||
row.child(UIComponents.texture(icon, 0, 0, iconWidth, iconHeight, iconWidth, iconHeight))
|
||||
.horizontalAlignment(HorizontalAlignment.LEFT)
|
||||
.verticalAlignment(VerticalAlignment.CENTER);
|
||||
|
||||
FlowLayout textStack = UIContainers.verticalFlow(Sizing.content(), Sizing.content());
|
||||
textStack.gap(2);
|
||||
textStack.horizontalAlignment(HorizontalAlignment.LEFT);
|
||||
textStack.verticalAlignment(VerticalAlignment.CENTER);
|
||||
|
||||
var titleLabel = UIComponents.label(
|
||||
Component.literal(title)
|
||||
.withStyle(style -> style.withFont(new FontDescription.Resource(titleFont)))
|
||||
);
|
||||
titleLabel.color(Color.ofRgb(state.get() ? 0xffffff : 0x797b86));
|
||||
textStack.child(titleLabel);
|
||||
|
||||
textStack.child(UIComponents.label(Component.literal(description))
|
||||
.color(Color.ofRgb(0xa3a3ac))
|
||||
.maxWidth(130));
|
||||
|
||||
row.child(textStack);
|
||||
row.child(UIComponents.spacer());
|
||||
|
||||
FlowLayout settingsButton = SettingsControls.makeSmallButton(flatSurface, settingsIcon, onSettingsClick);
|
||||
row.child(settingsButton);
|
||||
|
||||
row.mouseEnter().subscribe(() -> row.surface(state.get() ? enabledSurface : disabledSurface));
|
||||
row.mouseLeave().subscribe(() -> row.surface(state.get() ? enabledSurface : disabledSurface));
|
||||
|
||||
row.mouseDown().subscribe((click, doubled) -> {
|
||||
boolean newState = !state.get();
|
||||
state.set(newState);
|
||||
|
||||
titleLabel.color(Color.ofRgb(newState ? 0xffffff : 0x797b86));
|
||||
row.surface(newState ? enabledSurface : disabledSurface);
|
||||
|
||||
if (newState) {
|
||||
CitrusToast.show(enabledToastTitle, enabledToastMessage);
|
||||
} else {
|
||||
CitrusToast.show(disabledToastTitle, disabledToastMessage);
|
||||
}
|
||||
|
||||
Minecraft.getInstance().getSoundManager().play(
|
||||
SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK.value(), 2.0F, 2)
|
||||
);
|
||||
return true;
|
||||
});
|
||||
|
||||
row.horizontalSizing().animate(150, Easing.CUBIC, Sizing.fixed(200)).forwards();
|
||||
row.verticalSizing().animate(150, Easing.CUBIC, Sizing.fixed(35)).forwards();
|
||||
|
||||
return row;
|
||||
}
|
||||
}
|
||||
@@ -73,15 +73,15 @@ public class SettingsControls {
|
||||
return button;
|
||||
}
|
||||
|
||||
public static FlowLayout makeCyclingButton(Surface baseSurface, List<ButtonState> states) {
|
||||
int[] currentIndex = {0};
|
||||
public static FlowLayout makeCyclingButton(Surface baseSurface, List<ButtonState> states, int initialIndex) {
|
||||
int[] currentIndex = { initialIndex };
|
||||
|
||||
FlowLayout button = UIContainers.verticalFlow(Sizing.fixed(50), Sizing.fixed(16));
|
||||
button.verticalAlignment(VerticalAlignment.CENTER);
|
||||
button.horizontalAlignment(HorizontalAlignment.CENTER);
|
||||
button.surface(baseSurface);
|
||||
|
||||
var label = UIComponents.label(Component.literal(states.get(0).label()))
|
||||
var label = UIComponents.label(Component.literal(states.get(initialIndex).label()))
|
||||
.color(Color.ofRgb(0xFFFFFF));
|
||||
button.child(label);
|
||||
|
||||
@@ -104,6 +104,11 @@ public class SettingsControls {
|
||||
return button;
|
||||
}
|
||||
|
||||
// keep the old call sites compiling; defaults to index 0
|
||||
public static FlowLayout makeCyclingButton(Surface baseSurface, List<ButtonState> states) {
|
||||
return makeCyclingButton(baseSurface, states, 0);
|
||||
}
|
||||
|
||||
public static FlowLayout makeSlider(Surface baseSurface, int width, double min, double max, double initial,
|
||||
DoubleFunction<String> labelFormatter, DoubleConsumer onChange) {
|
||||
int labelWidth = 34;
|
||||
|
||||
@@ -3,6 +3,7 @@ package de.fullrisk.citrusDev.client;
|
||||
|
||||
import de.fullrisk.citrusDev.Config;
|
||||
import de.fullrisk.citrusDev.UI.Module_FPS;
|
||||
import de.fullrisk.citrusDev.UI.Module_KeyStrokes;
|
||||
import de.fullrisk.citrusDev.UI.MyScreen;
|
||||
import de.fullrisk.citrusDev.UI.OverviewScreen;
|
||||
import io.wispforest.owo.ui.hud.Hud;
|
||||
@@ -21,6 +22,7 @@ public class CitrusDevClient implements ClientModInitializer {
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
Module_FPS.register();
|
||||
Module_KeyStrokes.register();
|
||||
|
||||
KeyMapping.Category category = KeyMapping.Category.register(
|
||||
Identifier.fromNamespaceAndPath("citrus-dev", "general"));
|
||||
@@ -41,7 +43,8 @@ public class CitrusDevClient implements ClientModInitializer {
|
||||
PlaytimeTracker.tick();
|
||||
}
|
||||
|
||||
Module_FPS.tick(); // update every tick, unconditionally
|
||||
Module_FPS.tick();
|
||||
Module_KeyStrokes.tick();
|
||||
while (openScreenKey.consumeClick()) {
|
||||
client.setScreen(new MyScreen(null)); // always general tab
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user