mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-19 04:15:14 -04:00
gui: poppers (wip), mouse movement fixes
This commit is contained in:
parent
9fd1688b39
commit
704de95b94
@ -33,7 +33,7 @@ class CopyToClipboardClickEvent(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
val dialog = CopyToClipboardDialog(guiRenderer, text)
|
val dialog = CopyToClipboardDialog(guiRenderer, text)
|
||||||
dialog.open()
|
dialog.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object : ClickEventFactory<CopyToClipboardClickEvent> {
|
companion object : ClickEventFactory<CopyToClipboardClickEvent> {
|
||||||
|
@ -40,7 +40,7 @@ class OpenFileClickEvent(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
val dialog = OpenFileConfirmationDialog(guiRenderer, path)
|
val dialog = OpenFileConfirmationDialog(guiRenderer, path)
|
||||||
dialog.open()
|
dialog.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object : ClickEventFactory<OpenFileClickEvent> {
|
companion object : ClickEventFactory<OpenFileClickEvent> {
|
||||||
|
@ -43,7 +43,7 @@ class OpenURLClickEvent(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
val dialog = URLConfirmationDialog(guiRenderer, url)
|
val dialog = URLConfirmationDialog(guiRenderer, url)
|
||||||
dialog.open()
|
dialog.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object : ClickEventFactory<OpenURLClickEvent> {
|
companion object : ClickEventFactory<OpenURLClickEvent> {
|
||||||
|
@ -34,7 +34,7 @@ class SendMessageClickEvent(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
val dialog = SendMessageDialog(guiRenderer, message)
|
val dialog = SendMessageDialog(guiRenderer, message)
|
||||||
dialog.open()
|
dialog.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object : ClickEventFactory<SendMessageClickEvent>, MultiNameFactory<SendMessageClickEvent> {
|
companion object : ClickEventFactory<SendMessageClickEvent>, MultiNameFactory<SendMessageClickEvent> {
|
||||||
|
@ -14,5 +14,12 @@
|
|||||||
package de.bixilon.minosoft.data.text.events.hover
|
package de.bixilon.minosoft.data.text.events.hover
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.text.events.ChatEvent
|
import de.bixilon.minosoft.data.text.events.ChatEvent
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
|
||||||
|
import glm_.vec2.Vec2i
|
||||||
|
|
||||||
interface HoverEvent : ChatEvent
|
interface HoverEvent : ChatEvent {
|
||||||
|
|
||||||
|
fun onMouseEnter(guiRenderer: GUIRenderer, position: Vec2i) = false
|
||||||
|
fun onMouseMove(guiRenderer: GUIRenderer, position: Vec2i) = false
|
||||||
|
fun onMouseLeave(guiRenderer: GUIRenderer) = false
|
||||||
|
}
|
||||||
|
@ -15,17 +15,39 @@ package de.bixilon.minosoft.data.text.events.hover
|
|||||||
|
|
||||||
import de.bixilon.kutil.json.JsonObject
|
import de.bixilon.kutil.json.JsonObject
|
||||||
import de.bixilon.minosoft.data.text.ChatComponent
|
import de.bixilon.minosoft.data.text.ChatComponent
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.popper.text.TextPopper
|
||||||
|
import glm_.vec2.Vec2i
|
||||||
import javafx.scene.text.Text
|
import javafx.scene.text.Text
|
||||||
|
|
||||||
class TextHoverEvent(
|
class TextHoverEvent(
|
||||||
text: Any?,
|
text: Any?,
|
||||||
) : HoverEvent {
|
) : HoverEvent {
|
||||||
val text = ChatComponent.of(text)
|
val text = ChatComponent.of(text)
|
||||||
|
private var popper: TextPopper? = null
|
||||||
|
|
||||||
override fun applyJavaFX(text: Text) {
|
override fun applyJavaFX(text: Text) {
|
||||||
text.accessibleText = this.text.message
|
text.accessibleText = this.text.message
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onMouseEnter(guiRenderer: GUIRenderer, position: Vec2i): Boolean {
|
||||||
|
val popper = TextPopper(guiRenderer, position, text)
|
||||||
|
popper.show()
|
||||||
|
this.popper = popper
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMouseMove(guiRenderer: GUIRenderer, position: Vec2i): Boolean {
|
||||||
|
popper?.position = position
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMouseLeave(guiRenderer: GUIRenderer): Boolean {
|
||||||
|
this.popper?.let { guiRenderer.popper -= it }
|
||||||
|
this.popper = null
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
companion object : HoverEventFactory<TextHoverEvent> {
|
companion object : HoverEventFactory<TextHoverEvent> {
|
||||||
override val name: String = "show_text"
|
override val name: String = "show_text"
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ import de.bixilon.minosoft.gui.rendering.gui.atlas.AtlasManager
|
|||||||
import de.bixilon.minosoft.gui.rendering.gui.gui.GUIManager
|
import de.bixilon.minosoft.gui.rendering.gui.gui.GUIManager
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.hud.HUDManager
|
import de.bixilon.minosoft.gui.rendering.gui.hud.HUDManager
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.input.ModifierKeys
|
import de.bixilon.minosoft.gui.rendering.gui.input.ModifierKeys
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.popper.PopperManager
|
||||||
import de.bixilon.minosoft.gui.rendering.input.InputHandler
|
import de.bixilon.minosoft.gui.rendering.input.InputHandler
|
||||||
import de.bixilon.minosoft.gui.rendering.modding.events.ResizeWindowEvent
|
import de.bixilon.minosoft.gui.rendering.modding.events.ResizeWindowEvent
|
||||||
import de.bixilon.minosoft.gui.rendering.renderer.Renderer
|
import de.bixilon.minosoft.gui.rendering.renderer.Renderer
|
||||||
@ -47,6 +48,7 @@ class GUIRenderer(
|
|||||||
var scaledSize: Vec2i = renderWindow.window.size
|
var scaledSize: Vec2i = renderWindow.window.size
|
||||||
val gui = GUIManager(this)
|
val gui = GUIManager(this)
|
||||||
val hud = HUDManager(this)
|
val hud = HUDManager(this)
|
||||||
|
val popper = PopperManager(this)
|
||||||
var matrix: Mat4 = Mat4()
|
var matrix: Mat4 = Mat4()
|
||||||
private set
|
private set
|
||||||
var matrixChange = true
|
var matrixChange = true
|
||||||
@ -64,6 +66,7 @@ class GUIRenderer(
|
|||||||
atlasManager.init()
|
atlasManager.init()
|
||||||
gui.init()
|
gui.init()
|
||||||
hud.init()
|
hud.init()
|
||||||
|
popper.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun postInit(latch: CountUpAndDownLatch) {
|
override fun postInit(latch: CountUpAndDownLatch) {
|
||||||
@ -77,6 +80,7 @@ class GUIRenderer(
|
|||||||
|
|
||||||
gui.postInit()
|
gui.postInit()
|
||||||
hud.postInit()
|
hud.postInit()
|
||||||
|
popper.postInit()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun recalculateMatrices(windowSize: Vec2i = renderWindow.window.size, scale: Float = profile.scale) {
|
private fun recalculateMatrices(windowSize: Vec2i = renderWindow.window.size, scale: Float = profile.scale) {
|
||||||
@ -86,6 +90,7 @@ class GUIRenderer(
|
|||||||
|
|
||||||
gui.onMatrixChange()
|
gui.onMatrixChange()
|
||||||
hud.onMatrixChange()
|
hud.onMatrixChange()
|
||||||
|
popper.onMatrixChange()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setup() {
|
fun setup() {
|
||||||
@ -119,6 +124,7 @@ class GUIRenderer(
|
|||||||
override fun drawOther() {
|
override fun drawOther() {
|
||||||
hud.draw()
|
hud.draw()
|
||||||
gui.draw()
|
gui.draw()
|
||||||
|
popper.draw()
|
||||||
if (this.matrixChange) {
|
if (this.matrixChange) {
|
||||||
this.matrixChange = false
|
this.matrixChange = false
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,7 @@ open class TextElement(
|
|||||||
parent: Element? = null,
|
parent: Element? = null,
|
||||||
scale: Float = 1.0f,
|
scale: Float = 1.0f,
|
||||||
) : Element(guiRenderer, text.toString().length * 6 * GUIMesh.GUIMeshStruct.FLOATS_PER_VERTEX), Labeled {
|
) : Element(guiRenderer, text.toString().length * 6 * GUIMesh.GUIMeshStruct.FLOATS_PER_VERTEX), Labeled {
|
||||||
|
private var activeElement: TextComponent? = null
|
||||||
lateinit var renderInfo: TextRenderInfo
|
lateinit var renderInfo: TextRenderInfo
|
||||||
private set
|
private set
|
||||||
|
|
||||||
@ -175,12 +176,36 @@ open class TextElement(
|
|||||||
if (action != MouseActions.PRESS || button != MouseButtons.LEFT) {
|
if (action != MouseActions.PRESS || button != MouseButtons.LEFT) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
val text = getTextComponentAt(position) ?: return false
|
val pair = getTextComponentAt(position) ?: return false
|
||||||
text.clickEvent?.onClick(guiRenderer, position, button, action)
|
pair.first.clickEvent?.onClick(guiRenderer, pair.second, button, action)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getTextComponentAt(position: Vec2i): TextComponent? {
|
override fun onMouseEnter(position: Vec2i): Boolean {
|
||||||
|
val pair = getTextComponentAt(position) ?: return false
|
||||||
|
activeElement = pair.first
|
||||||
|
pair.first.hoverEvent?.onMouseEnter(guiRenderer, pair.second)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMouseMove(position: Vec2i): Boolean {
|
||||||
|
val pair = getTextComponentAt(position)
|
||||||
|
|
||||||
|
if (activeElement != pair?.first) {
|
||||||
|
val activeElement = activeElement
|
||||||
|
this.activeElement = pair?.first
|
||||||
|
return (activeElement?.hoverEvent?.onMouseLeave(guiRenderer) ?: false) || (pair?.first?.hoverEvent?.onMouseEnter(guiRenderer, pair.second) ?: false)
|
||||||
|
}
|
||||||
|
return pair?.first?.hoverEvent?.onMouseMove(guiRenderer, pair.second) ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMouseLeave(): Boolean {
|
||||||
|
activeElement?.hoverEvent?.onMouseLeave(guiRenderer) ?: return false
|
||||||
|
activeElement = null
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getTextComponentAt(position: Vec2i): Pair<TextComponent, Vec2i>? {
|
||||||
val offset = Vec2i(position)
|
val offset = Vec2i(position)
|
||||||
val line = renderInfo.lines.getOrNull(offset.y / charHeight) ?: return null
|
val line = renderInfo.lines.getOrNull(offset.y / charHeight) ?: return null
|
||||||
offset.y = offset.y % charHeight
|
offset.y = offset.y % charHeight
|
||||||
@ -191,7 +216,7 @@ open class TextElement(
|
|||||||
|
|
||||||
offset.x += fontAlignment.getOffset(size.x, line.width)
|
offset.x += fontAlignment.getOffset(size.x, line.width)
|
||||||
|
|
||||||
return line.text.getTextAt(textElement.renderInfo.lines.getOrNull(0)?.text?.message?.length ?: return null)
|
return Pair(line.text.getTextAt(textElement.renderInfo.lines.getOrNull(0)?.text?.message?.length ?: return null), offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
|
@ -22,8 +22,7 @@ import de.bixilon.minosoft.gui.rendering.font.Font
|
|||||||
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.primitive.ColorElement
|
import de.bixilon.minosoft.gui.rendering.gui.elements.primitive.ColorElement
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.input.mouse.MouseActions
|
import de.bixilon.minosoft.gui.rendering.gui.gui.ActiveMouseMove
|
||||||
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.GUIVertexConsumer
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
|
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
|
||||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.EMPTY
|
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.EMPTY
|
||||||
@ -34,9 +33,10 @@ import glm_.vec2.Vec2i
|
|||||||
open class TextFlowElement(
|
open class TextFlowElement(
|
||||||
guiRenderer: GUIRenderer,
|
guiRenderer: GUIRenderer,
|
||||||
var messageExpireTime: Long,
|
var messageExpireTime: Long,
|
||||||
) : Element(guiRenderer) {
|
) : Element(guiRenderer), ActiveMouseMove<TextElement> {
|
||||||
private val messages: MutableList<TextFlowTextElement> = synchronizedListOf() // all messages **from newest to oldest**
|
private val messages: MutableList<TextFlowTextElement> = synchronizedListOf() // all messages **from newest to oldest**
|
||||||
private var visibleLines: List<TextFlowLineElement> = listOf() // all visible lines **from bottom to top**
|
private var visibleLines: List<TextFlowLineElement> = listOf() // all visible lines **from bottom to top**
|
||||||
|
override var activeElement: TextElement? = null
|
||||||
|
|
||||||
private val background = ColorElement(guiRenderer, size, RenderConstants.TEXT_BACKGROUND_COLOR)
|
private val background = ColorElement(guiRenderer, size, RenderConstants.TEXT_BACKGROUND_COLOR)
|
||||||
|
|
||||||
@ -181,13 +181,12 @@ open class TextFlowElement(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMouseAction(position: Vec2i, button: MouseButtons, action: MouseActions): Boolean {
|
override fun getAt(position: Vec2i): Pair<TextElement, Vec2i>? {
|
||||||
val pair = getAt(position) ?: return false
|
val line = getLineAt(position) ?: return null
|
||||||
pair.first.textElement.onMouseAction(pair.second, button, action)
|
return Pair(line.first.textElement, line.second)
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getAt(position: Vec2i): Pair<TextFlowLineElement, Vec2i>? {
|
private fun getLineAt(position: Vec2i): Pair<TextFlowLineElement, Vec2i>? {
|
||||||
val reversedY = size.y - position.y
|
val reversedY = size.y - position.y
|
||||||
val line = visibleLines.getOrNull(reversedY / Font.TOTAL_CHAR_HEIGHT) ?: return null
|
val line = visibleLines.getOrNull(reversedY / Font.TOTAL_CHAR_HEIGHT) ?: return null
|
||||||
if (position.x > line.textElement.size.x) {
|
if (position.x > line.textElement.size.x) {
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* 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 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.gui
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.elements.Element
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.input.InputElement
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.input.mouse.MouseActions
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.input.mouse.MouseButtons
|
||||||
|
import glm_.vec2.Vec2i
|
||||||
|
|
||||||
|
interface ActiveMouseMove<T : Element> : InputElement {
|
||||||
|
var activeElement: T?
|
||||||
|
|
||||||
|
fun getAt(position: Vec2i): Pair<T, Vec2i>?
|
||||||
|
|
||||||
|
override fun onMouseEnter(position: Vec2i): Boolean {
|
||||||
|
val pair = getAt(position)
|
||||||
|
activeElement = pair?.first
|
||||||
|
return pair?.first?.onMouseEnter(pair.second) ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMouseMove(position: Vec2i): Boolean {
|
||||||
|
val pair = getAt(position)
|
||||||
|
|
||||||
|
if (activeElement != pair?.first) {
|
||||||
|
val activeElement = activeElement
|
||||||
|
this.activeElement = pair?.first
|
||||||
|
return (activeElement?.onMouseLeave() ?: false) || (pair?.first?.onMouseEnter(pair.second) ?: false)
|
||||||
|
}
|
||||||
|
return pair?.first?.onMouseMove(pair.second) ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMouseLeave(): Boolean {
|
||||||
|
val activeElement = activeElement
|
||||||
|
this.activeElement = null
|
||||||
|
return activeElement?.onMouseLeave() ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMouseAction(position: Vec2i, button: MouseButtons, action: MouseActions): Boolean {
|
||||||
|
val pair = getAt(position) ?: return false
|
||||||
|
return pair.first.onMouseAction(pair.second, button, action)
|
||||||
|
}
|
||||||
|
}
|
@ -80,6 +80,11 @@ class GUIManager(
|
|||||||
|
|
||||||
fun draw() {
|
fun draw() {
|
||||||
val order = elementOrder.reversed()
|
val order = elementOrder.reversed()
|
||||||
|
val time = TimeUtil.time
|
||||||
|
val tick = time - lastTickTime > ProtocolDefinition.TICK_TIME
|
||||||
|
if (tick) {
|
||||||
|
lastTickTime = time
|
||||||
|
}
|
||||||
for ((index, element) in order.withIndex()) {
|
for ((index, element) in order.withIndex()) {
|
||||||
if (!element.enabled) {
|
if (!element.enabled) {
|
||||||
continue
|
continue
|
||||||
@ -87,8 +92,7 @@ class GUIManager(
|
|||||||
if (index != order.size - 1 && !element.activeWhenHidden) {
|
if (index != order.size - 1 && !element.activeWhenHidden) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
val time = TimeUtil.time
|
if (tick) {
|
||||||
if (time - lastTickTime > ProtocolDefinition.TICK_TIME) {
|
|
||||||
element.tick()
|
element.tick()
|
||||||
if (element is Pollable) {
|
if (element is Pollable) {
|
||||||
if (element.poll()) {
|
if (element.poll()) {
|
||||||
@ -220,6 +224,7 @@ class GUIManager(
|
|||||||
previous.onClose()
|
previous.onClose()
|
||||||
if (elementOrder.isEmpty()) {
|
if (elementOrder.isEmpty()) {
|
||||||
renderWindow.inputHandler.inputHandler = null
|
renderWindow.inputHandler.inputHandler = null
|
||||||
|
guiRenderer.popper.clear()
|
||||||
}
|
}
|
||||||
val now = elementOrder.firstOrNull() ?: return
|
val now = elementOrder.firstOrNull() ?: return
|
||||||
now.onOpen()
|
now.onOpen()
|
||||||
@ -230,6 +235,7 @@ class GUIManager(
|
|||||||
element.onClose()
|
element.onClose()
|
||||||
}
|
}
|
||||||
elementOrder.clear()
|
elementOrder.clear()
|
||||||
|
guiRenderer.popper.clear()
|
||||||
renderWindow.inputHandler.inputHandler = null
|
renderWindow.inputHandler.inputHandler = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ package de.bixilon.minosoft.gui.rendering.gui.gui.screen.menu
|
|||||||
import de.bixilon.minosoft.config.key.KeyCodes
|
import de.bixilon.minosoft.config.key.KeyCodes
|
||||||
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.gui.ActiveMouseMove
|
||||||
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
|
||||||
@ -29,13 +30,13 @@ import glm_.vec2.Vec2i
|
|||||||
abstract class Menu(
|
abstract class Menu(
|
||||||
guiRenderer: GUIRenderer,
|
guiRenderer: GUIRenderer,
|
||||||
val preferredElementWidth: Int = 150,
|
val preferredElementWidth: Int = 150,
|
||||||
) : Screen(guiRenderer) {
|
) : Screen(guiRenderer), ActiveMouseMove<Element> {
|
||||||
private val elements: MutableList<Element> = mutableListOf()
|
private val elements: MutableList<Element> = mutableListOf()
|
||||||
|
|
||||||
private var maxElementWidth = -1
|
private var maxElementWidth = -1
|
||||||
private var totalHeight = -1
|
private var totalHeight = -1
|
||||||
|
|
||||||
private var activeElement: Element? = null
|
override var activeElement: Element? = null
|
||||||
|
|
||||||
override fun forceSilentApply() {
|
override fun forceSilentApply() {
|
||||||
val elementWidth = maxOf(minOf(preferredElementWidth, size.x / 3), 0)
|
val elementWidth = maxOf(minOf(preferredElementWidth, size.x / 3), 0)
|
||||||
@ -75,32 +76,6 @@ abstract class Menu(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMouseLeave(): Boolean {
|
|
||||||
activeElement?.onMouseLeave()
|
|
||||||
activeElement = null
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMouseMove(position: Vec2i): Boolean {
|
|
||||||
val pair = getAt(position)
|
|
||||||
|
|
||||||
if (activeElement != pair?.first) {
|
|
||||||
activeElement?.onMouseLeave()
|
|
||||||
pair?.first?.onMouseEnter(pair.second)
|
|
||||||
activeElement = pair?.first
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
pair?.first?.onMouseMove(pair.second)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMouseEnter(position: Vec2i): Boolean {
|
|
||||||
val pair = getAt(position)
|
|
||||||
pair?.first?.onMouseEnter(pair.second)
|
|
||||||
activeElement = pair?.first
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMouseAction(position: Vec2i, button: MouseButtons, action: MouseActions): Boolean {
|
override fun onMouseAction(position: Vec2i, button: MouseButtons, action: MouseActions): Boolean {
|
||||||
val (element, delta) = getAt(position) ?: return true
|
val (element, delta) = getAt(position) ?: return true
|
||||||
element.onMouseAction(delta, button, action)
|
element.onMouseAction(delta, button, action)
|
||||||
@ -111,7 +86,7 @@ abstract class Menu(
|
|||||||
forceSilentApply()
|
forceSilentApply()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAt(position: Vec2i): Pair<Element, Vec2i>? {
|
override fun getAt(position: Vec2i): Pair<Element, Vec2i>? {
|
||||||
var element: Element? = null
|
var element: Element? = null
|
||||||
val delta = Vec2i(position)
|
val delta = Vec2i(position)
|
||||||
val elementWidth = maxElementWidth
|
val elementWidth = maxElementWidth
|
||||||
|
@ -34,7 +34,7 @@ abstract class AbstractConfirmationMenu(
|
|||||||
guiRenderer.gui.pop()
|
guiRenderer.gui.pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun open() {
|
fun show() {
|
||||||
guiRenderer.gui.push(this)
|
guiRenderer.gui.push(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,9 +121,10 @@ class LayoutedGUIElement<T : LayoutedElement>(
|
|||||||
return elementLayout.onMouseLeave()
|
return elementLayout.onMouseLeave()
|
||||||
}
|
}
|
||||||
val delta = position - offset
|
val delta = position - offset
|
||||||
|
val previousOutside = lastPosition == INVALID_MOUSE_POSITION
|
||||||
this.lastPosition = delta
|
this.lastPosition = delta
|
||||||
|
|
||||||
if (lastPosition.isOutside(offset, size)) {
|
if (previousOutside) {
|
||||||
return elementLayout.onMouseEnter(delta)
|
return elementLayout.onMouseEnter(delta)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,10 +136,7 @@ class LayoutedGUIElement<T : LayoutedElement>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onKeyPress(type: KeyChangeTypes, key: KeyCodes): Boolean {
|
override fun onKeyPress(type: KeyChangeTypes, key: KeyCodes): Boolean {
|
||||||
val mouseButton = MouseButtons[key]
|
val mouseButton = MouseButtons[key] ?: return elementLayout.onKey(key, type)
|
||||||
if (mouseButton == null) {
|
|
||||||
return elementLayout.onKey(key, type)
|
|
||||||
}
|
|
||||||
|
|
||||||
val position = lastPosition
|
val position = lastPosition
|
||||||
if (position == INVALID_MOUSE_POSITION) {
|
if (position == INVALID_MOUSE_POSITION) {
|
||||||
|
@ -17,6 +17,7 @@ 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.LayoutedElement
|
import de.bixilon.minosoft.gui.rendering.gui.elements.LayoutedElement
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.elements.text.TextFlowElement
|
import de.bixilon.minosoft.gui.rendering.gui.elements.text.TextFlowElement
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.gui.ActiveMouseMove
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.hud.Initializable
|
import de.bixilon.minosoft.gui.rendering.gui.hud.Initializable
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
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
|
||||||
@ -24,16 +25,16 @@ import de.bixilon.minosoft.gui.rendering.renderer.Drawable
|
|||||||
import glm_.vec2.Vec2d
|
import glm_.vec2.Vec2d
|
||||||
import glm_.vec2.Vec2i
|
import glm_.vec2.Vec2i
|
||||||
|
|
||||||
abstract class AbstractChatElement(guiRenderer: GUIRenderer) : Element(guiRenderer), LayoutedElement, Initializable, Drawable {
|
abstract class AbstractChatElement(guiRenderer: GUIRenderer) : Element(guiRenderer), LayoutedElement, Initializable, Drawable, ActiveMouseMove<Element> {
|
||||||
protected val connection = renderWindow.connection
|
protected val connection = renderWindow.connection
|
||||||
protected val profile = connection.profiles.gui
|
protected val profile = connection.profiles.gui
|
||||||
protected val messages = TextFlowElement(guiRenderer, 20000).apply { parent = this@AbstractChatElement }
|
protected val messages = TextFlowElement(guiRenderer, 20000).apply { parent = this@AbstractChatElement }
|
||||||
|
override var activeElement: Element? = null
|
||||||
|
|
||||||
override fun forceRender(offset: Vec2i, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
|
override fun forceRender(offset: Vec2i, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
|
||||||
messages.render(offset + Vec2i(ChatElement.CHAT_INPUT_MARGIN, 0), consumer, options)
|
messages.render(offset + Vec2i(ChatElement.CHAT_INPUT_MARGIN, 0), consumer, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onScroll(position: Vec2i, scrollOffset: Vec2d): Boolean {
|
override fun onScroll(position: Vec2i, scrollOffset: Vec2d): Boolean {
|
||||||
val size = messages.size
|
val size = messages.size
|
||||||
if (position.y > size.y || position.x > messages.size.x) {
|
if (position.y > size.y || position.x > messages.size.x) {
|
||||||
|
@ -27,8 +27,6 @@ import de.bixilon.minosoft.gui.rendering.gui.gui.GUIBuilder
|
|||||||
import de.bixilon.minosoft.gui.rendering.gui.gui.elements.input.TextInputElement
|
import de.bixilon.minosoft.gui.rendering.gui.gui.elements.input.TextInputElement
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.HUDBuilder
|
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.HUDBuilder
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.LayoutedGUIElement
|
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.LayoutedGUIElement
|
||||||
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.GUIVertexConsumer
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
|
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
|
||||||
import de.bixilon.minosoft.gui.rendering.system.window.KeyChangeTypes
|
import de.bixilon.minosoft.gui.rendering.system.window.KeyChangeTypes
|
||||||
@ -202,13 +200,7 @@ class ChatElement(guiRenderer: GUIRenderer) : AbstractChatElement(guiRenderer) {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMouseAction(position: Vec2i, button: MouseButtons, action: MouseActions): Boolean {
|
override fun getAt(position: Vec2i): Pair<Element, Vec2i>? {
|
||||||
val pair = getAt(position) ?: return false
|
|
||||||
pair.first.onMouseAction(pair.second, button, action)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getAt(position: Vec2i): Pair<Element, Vec2i>? {
|
|
||||||
if (position.x < CHAT_INPUT_MARGIN) {
|
if (position.x < CHAT_INPUT_MARGIN) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,6 @@ import de.bixilon.minosoft.gui.rendering.gui.elements.Element
|
|||||||
import de.bixilon.minosoft.gui.rendering.gui.gui.GUIBuilder
|
import de.bixilon.minosoft.gui.rendering.gui.gui.GUIBuilder
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.HUDBuilder
|
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.HUDBuilder
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.LayoutedGUIElement
|
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.LayoutedGUIElement
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.input.mouse.MouseActions
|
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.input.mouse.MouseButtons
|
|
||||||
import de.bixilon.minosoft.modding.event.events.InternalMessageReceiveEvent
|
import de.bixilon.minosoft.modding.event.events.InternalMessageReceiveEvent
|
||||||
import de.bixilon.minosoft.modding.event.invoker.CallbackEventInvoker
|
import de.bixilon.minosoft.modding.event.invoker.CallbackEventInvoker
|
||||||
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||||
@ -82,13 +80,7 @@ class InternalChatElement(guiRenderer: GUIRenderer) : AbstractChatElement(guiRen
|
|||||||
guiRenderer.gui.pop() // pop normal chat
|
guiRenderer.gui.pop() // pop normal chat
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMouseAction(position: Vec2i, button: MouseButtons, action: MouseActions): Boolean {
|
override fun getAt(position: Vec2i): Pair<Element, Vec2i>? {
|
||||||
val pair = getAt(position) ?: return false
|
|
||||||
pair.first.onMouseAction(pair.second, button, action)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getAt(position: Vec2i): Pair<Element, Vec2i>? {
|
|
||||||
if (position.x < ChatElement.CHAT_INPUT_MARGIN) {
|
if (position.x < ChatElement.CHAT_INPUT_MARGIN) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,8 @@ import de.bixilon.minosoft.gui.rendering.system.window.KeyChangeTypes
|
|||||||
import glm_.vec2.Vec2d
|
import glm_.vec2.Vec2d
|
||||||
import glm_.vec2.Vec2i
|
import glm_.vec2.Vec2i
|
||||||
|
|
||||||
interface InputElement {
|
interface InputElement : MouseInputElement {
|
||||||
|
|
||||||
fun onMouseMove(position: Vec2i) = false
|
|
||||||
fun onMouseEnter(position: Vec2i) = false
|
|
||||||
fun onMouseLeave() = false
|
|
||||||
fun onMouseAction(position: Vec2i, button: MouseButtons, action: MouseActions) = false
|
fun onMouseAction(position: Vec2i, button: MouseButtons, action: MouseActions) = false
|
||||||
fun onScroll(position: Vec2i, scrollOffset: Vec2d) = false
|
fun onScroll(position: Vec2i, scrollOffset: Vec2d) = false
|
||||||
|
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* 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 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.input
|
||||||
|
|
||||||
|
import glm_.vec2.Vec2i
|
||||||
|
|
||||||
|
interface MouseInputElement {
|
||||||
|
|
||||||
|
fun onMouseEnter(position: Vec2i) = false
|
||||||
|
fun onMouseMove(position: Vec2i) = false
|
||||||
|
fun onMouseLeave() = false
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* 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 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.popper
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.text.ChatColors
|
||||||
|
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.LayoutedElement
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.elements.primitive.ColorElement
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
|
||||||
|
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.EMPTY
|
||||||
|
import glm_.vec2.Vec2i
|
||||||
|
|
||||||
|
abstract class Popper(
|
||||||
|
guiRenderer: GUIRenderer,
|
||||||
|
var position: Vec2i,
|
||||||
|
) : Element(guiRenderer), LayoutedElement {
|
||||||
|
private val background = ColorElement(guiRenderer, Vec2i.EMPTY, color = ChatColors.YELLOW)
|
||||||
|
open var dead = false
|
||||||
|
override val layoutOffset: Vec2i = position
|
||||||
|
|
||||||
|
override fun forceRender(offset: Vec2i, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
|
||||||
|
background.render(offset, consumer, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun forceSilentApply() {
|
||||||
|
background.size = size
|
||||||
|
}
|
||||||
|
|
||||||
|
fun show() {
|
||||||
|
guiRenderer.popper += this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hide() {
|
||||||
|
dead = true
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* 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.popper
|
||||||
|
|
||||||
|
import de.bixilon.kutil.time.TimeUtil
|
||||||
|
import de.bixilon.minosoft.config.key.KeyCodes
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.GUIElementDrawer
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.hud.Initializable
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.LayoutedGUIElement
|
||||||
|
import de.bixilon.minosoft.gui.rendering.input.InputHandler
|
||||||
|
import de.bixilon.minosoft.gui.rendering.system.window.KeyChangeTypes
|
||||||
|
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||||
|
import glm_.vec2.Vec2d
|
||||||
|
import glm_.vec2.Vec2i
|
||||||
|
|
||||||
|
class PopperManager(
|
||||||
|
override val guiRenderer: GUIRenderer,
|
||||||
|
) : Initializable, InputHandler, GUIElementDrawer {
|
||||||
|
var poppers: MutableList<LayoutedGUIElement<Popper>> = mutableListOf()
|
||||||
|
private val renderWindow = guiRenderer.renderWindow
|
||||||
|
override var lastTickTime: Long = -1L
|
||||||
|
|
||||||
|
|
||||||
|
fun onMatrixChange() {
|
||||||
|
for (element in poppers) {
|
||||||
|
element.layout.forceSilentApply()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun draw() {
|
||||||
|
val toRemove: MutableSet<LayoutedGUIElement<Popper>> = mutableSetOf()
|
||||||
|
val time = TimeUtil.time
|
||||||
|
val tick = time - lastTickTime > ProtocolDefinition.TICK_TIME
|
||||||
|
if (tick) {
|
||||||
|
lastTickTime = time
|
||||||
|
}
|
||||||
|
|
||||||
|
for (popper in poppers) {
|
||||||
|
if (popper.layout.dead) {
|
||||||
|
toRemove += popper
|
||||||
|
popper.onClose()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (tick) {
|
||||||
|
popper.tick()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!popper.skipDraw) {
|
||||||
|
popper.draw()
|
||||||
|
}
|
||||||
|
popper.prepare()
|
||||||
|
|
||||||
|
guiRenderer.setup()
|
||||||
|
if (!popper.enabled || popper.mesh.data.isEmpty) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
popper.mesh.draw()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCharPress(char: Int): Boolean {
|
||||||
|
for ((index, element) in poppers.toList().withIndex()) {
|
||||||
|
if (index != 0 && !element.activeWhenHidden) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (element.onCharPress(char)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMouseMove(position: Vec2i): Boolean {
|
||||||
|
for ((index, element) in poppers.toList().withIndex()) {
|
||||||
|
if (index != 0 && !element.activeWhenHidden) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (element.onMouseMove(position)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onKeyPress(type: KeyChangeTypes, key: KeyCodes): Boolean {
|
||||||
|
for ((index, element) in poppers.toList().withIndex()) {
|
||||||
|
if (index != 0 && !element.activeWhenHidden) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (element.onKeyPress(type, key)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onScroll(scrollOffset: Vec2d): Boolean {
|
||||||
|
for ((index, element) in poppers.toList().withIndex()) {
|
||||||
|
if (index != 0 && !element.activeWhenHidden) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (element.onScroll(scrollOffset)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun add(popper: Popper) {
|
||||||
|
poppers += LayoutedGUIElement(popper)
|
||||||
|
popper.onOpen()
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun plusAssign(popper: Popper) {
|
||||||
|
add(popper)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun remove(popper: Popper?) {
|
||||||
|
for (popperEntry in poppers) {
|
||||||
|
if (popperEntry.layout == popper) {
|
||||||
|
poppers.remove(popperEntry)
|
||||||
|
popperEntry.onClose()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun minusAssign(popper: Popper?) = remove(popper)
|
||||||
|
|
||||||
|
fun clear() {
|
||||||
|
for (popper in poppers) {
|
||||||
|
popper.onClose()
|
||||||
|
}
|
||||||
|
poppers.clear()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* 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 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.popper.text
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.elements.text.TextElement
|
||||||
|
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.popper.Popper
|
||||||
|
import glm_.vec2.Vec2i
|
||||||
|
|
||||||
|
class TextPopper(
|
||||||
|
guiRenderer: GUIRenderer,
|
||||||
|
position: Vec2i,
|
||||||
|
text: Any,
|
||||||
|
) : Popper(guiRenderer, position) {
|
||||||
|
private val textElement = TextElement(guiRenderer, text, parent = this)
|
||||||
|
|
||||||
|
override fun forceRender(offset: Vec2i, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
|
||||||
|
super.forceRender(offset, consumer, options)
|
||||||
|
|
||||||
|
textElement.render(offset, consumer, options)
|
||||||
|
}
|
||||||
|
}
|
@ -52,7 +52,7 @@ class ScreenshotTaker(
|
|||||||
while (File(path).exists()) {
|
while (File(path).exists()) {
|
||||||
path = "${basePath}_${i++}.png"
|
path = "${basePath}_${i++}.png"
|
||||||
if (i > MAX_FILES_CHECK) {
|
if (i > MAX_FILES_CHECK) {
|
||||||
throw StackOverflowError("There are already > $MAX_FILES_CHECK screenshots with this date! Please try again!")
|
throw StackOverflowError("There are already > $MAX_FILES_CHECK screenshots with this date! Please try again later!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ class ScreenshotTaker(
|
|||||||
TextComponent("[DELETE]").apply {
|
TextComponent("[DELETE]").apply {
|
||||||
color = ChatColors.RED
|
color = ChatColors.RED
|
||||||
bold()
|
bold()
|
||||||
clickEvent = ClickCallbackClickEvent { DeleteScreenshotDialog(renderWindow.renderer[GUIRenderer] ?: return@ClickCallbackClickEvent, file).open() }
|
clickEvent = ClickCallbackClickEvent { DeleteScreenshotDialog(renderWindow.renderer[GUIRenderer] ?: return@ClickCallbackClickEvent, file).show() }
|
||||||
hoverEvent = TextHoverEvent("Click to delete screenshot")
|
hoverEvent = TextHoverEvent("Click to delete screenshot")
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user