fix crash when shutting down; improve element handling of menu

This commit is contained in:
Bixilon 2022-01-25 14:03:53 +01:00
parent 1f010c44a6
commit dc4c54d069
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
6 changed files with 76 additions and 56 deletions

View File

@ -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 :(
"""
}

View File

@ -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
}

View File

@ -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() {

View File

@ -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 {

View File

@ -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() })
}

View File

@ -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)
}