feat: Add macro editing UI
This commit is contained in:
@@ -10,6 +10,7 @@ import moe.nea.firmament.events.WorldKeyboardEvent
|
|||||||
import moe.nea.firmament.keybindings.SavedKeyBinding
|
import moe.nea.firmament.keybindings.SavedKeyBinding
|
||||||
import moe.nea.firmament.util.MC
|
import moe.nea.firmament.util.MC
|
||||||
import moe.nea.firmament.util.TimeMark
|
import moe.nea.firmament.util.TimeMark
|
||||||
|
import moe.nea.firmament.util.tr
|
||||||
|
|
||||||
object ComboProcessor {
|
object ComboProcessor {
|
||||||
|
|
||||||
@@ -22,18 +23,13 @@ object ComboProcessor {
|
|||||||
var isInputting = false
|
var isInputting = false
|
||||||
var lastInput = TimeMark.farPast()
|
var lastInput = TimeMark.farPast()
|
||||||
val breadCrumbs = mutableListOf<SavedKeyBinding>()
|
val breadCrumbs = mutableListOf<SavedKeyBinding>()
|
||||||
// TODO: keep breadcrumbs
|
|
||||||
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val f = SavedKeyBinding(InputUtil.GLFW_KEY_F)
|
val f = SavedKeyBinding(InputUtil.GLFW_KEY_F)
|
||||||
val one = SavedKeyBinding(InputUtil.GLFW_KEY_1)
|
val one = SavedKeyBinding(InputUtil.GLFW_KEY_1)
|
||||||
val two = SavedKeyBinding(InputUtil.GLFW_KEY_2)
|
val two = SavedKeyBinding(InputUtil.GLFW_KEY_2)
|
||||||
setActions(
|
setActions(
|
||||||
listOf(
|
MacroData.DConfig.data.comboActions
|
||||||
ComboKeyAction(CommandAction("wardrobe"), listOf(f, one)),
|
|
||||||
ComboKeyAction(CommandAction("equipment"), listOf(f, two)),
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,10 +64,24 @@ object ComboProcessor {
|
|||||||
0F
|
0F
|
||||||
)
|
)
|
||||||
val breadCrumbText = breadCrumbs.joinToString(" > ")
|
val breadCrumbText = breadCrumbs.joinToString(" > ")
|
||||||
event.context.drawText(MC.font, breadCrumbText, 0, 0, -1, true)
|
event.context.drawText(
|
||||||
|
MC.font,
|
||||||
|
tr("firmament.combo.active", "Current Combo: ").append(breadCrumbText),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
-1,
|
||||||
|
true
|
||||||
|
)
|
||||||
event.context.matrices.translate(0F, MC.font.fontHeight + 2F, 0F)
|
event.context.matrices.translate(0F, MC.font.fontHeight + 2F, 0F)
|
||||||
for ((key, value) in activeTrie.nodes) {
|
for ((key, value) in activeTrie.nodes) {
|
||||||
event.context.drawText(MC.font, Text.literal("$breadCrumbText > $key: ").append(value.label), 0, 0, -1, true)
|
event.context.drawText(
|
||||||
|
MC.font,
|
||||||
|
Text.literal("$breadCrumbText > $key: ").append(value.label),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
-1,
|
||||||
|
true
|
||||||
|
)
|
||||||
event.context.matrices.translate(0F, MC.font.fontHeight + 1F, 0F)
|
event.context.matrices.translate(0F, MC.font.fontHeight + 1F, 0F)
|
||||||
}
|
}
|
||||||
event.context.matrices.pop()
|
event.context.matrices.pop()
|
||||||
|
|||||||
@@ -1,14 +1,19 @@
|
|||||||
package moe.nea.firmament.features.macros
|
package moe.nea.firmament.features.macros
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
import moe.nea.firmament.util.MC
|
import moe.nea.firmament.util.MC
|
||||||
|
|
||||||
interface HotkeyAction {
|
@Serializable
|
||||||
|
sealed interface HotkeyAction {
|
||||||
// TODO: execute
|
// TODO: execute
|
||||||
val label: Text
|
val label: Text
|
||||||
fun execute()
|
fun execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("command")
|
||||||
data class CommandAction(val command: String) : HotkeyAction {
|
data class CommandAction(val command: String) : HotkeyAction {
|
||||||
override val label: Text
|
override val label: Text
|
||||||
get() = Text.literal("/$command")
|
get() = Text.literal("/$command")
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package moe.nea.firmament.features.macros
|
package moe.nea.firmament.features.macros
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
import moe.nea.firmament.keybindings.SavedKeyBinding
|
import moe.nea.firmament.keybindings.SavedKeyBinding
|
||||||
|
import moe.nea.firmament.util.ErrorUtil
|
||||||
|
|
||||||
sealed interface KeyComboTrie {
|
sealed interface KeyComboTrie {
|
||||||
val label: Text
|
val label: Text
|
||||||
@@ -13,28 +15,37 @@ sealed interface KeyComboTrie {
|
|||||||
val root = Branch(mutableMapOf())
|
val root = Branch(mutableMapOf())
|
||||||
for (combo in combos) {
|
for (combo in combos) {
|
||||||
var p = root
|
var p = root
|
||||||
require(combo.keys.isNotEmpty())
|
if (combo.keys.isEmpty()) {
|
||||||
|
ErrorUtil.softUserError("Key Combo for ${combo.action.label.string} is empty")
|
||||||
|
continue
|
||||||
|
}
|
||||||
for ((index, key) in combo.keys.withIndex()) {
|
for ((index, key) in combo.keys.withIndex()) {
|
||||||
val m = (p.nodes as MutableMap)
|
val m = (p.nodes as MutableMap)
|
||||||
if (index == combo.keys.lastIndex) {
|
if (index == combo.keys.lastIndex) {
|
||||||
if (key in m)
|
if (key in m) {
|
||||||
error("Overlapping actions found for ${combo.keys} (another action ${m[key]} already exists).")
|
ErrorUtil.softUserError("Overlapping actions found for ${combo.keys.joinToString(" > ")} (another action ${m[key]} already exists).")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
m[key] = Leaf(combo.action)
|
m[key] = Leaf(combo.action)
|
||||||
} else {
|
} else {
|
||||||
val c = m.getOrPut(key) { Branch(mutableMapOf()) }
|
val c = m.getOrPut(key) { Branch(mutableMapOf()) }
|
||||||
if (c !is Branch)
|
if (c !is Branch) {
|
||||||
error("Overlapping actions found for ${combo.keys} (final node exists at index $index) through another action already")
|
ErrorUtil.softUserError("Overlapping actions found for ${combo.keys} (final node exists at index $index) through another action already")
|
||||||
|
break
|
||||||
|
} else {
|
||||||
p = c
|
p = c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return root
|
return root
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class ComboKeyAction(
|
data class ComboKeyAction(
|
||||||
val action: HotkeyAction,
|
val action: HotkeyAction,
|
||||||
val keys: List<SavedKeyBinding>,
|
val keys: List<SavedKeyBinding>,
|
||||||
|
|||||||
11
src/main/kotlin/features/macros/MacroData.kt
Normal file
11
src/main/kotlin/features/macros/MacroData.kt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package moe.nea.firmament.features.macros
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import moe.nea.firmament.util.data.DataHolder
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class MacroData(
|
||||||
|
var comboActions: List<ComboKeyAction> = listOf(),
|
||||||
|
){
|
||||||
|
object DConfig : DataHolder<MacroData>(kotlinx.serialization.serializer(), "macros", ::MacroData)
|
||||||
|
}
|
||||||
161
src/main/kotlin/features/macros/MacroUI.kt
Normal file
161
src/main/kotlin/features/macros/MacroUI.kt
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
package moe.nea.firmament.features.macros
|
||||||
|
|
||||||
|
import io.github.notenoughupdates.moulconfig.gui.CloseEventListener
|
||||||
|
import io.github.notenoughupdates.moulconfig.observer.ObservableList
|
||||||
|
import io.github.notenoughupdates.moulconfig.xml.Bind
|
||||||
|
import moe.nea.firmament.annotations.Subscribe
|
||||||
|
import moe.nea.firmament.commands.thenExecute
|
||||||
|
import moe.nea.firmament.events.CommandEvent
|
||||||
|
import moe.nea.firmament.gui.config.AllConfigsGui.toObservableList
|
||||||
|
import moe.nea.firmament.gui.config.KeyBindingStateManager
|
||||||
|
import moe.nea.firmament.keybindings.SavedKeyBinding
|
||||||
|
import moe.nea.firmament.util.MC
|
||||||
|
import moe.nea.firmament.util.MoulConfigUtils
|
||||||
|
import moe.nea.firmament.util.ScreenUtil
|
||||||
|
|
||||||
|
class MacroUI {
|
||||||
|
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@Subscribe
|
||||||
|
fun onCommands(event: CommandEvent.SubCommand) {
|
||||||
|
// TODO: add button in config
|
||||||
|
event.subcommand("macros") {
|
||||||
|
thenExecute {
|
||||||
|
ScreenUtil.setScreenLater(MoulConfigUtils.loadScreen("config/macros/index", MacroUI(), null))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@field:Bind("combos")
|
||||||
|
val combos = Combos()
|
||||||
|
|
||||||
|
class Combos {
|
||||||
|
@field:Bind("actions")
|
||||||
|
val actions: ObservableList<ActionEditor> = ObservableList(
|
||||||
|
MacroData.DConfig.data.comboActions.mapTo(mutableListOf()) {
|
||||||
|
ActionEditor(it, this)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var dontSave = false
|
||||||
|
|
||||||
|
@Bind
|
||||||
|
fun beforeClose(): CloseEventListener.CloseAction {
|
||||||
|
if (!dontSave)
|
||||||
|
save()
|
||||||
|
return CloseEventListener.CloseAction.NO_OBJECTIONS_TO_CLOSE
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bind
|
||||||
|
fun addCommand() {
|
||||||
|
actions.add(
|
||||||
|
ActionEditor(
|
||||||
|
ComboKeyAction(
|
||||||
|
CommandAction("ac Hello from a Firmament Hotkey"),
|
||||||
|
listOf()
|
||||||
|
),
|
||||||
|
this
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bind
|
||||||
|
fun discard() {
|
||||||
|
dontSave = true
|
||||||
|
MC.screen?.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bind
|
||||||
|
fun saveAndClose() {
|
||||||
|
save()
|
||||||
|
MC.screen?.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bind
|
||||||
|
fun save() {
|
||||||
|
MacroData.DConfig.data.comboActions = actions.map { it.asSaveable() }
|
||||||
|
MacroData.DConfig.markDirty()
|
||||||
|
ComboProcessor.setActions(MacroData.DConfig.data.comboActions) // TODO: automatically reload those from the config on startup
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KeyBindingEditor(var binding: SavedKeyBinding, val parent: ActionEditor) {
|
||||||
|
val sm = KeyBindingStateManager(
|
||||||
|
{ binding },
|
||||||
|
{ binding = it },
|
||||||
|
::blur,
|
||||||
|
::requestFocus
|
||||||
|
)
|
||||||
|
|
||||||
|
@field:Bind
|
||||||
|
val button = sm.createButton()
|
||||||
|
|
||||||
|
init {
|
||||||
|
sm.updateLabel()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun blur() {
|
||||||
|
button.blur()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bind
|
||||||
|
fun delete() {
|
||||||
|
parent.combo.removeIf { it === this }
|
||||||
|
parent.combo.update()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun requestFocus() {
|
||||||
|
button.requestFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ActionEditor(val action: ComboKeyAction, val parent: MacroUI.Combos) {
|
||||||
|
fun asSaveable(): ComboKeyAction {
|
||||||
|
return ComboKeyAction(
|
||||||
|
CommandAction(command),
|
||||||
|
combo.map { it.binding }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@field:Bind("command")
|
||||||
|
var command: String = (action.action as CommandAction).command
|
||||||
|
|
||||||
|
@field:Bind("combo")
|
||||||
|
val combo = action.keys.map { KeyBindingEditor(it, this) }.toObservableList()
|
||||||
|
|
||||||
|
@Bind
|
||||||
|
fun formattedCombo() =
|
||||||
|
combo.joinToString(" > ") { it.binding.toString() }
|
||||||
|
|
||||||
|
@Bind
|
||||||
|
fun addStep() {
|
||||||
|
combo.add(KeyBindingEditor(SavedKeyBinding.unbound(), this))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bind
|
||||||
|
fun back() {
|
||||||
|
MC.screen?.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bind
|
||||||
|
fun delete() {
|
||||||
|
parent.actions.removeIf { it === this }
|
||||||
|
parent.actions.update()
|
||||||
|
}
|
||||||
|
@Bind
|
||||||
|
fun edit() {
|
||||||
|
MC.screen = MoulConfigUtils.loadScreen("config/macros/editor", this, MC.screen)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T> ObservableList<T>.setAll(ts: Collection<T>) {
|
||||||
|
val observer = this.observer
|
||||||
|
this.clear()
|
||||||
|
this.addAll(ts)
|
||||||
|
this.observer = observer
|
||||||
|
this.update()
|
||||||
|
}
|
||||||
@@ -40,34 +40,7 @@ class KeyBindingHandler(val name: String, val managedConfig: ManagedConfig) :
|
|||||||
{ button.blur() },
|
{ button.blur() },
|
||||||
{ button.requestFocus() }
|
{ button.requestFocus() }
|
||||||
)
|
)
|
||||||
button = object : FirmButtonComponent(
|
button = sm.createButton()
|
||||||
TextComponent(
|
|
||||||
IMinecraft.instance.defaultFontRenderer,
|
|
||||||
{ sm.label.string },
|
|
||||||
130,
|
|
||||||
TextComponent.TextAlignment.LEFT,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
), action = {
|
|
||||||
sm.onClick()
|
|
||||||
}) {
|
|
||||||
override fun keyboardEvent(event: KeyboardEvent, context: GuiImmediateContext): Boolean {
|
|
||||||
if (event is KeyboardEvent.KeyPressed) {
|
|
||||||
return sm.keyboardEvent(event.keycode, event.pressed)
|
|
||||||
}
|
|
||||||
return super.keyboardEvent(event, context)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getBackground(context: GuiImmediateContext): NinePatch<MyResourceLocation> {
|
|
||||||
if (sm.editing) return activeBg
|
|
||||||
return super.getBackground(context)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override fun onLostFocus() {
|
|
||||||
sm.onLostFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sm.updateLabel()
|
sm.updateLabel()
|
||||||
return button
|
return button
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
package moe.nea.firmament.gui.config
|
package moe.nea.firmament.gui.config
|
||||||
|
|
||||||
|
import io.github.notenoughupdates.moulconfig.common.IMinecraft
|
||||||
|
import io.github.notenoughupdates.moulconfig.common.MyResourceLocation
|
||||||
|
import io.github.notenoughupdates.moulconfig.deps.libninepatch.NinePatch
|
||||||
|
import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
|
||||||
|
import io.github.notenoughupdates.moulconfig.gui.KeyboardEvent
|
||||||
|
import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
|
||||||
import org.lwjgl.glfw.GLFW
|
import org.lwjgl.glfw.GLFW
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
import net.minecraft.util.Formatting
|
import net.minecraft.util.Formatting
|
||||||
|
import moe.nea.firmament.gui.FirmButtonComponent
|
||||||
import moe.nea.firmament.keybindings.SavedKeyBinding
|
import moe.nea.firmament.keybindings.SavedKeyBinding
|
||||||
|
|
||||||
class KeyBindingStateManager(
|
class KeyBindingStateManager(
|
||||||
@@ -51,9 +58,11 @@ class KeyBindingStateManager(
|
|||||||
) {
|
) {
|
||||||
lastPressed = ch
|
lastPressed = ch
|
||||||
} else {
|
} else {
|
||||||
setValue(SavedKeyBinding(
|
setValue(
|
||||||
|
SavedKeyBinding(
|
||||||
ch, modifiers
|
ch, modifiers
|
||||||
))
|
)
|
||||||
|
)
|
||||||
editing = false
|
editing = false
|
||||||
blur()
|
blur()
|
||||||
lastPressed = 0
|
lastPressed = 0
|
||||||
@@ -104,5 +113,34 @@ class KeyBindingStateManager(
|
|||||||
label = stroke
|
label = stroke
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun createButton(): FirmButtonComponent {
|
||||||
|
return object : FirmButtonComponent(
|
||||||
|
TextComponent(
|
||||||
|
IMinecraft.instance.defaultFontRenderer,
|
||||||
|
{ this@KeyBindingStateManager.label.string },
|
||||||
|
130,
|
||||||
|
TextComponent.TextAlignment.LEFT,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
), action = {
|
||||||
|
this@KeyBindingStateManager.onClick()
|
||||||
|
}) {
|
||||||
|
override fun keyboardEvent(event: KeyboardEvent, context: GuiImmediateContext): Boolean {
|
||||||
|
if (event is KeyboardEvent.KeyPressed) {
|
||||||
|
return this@KeyBindingStateManager.keyboardEvent(event.keycode, event.pressed)
|
||||||
|
}
|
||||||
|
return super.keyboardEvent(event, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getBackground(context: GuiImmediateContext): NinePatch<MyResourceLocation> {
|
||||||
|
if (this@KeyBindingStateManager.editing) return activeBg
|
||||||
|
return super.getBackground(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onLostFocus() {
|
||||||
|
this@KeyBindingStateManager.onLostFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,8 @@ data class SavedKeyBinding(
|
|||||||
fun isShiftDown() = InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_LEFT_SHIFT)
|
fun isShiftDown() = InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_LEFT_SHIFT)
|
||||||
|| InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_RIGHT_SHIFT)
|
|| InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_RIGHT_SHIFT)
|
||||||
|
|
||||||
|
fun unbound(): SavedKeyBinding =
|
||||||
|
SavedKeyBinding(GLFW.GLFW_KEY_UNKNOWN)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isPressed(atLeast: Boolean = false): Boolean {
|
fun isPressed(atLeast: Boolean = false): Boolean {
|
||||||
|
|||||||
@@ -75,4 +75,7 @@ object ErrorUtil {
|
|||||||
return nullable
|
return nullable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun softUserError(string: String) {
|
||||||
|
MC.sendChat(tr("frimanet.usererror", "Firmament encountered a user caused error: $string"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package moe.nea.firmament.util
|
package moe.nea.firmament.util
|
||||||
|
|
||||||
import io.github.moulberry.repo.data.Coordinate
|
import io.github.moulberry.repo.data.Coordinate
|
||||||
|
import io.github.notenoughupdates.moulconfig.gui.GuiComponentWrapper
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue
|
import java.util.concurrent.ConcurrentLinkedQueue
|
||||||
import kotlin.jvm.optionals.getOrNull
|
import kotlin.jvm.optionals.getOrNull
|
||||||
import net.minecraft.client.MinecraftClient
|
import net.minecraft.client.MinecraftClient
|
||||||
@@ -126,6 +127,8 @@ object MC {
|
|||||||
}
|
}
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
val currentMoulConfigContext
|
||||||
|
get() = (screen as? GuiComponentWrapper)?.context
|
||||||
|
|
||||||
fun openUrl(uri: String) {
|
fun openUrl(uri: String) {
|
||||||
Util.getOperatingSystem().open(uri)
|
Util.getOperatingSystem().open(uri)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package moe.nea.firmament.util
|
|||||||
|
|
||||||
object TestUtil {
|
object TestUtil {
|
||||||
inline fun <T> unlessTesting(block: () -> T): T? = if (isInTest) null else block()
|
inline fun <T> unlessTesting(block: () -> T): T? = if (isInTest) null else block()
|
||||||
|
@JvmField
|
||||||
val isInTest =
|
val isInTest =
|
||||||
Thread.currentThread().stackTrace.any {
|
Thread.currentThread().stackTrace.any {
|
||||||
it.className.startsWith("org.junit.") || it.className.startsWith("io.kotest.")
|
it.className.startsWith("org.junit.") || it.className.startsWith("io.kotest.")
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<Root xmlns="http://notenoughupdates.org/moulconfig" xmlns:firm="http://firmament.nea.moe/moulconfig"
|
||||||
|
>
|
||||||
|
<Panel background="TRANSPARENT" insets="10">
|
||||||
|
<Column>
|
||||||
|
<Meta beforeClose="@beforeClose"/>
|
||||||
|
<ScrollPanel width="380" height="300">
|
||||||
|
<Align horizontal="CENTER">
|
||||||
|
<Array data="@actions">
|
||||||
|
<!-- evenBackground="#8B8B8B" oddBackground="#C6C6C6" -->
|
||||||
|
<Panel background="TRANSPARENT" insets="3">
|
||||||
|
<Panel background="VANILLA" insets="6">
|
||||||
|
<Column>
|
||||||
|
<Row>
|
||||||
|
<Text text="@command" width="280"/>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Text text="@formattedCombo" width="250"/>
|
||||||
|
<Align horizontal="RIGHT">
|
||||||
|
<Row>
|
||||||
|
<firm:Button onClick="@edit">
|
||||||
|
<Text text="Edit"/>
|
||||||
|
</firm:Button>
|
||||||
|
<Spacer width="12"/>
|
||||||
|
<firm:Button onClick="@delete">
|
||||||
|
<Text text="Delete"/>
|
||||||
|
</firm:Button>
|
||||||
|
</Row>
|
||||||
|
</Align>
|
||||||
|
</Row>
|
||||||
|
</Column>
|
||||||
|
</Panel>
|
||||||
|
|
||||||
|
</Panel>
|
||||||
|
</Array>
|
||||||
|
</Align>
|
||||||
|
</ScrollPanel>
|
||||||
|
<Align horizontal="RIGHT">
|
||||||
|
<Row>
|
||||||
|
<firm:Button onClick="@discard">
|
||||||
|
<Text text="Discard Changes"/>
|
||||||
|
</firm:Button>
|
||||||
|
<firm:Button onClick="@saveAndClose">
|
||||||
|
<Text text="Save & Close"/>
|
||||||
|
</firm:Button>
|
||||||
|
<firm:Button onClick="@save">
|
||||||
|
<Text text="Save"/>
|
||||||
|
</firm:Button>
|
||||||
|
<firm:Button onClick="@addCommand">
|
||||||
|
<Text text="Add Combo Command"/>
|
||||||
|
</firm:Button>
|
||||||
|
</Row>
|
||||||
|
</Align>
|
||||||
|
</Column>
|
||||||
|
</Panel>
|
||||||
|
</Root>
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<Root xmlns="http://notenoughupdates.org/moulconfig" xmlns:firm="http://firmament.nea.moe/moulconfig"
|
||||||
|
>
|
||||||
|
<Center>
|
||||||
|
<Panel background="VANILLA" insets="10">
|
||||||
|
<Column>
|
||||||
|
<Row>
|
||||||
|
<firm:Button onClick="@back">
|
||||||
|
<Text text="←"/>
|
||||||
|
</firm:Button>
|
||||||
|
<Text text="Editing command macro"/>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Text text="Command: /"/>
|
||||||
|
<Align horizontal="RIGHT">
|
||||||
|
<TextField value="@command" width="200"/>
|
||||||
|
</Align>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Text text="Key Combo:"/>
|
||||||
|
<Align horizontal="RIGHT">
|
||||||
|
<firm:Button onClick="@addStep">
|
||||||
|
<Text text="+"/>
|
||||||
|
</firm:Button>
|
||||||
|
</Align>
|
||||||
|
</Row>
|
||||||
|
<Array data="@combo">
|
||||||
|
<Row>
|
||||||
|
<firm:Fixed width="160">
|
||||||
|
<Indirect value="@button"/>
|
||||||
|
</firm:Fixed>
|
||||||
|
<Align horizontal="RIGHT">
|
||||||
|
<firm:Button onClick="@delete">
|
||||||
|
<Text text="Delete"/>
|
||||||
|
</firm:Button>
|
||||||
|
</Align>
|
||||||
|
</Row>
|
||||||
|
</Array>
|
||||||
|
</Column>
|
||||||
|
</Panel>
|
||||||
|
</Center>
|
||||||
|
</Root>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<Root xmlns="http://notenoughupdates.org/moulconfig"
|
||||||
|
xmlns:firm="http://firmament.nea.moe/moulconfig">
|
||||||
|
<Center>
|
||||||
|
<Tabs>
|
||||||
|
<Tab>
|
||||||
|
<Tab.Header>
|
||||||
|
<Text text="Combo Macros"/>
|
||||||
|
</Tab.Header>
|
||||||
|
<Tab.Body>
|
||||||
|
<Fragment value="firmament:gui/config/macros/combos.xml" bind="@combos"/>
|
||||||
|
</Tab.Body>
|
||||||
|
</Tab>
|
||||||
|
</Tabs>
|
||||||
|
</Center>
|
||||||
|
</Root>
|
||||||
Reference in New Issue
Block a user