gui: switches, sign editor: option to remove limit

This commit is contained in:
Bixilon 2022-04-23 20:18:02 +02:00
parent e103543534
commit 647bfb25a5
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
11 changed files with 280 additions and 10 deletions

View File

@ -21,6 +21,7 @@ import de.bixilon.minosoft.config.profile.profiles.gui.GUIProfileManager.latestV
import de.bixilon.minosoft.config.profile.profiles.gui.chat.ChatC
import de.bixilon.minosoft.config.profile.profiles.gui.confirmation.ConfirmationC
import de.bixilon.minosoft.config.profile.profiles.gui.hud.HudC
import de.bixilon.minosoft.config.profile.profiles.gui.sign.SignC
/**
* Profile for gui (rendering)
@ -46,6 +47,7 @@ class GUIProfile(
val chat = ChatC()
val hud = HudC()
val confirmation = ConfirmationC()
val sign = SignC()
override fun toString(): String {
return GUIProfileManager.getName(this)

View File

@ -1,6 +1,6 @@
/*
* Minosoft
* Copyright (C) 2022 Moritz Zwerger
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
@ -16,8 +16,8 @@ package de.bixilon.minosoft.config.profile.profiles.gui.confirmation
import de.bixilon.minosoft.config.profile.profiles.gui.GUIProfileManager.delegate
class ConfirmationC {
val copyToClipboard by delegate(true)
val openFile by delegate(true)
val openURL by delegate(true)
val sendMessage by delegate(true)
var copyToClipboard by delegate(true)
var openFile by delegate(true)
var openURL by delegate(true)
var sendMessage by delegate(true)
}

View File

@ -0,0 +1,20 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.config.profile.profiles.gui.sign
import de.bixilon.minosoft.config.profile.profiles.gui.GUIProfileManager.delegate
class SignC {
var limitLength by delegate(true)
}

View File

@ -199,13 +199,11 @@ abstract class Element(val guiRenderer: GUIRenderer, var initialCacheSize: Int =
/**
* Force applies all changes made to any property, but does not notify the parent about the change
*/
@Deprecated("Generally a bad idea to call")
abstract fun forceSilentApply()
/**
* Force applied all changes made to any property and calls `parent?.onChildChange(this)`
*/
@Deprecated("Generally a bad idea to call")
open fun forceApply() {
if (this is Pollable) {
poll()

View File

@ -31,7 +31,7 @@ enum class VerticalAlignments {
}
fun VerticalAlignments.getOffset(size: Vec2i, childSize: Vec2i): Vec2i {
return Vec2i(0, getOffset(size.x, childSize.x))
return Vec2i(0, getOffset(size.y, childSize.y))
}
}
}

View File

@ -0,0 +1,19 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.gui.elements.input.checkbox
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
import de.bixilon.minosoft.gui.rendering.gui.elements.Element
abstract class AbstractCheckboxElement(guiRenderer: GUIRenderer) : Element(guiRenderer)

View File

