mirror of
https://github.com/geode-sdk/android-launcher.git
synced 2026-10-22 16:42:38 +00:00
add fps limiting option
This commit is contained in:
8 files changed
+272
-10
No files matched your search
@@ -67,6 +67,7 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
|
|||||||
|
|
||||||
private var displayMode = DisplayMode.DEFAULT
|
private var displayMode = DisplayMode.DEFAULT
|
||||||
private var forceRefreshRate = false
|
private var forceRefreshRate = false
|
||||||
|
private var mLimitedRefreshRate: Int? = null
|
||||||
private var mAspectRatio = 0.0f
|
private var mAspectRatio = 0.0f
|
||||||
private var mScreenZoom = 1.0f
|
private var mScreenZoom = 1.0f
|
||||||
private var mScreenZoomFit = false
|
private var mScreenZoomFit = false
|
||||||
@@ -425,10 +426,17 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
|
|||||||
val renderer = Cocos2dxRenderer(glSurfaceView)
|
val renderer = Cocos2dxRenderer(glSurfaceView)
|
||||||
glSurfaceView.setCocos2dxRenderer(renderer)
|
glSurfaceView.setCocos2dxRenderer(renderer)
|
||||||
|
|
||||||
if (forceRefreshRate) {
|
val frameRate = mLimitedRefreshRate
|
||||||
|
|
||||||
|
// force refresh rate causes some issues if the limited framerate isn't supported by device
|
||||||
|
if (forceRefreshRate && frameRate == null) {
|
||||||
renderer.setFrameRate = true
|
renderer.setFrameRate = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (frameRate != null) {
|
||||||
|
renderer.limitFrameRate(frameRate)
|
||||||
|
}
|
||||||
|
|
||||||
editText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
|
editText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
|
||||||
glSurfaceView.cocos2dxEditText = editText
|
glSurfaceView.cocos2dxEditText = editText
|
||||||
|
|
||||||
@@ -449,6 +457,7 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
|
|||||||
mScreenZoomFit = preferenceUtils.getBoolean(PreferenceUtils.Key.SCREEN_ZOOM_FIT)
|
mScreenZoomFit = preferenceUtils.getBoolean(PreferenceUtils.Key.SCREEN_ZOOM_FIT)
|
||||||
|
|
||||||
forceRefreshRate = preferenceUtils.getBoolean(PreferenceUtils.Key.FORCE_HRR)
|
forceRefreshRate = preferenceUtils.getBoolean(PreferenceUtils.Key.FORCE_HRR)
|
||||||
|
mLimitedRefreshRate = preferenceUtils.getInt(PreferenceUtils.Key.LIMIT_FRAME_RATE).takeIf { it != 0 }
|
||||||
|
|
||||||
if (forceRefreshRate && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
if (forceRefreshRate && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
val maxRefreshRate = display?.supportedModes?.maxBy { it.refreshRate }?.refreshRate
|
val maxRefreshRate = display?.supportedModes?.maxBy { it.refreshRate }?.refreshRate
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import android.content.Intent
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.provider.DocumentsContract
|
import android.provider.DocumentsContract
|
||||||
|
import android.view.WindowManager
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.OnBackPressedDispatcher
|
import androidx.activity.OnBackPressedDispatcher
|
||||||
@@ -52,13 +53,13 @@ import com.geode.launcher.updater.ReleaseViewModel
|
|||||||
import com.geode.launcher.ui.theme.GeodeLauncherTheme
|
import com.geode.launcher.ui.theme.GeodeLauncherTheme
|
||||||
import com.geode.launcher.ui.theme.LocalTheme
|
import com.geode.launcher.ui.theme.LocalTheme
|
||||||
import com.geode.launcher.ui.theme.Theme
|
import com.geode.launcher.ui.theme.Theme
|
||||||
import com.geode.launcher.ui.theme.Typography
|
|
||||||
import com.geode.launcher.utils.Constants
|
import com.geode.launcher.utils.Constants
|
||||||
import com.geode.launcher.utils.GamePackageUtils
|
import com.geode.launcher.utils.GamePackageUtils
|
||||||
import com.geode.launcher.utils.LaunchUtils
|
import com.geode.launcher.utils.LaunchUtils
|
||||||
import com.geode.launcher.utils.PreferenceUtils
|
import com.geode.launcher.utils.PreferenceUtils
|
||||||
import java.net.ConnectException
|
import java.net.ConnectException
|
||||||
import java.net.UnknownHostException
|
import java.net.UnknownHostException
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
class SettingsActivity : ComponentActivity() {
|
class SettingsActivity : ComponentActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
@@ -356,6 +357,7 @@ fun SettingsScreen(
|
|||||||
if (currentDisplayMode == 1) {
|
if (currentDisplayMode == 1) {
|
||||||
SettingsStringSelectCard(
|
SettingsStringSelectCard(
|
||||||
title = stringResource(R.string.preference_custom_aspect_ratio_name),
|
title = stringResource(R.string.preference_custom_aspect_ratio_name),
|
||||||
|
description = stringResource(R.string.preference_custom_aspect_ratio_description),
|
||||||
dialogTitle = stringResource(R.string.preference_custom_aspect_ratio_select),
|
dialogTitle = stringResource(R.string.preference_custom_aspect_ratio_select),
|
||||||
preferenceKey = PreferenceUtils.Key.CUSTOM_ASPECT_RATIO,
|
preferenceKey = PreferenceUtils.Key.CUSTOM_ASPECT_RATIO,
|
||||||
options = linkedMapOf(
|
options = linkedMapOf(
|
||||||
@@ -369,6 +371,7 @@ fun SettingsScreen(
|
|||||||
|
|
||||||
SettingsRangeCard(
|
SettingsRangeCard(
|
||||||
title = stringResource(R.string.preference_screen_zoom_name),
|
title = stringResource(R.string.preference_screen_zoom_name),
|
||||||
|
description = stringResource(R.string.preference_screen_zoom_description),
|
||||||
dialogTitle = stringResource(R.string.preference_screen_zoom_select),
|
dialogTitle = stringResource(R.string.preference_screen_zoom_select),
|
||||||
preferenceKey = PreferenceUtils.Key.SCREEN_ZOOM,
|
preferenceKey = PreferenceUtils.Key.SCREEN_ZOOM,
|
||||||
labelSuffix = "x",
|
labelSuffix = "x",
|
||||||
@@ -382,6 +385,22 @@ fun SettingsScreen(
|
|||||||
asCard = false
|
asCard = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val maxFrameRate = remember {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
|
context.display.supportedModes.maxOf { it.refreshRate }
|
||||||
|
} else {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
(context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay.refreshRate
|
||||||
|
}.roundToInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsFPSCard(
|
||||||
|
title = stringResource(R.string.preference_limit_framerate_name),
|
||||||
|
dialogTitle = stringResource(R.string.preference_limit_framerate_select),
|
||||||
|
preferenceKey = PreferenceUtils.Key.LIMIT_FRAME_RATE,
|
||||||
|
maxFrameRate = maxFrameRate
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionsGroup(context.getString(R.string.preference_category_updater)) {
|
OptionsGroup(context.getString(R.string.preference_category_updater)) {
|
||||||
|
|||||||
@@ -3,17 +3,21 @@ package com.geode.launcher.preferences
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.selection.toggleable
|
import androidx.compose.foundation.selection.toggleable
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Add
|
||||||
import androidx.compose.material.icons.filled.Clear
|
import androidx.compose.material.icons.filled.Clear
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
@@ -38,6 +42,7 @@ import androidx.compose.runtime.staticCompositionLocalOf
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.semantics.Role
|
import androidx.compose.ui.semantics.Role
|
||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
@@ -51,6 +56,8 @@ import com.geode.launcher.ui.theme.Typography
|
|||||||
import com.geode.launcher.utils.LabelledText
|
import com.geode.launcher.utils.LabelledText
|
||||||
import com.geode.launcher.utils.PreferenceUtils
|
import com.geode.launcher.utils.PreferenceUtils
|
||||||
import kotlin.math.log10
|
import kotlin.math.log10
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.min
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
|
||||||
@@ -133,14 +140,15 @@ fun SettingsStringSelectCard(
|
|||||||
dialogTitle: String,
|
dialogTitle: String,
|
||||||
preferenceKey: PreferenceUtils.Key,
|
preferenceKey: PreferenceUtils.Key,
|
||||||
options: Map<String, String>,
|
options: Map<String, String>,
|
||||||
extraSelectBehavior: ((String?) -> Unit)? = null
|
extraSelectBehavior: ((String?) -> Unit)? = null,
|
||||||
|
description: String? = null,
|
||||||
) {
|
) {
|
||||||
val preferenceValue by PreferenceUtils.useStringPreference(preferenceKey)
|
val preferenceValue by PreferenceUtils.useStringPreference(preferenceKey)
|
||||||
|
|
||||||
var showDialog by remember { mutableStateOf(false) }
|
var showDialog by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
OptionsCard(
|
OptionsCard(
|
||||||
title = { OptionsTitle(title = title) },
|
title = { OptionsTitle(title = title, description = description) },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clickable(
|
.clickable(
|
||||||
onClick = {
|
onClick = {
|
||||||
@@ -322,6 +330,170 @@ fun RangeDialog(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun FrameRateDialog(
|
||||||
|
title: String,
|
||||||
|
onDismissRequest: () -> Unit,
|
||||||
|
onSelect: (Int) -> Unit,
|
||||||
|
initialValue: Int,
|
||||||
|
maxFrameRate: Int,
|
||||||
|
) {
|
||||||
|
var enteredValue by remember {
|
||||||
|
mutableStateOf(
|
||||||
|
if (initialValue == 0) maxFrameRate.toString()
|
||||||
|
else initialValue.toString()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var minFrameRate = 5
|
||||||
|
val currentValue = enteredValue.toIntOrNull()
|
||||||
|
var maximumReached = currentValue != null && currentValue > maxFrameRate
|
||||||
|
var minimumReached = currentValue != null && currentValue < minFrameRate
|
||||||
|
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = { onDismissRequest() },
|
||||||
|
title = {
|
||||||
|
Text(title)
|
||||||
|
},
|
||||||
|
text = {
|
||||||
|
Column {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = Modifier.weight(1.0f, false)
|
||||||
|
) {
|
||||||
|
IconButton(onClick = {
|
||||||
|
val prevValue = max((currentValue ?: 0) - 5, minFrameRate)
|
||||||
|
enteredValue = prevValue.toString()
|
||||||
|
}, enabled = currentValue == null || currentValue > minFrameRate) {
|
||||||
|
Icon(
|
||||||
|
painterResource(R.drawable.icon_remove),
|
||||||
|
contentDescription = stringResource(R.string.preference_limit_framerate_subtract)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(Modifier.size(8.dp))
|
||||||
|
|
||||||
|
OutlinedTextField(
|
||||||
|
value = enteredValue.toString(),
|
||||||
|
onValueChange = {
|
||||||
|
enteredValue = it
|
||||||
|
},
|
||||||
|
singleLine = true,
|
||||||
|
keyboardOptions = KeyboardOptions(
|
||||||
|
keyboardType = KeyboardType.Number,
|
||||||
|
),
|
||||||
|
suffix = {
|
||||||
|
Text(stringResource(R.string.preference_limit_framerate_suffix))
|
||||||
|
},
|
||||||
|
label = {
|
||||||
|
Text(stringResource(R.string.preference_limit_framerate_label))
|
||||||
|
},
|
||||||
|
isError = minimumReached || maximumReached,
|
||||||
|
modifier = Modifier.weight(1.0f),
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(Modifier.size(8.dp))
|
||||||
|
|
||||||
|
IconButton(onClick = {
|
||||||
|
val nextValue = min((currentValue ?: 0) + 5, maxFrameRate)
|
||||||
|
enteredValue = nextValue.toString()
|
||||||
|
}, enabled = currentValue == null || currentValue < maxFrameRate) {
|
||||||
|
Icon(
|
||||||
|
Icons.Filled.Add,
|
||||||
|
contentDescription = stringResource(R.string.preference_limit_framerate_add)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
IconButton(onClick = { onSelect(0) }) {
|
||||||
|
Icon(
|
||||||
|
painterResource(R.drawable.icon_delete),
|
||||||
|
contentDescription = stringResource(R.string.preference_limit_framerate_reset)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (minimumReached) {
|
||||||
|
Spacer(Modifier.size(8.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
stringResource(R.string.preference_limit_framerate_error_min, minFrameRate),
|
||||||
|
color = MaterialTheme.colorScheme.error,
|
||||||
|
style = MaterialTheme.typography.labelLarge,
|
||||||
|
)
|
||||||
|
} else if (maximumReached) {
|
||||||
|
Spacer(Modifier.size(8.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
stringResource(
|
||||||
|
R.string.preference_limit_framerate_error_max,
|
||||||
|
maxFrameRate
|
||||||
|
),
|
||||||
|
color = MaterialTheme.colorScheme.error,
|
||||||
|
style = MaterialTheme.typography.labelLarge,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(
|
||||||
|
onClick = { onSelect(currentValue ?: 0) },
|
||||||
|
enabled = !minimumReached && !maximumReached && currentValue != null
|
||||||
|
) {
|
||||||
|
Text(stringResource(R.string.message_box_accept))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dismissButton = {
|
||||||
|
TextButton(onClick = onDismissRequest) {
|
||||||
|
Text(stringResource(R.string.message_box_cancel))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SettingsFPSCard(
|
||||||
|
title: String,
|
||||||
|
dialogTitle: String,
|
||||||
|
preferenceKey: PreferenceUtils.Key,
|
||||||
|
maxFrameRate: Int,
|
||||||
|
description: String? = null,
|
||||||
|
) {
|
||||||
|
var preferenceValue by PreferenceUtils.useIntPreference(preferenceKey)
|
||||||
|
|
||||||
|
var showDialog by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
OptionsCard(
|
||||||
|
title = { OptionsTitle(title = title, description = description) },
|
||||||
|
modifier = Modifier
|
||||||
|
.clickable(
|
||||||
|
onClick = {
|
||||||
|
showDialog = true
|
||||||
|
},
|
||||||
|
role = Role.Button
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
if (preferenceValue == 0) {
|
||||||
|
Text(stringResource(R.string.preference_limit_framerate_default))
|
||||||
|
} else {
|
||||||
|
Text(stringResource(R.string.preference_limit_framerate_value, preferenceValue))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showDialog) {
|
||||||
|
FrameRateDialog(
|
||||||
|
title = dialogTitle,
|
||||||
|
onDismissRequest = { showDialog = false },
|
||||||
|
onSelect = {
|
||||||
|
preferenceValue = it
|
||||||
|
showDialog = false
|
||||||
|
},
|
||||||
|
initialValue = preferenceValue,
|
||||||
|
maxFrameRate = maxFrameRate
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SettingsRangeCard(
|
fun SettingsRangeCard(
|
||||||
title: String,
|
title: String,
|
||||||
@@ -331,6 +503,7 @@ fun SettingsRangeCard(
|
|||||||
range: IntRange,
|
range: IntRange,
|
||||||
scale: Int,
|
scale: Int,
|
||||||
step: Int,
|
step: Int,
|
||||||
|
description: String? = null,
|
||||||
children: @Composable () -> Unit = {}
|
children: @Composable () -> Unit = {}
|
||||||
) {
|
) {
|
||||||
var preferenceValue by PreferenceUtils.useIntPreference(preferenceKey)
|
var preferenceValue by PreferenceUtils.useIntPreference(preferenceKey)
|
||||||
@@ -338,7 +511,9 @@ fun SettingsRangeCard(
|
|||||||
var showDialog by remember { mutableStateOf(false) }
|
var showDialog by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
OptionsCard(
|
OptionsCard(
|
||||||
title = { OptionsTitle(title = title) },
|
title = {
|
||||||
|
OptionsTitle(title = title, description = description)
|
||||||
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clickable(
|
.clickable(
|
||||||
onClick = {
|
onClick = {
|
||||||
@@ -469,7 +644,8 @@ fun OptionsButton(title: String, description: String? = null, icon: (@Composable
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clickable(onClick = onClick, role = Role.Button)
|
.clickable(onClick = onClick, role = Role.Button),
|
||||||
|
wrapContent = true
|
||||||
) {
|
) {
|
||||||
if (displayInline && description != null) {
|
if (displayInline && description != null) {
|
||||||
Text(description, textAlign = TextAlign.End)
|
Text(description, textAlign = TextAlign.End)
|
||||||
@@ -487,7 +663,6 @@ fun SettingsCard(title: String, description: String? = null, icon: (@Composable
|
|||||||
OptionsCard(
|
OptionsCard(
|
||||||
title = {
|
title = {
|
||||||
OptionsTitle(
|
OptionsTitle(
|
||||||
Modifier.fillMaxWidth(0.75f),
|
|
||||||
title = title,
|
title = title,
|
||||||
description = description,
|
description = description,
|
||||||
icon = icon
|
icon = icon
|
||||||
@@ -531,7 +706,7 @@ fun OptionsTitle(modifier: Modifier = Modifier, title: String, description: Stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun OptionsCard(modifier: Modifier = Modifier, title: @Composable () -> Unit, content: @Composable () -> Unit) {
|
fun OptionsCard(modifier: Modifier = Modifier, wrapContent: Boolean = false, title: @Composable () -> Unit, content: @Composable () -> Unit) {
|
||||||
Row(
|
Row(
|
||||||
modifier
|
modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@@ -540,7 +715,15 @@ fun OptionsCard(modifier: Modifier = Modifier, title: @Composable () -> Unit, co
|
|||||||
Arrangement.SpaceBetween,
|
Arrangement.SpaceBetween,
|
||||||
Alignment.CenterVertically,
|
Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
|
if (!wrapContent) {
|
||||||
|
Box(modifier = Modifier.weight(1.0f)) {
|
||||||
title()
|
title()
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.size(12.dp))
|
||||||
|
} else {
|
||||||
|
title()
|
||||||
|
}
|
||||||
|
|
||||||
content()
|
content()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -146,6 +146,7 @@ class PreferenceUtils(private val sharedPreferences: SharedPreferences) {
|
|||||||
CUSTOM_ASPECT_RATIO,
|
CUSTOM_ASPECT_RATIO,
|
||||||
SCREEN_ZOOM,
|
SCREEN_ZOOM,
|
||||||
SCREEN_ZOOM_FIT,
|
SCREEN_ZOOM_FIT,
|
||||||
|
LIMIT_FRAME_RATE
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun defaultValueForBooleanKey(key: Key): Boolean {
|
private fun defaultValueForBooleanKey(key: Key): Boolean {
|
||||||
@@ -192,6 +193,7 @@ class PreferenceUtils(private val sharedPreferences: SharedPreferences) {
|
|||||||
Key.CUSTOM_ASPECT_RATIO -> "PreferenceCustomAspectRatio"
|
Key.CUSTOM_ASPECT_RATIO -> "PreferenceCustomAspectRatio"
|
||||||
Key.SCREEN_ZOOM -> "PreferenceScreenZoom"
|
Key.SCREEN_ZOOM -> "PreferenceScreenZoom"
|
||||||
Key.SCREEN_ZOOM_FIT -> "PreferenceScreenZoomFit"
|
Key.SCREEN_ZOOM_FIT -> "PreferenceScreenZoomFit"
|
||||||
|
Key.LIMIT_FRAME_RATE -> "PreferenceLimitFrameRate"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -115,9 +115,9 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.R)
|
@RequiresApi(Build.VERSION_CODES.R)
|
||||||
fun updateRefreshRate() {
|
fun updateRefreshRate() {
|
||||||
val maxRefreshRate = display.supportedModes.maxBy { it.refreshRate }
|
val maxRefreshRate = display.supportedModes.maxBy { it.refreshRate }.refreshRate
|
||||||
holder.surface.setFrameRate(
|
holder.surface.setFrameRate(
|
||||||
maxRefreshRate.refreshRate,
|
maxRefreshRate,
|
||||||
Surface.FRAME_RATE_COMPATIBILITY_DEFAULT
|
Surface.FRAME_RATE_COMPATIBILITY_DEFAULT
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ import android.os.Build
|
|||||||
import javax.microedition.khronos.egl.EGLConfig
|
import javax.microedition.khronos.egl.EGLConfig
|
||||||
import javax.microedition.khronos.opengles.GL10
|
import javax.microedition.khronos.opengles.GL10
|
||||||
|
|
||||||
|
private const val NANOSECONDS_PER_SECOND = 1000000000L
|
||||||
|
private const val NANOSECONDS_PER_MICROSECOND = 1000000L
|
||||||
|
|
||||||
@Suppress("unused", "KotlinJniMissingFunction")
|
@Suppress("unused", "KotlinJniMissingFunction")
|
||||||
class Cocos2dxRenderer(private var handler: Cocos2dxGLSurfaceView) : GLSurfaceView.Renderer {
|
class Cocos2dxRenderer(private var handler: Cocos2dxGLSurfaceView) : GLSurfaceView.Renderer {
|
||||||
companion object {
|
companion object {
|
||||||
@@ -62,6 +65,11 @@ class Cocos2dxRenderer(private var handler: Cocos2dxGLSurfaceView) : GLSurfaceVi
|
|||||||
private var screenHeight = 0
|
private var screenHeight = 0
|
||||||
var sendResizeEvents = false
|
var sendResizeEvents = false
|
||||||
var setFrameRate = false
|
var setFrameRate = false
|
||||||
|
private var mAnimationInterval: Long? = null
|
||||||
|
|
||||||
|
fun limitFrameRate(rate: Int) {
|
||||||
|
mAnimationInterval = NANOSECONDS_PER_SECOND/rate
|
||||||
|
}
|
||||||
|
|
||||||
fun setScreenWidthAndHeight(surfaceWidth: Int, surfaceHeight: Int) {
|
fun setScreenWidthAndHeight(surfaceWidth: Int, surfaceHeight: Int) {
|
||||||
screenWidth = surfaceWidth
|
screenWidth = surfaceWidth
|
||||||
@@ -80,7 +88,23 @@ class Cocos2dxRenderer(private var handler: Cocos2dxGLSurfaceView) : GLSurfaceVi
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onDrawFrame(gl: GL10?) {
|
override fun onDrawFrame(gl: GL10?) {
|
||||||
|
val animationInterval = mAnimationInterval
|
||||||
|
if (animationInterval == null) {
|
||||||
nativeRender()
|
nativeRender()
|
||||||
|
} else {
|
||||||
|
nativeRender()
|
||||||
|
|
||||||
|
var now = System.nanoTime()
|
||||||
|
var interval = now - this.lastTickInNanoSeconds
|
||||||
|
|
||||||
|
if (interval < animationInterval) {
|
||||||
|
try {
|
||||||
|
Thread.sleep((animationInterval - interval) / NANOSECONDS_PER_MICROSECOND)
|
||||||
|
} catch (e: Exception) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
lastTickInNanoSeconds = System.nanoTime()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun handleActionDown(id: Int, x: Float, y: Float) {
|
fun handleActionDown(id: Int, x: Float, y: Float) {
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M200,520L200,440L760,440L760,520L200,520Z"/>
|
||||||
|
</vector>
|
||||||
@@ -141,6 +141,7 @@
|
|||||||
<string name="preference_display_mode_default">Default</string>
|
<string name="preference_display_mode_default">Default</string>
|
||||||
|
|
||||||
<string name="preference_custom_aspect_ratio_name">Aspect ratio</string>
|
<string name="preference_custom_aspect_ratio_name">Aspect ratio</string>
|
||||||
|
<string name="preference_custom_aspect_ratio_description">Limits aspect ratio of the game.</string>
|
||||||
<string name="preference_custom_aspect_ratio_select">Select aspect ratio</string>
|
<string name="preference_custom_aspect_ratio_select">Select aspect ratio</string>
|
||||||
<string name="preference_custom_aspect_ratio_16x9">16:9</string>
|
<string name="preference_custom_aspect_ratio_16x9">16:9</string>
|
||||||
<string name="preference_custom_aspect_ratio_16x10">16:10</string>
|
<string name="preference_custom_aspect_ratio_16x10">16:10</string>
|
||||||
@@ -148,9 +149,23 @@
|
|||||||
<string name="preference_custom_aspect_ratio_1x1">1:1</string>
|
<string name="preference_custom_aspect_ratio_1x1">1:1</string>
|
||||||
|
|
||||||
<string name="preference_screen_zoom_name">Screen zoom</string>
|
<string name="preference_screen_zoom_name">Screen zoom</string>
|
||||||
|
<string name="preference_screen_zoom_description">Reduces the size of the game window.</string>
|
||||||
<string name="preference_screen_zoom_select">Edit screen zoom</string>
|
<string name="preference_screen_zoom_select">Edit screen zoom</string>
|
||||||
<string name="preference_screen_zoom_fit_name">Fit to screen</string>
|
<string name="preference_screen_zoom_fit_name">Fit to screen</string>
|
||||||
|
|
||||||
|
<string name="preference_limit_framerate_name">Limit max framerate</string>
|
||||||
|
<string name="preference_limit_framerate_description">Limits framerate during rendering.</string>
|
||||||
|
<string name="preference_limit_framerate_select">Edit maximum framerate</string>
|
||||||
|
<string name="preference_limit_framerate_default">Disabled</string>
|
||||||
|
<string name="preference_limit_framerate_label">Framerate</string>
|
||||||
|
<string name="preference_limit_framerate_suffix">FPS</string>
|
||||||
|
<string name="preference_limit_framerate_value">%1$d FPS</string>
|
||||||
|
<string name="preference_limit_framerate_error_max">This device supports at most %1$s FPS.</string>
|
||||||
|
<string name="preference_limit_framerate_error_min">Framerate must be at least %1$s FPS.</string>
|
||||||
|
<string name="preference_limit_framerate_subtract">Decrement</string>
|
||||||
|
<string name="preference_limit_framerate_add">Increment</string>
|
||||||
|
<string name="preference_limit_framerate_reset">Disable</string>
|
||||||
|
|
||||||
<string name="preference_category_updater">Updates</string>
|
<string name="preference_category_updater">Updates</string>
|
||||||
<string name="preference_update_automatically_name">Enable automatic updates</string>
|
<string name="preference_update_automatically_name">Enable automatic updates</string>
|
||||||
<string name="preference_release_channel_name">Use nightly release channel</string>
|
<string name="preference_release_channel_name">Use nightly release channel</string>
|
||||||
|
|||||||
Reference in new issue
Block a user