From f07ba798f41cfd4ec9a04f5f77ce0931b101a611 Mon Sep 17 00:00:00 2001 From: FullRisk Date: Tue, 14 Jul 2026 10:46:09 +0200 Subject: [PATCH] updated icons and added credits (secret) --- .../fullrisk/citrusDev/UI/CreditsScreen.java | 107 ++++++++++++++++++ .../java/de/fullrisk/citrusDev/UI/MainUI.java | 12 +- .../citrusDev/UIHelper/ModuleRows.java | 2 +- .../citrusDev/UIHelper/ModuleSettings.java | 3 +- .../citrusDev/UIHelper/SettingsControls.java | 31 +++-- .../citrusDev/mixin/SliderComponentMixin.java | 10 +- .../citrus-dev/textures/icons/keystrokes.png | Bin 16798 -> 190 bytes 7 files changed, 152 insertions(+), 13 deletions(-) create mode 100644 src/main/java/de/fullrisk/citrusDev/UI/CreditsScreen.java diff --git a/src/main/java/de/fullrisk/citrusDev/UI/CreditsScreen.java b/src/main/java/de/fullrisk/citrusDev/UI/CreditsScreen.java new file mode 100644 index 0000000..3dbfb1d --- /dev/null +++ b/src/main/java/de/fullrisk/citrusDev/UI/CreditsScreen.java @@ -0,0 +1,107 @@ +package de.fullrisk.citrusDev.UI; + +import de.fullrisk.citrusDev.UIHelper.SettingsControls; +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.*; +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.sounds.SoundEvents; + +import java.util.List; + +import static de.fullrisk.citrusDev.UI.MainUI.buildPanelSurface; +import static de.fullrisk.citrusDev.UI.MainUI.MC_FIVE; + +public class CreditsScreen extends BaseOwoScreen { + + public static Surface PANEL_SURFACE = buildPanelSurface(); + + private static final int PANEL_WIDTH = 180; + private static final int PANEL_HEIGHT = 120; + + private static final List CREDITS = List.of( + "citrus team - testing", + "owo-ui - framework", + "nrc - inspiration" + ); + + public CreditsScreen() { + super(Component.literal("Credits")); + Minecraft.getInstance().getSoundManager().play( + SimpleSoundInstance.forUI(SoundEvents.UI_TOAST_IN, 1.5F, 2) + ); + } + + @Override + protected OwoUIAdapter createAdapter() { + return OwoUIAdapter.create(this, UIContainers::verticalFlow); + } + + @Override + protected void build(FlowLayout rootComponent) { + rootComponent.horizontalAlignment(HorizontalAlignment.CENTER) + .verticalAlignment(VerticalAlignment.CENTER); + + FlowLayout panel = UIContainers.verticalFlow(Sizing.fixed(PANEL_WIDTH), Sizing.fixed(PANEL_HEIGHT)); + panel.gap(6); + panel.padding(Insets.of(8)); + panel.horizontalAlignment(HorizontalAlignment.CENTER); + panel.verticalAlignment(VerticalAlignment.TOP); + panel.surface(PANEL_SURFACE); + + var title = UIComponents.label(Component.literal("Credits") + .withStyle(s -> s.withFont(new FontDescription.Resource(MC_FIVE)))) + .color(Color.ofRgb(0xFFFFFF)) + .horizontalTextAlignment(HorizontalAlignment.CENTER); + panel.child(title); + + FlowLayout list = UIContainers.verticalFlow(Sizing.fixed(PANEL_WIDTH - 16), Sizing.content()); + list.gap(4); + list.horizontalAlignment(HorizontalAlignment.CENTER); + + for (String entry : CREDITS) { + var line = UIComponents.label(Component.literal(entry) + .withStyle(s -> s.withFont(new FontDescription.Resource(MC_FIVE)))) + .color(Color.ofRgb(0xB0B6C0)) + .horizontalTextAlignment(HorizontalAlignment.CENTER); + list.child(line); + } + panel.child(list); + + panel.child(UIComponents.spacer()); + + FlowLayout footer = UIContainers.horizontalFlow(Sizing.content(), Sizing.content()); + footer.verticalAlignment(VerticalAlignment.CENTER); + footer.horizontalAlignment(HorizontalAlignment.CENTER); + footer.gap(4); + + // eig hab ichs ja gemacht... egal mein name bleibt da + + var madeBy = UIComponents.label(Component.literal("made by fullrisk") + .withStyle(s -> s.withFont(new FontDescription.Resource(MC_FIVE)))) + .color(Color.ofRgb(0xB0B6C0)); + footer.child(madeBy); + + var heart = UIComponents.texture( + net.minecraft.resources.Identifier.fromNamespaceAndPath("minecraft", "textures/gui/sprites/hud/heart/full.png"), + 0, 0, 9, 9, 9, 9 + ); + footer.child(heart); + + panel.child(footer); + + panel.child(SettingsControls.makeTextButton(PANEL_SURFACE, "Back", () -> + Minecraft.getInstance().setScreen(new MainUI()) + )); + + rootComponent.child(panel); + } + + @Override + public boolean isPauseScreen() { return false; } +} \ No newline at end of file diff --git a/src/main/java/de/fullrisk/citrusDev/UI/MainUI.java b/src/main/java/de/fullrisk/citrusDev/UI/MainUI.java index 3def889..c926a33 100644 --- a/src/main/java/de/fullrisk/citrusDev/UI/MainUI.java +++ b/src/main/java/de/fullrisk/citrusDev/UI/MainUI.java @@ -26,7 +26,7 @@ public class MainUI extends BaseOwoScreen { public static Surface DISABLED = buildDisabledSurface(); public static Surface FLAT = buildFlatSurface(); - private static Surface buildPanelSurface() { + static Surface buildPanelSurface() { float blur = Config.get().panelBlur; int fill = Config.get().darkMode ? 0x601c1c1c : 0x40FFFFFF; if (blur <= 0f) return Surface.flat(fill).and(Surface.outline(0x64de4b)); @@ -60,6 +60,8 @@ public class MainUI extends BaseOwoScreen { private static int bright() { return 0xFFFFFF; } private static int tabText() { return 0xCCCCCC; } + //sowwwy wenn sich das wer anschaut, ik ist hässlich aber kann man nix machen + public static final int PANEL_WIDTH = 320; public static final int PANEL_HEIGHT = 190; public static final int INNER_WIDTH = PANEL_WIDTH - 4; @@ -128,6 +130,10 @@ public class MainUI extends BaseOwoScreen { var logo = UIComponents.texture(Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/citrus-logo.png"), 0, 0, 30, 30, 30, 30); logo.positioning(Positioning.absolute(4, (NAVBAR_HEIGHT - 30) / 2)); + logo.mouseDown().subscribe((click, doubled) -> { + Minecraft.getInstance().setScreen(new CreditsScreen()); + return true; + }); navbar.child(logo); for (TabDef tab : List.of( @@ -211,6 +217,8 @@ public class MainUI extends BaseOwoScreen { private static int sidebarBtnOutline() { return Config.get().darkMode ? 0xFF888888 : 0xFFFFFFFF; } private static int sidebarBtnHoverOutline() { return Config.get().darkMode ? 0xFFcccccc : 0xFFFFFFFF; } + // 3h für darkmode btw (ich hasse mein leben) + private FlowLayout buildSidebar() { FlowLayout sidebar = UIContainers.verticalFlow(Sizing.fixed(SIDEBAR_WIDTH), Sizing.fixed(ROW_HEIGHT)); sidebar.horizontalAlignment(HorizontalAlignment.CENTER); @@ -240,6 +248,8 @@ public class MainUI extends BaseOwoScreen { return sidebar; } + // sorry awa i schär mi nd dass i des wo anders hin dua + private ScalableButton makeSidebarButton(String symbol, int animateDelay) { var button = new ScalableButton(Component.literal(symbol), btn -> Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK.value(), 2.0F, 2)), diff --git a/src/main/java/de/fullrisk/citrusDev/UIHelper/ModuleRows.java b/src/main/java/de/fullrisk/citrusDev/UIHelper/ModuleRows.java index 85ddf7f..965e068 100644 --- a/src/main/java/de/fullrisk/citrusDev/UIHelper/ModuleRows.java +++ b/src/main/java/de/fullrisk/citrusDev/UIHelper/ModuleRows.java @@ -52,7 +52,7 @@ public class ModuleRows { "Module Disabled", "KeyStrokes is now inactive")), entry("FPS", ModuleRow.build( GLASS_PANEL, DISABLED, FLAT, - Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/fps.png"), 18, 18, MC_FIVE, + Identifier.fromNamespaceAndPath("minecraft", "textures/item/clock_00.png"), 20, 20, MC_FIVE, "FPS", "Displays your FPS", toggleState(Module_FPS::isEnabled, Module_FPS::setEnabled), SETTINGS_ICON, () -> { Config.get().lastModule = "FPS"; Config.get().save(); openSettingsByKey.accept("FPS"); }, diff --git a/src/main/java/de/fullrisk/citrusDev/UIHelper/ModuleSettings.java b/src/main/java/de/fullrisk/citrusDev/UIHelper/ModuleSettings.java index afa0981..2528010 100644 --- a/src/main/java/de/fullrisk/citrusDev/UIHelper/ModuleSettings.java +++ b/src/main/java/de/fullrisk/citrusDev/UIHelper/ModuleSettings.java @@ -43,7 +43,7 @@ public class ModuleSettings { return List.of( new SettingRow("Position", SettingsControls.makeCyclingButton(GLASS_PANEL, positionStates, positionIndex(Config.get().fpsX, Config.get().fpsY))), - new SettingRow("", SettingsControls.makeSectionHeader(CONTENT_WIDTH - 8, "Display Options")), + new SettingRow("", SettingsControls.makeSectionHeader(CONTENT_WIDTH - 8, "Visual")), new SettingRow("Padding", paddingSlider) ); } @@ -109,6 +109,7 @@ public class ModuleSettings { return List.of( new SettingRow("Position", SettingsControls.makeCyclingButton(GLASS_PANEL, positionStates, positionIndex(Config.get().effectsX, Config.get().effectsY))), + new SettingRow("", SettingsControls.makeSectionHeader(CONTENT_WIDTH - 8, "Visual")), new SettingRow("Show Background", SettingsControls.makeCheckbox(FLAT, GLASS_PANEL, Module_Effects.isBackgroundEnabled(), Module_Effects::setBackgroundEnabled)), new SettingRow("Show Timer", SettingsControls.makeCheckbox(FLAT, GLASS_PANEL, Module_Effects.isTimerEnabled(), Module_Effects::setTimerEnabled)), new SettingRow("Show Name", SettingsControls.makeCheckbox(FLAT, GLASS_PANEL, Module_Effects.isNameEnabled(), Module_Effects::setNameEnabled)) diff --git a/src/main/java/de/fullrisk/citrusDev/UIHelper/SettingsControls.java b/src/main/java/de/fullrisk/citrusDev/UIHelper/SettingsControls.java index 7d680db..01c13cd 100644 --- a/src/main/java/de/fullrisk/citrusDev/UIHelper/SettingsControls.java +++ b/src/main/java/de/fullrisk/citrusDev/UIHelper/SettingsControls.java @@ -24,7 +24,7 @@ public class SettingsControls { private static final Identifier MC_FIVE = Identifier.fromNamespaceAndPath("citrus-dev", "minecraft_five"); private static int secColor() { - return Config.get().darkMode ? 0xFFd0d4da : 0xFFb0b6c0; + return Config.get().darkMode ? 0xFF7a7979 : 0xFFb0b6c0; } public record ButtonState(String label, Runnable onSelect) {} @@ -194,19 +194,36 @@ public class SettingsControls { row.horizontalAlignment(HorizontalAlignment.LEFT); row.gap(4); - FlowLayout shortLine = UIContainers.horizontalFlow(Sizing.fixed(10), Sizing.fixed(1)); - shortLine.surface(Surface.flat(0x80FFFFFF)); - row.child(shortLine); + int shortLineWidth = 12; + row.child(makeDottedLine(0x90636363, shortLineWidth)); var label = UIComponents.label(Component.literal(text.toUpperCase()) .withStyle(style -> style.withFont(new FontDescription.Resource(MC_FIVE)))) .color(Color.ofRgb(secColor())); row.child(label); - FlowLayout longLine = UIContainers.horizontalFlow(Sizing.fill(100), Sizing.fixed(1)); - longLine.surface(Surface.flat(0x80FFFFFF)); - row.child(longLine); + int textWidth = Minecraft.getInstance().font.width(text.toUpperCase()); + int gapTotal = 4 + 4; // gap(4) appears twice: before label, after label + int longLineWidth = width - shortLineWidth - textWidth - gapTotal; + row.child(makeDottedLine(0x90636363, Math.max(longLineWidth, 20))); return row; } + + private static FlowLayout makeDottedLine(int color, int targetWidth) { + FlowLayout dotted = UIContainers.horizontalFlow(Sizing.fixed(targetWidth), Sizing.fixed(1)); + dotted.verticalAlignment(VerticalAlignment.CENTER); + dotted.gap(3); + + int segmentWidth = 3; + int segmentCount = Math.max(1, targetWidth / (segmentWidth + 3)); + + for (int i = 0; i < segmentCount; i++) { + FlowLayout dot = UIContainers.horizontalFlow(Sizing.fixed(segmentWidth), Sizing.fixed(1)); + dot.surface(Surface.flat(color)); + dotted.child(dot); + } + + return dotted; + } } \ No newline at end of file diff --git a/src/main/java/de/fullrisk/citrusDev/mixin/SliderComponentMixin.java b/src/main/java/de/fullrisk/citrusDev/mixin/SliderComponentMixin.java index 55ec066..a26cd4e 100644 --- a/src/main/java/de/fullrisk/citrusDev/mixin/SliderComponentMixin.java +++ b/src/main/java/de/fullrisk/citrusDev/mixin/SliderComponentMixin.java @@ -27,11 +27,15 @@ public abstract class SliderComponentMixin { OwoUIGraphics owo = OwoUIGraphics.of(graphics); - owo.fill(RenderPipelines.GUI, x, y, x + w, y + h, 0x40FFFFFF); + int trackHeight = Math.max(2, h / 3); + int trackY = y + (h - trackHeight) / 2; + owo.fill(RenderPipelines.GUI, x, trackY, x + w, trackY + trackHeight, 0x40FFFFFF); - int handleWidth = 4; + int handleWidth = 3; + int handleHeight = h; + int handleY = y + (h - handleHeight) / 2; int handleX = x + (int) (slider.value() * (w - handleWidth)); - owo.fill(RenderPipelines.GUI, handleX, y, handleX + handleWidth, y + h, 0xFFFFFFFF); + owo.fill(RenderPipelines.GUI, handleX, handleY, handleX + handleWidth, handleY + handleHeight, 0xFF64de4b); ci.cancel(); } diff --git a/src/main/resources/assets/citrus-dev/textures/icons/keystrokes.png b/src/main/resources/assets/citrus-dev/textures/icons/keystrokes.png index 50d91f75a7d8a685a76c21e4f16730b0e0493468..cc737a188e212cb9bd3dbdecc98b06f259bf9db4 100644 GIT binary patch literal 190 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE;AtEY=&NX4zYR}OL>P~d5OsQ2<< zw0e;M|2hS}2VCnWbv?D$*wQYcVe&y?d4I-{$7{3J7Da?<6xcF`@Ni6 z{(*^x#{{3>ad=|$z9H+twOc&T_V9m`3*m2KVD#>nQfc_&vU|$Q6FQmC`DXUj$*cTl ouQbzM#_ZTA?(xR1Q~woH0>_{E@204h03F2O>FVdQ&MBb@04moh($ literal 16798 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�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 J9_wMF{tpSmw9)_o