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

commonMain.ru.casperix.spine.renderer.SkeletonRenderer.kt Maven / Gradle / Ivy

There is a newer version: 0.9.0
Show newest version
package ru.casperix.spine.renderer

import ru.casperix.math.axis_aligned.float32.Box2f
import ru.casperix.math.color.Colors
import ru.casperix.math.geometry.builder.UniformArrowMode
import ru.casperix.math.geometry.toSegment
import ru.casperix.math.quad_matrix.float32.Matrix3f
import ru.casperix.math.straight_line.float32.LineSegment2f
import ru.casperix.math.vector.float32.Vector2f
import ru.casperix.math.vector.toQuad
import ru.casperix.multiplatform.font.FontReference
import ru.casperix.multiplatform.text.drawText
import ru.casperix.renderer.Renderer2D
import ru.casperix.renderer.material.SimpleMaterial
import ru.casperix.renderer.vector.GeometryBuilder.texturedQuad
import ru.casperix.renderer.vector.VectorGraphic
import ru.casperix.renderer.vector.VectorShape
import ru.casperix.spine.RegionAttachment
import ru.casperix.spine.Skeleton

object SkeletonRenderer {
    fun Renderer2D.drawSkeleton(skeleton: Skeleton) {
        drawGraphic(assemble(skeleton))
    }

    fun assemble(skeleton: Skeleton) = VectorGraphic(skeleton.slots.mapNotNull { slot ->
        val bone = slot.bone
        val boneSummaryMatrix = bone.world * skeleton.parentMatrix
        val attachment = slot.attachment
        when (attachment) {
            is RegionAttachment -> {
                val attachmentMatrix = attachment.transform.toLHSMatrix()

                val imageMatrix = Matrix3f.rotate(-attachment.region.rotate)
                val summaryMatrix = imageMatrix * attachmentMatrix * 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) }

                val textures = Box2f(
                    pixels.min / attachment.region.pixels.dimension.toVector2f(),
                    pixels.max / attachment.region.pixels.dimension.toVector2f()
                ).toQuad()


                VectorShape(SimpleMaterial(attachment.region.pixels), texturedQuad(positions, textures))
            }

            else -> {
                null
            }
        }
    })

    fun Renderer2D.drawSkeletonDebug(skeleton: Skeleton) {
        skeleton.bones.forEach { bone ->
            val boneSummaryMatrix = bone.world * skeleton.parentMatrix

            val length = bone.data.length
            val center = boneSummaryMatrix.transform(Vector2f.ZERO)
            if (length <= 0.1f) {
                drawCircle(Colors.RED, center, 10f, 12f, 64, Matrix3f.IDENTITY)
            } else {
                val line = LineSegment2f.byDelta(Vector2f.ZERO, Vector2f(bone.data.length, 0f)).toLine().convert { boneSummaryMatrix.transform(it) }
                drawArrow(Colors.RED, line.toSegment(), 2f, UniformArrowMode(0.5f, 20f, 10f))
            }

            drawText(bone.data.name, FontReference("Arial", 12), boneSummaryMatrix)
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy