Exosuit display toggle button

This commit is contained in:
DBotThePony 2022-10-21 22:44:12 +07:00
parent 834efad363
commit a53438e1f9
Signed by: DBot
GPG Key ID: DCC23B5715498507
9 changed files with 233 additions and 45 deletions

View File

@ -5,7 +5,6 @@ import ru.dbotthepony.mc.otm.OverdriveThatMatters
object WidgetLocation {
val WIDGETS_18 = ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/widgets_18.png")
val WIDGETS_8 = ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/widgets_8.png")
val MISC = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "widgets/misc"), 64f, 64f)
val PATTERN_PANEL_TABS = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "widgets/pattern_panel_tabs"), 64f, 32f)

View File

@ -1,33 +1,26 @@
package ru.dbotthepony.mc.otm.client.render
import net.minecraft.resources.ResourceLocation
import ru.dbotthepony.mc.otm.OverdriveThatMatters
object Widgets8 {
val GRID = SkinGrid(WidgetLocation.WIDGETS_8, 8f, 8f)
val GRID = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "widgets_8"), 64f, 32f).subGrid(8f, 8f, 64 / 8, 32 / 8)
val BUTTON_IDLE = GRID.next()
val WHITE_ARROW_DOWN = GRID.next()
val S = GRID.next()
val F = GRID.next()
val E = GRID.next()
val ONE = GRID.next()
val BUTTON_IDLE = GRID[0, 0]
val BUTTON_HOVERED = GRID[0, 1]
val BUTTON_PRESSED = GRID[0, 2]
val BUTTON_DISABLED = GRID[0, 3]
init {
GRID.jump()
}
val WHITE_ARROW_DOWN = GRID[1, 0]
val S = GRID[2, 0]
val F = GRID[3, 0]
val E = GRID[4, 0]
val ONE = GRID[5, 0]
val BUTTON_HOVERED = GRID.next()
val ARROW_SIDEWAYS = GRID.next()
val ARROW_SIDEWAYS = GRID[1, 1]
val ARROW_PAINTED_UP = GRID[1, 2]
val MINUS = GRID[1, 3]
init {
GRID.jump()
}
val BUTTON_PRESSED = GRID.next()
val ARROW_PAINTED_UP = GRID.next()
init {
GRID.jump()
}
val BUTTON_DISABLED = GRID.next()
val MINUS = GRID.next()
val EXOSUIT_SHOWN = GRID[2, 1]
val EXOSUIT_HIDDEN = GRID[3, 1]
}

View File

@ -15,6 +15,7 @@ import ru.dbotthepony.mc.otm.client.render.Widgets8
import ru.dbotthepony.mc.otm.client.screen.panels.*
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
import ru.dbotthepony.mc.otm.core.maxScrollDivision
import ru.dbotthepony.mc.otm.core.formatReadableNumber
import ru.dbotthepony.mc.otm.core.formatSiComponent
@ -127,7 +128,7 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp
val refillPriority = SmallEnumRectangleButtonPanel(this, arrowLine,
enum = ItemMonitorPlayerSettings.IngredientPriority::class.java,
prop = menu.settings::ingredientPriority,
prop = menu.settings::ingredientPriority.asGetterSetter(),
defaultValue = ItemMonitorPlayerSettings.IngredientPriority.SYSTEM,
onChange = { menu.sendSettingsToServer() })
@ -149,7 +150,7 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp
val resultTarget = SmallEnumRectangleButtonPanel(this, resultAndButtons, y = 38f,
enum = ItemMonitorPlayerSettings.ResultTarget::class.java,
prop = menu.settings::resultTarget,
prop = menu.settings::resultTarget.asGetterSetter(),
defaultValue = ItemMonitorPlayerSettings.ResultTarget.MIXED,
onChange = { menu.sendSettingsToServer() })
@ -160,7 +161,7 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp
val craftingAmount = SmallEnumRectangleButtonPanel(this, resultAndButtons, x = 10f, y = 38f,
enum = ItemMonitorPlayerSettings.Amount::class.java,
prop = menu.settings::craftingAmount,
prop = menu.settings::craftingAmount.asGetterSetter(),
defaultValue = ItemMonitorPlayerSettings.Amount.STACK,
onChange = { menu.sendSettingsToServer() })

View File

