Added Module Settings and removed test screen

This commit is contained in:
2026-07-08 15:34:04 +02:00
parent 1bf7636470
commit 596612880b
16 changed files with 440 additions and 165 deletions
@@ -9,17 +9,30 @@ import io.wispforest.owo.ui.hud.Hud;
import net.minecraft.client.Minecraft;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.Identifier;
import de.fullrisk.citrusDev.Config;
public class Module_FPS {
private static LabelComponent fpsLabel;
private static FlowLayout fpsContainer;
public static FlowLayout fpsContainer;
static boolean toggle = true;
private static boolean shown = false;
private static final Config CONFIG = Config.get();
private static final Surface GLASS_PANEL = Surface.blur(5f, 15f)
.and(Surface.flat(0x40FFFFFF));
public static void setPosition(int x, int y) {
if (fpsContainer != null) {
fpsContainer.positioning(Positioning.relative(x, y));
}
CONFIG.fpsX = x;
CONFIG.fpsY = y;
CONFIG.save();
}
public static void register() {
Hud.add(Identifier.fromNamespaceAndPath("citrus-dev", "fps_display"), () -> {
if (fpsContainer == null) {
@@ -29,8 +42,9 @@ public class Module_FPS {
fpsContainer.gap(4);
fpsContainer.verticalAlignment(VerticalAlignment.CENTER);
fpsContainer.horizontalAlignment(HorizontalAlignment.CENTER);
fpsContainer.positioning(Positioning.absolute(10, 10));
fpsContainer.padding(Insets.of(0));
fpsContainer.positioning(Positioning.relative(CONFIG.fpsX, CONFIG.fpsY));
}
return fpsContainer;
});
@@ -45,7 +59,6 @@ public class Module_FPS {
fpsContainer.child(fpsLabel);
shown = true;
} else if (!toggle && shown) {
// turning off: strip everything so it collapses to nothing
fpsContainer.clearChildren();
fpsContainer.surface(Surface.flat(0));
fpsContainer.padding(Insets.of(0));
@@ -1,5 +1,6 @@
package de.fullrisk.citrusDev.UI;
import de.fullrisk.citrusDev.Config;
import io.wispforest.owo.ui.base.BaseOwoScreen;
import io.wispforest.owo.ui.component.UIComponents;
import io.wispforest.owo.ui.container.FlowLayout;
@@ -17,6 +18,7 @@ import de.fullrisk.citrusDev.UIHelper.ScaleValue;
import java.util.List;
import static de.fullrisk.citrusDev.UI.Module_FPS.fpsContainer;
import static de.fullrisk.citrusDev.UI.Module_FPS.toggle;
public class MyScreen extends BaseOwoScreen<FlowLayout> {
@@ -44,11 +46,18 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
private static final int CONTENT_WIDTH = INNER_WIDTH - SIDEBAR_WIDTH - DIVIDER_SIZE;
private record TabDef(String label, Runnable onClick) {}
private record SettingRow(String label, FlowLayout control) {}
private FlowLayout content;
private final String initialModule;
public MyScreen() {
this(null);
}
public MyScreen(String initialModule) {
super(Component.literal("Citrus Dev"));
this.initialModule = initialModule;
Minecraft.getInstance().getSoundManager().play(
SimpleSoundInstance.forUI(SoundEvents.UI_TOAST_IN, 1.5F, 2)
);
@@ -96,7 +105,6 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
content.padding(Insets.of(4));
content.horizontalAlignment(HorizontalAlignment.CENTER);
content.verticalAlignment(VerticalAlignment.TOP);
buildGeneralPanel(content);
row.child(content);
panel.child(row);
@@ -116,6 +124,13 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
panel.child(version);
rootComponent.child(panel);
// Now that content is attached to the tree, decide what to show.
if ("FPS".equals(initialModule)) {
openModuleSettings("FPS", fpsModuleSettings());
} else {
buildGeneralPanel(content);
}
}
private void buildNavbar(FlowLayout navbar) {
@@ -131,14 +146,20 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
List<TabDef> tabs = List.of(
new TabDef("general", () -> {
content.clearChildren();
content.horizontalAlignment(HorizontalAlignment.CENTER);
content.verticalAlignment(VerticalAlignment.TOP);
buildGeneralPanel(content);
}),
new TabDef("modules", () -> {
new TabDef("quests", () -> {
content.clearChildren();
buildModulesPanel(content);
content.horizontalAlignment(HorizontalAlignment.CENTER);
content.verticalAlignment(VerticalAlignment.TOP);
buildQuestsPanel(content);
}),
new TabDef("settings", () -> {
content.clearChildren();
content.horizontalAlignment(HorizontalAlignment.CENTER);
content.verticalAlignment(VerticalAlignment.TOP);
buildSettingsPanel(content);
})
);
@@ -264,7 +285,10 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
FLAT,
Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/settings.png"),
() -> {
Minecraft.getInstance().setScreen(new MyScreen());
Config.get().lastModule = "FPS";
Config.get().save();
openModuleSettings("FPS", fpsModuleSettings());
}
);
iconButton.child(settingsButton);
@@ -289,36 +313,96 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
content.child(iconButton);
}
private void buildModulesPanel(FlowLayout content) {
content.child(UIComponents.label(Component.literal("Modules tab - coming soon")));
private void buildQuestsPanel(FlowLayout content) {
content.child(UIComponents.label(Component.literal("Quests - coming soon")));
}
private void buildSettingsPanel(FlowLayout content) {
content.child(UIComponents.label(Component.literal("Settings")));
content.child(makeCyclingButton());
}
/**
* Opens a per-module settings view inside the "content" container,
* replacing whatever was there before. A back arrow returns to General.
*/
private void openModuleSettings(String title, List<SettingRow> rows) {
content.clearChildren();
// re-assert alignment explicitly - clearChildren can reset it
content.horizontalAlignment(HorizontalAlignment.LEFT);
content.verticalAlignment(VerticalAlignment.TOP);
FlowLayout header = UIContainers.horizontalFlow(Sizing.fixed(CONTENT_WIDTH - 8), Sizing.content());
header.verticalAlignment(VerticalAlignment.CENTER);
header.horizontalAlignment(HorizontalAlignment.LEFT);
header.gap(6);
header.child(makeTextButton(FLAT, "<", () -> {
content.clearChildren();
content.horizontalAlignment(HorizontalAlignment.CENTER);
content.verticalAlignment(VerticalAlignment.TOP);
buildGeneralPanel(content);
}));
header.child(UIComponents.label(Component.literal(title)
.withStyle(style -> style.withFont(new FontDescription.Resource(MC_FIVE))))
.color(Color.ofRgb(0xCCCCCC)));
content.child(header);
for (SettingRow row : rows) {
content.child(makeSettingRow(row));
}
}
private FlowLayout makeSettingRow(SettingRow setting) {
FlowLayout row = UIContainers.horizontalFlow(Sizing.fixed(CONTENT_WIDTH - 8), Sizing.content());
row.verticalAlignment(VerticalAlignment.TOP);
row.horizontalAlignment(HorizontalAlignment.LEFT);
row.padding(Insets.of(2));
row.gap(6);
row.child(UIComponents.label(Component.literal(setting.label()))
.color(Color.ofRgb(0xa3a3ac)));
row.child(UIComponents.spacer());
row.child(setting.control());
return row;
}
private List<SettingRow> fpsModuleSettings() {
return List.of(
new SettingRow("Position", makeCyclingButton())
);
}
private record ButtonState(String label, Runnable onSelect) {}
private FlowLayout makeCyclingButton() { // muss ich noch fertig machen, bitte es geht mir nd gut, es ist 23:00
private FlowLayout makeCyclingButton() {
List<ButtonState> states = List.of(
new ButtonState("Off", () -> {
Module_FPS.setPosition(1, 1);
}),
new ButtonState("Low", () -> {
Module_FPS.setPosition(99, 1);
}),
new ButtonState("Medium", () -> {
Module_FPS.setPosition(99, 99);
}),
new ButtonState("High", () -> {
Module_FPS.setPosition(1, 99);
})
);
int[] currentIndex = {0};
FlowLayout button = UIContainers.verticalFlow(Sizing.fixed(60), Sizing.fixed(20));
FlowLayout button = UIContainers.verticalFlow(Sizing.fixed(50), Sizing.fixed(16));
button.verticalAlignment(VerticalAlignment.CENTER);
button.horizontalAlignment(HorizontalAlignment.CENTER);
button.surface(FLAT);
button.surface(GLASS_PANEL);
var label = UIComponents.label(Component.literal(states.get(0).label()))
.color(Color.ofRgb(0xFFFFFF));
@@ -337,7 +421,12 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
return true;
});
button.mouseEnter().subscribe(() -> {
label.color(Color.ofRgb(0xFFFFFF));
});
button.mouseLeave().subscribe(() -> {
label.color(Color.ofRgb(0xCCCCCC));
});
return button;
}
@@ -366,6 +455,30 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
return button;
}
private FlowLayout makeTextButton(Surface baseSurface, String text, Runnable onClick) {
FlowLayout button = UIContainers.verticalFlow(Sizing.content(), Sizing.content());
button.verticalAlignment(VerticalAlignment.CENTER);
button.horizontalAlignment(HorizontalAlignment.CENTER);
button.padding(Insets.of(2, 2, 4, 4));
button.surface(baseSurface);
button.child(UIComponents.label(Component.literal(text)).color(Color.ofRgb(0xFFFFFF)));
button.mouseEnter().subscribe(() -> button.surface(
Surface.blur(5f, 15f).and(Surface.flat(0x70FFFFFF)).and(Surface.outline(0xFFFFFFFF))
));
button.mouseLeave().subscribe(() -> button.surface(baseSurface));
button.mouseDown().subscribe((click, doubled) -> {
Minecraft.getInstance().getSoundManager().play(
SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK.value(), 2.0F, 2)
);
onClick.run();
return true;
});
return button;
}
@Override
public boolean isPauseScreen() {
return false;
@@ -1,152 +1,5 @@
package de.fullrisk.citrusDev.UI;
import io.wispforest.owo.ui.base.BaseOwoScreen;
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.HorizontalAlignment;
import io.wispforest.owo.ui.core.OwoUIAdapter;
import io.wispforest.owo.ui.core.VerticalAlignment;
import net.minecraft.network.chat.Component;
import io.wispforest.owo.ui.core.*;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
import net.minecraft.network.chat.FontDescription;
import net.minecraft.resources.Identifier;
import net.minecraft.sounds.SoundEvents;
import de.fullrisk.citrusDev.UIHelper.ScalableLabel;
import de.fullrisk.citrusDev.UIHelper.ScalableButton;
import de.fullrisk.citrusDev.UIHelper.ScaleValue;
public class OverviewScreen {
public class OverviewScreen extends BaseOwoScreen<FlowLayout> {
private static final Identifier MC_FIVE = Identifier.fromNamespaceAndPath("citrus-dev", "minecraft_five");
@Override
protected OwoUIAdapter<FlowLayout> createAdapter() {
return OwoUIAdapter.create(this, UIContainers::verticalFlow);
}
@Override
protected void build(FlowLayout rootComponent) {
rootComponent.gap(2);
rootComponent
.horizontalAlignment(HorizontalAlignment.CENTER)
.verticalAlignment(VerticalAlignment.CENTER);
Surface glassPanel = Surface.blur(5f, 15f)
.and(Surface.flat(0x40FFFFFF))
.and(Surface.outline(0xFFFFFFFF));
Surface Flat = Surface.blur(5f, 15f)
.and(Surface.flat(0x40FFFFFF));
FlowLayout iconButton = UIContainers.horizontalFlow(Sizing.content(), Sizing.content());
iconButton.gap(8);
iconButton.verticalAlignment(VerticalAlignment.CENTER);
iconButton.horizontalAlignment(HorizontalAlignment.CENTER);
iconButton.padding(Insets.of(6));
iconButton.horizontalSizing(Sizing.fixed(0));
iconButton.verticalSizing(Sizing.fixed(0));
iconButton.surface(glassPanel);
iconButton.child(UIComponents.texture(
Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/block_culling_file.png"),
0, 0, 18, 12, 18, 12
)).horizontalAlignment(HorizontalAlignment.LEFT);
FlowLayout textStack = UIContainers.verticalFlow(Sizing.content(), Sizing.content());
textStack.gap(2);
textStack.horizontalAlignment(HorizontalAlignment.LEFT);
textStack.verticalAlignment(VerticalAlignment.CENTER);
textStack.child(UIComponents.label(
Component.literal("FPS")
.withStyle(style -> style.withFont(new FontDescription.Resource(MC_FIVE))))
);
textStack.child(UIComponents.label(
Component.literal("Displays your FPS"))
.color(Color.ofRgb(0xAAAAAA))
.maxWidth(130)
);
iconButton.child(textStack);
// ich liebe spacer
iconButton.child(UIComponents.spacer());
FlowLayout settingsButton = makeSmallButton(
Flat,
Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/settings.png"),
() -> {
Minecraft.getInstance().setScreen(new MyScreen()); // whatever, nur zum testen rn
}
);
FlowLayout secondButton = makeSmallButton(
glassPanel,
Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/some_other_icon.png"),
() -> {
Minecraft.getInstance().setScreen(new MyScreen());
}
);
iconButton.child(settingsButton);
iconButton.mouseEnter().subscribe(() -> {
iconButton.surface(Surface.blur(5f, 15f)
.and(Surface.flat(0x40FFFFFF))
.and(Surface.outline(0xFFFFFFFF)));
});
iconButton.mouseLeave().subscribe(() -> {
iconButton.surface(Surface.blur(5f, 15f)
.and(Surface.flat(0x40FFFFFF)));
});
iconButton.mouseDown().subscribe((click, doubled) -> {
Module_FPS.toggle = !Module_FPS.toggle;
Minecraft.getInstance().getSoundManager().play(
SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK.value(), 2.0F, 2)
);
return true;
});
iconButton.horizontalSizing().animate(150, Easing.CUBIC, Sizing.fixed(220)).forwards();
iconButton.verticalSizing().animate(150, Easing.CUBIC, Sizing.fixed(40)).forwards();
rootComponent.child(iconButton);
}
// idk was ich hier gekocht hab, macht das leben leichter
private FlowLayout makeSmallButton(Surface baseSurface, Identifier texture, Runnable onClick) {
FlowLayout button = UIContainers.verticalFlow(Sizing.fixed(16), Sizing.fixed(16));
button.verticalAlignment(VerticalAlignment.CENTER);
button.horizontalAlignment(HorizontalAlignment.CENTER);
button.surface(baseSurface);
button.child(UIComponents.texture(texture, 0, 0, 12, 12, 12, 12))
.horizontalAlignment(HorizontalAlignment.CENTER)
.verticalAlignment(VerticalAlignment.CENTER);
button.mouseEnter().subscribe(() -> button.surface(
Surface.blur(5f, 15f).and(Surface.flat(0x70FFFFFF)).and(Surface.outline(0xFFFFFFFF))
));
button.mouseLeave().subscribe(() ->
button.surface(baseSurface));
button.mouseDown().subscribe((click, doubled) -> {
Minecraft.getInstance().getSoundManager().play(
SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK.value(), 2.0F, 2)
);
onClick.run(); // geht das so? Edit: ja
return true;
});
return button;
}
@Override
public boolean isPauseScreen() {
return false;
}
}