commonMain.ru.casperix.demo_platform.camera.OrthographicCameraController.kt Maven / Gradle / Ivy
package ru.casperix.demo_platform.camera
import ru.casperix.input.*
import ru.casperix.math.axis_aligned.float32.Box2f
import ru.casperix.math.axis_aligned.int32.Dimension2i
import ru.casperix.math.camera.OrthographicCamera2f
import ru.casperix.math.vector.float32.Vector2f
import ru.casperix.math.vector.int32.Vector2i
import ru.casperix.misc.clamp
class OrthographicCameraController(val camera: OrthographicCamera2f, val config: CameraConfig) {
private var zoomFactor = 1.1f
private var startPoint: Vector2i? = null
private val translateButton = PointerButton.RIGHT
init {
// apply camera limits:
setZoom(camera.zoom)
setPosition(camera.position)
}
fun update(viewport: Dimension2i) {
camera.viewport = viewport
}
fun input(event: InputEvent) {
when (event) {
is PointerDown -> if (translateButton == event.button) {
startPoint = event.position.roundToVector2i()
event.captured = true
}
is PointerUp -> if (translateButton == event.button) {
startPoint = null
event.captured = true
}
is PointerMove -> {
val lastPoint = startPoint ?: return
val currentPoint = event.position.roundToVector2i()
val delta = (currentPoint - lastPoint) * Vector2i(1, -1)
startPoint = currentPoint
setPosition(camera.position - delta.toVector2f() * camera.zoom)
event.captured = true
}
is MouseWheel -> {
val wheelOffset = event.wheel.y
if (wheelOffset != 0f) {
val factor = if (wheelOffset < 0) zoomFactor
else 1f / zoomFactor
setZoom(camera.zoom * factor)
}
}
}
}
private fun setPosition(value: Vector2f) {
camera.position = if (config.bound != null) {
bound(value, config.bound)
} else {
value
}
}
private fun bound(value: Vector2f, bound: Box2f): Vector2f {
val min = bound.min
val max = bound.max
var result = value
if (result.x < min.x) result = result.copy(x = min.x)
if (result.y < min.y) result = result.copy(y = min.y)
if (result.x > max.x) result = result.copy(x = max.x)
if (result.y > max.y) result = result.copy(y = max.y)
return result
}
private fun setZoom(value: Float) {
camera.zoom = value.clamp(config.minZoom, config.maxZoom)
}
}