All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.ru.casperix.spine.intersection.SkeletonIntersection.kt Maven / Gradle / Ivy

There is a newer version: 1.1.1
Show newest version
package ru.casperix.spine.intersection

import ru.casperix.math.axis_aligned.float32.Box2f
import ru.casperix.math.intersection.float32.Intersection2Float
import ru.casperix.math.quad_matrix.float32.Matrix3f
import ru.casperix.math.vector.float32.Vector2f
import ru.casperix.math.vector.toQuad
import ru.casperix.spine.Bone
import ru.casperix.spine.RegionAttachment
import ru.casperix.spine.Skeleton
import ru.casperix.spine.Slot
import ru.casperix.spine.renderer.SpineController

object SkeletonIntersection {
    class Intersection(val slot: Slot, val point: Vector2f)

    fun hasSlot(controller: SpineController, worldPosition: Vector2f, slotName: String): Boolean =
        firstSlot(controller.skeleton, controller.worldMatrix, worldPosition, slotName) != null

    fun hasBone(controller: SpineController, worldPosition: Vector2f, boneName: String): Boolean =
        firstBone(controller.skeleton, controller.worldMatrix, worldPosition, boneName) != null

    fun firstSlot(skeleton: Skeleton, skeletonWorldMatrix: Matrix3f, worldPosition: Vector2f, slotName: String): Slot? {
        return getAll(skeleton, skeletonWorldMatrix, worldPosition).firstOrNull { it.slot.data.name == slotName }?.slot
    }

    fun firstBone(skeleton: Skeleton, skeletonWorldMatrix: Matrix3f, worldPosition: Vector2f, boneName: String): Bone? {
        return getAll(skeleton, skeletonWorldMatrix, worldPosition).firstOrNull { it.slot.bone.data.name == boneName }?.slot?.bone
    }

    fun getAll(controller: SpineController, worldPosition: Vector2f): Sequence =
        getAll(controller.skeleton, controller.worldMatrix, worldPosition)

    fun getAll(skeleton: Skeleton, skeletonWorldMatrix: Matrix3f, worldPosition: Vector2f): Sequence =
        skeleton.drawOrder.asSequence().mapNotNull { slot ->
            val bone = slot.bone
            val boneSummaryMatrix = bone.world.toMatrix() * skeletonWorldMatrix
            when (val attachment = slot.attachment) {
                is RegionAttachment -> {
                    val summaryMatrix = attachment.transform.value * boneSummaryMatrix
                    val pixels = attachment.region.bounds.toBox2f()
                    val dimension = pixels.dimension

                    val positions =
                        Box2f.byDimension(
                            -Vector2f(dimension.x, dimension.y) / 2f,
                            Vector2f(dimension.x, dimension.y)
                        ).toQuad().convert { summaryMatrix.transform(it) }

                    if (Intersection2Float.hasPointWithPolygon(worldPosition, positions)) {
                        Intersection(slot, worldPosition)
                    } else null

                }

                else -> {
                    null
                }
            }
        }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy