mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-11-08 12:35:01 +00:00
Make dynamic lights config less heavy (#2051)
This commit is contained in:
1 parent
67f2484976
commit
269b7245d3
12 files changed
+535
-157
No files matched your search
@@ -0,0 +1,96 @@
|
||||
package com.gtnewhorizons.angelica.client.gui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public record DynamicLightsEntityFilter(List<String> modPrefixes, List<String> nameTerms, DynamicLightsEntityFilter.State state) {
|
||||
|
||||
public enum State {
|
||||
ANY,
|
||||
ENABLED,
|
||||
DISABLED
|
||||
}
|
||||
|
||||
private static final Pattern WHITESPACE = Pattern.compile("\\s+");
|
||||
private static final DynamicLightsEntityFilter MATCH_ALL = new DynamicLightsEntityFilter(List.of(), List.of(), State.ANY);
|
||||
|
||||
public DynamicLightsEntityFilter {
|
||||
modPrefixes = List.copyOf(modPrefixes);
|
||||
nameTerms = List.copyOf(nameTerms);
|
||||
}
|
||||
|
||||
public static DynamicLightsEntityFilter parse(String query) {
|
||||
if (query == null) {
|
||||
return MATCH_ALL;
|
||||
}
|
||||
|
||||
final var normalized = query.strip().toLowerCase(Locale.ROOT);
|
||||
if (normalized.isEmpty()) {
|
||||
return MATCH_ALL;
|
||||
}
|
||||
|
||||
final var modPrefixes = new ArrayList<String>();
|
||||
final var nameTerms = new ArrayList<String>();
|
||||
var wantEnabled = false;
|
||||
var wantDisabled = false;
|
||||
|
||||
for (final var token : WHITESPACE.split(normalized)) {
|
||||
switch (token) {
|
||||
case "$on" -> wantEnabled = true;
|
||||
case "$off" -> wantDisabled = true;
|
||||
default -> {
|
||||
if (token.length() > 1 && token.charAt(0) == '@') {
|
||||
modPrefixes.add(token.substring(1));
|
||||
} else {
|
||||
nameTerms.add(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final var state = wantEnabled == wantDisabled ? State.ANY : wantEnabled ? State.ENABLED : State.DISABLED;
|
||||
if (modPrefixes.isEmpty() && nameTerms.isEmpty() && state == State.ANY) {
|
||||
return MATCH_ALL;
|
||||
}
|
||||
return new DynamicLightsEntityFilter(modPrefixes, nameTerms, state);
|
||||
}
|
||||
|
||||
public boolean isMatchAll() {
|
||||
return modPrefixes.isEmpty() && nameTerms.isEmpty() && state == State.ANY;
|
||||
}
|
||||
|
||||
public boolean matches(String lowerName, String lowerModId, boolean enabled) {
|
||||
return matchesState(enabled) && matchesAnyMod(lowerModId) && containsAllTerms(lowerName);
|
||||
}
|
||||
|
||||
private boolean matchesState(boolean enabled) {
|
||||
return switch (state) {
|
||||
case ANY -> true;
|
||||
case ENABLED -> enabled;
|
||||
case DISABLED -> !enabled;
|
||||
};
|
||||
}
|
||||
|
||||
private boolean matchesAnyMod(String lowerModId) {
|
||||
if (modPrefixes.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
for (final var prefix : modPrefixes) {
|
||||
if (lowerModId.startsWith(prefix)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean containsAllTerms(String lowerName) {
|
||||
for (final var term : nameTerms) {
|
||||
if (!lowerName.contains(term)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
package com.gtnewhorizons.angelica.client.gui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.GuiTextField;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.input.Mouse;
|
||||
|
||||
import com.gtnewhorizons.angelica.dynamiclights.config.EntityLightConfig;
|
||||
import com.gtnewhorizons.angelica.dynamiclights.config.EntityTypeEntry;
|
||||
|
||||
import net.coderbot.iris.gui.element.IrisGuiSlot;
|
||||
import net.coderbot.iris.gui.element.widget.IrisButton;
|
||||
|
||||
public class DynamicLightsEntityScreen extends GuiScreen {
|
||||
|
||||
private static final String ENABLED_PREFIX = EnumChatFormatting.GREEN + "[x] " + EnumChatFormatting.WHITE;
|
||||
private static final String DISABLED_PREFIX = EnumChatFormatting.DARK_GRAY + "[ ] " + EnumChatFormatting.GRAY;
|
||||
|
||||
private static List<EntityTypeEntry> entityTypes;
|
||||
|
||||
private final GuiScreen parent;
|
||||
private final String title = I18n.format("options.dynamiclights.entities.title");
|
||||
private final String info = I18n.format("options.dynamiclights.entities.info");
|
||||
|
||||
private List<EntityTypeEntry> displayed;
|
||||
private String countLabel;
|
||||
private String search = "";
|
||||
private boolean dirty;
|
||||
|
||||
private GuiTextField searchBox;
|
||||
private EntityRowList rowList;
|
||||
private IrisButton toggleButton;
|
||||
|
||||
public DynamicLightsEntityScreen(GuiScreen parent) {
|
||||
this.parent = parent;
|
||||
this.refilter();
|
||||
}
|
||||
|
||||
private static List<EntityTypeEntry> entityTypes() {
|
||||
if (entityTypes == null) {
|
||||
entityTypes = EntityLightConfig.getAllEntityTypes();
|
||||
}
|
||||
return entityTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initGui() {
|
||||
Keyboard.enableRepeatEvents(true);
|
||||
|
||||
this.searchBox = new GuiTextField(this.fontRendererObj, this.width / 2 - 150, 30, 300, 20);
|
||||
this.searchBox.setMaxStringLength(64);
|
||||
this.searchBox.setText(this.search);
|
||||
this.rowList = new EntityRowList();
|
||||
|
||||
this.toggleButton = new IrisButton(this.width / 2 - 154, this.height - 27, 150, 20, "", button -> this.toggleVisible());
|
||||
this.updateToggleButton();
|
||||
|
||||
this.buttonList.add(this.toggleButton);
|
||||
this.buttonList.add(new IrisButton(this.width / 2 + 4, this.height - 27, 150, 20, I18n.format("gui.done"), button -> this.onClose()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGuiClosed() {
|
||||
Keyboard.enableRepeatEvents(false);
|
||||
}
|
||||
|
||||
private void onClose() {
|
||||
if (this.dirty) {
|
||||
EntityLightConfig.save();
|
||||
this.dirty = false;
|
||||
}
|
||||
this.mc.displayGuiScreen(this.parent);
|
||||
}
|
||||
|
||||
private void refilter() {
|
||||
final var filter = DynamicLightsEntityFilter.parse(this.search);
|
||||
if (filter.isMatchAll()) {
|
||||
this.displayed = entityTypes();
|
||||
} else {
|
||||
final var matches = new ArrayList<EntityTypeEntry>();
|
||||
for (final var entry : entityTypes()) {
|
||||
if (filter.matches(entry.getSearchName(), entry.getSearchModId(), EntityLightConfig.isEntityTypeEnabled(entry.getEntityClass()))) {
|
||||
matches.add(entry);
|
||||
}
|
||||
}
|
||||
this.displayed = matches;
|
||||
}
|
||||
this.countLabel = this.displayed.size() + " / " + entityTypes().size();
|
||||
this.updateToggleButton();
|
||||
}
|
||||
|
||||
private boolean anyDisplayedEnabled() {
|
||||
for (final var entry : this.displayed) {
|
||||
if (EntityLightConfig.isEntityTypeEnabled(entry.getEntityClass())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void updateToggleButton() {
|
||||
if (this.toggleButton == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final var subset = this.displayed.size() != entityTypes().size();
|
||||
final var key = this.anyDisplayedEnabled()
|
||||
? (subset ? "options.dynamiclights.entities.disableshown" : "options.dynamiclights.entities.disableall")
|
||||
: (subset ? "options.dynamiclights.entities.enableshown" : "options.dynamiclights.entities.enableall");
|
||||
|
||||
this.toggleButton.displayString = I18n.format(key);
|
||||
this.toggleButton.enabled = !this.displayed.isEmpty();
|
||||
}
|
||||
|
||||
private void toggleVisible() {
|
||||
final var enable = !this.anyDisplayedEnabled();
|
||||
for (final var entry : this.displayed) {
|
||||
EntityLightConfig.setEntityTypeEnabled(entry.getEntityClass(), enable);
|
||||
}
|
||||
this.dirty = true;
|
||||
this.refilter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawScreen(int mouseX, int mouseY, float partialTicks) {
|
||||
this.drawDefaultBackground();
|
||||
this.rowList.drawScreen(mouseX, mouseY, partialTicks);
|
||||
super.drawScreen(mouseX, mouseY, partialTicks);
|
||||
|
||||
drawCenteredString(this.fontRendererObj, this.title, this.width / 2, 8, 0xFFFFFF);
|
||||
drawCenteredString(this.fontRendererObj, this.info, this.width / 2, 20, 0xA0A0A0);
|
||||
this.searchBox.drawTextBox();
|
||||
if (!this.searchBox.isFocused() && this.search.isEmpty()) {
|
||||
this.drawString(this.fontRendererObj, I18n.format("options.dynamiclights.entities.search"), this.width / 2 - 144, 36, 0x808080);
|
||||
}
|
||||
drawCenteredString(this.fontRendererObj, this.countLabel, this.width / 2, this.height - 39, 0x808080);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateScreen() {
|
||||
this.searchBox.updateCursorCounter();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) {
|
||||
if (!this.rowList.mouseClicked(mouseX, mouseY, mouseButton)) {
|
||||
super.mouseClicked(mouseX, mouseY, mouseButton);
|
||||
}
|
||||
this.searchBox.mouseClicked(mouseX, mouseY, mouseButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseMovedOrUp(int mouseX, int mouseY, int state) {
|
||||
if (state == -1 || !this.rowList.mouseReleased(mouseX, mouseY, Mouse.getEventButton())) {
|
||||
super.mouseMovedOrUp(mouseX, mouseY, state);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void actionPerformed(GuiButton button) {
|
||||
if (button.enabled && button instanceof IrisButton irisButton) {
|
||||
irisButton.onPress();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void keyTyped(char typedChar, int keyCode) {
|
||||
if (this.searchBox.isFocused()) {
|
||||
if (keyCode == Keyboard.KEY_ESCAPE) {
|
||||
this.searchBox.setFocused(false);
|
||||
return;
|
||||
}
|
||||
this.searchBox.textboxKeyTyped(typedChar, keyCode);
|
||||
if (!this.searchBox.getText().equals(this.search)) {
|
||||
this.search = this.searchBox.getText();
|
||||
this.refilter();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (keyCode == Keyboard.KEY_ESCAPE) {
|
||||
this.onClose();
|
||||
return;
|
||||
}
|
||||
super.keyTyped(typedChar, keyCode);
|
||||
}
|
||||
|
||||
private class EntityRowList extends IrisGuiSlot {
|
||||
|
||||
EntityRowList() {
|
||||
super(DynamicLightsEntityScreen.this.mc, DynamicLightsEntityScreen.this.width, DynamicLightsEntityScreen.this.height, 56, DynamicLightsEntityScreen.this.height - 44, 18);
|
||||
this.setRenderBackground(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSize() {
|
||||
return displayed.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSelected(int index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawBackground() {}
|
||||
|
||||
@Override
|
||||
public int getListWidth() {
|
||||
return Math.min(400, DynamicLightsEntityScreen.this.width - 40);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean elementClicked(int index, boolean doubleClick, int mouseX, int mouseY, int button) {
|
||||
if (button != 0 || index >= displayed.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final var entry = displayed.get(index);
|
||||
EntityLightConfig.setEntityTypeEnabled(entry.getEntityClass(), !EntityLightConfig.isEntityTypeEnabled(entry.getEntityClass()));
|
||||
dirty = true;
|
||||
updateToggleButton();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawSlot(int index, int x, int y, int slotHeight, Tessellator tessellator, int mouseX, int mouseY) {
|
||||
final var entry = displayed.get(index);
|
||||
final var enabled = EntityLightConfig.isEntityTypeEnabled(entry.getEntityClass());
|
||||
final var label = (enabled ? ENABLED_PREFIX : DISABLED_PREFIX) + entry.getDisplayName() + EnumChatFormatting.DARK_GRAY + " (" + entry.getModId() + ")";
|
||||
|
||||
drawString(fontRendererObj, fontRendererObj.trimStringToWidth(label, this.getListWidth() - 8), x, y + 5, 0xFFFFFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,105 +1,32 @@
|
||||
package com.gtnewhorizons.angelica.client.gui;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.gtnewhorizons.angelica.dynamiclights.DynamicLights;
|
||||
import com.gtnewhorizons.angelica.dynamiclights.config.EntityLightConfig;
|
||||
import com.gtnewhorizons.angelica.dynamiclights.config.EntityLightConfigStorage;
|
||||
import com.gtnewhorizons.angelica.dynamiclights.config.EntityTypeEntry;
|
||||
import jss.notfine.core.Settings;
|
||||
import me.jellysquid.mods.sodium.client.gui.options.Option;
|
||||
import me.jellysquid.mods.sodium.client.gui.options.OptionGroup;
|
||||
import me.jellysquid.mods.sodium.client.gui.options.OptionImpl;
|
||||
import me.jellysquid.mods.sodium.client.gui.options.OptionImpact;
|
||||
import me.jellysquid.mods.sodium.client.gui.options.OptionPage;
|
||||
import me.jellysquid.mods.sodium.client.gui.options.control.TickBoxControl;
|
||||
import me.jellysquid.mods.sodium.client.gui.options.SubScreenOption;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class DynamicLightsOptionPages {
|
||||
|
||||
public static OptionPage dynamicLights() {
|
||||
if (!DynamicLights.configEnabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<OptionGroup> groups = new ArrayList<>();
|
||||
|
||||
groups.add(OptionGroup.createBuilder()
|
||||
.add(Settings.DYNAMIC_LIGHTS.option)
|
||||
.add(Settings.DYNAMIC_LIGHTS_SHADER_FORCE.option)
|
||||
.build());
|
||||
|
||||
groups.add(OptionGroup.createBuilder()
|
||||
.add(Settings.DYNAMIC_LIGHTS_FRUSTUM_CULLING.option)
|
||||
.add(Settings.DYNAMIC_LIGHTS_ADAPTIVE_TICKING.option)
|
||||
.add(Settings.DYNAMIC_LIGHTS_CULL_TIMEOUT.option)
|
||||
.build());
|
||||
|
||||
groups.add(OptionGroup.createBuilder()
|
||||
.add(Settings.DYNAMIC_LIGHTS_SLOW_DIST.option)
|
||||
.add(Settings.DYNAMIC_LIGHTS_SLOWER_DIST.option)
|
||||
.add(Settings.DYNAMIC_LIGHTS_BACKGROUND_DIST.option)
|
||||
.build());
|
||||
|
||||
// Entity type toggles - grouped by mod ID
|
||||
List<EntityTypeEntry> allEntities = EntityLightConfig.getAllEntityTypes();
|
||||
Map<String, List<EntityTypeEntry>> byMod = new LinkedHashMap<>();
|
||||
|
||||
for (EntityTypeEntry entry : allEntities) {
|
||||
byMod.computeIfAbsent(entry.getModId(), _ -> new ArrayList<>()).add(entry);
|
||||
}
|
||||
|
||||
// Create a group for each mod's entities
|
||||
for (Map.Entry<String, List<EntityTypeEntry>> modEntry : byMod.entrySet()) {
|
||||
String modId = modEntry.getKey();
|
||||
List<EntityTypeEntry> entities = modEntry.getValue();
|
||||
|
||||
OptionGroup.Builder groupBuilder = OptionGroup.createBuilder();
|
||||
|
||||
for (EntityTypeEntry entity : entities) {
|
||||
Option<Boolean> option = createEntityOption(entity);
|
||||
if (option != null) {
|
||||
groupBuilder.add(option);
|
||||
}
|
||||
}
|
||||
|
||||
// Only add group if it has options
|
||||
OptionGroup group = groupBuilder.build();
|
||||
if (!group.getOptions().isEmpty()) {
|
||||
groups.add(group);
|
||||
}
|
||||
}
|
||||
|
||||
return new OptionPage(I18n.format("options.dynamiclights.page"), ImmutableList.copyOf(groups));
|
||||
}
|
||||
|
||||
private static Option<Boolean> createEntityOption(EntityTypeEntry entry) {
|
||||
final String className = entry.getClassName();
|
||||
|
||||
// Resolve class once during option creation, not on every get/set
|
||||
Class<?> resolvedClass;
|
||||
try {
|
||||
resolvedClass = Class.forName(className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
// Class not loaded, skip this option
|
||||
return null;
|
||||
}
|
||||
|
||||
final Class<?> entityClass = resolvedClass;
|
||||
|
||||
return OptionImpl.createBuilder(Boolean.class, EntityLightConfigStorage.INSTANCE)
|
||||
.setName(entry.getDisplayName() + " (" + entry.getModId() + ")")
|
||||
.setTooltip(I18n.format("options.dynamiclights.entity.tooltip", entry.getDisplayName()))
|
||||
.setControl(TickBoxControl::new)
|
||||
.setBinding(
|
||||
(_, value) -> EntityLightConfig.setEntityTypeEnabled(entityClass, value),
|
||||
storage -> EntityLightConfig.isEntityTypeEnabled(entityClass)
|
||||
)
|
||||
.setImpact(OptionImpact.LOW)
|
||||
.build();
|
||||
return new OptionPage(I18n.format("options.dynamiclights.page"), ImmutableList.of(
|
||||
OptionGroup.createBuilder()
|
||||
.add(Settings.DYNAMIC_LIGHTS.option)
|
||||
.add(Settings.DYNAMIC_LIGHTS_SHADER_FORCE.option)
|
||||
.build(),
|
||||
OptionGroup.createBuilder()
|
||||
.add(Settings.DYNAMIC_LIGHTS_FRUSTUM_CULLING.option)
|
||||
.add(Settings.DYNAMIC_LIGHTS_ADAPTIVE_TICKING.option)
|
||||
.add(Settings.DYNAMIC_LIGHTS_CULL_TIMEOUT.option)
|
||||
.build(),
|
||||
OptionGroup.createBuilder()
|
||||
.add(Settings.DYNAMIC_LIGHTS_SLOW_DIST.option)
|
||||
.add(Settings.DYNAMIC_LIGHTS_SLOWER_DIST.option)
|
||||
.add(Settings.DYNAMIC_LIGHTS_BACKGROUND_DIST.option)
|
||||
.build(),
|
||||
OptionGroup.createBuilder()
|
||||
.add(new SubScreenOption(I18n.format("options.dynamiclights.entities"), I18n.format("options.dynamiclights.entities.tooltip"), DynamicLightsEntityScreen::new))
|
||||
.build()));
|
||||
}
|
||||
}
|
||||
+1
-3
@@ -71,7 +71,6 @@ public final class EntityLightConfig {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static List<EntityTypeEntry> getAllEntityTypes() {
|
||||
List<EntityTypeEntry> entries = new ArrayList<>();
|
||||
Set<String> seenClasses = new HashSet<>();
|
||||
@@ -88,9 +87,8 @@ public final class EntityLightConfig {
|
||||
|
||||
String modId = getModIdForEntity(entityClass, entityId);
|
||||
String displayName = getDisplayName(entityId, entityClass);
|
||||
boolean enabled = !disabledClassNames.contains(className);
|
||||
|
||||
entries.add(new EntityTypeEntry(displayName, className, modId, enabled));
|
||||
entries.add(new EntityTypeEntry(displayName, entityClass, modId));
|
||||
}
|
||||
|
||||
// Sort by mod ID, then by display name
|
||||
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
package com.gtnewhorizons.angelica.dynamiclights.config;
|
||||
|
||||
import me.jellysquid.mods.sodium.client.gui.options.storage.OptionStorage;
|
||||
|
||||
public class EntityLightConfigStorage implements OptionStorage<EntityLightConfigStorage> {
|
||||
|
||||
public static final EntityLightConfigStorage INSTANCE = new EntityLightConfigStorage();
|
||||
|
||||
private EntityLightConfigStorage() {}
|
||||
|
||||
@Override
|
||||
public EntityLightConfigStorage getData() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
EntityLightConfig.save();
|
||||
}
|
||||
}
|
||||
+20
-15
@@ -1,42 +1,47 @@
|
||||
package com.gtnewhorizons.angelica.dynamiclights.config;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class EntityTypeEntry {
|
||||
private final String displayName;
|
||||
private final String className;
|
||||
private final String modId;
|
||||
private boolean enabled;
|
||||
public final class EntityTypeEntry {
|
||||
|
||||
public EntityTypeEntry(@NotNull String displayName, @NotNull String className, @NotNull String modId, boolean enabled) {
|
||||
private final String displayName;
|
||||
private final Class<?> entityClass;
|
||||
private final String modId;
|
||||
private final String searchName;
|
||||
private final String searchModId;
|
||||
|
||||
public EntityTypeEntry(@NotNull String displayName, @NotNull Class<?> entityClass, @NotNull String modId) {
|
||||
this.displayName = displayName;
|
||||
this.className = className;
|
||||
this.entityClass = entityClass;
|
||||
this.modId = modId;
|
||||
this.enabled = enabled;
|
||||
this.searchName = displayName.toLowerCase(Locale.ROOT);
|
||||
this.searchModId = modId.toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return className;
|
||||
public Class<?> getEntityClass() {
|
||||
return entityClass;
|
||||
}
|
||||
|
||||
public String getModId() {
|
||||
return modId;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
public String getSearchName() {
|
||||
return searchName;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
public String getSearchModId() {
|
||||
return searchModId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return displayName + " (" + modId + ") [" + (enabled ? "ON" : "OFF") + "]";
|
||||
return displayName + " (" + modId + ")";
|
||||
}
|
||||
}
|
||||
+1
-10
@@ -202,16 +202,7 @@ public class ReeseSodiumVideoOptionsScreen extends SodiumOptionsGUI {
|
||||
}
|
||||
|
||||
private void updateControls() {
|
||||
boolean hasChanges = this.getAllOptions()
|
||||
.anyMatch(Option::hasChanged);
|
||||
|
||||
for (OptionPage page : this.pages) {
|
||||
for (Option<?> option : page.getOptions()) {
|
||||
if (option.hasChanged()) {
|
||||
hasChanges = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
final boolean hasChanges = this.getAllOptions().anyMatch(Option::hasChanged);
|
||||
|
||||
this.applyButton.setEnabled(hasChanges);
|
||||
this.undoButton.setVisible(hasChanges);
|
||||
|
||||
@@ -54,7 +54,6 @@ public class SodiumOptionsGUI extends ScrollableGuiScreen {
|
||||
|
||||
protected OptionPage shaderPacks;
|
||||
|
||||
|
||||
public SodiumOptionsGUI(GuiScreen prevScreen) {
|
||||
this.prevScreen = prevScreen;
|
||||
|
||||
@@ -67,10 +66,7 @@ public class SodiumOptionsGUI extends ScrollableGuiScreen {
|
||||
|
||||
// Add Dynamic Lights page if enabled
|
||||
if (DynamicLights.configEnabled) {
|
||||
var dlPage = DynamicLightsOptionPages.dynamicLights();
|
||||
if (dlPage != null) {
|
||||
this.pages.add(dlPage);
|
||||
}
|
||||
this.pages.add(DynamicLightsOptionPages.dynamicLights());
|
||||
}
|
||||
|
||||
if (Iris.enabled) {
|
||||
@@ -194,15 +190,7 @@ public class SodiumOptionsGUI extends ScrollableGuiScreen {
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
boolean hasChanges = this.getAllOptions().anyMatch(Option::hasChanged);
|
||||
|
||||
for (OptionPage page : this.pages) {
|
||||
for (Option<?> option : page.getOptions()) {
|
||||
if (option.hasChanged()) {
|
||||
hasChanges = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
final boolean hasChanges = this.getAllOptions().anyMatch(Option::hasChanged);
|
||||
|
||||
this.applyButton.setEnabled(hasChanges);
|
||||
this.undoButton.setVisible(hasChanges);
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
package me.jellysquid.mods.sodium.client.gui.options;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.function.Function;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
|
||||
import me.jellysquid.mods.sodium.client.gui.options.control.Control;
|
||||
import me.jellysquid.mods.sodium.client.gui.options.control.ControlElement;
|
||||
import me.jellysquid.mods.sodium.client.gui.options.control.element.ControlElementFactory;
|
||||
import me.jellysquid.mods.sodium.client.gui.options.control.element.SodiumControlElement;
|
||||
import me.jellysquid.mods.sodium.client.gui.options.storage.OptionStorage;
|
||||
import me.jellysquid.mods.sodium.client.util.Dim2i;
|
||||
|
||||
/** "Option" that opens a sub screen */
|
||||
public class SubScreenOption implements Option<Void> {
|
||||
|
||||
private static final int ARROW_HOVERED = 0xFF94E4D3;
|
||||
private static final int ARROW_IDLE = 0xFFAAAAAA;
|
||||
private static final String ARROW = ">";
|
||||
|
||||
private static final OptionStorage<Void> NO_STORAGE = new OptionStorage<Void>() {
|
||||
|
||||
@Override
|
||||
public Void getData() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {}
|
||||
};
|
||||
|
||||
private final String name;
|
||||
private final String tooltip;
|
||||
private final Function<GuiScreen, GuiScreen> destination;
|
||||
private final Control<Void> control = new SubScreenControl(this);
|
||||
|
||||
public SubScreenOption(String name, String tooltip, Function<GuiScreen, GuiScreen> destination) {
|
||||
this.name = name;
|
||||
this.tooltip = tooltip;
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
private void open() {
|
||||
final var mc = Minecraft.getMinecraft();
|
||||
mc.displayGuiScreen(this.destination.apply(mc.currentScreen));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTooltip() {
|
||||
return this.tooltip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OptionImpact getImpact() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Control<Void> getControl() {
|
||||
return this.control;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void getValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Void value) {}
|
||||
|
||||
@Override
|
||||
public void reset() {}
|
||||
|
||||
@Override
|
||||
public OptionStorage<?> getStorage() {
|
||||
return NO_STORAGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasChanged() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyChanges() {}
|
||||
|
||||
@Override
|
||||
public Collection<OptionFlag> getFlags() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
private record SubScreenControl(SubScreenOption target) implements Control<Void> {
|
||||
|
||||
@Override
|
||||
public Option<Void> getOption() {
|
||||
return this.target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ControlElement<Void> createElement(Dim2i dim, ControlElementFactory factory) {
|
||||
return new SubScreenElement(this.target, dim);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxWidth() {
|
||||
return 30;
|
||||
}
|
||||
}
|
||||
|
||||
private static class SubScreenElement extends SodiumControlElement<Void> {
|
||||
|
||||
private final SubScreenOption target;
|
||||
|
||||
SubScreenElement(SubScreenOption option, Dim2i dim) {
|
||||
super(option, dim);
|
||||
this.target = option;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(int mouseX, int mouseY, float delta) {
|
||||
super.render(mouseX, mouseY, delta);
|
||||
|
||||
final var width = this.font.getStringWidth(ARROW);
|
||||
this.drawString(ARROW, this.dim.getLimitX() - width - 6, this.dim.getCenterY() - 4, this.hovered ? ARROW_HOVERED : ARROW_IDLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||
if (button != 0 || !this.dim.containsCursor(mouseX, mouseY)) return false;
|
||||
|
||||
this.playClickSound();
|
||||
this.target.open();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -190,10 +190,14 @@ options.dynamic_lights_cull_timeout=Culling Timeout (ticks)
|
||||
options.dynamic_lights_cull_timeout.tooltip=Maximum ticks a hidden chunk can wait before being forced to rebuild. Lower = more responsive but more GPU work.
|
||||
options.dynamiclights.page=Dynamic Lights
|
||||
options.dynamiclights.entities=Configure Entities...
|
||||
options.dynamiclights.entities.tooltip=Choose which entity types emit dynamic light.
|
||||
options.dynamiclights.entities.title=Dynamic Lights - Entities
|
||||
options.dynamiclights.entities.info=Toggle which entity types emit dynamic light. Some entries are for mod compatibility.
|
||||
options.dynamiclights.entities.search=Search (@mod, $on, $off)
|
||||
options.dynamiclights.entity.tooltip=Toggle dynamic lighting for %s entities. Disable to improve performance if this entity type emits unwanted lights.
|
||||
options.dynamiclights.entities.enableall=Enable All
|
||||
options.dynamiclights.entities.disableall=Disable All
|
||||
options.dynamiclights.entities.enableshown=Enable Shown
|
||||
options.dynamiclights.entities.disableshown=Disable Shown
|
||||
|
||||
options.angelica.search.no_results=No matching options
|
||||
options.angelica.fontconfig=Font Configuration...
|
||||
|
||||
@@ -161,7 +161,6 @@ options.dynamiclights.entities=エンティティの設定...
|
||||
options.dynamiclights.entities.title=ダイナミックライト- エンティティ
|
||||
options.dynamiclights.entities.info=ダイナミックライトを適用するエンティティの種類を設定します。一部の項目はMODとの互換性のために設定されています。
|
||||
options.dynamiclights.entities.search=検索 (@mod, $on, $off)
|
||||
options.dynamiclights.entity.tooltip=%sのエンティティのダイナミックライトを設定します。そのエンティティタイプが不要な光を発する場合は、パフォーマンス向上のために無効にしてください。
|
||||
|
||||
options.angelica.search.no_results=該当する設定が見つかりません
|
||||
options.angelica.fontconfig=フォント設定...
|
||||
|
||||
@@ -164,7 +164,6 @@ options.dynamiclights.entities=配置实体……
|
||||
options.dynamiclights.entities.title=动态光源 - 实体
|
||||
options.dynamiclights.entities.info=切换哪些实体类型发射动态光。部分条目用于模组兼容性。
|
||||
options.dynamiclights.entities.search=搜索(@模组, $开启, $关闭)
|
||||
options.dynamiclights.entity.tooltip=切换 %s 实体的动态光照。如果此类型实体产生不必要光照,禁用以提升性能。
|
||||
|
||||
options.angelica.search.no_results=无匹配选项
|
||||
options.angelica.fontconfig=字体配置...
|
||||
|
||||
Reference in new issue
Block a user