mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-16 02:45:13 -04:00
gui: poppers (wip), mouse movement fixes
This commit is contained in:
parent
9fd1688b39
commit
704de95b94
@ -33,7 +33,7 @@ class CopyToClipboardClickEvent(
|
||||
return
|
||||
}
|
||||
val dialog = CopyToClipboardDialog(guiRenderer, text)
|
||||
dialog.open()
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
companion object : ClickEventFactory<CopyToClipboardClickEvent> {
|
||||
|
@ -40,7 +40,7 @@ class OpenFileClickEvent(
|
||||
return
|
||||
}
|
||||
val dialog = OpenFileConfirmationDialog(guiRenderer, path)
|
||||
dialog.open()
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
companion object : ClickEventFactory<OpenFileClickEvent> {
|
||||
|
@ -43,7 +43,7 @@ class OpenURLClickEvent(
|
||||
return
|
||||
}
|
||||
val dialog = URLConfirmationDialog(guiRenderer, url)
|
||||
dialog.open()
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
companion object : ClickEventFactory<OpenURLClickEvent> {
|
||||
|
@ -34,7 +34,7 @@ class SendMessageClickEvent(
|
||||
return
|
||||
}
|
||||
val dialog = SendMessageDialog(guiRenderer, message)
|
||||
dialog.open()
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
companion object : ClickEventFactory<SendMessageClickEvent>, MultiNameFactory<SendMessageClickEvent> {
|
||||
|
@ -14,5 +14,12 @@
|
||||
package de.bixilon.minosoft.data.text.events.hover
|
||||
|
||||
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.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
|
||||
|
||||
class TextHoverEvent(
|
||||
text: Any?,
|
||||
) : HoverEvent {
|
||||
val text = ChatComponent.of(text)
|
||||
private var popper: TextPopper? = null
|
||||
|
||||
override fun applyJavaFX(text: Text) {
|
||||
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> {
|
||||
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.hud.HUDManager
|
||||
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.modding.events.ResizeWindowEvent
|
||||
import de.bixilon.minosoft.gui.rendering.renderer.Renderer
|
||||
@ -47,6 +48,7 @@ class GUIRenderer(
|
||||
var scaledSize: Vec2i = renderWindow.window.size
|
||||
val gui = GUIManager(this)
|
||||
val hud = HUDManager(this)
|
||||
val popper = PopperManager(this)
|
||||
var matrix: Mat4 = Mat4()
|
||||
private set
|
||||
var matrixChange = true
|
||||
@ -64,6 +66,7 @@ class GUIRenderer(
|
||||
atlasManager.init()
|
||||
gui.init()
|
||||
hud.init()
|
||||
popper.init()
|
||||
}
|
||||
|
||||
override fun postInit(latch: CountUpAndDownLatch) {
|
||||
@ -77,6 +80,7 @@ class GUIRenderer(
|
||||
|
||||
gui.postInit()
|
||||
hud.postInit()
|
||||
popper.postInit()
|
||||
}
|
||||
|
||||
private fun recalculateMatrices(windowSize: Vec2i = renderWindow.window.size, scale: Float = profile.scale) {
|
||||
@ -86,6 +90,7 @@ class GUIRenderer(
|
||||
|
||||
gui.onMatrixChange()
|
||||
hud.onMatrixChange()
|
||||
popper.onMatrixChange()
|
||||
}
|
||||
|
||||
fun setup() {
|
||||
@ -119,6 +124,7 @@ class GUIRenderer(
|
||||
override fun drawOther() {
|
||||
hud.draw()
|
||||
gui.draw()
|
||||
popper.draw()
|
||||
if (this.matrixChange) {
|
||||
this.matrixChange = false
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ open class TextElement(
|
||||
parent: Element? = null,
|
||||
scale: Float = 1.0f,
|
||||
) : Element(guiRenderer, text.toString().length * 6 * GUIMesh.GUIMeshStruct.FLOATS_PER_VERTEX), Labeled {
|
||||
private var activeElement: TextComponent? = null
|
||||
lateinit var renderInfo: TextRenderInfo
|
||||
private set
|
||||
|
||||
@ -175,12 +176,36 @@ open class TextElement(
|
||||
if (action != MouseActions.PRESS || button != MouseButtons.LEFT) {
|
||||
return true
|
||||
}
|
||||
val text = getTextComponentAt(position) ?: return false
|
||||
text.clickEvent?.onClick(guiRenderer, position, button, action)
|
||||
val pair = getTextComponentAt(position) ?: return false
|
||||
pair.first.clickEvent?.onClick(guiRenderer, pair.second, button, action)
|
||||
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 line = renderInfo.lines.getOrNull(offset.y / charHeight) ?: return null
|
||||
offset.y = offset.y % charHeight
|
||||
@ -191,7 +216,7 @@ open class TextElement(
|
||||
|
||||
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 {
|
||||
|
@ -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.elements.Element
|
||||
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.input.mouse.MouseButtons
|
||||
import de.bixilon.minosoft.gui.rendering.gui.gui.ActiveMouseMove
|
||||
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
|
||||
@ -34,9 +33,10 @@ import glm_.vec2.Vec2i
|
||||
open class TextFlowElement(
|
||||
guiRenderer: GUIRenderer,
|
||||
var messageExpireTime: Long,
|
||||
) : Element(guiRenderer) {
|
||||
) : Element(guiRenderer), ActiveMouseMove<TextElement> {
|
||||
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**
|
||||
override var activeElement: TextElement? = null
|
||||
|
||||
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 {
|
||||
val pair = getAt(position) ?: return false
|
||||
pair.first.textElement.onMouseAction(pair.second, button, action)
|
||||
return true
|
||||
override fun getAt(position: Vec2i): Pair<TextElement, Vec2i>? {
|
||||
val line = getLineAt(position) ?: return null
|
||||
return Pair(line.first.textElement, line.second)
|
||||
}
|
||||
|
||||
private fun getAt(position: Vec2i): Pair<TextFlowLineElement, Vec2i>? {
|
||||
private fun getLineAt(position: Vec2i): Pair<TextFlowLineElement, Vec2i>? {
|
||||
val reversedY = size.y - position.y
|
||||
val line = visibleLines.getOrNull(reversedY / Font.TOTAL_CHAR_HEIGHT) ?: return null
|
||||
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() {
|
||||
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()) {
|
||||
if (!element.enabled) {
|
||||
continue
|
||||
@ -87,8 +92,7 @@ class GUIManager(
|
||||
if (index != order.size - 1 && !element.activeWhenHidden) {
|
||||
continue
|
||||
}
|
||||
val time = TimeUtil.time
|
||||
if (time - lastTickTime > ProtocolDefinition.TICK_TIME) {
|
||||
if (tick) {
|
||||
element.tick()
|
||||
if (element is Pollable) {
|
||||
if (element.poll()) {
|
||||
@ -220,6 +224,7 @@ class GUIManager(
|
||||
previous.onClose()
|
||||
if (elementOrder.isEmpty()) {
|
||||
renderWindow.inputHandler.inputHandler = null
|
||||
guiRenderer.popper.clear()
|
||||
}
|
||||
val now = elementOrder.firstOrNull() ?: return
|
||||
now.onOpen()
|
||||
@ -230,6 +235,7 @@ class GUIManager(
|
||||
element.onClose()
|
||||
}
|
||||
elementOrder.clear()
|
||||
guiRenderer.popper.clear()
|
||||
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.gui.rendering.gui.GUIRenderer
|
||||
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.input.mouse.MouseActions
|
||||
import de.bixilon.minosoft.gui.rendering.gui.input.mouse.MouseButtons
|
||||
@ -29,13 +30,13 @@ import glm_.vec2.Vec2i
|
||||
abstract class Menu(
|
||||
guiRenderer: GUIRenderer,
|
||||
val preferredElementWidth: Int = 150,
|
||||
) : Screen(guiRenderer) {
|
||||
) : Screen(guiRenderer), ActiveMouseMove<Element> {
|
||||
private val elements: MutableList<Element> = mutableListOf()
|
||||
|
||||
private var maxElementWidth = -1
|
||||
private var totalHeight = -1
|
||||
|
||||
private var activeElement: Element? = null
|
||||
override var activeElement: Element? = null
|
||||
|
||||
override fun forceSilentApply() {
|
||||
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 {
|
||||
val (element, delta) = getAt(position) ?: return true
|
||||
element.onMouseAction(delta, button, action)
|
||||
@ -111,7 +86,7 @@ abstract class Menu(
|
||||
forceSilentApply()
|
||||
}
|
||||
|
||||
fun getAt(position: Vec2i): Pair<Element, Vec2i>? {
|
||||
override fun getAt(position: Vec2i): Pair<Element, Vec2i>? {
|
||||
var element: Element? = null
|
||||
val delta = Vec2i(position)
|
||||
val elementWidth = maxElementWidth
|
||||
|
@ -34,7 +34,7 @@ abstract class AbstractConfirmationMenu(
|
||||
guiRenderer.gui.pop()
|
||||
}
|
||||
|
||||
fun open() {
|
||||
fun show() {
|
||||
guiRenderer.gui.push(this)
|
||||
}
|
||||
|
||||
|
@ -121,9 +121,10 @@ class LayoutedGUIElement<T : LayoutedElement>(
|
||||
return elementLayout.onMouseLeave()
|
||||
}
|
||||
val delta = position - offset
|
||||
val previousOutside = lastPosition == INVALID_MOUSE_POSITION
|
||||
this.lastPosition = delta
|
||||
|
||||
if (lastPosition.isOutside(offset, size)) {
|
||||
if (previousOutside) {
|
||||
return elementLayout.onMouseEnter(delta)
|
||||
}
|
||||
|
||||
@ -135,10 +136,7 @@ class LayoutedGUIElement<T : LayoutedElement>(
|
||||
}
|
||||
|
||||
override fun onKeyPress(type: KeyChangeTypes, key: KeyCodes): Boolean {
|
||||
val mouseButton = MouseButtons[key]
|
||||
if (mouseButton == null) {
|
||||
return elementLayout.onKey(key, type)
|
||||
}
|
||||
val mouseButton = MouseButtons[key] ?: return elementLayout.onKey(key, type)
|
||||
|
||||
val position = lastPosition
|
||||
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.LayoutedElement
|
||||
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.mesh.GUIVertexConsumer
|
||||
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.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 profile = connection.profiles.gui
|
||||
protected val messages = TextFlowElement(guiRenderer, 20000).apply { parent = this@AbstractChatElement }
|
||||
override var activeElement: Element? = null
|
||||
|
||||
override fun forceRender(offset: Vec2i, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
|
||||
messages.render(offset + Vec2i(ChatElement.CHAT_INPUT_MARGIN, 0), consumer, options)
|
||||
}
|
||||
|
||||
|
||||
override fun onScroll(position: Vec2i, scrollOffset: Vec2d): Boolean {
|
||||
val size = messages.size
|
||||
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.hud.elements.HUDBuilder
|
||||
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.GUIVertexOptions
|
||||
import de.bixilon.minosoft.gui.rendering.system.window.KeyChangeTypes
|
||||
@ -202,13 +200,7 @@ class ChatElement(guiRenderer: GUIRenderer) : AbstractChatElement(guiRenderer) {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onMouseAction(position: Vec2i, button: MouseButtons, action: MouseActions): Boolean {
|
||||
val pair = getAt(position) ?: return false
|
||||
pair.first.onMouseAction(pair.second, button, action)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun getAt(position: Vec2i): Pair<Element, Vec2i>? {
|
||||
override fun getAt(position: Vec2i): Pair<Element, Vec2i>? {
|
||||
if (position.x < CHAT_INPUT_MARGIN) {
|
||||
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.hud.elements.HUDBuilder
|
||||
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.invoker.CallbackEventInvoker
|
||||
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||
@ -82,13 +80,7 @@ class InternalChatElement(guiRenderer: GUIRenderer) : AbstractChatElement(guiRen
|
||||
guiRenderer.gui.pop() // pop normal chat
|
||||
}
|
||||
|
||||
override fun onMouseAction(position: Vec2i, button: MouseButtons, action: MouseActions): Boolean {
|
||||
val pair = getAt(position) ?: return false
|
||||
pair.first.onMouseAction(pair.second, button, action)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun getAt(position: Vec2i): Pair<Element, Vec2i>? {
|
||||
override fun getAt(position: Vec2i): Pair<Element, Vec2i>? {
|
||||
if (position.x < ChatElement.CHAT_INPUT_MARGIN) {
|
||||
return null
|
||||
}
|
||||
|
@ -20,11 +20,8 @@ import de.bixilon.minosoft.gui.rendering.system.window.KeyChangeTypes
|
||||
import glm_.vec2.Vec2d
|
||||
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 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()) {
|
||||
path = "${basePath}_${i++}.png"
|
||||
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 {
|
||||
color = ChatColors.RED
|
||||
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")
|
||||
},
|
||||
))
|
||||
|
Loading…
x
Reference in New Issue
Block a user