From c0095801a1d1527d76af295fbb608eb581d8e68a Mon Sep 17 00:00:00 2001 From: Carlos Ballesteros Velasco Date: Tue, 2 Jul 2024 14:27:56 +0200 Subject: [PATCH] IPC: Add event for bidirectional communication between the game and the projector (#2257) * IPC: Add event for bidirectional communication between the game and the projector * Test Generic Event parsing and writing --- korge-core/src/korlibs/event/Events.kt | 19 +++++++++++++++++++ .../korlibs/korge/ipc/KorgeIPCSocket.kt | 16 ++++++++++++++++ .../korge/ipc/KorgeIPCServerSocketTest.kt | 8 ++++++++ .../korlibs/korge/IPCViewsCompleter.kt | 10 +++++++++- 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/korge-core/src/korlibs/event/Events.kt b/korge-core/src/korlibs/event/Events.kt index 040b5c3804..cb116a26d4 100644 --- a/korge-core/src/korlibs/event/Events.kt +++ b/korge-core/src/korlibs/event/Events.kt @@ -407,6 +407,25 @@ data class TouchEvent( val isEnd get() = type == Type.END } +class GenericEvent( + override var type: Type, + var kind: String, + var data: ByteArray +) : Event(), TEvent { + enum class Type : EventType { + PROJECTOR_TO_GAME, GAME_TO_PROJECTOR; + companion object { + val ALL = Type.entries + } + } + + fun copyFrom(other: GenericEvent) { + this.type = other.type + this.kind = other.kind + this.data = other.data + } +} + data class KeyEvent constructor( override var type: Type = Type.UP, var id: Int = 0, diff --git a/korge-ipc/src/main/kotlin/korlibs/korge/ipc/KorgeIPCSocket.kt b/korge-ipc/src/main/kotlin/korlibs/korge/ipc/KorgeIPCSocket.kt index fae3ea0473..7dda39e56b 100644 --- a/korge-ipc/src/main/kotlin/korlibs/korge/ipc/KorgeIPCSocket.kt +++ b/korge-ipc/src/main/kotlin/korlibs/korge/ipc/KorgeIPCSocket.kt @@ -200,6 +200,9 @@ class IPCPacket( val KEY_UP = 0x0302 val KEY_TYPE = 0x0303 + val EVENT_GAME_TO_PROJECTOR = 0x0401 + val EVENT_PROJECTOR_TO_GAME = 0x0402 + val REQUEST_NODE_CHILDREN = 0x7701 val REQUEST_NODE_PROPS = 0x7702 val REQUEST_NODE_SET_PROP = 0x7703 @@ -239,6 +242,19 @@ class IPCPacket( } } +fun IPCPacket.Companion.genericEventGen(kind: String, eventData: ByteArray): ByteArray = MemorySyncStreamToByteArray(16 + kind.length + 4 + eventData.size + 4) { + val kindBytes = kind.encodeToByteArray() + writeU_VL(kindBytes.size); writeBytes(kindBytes) + writeU_VL(eventData.size); writeBytes(eventData) +} + +fun IPCPacket.Companion.genericEventParse(data: ByteArray): Pair { + val s = data.openFastStream() + val type = s.readBytes(s.readU_VL()).decodeToString() + val data = s.readBytes(s.readU_VL()) + return type to data +} + private operator fun IntBuffer.set(index: Int, value: Int) { this.put(index, value) } diff --git a/korge-ipc/src/test/kotlin/korlibs/korge/ipc/KorgeIPCServerSocketTest.kt b/korge-ipc/src/test/kotlin/korlibs/korge/ipc/KorgeIPCServerSocketTest.kt index 8868cb705d..4f67180f80 100644 --- a/korge-ipc/src/test/kotlin/korlibs/korge/ipc/KorgeIPCServerSocketTest.kt +++ b/korge-ipc/src/test/kotlin/korlibs/korge/ipc/KorgeIPCServerSocketTest.kt @@ -90,4 +90,12 @@ class KorgeIPCServerSocketTest { assertEquals("HELLO", bytes.decodeToString()) } + + @Test + fun testGenericEvent() { + val bytes = IPCPacket.genericEventGen("hello", byteArrayOf(1, 2, 3)) + val (kind, data) = IPCPacket.genericEventParse(bytes) + assertEquals("hello", kind) + assertEquals(byteArrayOf(1, 2, 3).toList(), data.toList()) + } } diff --git a/korge/src@jvm/korlibs/korge/IPCViewsCompleter.kt b/korge/src@jvm/korlibs/korge/IPCViewsCompleter.kt index 92fd75c250..cd197a742a 100644 --- a/korge/src@jvm/korlibs/korge/IPCViewsCompleter.kt +++ b/korge/src@jvm/korlibs/korge/IPCViewsCompleter.kt @@ -2,6 +2,7 @@ package korlibs.korge import korlibs.event.* import korlibs.graphics.* +import korlibs.io.stream.* import korlibs.korge.ipc.* import korlibs.korge.view.* import korlibs.korge.view.property.* @@ -17,6 +18,10 @@ class IPCViewsCompleter : ViewsCompleter { val viewsNodeId = ViewsNodeId(views) + views.onEvent(GenericEvent.Type.GAME_TO_PROJECTOR) { e -> + ipc.writeEvent(IPCPacket(IPCPacket.EVENT_GAME_TO_PROJECTOR, IPCPacket.genericEventGen(e.kind, e.data))) + } + views.onBeforeRender { while (true) { val e = ipc.tryReadEvent() ?: break @@ -44,7 +49,10 @@ class IPCViewsCompleter : ViewsCompleter { str = null, ) } - + IPCPacket.EVENT_PROJECTOR_TO_GAME -> { + val (type, data) = IPCPacket.genericEventParse(e.data) + views.dispatch(GenericEvent(GenericEvent.Type.PROJECTOR_TO_GAME, type, data)) + } IPCPacket.MOUSE_MOVE, IPCPacket.MOUSE_DOWN, IPCPacket.MOUSE_UP, IPCPacket.MOUSE_CLICK, IPCPacket.MOUSE_SCROLL -> { val x = e.buffer.getInt() val y = e.buffer.getInt()