From a53438e1f95ba8d590e9ac3fe7cb08437de8f654 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 21 Oct 2022 22:44:12 +0700 Subject: [PATCH] Exosuit display toggle button --- .../mc/otm/client/render/WidgetLocation.kt | 1 - .../mc/otm/client/render/Widgets8.kt | 43 +++----- .../mc/otm/client/screen/ItemMonitorScreen.kt | 7 +- .../otm/client/screen/panels/ButtonPanel.kt | 103 +++++++++++++++--- .../screen/panels/EntityRendererPanel.kt | 40 ++++++- .../dbotthepony/mc/otm/core/GetterSetter.kt | 63 +++++++++++ .../network/MatteryPlayerNetworkChannel.kt | 21 ++++ .../textures/gui/widgets_8.png | Bin 885 -> 915 bytes .../textures/gui/widgets_8.xcf | Bin 5597 -> 6564 bytes 9 files changed, 233 insertions(+), 45 deletions(-) create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/core/GetterSetter.kt diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/WidgetLocation.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/WidgetLocation.kt index e49f0e87d..85b3a3bb3 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/WidgetLocation.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/WidgetLocation.kt @@ -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) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Widgets8.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Widgets8.kt index c80c0c379..4b39a9136 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Widgets8.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Widgets8.kt @@ -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] } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ItemMonitorScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ItemMonitorScreen.kt index a8b2ed4af..489fc4ea7 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ItemMonitorScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ItemMonitorScreen.kt @@ -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() }) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/ButtonPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/ButtonPanel.kt index 89c4b7e7c..99271f525 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/ButtonPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/ButtonPanel.kt @@ -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>( width: Float, height: Float, val enum: Class, - val prop: KMutableProperty0, + val prop: GetterSetter, val defaultValue: T, val onChange: ((newValue: T) -> Unit)? = null, ) : RectangleButtonPanel(screen, parent, x, y, width, height, null) { private var building = true - protected val enumMapping = EnumMap>(enum) + protected val enumMapping = EnumMap>(enum) protected val tooltipMapping = EnumMap(enum) fun addTooltip(value: T, component: Component): EnumRectangleButtonPanel { @@ -246,19 +248,19 @@ abstract class EnumRectangleButtonPanel>( return missing } - fun add(value: T, skinElement: SkinElement, winding: UVWindingOrder = UVWindingOrder.NORMAL): EnumRectangleButtonPanel { + fun add(value: T, skinElement: AbstractSkinElement, winding: UVWindingOrder = UVWindingOrder.NORMAL): EnumRectangleButtonPanel { return add(value, skinElement to winding) } - fun add(value: T, skinElement: SkinElement, component: Component, winding: UVWindingOrder = UVWindingOrder.NORMAL): EnumRectangleButtonPanel { + fun add(value: T, skinElement: AbstractSkinElement, component: Component, winding: UVWindingOrder = UVWindingOrder.NORMAL): EnumRectangleButtonPanel { return add(value, component, skinElement to winding) } - fun add(value: T, component: Component, skinElement: SkinElement, winding: UVWindingOrder = UVWindingOrder.NORMAL): EnumRectangleButtonPanel { + fun add(value: T, component: Component, skinElement: AbstractSkinElement, winding: UVWindingOrder = UVWindingOrder.NORMAL): EnumRectangleButtonPanel { return add(value, component, skinElement to winding) } - fun add(value: T, pair: Pair): EnumRectangleButtonPanel { + fun add(value: T, pair: Pair): EnumRectangleButtonPanel { check(building) { "Not building" } check(enumMapping.put(value, pair) == null) { "Already has mapping for $value" } @@ -269,7 +271,7 @@ abstract class EnumRectangleButtonPanel>( return this } - fun add(value: T, component: Component, pair: Pair): EnumRectangleButtonPanel { + fun add(value: T, component: Component, pair: Pair): EnumRectangleButtonPanel { addTooltip(value, component) return add(value, pair) } @@ -304,18 +306,18 @@ abstract class EnumRectangleButtonPanel>( 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>( } } +abstract class BooleanRectangleButtonPanel( + screen: S, + parent: EditablePanel<*>?, + x: Float = 0f, + y: Float = 0f, + width: Float, + height: Float, + val prop: GetterSetter, + val skinElementActive: AbstractSkinElement? = null, + val skinElementInactive: AbstractSkinElement? = null, + val onChange: ((newValue: Boolean) -> Unit)? = null, +) : RectangleButtonPanel(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( screen: S, parent: EditablePanel<*>?, @@ -370,7 +403,7 @@ open class LargeRectangleButtonPanel( width: Float = SIZE, height: Float = SIZE, onPress: ((clickButton: Int) -> Unit)? = null, - val skinElement: SkinElement? = null, + val skinElement: AbstractSkinElement? = null, val skinElementWinding: UVWindingOrder? = null, ) : RectangleButtonPanel(screen, parent, x, y, width, height, onPress) { final override val IDLE = Widgets18.BUTTON_IDLE @@ -401,7 +434,7 @@ open class LargeEnumRectangleButtonPanel>( width: Float = SIZE, height: Float = SIZE, enum: Class, - prop: KMutableProperty0, + prop: GetterSetter, defaultValue: T, onChange: ((newValue: T) -> Unit)? = null, ) : EnumRectangleButtonPanel(screen, parent, x, y, width, height, enum, prop, defaultValue, onChange) { @@ -415,6 +448,28 @@ open class LargeEnumRectangleButtonPanel>( } } +open class LargeBooleanRectangleButtonPanel( + screen: S, + parent: EditablePanel<*>?, + x: Float = 0f, + y: Float = 0f, + width: Float = SIZE, + height: Float = SIZE, + prop: GetterSetter, + skinElementActive: AbstractSkinElement? = null, + skinElementInactive: AbstractSkinElement? = null, + onChange: ((newValue: Boolean) -> Unit)? = null, +) : BooleanRectangleButtonPanel(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( screen: S, parent: EditablePanel<*>?, @@ -454,7 +509,7 @@ open class SmallEnumRectangleButtonPanel>( width: Float = SIZE, height: Float = SIZE, enum: Class, - prop: KMutableProperty0, + prop: GetterSetter, defaultValue: T, onChange: ((newValue: T) -> Unit)? = null, ) : EnumRectangleButtonPanel(screen, parent, x, y, width, height, enum, prop, defaultValue, onChange) { @@ -467,3 +522,25 @@ open class SmallEnumRectangleButtonPanel>( const val SIZE = 8f } } + +open class SmallBooleanRectangleButtonPanel( + screen: S, + parent: EditablePanel<*>?, + x: Float = 0f, + y: Float = 0f, + width: Float = SIZE, + height: Float = SIZE, + prop: GetterSetter, + skinElementActive: AbstractSkinElement? = null, + skinElementInactive: AbstractSkinElement? = null, + onChange: ((newValue: Boolean) -> Unit)? = null, +) : BooleanRectangleButtonPanel(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 + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EntityRendererPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EntityRendererPanel.kt index 45f58d039..86db7000e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EntityRendererPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EntityRendererPanel.kt @@ -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 @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 @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 + } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/GetterSetter.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/GetterSetter.kt new file mode 100644 index 000000000..10de8c854 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/GetterSetter.kt @@ -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 GetterSetter.value: V + get() = get() + set(value) { accept(value) } + +@Suppress("nothing_to_inline") +inline operator fun GetterSetter.getValue(thisRef: Any, property: KProperty<*>): V { + return get() +} + +@Suppress("nothing_to_inline") +inline operator fun GetterSetter.setValue(thisRef: Any, property: KProperty<*>, value: V) { + accept(value) +} + +interface GetterSetter : Supplier, Consumer { + companion object { + fun of(getter: Supplier, setter: Consumer): GetterSetter { + return object : GetterSetter { + override fun get(): V { + return getter.get() + } + + override fun accept(t: V) { + setter.accept(t) + } + } + } + + fun of(getter: () -> V, setter: (V) -> Unit): GetterSetter { + return object : GetterSetter { + override fun get(): V { + return getter.invoke() + } + + override fun accept(t: V) { + setter.invoke(t) + } + } + } + + fun of(property: KMutableProperty0): GetterSetter { + return object : GetterSetter { + override fun get(): V { + return property.get() + } + + override fun accept(t: V) { + property.set(t) + } + } + } + } +} + +fun KMutableProperty0.asGetterSetter() = GetterSetter.of(this) +fun KMutableProperty0.asGetterOnly() = GetterSetter.of(Supplier { this.get() }, Consumer { /* do nothing */ }) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerNetworkChannel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerNetworkChannel.kt index e237c8703..ec10ba2a9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerNetworkChannel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerNetworkChannel.kt @@ -492,6 +492,24 @@ class ShockwaveEffectPacket(val pos: Vector) : MatteryPacket { } } +object DisplayExosuitPacket : MatteryPacket { + override fun write(buff: FriendlyByteBuf) {} + + override fun play(context: Supplier) { + context.packetHandled = true + context.sender?.matteryPlayer?.displayExoSuit = true + } +} + +object HideExosuitPacket : MatteryPacket { + override fun write(buff: FriendlyByteBuf) {} + + override fun play(context: Supplier) { + 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) } } diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets_8.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets_8.png index bb630b4daee245c1497312e9e08652feccf0fe58..8144a8fa67cf6621d891b5f0236cc3d7723a3318 100644 GIT binary patch literal 915 zcmV;E18n?>P)EX>4Tx04R}tkv&MmKpe$iQ$;B)4ptO#$WWauh>AE$6^me@v=v%)FuC*#nlvOS zE{=k0!NHHks)LKOt`4q(Aou~|=;Wm6A|?JWDYS_3;J6>}?mh0_0Yam~RI_UWP&La) z#baVNw<`9$B7gyeFo=l6Og)ia%)oPe-NVP%yC~1{KKJJcDS49tK9P8i>4rtTK|Hf* z>74h8!>lAJ#OK8023?T&k?XR{Z=8z`3p_JyWK#3QVPdh^!Ey()lA#h$6Gs$PqkJLj zvch?bvs$UK);;+PgL!Qw&2^e1h+_!}Bq2gZ4P{hdAxf)8iis5M$2|PQjz38*nOtQs zax9<<6_Voz|AXJ%nuV!JHz^ncx?gPjV-)Dw1)6o+{yw(t<_X|`2ClTWzuEw1KS{5* zwa5|Bw+&oew>5bWxZDATo^;8O9LY~pC=`JAGy0|+(0>aA*4*A&`#607GSt=b4RCM> zj1?(+-Q(T8oxS~grq$mMkhyZRVnLd700006VoOIv0RI600RN!9r;`8x010qNS#tmY z3ljhU3ljkVnw%H_000McNliru<_Z-LD>Qv3qtXBX0gy>VK~!ko?N~8VgfJ9+*;!XR zYDWhx?d%w&r}6+a(%QNgu<`<1+hW53yaF$(&jD9e&y##jP?@B2bB&-2NtdMpBUV$izgk+kgwdc*2(z}DUC|Q;XMGS&~06-kaLOw|n zGMOH**>*eS`Q`mTyee4V(fNT#i$^rZ+H0}!M>;ZNP*w5jKj=?Yt?H*87m5_8CXZ8ZvO;G1h p*Kcs^023TA=Sg54U`n@_;Rg%5=0fI#A$R})002ovPDHLkV1hWyl`sGR literal 885 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7xzrU~J8Fb`J1#c2+1T%1_J8No8Qr zm{>c}*5j~)%+dJZty-e&)*TipD;`~FTG6pMWFv=|SMs5{T z6T8+F+A9d;amMr&A@%Vg| z=|1at4T{bzW)hwBnEikA{kyYTPjZ@TN-$f+=lo7);dsN;J1e(d{&v}8mJjyK;ZdjK zS27#VUvfPv>IcV*`)qpaqG#=4k9o(??7u6;qwmRbO%bjGza?vf`6PC*R)ycaH|w`W zErZdOtCx5S3OIViG^@`(zI*rW-oMq$ZrFdh=jFXd{S*iVUbs8`#3q4&NLn>~)y>&3~ zuz>*U1ykmjyS`Q)+=Y?>T)9V&TUTx+ITKiZ$I;ENo;NOEEBaK|$ZkXZVgr)vl@ayL!}k=dUk2mrB{oG~74HJrgv!sQ2_$ z{q~mIwmG@)rpfMARdl<4?d>0H^#fZpy?JHY6IKRpS7~^5-;i%(UShfM$LT#|QQ^9qLJgPRGnVbXn^P#k_MJiK!SBEe zng?tf6j%I|JD?3>6mT7|W%&PJV#odWYn|SHXIOqYbK8w=YehftI(+1uu=$&Lfwu;u rhArcp5>AJcoDZ_)fuTwY(74H-CA%(g$;+QdK-xTA{an^LB{Ts5Ym0ky diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets_8.xcf b/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets_8.xcf index ea899055572248bd9bad66ff2e2e0e21127357ac..594d60564c6ac3e44c0e6d34b4f2639b71313647 100644 GIT binary patch delta 1044 zcmbVKO=uHA7~Pr8ZZ_E_+1=)+X(3%gJ(L_Y*y^FFe`XPrM$q}jt&P$KQ`nK;3s#;9 z4xSXO{T3W1g1g29N27vcX9b%(1Y7HZ<4*)9PYdo*h>QAd+ikiF?n`%x)g`auRlVEp zYul^13*L-Z^Qy$N>Pin=(MSW2n1{r2yUH@j>%Ca+CtrfeX?bs3*CeHgq@Ts*)z#&q z^lzgSHL2|x9vvO-czliDvqtG!$Kz`@Jrqd_MTdFmfKpkaRO2_|g@eEOz_xkax9|Y- z>>=jeH>4c9rx<(*G9P50d?)Y~GAjr&E9v%#wL$AQ2yUwrRHH0HaVKY(&HBxn+ zhHfAn(?E?4a5WU;e|LV!jGiDhJ?zwU8DV1*OvZIsH6A!CUH1{T_JC>~2h}PQ68%VW zW}T?U5ggCLFuo6l@p0#-F^zEI138xHL*GG6>Q2F8Ia3v|rXGQsdf}{hmk>_dpr#94 XJ(WHo?!|udj53b4ftLB7$$t75FMJS@ delta 571 zcmZ2td{^5iJu|mJp&~g=q0GS0kO2r9pcurS2E>9u%*Y5Ngn-x)h!sE_2@oLwA~=|U zL;#5JnCNcLXgsm~b>sse4+xk$AvCKtgl0Pep*b2MG?zVu=AH_ndBY$yzc_>zxDTO) zra)*ByUDj1 zV$%Q#vblf-*)_LpFJ4#v$VxN8`hIO{=zoU_4# zoSQdS@wPBBaa)1}xkG`1;vBgUCoxR+=NH`^z|YIb#4`gV&9eophv&@Z$pSMOnfTH{ zf_%+jLB83OlZ0-wfWm6BJl}-LCx!i)1foF-1j@k*1o}7oiPSSP2?>A%g>*oITtY5T zs~9HRi%Eg-W_vLUMke81AVtF0z&eHBZC)#$$;c!c2@(`71qnup_QG^>FtCO(V!<2? J