mirror of
https://github.com/Lime3DS/Lime3DS.git
synced 2025-01-09 16:29:25 +01:00
Refactored layout code in preparation for Android custom layout GUI
This commit is contained in:
parent
c5ac6e84da
commit
7e5b83f126
@ -158,8 +158,9 @@ object NativeLibrary {
|
|||||||
/**
|
/**
|
||||||
* Notifies the core emulation that the orientation has changed.
|
* Notifies the core emulation that the orientation has changed.
|
||||||
*/
|
*/
|
||||||
external fun notifyOrientationChange(layoutOption: Int, rotation: Int)
|
external fun notifyOrientationChange(layoutOption: Int, rotation: Int, isPortrait: Boolean)
|
||||||
|
|
||||||
|
external fun notifyPortraitLayoutChange(layoutOption: Int, rotation: Int, isPortrait: Boolean)
|
||||||
/**
|
/**
|
||||||
* Swaps the top and bottom screens.
|
* Swaps the top and bottom screens.
|
||||||
*/
|
*/
|
||||||
@ -266,6 +267,10 @@ object NativeLibrary {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun landscapeScreenLayout(): Int = EmulationMenuSettings.landscapeScreenLayout
|
fun landscapeScreenLayout(): Int = EmulationMenuSettings.landscapeScreenLayout
|
||||||
|
|
||||||
|
@Keep
|
||||||
|
@JvmStatic
|
||||||
|
fun portraitScreenLayout(): Int = EmulationMenuSettings.portraitScreenLayout
|
||||||
|
|
||||||
@Keep
|
@Keep
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun displayAlertMsg(title: String, message: String, yesNo: Boolean): Boolean {
|
fun displayAlertMsg(title: String, message: String, yesNo: Boolean): Boolean {
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright 2023 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
package io.github.lime3ds.android.display
|
||||||
|
|
||||||
|
enum class PortraitScreenLayout(val int: Int) {
|
||||||
|
// These must match what is defined in src/common/settings.h
|
||||||
|
TOP_FULL_WIDTH(0),
|
||||||
|
CUSTOM_PORTRAIT_LAYOUT(1);
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun from(int: Int): PortraitScreenLayout {
|
||||||
|
return entries.firstOrNull { it.int == int } ?: TOP_FULL_WIDTH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -12,8 +12,10 @@ import io.github.lime3ds.android.features.settings.model.Settings
|
|||||||
import io.github.lime3ds.android.features.settings.utils.SettingsFile
|
import io.github.lime3ds.android.features.settings.utils.SettingsFile
|
||||||
import io.github.lime3ds.android.utils.EmulationMenuSettings
|
import io.github.lime3ds.android.utils.EmulationMenuSettings
|
||||||
|
|
||||||
class ScreenAdjustmentUtil(private val windowManager: WindowManager,
|
class ScreenAdjustmentUtil(
|
||||||
private val settings: Settings) {
|
private val windowManager: WindowManager,
|
||||||
|
private val settings: Settings
|
||||||
|
) {
|
||||||
fun swapScreen() {
|
fun swapScreen() {
|
||||||
val isEnabled = !EmulationMenuSettings.swapScreens
|
val isEnabled = !EmulationMenuSettings.swapScreens
|
||||||
EmulationMenuSettings.swapScreens = isEnabled
|
EmulationMenuSettings.swapScreens = isEnabled
|
||||||
@ -25,18 +27,39 @@ class ScreenAdjustmentUtil(private val windowManager: WindowManager,
|
|||||||
settings.saveSetting(BooleanSetting.SWAP_SCREEN, SettingsFile.FILE_NAME_CONFIG)
|
settings.saveSetting(BooleanSetting.SWAP_SCREEN, SettingsFile.FILE_NAME_CONFIG)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Consider how cycling should handle custom layout
|
||||||
|
// right now it simply skips it
|
||||||
fun cycleLayouts() {
|
fun cycleLayouts() {
|
||||||
val nextLayout = (EmulationMenuSettings.landscapeScreenLayout + 1) % ScreenLayout.entries.size
|
val nextLayout = if (NativeLibrary.isPortraitMode) {
|
||||||
changeScreenOrientation(ScreenLayout.from(nextLayout))
|
(EmulationMenuSettings.portraitScreenLayout + 1) % (PortraitScreenLayout.entries.size - 1)
|
||||||
|
} else {
|
||||||
|
(EmulationMenuSettings.landscapeScreenLayout + 1) % (ScreenLayout.entries.size - 1)
|
||||||
|
}
|
||||||
|
settings.loadSettings()
|
||||||
|
|
||||||
|
changeScreenOrientation(nextLayout)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun changeScreenOrientation(layoutOption: ScreenLayout) {
|
fun changePortraitOrientation(layoutOption: Int) {
|
||||||
EmulationMenuSettings.landscapeScreenLayout = layoutOption.int
|
EmulationMenuSettings.portraitScreenLayout = layoutOption
|
||||||
|
NativeLibrary.notifyPortraitLayoutChange(
|
||||||
|
EmulationMenuSettings.portraitScreenLayout,
|
||||||
|
windowManager.defaultDisplay.rotation,
|
||||||
|
NativeLibrary::isPortraitMode.get()
|
||||||
|
)
|
||||||
|
IntSetting.PORTRAIT_SCREEN_LAYOUT.int = layoutOption
|
||||||
|
settings.saveSetting(IntSetting.PORTRAIT_SCREEN_LAYOUT, SettingsFile.FILE_NAME_CONFIG)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun changeScreenOrientation(layoutOption: Int) {
|
||||||
|
EmulationMenuSettings.landscapeScreenLayout = layoutOption
|
||||||
NativeLibrary.notifyOrientationChange(
|
NativeLibrary.notifyOrientationChange(
|
||||||
EmulationMenuSettings.landscapeScreenLayout,
|
EmulationMenuSettings.landscapeScreenLayout,
|
||||||
windowManager.defaultDisplay.rotation
|
windowManager.defaultDisplay.rotation,
|
||||||
|
NativeLibrary::isPortraitMode.get()
|
||||||
)
|
)
|
||||||
IntSetting.SCREEN_LAYOUT.int = layoutOption.int
|
IntSetting.SCREEN_LAYOUT.int = layoutOption
|
||||||
settings.saveSetting(IntSetting.SCREEN_LAYOUT, SettingsFile.FILE_NAME_CONFIG)
|
settings.saveSetting(IntSetting.SCREEN_LAYOUT, SettingsFile.FILE_NAME_CONFIG)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,17 +6,18 @@ package io.github.lime3ds.android.display
|
|||||||
|
|
||||||
enum class ScreenLayout(val int: Int) {
|
enum class ScreenLayout(val int: Int) {
|
||||||
// These must match what is defined in src/common/settings.h
|
// These must match what is defined in src/common/settings.h
|
||||||
DEFAULT(0),
|
TOP_BOTTOM(0),
|
||||||
SINGLE_SCREEN(1),
|
SINGLE_SCREEN(1),
|
||||||
LARGE_SCREEN(2),
|
LARGE_SCREEN(2),
|
||||||
SIDE_SCREEN(3),
|
SIDE_SCREEN(3),
|
||||||
HYBRID_SCREEN(4),
|
HYBRID_SCREEN(4),
|
||||||
MOBILE_PORTRAIT(5),
|
CUSTOM_LAYOUT(5),
|
||||||
MOBILE_LANDSCAPE(6);
|
MOBILE_LANDSCAPE(6);
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun from(int: Int): ScreenLayout {
|
fun from(int: Int): ScreenLayout {
|
||||||
return entries.firstOrNull { it.int == int } ?: DEFAULT
|
return entries.firstOrNull { it.int == int } ?: MOBILE_LANDSCAPE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ enum class BooleanSetting(
|
|||||||
PLUGIN_LOADER("plugin_loader", Settings.SECTION_SYSTEM, false),
|
PLUGIN_LOADER("plugin_loader", Settings.SECTION_SYSTEM, false),
|
||||||
ALLOW_PLUGIN_LOADER("allow_plugin_loader", Settings.SECTION_SYSTEM, true),
|
ALLOW_PLUGIN_LOADER("allow_plugin_loader", Settings.SECTION_SYSTEM, true),
|
||||||
SWAP_SCREEN("swap_screen", Settings.SECTION_LAYOUT, false),
|
SWAP_SCREEN("swap_screen", Settings.SECTION_LAYOUT, false),
|
||||||
|
CUSTOM_LAYOUT("custom_layout",Settings.SECTION_LAYOUT,false),
|
||||||
ADRENO_GPU_BOOST("adreno_gpu_boost", Settings.SECTION_RENDERER, false);
|
ADRENO_GPU_BOOST("adreno_gpu_boost", Settings.SECTION_RENDERER, false);
|
||||||
|
|
||||||
override var boolean: Boolean = defaultValue
|
override var boolean: Boolean = defaultValue
|
||||||
|
@ -23,6 +23,7 @@ enum class IntSetting(
|
|||||||
CARDBOARD_X_SHIFT("cardboard_x_shift", Settings.SECTION_LAYOUT, 0),
|
CARDBOARD_X_SHIFT("cardboard_x_shift", Settings.SECTION_LAYOUT, 0),
|
||||||
CARDBOARD_Y_SHIFT("cardboard_y_shift", Settings.SECTION_LAYOUT, 0),
|
CARDBOARD_Y_SHIFT("cardboard_y_shift", Settings.SECTION_LAYOUT, 0),
|
||||||
SCREEN_LAYOUT("layout_option", Settings.SECTION_LAYOUT, 0),
|
SCREEN_LAYOUT("layout_option", Settings.SECTION_LAYOUT, 0),
|
||||||
|
PORTRAIT_SCREEN_LAYOUT("portrait_layout_option",Settings.SECTION_LAYOUT,0),
|
||||||
AUDIO_INPUT_TYPE("output_type", Settings.SECTION_AUDIO, 0),
|
AUDIO_INPUT_TYPE("output_type", Settings.SECTION_AUDIO, 0),
|
||||||
NEW_3DS("is_new_3ds", Settings.SECTION_SYSTEM, 1),
|
NEW_3DS("is_new_3ds", Settings.SECTION_SYSTEM, 1),
|
||||||
LLE_APPLETS("lle_applets", Settings.SECTION_SYSTEM, 0),
|
LLE_APPLETS("lle_applets", Settings.SECTION_SYSTEM, 0),
|
||||||
|
@ -131,7 +131,6 @@ class Settings {
|
|||||||
const val KEY_CSTICK_AXIS_HORIZONTAL = "cstick_axis_horizontal"
|
const val KEY_CSTICK_AXIS_HORIZONTAL = "cstick_axis_horizontal"
|
||||||
const val KEY_DPAD_AXIS_VERTICAL = "dpad_axis_vertical"
|
const val KEY_DPAD_AXIS_VERTICAL = "dpad_axis_vertical"
|
||||||
const val KEY_DPAD_AXIS_HORIZONTAL = "dpad_axis_horizontal"
|
const val KEY_DPAD_AXIS_HORIZONTAL = "dpad_axis_horizontal"
|
||||||
|
|
||||||
const val HOTKEY_SCREEN_SWAP = "hotkey_screen_swap"
|
const val HOTKEY_SCREEN_SWAP = "hotkey_screen_swap"
|
||||||
const val HOTKEY_CYCLE_LAYOUT = "hotkey_toggle_layout"
|
const val HOTKEY_CYCLE_LAYOUT = "hotkey_toggle_layout"
|
||||||
const val HOTKEY_CLOSE_GAME = "hotkey_close_game"
|
const val HOTKEY_CLOSE_GAME = "hotkey_close_game"
|
||||||
|
@ -51,6 +51,7 @@ import io.github.lime3ds.android.activities.EmulationActivity
|
|||||||
import io.github.lime3ds.android.databinding.DialogCheckboxBinding
|
import io.github.lime3ds.android.databinding.DialogCheckboxBinding
|
||||||
import io.github.lime3ds.android.databinding.DialogSliderBinding
|
import io.github.lime3ds.android.databinding.DialogSliderBinding
|
||||||
import io.github.lime3ds.android.databinding.FragmentEmulationBinding
|
import io.github.lime3ds.android.databinding.FragmentEmulationBinding
|
||||||
|
import io.github.lime3ds.android.display.PortraitScreenLayout
|
||||||
import io.github.lime3ds.android.display.ScreenAdjustmentUtil
|
import io.github.lime3ds.android.display.ScreenAdjustmentUtil
|
||||||
import io.github.lime3ds.android.display.ScreenLayout
|
import io.github.lime3ds.android.display.ScreenLayout
|
||||||
import io.github.lime3ds.android.features.settings.model.SettingsViewModel
|
import io.github.lime3ds.android.features.settings.model.SettingsViewModel
|
||||||
@ -142,7 +143,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
|||||||
retainInstance = true
|
retainInstance = true
|
||||||
emulationState = EmulationState(game.path)
|
emulationState = EmulationState(game.path)
|
||||||
emulationActivity = requireActivity() as EmulationActivity
|
emulationActivity = requireActivity() as EmulationActivity
|
||||||
screenAdjustmentUtil = ScreenAdjustmentUtil(emulationActivity.windowManager, settingsViewModel.settings)
|
screenAdjustmentUtil =
|
||||||
|
ScreenAdjustmentUtil(emulationActivity.windowManager, settingsViewModel.settings)
|
||||||
EmulationLifecycleUtil.addShutdownHook(hook = { emulationState.stop() })
|
EmulationLifecycleUtil.addShutdownHook(hook = { emulationState.stop() })
|
||||||
EmulationLifecycleUtil.addPauseResumeHook(hook = { togglePause() })
|
EmulationLifecycleUtil.addPauseResumeHook(hook = { togglePause() })
|
||||||
}
|
}
|
||||||
@ -207,16 +209,18 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
binding.inGameMenu.menu.findItem(R.id.menu_lock_drawer).apply {
|
binding.inGameMenu.menu.findItem(R.id.menu_lock_drawer).apply {
|
||||||
val titleId = if (EmulationMenuSettings.drawerLockMode == DrawerLayout.LOCK_MODE_LOCKED_CLOSED) {
|
val titleId =
|
||||||
R.string.unlock_drawer
|
if (EmulationMenuSettings.drawerLockMode == DrawerLayout.LOCK_MODE_LOCKED_CLOSED) {
|
||||||
} else {
|
R.string.unlock_drawer
|
||||||
R.string.lock_drawer
|
} else {
|
||||||
}
|
R.string.lock_drawer
|
||||||
val iconId = if (EmulationMenuSettings.drawerLockMode == DrawerLayout.LOCK_MODE_UNLOCKED) {
|
}
|
||||||
R.drawable.ic_unlocked
|
val iconId =
|
||||||
} else {
|
if (EmulationMenuSettings.drawerLockMode == DrawerLayout.LOCK_MODE_UNLOCKED) {
|
||||||
R.drawable.ic_lock
|
R.drawable.ic_unlocked
|
||||||
}
|
} else {
|
||||||
|
R.drawable.ic_lock
|
||||||
|
}
|
||||||
|
|
||||||
title = getString(titleId)
|
title = getString(titleId)
|
||||||
icon = ResourcesCompat.getDrawable(
|
icon = ResourcesCompat.getDrawable(
|
||||||
@ -267,7 +271,12 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
|||||||
}
|
}
|
||||||
|
|
||||||
R.id.menu_landscape_screen_layout -> {
|
R.id.menu_landscape_screen_layout -> {
|
||||||
showScreenLayoutMenu()
|
showLandscapeScreenLayoutMenu()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.menu_portrait_screen_layout -> {
|
||||||
|
showPortraitScreenLayoutMenu()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -423,7 +432,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun togglePause() {
|
private fun togglePause() {
|
||||||
if(emulationState.isPaused) {
|
if (emulationState.isPaused) {
|
||||||
emulationState.unpause()
|
emulationState.unpause()
|
||||||
} else {
|
} else {
|
||||||
emulationState.pause()
|
emulationState.pause()
|
||||||
@ -769,7 +778,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
|||||||
popupMenu.show()
|
popupMenu.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showScreenLayoutMenu() {
|
private fun showLandscapeScreenLayoutMenu() {
|
||||||
val popupMenu = PopupMenu(
|
val popupMenu = PopupMenu(
|
||||||
requireContext(),
|
requireContext(),
|
||||||
binding.inGameMenu.findViewById(R.id.menu_landscape_screen_layout)
|
binding.inGameMenu.findViewById(R.id.menu_landscape_screen_layout)
|
||||||
@ -784,12 +793,12 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
|||||||
ScreenLayout.SIDE_SCREEN.int ->
|
ScreenLayout.SIDE_SCREEN.int ->
|
||||||
R.id.menu_screen_layout_sidebyside
|
R.id.menu_screen_layout_sidebyside
|
||||||
|
|
||||||
ScreenLayout.MOBILE_PORTRAIT.int ->
|
|
||||||
R.id.menu_screen_layout_portrait
|
|
||||||
|
|
||||||
ScreenLayout.HYBRID_SCREEN.int ->
|
ScreenLayout.HYBRID_SCREEN.int ->
|
||||||
R.id.menu_screen_layout_hybrid
|
R.id.menu_screen_layout_hybrid
|
||||||
|
|
||||||
|
ScreenLayout.CUSTOM_LAYOUT.int ->
|
||||||
|
R.id.menu_screen_layout_custom
|
||||||
|
|
||||||
else -> R.id.menu_screen_layout_landscape
|
else -> R.id.menu_screen_layout_landscape
|
||||||
}
|
}
|
||||||
popupMenu.menu.findItem(layoutOptionMenuItem).setChecked(true)
|
popupMenu.menu.findItem(layoutOptionMenuItem).setChecked(true)
|
||||||
@ -797,27 +806,68 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
|||||||
popupMenu.setOnMenuItemClickListener {
|
popupMenu.setOnMenuItemClickListener {
|
||||||
when (it.itemId) {
|
when (it.itemId) {
|
||||||
R.id.menu_screen_layout_landscape -> {
|
R.id.menu_screen_layout_landscape -> {
|
||||||
screenAdjustmentUtil.changeScreenOrientation(ScreenLayout.MOBILE_LANDSCAPE)
|
screenAdjustmentUtil.changeScreenOrientation(ScreenLayout.MOBILE_LANDSCAPE.int)
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.menu_screen_layout_portrait -> {
|
|
||||||
screenAdjustmentUtil.changeScreenOrientation(ScreenLayout.MOBILE_PORTRAIT)
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.menu_screen_layout_single -> {
|
R.id.menu_screen_layout_single -> {
|
||||||
screenAdjustmentUtil.changeScreenOrientation(ScreenLayout.SINGLE_SCREEN)
|
screenAdjustmentUtil.changeScreenOrientation(ScreenLayout.SINGLE_SCREEN.int)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.menu_screen_layout_sidebyside -> {
|
R.id.menu_screen_layout_sidebyside -> {
|
||||||
screenAdjustmentUtil.changeScreenOrientation(ScreenLayout.SIDE_SCREEN)
|
screenAdjustmentUtil.changeScreenOrientation(ScreenLayout.SIDE_SCREEN.int)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.menu_screen_layout_hybrid -> {
|
R.id.menu_screen_layout_hybrid -> {
|
||||||
screenAdjustmentUtil.changeScreenOrientation(ScreenLayout.HYBRID_SCREEN)
|
screenAdjustmentUtil.changeScreenOrientation(ScreenLayout.HYBRID_SCREEN.int)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.menu_screen_layout_custom -> {
|
||||||
|
screenAdjustmentUtil.changeScreenOrientation(ScreenLayout.CUSTOM_LAYOUT.int)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
popupMenu.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showPortraitScreenLayoutMenu() {
|
||||||
|
val popupMenu = PopupMenu(
|
||||||
|
requireContext(),
|
||||||
|
binding.inGameMenu.findViewById(R.id.menu_portrait_screen_layout)
|
||||||
|
)
|
||||||
|
|
||||||
|
popupMenu.menuInflater.inflate(R.menu.menu_portrait_screen_layout, popupMenu.menu)
|
||||||
|
|
||||||
|
val layoutOptionMenuItem = when (EmulationMenuSettings.portraitScreenLayout) {
|
||||||
|
PortraitScreenLayout.TOP_FULL_WIDTH.int ->
|
||||||
|
R.id.menu_portrait_layout_top_full
|
||||||
|
|
||||||
|
PortraitScreenLayout.CUSTOM_PORTRAIT_LAYOUT.int ->
|
||||||
|
R.id.menu_portrait_layout_custom
|
||||||
|
|
||||||
|
else ->
|
||||||
|
R.id.menu_portrait_layout_top_full
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
popupMenu.menu.findItem(layoutOptionMenuItem).setChecked(true)
|
||||||
|
|
||||||
|
popupMenu.setOnMenuItemClickListener {
|
||||||
|
when (it.itemId) {
|
||||||
|
R.id.menu_portrait_layout_top_full -> {
|
||||||
|
screenAdjustmentUtil.changePortraitOrientation(PortraitScreenLayout.TOP_FULL_WIDTH.int)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.menu_portrait_layout_custom -> {
|
||||||
|
screenAdjustmentUtil.changePortraitOrientation(PortraitScreenLayout.CUSTOM_PORTRAIT_LAYOUT.int)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -959,7 +1009,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
|||||||
resetScale("controlScale-" + NativeLibrary.ButtonType.BUTTON_SWAP)
|
resetScale("controlScale-" + NativeLibrary.ButtonType.BUTTON_SWAP)
|
||||||
binding.surfaceInputOverlay.refreshControls()
|
binding.surfaceInputOverlay.refreshControls()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setControlOpacity(opacity: Int) {
|
private fun setControlOpacity(opacity: Int) {
|
||||||
preferences.edit()
|
preferences.edit()
|
||||||
.putInt("controlOpacity", opacity)
|
.putInt("controlOpacity", opacity)
|
||||||
|
@ -7,6 +7,7 @@ package io.github.lime3ds.android.utils
|
|||||||
import androidx.drawerlayout.widget.DrawerLayout
|
import androidx.drawerlayout.widget.DrawerLayout
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import io.github.lime3ds.android.LimeApplication
|
import io.github.lime3ds.android.LimeApplication
|
||||||
|
import io.github.lime3ds.android.display.PortraitScreenLayout
|
||||||
import io.github.lime3ds.android.display.ScreenLayout
|
import io.github.lime3ds.android.display.ScreenLayout
|
||||||
|
|
||||||
object EmulationMenuSettings {
|
object EmulationMenuSettings {
|
||||||
@ -30,13 +31,23 @@ object EmulationMenuSettings {
|
|||||||
var landscapeScreenLayout: Int
|
var landscapeScreenLayout: Int
|
||||||
get() = preferences.getInt(
|
get() = preferences.getInt(
|
||||||
"EmulationMenuSettings_LandscapeScreenLayout",
|
"EmulationMenuSettings_LandscapeScreenLayout",
|
||||||
ScreenLayout.MOBILE_LANDSCAPE.int
|
ScreenLayout.LARGE_SCREEN.int
|
||||||
)
|
)
|
||||||
set(value) {
|
set(value) {
|
||||||
preferences.edit()
|
preferences.edit()
|
||||||
.putInt("EmulationMenuSettings_LandscapeScreenLayout", value)
|
.putInt("EmulationMenuSettings_LandscapeScreenLayout", value)
|
||||||
.apply()
|
.apply()
|
||||||
}
|
}
|
||||||
|
var portraitScreenLayout: Int
|
||||||
|
get() = preferences.getInt(
|
||||||
|
"EmulationMenuSettings_PortraitScreenLayout",
|
||||||
|
PortraitScreenLayout.TOP_FULL_WIDTH.int
|
||||||
|
)
|
||||||
|
set(value) {
|
||||||
|
preferences.edit()
|
||||||
|
.putInt("EmulationMenuSettings_PortraitScreenLayout", value)
|
||||||
|
.apply()
|
||||||
|
}
|
||||||
var showFps: Boolean
|
var showFps: Boolean
|
||||||
get() = preferences.getBoolean("EmulationMenuSettings_ShowFps", false)
|
get() = preferences.getBoolean("EmulationMenuSettings_ShowFps", false)
|
||||||
set(value) {
|
set(value) {
|
||||||
|
@ -174,7 +174,7 @@ void Config::ReadValues() {
|
|||||||
|
|
||||||
// Layout
|
// Layout
|
||||||
Settings::values.layout_option = static_cast<Settings::LayoutOption>(sdl2_config->GetInteger(
|
Settings::values.layout_option = static_cast<Settings::LayoutOption>(sdl2_config->GetInteger(
|
||||||
"Layout", "layout_option", static_cast<int>(Settings::LayoutOption::MobileLandscape)));
|
"Layout", "layout_option", static_cast<int>(Settings::LayoutOption::LargeScreen)));
|
||||||
ReadSetting("Layout", Settings::values.custom_layout);
|
ReadSetting("Layout", Settings::values.custom_layout);
|
||||||
ReadSetting("Layout", Settings::values.custom_top_x);
|
ReadSetting("Layout", Settings::values.custom_top_x);
|
||||||
ReadSetting("Layout", Settings::values.custom_top_y);
|
ReadSetting("Layout", Settings::values.custom_top_y);
|
||||||
@ -188,7 +188,10 @@ void Config::ReadValues() {
|
|||||||
ReadSetting("Layout", Settings::values.cardboard_x_shift);
|
ReadSetting("Layout", Settings::values.cardboard_x_shift);
|
||||||
ReadSetting("Layout", Settings::values.cardboard_y_shift);
|
ReadSetting("Layout", Settings::values.cardboard_y_shift);
|
||||||
|
|
||||||
ReadSetting("Layout", Settings::values.custom_portrait_layout);
|
Settings::values.portrait_layout_option =
|
||||||
|
static_cast<Settings::PortraitLayoutOption>(sdl2_config->GetInteger(
|
||||||
|
"Layout", "portrait_layout_option",
|
||||||
|
static_cast<int>(Settings::PortraitLayoutOption::PortraitTopFullWidth)));
|
||||||
ReadSetting("Layout", Settings::values.custom_portrait_top_x);
|
ReadSetting("Layout", Settings::values.custom_portrait_top_x);
|
||||||
ReadSetting("Layout", Settings::values.custom_portrait_top_y);
|
ReadSetting("Layout", Settings::values.custom_portrait_top_y);
|
||||||
ReadSetting("Layout", Settings::values.custom_portrait_top_width);
|
ReadSetting("Layout", Settings::values.custom_portrait_top_width);
|
||||||
|
@ -179,15 +179,15 @@ anaglyph_shader_name =
|
|||||||
filter_mode =
|
filter_mode =
|
||||||
|
|
||||||
[Layout]
|
[Layout]
|
||||||
# Layout for the screen inside the render window.
|
# Layout for the screen inside the render window, landscape mode
|
||||||
# 0 (default): Default Top Bottom Screen, 1: Single Screen Only, 2: Large Screen Small Screen, 3: Side by Side
|
# 0 (default): Default Top Bottom Screen,
|
||||||
|
# 1: Single Screen Only,
|
||||||
|
# 2: Large Screen Small Screen
|
||||||
|
# 3: Side by Side
|
||||||
|
# 4: Hybrid
|
||||||
|
# 5: Custom Layout
|
||||||
layout_option =
|
layout_option =
|
||||||
|
|
||||||
# Toggle custom layout (using the settings below) on or off.
|
|
||||||
# Only applies to landscape on Android
|
|
||||||
# 0 (default): Off, 1: On
|
|
||||||
custom_layout =
|
|
||||||
|
|
||||||
# Screen placement when using Custom layout option
|
# Screen placement when using Custom layout option
|
||||||
# 0x, 0y is the top left corner of the render window.
|
# 0x, 0y is the top left corner of the render window.
|
||||||
custom_top_x =
|
custom_top_x =
|
||||||
@ -199,12 +199,12 @@ custom_bottom_y =
|
|||||||
custom_bottom_width =
|
custom_bottom_width =
|
||||||
custom_bottom_height =
|
custom_bottom_height =
|
||||||
|
|
||||||
# Custom Layout Options for Android Portrait Mode
|
# Layout for the portrait mode
|
||||||
# Toggle custom layout (using the settings below) on or off.
|
# 0 (default): Top and bottom screens at top, full width
|
||||||
# 0 (default): Off, 1: On
|
# 1: Custom Layout
|
||||||
custom_portrait_layout =
|
portrait_layout_option =
|
||||||
|
|
||||||
# Screen placement when using Custom layout option
|
# Screen placement when using Portrait Custom layout option
|
||||||
# 0x, 0y is the top left corner of the render window.
|
# 0x, 0y is the top left corner of the render window.
|
||||||
custom_portrait_top_x =
|
custom_portrait_top_x =
|
||||||
custom_portrait_top_y =
|
custom_portrait_top_y =
|
||||||
|
@ -27,6 +27,12 @@ static void UpdateLandscapeScreenLayout() {
|
|||||||
IDCache::GetNativeLibraryClass(), IDCache::GetLandscapeScreenLayout()));
|
IDCache::GetNativeLibraryClass(), IDCache::GetLandscapeScreenLayout()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void UpdatePortraitScreenLayout() {
|
||||||
|
Settings::values.portrait_layout_option =
|
||||||
|
static_cast<Settings::PortraitLayoutOption>(IDCache::GetEnvForThread()->CallStaticIntMethod(
|
||||||
|
IDCache::GetNativeLibraryClass(), IDCache::GetPortraitScreenLayout()));
|
||||||
|
}
|
||||||
|
|
||||||
bool EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
|
bool EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
|
||||||
if (render_window == surface) {
|
if (render_window == surface) {
|
||||||
return false;
|
return false;
|
||||||
@ -58,6 +64,7 @@ void EmuWindow_Android::OnTouchMoved(int x, int y) {
|
|||||||
|
|
||||||
void EmuWindow_Android::OnFramebufferSizeChanged() {
|
void EmuWindow_Android::OnFramebufferSizeChanged() {
|
||||||
UpdateLandscapeScreenLayout();
|
UpdateLandscapeScreenLayout();
|
||||||
|
UpdatePortraitScreenLayout();
|
||||||
const bool is_portrait_mode{IsPortraitMode()};
|
const bool is_portrait_mode{IsPortraitMode()};
|
||||||
|
|
||||||
const int bigger{window_width > window_height ? window_width : window_height};
|
const int bigger{window_width > window_height ? window_width : window_height};
|
||||||
|
@ -27,6 +27,7 @@ static jclass s_native_library_class;
|
|||||||
static jmethodID s_on_core_error;
|
static jmethodID s_on_core_error;
|
||||||
static jmethodID s_is_portrait_mode;
|
static jmethodID s_is_portrait_mode;
|
||||||
static jmethodID s_landscape_screen_layout;
|
static jmethodID s_landscape_screen_layout;
|
||||||
|
static jmethodID s_portrait_screen_layout;
|
||||||
static jmethodID s_exit_emulation_activity;
|
static jmethodID s_exit_emulation_activity;
|
||||||
static jmethodID s_request_camera_permission;
|
static jmethodID s_request_camera_permission;
|
||||||
static jmethodID s_request_mic_permission;
|
static jmethodID s_request_mic_permission;
|
||||||
@ -90,6 +91,10 @@ jmethodID GetLandscapeScreenLayout() {
|
|||||||
return s_landscape_screen_layout;
|
return s_landscape_screen_layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jmethodID GetPortraitScreenLayout() {
|
||||||
|
return s_portrait_screen_layout;
|
||||||
|
}
|
||||||
|
|
||||||
jmethodID GetExitEmulationActivity() {
|
jmethodID GetExitEmulationActivity() {
|
||||||
return s_exit_emulation_activity;
|
return s_exit_emulation_activity;
|
||||||
}
|
}
|
||||||
@ -174,6 +179,8 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
|||||||
s_is_portrait_mode = env->GetStaticMethodID(s_native_library_class, "isPortraitMode", "()Z");
|
s_is_portrait_mode = env->GetStaticMethodID(s_native_library_class, "isPortraitMode", "()Z");
|
||||||
s_landscape_screen_layout =
|
s_landscape_screen_layout =
|
||||||
env->GetStaticMethodID(s_native_library_class, "landscapeScreenLayout", "()I");
|
env->GetStaticMethodID(s_native_library_class, "landscapeScreenLayout", "()I");
|
||||||
|
s_portrait_screen_layout =
|
||||||
|
env->GetStaticMethodID(s_native_library_class, "portraitScreenLayout", "()I");
|
||||||
s_exit_emulation_activity =
|
s_exit_emulation_activity =
|
||||||
env->GetStaticMethodID(s_native_library_class, "exitEmulationActivity", "(I)V");
|
env->GetStaticMethodID(s_native_library_class, "exitEmulationActivity", "(I)V");
|
||||||
s_request_camera_permission =
|
s_request_camera_permission =
|
||||||
|
@ -27,6 +27,7 @@ jmethodID GetDisplayAlertPrompt();
|
|||||||
jmethodID GetAlertPromptButton();
|
jmethodID GetAlertPromptButton();
|
||||||
jmethodID GetIsPortraitMode();
|
jmethodID GetIsPortraitMode();
|
||||||
jmethodID GetLandscapeScreenLayout();
|
jmethodID GetLandscapeScreenLayout();
|
||||||
|
jmethodID GetPortraitScreenLayout();
|
||||||
jmethodID GetExitEmulationActivity();
|
jmethodID GetExitEmulationActivity();
|
||||||
jmethodID GetRequestCameraPermission();
|
jmethodID GetRequestCameraPermission();
|
||||||
jmethodID GetRequestMicPermission();
|
jmethodID GetRequestMicPermission();
|
||||||
|
@ -347,9 +347,23 @@ void JNICALL Java_io_github_lime3ds_android_NativeLibrary_enableAdrenoTurboMode(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Java_io_github_lime3ds_android_NativeLibrary_notifyOrientationChange(
|
void Java_io_github_lime3ds_android_NativeLibrary_notifyOrientationChange(
|
||||||
[[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject obj, jint layout_option, jint rotation) {
|
[[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject obj, jint layout_option, jint rotation,
|
||||||
|
jboolean portrait) {
|
||||||
Settings::values.layout_option = static_cast<Settings::LayoutOption>(layout_option);
|
Settings::values.layout_option = static_cast<Settings::LayoutOption>(layout_option);
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = Core::System::GetInstance();
|
||||||
|
if (system.IsPoweredOn()) {
|
||||||
|
|
||||||
|
system.GPU().Renderer().UpdateCurrentFramebufferLayout(portrait);
|
||||||
|
}
|
||||||
|
InputManager::screen_rotation = rotation;
|
||||||
|
Camera::NDK::g_rotation = rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Java_io_github_lime3ds_android_NativeLibrary_notifyPortraitLayoutChange(
|
||||||
|
[[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject obj, jint layout_option, jint rotation) {
|
||||||
|
Settings::values.portrait_layout_option =
|
||||||
|
static_cast<Settings::PortraitLayoutOption>(layout_option);
|
||||||
|
auto& system = Core::System::GetInstance();
|
||||||
if (system.IsPoweredOn()) {
|
if (system.IsPoweredOn()) {
|
||||||
system.GPU().Renderer().UpdateCurrentFramebufferLayout(!(rotation % 2));
|
system.GPU().Renderer().UpdateCurrentFramebufferLayout(!(rotation % 2));
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@
|
|||||||
<menu>
|
<menu>
|
||||||
<group android:checkableBehavior="single">
|
<group android:checkableBehavior="single">
|
||||||
<item
|
<item
|
||||||
android:id="@+id/menu_screen_layout_landscape"
|
android:id="@+id/menu_portrait_layout_top_full"
|
||||||
android:title="@string/emulation_screen_layout_landscape" />
|
android:title="@string/emulation_screen_layout_landscape" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
|
@ -27,6 +27,11 @@
|
|||||||
android:icon="@drawable/ic_fit_screen"
|
android:icon="@drawable/ic_fit_screen"
|
||||||
android:title="@string/emulation_switch_screen_layout" />
|
android:title="@string/emulation_switch_screen_layout" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_portrait_screen_layout"
|
||||||
|
android:icon="@drawable/ic_fit_screen"
|
||||||
|
android:title="@string/emulation_switch_portrait_layout" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/menu_swap_screens"
|
android:id="@+id/menu_swap_screens"
|
||||||
android:icon="@drawable/ic_splitscreen"
|
android:icon="@drawable/ic_splitscreen"
|
||||||
|
@ -7,10 +7,6 @@
|
|||||||
android:id="@+id/menu_screen_layout_landscape"
|
android:id="@+id/menu_screen_layout_landscape"
|
||||||
android:title="@string/emulation_screen_layout_landscape" />
|
android:title="@string/emulation_screen_layout_landscape" />
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/menu_screen_layout_portrait"
|
|
||||||
android:title="@string/emulation_screen_layout_portrait" />
|
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/menu_screen_layout_single"
|
android:id="@+id/menu_screen_layout_single"
|
||||||
android:title="@string/emulation_screen_layout_single" />
|
android:title="@string/emulation_screen_layout_single" />
|
||||||
@ -23,6 +19,9 @@
|
|||||||
android:id="@+id/menu_screen_layout_hybrid"
|
android:id="@+id/menu_screen_layout_hybrid"
|
||||||
android:title="@string/emulation_screen_layout_hybrid" />
|
android:title="@string/emulation_screen_layout_hybrid" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_screen_layout_custom"
|
||||||
|
android:title="@string/emulation_screen_layout_custom" />
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<group android:checkableBehavior="single">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_portrait_layout_top_full"
|
||||||
|
android:title="@string/emulation_portrait_layout_top_full" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_portrait_layout_custom"
|
||||||
|
android:title="@string/emulation_screen_layout_custom" />
|
||||||
|
</group>
|
||||||
|
|
||||||
|
</menu>
|
@ -359,12 +359,15 @@
|
|||||||
<string name="emulation_open_settings">Open Settings</string>
|
<string name="emulation_open_settings">Open Settings</string>
|
||||||
<string name="emulation_open_cheats">Open Cheats</string>
|
<string name="emulation_open_cheats">Open Cheats</string>
|
||||||
<string name="emulation_switch_screen_layout">Landscape Screen Layout</string>
|
<string name="emulation_switch_screen_layout">Landscape Screen Layout</string>
|
||||||
|
<string name="emulation_switch_portrait_layout">Portrait Screen Layout</string>
|
||||||
<string name="emulation_screen_layout_landscape">Default</string>
|
<string name="emulation_screen_layout_landscape">Default</string>
|
||||||
<string name="emulation_screen_layout_portrait">Portrait</string>
|
<string name="emulation_screen_layout_portrait">Portrait</string>
|
||||||
<string name="emulation_screen_layout_single">Single Screen</string>
|
<string name="emulation_screen_layout_single">Single Screen</string>
|
||||||
<string name="emulation_screen_layout_sidebyside">Side by Side Screens</string>
|
<string name="emulation_screen_layout_sidebyside">Side by Side Screens</string>
|
||||||
<string name="emulation_screen_layout_hybrid">Hybrid Screens</string>
|
<string name="emulation_screen_layout_hybrid">Hybrid Screens</string>
|
||||||
<string name="emulation_cycle_landscape_layouts">Cycle Landscape Layouts</string>
|
<string name="emulation_portrait_layout_top_full">Default</string>
|
||||||
|
<string name="emulation_screen_layout_custom">Custom Layout</string>
|
||||||
|
<string name="emulation_cycle_landscape_layouts">Cycle Layouts</string>
|
||||||
<string name="emulation_swap_screens">Swap Screens</string>
|
<string name="emulation_swap_screens">Swap Screens</string>
|
||||||
<string name="emulation_touch_overlay_reset">Reset Overlay</string>
|
<string name="emulation_touch_overlay_reset">Reset Overlay</string>
|
||||||
<string name="emulation_show_overlay">Show Overlay</string>
|
<string name="emulation_show_overlay">Show Overlay</string>
|
||||||
|
@ -108,6 +108,7 @@ void LogSettings() {
|
|||||||
log_setting("Renderer_AnaglyphShader", values.anaglyph_shader_name.GetValue());
|
log_setting("Renderer_AnaglyphShader", values.anaglyph_shader_name.GetValue());
|
||||||
}
|
}
|
||||||
log_setting("Layout_LayoutOption", values.layout_option.GetValue());
|
log_setting("Layout_LayoutOption", values.layout_option.GetValue());
|
||||||
|
log_setting("Layout_PortraitLayoutOption", values.portrait_layout_option.GetValue());
|
||||||
log_setting("Layout_SwapScreen", values.swap_screen.GetValue());
|
log_setting("Layout_SwapScreen", values.swap_screen.GetValue());
|
||||||
log_setting("Layout_UprightScreen", values.upright_screen.GetValue());
|
log_setting("Layout_UprightScreen", values.upright_screen.GetValue());
|
||||||
log_setting("Layout_LargeScreenProportion", values.large_screen_proportion.GetValue());
|
log_setting("Layout_LargeScreenProportion", values.large_screen_proportion.GetValue());
|
||||||
@ -196,6 +197,7 @@ void RestoreGlobalState(bool is_powered_on) {
|
|||||||
values.texture_filter.SetGlobal(true);
|
values.texture_filter.SetGlobal(true);
|
||||||
values.texture_sampling.SetGlobal(true);
|
values.texture_sampling.SetGlobal(true);
|
||||||
values.layout_option.SetGlobal(true);
|
values.layout_option.SetGlobal(true);
|
||||||
|
values.portrait_layout_option.SetGlobal(true);
|
||||||
values.swap_screen.SetGlobal(true);
|
values.swap_screen.SetGlobal(true);
|
||||||
values.upright_screen.SetGlobal(true);
|
values.upright_screen.SetGlobal(true);
|
||||||
values.large_screen_proportion.SetGlobal(true);
|
values.large_screen_proportion.SetGlobal(true);
|
||||||
|
@ -33,6 +33,7 @@ enum class InitTicks : u32 {
|
|||||||
Fixed = 1,
|
Fixed = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Defines the layout option for desktop and mobile landscape */
|
||||||
enum class LayoutOption : u32 {
|
enum class LayoutOption : u32 {
|
||||||
Default,
|
Default,
|
||||||
SingleScreen,
|
SingleScreen,
|
||||||
@ -42,18 +43,20 @@ enum class LayoutOption : u32 {
|
|||||||
SeparateWindows,
|
SeparateWindows,
|
||||||
#endif
|
#endif
|
||||||
HybridScreen,
|
HybridScreen,
|
||||||
#ifndef ANDROID // TODO: Implement custom layouts on Android
|
|
||||||
CustomLayout,
|
CustomLayout,
|
||||||
#endif
|
|
||||||
// Similiar to default, but better for mobile devices in portrait mode. Top screen in clamped to
|
|
||||||
// the top of the frame, and the bottom screen is enlarged to match the top screen.
|
|
||||||
MobilePortrait,
|
|
||||||
|
|
||||||
// Similiar to LargeScreen, but better for mobile devices in landscape mode. The screens are
|
// Similiar to LargeScreen, but better for mobile devices in landscape mode. The screens are
|
||||||
// clamped to the top of the frame, and the bottom screen is a bit bigger.
|
// clamped to the top of the frame, and the bottom screen is a bit bigger.
|
||||||
MobileLandscape,
|
MobileLandscape,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Defines the layout option for mobile portrait */
|
||||||
|
enum class PortraitLayoutOption : u32 {
|
||||||
|
// formerly mobile portrait
|
||||||
|
PortraitTopFullWidth,
|
||||||
|
PortraitCustomLayout,
|
||||||
|
};
|
||||||
|
|
||||||
enum class StereoRenderOption : u32 {
|
enum class StereoRenderOption : u32 {
|
||||||
Off = 0,
|
Off = 0,
|
||||||
SideBySide = 1,
|
SideBySide = 1,
|
||||||
@ -482,21 +485,22 @@ struct Values {
|
|||||||
SwitchableSetting<TextureFilter> texture_filter{TextureFilter::None, "texture_filter"};
|
SwitchableSetting<TextureFilter> texture_filter{TextureFilter::None, "texture_filter"};
|
||||||
SwitchableSetting<TextureSampling> texture_sampling{TextureSampling::GameControlled,
|
SwitchableSetting<TextureSampling> texture_sampling{TextureSampling::GameControlled,
|
||||||
"texture_sampling"};
|
"texture_sampling"};
|
||||||
|
|
||||||
SwitchableSetting<LayoutOption> layout_option{LayoutOption::Default, "layout_option"};
|
SwitchableSetting<LayoutOption> layout_option{LayoutOption::Default, "layout_option"};
|
||||||
SwitchableSetting<bool> swap_screen{false, "swap_screen"};
|
SwitchableSetting<bool> swap_screen{false, "swap_screen"};
|
||||||
SwitchableSetting<bool> upright_screen{false, "upright_screen"};
|
SwitchableSetting<bool> upright_screen{false, "upright_screen"};
|
||||||
SwitchableSetting<float, true> large_screen_proportion{4.f, 1.f, 16.f,
|
SwitchableSetting<float, true> large_screen_proportion{4.f, 1.f, 16.f,
|
||||||
"large_screen_proportion"};
|
"large_screen_proportion"};
|
||||||
|
// I think the custom_layout setting below is no longer needed
|
||||||
|
// since custom layout is now just part of the layout option above?
|
||||||
Setting<bool> custom_layout{false, "custom_layout"};
|
Setting<bool> custom_layout{false, "custom_layout"};
|
||||||
Setting<u16> custom_top_x{0, "custom_top_x"};
|
Setting<u16> custom_top_x{0, "custom_top_x"};
|
||||||
Setting<u16> custom_top_y{0, "custom_top_y"};
|
Setting<u16> custom_top_y{0, "custom_top_y"};
|
||||||
Setting<u16> custom_top_width{400, "custom_top_width"};
|
Setting<u16> custom_top_width{800, "custom_top_width"};
|
||||||
Setting<u16> custom_top_height{240, "custom_top_height"};
|
Setting<u16> custom_top_height{480, "custom_top_height"};
|
||||||
Setting<u16> custom_bottom_x{40, "custom_bottom_x"};
|
Setting<u16> custom_bottom_x{80, "custom_bottom_x"};
|
||||||
Setting<u16> custom_bottom_y{240, "custom_bottom_y"};
|
Setting<u16> custom_bottom_y{500, "custom_bottom_y"};
|
||||||
Setting<u16> custom_bottom_width{320, "custom_bottom_width"};
|
Setting<u16> custom_bottom_width{640, "custom_bottom_width"};
|
||||||
Setting<u16> custom_bottom_height{240, "custom_bottom_height"};
|
Setting<u16> custom_bottom_height{480, "custom_bottom_height"};
|
||||||
Setting<u16> custom_second_layer_opacity{100, "custom_second_layer_opacity"};
|
Setting<u16> custom_second_layer_opacity{100, "custom_second_layer_opacity"};
|
||||||
|
|
||||||
SwitchableSetting<bool> screen_top_stretch{false, "screen_top_stretch"};
|
SwitchableSetting<bool> screen_top_stretch{false, "screen_top_stretch"};
|
||||||
@ -506,14 +510,15 @@ struct Values {
|
|||||||
Setting<u16> screen_bottom_leftright_padding{0, "screen_bottom_leftright_padding"};
|
Setting<u16> screen_bottom_leftright_padding{0, "screen_bottom_leftright_padding"};
|
||||||
Setting<u16> screen_bottom_topbottom_padding{0, "screen_bottom_topbottom_padding"};
|
Setting<u16> screen_bottom_topbottom_padding{0, "screen_bottom_topbottom_padding"};
|
||||||
|
|
||||||
Setting<bool> custom_portrait_layout{false, "custom_portrait_layout"};
|
SwitchableSetting<PortraitLayoutOption> portrait_layout_option{
|
||||||
|
PortraitLayoutOption::PortraitTopFullWidth, "portrait_layout_option"};
|
||||||
Setting<u16> custom_portrait_top_x{0, "custom_portrait_top_x"};
|
Setting<u16> custom_portrait_top_x{0, "custom_portrait_top_x"};
|
||||||
Setting<u16> custom_portrait_top_y{0, "custom_portrait_top_y"};
|
Setting<u16> custom_portrait_top_y{0, "custom_portrait_top_y"};
|
||||||
Setting<u16> custom_portrait_top_width{400, "custom_portrait_top_width"};
|
Setting<u16> custom_portrait_top_width{800, "custom_portrait_top_width"};
|
||||||
Setting<u16> custom_portrait_top_height{240, "custom_portrait_top_height"};
|
Setting<u16> custom_portrait_top_height{480, "custom_portrait_top_height"};
|
||||||
Setting<u16> custom_portrait_bottom_x{40, "custom_portrait_bottom_x"};
|
Setting<u16> custom_portrait_bottom_x{80, "custom_portrait_bottom_x"};
|
||||||
Setting<u16> custom_portrait_bottom_y{240, "custom_portrait_bottom_y"};
|
Setting<u16> custom_portrait_bottom_y{500, "custom_portrait_bottom_y"};
|
||||||
Setting<u16> custom_portrait_bottom_width{360, "custom_portrait_bottom_width"};
|
Setting<u16> custom_portrait_bottom_width{640, "custom_portrait_bottom_width"};
|
||||||
Setting<u16> custom_portrait_bottom_height{480, "custom_portrait_bottom_height"};
|
Setting<u16> custom_portrait_bottom_height{480, "custom_portrait_bottom_height"};
|
||||||
|
|
||||||
SwitchableSetting<float> bg_red{0.f, "bg_red"};
|
SwitchableSetting<float> bg_red{0.f, "bg_red"};
|
||||||
|
@ -176,22 +176,33 @@ void EmuWindow::TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y) {
|
|||||||
void EmuWindow::UpdateCurrentFramebufferLayout(u32 width, u32 height, bool is_portrait_mode) {
|
void EmuWindow::UpdateCurrentFramebufferLayout(u32 width, u32 height, bool is_portrait_mode) {
|
||||||
Layout::FramebufferLayout layout;
|
Layout::FramebufferLayout layout;
|
||||||
|
|
||||||
// If in portrait mode, only the MobilePortrait option really makes sense
|
const Settings::LayoutOption layout_option = Settings::values.layout_option.GetValue();
|
||||||
const Settings::LayoutOption layout_option = is_portrait_mode
|
const Settings::PortraitLayoutOption portrait_layout_option =
|
||||||
? Settings::LayoutOption::MobilePortrait
|
Settings::values.portrait_layout_option.GetValue();
|
||||||
: Settings::values.layout_option.GetValue();
|
const auto min_size = is_portrait_mode
|
||||||
const auto min_size =
|
? Layout::GetMinimumSizeFromPortraitLayout()
|
||||||
Layout::GetMinimumSizeFromLayout(layout_option, Settings::values.upright_screen.GetValue());
|
: Layout::GetMinimumSizeFromLayout(
|
||||||
|
layout_option, Settings::values.upright_screen.GetValue());
|
||||||
|
|
||||||
if ((Settings::values.custom_layout.GetValue() == true && !is_portrait_mode) ||
|
width = std::max(width, min_size.first);
|
||||||
(Settings::values.custom_portrait_layout.GetValue() == true && is_portrait_mode)) {
|
height = std::max(height, min_size.second);
|
||||||
layout = Layout::CustomFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
|
if (is_portrait_mode) {
|
||||||
is_portrait_mode);
|
switch (portrait_layout_option) {
|
||||||
|
case Settings::PortraitLayoutOption::PortraitTopFullWidth:
|
||||||
|
layout = Layout::PortraitTopFullFrameLayout(width, height,
|
||||||
|
Settings::values.swap_screen.GetValue());
|
||||||
|
break;
|
||||||
|
case Settings::PortraitLayoutOption::PortraitCustomLayout:
|
||||||
|
layout = Layout::CustomFrameLayout(
|
||||||
|
width, height, Settings::values.swap_screen.GetValue(), is_portrait_mode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
width = std::max(width, min_size.first);
|
|
||||||
height = std::max(height, min_size.second);
|
|
||||||
|
|
||||||
switch (layout_option) {
|
switch (layout_option) {
|
||||||
|
case Settings::LayoutOption::CustomLayout:
|
||||||
|
layout = Layout::CustomFrameLayout(
|
||||||
|
width, height, Settings::values.swap_screen.GetValue(), is_portrait_mode);
|
||||||
|
break;
|
||||||
case Settings::LayoutOption::SingleScreen:
|
case Settings::LayoutOption::SingleScreen:
|
||||||
layout =
|
layout =
|
||||||
Layout::SingleFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
|
Layout::SingleFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
|
||||||
@ -221,21 +232,12 @@ void EmuWindow::UpdateCurrentFramebufferLayout(u32 width, u32 height, bool is_po
|
|||||||
Settings::values.upright_screen.GetValue());
|
Settings::values.upright_screen.GetValue());
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case Settings::LayoutOption::MobilePortrait:
|
|
||||||
layout = Layout::MobilePortraitFrameLayout(width, height,
|
|
||||||
Settings::values.swap_screen.GetValue());
|
|
||||||
break;
|
|
||||||
case Settings::LayoutOption::MobileLandscape:
|
case Settings::LayoutOption::MobileLandscape:
|
||||||
layout =
|
layout =
|
||||||
Layout::LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
|
Layout::LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
|
||||||
false, 2.25f, Layout::VerticalAlignment::Top);
|
false, 2.25f, Layout::VerticalAlignment::Top);
|
||||||
break;
|
break;
|
||||||
#ifndef ANDROID // TODO: Implement custom layouts on Android
|
|
||||||
case Settings::LayoutOption::CustomLayout:
|
|
||||||
layout =
|
|
||||||
Layout::CustomFrameLayout(width, height, Settings::values.swap_screen.GetValue());
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case Settings::LayoutOption::Default:
|
case Settings::LayoutOption::Default:
|
||||||
default:
|
default:
|
||||||
layout =
|
layout =
|
||||||
@ -243,8 +245,9 @@ void EmuWindow::UpdateCurrentFramebufferLayout(u32 width, u32 height, bool is_po
|
|||||||
Settings::values.upright_screen.GetValue());
|
Settings::values.upright_screen.GetValue());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
UpdateMinimumWindowSize(min_size);
|
|
||||||
}
|
}
|
||||||
|
UpdateMinimumWindowSize(min_size);
|
||||||
|
|
||||||
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::CardboardVR) {
|
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::CardboardVR) {
|
||||||
layout = Layout::GetCardboardSettings(layout);
|
layout = Layout::GetCardboardSettings(layout);
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height, bool swapped, bool u
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
FramebufferLayout MobilePortraitFrameLayout(u32 width, u32 height, bool swapped) {
|
FramebufferLayout PortraitTopFullFrameLayout(u32 width, u32 height, bool swapped) {
|
||||||
ASSERT(width > 0);
|
ASSERT(width > 0);
|
||||||
ASSERT(height > 0);
|
ASSERT(height > 0);
|
||||||
|
|
||||||
@ -419,119 +419,126 @@ FramebufferLayout CustomFrameLayout(u32 width, u32 height, bool is_swapped, bool
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondary) {
|
FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondary,
|
||||||
bool is_portrait_mode =
|
bool is_portrait) {
|
||||||
Settings::values.layout_option.GetValue() == Settings::LayoutOption::MobilePortrait;
|
|
||||||
if (Settings::values.custom_layout.GetValue() == true && !is_portrait_mode) {
|
|
||||||
return CustomFrameLayout(std::max(Settings::values.custom_top_x.GetValue() +
|
|
||||||
Settings::values.custom_top_width.GetValue(),
|
|
||||||
Settings::values.custom_bottom_x.GetValue() +
|
|
||||||
Settings::values.custom_bottom_width.GetValue()),
|
|
||||||
std::max(Settings::values.custom_top_y.GetValue() +
|
|
||||||
Settings::values.custom_top_height.GetValue(),
|
|
||||||
Settings::values.custom_bottom_y.GetValue() +
|
|
||||||
Settings::values.custom_bottom_height.GetValue()),
|
|
||||||
Settings::values.swap_screen.GetValue(), is_portrait_mode);
|
|
||||||
} else if (Settings::values.custom_portrait_layout.GetValue() == true && is_portrait_mode) {
|
|
||||||
return CustomFrameLayout(
|
|
||||||
std::max(Settings::values.custom_portrait_top_x.GetValue() +
|
|
||||||
Settings::values.custom_portrait_top_width.GetValue(),
|
|
||||||
Settings::values.custom_portrait_bottom_x.GetValue() +
|
|
||||||
Settings::values.custom_portrait_bottom_width.GetValue()),
|
|
||||||
std::max(Settings::values.custom_portrait_top_y.GetValue() +
|
|
||||||
Settings::values.custom_portrait_top_height.GetValue(),
|
|
||||||
Settings::values.custom_portrait_bottom_y.GetValue() +
|
|
||||||
Settings::values.custom_portrait_bottom_height.GetValue()),
|
|
||||||
Settings::values.swap_screen.GetValue(), is_portrait_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
int width, height;
|
int width, height;
|
||||||
switch (Settings::values.layout_option.GetValue()) {
|
if (is_portrait) {
|
||||||
case Settings::LayoutOption::SingleScreen:
|
auto layout_option = Settings::values.portrait_layout_option.GetValue();
|
||||||
#ifndef ANDROID
|
switch (layout_option) {
|
||||||
case Settings::LayoutOption::SeparateWindows:
|
case Settings::PortraitLayoutOption::PortraitCustomLayout:
|
||||||
#endif
|
return CustomFrameLayout(
|
||||||
{
|
std::max(Settings::values.custom_portrait_top_x.GetValue() +
|
||||||
const bool swap_screens = is_secondary || Settings::values.swap_screen.GetValue();
|
Settings::values.custom_portrait_top_width.GetValue(),
|
||||||
if (swap_screens) {
|
Settings::values.custom_portrait_bottom_x.GetValue() +
|
||||||
width = Core::kScreenBottomWidth * res_scale;
|
Settings::values.custom_portrait_bottom_width.GetValue()),
|
||||||
height = Core::kScreenBottomHeight * res_scale;
|
std::max(Settings::values.custom_portrait_top_y.GetValue() +
|
||||||
} else {
|
Settings::values.custom_portrait_top_height.GetValue(),
|
||||||
|
Settings::values.custom_portrait_bottom_y.GetValue() +
|
||||||
|
Settings::values.custom_portrait_bottom_height.GetValue()),
|
||||||
|
Settings::values.swap_screen.GetValue(), is_portrait);
|
||||||
|
case Settings::PortraitLayoutOption::PortraitTopFullWidth:
|
||||||
width = Core::kScreenTopWidth * res_scale;
|
width = Core::kScreenTopWidth * res_scale;
|
||||||
height = Core::kScreenTopHeight * res_scale;
|
height = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale;
|
||||||
|
return PortraitTopFullFrameLayout(width, height,
|
||||||
|
Settings::values.swap_screen.GetValue());
|
||||||
}
|
}
|
||||||
if (Settings::values.upright_screen.GetValue()) {
|
} else {
|
||||||
std::swap(width, height);
|
auto layout_option = Settings::values.layout_option.GetValue();
|
||||||
}
|
switch (layout_option) {
|
||||||
return SingleFrameLayout(width, height, swap_screens,
|
case Settings::LayoutOption::CustomLayout:
|
||||||
Settings::values.upright_screen.GetValue());
|
return CustomFrameLayout(std::max(Settings::values.custom_top_x.GetValue() +
|
||||||
}
|
Settings::values.custom_top_width.GetValue(),
|
||||||
|
Settings::values.custom_bottom_x.GetValue() +
|
||||||
|
Settings::values.custom_bottom_width.GetValue()),
|
||||||
|
std::max(Settings::values.custom_top_y.GetValue() +
|
||||||
|
Settings::values.custom_top_height.GetValue(),
|
||||||
|
Settings::values.custom_bottom_y.GetValue() +
|
||||||
|
Settings::values.custom_bottom_height.GetValue()),
|
||||||
|
Settings::values.swap_screen.GetValue(), is_portrait);
|
||||||
|
|
||||||
case Settings::LayoutOption::LargeScreen:
|
case Settings::LayoutOption::SingleScreen:
|
||||||
if (Settings::values.swap_screen.GetValue()) {
|
#ifndef ANDROID
|
||||||
width = (Core::kScreenBottomWidth +
|
case Settings::LayoutOption::SeparateWindows:
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
const bool swap_screens = is_secondary || Settings::values.swap_screen.GetValue();
|
||||||
|
if (swap_screens) {
|
||||||
|
width = Core::kScreenBottomWidth * res_scale;
|
||||||
|
height = Core::kScreenBottomHeight * res_scale;
|
||||||
|
} else {
|
||||||
|
width = Core::kScreenTopWidth * res_scale;
|
||||||
|
height = Core::kScreenTopHeight * res_scale;
|
||||||
|
}
|
||||||
|
if (Settings::values.upright_screen.GetValue()) {
|
||||||
|
std::swap(width, height);
|
||||||
|
}
|
||||||
|
return SingleFrameLayout(width, height, swap_screens,
|
||||||
|
Settings::values.upright_screen.GetValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
case Settings::LayoutOption::LargeScreen:
|
||||||
|
if (Settings::values.swap_screen.GetValue()) {
|
||||||
|
width =
|
||||||
|
(Core::kScreenBottomWidth +
|
||||||
Core::kScreenTopWidth /
|
Core::kScreenTopWidth /
|
||||||
static_cast<int>(Settings::values.large_screen_proportion.GetValue())) *
|
static_cast<int>(Settings::values.large_screen_proportion.GetValue())) *
|
||||||
res_scale;
|
res_scale;
|
||||||
height = Core::kScreenBottomHeight * res_scale;
|
height = Core::kScreenBottomHeight * res_scale;
|
||||||
} else {
|
} else {
|
||||||
width = (Core::kScreenTopWidth +
|
width =
|
||||||
|
(Core::kScreenTopWidth +
|
||||||
Core::kScreenBottomWidth /
|
Core::kScreenBottomWidth /
|
||||||
static_cast<int>(Settings::values.large_screen_proportion.GetValue())) *
|
static_cast<int>(Settings::values.large_screen_proportion.GetValue())) *
|
||||||
res_scale;
|
res_scale;
|
||||||
|
height = Core::kScreenTopHeight * res_scale;
|
||||||
|
}
|
||||||
|
if (Settings::values.upright_screen.GetValue()) {
|
||||||
|
std::swap(width, height);
|
||||||
|
}
|
||||||
|
return LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
|
||||||
|
Settings::values.upright_screen.GetValue(),
|
||||||
|
Settings::values.large_screen_proportion.GetValue(),
|
||||||
|
VerticalAlignment::Bottom);
|
||||||
|
|
||||||
|
case Settings::LayoutOption::SideScreen:
|
||||||
|
width = (Core::kScreenTopWidth + Core::kScreenBottomWidth) * res_scale;
|
||||||
height = Core::kScreenTopHeight * res_scale;
|
height = Core::kScreenTopHeight * res_scale;
|
||||||
|
|
||||||
|
if (Settings::values.upright_screen.GetValue()) {
|
||||||
|
std::swap(width, height);
|
||||||
|
}
|
||||||
|
return LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
|
||||||
|
Settings::values.upright_screen.GetValue(), 1,
|
||||||
|
VerticalAlignment::Middle);
|
||||||
|
|
||||||
|
case Settings::LayoutOption::MobileLandscape: {
|
||||||
|
constexpr float large_screen_proportion = 2.25f;
|
||||||
|
if (Settings::values.swap_screen.GetValue()) {
|
||||||
|
width = (Core::kScreenBottomWidth +
|
||||||
|
static_cast<int>(Core::kScreenTopWidth / large_screen_proportion)) *
|
||||||
|
res_scale;
|
||||||
|
height = Core::kScreenBottomHeight * res_scale;
|
||||||
|
} else {
|
||||||
|
width = (Core::kScreenTopWidth +
|
||||||
|
static_cast<int>(Core::kScreenBottomWidth / large_screen_proportion)) *
|
||||||
|
res_scale;
|
||||||
|
height = Core::kScreenTopHeight * res_scale;
|
||||||
|
}
|
||||||
|
return LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(), false,
|
||||||
|
large_screen_proportion, VerticalAlignment::Top);
|
||||||
}
|
}
|
||||||
if (Settings::values.upright_screen.GetValue()) {
|
|
||||||
std::swap(width, height);
|
case Settings::LayoutOption::Default:
|
||||||
|
default:
|
||||||
|
width = Core::kScreenTopWidth * res_scale;
|
||||||
|
height = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale;
|
||||||
|
|
||||||
|
if (Settings::values.upright_screen.GetValue()) {
|
||||||
|
std::swap(width, height);
|
||||||
|
}
|
||||||
|
return DefaultFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
|
||||||
|
Settings::values.upright_screen.GetValue());
|
||||||
}
|
}
|
||||||
return LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
|
|
||||||
Settings::values.upright_screen.GetValue(),
|
|
||||||
Settings::values.large_screen_proportion.GetValue(),
|
|
||||||
VerticalAlignment::Bottom);
|
|
||||||
|
|
||||||
case Settings::LayoutOption::SideScreen:
|
|
||||||
width = (Core::kScreenTopWidth + Core::kScreenBottomWidth) * res_scale;
|
|
||||||
height = Core::kScreenTopHeight * res_scale;
|
|
||||||
|
|
||||||
if (Settings::values.upright_screen.GetValue()) {
|
|
||||||
std::swap(width, height);
|
|
||||||
}
|
|
||||||
return LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
|
|
||||||
Settings::values.upright_screen.GetValue(), 1,
|
|
||||||
VerticalAlignment::Middle);
|
|
||||||
|
|
||||||
case Settings::LayoutOption::MobilePortrait:
|
|
||||||
width = Core::kScreenTopWidth * res_scale;
|
|
||||||
height = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale;
|
|
||||||
return MobilePortraitFrameLayout(width, height, Settings::values.swap_screen.GetValue());
|
|
||||||
|
|
||||||
case Settings::LayoutOption::MobileLandscape: {
|
|
||||||
constexpr float large_screen_proportion = 2.25f;
|
|
||||||
if (Settings::values.swap_screen.GetValue()) {
|
|
||||||
width = (Core::kScreenBottomWidth +
|
|
||||||
static_cast<int>(Core::kScreenTopWidth / large_screen_proportion)) *
|
|
||||||
res_scale;
|
|
||||||
height = Core::kScreenBottomHeight * res_scale;
|
|
||||||
} else {
|
|
||||||
width = (Core::kScreenTopWidth +
|
|
||||||
static_cast<int>(Core::kScreenBottomWidth / large_screen_proportion)) *
|
|
||||||
res_scale;
|
|
||||||
height = Core::kScreenTopHeight * res_scale;
|
|
||||||
}
|
|
||||||
return LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(), false,
|
|
||||||
large_screen_proportion, VerticalAlignment::Top);
|
|
||||||
}
|
|
||||||
|
|
||||||
case Settings::LayoutOption::Default:
|
|
||||||
default:
|
|
||||||
width = Core::kScreenTopWidth * res_scale;
|
|
||||||
height = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale;
|
|
||||||
|
|
||||||
if (Settings::values.upright_screen.GetValue()) {
|
|
||||||
std::swap(width, height);
|
|
||||||
}
|
|
||||||
return DefaultFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
|
|
||||||
Settings::values.upright_screen.GetValue());
|
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
@ -554,11 +561,27 @@ FramebufferLayout GetCardboardSettings(const FramebufferLayout& layout) {
|
|||||||
|
|
||||||
u32 cardboard_screen_width;
|
u32 cardboard_screen_width;
|
||||||
u32 cardboard_screen_height;
|
u32 cardboard_screen_height;
|
||||||
switch (Settings::values.layout_option.GetValue()) {
|
if (is_portrait) {
|
||||||
case Settings::LayoutOption::MobileLandscape:
|
switch (Settings::values.portrait_layout_option.GetValue()) {
|
||||||
case Settings::LayoutOption::SideScreen:
|
case Settings::PortraitLayoutOption::PortraitTopFullWidth:
|
||||||
// If orientation is portrait, only use MobilePortrait
|
cardboard_screen_width = top_screen_width;
|
||||||
if (!is_portrait) {
|
cardboard_screen_height = top_screen_height + bottom_screen_height;
|
||||||
|
bottom_screen_left += (top_screen_width - bottom_screen_width) / 2;
|
||||||
|
if (is_swapped)
|
||||||
|
top_screen_top += bottom_screen_height;
|
||||||
|
else
|
||||||
|
bottom_screen_top += top_screen_height;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
cardboard_screen_width = is_swapped ? bottom_screen_width : top_screen_width;
|
||||||
|
cardboard_screen_height = is_swapped ? bottom_screen_height : top_screen_height;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (Settings::values.layout_option.GetValue()) {
|
||||||
|
case Settings::LayoutOption::MobileLandscape:
|
||||||
|
case Settings::LayoutOption::SideScreen:
|
||||||
|
// If orientation is portrait, only use MobilePortrait
|
||||||
|
|
||||||
cardboard_screen_width = top_screen_width + bottom_screen_width;
|
cardboard_screen_width = top_screen_width + bottom_screen_width;
|
||||||
cardboard_screen_height = is_swapped ? bottom_screen_height : top_screen_height;
|
cardboard_screen_height = is_swapped ? bottom_screen_height : top_screen_height;
|
||||||
if (is_swapped)
|
if (is_swapped)
|
||||||
@ -566,28 +589,14 @@ FramebufferLayout GetCardboardSettings(const FramebufferLayout& layout) {
|
|||||||
else
|
else
|
||||||
bottom_screen_left += top_screen_width;
|
bottom_screen_left += top_screen_width;
|
||||||
break;
|
break;
|
||||||
} else {
|
|
||||||
[[fallthrough]];
|
case Settings::LayoutOption::SingleScreen:
|
||||||
}
|
default:
|
||||||
case Settings::LayoutOption::SingleScreen:
|
|
||||||
default:
|
|
||||||
if (!is_portrait) {
|
|
||||||
// Default values when using LayoutOption::SingleScreen
|
|
||||||
cardboard_screen_width = is_swapped ? bottom_screen_width : top_screen_width;
|
cardboard_screen_width = is_swapped ? bottom_screen_width : top_screen_width;
|
||||||
cardboard_screen_height = is_swapped ? bottom_screen_height : top_screen_height;
|
cardboard_screen_height = is_swapped ? bottom_screen_height : top_screen_height;
|
||||||
break;
|
break;
|
||||||
} else {
|
|
||||||
[[fallthrough]];
|
|
||||||
}
|
}
|
||||||
case Settings::LayoutOption::MobilePortrait:
|
|
||||||
cardboard_screen_width = top_screen_width;
|
|
||||||
cardboard_screen_height = top_screen_height + bottom_screen_height;
|
|
||||||
bottom_screen_left += (top_screen_width - bottom_screen_width) / 2;
|
|
||||||
if (is_swapped)
|
|
||||||
top_screen_top += bottom_screen_height;
|
|
||||||
else
|
|
||||||
bottom_screen_top += top_screen_height;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
s32 cardboard_max_x_shift = (layout.width / 2 - cardboard_screen_width) / 2;
|
s32 cardboard_max_x_shift = (layout.width / 2 - cardboard_screen_width) / 2;
|
||||||
s32 cardboard_user_x_shift =
|
s32 cardboard_user_x_shift =
|
||||||
@ -620,6 +629,15 @@ FramebufferLayout GetCardboardSettings(const FramebufferLayout& layout) {
|
|||||||
|
|
||||||
return new_layout;
|
return new_layout;
|
||||||
}
|
}
|
||||||
|
/*f
|
||||||
|
* TODO: remove this?
|
||||||
|
*/
|
||||||
|
std::pair<unsigned, unsigned> GetMinimumSizeFromPortraitLayout() {
|
||||||
|
u32 min_width, min_height;
|
||||||
|
min_width = Core::kScreenTopWidth;
|
||||||
|
min_height = Core::kScreenTopHeight + Core::kScreenBottomHeight;
|
||||||
|
return std::make_pair(min_width, min_height);
|
||||||
|
}
|
||||||
|
|
||||||
std::pair<unsigned, unsigned> GetMinimumSizeFromLayout(Settings::LayoutOption layout,
|
std::pair<unsigned, unsigned> GetMinimumSizeFromLayout(Settings::LayoutOption layout,
|
||||||
bool upright_screen) {
|
bool upright_screen) {
|
||||||
|
@ -85,13 +85,14 @@ struct FramebufferLayout {
|
|||||||
FramebufferLayout DefaultFrameLayout(u32 width, u32 height, bool is_swapped, bool upright);
|
FramebufferLayout DefaultFrameLayout(u32 width, u32 height, bool is_swapped, bool upright);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory method for constructing a mobile portrait FramebufferLayout
|
* Factory method for constructing the mobile Full Width Top layout
|
||||||
|
* Two screens at top, full width, no gap between them
|
||||||
* @param width Window framebuffer width in pixels
|
* @param width Window framebuffer width in pixels
|
||||||
* @param height Window framebuffer height in pixels
|
* @param height Window framebuffer height in pixels
|
||||||
* @param is_swapped if true, the bottom screen will be displayed above the top screen
|
* @param is_swapped if true, the bottom screen will be displayed above the top screen
|
||||||
* @return Newly created FramebufferLayout object with mobile portrait screen regions initialized
|
* @return Newly created FramebufferLayout object with mobile portrait screen regions initialized
|
||||||
*/
|
*/
|
||||||
FramebufferLayout MobilePortraitFrameLayout(u32 width, u32 height, bool is_swapped);
|
FramebufferLayout PortraitTopFullFrameLayout(u32 width, u32 height, bool is_swapped);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory method for constructing a FramebufferLayout with only the top or bottom screen
|
* Factory method for constructing a FramebufferLayout with only the top or bottom screen
|
||||||
@ -152,8 +153,10 @@ FramebufferLayout CustomFrameLayout(u32 width, u32 height, bool is_swapped,
|
|||||||
* Convenience method to get frame layout by resolution scale
|
* Convenience method to get frame layout by resolution scale
|
||||||
* Read from the current settings to determine which layout to use.
|
* Read from the current settings to determine which layout to use.
|
||||||
* @param res_scale resolution scale factor
|
* @param res_scale resolution scale factor
|
||||||
|
* @param is_portrait_mode defaults to false
|
||||||
*/
|
*/
|
||||||
FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondary = false);
|
FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondary = false,
|
||||||
|
bool is_portrait_mode = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method for transforming a frame layout when using Cardboard VR
|
* Convenience method for transforming a frame layout when using Cardboard VR
|
||||||
@ -165,4 +168,6 @@ FramebufferLayout GetCardboardSettings(const FramebufferLayout& layout);
|
|||||||
std::pair<unsigned, unsigned> GetMinimumSizeFromLayout(Settings::LayoutOption layout,
|
std::pair<unsigned, unsigned> GetMinimumSizeFromLayout(Settings::LayoutOption layout,
|
||||||
bool upright_screen);
|
bool upright_screen);
|
||||||
|
|
||||||
|
std::pair<unsigned, unsigned> GetMinimumSizeFromPortraitLayout();
|
||||||
|
|
||||||
} // namespace Layout
|
} // namespace Layout
|
||||||
|
@ -183,7 +183,7 @@ void Config::ReadValues() {
|
|||||||
ReadSetting("Layout", Settings::values.screen_bottom_leftright_padding);
|
ReadSetting("Layout", Settings::values.screen_bottom_leftright_padding);
|
||||||
ReadSetting("Layout", Settings::values.screen_bottom_topbottom_padding);
|
ReadSetting("Layout", Settings::values.screen_bottom_topbottom_padding);
|
||||||
|
|
||||||
ReadSetting("Layout", Settings::values.custom_portrait_layout);
|
ReadSetting("Layout", Settings::values.portrait_layout_option);
|
||||||
ReadSetting("Layout", Settings::values.custom_portrait_top_x);
|
ReadSetting("Layout", Settings::values.custom_portrait_top_x);
|
||||||
ReadSetting("Layout", Settings::values.custom_portrait_top_y);
|
ReadSetting("Layout", Settings::values.custom_portrait_top_y);
|
||||||
ReadSetting("Layout", Settings::values.custom_portrait_top_width);
|
ReadSetting("Layout", Settings::values.custom_portrait_top_width);
|
||||||
|
@ -538,7 +538,7 @@ void Config::ReadLayoutValues() {
|
|||||||
ReadBasicSetting(Settings::values.screen_bottom_stretch);
|
ReadBasicSetting(Settings::values.screen_bottom_stretch);
|
||||||
ReadBasicSetting(Settings::values.screen_bottom_leftright_padding);
|
ReadBasicSetting(Settings::values.screen_bottom_leftright_padding);
|
||||||
ReadBasicSetting(Settings::values.screen_bottom_topbottom_padding);
|
ReadBasicSetting(Settings::values.screen_bottom_topbottom_padding);
|
||||||
ReadBasicSetting(Settings::values.custom_portrait_layout);
|
ReadBasicSetting(Settings::values.portrait_layout_option);
|
||||||
ReadBasicSetting(Settings::values.custom_portrait_top_x);
|
ReadBasicSetting(Settings::values.custom_portrait_top_x);
|
||||||
ReadBasicSetting(Settings::values.custom_portrait_top_y);
|
ReadBasicSetting(Settings::values.custom_portrait_top_y);
|
||||||
ReadBasicSetting(Settings::values.custom_portrait_top_width);
|
ReadBasicSetting(Settings::values.custom_portrait_top_width);
|
||||||
@ -1099,7 +1099,6 @@ void Config::SaveLayoutValues() {
|
|||||||
WriteBasicSetting(Settings::values.screen_bottom_stretch);
|
WriteBasicSetting(Settings::values.screen_bottom_stretch);
|
||||||
WriteBasicSetting(Settings::values.screen_bottom_leftright_padding);
|
WriteBasicSetting(Settings::values.screen_bottom_leftright_padding);
|
||||||
WriteBasicSetting(Settings::values.screen_bottom_topbottom_padding);
|
WriteBasicSetting(Settings::values.screen_bottom_topbottom_padding);
|
||||||
WriteBasicSetting(Settings::values.custom_portrait_layout);
|
|
||||||
WriteBasicSetting(Settings::values.custom_portrait_top_x);
|
WriteBasicSetting(Settings::values.custom_portrait_top_x);
|
||||||
WriteBasicSetting(Settings::values.custom_portrait_top_y);
|
WriteBasicSetting(Settings::values.custom_portrait_top_y);
|
||||||
WriteBasicSetting(Settings::values.custom_portrait_top_width);
|
WriteBasicSetting(Settings::values.custom_portrait_top_width);
|
||||||
|
@ -634,6 +634,10 @@ void RendererOpenGL::DrawSingleScreenStereo(const ScreenInfo& screen_info_l,
|
|||||||
* Draws the emulated screens to the emulator window.
|
* Draws the emulated screens to the emulator window.
|
||||||
*/
|
*/
|
||||||
void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool flipped) {
|
void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool flipped) {
|
||||||
|
bool isPortrait = false;
|
||||||
|
#ifdef ANDROID
|
||||||
|
isPortrait = layout.height > layout.width;
|
||||||
|
#endif
|
||||||
if (settings.bg_color_update_requested.exchange(false)) {
|
if (settings.bg_color_update_requested.exchange(false)) {
|
||||||
// Update background color before drawing
|
// Update background color before drawing
|
||||||
glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(),
|
glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(),
|
||||||
@ -675,12 +679,12 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f
|
|||||||
if (!Settings::values.swap_screen.GetValue()) {
|
if (!Settings::values.swap_screen.GetValue()) {
|
||||||
DrawTopScreen(layout, top_screen);
|
DrawTopScreen(layout, top_screen);
|
||||||
glUniform1i(uniform_layer, 0);
|
glUniform1i(uniform_layer, 0);
|
||||||
ApplySecondLayerOpacity();
|
ApplySecondLayerOpacity(isPortrait);
|
||||||
DrawBottomScreen(layout, bottom_screen);
|
DrawBottomScreen(layout, bottom_screen);
|
||||||
} else {
|
} else {
|
||||||
DrawBottomScreen(layout, bottom_screen);
|
DrawBottomScreen(layout, bottom_screen);
|
||||||
glUniform1i(uniform_layer, 0);
|
glUniform1i(uniform_layer, 0);
|
||||||
ApplySecondLayerOpacity();
|
ApplySecondLayerOpacity(isPortrait);
|
||||||
DrawTopScreen(layout, top_screen);
|
DrawTopScreen(layout, top_screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -692,11 +696,17 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f
|
|||||||
DrawBottomScreen(layout, additional_screen);
|
DrawBottomScreen(layout, additional_screen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ResetSecondLayerOpacity();
|
ResetSecondLayerOpacity(isPortrait);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererOpenGL::ApplySecondLayerOpacity() {
|
void RendererOpenGL::ApplySecondLayerOpacity(bool isPortrait) {
|
||||||
#ifndef ANDROID // TODO: Implement custom layouts on Android
|
#ifdef ANDROID
|
||||||
|
// TODO: Allow for second layer opacity in portrait mode android
|
||||||
|
if (isPortrait) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if ((Settings::values.layout_option.GetValue() == Settings::LayoutOption::CustomLayout ||
|
if ((Settings::values.layout_option.GetValue() == Settings::LayoutOption::CustomLayout ||
|
||||||
Settings::values.custom_layout) &&
|
Settings::values.custom_layout) &&
|
||||||
Settings::values.custom_second_layer_opacity.GetValue() < 100) {
|
Settings::values.custom_second_layer_opacity.GetValue() < 100) {
|
||||||
@ -706,11 +716,16 @@ void RendererOpenGL::ApplySecondLayerOpacity() {
|
|||||||
state.blend.dst_rgb_func = GL_ONE_MINUS_CONSTANT_ALPHA;
|
state.blend.dst_rgb_func = GL_ONE_MINUS_CONSTANT_ALPHA;
|
||||||
state.blend.color.alpha = Settings::values.custom_second_layer_opacity.GetValue() / 100.0f;
|
state.blend.color.alpha = Settings::values.custom_second_layer_opacity.GetValue() / 100.0f;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererOpenGL::ResetSecondLayerOpacity() {
|
void RendererOpenGL::ResetSecondLayerOpacity(bool isPortrait) {
|
||||||
#ifndef ANDROID // TODO: Implement custom layouts on Android
|
#ifdef ANDROID
|
||||||
|
// TODO: Allow for second layer opacity in portrait mode android
|
||||||
|
if (isPortrait) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if ((Settings::values.layout_option.GetValue() == Settings::LayoutOption::CustomLayout ||
|
if ((Settings::values.layout_option.GetValue() == Settings::LayoutOption::CustomLayout ||
|
||||||
Settings::values.custom_layout) &&
|
Settings::values.custom_layout) &&
|
||||||
Settings::values.custom_second_layer_opacity.GetValue() < 100) {
|
Settings::values.custom_second_layer_opacity.GetValue() < 100) {
|
||||||
@ -720,7 +735,6 @@ void RendererOpenGL::ResetSecondLayerOpacity() {
|
|||||||
state.blend.dst_a_func = GL_ZERO;
|
state.blend.dst_a_func = GL_ZERO;
|
||||||
state.blend.color.alpha = 0.0f;
|
state.blend.color.alpha = 0.0f;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererOpenGL::DrawTopScreen(const Layout::FramebufferLayout& layout,
|
void RendererOpenGL::DrawTopScreen(const Layout::FramebufferLayout& layout,
|
||||||
|
@ -65,8 +65,8 @@ private:
|
|||||||
void ConfigureFramebufferTexture(TextureInfo& texture,
|
void ConfigureFramebufferTexture(TextureInfo& texture,
|
||||||
const Pica::FramebufferConfig& framebuffer);
|
const Pica::FramebufferConfig& framebuffer);
|
||||||
void DrawScreens(const Layout::FramebufferLayout& layout, bool flipped);
|
void DrawScreens(const Layout::FramebufferLayout& layout, bool flipped);
|
||||||
void ApplySecondLayerOpacity();
|
void ApplySecondLayerOpacity(bool isPortrait = false);
|
||||||
void ResetSecondLayerOpacity();
|
void ResetSecondLayerOpacity(bool isPortrait = false);
|
||||||
void DrawBottomScreen(const Layout::FramebufferLayout& layout,
|
void DrawBottomScreen(const Layout::FramebufferLayout& layout,
|
||||||
const Common::Rectangle<u32>& bottom_screen);
|
const Common::Rectangle<u32>& bottom_screen);
|
||||||
void DrawTopScreen(const Layout::FramebufferLayout& layout,
|
void DrawTopScreen(const Layout::FramebufferLayout& layout,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user