Skip to content

Commit

Permalink
add splashscreen
Browse files Browse the repository at this point in the history
  • Loading branch information
Arisotura committed Oct 31, 2024
1 parent 540ebe7 commit 6c6cefa
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 7 deletions.
1 change: 1 addition & 0 deletions res/melon.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
<RCC version="1.0">
<qresource>
<file alias="melon-icon">icon/melon_256x256.png</file>
<file alias="melon-logo">melon.svg</file>
</qresource>
</RCC>
5 changes: 3 additions & 2 deletions src/frontend/qt_sdl/OSD_shaders.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ uniform vec2 uScreenSize;
uniform ivec2 uOSDPos;
uniform ivec2 uOSDSize;
uniform float uScaleFactor;
uniform float uTexScale;

in vec2 vPosition;

Expand All @@ -35,8 +36,8 @@ void main()
{
vec4 fpos;

vec2 osdpos = (vPosition * vec2(uOSDSize * uScaleFactor));
fTexcoord = osdpos;
vec2 osdpos = (vPosition * vec2(uOSDSize));
fTexcoord = osdpos * uTexScale;
osdpos += uOSDPos;

fpos.xy = ((osdpos * 2.0) / uScreenSize * uScaleFactor) - 1.0;
Expand Down
185 changes: 182 additions & 3 deletions src/frontend/qt_sdl/Screen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,13 @@
#include "main_shaders.h"
#include "OSD_shaders.h"
#include "font.h"
#include "version.h"

using namespace melonDS;


const u32 kOSDMargin = 6;
const int kLogoWidth = 192;


ScreenPanel::ScreenPanel(QWidget* parent) : QWidget(parent)
Expand Down Expand Up @@ -80,6 +82,29 @@ ScreenPanel::ScreenPanel(QWidget* parent) : QWidget(parent)

loadConfig();
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()
Expand Down Expand Up @@ -150,6 +175,8 @@ void ScreenPanel::setupScreenLayout()
aspectBot);

numScreens = layout.GetScreenTransforms(screenMatrix[0], screenKind);

calcSplashLayout();
}

QSize ScreenPanel::screenGetMinSize(int factor = 1)
Expand Down Expand Up @@ -483,8 +510,14 @@ void ScreenPanel::osdRenderItem(OSDItem* item)
u32 color = item->color;

bool rainbow = (color == 0);
u32 ticks = (u32)QDateTime::currentMSecsSinceEpoch();
u32 rainbowinc = ((text[0] * 17) + (ticks * 13)) % 600;
u32 rainbowinc;
if (item->rainbowstart == -1)
{
u32 ticks = (u32) QDateTime::currentMSecsSinceEpoch();
rainbowinc = ((text[0] * 17) + (ticks * 13)) % 600;
}
else
rainbowinc = (u32)item->rainbowstart;

color |= 0xFF000000;
const u32 shadow = 0xE0000000;
Expand Down Expand Up @@ -582,6 +615,8 @@ void ScreenPanel::osdRenderItem(OSDItem* item)
bitmap[(y * w) + x] = shadow;
}
}

item->rainbowend = (int)rainbowinc;
}

void ScreenPanel::osdDeleteItem(OSDItem* item)
Expand All @@ -603,11 +638,12 @@ void ScreenPanel::osdAddMessage(unsigned int color, const char* text)

OSDItem item;

item.id = osdID++;
item.id = (osdID++) & 0x7FFFFFFF;
item.timestamp = QDateTime::currentMSecsSinceEpoch();
strncpy(item.text, text, 255); item.text[255] = '\0';
item.color = color;
item.rendered = false;
item.rainbowstart = -1;

osdItems.push_back(item);

Expand Down Expand Up @@ -641,6 +677,73 @@ void ScreenPanel::osdUpdate()
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();
}

Expand Down Expand Up @@ -708,6 +811,20 @@ void ScreenPanelNative::paintEvent(QPaintEvent* event)
}

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)
{
osdMutex.lock();
Expand Down Expand Up @@ -862,6 +979,7 @@ void ScreenPanelGL::initOpenGL()
osdPosULoc = glGetUniformLocation(osdShader, "uOSDPos");
osdSizeULoc = glGetUniformLocation(osdShader, "uOSDSize");
osdScaleFactorULoc = glGetUniformLocation(osdShader, "uScaleFactor");
osdTexScaleULoc = glGetUniformLocation(osdShader, "uTexScale");

const float osdvertices[6*2] =
{
Expand All @@ -882,6 +1000,18 @@ void ScreenPanelGL::initOpenGL()
glEnableVertexAttribArray(0); // position
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();
glInited = true;
}
Expand All @@ -908,6 +1038,8 @@ void ScreenPanelGL::deinitOpenGL()
glDeleteVertexArrays(1, &osdVertexArray);
glDeleteBuffers(1, &osdVertexBuffer);

glDeleteTextures(1, &logoTexture);

glDeleteProgram(osdShader);


Expand Down Expand Up @@ -1023,6 +1155,52 @@ void ScreenPanelGL::drawScreenGL()
}

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)
{
osdMutex.lock();
Expand All @@ -1033,6 +1211,7 @@ void ScreenPanelGL::drawScreenGL()

glUniform2f(osdScreenSizeULoc, w, h);
glUniform1f(osdScaleFactorULoc, factor);
glUniform1f(osdTexScaleULoc, 1.0);

glBindBuffer(GL_ARRAY_BUFFER, osdVertexBuffer);
glBindVertexArray(osdVertexArray);
Expand Down
16 changes: 14 additions & 2 deletions src/frontend/qt_sdl/Screen.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,20 @@ private slots:

bool rendered;
QImage bitmap;

int rainbowstart;
int rainbowend;
};

QMutex osdMutex;
bool osdEnabled;
unsigned int osdID;
std::deque<OSDItem> osdItems;

QPixmap splashLogo;
OSDItem splashText[3];
QPoint splashPos[4];

void loadConfig();

virtual void setupScreenLayout();
Expand All @@ -141,6 +148,8 @@ private slots:
virtual void osdDeleteItem(OSDItem* item);

void osdUpdate();

void calcSplashLayout();
};


Expand Down Expand Up @@ -202,7 +211,7 @@ class ScreenPanelGL : public ScreenPanel
GLuint screenVertexBuffer, screenVertexArray;
GLuint screenTexture;
GLuint screenShaderProgram;
GLuint screenShaderTransformULoc, screenShaderScreenSizeULoc;
GLint screenShaderTransformULoc, screenShaderScreenSizeULoc;

QMutex screenSettingsLock;
WindowInfo windowInfo;
Expand All @@ -211,11 +220,14 @@ class ScreenPanelGL : public ScreenPanel

GLuint osdShader;
GLint osdScreenSizeULoc, osdPosULoc, osdSizeULoc;
GLfloat osdScaleFactorULoc;
GLint osdScaleFactorULoc;
GLint osdTexScaleULoc;
GLuint osdVertexArray;
GLuint osdVertexBuffer;
std::map<unsigned int, GLuint> osdTextures;

GLuint logoTexture;

void osdRenderItem(OSDItem* item) override;
void osdDeleteItem(OSDItem* item) override;
};
Expand Down

0 comments on commit 6c6cefa

Please sign in to comment.