summaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni/utils/renderables/RenderableInventory.kt
blob: 9760ef867f98314b3d1e823c78a64ab3f7e710f0 (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
package at.hannibal2.skyhanni.utils.renderables

import at.hannibal2.skyhanni.utils.RenderUtils.HorizontalAlignment
import at.hannibal2.skyhanni.utils.RenderUtils.VerticalAlignment
import net.minecraft.item.ItemStack
import net.minecraft.util.ResourceLocation
import kotlin.math.ceil

object RenderableInventory {

    private val inventoryTextures by lazy { ResourceLocation("skyhanni", "gui/slot.png") }
    private const val TEXTURE_WIDTH = 90
    private const val TEXTURE_HEIGHT = 54

    private enum class SlotsUv(val uMin: Int, val uMax: Int, val vMin: Int, val vMax: Int) {
        TOP_LEFT_CORNER(14, 18, 32, 36),
        TOP_BORDER(18, 36, 32, 36),
        TOP_RIGHT_CORNER(36, 40, 32, 36),
        LEFT_BORDER(68, 72, 18, 36),
        CENTER(0, 18, 0, 18),
        RIGHT_BORDER(72, 76, 18, 36),
        BOTTOM_LEFT_CORNER(14, 18, 36, 40),
        BOTTOM_BORDER(18, 36, 36, 40),
        BOTTOM_RIGHT_CORNER(36, 40, 36, 40),
        HALF_EMPTY(54, 63, 0, 18),
        EMPTY(18, 36, 0, 18),
        ;

        fun getUvCoords(): FloatArray {
            return floatArrayOf(
                (uMin.toFloat() / TEXTURE_WIDTH),
                (uMax.toFloat() / TEXTURE_WIDTH),
                (vMin.toFloat() / TEXTURE_HEIGHT),
                (vMax.toFloat() / TEXTURE_HEIGHT),
            )
        }

        fun height() = vMax - vMin
        fun width() = uMax - uMin
    }

    private fun createUvList(size: Int, maxSize: Int) = buildList {
        val length = if (size >= maxSize) maxSize else size
        val lastLength = if (size % maxSize == 0) maxSize else size % maxSize
        val isWeird = lastLength % 2 != length % 2

        val rows = ceil(size.toDouble() / maxSize).toInt()

        for (i in 0 until rows + 2) {
            val row = mutableListOf<SlotsUv>()
            if (i == 0) { // top border
                row.add(SlotsUv.TOP_LEFT_CORNER)
                row.addAll(List(length) { SlotsUv.TOP_BORDER })
                row.add(SlotsUv.TOP_RIGHT_CORNER)
            } else if (i == rows + 1) { // last border
                row.add(SlotsUv.BOTTOM_LEFT_CORNER)
                row.addAll(List(length) { SlotsUv.BOTTOM_BORDER })
                row.add(SlotsUv.BOTTOM_RIGHT_CORNER)
            } else if (i == rows && rows != 1) { // last row
                val spaces = if (isWeird) (length - lastLength) - 1 else length - lastLength
                row.add(SlotsUv.LEFT_BORDER)
                row.addAll(List(spaces / 2) { SlotsUv.EMPTY })
                if (isWeird) row.add(SlotsUv.HALF_EMPTY)
                row.addAll(List(lastLength) { SlotsUv.CENTER })
                if (isWeird) row.add(SlotsUv.HALF_EMPTY)
                row.addAll(List(spaces / 2) { SlotsUv.EMPTY })
                row.add(SlotsUv.RIGHT_BORDER)
            } else {
                row.add(SlotsUv.LEFT_BORDER)
                row.addAll(List(length) { SlotsUv.CENTER })
                row.add(SlotsUv.RIGHT_BORDER)
            }
            add(row.toList())
        }
    }

    fun fakeInventory(
        items: List<ItemStack?>,
        maxRowSize: Int,
        scale: Double,
        horizontalAlign: HorizontalAlignment = HorizontalAlignment.LEFT,
        verticalAlign: VerticalAlignment = VerticalAlignment.TOP,
    ): Renderable {
        val uvList = createUvList(items.size, maxRowSize)
        var index = 0
        val finalList = uvList.map { uvRow ->
            uvRow.map { uv ->
                val uvArray = uv.getUvCoords()
                val renderable = if (uv == SlotsUv.CENTER) {
                    (items[index]?.let { item ->
                        Renderable.itemStack(
                            item,
                            scale,
                            0,
                            0,
                            false,
                        )
                    } ?: Renderable.placeholder((16 * scale).toInt(), (16 * scale).toInt())).also { index++ }
                } else Renderable.placeholder(0, 0)
                Renderable.drawInsideFixedSizedImage(
                    renderable,
                    inventoryTextures,
                    (uv.width() * scale).toInt(),
                    (uv.height() * scale).toInt(),
                    padding = scale.toInt(),
                    uMin = uvArray[0],
                    uMax = uvArray[1],
                    vMin = uvArray[2],
                    vMax = uvArray[3],
                )
            }
        }

        return Renderable.verticalContainer(
            finalList.map { Renderable.horizontalContainer(it, 0) },
            0,
            horizontalAlign = horizontalAlign,
            verticalAlign = verticalAlign,
        )
    }
}