~cytrogen/vbhelper

1a09e40d1d3b0ec736221ad05663c73c17fbe63c — nacabaro 8 months ago d46769b + 39ba48d
Merge pull request #31 from nacabaro/database/get_all_sprites

Fetch all the character sprites into the internal database
M app/src/main/java/com/github/nacabaro/vbhelper/MainActivity.kt => app/src/main/java/com/github/nacabaro/vbhelper/MainActivity.kt +7 -3
@@ 14,6 14,7 @@ import com.github.nacabaro.vbhelper.screens.itemsScreen.ItemsScreenControllerImp
import com.github.nacabaro.vbhelper.screens.scanScreen.ScanScreenControllerImpl
import com.github.nacabaro.vbhelper.screens.settingsScreen.SettingsScreenControllerImpl
import com.github.nacabaro.vbhelper.screens.adventureScreen.AdventureScreenControllerImpl
import com.github.nacabaro.vbhelper.screens.spriteViewer.SpriteViewerControllerImpl
import com.github.nacabaro.vbhelper.screens.storageScreen.StorageScreenControllerImpl
import com.github.nacabaro.vbhelper.ui.theme.VBHelperTheme



@@ 45,6 46,7 @@ class MainActivity : ComponentActivity() {
        val adventureScreenController = AdventureScreenControllerImpl(this)
        val storageScreenController = StorageScreenControllerImpl(this)
        val homeScreenController = HomeScreenControllerImpl(this)
        val spriteViewerController = SpriteViewerControllerImpl(this)

        super.onCreate(savedInstanceState)



@@ 58,7 60,8 @@ class MainActivity : ComponentActivity() {
                    itemsScreenController = itemsScreenController,
                    adventureScreenController = adventureScreenController,
                    homeScreenController = homeScreenController,
                    storageScreenController = storageScreenController
                    storageScreenController = storageScreenController,
                    spriteViewerController = spriteViewerController
                )
            }
        }


