Repository: skyline-emu/skyline
File: app/src/main/java/emu/skyline/input/onscreen/OnScreenButton.kt (Kotlin)

Code before:

    var isEditing = false
        private set

    protected open fun renderCenteredText(canvas : Canvas, text : String, size : Float, x : Float, y : Float, alpha : Int) {
        buttonSymbolPaint.apply {
            textSize = size
            textAlign = Paint.Align.LEFT
            this.alpha = alpha
            getTextBounds(text, 0, text.length, textBoundsRect)
        }
        canvas.drawText(text, x - textBoundsRect.width() / 2f - textBoundsRect.left, y + textBoundsRect.height() / 2f - textBoundsRect.bottom, buttonSymbolPaint)
    }

    open fun render(canvas : Canvas) {
        val bounds = currentBounds
        val alpha = if (isPressed) (config.alpha - 130).coerceIn(30..255) else config.alpha
        drawable.apply {
            this.bounds = bounds
            this.alpha = alpha
            draw(canvas)
        }

        renderCenteredText(canvas, buttonId.short!!, itemWidth.coerceAtMost(itemHeight) * 0.4f, bounds.centerX().toFloat(), bounds.centerY().toFloat(), alpha)
    }

    abstract fun isTouched(x : Float, y : Float) : Boolean

    open fun onFingerDown(x : Float, y : Float) {
        isPressed = true
    }

    open fun onFingerUp(x : Float, y : Float) {
        isPressed = false
    }

    fun loadConfigValues() {
        relativeX = config.relativeX
        relativeY = config.relativeY
    }

    fun startEdit() {
        isEditing = true
    }

    open fun edit(x : Float, y : Float) {
        relativeX = x / width
        relativeY = (y - heightDiff) / adjustedHeight
    }

    fun endEdit() {

Review comment (suggestion):
Since color is only updated by the user, try setting the color to the drawable in an `init` block and provide a way to recreate the buttons when the user changes colors (it might not be needed depending on how `invalidate()` works), rather than setting the color at every render.

Code after:
     */
    var touchPointerId = -1
    var partnerPointerId = -1

    var isPressed = false

    var hapticFeedback = false

    var isEditing = false
        private set

    protected open fun renderCenteredText(canvas : Canvas, text : String, size : Float, x : Float, y : Float, alpha : Int) {
        buttonSymbolPaint.apply {
            textSize = size
            textAlign = Paint.Align.LEFT
            color = config.textColor
            this.alpha = alpha
            getTextBounds(text, 0, text.length, textBoundsRect)
        }
        canvas.drawText(text, x - textBoundsRect.width() / 2f - textBoundsRect.left, y + textBoundsRect.height() / 2f - textBoundsRect.bottom, buttonSymbolPaint)
    }

    open fun render(canvas : Canvas) {
        val bounds = currentBounds
        val alpha = if (isPressed) (config.alpha - 130).coerceIn(30..255) else config.alpha
        renderColors(drawable)
        drawable.apply {
            this.bounds = bounds
            this.alpha = alpha
            draw(canvas)
        }
        renderCenteredText(canvas, buttonId.short!!, itemWidth.coerceAtMost(itemHeight) * 0.4f, bounds.centerX().toFloat(), bounds.centerY().toFloat(), alpha)
    }

    private fun renderColors(drawable : Drawable) {
        when (drawable) {
            is GradientDrawable -> drawable.setColor(config.backgroundColor)
            is LayerDrawable -> {
                for (i in 0 until drawable.numberOfLayers) renderColors(drawable.getDrawable(i))
            }
            else -> drawable.setTint(config.backgroundColor)
        }
    }

    abstract fun isTouched(x : Float, y : Float) : Boolean

    open fun onFingerDown(x : Float, y : Float) {
        isPressed = true
    }

    open fun onFingerUp(x : Float, y : Float) {