Mod Preview

This commit is contained in:
2026-03-24 01:38:43 +01:00
parent 2b6194223a
commit 174c95240c
12 changed files with 224 additions and 161 deletions
@@ -60,17 +60,17 @@ public class Element {
public Element centerHorizontal(int w, int h, int offsetX, int offsetY) {
this.x = (w - (int) (width * scale)) / 2 + offsetX;
this.y = offsetY;
this.y += offsetY;
return this;
}
public Element center(int w, int h) {
this.centerOffset(w, h, 0, 0);
this.center(w, h, 0, 0);
return this;
}
public Element centerOffset(int w, int h, int offsetX, int offsetY) {
public Element center(int w, int h, int offsetX, int offsetY) {
this.x = (w - (int) (width * scale)) / 2 + offsetX;
this.y = (h - (int) (height * scale)) / 2 + offsetY;
@@ -0,0 +1,27 @@
package org.saturnclient.ui.components;
import org.saturnclient.feature.FeatureLayout;
import org.saturnclient.feature.HudFeature;
import org.saturnclient.ui.Element;
import org.saturnclient.ui.ElementContext;
import org.saturnclient.ui.RenderScope;
public class HudModPreview extends Element {
HudFeature feature;
public HudModPreview(HudFeature feature) {
this.feature = feature;
}
@Override
public void render(RenderScope scope, ElementContext ctx) {
FeatureLayout layout = feature.getDimensions();
if (layout.renderBackground) {
scope.drawRoundedRectangle(0, 0, layout.width, layout.height,
layout.radius.value, layout.bgColor.value);
}
feature.renderDummy(scope);
}
}
@@ -3,6 +3,7 @@ package org.saturnclient.ui.components;
import org.saturnclient.common.provider.Providers;
import org.saturnclient.config.Theme;
import org.saturnclient.feature.Feature;
import org.saturnclient.feature.HudFeature;
import org.saturnclient.ui.Element;
import org.saturnclient.ui.ElementContext;
import org.saturnclient.ui.RenderScope;
@@ -13,149 +14,153 @@ import org.saturnclient.ui.screens.ConfigEditor;
public class SaturnModule extends Element {
private final Feature mod;
private final Feature mod;
static int p = 10; // padding
static int s = 14; // settings icon size
static int expand = 5; // settings icon click area
static int p = 10; // padding
static int s = 14; // settings icon size
static int expand = 5; // settings icon click area
public SaturnModule(Feature mod) {
this.mod = mod;
this.width = 160;
this.height = 50;
public SaturnModule(Feature mod) {
this.mod = mod;
this.width = 160;
this.height = 50;
}
@Override
public void render(RenderScope renderScope, ElementContext ctx) {
boolean hovered = ctx.isHovering();
boolean enabled = mod.isEnabled();
int iconX = width - s - p;
int iconY = height - s - p;
boolean settingsHover = ctx.isHovering(
getSettingsX(),
getSettingsY(),
getSettingsHitBox(),
getSettingsHitBox());
// Resolve theme colors
int bgColor = Theme.PRIMARY.value;
int fgColor = hovered && !settingsHover ? Theme.ACCENT.value : Theme.PRIMARY_FG.value;
int iconBg = enabled ? Theme.ACCENT.value : Theme.PRIMARY.value;
int iconFg = enabled ? Theme.ACCENT_FG.value : fgColor;
int settingsColor = settingsHover
? Theme.ACCENT.value
: Theme.withAlpha(160, fgColor);
int h = height - (p * 2);
// Main background
renderScope.drawRoundedRectangle(
0, 0,
width, height,
Theme.WIDGET_RADIUS.value,
bgColor);
// Icon background
renderScope.drawRoundedRectangle(
p, p,
h, h,
Theme.WIDGET_RADIUS.value,
iconBg);
// Icon
renderScope.drawTexture(
mod.getIconTexture(),
p + (p / 2),
p + (p / 2),
0, 0,
h - p,
h - p,
iconFg);
// Module name
renderScope.drawText(
0.6f,
mod.getName(),
p + h + 4,
p + 1,
Theme.FONT.value,
fgColor);
// Version (right aligned)
String version = mod.getVersion();
int versionWidth = (int) (Fonts.getWidth(version, Theme.FONT.value) * 0.35f);
renderScope.drawText(
0.35f,
version,
width - p - versionWidth,
p + 1,
Theme.FONT.value,
fgColor);
// Tags
int xt = p + h + 4;
for (String tag : mod.getTags()) {
int tagWidth = (int) (Fonts.getWidth(tag, Theme.FONT.value) * 0.4f);
renderScope.drawRoundedRectangle(
xt,
p + (h / 2),
tagWidth + 6,
12,
5,
Theme.ACCENT.value);
renderScope.drawText(
0.4f,
tag,
xt + 2,
p + (h / 2) + 3,
Theme.FONT.value,
Theme.ACCENT_FG.value);
xt += tagWidth + 9;
}
@Override
public void render(RenderScope renderScope, ElementContext ctx) {
boolean hovered = ctx.isHovering();
boolean enabled = mod.isEnabled();
// Settings icon
renderScope.drawTexture(
Textures.SETTINGS,
iconX,
iconY,
0, 0,
s, s,
settingsColor);
}
int iconX = width - s - p;
int iconY = height - s - p;
@Override
public void click(int mouseX, int mouseY) {
boolean settingsHover = Utils.isHovering(
mouseX - getSettingsX(),
mouseY - getSettingsY(),
getSettingsHitBox(),
getSettingsHitBox(),
1.0f);
boolean settingsHover = ctx.isHovering(
getSettingsX(),
getSettingsY(),
getSettingsHitBox(),
getSettingsHitBox());
// Resolve theme colors
int bgColor = Theme.PRIMARY.value;
int fgColor = hovered && !settingsHover ? Theme.ACCENT.value : Theme.PRIMARY_FG.value;
int iconBg = enabled ? Theme.ACCENT.value : Theme.PRIMARY.value;
int iconFg = enabled ? Theme.ACCENT_FG.value : fgColor;
int settingsColor = settingsHover
? Theme.ACCENT.value
: Theme.withAlpha(160, fgColor);
int h = height - (p * 2);
// Main background
renderScope.drawRoundedRectangle(
0, 0,
width, height,
Theme.WIDGET_RADIUS.value,
bgColor);
// Icon background
renderScope.drawRoundedRectangle(
p, p,
h, h,
Theme.WIDGET_RADIUS.value,
iconBg);
// Icon
renderScope.drawTexture(
mod.getIconTexture(),
p + (p / 2),
p + (p / 2),
0, 0,
h - p,
h - p,
iconFg);
// Module name
renderScope.drawText(
0.6f,
mod.getName(),
p + h + 4,
p + 1,
Theme.FONT.value,
fgColor);
// Version (right aligned)
String version = mod.getVersion();
int versionWidth = (int) (Fonts.getWidth(version, Theme.FONT.value) * 0.35f);
renderScope.drawText(
0.35f,
version,
width - p - versionWidth,
p + 1,
Theme.FONT.value,
fgColor);
// Tags
int xt = p + h + 4;
for (String tag : mod.getTags()) {
int tagWidth = (int) (Fonts.getWidth(tag, Theme.FONT.value) * 0.4f);
renderScope.drawRoundedRectangle(
xt,
p + (h / 2),
tagWidth + 6,
12,
5,
Theme.ACCENT.value);
renderScope.drawText(
0.4f,
tag,
xt + 2,
p + (h / 2) + 3,
Theme.FONT.value,
Theme.ACCENT_FG.value);
xt += tagWidth + 9;
}
// Settings icon
renderScope.drawTexture(
Textures.SETTINGS,
iconX,
iconY,
0, 0,
s, s,
settingsColor);
if (settingsHover) {
if (mod instanceof HudFeature h) {
Providers.saturn.getClient().setScreen(new ConfigEditor(mod.getConfig(), h));
} else {
Providers.saturn.getClient().setScreen(new ConfigEditor(mod.getConfig()));
}
} else {
mod.setEnabled(!mod.isEnabled());
}
}
@Override
public void click(int mouseX, int mouseY) {
boolean settingsHover = Utils.isHovering(
mouseX - getSettingsX(),
mouseY - getSettingsY(),
getSettingsHitBox(),
getSettingsHitBox(),
1.0f);
private int getSettingsX() {
return width - s - p - expand;
}
if (settingsHover) {
Providers.saturn.getClient().setScreen(new ConfigEditor(mod.getConfig()));
} else {
mod.setEnabled(!mod.isEnabled());
}
}
private int getSettingsY() {
return height - s - p - expand;
}
private int getSettingsX() {
return width - s - p - expand;
}
private int getSettingsY() {
return height - s - p - expand;
}
private int getSettingsHitBox() {
return s + expand * 2;
}
private int getSettingsHitBox() {
return s + expand * 2;
}
}
@@ -12,7 +12,11 @@ import org.saturnclient.config.property.KeybindingProperty;
import org.saturnclient.config.property.NamespaceProperty;
import org.saturnclient.config.property.Property;
import org.saturnclient.config.property.SelectProperty;
import org.saturnclient.feature.FeatureLayout;
import org.saturnclient.feature.HudFeature;
import org.saturnclient.ui.RenderScope;
import org.saturnclient.ui.SaturnScreen;
import org.saturnclient.ui.components.HudModPreview;
import org.saturnclient.ui.components.Sidebar;
import org.saturnclient.ui.components.inputs.FloatInput;
import org.saturnclient.ui.components.inputs.ColorInput;
@@ -26,6 +30,8 @@ import org.saturnclient.ui.resources.Fonts;
public class ConfigEditor extends SaturnScreen {
private ConfigManager config;
private HudFeature hudFeature;
private HudModPreview preview;
public ConfigEditor(ConfigManager config) {
super("Config Editor");
@@ -33,6 +39,13 @@ public class ConfigEditor extends SaturnScreen {
this.config = config;
}
public ConfigEditor(ConfigManager config, HudFeature hudFeature) {
super("Config Editor");
this.config = config;
this.hudFeature = hudFeature;
}
@Override
public void ui() {
int p = 10;
@@ -44,9 +57,13 @@ public class ConfigEditor extends SaturnScreen {
int scrollWidth = 480 + 10 + (g * 2) + (p * 2);
if (this.hudFeature != null) {
this.preview = new HudModPreview(this.hudFeature);
}
draw(scroll.dimensions(scrollWidth, 350).center(width, height));
draw(new Sidebar(1, this.provider::close).centerOffset(width, height, -(scrollWidth / 2 + 20), 0));
draw(new Sidebar(1, this.provider::close).center(width, height, -(scrollWidth / 2 + 20), 0));
}
private int drawProperties(Scroll configScroll, Map<String, Property> properties, int row, int col, int w) {
@@ -139,4 +156,18 @@ public class ConfigEditor extends SaturnScreen {
public static boolean isFull(Property prop) {
return !(prop instanceof BoolProperty);
}
@Override
public void render(RenderScope renderScope, int mouseX, int mouseY, float delta, long elapsed) {
if (this.preview != null) {
FeatureLayout layout = hudFeature.getDimensions();
draw(this.preview
.dimensions(layout.width, (int) (layout.height * layout.scale.value * 2.0f))
.scale(1.0f) // Because the centering won't work properly
.center(width, height, (530 / 2) + 40, 0)
.scale(layout.scale.value * 2.0f));
}
super.render(renderScope, mouseX, mouseY, delta, elapsed);
}
}
@@ -32,12 +32,12 @@ public class EmoteWheel extends SaturnScreen {
draw(new ImageTexture(Textures.LOGO_TEXT)
.dimensions(98, 10)
.centerOffset(width, height, 0, -105)
.center(width, height, 0, -105)
.animation(new Fade(AnimationConfig.logo.duration.value)));
draw(new ImageTexture(Config.getLogo())
.dimensions(98, 98)
.centerOffset(width, height, 0, -149)
.center(width, height, 0, -149)
.animation(new SlideY(AnimationConfig.logo, -20)));
// =============================
@@ -51,7 +51,7 @@ public class EmoteWheel extends SaturnScreen {
ui();
}
}).dimensions(30, 30)
.centerOffset(width, height, -50, 105)
.center(width, height, -50, 105)
.animation(new Fade(500)));
draw(new TextureButton(Textures.RIGHT, () -> {
@@ -61,7 +61,7 @@ public class EmoteWheel extends SaturnScreen {
ui();
}
}).dimensions(30, 30)
.centerOffset(width, height, 50, 105)
.center(width, height, 50, 105)
.animation(new Fade(500)));
// =============================
@@ -86,7 +86,7 @@ public class EmoteWheel extends SaturnScreen {
provider.close();
})
.dimensions(70, 70)
.centerOffset(width, height,
.center(width, height,
-80 + (col * 80),
-35 + (row * 80))
.animation(new SlideY(AnimationConfig.emoteWheel, 12)));
@@ -49,7 +49,7 @@ public class ModMenu extends SaturnScreen {
draw(scroll.dimensions(scrollWidth, 350).center(width, height));
draw(new Sidebar(0, this.provider::close).centerOffset(width, height, -(scrollWidth / 2 + 20), 0));
draw(new Sidebar(0, this.provider::close).center(width, height, -(scrollWidth / 2 + 20), 0));
draw(new ImageTexture(Textures.LOGO_TEXT_BIG).dimensions(180, 18).position(width - 180 - 20, height - 18 - 20));
}
@@ -23,12 +23,12 @@ public class ShiftMenu extends SaturnScreen {
// Logo animations (unchanged)
draw(new ImageTexture(Textures.LOGO_TEXT)
.dimensions(98, 10)
.centerOffset(width, height, 0, -36)
.center(width, height, 0, -36)
.animation(new Fade(AnimationConfig.logo.duration.value)));
draw(new ImageTexture(Config.getLogo())
.dimensions(98, 98)
.centerOffset(width, height, 0, -80)
.center(width, height, 0, -80)
.animation(new SlideY(AnimationConfig.logo, -20)));
// Spacing and sizes
@@ -56,7 +56,7 @@ public class ShiftMenu extends SaturnScreen {
.animation(new Fade(AnimationConfig.shiftMenu)));
// Draw the stagger at the absolute center of the screen
draw(stagger.dimensions(btnWidth + (btnHeight * 2) + (spacing * 2), btnHeight).centerOffset(width, height, 0,
draw(stagger.dimensions(btnWidth + (btnHeight * 2) + (spacing * 2), btnHeight).center(width, height, 0,
0));
}
}
@@ -25,9 +25,9 @@ public class TitleMenu extends SaturnScreen {
public void ui() {
backgroundBlur = 0;
draw(new ImageTexture(Textures.LOGO_TEXT).dimensions(98, 10).centerOffset(width, height, 0, -40)
draw(new ImageTexture(Textures.LOGO_TEXT).dimensions(98, 10).center(width, height, 0, -40)
.animation(new Fade(AnimationConfig.logo.duration.value)));
draw(new ImageTexture(Config.getLogo()).dimensions(98, 98).centerOffset(width, height, 0, -84)
draw(new ImageTexture(Config.getLogo()).dimensions(98, 98).center(width, height, 0, -84)
.animation(new SlideY(AnimationConfig.logo, -20)));
AnimationStagger mainButtonStagger = new AnimationStagger(AnimationConfig.mainMenu);
@@ -52,7 +52,7 @@ public class TitleMenu extends SaturnScreen {
}).scale(0.69f).dimensions(206, 52).position(146, 80)
.animation(new SlideFade(AnimationConfig.mainMenu, -10)));
draw(mainButtonStagger.dimensions(289, 143).centerOffset(width, height, 0, 50));
draw(mainButtonStagger.dimensions(289, 143).center(width, height, 0, 50));
int s = Fonts.getHeight() + 20;
@@ -69,7 +69,7 @@ public class CloakMenu extends SaturnScreen {
.animation(new Fade(500)));
draw(new Sidebar(2, this.provider::close)
.centerOffset(width, height, -(scrollWidth / 2 + 20), 0));
.center(width, height, -(scrollWidth / 2 + 20), 0));
draw(new TabMenu(0,
new TabMenuComponent(Textures.CLOAK, () -> {
@@ -77,6 +77,6 @@ public class CloakMenu extends SaturnScreen {
new TabMenuComponent(Textures.HAT, () -> {
Providers.saturn.getClient().setScreen(new HatMenu());
}))
.centerOffset(width, height, 0, -195));
.center(width, height, 0, -195));
}
}
@@ -69,7 +69,7 @@ public class HatMenu extends SaturnScreen {
.animation(new Fade(500)));
draw(new Sidebar(2, this.provider::close)
.centerOffset(width, height, -(scrollWidth / 2 + 20), 0));
.center(width, height, -(scrollWidth / 2 + 20), 0));
draw(new TabMenu(1,
new TabMenuComponent(Textures.CLOAK, () -> {
@@ -77,6 +77,6 @@ public class HatMenu extends SaturnScreen {
}),
new TabMenuComponent(Textures.HAT, () -> {
}))
.centerOffset(width, height, 0, -195));
.center(width, height, 0, -195));
}
}
@@ -96,10 +96,10 @@ public class CloakStore extends SaturnScreen {
draw(scroll
.dimensions(scrollWidth, 350)
.centerOffset(width, height, 15, 0));
.center(width, height, 15, 0));
draw(new Sidebar(5, this.provider::close)
.centerOffset(width, height, -((scrollWidth - 30) / 2 + 20), 0));
.center(width, height, -((scrollWidth - 30) / 2 + 20), 0));
draw(new TabMenu(0,
new TabMenuComponent(Textures.CLOAK, () -> {
@@ -107,7 +107,7 @@ public class CloakStore extends SaturnScreen {
new TabMenuComponent(Textures.HAT, () -> {
Providers.saturn.getClient().setScreen(new HatStore());
}))
.centerOffset(width, height, 0, -195));
.center(width, height, 0, -195));
}
private void handlePurchase(String cloak) {
@@ -96,10 +96,10 @@ public class HatStore extends SaturnScreen {
draw(scroll
.dimensions(scrollWidth, 350)
.centerOffset(width, height, 15, 0));
.center(width, height, 15, 0));
draw(new Sidebar(5, this.provider::close)
.centerOffset(width, height, -((scrollWidth - 30) / 2 + 20), 0));
.center(width, height, -((scrollWidth - 30) / 2 + 20), 0));
draw(new TabMenu(1,
new TabMenuComponent(Textures.CLOAK, () -> {
@@ -107,7 +107,7 @@ public class HatStore extends SaturnScreen {
}),
new TabMenuComponent(Textures.HAT, () -> {
}))
.centerOffset(width, height, 0, -195));
.center(width, height, 0, -195));
}
private void handlePurchase(String hat) {