Refactored layout code in preparation for Android custom layout GUI

This commit is contained in:
David Griswold
2024-08-11 15:59:41 +01:00
committed by OpenSauce04
parent c78e893cd7
commit b293a253f5
29 changed files with 453 additions and 244 deletions

View File

@@ -176,22 +176,33 @@ void EmuWindow::TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y) {
void EmuWindow::UpdateCurrentFramebufferLayout(u32 width, u32 height, bool is_portrait_mode) {
Layout::FramebufferLayout layout;
// If in portrait mode, only the MobilePortrait option really makes sense
const Settings::LayoutOption layout_option = is_portrait_mode
? Settings::LayoutOption::MobilePortrait
: Settings::values.layout_option.GetValue();
const auto min_size =
Layout::GetMinimumSizeFromLayout(layout_option, Settings::values.upright_screen.GetValue());
const Settings::LayoutOption layout_option = Settings::values.layout_option.GetValue();
const Settings::PortraitLayoutOption portrait_layout_option =
Settings::values.portrait_layout_option.GetValue();
const auto min_size = is_portrait_mode
? Layout::GetMinimumSizeFromPortraitLayout()
: Layout::GetMinimumSizeFromLayout(
layout_option, Settings::values.upright_screen.GetValue());
if ((Settings::values.custom_layout.GetValue() == true && !is_portrait_mode) ||
(Settings::values.custom_portrait_layout.GetValue() == true && is_portrait_mode)) {
layout = Layout::CustomFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
is_portrait_mode);
width = std::max(width, min_size.first);
height = std::max(height, min_size.second);
if (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 {
width = std::max(width, min_size.first);
height = std::max(height, min_size.second);
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:
layout =
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());
break;
#endif
case Settings::LayoutOption::MobilePortrait:
layout = Layout::MobilePortraitFrameLayout(width, height,
Settings::values.swap_screen.GetValue());
break;
case Settings::LayoutOption::MobileLandscape:
layout =
Layout::LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
false, 2.25f, Layout::VerticalAlignment::Top);
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:
default:
layout =
@@ -243,8 +245,9 @@ void EmuWindow::UpdateCurrentFramebufferLayout(u32 width, u32 height, bool is_po
Settings::values.upright_screen.GetValue());
break;
}
UpdateMinimumWindowSize(min_size);
}
UpdateMinimumWindowSize(min_size);
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::CardboardVR) {
layout = Layout::GetCardboardSettings(layout);
}

View File

@@ -117,7 +117,7 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height, bool swapped, bool u
return res;
}
FramebufferLayout MobilePortraitFrameLayout(u32 width, u32 height, bool swapped) {
FramebufferLayout PortraitTopFullFrameLayout(u32 width, u32 height, bool swapped) {
ASSERT(width > 0);
ASSERT(height > 0);
@@ -419,119 +419,126 @@ FramebufferLayout CustomFrameLayout(u32 width, u32 height, bool is_swapped, bool
return res;
}
FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondary) {
bool is_portrait_mode =
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);
}
FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondary,
bool is_portrait) {
int width, height;
switch (Settings::values.layout_option.GetValue()) {
case Settings::LayoutOption::SingleScreen:
#ifndef ANDROID
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 {
if (is_portrait) {
auto layout_option = Settings::values.portrait_layout_option.GetValue();
switch (layout_option) {
case Settings::PortraitLayoutOption::PortraitCustomLayout:
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);
case Settings::PortraitLayoutOption::PortraitTopFullWidth:
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()) {
std::swap(width, height);
}
return SingleFrameLayout(width, height, swap_screens,
Settings::values.upright_screen.GetValue());
}
} else {
auto layout_option = Settings::values.layout_option.GetValue();
switch (layout_option) {
case Settings::LayoutOption::CustomLayout:
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:
if (Settings::values.swap_screen.GetValue()) {
width = (Core::kScreenBottomWidth +
case Settings::LayoutOption::SingleScreen:
#ifndef ANDROID
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 /
static_cast<int>(Settings::values.large_screen_proportion.GetValue())) *
res_scale;
height = Core::kScreenBottomHeight * res_scale;
} else {
width = (Core::kScreenTopWidth +
height = Core::kScreenBottomHeight * res_scale;
} else {
width =
(Core::kScreenTopWidth +
Core::kScreenBottomWidth /
static_cast<int>(Settings::values.large_screen_proportion.GetValue())) *
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;
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();
}
@@ -554,11 +561,27 @@ FramebufferLayout GetCardboardSettings(const FramebufferLayout& layout) {
u32 cardboard_screen_width;
u32 cardboard_screen_height;
switch (Settings::values.layout_option.GetValue()) {
case Settings::LayoutOption::MobileLandscape:
case Settings::LayoutOption::SideScreen:
// If orientation is portrait, only use MobilePortrait
if (!is_portrait) {
if (is_portrait) {
switch (Settings::values.portrait_layout_option.GetValue()) {
case Settings::PortraitLayoutOption::PortraitTopFullWidth:
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;
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_height = is_swapped ? bottom_screen_height : top_screen_height;
if (is_swapped)
@@ -566,28 +589,14 @@ FramebufferLayout GetCardboardSettings(const FramebufferLayout& layout) {
else
bottom_screen_left += top_screen_width;
break;
} else {
[[fallthrough]];
}
case Settings::LayoutOption::SingleScreen:
default:
if (!is_portrait) {
// Default values when using LayoutOption::SingleScreen
case Settings::LayoutOption::SingleScreen:
default:
cardboard_screen_width = is_swapped ? bottom_screen_width : top_screen_width;
cardboard_screen_height = is_swapped ? bottom_screen_height : top_screen_height;
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_user_x_shift =
@@ -620,6 +629,15 @@ FramebufferLayout GetCardboardSettings(const FramebufferLayout& 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,
bool upright_screen) {

View File

@@ -85,13 +85,14 @@ struct FramebufferLayout {
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 height Window framebuffer height in pixels
* @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
*/
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
@@ -152,8 +153,10 @@ FramebufferLayout CustomFrameLayout(u32 width, u32 height, bool is_swapped,
* Convenience method to get frame layout by resolution scale
* Read from the current settings to determine which layout to use.
* @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
@@ -165,4 +168,6 @@ FramebufferLayout GetCardboardSettings(const FramebufferLayout& layout);
std::pair<unsigned, unsigned> GetMinimumSizeFromLayout(Settings::LayoutOption layout,
bool upright_screen);
std::pair<unsigned, unsigned> GetMinimumSizeFromPortraitLayout();
} // namespace Layout