port screen layout stuff. encapsulate screen layout code.

This commit is contained in:
Arisotura 2024-05-26 00:16:55 +02:00
parent 2451f3fed8
commit d480808d72
14 changed files with 797 additions and 790 deletions

View File

@ -1,100 +0,0 @@
/*
Copyright 2016-2023 melonDS team
This file is part of melonDS.
melonDS is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option)
any later version.
melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with melonDS. If not, see http://www.gnu.org/licenses/.
*/
#ifndef FRONTENDUTIL_H
#define FRONTENDUTIL_H
#include "types.h"
#include <string>
#include <vector>
namespace melonDS
{
class NDS;
}
namespace Frontend
{
using namespace melonDS;
enum ScreenLayout
{
screenLayout_Natural, // top screen above bottom screen always
screenLayout_Horizontal,
screenLayout_Vertical,
screenLayout_Hybrid,
screenLayout_MAX,
};
enum ScreenRotation
{
screenRot_0Deg,
screenRot_90Deg,
screenRot_180Deg,
screenRot_270Deg,
screenRot_MAX,
};
enum ScreenSizing
{
screenSizing_Even, // both screens get same size
screenSizing_EmphTop, // make top screen as big as possible, fit bottom screen in remaining space
screenSizing_EmphBot,
screenSizing_Auto, // not applied in SetupScreenLayout
screenSizing_TopOnly,
screenSizing_BotOnly,
screenSizing_MAX,
};
// setup the display layout based on the provided display size and parameters
// * screenWidth/screenHeight: size of the host display
// * screenLayout: how the DS screens are laid out
// * rotation: angle at which the DS screens are presented
// * sizing: how the display size is shared between the two screens
// * screenGap: size of the gap between the two screens in pixels
// * integerScale: force screens to be scaled up at integer scaling factors
// * screenSwap: whether to swap the position of both screens
// * topAspect/botAspect: ratio by which to scale the top and bottom screen respectively
void SetupScreenLayout(int screenWidth, int screenHeight,
ScreenLayout screenLayout,
ScreenRotation rotation,
ScreenSizing sizing,
int screenGap,
bool integerScale,
bool swapScreens,
float topAspect, float botAspect);
const int MaxScreenTransforms = 3;
// get a 2x3 transform matrix for each screen and whether it's a top or bottom screen
// note: the transform assumes an origin point at the top left of the display,
// X going right and Y going down
// for each screen the source coordinates should be (0,0) and (256,192)
// 'out' should point to an array of 6*MaxScreenTransforms floats
// 'kind' should point to an array of MaxScreenTransforms ints
// (0 = indicates top screen, 1 = bottom screen)
// returns the amount of screens
int GetScreenTransforms(float* out, int* kind);
// de-transform the provided host display coordinates to get coordinates
// on the bottom screen
bool GetTouchCoords(int& x, int& y, bool clamp);
}
#endif // FRONTENDUTIL_H

View File