@@ 90,7 93,7 @@ class MainActivity : ComponentActivity() {
        adventureScreenController: AdventureScreenControllerImpl,
        storageScreenController: StorageScreenControllerImpl,
        homeScreenController: HomeScreenControllerImpl,

        spriteViewerController: SpriteViewerControllerImpl
        ) {
        AppNavigation(
            applicationNavigationHandlers = AppNavigationHandlers(


@@ 99,7 102,8 @@ class MainActivity : ComponentActivity() {
                itemsScreenController,
                adventureScreenController,
                storageScreenController,
                homeScreenController
                homeScreenController,
                spriteViewerController
            )
        )
    }

M app/src/main/java/com/github/nacabaro/vbhelper/daos/AdventureDao.kt => app/src/main/java/com/github/nacabaro/vbhelper/daos/AdventureDao.kt +4 -3
@@ 23,14 23,15 @@ interface AdventureDao {
            uc.*,
            c.stage,
            c.attribute,
            c.sprite1 AS spriteIdle,
            c.spritesWidth AS spriteWidth,
            c.spritesHeight AS spriteHeight,
            s.spriteIdle1 AS spriteIdle,
            s.width AS spriteWidth,
            s.height AS spriteHeight,
            d.isBEm as isBemCard,
            a.finishesAdventure AS finishesAdventure,
            a.originalDuration AS originalTimeInMinutes
        FROM UserCharacter uc
        JOIN Character c ON uc.charId = c.id
        JOIN Sprite s ON s.id = c.spriteId
        JOIN Card d ON c.dimId = d.id
        JOIN Adventure a ON uc.id = a.characterId
    """)

M app/src/main/java/com/github/nacabaro/vbhelper/daos/CharacterDao.kt => app/src/main/java/com/github/nacabaro/vbhelper/daos/CharacterDao.kt +4 -4
@@ 4,7 4,7 @@ import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import com.github.nacabaro.vbhelper.domain.characters.Character
import com.github.nacabaro.vbhelper.domain.Sprites
import com.github.nacabaro.vbhelper.domain.characters.Sprite
import com.github.nacabaro.vbhelper.dtos.CharacterDtos

@Dao


@@ 22,10 22,10 @@ interface CharacterDao {
    fun getCharacterByMonIndex(monIndex: Int, dimId: Long): Character

    @Insert
    suspend fun insertSprite(vararg sprite: Sprites)
    suspend fun insertSprite(vararg sprite: Sprite)

    @Query("SELECT * FROM Sprites")
    suspend fun getAllSprites(): List<Sprites>
    @Query("SELECT * FROM Sprite")
    suspend fun getAllSprites(): List<Sprite>

    @Query(
        """

M app/src/main/java/com/github/nacabaro/vbhelper/daos/DexDao.kt => app/src/main/java/com/github/nacabaro/vbhelper/daos/DexDao.kt +5 -4
@@ 19,11 19,12 @@ interface DexDao {
    @Query("""
        SELECT 
            c.id AS id,
            c.sprite1 AS spriteIdle,
            c.spritesWidth AS spriteWidth,
            c.spritesHeight AS spriteHeight,
            s.spriteIdle1 AS spriteIdle,
            s.width AS spriteWidth,
            s.height AS spriteHeight,
            d.discoveredOn AS discoveredOn
        FROM character c
        FROM Character c
        JOIN Sprite s ON c.spriteId = s.id
        LEFT JOIN dex d ON c.id = d.id
        WHERE c.dimId = :cardId
    """)

A app/src/main/java/com/github/nacabaro/vbhelper/daos/SpriteDao.kt => app/src/main/java/com/github/nacabaro/vbhelper/daos/SpriteDao.kt +16 -0
@@ 0,0 1,16 @@
package com.github.nacabaro.vbhelper.daos

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.github.nacabaro.vbhelper.domain.characters.Sprite

@Dao
interface SpriteDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insertSprite(sprite: Sprite): Long

    @Query("SELECT * FROM Sprite")
    suspend fun getAllSprites(): List<Sprite>
}
\ No newline at end of file

M app/src/main/java/com/github/nacabaro/vbhelper/daos/UserCharacterDao.kt => app/src/main/java/com/github/nacabaro/vbhelper/daos/UserCharacterDao.kt +20 -13
@@ 31,13 31,14 @@ interface UserCharacterDao {
    @Query("""
        SELECT 
            c.id AS id,
            c.sprite1 AS spriteIdle,
            c.spritesWidth AS spriteWidth,
            c.spritesHeight AS spriteHeight,
            s.spriteIdle1 AS spriteIdle,
            s.width AS spriteWidth,
            s.height AS spriteHeight,
            c.monIndex AS monIndex, 
            t.transformationDate AS transformationDate
        FROM TransformationHistory t 
        JOIN Character c ON c.id = t.stageId
        JOIN Sprite s ON s.id = c.spriteId
        WHERE monId = :monId
    """)
    fun getTransformationHistory(monId: Long): List<CharacterDtos.TransformationHistory>?


@@ 48,9 49,10 @@ interface UserCharacterDao {
            uc.*,
            c.stage,
            c.attribute,
            c.sprite1 AS spriteIdle,
            c.spritesWidth AS spriteWidth,
            c.spritesHeight AS spriteHeight,
            s.spriteIdle1 AS spriteIdle,
            s.spriteIdle2 AS spriteIdle2,
            s.width AS spriteWidth,
            s.height AS spriteHeight,
            c.name as nameSprite,
            c.nameWidth as nameSpriteWidth,
            c.nameHeight as nameSpriteHeight,


@@ 58,7 60,8 @@ interface UserCharacterDao {
            a.characterId = uc.id as isInAdventure
        FROM UserCharacter uc
        JOIN Character c ON uc.charId = c.id
        JOIN Card d ON c.dimId = d.id
        JOIN Card d ON  d.id = c.dimId
        JOIN Sprite s ON s.id = c.spriteId
        LEFT JOIN Adventure a ON a.characterId = uc.id
        """
    )


@@ 70,9 73,10 @@ interface UserCharacterDao {
            uc.*,
            c.stage,
            c.attribute,
            c.sprite1 AS spriteIdle,
            c.spritesWidth AS spriteWidth,
            c.spritesHeight AS spriteHeight,
            s.spriteIdle1 AS spriteIdle,
            s.spriteIdle2 AS spriteIdle2,
            s.width AS spriteWidth,
            s.height AS spriteHeight,
            c.name as nameSprite,
            c.nameWidth as nameSpriteWidth,
            c.nameHeight as nameSpriteHeight,


@@ 81,6 85,7 @@ interface UserCharacterDao {
        FROM UserCharacter uc
        JOIN Character c ON uc.charId = c.id
        JOIN Card d ON c.dimId = d.id
        JOIN Sprite s ON s.id = c.spriteId
        LEFT JOIN Adventure a ON a.characterId = uc.id
        WHERE uc.id = :id
    """)


@@ 98,9 103,10 @@ interface UserCharacterDao {
            uc.*,
            c.stage,
            c.attribute,
            c.sprite1 AS spriteIdle,
            c.spritesWidth AS spriteWidth,
            c.spritesHeight AS spriteHeight,
            s.spriteIdle1 AS spriteIdle,
            s.spriteIdle2 AS spriteIdle2,
            s.width AS spriteWidth,
            s.height AS spriteHeight,
            c.name as nameSprite,
            c.nameWidth as nameSpriteWidth,
            c.nameHeight as nameSpriteHeight,


@@ 109,6 115,7 @@ interface UserCharacterDao {
        FROM UserCharacter uc
        JOIN Character c ON uc.charId = c.id
        JOIN Card d ON c.dimId = d.id
        JOIN Sprite s ON s.id = c.spriteId
        LEFT JOIN Adventure a ON a.characterId = uc.id
        WHERE uc.isActive = 1
        LIMIT 1

M app/src/main/java/com/github/nacabaro/vbhelper/database/AppDatabase.kt => app/src/main/java/com/github/nacabaro/vbhelper/database/AppDatabase.kt +4 -2
@@ 7,10 7,11 @@ import com.github.nacabaro.vbhelper.daos.CharacterDao
import com.github.nacabaro.vbhelper.daos.DexDao
import com.github.nacabaro.vbhelper.daos.DiMDao
import com.github.nacabaro.vbhelper.daos.ItemDao
import com.github.nacabaro.vbhelper.daos.SpriteDao
import com.github.nacabaro.vbhelper.daos.UserCharacterDao
import com.github.nacabaro.vbhelper.domain.characters.Character
import com.github.nacabaro.vbhelper.domain.characters.Card
import com.github.nacabaro.vbhelper.domain.Sprites
import com.github.nacabaro.vbhelper.domain.characters.Sprite
import com.github.nacabaro.vbhelper.domain.characters.Adventure
import com.github.nacabaro.vbhelper.domain.characters.Dex
import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData


@@ 23,7 24,7 @@ import com.github.nacabaro.vbhelper.domain.items.Items
    entities = [
        Card::class,
        Character::class,
        Sprites::class,
        Sprite::class,
        UserCharacter::class,
        BECharacterData::class,
        TransformationHistory::class,


@@ 39,4 40,5 @@ abstract class AppDatabase : RoomDatabase() {
    abstract fun dexDao(): DexDao
    abstract fun itemDao(): ItemDao
    abstract fun adventureDao(): AdventureDao
    abstract fun spriteDao(): SpriteDao
}
\ No newline at end of file

D app/src/main/java/com/github/nacabaro/vbhelper/domain/Sprites.kt => app/src/main/java/com/github/nacabaro/vbhelper/domain/Sprites.kt +0 -12
@@ 1,12 0,0 @@
package com.github.nacabaro.vbhelper.domain

import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity
data class Sprites(
    @PrimaryKey(autoGenerate = true) val id : Int,
    val sprite: ByteArray,
    val width: Int,
    val height: Int
)

M app/src/main/java/com/github/nacabaro/vbhelper/domain/characters/Character.kt => app/src/main/java/com/github/nacabaro/vbhelper/domain/characters/Character.kt +9 -5
@@ 12,9 12,16 @@ import com.github.cfogrady.vbnfc.data.NfcCharacter
            parentColumns = ["id"],
            childColumns = ["dimId"],
            onDelete = ForeignKey.CASCADE
        ),
        ForeignKey(
            entity = Sprite::class,
            parentColumns = ["id"],
            childColumns = ["spriteId"],
            onDelete = ForeignKey.CASCADE
        )
    ]
)

/*
 * Character represents a character on a DIM card. There should only be one of these per dimId
 * and monIndex.


@@ 23,6 30,7 @@ import com.github.cfogrady.vbnfc.data.NfcCharacter
data class Character (
    @PrimaryKey(autoGenerate = true) val id: Long = 0,
    val dimId: Long,
    val spriteId: Long,
    val monIndex: Int,
    val name: ByteArray,
    val stage: Int, // These should be replaced with enums


@@ 30,10 38,6 @@ data class Character (
    val baseHp: Int,
    val baseBp: Int,
    val baseAp: Int,
    val sprite1: ByteArray,
    val sprite2: ByteArray,
    val nameWidth: Int,
    val nameHeight: Int,
    val spritesWidth: Int,
    val spritesHeight: Int
    val nameHeight: Int
)

A app/src/main/java/com/github/nacabaro/vbhelper/domain/characters/Sprite.kt => app/src/main/java/com/github/nacabaro/vbhelper/domain/characters/Sprite.kt +23 -0
@@ 0,0 1,23 @@
package com.github.nacabaro.vbhelper.domain.characters

import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity
data class Sprite(
    @PrimaryKey(autoGenerate = true) val id : Int = 0,
    val spriteIdle1: ByteArray,
    val spriteIdle2: ByteArray,
    val spriteWalk1: ByteArray,
    val spriteWalk2: ByteArray,
    val spriteRun1: ByteArray,
    val spriteRun2: ByteArray,
    val spriteTrain1: ByteArray,
    val spriteTrain2: ByteArray,
    val spriteHappy: ByteArray,
    val spriteSleep: ByteArray,
    val spriteAttack: ByteArray,
    val spriteDodge: ByteArray,
    val width: Int,
    val height: Int
)

M app/src/main/java/com/github/nacabaro/vbhelper/dtos/CharacterDtos.kt => app/src/main/java/com/github/nacabaro/vbhelper/dtos/CharacterDtos.kt +1 -0
@@ 25,6 25,7 @@ object CharacterDtos {
        var heartRateCurrent: Int,
        var characterType: DeviceType,
        val spriteIdle: ByteArray,
        val spriteIdle2: ByteArray,
        val spriteWidth: Int,
        val spriteHeight: Int,
        val nameSprite: ByteArray,

M app/src/main/java/com/github/nacabaro/vbhelper/navigation/AppNavigation.kt => app/src/main/java/com/github/nacabaro/vbhelper/navigation/AppNavigation.kt +6 -3
@@ 15,7 15,7 @@ import com.github.nacabaro.vbhelper.screens.itemsScreen.ItemsScreen
import com.github.nacabaro.vbhelper.screens.scanScreen.ScanScreen
import com.github.nacabaro.vbhelper.screens.scanScreen.ScanScreenControllerImpl
import com.github.nacabaro.vbhelper.screens.settingsScreen.SettingsScreen
import com.github.nacabaro.vbhelper.screens.SpriteViewer
import com.github.nacabaro.vbhelper.screens.spriteViewer.SpriteViewer
import com.github.nacabaro.vbhelper.screens.homeScreens.HomeScreenControllerImpl
import com.github.nacabaro.vbhelper.screens.storageScreen.StorageScreen
import com.github.nacabaro.vbhelper.screens.itemsScreen.ChooseCharacterScreen


@@ 24,6 24,7 @@ import com.github.nacabaro.vbhelper.screens.settingsScreen.SettingsScreenControl
import com.github.nacabaro.vbhelper.screens.adventureScreen.AdventureScreen
import com.github.nacabaro.vbhelper.screens.adventureScreen.AdventureScreenControllerImpl
import com.github.nacabaro.vbhelper.screens.settingsScreen.CreditsScreen
import com.github.nacabaro.vbhelper.screens.spriteViewer.SpriteViewerControllerImpl
import com.github.nacabaro.vbhelper.screens.storageScreen.StorageScreenControllerImpl

data class AppNavigationHandlers(


@@ 32,7 33,8 @@ data class AppNavigationHandlers(
    val itemsScreenController: ItemsScreenControllerImpl,
    val adventureScreenController: AdventureScreenControllerImpl,
    val storageScreenController: StorageScreenControllerImpl,
    val homeScreenController: HomeScreenControllerImpl
    val homeScreenController: HomeScreenControllerImpl,
    val spriteViewerController: SpriteViewerControllerImpl
)

@Composable


@@ 91,7 93,8 @@ fun AppNavigation(
            }
            composable(NavigationItems.Viewer.route) {
                SpriteViewer(
                    navController = navController
                    navController = navController,
                    spriteViewerController = applicationNavigationHandlers.spriteViewerController
                )
            }
            composable(NavigationItems.CardView.route) {

M app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreenControllerImpl.kt => app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreenControllerImpl.kt +48 -19
@@ 10,11 10,12 @@ import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import com.github.cfogrady.vb.dim.card.BemCard
import com.github.cfogrady.vb.dim.card.DimCard
import com.github.cfogrady.vb.dim.card.DimReader
import com.github.cfogrady.vbnfc.data.NfcCharacter
import com.github.nacabaro.vbhelper.database.AppDatabase
import com.github.nacabaro.vbhelper.di.VBHelper
import com.github.nacabaro.vbhelper.domain.Sprites
import com.github.nacabaro.vbhelper.domain.characters.Sprite
import com.github.nacabaro.vbhelper.domain.characters.Card
import com.github.nacabaro.vbhelper.domain.characters.Character
import com.github.nacabaro.vbhelper.source.ApkSecretsImporter


@@ 139,9 140,53 @@ class SettingsScreenControllerImpl(
                val domainCharacters = mutableListOf<Character>()

                for (index in 0 until characters.size) {
                    var domainSprite: Sprite? = null;

                    if (index < 2 && card is DimCard) {
                        domainSprite = Sprite(
                            width = card.spriteData.sprites[spriteCounter + 1].spriteDimensions.width,
                            height = card.spriteData.sprites[spriteCounter + 1].spriteDimensions.height,
                            spriteIdle1 = card.spriteData.sprites[spriteCounter + 1].pixelData,
                            spriteIdle2 = card.spriteData.sprites[spriteCounter + 2].pixelData,
                            spriteWalk1 = card.spriteData.sprites[spriteCounter + 1].pixelData,
                            spriteWalk2 = card.spriteData.sprites[spriteCounter + 3].pixelData,
                            spriteRun1 = card.spriteData.sprites[spriteCounter + 1].pixelData,
                            spriteRun2 = card.spriteData.sprites[spriteCounter + 3].pixelData,
                            spriteTrain1 = card.spriteData.sprites[spriteCounter + 1].pixelData,
                            spriteTrain2 = card.spriteData.sprites[spriteCounter + 3].pixelData,
                            spriteHappy = card.spriteData.sprites[spriteCounter + 4].pixelData,
                            spriteSleep = card.spriteData.sprites[spriteCounter + 5].pixelData,
                            spriteAttack = card.spriteData.sprites[spriteCounter + 2].pixelData,
                            spriteDodge = card.spriteData.sprites[spriteCounter + 3].pixelData
                        )
                    } else {
                        domainSprite = Sprite(
                            width = card.spriteData.sprites[spriteCounter + 1].spriteDimensions.width,
                            height = card.spriteData.sprites[spriteCounter + 1].spriteDimensions.height,
                            spriteIdle1 = card.spriteData.sprites[spriteCounter + 1].pixelData,
                            spriteIdle2 = card.spriteData.sprites[spriteCounter + 2].pixelData,
                            spriteWalk1 = card.spriteData.sprites[spriteCounter + 3].pixelData,
                            spriteWalk2 = card.spriteData.sprites[spriteCounter + 4].pixelData,
                            spriteRun1 = card.spriteData.sprites[spriteCounter + 5].pixelData,
                            spriteRun2 = card.spriteData.sprites[spriteCounter + 6].pixelData,
                            spriteTrain1 = card.spriteData.sprites[spriteCounter + 7].pixelData,
                            spriteTrain2 = card.spriteData.sprites[spriteCounter + 8].pixelData,
                            spriteHappy = card.spriteData.sprites[spriteCounter + 9].pixelData,
                            spriteSleep = card.spriteData.sprites[spriteCounter + 10].pixelData,
                            spriteAttack = card.spriteData.sprites[spriteCounter + 11].pixelData,
                            spriteDodge = card.spriteData.sprites[spriteCounter + 12].pixelData
                        )
                    }


                    val spriteId = database
                        .spriteDao()
                        .insertSprite(domainSprite)

                    domainCharacters.add(
                        Character(
                            dimId = dimId,
                            spriteId = spriteId,
                            monIndex = index,
                            name = card.spriteData.sprites[spriteCounter].pixelData,
                            stage = characters[index].stage,


@@ 149,12 194,8 @@ class SettingsScreenControllerImpl(
                            baseHp = characters[index].hp,
                            baseBp = characters[index].dp,
                            baseAp = characters[index].ap,
                            sprite1 = card.spriteData.sprites[spriteCounter + 1].pixelData,
                            sprite2 = card.spriteData.sprites[spriteCounter + 2].pixelData,
                            nameWidth = card.spriteData.sprites[spriteCounter].width,
                            nameHeight = card.spriteData.sprites[spriteCounter].height,
                            spritesWidth = card.spriteData.sprites[spriteCounter + 1].width,
                            spritesHeight = card.spriteData.sprites[spriteCounter + 1].height
                            nameWidth = card.spriteData.sprites[spriteCounter].spriteDimensions.width,
                            nameHeight = card.spriteData.sprites[spriteCounter].spriteDimensions.height,
                        )
                    )



@@ 172,18 213,6 @@ class SettingsScreenControllerImpl(
                database
                    .characterDao()
                    .insertCharacter(*domainCharacters.toTypedArray())

                val sprites = card.spriteData.sprites.map { sprite ->
                    Sprites(
                        id = 0,
                        sprite = sprite.pixelData,
                        width = sprite.width,
                        height = sprite.height
                    )
                }
                database
                    .characterDao()
                    .insertSprite(*sprites.toTypedArray())
            }

            inputStream?.close()

R app/src/main/java/com/github/nacabaro/vbhelper/screens/SpriteViewer.kt => app/src/main/java/com/github/nacabaro/vbhelper/screens/spriteViewer/SpriteViewer.kt +9 -32
@@ 1,55 1,38 @@
package com.github.nacabaro.vbhelper.screens
package com.github.nacabaro.vbhelper.screens.spriteViewer

import android.graphics.Bitmap
import android.util.Log
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.github.nacabaro.vbhelper.components.TopBanner
import com.github.nacabaro.vbhelper.di.VBHelper
import com.github.nacabaro.vbhelper.domain.Sprites
import com.github.nacabaro.vbhelper.source.SpriteRepo
import kotlinx.coroutines.launch
import java.nio.ByteBuffer

@Composable
fun SpriteViewer(
    navController: NavController
    navController: NavController,
    spriteViewerController: SpriteViewerController
) {
    val coroutineScope = rememberCoroutineScope()
    val application = LocalContext.current.applicationContext as VBHelper
    val db = application.container.db
    val spriteRepo = SpriteRepo(db)

    val spriteList = remember { mutableStateListOf<Sprites>() }
    val spriteList = remember { mutableStateListOf<Bitmap>() }

    Log.d("SpriteViewer", "spriteList: $spriteList")

    LaunchedEffect(spriteRepo) {
        coroutineScope.launch {
            spriteList.clear()
            spriteList.addAll(spriteRepo.getAllSprites())
        }
    LaunchedEffect(spriteViewerController) {
        val sprites = spriteViewerController.getAllSprites()
        val bitmapData = spriteViewerController.convertToBitmap(sprites)
        spriteList.addAll(bitmapData)
    }

    Scaffold (


@@ 69,13 52,7 @@ fun SpriteViewer(
                .padding(top = contentPadding.calculateTopPadding())
        ) {
            items(spriteList) { sprite ->
                val bitmap = remember (sprite.sprite) {
                    Log.d("SpriteViewer", "sprite: $sprite")
                    Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
                        copyPixelsFromBuffer(ByteBuffer.wrap(sprite.sprite))
                    }
                }
                val imageBitmap = remember(bitmap) { bitmap.asImageBitmap() }
                val imageBitmap = remember(sprite) { sprite.asImageBitmap() }
                Image(
                    bitmap = imageBitmap,
                    contentDescription = "Sprite",

A app/src/main/java/com/github/nacabaro/vbhelper/screens/spriteViewer/SpriteViewerController.kt => app/src/main/java/com/github/nacabaro/vbhelper/screens/spriteViewer/SpriteViewerController.kt +9 -0
@@ 0,0 1,9 @@
package com.github.nacabaro.vbhelper.screens.spriteViewer

import android.graphics.Bitmap
import com.github.nacabaro.vbhelper.domain.characters.Sprite

interface SpriteViewerController {
    suspend fun getAllSprites(): List<Sprite>
    fun convertToBitmap(sprites: List<Sprite>): List<Bitmap>
}
\ No newline at end of file

A app/src/main/java/com/github/nacabaro/vbhelper/screens/spriteViewer/SpriteViewerControllerImpl.kt => app/src/main/java/com/github/nacabaro/vbhelper/screens/spriteViewer/SpriteViewerControllerImpl.kt +68 -0
@@ 0,0 1,68 @@
package com.github.nacabaro.vbhelper.screens.spriteViewer

import android.graphics.Bitmap
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.asImageBitmap
import com.github.nacabaro.vbhelper.di.VBHelper
import com.github.nacabaro.vbhelper.domain.characters.Sprite
import java.nio.ByteBuffer

class SpriteViewerControllerImpl(
    private val context: ComponentActivity
) : SpriteViewerController {
    override suspend fun getAllSprites(): List<Sprite> {
        val applicationContext = context.applicationContext as VBHelper
        val db = applicationContext.container.db
        val sprites = db.spriteDao().getAllSprites()
        return sprites
    }

    // I don't like this, chief
    override fun convertToBitmap(sprites: List<Sprite>): List<Bitmap> {
        val bitmapList = mutableListOf<Bitmap>()

        for (sprite in sprites) {
            Log.d("SpriteViewer", "sprite: $sprite")
            bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
                copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteIdle1))
            })
            bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
                copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteIdle2))
            })
            bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
                copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteWalk1))
            })
            bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
                copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteWalk2))
            })
            bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
                copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteRun1))
            })
            bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
                copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteRun2))
            })
            bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
                copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteTrain1))
            })
            bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
                copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteTrain2))
            })
            bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
                copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteHappy))
            })
            bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
                copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteSleep))
            })
            bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
                copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteAttack))
            })
            bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
                copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteDodge))
            })
        }

        return bitmapList
    }
}
\ No newline at end of file

D app/src/main/java/com/github/nacabaro/vbhelper/source/SpriteRepo.kt => app/src/main/java/com/github/nacabaro/vbhelper/source/SpriteRepo.kt +0 -12
@@ 1,12 0,0 @@
package com.github.nacabaro.vbhelper.source

import com.github.nacabaro.vbhelper.database.AppDatabase
import com.github.nacabaro.vbhelper.domain.Sprites

class SpriteRepo (
    private val db: AppDatabase
) {
    suspend fun getAllSprites(): List<Sprites> {
        return db.characterDao().getAllSprites()
    }
}