mirror of https://github.com/stella-emu/stella.git
added interactive palette display to VideoDialog
This commit is contained in:
parent
b21efb6269
commit
85f438f693
|
@ -46,7 +46,7 @@ PaletteHandler::PaletteType PaletteHandler::toPaletteType(const string& name) co
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string PaletteHandler::toPaletteName(PaletteType type) const
|
||||
{
|
||||
string SETTING_NAMES[int(PaletteType::NumTypes)] = {
|
||||
const string SETTING_NAMES[int(PaletteType::NumTypes)] = {
|
||||
SETTING_STANDARD, SETTING_Z26, SETTING_USER, SETTING_CUSTOM
|
||||
};
|
||||
|
||||
|
@ -56,7 +56,7 @@ string PaletteHandler::toPaletteName(PaletteType type) const
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PaletteHandler::changePalette(bool increase)
|
||||
{
|
||||
string MESSAGES[PaletteType::NumTypes] = {
|
||||
const string MESSAGES[PaletteType::NumTypes] = {
|
||||
"Standard Stella", "Z26", "User-defined", "Custom"
|
||||
};
|
||||
|
||||
|
@ -98,7 +98,7 @@ void PaletteHandler::changePalette(bool increase)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PaletteHandler::selectAdjustable(bool next)
|
||||
{
|
||||
bool isCustomPalette = "custom" == myOSystem.settings().getString("palette");
|
||||
const bool isCustomPalette = "custom" == myOSystem.settings().getString("palette");
|
||||
|
||||
do {
|
||||
if(next)
|
||||
|
@ -154,10 +154,54 @@ void PaletteHandler::changeAdjustable(bool increase)
|
|||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PaletteHandler::changeColorPhaseShift(bool increase)
|
||||
{
|
||||
const ConsoleTiming timing = myOSystem.console().timing();
|
||||
|
||||
// SECAM is not supported
|
||||
if(timing != ConsoleTiming::secam)
|
||||
{
|
||||
constexpr char DEGREE = 0x1c;
|
||||
const bool isNTSC = timing == ConsoleTiming::ntsc;
|
||||
const float shift = isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT;
|
||||
float phase = isNTSC ? myPhaseNTSC : myPhasePAL;
|
||||
|
||||
if(increase) // increase color phase shift
|
||||
{
|
||||
phase += 0.3F;
|
||||
phase = std::min(phase, shift + MAX_SHIFT);
|
||||
}
|
||||
else // decrease color phase shift
|
||||
{
|
||||
phase -= 0.3F;
|
||||
phase = std::max(phase, shift - MAX_SHIFT);
|
||||
}
|
||||
if(isNTSC)
|
||||
myPhaseNTSC = phase;
|
||||
else
|
||||
myPhasePAL = phase;
|
||||
|
||||
generateCustomPalette(timing);
|
||||
setPalette("custom");
|
||||
|
||||
ostringstream ss;
|
||||
ss << "Color phase shift at "
|
||||
<< std::fixed << std::setprecision(1) << phase << DEGREE;
|
||||
|
||||
myOSystem.frameBuffer().showMessage(ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PaletteHandler::loadConfig(const Settings& settings)
|
||||
{
|
||||
// Load adjustables
|
||||
myPhaseNTSC = BSPF::clamp(settings.getFloat("tv.phase_ntsc"),
|
||||
DEF_NTSC_SHIFT - MAX_SHIFT, DEF_NTSC_SHIFT + MAX_SHIFT);
|
||||
myPhasePAL = BSPF::clamp(settings.getFloat("tv.phase_pal"),
|
||||
DEF_PAL_SHIFT - MAX_SHIFT, DEF_PAL_SHIFT + MAX_SHIFT);
|
||||
|
||||
myHue = BSPF::clamp(settings.getFloat("tv.hue"), -1.0F, 1.0F);
|
||||
mySaturation = BSPF::clamp(settings.getFloat("tv.saturation"), -1.0F, 1.0F);
|
||||
myContrast = BSPF::clamp(settings.getFloat("tv.contrast"), -1.0F, 1.0F);
|
||||
|
@ -169,6 +213,9 @@ void PaletteHandler::loadConfig(const Settings& settings)
|
|||
void PaletteHandler::saveConfig(Settings& settings) const
|
||||
{
|
||||
// Save adjustables
|
||||
settings.setValue("tv.phase_ntsc", myPhaseNTSC);
|
||||
settings.setValue("tv.phase_pal", myPhasePAL);
|
||||
|
||||
settings.setValue("tv.hue", myHue);
|
||||
settings.setValue("tv.saturation", mySaturation);
|
||||
settings.setValue("tv.contrast", myContrast);
|
||||
|
@ -177,8 +224,11 @@ void PaletteHandler::saveConfig(Settings& settings) const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PaletteHandler::setAdjustables(Adjustable& adjustable)
|
||||
void PaletteHandler::setAdjustables(const Adjustable& adjustable)
|
||||
{
|
||||
myPhaseNTSC = adjustable.phaseNtsc / 10.F;
|
||||
myPhasePAL = adjustable.phasePal / 10.F;
|
||||
|
||||
myHue = scaleFrom100(adjustable.hue);
|
||||
mySaturation = scaleFrom100(adjustable.saturation);
|
||||
myContrast = scaleFrom100(adjustable.contrast);
|
||||
|
@ -189,6 +239,9 @@ void PaletteHandler::setAdjustables(Adjustable& adjustable)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PaletteHandler::getAdjustables(Adjustable& adjustable) const
|
||||
{
|
||||
adjustable.phaseNtsc = myPhaseNTSC * 10.F;
|
||||
adjustable.phasePal = myPhasePAL * 10.F;
|
||||
|
||||
adjustable.hue = scaleTo100(myHue);
|
||||
adjustable.saturation = scaleTo100(mySaturation);
|
||||
adjustable.contrast = scaleTo100(myContrast);
|
||||
|
@ -196,46 +249,6 @@ void PaletteHandler::getAdjustables(Adjustable& adjustable) const
|
|||
adjustable.gamma = scaleTo100(myGamma);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PaletteHandler::changeColorPhaseShift(bool increase)
|
||||
{
|
||||
const ConsoleTiming timing = myOSystem.console().timing();
|
||||
|
||||
// SECAM is not supported
|
||||
if(timing != ConsoleTiming::secam)
|
||||
{
|
||||
const char DEGREE = 0x1c;
|
||||
const float NTSC_SHIFT = 26.2F;
|
||||
const float PAL_SHIFT = 31.3F; // 360 / 11.5
|
||||
const bool isNTSC = timing == ConsoleTiming::ntsc;
|
||||
const string key = isNTSC ? "tv.phase_ntsc" : "tv.phase_pal";
|
||||
const float shift = isNTSC ? NTSC_SHIFT : PAL_SHIFT;
|
||||
float phase = myOSystem.settings().getFloat(key);
|
||||
|
||||
if(increase) // increase color phase shift
|
||||
{
|
||||
phase += 0.3F;
|
||||
phase = std::min(phase, shift + 4.5F);
|
||||
}
|
||||
else // decrease color phase shift
|
||||
{
|
||||
phase -= 0.3F;
|
||||
phase = std::max(phase, shift - 4.5F);
|
||||
}
|
||||
myOSystem.settings().setValue(key, phase);
|
||||
generateCustomPalette(timing);
|
||||
|
||||
setPalette("custom");
|
||||
|
||||
ostringstream ss;
|
||||
ss << "Color phase shift at "
|
||||
<< std::fixed << std::setprecision(1) << phase << DEGREE;
|
||||
|
||||
myOSystem.frameBuffer().showMessage(ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PaletteHandler::setPalette(const string& name)
|
||||
{
|
||||
|
@ -251,7 +264,7 @@ void PaletteHandler::setPalette()
|
|||
|
||||
// Look at all the palettes, since we don't know which one is
|
||||
// currently active
|
||||
static constexpr BSPF::array2D<PaletteArray*, PaletteType::NumTypes, int(ConsoleTiming::numTimings)> palettes = {{
|
||||
static constexpr BSPF::array2D<const PaletteArray*, PaletteType::NumTypes, int(ConsoleTiming::numTimings)> palettes = {{
|
||||
{ &ourNTSCPalette, &ourPALPalette, &ourSECAMPalette },
|
||||
{ &ourNTSCPaletteZ26, &ourPALPaletteZ26, &ourSECAMPaletteZ26 },
|
||||
{ &ourUserNTSCPalette, &ourUserPALPalette, &ourUserSECAMPalette },
|
||||
|
@ -274,19 +287,19 @@ PaletteArray PaletteHandler::adjustPalette(const PaletteArray& palette)
|
|||
{
|
||||
PaletteArray destPalette;
|
||||
// Constants for saturation and gray scale calculation
|
||||
const float PR = .2989F;
|
||||
const float PG = .5870F;
|
||||
const float PB = .1140F;
|
||||
constexpr float PR = .2989F;
|
||||
constexpr float PG = .5870F;
|
||||
constexpr float PB = .1140F;
|
||||
// Generate adjust table
|
||||
const int ADJUST_SIZE = 256;
|
||||
const int RGB_UNIT = 1 << 8;
|
||||
const float RGB_OFFSET = 0.5F;
|
||||
constexpr int ADJUST_SIZE = 256;
|
||||
constexpr int RGB_UNIT = 1 << 8;
|
||||
constexpr float RGB_OFFSET = 0.5F;
|
||||
const float brightness = myBrightness * (0.5F * RGB_UNIT) + RGB_OFFSET;
|
||||
const float contrast = myContrast * (0.5F * RGB_UNIT) + RGB_UNIT;
|
||||
const float saturation = mySaturation + 1;
|
||||
const float gamma = 1.1333F - myGamma * 0.5F;
|
||||
/* match common PC's 2.2 gamma to TV's 2.65 gamma */
|
||||
const float toFloat = 1.F / (ADJUST_SIZE - 1);
|
||||
constexpr float toFloat = 1.F / (ADJUST_SIZE - 1);
|
||||
std::array<float, ADJUST_SIZE> adjust;
|
||||
|
||||
for(int i = 0; i < ADJUST_SIZE; i++)
|
||||
|
@ -341,13 +354,13 @@ void PaletteHandler::loadUserPalette()
|
|||
for(int i = 0; i < 128; i++) // NTSC palette
|
||||
{
|
||||
in.read(reinterpret_cast<char*>(pixbuf.data()), 3);
|
||||
uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
|
||||
const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
|
||||
ourUserNTSCPalette[(i<<1)] = pixel;
|
||||
}
|
||||
for(int i = 0; i < 128; i++) // PAL palette
|
||||
{
|
||||
in.read(reinterpret_cast<char*>(pixbuf.data()), 3);
|
||||
uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
|
||||
const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
|
||||
ourUserPALPalette[(i<<1)] = pixel;
|
||||
}
|
||||
|
||||
|
@ -355,7 +368,7 @@ void PaletteHandler::loadUserPalette()
|
|||
for(int i = 0; i < 8; i++) // SECAM palette
|
||||
{
|
||||
in.read(reinterpret_cast<char*>(pixbuf.data()), 3);
|
||||
uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
|
||||
const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
|
||||
secam[(i<<1)] = pixel;
|
||||
secam[(i<<1)+1] = 0;
|
||||
}
|
||||
|
@ -383,8 +396,7 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing)
|
|||
{
|
||||
// YIQ is YUV shifted by 33°
|
||||
constexpr float offset = 33 * (2 * BSPF::PI_f / 360);
|
||||
const float shift = myOSystem.settings().getFloat("tv.phase_ntsc") *
|
||||
(2 * BSPF::PI_f / 360);
|
||||
const float shift = myPhaseNTSC * (2 * BSPF::PI_f / 360);
|
||||
|
||||
// color 0 is grayscale
|
||||
for(int chroma = 1; chroma < NUM_CHROMA; chroma++)
|
||||
|
@ -429,8 +441,7 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing)
|
|||
else if(timing == ConsoleTiming::pal)
|
||||
{
|
||||
constexpr float offset = 180 * (2 * BSPF::PI_f / 360);
|
||||
float shift = myOSystem.settings().getFloat("tv.phase_pal") *
|
||||
(2 * BSPF::PI_f / 360);
|
||||
const float shift = myPhasePAL * (2 * BSPF::PI_f / 360);
|
||||
constexpr float fixedShift = 22.5F * (2 * BSPF::PI_f / 360);
|
||||
|
||||
// colors 0, 1, 14 and 15 are grayscale
|
||||
|
@ -453,11 +464,10 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing)
|
|||
{
|
||||
const float Y = 0.05F + luma / 8.24F; // 0.05..~0.90
|
||||
|
||||
// Most sources
|
||||
// Most sources
|
||||
float R = Y + 1.403F * V;
|
||||
float G = Y - 0.344F * U - 0.714F * V;
|
||||
float B = Y + 1.770F * U;
|
||||
|
||||
// German Wikipedia, huh???
|
||||
//float B = Y + 1 / 0.493 * U;
|
||||
//float R = Y + 1 / 0.877 * V;
|
||||
|
@ -504,8 +514,7 @@ void PaletteHandler::changeSaturation(int& R, int& G, int& B, float change)
|
|||
constexpr float PR = .2989F;
|
||||
constexpr float PG = .5870F;
|
||||
constexpr float PB = .1140F;
|
||||
|
||||
float P = sqrt(R * R * PR + G * G * PG + B * B * PB) ;
|
||||
const float P = sqrt(R * R * PR + G * G * PG + B * B * PB) ;
|
||||
|
||||
R = P + (R - P) * change;
|
||||
G = P + (G - P) * change;
|
||||
|
@ -517,7 +526,7 @@ void PaletteHandler::changeSaturation(int& R, int& G, int& B, float change)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
PaletteArray PaletteHandler::ourNTSCPalette = {
|
||||
const PaletteArray PaletteHandler::ourNTSCPalette = {
|
||||
0x000000, 0, 0x4a4a4a, 0, 0x6f6f6f, 0, 0x8e8e8e, 0,
|
||||
0xaaaaaa, 0, 0xc0c0c0, 0, 0xd6d6d6, 0, 0xececec, 0,
|
||||
0x484800, 0, 0x69690f, 0, 0x86861d, 0, 0xa2a22a, 0,
|
||||
|
@ -553,7 +562,7 @@ PaletteArray PaletteHandler::ourNTSCPalette = {
|
|||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
PaletteArray PaletteHandler::ourPALPalette = {
|
||||
const PaletteArray PaletteHandler::ourPALPalette = {
|
||||
0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 180 0
|
||||
0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0, // was 0x111111..0xcccccc
|
||||
0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 198 1
|
||||
|
@ -589,7 +598,7 @@ PaletteArray PaletteHandler::ourPALPalette = {
|
|||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
PaletteArray PaletteHandler::ourSECAMPalette = {
|
||||
const PaletteArray PaletteHandler::ourSECAMPalette = {
|
||||
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
|
||||
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
|
||||
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
|
||||
|
@ -625,7 +634,7 @@ PaletteArray PaletteHandler::ourSECAMPalette = {
|
|||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
PaletteArray PaletteHandler::ourNTSCPaletteZ26 = {
|
||||
const PaletteArray PaletteHandler::ourNTSCPaletteZ26 = {
|
||||
0x000000, 0, 0x505050, 0, 0x646464, 0, 0x787878, 0,
|
||||
0x8c8c8c, 0, 0xa0a0a0, 0, 0xb4b4b4, 0, 0xc8c8c8, 0,
|
||||
0x445400, 0, 0x586800, 0, 0x6c7c00, 0, 0x809000, 0,
|
||||
|
@ -661,7 +670,7 @@ PaletteArray PaletteHandler::ourNTSCPaletteZ26 = {
|
|||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
PaletteArray PaletteHandler::ourPALPaletteZ26 = {
|
||||
const PaletteArray PaletteHandler::ourPALPaletteZ26 = {
|
||||
0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0,
|
||||
0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0,
|
||||
0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0,
|
||||
|
@ -697,7 +706,7 @@ PaletteArray PaletteHandler::ourPALPaletteZ26 = {
|
|||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
PaletteArray PaletteHandler::ourSECAMPaletteZ26 = {
|
||||
const PaletteArray PaletteHandler::ourSECAMPaletteZ26 = {
|
||||
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
|
||||
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
|
||||
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "bspf.hxx"
|
||||
#include "OSystem.hxx"
|
||||
#include "ConsoleTiming.hxx"
|
||||
|
||||
class PaletteHandler
|
||||
{
|
||||
|
@ -29,6 +30,10 @@ class PaletteHandler
|
|||
static constexpr const char* SETTING_USER = "user";
|
||||
static constexpr const char* SETTING_CUSTOM = "custom";
|
||||
|
||||
static constexpr float DEF_NTSC_SHIFT = 26.2F;
|
||||
static constexpr float DEF_PAL_SHIFT = 31.3F; // 360 / 11.5
|
||||
static constexpr float MAX_SHIFT = 4.5F;
|
||||
|
||||
enum DisplayType {
|
||||
NTSC,
|
||||
PAL,
|
||||
|
@ -37,6 +42,7 @@ class PaletteHandler
|
|||
};
|
||||
|
||||
struct Adjustable {
|
||||
float phaseNtsc, phasePal;
|
||||
uInt32 hue, saturation, contrast, brightness, gamma;
|
||||
};
|
||||
|
||||
|
@ -55,7 +61,7 @@ class PaletteHandler
|
|||
|
||||
void loadConfig(const Settings& settings);
|
||||
void saveConfig(Settings& settings) const;
|
||||
void setAdjustables(Adjustable& adjustable);
|
||||
void setAdjustables(const Adjustable& adjustable);
|
||||
void getAdjustables(Adjustable& adjustable) const;
|
||||
|
||||
/**
|
||||
|
@ -114,7 +120,7 @@ class PaletteHandler
|
|||
|
||||
|
||||
private:
|
||||
static const int NUM_ADJUSTABLES = 6;
|
||||
static constexpr int NUM_ADJUSTABLES = 6;
|
||||
|
||||
OSystem& myOSystem;
|
||||
|
||||
|
@ -133,11 +139,13 @@ class PaletteHandler
|
|||
{ "gamma", &myGamma },
|
||||
} };
|
||||
|
||||
float myPhaseNTSC{0.0F};
|
||||
float myPhasePAL{0.0F};
|
||||
// range -1.0 to +1.0 (as in AtariNTSC)
|
||||
// Basic parameters
|
||||
float myContrast{0.0F}; // -1 = dark (0.5) +1 = light (1.5)
|
||||
float myHue{0.0F}; // -1 = -180 degrees +1 = +180 degrees
|
||||
float mySaturation{0.0F}; // -1 = grayscale (0.0) +1 = oversaturated colors (2.0)
|
||||
float myContrast{0.0F}; // -1 = dark (0.5) +1 = light (1.5)
|
||||
float myBrightness{0.0F}; // -1 = dark (0.5) +1 = light (1.5)
|
||||
// Advanced parameters
|
||||
float myGamma{0.0F}; // -1 = dark (1.5) +1 = light (0.5)
|
||||
|
@ -147,14 +155,14 @@ class PaletteHandler
|
|||
bool myUserPaletteDefined{false};
|
||||
|
||||
// Table of RGB values for NTSC, PAL and SECAM
|
||||
static PaletteArray ourNTSCPalette;
|
||||
static PaletteArray ourPALPalette;
|
||||
static PaletteArray ourSECAMPalette;
|
||||
static const PaletteArray ourNTSCPalette;
|
||||
static const PaletteArray ourPALPalette;
|
||||
static const PaletteArray ourSECAMPalette;
|
||||
|
||||
// Table of RGB values for NTSC, PAL and SECAM - Z26 version
|
||||
static PaletteArray ourNTSCPaletteZ26;
|
||||
static PaletteArray ourPALPaletteZ26;
|
||||
static PaletteArray ourSECAMPaletteZ26;
|
||||
static const PaletteArray ourNTSCPaletteZ26;
|
||||
static const PaletteArray ourPALPaletteZ26;
|
||||
static const PaletteArray ourSECAMPaletteZ26;
|
||||
|
||||
// Table of RGB values for NTSC, PAL and SECAM - user-defined
|
||||
static PaletteArray ourUserNTSCPalette;
|
||||
|
|
|
@ -25,10 +25,11 @@
|
|||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
ColorWidget::ColorWidget(GuiObject* boss, const GUI::Font& font,
|
||||
int x, int y, int w, int h, int cmd)
|
||||
int x, int y, int w, int h, int cmd, bool framed)
|
||||
: Widget(boss, font, x, y, w, h),
|
||||
CommandSender(boss),
|
||||
_cmd(cmd)
|
||||
_cmd(cmd),
|
||||
_framed(framed)
|
||||
{
|
||||
_flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS;
|
||||
}
|
||||
|
@ -46,11 +47,18 @@ void ColorWidget::drawWidget(bool hilite)
|
|||
FBSurface& s = dialog().surface();
|
||||
bool onTop = _boss->dialog().isOnTop();
|
||||
|
||||
if(_framed)
|
||||
{
|
||||
// Draw a thin frame around us.
|
||||
s.frameRect(_x, _y, _w, _h + 1, kColor);
|
||||
s.frameRect(_x, _y, _w, _h + 1, kColor);
|
||||
|
||||
// Show the currently selected color
|
||||
s.fillRect(_x+1, _y+1, _w-2, _h-1, onTop ? isEnabled() ? _color : kWidColor : kBGColorLo);
|
||||
// Show the currently selected color
|
||||
s.fillRect(_x + 1, _y + 1, _w - 2, _h - 1, onTop ? isEnabled() ? _color : kWidColor : kBGColorLo);
|
||||
}
|
||||
else
|
||||
{
|
||||
s.fillRect(_x, _y, _w, _h, onTop ? isEnabled() ? _color : kWidColor : kBGColorLo);
|
||||
}
|
||||
|
||||
// Cross out the grid?
|
||||
if(_crossGrid)
|
||||
|
|
|
@ -36,7 +36,7 @@ class ColorWidget : public Widget, public CommandSender
|
|||
|
||||
public:
|
||||
ColorWidget(GuiObject* boss, const GUI::Font& font,
|
||||
int x, int y, int w, int h, int cmd = 0);
|
||||
int x, int y, int w, int h, int cmd = 0, bool framed = true);
|
||||
virtual ~ColorWidget() = default;
|
||||
|
||||
void setColor(ColorId color);
|
||||
|
@ -49,6 +49,7 @@ class ColorWidget : public Widget, public CommandSender
|
|||
|
||||
protected:
|
||||
ColorId _color{kNone};
|
||||
bool _framed{true};
|
||||
int _cmd{0};
|
||||
|
||||
bool _crossGrid{false};
|
||||
|
|
|
@ -18,12 +18,14 @@
|
|||
#include <cmath>
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Base.hxx"
|
||||
#include "Control.hxx"
|
||||
#include "Dialog.hxx"
|
||||
#include "Menu.hxx"
|
||||
#include "OSystem.hxx"
|
||||
#include "EditTextWidget.hxx"
|
||||
#include "PopUpWidget.hxx"
|
||||
#include "ColorWidget.hxx"
|
||||
#include "Console.hxx"
|
||||
#include "PaletteHandler.hxx"
|
||||
#include "TIA.hxx"
|
||||
|
@ -104,6 +106,14 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent,
|
|||
addPaletteTab();
|
||||
addTVEffectsTab();
|
||||
|
||||
//const int req_w = std::max(myFastSCBios->getRight(), myCloneBad->getRight()) + HBORDER + 1;
|
||||
//const int req_h = _th + VGAP * 3
|
||||
// + std::max(myUseVSync->getBottom(), myTVScanIntense->getBottom())
|
||||
// + buttonHeight + VBORDER * 2;
|
||||
//// Set real dimensions
|
||||
//setSize(req_w, req_h, max_w, max_h);
|
||||
|
||||
|
||||
// Add Defaults, OK and Cancel buttons
|
||||
WidgetArray wid;
|
||||
addDefaultsOKCancelBGroup(wid, _font);
|
||||
|
@ -266,7 +276,8 @@ void VideoDialog::addPaletteTab()
|
|||
myPhaseShiftNtsc =
|
||||
new SliderWidget(myTab, _font, xpos + INDENT, ypos-1, pswidth, lineHeight,
|
||||
"NTSC phase", plWidth, kNtscShiftChanged, fontWidth * 5);
|
||||
myPhaseShiftNtsc->setMinValue(262 - 45); myPhaseShiftNtsc->setMaxValue(262 + 45);
|
||||
myPhaseShiftNtsc->setMinValue((PaletteHandler::DEF_NTSC_SHIFT - PaletteHandler::MAX_SHIFT) * 10);
|
||||
myPhaseShiftNtsc->setMaxValue((PaletteHandler::DEF_NTSC_SHIFT + PaletteHandler::MAX_SHIFT) * 10);
|
||||
myPhaseShiftNtsc->setTickmarkIntervals(4);
|
||||
wid.push_back(myPhaseShiftNtsc);
|
||||
ypos += lineHeight + VGAP;
|
||||
|
@ -274,7 +285,8 @@ void VideoDialog::addPaletteTab()
|
|||
myPhaseShiftPal =
|
||||
new SliderWidget(myTab, _font, xpos + INDENT, ypos-1, pswidth, lineHeight,
|
||||
"PAL phase", plWidth, kPalShiftChanged, fontWidth * 5);
|
||||
myPhaseShiftPal->setMinValue(313 - 45); myPhaseShiftPal->setMaxValue(313 + 45);
|
||||
myPhaseShiftPal->setMinValue((PaletteHandler::DEF_PAL_SHIFT - PaletteHandler::MAX_SHIFT) * 10);
|
||||
myPhaseShiftPal->setMaxValue((PaletteHandler::DEF_PAL_SHIFT + PaletteHandler::MAX_SHIFT) * 10);
|
||||
myPhaseShiftPal->setTickmarkIntervals(4);
|
||||
wid.push_back(myPhaseShiftPal);
|
||||
ypos += lineHeight + VGAP;
|
||||
|
@ -288,11 +300,15 @@ void VideoDialog::addPaletteTab()
|
|||
wid.push_back(myTV ## obj); \
|
||||
ypos += lineHeight + VGAP;
|
||||
|
||||
CREATE_CUSTOM_SLIDERS(Hue, "Hue ", 0)
|
||||
CREATE_CUSTOM_SLIDERS(Satur, "Saturation ", 0)
|
||||
CREATE_CUSTOM_SLIDERS(Contrast, "Contrast ", 0)
|
||||
CREATE_CUSTOM_SLIDERS(Bright, "Brightness ", 0)
|
||||
CREATE_CUSTOM_SLIDERS(Gamma, "Gamma ", 0)
|
||||
CREATE_CUSTOM_SLIDERS(Hue, "Hue ", kPaletteUpdated)
|
||||
CREATE_CUSTOM_SLIDERS(Satur, "Saturation ", kPaletteUpdated)
|
||||
CREATE_CUSTOM_SLIDERS(Contrast, "Contrast ", kPaletteUpdated)
|
||||
CREATE_CUSTOM_SLIDERS(Bright, "Brightness ", kPaletteUpdated)
|
||||
CREATE_CUSTOM_SLIDERS(Gamma, "Gamma ", kPaletteUpdated)
|
||||
|
||||
// The resulting palette
|
||||
addPalette(myPhaseShiftNtsc->getRight() + fontWidth * 2, VBORDER,
|
||||
fontWidth * 2 * 8, myTVGamma->getBottom() - myTIAPalette->getTop());
|
||||
|
||||
// Add items for tab 2
|
||||
addToFocusList(wid, myTab, tabID);
|
||||
|
@ -412,13 +428,20 @@ void VideoDialog::loadConfig()
|
|||
myTIAZoom->setValue(instance().settings().getFloat("tia.zoom") * 100);
|
||||
|
||||
// TIA Palette
|
||||
myTIAPalette->setSelected(
|
||||
instance().settings().getString("palette"), "standard");
|
||||
myPalette = instance().settings().getString("palette");
|
||||
myTIAPalette->setSelected(myPalette, "standard");
|
||||
|
||||
// Custom Palette
|
||||
myPhaseShiftNtsc->setValue(instance().settings().getFloat("tv.phase_ntsc") * 10);
|
||||
myPhaseShiftPal->setValue(instance().settings().getFloat("tv.phase_pal") * 10);
|
||||
// Palette adjustables
|
||||
instance().frameBuffer().tiaSurface().paletteHandler().getAdjustables(myPaletteAdj);
|
||||
myPhaseShiftNtsc->setValue(myPaletteAdj.phaseNtsc);
|
||||
myPhaseShiftPal->setValue(myPaletteAdj.phasePal);
|
||||
myTVHue->setValue(myPaletteAdj.hue);
|
||||
myTVBright->setValue(myPaletteAdj.brightness);
|
||||
myTVContrast->setValue(myPaletteAdj.contrast);
|
||||
myTVSatur->setValue(myPaletteAdj.saturation);
|
||||
myTVGamma->setValue(myPaletteAdj.gamma);
|
||||
handlePaletteChange();
|
||||
colorPalette();
|
||||
|
||||
// TIA interpolation
|
||||
myTIAInterpolate->setState(instance().settings().getBool("tia.inter"));
|
||||
|
@ -459,15 +482,6 @@ void VideoDialog::loadConfig()
|
|||
int preset = instance().settings().getInt("tv.filter");
|
||||
handleTVModeChange(NTSCFilter::Preset(preset));
|
||||
|
||||
// Palette adjustables
|
||||
PaletteHandler::Adjustable paletteAdj;
|
||||
instance().frameBuffer().tiaSurface().paletteHandler().getAdjustables(paletteAdj);
|
||||
myTVHue->setValue(paletteAdj.hue);
|
||||
myTVBright->setValue(paletteAdj.brightness);
|
||||
myTVContrast->setValue(paletteAdj.contrast);
|
||||
myTVSatur->setValue(paletteAdj.saturation);
|
||||
myTVGamma->setValue(paletteAdj.gamma);
|
||||
|
||||
// TV Custom adjustables
|
||||
loadTVAdjustables(NTSCFilter::Preset::CUSTOM);
|
||||
|
||||
|
@ -491,31 +505,12 @@ void VideoDialog::saveConfig()
|
|||
instance().settings().setValue("video",
|
||||
myRenderer->getSelectedTag().toString());
|
||||
|
||||
// TIA zoom levels
|
||||
instance().settings().setValue("tia.zoom", myTIAZoom->getValue() / 100.0);
|
||||
|
||||
// TIA Palette
|
||||
instance().settings().setValue("palette",
|
||||
myTIAPalette->getSelectedTag().toString());
|
||||
|
||||
// Custom Palette
|
||||
instance().settings().setValue("tv.phase_ntsc", myPhaseShiftNtsc->getValue() / 10.0);
|
||||
instance().settings().setValue("tv.phase_pal", myPhaseShiftPal->getValue() / 10.0);
|
||||
|
||||
// TIA interpolation
|
||||
instance().settings().setValue("tia.inter", myTIAInterpolate->getState());
|
||||
|
||||
// Aspect ratio setting (NTSC and PAL)
|
||||
int oldAdjust = instance().settings().getInt("tia.vsizeadjust");
|
||||
int newAdjust = myVSizeAdjust->getValue();
|
||||
bool vsizeChanged = oldAdjust != newAdjust;
|
||||
|
||||
instance().settings().setValue("tia.vsizeadjust", newAdjust);
|
||||
// Note: Palette values are saved directly when changed!
|
||||
|
||||
// Speed
|
||||
int speedup = mySpeed->getValue();
|
||||
instance().settings().setValue("speed", unmapSpeed(speedup));
|
||||
if (instance().hasConsole()) instance().console().initializeAudio();
|
||||
|
||||
// Fullscreen
|
||||
instance().settings().setValue("fullscreen", myFullscreen->getState());
|
||||
|
@ -524,6 +519,22 @@ void VideoDialog::saveConfig()
|
|||
// Fullscreen overscan
|
||||
instance().settings().setValue("tia.fs_overscan", myTVOverscan->getValueLabel());
|
||||
|
||||
// TIA zoom levels
|
||||
instance().settings().setValue("tia.zoom", myTIAZoom->getValue() / 100.0);
|
||||
|
||||
// Aspect ratio setting (NTSC and PAL)
|
||||
const int oldAdjust = instance().settings().getInt("tia.vsizeadjust");
|
||||
const int newAdjust = myVSizeAdjust->getValue();
|
||||
const bool vsizeChanged = oldAdjust != newAdjust;
|
||||
|
||||
instance().settings().setValue("tia.vsizeadjust", newAdjust);
|
||||
|
||||
// Speed
|
||||
const int speedup = mySpeed->getValue();
|
||||
instance().settings().setValue("speed", unmapSpeed(speedup));
|
||||
if (instance().hasConsole())
|
||||
instance().console().initializeAudio();
|
||||
|
||||
// Use sync to vertical blank
|
||||
instance().settings().setValue("vsync", myUseVSync->getState());
|
||||
|
||||
|
@ -541,16 +552,6 @@ void VideoDialog::saveConfig()
|
|||
// TV Mode
|
||||
instance().settings().setValue("tv.filter",
|
||||
myTVMode->getSelectedTag().toString());
|
||||
|
||||
// Palette adjustables
|
||||
PaletteHandler::Adjustable paletteAdj;
|
||||
paletteAdj.hue = myTVHue->getValue();
|
||||
paletteAdj.saturation = myTVSatur->getValue();
|
||||
paletteAdj.contrast = myTVContrast->getValue();
|
||||
paletteAdj.brightness = myTVBright->getValue();
|
||||
paletteAdj.gamma = myTVGamma->getValue();
|
||||
instance().frameBuffer().tiaSurface().paletteHandler().setAdjustables(paletteAdj);
|
||||
|
||||
// TV Custom adjustables
|
||||
NTSCFilter::Adjustable ntscAdj;
|
||||
ntscAdj.sharpness = myTVSharp->getValue();
|
||||
|
@ -596,32 +597,36 @@ void VideoDialog::setDefaults()
|
|||
case 0: // General
|
||||
{
|
||||
myRenderer->setSelectedIndex(0);
|
||||
myTIAZoom->setValue(300);
|
||||
myTIAInterpolate->setState(false);
|
||||
myVSizeAdjust->setValue(0);
|
||||
mySpeed->setValue(0);
|
||||
|
||||
// screen size
|
||||
myFullscreen->setState(false);
|
||||
//myFullScreenMode->setSelectedIndex(0);
|
||||
myUseStretch->setState(false);
|
||||
myTVOverscan->setValue(0);
|
||||
myTIAZoom->setValue(300);
|
||||
myVSizeAdjust->setValue(0);
|
||||
// speed
|
||||
mySpeed->setValue(0);
|
||||
myUseVSync->setState(true);
|
||||
// misc
|
||||
myUIMessages->setState(true);
|
||||
myFastSCBios->setState(true);
|
||||
myUseThreads->setState(false);
|
||||
|
||||
handlePaletteChange();
|
||||
handleFullScreenChange();
|
||||
break;
|
||||
}
|
||||
|
||||
case 1: // Palettes
|
||||
myTIAPalette->setSelected("standard", "");
|
||||
myPhaseShiftNtsc->setValue(262);
|
||||
myPhaseShiftPal->setValue(313);
|
||||
myPhaseShiftNtsc->setValue(PaletteHandler::DEF_NTSC_SHIFT * 10);
|
||||
myPhaseShiftPal->setValue(PaletteHandler::DEF_PAL_SHIFT * 10);
|
||||
myTVHue->setValue(50);
|
||||
myTVSatur->setValue(50);
|
||||
myTVContrast->setValue(50);
|
||||
myTVBright->setValue(50);
|
||||
myTVGamma->setValue(50);
|
||||
handlePaletteChange();
|
||||
break;
|
||||
|
||||
case 2: // TV effects
|
||||
|
@ -685,6 +690,27 @@ void VideoDialog::handlePaletteChange()
|
|||
myPhaseShiftPal->setEnabled(enable);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void VideoDialog::handlePaletteUpdate()
|
||||
{
|
||||
// TIA Palette
|
||||
instance().settings().setValue("palette",
|
||||
myTIAPalette->getSelectedTag().toString());
|
||||
// Palette adjustables
|
||||
PaletteHandler::Adjustable paletteAdj;
|
||||
paletteAdj.phaseNtsc = myPhaseShiftNtsc->getValue();
|
||||
paletteAdj.phasePal = myPhaseShiftPal->getValue();
|
||||
paletteAdj.hue = myTVHue->getValue();
|
||||
paletteAdj.saturation = myTVSatur->getValue();
|
||||
paletteAdj.contrast = myTVContrast->getValue();
|
||||
paletteAdj.brightness = myTVBright->getValue();
|
||||
paletteAdj.gamma = myTVGamma->getValue();
|
||||
instance().frameBuffer().tiaSurface().paletteHandler().setAdjustables(paletteAdj);
|
||||
|
||||
if(instance().hasConsole())
|
||||
instance().frameBuffer().tiaSurface().paletteHandler().setPalette();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void VideoDialog::handleFullScreenChange()
|
||||
{
|
||||
|
@ -722,12 +748,24 @@ void VideoDialog::handleCommand(CommandSender* sender, int cmd,
|
|||
close();
|
||||
break;
|
||||
|
||||
case GuiObject::kCloseCmd:
|
||||
// restore palette settings
|
||||
instance().frameBuffer().tiaSurface().paletteHandler().setAdjustables(myPaletteAdj);
|
||||
instance().frameBuffer().tiaSurface().paletteHandler().setPalette(myPalette);
|
||||
Dialog::handleCommand(sender, cmd, data, 0);
|
||||
break;
|
||||
|
||||
case GuiObject::kDefaultsCmd:
|
||||
setDefaults();
|
||||
break;
|
||||
|
||||
case kPaletteChanged:
|
||||
handlePaletteChange();
|
||||
handlePaletteUpdate();
|
||||
break;
|
||||
|
||||
case kPaletteUpdated:
|
||||
handlePaletteUpdate();
|
||||
break;
|
||||
|
||||
case kNtscShiftChanged:
|
||||
|
@ -737,6 +775,7 @@ void VideoDialog::handleCommand(CommandSender* sender, int cmd,
|
|||
ss << std::setw(4) << std::fixed << std::setprecision(1)
|
||||
<< (0.1 * abs(myPhaseShiftNtsc->getValue())) << DEGREE;
|
||||
myPhaseShiftNtsc->setValueLabel(ss.str());
|
||||
handlePaletteUpdate();
|
||||
break;
|
||||
}
|
||||
case kPalShiftChanged:
|
||||
|
@ -746,6 +785,7 @@ void VideoDialog::handleCommand(CommandSender* sender, int cmd,
|
|||
ss << std::setw(4) << std::fixed << std::setprecision(1)
|
||||
<< (0.1 * abs(myPhaseShiftPal->getValue())) << DEGREE;
|
||||
myPhaseShiftPal->setValueLabel(ss.str());
|
||||
handlePaletteUpdate();
|
||||
break;
|
||||
}
|
||||
case kVSizeChanged:
|
||||
|
@ -818,3 +858,57 @@ void VideoDialog::handleCommand(CommandSender* sender, int cmd,
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void VideoDialog::addPalette(int x, int y, int w, int h)
|
||||
{
|
||||
if(instance().hasConsole())
|
||||
{
|
||||
constexpr int NUM_LUMA = 8;
|
||||
constexpr int NUM_CHROMA = 16;
|
||||
const GUI::Font& ifont = instance().frameBuffer().infoFont();
|
||||
const int lwidth = ifont.getMaxCharWidth() * 1.5;
|
||||
const float COLW = float(w - lwidth) / NUM_LUMA;
|
||||
const float COLH = float(h) / NUM_CHROMA;
|
||||
const int yofs = (COLH - ifont.getFontHeight() + 1) / 2;
|
||||
|
||||
for(int idx = 0; idx < NUM_CHROMA; ++idx)
|
||||
{
|
||||
myColorLbl[idx] = new StaticTextWidget(myTab, ifont, x, y + yofs + idx * COLH, " ");
|
||||
for(int lum = 0; lum < NUM_LUMA; ++lum)
|
||||
{
|
||||
myColor[idx][lum] = new ColorWidget(myTab, _font, x + lwidth + lum * COLW, y + idx * COLH,
|
||||
COLW + 1, COLH + 1, 0, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void VideoDialog::colorPalette()
|
||||
{
|
||||
if(instance().hasConsole())
|
||||
{
|
||||
constexpr int NUM_LUMA = 8;
|
||||
constexpr int NUM_CHROMA = 16;
|
||||
const int order[2][NUM_CHROMA] =
|
||||
{
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
|
||||
{0, 1, 2, 4, 6, 8, 10, 12, 13, 11, 9, 7, 5, 3, 14, 15}
|
||||
};
|
||||
const int type = instance().console().timing() == ConsoleTiming::pal ? 1 : 0;
|
||||
|
||||
for(int idx = 0; idx < NUM_CHROMA; ++idx)
|
||||
{
|
||||
ostringstream ss;
|
||||
const int color = order[type][idx];
|
||||
|
||||
ss << Common::Base::HEX1 << std::uppercase << color;
|
||||
myColorLbl[idx]->setLabel(ss.str());
|
||||
for(int lum = 0; lum < NUM_LUMA; ++lum)
|
||||
{
|
||||
myColor[idx][lum]->setColor(color * NUM_CHROMA + lum * 2); // skip grayscale colors
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
class CommandSender;
|
||||
class CheckboxWidget;
|
||||
class ColorWidget;
|
||||
class DialogContainer;
|
||||
class PopUpWidget;
|
||||
class RadioButtonGroup;
|
||||
|
@ -29,6 +30,7 @@ class TabWidget;
|
|||
class OSystem;
|
||||
|
||||
#include "Dialog.hxx"
|
||||
#include "PaletteHandler.hxx"
|
||||
#include "NTSCFilter.hxx"
|
||||
#include "bspf.hxx"
|
||||
|
||||
|
@ -50,10 +52,13 @@ class VideoDialog : public Dialog
|
|||
void handleTVModeChange(NTSCFilter::Preset);
|
||||
void loadTVAdjustables(NTSCFilter::Preset preset);
|
||||
void handlePaletteChange();
|
||||
void handlePaletteUpdate();
|
||||
void handleFullScreenChange();
|
||||
void handleOverscanChange();
|
||||
void handlePhosphorChange();
|
||||
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
|
||||
void addPalette(int x, int y, int h, int w);
|
||||
void colorPalette();
|
||||
|
||||
private:
|
||||
TabWidget* myTab;
|
||||
|
@ -77,6 +82,9 @@ class VideoDialog : public Dialog
|
|||
CheckboxWidget* myUIMessages{nullptr};
|
||||
CheckboxWidget* myFastSCBios{nullptr};
|
||||
CheckboxWidget* myUseThreads{nullptr};
|
||||
std::array<StaticTextWidget*, 16> myColorLbl{nullptr};
|
||||
//std::array<ColorWidget*, 16> myColor{nullptr};
|
||||
ColorWidget* myColor[16][8]{nullptr};
|
||||
|
||||
// TV effects adjustables (custom mode)
|
||||
PopUpWidget* myTVMode{nullptr};
|
||||
|
@ -106,10 +114,14 @@ class VideoDialog : public Dialog
|
|||
ButtonWidget* myCloneBad{nullptr};
|
||||
ButtonWidget* myCloneCustom{nullptr};
|
||||
|
||||
string myPalette;
|
||||
PaletteHandler::Adjustable myPaletteAdj{0.0F};
|
||||
|
||||
enum {
|
||||
kPaletteChanged = 'VDpl',
|
||||
kNtscShiftChanged = 'VDns',
|
||||
kPalShiftChanged = 'VDps',
|
||||
kPaletteUpdated = 'VDpu',
|
||||
kSpeedupChanged = 'VDSp',
|
||||
kVSizeChanged = 'VDVs',
|
||||
kFullScreenChanged = 'VDFs',
|
||||
|
|
Loading…
Reference in New Issue