diff --git a/src/mindustryX/features/ArcRadar.java b/src/mindustryX/features/ArcRadar.java index 9c05cebb298..d01c7e4c9a3 100644 --- a/src/mindustryX/features/ArcRadar.java +++ b/src/mindustryX/features/ArcRadar.java @@ -7,6 +7,7 @@ import arc.scene.event.*; import arc.scene.ui.layout.*; import arc.util.*; +import kotlin.collections.*; import mindustry.game.*; import mindustry.gen.*; import mindustry.graphics.*; @@ -16,7 +17,7 @@ import mindustryX.features.SettingsV2.*; import mindustryX.features.func.*; -import java.util.*; +import java.util.List; import static mindustry.Vars.*; @@ -46,23 +47,19 @@ public class ArcRadar{ private static boolean working = false; private static Table t; - private static SettingsV2.SliderPref mode, size; - public static List settings = new ArrayList<>(); + private static final SettingsV2.Data + mode = new SliderPref(1, 30, 1, s -> switch(s){ + case 0 -> "关闭"; + case 30 -> "瞬间完成"; + default -> "[lightgray]x[white]" + Strings.autoFixed(s * 0.2f, 1) + "倍搜索速度"; + }).create("radarMode", 1), + size = new SliderPref(0, 50, 1, s -> { + if(s == 0) return "固定大小"; + return "[lightgray]x[white]" + Strings.autoFixed(s * 0.1f, 1) + "倍"; + }).create("radarSize", 0); + public static List> settings = CollectionsKt.listOf(mode, size); static{ - mode = new SliderPref("radarMode", 1, 1, 30, 1); - mode.setLabelMap(s -> switch(s){ - case 0 -> "关闭"; - case 30 -> "瞬间完成"; - default -> "[lightgray]x[white]" + Strings.autoFixed(s * 0.2f, 1) + "倍搜索速度"; - }); - settings.add(mode); - size = new SliderPref("radarSize", 0, 0, 50, 1); - size.setLabelMap(s -> { - if(s == 0) return "固定大小"; - return "[lightgray]x[white]" + Strings.autoFixed(s * 0.1f, 1) + "倍"; - }); - settings.add(size); Events.on(EventType.WorldLoadEvent.class, event -> scanTime = Math.max(Mathf.dst(world.width(), world.height()) / 20f, 7.5f)); } diff --git a/src/mindustryX/features/AutoFill.kt b/src/mindustryX/features/AutoFill.kt index 08e6b801825..649975b95de 100644 --- a/src/mindustryX/features/AutoFill.kt +++ b/src/mindustryX/features/AutoFill.kt @@ -18,9 +18,9 @@ object AutoFill { @JvmField var enable = false private val transferredThisTick = mutableSetOf() - val cooldown = SettingsV2.SliderPref("autoFill.cooldown", 300, 0, 3000, 100) - val minFill = SettingsV2.SliderPref("autoFill.minFill", 5, 1, 20, 1) - val fillStorageBlock = SettingsV2.CheckPref("autoFill.fillStorageBlock") + val cooldown = SettingsV2.SliderPref(0, 3000, 100).create("autoFill.cooldown", 300) + val minFill = SettingsV2.SliderPref(1, 20, 1).create("autoFill.minFill", 5) + val fillStorageBlock = SettingsV2.CheckPref.create("autoFill.fillStorageBlock") val settings = listOf(cooldown, minFill, fillStorageBlock) private var timer = Interval() diff --git a/src/mindustryX/features/SettingsV2.kt b/src/mindustryX/features/SettingsV2.kt index 90cb7a9117e..b177f38f10d 100644 --- a/src/mindustryX/features/SettingsV2.kt +++ b/src/mindustryX/features/SettingsV2.kt @@ -2,7 +2,6 @@ package mindustryX.features import arc.Core import arc.input.KeyCode -import arc.scene.Element import arc.scene.event.ClickListener import arc.scene.event.InputEvent import arc.scene.event.Touchable @@ -13,6 +12,7 @@ import arc.util.Log import arc.util.Reflect import arc.util.Time import mindustry.Vars +import mindustry.gen.Icon import mindustry.ui.Styles import mindustry.ui.dialogs.BaseDialog @@ -21,154 +21,152 @@ import mindustry.ui.dialogs.BaseDialog * 接口与Core.settings解耦,所有设置项将在实例化时读取 * 所有读取修改应该通过value字段进行 */ -object SettingsV2 { - val ALL = mutableMapOf() - interface ISetting { - var changed: Boolean - val name: String - fun load() - fun build(table: Table) - } +object SettingsV2 { + data class Data(val name: String, val def: T, val ext: SettingExt, var persistentProvider: PersistentProvider? = PersistentProvider.Arc) { + private val changedSet = mutableSetOf() + var value: T = def + set(value) { + val v = ext.transformValue(value) + if (v == field) return + field = value + persistentProvider?.set(name, value) + changedSet.clear() + } - abstract class BaseSetting : ISetting { - //所有子类都有 value, def字段,因为泛型涉及到包装,此处不声明 - override var changed: Boolean = true - get() { - if (!field) return false - field = false - return field + init { + if (name in ALL) + Log.warn("Settings initialized!: $name") + ALL[name] = this + persistentProvider?.run { + value = get(name, def) } + } + + @JvmOverloads + fun changed(name: String = "DEFAULT"): Boolean { + return changedSet.add(name) + } //util - protected val title get() = Core.bundle.get("setting.${name}.name", name) - protected fun Element.addDesc() { - val desc = Core.bundle.getOrNull("setting.${name}.description") ?: return - Vars.ui.addDescTooltip(this, desc) + val title: String get() = Core.bundle.get("setting.${name}.name", name) + fun resetDefault() { + persistentProvider?.reset(name) + value = def + } + + fun buildUI(table: Table) { + Table().apply { + button(Icon.undo, Styles.clearNonei) { resetDefault() }.tooltip("@settings.reset") + .fillY().disabled { value == def } + ext.build(this@Data, this) + + Core.bundle.getOrNull("setting.${name}.description")?.let { + Vars.ui.addDescTooltip(this, it) + } + table.add(this).left().row() + } } } - data class CheckPref(override val name: String, val def: Boolean = false) : BaseSetting() { - var value = def - set(value) { - if (value == field) return - field = value + sealed interface PersistentProvider { + fun get(name: String, def: T): T + fun set(name: String, value: T) + fun reset(name: String) + + data object Arc : PersistentProvider { + override fun get(name: String, def: T): T { + @Suppress("UNCHECKED_CAST") + return Core.settings.get(name, def) as T + } + + override fun set(name: String, value: T) { Core.settings.put(name, value) - changed = true } - override fun load() { - value = Core.settings.getBool(name, def) + override fun reset(name: String) { + Core.settings.remove(name) + } } + } - override fun build(table: Table) { - val box = CheckBox(title) - box.changed { value = box.isChecked } - box.update { box.isChecked = value } - box.addDesc() - table.add(box).left().padTop(3f).row() - } + sealed interface SettingExt { + fun transformValue(value: T): T = value + fun build(s: Data, table: Table) - init { - register() - } + //util + fun create(name: String, def: T) = Data(name, def, this) + fun create(name: String, def: T, persistentProvider: PersistentProvider?) = Data(name, def, this, persistentProvider) } - data class SliderPref(override val name: String, val def: Int, val min: Int, val max: Int, val step: Int = 1) : BaseSetting() { - var value = def - set(value) { - field = value.coerceIn(min, max) - Core.settings.put(name, field) - changed = true - } - var labelMap: (Int) -> String = { it.toString() } - - override fun load() { - value = Core.settings.getInt(name, def) + data object CheckPref : SettingExt { + override fun build(s: Data, table: Table) { + val box = CheckBox(s.title) + box.changed { s.value = box.isChecked } + box.update { box.isChecked = s.value } + table.add(box).left().padTop(3f) } - override fun build(table: Table) { + fun create(name: String) = create(name, false) + } + + data class SliderPref @JvmOverloads constructor(val min: Int, val max: Int, val step: Int = 1, val labelMap: (Int) -> String = { it.toString() }) : SettingExt { + override fun transformValue(value: Int): Int = value.coerceIn(min, max) + override fun build(s: Data, table: Table) { val elem = Slider(min.toFloat(), max.toFloat(), step.toFloat(), false) - elem.changed { value = elem.value.toInt() } - elem.update { elem.value = value.toFloat() } + elem.changed { s.value = elem.value.toInt() } + elem.update { elem.value = s.value.toFloat() } val content = Table().apply { touchable = Touchable.disabled - add(title, Styles.outlineLabel).left().growX().wrap() - label { labelMap(value) }.style(Styles.outlineLabel).padLeft(10f).right().get() + add(s.title, Styles.outlineLabel).left().growX().wrap() + label { labelMap(s.value) }.style(Styles.outlineLabel).padLeft(10f).right().get() } table.stack(elem, content).minWidth(220f).growX().padTop(4f) - .also { it.get().addDesc() }.row() - } - - init { - register() } } data class ChoosePref( - override val name: String, val values: List, val def: Int = 0, - private val impl: SliderPref = SliderPref(name, def, 0, values.size - 1).apply { - labelMap = { values[it] } - } - ) : ISetting by impl - - data class TextPref(override val name: String, val def: String = "", val area: Boolean = false) : BaseSetting() { - var value = def - set(value) { - field = value - Core.settings.put(name, value) - changed = true - } + val values: List, + private val impl: SliderPref = SliderPref(0, values.size, labelMap = { values[it] }) + ) : SettingExt by impl - override fun load() { - value = Core.settings.getString(name, def) - } - - override fun build(table: Table) { - if (area) { - val elem = TextArea("") - elem.setPrefRows(5f) - elem.changed { value = elem.text } - elem.update { elem.text = value } - table.add(title).left().padTop(3f).get().addDesc() - table.row().add(elem).fillX().row() - return - } + data object TextPref : SettingExt { + override fun transformValue(value: String): String = value.trim() + override fun build(s: Data, table: Table) { val elem = TextField() - elem.changed { value = elem.text } - elem.update { elem.text = value } + elem.changed { s.value = elem.text } + elem.update { elem.text = s.value } table.table().left().padTop(3f).fillX().get().apply { - add(title).padRight(8f) + add(s.title).padRight(8f) add(elem).growX() - }.addDesc() - table.row() + } } + } - init { - register() + data object TextAreaPref : SettingExt { + override fun transformValue(value: String): String = value.trim() + override fun build(s: Data, table: Table) { + val elem = TextArea("") + elem.setPrefRows(5f) + elem.changed { s.value = elem.text } + elem.update { elem.text = s.value } + table.add(s.title).left().padTop(3f) + table.row().add(elem).colspan(2).fillX() } } - fun ISetting.register() { - if (name in ALL) - Log.warn("Settings initialized!: $name") - ALL[name] = this - load() - } + val ALL = LinkedHashMap>() - class SettingDialog(val settings: List) : BaseDialog("@settings") { + class SettingDialog(val settings: Iterable>) : BaseDialog("@settings") { init { - cont.add(Table().also { - settings.forEach { s -> s.build(it) } + cont.add(Table().also { t -> + settings.forEach { it.buildUI(t) } }).fill().row() cont.button("@settings.reset") { - settings.forEach { - Core.settings.remove(it.name) - it.load() - } + settings.forEach { it.resetDefault() } } addCloseButton() closeOnBack() @@ -177,7 +175,7 @@ object SettingsV2 { fun showFloatPanel(x: Float, y: Float) { val table = Table().apply { background(Styles.black8).margin(8f) - settings.forEach { s -> s.build(this) } + settings.forEach { it.buildUI(this) } button("@close") { this.remove() }.fillX() } Core.scene.add(table) @@ -187,9 +185,8 @@ object SettingsV2 { } } - @JvmStatic - fun bindQuickSettings(button: Button, settings: List) { + fun bindQuickSettings(button: Button, settings: Iterable>) { button.removeListener(button.clickListener) Reflect.set(Button::class.java, button, "clickListener", object : ClickListener() { private var startTime: Long = Long.MAX_VALUE diff --git a/src/mindustryX/features/UIExt.java b/src/mindustryX/features/UIExt.java index 6cd2855ef6e..f9ac6c90e58 100644 --- a/src/mindustryX/features/UIExt.java +++ b/src/mindustryX/features/UIExt.java @@ -29,6 +29,8 @@ public class UIExt{ public static WaveInfoDisplay waveInfoDisplay = new WaveInfoDisplay(); public static NewCoreItemsDisplay coreItems = new NewCoreItemsDisplay(); + public static SettingsV2.Data quickToolOffset = new SettingsV2.SliderPref(-250, 250, 10).create("quickToolOffset", 0); + public static void init(){ teamSelect = new TeamSelectDialog(); @@ -41,7 +43,7 @@ public static void init(){ ui.hudGroup.fill(t -> { t.right().name = "quickTool"; - t.update(() -> t.y = Core.settings.getInt("quickToolOffset")); + t.update(() -> t.y = quickToolOffset.getValue()); t.add(auxiliaryTools.wrapped()).growX().row(); t.add(hudSettingsTable.wrapped()).growX().row(); t.add(advanceToolTable.wrapped()).growX().row(); diff --git a/src/mindustryX/features/ui/WaveInfoDisplay.java b/src/mindustryX/features/ui/WaveInfoDisplay.java index 0389c700285..cbea3f73615 100644 --- a/src/mindustryX/features/ui/WaveInfoDisplay.java +++ b/src/mindustryX/features/ui/WaveInfoDisplay.java @@ -17,7 +17,7 @@ import static mindustry.Vars.*; public class WaveInfoDisplay extends Table{ - public static SettingsV2.CheckPref enable = new CheckPref("newWaveInfoDisplay", true); + public static SettingsV2.Data enable = CheckPref.INSTANCE.create("newWaveInfoDisplay", true); public static final float fontScl = 0.8f; private int waveOffset = 0; private final WaveInfoDialog waveInfoDialog = new WaveInfoDialog(); diff --git a/src/mindustryX/features/ui/toolTable/HudSettingsTable.java b/src/mindustryX/features/ui/toolTable/HudSettingsTable.java index 2bca336cdc3..1769bbc340b 100644 --- a/src/mindustryX/features/ui/toolTable/HudSettingsTable.java +++ b/src/mindustryX/features/ui/toolTable/HudSettingsTable.java @@ -117,8 +117,8 @@ protected void rebuild(){ checkPref("blockWeaponTargetLine"); checkPref("unitbuildplan"); sliderPref("minimapSize", 40, 400, 10, i -> i + ""); - sliderPref("quickToolOffset", -250, 250, 10, i -> i + ""); - WaveInfoDisplay.enable.build(this); + UIExt.quickToolOffset.buildUI(this); + WaveInfoDisplay.enable.buildUI(this); } private void arcQuickMsgTable(){