aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/features/inventory/buttons/InventoryButtonEditor.kt
blob: c57563e604a4f51d48da897e4c56b57b6453a221 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
package moe.nea.firmament.features.inventory.buttons

import io.github.notenoughupdates.moulconfig.common.IItemStack
import io.github.notenoughupdates.moulconfig.platform.ModernItemStack
import io.github.notenoughupdates.moulconfig.xml.Bind
import me.shedaniel.math.Point
import me.shedaniel.math.Rectangle
import org.lwjgl.glfw.GLFW
import net.minecraft.client.gui.DrawContext
import net.minecraft.client.gui.widget.ButtonWidget
import net.minecraft.client.util.InputUtil
import net.minecraft.text.Text
import net.minecraft.util.math.MathHelper
import net.minecraft.util.math.Vec2f
import moe.nea.firmament.util.ClipboardUtils
import moe.nea.firmament.util.FragmentGuiScreen
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.MoulConfigUtils

class InventoryButtonEditor(
    val lastGuiRect: Rectangle,
) : FragmentGuiScreen() {
    inner class Editor(val originalButton: InventoryButton) {
        @field:Bind
        var command: String = originalButton.command ?: ""

        @field:Bind
        var icon: String = originalButton.icon ?: ""

        @Bind
        fun getItemIcon(): IItemStack {
            save()
            return ModernItemStack.of(InventoryButton.getItemForName(icon))
        }

        @Bind
        fun delete() {
            buttons.removeIf { it === originalButton }
            popup = null
        }

        fun save() {
            originalButton.icon = icon
            originalButton.command = command
        }
    }

    var buttons: MutableList<InventoryButton> =
        InventoryButtons.DConfig.data.buttons.map { it.copy() }.toMutableList()

    override fun close() {
        InventoryButtons.DConfig.data.buttons = buttons
        InventoryButtons.DConfig.markDirty()
        super.close()
    }

    override fun init() {
        super.init()
        addDrawableChild(
            ButtonWidget.builder(Text.translatable("firmament.inventory-buttons.load-preset")) {
                val t = ClipboardUtils.getTextContents()
                val newButtons = InventoryButtonTemplates.loadTemplate(t)
                if (newButtons != null)
                    buttons = newButtons.toMutableList()
            }
                .position(lastGuiRect.minX + 10, lastGuiRect.minY + 35)
                .width(lastGuiRect.width - 20)
                .build()
        )
        addDrawableChild(
            ButtonWidget.builder(Text.translatable("firmament.inventory-buttons.save-preset")) {
                ClipboardUtils.setTextContent(InventoryButtonTemplates.saveTemplate(buttons))
            }
                .position(lastGuiRect.minX + 10, lastGuiRect.minY + 60)
                .width(lastGuiRect.width - 20)
                .build()
        )
    }

    override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
        super.render(context, mouseX, mouseY, delta)
        context.matrices.push()
        context.matrices.translate(0f, 0f, -10f)
        context.fill(lastGuiRect.minX, lastGuiRect.minY, lastGuiRect.maxX, lastGuiRect.maxY, -1)
        context.setShaderColor(1f, 1f, 1f, 1f)
        context.matrices.pop()
        for (button in buttons) {
            val buttonPosition = button.getBounds(lastGuiRect)
            context.matrices.push()
            context.matrices.translate(buttonPosition.minX.toFloat(), buttonPosition.minY.toFloat(), 0F)
            button.render(context)
            context.matrices.pop()
        }
    }

    override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
        if (super.keyPressed(keyCode, scanCode, modifiers)) return true
        if (keyCode == GLFW.GLFW_KEY_ESCAPE) {
            close()
            return true
        }
        return false
    }

    override fun mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean {
        if (super.mouseReleased(mouseX, mouseY, button)) return true
        val clickedButton = buttons.firstOrNull { it.getBounds(lastGuiRect).contains(Point(mouseX, mouseY)) }
        if (clickedButton != null && !justPerformedAClickAction) {
            createPopup(MoulConfigUtils.loadGui("button_editor_fragment", Editor(clickedButton)), Point(mouseX, mouseY))
            return true
        }
        justPerformedAClickAction = false
        lastDraggedButton = null
        return false
    }

    override fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean {
        if (super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)) return true

        if (initialDragMousePosition.distanceSquared(Vec2f(mouseX.toFloat(), mouseY.toFloat())) >= 4 * 4) {
            initialDragMousePosition = Vec2f(-10F, -10F)
            lastDraggedButton?.let { dragging ->
                justPerformedAClickAction = true
                val (anchorRight, anchorBottom, offsetX, offsetY) = getCoordsForMouse(mouseX.toInt(), mouseY.toInt())
                    ?: return true
                dragging.x = offsetX
                dragging.y = offsetY
                dragging.anchorRight = anchorRight
                dragging.anchorBottom = anchorBottom
            }
        }
        return false
    }

    var lastDraggedButton: InventoryButton? = null
    var justPerformedAClickAction = false
    var initialDragMousePosition = Vec2f(-10F, -10F)

    data class AnchoredCoords(
        val anchorRight: Boolean,
        val anchorBottom: Boolean,
        val offsetX: Int,
        val offsetY: Int,
    )

    fun getCoordsForMouse(mx: Int, my: Int): AnchoredCoords? {
        if (lastGuiRect.contains(mx, my) || lastGuiRect.contains(
                Point(
                    mx + InventoryButton.dimensions.width,
                    my + InventoryButton.dimensions.height,
                )
            )
        ) return null

        val anchorRight = mx > lastGuiRect.maxX
        val anchorBottom = my > lastGuiRect.maxY
        var offsetX = mx - if (anchorRight) lastGuiRect.maxX else lastGuiRect.minX
        var offsetY = my - if (anchorBottom) lastGuiRect.maxY else lastGuiRect.minY
        if (InputUtil.isKeyPressed(MC.window.handle, InputUtil.GLFW_KEY_LEFT_SHIFT)) {
            offsetX = MathHelper.floor(offsetX / 20F) * 20
            offsetY = MathHelper.floor(offsetY / 20F) * 20
        }
        return AnchoredCoords(anchorRight, anchorBottom, offsetX, offsetY)
    }

    override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
        if (super.mouseClicked(mouseX, mouseY, button)) return true
        val clickedButton = buttons.firstOrNull { it.getBounds(lastGuiRect).contains(Point(mouseX, mouseY)) }
        if (clickedButton != null) {
            lastDraggedButton = clickedButton
            initialDragMousePosition = Vec2f(mouseX.toFloat(), mouseY.toFloat())
            return true
        }
        val mx = mouseX.toInt()
        val my = mouseY.toInt()
        val (anchorRight, anchorBottom, offsetX, offsetY) = getCoordsForMouse(mx, my) ?: return true
        buttons.add(InventoryButton(offsetX, offsetY, anchorRight, anchorBottom, null, null))
        justPerformedAClickAction = true
        return true
    }

}