Compare commits
13
Commits
6d5df3057e
...
b14c5c4ffa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b14c5c4ffa | ||
|
|
fd9ec3222c | ||
|
|
917eba1e17 | ||
|
|
2ef28c9e14 | ||
|
|
e395068e76 | ||
|
|
e8f686b2d3 | ||
|
|
df5afe99e3 | ||
|
|
653738568a | ||
|
|
a6a324a61a | ||
|
|
b0d75af8c4 | ||
|
|
c973e053aa | ||
|
|
bbf6b88ed3 | ||
|
|
ba71a5b838 |
@@ -1,7 +1,11 @@
|
||||
package org.saturnclient.common.ref.game;
|
||||
|
||||
/**
|
||||
* An item stack. Its methods are implemented in ItemStackMixin, so their names must not match any of
|
||||
* ItemStack's own methods.
|
||||
*/
|
||||
public interface ItemStackRef {
|
||||
public boolean isEmpty();
|
||||
public int getMaxDamage();
|
||||
public int getDamage();
|
||||
public boolean isEmptyStack();
|
||||
public int getMaxItemDamage();
|
||||
public int getItemDamage();
|
||||
}
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
package org.saturnclient.common.ref.render;
|
||||
|
||||
/**
|
||||
* The game window. Its methods are implemented in WindowMixin, so their names must not match any of
|
||||
* Window's own methods.
|
||||
*/
|
||||
public interface WindowRef {
|
||||
public int getWidth();
|
||||
/** The window's width in screen coordinates */
|
||||
public int getWindowWidth();
|
||||
|
||||
public int getHeight();
|
||||
/** The window's height in screen coordinates */
|
||||
public int getWindowHeight();
|
||||
|
||||
public int getFramebufferWidth();
|
||||
|
||||
|
||||
@@ -163,14 +163,6 @@ public class ConfigManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the config file has a value for {@code name} in this namespace,
|
||||
* which tells which version last saved it.
|
||||
*/
|
||||
public boolean isSaved(String name) {
|
||||
return getSaved(name) != null;
|
||||
}
|
||||
|
||||
private JsonNode getSaved(String name) {
|
||||
JsonNode source = cachedJson != null ? cachedJson : loadAndCache();
|
||||
if (source == null || !source.isObject())
|
||||
|
||||
@@ -10,26 +10,27 @@ import org.saturnclient.config.property.SelectProperty;
|
||||
public class Theme {
|
||||
public static ConfigManager config;
|
||||
|
||||
// Main UI background (slightly warm dark to match Saturn tone), translucent over the world
|
||||
public static final ColorProperty BACKGROUND = Property.color(0xD112100D);
|
||||
// Main UI background (a near-neutral dark, so the warm world showing through
|
||||
// doesn't muddy it), translucent over the world
|
||||
public static final ColorProperty BACKGROUND = Property.color(0xD1131417);
|
||||
|
||||
// Default text color
|
||||
public static final ColorProperty FOREGROUND = Property.color(0xFFF2E6D2);
|
||||
public static final ColorProperty FOREGROUND = Property.color(0xFFECEFF3);
|
||||
|
||||
// Widget default background (normal state), translucent over the world
|
||||
public static final ColorProperty PRIMARY = Property.color(0xB81C1915);
|
||||
public static final ColorProperty PRIMARY = Property.color(0xB81E2025);
|
||||
|
||||
// Widget text color
|
||||
public static final ColorProperty PRIMARY_FG = Property.color(0xFFEAD9B8);
|
||||
public static final ColorProperty PRIMARY_FG = Property.color(0xFFD5DAE1);
|
||||
|
||||
// Saturn brand color (hovered / enabled / selected)
|
||||
public static final ColorProperty ACCENT = Property.color(0xFFE2BF7D);
|
||||
// Saturn brand color, a pale frost (hovered / enabled / selected)
|
||||
public static final ColorProperty ACCENT = Property.color(0xFFD3DCE6);
|
||||
|
||||
// Text/icons shown on accent background
|
||||
public static final ColorProperty ACCENT_FG = Property.color(0xFF1A140A);
|
||||
public static final ColorProperty ACCENT_FG = Property.color(0xFF15181C);
|
||||
|
||||
// Misc colors
|
||||
public static final ColorProperty SCROLL = Property.color(0xFFE2BF7D);
|
||||
// Misc colors: the one warm touch, Saturn's butterscotch
|
||||
public static final ColorProperty SCROLL = Property.color(0xFFD9B98A);
|
||||
|
||||
// UI metrics
|
||||
public static final IntProperty BG_RADIUS = Property.integer(12).range(0, 24);
|
||||
@@ -62,10 +63,11 @@ public class Theme {
|
||||
}
|
||||
|
||||
public static final List<Preset> PRESETS = List.of(
|
||||
new Preset("Saturn", 0xD112100D, 0xFFF2E6D2, 0xB81C1915, 0xFFEAD9B8, 0xFFE2BF7D, 0xFF1A140A, 0xFFE2BF7D),
|
||||
new Preset("Midnight", 0xD10E1117, 0xFFE4EAF5, 0xB8171C26, 0xFFC9D4E8, 0xFF8FB3FF, 0xFF0A1224, 0xFF8FB3FF),
|
||||
new Preset("Amethyst", 0xD1120F17, 0xFFEDE4F7, 0xB81C1724, 0xFFD8C9EB, 0xFFC79BFF, 0xFF1A0F2A, 0xFFC79BFF),
|
||||
new Preset("Emerald", 0xD10D1210, 0xFFE2F2EA, 0xB816201B, 0xFFC4E0D2, 0xFF7FD1A8, 0xFF0A1F15, 0xFF7FD1A8));
|
||||
new Preset("Saturn", 0xD1131417, 0xFFECEFF3, 0xB81E2025, 0xFFD5DAE1, 0xFFD3DCE6, 0xFF15181C, 0xFFD9B98A),
|
||||
new Preset("Saturn Gold", 0xD112100D, 0xFFF2E6D2, 0xB81C1915, 0xFFEAD9B8, 0xFFE2BF7D, 0xFF1A140A, 0xFFE2BF7D),
|
||||
new Preset("Mono", 0xD1121212, 0xFFF0F0F0, 0xB81C1C1C, 0xFFDADADA, 0xFFF0F0F0, 0xFF121212, 0xFFF0F0F0),
|
||||
new Preset("Midnight", 0xD1121418, 0xFFE5E9F0, 0xB81C2027, 0xFFD8DEE9, 0xFF8FAFCF, 0xFF10151D, 0xFF8FAFCF),
|
||||
new Preset("Amethyst", 0xD1141317, 0xFFECE8F1, 0xB81F1D24, 0xFFDAD3E3, 0xFFB49CCB, 0xFF19131F, 0xFFB49CCB));
|
||||
|
||||
public static void init(ConfigManager parent) {
|
||||
config = new ConfigManager(parent, "UI Style");
|
||||
@@ -81,29 +83,6 @@ public class Theme {
|
||||
config.property("Widget Radius", WIDGET_RADIUS, "Corner rounding of buttons and cards");
|
||||
|
||||
config.property("Font", FONT, "Font of every Saturn screen");
|
||||
|
||||
if (!parent.isSaved(Config.MENU_BLUR)) {
|
||||
upgradeOpaqueColors();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Before 0.1.3 panels and cards were made translucent in code, and the
|
||||
* background and primary colors were saved fully opaque. Saved colors that
|
||||
* are an old default or preset get the translucency the colors now carry
|
||||
* themselves; colors the player picked are left as they are. Runs only on
|
||||
* configs from older versions, so a preset color later set opaque on
|
||||
* purpose stays opaque.
|
||||
*/
|
||||
private static void upgradeOpaqueColors() {
|
||||
for (Preset preset : PRESETS) {
|
||||
if (BACKGROUND.value == (preset.background() | 0xFF000000)) {
|
||||
BACKGROUND.value = preset.background();
|
||||
}
|
||||
if (PRIMARY.value == (preset.primary() | 0xFF000000)) {
|
||||
PRIMARY.value = preset.primary();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,7 +38,14 @@ public class Cloaks {
|
||||
availableCloaks.add(0, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* The cloak's texture, or null for no cloak ("", the "None" choice) and for a cloak this version
|
||||
* has no texture for, which would otherwise draw as the missing texture.
|
||||
*/
|
||||
public static IdentifierRef getCurrentCloakTexture(String cloakName) {
|
||||
if (cloakName == null || !Arrays.asList(ALL_CLOAKS).contains(cloakName)) {
|
||||
return null;
|
||||
}
|
||||
if (Arrays.asList(ANIMATED_CLOAKS).contains(cloakName)) {
|
||||
return IdentifierRef.ofSaturn("textures/cloaks/" + cloakName + ".gif");
|
||||
} else {
|
||||
|
||||
@@ -75,16 +75,16 @@ public class ArmorDisplayMod extends Mod implements HudMod {
|
||||
|
||||
int row = 0;
|
||||
|
||||
if (useMainHand.value && !mainHand.isEmpty()) {
|
||||
if (useMainHand.value && !mainHand.isEmptyStack()) {
|
||||
row = renderSlot(scope, mainHand, row);
|
||||
}
|
||||
if (!helmet.isEmpty())
|
||||
if (!helmet.isEmptyStack())
|
||||
row = renderSlot(scope, helmet, row);
|
||||
if (!chestplate.isEmpty())
|
||||
if (!chestplate.isEmptyStack())
|
||||
row = renderSlot(scope, chestplate, row);
|
||||
if (!leggings.isEmpty())
|
||||
if (!leggings.isEmptyStack())
|
||||
row = renderSlot(scope, leggings, row);
|
||||
if (!boots.isEmpty())
|
||||
if (!boots.isEmptyStack())
|
||||
row = renderSlot(scope, boots, row);
|
||||
}
|
||||
|
||||
@@ -94,8 +94,8 @@ public class ArmorDisplayMod extends Mod implements HudMod {
|
||||
private int renderSlot(RenderScope scope, ItemStackRef item, int row) {
|
||||
scope.drawItem(item, 0, 15 * row);
|
||||
|
||||
if (item.getMaxDamage() > 0) {
|
||||
int remaining = item.getMaxDamage() - item.getDamage();
|
||||
if (item.getMaxItemDamage() > 0) {
|
||||
int remaining = item.getMaxItemDamage() - item.getItemDamage();
|
||||
scope.drawText(0.5f, String.valueOf(remaining),
|
||||
17, (15 * row) + 3,
|
||||
layout.font.value, layout.fgColor.value);
|
||||
|
||||
@@ -22,9 +22,9 @@ public class Sidebar extends Element {
|
||||
|
||||
// Values for the constructor's `active`
|
||||
public static final int MODS = 0;
|
||||
public static final int COSMETICS = 1;
|
||||
public static final int HUD_EDITOR = 2;
|
||||
public static final int SETTINGS = 3;
|
||||
public static final int SETTINGS = 1;
|
||||
public static final int COSMETICS = 2;
|
||||
public static final int HUD_EDITOR = 3;
|
||||
|
||||
private static final int LOGO = 32;
|
||||
private static final int BUTTON = 44;
|
||||
@@ -35,11 +35,12 @@ public class Sidebar extends Element {
|
||||
private record Item(IdentifierRef icon, Runnable onClick) {
|
||||
}
|
||||
|
||||
// In the order of the constants above
|
||||
private final Item[] items = {
|
||||
new Item(Textures.ICON_MODS, () -> Providers.saturn.getClient().setScreen(new ModMenu())),
|
||||
new Item(Textures.ICON_SETTINGS, () -> Providers.saturn.getClient().setScreen(new ClientSettings())),
|
||||
new Item(Textures.ICON_COSMETICS, () -> Providers.saturn.getClient().setScreen(new CosmeticsMenu())),
|
||||
new Item(Textures.ICON_HUD_EDITOR, () -> Providers.saturn.getClient().setScreen(new HudEditor())),
|
||||
new Item(Textures.ICON_SETTINGS, () -> Providers.saturn.getClient().setScreen(new ClientSettings())),
|
||||
};
|
||||
|
||||
private final int active;
|
||||
|
||||
@@ -12,6 +12,8 @@ import org.saturnclient.ui.resources.Fonts;
|
||||
*/
|
||||
public class ThemePresetCard extends Element {
|
||||
public static final int HEIGHT = 92;
|
||||
/** The narrowest card that still fits its preview's widgets */
|
||||
public static final int MIN_WIDTH = 100;
|
||||
|
||||
private static final int PADDING = 10;
|
||||
private static final int PREVIEW_HEIGHT = 44;
|
||||
|
||||
@@ -20,9 +20,9 @@ public class ImageTexture extends Element {
|
||||
if (sprite.toString().endsWith(".svg")) {
|
||||
MinecraftClientRef client = Providers.saturn.getClient();
|
||||
|
||||
int renderWidth = (int) (width * client.getWindow().getFramebufferWidth() / client.getWindow().getWidth());
|
||||
int renderWidth = (int) (width * client.getWindow().getFramebufferWidth() / client.getWindow().getWindowWidth());
|
||||
int renderHeight = (int) (height * client.getWindow().getFramebufferHeight()
|
||||
/ client.getWindow().getHeight());
|
||||
/ client.getWindow().getWindowHeight());
|
||||
|
||||
IdentifierRef pngId = SvgTexture.getSvg(sprite, renderWidth * 2, renderHeight * 2);
|
||||
|
||||
|
||||
@@ -102,15 +102,20 @@ public class ClientSettings extends PanelScreen {
|
||||
Map<String, Property> properties = Theme.config.getProperties();
|
||||
|
||||
int y = PropertyList.drawSection(scroll, "Presets", 0) + 10;
|
||||
int cardWidth = (width - PRESET_GAP * (Theme.PRESETS.size() - 1)) / Theme.PRESETS.size();
|
||||
// One row when the cards fit, otherwise as many rows as they need
|
||||
int columns = Math.max(1, Math.min(Theme.PRESETS.size(),
|
||||
(width + PRESET_GAP) / (ThemePresetCard.MIN_WIDTH + PRESET_GAP)));
|
||||
int rows = (Theme.PRESETS.size() + columns - 1) / columns;
|
||||
int cardWidth = (width - PRESET_GAP * (columns - 1)) / columns;
|
||||
|
||||
for (int i = 0; i < Theme.PRESETS.size(); i++) {
|
||||
// Rebuild so the color inputs show the preset's colors
|
||||
scroll.draw(new ThemePresetCard(Theme.PRESETS.get(i), cardWidth, this::init)
|
||||
.position(i * (cardWidth + PRESET_GAP), y));
|
||||
.position(i % columns * (cardWidth + PRESET_GAP),
|
||||
y + i / columns * (ThemePresetCard.HEIGHT + PRESET_GAP)));
|
||||
}
|
||||
|
||||
y += ThemePresetCard.HEIGHT + SECTION_GAP;
|
||||
y += rows * ThemePresetCard.HEIGHT + (rows - 1) * PRESET_GAP + SECTION_GAP;
|
||||
y = PropertyList.drawSection(scroll, "Colors", y) + 10;
|
||||
y = ColorGrid.draw(scroll, properties, width, y) + SECTION_GAP;
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ import org.saturnclient.ui.resources.Textures;
|
||||
|
||||
/**
|
||||
* Saturn's title screen: the logo over the game's menus in the middle, the
|
||||
* player and a quit button in the top corners, and along the bottom a dock of
|
||||
* Saturn's screens, the shift menu and Minecraft's options, and the version.
|
||||
* player and a quit button in the top corners, and along the bottom a dock
|
||||
* (Saturn's settings, its mods and cosmetics, then Minecraft's options) and the version.
|
||||
*/
|
||||
public class TitleMenu extends SaturnScreen {
|
||||
// The logo and wordmark as the shift menu has them: the wordmark over the logo's foot
|
||||
@@ -106,12 +106,12 @@ public class TitleMenu extends SaturnScreen {
|
||||
.position(width - TOP_EDGE - QUIT_SIZE, TOP_EDGE)
|
||||
.animation(step(new SlideFade(AnimationConfig.mainMenu, 8), STEP_QUIT)));
|
||||
|
||||
// Along the bottom: the dock of Saturn's screens, the shift menu and Minecraft's options, and the version
|
||||
// Along the bottom: the dock, Saturn first (its settings) and Minecraft's options last, and the version
|
||||
Dock dock = new Dock(List.of(
|
||||
new Dock.Item(Textures.LOGO, () -> Providers.saturn.getClient().setScreen(new ClientSettings())),
|
||||
new Dock.Item(Textures.ICON_MODS, () -> Providers.saturn.getClient().setScreen(new ModMenu())),
|
||||
new Dock.Item(Textures.ICON_COSMETICS,
|
||||
() -> Providers.saturn.getClient().setScreen(new CosmeticsMenu())),
|
||||
new Dock.Item(Textures.LOGO, () -> Providers.saturn.getClient().setScreen(new ShiftMenu())),
|
||||
new Dock.Item(Textures.ICON_SETTINGS,
|
||||
() -> Providers.saturn.getClient().setScreen(MinecraftScreen.Options))));
|
||||
draw(dock.position((width - dock.width) / 2, height - EDGE - Dock.HEIGHT)
|
||||
|
||||
Reference in New Issue
Block a user