mirror of
https://gitlab.com/cc-ru/ocelot/ocelot-desktop.git
synced 2025-12-20 11:09:20 +01:00
Implement touch, drag, drop, scroll, and clipboard signals
This commit is contained in:
parent
1f55223013
commit
1dee04c246
@ -1,8 +1,8 @@
|
|||||||
package ocelot.desktop.util
|
package ocelot.desktop.ui
|
||||||
|
|
||||||
import ocelot.desktop.ui.event.KeyEvent
|
import ocelot.desktop.ui.event.KeyEvent
|
||||||
|
import ocelot.desktop.util.KeyMapping
|
||||||
import org.apache.logging.log4j.scala.Logging
|
import org.apache.logging.log4j.scala.Logging
|
||||||
import org.lwjgl.glfw.GLFW
|
|
||||||
|
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
import scala.collection.mutable.ListBuffer
|
import scala.collection.mutable.ListBuffer
|
||||||
@ -16,12 +16,7 @@ object KeyHandler extends Logging {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def handleKey(window: Long, key: Int, scancode: Int, action: Int, mods: Int): Unit = {
|
def handleKey(window: Long, key: Int, scancode: Int, action: Int, mods: Int): Unit = {
|
||||||
val state = action match {
|
val state = KeyEvent.State(action)
|
||||||
case GLFW.GLFW_PRESS => KeyEvent.State.Press
|
|
||||||
case GLFW.GLFW_REPEAT => KeyEvent.State.Repeat
|
|
||||||
case GLFW.GLFW_RELEASE => KeyEvent.State.Release
|
|
||||||
}
|
|
||||||
|
|
||||||
val code = KeyMapping.map(key)
|
val code = KeyMapping.map(key)
|
||||||
val char = charMap.getOrElse(code, '\0')
|
val char = charMap.getOrElse(code, '\0')
|
||||||
|
|
||||||
20
src/main/scala/ocelot/desktop/ui/MouseHandler.scala
Normal file
20
src/main/scala/ocelot/desktop/ui/MouseHandler.scala
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package ocelot.desktop.ui
|
||||||
|
|
||||||
|
import ocelot.desktop.ui.event.MouseEvent
|
||||||
|
|
||||||
|
import scala.collection.mutable.ListBuffer
|
||||||
|
|
||||||
|
object MouseHandler {
|
||||||
|
val events = new ListBuffer[MouseEvent]
|
||||||
|
|
||||||
|
def reset(): Unit = {
|
||||||
|
events.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
def handleMouseButton(window: Long, _button: Int, action: Int, mods: Int): Unit = {
|
||||||
|
val state = MouseEvent.State(action)
|
||||||
|
val button = MouseEvent.Button(_button)
|
||||||
|
|
||||||
|
events += MouseEvent(state, button)
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/main/scala/ocelot/desktop/ui/ScrollHandler.scala
Normal file
17
src/main/scala/ocelot/desktop/ui/ScrollHandler.scala
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package ocelot.desktop.ui
|
||||||
|
|
||||||
|
import ocelot.desktop.ui.event.ScrollEvent
|
||||||
|
|
||||||
|
import scala.collection.mutable.ListBuffer
|
||||||
|
|
||||||
|
object ScrollHandler {
|
||||||
|
val events = new ListBuffer[ScrollEvent]
|
||||||
|
|
||||||
|
def reset(): Unit = {
|
||||||
|
events.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
def handleScroll(window: Long, xoffset: Double, yoffset: Double): Unit = {
|
||||||
|
events += ScrollEvent(yoffset.asInstanceOf[Int])
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,9 +1,9 @@
|
|||||||
package ocelot.desktop.ui
|
package ocelot.desktop.ui
|
||||||
|
|
||||||
import ocelot.desktop.geometry.Size2D
|
import ocelot.desktop.geometry.{Size2D, Vector2D}
|
||||||
import ocelot.desktop.graphics.Graphics
|
import ocelot.desktop.graphics.Graphics
|
||||||
import ocelot.desktop.ui.widget.RootWidget
|
import ocelot.desktop.ui.widget.RootWidget
|
||||||
import ocelot.desktop.util.{FPSCalculator, FontLoader, KeyHandler}
|
import ocelot.desktop.util.{FPSCalculator, FontLoader}
|
||||||
import org.apache.logging.log4j.scala.Logging
|
import org.apache.logging.log4j.scala.Logging
|
||||||
import org.lwjgl.glfw.{GLFW, GLFWErrorCallback}
|
import org.lwjgl.glfw.{GLFW, GLFWErrorCallback}
|
||||||
import org.lwjgl.opengl.{GL, GL11}
|
import org.lwjgl.opengl.{GL, GL11}
|
||||||
@ -12,6 +12,8 @@ import org.lwjgl.system.MemoryUtil.NULL
|
|||||||
class UiHandler(val root: RootWidget) extends Logging {
|
class UiHandler(val root: RootWidget) extends Logging {
|
||||||
val windowSize: Size2D = Size2D(0, 0)
|
val windowSize: Size2D = Size2D(0, 0)
|
||||||
|
|
||||||
|
root.uiHandler = this
|
||||||
|
|
||||||
private var graphics: Graphics = _
|
private var graphics: Graphics = _
|
||||||
private var window: Long = _
|
private var window: Long = _
|
||||||
private var fullRedraw = true
|
private var fullRedraw = true
|
||||||
@ -20,6 +22,16 @@ class UiHandler(val root: RootWidget) extends Logging {
|
|||||||
|
|
||||||
def fps: Float = fpsCalculator.fps
|
def fps: Float = fpsCalculator.fps
|
||||||
|
|
||||||
|
def mousePosition: Vector2D = {
|
||||||
|
val x = Array(0.0)
|
||||||
|
val y = Array(0.0)
|
||||||
|
GLFW.glfwGetCursorPos(window, x, y)
|
||||||
|
|
||||||
|
Vector2D(x.head, y.head)
|
||||||
|
}
|
||||||
|
|
||||||
|
def clipboard: String = GLFW.glfwGetClipboardString(window)
|
||||||
|
|
||||||
def init(): Unit = {
|
def init(): Unit = {
|
||||||
GLFWErrorCallback.createPrint(System.err).set
|
GLFWErrorCallback.createPrint(System.err).set
|
||||||
|
|
||||||
@ -40,6 +52,8 @@ class UiHandler(val root: RootWidget) extends Logging {
|
|||||||
|
|
||||||
GLFW.glfwSetKeyCallback(window, KeyHandler.handleKey)
|
GLFW.glfwSetKeyCallback(window, KeyHandler.handleKey)
|
||||||
GLFW.glfwSetCharCallback(window, KeyHandler.handleChar)
|
GLFW.glfwSetCharCallback(window, KeyHandler.handleChar)
|
||||||
|
GLFW.glfwSetMouseButtonCallback(window, MouseHandler.handleMouseButton)
|
||||||
|
GLFW.glfwSetScrollCallback(window, ScrollHandler.handleScroll)
|
||||||
GLFW.glfwSetWindowSizeCallback(window, handleResize)
|
GLFW.glfwSetWindowSizeCallback(window, handleResize)
|
||||||
GLFW.glfwSetWindowRefreshCallback(window, handleRefresh)
|
GLFW.glfwSetWindowRefreshCallback(window, handleRefresh)
|
||||||
GLFW.glfwSetInputMode(window, GLFW.GLFW_STICKY_KEYS, GLFW.GLFW_FALSE)
|
GLFW.glfwSetInputMode(window, GLFW.GLFW_STICKY_KEYS, GLFW.GLFW_FALSE)
|
||||||
@ -59,7 +73,10 @@ class UiHandler(val root: RootWidget) extends Logging {
|
|||||||
graphics.setViewport(windowSize.width.asInstanceOf[Int], windowSize.height.asInstanceOf[Int])
|
graphics.setViewport(windowSize.width.asInstanceOf[Int], windowSize.height.asInstanceOf[Int])
|
||||||
|
|
||||||
KeyHandler.reset()
|
KeyHandler.reset()
|
||||||
|
MouseHandler.reset()
|
||||||
|
ScrollHandler.reset()
|
||||||
GLFW.glfwPollEvents()
|
GLFW.glfwPollEvents()
|
||||||
|
|
||||||
update()
|
update()
|
||||||
|
|
||||||
if (fullRedraw) {
|
if (fullRedraw) {
|
||||||
@ -79,7 +96,7 @@ class UiHandler(val root: RootWidget) extends Logging {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private def update(): Unit = {
|
private def update(): Unit = {
|
||||||
for (event <- KeyHandler.events)
|
for (event <- KeyHandler.events.iterator ++ MouseHandler.events.iterator ++ ScrollHandler.events.iterator)
|
||||||
root.handleEvent(event)
|
root.handleEvent(event)
|
||||||
|
|
||||||
root.update()
|
root.update()
|
||||||
|
|||||||
@ -6,7 +6,7 @@ object MouseEvent {
|
|||||||
|
|
||||||
object State extends Enumeration {
|
object State extends Enumeration {
|
||||||
val Press: State.Value = Value(GLFW.GLFW_PRESS)
|
val Press: State.Value = Value(GLFW.GLFW_PRESS)
|
||||||
val Release: State.Value = Value(GLFW.GLFW_PRESS)
|
val Release: State.Value = Value(GLFW.GLFW_RELEASE)
|
||||||
}
|
}
|
||||||
|
|
||||||
object Button extends Enumeration {
|
object Button extends Enumeration {
|
||||||
|
|||||||
3
src/main/scala/ocelot/desktop/ui/event/ScrollEvent.scala
Normal file
3
src/main/scala/ocelot/desktop/ui/event/ScrollEvent.scala
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
package ocelot.desktop.ui.event
|
||||||
|
|
||||||
|
case class ScrollEvent(offset: Int) extends Event
|
||||||
@ -1,6 +1,11 @@
|
|||||||
package ocelot.desktop.ui.widget
|
package ocelot.desktop.ui.widget
|
||||||
|
|
||||||
|
import ocelot.desktop.ui.UiHandler
|
||||||
|
|
||||||
abstract class RootWidget extends Widget {
|
abstract class RootWidget extends Widget {
|
||||||
|
// TODO: Remove
|
||||||
|
var uiHandler: UiHandler = _
|
||||||
|
|
||||||
def windowTitle: String
|
def windowTitle: String
|
||||||
|
|
||||||
def update(): Unit = {}
|
def update(): Unit = {}
|
||||||
|
|||||||
@ -1,14 +1,16 @@
|
|||||||
package ocelot.desktop.ui.widget
|
package ocelot.desktop.ui.widget
|
||||||
|
|
||||||
import ocelot.desktop.color.IntColor
|
import ocelot.desktop.color.IntColor
|
||||||
import ocelot.desktop.geometry.Size2D
|
import ocelot.desktop.geometry.{Size2D, Vector2D}
|
||||||
import ocelot.desktop.graphics.Graphics
|
import ocelot.desktop.graphics.Graphics
|
||||||
import ocelot.desktop.ui.event.KeyEvent
|
import ocelot.desktop.ui.event.{KeyEvent, MouseEvent, ScrollEvent}
|
||||||
import ocelot.desktop.util.FontLoader
|
import ocelot.desktop.util.FontLoader
|
||||||
import org.apache.logging.log4j.scala.Logging
|
import org.apache.logging.log4j.scala.Logging
|
||||||
import totoro.ocelot.brain.entity.Screen
|
import totoro.ocelot.brain.entity.Screen
|
||||||
import totoro.ocelot.brain.user.User
|
import totoro.ocelot.brain.user.User
|
||||||
|
|
||||||
|
import scala.collection.mutable
|
||||||
|
|
||||||
class ScreenWidget(screen: Screen) extends RootWidget with Logging {
|
class ScreenWidget(screen: Screen) extends RootWidget with Logging {
|
||||||
private val fontSize = 16f
|
private val fontSize = 16f
|
||||||
|
|
||||||
@ -24,14 +26,54 @@ class ScreenWidget(screen: Screen) extends RootWidget with Logging {
|
|||||||
|
|
||||||
override def maximumSize: Option[Size2D] = minimumSize
|
override def maximumSize: Option[Size2D] = minimumSize
|
||||||
|
|
||||||
|
private var lastMousePos = Vector2D(0, 0)
|
||||||
|
private var pressedMouseButtons = new mutable.HashSet[MouseEvent.Button.Value]()
|
||||||
|
|
||||||
eventHandlers += {
|
eventHandlers += {
|
||||||
case event: KeyEvent =>
|
case event: KeyEvent =>
|
||||||
event.state match {
|
event.state match {
|
||||||
case KeyEvent.State.Press | KeyEvent.State.Repeat =>
|
case KeyEvent.State.Press | KeyEvent.State.Repeat =>
|
||||||
screen.keyDown(event.char, event.code, User("myself"))
|
screen.keyDown(event.char, event.code, User("myself"))
|
||||||
|
|
||||||
|
// note: in opencomputers, key_down signal is fired __before__ clipboard signal
|
||||||
|
if (event.code == 210)
|
||||||
|
screen.clipboard(uiHandler.clipboard, User("myself"))
|
||||||
case KeyEvent.State.Release =>
|
case KeyEvent.State.Release =>
|
||||||
screen.keyUp(event.char, event.code, User("myself"))
|
screen.keyUp(event.char, event.code, User("myself"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case event: MouseEvent =>
|
||||||
|
lastMousePos = convertMousePos(uiHandler.mousePosition)
|
||||||
|
|
||||||
|
if (event.button == MouseEvent.Button.Middle)
|
||||||
|
screen.clipboard(uiHandler.clipboard, User("myself"))
|
||||||
|
else {
|
||||||
|
event.state match {
|
||||||
|
case MouseEvent.State.Press =>
|
||||||
|
pressedMouseButtons += event.button
|
||||||
|
screen.mouseDown(lastMousePos.x, lastMousePos.y, event.button.id, User("myself"))
|
||||||
|
|
||||||
|
case MouseEvent.State.Release =>
|
||||||
|
pressedMouseButtons -= event.button
|
||||||
|
screen.mouseUp(lastMousePos.x, lastMousePos.y, event.button.id, User("myself"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case event: ScrollEvent =>
|
||||||
|
screen.mouseScroll(lastMousePos.x, lastMousePos.y, event.offset, User("myself"))
|
||||||
|
}
|
||||||
|
|
||||||
|
def convertMousePos(p: Vector2D): Vector2D = Vector2D(p.x / fontSize * 2f, p.y / fontSize)
|
||||||
|
|
||||||
|
override def update(): Unit = {
|
||||||
|
val currentMousePos = convertMousePos(uiHandler.mousePosition)
|
||||||
|
if (currentMousePos == lastMousePos) return
|
||||||
|
|
||||||
|
lastMousePos = currentMousePos
|
||||||
|
|
||||||
|
for (button <- pressedMouseButtons) {
|
||||||
|
screen.mouseDrag(lastMousePos.x, lastMousePos.y, button.id, User("myself"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override def windowTitle: String = f"Ocelot Desktop"
|
override def windowTitle: String = f"Ocelot Desktop"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user