add bottom popup ingame

This commit is contained in:
Emmanuel Hansen 2023-08-05 22:06:34 +00:00
parent 0bf93ef754
commit 8c0bd460d9
7 changed files with 163 additions and 24 deletions

View File

@ -36,6 +36,7 @@ android {
release { release {
minifyEnabled false minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug
} }
} }
compileOptions { compileOptions {
@ -92,6 +93,7 @@ dependencies {
implementation "androidx.preference:preference-ktx:1.2.0" implementation "androidx.preference:preference-ktx:1.2.0"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.2' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.2'
implementation 'com.google.code.gson:gson:2.10.1' implementation 'com.google.code.gson:gson:2.10.1'
implementation("br.com.devsrsouza.compose.icons:css-gg:1.1.0")
implementation "io.coil-kt:coil-compose:2.4.0" implementation "io.coil-kt:coil-compose:2.4.0"
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.ext:junit:1.1.5'

View File

@ -224,4 +224,4 @@ extern "C"
void debug_break(int code){ void debug_break(int code){
if(code >= 3) if(code >= 3)
int r = 0; int r = 0;
} }

View File

@ -46,15 +46,17 @@ class GameController(var activity: Activity) {
return view return view
} }
@Composable @Composable
fun Compose(viewModel: MainViewModel) : Unit fun Compose(viewModel: MainViewModel) : Unit {
{
AndroidView( AndroidView(
modifier = Modifier.fillMaxSize(), factory = { context -> modifier = Modifier.fillMaxSize(), factory = { context ->
val controller = GameController(viewModel.activity) val controller = GameController(viewModel.activity)
val c = Create(context, viewModel.activity, controller) val c = Create(context, viewModel.activity, controller)
viewModel.activity.lifecycleScope.apply { viewModel.activity.lifecycleScope.apply {
viewModel.activity.lifecycleScope.launch { viewModel.activity.lifecycleScope.launch {
val events = merge(controller.leftGamePad.events(),controller.rightGamePad.events()) val events = merge(
controller.leftGamePad.events(),
controller.rightGamePad.events()
)
.shareIn(viewModel.activity.lifecycleScope, SharingStarted.Lazily) .shareIn(viewModel.activity.lifecycleScope, SharingStarted.Lazily)
events.safeCollect { events.safeCollect {
controller.handleEvent(it) controller.handleEvent(it)

View File

@ -1,8 +1,14 @@
package org.ryujinx.android package org.ryujinx.android
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.KeyboardArrowUp
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.PathFillType import androidx.compose.ui.graphics.PathFillType
import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.graphics.SolidColor
@ -10,13 +16,17 @@ import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.StrokeJoin import androidx.compose.ui.graphics.StrokeJoin
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.graphics.vector.path
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import compose.icons.CssGgIcons
import compose.icons.cssggicons.Games
class Icons { class Icons {
companion object{ companion object{
/// Icons exported from https://www.composables.com/icons /// Icons exported from https://www.composables.com/icons
@Composable @Composable
fun Download(): ImageVector { fun download(): ImageVector {
val primaryColor = MaterialTheme.colorScheme.primary
return remember { return remember {
ImageVector.Builder( ImageVector.Builder(
name = "download", name = "download",
@ -26,9 +36,9 @@ class Icons {
viewportHeight = 40.0f viewportHeight = 40.0f
).apply { ).apply {
path( path(
fill = SolidColor(Color.Black), fill = SolidColor(Color.Black.copy(alpha = 0.5f)),
stroke = SolidColor(primaryColor),
fillAlpha = 1f, fillAlpha = 1f,
stroke = null,
strokeAlpha = 1f, strokeAlpha = 1f,
strokeLineWidth = 1.0f, strokeLineWidth = 1.0f,
strokeLineCap = StrokeCap.Butt, strokeLineCap = StrokeCap.Butt,
@ -84,7 +94,77 @@ class Icons {
} }
} }
@Composable @Composable
fun VideoGame(): ImageVector { fun vSync(): ImageVector {
val primaryColor = MaterialTheme.colorScheme.primary
return remember {
ImageVector.Builder(
name = "60fps",
defaultWidth = 40.0.dp,
defaultHeight = 40.0.dp,
viewportWidth = 40.0f,
viewportHeight = 40.0f
).apply {
path(
fill = SolidColor(Color.Black.copy(alpha = 0.5f)),
stroke = SolidColor(primaryColor),
fillAlpha = 1f,
strokeAlpha = 1f,
strokeLineWidth = 1.0f,
strokeLineCap = StrokeCap.Butt,
strokeLineJoin = StrokeJoin.Miter,
strokeLineMiter = 1f,
pathFillType = PathFillType.NonZero
) {
moveTo(7.292f, 31.458f)
quadToRelative(-1.542f, 0f, -2.625f, -1.041f)
quadToRelative(-1.084f, -1.042f, -1.084f, -2.625f)
verticalLineTo(12.208f)
quadToRelative(0f, -1.583f, 1.084f, -2.625f)
quadTo(5.75f, 8.542f, 7.292f, 8.542f)
horizontalLineTo(14f)
quadToRelative(0.75f, 0f, 1.292f, 0.541f)
quadToRelative(0.541f, 0.542f, 0.541f, 1.292f)
reflectiveQuadToRelative(-0.541f, 1.292f)
quadToRelative(-0.542f, 0.541f, -1.292f, 0.541f)
horizontalLineTo(7.208f)
verticalLineToRelative(5.084f)
horizontalLineToRelative(6.709f)
quadToRelative(1.541f, 0f, 2.583f, 1.041f)
quadToRelative(1.042f, 1.042f, 1.042f, 2.625f)
verticalLineToRelative(6.834f)
quadToRelative(0f, 1.583f, -1.042f, 2.625f)
quadToRelative(-1.042f, 1.041f, -2.583f, 1.041f)
close()
moveToRelative(-0.084f, -10.5f)
verticalLineToRelative(6.834f)
horizontalLineToRelative(6.709f)
verticalLineToRelative(-6.834f)
close()
moveToRelative(17.125f, 6.834f)
horizontalLineToRelative(8.459f)
verticalLineTo(12.208f)
horizontalLineToRelative(-8.459f)
verticalLineToRelative(15.584f)
close()
moveToRelative(0f, 3.666f)
quadToRelative(-1.541f, 0f, -2.583f, -1.041f)
quadToRelative(-1.042f, -1.042f, -1.042f, -2.625f)
verticalLineTo(12.208f)
quadToRelative(0f, -1.583f, 1.042f, -2.625f)
quadToRelative(1.042f, -1.041f, 2.583f, -1.041f)
horizontalLineToRelative(8.459f)
quadToRelative(1.541f, 0f, 2.583f, 1.041f)
quadToRelative(1.042f, 1.042f, 1.042f, 2.625f)
verticalLineToRelative(15.584f)
quadToRelative(0f, 1.583f, -1.042f, 2.625f)
quadToRelative(-1.042f, 1.041f, -2.583f, 1.041f)
close()
}
}.build()
}
}
@Composable
fun videoGame(): ImageVector {
val primaryColor = MaterialTheme.colorScheme.primary val primaryColor = MaterialTheme.colorScheme.primary
return remember { return remember {
ImageVector.Builder( ImageVector.Builder(
@ -96,8 +176,8 @@ class Icons {
).apply { ).apply {
path( path(
fill = SolidColor(Color.Black.copy(alpha = 0.5f)), fill = SolidColor(Color.Black.copy(alpha = 0.5f)),
fillAlpha = 1f,
stroke = SolidColor(primaryColor), stroke = SolidColor(primaryColor),
fillAlpha = 1f,
strokeAlpha = 1f, strokeAlpha = 1f,
strokeLineWidth = 1.0f, strokeLineWidth = 1.0f,
strokeLineCap = StrokeCap.Butt, strokeLineCap = StrokeCap.Butt,
@ -179,4 +259,16 @@ class Icons {
} }
} }
} }
} }
@Preview
@Composable
fun Preview(){
IconButton(modifier = Modifier.padding(4.dp), onClick = {
}) {
Icon(
imageVector = CssGgIcons.Games,
contentDescription = "Open Panel"
)
}
}

View File

@ -228,6 +228,7 @@ class HomeViews {
mutableStateListOf<GameModel>() mutableStateListOf<GameModel>()
} }
if(refresh.value) { if(refresh.value) {
viewModel.setViewList(list) viewModel.setViewList(list)
refresh.value = false refresh.value = false
@ -342,7 +343,7 @@ class HomeViews {
) { ) {
Column(modifier = Modifier.padding(16.dp)) { Column(modifier = Modifier.padding(16.dp)) {
Icon( Icon(
imageVector = org.ryujinx.android.Icons.Download(), imageVector = org.ryujinx.android.Icons.download(),
contentDescription = "Game Dlc", contentDescription = "Game Dlc",
tint = Color.Green, tint = Color.Green,
modifier = Modifier modifier = Modifier

View File

@ -25,24 +25,22 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.PathFillType
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.StrokeJoin
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.path
import androidx.compose.ui.input.pointer.PointerEventType import androidx.compose.ui.input.pointer.PointerEventType
import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView import androidx.compose.ui.viewinterop.AndroidView
import androidx.compose.ui.window.Popup
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import compose.icons.CssGgIcons
import compose.icons.cssggicons.ToolbarBottom
import org.ryujinx.android.GameController import org.ryujinx.android.GameController
import org.ryujinx.android.GameHost import org.ryujinx.android.GameHost
import org.ryujinx.android.Icons import org.ryujinx.android.Icons
import org.ryujinx.android.RyujinxNative import org.ryujinx.android.RyujinxNative
import org.ryujinx.android.viewmodels.MainViewModel import org.ryujinx.android.viewmodels.MainViewModel
import org.ryujinx.android.viewmodels.QuickSettings
import org.ryujinx.android.viewmodels.SettingsViewModel import org.ryujinx.android.viewmodels.SettingsViewModel
import kotlin.math.roundToInt import kotlin.math.roundToInt
@ -88,6 +86,16 @@ class MainView {
val ryujinxNative = RyujinxNative() val ryujinxNative = RyujinxNative()
var showController = remember {
mutableStateOf(QuickSettings(mainViewModel.activity).useVirtualController)
}
var enableVsync = remember {
mutableStateOf(QuickSettings(mainViewModel.activity).enableVsync)
}
var showMore = remember {
mutableStateOf(false)
}
// touch surface // touch surface
Surface(color = Color.Transparent, modifier = Modifier Surface(color = Color.Transparent, modifier = Modifier
.fillMaxSize() .fillMaxSize()
@ -95,8 +103,9 @@ class MainView {
.pointerInput(Unit) { .pointerInput(Unit) {
awaitPointerEventScope { awaitPointerEventScope {
while (true) { while (true) {
Thread.sleep(2)
val event = awaitPointerEvent() val event = awaitPointerEvent()
if (!showController.value)
continue
val change = event val change = event
.component1() .component1()
@ -137,15 +146,46 @@ class MainView {
.padding(8.dp) .padding(8.dp)
) { ) {
IconButton(modifier = Modifier.padding(4.dp), onClick = { IconButton(modifier = Modifier.padding(4.dp), onClick = {
mainViewModel.controller?.setVisible(!mainViewModel.controller!!.isVisible) showMore.value = true
}) { }) {
Icon( Icon(
imageVector = Icons.VideoGame(), imageVector = CssGgIcons.ToolbarBottom,
contentDescription = "Toggle Virtual Pad" contentDescription = "Open Panel"
) )
} }
} }
if(showMore.value){
Popup(alignment = Alignment.BottomCenter, onDismissRequest = {showMore.value = false}) {
Surface(modifier = Modifier.padding(16.dp),
shape = MaterialTheme.shapes.medium) {
Row(modifier = Modifier.padding(8.dp)) {
IconButton(modifier = Modifier.padding(4.dp), onClick = {
showMore.value = false
showController.value = !showController.value
mainViewModel.controller?.setVisible(showController.value)
}) {
Icon(
imageVector = Icons.videoGame(),
contentDescription = "Toggle Virtual Pad"
)
}
IconButton(modifier = Modifier.padding(4.dp), onClick = {
showMore.value = false
enableVsync.value = !enableVsync.value
RyujinxNative().graphicsRendererSetVsync(enableVsync.value)
}) {
Icon(
imageVector = Icons.vSync(),
tint = if(enableVsync.value) Color.Green else Color.Red,
contentDescription = "Toggle VSync"
)
}
}
}
}
}
var showBackNotice = remember { var showBackNotice = remember {
mutableStateOf(false) mutableStateOf(false)
} }
@ -227,4 +267,4 @@ class MainView {
mainViewModel.setStatStates(fifo, gameFps, gameTime) mainViewModel.setStatStates(fifo, gameFps, gameTime)
} }
} }
} }

View File

@ -4,6 +4,7 @@ pluginManagement {
mavenCentral() mavenCentral()
gradlePluginPortal() gradlePluginPortal()
maven { url 'https://jitpack.io' } maven { url 'https://jitpack.io' }
maven { url "https://maven.pkg.jetbrains.space/public/p/compose/dev" }
} }
} }
dependencyResolutionManagement { dependencyResolutionManagement {
@ -12,6 +13,7 @@ dependencyResolutionManagement {
google() google()
mavenCentral() mavenCentral()
maven { url 'https://jitpack.io' } maven { url 'https://jitpack.io' }
maven { url "https://maven.pkg.jetbrains.space/public/p/compose/dev" }
} }
} }
rootProject.name = "RyujinxAndroid" rootProject.name = "RyujinxAndroid"