@ -0,0 +1,171 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.gui.elements.input.checkbox
import de.bixilon.kotlinglm.vec2.Vec2i
import de.bixilon.minosoft.config.key.KeyCodes
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
import de.bixilon.minosoft.gui.rendering.gui.elements.Element
import de.bixilon.minosoft.gui.rendering.gui.elements.VerticalAlignments
import de.bixilon.minosoft.gui.rendering.gui.elements.VerticalAlignments.Companion.getOffset
import de.bixilon.minosoft.gui.rendering.gui.elements.primitive.AtlasImageElement
import de.bixilon.minosoft.gui.rendering.gui.elements.text.TextElement
import de.bixilon.minosoft.gui.rendering.gui.input.mouse.MouseActions
import de.bixilon.minosoft.gui.rendering.gui.input.mouse.MouseButtons
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
import de.bixilon.minosoft.gui.rendering.system.window.CursorShapes
import de.bixilon.minosoft.gui.rendering.system.window.KeyChangeTypes
import de.bixilon.minosoft.util.KUtil.toResourceLocation
open class SwitchElement(
guiRenderer: GUIRenderer,
text: Any,
state: Boolean = false,
disabled: Boolean = false,
parent: Element?,
var onChange: (state: Boolean) -> Unit,
) : AbstractCheckboxElement(guiRenderer) {
protected val textElement = TextElement(guiRenderer, text, background = false).apply { this.parent = this@SwitchElement }
private val disabledAtlas = guiRenderer.atlasManager["minosoft:switch_disabled"]
private val normalAtlas = guiRenderer.atlasManager["minosoft:switch_normal"]
private val hoveredAtlas = guiRenderer.atlasManager["minosoft:switch_hovered"]
private val onStateAtlas = guiRenderer.atlasManager["minosoft:switch_state_on"]
private val offStateAtlas = guiRenderer.atlasManager["minosoft:switch_state_off"]
var state: Boolean = state
set(value) {
if (field == value) {
return
}
field = value
onChange(state)
forceApply()
}
var disabled: Boolean = disabled
set(value) {
if (field == value) {
return
}
field = value
forceApply()
}
var hovered: Boolean = false
private set(value) {
if (field == value) {
return
}
field = value
forceApply()
}
override val canFocus: Boolean
get() = !disabled
init {
size = SIZE + Vec2i(5 + TEXT_MARGIN + textElement.size.x, 0)
this.parent = parent
}
override fun forceRender(offset: Vec2i, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
val texture = when {
disabled -> disabledAtlas
hovered -> hoveredAtlas
else -> normalAtlas
} ?: guiRenderer.renderWindow.WHITE_TEXTURE
val size = size
val background = AtlasImageElement(guiRenderer, texture)
background.size = SIZE
background.render(offset, consumer, options)
if (state) {
AtlasImageElement(guiRenderer, onStateAtlas, size = SLIDER_SIZE).render(offset + Vec2i(SIZE.x - SLIDER_SIZE.x, 0), consumer, options)
} else {
AtlasImageElement(guiRenderer, offStateAtlas, size = SLIDER_SIZE).render(offset, consumer, options)
}
textElement.render(offset + Vec2i(SIZE.x + TEXT_MARGIN, VerticalAlignments.CENTER.getOffset(size.y, textElement.size.y)), consumer, options)
}
override fun forceSilentApply() {
textElement.silentApply()
cacheUpToDate = false
}
override fun onMouseAction(position: Vec2i, button: MouseButtons, action: MouseActions, count: Int): Boolean {
if (disabled) {
return true
}
if (button != MouseButtons.LEFT) {
return true
}
if (action != MouseActions.PRESS) {
return true
}
switchState()
return true
}
override fun onKey(key: KeyCodes, type: KeyChangeTypes): Boolean {
if (!hovered) {
return true
}
if (disabled) {
return true
}
if (key != KeyCodes.KEY_ENTER) {
return true
}
if (type != KeyChangeTypes.PRESS) {
return true
}
switchState()
return true
}
override fun onMouseEnter(position: Vec2i, absolute: Vec2i): Boolean {
hovered = true
renderWindow.window.cursorShape = CursorShapes.HAND
return true
}
override fun onMouseLeave(): Boolean {
hovered = false
renderWindow.window.resetCursor()
return true
}
open fun switchState() {
state = !state
if (guiRenderer.connection.profiles.audio.gui.button) {
guiRenderer.connection.world.play2DSound(CLICK_SOUND)
}
}
private companion object {
val CLICK_SOUND = "minecraft:ui.button.click".toResourceLocation()
const val TEXT_MARGIN = 5
val SIZE = Vec2i(30, 20)
val SLIDER_SIZE = Vec2i(6, 20)
}
}

View File