@ -8,9 +8,11 @@ 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
@ -201,13 +203,13 @@ abstract class EnumRectangleButtonPanel<out S : Screen, T : Enum<T>>(
width: Float,
height: Float,
val enum: Class<T>,
val prop: KMutableProperty0<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<SkinElement, UVWindingOrder>>(enum)
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> {
@ -246,19 +248,19 @@ abstract class EnumRectangleButtonPanel<out S : Screen, T : Enum<T>>(
return missing
}
fun add(value: T, skinElement: SkinElement, winding: UVWindingOrder = UVWindingOrder.NORMAL): EnumRectangleButtonPanel<S, T> {
fun add(value: T, skinElement: AbstractSkinElement, winding: UVWindingOrder = UVWindingOrder.NORMAL): EnumRectangleButtonPanel<S, T> {
return add(value, skinElement to winding)
}
fun add(value: T, skinElement: SkinElement, component: Component, winding: UVWindingOrder = UVWindingOrder.NORMAL): EnumRectangleButtonPanel<S, T> {
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: SkinElement, winding: UVWindingOrder = UVWindingOrder.NORMAL): EnumRectangleButtonPanel<S, T> {
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<SkinElement, UVWindingOrder>): EnumRectangleButtonPanel<S, T> {
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" }
@ -269,7 +271,7 @@ abstract class EnumRectangleButtonPanel<out S : Screen, T : Enum<T>>(
return this
}
fun add(value: T, component: Component, pair: Pair<SkinElement, UVWindingOrder>): EnumRectangleButtonPanel<S, T> {
fun add(value: T, component: Component, pair: Pair<AbstractSkinElement, UVWindingOrder>): EnumRectangleButtonPanel<S, T> {
addTooltip(value, component)
return add(value, pair)
}
@ -304,18 +306,18 @@ abstract class EnumRectangleButtonPanel<out S : Screen, T : Enum<T>>(
override fun onClick(clickButton: Int) {
when (clickButton) {
InputConstants.MOUSE_BUTTON_LEFT -> {
prop.set(prop.get().next(enum.enumConstants))
prop.value = prop.value.next(enum.enumConstants)
onChange?.invoke(prop.get())
}
InputConstants.MOUSE_BUTTON_RIGHT -> {
prop.set(prop.get().prev(enum.enumConstants))
prop.value = prop.value.prev(enum.enumConstants)
onChange?.invoke(prop.get())
}
InputConstants.MOUSE_BUTTON_MIDDLE -> {
if (prop.get() != defaultValue) {
prop.set(defaultValue)
prop.value = defaultValue
onChange?.invoke(prop.get())
}
}
@ -362,6 +364,37 @@ abstract class EnumRectangleButtonPanel<out S : Screen, T : Enum<T>>(
}
}
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<*>?,
@ -370,7 +403,7 @@ open class LargeRectangleButtonPanel<out S : Screen>(
width: Float = SIZE,
height: Float = SIZE,
onPress: ((clickButton: Int) -> Unit)? = null,
val skinElement: SkinElement? = 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
@ -401,7 +434,7 @@ open class LargeEnumRectangleButtonPanel<out S : Screen, T : Enum<T>>(
width: Float = SIZE,
height: Float = SIZE,
enum: Class<T>,
prop: KMutableProperty0<T>,
prop: GetterSetter<T>,
defaultValue: T,
onChange: ((newValue: T) -> Unit)? = null,
) : EnumRectangleButtonPanel<S, T>(screen, parent, x, y, width, height, enum, prop, defaultValue, onChange) {
@ -415,6 +448,28 @@ open class LargeEnumRectangleButtonPanel<out S : Screen, T : Enum<T>>(
}
}
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<*>?,
@ -454,7 +509,7 @@ open class SmallEnumRectangleButtonPanel<out S : Screen, T : Enum<T>>(
width: Float = SIZE,
height: Float = SIZE,
enum: Class<T>,
prop: KMutableProperty0<T>,
prop: GetterSetter<T>,
defaultValue: T,
onChange: ((newValue: T) -> Unit)? = null,
) : EnumRectangleButtonPanel<S, T>(screen, parent, x, y, width, height, enum, prop, defaultValue, onChange) {
@ -467,3 +522,25 @@ open class SmallEnumRectangleButtonPanel<out S : Screen, T : Enum<T>>(
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
}
}

View File

@ -6,10 +6,16 @@ import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
import net.minecraft.client.gui.screens.inventory.InventoryScreen
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player
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.compat.cos.CosmeticToggleRenderButton
import ru.dbotthepony.mc.otm.compat.cos.isCosmeticArmorLoaded
import ru.dbotthepony.mc.otm.core.asGetterOnly
import ru.dbotthepony.mc.otm.network.DisplayExosuitPacket
import ru.dbotthepony.mc.otm.network.HideExosuitPacket
import ru.dbotthepony.mc.otm.network.MatteryPlayerNetworkChannel
private fun calculateScale(width: Float, height: Float): Int {
val aspectRatio = width / height
@ -49,6 +55,25 @@ class EntityRendererPanel<out S : Screen> @JvmOverloads constructor(
if (entity is Player && isCosmeticArmorLoaded) {
CosmeticToggleRenderButton(screen, this, x = this.width - 7f, y = this.height - 7f)
}
if (entity is Player) {
val matteryPlayer = entity.matteryPlayer
if (matteryPlayer != null && matteryPlayer.hasExoSuit) {
SmallBooleanRectangleButtonPanel(screen, this, this.width - 2f - SmallBooleanRectangleButtonPanel.SIZE, 2f,
prop = matteryPlayer::displayExoSuit.asGetterOnly(),
skinElementActive = Widgets8.EXOSUIT_SHOWN,
skinElementInactive = Widgets8.EXOSUIT_HIDDEN,
onChange = {
if (it) {
MatteryPlayerNetworkChannel.sendToServer(DisplayExosuitPacket)
} else {
MatteryPlayerNetworkChannel.sendToServer(HideExosuitPacket)
}
}
)
}
}
}
override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
@ -72,10 +97,19 @@ class EntityRendererPanel<out S : Screen> @JvmOverloads constructor(
override fun performLayout() {
super.performLayout()
val button = children.firstOrNull { it is CosmeticToggleRenderButton } as CosmeticToggleRenderButton? ?: return
val cosButton = children.firstOrNull { it is CosmeticToggleRenderButton } as CosmeticToggleRenderButton?
button.x = this.width - 7f
button.y = this.height - 7f
if (cosButton != null) {
cosButton.x = this.width - 7f
cosButton.y = this.height - 7f
}
val toggleButton = children.firstOrNull { it is SmallBooleanRectangleButtonPanel } as SmallBooleanRectangleButtonPanel?
if (toggleButton != null) {
toggleButton.x = this.width - 2f - toggleButton.width
toggleButton.y = 2f
}
}
}

View File

@ -0,0 +1,63 @@
package ru.dbotthepony.mc.otm.core
import java.util.function.Consumer
import java.util.function.Supplier
import kotlin.reflect.KMutableProperty0
import kotlin.reflect.KProperty
inline var <V> GetterSetter<V>.value: V
get() = get()
set(value) { accept(value) }
@Suppress("nothing_to_inline")
inline operator fun <V> GetterSetter<V>.getValue(thisRef: Any, property: KProperty<*>): V {
return get()
}
@Suppress("nothing_to_inline")
inline operator fun <V> GetterSetter<V>.setValue(thisRef: Any, property: KProperty<*>, value: V) {
accept(value)
}
interface GetterSetter<V> : Supplier<V>, Consumer<V> {
companion object {
fun <V> of(getter: Supplier<V>, setter: Consumer<V>): GetterSetter<V> {
return object : GetterSetter<V> {
override fun get(): V {
return getter.get()
}
override fun accept(t: V) {
setter.accept(t)
}
}
}
fun <V> of(getter: () -> V, setter: (V) -> Unit): GetterSetter<V> {
return object : GetterSetter<V> {
override fun get(): V {
return getter.invoke()
}
override fun accept(t: V) {
setter.invoke(t)
}
}
}
fun <V> of(property: KMutableProperty0<V>): GetterSetter<V> {
return object : GetterSetter<V> {
override fun get(): V {
return property.get()
}
override fun accept(t: V) {
property.set(t)
}
}
}
}
}
fun <V> KMutableProperty0<V>.asGetterSetter() = GetterSetter.of(this)
fun <V> KMutableProperty0<V>.asGetterOnly() = GetterSetter.of(Supplier { this.get() }, Consumer { /* do nothing */ })

View File

@ -492,6 +492,24 @@ class ShockwaveEffectPacket(val pos: Vector) : MatteryPacket {
}
}
object DisplayExosuitPacket : MatteryPacket {
override fun write(buff: FriendlyByteBuf) {}
override fun play(context: Supplier<NetworkEvent.Context>) {
context.packetHandled = true
context.sender?.matteryPlayer?.displayExoSuit = true
}
}
object HideExosuitPacket : MatteryPacket {
override fun write(buff: FriendlyByteBuf) {}
override fun play(context: Supplier<NetworkEvent.Context>) {
context.packetHandled = true
context.sender?.matteryPlayer?.displayExoSuit = false
}
}
object MatteryPlayerNetworkChannel : MatteryNetworkChannel(
version = "1",
name = "player"
@ -522,5 +540,8 @@ object MatteryPlayerNetworkChannel : MatteryNetworkChannel(
add(GlitchPacket::class, GlitchPacket.Companion::read, PLAY_TO_CLIENT)
add(ShockwaveEffectPacket::class, ShockwaveEffectPacket.Companion::read, PLAY_TO_CLIENT)
add(DisplayExosuitPacket::class, { DisplayExosuitPacket }, PLAY_TO_SERVER)
add(HideExosuitPacket::class, { HideExosuitPacket }, PLAY_TO_SERVER)
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 885 B

After

Width:  |  Height:  |  Size: 915 B