Split buttons panel file
This commit is contained in:
parent
a53438e1f9
commit
b2181819ca
@ -18,7 +18,7 @@ import ru.dbotthepony.mc.otm.client.screen.ExoSuitInventoryScreen
|
||||
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.AbstractSlotPanel
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.DiscreteScrollBarPanel
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.LargeRectangleButtonPanel
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.buttons.LargeRectangleButtonPanel
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.Panel2Widget
|
||||
import ru.dbotthepony.mc.otm.compat.InventoryScrollPacket
|
||||
import ru.dbotthepony.mc.otm.compat.cos.isCosmeticArmorScreen
|
||||
|
@ -1,25 +1,21 @@
|
||||
package ru.dbotthepony.mc.otm.client.screen
|
||||
|
||||
import com.mojang.blaze3d.platform.InputConstants
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import net.minecraft.client.gui.screens.inventory.InventoryScreen
|
||||
import ru.dbotthepony.mc.otm.client.mousePos
|
||||
import ru.dbotthepony.mc.otm.client.moveMousePos
|
||||
import ru.dbotthepony.mc.otm.client.moveMousePosScaled
|
||||
import ru.dbotthepony.mc.otm.client.render.Widgets18
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.client.render.element
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.*
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.buttons.LargeRectangleButtonPanel
|
||||
import ru.dbotthepony.mc.otm.client.setMousePos
|
||||
import ru.dbotthepony.mc.otm.client.shouldOpenVanillaInventory
|
||||
import ru.dbotthepony.mc.otm.compat.cos.CosmeticToggleButton
|
||||
import ru.dbotthepony.mc.otm.compat.curios.curiosSlots
|
||||
import ru.dbotthepony.mc.otm.core.maxScrollDivision
|
||||
import ru.dbotthepony.mc.otm.menu.ExoSuitInventoryMenu
|
||||
import ru.dbotthepony.mc.otm.network.ExoSuitMenuOpen
|
||||
import ru.dbotthepony.mc.otm.network.MatteryPlayerNetworkChannel
|
||||
import yalter.mousetweaks.api.MouseTweaksDisableWheelTweak
|
||||
import kotlin.math.cos
|
||||
|
||||
@MouseTweaksDisableWheelTweak
|
||||
class ExoSuitInventoryScreen(menu: ExoSuitInventoryMenu) : MatteryScreen<ExoSuitInventoryMenu>(menu, TranslatableComponent("otm.gui.exosuit")) {
|
||||
|
@ -13,6 +13,7 @@ import ru.dbotthepony.mc.otm.block.entity.storage.ItemMonitorPlayerSettings
|
||||
import ru.dbotthepony.mc.otm.client.render.UVWindingOrder
|
||||
import ru.dbotthepony.mc.otm.client.render.Widgets8
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.*
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.buttons.SmallEnumRectangleButtonPanel
|
||||
import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel
|
||||
import ru.dbotthepony.mc.otm.client.screen.widget.WidePowerGaugePanel
|
||||
import ru.dbotthepony.mc.otm.core.asGetterSetter
|
||||
|
@ -1,546 +0,0 @@
|
||||
package ru.dbotthepony.mc.otm.client.screen.panels
|
||||
|
||||
import com.mojang.blaze3d.platform.InputConstants
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import net.minecraft.network.chat.Component
|
||||
import ru.dbotthepony.mc.otm.client.playGuiClickSound
|
||||
import ru.dbotthepony.mc.otm.core.TextComponent
|
||||
import ru.dbotthepony.mc.otm.client.render.*
|
||||
import ru.dbotthepony.mc.otm.core.GetterSetter
|
||||
import ru.dbotthepony.mc.otm.core.RGBAColor
|
||||
import ru.dbotthepony.mc.otm.core.next
|
||||
import ru.dbotthepony.mc.otm.core.prev
|
||||
import ru.dbotthepony.mc.otm.core.value
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.reflect.KMutableProperty0
|
||||
|
||||
open class ButtonPanel<out S : Screen>(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float = 40f,
|
||||
height: Float = HEIGHT,
|
||||
var label: Component
|
||||
) : EditablePanel<S>(screen, parent, x, y, width, height) {
|
||||
constructor(screen: S, parent: EditablePanel<*>?, label: Component) : this(screen, parent, x = 0f, label = label)
|
||||
|
||||
constructor(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float = 40f,
|
||||
height: Float = HEIGHT,
|
||||
label: Component,
|
||||
onPress: Runnable
|
||||
) : this(screen, parent, x, y, width, height, label) {
|
||||
this.callback = onPress
|
||||
}
|
||||
|
||||
protected var callback: Runnable? = null
|
||||
protected var pressed = false
|
||||
|
||||
protected open fun onClick(button: Int) {
|
||||
callback?.run()
|
||||
}
|
||||
|
||||
override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean {
|
||||
if (isDisabled || pressed) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (!tryToGrabMouseInput()) {
|
||||
return true
|
||||
}
|
||||
|
||||
pressed = true
|
||||
playGuiClickSound()
|
||||
return true
|
||||
}
|
||||
|
||||
override fun mouseReleasedInner(x: Double, y: Double, button: Int): Boolean {
|
||||
if (!pressed) {
|
||||
return true
|
||||
}
|
||||
|
||||
grabMouseInput = false
|
||||
pressed = false
|
||||
|
||||
if (isHovered) {
|
||||
onClick(button)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun bind(runnable: Runnable) {
|
||||
callback = runnable
|
||||
}
|
||||
|
||||
var textColor = RGBAColor.WHITE
|
||||
|
||||
var isDisabled = false
|
||||
set(value) {
|
||||
if (field != value) {
|
||||
if (!value) {
|
||||
pressed = false
|
||||
grabMouseInput = false
|
||||
}
|
||||
|
||||
field = value
|
||||
}
|
||||
}
|
||||
|
||||
override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
|
||||
if (isDisabled) {
|
||||
Widgets18.BUTTON_DISABLED_STRETCHABLE.render(stack, width = width, height = height)
|
||||
} else if (pressed) {
|
||||
Widgets18.BUTTON_PRESSED_STRETCHABLE.render(stack, width = width, height = height)
|
||||
} else if (isHovered) {
|
||||
Widgets18.BUTTON_HOVERED_STRETCHABLE.render(stack, width = width, height = height)
|
||||
} else {
|
||||
Widgets18.BUTTON_IDLE_STRETCHABLE.render(stack, width = width, height = height)
|
||||
}
|
||||
|
||||
font.drawAligned(stack, label, TextAlign.CENTER_CENTER, width / 2f, height / 2f, textColor.toInt())
|
||||
}
|
||||
|
||||
override fun sizeToContents() {
|
||||
super.sizeToContents()
|
||||
|
||||
height = height.coerceAtLeast(HEIGHT).coerceAtLeast(font.lineHeight.toFloat() + 2f)
|
||||
width = width.coerceAtLeast(HEIGHT).coerceAtLeast(font.width(label) + 4f)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val HEIGHT = 18f
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("PropertyName")
|
||||
abstract class RectangleButtonPanel<out S : Screen>(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float,
|
||||
height: Float,
|
||||
val onPress: ((clickButton: Int) -> Unit)? = null,
|
||||
) : EditablePanel<S>(screen, parent, x, y, width, height) {
|
||||
protected var pressed = false
|
||||
|
||||
protected open fun onClick(clickButton: Int) {
|
||||
onPress?.invoke(clickButton)
|
||||
}
|
||||
|
||||
abstract val PRESSED: AbstractSkinElement
|
||||
abstract val HOVERED: AbstractSkinElement
|
||||
abstract val IDLE: AbstractSkinElement
|
||||
abstract val DISABLED: AbstractSkinElement
|
||||
|
||||
var isDisabled = false
|
||||
set(value) {
|
||||
if (field != value) {
|
||||
if (!value) {
|
||||
pressed = false
|
||||
grabMouseInput = false
|
||||
}
|
||||
|
||||
field = value
|
||||
}
|
||||
}
|
||||
|
||||
override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
|
||||
if (isDisabled) {
|
||||
DISABLED.render(stack, 0f, 0f, width, height)
|
||||
} else if (pressed) {
|
||||
PRESSED.render(stack, 0f, 0f, width, height)
|
||||
} else if (isHovered) {
|
||||
HOVERED.render(stack, 0f, 0f, width, height)
|
||||
} else {
|
||||
IDLE.render(stack, 0f, 0f, width, height)
|
||||
}
|
||||
}
|
||||
|
||||
override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean {
|
||||
if (!isDisabled) {
|
||||
if (!pressed) {
|
||||
playGuiClickSound()
|
||||
}
|
||||
|
||||
if (tryToGrabMouseInput()) {
|
||||
pressed = true
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun mouseReleasedInner(x: Double, y: Double, button: Int): Boolean {
|
||||
if (!isDisabled && pressed) {
|
||||
pressed = false
|
||||
|
||||
if (isHovered) {
|
||||
onClick(button)
|
||||
}
|
||||
}
|
||||
|
||||
grabMouseInput = false
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
abstract class EnumRectangleButtonPanel<out S : Screen, T : Enum<T>>(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float,
|
||||
height: Float,
|
||||
val enum: Class<T>,
|
||||
val prop: GetterSetter<T>,
|
||||
val defaultValue: T,
|
||||
val onChange: ((newValue: T) -> Unit)? = null,
|
||||
) : RectangleButtonPanel<S>(screen, parent, x, y, width, height, null) {
|
||||
private var building = true
|
||||
|
||||
protected val enumMapping = EnumMap<T, Pair<AbstractSkinElement, UVWindingOrder>>(enum)
|
||||
protected val tooltipMapping = EnumMap<T, Component>(enum)
|
||||
|
||||
fun addTooltip(value: T, component: Component): EnumRectangleButtonPanel<S, T> {
|
||||
check(tooltipMapping.put(value, component) == null) { "Already has mapping for $value" }
|
||||
return this
|
||||
}
|
||||
|
||||
var mainTooltip: Component? = null
|
||||
set(value) {
|
||||
if (field != null) {
|
||||
throw UnsupportedOperationException("Write once only")
|
||||
}
|
||||
|
||||
field = value
|
||||
}
|
||||
|
||||
fun isFullyDefined(): Boolean {
|
||||
for (value in enum.enumConstants) {
|
||||
if (enumMapping[value] == null) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
val missingValues: List<T> get() {
|
||||
val missing = ArrayList<T>()
|
||||
|
||||
for (value in enum.enumConstants) {
|
||||
if (enumMapping[value] == null) {
|
||||
missing.add(value)
|
||||
}
|
||||
}
|
||||
|
||||
return missing
|
||||
}
|
||||
|
||||
fun add(value: T, skinElement: AbstractSkinElement, winding: UVWindingOrder = UVWindingOrder.NORMAL): EnumRectangleButtonPanel<S, T> {
|
||||
return add(value, skinElement to winding)
|
||||
}
|
||||
|
||||
fun add(value: T, skinElement: AbstractSkinElement, component: Component, winding: UVWindingOrder = UVWindingOrder.NORMAL): EnumRectangleButtonPanel<S, T> {
|
||||
return add(value, component, skinElement to winding)
|
||||
}
|
||||
|
||||
fun add(value: T, component: Component, skinElement: AbstractSkinElement, winding: UVWindingOrder = UVWindingOrder.NORMAL): EnumRectangleButtonPanel<S, T> {
|
||||
return add(value, component, skinElement to winding)
|
||||
}
|
||||
|
||||
fun add(value: T, pair: Pair<AbstractSkinElement, UVWindingOrder>): EnumRectangleButtonPanel<S, T> {
|
||||
check(building) { "Not building" }
|
||||
check(enumMapping.put(value, pair) == null) { "Already has mapping for $value" }
|
||||
|
||||
if (enumMapping.size == enum.enumConstants.size) {
|
||||
finish()
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
fun add(value: T, component: Component, pair: Pair<AbstractSkinElement, UVWindingOrder>): EnumRectangleButtonPanel<S, T> {
|
||||
addTooltip(value, component)
|
||||
return add(value, pair)
|
||||
}
|
||||
|
||||
fun finish(): EnumRectangleButtonPanel<S, T> {
|
||||
check(building) { "Not building" }
|
||||
check(isFullyDefined()) {
|
||||
"Not all enums having their mapping defined, missing are: ${missingValues.joinToString(", ")}"
|
||||
}
|
||||
|
||||
building = false
|
||||
return this
|
||||
}
|
||||
|
||||
override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
|
||||
check(!building) { "Still building this button!" }
|
||||
super.innerRender(stack, mouseX, mouseY, partialTick)
|
||||
val pair = checkNotNull(enumMapping[prop.get()]) { "HOW" }
|
||||
pair.first.render(stack, 0f, 0f, width, height, pair.second)
|
||||
}
|
||||
|
||||
override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean {
|
||||
check(!building) { "Still building this button!" }
|
||||
return super.mouseClickedInner(x, y, button)
|
||||
}
|
||||
|
||||
override fun mouseReleasedInner(x: Double, y: Double, button: Int): Boolean {
|
||||
check(!building) { "Still building this button!" }
|
||||
return super.mouseReleasedInner(x, y, button)
|
||||
}
|
||||
|
||||
override fun onClick(clickButton: Int) {
|
||||
when (clickButton) {
|
||||
InputConstants.MOUSE_BUTTON_LEFT -> {
|
||||
prop.value = prop.value.next(enum.enumConstants)
|
||||
onChange?.invoke(prop.get())
|
||||
}
|
||||
|
||||
InputConstants.MOUSE_BUTTON_RIGHT -> {
|
||||
prop.value = prop.value.prev(enum.enumConstants)
|
||||
onChange?.invoke(prop.get())
|
||||
}
|
||||
|
||||
InputConstants.MOUSE_BUTTON_MIDDLE -> {
|
||||
if (prop.get() != defaultValue) {
|
||||
prop.value = defaultValue
|
||||
onChange?.invoke(prop.get())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun innerRenderTooltips(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float): Boolean {
|
||||
if (!isHovered && !isGrabbingMouseInput()) {
|
||||
return super.innerRenderTooltips(stack, mouseX, mouseY, partialTick)
|
||||
}
|
||||
|
||||
if (mainTooltip == null && tooltipMapping.size == 0) {
|
||||
return super.innerRenderTooltips(stack, mouseX, mouseY, partialTick)
|
||||
}
|
||||
|
||||
val listing = ArrayList<Component>()
|
||||
|
||||
if (mainTooltip != null) {
|
||||
listing.add(mainTooltip!!)
|
||||
listing.add(SPACE)
|
||||
}
|
||||
|
||||
for ((key, value) in tooltipMapping) {
|
||||
if (key == prop.get()) {
|
||||
listing.add(value.copy().withStyle(ChatFormatting.WHITE))
|
||||
} else {
|
||||
listing.add(value.copy().withStyle(ChatFormatting.GRAY))
|
||||
}
|
||||
}
|
||||
|
||||
screen.renderComponentTooltip(
|
||||
stack,
|
||||
listing,
|
||||
mouseX.toInt(),
|
||||
mouseY.toInt(),
|
||||
font
|
||||
)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val SPACE = TextComponent("")
|
||||
}
|
||||
}
|
||||
|
||||
abstract class BooleanRectangleButtonPanel<out S : Screen>(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float,
|
||||
height: Float,
|
||||
val prop: GetterSetter<Boolean>,
|
||||
val skinElementActive: AbstractSkinElement? = null,
|
||||
val skinElementInactive: AbstractSkinElement? = null,
|
||||
val onChange: ((newValue: Boolean) -> Unit)? = null,
|
||||
) : RectangleButtonPanel<S>(screen, parent, x, y, width, height, null) {
|
||||
override fun onClick(clickButton: Int) {
|
||||
if (clickButton == InputConstants.MOUSE_BUTTON_LEFT) {
|
||||
val newValue = !prop.value
|
||||
prop.value = newValue
|
||||
onChange?.invoke(newValue)
|
||||
}
|
||||
}
|
||||
|
||||
override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
|
||||
super.innerRender(stack, mouseX, mouseY, partialTick)
|
||||
|
||||
if (prop.value) {
|
||||
skinElementActive?.render(stack, width = width, height = height)
|
||||
} else {
|
||||
skinElementInactive?.render(stack, width = width, height = height)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class LargeRectangleButtonPanel<out S : Screen>(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float = SIZE,
|
||||
height: Float = SIZE,
|
||||
onPress: ((clickButton: Int) -> Unit)? = null,
|
||||
val skinElement: AbstractSkinElement? = null,
|
||||
val skinElementWinding: UVWindingOrder? = null,
|
||||
) : RectangleButtonPanel<S>(screen, parent, x, y, width, height, onPress) {
|
||||
final override val IDLE = Widgets18.BUTTON_IDLE
|
||||
final override val HOVERED = Widgets18.BUTTON_HOVERED
|
||||
final override val PRESSED = Widgets18.BUTTON_PRESSED
|
||||
final override val DISABLED = Widgets18.BUTTON_DISABLED
|
||||
|
||||
override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
|
||||
super.innerRender(stack, mouseX, mouseY, partialTick)
|
||||
|
||||
if (skinElementWinding != null) {
|
||||
skinElement?.render(stack, width = width, height = height, winding = skinElementWinding)
|
||||
} else {
|
||||
skinElement?.render(stack, width = width, height = height)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val SIZE = 18f
|
||||
}
|
||||
}
|
||||
|
||||
open class LargeEnumRectangleButtonPanel<out S : Screen, T : Enum<T>>(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float = SIZE,
|
||||
height: Float = SIZE,
|
||||
enum: Class<T>,
|
||||
prop: GetterSetter<T>,
|
||||
defaultValue: T,
|
||||
onChange: ((newValue: T) -> Unit)? = null,
|
||||
) : EnumRectangleButtonPanel<S, T>(screen, parent, x, y, width, height, enum, prop, defaultValue, onChange) {
|
||||
final override val IDLE = Widgets18.BUTTON_IDLE
|
||||
final override val HOVERED = Widgets18.BUTTON_HOVERED
|
||||
final override val PRESSED = Widgets18.BUTTON_PRESSED
|
||||
final override val DISABLED = Widgets18.BUTTON_DISABLED
|
||||
|
||||
companion object {
|
||||
const val SIZE = 18f
|
||||
}
|
||||
}
|
||||
|
||||
open class LargeBooleanRectangleButtonPanel<out S : Screen>(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float = SIZE,
|
||||
height: Float = SIZE,
|
||||
prop: GetterSetter<Boolean>,
|
||||
skinElementActive: AbstractSkinElement? = null,
|
||||
skinElementInactive: AbstractSkinElement? = null,
|
||||
onChange: ((newValue: Boolean) -> Unit)? = null,
|
||||
) : BooleanRectangleButtonPanel<S>(screen, parent, x, y, width, height, prop, skinElementActive, skinElementInactive, onChange) {
|
||||
final override val IDLE = Widgets18.BUTTON_IDLE
|
||||
final override val HOVERED = Widgets18.BUTTON_HOVERED
|
||||
final override val PRESSED = Widgets18.BUTTON_PRESSED
|
||||
final override val DISABLED = Widgets18.BUTTON_DISABLED
|
||||
|
||||
companion object {
|
||||
const val SIZE = 18f
|
||||
}
|
||||
}
|
||||
|
||||
open class SmallRectangleButtonPanel<out S : Screen>(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float = SIZE,
|
||||
height: Float = SIZE,
|
||||
onPress: ((clickButton: Int) -> Unit)? = null,
|
||||
val skinElement: SkinElement? = null,
|
||||
val skinElementWinding: UVWindingOrder? = null,
|
||||
) : RectangleButtonPanel<S>(screen, parent, x, y, width, height, onPress) {
|
||||
final override val IDLE = Widgets8.BUTTON_IDLE
|
||||
final override val HOVERED = Widgets8.BUTTON_HOVERED
|
||||
final override val PRESSED = Widgets8.BUTTON_PRESSED
|
||||
final override val DISABLED = Widgets8.BUTTON_DISABLED
|
||||
|
||||
override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
|
||||
super.innerRender(stack, mouseX, mouseY, partialTick)
|
||||
|
||||
if (skinElementWinding != null) {
|
||||
skinElement?.render(stack, width = width, height = height, winding = skinElementWinding)
|
||||
} else {
|
||||
skinElement?.render(stack, width = width, height = height)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val SIZE = 8f
|
||||
}
|
||||
}
|
||||
|
||||
open class SmallEnumRectangleButtonPanel<out S : Screen, T : Enum<T>>(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float = SIZE,
|
||||
height: Float = SIZE,
|
||||
enum: Class<T>,
|
||||
prop: GetterSetter<T>,
|
||||
defaultValue: T,
|
||||
onChange: ((newValue: T) -> Unit)? = null,
|
||||
) : EnumRectangleButtonPanel<S, T>(screen, parent, x, y, width, height, enum, prop, defaultValue, onChange) {
|
||||
final override val IDLE = Widgets8.BUTTON_IDLE
|
||||
final override val HOVERED = Widgets8.BUTTON_HOVERED
|
||||
final override val PRESSED = Widgets8.BUTTON_PRESSED
|
||||
final override val DISABLED = Widgets8.BUTTON_DISABLED
|
||||
|
||||
companion object {
|
||||
const val SIZE = 8f
|
||||
}
|
||||
}
|
||||
|
||||
open class SmallBooleanRectangleButtonPanel<out S : Screen>(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float = SIZE,
|
||||
height: Float = SIZE,
|
||||
prop: GetterSetter<Boolean>,
|
||||
skinElementActive: AbstractSkinElement? = null,
|
||||
skinElementInactive: AbstractSkinElement? = null,
|
||||
onChange: ((newValue: Boolean) -> Unit)? = null,
|
||||
) : BooleanRectangleButtonPanel<S>(screen, parent, x, y, width, height, prop, skinElementActive, skinElementInactive, onChange) {
|
||||
final override val IDLE = Widgets8.BUTTON_IDLE
|
||||
final override val HOVERED = Widgets8.BUTTON_HOVERED
|
||||
final override val PRESSED = Widgets8.BUTTON_PRESSED
|
||||
final override val DISABLED = Widgets8.BUTTON_DISABLED
|
||||
|
||||
companion object {
|
||||
const val SIZE = 8f
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@ import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
||||
import ru.dbotthepony.mc.otm.client.render.Widgets8
|
||||
import ru.dbotthepony.mc.otm.client.render.element
|
||||
import ru.dbotthepony.mc.otm.client.screen.ExoSuitInventoryScreen
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.buttons.SmallBooleanRectangleButtonPanel
|
||||
import ru.dbotthepony.mc.otm.compat.cos.CosmeticToggleRenderButton
|
||||
import ru.dbotthepony.mc.otm.compat.cos.isCosmeticArmorLoaded
|
||||
import ru.dbotthepony.mc.otm.core.asGetterOnly
|
||||
|
@ -3,8 +3,8 @@ package ru.dbotthepony.mc.otm.client.screen.panels
|
||||
import com.mojang.blaze3d.platform.InputConstants
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import ru.dbotthepony.mc.otm.client.render.AbstractSkinElement
|
||||
import ru.dbotthepony.mc.otm.client.render.SkinElement
|
||||
import ru.dbotthepony.mc.otm.client.render.Widgets
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.buttons.RectangleButtonPanel
|
||||
|
||||
open class HeightControls<out S : Screen>(
|
||||
screen: S,
|
||||
|
@ -0,0 +1,40 @@
|
||||
package ru.dbotthepony.mc.otm.client.screen.panels.buttons
|
||||
|
||||
import com.mojang.blaze3d.platform.InputConstants
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import ru.dbotthepony.mc.otm.client.render.AbstractSkinElement
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
|
||||
import ru.dbotthepony.mc.otm.core.GetterSetter
|
||||
import ru.dbotthepony.mc.otm.core.value
|
||||
|
||||
abstract class BooleanRectangleButtonPanel<out S : Screen>(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float,
|
||||
height: Float,
|
||||
val prop: GetterSetter<Boolean>,
|
||||
val skinElementActive: AbstractSkinElement? = null,
|
||||
val skinElementInactive: AbstractSkinElement? = null,
|
||||
val onChange: ((newValue: Boolean) -> Unit)? = null,
|
||||
) : RectangleButtonPanel<S>(screen, parent, x, y, width, height, null) {
|
||||
override fun onClick(clickButton: Int) {
|
||||
if (clickButton == InputConstants.MOUSE_BUTTON_LEFT) {
|
||||
val newValue = !prop.value
|
||||
prop.value = newValue
|
||||
onChange?.invoke(newValue)
|
||||
}
|
||||
}
|
||||
|
||||
override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
|
||||
super.innerRender(stack, mouseX, mouseY, partialTick)
|
||||
|
||||
if (prop.value) {
|
||||
skinElementActive?.render(stack, width = width, height = height)
|
||||
} else {
|
||||
skinElementInactive?.render(stack, width = width, height = height)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
package ru.dbotthepony.mc.otm.client.screen.panels.buttons
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import net.minecraft.network.chat.Component
|
||||
import ru.dbotthepony.mc.otm.client.playGuiClickSound
|
||||
import ru.dbotthepony.mc.otm.client.render.TextAlign
|
||||
import ru.dbotthepony.mc.otm.client.render.Widgets18
|
||||
import ru.dbotthepony.mc.otm.client.render.drawAligned
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
|
||||
import ru.dbotthepony.mc.otm.core.RGBAColor
|
||||
|
||||
open class ButtonPanel<out S : Screen>(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float = 40f,
|
||||
height: Float = HEIGHT,
|
||||
var label: Component
|
||||
) : EditablePanel<S>(screen, parent, x, y, width, height) {
|
||||
constructor(screen: S, parent: EditablePanel<*>?, label: Component) : this(screen, parent, x = 0f, label = label)
|
||||
|
||||
constructor(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float = 40f,
|
||||
height: Float = HEIGHT,
|
||||
label: Component,
|
||||
onPress: Runnable
|
||||
) : this(screen, parent, x, y, width, height, label) {
|
||||
this.callback = onPress
|
||||
}
|
||||
|
||||
protected var callback: Runnable? = null
|
||||
protected var pressed = false
|
||||
|
||||
protected open fun onClick(button: Int) {
|
||||
callback?.run()
|
||||
}
|
||||
|
||||
override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean {
|
||||
if (isDisabled || pressed) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (!tryToGrabMouseInput()) {
|
||||
return true
|
||||
}
|
||||
|
||||
pressed = true
|
||||
playGuiClickSound()
|
||||
return true
|
||||
}
|
||||
|
||||
override fun mouseReleasedInner(x: Double, y: Double, button: Int): Boolean {
|
||||
if (!pressed) {
|
||||
return true
|
||||
}
|
||||
|
||||
grabMouseInput = false
|
||||
pressed = false
|
||||
|
||||
if (isHovered) {
|
||||
onClick(button)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun bind(runnable: Runnable) {
|
||||
callback = runnable
|
||||
}
|
||||
|
||||
var textColor = RGBAColor.WHITE
|
||||
|
||||
var isDisabled = false
|
||||
set(value) {
|
||||
if (field != value) {
|
||||
if (!value) {
|
||||
pressed = false
|
||||
grabMouseInput = false
|
||||
}
|
||||
|
||||
field = value
|
||||
}
|
||||
}
|
||||
|
||||
override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
|
||||
if (isDisabled) {
|
||||
Widgets18.BUTTON_DISABLED_STRETCHABLE.render(stack, width = width, height = height)
|
||||
} else if (pressed) {
|
||||
Widgets18.BUTTON_PRESSED_STRETCHABLE.render(stack, width = width, height = height)
|
||||
} else if (isHovered) {
|
||||
Widgets18.BUTTON_HOVERED_STRETCHABLE.render(stack, width = width, height = height)
|
||||
} else {
|
||||
Widgets18.BUTTON_IDLE_STRETCHABLE.render(stack, width = width, height = height)
|
||||
}
|
||||
|
||||
font.drawAligned(stack, label, TextAlign.CENTER_CENTER, width / 2f, height / 2f, textColor.toInt())
|
||||
}
|
||||
|
||||
override fun sizeToContents() {
|
||||
super.sizeToContents()
|
||||
|
||||
height = height.coerceAtLeast(HEIGHT).coerceAtLeast(font.lineHeight.toFloat() + 2f)
|
||||
width = width.coerceAtLeast(HEIGHT).coerceAtLeast(font.width(label) + 4f)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val HEIGHT = 18f
|
||||
}
|
||||
}
|
@ -0,0 +1,186 @@
|
||||
package ru.dbotthepony.mc.otm.client.screen.panels.buttons
|
||||
|
||||
import com.mojang.blaze3d.platform.InputConstants
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import net.minecraft.network.chat.Component
|
||||
import ru.dbotthepony.mc.otm.client.render.AbstractSkinElement
|
||||
import ru.dbotthepony.mc.otm.client.render.UVWindingOrder
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
|
||||
import ru.dbotthepony.mc.otm.core.GetterSetter
|
||||
import ru.dbotthepony.mc.otm.core.TextComponent
|
||||
import ru.dbotthepony.mc.otm.core.next
|
||||
import ru.dbotthepony.mc.otm.core.prev
|
||||
import ru.dbotthepony.mc.otm.core.value
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
abstract class EnumRectangleButtonPanel<out S : Screen, T : Enum<T>>(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float,
|
||||
height: Float,
|
||||
val enum: Class<T>,
|
||||
val prop: GetterSetter<T>,
|
||||
val defaultValue: T,
|
||||
val onChange: ((newValue: T) -> Unit)? = null,
|
||||
) : RectangleButtonPanel<S>(screen, parent, x, y, width, height, null) {
|
||||
private var building = true
|
||||
|
||||
protected val enumMapping = EnumMap<T, Pair<AbstractSkinElement, UVWindingOrder>>(enum)
|
||||
protected val tooltipMapping = EnumMap<T, Component>(enum)
|
||||
|
||||
fun addTooltip(value: T, component: Component): EnumRectangleButtonPanel<S, T> {
|
||||
check(tooltipMapping.put(value, component) == null) { "Already has mapping for $value" }
|
||||
return this
|
||||
}
|
||||
|
||||
var mainTooltip: Component? = null
|
||||
set(value) {
|
||||
if (field != null) {
|
||||
throw UnsupportedOperationException("Write once only")
|
||||
}
|
||||
|
||||
field = value
|
||||
}
|
||||
|
||||
fun isFullyDefined(): Boolean {
|
||||
for (value in enum.enumConstants) {
|
||||
if (enumMapping[value] == null) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
val missingValues: List<T> get() {
|
||||
val missing = ArrayList<T>()
|
||||
|
||||
for (value in enum.enumConstants) {
|
||||
if (enumMapping[value] == null) {
|
||||
missing.add(value)
|
||||
}
|
||||
}
|
||||
|
||||
return missing
|
||||
}
|
||||
|
||||
fun add(value: T, skinElement: AbstractSkinElement, winding: UVWindingOrder = UVWindingOrder.NORMAL): EnumRectangleButtonPanel<S, T> {
|
||||
return add(value, skinElement to winding)
|
||||
}
|
||||
|
||||
fun add(value: T, skinElement: AbstractSkinElement, component: Component, winding: UVWindingOrder = UVWindingOrder.NORMAL): EnumRectangleButtonPanel<S, T> {
|
||||
return add(value, component, skinElement to winding)
|
||||
}
|
||||
|
||||
fun add(value: T, component: Component, skinElement: AbstractSkinElement, winding: UVWindingOrder = UVWindingOrder.NORMAL): EnumRectangleButtonPanel<S, T> {
|
||||
return add(value, component, skinElement to winding)
|
||||
}
|
||||
|
||||
fun add(value: T, pair: Pair<AbstractSkinElement, UVWindingOrder>): EnumRectangleButtonPanel<S, T> {
|
||||
check(building) { "Not building" }
|
||||
check(enumMapping.put(value, pair) == null) { "Already has mapping for $value" }
|
||||
|
||||
if (enumMapping.size == enum.enumConstants.size) {
|
||||
finish()
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
fun add(value: T, component: Component, pair: Pair<AbstractSkinElement, UVWindingOrder>): EnumRectangleButtonPanel<S, T> {
|
||||
addTooltip(value, component)
|
||||
return add(value, pair)
|
||||
}
|
||||
|
||||
fun finish(): EnumRectangleButtonPanel<S, T> {
|
||||
check(building) { "Not building" }
|
||||
check(isFullyDefined()) {
|
||||
"Not all enums having their mapping defined, missing are: ${missingValues.joinToString(", ")}"
|
||||
}
|
||||
|
||||
building = false
|
||||
return this
|
||||
}
|
||||
|
||||
override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
|
||||
check(!building) { "Still building this button!" }
|
||||
super.innerRender(stack, mouseX, mouseY, partialTick)
|
||||
val pair = checkNotNull(enumMapping[prop.get()]) { "HOW" }
|
||||
pair.first.render(stack, 0f, 0f, width, height, pair.second)
|
||||
}
|
||||
|
||||
override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean {
|
||||
check(!building) { "Still building this button!" }
|
||||
return super.mouseClickedInner(x, y, button)
|
||||
}
|
||||
|
||||
override fun mouseReleasedInner(x: Double, y: Double, button: Int): Boolean {
|
||||
check(!building) { "Still building this button!" }
|
||||
return super.mouseReleasedInner(x, y, button)
|
||||
}
|
||||
|
||||
override fun onClick(clickButton: Int) {
|
||||
when (clickButton) {
|
||||
InputConstants.MOUSE_BUTTON_LEFT -> {
|
||||
prop.value = prop.value.next(enum.enumConstants)
|
||||
onChange?.invoke(prop.get())
|
||||
}
|
||||
|
||||
InputConstants.MOUSE_BUTTON_RIGHT -> {
|
||||
prop.value = prop.value.prev(enum.enumConstants)
|
||||
onChange?.invoke(prop.get())
|
||||
}
|
||||
|
||||
InputConstants.MOUSE_BUTTON_MIDDLE -> {
|
||||
if (prop.get() != defaultValue) {
|
||||
prop.value = defaultValue
|
||||
onChange?.invoke(prop.get())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun innerRenderTooltips(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float): Boolean {
|
||||
if (!isHovered && !isGrabbingMouseInput()) {
|
||||
return super.innerRenderTooltips(stack, mouseX, mouseY, partialTick)
|
||||
}
|
||||
|
||||
if (mainTooltip == null && tooltipMapping.size == 0) {
|
||||
return super.innerRenderTooltips(stack, mouseX, mouseY, partialTick)
|
||||
}
|
||||
|
||||
val listing = ArrayList<Component>()
|
||||
|
||||
if (mainTooltip != null) {
|
||||
listing.add(mainTooltip!!)
|
||||
listing.add(SPACE)
|
||||
}
|
||||
|
||||
for ((key, value) in tooltipMapping) {
|
||||
if (key == prop.get()) {
|
||||
listing.add(value.copy().withStyle(ChatFormatting.WHITE))
|
||||
} else {
|
||||
listing.add(value.copy().withStyle(ChatFormatting.GRAY))
|
||||
}
|
||||
}
|
||||
|
||||
screen.renderComponentTooltip(
|
||||
stack,
|
||||
listing,
|
||||
mouseX.toInt(),
|
||||
mouseY.toInt(),
|
||||
font
|
||||
)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val SPACE = TextComponent("")
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package ru.dbotthepony.mc.otm.client.screen.panels.buttons
|
||||
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import ru.dbotthepony.mc.otm.client.render.AbstractSkinElement
|
||||
import ru.dbotthepony.mc.otm.client.render.Widgets18
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
|
||||
import ru.dbotthepony.mc.otm.core.GetterSetter
|
||||
|
||||
open class LargeBooleanRectangleButtonPanel<out S : Screen>(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float = SIZE,
|
||||
height: Float = SIZE,
|
||||
prop: GetterSetter<Boolean>,
|
||||
skinElementActive: AbstractSkinElement? = null,
|
||||
skinElementInactive: AbstractSkinElement? = null,
|
||||
onChange: ((newValue: Boolean) -> Unit)? = null,
|
||||
) : BooleanRectangleButtonPanel<S>(screen, parent, x, y, width, height, prop, skinElementActive, skinElementInactive, onChange) {
|
||||
final override val IDLE = Widgets18.BUTTON_IDLE
|
||||
final override val HOVERED = Widgets18.BUTTON_HOVERED
|
||||
final override val PRESSED = Widgets18.BUTTON_PRESSED
|
||||
final override val DISABLED = Widgets18.BUTTON_DISABLED
|
||||
|
||||
companion object {
|
||||
const val SIZE = 18f
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package ru.dbotthepony.mc.otm.client.screen.panels.buttons
|
||||
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import ru.dbotthepony.mc.otm.client.render.Widgets18
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
|
||||
import ru.dbotthepony.mc.otm.core.GetterSetter
|
||||
|
||||
open class LargeEnumRectangleButtonPanel<out S : Screen, T : Enum<T>>(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float = SIZE,
|
||||
height: Float = SIZE,
|
||||
enum: Class<T>,
|
||||
prop: GetterSetter<T>,
|
||||
defaultValue: T,
|
||||
onChange: ((newValue: T) -> Unit)? = null,
|
||||
) : EnumRectangleButtonPanel<S, T>(screen, parent, x, y, width, height, enum, prop, defaultValue, onChange) {
|
||||
final override val IDLE = Widgets18.BUTTON_IDLE
|
||||
final override val HOVERED = Widgets18.BUTTON_HOVERED
|
||||
final override val PRESSED = Widgets18.BUTTON_PRESSED
|
||||
final override val DISABLED = Widgets18.BUTTON_DISABLED
|
||||
|
||||
companion object {
|
||||
const val SIZE = 18f
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package ru.dbotthepony.mc.otm.client.screen.panels.buttons
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import ru.dbotthepony.mc.otm.client.render.AbstractSkinElement
|
||||
import ru.dbotthepony.mc.otm.client.render.UVWindingOrder
|
||||
import ru.dbotthepony.mc.otm.client.render.Widgets18
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
|
||||
|
||||
open class LargeRectangleButtonPanel<out S : Screen>(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float = SIZE,
|
||||
height: Float = SIZE,
|
||||
onPress: ((clickButton: Int) -> Unit)? = null,
|
||||
val skinElement: AbstractSkinElement? = null,
|
||||
val skinElementWinding: UVWindingOrder? = null,
|
||||
) : RectangleButtonPanel<S>(screen, parent, x, y, width, height, onPress) {
|
||||
final override val IDLE = Widgets18.BUTTON_IDLE
|
||||
final override val HOVERED = Widgets18.BUTTON_HOVERED
|
||||
final override val PRESSED = Widgets18.BUTTON_PRESSED
|
||||
final override val DISABLED = Widgets18.BUTTON_DISABLED
|
||||
|
||||
override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
|
||||
super.innerRender(stack, mouseX, mouseY, partialTick)
|
||||
|
||||
if (skinElementWinding != null) {
|
||||
skinElement?.render(stack, width = width, height = height, winding = skinElementWinding)
|
||||
} else {
|
||||
skinElement?.render(stack, width = width, height = height)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val SIZE = 18f
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
package ru.dbotthepony.mc.otm.client.screen.panels.buttons
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import ru.dbotthepony.mc.otm.client.playGuiClickSound
|
||||
import ru.dbotthepony.mc.otm.client.render.AbstractSkinElement
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
|
||||
|
||||
@Suppress("PropertyName")
|
||||
abstract class RectangleButtonPanel<out S : Screen>(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float,
|
||||
height: Float,
|
||||
val onPress: ((clickButton: Int) -> Unit)? = null,
|
||||
) : EditablePanel<S>(screen, parent, x, y, width, height) {
|
||||
protected var pressed = false
|
||||
|
||||
protected open fun onClick(clickButton: Int) {
|
||||
onPress?.invoke(clickButton)
|
||||
}
|
||||
|
||||
abstract val PRESSED: AbstractSkinElement
|
||||
abstract val HOVERED: AbstractSkinElement
|
||||
abstract val IDLE: AbstractSkinElement
|
||||
abstract val DISABLED: AbstractSkinElement
|
||||
|
||||
var isDisabled = false
|
||||
set(value) {
|
||||
if (field != value) {
|
||||
if (!value) {
|
||||
pressed = false
|
||||
grabMouseInput = false
|
||||
}
|
||||
|
||||
field = value
|
||||
}
|
||||
}
|
||||
|
||||
override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
|
||||
if (isDisabled) {
|
||||
DISABLED.render(stack, 0f, 0f, width, height)
|
||||
} else if (pressed) {
|
||||
PRESSED.render(stack, 0f, 0f, width, height)
|
||||
} else if (isHovered) {
|
||||
HOVERED.render(stack, 0f, 0f, width, height)
|
||||
} else {
|
||||
IDLE.render(stack, 0f, 0f, width, height)
|
||||
}
|
||||
}
|
||||
|
||||
override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean {
|
||||
if (!isDisabled) {
|
||||
if (!pressed) {
|
||||
playGuiClickSound()
|
||||
}
|
||||
|
||||
if (tryToGrabMouseInput()) {
|
||||
pressed = true
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun mouseReleasedInner(x: Double, y: Double, button: Int): Boolean {
|
||||
if (!isDisabled && pressed) {
|
||||
pressed = false
|
||||
|
||||
if (isHovered) {
|
||||
onClick(button)
|
||||
}
|
||||
}
|
||||
|
||||
grabMouseInput = false
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package ru.dbotthepony.mc.otm.client.screen.panels.buttons
|
||||
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import ru.dbotthepony.mc.otm.client.render.*
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
|
||||
import ru.dbotthepony.mc.otm.core.GetterSetter
|
||||
|
||||
open class SmallBooleanRectangleButtonPanel<out S : Screen>(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float = SIZE,
|
||||
height: Float = SIZE,
|
||||
prop: GetterSetter<Boolean>,
|
||||
skinElementActive: AbstractSkinElement? = null,
|
||||
skinElementInactive: AbstractSkinElement? = null,
|
||||
onChange: ((newValue: Boolean) -> Unit)? = null,
|
||||
) : BooleanRectangleButtonPanel<S>(screen, parent, x, y, width, height, prop, skinElementActive, skinElementInactive, onChange) {
|
||||
final override val IDLE = Widgets8.BUTTON_IDLE
|
||||
final override val HOVERED = Widgets8.BUTTON_HOVERED
|
||||
final override val PRESSED = Widgets8.BUTTON_PRESSED
|
||||
final override val DISABLED = Widgets8.BUTTON_DISABLED
|
||||
|
||||
companion object {
|
||||
const val SIZE = 8f
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package ru.dbotthepony.mc.otm.client.screen.panels.buttons
|
||||
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import ru.dbotthepony.mc.otm.client.render.Widgets8
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
|
||||
import ru.dbotthepony.mc.otm.core.GetterSetter
|
||||
|
||||
open class SmallEnumRectangleButtonPanel<out S : Screen, T : Enum<T>>(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float = SIZE,
|
||||
height: Float = SIZE,
|
||||
enum: Class<T>,
|
||||
prop: GetterSetter<T>,
|
||||
defaultValue: T,
|
||||
onChange: ((newValue: T) -> Unit)? = null,
|
||||
) : EnumRectangleButtonPanel<S, T>(screen, parent, x, y, width, height, enum, prop, defaultValue, onChange) {
|
||||
final override val IDLE = Widgets8.BUTTON_IDLE
|
||||
final override val HOVERED = Widgets8.BUTTON_HOVERED
|
||||
final override val PRESSED = Widgets8.BUTTON_PRESSED
|
||||
final override val DISABLED = Widgets8.BUTTON_DISABLED
|
||||
|
||||
companion object {
|
||||
const val SIZE = 8f
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package ru.dbotthepony.mc.otm.client.screen.panels.buttons
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import ru.dbotthepony.mc.otm.client.render.SkinElement
|
||||
import ru.dbotthepony.mc.otm.client.render.UVWindingOrder
|
||||
import ru.dbotthepony.mc.otm.client.render.Widgets8
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
|
||||
|
||||
open class SmallRectangleButtonPanel<out S : Screen>(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float = SIZE,
|
||||
height: Float = SIZE,
|
||||
onPress: ((clickButton: Int) -> Unit)? = null,
|
||||
val skinElement: SkinElement? = null,
|
||||
val skinElementWinding: UVWindingOrder? = null,
|
||||
) : RectangleButtonPanel<S>(screen, parent, x, y, width, height, onPress) {
|
||||
final override val IDLE = Widgets8.BUTTON_IDLE
|
||||
final override val HOVERED = Widgets8.BUTTON_HOVERED
|
||||
final override val PRESSED = Widgets8.BUTTON_PRESSED
|
||||
final override val DISABLED = Widgets8.BUTTON_DISABLED
|
||||
|
||||
override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
|
||||
super.innerRender(stack, mouseX, mouseY, partialTick)
|
||||
|
||||
if (skinElementWinding != null) {
|
||||
skinElement?.render(stack, width = width, height = height, winding = skinElementWinding)
|
||||
} else {
|
||||
skinElement?.render(stack, width = width, height = height)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val SIZE = 8f
|
||||
}
|
||||
}
|
@ -5,7 +5,6 @@ import com.mojang.blaze3d.vertex.PoseStack
|
||||
import lain.mods.cos.impl.ModObjects
|
||||
import lain.mods.cos.impl.client.PlayerRenderHandler
|
||||
import lain.mods.cos.impl.client.gui.GuiCosArmorInventory
|
||||
import lain.mods.cos.impl.client.gui.GuiCosArmorToggleButton
|
||||
import lain.mods.cos.impl.network.packet.PacketSetSkinArmor
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
@ -20,9 +19,8 @@ import net.minecraftforge.fml.ModList
|
||||
import ru.dbotthepony.mc.otm.client.minecraft
|
||||
import ru.dbotthepony.mc.otm.client.render.SkinElement
|
||||
import ru.dbotthepony.mc.otm.client.render.element
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.AbstractSlotPanel
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.RectangleButtonPanel
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.buttons.RectangleButtonPanel
|
||||
import ru.dbotthepony.mc.otm.compat.cos.CosmeticToggleButton.Companion.BUTTON_ACTIVE
|
||||
import ru.dbotthepony.mc.otm.compat.cos.CosmeticToggleButton.Companion.BUTTON_INACTIVE
|
||||
import ru.dbotthepony.mc.otm.container.awareStream
|
||||
|
Loading…
Reference in New Issue
Block a user