Skip to content

Commit

Permalink
add fps limiting option
Browse files Browse the repository at this point in the history
  • Loading branch information
qimiko committed Jan 19, 2025
1 parent 327e9b4 commit 53cd339
Show file tree
Hide file tree
Showing 8 changed files with 274 additions and 12 deletions.
11 changes: 10 additions & 1 deletion app/src/main/java/com/geode/launcher/GeometryDashActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL

private var displayMode = DisplayMode.DEFAULT
private var forceRefreshRate = false
private var mLimitedRefreshRate: Int? = null
private var mAspectRatio = 0.0f
private var mScreenZoom = 1.0f
private var mScreenZoomFit = false
Expand Down Expand Up @@ -425,10 +426,17 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
val renderer = Cocos2dxRenderer(glSurfaceView)
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
}

if (frameRate != null) {
renderer.limitFrameRate(frameRate)
}

editText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
glSurfaceView.cocos2dxEditText = editText

Expand All @@ -449,6 +457,7 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
mScreenZoomFit = preferenceUtils.getBoolean(PreferenceUtils.Key.SCREEN_ZOOM_FIT)

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) {
val maxRefreshRate = display?.supportedModes?.maxBy { it.refreshRate }?.refreshRate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.provider.DocumentsContract
import android.view.WindowManager
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.OnBackPressedDispatcher
Expand Down Expand Up @@ -52,13 +53,13 @@ import com.geode.launcher.updater.ReleaseViewModel
import com.geode.launcher.ui.theme.GeodeLauncherTheme
import com.geode.launcher.ui.theme.LocalTheme
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.GamePackageUtils
import com.geode.launcher.utils.LaunchUtils
import com.geode.launcher.utils.PreferenceUtils
import java.net.ConnectException
import java.net.UnknownHostException
import kotlin.math.roundToInt

class SettingsActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
Expand Down Expand Up @@ -356,6 +357,7 @@ fun SettingsScreen(
if (currentDisplayMode == 1) {
SettingsStringSelectCard(
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),
preferenceKey = PreferenceUtils.Key.CUSTOM_ASPECT_RATIO,
options = linkedMapOf(
Expand All @@ -369,6 +371,7 @@ fun SettingsScreen(

SettingsRangeCard(
title = stringResource(R.string.preference_screen_zoom_name),
description = stringResource(R.string.preference_screen_zoom_description),
dialogTitle = stringResource(R.string.preference_screen_zoom_select),
preferenceKey = PreferenceUtils.Key.SCREEN_ZOOM,
labelSuffix = "x",
Expand All @@ -382,6 +385,22 @@ fun SettingsScreen(
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)) {
Expand Down
197 changes: 190 additions & 7 deletions app/src/main/java/com/geode/launcher/preferences/SettingsComponents.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@ package com.geode.launcher.preferences
import android.content.Context
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
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.rememberScrollState
import androidx.compose.foundation.selection.toggleable
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Clear
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Card
Expand All @@ -38,6 +42,7 @@ import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.input.KeyboardType
Expand All @@ -51,6 +56,8 @@ import com.geode.launcher.ui.theme.Typography
import com.geode.launcher.utils.LabelledText
import com.geode.launcher.utils.PreferenceUtils
import kotlin.math.log10
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt


Expand Down Expand Up @@ -133,14 +140,15 @@ fun SettingsStringSelectCard(
dialogTitle: String,
preferenceKey: PreferenceUtils.Key,
options: Map<String, String>,
extraSelectBehavior: ((String?) -> Unit)? = null
extraSelectBehavior: ((String?) -> Unit)? = null,
description: String? = null,
) {
val preferenceValue by PreferenceUtils.useStringPreference(preferenceKey)

var showDialog by remember { mutableStateOf(false) }

OptionsCard(
title = { OptionsTitle(title = title) },
title = { OptionsTitle(title = title, description = description) },
modifier = Modifier
.clickable(
onClick = {
Expand Down Expand Up @@ -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
fun SettingsRangeCard(
title: String,
Expand All @@ -331,14 +503,17 @@ fun SettingsRangeCard(
range: IntRange,
scale: Int,
step: Int,
description: String? = null,
children: @Composable () -> Unit = {}
) {
var preferenceValue by PreferenceUtils.useIntPreference(preferenceKey)

var showDialog by remember { mutableStateOf(false) }

OptionsCard(
title = { OptionsTitle(title = title) },
title = {
OptionsTitle(title = title, description = description)
},
modifier = Modifier
.clickable(
onClick = {
Expand Down Expand Up @@ -469,7 +644,8 @@ fun OptionsButton(title: String, description: String? = null, icon: (@Composable
)
},
modifier = Modifier
.clickable(onClick = onClick, role = Role.Button)
.clickable(onClick = onClick, role = Role.Button),
wrapContent = true
) {
if (displayInline && description != null) {
Text(description, textAlign = TextAlign.End)
Expand All @@ -487,7 +663,6 @@ fun SettingsCard(title: String, description: String? = null, icon: (@Composable
OptionsCard(
title = {
OptionsTitle(
Modifier.fillMaxWidth(0.75f),
title = title,
description = description,
icon = icon
Expand Down Expand Up @@ -531,7 +706,7 @@ fun OptionsTitle(modifier: Modifier = Modifier, title: String, description: Stri
}

@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(
modifier
.fillMaxWidth()
Expand All @@ -540,7 +715,15 @@ fun OptionsCard(modifier: Modifier = Modifier, title: @Composable () -> Unit, co
Arrangement.SpaceBetween,
Alignment.CenterVertically,
) {
title()
if (!wrapContent) {
Box(modifier = Modifier.weight(1.0f)) {
title()
}
Spacer(modifier = Modifier.size(12.dp))
} else {
title()
}

content()
}
}
Expand Down
Loading

0 comments on commit 53cd339

Please sign in to comment.