rendering: outsource input handling

This commit is contained in:
Bixilon 2021-04-21 22:44:07 +02:00
parent 710e045e90
commit 64b2d2eeb8
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
9 changed files with 240 additions and 196 deletions

View File

@ -99,7 +99,7 @@ class Camera(
var yOffset = yPos - this.lastMouseY var yOffset = yPos - this.lastMouseY
lastMouseX = xPos lastMouseX = xPos
lastMouseY = yPos lastMouseY = yPos
if (renderWindow.currentKeyConsumer != null) { if (renderWindow.inputHandler.currentKeyConsumer != null) {
return return
} }
xOffset *= mouseSensitivity xOffset *= mouseSensitivity
@ -123,31 +123,31 @@ class Camera(
} }
fun init(renderWindow: RenderWindow) { fun init(renderWindow: RenderWindow) {
renderWindow.registerKeyCallback(KeyBindingsNames.MOVE_FORWARD) { _: KeyCodes, keyAction: KeyAction -> renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.MOVE_FORWARD) { _: KeyCodes, keyAction: KeyAction ->
keyForwardDown = keyAction == KeyAction.PRESS keyForwardDown = keyAction == KeyAction.PRESS
} }
renderWindow.registerKeyCallback(KeyBindingsNames.MOVE_LEFT) { _: KeyCodes, keyAction: KeyAction -> renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.MOVE_LEFT) { _: KeyCodes, keyAction: KeyAction ->
keyLeftDown = keyAction == KeyAction.PRESS keyLeftDown = keyAction == KeyAction.PRESS
} }
renderWindow.registerKeyCallback(KeyBindingsNames.MOVE_BACKWARDS) { _: KeyCodes, keyAction: KeyAction -> renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.MOVE_BACKWARDS) { _: KeyCodes, keyAction: KeyAction ->
keyBackDown = keyAction == KeyAction.PRESS keyBackDown = keyAction == KeyAction.PRESS
} }
renderWindow.registerKeyCallback(KeyBindingsNames.MOVE_RIGHT) { _: KeyCodes, keyAction: KeyAction -> renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.MOVE_RIGHT) { _: KeyCodes, keyAction: KeyAction ->
keyRightDown = keyAction == KeyAction.PRESS keyRightDown = keyAction == KeyAction.PRESS
} }
renderWindow.registerKeyCallback(KeyBindingsNames.MOVE_FLY_UP) { _: KeyCodes, keyAction: KeyAction -> renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.MOVE_FLY_UP) { _: KeyCodes, keyAction: KeyAction ->
keyFlyUp = keyAction == KeyAction.PRESS keyFlyUp = keyAction == KeyAction.PRESS
} }
renderWindow.registerKeyCallback(KeyBindingsNames.MOVE_FLY_DOWN) { _: KeyCodes, keyAction: KeyAction -> renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.MOVE_FLY_DOWN) { _: KeyCodes, keyAction: KeyAction ->
keyFlyDown = keyAction == KeyAction.PRESS keyFlyDown = keyAction == KeyAction.PRESS
} }
renderWindow.registerKeyCallback(KeyBindingsNames.MOVE_SPRINT) { _: KeyCodes, keyAction: KeyAction -> renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.MOVE_SPRINT) { _: KeyCodes, keyAction: KeyAction ->
keySprintDown = keyAction == KeyAction.PRESS keySprintDown = keyAction == KeyAction.PRESS
} }
renderWindow.registerKeyCallback(KeyBindingsNames.ZOOM) { _: KeyCodes, keyAction: KeyAction -> renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.ZOOM) { _: KeyCodes, keyAction: KeyAction ->
keyZoomDown = keyAction == KeyAction.PRESS keyZoomDown = keyAction == KeyAction.PRESS
} }
renderWindow.registerKeyCallback(KeyBindingsNames.MOVE_JUMP) { _: KeyCodes, keyAction: KeyAction -> renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.MOVE_JUMP) { _: KeyCodes, keyAction: KeyAction ->
keyJumpDown = keyAction == KeyAction.PRESS keyJumpDown = keyAction == KeyAction.PRESS
} }
@ -158,7 +158,7 @@ class Camera(
} }
fun handleInput(deltaTime: Double) { fun handleInput(deltaTime: Double) {
if (renderWindow.currentKeyConsumer != null) { // ToDo if (renderWindow.inputHandler.currentKeyConsumer != null) { // ToDo
return return
} }
var cameraSpeed = movementSpeed * deltaTime var cameraSpeed = movementSpeed * deltaTime

View File

@ -0,0 +1,195 @@
/*
* Minosoft
* Copyright (C) 2021 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.input.key
import de.bixilon.minosoft.Minosoft
import de.bixilon.minosoft.config.StaticConfiguration
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames
import de.bixilon.minosoft.config.key.KeyAction
import de.bixilon.minosoft.config.key.KeyBinding
import de.bixilon.minosoft.config.key.KeyCodes
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.gui.input.camera.Camera
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.hud.elements.input.KeyConsumer
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import org.lwjgl.glfw.GLFW
class RenderWindowInputHandler(
val renderWindow: RenderWindow,
) {
val connection: PlayConnection = renderWindow.connection
private val keyBindingCallbacks: MutableMap<ResourceLocation, Pair<KeyBinding, MutableSet<((keyCode: KeyCodes, keyEvent: KeyAction) -> Unit)>>> = mutableMapOf()
private val keysDown: MutableSet<KeyCodes> = mutableSetOf()
private val keyBindingDown: MutableSet<KeyBinding> = mutableSetOf()
val camera: Camera = Camera(connection, Minosoft.getConfig().config.game.camera.fov, renderWindow)
private var skipNextCharPress = false
private var _currentInputConsumer: KeyConsumer? = null
var mouseCatch = !StaticConfiguration.DEBUG_MODE
init {
registerKeyCallback(KeyBindingsNames.DEBUG_MOUSE_CATCH) { _: KeyCodes, _: KeyAction ->
mouseCatch = !mouseCatch
if (mouseCatch) {
GLFW.glfwSetInputMode(renderWindow.windowId, GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_DISABLED)
} else {
GLFW.glfwSetInputMode(renderWindow.windowId, GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_NORMAL)
}
renderWindow.sendDebugMessage("Toggled mouse catch!")
}
}
var currentKeyConsumer: KeyConsumer?
get() = _currentInputConsumer
set(value) {
_currentInputConsumer = value
for ((_, binding) in keyBindingCallbacks) {
if (!keyBindingDown.contains(binding.first)) {
continue
}
if (!binding.first.action.containsKey(KeyAction.TOGGLE) && !binding.first.action.containsKey(KeyAction.CHANGE)) {
continue
}
for (keyCallback in binding.second) {
keyCallback.invoke(KeyCodes.KEY_UNKNOWN, KeyAction.RELEASE)
}
}
// ToDo: move to mouse consumer
if (value == null) {
if (mouseCatch) {
renderWindow.renderQueue.add { GLFW.glfwSetInputMode(renderWindow.windowId, GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_DISABLED) }
}
} else {
renderWindow.renderQueue.add { GLFW.glfwSetInputMode(renderWindow.windowId, GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_NORMAL) }
}
keyBindingDown.clear()
}
fun invoke(window: Long, key: Int, scancode: Int, action: Int, mods: Int) {
val keyCode = KeyCodes.KEY_CODE_GLFW_ID_MAP[key] ?: KeyCodes.KEY_UNKNOWN
val keyAction = when (action) {
GLFW.GLFW_PRESS -> KeyAction.PRESS
GLFW.GLFW_RELEASE -> KeyAction.RELEASE
// ToDo: Double, Hold
else -> return
}
if (keyAction == KeyAction.PRESS) {
keysDown.add(keyCode)
} else if (keyAction == KeyAction.RELEASE) {
keysDown.remove(keyCode)
}
if (keyAction == KeyAction.PRESS) {
// ToDo: Repeatable keys, long holding, etc
currentKeyConsumer?.keyInput(keyCode)
}
val previousKeyConsumer = currentKeyConsumer
for ((_, keyCallbackPair) in keyBindingCallbacks) {
run {
val keyBinding = keyCallbackPair.first
val keyCallbacks = keyCallbackPair.second
var anyCheckRun = false
keyBinding.action[KeyAction.MODIFIER]?.let {
val previousKeysDown = if (keyAction == KeyAction.RELEASE) {
val previousKeysDown = keysDown.toMutableList()
previousKeysDown.add(keyCode)
previousKeysDown
} else {
keysDown
}
if (!previousKeysDown.containsAll(it)) {
return@run
}
anyCheckRun = true
}
keyBinding.action[KeyAction.CHANGE]?.let {
if (!it.contains(keyCode)) {
return@run
}
anyCheckRun = true
}
// release or press
if (keyBinding.action[KeyAction.CHANGE] == null) {
keyBinding.action[keyAction].let {
if (it == null) {
return@run
}
if (!it.contains(keyCode)) {
return@run
}
anyCheckRun = true
}
}
if (!anyCheckRun) {
return@run
}
if (keyAction == KeyAction.PRESS) {
keyBindingDown.add(keyBinding)
} else if (keyAction == KeyAction.RELEASE) {
keyBindingDown.remove(keyBinding)
}
for (keyCallback in keyCallbacks) {
keyCallback.invoke(keyCode, keyAction)
if (previousKeyConsumer != currentKeyConsumer) {
skipNextCharPress = true
}
}
}
}
}
fun invoke(window: Long, char: Int) {
if (skipNextCharPress) {
skipNextCharPress = false
return
}
currentKeyConsumer?.charInput(char.toChar())
}
fun invoke(window: Long, xPos: Double, yPos: Double) {
camera.mouseCallback(xPos, yPos)
}
fun registerKeyCallback(resourceLocation: ResourceLocation, ignoreConsumer: Boolean = false, callback: ((keyCode: KeyCodes, keyEvent: KeyAction) -> Unit)) {
var resourceLocationCallbacks = keyBindingCallbacks[resourceLocation]?.second
if (resourceLocationCallbacks == null) {
resourceLocationCallbacks = mutableSetOf()
val keyBinding = Minosoft.getConfig().config.game.controls.keyBindings.entries[resourceLocation] ?: return
keyBindingCallbacks[resourceLocation] = Pair(keyBinding, resourceLocationCallbacks)
}
resourceLocationCallbacks.add { keyCode, keyEvent ->
if (!ignoreConsumer) {
if (currentKeyConsumer != null) {
return@add
}
}
callback.invoke(keyCode, keyEvent)
}
}
fun unregisterKeyBinding(it: ResourceLocation) {
keyBindingCallbacks.remove(it)
}
}

View File

@ -13,23 +13,19 @@
package de.bixilon.minosoft.gui.rendering package de.bixilon.minosoft.gui.rendering
import de.bixilon.minosoft.Minosoft
import de.bixilon.minosoft.config.StaticConfiguration
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames
import de.bixilon.minosoft.config.key.KeyAction import de.bixilon.minosoft.config.key.KeyAction
import de.bixilon.minosoft.config.key.KeyBinding
import de.bixilon.minosoft.config.key.KeyCodes import de.bixilon.minosoft.config.key.KeyCodes
import de.bixilon.minosoft.data.mappings.ResourceLocation import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.data.text.RGBColor import de.bixilon.minosoft.data.text.RGBColor
import de.bixilon.minosoft.gui.input.camera.Camera
import de.bixilon.minosoft.gui.input.camera.FrustumChangeCallback import de.bixilon.minosoft.gui.input.camera.FrustumChangeCallback
import de.bixilon.minosoft.gui.input.key.RenderWindowInputHandler
import de.bixilon.minosoft.gui.modding.events.RenderingStateChangeEvent import de.bixilon.minosoft.gui.modding.events.RenderingStateChangeEvent
import de.bixilon.minosoft.gui.rendering.chunk.WorldRenderer import de.bixilon.minosoft.gui.rendering.chunk.WorldRenderer
import de.bixilon.minosoft.gui.rendering.font.Font import de.bixilon.minosoft.gui.rendering.font.Font
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
import de.bixilon.minosoft.gui.rendering.hud.atlas.TextureLike import de.bixilon.minosoft.gui.rendering.hud.atlas.TextureLike
import de.bixilon.minosoft.gui.rendering.hud.atlas.TextureLikeTexture import de.bixilon.minosoft.gui.rendering.hud.atlas.TextureLikeTexture
import de.bixilon.minosoft.gui.rendering.hud.elements.input.KeyConsumer
import de.bixilon.minosoft.gui.rendering.shader.ShaderHolder import de.bixilon.minosoft.gui.rendering.shader.ShaderHolder
import de.bixilon.minosoft.gui.rendering.textures.Texture import de.bixilon.minosoft.gui.rendering.textures.Texture
import de.bixilon.minosoft.gui.rendering.textures.TextureArray import de.bixilon.minosoft.gui.rendering.textures.TextureArray
@ -57,26 +53,22 @@ class RenderWindow(
val connection: PlayConnection, val connection: PlayConnection,
val rendering: Rendering, val rendering: Rendering,
) { ) {
private val keyBindingCallbacks: MutableMap<ResourceLocation, Pair<KeyBinding, MutableSet<((keyCode: KeyCodes, keyEvent: KeyAction) -> Unit)>>> = mutableMapOf()
private val keysDown: MutableSet<KeyCodes> = mutableSetOf()
private val keyBindingDown: MutableSet<KeyBinding> = mutableSetOf()
val renderStats = RenderStats() val renderStats = RenderStats()
var screenDimensions = Vec2i(900, 500) var screenDimensions = Vec2i(900, 500)
private set private set
var screenDimensionsF = Vec2(screenDimensions) var screenDimensionsF = Vec2(screenDimensions)
private set private set
val inputHandler = RenderWindowInputHandler(this)
private var windowId = 0L var windowId = 0L
private var deltaFrameTime = 0.0 // time between current frame and last frame private var deltaFrameTime = 0.0 // time between current frame and last frame
private var lastFrame = 0.0 private var lastFrame = 0.0
val camera: Camera = Camera(connection, Minosoft.getConfig().config.game.camera.fov, this)
private val latch = CountUpAndDownLatch(1) private val latch = CountUpAndDownLatch(1)
private var renderingState = RenderingStates.RUNNING private var renderingState = RenderingStates.RUNNING
private var polygonEnabled = false private var polygonEnabled = false
private var mouseCatch = !StaticConfiguration.DEBUG_MODE
private val screenshotTaker = ScreenshotTaker(this) private val screenshotTaker = ScreenshotTaker(this)
val tintColorCalculator = TintColorCalculator(connection.world) val tintColorCalculator = TintColorCalculator(connection.world)
@ -87,45 +79,14 @@ class RenderWindow(
val renderQueue = ConcurrentLinkedQueue<Runnable>() val renderQueue = ConcurrentLinkedQueue<Runnable>()
private var _currentInputConsumer: KeyConsumer? = null
private var skipNextCharPress = false
lateinit var WHITE_TEXTURE: TextureLike lateinit var WHITE_TEXTURE: TextureLike
val screenResizeCallbacks: MutableSet<ScreenResizeCallback> = mutableSetOf(camera) val screenResizeCallbacks: MutableSet<ScreenResizeCallback> = mutableSetOf(inputHandler.camera)
var tickCount = 0L var tickCount = 0L
var lastTickTimer = System.currentTimeMillis() var lastTickTimer = System.currentTimeMillis()
var currentKeyConsumer: KeyConsumer?
get() = _currentInputConsumer
set(value) {
_currentInputConsumer = value
for ((_, binding) in keyBindingCallbacks) {
if (!keyBindingDown.contains(binding.first)) {
continue
}
if (!binding.first.action.containsKey(KeyAction.TOGGLE) && !binding.first.action.containsKey(KeyAction.CHANGE)) {
continue
}
for (keyCallback in binding.second) {
keyCallback.invoke(KeyCodes.KEY_UNKNOWN, KeyAction.RELEASE)
}
}
// ToDo: move to mouse consumer
if (value == null) {
if (mouseCatch) {
renderQueue.add { glfwSetInputMode(windowId, GLFW_CURSOR, GLFW_CURSOR_DISABLED) }
}
} else {
renderQueue.add { glfwSetInputMode(windowId, GLFW_CURSOR, GLFW_CURSOR_NORMAL) }
}
keyBindingDown.clear()
}
init { init {
connection.registerEvent(CallbackEventInvoker.of<ConnectionStateChangeEvent> { connection.registerEvent(CallbackEventInvoker.of<ConnectionStateChangeEvent> {
if (it.connection.isDisconnected) { if (it.connection.isDisconnected) {
@ -143,8 +104,8 @@ class RenderWindow(
latch.countDown() latch.countDown()
} }
renderQueue.add { renderQueue.add {
camera.setPosition(packet.position) inputHandler.camera.setPosition(packet.position)
camera.setRotation(packet.rotation.yaw, packet.rotation.pitch) inputHandler.camera.setRotation(packet.rotation.yaw, packet.rotation.pitch)
} }
}) })
@ -174,102 +135,20 @@ class RenderWindow(
glfwTerminate() glfwTerminate()
throw RuntimeException("Failed to create the GLFW window") throw RuntimeException("Failed to create the GLFW window")
} }
camera.init(this) inputHandler.camera.init(this)
tintColorCalculator.init(connection.assetsManager) tintColorCalculator.init(connection.assetsManager)
glfwSetKeyCallback(this.windowId) { _: Long, key: Int, _: Int, action: Int, _: Int -> glfwSetKeyCallback(this.windowId, inputHandler::invoke)
val keyCode = KeyCodes.KEY_CODE_GLFW_ID_MAP[key] ?: KeyCodes.KEY_UNKNOWN
val keyAction = when (action) {
GLFW_PRESS -> KeyAction.PRESS
GLFW_RELEASE -> KeyAction.RELEASE
// ToDo: Double, Hold
else -> return@glfwSetKeyCallback
}
if (keyAction == KeyAction.PRESS) {
keysDown.add(keyCode)
} else if (keyAction == KeyAction.RELEASE) {
keysDown.remove(keyCode)
}
if (keyAction == KeyAction.PRESS) { glfwSetCharCallback(windowId, inputHandler::invoke)
// ToDo: Repeatable keys, long holding, etc
currentKeyConsumer?.keyInput(keyCode)
}
val previousKeyConsumer = currentKeyConsumer if (inputHandler.mouseCatch) {
for ((_, keyCallbackPair) in keyBindingCallbacks) {
run {
val keyBinding = keyCallbackPair.first
val keyCallbacks = keyCallbackPair.second
var anyCheckRun = false
keyBinding.action[KeyAction.MODIFIER]?.let {
val previousKeysDown = if (keyAction == KeyAction.RELEASE) {
val previousKeysDown = keysDown.toMutableList()
previousKeysDown.add(keyCode)
previousKeysDown
} else {
keysDown
}
if (!previousKeysDown.containsAll(it)) {
return@run
}
anyCheckRun = true
}
keyBinding.action[KeyAction.CHANGE]?.let {
if (!it.contains(keyCode)) {
return@run
}
anyCheckRun = true
}
// release or press
if (keyBinding.action[KeyAction.CHANGE] == null) {
keyBinding.action[keyAction].let {
if (it == null) {
return@run
}
if (!it.contains(keyCode)) {
return@run
}
anyCheckRun = true
}
}
if (!anyCheckRun) {
return@run
}
if (keyAction == KeyAction.PRESS) {
keyBindingDown.add(keyBinding)
} else if (keyAction == KeyAction.RELEASE) {
keyBindingDown.remove(keyBinding)
}
for (keyCallback in keyCallbacks) {
keyCallback.invoke(keyCode, keyAction)
if (previousKeyConsumer != currentKeyConsumer) {
skipNextCharPress = true
}
}
}
}
}
glfwSetCharCallback(windowId) { _: Long, char: Int ->
if (skipNextCharPress) {
skipNextCharPress = false
return@glfwSetCharCallback
}
currentKeyConsumer?.charInput(char.toChar())
}
if (mouseCatch) {
glfwSetInputMode(windowId, GLFW_CURSOR, GLFW_CURSOR_DISABLED) glfwSetInputMode(windowId, GLFW_CURSOR, GLFW_CURSOR_DISABLED)
} }
glfwSetCursorPosCallback(windowId) { _: Long, xPos: Double, yPos: Double -> camera.mouseCallback(xPos, yPos) } glfwSetCursorPosCallback(windowId, inputHandler::invoke)
MemoryStack.stackPush().let { stack -> MemoryStack.stackPush().let { stack ->
val pWidth = stack.mallocInt(1) val pWidth = stack.mallocInt(1)
val pHeight = stack.mallocInt(1) val pHeight = stack.mallocInt(1)
@ -328,7 +207,7 @@ class RenderWindow(
for (renderer in rendererMap.values) { for (renderer in rendererMap.values) {
renderer.postInit() renderer.postInit()
if (renderer is ShaderHolder) { if (renderer is ShaderHolder) {
camera.addShaders(renderer.shader) inputHandler.camera.addShaders(renderer.shader)
} }
} }
@ -382,7 +261,7 @@ class RenderWindow(
} }
private fun registerGlobalKeyCombinations() { private fun registerGlobalKeyCombinations() {
registerKeyCallback(KeyBindingsNames.DEBUG_POLYGON) { _: KeyCodes, _: KeyAction -> inputHandler.registerKeyCallback(KeyBindingsNames.DEBUG_POLYGON) { _: KeyCodes, _: KeyAction ->
polygonEnabled = !polygonEnabled polygonEnabled = !polygonEnabled
glPolygonMode(GL_FRONT_AND_BACK, if (polygonEnabled) { glPolygonMode(GL_FRONT_AND_BACK, if (polygonEnabled) {
GL_LINE GL_LINE
@ -391,19 +270,10 @@ class RenderWindow(
}) })
sendDebugMessage("Toggled polygon mode!") sendDebugMessage("Toggled polygon mode!")
} }
registerKeyCallback(KeyBindingsNames.DEBUG_MOUSE_CATCH) { _: KeyCodes, _: KeyAction -> inputHandler.registerKeyCallback(KeyBindingsNames.QUIT_RENDERING) { _: KeyCodes, _: KeyAction ->
mouseCatch = !mouseCatch
if (mouseCatch) {
glfwSetInputMode(windowId, GLFW_CURSOR, GLFW_CURSOR_DISABLED)
} else {
glfwSetInputMode(windowId, GLFW_CURSOR, GLFW_CURSOR_NORMAL)
}
sendDebugMessage("Toggled mouse catch!")
}
registerKeyCallback(KeyBindingsNames.QUIT_RENDERING) { _: KeyCodes, _: KeyAction ->
glfwSetWindowShouldClose(windowId, true) glfwSetWindowShouldClose(windowId, true)
} }
registerKeyCallback(KeyBindingsNames.TAKE_SCREENSHOT, true) { _: KeyCodes, _: KeyAction -> inputHandler.registerKeyCallback(KeyBindingsNames.TAKE_SCREENSHOT, true) { _: KeyCodes, _: KeyAction ->
screenshotTaker.takeScreenshot() screenshotTaker.takeScreenshot()
} }
} }
@ -422,7 +292,7 @@ class RenderWindow(
val currentTickTime = System.currentTimeMillis() val currentTickTime = System.currentTimeMillis()
if (currentTickTime - this.lastTickTimer > ProtocolDefinition.TICK_TIME) { if (currentTickTime - this.lastTickTimer > ProtocolDefinition.TICK_TIME) {
tickCount++ tickCount++
currentKeyConsumer?.tick(tickCount) inputHandler.currentKeyConsumer?.tick(tickCount)
this.lastTickTimer = currentTickTime this.lastTickTimer = currentTickTime
} }
@ -443,8 +313,8 @@ class RenderWindow(
glfwSwapBuffers(windowId) glfwSwapBuffers(windowId)
glfwPollEvents() glfwPollEvents()
camera.draw() inputHandler.camera.draw()
camera.handleInput(deltaFrameTime) inputHandler.camera.handleInput(deltaFrameTime)
// handle opengl context tasks, but limit it per frame // handle opengl context tasks, but limit it per frame
var actionsDone = 0 var actionsDone = 0
@ -496,23 +366,6 @@ class RenderWindow(
connection.fireEvent(RenderingStateChangeEvent(connection, previousState, renderingState)) connection.fireEvent(RenderingStateChangeEvent(connection, previousState, renderingState))
} }
fun registerKeyCallback(resourceLocation: ResourceLocation, ignoreConsumer: Boolean = false, callback: ((keyCode: KeyCodes, keyEvent: KeyAction) -> Unit)) {
var resourceLocationCallbacks = keyBindingCallbacks[resourceLocation]?.second
if (resourceLocationCallbacks == null) {
resourceLocationCallbacks = mutableSetOf()
val keyBinding = Minosoft.getConfig().config.game.controls.keyBindings.entries[resourceLocation] ?: return
keyBindingCallbacks[resourceLocation] = Pair(keyBinding, resourceLocationCallbacks)
}
resourceLocationCallbacks.add { keyCode, keyEvent ->
if (!ignoreConsumer) {
if (currentKeyConsumer != null) {
return@add
}
}
callback.invoke(keyCode, keyEvent)
}
}
fun registerRenderer(renderBuilder: RenderBuilder) { fun registerRenderer(renderBuilder: RenderBuilder) {
val renderer = renderBuilder.build(connection, this) val renderer = renderBuilder.build(connection, this)
rendererMap[renderBuilder.RESOURCE_LOCATION] = renderer rendererMap[renderBuilder.RESOURCE_LOCATION] = renderer
@ -520,7 +373,7 @@ class RenderWindow(
screenResizeCallbacks.add(renderer) screenResizeCallbacks.add(renderer)
} }
if (renderer is FrustumChangeCallback) { if (renderer is FrustumChangeCallback) {
camera.addFrustumChangeCallback(renderer) inputHandler.camera.addFrustumChangeCallback(renderer)
} }
} }
@ -531,8 +384,4 @@ class RenderWindow(
fun sendDebugMessage(message: String) { fun sendDebugMessage(message: String) {
connection.sender.sendFakeChatMessage(RenderConstants.DEBUG_MESSAGES_PREFIX + message) connection.sender.sendFakeChatMessage(RenderConstants.DEBUG_MESSAGES_PREFIX + message)
} }
fun unregisterKeyBinding(it: ResourceLocation) {
keyBindingCallbacks.remove(it)
}
} }

View File

@ -118,7 +118,7 @@ class WorldRenderer(
// register keybindings // register keybindings
renderWindow.registerKeyCallback(KeyBindingsNames.DEBUG_CLEAR_CHUNK_CACHE) { _, _ -> renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.DEBUG_CLEAR_CHUNK_CACHE) { _, _ ->
clearChunkCache() clearChunkCache()
renderWindow.sendDebugMessage("Cleared chunk cache!") renderWindow.sendDebugMessage("Cleared chunk cache!")
prepareWorld(world) prepareWorld(world)
@ -324,7 +324,7 @@ class WorldRenderer(
sectionMap[index] = meshCollection sectionMap[index] = meshCollection
if (renderWindow.camera.frustum.containsChunk(chunkPosition, lowestBlockHeight, highestBlockHeight)) { if (renderWindow.inputHandler.camera.frustum.containsChunk(chunkPosition, lowestBlockHeight, highestBlockHeight)) {
visibleChunks.getOrPut(chunkPosition, { ConcurrentHashMap() })[index] = meshCollection visibleChunks.getOrPut(chunkPosition, { ConcurrentHashMap() })[index] = meshCollection
} else { } else {
visibleChunks[chunkPosition]?.remove(index) visibleChunks[chunkPosition]?.remove(index)
@ -392,7 +392,7 @@ class WorldRenderer(
for ((chunkLocation, indexMap) in allChunkSections) { for ((chunkLocation, indexMap) in allChunkSections) {
val visibleIndexMap: MutableMap<Int, ChunkMeshCollection> = Collections.synchronizedMap(ConcurrentHashMap()) val visibleIndexMap: MutableMap<Int, ChunkMeshCollection> = Collections.synchronizedMap(ConcurrentHashMap())
for ((index, mesh) in indexMap) { for ((index, mesh) in indexMap) {
if (renderWindow.camera.frustum.containsChunk(chunkLocation, mesh.lowestBlockHeight, mesh.highestBlockHeight)) { if (renderWindow.inputHandler.camera.frustum.containsChunk(chunkLocation, mesh.lowestBlockHeight, mesh.highestBlockHeight)) {
visibleIndexMap[index] = mesh visibleIndexMap[index] = mesh
} }
} }

View File

@ -65,7 +65,7 @@ class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow
registerDefaultElements() registerDefaultElements()
renderWindow.registerKeyCallback(KeyBindingsNames.TOGGLE_HUD) { _, _ -> renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.TOGGLE_HUD) { _, _ ->
hudEnabled = !hudEnabled hudEnabled = !hudEnabled
} }
@ -116,7 +116,7 @@ class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow
properties.toggleKeyBinding?.let { properties.toggleKeyBinding?.let {
// register key binding // register key binding
renderWindow.registerKeyCallback(it) { _, _ -> renderWindow.inputHandler.registerKeyCallback(it) { _, _ ->
if (enabledHUDElement.contains(resourceLocation)) { if (enabledHUDElement.contains(resourceLocation)) {
enabledHUDElement.remove(resourceLocation) enabledHUDElement.remove(resourceLocation)
} else { } else {
@ -142,7 +142,7 @@ class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow
} }
element.first.toggleKeyBinding?.let { element.first.toggleKeyBinding?.let {
renderWindow.unregisterKeyBinding(it) renderWindow.inputHandler.unregisterKeyBinding(it)
} }
enabledHUDElement.remove(resourceLocation) enabledHUDElement.remove(resourceLocation)
hudElements.remove(resourceLocation) hudElements.remove(resourceLocation)

View File

@ -40,10 +40,10 @@ class ChatBoxHUDElement(hudRenderer: HUDRenderer) : HUDElement(hudRenderer), Scr
layout.addChild(Vec2i(0, 0), inputField) layout.addChild(Vec2i(0, 0), inputField)
inputField.apply() inputField.apply()
hudRenderer.renderWindow.registerKeyCallback(KeyBindingsNames.OPEN_CHAT) { _, _ -> hudRenderer.renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.OPEN_CHAT) { _, _ ->
openChat() openChat()
} }
hudRenderer.renderWindow.registerKeyCallback(KeyBindingsNames.CLOSE_CHAT) { _, _ -> hudRenderer.renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.CLOSE_CHAT) { _, _ ->
closeChat() closeChat()
} }
} }
@ -58,12 +58,12 @@ class ChatBoxHUDElement(hudRenderer: HUDRenderer) : HUDElement(hudRenderer), Scr
fun openChat() { fun openChat() {
layout.addChild(Vec2i(0, 0), inputFieldBackground) layout.addChild(Vec2i(0, 0), inputFieldBackground)
hudRenderer.renderWindow.currentKeyConsumer = inputField hudRenderer.renderWindow.inputHandler.currentKeyConsumer = inputField
} }
fun closeChat() { fun closeChat() {
layout.removeChild(inputFieldBackground) layout.removeChild(inputFieldBackground)
inputField.clearText() inputField.clearText()
hudRenderer.renderWindow.currentKeyConsumer = null hudRenderer.renderWindow.inputHandler.currentKeyConsumer = null
} }
} }

View File

@ -22,7 +22,7 @@ import de.bixilon.minosoft.util.UnitFormatter
class HUDWorldDebugNode(hudRenderer: HUDRenderer) : DebugScreenNode(hudRenderer) { class HUDWorldDebugNode(hudRenderer: HUDRenderer) : DebugScreenNode(hudRenderer) {
private val camera = hudRenderer.renderWindow.camera private val camera = hudRenderer.renderWindow.inputHandler.camera
private val worldRenderer = hudRenderer.renderWindow.rendererMap[WorldRenderer.RESOURCE_LOCATION] as WorldRenderer? private val worldRenderer = hudRenderer.renderWindow.rendererMap[WorldRenderer.RESOURCE_LOCATION] as WorldRenderer?
init { init {
@ -128,8 +128,8 @@ class HUDWorldDebugNode(hudRenderer: HUDRenderer) : DebugScreenNode(hudRenderer)
} }
private fun getFacing(): String { private fun getFacing(): String {
val yaw = hudRenderer.renderWindow.camera.playerEntity.rotation.yaw val yaw = hudRenderer.renderWindow.inputHandler.camera.playerEntity.rotation.yaw
val pitch = hudRenderer.renderWindow.camera.playerEntity.rotation.pitch val pitch = hudRenderer.renderWindow.inputHandler.camera.playerEntity.rotation.pitch
val direction = Directions.byDirection(camera.cameraFront) val direction = Directions.byDirection(camera.cameraFront)
return "${Directions.byDirection(camera.cameraFront).name.toLowerCase()} ${direction.directionVector} (${formatRotation(yaw.toDouble())} / ${formatRotation(pitch.toDouble())})" return "${Directions.byDirection(camera.cameraFront).name.toLowerCase()} ${direction.directionVector} (${formatRotation(yaw.toDouble())} / ${formatRotation(pitch.toDouble())})"
} }

View File

@ -121,7 +121,7 @@ class PlayConnection(
for (entity in world.entityIdMap.values) { for (entity in world.entityIdMap.values) {
entity.computeTimeStep(deltaTime) entity.computeTimeStep(deltaTime)
} }
renderer?.renderWindow?.camera?.checkPosition() renderer?.renderWindow?.inputHandler?.camera?.checkPosition()
velocityHandlerLastExecutionTime = currentTime velocityHandlerLastExecutionTime = currentTime
} }
TimeWorker.addTask(velocityHandlerTask) TimeWorker.addTask(velocityHandlerTask)