diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/GameController.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/GameController.kt index 7323876c6..5cc1e20c3 100644 --- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/GameController.kt +++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/GameController.kt @@ -50,6 +50,14 @@ class GameController(var activity: Activity, var ryujinxNative: RyujinxNative = var leftGamePad: GamePad var rightGamePad: GamePad var controllerId: Int = -1 + val isVisible : Boolean + get() { + controllerView?.apply { + return this.isVisible + } + + return false; + } init { leftGamePad = GamePad(generateConfig(true), 16f, activity) @@ -97,6 +105,9 @@ class GameController(var activity: Activity, var ryujinxNative: RyujinxNative = fun setVisible(isVisible: Boolean){ controllerView?.apply { this.isVisible = isVisible + + if(isVisible) + connect() } } diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/GameHost.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/GameHost.kt index 2c99d5f04..6cc28cc33 100644 --- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/GameHost.kt +++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/GameHost.kt @@ -33,26 +33,6 @@ class GameHost(context: Context?, val controller: GameController, val mainViewMo holder.addCallback(this) } - override fun onTouchEvent(event: MotionEvent?): Boolean { - if (_isStarted) - return when (event!!.actionMasked) { - MotionEvent.ACTION_MOVE -> { - _nativeRyujinx.inputSetTouchPoint(event.x.roundToInt(), event.y.roundToInt()) - true - } - MotionEvent.ACTION_DOWN -> { - _nativeRyujinx.inputSetTouchPoint(event.x.roundToInt(), event.y.roundToInt()) - true - } - MotionEvent.ACTION_UP -> { - _nativeRyujinx.inputReleaseTouchPoint() - true - } - else -> super.onTouchEvent(event) - } - return super.onTouchEvent(event) - } - override fun surfaceCreated(holder: SurfaceHolder) { } diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/MainView.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/MainView.kt index faa2c9351..ed3487433 100644 --- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/MainView.kt +++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/MainView.kt @@ -1,17 +1,30 @@ package org.ryujinx.android.views +import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier 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.pointerInput import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView import androidx.lifecycle.lifecycleScope @@ -20,8 +33,10 @@ import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import org.ryujinx.android.GameController import org.ryujinx.android.GameHost +import org.ryujinx.android.RyujinxNative import org.ryujinx.android.viewmodels.MainViewModel import org.ryujinx.android.viewmodels.SettingsViewModel +import kotlin.math.roundToInt class MainView { companion object { @@ -40,9 +55,8 @@ class MainView { @Composable fun GameView(mainViewModel: MainViewModel){ Box(modifier = Modifier.fillMaxSize()) { - var controller = GameController(mainViewModel.activity) - Surface(color = Color.Green, modifier = Modifier.fillMaxSize()) { - + val controller = remember { + GameController(mainViewModel.activity) } AndroidView( modifier = Modifier.fillMaxSize(), @@ -50,11 +64,164 @@ class MainView { GameHost(context, controller, mainViewModel) } ) - GameStats(mainViewModel) - controller.Compose(mainViewModel.activity.lifecycleScope, mainViewModel.activity.lifecycle) + GameOverlay(mainViewModel, controller) } } - + + @Composable + fun GameOverlay(mainViewModel: MainViewModel, controller: GameController){ + Box(modifier = Modifier.fillMaxSize()) { + GameStats(mainViewModel) + + var ryujinxNative = RyujinxNative() + + // touch surface + Surface(color = Color.Transparent, modifier = Modifier + .fillMaxSize() + .padding(0.dp) + .pointerInput(Unit) { + awaitPointerEventScope { + while (true) { + Thread.sleep(2); + val event = awaitPointerEvent() + + if(controller.isVisible) + continue + + var change = event + .component1() + .firstOrNull() + change?.apply { + var position = this.position + + if (event.type == PointerEventType.Press) { + ryujinxNative.inputSetTouchPoint( + position.x.roundToInt(), + position.y.roundToInt() + ) + } else if (event.type == PointerEventType.Release) { + ryujinxNative.inputReleaseTouchPoint() + + } else if (event.type == PointerEventType.Move) { + ryujinxNative.inputSetTouchPoint( + position.x.roundToInt(), + position.y.roundToInt() + ) + + } + } + } + } + }) { + } + controller.Compose(mainViewModel.activity.lifecycleScope, mainViewModel.activity.lifecycle) + Row(modifier = Modifier + .align(Alignment.BottomCenter) + .padding(8.dp)) { + IconButton(modifier = Modifier.padding(4.dp),onClick = { + controller.setVisible(!controller.isVisible) + }) { + Icon(imageVector = rememberVideogameAsset(), contentDescription = "Toggle Virtual Pad") + } + } + } + } + @Composable + fun rememberVideogameAsset(): ImageVector { + var primaryColor = MaterialTheme.colorScheme.primary + return remember { + ImageVector.Builder( + name = "videogame_asset", + defaultWidth = 40.0.dp, + defaultHeight = 40.0.dp, + viewportWidth = 40.0f, + viewportHeight = 40.0f + ).apply { + path( + fill = SolidColor(Color.Black.copy(alpha = 0.5f)), + fillAlpha = 1f, + stroke = SolidColor(primaryColor), + strokeAlpha = 1f, + strokeLineWidth = 1.0f, + strokeLineCap = StrokeCap.Butt, + strokeLineJoin = StrokeJoin.Miter, + strokeLineMiter = 1f, + pathFillType = PathFillType.NonZero + ) { + moveTo(6.25f, 29.792f) + quadToRelative(-1.083f, 0f, -1.854f, -0.792f) + quadToRelative(-0.771f, -0.792f, -0.771f, -1.833f) + verticalLineTo(12.833f) + quadToRelative(0f, -1.083f, 0.771f, -1.854f) + quadToRelative(0.771f, -0.771f, 1.854f, -0.771f) + horizontalLineToRelative(27.5f) + quadToRelative(1.083f, 0f, 1.854f, 0.771f) + quadToRelative(0.771f, 0.771f, 0.771f, 1.854f) + verticalLineToRelative(14.334f) + quadToRelative(0f, 1.041f, -0.771f, 1.833f) + reflectiveQuadToRelative(-1.854f, 0.792f) + close() + moveToRelative(0f, -2.625f) + horizontalLineToRelative(27.5f) + verticalLineTo(12.833f) + horizontalLineTo(6.25f) + verticalLineToRelative(14.334f) + close() + moveToRelative(7.167f, -1.792f) + quadToRelative(0.541f, 0f, 0.916f, -0.375f) + reflectiveQuadToRelative(0.375f, -0.917f) + verticalLineToRelative(-2.791f) + horizontalLineToRelative(2.75f) + quadToRelative(0.584f, 0f, 0.959f, -0.375f) + reflectiveQuadToRelative(0.375f, -0.917f) + quadToRelative(0f, -0.542f, -0.375f, -0.938f) + quadToRelative(-0.375f, -0.395f, -0.959f, -0.395f) + horizontalLineToRelative(-2.75f) + verticalLineToRelative(-2.75f) + quadToRelative(0f, -0.542f, -0.375f, -0.938f) + quadToRelative(-0.375f, -0.396f, -0.916f, -0.396f) + quadToRelative(-0.584f, 0f, -0.959f, 0.396f) + reflectiveQuadToRelative(-0.375f, 0.938f) + verticalLineToRelative(2.75f) + horizontalLineToRelative(-2.75f) + quadToRelative(-0.541f, 0f, -0.937f, 0.395f) + quadTo(8f, 19.458f, 8f, 20f) + quadToRelative(0f, 0.542f, 0.396f, 0.917f) + reflectiveQuadToRelative(0.937f, 0.375f) + horizontalLineToRelative(2.75f) + verticalLineToRelative(2.791f) + quadToRelative(0f, 0.542f, 0.396f, 0.917f) + reflectiveQuadToRelative(0.938f, 0.375f) + close() + moveToRelative(11.125f, -0.5f) + quadToRelative(0.791f, 0f, 1.396f, -0.583f) + quadToRelative(0.604f, -0.584f, 0.604f, -1.375f) + quadToRelative(0f, -0.834f, -0.604f, -1.417f) + quadToRelative(-0.605f, -0.583f, -1.396f, -0.583f) + quadToRelative(-0.834f, 0f, -1.417f, 0.583f) + quadToRelative(-0.583f, 0.583f, -0.583f, 1.375f) + quadToRelative(0f, 0.833f, 0.583f, 1.417f) + quadToRelative(0.583f, 0.583f, 1.417f, 0.583f) + close() + moveToRelative(3.916f, -5.833f) + quadToRelative(0.834f, 0f, 1.417f, -0.584f) + quadToRelative(0.583f, -0.583f, 0.583f, -1.416f) + quadToRelative(0f, -0.792f, -0.583f, -1.375f) + quadToRelative(-0.583f, -0.584f, -1.417f, -0.584f) + quadToRelative(-0.791f, 0f, -1.375f, 0.584f) + quadToRelative(-0.583f, 0.583f, -0.583f, 1.375f) + quadToRelative(0f, 0.833f, 0.583f, 1.416f) + quadToRelative(0.584f, 0.584f, 1.375f, 0.584f) + close() + moveTo(6.25f, 27.167f) + verticalLineTo(12.833f) + verticalLineToRelative(14.334f) + close() + } + }.build() + } + } + @Composable fun GameStats(mainViewModel: MainViewModel){ var fifo = remember {