DeflatedPickle/FAOSDance

View on GitHub
src/main/kotlin/com/deflatedpickle/faosdance/gui/SpritePanel.kt

Summary

Maintainability
F
4 days
Test Coverage
package com.deflatedpickle.faosdance.gui

import com.deflatedpickle.faosdance.util.GlobalValues
import com.deflatedpickle.faosdance.backend.RubyThread
import com.deflatedpickle.faosdance.ScalingType
import com.deflatedpickle.faosdance.gui.settings.general.SpriteCategory
import java.awt.*
import java.awt.datatransfer.DataFlavor
import java.awt.dnd.DnDConstants
import java.awt.dnd.DropTarget
import java.awt.dnd.DropTargetDropEvent
import java.awt.event.ActionListener
import java.awt.image.BufferedImage
import java.io.File
import javax.swing.JPanel
import javax.swing.Timer

class SpritePanel : JPanel() {
    init {
        isOpaque = false

        dropTarget = object : DropTarget() {
            override fun drop(dtde: DropTargetDropEvent) {
                dtde.acceptDrop(DnDConstants.ACTION_COPY)
                val droppedFiles = dtde.transferable.getTransferData(DataFlavor.javaFileListFlavor) as List<File>

                if (droppedFiles.size == 1) {
                    SpriteCategory.loadSpriteSheet(droppedFiles[0])
                }
            }
        }

        GlobalValues.timer = Timer(1000 / GlobalValues.optionsMap.getMap("sprite")!!.getMap("animation")!!.getOption<Int>("fps")!!, ActionListener {
            if (GlobalValues.sheet != null) {
                if (GlobalValues.optionsMap.getMap("sprite")!!.getMap("animation")!!.getOption<Boolean>("play")!!) {
                    if (GlobalValues.optionsMap.getMap("sprite")!!.getMap("animation")!!.getOption<Boolean>("rewind")!!) {
                        val frame = GlobalValues.optionsMap.getMap("sprite")!!.getMap("animation")!!.getOption<Int>("frame")!!
                        GlobalValues.optionsMap.getMap("sprite")!!.getMap("animation")!!.setOption("frame", frame - 1)

                        if (GlobalValues.optionsMap.getMap("sprite")!!.getMap("animation")!!.getOption<Int>("frame")!! <= 0) {
                            GlobalValues.optionsMap.getMap("sprite")!!.getMap("animation")!!.setOption("frame", 7)
                        }
                    } else {
                        val frame = GlobalValues.optionsMap.getMap("sprite")!!.getMap("animation")!!.getOption<Int>("frame")!!
                        GlobalValues.optionsMap.getMap("sprite")!!.getMap("animation")!!.setOption("frame", frame + 1)

                        if (GlobalValues.optionsMap.getMap("sprite")!!.getMap("animation")!!.getOption<Int>("frame")!! >= 8) {
                            GlobalValues.optionsMap.getMap("sprite")!!.getMap("animation")!!.setOption("frame", 0)
                        }
                    }

                    GlobalValues.animationControls?.second?.value = GlobalValues.optionsMap.getMap("sprite")!!.getMap("animation")!!.getOption<Int>("frame")!!
                }

                GlobalValues.mutableSprite = GlobalValues.sheet!!.spriteMap[GlobalValues.optionsMap.getMap("sprite")!!.getMap("animation")!!.getOption<String>("action")!!]!![GlobalValues.optionsMap.getMap("sprite")!!.getMap("animation")!!.getOption<Int>("frame")!!]

                GlobalValues.frame!!.revalidate()
                GlobalValues.frame!!.repaint()
            }
        })
        GlobalValues.timer!!.start()
    }

    override fun paintComponent(g: Graphics) {
        super.paintComponent(g)

        if (GlobalValues.sheet == null) return

        val g2D = g as Graphics2D
        g2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, when (ScalingType.valueOf(
            GlobalValues.unsanatizeEnumValue(
                GlobalValues.optionsMap.getMap("sprite")!!.getOption<String>("scaling_type")!!))) {
            ScalingType.BILINEAR -> RenderingHints.VALUE_INTERPOLATION_BILINEAR
            ScalingType.BICUBIC -> RenderingHints.VALUE_INTERPOLATION_BICUBIC
            ScalingType.NEAREST_NEIGHBOR -> RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR
        })

        for (i in RubyThread.extensions) {
            if (GlobalValues.isEnabled(i)) {
                RubyThread.rubyContainer.callMethod(i, "pre_draw", g2D)
            }
        }

