add zoom control

This commit is contained in:
Chloe committed 2025-01-19 01:25:49 -07:00
1 parent 10a0670a47
commit 327e9b4d39
6 files changed
+192 -12

No files matched your search

@@ -68,6 +68,8 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
private var displayMode = DisplayMode.DEFAULT
private var forceRefreshRate = false
private var mAspectRatio = 0.0f
private var mScreenZoom = 1.0f
private var mScreenZoomFit = false
override fun onCreate(savedInstanceState: Bundle?) {
setupUIState()
@@ -379,6 +381,15 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
frameLayout.aspectRatio = mAspectRatio
}
if (mScreenZoomFit && mScreenZoom != 1.0f) {
frameLayout.scaleX = 1/mScreenZoom
frameLayout.scaleY = 1/mScreenZoom
}
if (mScreenZoom != 1.0f) {
frameLayout.zoom = mScreenZoom
}
val editTextLayoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
@@ -434,6 +445,8 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
)
mAspectRatio = ratioForPreference(preferenceUtils.getString(PreferenceUtils.Key.CUSTOM_ASPECT_RATIO) ?: "16_9")
mScreenZoom = preferenceUtils.getInt(PreferenceUtils.Key.SCREEN_ZOOM) / 100.0f
mScreenZoomFit = preferenceUtils.getBoolean(PreferenceUtils.Key.SCREEN_ZOOM_FIT)
forceRefreshRate = preferenceUtils.getBoolean(PreferenceUtils.Key.FORCE_HRR)
@@ -366,6 +366,22 @@ fun SettingsScreen(
)
)
}
SettingsRangeCard(
title = stringResource(R.string.preference_screen_zoom_name),
dialogTitle = stringResource(R.string.preference_screen_zoom_select),
preferenceKey = PreferenceUtils.Key.SCREEN_ZOOM,
labelSuffix = "x",
range = 25..100,
scale = 100,
step = 5,
) {
SettingsCard(
title = context.getString(R.string.preference_screen_zoom_fit_name),
preferenceKey = PreferenceUtils.Key.SCREEN_ZOOM_FIT,
asCard = false
)
}
}
OptionsGroup(context.getString(R.string.preference_category_updater)) {
@@ -22,6 +22,7 @@ import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Slider
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
@@ -29,6 +30,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
@@ -48,6 +50,8 @@ import com.geode.launcher.ui.theme.GeodeLauncherTheme
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.roundToInt
fun toggleSetting(context: Context, preferenceKey: PreferenceUtils.Key): Boolean {
@@ -260,6 +264,113 @@ fun StringDialog(
)
}
@Composable
fun RangeDialog(
title: String,
onDismissRequest: () -> Unit,
onSelect: (Int) -> Unit,
labelSuffix: String,
initialValue: Int,
range: IntRange,
scale: Int,
step: Int,
children: @Composable () -> Unit
) {
var enteredValue by remember {
mutableFloatStateOf(initialValue / scale.toFloat())
}
AlertDialog(
onDismissRequest = { onDismissRequest() },
title = {
Text(title)
},
text = {
Column {
Row(
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.weight(1.0f, false)
) {
val precision = log10(scale.toFloat()).roundToInt()
Slider(
value = enteredValue,
onValueChange = { enteredValue = it },
valueRange = (range.first.toFloat()/scale)..(range.last.toFloat()/scale),
steps = ((range.last - range.first) - 1) / step,
modifier = Modifier.weight(1.0f)
)
Text("%.${precision}f$labelSuffix".format(enteredValue))
}
children()
}
},
confirmButton = {
TextButton(onClick = { onSelect((enteredValue * scale).roundToInt()) }) {
Text(stringResource(R.string.message_box_accept))
}
},
dismissButton = {
TextButton(onClick = onDismissRequest) {
Text(stringResource(R.string.message_box_cancel))
}
},
)
}
@Composable
fun SettingsRangeCard(
title: String,
dialogTitle: String,
preferenceKey: PreferenceUtils.Key,
labelSuffix: String,
range: IntRange,
scale: Int,
step: Int,
children: @Composable () -> Unit = {}
) {
var preferenceValue by PreferenceUtils.useIntPreference(preferenceKey)
var showDialog by remember { mutableStateOf(false) }
OptionsCard(
title = { OptionsTitle(title = title) },
modifier = Modifier
.clickable(
onClick = {
showDialog = true
},
role = Role.Button
)
) {
val precision = log10(scale.toFloat()).roundToInt()
val scaledValue = preferenceValue / scale.toFloat()
Text("%.${precision}f$labelSuffix".format(scaledValue))
}
if (showDialog) {
RangeDialog(
title = dialogTitle,
onDismissRequest = { showDialog = false },
onSelect = {
preferenceValue = it
showDialog = false
},
initialValue = preferenceValue,
range = range,
scale = scale,
labelSuffix = labelSuffix,
step = step,
children = children,
)
}
}
internal val LocalSelectValue = compositionLocalOf<Any> { 0 }
internal val LocalSelectSetValue = staticCompositionLocalOf<(Any) -> Unit> { {} }
@@ -367,7 +478,7 @@ fun OptionsButton(title: String, description: String? = null, icon: (@Composable
}
@Composable
fun SettingsCard(title: String, description: String? = null, icon: (@Composable () -> Unit)? = null, preferenceKey: PreferenceUtils.Key) {
fun SettingsCard(title: String, description: String? = null, icon: (@Composable () -> Unit)? = null, asCard: Boolean = true, preferenceKey: PreferenceUtils.Key) {
val context = LocalContext.current
val settingEnabled = remember {
mutableStateOf(getSetting(context, preferenceKey))
@@ -382,13 +493,18 @@ fun SettingsCard(title: String, description: String? = null, icon: (@Composable
icon = icon
)
},
modifier = Modifier.toggleable(
modifier = if (asCard) Modifier.toggleable(
value = settingEnabled.value,
onValueChange = { settingEnabled.value = toggleSetting(context, preferenceKey) },
role = Role.Switch,
)
) else Modifier
) {
Switch(checked = settingEnabled.value, onCheckedChange = null)
Switch(
checked = settingEnabled.value,
onCheckedChange = if (!asCard)
{ _ -> settingEnabled.value = toggleSetting(context, preferenceKey) }
else null
)
}
}
@@ -2,26 +2,52 @@ package com.geode.launcher.utils
import android.content.Context
import android.widget.FrameLayout
import kotlin.math.roundToInt
class ConstrainedFrameLayout(context: Context) : FrameLayout(context) {
// avoid running the aspect ratio fix when we don't need it
var aspectRatio: Float? = null;
var aspectRatio: Float? = null
var zoom: Float? = null
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
if (aspectRatio != null) {
var paddingX = 0
var paddingY = 0
val currentAspectRatio = aspectRatio
if (currentAspectRatio != null) {
val width = MeasureSpec.getSize(widthMeasureSpec)
val height = MeasureSpec.getSize(heightMeasureSpec)
if (width == 0 || height == 0) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
return
}
val calculatedWidth = height * (aspectRatio ?: 1.0f);
val calculatedWidth = height * currentAspectRatio
val padding = ((width - calculatedWidth) / 2).toInt()
// ignore paddings where the screen ends up looking odd
if (padding > 0) {
setPadding(padding, 0, padding, 0)
paddingX += padding
}
val currentZoom = zoom
if (currentZoom != null) {
val width = MeasureSpec.getSize(widthMeasureSpec)
val height = MeasureSpec.getSize(heightMeasureSpec)
if (width == 0 || height == 0) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
return
}
val zoomFactor = 1 - currentZoom
val widthFactor = width/2.0f + paddingX/4.0f
val heightFactor = height/2.0f
paddingX = (widthFactor * zoomFactor).roundToInt()
paddingY = (heightFactor * zoomFactor).roundToInt()
}
if (paddingX > 0 || paddingY > 0) {
setPadding(paddingX, paddingY, paddingX, paddingY)
}
super.onMeasure(
@@ -144,6 +144,8 @@ class PreferenceUtils(private val sharedPreferences: SharedPreferences) {
CLEANUP_APKS,
CUSTOM_SYMBOL_LIST,
CUSTOM_ASPECT_RATIO,
SCREEN_ZOOM,
SCREEN_ZOOM_FIT,
}
private fun defaultValueForBooleanKey(key: Key): Boolean {
@@ -156,6 +158,7 @@ class PreferenceUtils(private val sharedPreferences: SharedPreferences) {
private fun defaultValueForIntKey(key: Key) = when (key) {
Key.DISPLAY_MODE -> if (this.getBoolean(Key.LIMIT_ASPECT_RATIO)) 1 else 0
Key.SCREEN_ZOOM -> 10
// people wanted a reset on nightly anyways, so this is a good excuse to do so
else -> 0
}
@@ -187,6 +190,8 @@ class PreferenceUtils(private val sharedPreferences: SharedPreferences) {
Key.CLEANUP_APKS -> "PreferenceCleanupPackages"
Key.CUSTOM_SYMBOL_LIST -> "PreferenceCustomSymbolList"
Key.CUSTOM_ASPECT_RATIO -> "PreferenceCustomAspectRatio"
Key.SCREEN_ZOOM -> "PreferenceScreenZoom"
Key.SCREEN_ZOOM_FIT -> "PreferenceScreenZoomFit"
}
}