The Animations section shows each menu's duration, stagger and curve under the menu's name instead of one flat list of 18 rows. AnimationConfig keeps its name and lists every menu's config; it's saved under the same keys as before, so existing settings keep loading. Co-Authored-By: Claude Opus 5.5 <[email protected]>
164 lines
6.3 KiB
Java
164 lines
6.3 KiB
Java
package org.saturnclient.ui.screens;
|
|
|
|
import java.util.LinkedHashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.function.Predicate;
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Stream;
|
|
|
|
import org.saturnclient.common.ref.asset.IdentifierRef;
|
|
import org.saturnclient.config.AnimationConfig;
|
|
import org.saturnclient.config.Config;
|
|
import org.saturnclient.config.Theme;
|
|
import org.saturnclient.config.property.ColorProperty;
|
|
import org.saturnclient.config.property.NamespaceProperty;
|
|
import org.saturnclient.config.property.Property;
|
|
import org.saturnclient.ui.PanelScreen;
|
|
import org.saturnclient.ui.components.ColorGrid;
|
|
import org.saturnclient.ui.components.PropertyList;
|
|
import org.saturnclient.ui.components.SectionNav;
|
|
import org.saturnclient.ui.components.Sidebar;
|
|
import org.saturnclient.ui.components.ThemePresetCard;
|
|
import org.saturnclient.ui.elements.ActionButton;
|
|
import org.saturnclient.ui.elements.Divider;
|
|
import org.saturnclient.ui.elements.Label;
|
|
import org.saturnclient.ui.elements.Scroll;
|
|
import org.saturnclient.ui.resources.Textures;
|
|
|
|
/**
|
|
* The client's own settings, split into sections picked from a list on the left.
|
|
*/
|
|
public class ClientSettings extends PanelScreen {
|
|
private enum Section {
|
|
GENERAL("General", "Title screen, emotes and cosmetics", Textures.ICON_SLIDERS),
|
|
UI_STYLE("UI Style", "Colors, corners and font for every Saturn screen", Textures.ICON_PALETTE),
|
|
ANIMATIONS("Animations", "How long menu animations take, and their easing", Textures.ICON_ANIMATIONS);
|
|
|
|
final String title;
|
|
final String description;
|
|
final IdentifierRef icon;
|
|
|
|
Section(String title, String description, IdentifierRef icon) {
|
|
this.title = title;
|
|
this.description = description;
|
|
this.icon = icon;
|
|
}
|
|
}
|
|
|
|
private static final int NAV_WIDTH = 170;
|
|
private static final int NAV_GAP = 16;
|
|
private static final int LIST_Y = 58;
|
|
private static final int SECTION_GAP = 22;
|
|
private static final int PRESET_GAP = 10;
|
|
|
|
private Section section = Section.GENERAL;
|
|
|
|
public ClientSettings() {
|
|
super("Settings", Sidebar.SETTINGS);
|
|
}
|
|
|
|
@Override
|
|
protected void panel() {
|
|
List<SectionNav.Item> items = Stream.of(Section.values())
|
|
.map(s -> new SectionNav.Item(s.icon, s.title))
|
|
.toList();
|
|
|
|
draw(new SectionNav("SATURN CLIENT", items, section.ordinal(), NAV_WIDTH, i -> {
|
|
section = Section.values()[i];
|
|
init();
|
|
}).position(contentX, contentY + 4));
|
|
|
|
int dividerX = contentX + NAV_WIDTH + NAV_GAP;
|
|
draw(new Divider(1).dimensions(1, panelHeight).position(dividerX, panelY));
|
|
|
|
int x = dividerX + 1 + NAV_GAP + 4;
|
|
int width = contentX + contentWidth - x;
|
|
|
|
// Header
|
|
draw(new Label(() -> section.title, 1.15f, () -> Theme.FONT.value, () -> Theme.FOREGROUND.value)
|
|
.position(x, contentY + 2));
|
|
draw(new Label(() -> section.description, 0.66f, Theme::getBodyFont, Theme::getMutedFg)
|
|
.position(x, contentY + 28));
|
|
|
|
ActionButton reset = new ActionButton(Textures.ICON_RESET, "Reset", true, this::reset);
|
|
draw(reset.position(x + width - reset.width, contentY + 4));
|
|
|
|
// The section's settings
|
|
Scroll scroll = new Scroll(0).noBackground();
|
|
int listWidth = scrollContentWidth(width);
|
|
|
|
switch (section) {
|
|
case GENERAL -> PropertyList.draw(scroll, getGeneralProperties(), Set.of(), listWidth, 0);
|
|
case UI_STYLE -> drawUiStyle(scroll, listWidth);
|
|
case ANIMATIONS -> drawAnimations(scroll, listWidth);
|
|
}
|
|
|
|
draw(scroll.dimensions(scrollWidth(width), contentHeight - LIST_Y).position(x, contentY + LIST_Y));
|
|
}
|
|
|
|
private void drawUiStyle(Scroll scroll, int width) {
|
|
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();
|
|
|
|
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));
|
|
}
|
|
|
|
y += ThemePresetCard.HEIGHT + SECTION_GAP;
|
|
y = PropertyList.drawSection(scroll, "Colors", y) + 10;
|
|
y = ColorGrid.draw(scroll, properties, width, y) + SECTION_GAP;
|
|
|
|
y = PropertyList.drawSection(scroll, "Shape & type", y) + 4;
|
|
PropertyList.draw(scroll, properties, getNames(properties, p -> p instanceof ColorProperty), width, y);
|
|
}
|
|
|
|
/**
|
|
* Each menu's animation settings under the menu's name.
|
|
*/
|
|
private static void drawAnimations(Scroll scroll, int width) {
|
|
int y = 0;
|
|
|
|
for (AnimationConfig animation : AnimationConfig.ALL) {
|
|
y = PropertyList.drawSection(scroll, animation.name, y) + 4;
|
|
y = PropertyList.draw(scroll, animation.getProperties(), Set.of(), width, y) + SECTION_GAP;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The top-level settings. The namespaces have sections of their own.
|
|
*/
|
|
private static Map<String, Property> getGeneralProperties() {
|
|
return Config.config.getProperties().entrySet().stream()
|
|
.filter(e -> !(e.getValue() instanceof NamespaceProperty))
|
|
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a,
|
|
LinkedHashMap::new));
|
|
}
|
|
|
|
private static Set<String> getNames(Map<String, Property> properties, Predicate<Property> filter) {
|
|
return properties.entrySet().stream()
|
|
.filter(e -> filter.test(e.getValue()))
|
|
.map(Map.Entry::getKey)
|
|
.collect(Collectors.toSet());
|
|
}
|
|
|
|
/**
|
|
* Puts the current section's settings back to their defaults.
|
|
*/
|
|
private void reset() {
|
|
Map<String, Property> properties = switch (section) {
|
|
case GENERAL -> getGeneralProperties();
|
|
case UI_STYLE -> Theme.config.getProperties();
|
|
case ANIMATIONS -> AnimationConfig.config.getProperties();
|
|
};
|
|
|
|
properties.values().forEach(Property::reset);
|
|
init();
|
|
}
|
|
}
|