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