        // Change the opacity
        g2D.composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, GlobalValues.optionsMap.getMap("sprite")!!.getOption<Double>("opacity")!!.toFloat())

        // Rotate the matrix
        g2D.rotate(
            Math.toRadians(GlobalValues.optionsMap.getMap("sprite")!!.getMap("rotation")!!.getOption<Int>("z")!!.toDouble()),
            (this.width / 2).toDouble(),
            (this.height / 2).toDouble()
        )

        // Translate to the centre
        g2D.translate(
            (this.width - GlobalValues.sheet!!.spriteWidth * GlobalValues.optionsMap.getMap("sprite")!!.getMap("size")!!.getOption<Double>("width")!!) / 2,
            (this.height - GlobalValues.sheet!!.spriteHeight * GlobalValues.optionsMap.getMap("sprite")!!.getMap("size")!!.getOption<Double>("height")!!) / 2
        )

        // Translate upwards the size of the sprite plus the reflection padding
        if (GlobalValues.optionsMap.getMap("reflection")!!.getOption<Boolean>("visible")!!) {
            g2D.translate(
                0.0,
                -(GlobalValues.sheet!!.spriteHeight * GlobalValues.optionsMap.getMap("sprite")!!.getMap("size")!!.getOption<Double>("height")!!) / 2 - GlobalValues.optionsMap.getMap("reflection")!!.getOption<Double>("padding")!!
            )
        }
        // Scale the sprite
        g2D.scale(GlobalValues.optionsMap.getMap("sprite")!!.getMap("size")!!.getOption<Double>("width")!!, GlobalValues.optionsMap.getMap("sprite")!!.getMap("size")!!.getOption<Double>("height")!!)

        // Draw the sprite
        if (GlobalValues.optionsMap.getMap("sprite")!!.getOption<Boolean>("visible")!!) {
            val sprite = BufferedImage(
                GlobalValues.sheet!!.spriteWidth,
                GlobalValues.sheet!!.spriteHeight,
                BufferedImage.TYPE_INT_ARGB
            )
            val spriteGraphics = sprite.createGraphics()

            for (i in RubyThread.extensions) {
                if (GlobalValues.isEnabled(i)) {
                    RubyThread.rubyContainer.callMethod(i, "pre_draw_sprite", spriteGraphics)
                }
            }

            spriteGraphics.drawRenderedImage(
                GlobalValues.mutableSprite,
                null
            )

            for (i in RubyThread.extensions) {
                if (GlobalValues.isEnabled(i)) {
                    RubyThread.rubyContainer.callMethod(i, "during_draw_sprite", spriteGraphics)
                }
            }

            spriteGraphics.dispose()
            g2D.drawRenderedImage(sprite, null)

            for (i in RubyThread.extensions) {
                if (GlobalValues.isEnabled(i)) {
                    RubyThread.rubyContainer.callMethod(i, "post_draw_sprite", g2D)
                }
            }
        }

        // Move to the bottom of the sprite
        g2D.translate(
            0.0,
            (GlobalValues.sheet!!.spriteHeight) * 2 + (GlobalValues.optionsMap.getMap("reflection")!!.getOption<Double>("padding")!!)
        )
        // Flip the matrix, so the reflection is upside down
        g2D.scale(1.0, -1.0)

        // Create a new image for the reflection
        if (GlobalValues.optionsMap.getMap("reflection")!!.getOption<Boolean>("visible")!!) {
            val reflection = BufferedImage(
                GlobalValues.sheet!!.spriteWidth,
                GlobalValues.sheet!!.spriteHeight,
                BufferedImage.TYPE_INT_ARGB
            )
            val reflectionGraphics = reflection.createGraphics()

            for (i in RubyThread.extensions) {
                if (GlobalValues.isEnabled(i)) {
                    RubyThread.rubyContainer.callMethod(i, "pre_draw_reflection", reflectionGraphics)
                }
            }

            // Draw the reflection
            reflectionGraphics.drawRenderedImage(
                GlobalValues.mutableSprite,
                null
            )

            for (i in RubyThread.extensions) {
                if (GlobalValues.isEnabled(i)) {
                    RubyThread.rubyContainer.callMethod(i, "during_draw_reflection", reflectionGraphics)
                }
            }

            reflectionGraphics.composite = AlphaComposite.getInstance(AlphaComposite.DST_IN)
            // Apply a gradient paint, so the reflection fades out
            reflectionGraphics.paint = GradientPaint(
                0f,
                GlobalValues.sheet!!.spriteHeight.toFloat() * GlobalValues.optionsMap.getMap("reflection")!!.getMap("fade")!!.getOption<Float>("height")!!,
                Color(0.0f, 0.0f, 0.0f, 0.0f),
                0f,
                GlobalValues.sheet!!.spriteHeight.toFloat(),
                Color(0.0f, 0.0f, 0.0f, GlobalValues.optionsMap.getMap("reflection")!!.getMap("fade")!!.getOption<Float>("opacity")!!)
            )
            reflectionGraphics.fillRect(0, 0, GlobalValues.sheet!!.spriteWidth, GlobalValues.sheet!!.spriteHeight)
            reflectionGraphics.dispose()
            g2D.drawRenderedImage(reflection, null)

            for (i in RubyThread.extensions) {
                if (GlobalValues.isEnabled(i)) {
                    RubyThread.rubyContainer.callMethod(i, "post_draw_reflection", g2D)
                }
            }
        }

        for (i in RubyThread.extensions) {
            if (GlobalValues.isEnabled(i)) {
                RubyThread.rubyContainer.callMethod(i, "post_draw", g2D)
            }
        }
    }
}