net.peanuuutz.fork.ui.scene.screen.ScreenPointerService.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fork-ui Show documentation
Show all versions of fork-ui Show documentation
Comprehensive API designed for Minecraft modders
The newest version!
package net.peanuuutz.fork.ui.scene.screen
import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import kotlinx.coroutines.Dispatchers
import net.peanuuutz.fork.coroutine.core.Client
import net.peanuuutz.fork.ui.ui.context.pointer.PointerIcon
import net.peanuuutz.fork.ui.ui.context.pointer.PointerService
import net.peanuuutz.fork.ui.ui.unit.FloatOffset
import net.peanuuutz.fork.util.fork.InternalForkApi
import net.peanuuutz.fork.util.minecraft.client
import org.lwjgl.glfw.GLFW
import kotlin.coroutines.EmptyCoroutineContext
@Stable
object ScreenPointerService : PointerService {
// -------- Position --------
override var position: FloatOffset
get() = _position
set(value) {
if (_position == value) {
return
}
_position = value
recordPositionModification(value)
}
private var _position: FloatOffset by mutableStateOf(FloatOffset.Zero)
@InternalForkApi
fun setPosition(x: Float, y: Float) { // From Java
position = FloatOffset(x, y)
}
private fun recordPositionModification(new: FloatOffset) {
recordModification {
val window = client.window
val scaleFactor = window.scaleFactor
val scaledX = new.x * scaleFactor
val scaledY = new.y * scaleFactor
GLFW.glfwSetCursorPos(window.handle, scaledX, scaledY)
}
}
// -------- Icon --------
private var icon = PointerIcon.Default
private val iconStack: ArrayDeque = ArrayDeque(4)
private val createdPointerHandle: MutableMap = mutableMapOf()
override fun pushIcon(icon: PointerIcon) {
iconStack.add(icon)
if (ScreenPointerService.icon == icon) {
return
}
ScreenPointerService.icon = icon
recordIconModification(icon)
}
override fun popIcon() {
iconStack.removeLastOrNull()
val icon = iconStack.lastOrNull() ?: PointerIcon.Default
if (ScreenPointerService.icon == icon) {
return
}
ScreenPointerService.icon = icon
recordIconModification(icon)
}
private fun recordIconModification(new: PointerIcon) {
recordModification {
val newPointer = createdPointerHandle.getOrPut(new) {
GLFW.glfwCreateStandardCursor(new.code)
}
GLFW.glfwSetCursor(client.window.handle, newPointer)
}
}
// -------- Record --------
private fun recordModification(block: () -> Unit) {
Dispatchers.Client.dispatch(EmptyCoroutineContext, block)
}
}