dermy-map/android/src/xyz/r0r5chach/dermy_app/map/MapCameraController.kt

85 lines
3.0 KiB
Kotlin

package xyz.r0r5chach.dermy_app.map
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.PerspectiveCamera
import com.badlogic.gdx.graphics.g3d.ModelInstance
import com.badlogic.gdx.graphics.g3d.model.MeshPart
import com.badlogic.gdx.graphics.g3d.utils.CameraInputController
import com.badlogic.gdx.math.Intersector
import com.badlogic.gdx.math.Vector3
import xyz.r0r5chach.dermy_app.map.locations.BodyPart
import xyz.r0r5chach.dermy_app.map.locations.Location
import xyz.r0r5chach.dermy_app.map.locations.Side
import kotlin.math.abs
import kotlin.properties.Delegates
class MapCameraController(
camera: PerspectiveCamera?,
var modelInstance: ModelInstance?
) : CameraInputController(camera) {
private var initialX: Int = 0
private var initialY: Int = 0
private var selectedLocation: Location by Delegates.observable(Location(Side.NONE, BodyPart.NONE)) { _, _, newValue ->
notifyObservers(newValue)
}
private val observers = mutableListOf<(Location) -> Unit>()
init {
this.pinchZoomFactor = 25f
}
fun addObserver(observer: (Location) -> Unit) {
observers.add(observer)
}
private fun notifyObservers(newValue: Location) {
for (observer in observers) {
observer(newValue)
}
}
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
initialX = screenX
initialY = screenY
return super.touchDown(screenX, screenY, pointer, button)
}
override fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
if (abs((initialX - screenX).toDouble()) < 10 && abs((initialY - screenY).toDouble()) < 10) {
handleClick()
}
return super.touchUp(screenX, screenY, pointer, button)
}
private fun handleClick() {
if (modelInstance != null) {
val selectionRay = camera.getPickRay(Gdx.input.x.toFloat(), Gdx.input.y.toFloat())
var closestDistance = Float.MAX_VALUE
var closestPart: MeshPart? = null
val meshes = modelInstance!!.model.meshParts
for (part in meshes) {
val bounds = part.mesh.calculateBoundingBox()
bounds.mul(modelInstance!!.transform)
val intersection = Vector3()
if (Intersector.intersectRayBounds(selectionRay, bounds, intersection)) {
val distance = selectionRay.origin.dst(intersection)
if (distance < closestDistance) {
closestDistance = distance
closestPart = part
}
}
}
val id = closestPart?.id
val side = when (id?.get(0)) {
'L' -> Side.LEFT
'R' -> Side.RIGHT
else -> Side.LEFT
}
val bodyPart = BodyPart.valueOf(id!!.substring(1).uppercase())
selectedLocation = Location(side, bodyPart)
}
}
}