commonMain.ru.casperix.spine.intersection.SkeletonIntersection.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of spine-jvm Show documentation
Show all versions of spine-jvm Show documentation
Signals for all occasions
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
}
}
}
}