cleanup code

This commit is contained in:
SSimco
2025-03-10 18:04:26 +02:00
parent 72cf7c7587
commit 8c74158078
59 changed files with 738 additions and 13112 deletions
-1
View File
@@ -67,7 +67,6 @@ add_library(CemuCafe
HW/Espresso/Recompiler/PPCFunctionBoundaryTracker.h
HW/Espresso/Recompiler/PPCRecompiler.cpp
HW/Espresso/Recompiler/PPCRecompiler.h
HW/Espresso/Recompiler/RecompilerTests.cpp
HW/Espresso/Recompiler/IML/IML.h
HW/Espresso/Recompiler/IML/IMLSegment.cpp
HW/Espresso/Recompiler/IML/IMLSegment.h
+7 -2
View File
@@ -72,6 +72,10 @@
#include <sys/sysctl.h>
#endif
#if __ANDROID__
#include <android/api-level.h>
#endif
std::string _pathToExecutable;
std::string _pathToBaseExecutable;
@@ -518,8 +522,9 @@ namespace CafeSystem
{
std::string buffer;
const char* platform = NULL;
#if __ANDROID__
platform = "Android";
#if __ANDROID__
buffer = fmt::format("Android (API level {})", android_get_device_api_level());;
platform = buffer.c_str();
#elif BOOST_OS_WINDOWS
uint32 buildNumber;
std::string windowsVersionName = GetWindowsNamedVersion(buildNumber);
File diff suppressed because it is too large Load Diff
@@ -1,3 +0,0 @@
#pragma once
void runRecompilerTests();
+15 -1
View File
@@ -333,8 +333,22 @@ inline uint64 _udiv128(uint64 highDividend, uint64 lowDividend, uint64 divisor,
// On aarch64 we handle some of the x86 intrinsics by implementing them as wrappers
#if defined(__aarch64__)
inline void _mm_pause(void)
{
asm volatile("isb");
}
#include "sse2neon.h";
inline uint64 __rdtsc()
{
uint64 t;
asm volatile("mrs %0, cntvct_el0" : "=r" (t));
return t;
}
inline void _mm_mfence()
{
}
inline unsigned char _addcarry_u64(unsigned char carry, unsigned long long a, unsigned long long b, unsigned long long *result)
{
File diff suppressed because it is too large Load Diff
@@ -8,6 +8,8 @@ import android.provider.DocumentsContract
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
@@ -25,25 +27,23 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import info.cemu.cemu.about.AboutCemuActivity
import info.cemu.cemu.about.AboutCemuRoute
import info.cemu.cemu.about.aboutCemuNavigation
import info.cemu.cemu.emulation.EmulationActivity
import info.cemu.cemu.features.DocumentsProvider
import info.cemu.cemu.gamelist.GameDetailsScreen
import info.cemu.cemu.gamelist.GameProfileEditScreen
import info.cemu.cemu.gamelist.GameViewModel
import info.cemu.cemu.gamelist.GamesListScreen
import info.cemu.cemu.gamelist.GamesListScreenActions
import info.cemu.cemu.graphicpacks.GraphicPacksActivity
import info.cemu.cemu.guicore.ActivityContent
import info.cemu.cemu.gamelist.GameListRoute
import info.cemu.cemu.gamelist.gameListNavigation
import info.cemu.cemu.graphicpacks.GraphicPacksRoute
import info.cemu.cemu.graphicpacks.graphicPacksNavigation
import info.cemu.cemu.guicore.components.ActivityContent
import info.cemu.cemu.nativeinterface.NativeGameTitles.Game
import info.cemu.cemu.nativeinterface.NativeSettings
import info.cemu.cemu.settings.SettingsActivity
import info.cemu.cemu.titlemanager.TitleManagerActivity
import kotlinx.serialization.Serializable
import info.cemu.cemu.settings.SettingsRoute
import info.cemu.cemu.settings.settingsNavigation
import info.cemu.cemu.titlemanager.TitleManagerRoute
import info.cemu.cemu.titlemanager.titleManagerNavigation
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
@@ -62,135 +62,98 @@ class MainActivity : ComponentActivity() {
}
private fun startGame(context: Context, game: Game) {
context.startActivity(
Intent(
context,
EmulationActivity::class.java
).apply {
putExtra(EmulationActivity.EXTRA_LAUNCH_PATH, game.path)
}
)
Intent(
context,
EmulationActivity::class.java
).apply {
putExtra(EmulationActivity.EXTRA_LAUNCH_PATH, game.path)
context.startActivity(this)
}
}
sealed class MainRoutes {
@Serializable
object GamesRoute
@Serializable
object GameDetailsRoute
@Serializable
object GameProfileEditRoute
}
@Composable
fun MainNav() {
private fun MainNav() {
val navController = rememberNavController()
val selectedGameViewModel: GameViewModel = viewModel()
fun navigateBack() {
navController.popBackStack()
}
NavHost(navController = navController, startDestination = MainRoutes.GamesRoute) {
composable<MainRoutes.GamesRoute> {
val context = LocalContext.current
GamesListScreen(
selectedGameViewModel = selectedGameViewModel,
gameListActions = GamesListScreenActions(
goToGameEditProfile = { navController.navigate(MainRoutes.GameProfileEditRoute) },
startGame = { startGame(context, it) },
goToGameDetails = { navController.navigate(MainRoutes.GameDetailsRoute) },
),
toolbarActions = {
GameListToolBarActions()
}
)
}
composable<MainRoutes.GameDetailsRoute> {
GameDetailsScreen(
selectedGameViewModel = selectedGameViewModel,
navigateBack = ::navigateBack,
)
}
composable<MainRoutes.GameProfileEditRoute> {
GameProfileEditScreen(
selectedGameViewModel = selectedGameViewModel,
navigateBack = ::navigateBack,
val context = LocalContext.current
NavHost(
navController = navController,
startDestination = GameListRoute,
enterTransition = { EnterTransition.None },
exitTransition = { ExitTransition.None }
) {
gameListNavigation(navController, startGame = { startGame(context, it) }) {
GameListToolBarActionsMenu(
goToSettings = { navController.navigate(SettingsRoute) },
goToTitleManager = { navController.navigate(TitleManagerRoute) },
goToGraphicPacks = { navController.navigate(GraphicPacksRoute) },
goToAboutCemu = { navController.navigate(AboutCemuRoute) }
)
}
settingsNavigation(navController)
titleManagerNavigation(navController)
graphicPacksNavigation(navController)
aboutCemuNavigation(navController)
}
}
@Composable
fun GameListToolBarActions() {
private fun GameListToolBarActionsMenu(
goToSettings: () -> Unit,
goToTitleManager: () -> Unit,
goToGraphicPacks: () -> Unit,
goToAboutCemu: () -> Unit,
) {
var expandMenu by remember { mutableStateOf(false) }
val context = LocalContext.current
@Composable
fun DropdownMenuItem(onClick: () -> Unit, text: String) {
DropdownMenuItem(
onClick = {
onClick()
expandMenu = false
},
text = { Text(text) },
)
}
IconButton(
modifier = Modifier.padding(end = 8.dp),
onClick = { expandMenu = true },
) {
IconButton(
onClick = { expandMenu = true }
) {
Icon(
imageVector = Icons.Filled.MoreVert,
contentDescription = "More options"
)
}
Icon(
imageVector = Icons.Filled.MoreVert,
contentDescription = "More options"
)
}
DropdownMenu(
expanded = expandMenu,
onDismissRequest = { expandMenu = false }
) {
DropdownMenuItem(
onClick = {
context.goToActivity(SettingsActivity::class.java)
expandMenu = false
},
text = { Text(stringResource(R.string.settings)) },
onClick = goToSettings,
text = stringResource(R.string.settings)
)
DropdownMenuItem(
onClick = {
context.goToActivity(GraphicPacksActivity::class.java)
expandMenu = false
},
text = { Text(stringResource(R.string.graphic_packs)) },
onClick = goToGraphicPacks,
text = stringResource(R.string.graphic_packs)
)
DropdownMenuItem(
onClick = {
context.goToActivity(TitleManagerActivity::class.java)
expandMenu = false
},
text = { Text(stringResource(R.string.title_manager)) },
onClick = goToTitleManager,
text = stringResource(R.string.title_manager)
)
DropdownMenuItem(
onClick = {
openCemuFolder(context)
expandMenu = false
},
text = { Text(stringResource(R.string.open_cemu_folder)) },
onClick = { openCemuFolder(context) },
text = stringResource(R.string.open_cemu_folder)
)
DropdownMenuItem(
onClick = {
context.goToActivity(AboutCemuActivity::class.java)
expandMenu = false
},
text = { Text(stringResource(R.string.about_cemu)) },
onClick = goToAboutCemu,
text = stringResource(R.string.about_cemu),
)
}
}
private fun <T : ComponentActivity> Context.goToActivity(activityClass: Class<T>) {
startActivity(
Intent(
this,
activityClass,
)
)
}
fun openCemuFolder(context: Context) {
private fun openCemuFolder(context: Context) {
try {
Intent(Intent.ACTION_VIEW).apply {
addCategory(Intent.CATEGORY_DEFAULT)
@@ -1,18 +0,0 @@
package info.cemu.cemu.about
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import info.cemu.cemu.guicore.ActivityContent
class AboutCemuActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ActivityContent {
AboutCemuScreen(::onNavigateUp)
}
}
}
}
@@ -0,0 +1,15 @@
package info.cemu.cemu.about
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.compose.composable
import kotlinx.serialization.Serializable
@Serializable
object AboutCemuRoute
fun NavGraphBuilder.aboutCemuNavigation(navController: NavHostController) {
composable<AboutCemuRoute> {
AboutCemuScreen { navController.popBackStack() }
}
}
@@ -23,7 +23,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import info.cemu.cemu.BuildConfig
import info.cemu.cemu.R
import info.cemu.cemu.guicore.ScreenContent
import info.cemu.cemu.guicore.components.ScreenContent
@Composable
fun AboutCemuScreen(navigateBack: () -> Unit) {
@@ -7,32 +7,31 @@ import androidx.compose.foundation.layout.size
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import info.cemu.cemu.R
import info.cemu.cemu.guicore.ScreenContent
import info.cemu.cemu.guicore.enumtostringmapper.native.regionToStringId
import info.cemu.cemu.guicore.components.ScreenContent
import info.cemu.cemu.guicore.nativeenummapper.regionToStringId
import info.cemu.cemu.nativeinterface.NativeGameTitles.Game
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
@Composable
fun GameDetailsScreen(selectedGameViewModel: GameViewModel, navigateBack: () -> Unit) {
val game by selectedGameViewModel.game.collectAsState()
if (game == null) return
fun GameDetailsScreen(game: Game?, navigateBack: () -> Unit) {
if (game == null)
return
ScreenContent(
appBarText = stringResource(R.string.about_title),
contentModifier = Modifier.padding(16.dp),
contentVerticalArrangement = Arrangement.spacedBy(16.dp),
navigateBack = navigateBack,
) {
GameDetails(game!!)
GameDetails(game)
}
}
@@ -0,0 +1,76 @@
package info.cemu.cemu.gamelist
import androidx.compose.animation.AnimatedContentScope
import androidx.compose.foundation.layout.RowScope
import androidx.compose.runtime.Composable
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.compose.composable
import androidx.navigation.compose.navigation
import info.cemu.cemu.nativeinterface.NativeGameTitles
import kotlinx.serialization.Serializable
@Serializable
object GameListRoute
private object GameListRoutes {
@Serializable
object GamesRoute
@Serializable
object GameDetailsRoute
@Serializable
object GameProfileEditRoute
}
private inline fun <reified T : Any> NavGraphBuilder.composableGameScreen(
navController: NavController,
noinline content: @Composable (AnimatedContentScope.(NativeGameTitles.Game) -> Unit),
) {
composable<T> {
val previousBackStackEntry =
navController.previousBackStackEntry ?: return@composable
val game =
viewModel<GameViewModel>(previousBackStackEntry).game ?: return@composable
content(game)
}
}
fun NavGraphBuilder.gameListNavigation(
navController: NavHostController,
startGame: (NativeGameTitles.Game) -> Unit,
gameListToolBarActions: @Composable (RowScope.() -> Unit),
) {
navigation<GameListRoute>(startDestination = GameListRoutes.GamesRoute) {
composable<GameListRoutes.GamesRoute> { backStackEntry ->
val gameViewModel: GameViewModel = viewModel(backStackEntry)
GamesListScreen(
startGame = startGame,
goToGameEditProfile = { game ->
gameViewModel.game = game
navController.navigate(GameListRoutes.GameProfileEditRoute)
},
goToGameDetails = { game ->
gameViewModel.game = game
navController.navigate(GameListRoutes.GameDetailsRoute)
},
toolbarActions = gameListToolBarActions
)
}
composableGameScreen<GameListRoutes.GameDetailsRoute>(navController) { game ->
GameDetailsScreen(
game = game,
navigateBack = { navController.popBackStack() },
)
}
composableGameScreen<GameListRoutes.GameProfileEditRoute>(navController) { game ->
GameProfileEditScreen(
game = game,
navigateBack = { navController.popBackStack() },
)
}
}
}
@@ -15,14 +15,15 @@ import kotlinx.coroutines.flow.stateIn
class GameListViewModel : ViewModel() {
private var gamePaths = NativeSettings.getGamesPaths().toSet()
private val _filterText = MutableStateFlow("")
private val filterText = _filterText.asStateFlow()
val filterText = _filterText.asStateFlow()
fun setFilterText(filterText: String) {
_filterText.value = filterText
}
private val _games = MutableStateFlow<Set<Game>>(emptySet())
val games: StateFlow<List<Game>> = filterText.combine(_games) { filter, games ->
val games: StateFlow<List<Game>> = combine(_filterText, _games) { filter, games ->
if (filter.isBlank()) {
games
} else {
@@ -49,20 +50,8 @@ class GameListViewModel : ViewModel() {
refreshGames()
}
private val _gameToRemoveShaders = MutableStateFlow<Game?>(null)
val gameToRemoveShaders = _gameToRemoveShaders.asStateFlow()
fun removeShadersForSelectedGame() {
if (_gameToRemoveShaders.value == null) return
NativeGameTitles.removeShaderCacheFilesForTitle(_gameToRemoveShaders.value!!.titleId)
_gameToRemoveShaders.value = null
}
fun setGameForShadersRemoval(game: Game) {
_gameToRemoveShaders.value = game
}
fun clearSelectedGameForShaderRemoval() {
_gameToRemoveShaders.value = null
fun removeShadersForGame(game: Game) {
NativeGameTitles.removeShaderCacheFilesForTitle(game.titleId)
}
fun setGameTitleFavorite(game: Game, isFavorite: Boolean) {
@@ -6,18 +6,19 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import info.cemu.cemu.R
import info.cemu.cemu.guicore.Header
import info.cemu.cemu.guicore.ScreenContent
import info.cemu.cemu.guicore.SingleSelection
import info.cemu.cemu.guicore.Toggle
import info.cemu.cemu.guicore.enumtostringmapper.native.cpuModeToStringId
import info.cemu.cemu.guicore.components.Header
import info.cemu.cemu.guicore.components.ScreenContent
import info.cemu.cemu.guicore.components.SingleSelection
import info.cemu.cemu.guicore.components.Toggle
import info.cemu.cemu.guicore.nativeenummapper.cpuModeToStringId
import info.cemu.cemu.nativeinterface.NativeGameTitles
@Composable
fun GameProfileEditScreen(selectedGameViewModel: GameViewModel, navigateBack: () -> Unit) {
val game = selectedGameViewModel.game.collectAsStateWithLifecycle().value ?: return
fun GameProfileEditScreen(game: NativeGameTitles.Game?, navigateBack: () -> Unit) {
if (game == null)
return
val titleId = game.titleId
ScreenContent(
appBarText = stringResource(R.string.edit_game_profile),
@@ -2,14 +2,5 @@ package info.cemu.cemu.gamelist
import androidx.lifecycle.ViewModel
import info.cemu.cemu.nativeinterface.NativeGameTitles.Game
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
class GameViewModel : ViewModel() {
private val _game = MutableStateFlow<Game?>(null)
val game = _game.asStateFlow()
fun setCurrentGame(game: Game?) {
_game.value = game
}
}
class GameViewModel(var game: Game? = null) : ViewModel()
@@ -22,6 +22,7 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Checkbox
import androidx.compose.material3.DropdownMenu
@@ -63,24 +64,19 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import info.cemu.cemu.R
import info.cemu.cemu.emulation.EmulationActivity
import info.cemu.cemu.guicore.FilledSearchToolbar
import info.cemu.cemu.guicore.components.FilledSearchToolbar
import info.cemu.cemu.nativeinterface.NativeGameTitles
import info.cemu.cemu.nativeinterface.NativeGameTitles.Game
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import android.graphics.drawable.Icon as ShortcutIcon
data class GamesListScreenActions(
val goToGameDetails: () -> Unit,
val goToGameEditProfile: () -> Unit,
val startGame: (Game) -> Unit,
)
@Composable
fun GamesListScreen(
selectedGameViewModel: GameViewModel,
gameListViewModel: GameListViewModel = viewModel(),
gameListActions: GamesListScreenActions,
goToGameDetails: (Game) -> Unit,
goToGameEditProfile: (Game) -> Unit,
startGame: (Game) -> Unit,
toolbarActions: @Composable RowScope.() -> Unit,
) {
val context = LocalContext.current
@@ -88,8 +84,9 @@ fun GamesListScreen(
val lifecycleState by lifecycleOwner.lifecycle.currentStateFlow.collectAsState()
val coroutineScope = rememberCoroutineScope()
var refreshing by remember { mutableStateOf(false) }
val gameToRemoveShaders by gameListViewModel.gameToRemoveShaders.collectAsStateWithLifecycle()
val snackbarHostState = remember { SnackbarHostState() }
val gameSearchQuery by gameListViewModel.filterText.collectAsStateWithLifecycle()
val games by gameListViewModel.games.collectAsStateWithLifecycle()
val state = rememberPullToRefreshState()
@@ -109,6 +106,7 @@ fun GamesListScreen(
FilledSearchToolbar(
actions = toolbarActions,
hint = stringResource(R.string.search_games),
query = gameSearchQuery,
onValueChange = gameListViewModel::setFilterText
)
},
@@ -131,12 +129,26 @@ fun GamesListScreen(
),
) {
GameList(
gameListViewModel = gameListViewModel,
selectedGameViewModel = selectedGameViewModel,
actions = gameListActions,
onFailedToCreateShortCut = {
coroutineScope.launch { snackbarHostState.showSnackbar(context.getString(R.string.shortcut_not_supported)) }
}
games = games,
setFavorite = gameListViewModel::setGameTitleFavorite,
deleteShaderCaches = {
coroutineScope.launch { snackbarHostState.showSnackbar(context.getString(R.string.shader_caches_removed_notification)) }
gameListViewModel.removeShadersForGame(it)
},
startGame = startGame,
goToGameDetails = goToGameDetails,
goToGameEditProfile = goToGameEditProfile,
createShortcut = { game ->
createShortcutForGame(
context,
game,
onFailedToCreateShortCut = {
val errorMessage =
context.getString(R.string.shortcut_not_supported)
coroutineScope.launch { snackbarHostState.showSnackbar(errorMessage) }
}
)
},
)
PullToRefreshDefaults.Indicator(
modifier = Modifier.align(Alignment.TopCenter),
@@ -147,29 +159,18 @@ fun GamesListScreen(
)
}
}
if (gameToRemoveShaders != null) {
ShaderCachesConfirmationDialog(
gameName = gameToRemoveShaders?.name ?: "",
onDismissRequest = gameListViewModel::clearSelectedGameForShaderRemoval,
onConfirm = {
gameListViewModel.removeShadersForSelectedGame()
coroutineScope.launch { snackbarHostState.showSnackbar(context.getString(R.string.shader_caches_removed_notification)) }
},
)
}
}
@Composable
fun GameList(
gameListViewModel: GameListViewModel,
selectedGameViewModel: GameViewModel,
actions: GamesListScreenActions,
onFailedToCreateShortCut: () -> Unit,
private fun GameList(
games: List<Game>,
startGame: (Game) -> Unit,
goToGameDetails: (Game) -> Unit,
goToGameEditProfile: (Game) -> Unit,
setFavorite: (Game, Boolean) -> Unit,
createShortcut: (Game) -> Unit,
deleteShaderCaches: (Game) -> Unit,
) {
val games by gameListViewModel.games.collectAsStateWithLifecycle()
val context = LocalContext.current
LazyVerticalGrid(
modifier = Modifier
.padding(8.dp)
@@ -177,34 +178,39 @@ fun GameList(
columns = GridCells.Adaptive(620.dp)
) {
items(items = games, key = { it.titleId }) { game ->
var showDeleteShaderConfirmationDialog by remember { mutableStateOf(false) }
GameListItem(
modifier = Modifier.animateItem(),
game = game,
onStartGame = actions.startGame,
actions = GameContextMenuActions(
onIsFavoriteChanged = { isFavorite ->
gameListViewModel.setGameTitleFavorite(game, isFavorite)
},
onEditGameProfile = {
selectedGameViewModel.setCurrentGame(game)
actions.goToGameEditProfile()
},
onRemoveShaderCaches = { gameListViewModel.setGameForShadersRemoval(game) },
onAboutTitle = {
selectedGameViewModel.setCurrentGame(game)
actions.goToGameDetails()
},
onCreateShortcut = {
createShortcutForGame(
context = context,
game = game,
onFailedToCreateShortCut = onFailedToCreateShortCut
)
},
),
onStartGame = startGame,
onIsFavoriteChanged = { isFavorite ->
setFavorite(game, isFavorite)
},
onEditGameProfile = {
goToGameEditProfile(game)
},
onRemoveShaderCaches = { showDeleteShaderConfirmationDialog = true },
onAboutTitle = {
goToGameDetails(game)
},
onCreateShortcut = {
createShortcut(game)
},
)
if (showDeleteShaderConfirmationDialog)
ShaderCachesConfirmationDialog(
gameName = game.name ?: "",
onDismissRequest = { showDeleteShaderConfirmationDialog = false },
onConfirm = {
deleteShaderCaches(game)
showDeleteShaderConfirmationDialog = false
},
)
}
}
}
@Composable
@@ -240,8 +246,12 @@ fun ShaderCachesConfirmationDialog(
@Composable
fun GameListItem(
actions: GameContextMenuActions,
onStartGame: (Game) -> Unit,
onIsFavoriteChanged: (Boolean) -> Unit,
onEditGameProfile: () -> Unit,
onRemoveShaderCaches: () -> Unit,
onAboutTitle: () -> Unit,
onCreateShortcut: () -> Unit,
game: Game,
modifier: Modifier = Modifier,
) {
@@ -269,7 +279,7 @@ fun GameListItem(
.align(Alignment.TopEnd)
.padding(2.dp)
.size(24.dp)
.clip(androidx.compose.foundation.shape.CircleShape)
.clip(CircleShape)
.background(MaterialTheme.colorScheme.surfaceVariant),
painter = painterResource(R.drawable.ic_favorite),
tint = MaterialTheme.colorScheme.primary,
@@ -287,25 +297,25 @@ fun GameListItem(
GameContextMenu(
expanded = contextMenuExpanded,
onDismissRequest = { contextMenuExpanded = false },
actions = actions,
game = game,
onIsFavoriteChanged = onIsFavoriteChanged,
onEditGameProfile = onEditGameProfile,
onRemoveShaderCaches = onRemoveShaderCaches,
onAboutTitle = onAboutTitle,
onCreateShortcut = onCreateShortcut,
)
}
}
data class GameContextMenuActions(
val onIsFavoriteChanged: (Boolean) -> Unit,
val onEditGameProfile: () -> Unit,
val onRemoveShaderCaches: () -> Unit,
val onAboutTitle: () -> Unit,
val onCreateShortcut: () -> Unit,
)
@Composable
fun GameContextMenu(
expanded: Boolean,
onDismissRequest: () -> Unit,
actions: GameContextMenuActions,
onIsFavoriteChanged: (Boolean) -> Unit,
onEditGameProfile: () -> Unit,
onRemoveShaderCaches: () -> Unit,
onAboutTitle: () -> Unit,
onCreateShortcut: () -> Unit,
game: Game,
) {
@Composable
@@ -335,29 +345,29 @@ fun GameContextMenu(
NativeGameTitles.titleHasShaderCacheFiles(game.titleId)
}
GameContextMenuItem(
onClick = { actions.onIsFavoriteChanged(!game.isFavorite) },
onClick = { onIsFavoriteChanged(!game.isFavorite) },
text = stringResource(R.string.game_favorite),
trailingIcon = {
Checkbox(checked = game.isFavorite, onCheckedChange = null)
}
)
GameContextMenuItem(
onClick = actions.onEditGameProfile,
onClick = onEditGameProfile,
text = stringResource(R.string.edit_game_profile)
)
GameContextMenuItem(
enabled = gameTitleHasCaches,
onClick = {
actions.onRemoveShaderCaches()
onRemoveShaderCaches()
},
text = stringResource(R.string.remove_shader_caches)
)
GameContextMenuItem(
onClick = actions.onAboutTitle,
onClick = onAboutTitle,
text = stringResource(R.string.about_title),
)
GameContextMenuItem(
onClick = actions.onCreateShortcut,
onClick = onCreateShortcut,
text = stringResource(R.string.create_shortcut)
)
}
@@ -1,41 +1,21 @@
package info.cemu.cemu.graphicpacks
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.AnimatedContentScope
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.runtime.Composable
import androidx.lifecycle.viewmodel.MutableCreationExtras
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.NavHost
import androidx.navigation.NavHostController
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import info.cemu.cemu.guicore.ActivityContent
import info.cemu.cemu.nativeinterface.NativeSettings
import androidx.navigation.compose.navigation
import kotlinx.serialization.Serializable
class GraphicPacksActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ActivityContent {
GraphicPacksNav(parentNavBack = ::onNavigateUp)
}
}
}
@Serializable
object GraphicPacksRoute
override fun onPause() {
super.onPause()
NativeSettings.saveSettings()
}
}
object GraphicPackRoutes {
private object GraphicPackRoutes {
@Serializable
object GraphicPacksRootSectionRoute
@@ -62,42 +42,22 @@ private inline fun <reified T : Any, reified U : GraphicPackNode> NavGraphBuilde
}
}
@Composable
fun GraphicPacksNav(
parentNavBack: () -> Unit,
) {
val navController = rememberNavController()
fun navigateBack() {
if (!navController.popBackStack()) {
parentNavBack()
}
private fun graphicPacksNavigate(navController: NavController, graphicPackNode: GraphicPackNode) {
when (graphicPackNode) {
is GraphicPackSectionNode -> navController.navigate(GraphicPackRoutes.GraphicPackSectionScreenRoute)
is GraphicPackDataNode -> navController.navigate(GraphicPackRoutes.GraphicPackDataScreenRoute)
}
}
fun graphicPacksNavigate(graphicPackNode: GraphicPackNode) {
when (graphicPackNode) {
is GraphicPackSectionNode -> navController.navigate(GraphicPackRoutes.GraphicPackSectionScreenRoute)
is GraphicPackDataNode -> navController.navigate(GraphicPackRoutes.GraphicPackDataScreenRoute)
}
}
NavHost(
navController = navController,
startDestination = GraphicPackRoutes.GraphicPacksRootSectionRoute,
enterTransition = {
EnterTransition.None
},
exitTransition = {
ExitTransition.None
}
) {
fun NavGraphBuilder.graphicPacksNavigation(navController: NavHostController) {
navigation<GraphicPacksRoute>(startDestination = GraphicPackRoutes.GraphicPacksRootSectionRoute) {
composable<GraphicPackRoutes.GraphicPacksRootSectionRoute> { backStackEntry ->
val graphicPackViewModel: GraphicPackViewModel = viewModel(backStackEntry)
GraphicPacksRootSectionScreen(
navigateBack = ::navigateBack,
navigateBack = { navController.popBackStack() },
graphicPackNodeNavigate = {
graphicPackViewModel.graphicPackNode = it
graphicPacksNavigate(it)
graphicPacksNavigate(navController, it)
}
)
}
@@ -106,10 +66,10 @@ fun GraphicPacksNav(
) { backStackEntry, graphicPackNode ->
val graphicPacksViewModel: GraphicPackViewModel = viewModel(backStackEntry)
GraphicPacksSectionScreen(
navigateBack = ::navigateBack,
navigateBack = { navController.popBackStack() },
graphicPackNodeNavigate = {
graphicPacksViewModel.graphicPackNode = it
graphicPacksNavigate(it)
graphicPacksNavigate(navController, it)
},
graphicPackSectionNode = graphicPackNode,
)
@@ -125,7 +85,7 @@ fun GraphicPacksNav(
}
)
GraphicPackDataScreen(
navigateBack = ::navigateBack,
navigateBack = { navController.popBackStack() },
graphicPackDataViewModel = graphicPackDataViewModel,
)
}
@@ -58,10 +58,10 @@ import androidx.compose.ui.unit.sp
import androidx.lifecycle.compose.dropUnlessResumed
import androidx.lifecycle.viewmodel.compose.viewModel
import info.cemu.cemu.R
import info.cemu.cemu.guicore.DefaultAppBarTitle
import info.cemu.cemu.guicore.ScreenContentLazy
import info.cemu.cemu.guicore.SearchToolbarInput
import info.cemu.cemu.guicore.SingleSelection
import info.cemu.cemu.guicore.components.DefaultAppBarTitle
import info.cemu.cemu.guicore.components.ScreenContentLazy
import info.cemu.cemu.guicore.components.SearchToolbarInput
import info.cemu.cemu.guicore.components.SingleSelection
import kotlinx.coroutines.launch
@@ -1,4 +1,4 @@
package info.cemu.cemu.guicore
package info.cemu.cemu.guicore.components
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
@@ -1,4 +1,4 @@
package info.cemu.cemu.guicore
package info.cemu.cemu.guicore.components
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth

Some files were not shown because too many files have changed in this diff Show More