@ -16,29 +16,13 @@
with melonDS. If not, see http://www.gnu.org/licenses/.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cmath>
#include <algorithm>
#include "FrontendUtil.h"
#include "ScreenLayout.h"
namespace Frontend
{
float TopScreenMtx[6];
float BotScreenMtx[6];
float HybScreenMtx[6];
float TouchMtx[6];
float HybTouchMtx[6];
bool TopEnable;
bool BotEnable;
bool HybEnable;
int HybScreen;
int HybPrevTouchScreen; // 0:unknown, 1:buttom screen, 2:hybrid screen
void M23_Identity(float* m)
{
m[0] = 1; m[1] = 0;
@ -122,8 +106,22 @@ void M23_Transform(float* m, float& x, float& y)
}
void SetupScreenLayout(int screenWidth, int screenHeight,
ScreenLayout screenLayout,
ScreenLayout::ScreenLayout()
{
M23_Identity(TopScreenMtx);
M23_Identity(BotScreenMtx);
M23_Identity(HybScreenMtx);
M23_Identity(TouchMtx);
M23_Identity(HybTouchMtx);
TopEnable = true;
BotEnable = true;
HybEnable = false;
HybScreen = 0;
HybPrevTouchScreen = 0;
}
void ScreenLayout::Setup(int screenWidth, int screenHeight,
ScreenLayoutType screenLayout,
ScreenRotation rotation,
ScreenSizing sizing,
int screenGap,
@ -448,7 +446,7 @@ void SetupScreenLayout(int screenWidth, int screenHeight,
}
}
int GetScreenTransforms(float* out, int* kind)
int ScreenLayout::GetScreenTransforms(float* out, int* kind)
{
int num = 0;
if (TopEnable)
@ -469,7 +467,7 @@ int GetScreenTransforms(float* out, int* kind)
return num;
}
bool GetTouchCoords(int& x, int& y, bool clamp)
bool ScreenLayout::GetTouchCoords(int& x, int& y, bool clamp)
{
if (HybEnable && HybScreen == 1)
{
@ -548,6 +546,3 @@ bool GetTouchCoords(int& x, int& y, bool clamp)
return false;
}
}

104
src/frontend/ScreenLayout.h Normal file
View File

@ -0,0 +1,104 @@
/*
Copyright 2016-2023 melonDS team
This file is part of melonDS.
melonDS is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option)
any later version.
melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with melonDS. If not, see http://www.gnu.org/licenses/.
*/
#ifndef SCREENLAYOUT_H
#define SCREENLAYOUT_H
enum ScreenLayoutType
{
screenLayout_Natural, // top screen above bottom screen always
screenLayout_Horizontal,
screenLayout_Vertical,
screenLayout_Hybrid,
screenLayout_MAX,
};
enum ScreenRotation
{
screenRot_0Deg,
screenRot_90Deg,
screenRot_180Deg,
screenRot_270Deg,
screenRot_MAX,
};
enum ScreenSizing
{
screenSizing_Even, // both screens get same size
screenSizing_EmphTop, // make top screen as big as possible, fit bottom screen in remaining space
screenSizing_EmphBot,
screenSizing_Auto, // not applied in SetupScreenLayout
screenSizing_TopOnly,
screenSizing_BotOnly,
screenSizing_MAX,
};
const int kMaxScreenTransforms = 3;
class ScreenLayout
{
public:
ScreenLayout();
~ScreenLayout() {}
// setup the display layout based on the provided display size and parameters
// * screenWidth/screenHeight: size of the host display
// * screenLayout: how the DS screens are laid out
// * rotation: angle at which the DS screens are presented
// * sizing: how the display size is shared between the two screens
// * screenGap: size of the gap between the two screens in pixels
// * integerScale: force screens to be scaled up at integer scaling factors
// * screenSwap: whether to swap the position of both screens
// * topAspect/botAspect: ratio by which to scale the top and bottom screen respectively
void Setup(int screenWidth, int screenHeight,
ScreenLayoutType screenLayout,
ScreenRotation rotation,
ScreenSizing sizing,
int screenGap,
bool integerScale,
bool swapScreens,
float topAspect, float botAspect);
// get a 2x3 transform matrix for each screen and whether it's a top or bottom screen
// note: the transform assumes an origin point at the top left of the display,
// X going right and Y going down
// for each screen the source coordinates should be (0,0) and (256,192)
// 'out' should point to an array of 6*MaxScreenTransforms floats
// 'kind' should point to an array of MaxScreenTransforms ints
// (0 = indicates top screen, 1 = bottom screen)
// returns the amount of screens
int GetScreenTransforms(float* out, int* kind);
// de-transform the provided host display coordinates to get coordinates
// on the bottom screen
bool GetTouchCoords(int& x, int& y, bool clamp);
private:
float TopScreenMtx[6];
float BotScreenMtx[6];
float HybScreenMtx[6];
float TouchMtx[6];
float HybTouchMtx[6];
bool TopEnable;
bool BotEnable;
bool HybEnable;
int HybScreen;
int HybPrevTouchScreen; // 0:unknown, 1:buttom screen, 2:hybrid screen
};
#endif // SCREENLAYOUT_H

View File

@ -44,8 +44,7 @@ set(SOURCES_QT_SDL
ArchiveUtil.h
ArchiveUtil.cpp
../Util_Video.cpp
../FrontendUtil.h
../ScreenLayout.cpp
../mic_blow.h
../glad/glad.c

View File

@ -27,7 +27,7 @@
#include "Platform.h"
#include "Config.h"
#include "FrontendUtil.h"
#include "ScreenLayout.h"
#include "main.h"
using namespace std::string_literals;
@ -37,16 +37,6 @@ namespace Config
{
using namespace melonDS;
int ScreenRotation;
int ScreenGap;
int ScreenLayout;
bool ScreenSwap;
int ScreenSizing;
bool IntegerScaling;
int ScreenAspectTop;
int ScreenAspectBot;
bool ScreenFilter;
bool ScreenUseGL;
bool ScreenVSync;
int ScreenVSyncInterval;
@ -108,10 +98,10 @@ RangeList IntRanges =
{"Audio.Interpolation", {0, 3}},
{"Instance*.Audio.Volume", {0, 256}},
{"Mic.InputType", {0, micInputType_MAX-1}},
{"Instance*.Window*.ScreenRotation", {0, Frontend::screenRot_MAX-1}},
{"Instance*.Window*.ScreenRotation", {0, screenRot_MAX-1}},
{"Instance*.Window*.ScreenGap", {0, 500}},
{"Instance*.Window*.ScreenLayout", {0, Frontend::screenLayout_MAX-1}},
{"Instance*.Window*.ScreenSizing", {0, Frontend::screenSizing_MAX-1}},
{"Instance*.Window*.ScreenLayout", {0, screenLayout_MAX-1}},
{"Instance*.Window*.ScreenSizing", {0, screenSizing_MAX-1}},
{"Instance*.Window*.ScreenAspectTop", {0, AspectRatiosNum-1}},
{"Instance*.Window*.ScreenAspectBot", {0, AspectRatiosNum-1}},
{"MP.AudioMode", {0, 2}},

View File

@ -151,16 +151,6 @@ private:
};
extern int ScreenRotation;
extern int ScreenGap;
extern int ScreenLayout;
extern bool ScreenSwap;
extern int ScreenSizing;
extern int ScreenAspectTop;
extern int ScreenAspectBot;
extern bool IntegerScaling;
extern bool ScreenFilter;
extern bool ScreenUseGL;
extern bool ScreenVSync;
extern int ScreenVSyncInterval;

View File

@ -33,7 +33,7 @@
#include "types.h"
#include "version.h"
#include "FrontendUtil.h"
#include "ScreenLayout.h"
#include "Args.h"
#include "NDS.h"
@ -79,19 +79,6 @@ EmuThread::EmuThread(EmuInstance* inst, QObject* parent) : QThread(parent)
EmuRunning = emuStatus_Paused;
EmuPauseStack = EmuPauseStackRunning;
RunningSomething = false;
/*connect(this, SIGNAL(windowUpdate()), mainWindow->panel, SLOT(repaint()));
connect(this, SIGNAL(windowTitleChange(QString)), mainWindow, SLOT(onTitleUpdate(QString)));
connect(this, SIGNAL(windowEmuStart()), mainWindow, SLOT(onEmuStart()));
connect(this, SIGNAL(windowEmuStop()), mainWindow, SLOT(onEmuStop()));
connect(this, SIGNAL(windowEmuPause()), mainWindow->actPause, SLOT(trigger()));
connect(this, SIGNAL(windowEmuReset()), mainWindow->actReset, SLOT(trigger()));
connect(this, SIGNAL(windowEmuFrameStep()), mainWindow->actFrameStep, SLOT(trigger()));
connect(this, SIGNAL(windowLimitFPSChange()), mainWindow->actLimitFramerate, SLOT(trigger()));
connect(this, SIGNAL(screenLayoutChange()), mainWindow->panel, SLOT(onScreenLayoutChanged()));
connect(this, SIGNAL(windowFullscreenToggle()), mainWindow, SLOT(onFullscreenToggled()));
connect(this, SIGNAL(swapScreensToggle()), mainWindow->actScreenSwap, SLOT(trigger()));
connect(this, SIGNAL(screenEmphasisToggle()), mainWindow, SLOT(onScreenEmphasisToggled()));*/
}
void EmuThread::attachWindow(MainWindow* window)
@ -108,7 +95,7 @@ void EmuThread::attachWindow(MainWindow* window)
connect(this, SIGNAL(windowEmuReset()), window->actReset, SLOT(trigger()));
connect(this, SIGNAL(windowEmuFrameStep()), window->actFrameStep, SLOT(trigger()));
connect(this, SIGNAL(windowLimitFPSChange()), window->actLimitFramerate, SLOT(trigger()));
connect(this, SIGNAL(screenLayoutChange()), window->panel, SLOT(onScreenLayoutChanged()));
connect(this, SIGNAL(autoScreenSizingChange(int)), window->panel, SLOT(onAutoScreenSizingChanged(int)));
connect(this, SIGNAL(windowFullscreenToggle()), window, SLOT(onFullscreenToggled()));
connect(this, SIGNAL(swapScreensToggle()), window->actScreenSwap, SLOT(trigger()));
connect(this, SIGNAL(screenEmphasisToggle()), window, SLOT(onScreenEmphasisToggled()));
@ -124,7 +111,7 @@ void EmuThread::detachWindow(MainWindow* window)
disconnect(this, SIGNAL(windowEmuReset()), window->actReset, SLOT(trigger()));
disconnect(this, SIGNAL(windowEmuFrameStep()), window->actFrameStep, SLOT(trigger()));
disconnect(this, SIGNAL(windowLimitFPSChange()), window->actLimitFramerate, SLOT(trigger()));
disconnect(this, SIGNAL(screenLayoutChange()), window->panel, SLOT(onScreenLayoutChanged()));
disconnect(this, SIGNAL(autoScreenSizingChange(int)), window->panel, SLOT(onAutoScreenSizingChanged(int)));
disconnect(this, SIGNAL(windowFullscreenToggle()), window, SLOT(onFullscreenToggled()));
disconnect(this, SIGNAL(swapScreensToggle()), window->actScreenSwap, SLOT(trigger()));
disconnect(this, SIGNAL(screenEmphasisToggle()), window, SLOT(onScreenEmphasisToggled()));
@ -307,7 +294,6 @@ void EmuThread::run()
emuInstance->micProcess();
// auto screen layout
if (Config::ScreenSizing == Frontend::screenSizing_Auto)
{
mainScreenPos[2] = mainScreenPos[1];
mainScreenPos[1] = mainScreenPos[0];
@ -319,20 +305,20 @@ void EmuThread::run()
{
// constant flickering, likely displaying 3D on both screens
// TODO: when both screens are used for 2D only...???
guess = Frontend::screenSizing_Even;
guess = screenSizing_Even;
}
else
{
if (mainScreenPos[0] == 1)
guess = Frontend::screenSizing_EmphTop;
guess = screenSizing_EmphTop;
else
guess = Frontend::screenSizing_EmphBot;
guess = screenSizing_EmphBot;
}
if (guess != autoScreenSizing)
{
autoScreenSizing = guess;
emit screenLayoutChange();
emit autoScreenSizingChange(autoScreenSizing);
}
}

View File

@ -83,7 +83,7 @@ signals:
void windowLimitFPSChange();
void screenLayoutChange();
void autoScreenSizingChange(int sizing);
void windowFullscreenToggle();

View File

@ -59,7 +59,6 @@ using namespace melonDS;
// TEMP
extern bool RunningSomething;
extern int autoScreenSizing;
extern int videoRenderer;
extern bool videoSettingsDirty;
@ -91,6 +90,9 @@ ScreenPanel::ScreenPanel(QWidget* parent) : QWidget(parent)
osdEnabled = false;
osdID = 1;
loadConfig();
setFilter(mainWindow->getWindowConfig().GetBool("ScreenFilter"));
}
ScreenPanel::~ScreenPanel()
@ -99,6 +101,25 @@ ScreenPanel::~ScreenPanel()
delete mouseTimer;
}
void ScreenPanel::loadConfig()
{
auto& cfg = mainWindow->getWindowConfig();
screenRotation = cfg.GetInt("ScreenRotation");
screenGap = cfg.GetInt("ScreenGap");
screenLayout = cfg.GetInt("ScreenLayout");
screenSwap = cfg.GetBool("ScreenSwap");
screenSizing = cfg.GetInt("ScreenSizing");
integerScaling = cfg.GetBool("IntegerScaling");
screenAspectTop = cfg.GetInt("ScreenAspectTop");
screenAspectBot = cfg.GetInt("ScreenAspectBot");
}
void ScreenPanel::setFilter(bool filter)
{
this->filter = filter;
}
void ScreenPanel::setMouseHide(bool enable, int delay)
{
mouseHide = enable;
@ -112,16 +133,16 @@ void ScreenPanel::setupScreenLayout()
int w = width();
int h = height();
int sizing = Config::ScreenSizing;
if (sizing == 3) sizing = autoScreenSizing;
int sizing = screenSizing;
if (sizing == screenSizing_Auto) sizing = autoScreenSizing;
float aspectTop, aspectBot;
for (auto ratio : aspectRatios)
{
if (ratio.id == Config::ScreenAspectTop)
if (ratio.id == screenAspectTop)
aspectTop = ratio.ratio;
if (ratio.id == Config::ScreenAspectBot)
if (ratio.id == screenAspectBot)
aspectBot = ratio.ratio;
}
@ -131,49 +152,49 @@ void ScreenPanel::setupScreenLayout()
if (aspectBot == 0)
aspectBot = ((float) w / h) / (4.f / 3.f);
Frontend::SetupScreenLayout(w, h,
static_cast<Frontend::ScreenLayout>(Config::ScreenLayout),
static_cast<Frontend::ScreenRotation>(Config::ScreenRotation),
static_cast<Frontend::ScreenSizing>(sizing),
Config::ScreenGap,
Config::IntegerScaling != 0,
Config::ScreenSwap != 0,
layout.Setup(w, h,
static_cast<ScreenLayoutType>(screenLayout),
static_cast<ScreenRotation>(screenRotation),
static_cast<ScreenSizing>(sizing),
screenGap,
integerScaling != 0,
screenSwap != 0,
aspectTop,
aspectBot);
numScreens = Frontend::GetScreenTransforms(screenMatrix[0], screenKind);
numScreens = layout.GetScreenTransforms(screenMatrix[0], screenKind);
}
QSize ScreenPanel::screenGetMinSize(int factor = 1)
{
bool isHori = (Config::ScreenRotation == Frontend::screenRot_90Deg
|| Config::ScreenRotation == Frontend::screenRot_270Deg);
int gap = Config::ScreenGap * factor;
bool isHori = (screenRotation == screenRot_90Deg
|| screenRotation == screenRot_270Deg);
int gap = screenGap * factor;
int w = 256 * factor;
int h = 192 * factor;
if (Config::ScreenSizing == Frontend::screenSizing_TopOnly
|| Config::ScreenSizing == Frontend::screenSizing_BotOnly)
if (screenSizing == screenSizing_TopOnly
|| screenSizing == screenSizing_BotOnly)
{
return QSize(w, h);
}
if (Config::ScreenLayout == Frontend::screenLayout_Natural)
if (screenLayout == screenLayout_Natural)
{
if (isHori)
return QSize(h+gap+h, w);
else
return QSize(w, h+gap+h);
}
else if (Config::ScreenLayout == Frontend::screenLayout_Vertical)
else if (screenLayout == screenLayout_Vertical)
{
if (isHori)
return QSize(h, w+gap+w);
else
return QSize(w, h+gap+h);
}
else if (Config::ScreenLayout == Frontend::screenLayout_Horizontal)
else if (screenLayout == screenLayout_Horizontal)
{
if (isHori)
return QSize(h+gap+h, w);
@ -191,10 +212,20 @@ QSize ScreenPanel::screenGetMinSize(int factor = 1)
void ScreenPanel::onScreenLayoutChanged()
{
loadConfig();
setMinimumSize(screenGetMinSize());
setupScreenLayout();
}
void ScreenPanel::onAutoScreenSizingChanged(int sizing)
{
autoScreenSizing = sizing;
if (screenSizing != screenSizing_Auto) return;
setupScreenLayout();
}
void ScreenPanel::resizeEvent(QResizeEvent* event)
{
setupScreenLayout();
@ -209,7 +240,7 @@ void ScreenPanel::mousePressEvent(QMouseEvent* event)
int x = event->pos().x();
int y = event->pos().y();
if (Frontend::GetTouchCoords(x, y, false))
if (layout.GetTouchCoords(x, y, false))
{
touching = true;
assert(emuInstance->getNDS() != nullptr);
@ -242,7 +273,7 @@ void ScreenPanel::mouseMoveEvent(QMouseEvent* event)
int x = event->pos().x();
int y = event->pos().y();
if (Frontend::GetTouchCoords(x, y, true))
if (layout.GetTouchCoords(x, y, true))
{
assert(emuInstance->getNDS() != nullptr);
emuInstance->getNDS()->TouchScreen(x, y);
@ -261,7 +292,7 @@ void ScreenPanel::tabletEvent(QTabletEvent* event)
int x = event->x();
int y = event->y();
if (Frontend::GetTouchCoords(x, y, event->type()==QEvent::TabletMove))
if (layout.GetTouchCoords(x, y, event->type()==QEvent::TabletMove))
{
touching = true;
assert(emuInstance->getNDS() != nullptr);
@ -296,7 +327,7 @@ void ScreenPanel::touchEvent(QTouchEvent* event)
int x = (int)lastPosition.x();
int y = (int)lastPosition.y();
if (Frontend::GetTouchCoords(x, y, event->type()==QEvent::TouchUpdate))
if (layout.GetTouchCoords(x, y, event->type()==QEvent::TouchUpdate))
{
touching = true;
assert(emuInstance->getNDS() != nullptr);
@ -1115,7 +1146,6 @@ void ScreenPanelGL::transferLayout()
lastScreenHeight = windowInfo->surface_height;
}
this->filter = Config::ScreenFilter;
this->windowInfo = *windowInfo;
screenSettingsLock.unlock();

View File

@ -31,7 +31,7 @@
#include <QTimer>
#include "glad/glad.h"
#include "FrontendUtil.h"
#include "ScreenLayout.h"
#include "duckstation/gl/context.h"
@ -58,6 +58,8 @@ public:
explicit ScreenPanel(QWidget* parent);
virtual ~ScreenPanel();
void setFilter(bool filter);
void setMouseHide(bool enable, int delay);
QTimer* setupMouseTimer();
@ -70,11 +72,31 @@ public:
private slots:
void onScreenLayoutChanged();
void onAutoScreenSizingChanged(int sizing);
protected:
MainWindow* mainWindow;
EmuInstance* emuInstance;
bool filter;
int screenRotation;
int screenGap;
int screenLayout;
bool screenSwap;
int screenSizing;
bool integerScaling;
int screenAspectTop, screenAspectBot;
int autoScreenSizing;
ScreenLayout layout;
float screenMatrix[kMaxScreenTransforms][6];
int screenKind[kMaxScreenTransforms];
int numScreens;
bool touching = false;
bool mouseHide;
int mouseHideDelay;
@ -95,6 +117,8 @@ protected:
unsigned int osdID;
std::deque<OSDItem> osdItems;
void loadConfig();
virtual void setupScreenLayout();
void resizeEvent(QResizeEvent* event) override;
@ -107,12 +131,6 @@ protected:
void touchEvent(QTouchEvent* event);
bool event(QEvent* event) override;
float screenMatrix[Frontend::MaxScreenTransforms][6];
int screenKind[Frontend::MaxScreenTransforms];
int numScreens;
bool touching = false;
void showCursor();
int osdFindBreakPoint(const char* text, int i);
@ -141,7 +159,7 @@ private:
void setupScreenLayout() override;
QImage screen[2];
QTransform screenTrans[Frontend::MaxScreenTransforms];
QTransform screenTrans[kMaxScreenTransforms];
};
@ -187,7 +205,6 @@ private:
QMutex screenSettingsLock;
WindowInfo windowInfo;
bool filter;
int lastScreenWidth = -1, lastScreenHeight = -1;

View File

@ -462,7 +462,7 @@ MainWindow::MainWindow(int id, EmuInstance* inst, QWidget* parent) :
QMenu* submenu = menu->addMenu("Screen rotation");
grpScreenRotation = new QActionGroup(submenu);
for (int i = 0; i < Frontend::screenRot_MAX; i++)
for (int i = 0; i < screenRot_MAX; i++)
{
int data = i*90;
actScreenRotation[i] = submenu->addAction(QString("%1°").arg(data));
@ -496,7 +496,7 @@ MainWindow::MainWindow(int id, EmuInstance* inst, QWidget* parent) :
const char* screenlayout[] = {"Natural", "Vertical", "Horizontal", "Hybrid"};
for (int i = 0; i < Frontend::screenLayout_MAX; i++)
for (int i = 0; i < screenLayout_MAX; i++)
{
actScreenLayout[i] = submenu->addAction(QString(screenlayout[i]));
actScreenLayout[i]->setActionGroup(grpScreenLayout);
@ -518,7 +518,7 @@ MainWindow::MainWindow(int id, EmuInstance* inst, QWidget* parent) :
const char* screensizing[] = {"Even", "Emphasize top", "Emphasize bottom", "Auto", "Top only", "Bottom only"};
for (int i = 0; i < Frontend::screenSizing_MAX; i++)
for (int i = 0; i < screenSizing_MAX; i++)
{
actScreenSizing[i] = submenu->addAction(QString(screensizing[i]));
actScreenSizing[i]->setActionGroup(grpScreenSizing);
@ -594,8 +594,6 @@ MainWindow::MainWindow(int id, EmuInstance* inst, QWidget* parent) :
}
setMenuBar(menubar);
//resize(curW, curH);
if (localCfg.GetString("Firmware.Username") == "Arisotura")
actMPNewInstance->setText("Fart");
@ -606,10 +604,6 @@ MainWindow::MainWindow(int id, EmuInstance* inst, QWidget* parent) :
move(frameGeo.topLeft());
#endif
/*if (oldMax)
showMaximized();
else
show();*/
std::string geom = windowCfg.GetString("Geometry");
if (!geom.empty())
{
@ -658,32 +652,35 @@ MainWindow::MainWindow(int id, EmuInstance* inst, QWidget* parent) :
actSavestateSRAMReloc->setChecked(globalCfg.GetBool("Savestate.RelocSRAM"));
actScreenRotation[Config::ScreenRotation]->setChecked(true);
actScreenRotation[windowCfg.GetInt("ScreenRotation")]->setChecked(true);
int screenGap = windowCfg.GetInt("ScreenGap");
for (int i = 0; i < 6; i++)
{
if (actScreenGap[i]->data().toInt() == Config::ScreenGap)
if (actScreenGap[i]->data().toInt() == screenGap)
{
actScreenGap[i]->setChecked(true);
break;
}
}
actScreenLayout[Config::ScreenLayout]->setChecked(true);
actScreenSizing[Config::ScreenSizing]->setChecked(true);
actIntegerScaling->setChecked(Config::IntegerScaling);
actScreenLayout[windowCfg.GetInt("ScreenLayout")]->setChecked(true);
actScreenSizing[windowCfg.GetInt("ScreenSizing")]->setChecked(true);
actIntegerScaling->setChecked(windowCfg.GetBool("IntegerScaling"));
actScreenSwap->setChecked(Config::ScreenSwap);
actScreenSwap->setChecked(windowCfg.GetBool("ScreenSwap"));
int aspectTop = windowCfg.GetInt("ScreenAspectTop");
int aspectBot = windowCfg.GetInt("ScreenAspectBot");
for (int i = 0; i < AspectRatiosNum; i++)
{
if (Config::ScreenAspectTop == aspectRatios[i].id)
if (aspectTop == aspectRatios[i].id)
actScreenAspectTop[i]->setChecked(true);
if (Config::ScreenAspectBot == aspectRatios[i].id)
if (aspectBot == aspectRatios[i].id)
actScreenAspectBot[i]->setChecked(true);
}
actScreenFiltering->setChecked(Config::ScreenFilter);
actScreenFiltering->setChecked(windowCfg.GetBool("ScreenFilter"));
actShowOSD->setChecked(showOSD);
actLimitFramerate->setChecked(emuInstance->doLimitFPS);
@ -1886,7 +1883,7 @@ void MainWindow::onChangeScreenSize()
void MainWindow::onChangeScreenRotation(QAction* act)
{
int rot = act->data().toInt();
Config::ScreenRotation = rot;
windowCfg.SetInt("ScreenRotation", rot);
emit screenLayoutChange();
}
@ -1894,7 +1891,7 @@ void MainWindow::onChangeScreenRotation(QAction* act)
void MainWindow::onChangeScreenGap(QAction* act)
{
int gap = act->data().toInt();
Config::ScreenGap = gap;
windowCfg.SetInt("ScreenGap", gap);
emit screenLayoutChange();
}
@ -1902,30 +1899,32 @@ void MainWindow::onChangeScreenGap(QAction* act)
void MainWindow::onChangeScreenLayout(QAction* act)
{
int layout = act->data().toInt();
Config::ScreenLayout = layout;
windowCfg.SetInt("ScreenLayout", layout);
emit screenLayoutChange();
}
void MainWindow::onChangeScreenSwap(bool checked)
{
Config::ScreenSwap = checked?1:0;
windowCfg.SetBool("ScreenSwap", checked);
// Swap between top and bottom screen when displaying one screen.
if (Config::ScreenSizing == Frontend::screenSizing_TopOnly)
int sizing = windowCfg.GetInt("ScreenSizing");
if (sizing == screenSizing_TopOnly)
{
// Bottom Screen.
Config::ScreenSizing = Frontend::screenSizing_BotOnly;
actScreenSizing[Frontend::screenSizing_TopOnly]->setChecked(false);
actScreenSizing[Config::ScreenSizing]->setChecked(true);
sizing = screenSizing_BotOnly;
actScreenSizing[screenSizing_TopOnly]->setChecked(false);
actScreenSizing[sizing]->setChecked(true);
}
else if (Config::ScreenSizing == Frontend::screenSizing_BotOnly)
else if (sizing == screenSizing_BotOnly)
{
// Top Screen.
Config::ScreenSizing = Frontend::screenSizing_TopOnly;
actScreenSizing[Frontend::screenSizing_BotOnly]->setChecked(false);
actScreenSizing[Config::ScreenSizing]->setChecked(true);
sizing = screenSizing_TopOnly;
actScreenSizing[screenSizing_BotOnly]->setChecked(false);
actScreenSizing[sizing]->setChecked(true);
}
windowCfg.SetInt("ScreenSizing", sizing);
emit screenLayoutChange();
}
@ -1933,7 +1932,7 @@ void MainWindow::onChangeScreenSwap(bool checked)
void MainWindow::onChangeScreenSizing(QAction* act)
{
int sizing = act->data().toInt();
Config::ScreenSizing = sizing;
windowCfg.SetInt("ScreenSizing", sizing);
emit screenLayoutChange();
}
@ -1945,11 +1944,11 @@ void MainWindow::onChangeScreenAspect(QAction* act)
if (group == grpScreenAspectTop)
{
Config::ScreenAspectTop = aspect;
windowCfg.SetInt("ScreenAspectTop", aspect);
}
else
{
Config::ScreenAspectBot = aspect;
windowCfg.SetInt("ScreenAspectBot", aspect);
}
emit screenLayoutChange();
@ -1957,16 +1956,17 @@ void MainWindow::onChangeScreenAspect(QAction* act)
void MainWindow::onChangeIntegerScaling(bool checked)
{
Config::IntegerScaling = checked?1:0;
windowCfg.SetBool("IntegerScaling", checked);
emit screenLayoutChange();
}
void MainWindow::onChangeScreenFiltering(bool checked)
{
Config::ScreenFilter = checked?1:0;
windowCfg.SetBool("ScreenFilter", checked);
emit screenLayoutChange();
//emit screenLayoutChange();
panel->setFilter(checked);
}
void MainWindow::onChangeShowOSD(bool checked)
@ -2016,15 +2016,16 @@ void MainWindow::onFullscreenToggled()
void MainWindow::onScreenEmphasisToggled()
{
int currentSizing = Config::ScreenSizing;
if (currentSizing == Frontend::screenSizing_EmphTop)
int currentSizing = windowCfg.GetInt("ScreenSizing");
if (currentSizing == screenSizing_EmphTop)
{
Config::ScreenSizing = Frontend::screenSizing_EmphBot;
currentSizing = screenSizing_EmphBot;
}
else if (currentSizing == Frontend::screenSizing_EmphBot)
else if (currentSizing == screenSizing_EmphBot)
{
Config::ScreenSizing = Frontend::screenSizing_EmphTop;
currentSizing = screenSizing_EmphTop;
}
windowCfg.SetInt("ScreenSizing", currentSizing);
emit screenLayoutChange();
}

View File

@ -20,7 +20,7 @@
#define WINDOW_H
#include "glad/glad.h"
#include "FrontendUtil.h"
#include "ScreenLayout.h"
#include "duckstation/gl/context.h"
#include <QWidget>
@ -108,6 +108,7 @@ public:
~MainWindow();
EmuInstance* getEmuInstance() { return emuInstance; }
Config::Table& getWindowConfig() { return windowCfg; }
void attachEmuThread(EmuThread* thread);
@ -296,14 +297,14 @@ public:
QAction* actSavestateSRAMReloc;
QAction* actScreenSize[4];
QActionGroup* grpScreenRotation;
QAction* actScreenRotation[Frontend::screenRot_MAX];
QAction* actScreenRotation[screenRot_MAX];
QActionGroup* grpScreenGap;
QAction* actScreenGap[6];
QActionGroup* grpScreenLayout;
QAction* actScreenLayout[Frontend::screenLayout_MAX];
QAction* actScreenLayout[screenLayout_MAX];
QAction* actScreenSwap;
QActionGroup* grpScreenSizing;
QAction* actScreenSizing[Frontend::screenSizing_MAX];
QAction* actScreenSizing[screenSizing_MAX];
QAction* actIntegerScaling;
QActionGroup* grpScreenAspectTop;
QAction** actScreenAspectTop;

View File

@ -318,12 +318,6 @@ int main(int argc, char** argv)
#endif
SANITIZE(Config::ScreenVSyncInterval, 1, 20);
SANITIZE(Config::GL_ScaleFactor, 1, 16);
SANITIZE(Config::ScreenRotation, 0, (int)Frontend::screenRot_MAX);
SANITIZE(Config::ScreenGap, 0, 500);
SANITIZE(Config::ScreenLayout, 0, (int)Frontend::screenLayout_MAX);
SANITIZE(Config::ScreenSizing, 0, (int)Frontend::screenSizing_MAX);
SANITIZE(Config::ScreenAspectTop, 0, AspectRatiosNum);
SANITIZE(Config::ScreenAspectBot, 0, AspectRatiosNum);
#undef SANITIZE
camStarted[0] = false;

View File

@ -34,7 +34,7 @@
#include "EmuInstance.h"
#include "Window.h"
#include "EmuThread.h"
#include "FrontendUtil.h"
#include "ScreenLayout.h"
class MelonApplication : public QApplication
{