mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-18 20:05:02 -04:00
fix crash when shutting down; improve element handling of menu
This commit is contained in:
parent
1f010c44a6
commit
dc4c54d069
@ -40,7 +40,8 @@ class AboutController : EmbeddedJavaFXController<HBox>() {
|
||||
bixilonLogoFX.children.setAll(JavaFXUtil.BIXILON_LOGO)
|
||||
|
||||
versionStringFX.text = RunConfiguration.VERSION_STRING
|
||||
aboutTextFX.text = """
|
||||
aboutTextFX.text =
|
||||
"""
|
||||
No clue what to put here :(
|
||||
"""
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2022 Moritz Zwerger
|
||||
* Copyright (C) 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.
|
||||
*
|
||||
@ -11,7 +11,7 @@
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.gui.rendering.gui.elements.button
|
||||
package de.bixilon.minosoft.gui.rendering.gui.elements.input.button
|
||||
|
||||
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.gui.elements.Element
|
||||
@ -32,6 +32,7 @@ import glm_.vec2.Vec2i
|
||||
open class ButtonElement(
|
||||
guiRenderer: GUIRenderer,
|
||||
text: Any,
|
||||
disabled: Boolean = false,
|
||||
var onSubmit: () -> Unit,
|
||||
) : Element(guiRenderer) {
|
||||
protected val textElement = TextElement(guiRenderer, text, background = false).apply { parent = this@ButtonElement }
|
||||
@ -58,7 +59,7 @@ open class ButtonElement(
|
||||
super.size = value // will call forceApply
|
||||
}
|
||||
|
||||
var disabled: Boolean = false
|
||||
var disabled: Boolean = disabled
|
||||
set(value) {
|
||||
if (field == value) {
|
||||
return
|
||||
@ -103,6 +104,9 @@ open class ButtonElement(
|
||||
}
|
||||
|
||||
override fun onMouseAction(position: Vec2i, button: MouseButtons, action: MouseActions) {
|
||||
if (disabled) {
|
||||
return
|
||||
}
|
||||
if (button != MouseButtons.LEFT) {
|
||||
return
|
||||
}
|
||||
@ -117,6 +121,9 @@ open class ButtonElement(
|
||||
if (!hovered) {
|
||||
return
|
||||
}
|
||||
if (disabled) {
|
||||
return
|
||||
}
|
||||
if (key != InputSpecialKey.KEY_ENTER) {
|
||||
return
|
||||
}
|
@ -11,7 +11,7 @@
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.gui.rendering.gui.elements.button
|
||||
package de.bixilon.minosoft.gui.rendering.gui.elements.input.button
|
||||
|
||||
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
|
||||
|
||||
@ -19,8 +19,9 @@ open class ConfirmButtonElement(
|
||||
guiRenderer: GUIRenderer,
|
||||
val text: Any,
|
||||
val confirmText: Any,
|
||||
disabled: Boolean = false,
|
||||
onSubmit: () -> Unit,
|
||||
) : ButtonElement(guiRenderer, text, onSubmit) {
|
||||
) : ButtonElement(guiRenderer, text, disabled, onSubmit) {
|
||||
private var confirming = false
|
||||
|
||||
override fun submit() {
|
@ -15,7 +15,7 @@ package de.bixilon.minosoft.gui.rendering.gui.gui.screen.menu
|
||||
|
||||
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.button.ButtonElement
|
||||
import de.bixilon.minosoft.gui.rendering.gui.elements.input.button.ButtonElement
|
||||
import de.bixilon.minosoft.gui.rendering.gui.gui.screen.Screen
|
||||
import de.bixilon.minosoft.gui.rendering.gui.input.mouse.MouseActions
|
||||
import de.bixilon.minosoft.gui.rendering.gui.input.mouse.MouseButtons
|
||||
@ -23,26 +23,29 @@ import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
|
||||
import glm_.vec2.Vec2i
|
||||
|
||||
abstract class Menu(guiRenderer: GUIRenderer) : Screen(guiRenderer) {
|
||||
private val buttons: MutableList<ButtonElement> = mutableListOf()
|
||||
abstract class Menu(
|
||||
guiRenderer: GUIRenderer,
|
||||
val preferredElementWidth: Int = 150,
|
||||
) : Screen(guiRenderer) {
|
||||
private val elements: MutableList<Element> = mutableListOf()
|
||||
|
||||
private var buttonWidth = -1
|
||||
private var elementWidth = -1
|
||||
private var totalHeight = -1
|
||||
|
||||
private var activeButton: ButtonElement? = null
|
||||
private var activeElement: Element? = null
|
||||
|
||||
override fun forceSilentApply() {
|
||||
buttonWidth = size.x / 3 // 1 left and right
|
||||
elementWidth = maxOf(minOf(preferredElementWidth, size.x / 3), 0)
|
||||
|
||||
var totalHeight = 0
|
||||
for (button in buttons) {
|
||||
val currentButtonSize = button.size
|
||||
val buttonSize = Vec2i(buttonWidth, currentButtonSize.y)
|
||||
button.prefMaxSize = buttonSize
|
||||
button.size = buttonSize
|
||||
for (element in elements) {
|
||||
val currentButtonSize = element.size
|
||||
val elementSize = Vec2i(elementWidth, currentButtonSize.y)
|
||||
element.prefMaxSize = elementSize
|
||||
element.size = elementSize
|
||||
totalHeight += currentButtonSize.y
|
||||
}
|
||||
totalHeight += maxOf(0, (buttons.size - 1) * BUTTON_Y_MARGIN)
|
||||
totalHeight += maxOf(0, (elements.size - 1) * BUTTON_Y_MARGIN)
|
||||
this.totalHeight = totalHeight
|
||||
super.forceSilentApply()
|
||||
cacheUpToDate = false
|
||||
@ -50,70 +53,75 @@ abstract class Menu(guiRenderer: GUIRenderer) : Screen(guiRenderer) {
|
||||
|
||||
fun addButton(button: ButtonElement) {
|
||||
button.parent = this
|
||||
buttons += button
|
||||
elements += button
|
||||
forceSilentApply()
|
||||
}
|
||||
|
||||
override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer, options: GUIVertexOptions?): Int {
|
||||
val size = size
|
||||
var zUsed = super.forceRender(offset, z, consumer, options)
|
||||
val startOffset = (size - Vec2i(buttonWidth, totalHeight)) / 2
|
||||
for (button in buttons) {
|
||||
zUsed = maxOf(zUsed, button.render(offset + startOffset, z + zUsed, consumer, options) + zUsed)
|
||||
startOffset.y += BUTTON_Y_MARGIN + button.size.y
|
||||
val startOffset = (size - Vec2i(elementWidth, totalHeight)) / 2
|
||||
for (element in elements) {
|
||||
zUsed = maxOf(zUsed, element.render(offset + startOffset, z + zUsed, consumer, options) + zUsed)
|
||||
startOffset.y += BUTTON_Y_MARGIN + element.size.y
|
||||
}
|
||||
return zUsed
|
||||
}
|
||||
|
||||
override fun onMouseLeave() {
|
||||
activeButton?.onMouseLeave()
|
||||
activeButton = null
|
||||
activeElement?.onMouseLeave()
|
||||
activeElement = null
|
||||
}
|
||||
|
||||
override fun onMouseMove(position: Vec2i) {
|
||||
val (delta, button) = getButtonAndPositionAt(position)
|
||||
val (delta, element) = getAt(position)
|
||||
|
||||
if (activeButton != button) {
|
||||
activeButton?.onMouseLeave()
|
||||
button?.onMouseEnter(delta)
|
||||
activeButton = button
|
||||
if (activeElement != element) {
|
||||
activeElement?.onMouseLeave()
|
||||
element?.onMouseEnter(delta)
|
||||
activeElement = element
|
||||
return
|
||||
}
|
||||
button?.onMouseMove(delta)
|
||||
element?.onMouseMove(delta)
|
||||
}
|
||||
|
||||
override fun onMouseAction(position: Vec2i, button: MouseButtons, action: MouseActions) {
|
||||
val (delta, buttonElement) = getButtonAndPositionAt(position)
|
||||
buttonElement?.onMouseAction(delta, button, action)
|
||||
val (delta, element) = getAt(position)
|
||||
element?.onMouseAction(delta, button, action)
|
||||
}
|
||||
|
||||
override fun onChildChange(child: Element) {
|
||||
forceSilentApply()
|
||||
}
|
||||
|
||||
fun getButtonAndPositionAt(position: Vec2i): Pair<Vec2i, ButtonElement?> {
|
||||
var delta = position
|
||||
var button: ButtonElement? = null
|
||||
if (position.x in buttonWidth..buttonWidth * 2) {
|
||||
// x matches
|
||||
val yStart = (size.y - totalHeight) / 2
|
||||
var yOffset = position.y - yStart
|
||||
for (buttonEntry in buttons) {
|
||||
if (yOffset < 0) {
|
||||
break
|
||||
}
|
||||
val buttonSize = buttonEntry.size
|
||||
if (yOffset < buttonSize.y) {
|
||||
button = buttonEntry
|
||||
break
|
||||
}
|
||||
yOffset -= buttonSize.y
|
||||
yOffset -= BUTTON_Y_MARGIN
|
||||
}
|
||||
delta = Vec2i(position.x - buttonWidth, yOffset)
|
||||
fun getAt(position: Vec2i): Pair<Vec2i, Element?> {
|
||||
val delta = Vec2i(position)
|
||||
var element: Element? = null
|
||||
val elementWidth = elementWidth
|
||||
val size = size
|
||||
val xStart = (size.x - elementWidth) / 2
|
||||
if (position.x < xStart || position.x >= xStart + elementWidth) {
|
||||
return Pair(Vec2i(0, 0), null)
|
||||
}
|
||||
delta.x = position.x - xStart
|
||||
// x matches
|
||||
val yStart = (size.y - totalHeight) / 2
|
||||
var yOffset = position.y - yStart
|
||||
for (buttonEntry in elements) {
|
||||
if (yOffset < 0) {
|
||||
break
|
||||
}
|
||||
val buttonSize = buttonEntry.size
|
||||
if (yOffset < buttonSize.y) {
|
||||
element = buttonEntry
|
||||
break
|
||||
}
|
||||
yOffset -= buttonSize.y
|
||||
yOffset -= BUTTON_Y_MARGIN
|
||||
}
|
||||
delta.y = yOffset
|
||||
|
||||
return Pair(delta, button)
|
||||
return Pair(delta, element)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
@ -14,8 +14,8 @@
|
||||
package de.bixilon.minosoft.gui.rendering.gui.gui.screen.menu.pause
|
||||
|
||||
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.gui.elements.button.ButtonElement
|
||||
import de.bixilon.minosoft.gui.rendering.gui.elements.button.ConfirmButtonElement
|
||||
import de.bixilon.minosoft.gui.rendering.gui.elements.input.button.ButtonElement
|
||||
import de.bixilon.minosoft.gui.rendering.gui.elements.input.button.ConfirmButtonElement
|
||||
import de.bixilon.minosoft.gui.rendering.gui.gui.screen.menu.Menu
|
||||
import de.bixilon.minosoft.util.ShutdownManager
|
||||
|
||||
@ -23,6 +23,7 @@ class PauseMenu(guiRenderer: GUIRenderer) : Menu(guiRenderer) {
|
||||
|
||||
init {
|
||||
addButton(ButtonElement(guiRenderer, "Back to game") { guiRenderer.gui.pause(false) })
|
||||
addButton(ButtonElement(guiRenderer, "Debug options", disabled = true) { TODO() })
|
||||
addButton(ConfirmButtonElement(guiRenderer, "§cDisconnect", "§cClick again to disconnect!") { guiRenderer.connection.network.disconnect() })
|
||||
addButton(ConfirmButtonElement(guiRenderer, "§4Exit", "§4Click again to exit!") { guiRenderer.connection.network.disconnect(); ShutdownManager.shutdown() })
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
import de.bixilon.minosoft.util.logging.Log
|
||||
import de.bixilon.minosoft.util.logging.LogLevels
|
||||
import de.bixilon.minosoft.util.logging.LogMessageType
|
||||
import javafx.application.Platform
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
object ShutdownManager {
|
||||
@ -35,6 +36,7 @@ object ShutdownManager {
|
||||
}
|
||||
FileWatcherService.stop()
|
||||
DefaultThreadPool.shutdownNow()
|
||||
Platform.exit()
|
||||
exitProcess(reason.exitCode)
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user