85 lines
3.0 KiB
Kotlin
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)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|