mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2024-11-14 05:17:40 -07:00
add splashscreen
This commit is contained in:
parent
540ebe7256
commit
6c6cefad6c
@ -2,5 +2,6 @@
|
|||||||
<RCC version="1.0">
|
<RCC version="1.0">
|
||||||
<qresource>
|
<qresource>
|
||||||
<file alias="melon-icon">icon/melon_256x256.png</file>
|
<file alias="melon-icon">icon/melon_256x256.png</file>
|
||||||
|
<file alias="melon-logo">melon.svg</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
@ -26,6 +26,7 @@ uniform vec2 uScreenSize;
|
|||||||
uniform ivec2 uOSDPos;
|
uniform ivec2 uOSDPos;
|
||||||
uniform ivec2 uOSDSize;
|
uniform ivec2 uOSDSize;
|
||||||
uniform float uScaleFactor;
|
uniform float uScaleFactor;
|
||||||
|
uniform float uTexScale;
|
||||||
|
|
||||||
in vec2 vPosition;
|
in vec2 vPosition;
|
||||||
|
|
||||||
@ -35,8 +36,8 @@ void main()
|
|||||||
{
|
{
|
||||||
vec4 fpos;
|
vec4 fpos;
|
||||||
|
|
||||||
vec2 osdpos = (vPosition * vec2(uOSDSize * uScaleFactor));
|
vec2 osdpos = (vPosition * vec2(uOSDSize));
|
||||||
fTexcoord = osdpos;
|
fTexcoord = osdpos * uTexScale;
|
||||||
osdpos += uOSDPos;
|
osdpos += uOSDPos;
|
||||||
|
|
||||||
fpos.xy = ((osdpos * 2.0) / uScreenSize * uScaleFactor) - 1.0;
|
fpos.xy = ((osdpos * 2.0) / uScreenSize * uScaleFactor) - 1.0;
|
||||||
|
@ -46,11 +46,13 @@
|
|||||||
#include "main_shaders.h"
|
#include "main_shaders.h"
|
||||||
#include "OSD_shaders.h"
|
#include "OSD_shaders.h"
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
using namespace melonDS;
|
using namespace melonDS;
|
||||||
|
|
||||||
|
|
||||||
const u32 kOSDMargin = 6;
|
const u32 kOSDMargin = 6;
|
||||||
|
const int kLogoWidth = 192;
|
||||||
|
|
||||||
|
|
||||||
ScreenPanel::ScreenPanel(QWidget* parent) : QWidget(parent)
|
ScreenPanel::ScreenPanel(QWidget* parent) : QWidget(parent)
|
||||||
@ -80,6 +82,29 @@ ScreenPanel::ScreenPanel(QWidget* parent) : QWidget(parent)
|
|||||||
|
|
||||||
loadConfig();
|
loadConfig();
|
||||||
setFilter(mainWindow->getWindowConfig().GetBool("ScreenFilter"));
|
setFilter(mainWindow->getWindowConfig().GetBool("ScreenFilter"));
|
||||||
|
|
||||||
|
splashLogo = QPixmap(":/melon-logo");
|
||||||
|
|
||||||
|
strncpy(splashText[0].text, "File->Open ROM...", 256);
|
||||||
|
splashText[0].id = 0x80000000;
|
||||||
|
splashText[0].color = 0;
|
||||||
|
splashText[0].rendered = false;
|
||||||
|
splashText[0].rainbowstart = -1;
|
||||||
|
|
||||||
|
strncpy(splashText[1].text, "to get started", 256);
|
||||||
|
splashText[1].id = 0x80000001;
|
||||||
|
splashText[1].color = 0;
|
||||||
|
splashText[1].rendered = false;
|
||||||
|
splashText[1].rainbowstart = -1;
|
||||||
|
|
||||||
|
std::string url = MELONDS_URL;
|
||||||
|
int urlpos = url.find("://");
|
||||||
|
urlpos = (urlpos == std::string::npos) ? 0 : urlpos+3;
|
||||||
|
strncpy(splashText[2].text, url.c_str() + urlpos, 256);
|
||||||
|
splashText[2].id = 0x80000002;
|
||||||
|
splashText[2].color = 0;
|
||||||
|
splashText[2].rendered = false;
|
||||||
|
splashText[2].rainbowstart = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScreenPanel::~ScreenPanel()
|
ScreenPanel::~ScreenPanel()
|
||||||
@ -150,6 +175,8 @@ void ScreenPanel::setupScreenLayout()
|
|||||||
aspectBot);
|
aspectBot);
|
||||||
|
|
||||||
numScreens = layout.GetScreenTransforms(screenMatrix[0], screenKind);
|
numScreens = layout.GetScreenTransforms(screenMatrix[0], screenKind);
|
||||||
|
|
||||||
|
calcSplashLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize ScreenPanel::screenGetMinSize(int factor = 1)
|
QSize ScreenPanel::screenGetMinSize(int factor = 1)
|
||||||
@ -483,8 +510,14 @@ void ScreenPanel::osdRenderItem(OSDItem* item)
|
|||||||
u32 color = item->color;
|
u32 color = item->color;
|
||||||
|
|
||||||
bool rainbow = (color == 0);
|
bool rainbow = (color == 0);
|
||||||
u32 ticks = (u32)QDateTime::currentMSecsSinceEpoch();
|
u32 rainbowinc;
|
||||||
u32 rainbowinc = ((text[0] * 17) + (ticks * 13)) % 600;
|
if (item->rainbowstart == -1)
|
||||||
|
{
|
||||||
|
u32 ticks = (u32) QDateTime::currentMSecsSinceEpoch();
|
||||||
|
rainbowinc = ((text[0] * 17) + (ticks * 13)) % 600;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rainbowinc = (u32)item->rainbowstart;
|
||||||
|
|
||||||
color |= 0xFF000000;
|
color |= 0xFF000000;
|
||||||
const u32 shadow = 0xE0000000;
|
const u32 shadow = 0xE0000000;
|
||||||
@ -582,6 +615,8 @@ void ScreenPanel::osdRenderItem(OSDItem* item)
|
|||||||
bitmap[(y * w) + x] = shadow;
|
bitmap[(y * w) + x] = shadow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
item->rainbowend = (int)rainbowinc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenPanel::osdDeleteItem(OSDItem* item)
|
void ScreenPanel::osdDeleteItem(OSDItem* item)
|
||||||
@ -603,11 +638,12 @@ void ScreenPanel::osdAddMessage(unsigned int color, const char* text)
|
|||||||
|
|
||||||
OSDItem item;
|
OSDItem item;
|
||||||
|
|
||||||
item.id = osdID++;
|
item.id = (osdID++) & 0x7FFFFFFF;
|
||||||
item.timestamp = QDateTime::currentMSecsSinceEpoch();
|
item.timestamp = QDateTime::currentMSecsSinceEpoch();
|
||||||
strncpy(item.text, text, 255); item.text[255] = '\0';
|
strncpy(item.text, text, 255); item.text[255] = '\0';
|
||||||
item.color = color;
|
item.color = color;
|
||||||
item.rendered = false;
|
item.rendered = false;
|
||||||
|
item.rainbowstart = -1;
|
||||||
|
|
||||||
osdItems.push_back(item);
|
osdItems.push_back(item);
|
||||||
|
|
||||||
@ -641,6 +677,73 @@ void ScreenPanel::osdUpdate()
|
|||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// render splashscreen text items if needed
|
||||||
|
|
||||||
|
int rainbowinc = -1;
|
||||||
|
bool needrecalc = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
if (!splashText[i].rendered)
|
||||||
|
{
|
||||||
|
splashText[i].rainbowstart = rainbowinc;
|
||||||
|
osdRenderItem(&splashText[i]);
|
||||||
|
splashText[i].rendered = true;
|
||||||
|
rainbowinc = splashText[i].rainbowend;
|
||||||
|
needrecalc = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
osdMutex.unlock();
|
||||||
|
|
||||||
|
if (needrecalc)
|
||||||
|
calcSplashLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenPanel::calcSplashLayout()
|
||||||
|
{
|
||||||
|
if (!splashText[0].rendered)
|
||||||
|
return;
|
||||||
|
|
||||||
|
osdMutex.lock();
|
||||||
|
|
||||||
|
int w = width();
|
||||||
|
int h = height();
|
||||||
|
|
||||||
|
int xlogo = (w - kLogoWidth) / 2;
|
||||||
|
int ylogo = (h - kLogoWidth) / 2;
|
||||||
|
|
||||||
|
// top text
|
||||||
|
int totalwidth = splashText[0].bitmap.width() + 6 + splashText[1].bitmap.width();
|
||||||
|
if (totalwidth >= w)
|
||||||
|
{
|
||||||
|
// stacked vertically
|
||||||
|
splashPos[0].setX((width() - splashText[0].bitmap.width()) / 2);
|
||||||
|
splashPos[1].setX((width() - splashText[1].bitmap.width()) / 2);
|
||||||
|
|
||||||
|
int basey = ylogo / 2;
|
||||||
|
splashPos[0].setY(basey - splashText[0].bitmap.height() - 1);
|
||||||
|
splashPos[1].setY(basey + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// horizontal
|
||||||
|
splashPos[0].setX((w - totalwidth) / 2);
|
||||||
|
splashPos[1].setX(splashPos[0].x() + splashText[0].bitmap.width() + 6);
|
||||||
|
|
||||||
|
int basey = (ylogo - splashText[0].bitmap.height()) / 2;
|
||||||
|
splashPos[0].setY(basey);
|
||||||
|
splashPos[1].setY(basey);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bottom text
|
||||||
|
splashPos[2].setX((w - splashText[2].bitmap.width()) / 2);
|
||||||
|
splashPos[2].setY(ylogo + kLogoWidth + ((ylogo - splashText[2].bitmap.height()) / 2));
|
||||||
|
|
||||||
|
// logo
|
||||||
|
splashPos[3].setX(xlogo);
|
||||||
|
splashPos[3].setY(ylogo);
|
||||||
|
|
||||||
osdMutex.unlock();
|
osdMutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -708,6 +811,20 @@ void ScreenPanelNative::paintEvent(QPaintEvent* event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
osdUpdate();
|
osdUpdate();
|
||||||
|
|
||||||
|
if (!emuThread->emuIsActive())
|
||||||
|
{
|
||||||
|
// splashscreen
|
||||||
|
osdMutex.lock();
|
||||||
|
|
||||||
|
painter.drawPixmap(QRect(splashPos[3], QSize(kLogoWidth, kLogoWidth)), splashLogo);
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
painter.drawImage(splashPos[i], splashText[i].bitmap);
|
||||||
|
|
||||||
|
osdMutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
if (osdEnabled)
|
if (osdEnabled)
|
||||||
{
|
{
|
||||||
osdMutex.lock();
|
osdMutex.lock();
|
||||||
@ -862,6 +979,7 @@ void ScreenPanelGL::initOpenGL()
|
|||||||
osdPosULoc = glGetUniformLocation(osdShader, "uOSDPos");
|
osdPosULoc = glGetUniformLocation(osdShader, "uOSDPos");
|
||||||
osdSizeULoc = glGetUniformLocation(osdShader, "uOSDSize");
|
osdSizeULoc = glGetUniformLocation(osdShader, "uOSDSize");
|
||||||
osdScaleFactorULoc = glGetUniformLocation(osdShader, "uScaleFactor");
|
osdScaleFactorULoc = glGetUniformLocation(osdShader, "uScaleFactor");
|
||||||
|
osdTexScaleULoc = glGetUniformLocation(osdShader, "uTexScale");
|
||||||
|
|
||||||
const float osdvertices[6*2] =
|
const float osdvertices[6*2] =
|
||||||
{
|
{
|
||||||
@ -882,6 +1000,18 @@ void ScreenPanelGL::initOpenGL()
|
|||||||
glEnableVertexAttribArray(0); // position
|
glEnableVertexAttribArray(0); // position
|
||||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)(0));
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)(0));
|
||||||
|
|
||||||
|
// splash logo texture
|
||||||
|
QImage logo = splashLogo.scaled(kLogoWidth*2, kLogoWidth*2).toImage();
|
||||||
|
GLuint tex;
|
||||||
|
glGenTextures(1, &tex);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, tex);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, logo.width(), logo.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, logo.bits());
|
||||||
|
logoTexture = tex;
|
||||||
|
|
||||||
transferLayout();
|
transferLayout();
|
||||||
glInited = true;
|
glInited = true;
|
||||||
}
|
}
|
||||||
@ -908,6 +1038,8 @@ void ScreenPanelGL::deinitOpenGL()
|
|||||||
glDeleteVertexArrays(1, &osdVertexArray);
|
glDeleteVertexArrays(1, &osdVertexArray);
|
||||||
glDeleteBuffers(1, &osdVertexBuffer);
|
glDeleteBuffers(1, &osdVertexBuffer);
|
||||||
|
|
||||||
|
glDeleteTextures(1, &logoTexture);
|
||||||
|
|
||||||
glDeleteProgram(osdShader);
|
glDeleteProgram(osdShader);
|
||||||
|
|
||||||
|
|
||||||
@ -1023,6 +1155,52 @@ void ScreenPanelGL::drawScreenGL()
|
|||||||
}
|
}
|
||||||
|
|
||||||
osdUpdate();
|
osdUpdate();
|
||||||
|
|
||||||
|
if (!emuThread->emuIsActive())
|
||||||
|
{
|
||||||
|
// splashscreen
|
||||||
|
osdMutex.lock();
|
||||||
|
|
||||||
|
glUseProgram(osdShader);
|
||||||
|
|
||||||
|
glUniform2f(osdScreenSizeULoc, w, h);
|
||||||
|
glUniform1f(osdScaleFactorULoc, factor);
|
||||||
|
glUniform1f(osdTexScaleULoc, 2.0);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, osdVertexBuffer);
|
||||||
|
glBindVertexArray(osdVertexArray);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, logoTexture);
|
||||||
|
glUniform2i(osdPosULoc, splashPos[3].x(), splashPos[3].y());
|
||||||
|
glUniform2i(osdSizeULoc, kLogoWidth, kLogoWidth);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 2*3);
|
||||||
|
|
||||||
|
glUniform1f(osdTexScaleULoc, 1.0);
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
OSDItem& item = splashText[i];
|
||||||
|
|
||||||
|
if (!osdTextures.count(item.id))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, osdTextures[item.id]);
|
||||||
|
glUniform2i(osdPosULoc, splashPos[i].x(), splashPos[i].y());
|
||||||
|
glUniform2i(osdSizeULoc, item.bitmap.width(), item.bitmap.height());
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 2*3);
|
||||||
|
}
|
||||||
|
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
glUseProgram(0);
|
||||||
|
|
||||||
|
osdMutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
if (osdEnabled)
|
if (osdEnabled)
|
||||||
{
|
{
|
||||||
osdMutex.lock();
|
osdMutex.lock();
|
||||||
@ -1033,6 +1211,7 @@ void ScreenPanelGL::drawScreenGL()
|
|||||||
|
|
||||||
glUniform2f(osdScreenSizeULoc, w, h);
|
glUniform2f(osdScreenSizeULoc, w, h);
|
||||||
glUniform1f(osdScaleFactorULoc, factor);
|
glUniform1f(osdScaleFactorULoc, factor);
|
||||||
|
glUniform1f(osdTexScaleULoc, 1.0);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, osdVertexBuffer);
|
glBindBuffer(GL_ARRAY_BUFFER, osdVertexBuffer);
|
||||||
glBindVertexArray(osdVertexArray);
|
glBindVertexArray(osdVertexArray);
|
||||||
|
@ -110,6 +110,9 @@ protected:
|
|||||||
|
|
||||||
bool rendered;
|
bool rendered;
|
||||||
QImage bitmap;
|
QImage bitmap;
|
||||||
|
|
||||||
|
int rainbowstart;
|
||||||
|
int rainbowend;
|
||||||
};
|
};
|
||||||
|
|
||||||
QMutex osdMutex;
|
QMutex osdMutex;
|
||||||
@ -117,6 +120,10 @@ protected:
|
|||||||
unsigned int osdID;
|
unsigned int osdID;
|
||||||
std::deque<OSDItem> osdItems;
|
std::deque<OSDItem> osdItems;
|
||||||
|
|
||||||
|
QPixmap splashLogo;
|
||||||
|
OSDItem splashText[3];
|
||||||
|
QPoint splashPos[4];
|
||||||
|
|
||||||
void loadConfig();
|
void loadConfig();
|
||||||
|
|
||||||
virtual void setupScreenLayout();
|
virtual void setupScreenLayout();
|
||||||
@ -141,6 +148,8 @@ protected:
|
|||||||
virtual void osdDeleteItem(OSDItem* item);
|
virtual void osdDeleteItem(OSDItem* item);
|
||||||
|
|
||||||
void osdUpdate();
|
void osdUpdate();
|
||||||
|
|
||||||
|
void calcSplashLayout();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -202,7 +211,7 @@ private:
|
|||||||
GLuint screenVertexBuffer, screenVertexArray;
|
GLuint screenVertexBuffer, screenVertexArray;
|
||||||
GLuint screenTexture;
|
GLuint screenTexture;
|
||||||
GLuint screenShaderProgram;
|
GLuint screenShaderProgram;
|
||||||
GLuint screenShaderTransformULoc, screenShaderScreenSizeULoc;
|
GLint screenShaderTransformULoc, screenShaderScreenSizeULoc;
|
||||||
|
|
||||||
QMutex screenSettingsLock;
|
QMutex screenSettingsLock;
|
||||||
WindowInfo windowInfo;
|
WindowInfo windowInfo;
|
||||||
@ -211,11 +220,14 @@ private:
|
|||||||
|
|
||||||
GLuint osdShader;
|
GLuint osdShader;
|
||||||
GLint osdScreenSizeULoc, osdPosULoc, osdSizeULoc;
|
GLint osdScreenSizeULoc, osdPosULoc, osdSizeULoc;
|
||||||
GLfloat osdScaleFactorULoc;
|
GLint osdScaleFactorULoc;
|
||||||
|
GLint osdTexScaleULoc;
|
||||||
GLuint osdVertexArray;
|
GLuint osdVertexArray;
|
||||||
GLuint osdVertexBuffer;
|
GLuint osdVertexBuffer;
|
||||||
std::map<unsigned int, GLuint> osdTextures;
|
std::map<unsigned int, GLuint> osdTextures;
|
||||||
|
|
||||||
|
GLuint logoTexture;
|
||||||
|
|
||||||
void osdRenderItem(OSDItem* item) override;
|
void osdRenderItem(OSDItem* item) override;
|
||||||
void osdDeleteItem(OSDItem* item) override;
|
void osdDeleteItem(OSDItem* item) override;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user