@ -47,7 +47,7 @@ class TextInputElement(
val cutAtSize: Boolean = false,
parent: Element? = null,
) : Element(guiRenderer) {
private val cursor = ColorElement(guiRenderer, size = Vec2i(1, Font.TOTAL_CHAR_HEIGHT * scale))
private val cursor = ColorElement(guiRenderer, size = Vec2i(minOf(1.0f, scale), Font.TOTAL_CHAR_HEIGHT * scale))
private val textElement = MarkTextElement(guiRenderer, "", background = false, parent = this, scale = scale, shadow = shadow)
private val backgroundElement = ColorElement(guiRenderer, Vec2i.EMPTY, RenderConstants.TEXT_BACKGROUND_COLOR)
private var cursorOffset: Vec2i = Vec2i.EMPTY
@ -117,6 +117,9 @@ class TextInputElement(
if (newValue.length != this._value.length) {
_set(newValue.toString())
}
if (_pointer > newValue.length) {
_pointer = newValue.length
}
}
override fun forceSilentApply() {

View File

@ -21,13 +21,17 @@ import de.bixilon.kutil.cast.CastUtil.unsafeCast
import de.bixilon.minosoft.config.key.KeyCodes
import de.bixilon.minosoft.data.entities.block.SignBlockEntity
import de.bixilon.minosoft.data.registries.blocks.BlockState
import de.bixilon.minosoft.data.registries.blocks.types.entity.sign.SignBlock
import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.gui.rendering.font.Font
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
import de.bixilon.minosoft.gui.rendering.gui.elements.Element
import de.bixilon.minosoft.gui.rendering.gui.elements.HorizontalAlignments
import de.bixilon.minosoft.gui.rendering.gui.elements.HorizontalAlignments.Companion.getOffset
import de.bixilon.minosoft.gui.rendering.gui.elements.VerticalAlignments
import de.bixilon.minosoft.gui.rendering.gui.elements.VerticalAlignments.Companion.getOffset
import de.bixilon.minosoft.gui.rendering.gui.elements.input.button.ButtonElement
import de.bixilon.minosoft.gui.rendering.gui.elements.input.checkbox.SwitchElement
import de.bixilon.minosoft.gui.rendering.gui.elements.primitive.ImageElement
import de.bixilon.minosoft.gui.rendering.gui.elements.text.TextElement
import de.bixilon.minosoft.gui.rendering.gui.gui.AbstractLayout
@ -56,6 +60,7 @@ class SignEditorScreen(
private val backgroundElement = ImageElement(guiRenderer, getTexture(), uvStart = SIGN_UV_START, uvEnd = SIGN_UV_END, size = BACKGROUND_SIZE)
private val lines = Array(SignBlockEntity.LINES) { TextInputElement(guiRenderer, blockEntity?.lines?.get(it)?.message ?: "", 256, scale = TEXT_SCALE, background = false, cutAtSize = true, parent = this) }
private val doneButton = ButtonElement(guiRenderer, "Done") { guiRenderer.gui.pop() }.apply { size = Vec2i(BACKGROUND_SIZE.x, size.y);parent = this@SignEditorScreen }
private val lengthLimitSwitch = SwitchElement(guiRenderer, "Limit length", guiRenderer.connection.profiles.gui.sign.limitLength, parent = this) { guiRenderer.connection.profiles.gui.sign.limitLength = it; forceSilentApply() }
override var activeElement: Element? = null
override var activeDragElement: Element? = null
private var activeLine = 0
@ -68,11 +73,15 @@ class SignEditorScreen(
}
private fun getTexture(): AbstractTexture? {
return blockState?.blockModel?.nullCast<BakedBlockStateModel>()?.faces?.firstOrNull()?.firstOrNull()?.texture ?: guiRenderer.atlasManager["minecraft:sign_front"]?.texture
if (blockState?.block !is SignBlock) {
return guiRenderer.atlasManager["minecraft:sign_front"]?.texture
}
return blockState.blockModel?.nullCast<BakedBlockStateModel>()?.faces?.firstOrNull()?.firstOrNull()?.texture ?: guiRenderer.atlasManager["minecraft:sign_front"]?.texture
}
override fun forceRender(offset: Vec2i, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
super.forceRender(offset, consumer, options)
lengthLimitSwitch.render(offset + VerticalAlignments.BOTTOM.getOffset(size, lengthLimitSwitch.size), consumer, options)
val size = size
@ -111,9 +120,22 @@ class SignEditorScreen(
guiRenderer.connection.sendPacket(SignTextC2SP(blockPosition, text))
}
override fun forceSilentApply() {
super.forceSilentApply()
for (line in lines) {
line.prefMaxSize = Vec2i(if (lengthLimitSwitch.state) SignBlockEntityRenderer.SIGN_MAX_WIDTH * TEXT_SCALE else -1, line.prefMaxSize.y)
}
}
override fun getAt(position: Vec2i): Pair<Element, Vec2i>? {
val size = size
if (position.y in size.y - lengthLimitSwitch.size.y..size.y) {
position.y -= size.y - lengthLimitSwitch.size.y
getAtCheck(position, lengthLimitSwitch, HorizontalAlignments.LEFT, false)?.let { return it }
}
position.y -= size.y / 8
getAtCheck(position, headerElement, HorizontalAlignments.CENTER, true)?.let { return it }
if (position.y < 0) {

View File

@ -1333,5 +1333,40 @@
"start": [2, 2],
"end": [26, 14]
}
},
"minosoft:switch_normal": {
"0": {
"texture": "minosoft:textures/icons.png",
"start": [0, 10],
"end": [30, 31]
}
},
"minosoft:switch_disabled": {
"0": {
"texture": "minosoft:textures/icons.png",
"start": [30, 10],
"end": [60, 31]
}
},
"minosoft:switch_hovered": {
"0": {
"texture": "minosoft:textures/icons.png",
"start": [60, 10],
"end": [90, 31]
}
},
"minosoft:switch_state_off": {
"0": {
"texture": "minosoft:textures/icons.png",
"start": [90, 10],
"end": [96, 31]
}
},
"minosoft:switch_state_on": {
"0": {
"texture": "minosoft:textures/icons.png",
"start": [96, 10],
"end": [102, 31]
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 526 B

After

Width:  |  Height:  |  Size: 664 B