mirror of
https://github.com/nacabaro/vbhelper.git
synced 2026-01-27 16:05:32 +00:00
More things!
- Started slowly implementing the original model. - Names are bitmaps, so we use that. - Sprites are stored in RoomDB as bitmap. - Can now import DiMs, need to implement BEms. - Can also view all the sprites for all the DiMs and now you can view DiMs individually (these two are temporary). Things to do next - Use the new model when uploading characters from the watch. - Figure out why my implementation of ABGR to BGRA isn't working (or something like that) - Improve data retrieval from the database, maybe using flows and properly implemented view models. As of now the interface is quite flickery. - Improve code that handles DiMs and BEms. As for bugs - Interface sometimes likes flickering a lot, need to figure out why - I cannot for the life of me create transparent bitmaps... help! - Something else I might be forgetting... Going to continue working in this branch.
This commit is contained in:
parent
82292823d3
commit
19fbed0ef2
@ -10,25 +10,31 @@ import android.widget.Toast
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.github.cfogrady.vb.dim.card.DimReader
|
||||
import com.github.nacabaro.vbhelper.navigation.AppNavigation
|
||||
import com.github.cfogrady.vbnfc.CryptographicTransformer
|
||||
import com.github.cfogrady.vbnfc.R
|
||||
import com.github.cfogrady.vbnfc.TagCommunicator
|
||||
import com.github.cfogrady.vbnfc.be.BENfcCharacter
|
||||
import com.github.cfogrady.vbnfc.data.DeviceType
|
||||
import com.github.cfogrady.vbnfc.data.NfcCharacter
|
||||
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||
import com.github.nacabaro.vbhelper.domain.Dim
|
||||
import com.github.nacabaro.vbhelper.domain.Sprites
|
||||
import com.github.nacabaro.vbhelper.domain.Character
|
||||
import com.github.nacabaro.vbhelper.temporary_domain.TemporaryBECharacterData
|
||||
import com.github.nacabaro.vbhelper.temporary_domain.TemporaryCharacterData
|
||||
import com.github.nacabaro.vbhelper.temporary_domain.TemporaryTransformationHistory
|
||||
import com.github.nacabaro.vbhelper.ui.theme.VBHelperTheme
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
private lateinit var nfcAdapter: NfcAdapter
|
||||
@ -36,10 +42,14 @@ class MainActivity : ComponentActivity() {
|
||||
|
||||
private var nfcCharacter = MutableStateFlow<NfcCharacter?>(null)
|
||||
|
||||
private lateinit var activityResultLauncher: ActivityResultLauncher<Intent>
|
||||
|
||||
// EXTRACTED DIRECTLY FROM EXAMPLE APP
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
deviceToCryptographicTransformers = getMapOfCryptographicTransformers()
|
||||
|
||||
registerFileActivityResult()
|
||||
|
||||
val maybeNfcAdapter = NfcAdapter.getDefaultAdapter(this)
|
||||
if (maybeNfcAdapter == null) {
|
||||
Toast.makeText(this, "No NFC on device!", Toast.LENGTH_SHORT).show()
|
||||
@ -57,11 +67,109 @@ class MainActivity : ComponentActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun registerFileActivityResult() {
|
||||
activityResultLauncher = registerForActivityResult(
|
||||
ActivityResultContracts.StartActivityForResult()
|
||||
) {
|
||||
lifecycleScope.launch {
|
||||
if (it.resultCode != RESULT_OK) {
|
||||
Toast.makeText(applicationContext, "Import operation cancelled.", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
val contentResolver = applicationContext.contentResolver
|
||||
val inputStream = contentResolver.openInputStream(it.data!!.data!!)
|
||||
inputStream.use { fileReader ->
|
||||
val dimReader = DimReader()
|
||||
val card = dimReader.readCard(fileReader, false)
|
||||
val dimModel = Dim(
|
||||
id = card.header.dimId,
|
||||
logo = card.spriteData.sprites[0].pixelData,
|
||||
name = card.spriteData.text, // TODO Make user write card name
|
||||
stageCount = card.adventureLevels.levels.size,
|
||||
logoHeight = card.spriteData.sprites[0].height,
|
||||
logoWidth = card.spriteData.sprites[0].width
|
||||
)
|
||||
val application = applicationContext as VBHelper
|
||||
val storageRepository = application.container.db
|
||||
storageRepository.dimDao().insertNewDim(dimModel)
|
||||
|
||||
val characters = card.characterStats.characterEntries
|
||||
|
||||
/*
|
||||
Confusing math for me ahead
|
||||
sprite[0] logo
|
||||
sprite[10] name
|
||||
sprite[10 + 1] character_1
|
||||
sprite[10 + 2] character_2
|
||||
sprite[16] name 1
|
||||
sprite[17] character_1
|
||||
sprite[18] character_2
|
||||
sprite[23] name 2
|
||||
sprite[24] character_1
|
||||
sprite[25] character_2
|
||||
sprite[23 + 12 + 1] name 3
|
||||
sprite[23 + 12 + 2] character_1
|
||||
sprite[23 + 12 + 3] character_2
|
||||
*/
|
||||
|
||||
var spriteCounter = 10
|
||||
var domainCharacters = mutableListOf<Character>()
|
||||
|
||||
for (index in 0 until characters.size) {
|
||||
domainCharacters.add(
|
||||
Character(
|
||||
id = 0,
|
||||
dimId = card.header.dimId,
|
||||
monIndex = index,
|
||||
name = card.spriteData.sprites[spriteCounter].pixelData,
|
||||
stage = characters[index].stage,
|
||||
attribute = characters[index].attribute,
|
||||
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
|
||||
)
|
||||
)
|
||||
|
||||
if (index == 0) {
|
||||
spriteCounter += 6
|
||||
} else if (index == 1) {
|
||||
spriteCounter += 7
|
||||
} else {
|
||||
spriteCounter += 14
|
||||
}
|
||||
}
|
||||
|
||||
storageRepository
|
||||
.characterDao()
|
||||
.insertCharacter(*domainCharacters.toTypedArray())
|
||||
|
||||
val sprites = card.spriteData.sprites.map { sprite ->
|
||||
Sprites(
|
||||
id = 0,
|
||||
sprite = sprite.pixelData,
|
||||
width = sprite.width,
|
||||
height = sprite.height
|
||||
)
|
||||
}
|
||||
storageRepository
|
||||
.characterDao()
|
||||
.insertSprite(*sprites.toTypedArray())
|
||||
}
|
||||
inputStream?.close()
|
||||
Toast.makeText(applicationContext, "Import successful!", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MainApplication() {
|
||||
var isDoneReadingCharacter by remember { mutableStateOf(false) }
|
||||
val application = LocalContext.current.applicationContext as VBHelper
|
||||
val storageRepository = application.container.db
|
||||
|
||||
AppNavigation(
|
||||
isDoneReadingCharacter = isDoneReadingCharacter,
|
||||
onClickRead = {
|
||||
@ -75,6 +183,13 @@ class MainActivity : ComponentActivity() {
|
||||
},
|
||||
onClickScan = {
|
||||
isDoneReadingCharacter = false
|
||||
},
|
||||
onClickImportCard = {
|
||||
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
type = "*/*"
|
||||
}
|
||||
activityResultLauncher.launch(intent)
|
||||
}
|
||||
)
|
||||
}
|
||||
@ -160,6 +275,7 @@ class MainActivity : ComponentActivity() {
|
||||
*/
|
||||
private fun addCharacterScannedIntoDatabase() {
|
||||
val beCharacter = nfcCharacter as MutableStateFlow<BENfcCharacter?>
|
||||
|
||||
val temporaryCharacterData = TemporaryCharacterData(
|
||||
dimId = nfcCharacter.value!!.dimId.toInt(),
|
||||
charIndex = nfcCharacter.value!!.charIndex.toInt(),
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
package com.github.nacabaro.vbhelper.components
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.ImageBitmap
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun CharacterEntry(
|
||||
name: ImageBitmap,
|
||||
icon: ImageBitmap,
|
||||
modifier: Modifier = Modifier,
|
||||
onClick: () -> Unit = { }
|
||||
) {
|
||||
Card(
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
onClick = onClick,
|
||||
modifier = modifier
|
||||
.padding(8.dp)
|
||||
) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
) {
|
||||
Image(
|
||||
bitmap = icon,
|
||||
contentDescription = "Icon",
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.size(64.dp)
|
||||
)
|
||||
Image(
|
||||
bitmap = name,
|
||||
contentDescription = "Name",
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
package com.github.nacabaro.vbhelper.components
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.ImageBitmap
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun StorageEntry(
|
||||
name: String,
|
||||
nameBitmap: ImageBitmap? = null,
|
||||
modifier: Modifier = Modifier,
|
||||
icon: Int? = null,
|
||||
bitmap: ImageBitmap? = null,
|
||||
onClick: () -> Unit = { }
|
||||
) {
|
||||
Card(
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
onClick = onClick,
|
||||
modifier = modifier
|
||||
.padding(8.dp)
|
||||
) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
) {
|
||||
if (bitmap != null) {
|
||||
Image(
|
||||
bitmap = bitmap,
|
||||
contentDescription = name,
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.size(64.dp)
|
||||
)
|
||||
} else if (icon != null) {
|
||||
Image(
|
||||
painter = painterResource(id = icon),
|
||||
contentDescription = name,
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.size(64.dp)
|
||||
)
|
||||
}
|
||||
Text(
|
||||
text = name,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -20,7 +20,7 @@ fun TopBanner(
|
||||
text: String,
|
||||
modifier: Modifier = Modifier,
|
||||
onGearClick: (() -> Unit)? = null,
|
||||
onBackClick: (() -> Unit)? = null
|
||||
onBackClick: (() -> Unit)? = null,
|
||||
) {
|
||||
Box( // Use Box to overlay elements
|
||||
modifier = modifier
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
package com.github.nacabaro.vbhelper.daos
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.Query
|
||||
import com.github.nacabaro.vbhelper.domain.Character
|
||||
import com.github.nacabaro.vbhelper.domain.Sprites
|
||||
import org.w3c.dom.CharacterData
|
||||
|
||||
@Dao
|
||||
interface CharacterDao {
|
||||
@Insert
|
||||
suspend fun insertCharacter(vararg characterData: Character)
|
||||
|
||||
@Query("SELECT * FROM Character")
|
||||
suspend fun getAllCharacters(): List<Character>
|
||||
|
||||
@Query("SELECT * FROM Character WHERE dimId = :dimId")
|
||||
suspend fun getCharacterByDimId(dimId: Int): List<Character>
|
||||
|
||||
@Insert
|
||||
suspend fun insertSprite(vararg sprite: Sprites)
|
||||
|
||||
@Query("SELECT * FROM Sprites")
|
||||
suspend fun getAllSprites(): List<Sprites>
|
||||
}
|
||||
@ -2,15 +2,15 @@ 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.Dim
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface DiMDao {
|
||||
@Insert
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
suspend fun insertNewDim(dim: Dim)
|
||||
|
||||
@Query("SELECT * FROM Dim")
|
||||
fun getAllDims(): Flow<List<Dim>>
|
||||
suspend fun getAllDims(): List<Dim>
|
||||
}
|
||||
@ -2,6 +2,11 @@ package com.github.nacabaro.vbhelper.database
|
||||
|
||||
import androidx.room.Database
|
||||
import androidx.room.RoomDatabase
|
||||
import com.github.nacabaro.vbhelper.daos.CharacterDao
|
||||
import com.github.nacabaro.vbhelper.daos.DiMDao
|
||||
import com.github.nacabaro.vbhelper.domain.Character
|
||||
import com.github.nacabaro.vbhelper.domain.Dim
|
||||
import com.github.nacabaro.vbhelper.domain.Sprites
|
||||
import com.github.nacabaro.vbhelper.temporary_daos.TemporaryMonsterDao
|
||||
import com.github.nacabaro.vbhelper.temporary_domain.TemporaryBECharacterData
|
||||
import com.github.nacabaro.vbhelper.temporary_domain.TemporaryCharacterData
|
||||
@ -12,10 +17,14 @@ import com.github.nacabaro.vbhelper.temporary_domain.TemporaryTransformationHist
|
||||
entities = [
|
||||
TemporaryCharacterData::class,
|
||||
TemporaryBECharacterData::class,
|
||||
TemporaryTransformationHistory::class
|
||||
TemporaryTransformationHistory::class,
|
||||
Dim::class,
|
||||
Character::class,
|
||||
Sprites::class
|
||||
]
|
||||
)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun temporaryMonsterDao(): TemporaryMonsterDao
|
||||
|
||||
abstract fun dimDao(): DiMDao
|
||||
abstract fun characterDao(): CharacterDao
|
||||
}
|
||||
@ -14,15 +14,20 @@ import androidx.room.ForeignKey
|
||||
)
|
||||
]
|
||||
)
|
||||
data class Mon (
|
||||
@PrimaryKey val id: Int,
|
||||
data class Character (
|
||||
@PrimaryKey(autoGenerate = true) val id: Long,
|
||||
val dimId: Int,
|
||||
val monIndex: Int,
|
||||
val name: String,
|
||||
val name: ByteArray,
|
||||
val stage: Int, // These should be replaced with enums
|
||||
val attribute: Int, // This one too
|
||||
val baseHp: Int,
|
||||
val baseBp: Int,
|
||||
val baseAp: Int,
|
||||
val evoTime: Int, // In minutes
|
||||
val sprite1: ByteArray,
|
||||
val sprite2: ByteArray,
|
||||
val nameWidth: Int,
|
||||
val nameHeight: Int,
|
||||
val spritesWidth: Int,
|
||||
val spritesHeight: Int
|
||||
)
|
||||
@ -1,5 +1,6 @@
|
||||
package com.github.nacabaro.vbhelper.domain
|
||||
|
||||
import android.icu.text.ListFormatter.Width
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@ -7,6 +8,9 @@ import androidx.room.PrimaryKey
|
||||
data class Dim(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
val id: Int,
|
||||
val logo: ByteArray,
|
||||
val logoWidth: Int,
|
||||
val logoHeight: Int,
|
||||
val name: String,
|
||||
val stageCount: Int
|
||||
)
|
||||
|
||||
@ -7,13 +7,13 @@ import androidx.room.PrimaryKey
|
||||
@Entity(
|
||||
foreignKeys = [
|
||||
ForeignKey(
|
||||
entity = Mon::class,
|
||||
entity = Character::class,
|
||||
parentColumns = ["id"],
|
||||
childColumns = ["monId"],
|
||||
onDelete = ForeignKey.CASCADE
|
||||
),
|
||||
ForeignKey(
|
||||
entity = Mon::class,
|
||||
entity = Character::class,
|
||||
parentColumns = ["id"],
|
||||
childColumns = ["nextMon"],
|
||||
onDelete = ForeignKey.CASCADE
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
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
|
||||
)
|
||||
@ -13,7 +13,7 @@ import androidx.room.PrimaryKey
|
||||
onDelete = ForeignKey.CASCADE
|
||||
),
|
||||
ForeignKey(
|
||||
entity = Mon::class,
|
||||
entity = Character::class,
|
||||
parentColumns = ["id"],
|
||||
childColumns = ["monId"],
|
||||
onDelete = ForeignKey.CASCADE
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.github.nacabaro.vbhelper.navigation
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.runtime.Composable
|
||||
@ -9,15 +10,18 @@ import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.github.nacabaro.vbhelper.screens.BattlesScreen
|
||||
import com.github.nacabaro.vbhelper.screens.DexScreen
|
||||
import com.github.nacabaro.vbhelper.screens.DiMScreen
|
||||
import com.github.nacabaro.vbhelper.screens.HomeScreen
|
||||
import com.github.nacabaro.vbhelper.screens.ScanScreen
|
||||
import com.github.nacabaro.vbhelper.screens.SettingsScreen
|
||||
import com.github.nacabaro.vbhelper.screens.SpriteViewer
|
||||
import com.github.nacabaro.vbhelper.screens.StorageScreen
|
||||
|
||||
@Composable
|
||||
fun AppNavigation(
|
||||
onClickRead: () -> Unit,
|
||||
onClickScan: () -> Unit,
|
||||
onClickImportCard: () -> Unit,
|
||||
isDoneReadingCharacter: Boolean
|
||||
) {
|
||||
val navController = rememberNavController()
|
||||
@ -53,13 +57,31 @@ fun AppNavigation(
|
||||
)
|
||||
}
|
||||
composable(BottomNavItem.Dex.route) {
|
||||
DexScreen()
|
||||
DexScreen(
|
||||
navController = navController
|
||||
)
|
||||
}
|
||||
composable(BottomNavItem.Settings.route) {
|
||||
SettingsScreen(
|
||||
navController = navController,
|
||||
onClickImportCard = onClickImportCard
|
||||
)
|
||||
}
|
||||
composable(BottomNavItem.Viewer.route) {
|
||||
SpriteViewer(
|
||||
navController = navController
|
||||
)
|
||||
}
|
||||
composable(BottomNavItem.CardView.route) {
|
||||
val dimId = it.arguments?.getString("dimId")
|
||||
Log.d("dimId", dimId.toString())
|
||||
if (dimId != null) {
|
||||
DiMScreen(
|
||||
navController = navController,
|
||||
dimId = dimId.toInt()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,4 +13,6 @@ sealed class BottomNavItem (
|
||||
object Dex : BottomNavItem("Dex", R.drawable.baseline_menu_book_24, "Dex")
|
||||
object Storage : BottomNavItem("Storage", R.drawable.baseline_catching_pokemon_24, "Storage")
|
||||
object Settings : BottomNavItem("Settings", R.drawable.baseline_settings_24, "Settings")
|
||||
object Viewer : BottomNavItem("Viewer", R.drawable.baseline_image_24, "Viewer")
|
||||
object CardView : BottomNavItem("Card/{dimId}", R.drawable.baseline_image_24, "Card")
|
||||
}
|
||||
@ -1,5 +1,7 @@
|
||||
package com.github.nacabaro.vbhelper.screens
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
@ -7,38 +9,88 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
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.material3.Card
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
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.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.ImageBitmap
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavController
|
||||
import com.github.nacabaro.vbhelper.R
|
||||
import com.github.nacabaro.vbhelper.components.TopBanner
|
||||
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||
import com.github.nacabaro.vbhelper.domain.Dim
|
||||
import com.github.nacabaro.vbhelper.navigation.BottomNavItem
|
||||
import com.github.nacabaro.vbhelper.source.DexRepository
|
||||
import kotlinx.coroutines.launch
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
@Composable
|
||||
fun DexScreen() {
|
||||
fun DexScreen(
|
||||
navController: NavController
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val application = LocalContext.current.applicationContext as VBHelper
|
||||
val dexRepository = DexRepository(application.container.db)
|
||||
|
||||
val dimList = remember { mutableStateListOf<Dim>() }
|
||||
|
||||
LaunchedEffect(dexRepository) {
|
||||
coroutineScope.launch {
|
||||
dimList.clear()
|
||||
dimList.addAll(dexRepository.getAllDims())
|
||||
}
|
||||
}
|
||||
|
||||
Scaffold (
|
||||
topBar = { TopBanner("Discovered Digimon") }
|
||||
topBar = {
|
||||
TopBanner(
|
||||
text = "Discovered Digimon",
|
||||
onGearClick = {
|
||||
navController.navigate(BottomNavItem.Viewer.route)
|
||||
}
|
||||
)
|
||||
}
|
||||
) { contentPadding ->
|
||||
LazyColumn (
|
||||
modifier = Modifier
|
||||
.padding(top = contentPadding.calculateTopPadding())
|
||||
) {
|
||||
items(100) { i ->
|
||||
items(dimList) {
|
||||
val bitmap = remember (it.logo) {
|
||||
Bitmap.createBitmap(it.logoWidth, it.logoHeight, Bitmap.Config.RGB_565).apply {
|
||||
copyPixelsFromBuffer(ByteBuffer.wrap(it.logo))
|
||||
}
|
||||
}
|
||||
val imageBitmap = remember(bitmap) { bitmap.asImageBitmap() }
|
||||
|
||||
Log.d("DexScreen", "dimList: ${it.id}")
|
||||
|
||||
DexDiMEntry(
|
||||
name = "Digimon $i",
|
||||
icon = R.drawable.baseline_egg_24,
|
||||
onClick = {},
|
||||
name = it.name,
|
||||
logo = imageBitmap,
|
||||
onClick = {
|
||||
navController
|
||||
.navigate(
|
||||
BottomNavItem
|
||||
.CardView.route
|
||||
.replace("{dimId}", "${it.id}")
|
||||
)
|
||||
},
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
vertical = 8.dp,
|
||||
horizontal = 16.dp
|
||||
)
|
||||
.padding(8.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -48,7 +100,7 @@ fun DexScreen() {
|
||||
@Composable
|
||||
fun DexDiMEntry(
|
||||
name: String,
|
||||
icon: Int,
|
||||
logo: ImageBitmap,
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
@ -64,7 +116,7 @@ fun DexDiMEntry(
|
||||
.padding(8.dp)
|
||||
) {
|
||||
Image (
|
||||
painter = painterResource(id = icon),
|
||||
bitmap = logo,
|
||||
contentDescription = name,
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
|
||||
@ -0,0 +1,82 @@
|
||||
package com.github.nacabaro.vbhelper.screens
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||
import androidx.compose.foundation.lazy.grid.items
|
||||
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.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.navigation.NavController
|
||||
import com.github.nacabaro.vbhelper.components.CharacterEntry
|
||||
import com.github.nacabaro.vbhelper.components.StorageEntry
|
||||
import com.github.nacabaro.vbhelper.components.TopBanner
|
||||
import com.github.nacabaro.vbhelper.domain.Character
|
||||
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||
import com.github.nacabaro.vbhelper.navigation.BottomNavItem
|
||||
import com.github.nacabaro.vbhelper.source.DexRepository
|
||||
import kotlinx.coroutines.launch
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
@Composable
|
||||
fun DiMScreen(
|
||||
navController: NavController,
|
||||
dimId: Int
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val application = LocalContext.current.applicationContext as VBHelper
|
||||
val dexRepository = DexRepository(application.container.db)
|
||||
|
||||
val characterList = remember { mutableStateListOf<Character>() }
|
||||
|
||||
Log.d("dimId", dimId.toString())
|
||||
|
||||
LaunchedEffect(dexRepository) {
|
||||
coroutineScope.launch {
|
||||
characterList.clear()
|
||||
characterList.addAll(dexRepository.getCharactersByDimId(dimId))
|
||||
}
|
||||
}
|
||||
|
||||
Scaffold (
|
||||
topBar = {
|
||||
TopBanner(
|
||||
text = "Discovered Digimon",
|
||||
onBackClick = {
|
||||
navController.popBackStack()
|
||||
}
|
||||
)
|
||||
}
|
||||
) { contentPadding ->
|
||||
LazyVerticalGrid(
|
||||
columns = GridCells.Fixed(3),
|
||||
contentPadding = contentPadding
|
||||
) {
|
||||
items(characterList) { character ->
|
||||
val bitmapName = remember (character.name) {
|
||||
Bitmap.createBitmap(character.nameWidth, character.nameHeight, Bitmap.Config.RGB_565).apply {
|
||||
copyPixelsFromBuffer(ByteBuffer.wrap(character.name))
|
||||
}
|
||||
}
|
||||
val bitmapCharacter = remember (character.sprite1) {
|
||||
Bitmap.createBitmap(character.spritesWidth, character.spritesHeight, Bitmap.Config.RGB_565).apply {
|
||||
copyPixelsFromBuffer(ByteBuffer.wrap(character.sprite1))
|
||||
}
|
||||
}
|
||||
val imageBitmapName = remember(bitmapName) { bitmapName.asImageBitmap() }
|
||||
val imageBitmapCharacter = remember(bitmapCharacter) { bitmapCharacter.asImageBitmap() }
|
||||
CharacterEntry(
|
||||
name = imageBitmapName,
|
||||
icon = imageBitmapCharacter,
|
||||
onClick = { }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -29,7 +29,8 @@ import java.io.FileInputStream
|
||||
@Composable
|
||||
fun SettingsScreen(
|
||||
navController: NavController,
|
||||
dimReader: DimReader = DimReader()
|
||||
//dimReader: DimReader = DimReader(),
|
||||
onClickImportCard: () -> Unit
|
||||
) {
|
||||
Scaffold (
|
||||
topBar = {
|
||||
@ -56,7 +57,8 @@ fun SettingsScreen(
|
||||
SettingsEntry(title = "Import transform functions", description = "Import standard vital bracelet keys") { }
|
||||
SettingsEntry(title = "Import decryption key", description = "Import standard vital bracelet keys") { }
|
||||
SettingsSection("DiM/BEm management")
|
||||
SettingsEntry(title = "Import DiM card", description = "Import DiM card file") {
|
||||
SettingsEntry(title = "Import DiM card", description = "Import DiM/BEm card file") {
|
||||
onClickImportCard()
|
||||
// placeholder
|
||||
// val file = File("dummy_file.bin") //filePicker()
|
||||
// val fileInputStream = FileInputStream(file)
|
||||
@ -69,9 +71,6 @@ fun SettingsScreen(
|
||||
// val logo = beMemory.spriteData.sprites[0]
|
||||
// }
|
||||
}
|
||||
SettingsEntry(title = "Import BEm card", description = "Import BEm card file") {
|
||||
// placeholder
|
||||
}
|
||||
SettingsSection("About and credits")
|
||||
SettingsEntry(title = "Credits", description = "Credits") { }
|
||||
SettingsEntry(title = "About", description = "About") { }
|
||||
|
||||
@ -0,0 +1,89 @@
|
||||
package com.github.nacabaro.vbhelper.screens
|
||||
|
||||
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
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val application = LocalContext.current.applicationContext as VBHelper
|
||||
val db = application.container.db
|
||||
val spriteRepo = SpriteRepo(db)
|
||||
|
||||
val spriteList = remember { mutableStateListOf<Sprites>() }
|
||||
|
||||
Log.d("SpriteViewer", "spriteList: $spriteList")
|
||||
|
||||
LaunchedEffect(spriteRepo) {
|
||||
coroutineScope.launch {
|
||||
spriteList.clear()
|
||||
spriteList.addAll(spriteRepo.getAllSprites())
|
||||
}
|
||||
}
|
||||
|
||||
Scaffold (
|
||||
topBar = {
|
||||
TopBanner(
|
||||
text = "Sprite viewer",
|
||||
onBackClick = {
|
||||
navController.popBackStack()
|
||||
}
|
||||
)
|
||||
},
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
) { contentPadding ->
|
||||
LazyColumn (
|
||||
modifier = Modifier
|
||||
.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() }
|
||||
Image(
|
||||
bitmap = imageBitmap,
|
||||
contentDescription = "Sprite",
|
||||
modifier = Modifier
|
||||
.size(256.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,6 +38,7 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import com.github.nacabaro.vbhelper.R
|
||||
import com.github.nacabaro.vbhelper.components.StorageEntry
|
||||
import com.github.nacabaro.vbhelper.components.TopBanner
|
||||
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||
import com.github.nacabaro.vbhelper.source.StorageRepository
|
||||
@ -112,41 +113,6 @@ fun StorageScreen() {
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun StorageEntry(
|
||||
name: String,
|
||||
icon: Int,
|
||||
onClick: () -> Unit = {},
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
Card(
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
onClick = onClick,
|
||||
modifier = modifier
|
||||
.padding(8.dp)
|
||||
) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(id = icon),
|
||||
contentDescription = name,
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.size(64.dp)
|
||||
)
|
||||
Text(
|
||||
text = name,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun StorageDialog(
|
||||
characterId: Long,
|
||||
|
||||
@ -0,0 +1,18 @@
|
||||
package com.github.nacabaro.vbhelper.source
|
||||
|
||||
import com.github.nacabaro.vbhelper.database.AppDatabase
|
||||
import com.github.nacabaro.vbhelper.domain.Character
|
||||
import com.github.nacabaro.vbhelper.domain.Dim
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class DexRepository (
|
||||
private val db: AppDatabase
|
||||
) {
|
||||
suspend fun getAllDims(): List<Dim> {
|
||||
return db.dimDao().getAllDims()
|
||||
}
|
||||
|
||||
suspend fun getCharactersByDimId(dimId: Int): List<Character> {
|
||||
return db.characterDao().getCharacterByDimId(dimId)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
5
app/src/main/res/drawable/baseline_image_24.xml
Normal file
5
app/src/main/res/drawable/baseline_image_24.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<path android:fillColor="@android:color/white" android:pathData="M21,19V5c0,-1.1 -0.9,-2 -2,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2zM8.5,13.5l2.5,3.01L14.5,12l4.5,6H5l3.5,-4.5z"/>
|
||||
|
||||
</vector>
|
||||
Loading…
x
Reference in New Issue
Block a user