mirror of
https://github.com/wiiu-env/launchiine.git
synced 2024-11-22 17:59:16 +01:00
WIP; not compiling
This commit is contained in:
parent
b4cecf10e8
commit
a414e068c2
2
Makefile
2
Makefile
@ -44,7 +44,7 @@ CFLAGS := -g -Wall -O2 -ffunction-sections \
|
|||||||
|
|
||||||
CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__
|
CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__
|
||||||
|
|
||||||
CXXFLAGS := $(CFLAGS)
|
CXXFLAGS := $(CFLAGS) -std=c++20
|
||||||
|
|
||||||
ASFLAGS := -g $(ARCH)
|
ASFLAGS := -g $(ARCH)
|
||||||
LDFLAGS = -g $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map)
|
LDFLAGS = -g $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map)
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
#include "common/common.h"
|
#include "common/common.h"
|
||||||
#include "resources/Resources.h"
|
#include "resources/Resources.h"
|
||||||
#include "system/memory.h"
|
#include "system/memory.h"
|
||||||
#include "utils/AsyncExecutor.h"
|
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include <coreinit/core.h>
|
#include <coreinit/core.h>
|
||||||
#include <coreinit/foreground.h>
|
#include <coreinit/foreground.h>
|
||||||
@ -37,44 +36,30 @@ bool Application::quitRequest = false;
|
|||||||
|
|
||||||
Application::Application()
|
Application::Application()
|
||||||
: CThread(CThread::eAttributeAffCore1 | CThread::eAttributePinnedAff, 0, 0x800000), bgMusic(nullptr), video(nullptr), mainWindow(nullptr), fontSystem(nullptr), exitCode(0) {
|
: CThread(CThread::eAttributeAffCore1 | CThread::eAttributePinnedAff, 0, 0x800000), bgMusic(nullptr), video(nullptr), mainWindow(nullptr), fontSystem(nullptr), exitCode(0) {
|
||||||
controller[0] = new VPadController(GuiTrigger::CHANNEL_1);
|
controller[0] = std::make_unique<VPadController>(GuiTrigger::CHANNEL_1);
|
||||||
controller[1] = new WPadController(GuiTrigger::CHANNEL_2);
|
controller[1] = std::make_unique<WPadController>(GuiTrigger::CHANNEL_2);
|
||||||
controller[2] = new WPadController(GuiTrigger::CHANNEL_3);
|
controller[2] = std::make_unique<WPadController>(GuiTrigger::CHANNEL_3);
|
||||||
controller[3] = new WPadController(GuiTrigger::CHANNEL_4);
|
controller[3] = std::make_unique<WPadController>(GuiTrigger::CHANNEL_4);
|
||||||
controller[4] = new WPadController(GuiTrigger::CHANNEL_5);
|
controller[4] = std::make_unique<WPadController>(GuiTrigger::CHANNEL_5);
|
||||||
|
|
||||||
//! create bgMusic
|
//! create bgMusic
|
||||||
bgMusic = new GuiSound(Resources::GetFile("bgMusic.ogg"), Resources::GetFileSize("bgMusic.ogg"));
|
bgMusic = std::make_unique<GuiSound>(Resources::GetFile("bgMusic.ogg"));
|
||||||
bgMusic->SetLoop(true);
|
bgMusic->SetLoop(true);
|
||||||
bgMusic->Play();
|
bgMusic->Play();
|
||||||
bgMusic->SetVolume(50);
|
bgMusic->SetVolume(50);
|
||||||
|
|
||||||
AsyncExecutor::execute([] { DEBUG_FUNCTION_LINE("Hello"); });
|
|
||||||
|
|
||||||
exitApplication = false;
|
exitApplication = false;
|
||||||
|
|
||||||
ProcUIInit(OSSavesDone_ReadyToRelease);
|
ProcUIInit(OSSavesDone_ReadyToRelease);
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::~Application() {
|
Application::~Application() {
|
||||||
DEBUG_FUNCTION_LINE("Destroy music");
|
|
||||||
delete bgMusic;
|
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("Destroy controller");
|
|
||||||
|
|
||||||
for (auto &i : controller) {
|
|
||||||
delete i;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("Clear resources");
|
DEBUG_FUNCTION_LINE("Clear resources");
|
||||||
Resources::Clear();
|
Resources::Clear();
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("Stop sound handler");
|
DEBUG_FUNCTION_LINE("Stop sound handler");
|
||||||
SoundHandler::DestroyInstance();
|
SoundHandler::DestroyInstance();
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("Clear AsyncExecutor");
|
|
||||||
AsyncExecutor::destroyInstance();
|
|
||||||
|
|
||||||
ProcUIShutdown();
|
ProcUIShutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,10 +89,10 @@ void Application::fadeOut() {
|
|||||||
|
|
||||||
//! start rendering DRC
|
//! start rendering DRC
|
||||||
video->prepareDrcRendering();
|
video->prepareDrcRendering();
|
||||||
mainWindow->drawDrc(video);
|
mainWindow->drawDrc(*video);
|
||||||
|
|
||||||
GX2SetDepthOnlyControl(GX2_DISABLE, GX2_DISABLE, GX2_COMPARE_FUNC_ALWAYS);
|
GX2SetDepthOnlyControl(GX2_DISABLE, GX2_DISABLE, GX2_COMPARE_FUNC_ALWAYS);
|
||||||
fadeOut.draw(video);
|
fadeOut.draw(*video);
|
||||||
GX2SetDepthOnlyControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_FUNC_LEQUAL);
|
GX2SetDepthOnlyControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_FUNC_LEQUAL);
|
||||||
|
|
||||||
video->drcDrawDone();
|
video->drcDrawDone();
|
||||||
@ -115,10 +100,10 @@ void Application::fadeOut() {
|
|||||||
//! start rendering TV
|
//! start rendering TV
|
||||||
video->prepareTvRendering();
|
video->prepareTvRendering();
|
||||||
|
|
||||||
mainWindow->drawTv(video);
|
mainWindow->drawTv(*video);
|
||||||
|
|
||||||
GX2SetDepthOnlyControl(GX2_DISABLE, GX2_DISABLE, GX2_COMPARE_FUNC_ALWAYS);
|
GX2SetDepthOnlyControl(GX2_DISABLE, GX2_DISABLE, GX2_COMPARE_FUNC_ALWAYS);
|
||||||
fadeOut.draw(video);
|
fadeOut.draw(*video);
|
||||||
GX2SetDepthOnlyControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_FUNC_LEQUAL);
|
GX2SetDepthOnlyControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_FUNC_LEQUAL);
|
||||||
|
|
||||||
video->tvDrawDone();
|
video->tvDrawDone();
|
||||||
@ -148,12 +133,10 @@ bool Application::procUI() {
|
|||||||
video->drcEnable(true);
|
video->drcEnable(true);
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("delete fontSystem");
|
DEBUG_FUNCTION_LINE("delete fontSystem");
|
||||||
delete fontSystem;
|
fontSystem.reset();
|
||||||
fontSystem = nullptr;
|
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("delete video");
|
DEBUG_FUNCTION_LINE("delete video");
|
||||||
delete video;
|
video.reset();
|
||||||
video = nullptr;
|
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("deinitialze memory");
|
DEBUG_FUNCTION_LINE("deinitialze memory");
|
||||||
libgui_memoryRelease();
|
libgui_memoryRelease();
|
||||||
@ -171,17 +154,17 @@ bool Application::procUI() {
|
|||||||
libgui_memoryInitialize();
|
libgui_memoryInitialize();
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("Initialize video");
|
DEBUG_FUNCTION_LINE("Initialize video");
|
||||||
video = new CVideo(GX2_TV_SCAN_MODE_720P, GX2_DRC_RENDER_MODE_SINGLE);
|
video = std::make_unique<CVideo>(GX2_TV_SCAN_MODE_720P, GX2_DRC_RENDER_MODE_SINGLE);
|
||||||
DEBUG_FUNCTION_LINE("Video size %i x %i", video->getTvWidth(), video->getTvHeight());
|
DEBUG_FUNCTION_LINE("Video size %i x %i", video->getTvWidth(), video->getTvHeight());
|
||||||
|
|
||||||
//! setup default Font
|
//! setup default Font
|
||||||
DEBUG_FUNCTION_LINE("Initialize main font system");
|
DEBUG_FUNCTION_LINE("Initialize main font system");
|
||||||
auto *fontSystem = new FreeTypeGX(Resources::GetFile("font.ttf"), Resources::GetFileSize("font.ttf"), true);
|
fontSystem = std::make_shared<FreeTypeGX>(Resources::GetFile("font.ttf"), true);
|
||||||
GuiText::setPresetFont(fontSystem);
|
GuiText::setPresetFont(fontSystem);
|
||||||
|
|
||||||
if (mainWindow == nullptr) {
|
if (mainWindow == nullptr) {
|
||||||
DEBUG_FUNCTION_LINE("Initialize main window");
|
DEBUG_FUNCTION_LINE("Initialize main window");
|
||||||
mainWindow = new MainWindow(video->getTvWidth(), video->getTvHeight());
|
mainWindow = std::make_unique<MainWindow>(video->getTvWidth(), video->getTvHeight());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
executeProcess = true;
|
executeProcess = true;
|
||||||
@ -214,17 +197,17 @@ void Application::executeThread() {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
//! update controller states
|
//! update controller states
|
||||||
mainWindow->update(i);
|
mainWindow->update(*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! start rendering DRC
|
//! start rendering DRC
|
||||||
video->prepareDrcRendering();
|
video->prepareDrcRendering();
|
||||||
mainWindow->drawDrc(video);
|
mainWindow->drawDrc(*video);
|
||||||
video->drcDrawDone();
|
video->drcDrawDone();
|
||||||
|
|
||||||
//! start rendering TV
|
//! start rendering TV
|
||||||
video->prepareTvRendering();
|
video->prepareTvRendering();
|
||||||
mainWindow->drawTv(video);
|
mainWindow->drawTv(*video);
|
||||||
video->tvDrawDone();
|
video->tvDrawDone();
|
||||||
|
|
||||||
//! enable screen after first frame render
|
//! enable screen after first frame render
|
||||||
@ -245,16 +228,14 @@ void Application::executeThread() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("delete mainWindow");
|
DEBUG_FUNCTION_LINE("delete mainWindow");
|
||||||
delete mainWindow;
|
mainWindow.reset();
|
||||||
mainWindow = nullptr;
|
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("delete fontSystem");
|
DEBUG_FUNCTION_LINE("delete fontSystem");
|
||||||
delete fontSystem;
|
fontSystem.reset();
|
||||||
fontSystem = nullptr;
|
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("delete video");
|
DEBUG_FUNCTION_LINE("delete video");
|
||||||
delete video;
|
video.reset();
|
||||||
video = nullptr;
|
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("deinitialize memory");
|
DEBUG_FUNCTION_LINE("deinitialize memory");
|
||||||
libgui_memoryRelease();
|
libgui_memoryRelease();
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
#include "menu/MainWindow.h"
|
#include "menu/MainWindow.h"
|
||||||
#include "system/CThread.h"
|
#include "system/CThread.h"
|
||||||
#include <video/CVideo.h>
|
#include <video/CVideo.h>
|
||||||
|
#include <memory>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
// forward declaration
|
// forward declaration
|
||||||
class FreeTypeGX;
|
class FreeTypeGX;
|
||||||
@ -39,44 +41,43 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CVideo *getVideo(void) const {
|
[[nodiscard]] CVideo *getVideo() const {
|
||||||
return video;
|
return video.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow *getMainWindow(void) const {
|
[[nodiscard]] MainWindow *getMainWindow() const {
|
||||||
return mainWindow;
|
return mainWindow.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
GuiSound *getBgMusic(void) const {
|
[[nodiscard]] GuiSound *getBgMusic() const {
|
||||||
return bgMusic;
|
return bgMusic.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
int exec(void);
|
int exec();
|
||||||
|
|
||||||
void fadeOut(void);
|
void fadeOut();
|
||||||
|
|
||||||
void quit(int code);
|
void quit(int code);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Application();
|
Application();
|
||||||
|
|
||||||
virtual ~Application();
|
~Application() override;
|
||||||
|
|
||||||
bool procUI(void);
|
bool procUI();
|
||||||
|
|
||||||
static Application *applicationInstance;
|
static Application *applicationInstance;
|
||||||
static bool exitApplication;
|
static bool exitApplication;
|
||||||
static bool quitRequest;
|
static bool quitRequest;
|
||||||
|
|
||||||
void executeThread(void);
|
void executeThread() override;
|
||||||
|
|
||||||
GuiSound *bgMusic;
|
std::unique_ptr<GuiSound> bgMusic;
|
||||||
CVideo *video;
|
std::unique_ptr<CVideo> video;
|
||||||
MainWindow *mainWindow;
|
std::unique_ptr<MainWindow> mainWindow;
|
||||||
FreeTypeGX *fontSystem;
|
std::shared_ptr<FreeTypeGX> fontSystem;
|
||||||
GuiController *controller[5]{};
|
std::array<std::unique_ptr<GuiController>, 5> controller;
|
||||||
int exitCode;
|
int exitCode;
|
||||||
BOOL sFromHBL = FALSE;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //_APPLICATION_H
|
#endif //_APPLICATION_H
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#include "utils/logger.h"
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
|
||||||
#include "StorageUtils.h"
|
#include "StorageUtils.h"
|
||||||
|
#include "utils/logger.h"
|
||||||
|
|
||||||
#include <coreinit/thread.h>
|
#include <coreinit/thread.h>
|
||||||
#include <coreinit/title.h>
|
#include <coreinit/title.h>
|
||||||
@ -90,23 +90,21 @@ void initExternalStorage() {
|
|||||||
// the lib before actually using it.
|
// the lib before actually using it.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int connectedStorage = 0;
|
int numConnectedStorage;
|
||||||
if ((connectedStorage = numberUSBStorageDevicesConnected()) <= 0) {
|
int maxTries = 1200; // Wait up to 20 seconds, like the Wii U Menu
|
||||||
nn::spm::Initialize();
|
if ((numConnectedStorage = numberUSBStorageDevicesConnected()) <= 0) {
|
||||||
InitEmptyExternalStorage();
|
maxTries = 1; // Only try once if no USBStorageDrive is connected
|
||||||
nn::spm::Finalize();
|
} else {
|
||||||
return;
|
DEBUG_FUNCTION_LINE("Connected StorageDevices = %d", numConnectedStorage);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("Connected StorageDevices = %d", connectedStorage);
|
|
||||||
|
|
||||||
nn::spm::Initialize();
|
nn::spm::Initialize();
|
||||||
|
|
||||||
nn::spm::StorageListItem items[0x20];
|
nn::spm::StorageListItem items[0x20];
|
||||||
int tries = 0;
|
int tries = 0;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
while (tries < 1200) { // Wait up to 20 seconds, like the Wii U Menu
|
while (tries < maxTries) {
|
||||||
int32_t numItems = nn::spm::GetStorageList(items, 0x20);
|
int32_t numItems = nn::spm::GetStorageList(items, 0x20);
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("Number of items: %d", numItems);
|
DEBUG_FUNCTION_LINE("Number of items: %d", numItems);
|
||||||
@ -127,7 +125,7 @@ void initExternalStorage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (found || (connectedStorage == numItems)) {
|
if (found || (numConnectedStorage == numItems)) {
|
||||||
DEBUG_FUNCTION_LINE("Found all expected items, breaking.");
|
DEBUG_FUNCTION_LINE("Found all expected items, breaking.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -135,7 +133,10 @@ void initExternalStorage() {
|
|||||||
tries++;
|
tries++;
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
DEBUG_FUNCTION_LINE("USB Storage is connected but either it doesn't have a WFS partition or we ran into a timeout.");
|
if (numConnectedStorage > 0) {
|
||||||
|
DEBUG_FUNCTION_LINE(
|
||||||
|
"USB Storage is connected but either it doesn't have a WFS partition or we ran into a timeout.");
|
||||||
|
}
|
||||||
InitEmptyExternalStorage();
|
InitEmptyExternalStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,14 +7,7 @@
|
|||||||
#include <whb/log_udp.h>
|
#include <whb/log_udp.h>
|
||||||
|
|
||||||
int32_t main(int32_t argc, char **argv) {
|
int32_t main(int32_t argc, char **argv) {
|
||||||
bool moduleInit;
|
initLogging();
|
||||||
bool cafeInit = false;
|
|
||||||
bool udpInit = false;
|
|
||||||
|
|
||||||
if (!(moduleInit = WHBLogModuleInit())) {
|
|
||||||
cafeInit = WHBLogCafeInit();
|
|
||||||
udpInit = WHBLogUdpInit();
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("Starting launchiine " LAUNCHIINE_VERSION "");
|
DEBUG_FUNCTION_LINE("Starting launchiine " LAUNCHIINE_VERSION "");
|
||||||
|
|
||||||
@ -28,16 +21,6 @@ int32_t main(int32_t argc, char **argv) {
|
|||||||
|
|
||||||
DEBUG_FUNCTION_LINE("Peace out...");
|
DEBUG_FUNCTION_LINE("Peace out...");
|
||||||
|
|
||||||
if (cafeInit) {
|
deinitLogging();
|
||||||
WHBLogCafeDeinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (udpInit) {
|
|
||||||
WHBLogUdpDeinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (moduleInit) {
|
|
||||||
WHBLogModuleDeinit();
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
CFile::CFile() {
|
CFile::CFile() {
|
||||||
iFd = -1;
|
iFd = -1;
|
||||||
mem_file = NULL;
|
mem_file = nullptr;
|
||||||
filesize = 0;
|
filesize = 0;
|
||||||
pos = 0;
|
pos = 0;
|
||||||
}
|
}
|
||||||
@ -17,9 +17,9 @@ CFile::CFile(const std::string &filepath, eOpenTypes mode) {
|
|||||||
this->open(filepath, mode);
|
this->open(filepath, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFile::CFile(const uint8_t *mem, int32_t size) {
|
CFile::CFile(std::span<const uint8_t> data) {
|
||||||
iFd = -1;
|
iFd = -1;
|
||||||
this->open(mem, size);
|
this->open(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFile::~CFile() {
|
CFile::~CFile() {
|
||||||
@ -65,11 +65,11 @@ int32_t CFile::open(const std::string &filepath, eOpenTypes mode) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t CFile::open(const uint8_t *mem, int32_t size) {
|
int32_t CFile::open(std::span<const uint8_t> data) {
|
||||||
this->close();
|
this->close();
|
||||||
|
|
||||||
mem_file = mem;
|
mem_file = data.data();
|
||||||
filesize = size;
|
filesize = data.size();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -80,7 +80,7 @@ void CFile::close() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
iFd = -1;
|
iFd = -1;
|
||||||
mem_file = NULL;
|
mem_file = nullptr;
|
||||||
filesize = 0;
|
filesize = 0;
|
||||||
pos = 0;
|
pos = 0;
|
||||||
}
|
}
|
||||||
@ -104,7 +104,7 @@ int32_t CFile::read(uint8_t *ptr, size_t size) {
|
|||||||
return readsize;
|
return readsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mem_file != NULL) {
|
if (mem_file != nullptr) {
|
||||||
memcpy(ptr, mem_file + pos, readsize);
|
memcpy(ptr, mem_file + pos, readsize);
|
||||||
pos += readsize;
|
pos += readsize;
|
||||||
return readsize;
|
return readsize;
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
#ifndef CFILE_HPP_
|
#ifndef CFILE_HPP_
|
||||||
#define CFILE_HPP_
|
#define CFILE_HPP_
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <span>
|
||||||
#include <string.h>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <wut_types.h>
|
#include <wut_types.h>
|
||||||
@ -21,13 +22,13 @@ public:
|
|||||||
|
|
||||||
CFile(const std::string &filepath, eOpenTypes mode);
|
CFile(const std::string &filepath, eOpenTypes mode);
|
||||||
|
|
||||||
CFile(const uint8_t *memory, int32_t memsize);
|
CFile(std::span<const uint8_t> data);
|
||||||
|
|
||||||
virtual ~CFile();
|
virtual ~CFile();
|
||||||
|
|
||||||
int32_t open(const std::string &filepath, eOpenTypes mode);
|
int32_t open(const std::string &filepath, eOpenTypes mode);
|
||||||
|
|
||||||
int32_t open(const uint8_t *memory, int32_t memsize);
|
int32_t open(std::span<const uint8_t> data);
|
||||||
|
|
||||||
BOOL isOpen() const {
|
BOOL isOpen() const {
|
||||||
if (iFd >= 0) {
|
if (iFd >= 0) {
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
#include "GameList.h"
|
#include "GameList.h"
|
||||||
#include "common/common.h"
|
#include "common/common.h"
|
||||||
#include "utils/AsyncExecutor.h"
|
|
||||||
|
|
||||||
#include "fs/FSUtils.h"
|
#include "fs/FSUtils.h"
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
|
@ -31,20 +31,21 @@ using namespace std;
|
|||||||
/**
|
/**
|
||||||
* Default constructor for the FreeTypeGX class.
|
* Default constructor for the FreeTypeGX class.
|
||||||
*/
|
*/
|
||||||
FreeTypeGX::FreeTypeGX(const uint8_t *fontBuffer, FT_Long bufferSize, bool lastFace) {
|
FreeTypeGX::FreeTypeGX(std::vector<uint8_t> &&data, bool lastFace) {
|
||||||
int32_t faceIndex = 0;
|
int32_t faceIndex = 0;
|
||||||
GX2InitSampler(&ftSampler, GX2_TEX_CLAMP_MODE_CLAMP_BORDER, GX2_TEX_XY_FILTER_MODE_LINEAR);
|
GX2InitSampler(&ftSampler, GX2_TEX_CLAMP_MODE_CLAMP_BORDER, GX2_TEX_XY_FILTER_MODE_LINEAR);
|
||||||
|
rawFontData = std::move(data);
|
||||||
|
|
||||||
FT_Init_FreeType(&ftLibrary);
|
FT_Init_FreeType(&ftLibrary);
|
||||||
faceMutex.lock();
|
faceMutex.lock();
|
||||||
if (lastFace) {
|
if (lastFace) {
|
||||||
|
|
||||||
FT_New_Memory_Face(ftLibrary, (FT_Byte *) fontBuffer, bufferSize, -1, &ftFace);
|
FT_New_Memory_Face(ftLibrary, (FT_Byte *) rawFontData.data(), rawFontData.size(), -1, &ftFace);
|
||||||
faceIndex = ftFace->num_faces - 1; // Use the last face
|
faceIndex = ftFace->num_faces - 1; // Use the last face
|
||||||
FT_Done_Face(ftFace);
|
FT_Done_Face(ftFace);
|
||||||
ftFace = NULL;
|
ftFace = NULL;
|
||||||
}
|
}
|
||||||
FT_New_Memory_Face(ftLibrary, (FT_Byte *) fontBuffer, bufferSize, faceIndex, &ftFace);
|
FT_New_Memory_Face(ftLibrary, (FT_Byte *) rawFontData.data(), rawFontData.size(), faceIndex, &ftFace);
|
||||||
|
|
||||||
ftKerningEnabled = FT_HAS_KERNING(ftFace);
|
ftKerningEnabled = FT_HAS_KERNING(ftFace);
|
||||||
faceMutex.unlock();
|
faceMutex.unlock();
|
||||||
@ -60,6 +61,7 @@ FreeTypeGX::~FreeTypeGX() {
|
|||||||
FT_Done_Face(ftFace);
|
FT_Done_Face(ftFace);
|
||||||
faceMutex.unlock();
|
faceMutex.unlock();
|
||||||
FT_Done_FreeType(ftLibrary);
|
FT_Done_FreeType(ftLibrary);
|
||||||
|
rawFontData.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,8 +30,9 @@
|
|||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string.h>
|
#include <cstring>
|
||||||
#include <wchar.h>
|
#include <cwchar>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
#include <gui/gx2_ext.h>
|
#include <gui/gx2_ext.h>
|
||||||
@ -112,13 +113,14 @@ class CVideo;
|
|||||||
*/
|
*/
|
||||||
class FreeTypeGX {
|
class FreeTypeGX {
|
||||||
private:
|
private:
|
||||||
FT_Library ftLibrary; /**< FreeType FT_Library instance. */
|
FT_Library ftLibrary{}; /**< FreeType FT_Library instance. */
|
||||||
FT_Face ftFace; /**< FreeType reusable FT_Face typographic object. */
|
FT_Face ftFace; /**< FreeType reusable FT_Face typographic object. */
|
||||||
bool ftKerningEnabled; /**< Flag indicating the availability of font kerning data. */
|
bool ftKerningEnabled; /**< Flag indicating the availability of font kerning data. */
|
||||||
uint8_t vertexIndex; /**< Vertex format descriptor index. */
|
uint8_t vertexIndex{}; /**< Vertex format descriptor index. */
|
||||||
GX2Sampler ftSampler;
|
GX2Sampler ftSampler{};
|
||||||
std::recursive_mutex faceMutex;
|
std::recursive_mutex faceMutex;
|
||||||
std::recursive_mutex fontDataMutex;
|
std::recursive_mutex fontDataMutex;
|
||||||
|
std::vector<uint8_t> rawFontData;
|
||||||
|
|
||||||
typedef struct _ftGX2Data {
|
typedef struct _ftGX2Data {
|
||||||
ftgxDataOffset ftgxAlign;
|
ftgxDataOffset ftgxAlign;
|
||||||
@ -143,7 +145,7 @@ private:
|
|||||||
const float &superSamplingScale);
|
const float &superSamplingScale);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FreeTypeGX(const uint8_t *fontBuffer, FT_Long bufferSize, bool lastFace = false);
|
FreeTypeGX(std::vector<uint8_t>&& data, bool lastFace = false);
|
||||||
|
|
||||||
~FreeTypeGX();
|
~FreeTypeGX();
|
||||||
|
|
||||||
|
@ -1,40 +0,0 @@
|
|||||||
#include <gui/GameBgImage.h>
|
|
||||||
#include <video/CVideo.h>
|
|
||||||
#include <video/shaders/Shader3D.h>
|
|
||||||
|
|
||||||
GameBgImage::GameBgImage(const std::string &filename, GuiImageData *preloadImage)
|
|
||||||
: GuiImageAsync(filename, preloadImage) {
|
|
||||||
identity = glm::mat4(1.0f);
|
|
||||||
alphaFadeOut = glm::vec4(1.0f, 0.075f, 5.305f, 2.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
GameBgImage::~GameBgImage() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void GameBgImage::draw(CVideo *pVideo) {
|
|
||||||
if (!getImageData() || !getImageData()->getTexture()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! first setup 2D GUI positions
|
|
||||||
float currPosX = getCenterX();
|
|
||||||
float currPosY = getCenterY();
|
|
||||||
float currPosZ = getDepth();
|
|
||||||
float currScaleX = getScaleX() * (float) getWidth() * pVideo->getWidthScaleFactor();
|
|
||||||
float currScaleY = getScaleY() * (float) getHeight() * pVideo->getHeightScaleFactor();
|
|
||||||
float currScaleZ = getScaleZ() * (float) getWidth() * pVideo->getDepthScaleFactor();
|
|
||||||
|
|
||||||
glm::mat4 m_modelView = glm::translate(identity, glm::vec3(currPosX, currPosY, currPosZ));
|
|
||||||
m_modelView = glm::scale(m_modelView, glm::vec3(currScaleX, currScaleY, currScaleZ));
|
|
||||||
|
|
||||||
Shader3D::instance()->setShaders();
|
|
||||||
Shader3D::instance()->setProjectionMtx(identity);
|
|
||||||
Shader3D::instance()->setViewMtx(identity);
|
|
||||||
Shader3D::instance()->setModelViewMtx(m_modelView);
|
|
||||||
Shader3D::instance()->setTextureAndSampler(getImageData()->getTexture(), getImageData()->getSampler());
|
|
||||||
Shader3D::instance()->setAlphaFadeOut(alphaFadeOut);
|
|
||||||
Shader3D::instance()->setDistanceFadeOut(0.0f);
|
|
||||||
Shader3D::instance()->setColorIntensity(glm::vec4(1.0f, 1.0f, 1.0f, getAlpha()));
|
|
||||||
Shader3D::instance()->setAttributeBuffer();
|
|
||||||
Shader3D::instance()->draw();
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
#ifndef _GAME_BG_IMAGE_H_
|
|
||||||
#define _GAME_BG_IMAGE_H_
|
|
||||||
|
|
||||||
#include <gui/GuiImageAsync.h>
|
|
||||||
#include <video/shaders/Shader3D.h>
|
|
||||||
|
|
||||||
class GameBgImage : public GuiImageAsync {
|
|
||||||
public:
|
|
||||||
GameBgImage(const std::string &filename, GuiImageData *preloadImage);
|
|
||||||
|
|
||||||
virtual ~GameBgImage();
|
|
||||||
|
|
||||||
void setAlphaFadeOut(const glm::vec4 &a) {
|
|
||||||
alphaFadeOut = a;
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw(CVideo *pVideo) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
glm::mat4 identity;
|
|
||||||
glm::vec4 alphaFadeOut;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // _GAME_BG_IMAGE_H_
|
|
@ -114,47 +114,7 @@ GameIcon::~GameIcon() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameIcon::checkRayIntersection(const glm::vec3 &rayOrigin, const glm::vec3 &rayDirFrac) {
|
void GameIcon::drawEx(CVideo *pVideo, const glm::mat4 &projectionMtx, const glm::mat4 &viewMtx, const glm::mat4 &modelView) {
|
||||||
//! since we always face the camera we can just check the AABB intersection
|
|
||||||
//! otherwise an OOB intersection would be required
|
|
||||||
|
|
||||||
float currPosX = getCenterX() * Application::instance()->getVideo()->getWidthScaleFactor() * 2.0f;
|
|
||||||
float currPosY = getCenterY() * Application::instance()->getVideo()->getHeightScaleFactor() * 2.0f;
|
|
||||||
float currPosZ = getDepth() * Application::instance()->getVideo()->getDepthScaleFactor() * 2.0f;
|
|
||||||
float currScaleX = getScaleX() * (float) getWidth() * Application::instance()->getVideo()->getWidthScaleFactor();
|
|
||||||
float currScaleY = getScaleY() * (float) getHeight() * Application::instance()->getVideo()->getHeightScaleFactor();
|
|
||||||
float currScaleZ = getScaleZ() * (float) getWidth() * Application::instance()->getVideo()->getDepthScaleFactor();
|
|
||||||
//! lb is the corner of AABB with minimal coordinates - left bottom, rt is maximal corner
|
|
||||||
glm::vec3 lb(currPosX - currScaleX, currPosY - currScaleY, currPosZ - currScaleZ);
|
|
||||||
glm::vec3 rt(currPosX + currScaleX, currPosY + currScaleY, currPosZ + currScaleZ);
|
|
||||||
|
|
||||||
float t1 = (lb.x - rayOrigin.x) * rayDirFrac.x;
|
|
||||||
float t2 = (rt.x - rayOrigin.x) * rayDirFrac.x;
|
|
||||||
float t3 = (lb.y - rayOrigin.y) * rayDirFrac.y;
|
|
||||||
float t4 = (rt.y - rayOrigin.y) * rayDirFrac.y;
|
|
||||||
float t5 = (lb.z - rayOrigin.z) * rayDirFrac.z;
|
|
||||||
float t6 = (rt.z - rayOrigin.z) * rayDirFrac.z;
|
|
||||||
|
|
||||||
float tmin = std::max(std::max(std::min(t1, t2), std::min(t3, t4)), std::min(t5, t6));
|
|
||||||
float tmax = std::min(std::min(std::max(t1, t2), std::max(t3, t4)), std::max(t5, t6));
|
|
||||||
|
|
||||||
//! if tmax < 0, ray (line) is intersecting AABB, but whole AABB is behing us
|
|
||||||
if (tmax < 0) {
|
|
||||||
//t = tmax;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! if tmin > tmax, ray doesn't intersect AABB
|
|
||||||
if (tmin > tmax) {
|
|
||||||
//t = tmax;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//t = tmin;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GameIcon::draw(CVideo *pVideo, const glm::mat4 &projectionMtx, const glm::mat4 &viewMtx, const glm::mat4 &modelView) {
|
|
||||||
if (imageData == nullptr) {
|
if (imageData == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -6,22 +6,22 @@
|
|||||||
|
|
||||||
class GameIcon : public GuiImage {
|
class GameIcon : public GuiImage {
|
||||||
public:
|
public:
|
||||||
GameIcon(GuiImageData *preloadImage);
|
explicit GameIcon(GuiImageData *preloadImage);
|
||||||
|
|
||||||
virtual ~GameIcon();
|
~GameIcon() override;
|
||||||
|
|
||||||
void setRotationX(float r) {
|
void setRotationX(float r) {
|
||||||
rotationX = r;
|
rotationX = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setColorIntensity(const glm::vec4 &color) {
|
void setColorIntensity(const glm::vec4 &color) override {
|
||||||
colorIntensity = color;
|
colorIntensity = color;
|
||||||
colorIntensityMirror = colorIntensity;
|
colorIntensityMirror = colorIntensity;
|
||||||
selectionBlurOuterColorIntensity = color * glm::vec4(0.09411764f * 1.15f, 0.56862745f * 1.15f, 0.96862745098f * 1.15f, 1.0f);
|
selectionBlurOuterColorIntensity = color * glm::vec4(0.09411764f * 1.15f, 0.56862745f * 1.15f, 0.96862745098f * 1.15f, 1.0f);
|
||||||
selectionBlurInnerColorIntensity = color * glm::vec4(0.46666667f, 0.90588235f, 1.0f, 1.0f);
|
selectionBlurInnerColorIntensity = color * glm::vec4(0.46666667f, 0.90588235f, 1.0f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
const glm::vec4 &getColorIntensity() const {
|
[[nodiscard]] const glm::vec4 &getColorIntensity() const {
|
||||||
return colorIntensity;
|
return colorIntensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,14 +49,12 @@ public:
|
|||||||
bIconLast = enable;
|
bIconLast = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(CVideo *pVideo) {
|
void draw(CVideo *pVideo) override {
|
||||||
static const glm::mat4 identity(1.0f);
|
static const glm::mat4 identity(1.0f);
|
||||||
draw(pVideo, identity, identity, identity);
|
drawEx(pVideo, identity, identity, identity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(CVideo *pVideo, const glm::mat4 &projection, const glm::mat4 &view, const glm::mat4 &modelView);
|
void drawEx(CVideo *pVideo, const glm::mat4 &projection, const glm::mat4 &view, const glm::mat4 &modelView);
|
||||||
|
|
||||||
bool checkRayIntersection(const glm::vec3 &rayOrigin, const glm::vec3 &rayDirFrac);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum eRenderState {
|
enum eRenderState {
|
||||||
|
@ -1,104 +0,0 @@
|
|||||||
#include "utils/utils.h"
|
|
||||||
#include <gui/GridBackground.h>
|
|
||||||
#include <video/CVideo.h>
|
|
||||||
#include <video/shaders/Shader3D.h>
|
|
||||||
|
|
||||||
static const float bgRepeat = 1000.0f;
|
|
||||||
static const float bgTexRotate = 39.0f;
|
|
||||||
|
|
||||||
GridBackground::GridBackground(GuiImageData *img)
|
|
||||||
: GuiImage(img) {
|
|
||||||
colorIntensity = glm::vec4(1.0f, 1.0f, 1.0f, 0.9f);
|
|
||||||
alphaFadeOut = glm::vec4(0.0f);
|
|
||||||
distanceFadeOut = 0.15f;
|
|
||||||
|
|
||||||
vtxCount = 4;
|
|
||||||
|
|
||||||
//! texture and vertex coordinates
|
|
||||||
float *m_posVtxs = (float *) memalign(GX2_VERTEX_BUFFER_ALIGNMENT, vtxCount * Shader3D::cuVertexAttrSize);
|
|
||||||
float *m_texCoords = (float *) memalign(GX2_VERTEX_BUFFER_ALIGNMENT, vtxCount * Shader3D::cuTexCoordAttrSize);
|
|
||||||
|
|
||||||
if (m_posVtxs) {
|
|
||||||
int32_t i = 0;
|
|
||||||
m_posVtxs[i++] = -1.0f;
|
|
||||||
m_posVtxs[i++] = 0.0f;
|
|
||||||
m_posVtxs[i++] = 1.0f;
|
|
||||||
m_posVtxs[i++] = 1.0f;
|
|
||||||
m_posVtxs[i++] = 0.0f;
|
|
||||||
m_posVtxs[i++] = 1.0f;
|
|
||||||
m_posVtxs[i++] = 1.0f;
|
|
||||||
m_posVtxs[i++] = 0.0f;
|
|
||||||
m_posVtxs[i++] = -1.0f;
|
|
||||||
m_posVtxs[i++] = -1.0f;
|
|
||||||
m_posVtxs[i++] = 0.0f;
|
|
||||||
m_posVtxs[i++] = -1.0f;
|
|
||||||
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, m_posVtxs, vtxCount * Shader3D::cuVertexAttrSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_texCoords) {
|
|
||||||
glm::vec2 texCoordVec[4];
|
|
||||||
texCoordVec[0][0] = -0.5f * bgRepeat;
|
|
||||||
texCoordVec[0][1] = 0.5f * bgRepeat;
|
|
||||||
texCoordVec[1][0] = 0.5f * bgRepeat;
|
|
||||||
texCoordVec[1][1] = 0.5f * bgRepeat;
|
|
||||||
texCoordVec[2][0] = 0.5f * bgRepeat;
|
|
||||||
texCoordVec[2][1] = -0.5f * bgRepeat;
|
|
||||||
texCoordVec[3][0] = -0.5f * bgRepeat;
|
|
||||||
texCoordVec[3][1] = -0.5f * bgRepeat;
|
|
||||||
|
|
||||||
const float cosRot = cosf(DegToRad(bgTexRotate));
|
|
||||||
const float sinRot = sinf(DegToRad(bgTexRotate));
|
|
||||||
|
|
||||||
glm::mat2 texRotateMtx({cosRot, -sinRot,
|
|
||||||
sinRot, cosRot});
|
|
||||||
|
|
||||||
for (int32_t i = 0; i < 4; i++) {
|
|
||||||
texCoordVec[i] = texRotateMtx * texCoordVec[i];
|
|
||||||
m_texCoords[i * 2 + 0] = texCoordVec[i][0];
|
|
||||||
m_texCoords[i * 2 + 1] = texCoordVec[i][1];
|
|
||||||
}
|
|
||||||
|
|
||||||
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, m_texCoords, vtxCount * Shader3D::cuTexCoordAttrSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! assign to internal variables which are const but oh well
|
|
||||||
posVtxs = m_posVtxs;
|
|
||||||
texCoords = m_texCoords;
|
|
||||||
}
|
|
||||||
|
|
||||||
GridBackground::~GridBackground() {
|
|
||||||
//! remove image so it can not be drawn anymore from this point on
|
|
||||||
imageData = nullptr;
|
|
||||||
|
|
||||||
//! main image vertexes
|
|
||||||
if (posVtxs) {
|
|
||||||
free((void *) posVtxs);
|
|
||||||
posVtxs = NULL;
|
|
||||||
}
|
|
||||||
if (texCoords) {
|
|
||||||
free((void *) texCoords);
|
|
||||||
texCoords = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GridBackground::drawModel(CVideo *pVideo, const glm::mat4 &modelView) {
|
|
||||||
//! first setup 2D GUI positions
|
|
||||||
float currScaleX = bgRepeat * scaleX * (float) getWidth() * pVideo->getWidthScaleFactor();
|
|
||||||
float currScaleY = 1.0f;
|
|
||||||
float currScaleZ = bgRepeat * scaleZ * (float) getHeight() * pVideo->getDepthScaleFactor();
|
|
||||||
|
|
||||||
m_modelView = glm::scale(modelView, glm::vec3(currScaleX, currScaleY, currScaleZ));
|
|
||||||
|
|
||||||
colorIntensity[3] = getAlpha();
|
|
||||||
|
|
||||||
Shader3D::instance()->setShaders();
|
|
||||||
Shader3D::instance()->setTextureAndSampler(imageData->getTexture(), imageData->getSampler());
|
|
||||||
Shader3D::instance()->setProjectionMtx(pVideo->getProjectionMtx());
|
|
||||||
Shader3D::instance()->setViewMtx(pVideo->getViewMtx());
|
|
||||||
Shader3D::instance()->setModelViewMtx(m_modelView);
|
|
||||||
Shader3D::instance()->setDistanceFadeOut(distanceFadeOut);
|
|
||||||
Shader3D::instance()->setAlphaFadeOut(alphaFadeOut);
|
|
||||||
Shader3D::instance()->setColorIntensity(colorIntensity);
|
|
||||||
Shader3D::instance()->setAttributeBuffer(vtxCount, posVtxs, texCoords);
|
|
||||||
Shader3D::instance()->draw(GX2_PRIMITIVE_MODE_QUADS, vtxCount);
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
#ifndef _GRID_BACKGROUND_H_
|
|
||||||
#define _GRID_BACKGROUND_H_
|
|
||||||
|
|
||||||
#include <gui/GuiImage.h>
|
|
||||||
|
|
||||||
class GridBackground : public GuiImage {
|
|
||||||
public:
|
|
||||||
GridBackground(GuiImageData *imgData);
|
|
||||||
|
|
||||||
virtual ~GridBackground();
|
|
||||||
|
|
||||||
void setColorIntensity(const glm::vec4 &color) {
|
|
||||||
colorIntensity = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
const glm::vec4 &getColorIntensity() const {
|
|
||||||
return colorIntensity;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setDistanceFadeOut(const float &a) {
|
|
||||||
distanceFadeOut = a;
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawModel(CVideo *pVideo, const glm::mat4 &modelView);
|
|
||||||
|
|
||||||
private:
|
|
||||||
glm::mat4 m_modelView;
|
|
||||||
glm::vec4 colorIntensity;
|
|
||||||
glm::vec4 alphaFadeOut;
|
|
||||||
float distanceFadeOut;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // _GRID_BACKGROUND_H_
|
|
@ -19,23 +19,16 @@
|
|||||||
|
|
||||||
#include <gui/FreeTypeGX.h>
|
#include <gui/FreeTypeGX.h>
|
||||||
#include <gui/GameBgImage.h>
|
#include <gui/GameBgImage.h>
|
||||||
#include <gui/GridBackground.h>
|
|
||||||
#include <gui/GuiButton.h>
|
#include <gui/GuiButton.h>
|
||||||
#include <gui/GuiCheckBox.h>
|
|
||||||
#include <gui/GuiController.h>
|
#include <gui/GuiController.h>
|
||||||
#include <gui/GuiDragListener.h>
|
#include <gui/GuiDragListener.h>
|
||||||
#include <gui/GuiElement.h>
|
#include <gui/GuiElement.h>
|
||||||
#include <gui/GuiFrame.h>
|
#include <gui/GuiFrame.h>
|
||||||
#include <gui/GuiImage.h>
|
#include <gui/GuiImage.h>
|
||||||
#include <gui/GuiImageAsync.h>
|
|
||||||
#include <gui/GuiImageData.h>
|
#include <gui/GuiImageData.h>
|
||||||
#include <gui/GuiParticleImage.h>
|
#include <gui/GuiParticleImage.h>
|
||||||
#include <gui/GuiScrollbar.h>
|
|
||||||
#include <gui/GuiSelectBox.h>
|
|
||||||
#include <gui/GuiSound.h>
|
#include <gui/GuiSound.h>
|
||||||
#include <gui/GuiSwitch.h>
|
|
||||||
#include <gui/GuiText.h>
|
#include <gui/GuiText.h>
|
||||||
#include <gui/GuiToggle.h>
|
|
||||||
#include <gui/GuiTrigger.h>
|
#include <gui/GuiTrigger.h>
|
||||||
#include <gui/VPadController.h>
|
#include <gui/VPadController.h>
|
||||||
#include <gui/WPadController.h>
|
#include <gui/WPadController.h>
|
||||||
|
@ -58,32 +58,32 @@ GuiButton::GuiButton(float w, float h) {
|
|||||||
GuiButton::~GuiButton() {
|
GuiButton::~GuiButton() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiButton::setImage(GuiImage *img) {
|
void GuiButton::setImage(std::shared_ptr<GuiImage> img) {
|
||||||
image = img;
|
image = std::move(img);
|
||||||
if (img) { img->setParent(this); }
|
if (img) { img->setParent(this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiButton::setImageOver(GuiImage *img) {
|
void GuiButton::setImageOver(std::shared_ptr<GuiImage> img) {
|
||||||
imageOver = img;
|
imageOver = img;
|
||||||
if (img) { img->setParent(this); }
|
if (img) { img->setParent(this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiButton::setImageHold(GuiImage *img) {
|
void GuiButton::setImageHold(std::shared_ptr<GuiImage> img) {
|
||||||
imageHold = img;
|
imageHold = img;
|
||||||
if (img) { img->setParent(this); }
|
if (img) { img->setParent(this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiButton::setImageClick(GuiImage *img) {
|
void GuiButton::setImageClick(std::shared_ptr<GuiImage> img) {
|
||||||
imageClick = img;
|
imageClick = img;
|
||||||
if (img) { img->setParent(this); }
|
if (img) { img->setParent(this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiButton::setIcon(GuiImage *img) {
|
void GuiButton::setIcon(std::shared_ptr<GuiImage> img) {
|
||||||
icon = img;
|
icon = img;
|
||||||
if (img) { img->setParent(this); }
|
if (img) { img->setParent(this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiButton::setIconOver(GuiImage *img) {
|
void GuiButton::setIconOver(std::shared_ptr<GuiImage> img) {
|
||||||
iconOver = img;
|
iconOver = img;
|
||||||
if (img) { img->setParent(this); }
|
if (img) { img->setParent(this); }
|
||||||
}
|
}
|
||||||
@ -108,16 +108,16 @@ void GuiButton::setLabelClick(GuiText *txt, int32_t n) {
|
|||||||
if (txt) { txt->setParent(this); }
|
if (txt) { txt->setParent(this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiButton::setSoundOver(GuiSound *snd) {
|
void GuiButton::setSoundOver(std::unique_ptr<GuiSound> snd) {
|
||||||
soundOver = snd;
|
soundOver = std::move(snd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiButton::setSoundHold(GuiSound *snd) {
|
void GuiButton::setSoundHold(std::unique_ptr<GuiSound>snd) {
|
||||||
soundHold = snd;
|
soundHold = std::move(snd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiButton::setSoundClick(GuiSound *snd) {
|
void GuiButton::setSoundClick(std::unique_ptr<GuiSound>&& snd) {
|
||||||
soundClick = snd;
|
soundClick = std::move(snd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiButton::setTrigger(GuiTrigger *t, int32_t idx) {
|
void GuiButton::setTrigger(GuiTrigger *t, int32_t idx) {
|
||||||
@ -142,7 +142,7 @@ void GuiButton::resetState(void) {
|
|||||||
/**
|
/**
|
||||||
* Draw the button on screen
|
* Draw the button on screen
|
||||||
*/
|
*/
|
||||||
void GuiButton::draw(CVideo *v) {
|
void GuiButton::draw(const CVideo& v) {
|
||||||
if (!this->isVisible()) {
|
if (!this->isVisible()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -172,17 +172,17 @@ void GuiButton::draw(CVideo *v) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiButton::update(GuiController *c) {
|
void GuiButton::update(const GuiController& c) {
|
||||||
if (!c || isStateSet(STATE_DISABLED | STATE_HIDDEN | STATE_DISABLE_INPUT, c->chanIdx)) {
|
if (isStateSet(STATE_DISABLED | STATE_HIDDEN | STATE_DISABLE_INPUT, c.chanIdx)) {
|
||||||
return;
|
return;
|
||||||
} else if (parentElement && (parentElement->isStateSet(STATE_DISABLED | STATE_HIDDEN | STATE_DISABLE_INPUT, c->chanIdx))) {
|
} else if (parentElement && (parentElement->isStateSet(STATE_DISABLED | STATE_HIDDEN | STATE_DISABLE_INPUT, c.chanIdx))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectable) {
|
if (selectable) {
|
||||||
if (c->data.validPointer && this->isInside(c->data.x, c->data.y)) {
|
if (c.data.validPointer && this->isInside(c.data.x, c.data.y)) {
|
||||||
if (!isStateSet(STATE_OVER, c->chanIdx)) {
|
if (!isStateSet(STATE_OVER, c.chanIdx)) {
|
||||||
setState(STATE_OVER, c->chanIdx);
|
setState(STATE_OVER, c.chanIdx);
|
||||||
|
|
||||||
//if(this->isRumbleActive())
|
//if(this->isRumbleActive())
|
||||||
// this->rumble(t->chan);
|
// this->rumble(t->chan);
|
||||||
@ -200,8 +200,8 @@ void GuiButton::update(GuiController *c) {
|
|||||||
|
|
||||||
pointedOn(this, c);
|
pointedOn(this, c);
|
||||||
}
|
}
|
||||||
} else if (isStateSet(STATE_OVER, c->chanIdx)) {
|
} else if (isStateSet(STATE_OVER, c.chanIdx)) {
|
||||||
this->clearState(STATE_OVER, c->chanIdx);
|
this->clearState(STATE_OVER, c.chanIdx);
|
||||||
pointedOff(this, c);
|
pointedOff(this, c);
|
||||||
|
|
||||||
if (effectTarget == effectTargetOver && effectAmount == effectAmountOver) {
|
if (effectTarget == effectTargetOver && effectAmount == effectAmountOver) {
|
||||||
@ -223,28 +223,28 @@ void GuiButton::update(GuiController *c) {
|
|||||||
|
|
||||||
int32_t isClicked = trigger[i]->clicked(c);
|
int32_t isClicked = trigger[i]->clicked(c);
|
||||||
|
|
||||||
if (!clickedTrigger && (isClicked != GuiTrigger::CLICKED_NONE) && (trigger[i]->isClickEverywhere() || (isStateSet(STATE_SELECTED | STATE_OVER, c->chanIdx) && trigger[i]->isSelectionClickEverywhere()) || this->isInside(c->data.x, c->data.y))) {
|
if (!clickedTrigger && (isClicked != GuiTrigger::CLICKED_NONE) && (trigger[i]->isClickEverywhere() || (isStateSet(STATE_SELECTED | STATE_OVER, c.chanIdx) && trigger[i]->isSelectionClickEverywhere()) || this->isInside(c.data.x, c.data.y))) {
|
||||||
if (soundClick) {
|
if (soundClick) {
|
||||||
soundClick->Play();
|
soundClick->Play();
|
||||||
}
|
}
|
||||||
|
|
||||||
clickedTrigger = trigger[i];
|
clickedTrigger = trigger[i];
|
||||||
|
|
||||||
if (!isStateSet(STATE_CLICKED, c->chanIdx)) {
|
if (!isStateSet(STATE_CLICKED, c.chanIdx)) {
|
||||||
if (isClicked == GuiTrigger::CLICKED_TOUCH) {
|
if (isClicked == GuiTrigger::CLICKED_TOUCH) {
|
||||||
setState(STATE_CLICKED_TOUCH, c->chanIdx);
|
setState(STATE_CLICKED_TOUCH, c.chanIdx);
|
||||||
} else {
|
} else {
|
||||||
setState(STATE_CLICKED, c->chanIdx);
|
setState(STATE_CLICKED, c.chanIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clicked(this, c, trigger[i]);
|
clicked(this, &c, trigger[i]);
|
||||||
} else if ((isStateSet(STATE_CLICKED, c->chanIdx) || isStateSet(STATE_CLICKED_TOUCH, c->chanIdx)) && (clickedTrigger == trigger[i]) && !isStateSet(STATE_HELD, c->chanIdx) && !trigger[i]->held(c) &&
|
} else if ((isStateSet(STATE_CLICKED, c.chanIdx) || isStateSet(STATE_CLICKED_TOUCH, c.chanIdx)) && (clickedTrigger == trigger[i]) && !isStateSet(STATE_HELD, c.chanIdx) && !trigger[i]->held(c) &&
|
||||||
((isClicked == GuiTrigger::CLICKED_NONE) || trigger[i]->released(c))) {
|
((isClicked == GuiTrigger::CLICKED_NONE) || trigger[i]->released(c))) {
|
||||||
if ((isStateSet(STATE_CLICKED_TOUCH, c->chanIdx) && this->isInside(c->data.x, c->data.y)) || (isStateSet(STATE_CLICKED, c->chanIdx))) {
|
if ((isStateSet(STATE_CLICKED_TOUCH, c.chanIdx) && this->isInside(c.data.x, c.data.y)) || (isStateSet(STATE_CLICKED, c.chanIdx))) {
|
||||||
clickedTrigger = NULL;
|
clickedTrigger = nullptr;
|
||||||
clearState(STATE_CLICKED, c->chanIdx);
|
clearState(STATE_CLICKED, c.chanIdx);
|
||||||
released(this, c, trigger[i]);
|
released(this, &c, trigger[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -252,23 +252,23 @@ void GuiButton::update(GuiController *c) {
|
|||||||
if (holdable) {
|
if (holdable) {
|
||||||
bool isHeld = trigger[i]->held(c);
|
bool isHeld = trigger[i]->held(c);
|
||||||
|
|
||||||
if ((!heldTrigger || heldTrigger == trigger[i]) && isHeld && (trigger[i]->isHoldEverywhere() || (isStateSet(STATE_SELECTED | STATE_OVER, c->chanIdx) && trigger[i]->isSelectionClickEverywhere()) || this->isInside(c->data.x, c->data.y))) {
|
if ((!heldTrigger || heldTrigger == trigger[i]) && isHeld && (trigger[i]->isHoldEverywhere() || (isStateSet(STATE_SELECTED | STATE_OVER, c.chanIdx) && trigger[i]->isSelectionClickEverywhere()) || this->isInside(c.data.x, c.data.y))) {
|
||||||
heldTrigger = trigger[i];
|
heldTrigger = trigger[i];
|
||||||
|
|
||||||
if (!isStateSet(STATE_HELD, c->chanIdx)) {
|
if (!isStateSet(STATE_HELD, c.chanIdx)) {
|
||||||
setState(STATE_HELD, c->chanIdx);
|
setState(STATE_HELD, c.chanIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
held(this, c, trigger[i]);
|
held(this, &c, trigger[i]);
|
||||||
} else if (isStateSet(STATE_HELD, c->chanIdx) && (heldTrigger == trigger[i]) && (!isHeld || trigger[i]->released(c))) {
|
} else if (isStateSet(STATE_HELD, c.chanIdx) && (heldTrigger == trigger[i]) && (!isHeld || trigger[i]->released(c))) {
|
||||||
//! click is removed at this point and converted to held
|
//! click is removed at this point and converted to held
|
||||||
if (clickedTrigger == trigger[i]) {
|
if (clickedTrigger == trigger[i]) {
|
||||||
clickedTrigger = NULL;
|
clickedTrigger = nullptr;
|
||||||
clearState(STATE_CLICKED, c->chanIdx);
|
clearState(STATE_CLICKED, c.chanIdx);
|
||||||
}
|
}
|
||||||
heldTrigger = NULL;
|
heldTrigger = nullptr;
|
||||||
clearState(STATE_HELD, c->chanIdx);
|
clearState(STATE_HELD, c.chanIdx);
|
||||||
released(this, c, trigger[i]);
|
released(this, &c, trigger[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,27 +34,27 @@ public:
|
|||||||
GuiButton(float w, float h);
|
GuiButton(float w, float h);
|
||||||
|
|
||||||
//!Destructor
|
//!Destructor
|
||||||
virtual ~GuiButton();
|
~GuiButton() override;
|
||||||
|
|
||||||
//!Sets the button's image
|
//!Sets the button's image
|
||||||
//!\param i Pointer to GuiImage object
|
//!\param i Pointer to GuiImage object
|
||||||
void setImage(GuiImage *i);
|
void setImage(std::shared_ptr<GuiImage> i);
|
||||||
|
|
||||||
//!Sets the button's image on over
|
//!Sets the button's image on over
|
||||||
//!\param i Pointer to GuiImage object
|
//!\param i Pointer to GuiImage object
|
||||||
void setImageOver(GuiImage *i);
|
void setImageOver(std::shared_ptr<GuiImage> i);
|
||||||
|
|
||||||
void setIcon(GuiImage *i);
|
void setIcon(std::shared_ptr<GuiImage> i);
|
||||||
|
|
||||||
void setIconOver(GuiImage *i);
|
void setIconOver(std::shared_ptr<GuiImage> i);
|
||||||
|
|
||||||
//!Sets the button's image on hold
|
//!Sets the button's image on hold
|
||||||
//!\param i Pointer to GuiImage object
|
//!\param i Pointer to GuiImage object
|
||||||
void setImageHold(GuiImage *i);
|
void setImageHold(std::shared_ptr<GuiImage> i);
|
||||||
|
|
||||||
//!Sets the button's image on click
|
//!Sets the button's image on click
|
||||||
//!\param i Pointer to GuiImage object
|
//!\param i Pointer to GuiImage object
|
||||||
void setImageClick(GuiImage *i);
|
void setImageClick(std::shared_ptr<GuiImage> i);
|
||||||
|
|
||||||
//!Sets the button's label
|
//!Sets the button's label
|
||||||
//!\param t Pointer to GuiText object
|
//!\param t Pointer to GuiText object
|
||||||
@ -78,15 +78,15 @@ public:
|
|||||||
|
|
||||||
//!Sets the sound to play on over
|
//!Sets the sound to play on over
|
||||||
//!\param s Pointer to GuiSound object
|
//!\param s Pointer to GuiSound object
|
||||||
void setSoundOver(GuiSound *s);
|
void setSoundOver(std::unique_ptr<GuiSound> s);
|
||||||
|
|
||||||
//!Sets the sound to play on hold
|
//!Sets the sound to play on hold
|
||||||
//!\param s Pointer to GuiSound object
|
//!\param s Pointer to GuiSound object
|
||||||
void setSoundHold(GuiSound *s);
|
void setSoundHold(std::unique_ptr<GuiSound> s);
|
||||||
|
|
||||||
//!Sets the sound to play on click
|
//!Sets the sound to play on click
|
||||||
//!\param s Pointer to GuiSound object
|
//!\param s Pointer to GuiSound object
|
||||||
void setSoundClick(GuiSound *s);
|
void setSoundClick(std::unique_ptr<GuiSound> &&s);
|
||||||
|
|
||||||
//!Set a new GuiTrigger for the element
|
//!Set a new GuiTrigger for the element
|
||||||
//!\param i Index of trigger array to set
|
//!\param i Index of trigger array to set
|
||||||
@ -94,14 +94,14 @@ public:
|
|||||||
void setTrigger(GuiTrigger *t, int32_t idx = -1);
|
void setTrigger(GuiTrigger *t, int32_t idx = -1);
|
||||||
|
|
||||||
//!
|
//!
|
||||||
void resetState(void);
|
void resetState();
|
||||||
|
|
||||||
//!Constantly called to draw the GuiButton
|
//!Constantly called to draw the GuiButton
|
||||||
void draw(CVideo *video) override;
|
void draw(const CVideo& video) override;
|
||||||
|
|
||||||
//!Constantly called to allow the GuiButton to respond to updated input data
|
//!Constantly called to allow the GuiButton to respond to updated input data
|
||||||
//!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD
|
//!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD
|
||||||
void update(GuiController *c);
|
void update(const GuiController& c) override;
|
||||||
|
|
||||||
sigslot::signal2<GuiButton *, const GuiController *> selected;
|
sigslot::signal2<GuiButton *, const GuiController *> selected;
|
||||||
sigslot::signal2<GuiButton *, const GuiController *> deSelected;
|
sigslot::signal2<GuiButton *, const GuiController *> deSelected;
|
||||||
@ -114,19 +114,19 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
static const int32_t iMaxGuiTriggers = 10;
|
static const int32_t iMaxGuiTriggers = 10;
|
||||||
|
|
||||||
GuiImage *image; //!< Button image (default)
|
std::unique_ptr<GuiImage> image; //!< Button image (default)
|
||||||
GuiImage *imageOver; //!< Button image for STATE_SELECTED
|
std::unique_ptr<GuiImage> imageOver; //!< Button image for STATE_SELECTED
|
||||||
GuiImage *imageHold; //!< Button image for STATE_HELD
|
std::unique_ptr<GuiImage> imageHold; //!< Button image for STATE_HELD
|
||||||
GuiImage *imageClick; //!< Button image for STATE_CLICKED
|
std::unique_ptr<GuiImage> imageClick; //!< Button image for STATE_CLICKED
|
||||||
GuiImage *icon;
|
std::unique_ptr<GuiImage> icon;
|
||||||
GuiImage *iconOver;
|
std::unique_ptr<GuiImage> iconOver;
|
||||||
GuiText *label[4]; //!< Label(s) to display (default)
|
std::array<std::unique_ptr<GuiText>,4> label[4]; //!< Label(s) to display (default)
|
||||||
GuiText *labelOver[4]; //!< Label(s) to display for STATE_SELECTED
|
GuiText *labelOver[4]; //!< Label(s) to display for STATE_SELECTED
|
||||||
GuiText *labelHold[4]; //!< Label(s) to display for STATE_HELD
|
GuiText *labelHold[4]; //!< Label(s) to display for STATE_HELD
|
||||||
GuiText *labelClick[4]; //!< Label(s) to display for STATE_CLICKED
|
GuiText *labelClick[4]; //!< Label(s) to display for STATE_CLICKED
|
||||||
GuiSound *soundOver; //!< Sound to play for STATE_SELECTED
|
std::unique_ptr<GuiSound> soundOver; //!< Sound to play for STATE_SELECTED
|
||||||
GuiSound *soundHold; //!< Sound to play for STATE_HELD
|
std::unique_ptr<GuiSound> soundHold; //!< Sound to play for STATE_HELD
|
||||||
GuiSound *soundClick; //!< Sound to play for STATE_CLICKED
|
std::unique_ptr<GuiSound> soundClick; //!< Sound to play for STATE_CLICKED
|
||||||
GuiTrigger *trigger[iMaxGuiTriggers]; //!< GuiTriggers (input actions) that this element responds to
|
GuiTrigger *trigger[iMaxGuiTriggers]; //!< GuiTriggers (input actions) that this element responds to
|
||||||
GuiTrigger *clickedTrigger;
|
GuiTrigger *clickedTrigger;
|
||||||
GuiTrigger *heldTrigger;
|
GuiTrigger *heldTrigger;
|
||||||
|
@ -1,68 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* Copyright (C) 2016,2017 Maschell
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*
|
|
||||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
****************************************************************************/
|
|
||||||
#include <gui/GuiCheckBox.h>
|
|
||||||
#include <gui/GuiImage.h>
|
|
||||||
#include <gui/GuiImageData.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for the GuiCheckBox class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
GuiCheckBox::GuiCheckBox(GuiImage *background, bool checked, float width, float height)
|
|
||||||
: GuiToggle(checked, width, height) {
|
|
||||||
setImageBackground(background);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor for the GuiCheckBox class.
|
|
||||||
*/
|
|
||||||
GuiCheckBox::~GuiCheckBox() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiCheckBox::setImageBackground(GuiImage *img) {
|
|
||||||
backgroundImg = img;
|
|
||||||
if (img) {
|
|
||||||
img->setParent(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiCheckBox::setImageSelected(GuiImage *img) {
|
|
||||||
selectedImg = img;
|
|
||||||
if (img) {
|
|
||||||
img->setParent(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiCheckBox::setImageHighlighted(GuiImage *img) {
|
|
||||||
highlightedImg = img;
|
|
||||||
if (img) {
|
|
||||||
img->setParent(this);
|
|
||||||
}
|
|
||||||
setIconOver(img);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiCheckBox::update(GuiController *c) {
|
|
||||||
if (bChanged) {
|
|
||||||
if (selected) {
|
|
||||||
GuiButton::setImage(selectedImg);
|
|
||||||
} else {
|
|
||||||
GuiButton::setImage(backgroundImg);
|
|
||||||
}
|
|
||||||
bChanged = false;
|
|
||||||
}
|
|
||||||
GuiToggle::update(c);
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* Copyright (C) 2016,2017 Maschell
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*
|
|
||||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
****************************************************************************/
|
|
||||||
#ifndef GUI_CHECKBOX_H_
|
|
||||||
#define GUI_CHECKBOX_H_
|
|
||||||
|
|
||||||
#include <gui/GuiImage.h>
|
|
||||||
#include <gui/GuiImageData.h>
|
|
||||||
#include <gui/GuiToggle.h>
|
|
||||||
|
|
||||||
//!A simple CheckBox
|
|
||||||
class GuiCheckBox : public GuiToggle {
|
|
||||||
public:
|
|
||||||
//!Constructor
|
|
||||||
//!\param checked Checked
|
|
||||||
GuiCheckBox(GuiImage *background, bool checked, float width = 0.0f, float height = 0.0f);
|
|
||||||
|
|
||||||
//!Destructor
|
|
||||||
virtual ~GuiCheckBox();
|
|
||||||
|
|
||||||
void setImageBackground(GuiImage *img);
|
|
||||||
|
|
||||||
void setImageSelected(GuiImage *img);
|
|
||||||
|
|
||||||
void setImageHighlighted(GuiImage *img);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
GuiImage *backgroundImg = NULL;
|
|
||||||
GuiImage *selectedImg = NULL;
|
|
||||||
GuiImage *highlightedImg = NULL;
|
|
||||||
|
|
||||||
void update(GuiController *c);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -25,56 +25,51 @@
|
|||||||
GuiDragListener::GuiDragListener(float w, float h) {
|
GuiDragListener::GuiDragListener(float w, float h) {
|
||||||
width = w;
|
width = w;
|
||||||
height = h;
|
height = h;
|
||||||
for (int32_t i = 0; i < iMaxGuiTriggers; i++) {
|
for (auto &i : trigger) {
|
||||||
trigger[i] = NULL;
|
i.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destructor for the GuiDragListener class.
|
* Destructor for the GuiDragListener class.
|
||||||
*/
|
*/
|
||||||
GuiDragListener::~GuiDragListener() {
|
GuiDragListener::~GuiDragListener() = default;
|
||||||
}
|
|
||||||
|
|
||||||
void GuiDragListener::setState(int32_t i, int32_t c) {
|
|
||||||
GuiElement::setState(i, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiDragListener::setTrigger(GuiTrigger *t, int32_t idx) {
|
void GuiDragListener::setTrigger(const std::shared_ptr<GuiTrigger> &t, int32_t idx) {
|
||||||
if (idx >= 0 && idx < iMaxGuiTriggers) {
|
if (idx >= 0 && idx < trigger.size()) {
|
||||||
trigger[idx] = t;
|
trigger[idx] = t;
|
||||||
} else {
|
} else {
|
||||||
for (int32_t i = 0; i < iMaxGuiTriggers; i++) {
|
for (auto &i : trigger) {
|
||||||
if (!trigger[i]) {
|
if (!i) {
|
||||||
trigger[i] = t;
|
i = t;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiDragListener::update(GuiController *c) {
|
void GuiDragListener::update(const GuiController &c) {
|
||||||
if (!c || isStateSet(STATE_DISABLED | STATE_HIDDEN | STATE_DISABLE_INPUT, c->chanIdx)) {
|
if (isStateSet(STATE_DISABLED | STATE_HIDDEN | STATE_DISABLE_INPUT, c.chanIdx)) {
|
||||||
return;
|
return;
|
||||||
} else if (parentElement && (parentElement->isStateSet(STATE_DISABLED | STATE_HIDDEN | STATE_DISABLE_INPUT, c->chanIdx))) {
|
} else if (parentElement && (parentElement->isStateSet(STATE_DISABLED | STATE_HIDDEN | STATE_DISABLE_INPUT, c.chanIdx))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int32_t i = 0; i < iMaxGuiTriggers; i++) {
|
for (auto &i : trigger) {
|
||||||
if (!trigger[i]) {
|
if (!i) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isHeld = trigger[i]->held(c);
|
bool isHeld = i->held(c);
|
||||||
|
|
||||||
|
if (isHeld && this->isInside(c.data.x, c.data.y)) {
|
||||||
if (isHeld && this->isInside(c->data.x, c->data.y)) {
|
int32_t dx = c.data.x - c.lastData.x;
|
||||||
int32_t dx = c->data.x - c->lastData.x;
|
int32_t dy = c.data.y - c.lastData.y;
|
||||||
int32_t dy = c->data.y - c->lastData.y;
|
|
||||||
|
|
||||||
if (dx == 0 && dy == 0) { continue; }
|
if (dx == 0 && dy == 0) { continue; }
|
||||||
|
|
||||||
dragged(this, c, trigger[i], dx, dy);
|
dragged(this, &c, i.get(), dx, dy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,25 +30,21 @@ public:
|
|||||||
GuiDragListener(float w, float h);
|
GuiDragListener(float w, float h);
|
||||||
|
|
||||||
//!Destructor
|
//!Destructor
|
||||||
virtual ~GuiDragListener();
|
~GuiDragListener() override;
|
||||||
|
|
||||||
void setState(int32_t i, int32_t c);
|
|
||||||
|
|
||||||
//!Set a new GuiTrigger for the element
|
//!Set a new GuiTrigger for the element
|
||||||
//!\param i Index of trigger array to set
|
//!\param i Index of trigger array to set
|
||||||
//!\param t Pointer to GuiTrigger
|
//!\param t Pointer to GuiTrigger
|
||||||
void setTrigger(GuiTrigger *t, int32_t idx = -1);
|
void setTrigger(const std::shared_ptr<GuiTrigger> &, int32_t idx = -1);
|
||||||
|
|
||||||
//!Constantly called to allow the GuiDragListener to respond to updated input data
|
//!Constantly called to allow the GuiDragListener to respond to updated input data
|
||||||
//!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD
|
//!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD
|
||||||
void update(GuiController *c);
|
void update(const GuiController &c) override;
|
||||||
|
|
||||||
sigslot::signal5<GuiDragListener *, const GuiController *, GuiTrigger *, int32_t, int32_t> dragged;
|
sigslot::signal5<GuiDragListener *, const GuiController *, GuiTrigger *, int32_t, int32_t> dragged;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static const int32_t iMaxGuiTriggers = 10;
|
std::array<std::shared_ptr<GuiTrigger>, 10> trigger; //!< GuiTriggers (input actions) that this element responds to
|
||||||
|
|
||||||
GuiTrigger *trigger[iMaxGuiTriggers]; //!< GuiTriggers (input actions) that this element responds to
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,8 +33,8 @@ GuiElement::GuiElement() {
|
|||||||
scaleX = 1.0f;
|
scaleX = 1.0f;
|
||||||
scaleY = 1.0f;
|
scaleY = 1.0f;
|
||||||
scaleZ = 1.0f;
|
scaleZ = 1.0f;
|
||||||
for (int32_t i = 0; i < 5; i++) {
|
for (int & i : state) {
|
||||||
state[i] = STATE_DEFAULT;
|
i = STATE_DEFAULT;
|
||||||
}
|
}
|
||||||
stateChan = -1;
|
stateChan = -1;
|
||||||
parentElement = NULL;
|
parentElement = NULL;
|
||||||
|
@ -78,7 +78,7 @@ public:
|
|||||||
|
|
||||||
//!Set the element's parent
|
//!Set the element's parent
|
||||||
//!\param e Pointer to parent element
|
//!\param e Pointer to parent element
|
||||||
virtual void setParent(GuiElement *e) {
|
virtual void setParent(std::shared_ptr<GuiElement> e) {
|
||||||
parentElement = e;
|
parentElement = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -524,10 +524,10 @@ public:
|
|||||||
|
|
||||||
//!Called constantly to allow the element to respond to the current input data
|
//!Called constantly to allow the element to respond to the current input data
|
||||||
//!\param t Pointer to a GuiController, containing the current input data from PAD/WPAD/VPAD
|
//!\param t Pointer to a GuiController, containing the current input data from PAD/WPAD/VPAD
|
||||||
virtual void update(GuiController *t) {}
|
virtual void update(const GuiController &t) {}
|
||||||
|
|
||||||
//!Called constantly to redraw the element
|
//!Called constantly to redraw the element
|
||||||
virtual void draw(CVideo *v) {}
|
virtual void draw(const CVideo &v) {}
|
||||||
|
|
||||||
//!Called constantly to process stuff in the element
|
//!Called constantly to process stuff in the element
|
||||||
virtual void process() {}
|
virtual void process() {}
|
||||||
@ -579,8 +579,8 @@ protected:
|
|||||||
bool clickable; //!< Whether or not this element is clickable (can change to CLICKED state)
|
bool clickable; //!< Whether or not this element is clickable (can change to CLICKED state)
|
||||||
bool holdable; //!< Whether or not this element is holdable (can change to HELD state)
|
bool holdable; //!< Whether or not this element is holdable (can change to HELD state)
|
||||||
bool drawOverOnlyWhenSelected; //!< Whether or not this element is holdable (can change to HELD state)
|
bool drawOverOnlyWhenSelected; //!< Whether or not this element is holdable (can change to HELD state)
|
||||||
float width; //!< Element width
|
float width = {}; //!< Element width
|
||||||
float height; //!< Element height
|
float height = {}; //!< Element height
|
||||||
float xoffset; //!< Element X offset
|
float xoffset; //!< Element X offset
|
||||||
float yoffset; //!< Element Y offset
|
float yoffset; //!< Element Y offset
|
||||||
float zoffset; //!< Element Z offset
|
float zoffset; //!< Element Z offset
|
||||||
@ -590,7 +590,7 @@ protected:
|
|||||||
float scaleY; //!< Element scale (1 = 100%)
|
float scaleY; //!< Element scale (1 = 100%)
|
||||||
float scaleZ; //!< Element scale (1 = 100%)
|
float scaleZ; //!< Element scale (1 = 100%)
|
||||||
int32_t alignment; //!< Horizontal element alignment, respective to parent element
|
int32_t alignment; //!< Horizontal element alignment, respective to parent element
|
||||||
int32_t state[5]; //!< Element state (DEFAULT, SELECTED, CLICKED, DISABLED)
|
int32_t state[5]{}; //!< Element state (DEFAULT, SELECTED, CLICKED, DISABLED)
|
||||||
int32_t stateChan; //!< Which controller channel is responsible for the last change in state
|
int32_t stateChan; //!< Which controller channel is responsible for the last change in state
|
||||||
GuiElement *parentElement; //!< Parent element
|
GuiElement *parentElement; //!< Parent element
|
||||||
|
|
||||||
|
@ -16,26 +16,16 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#include <gui/GuiFrame.h>
|
#include <gui/GuiFrame.h>
|
||||||
|
|
||||||
GuiFrame::GuiFrame(GuiFrame *p) {
|
GuiFrame::GuiFrame() {
|
||||||
parent = p;
|
|
||||||
width = 0;
|
width = 0;
|
||||||
height = 0;
|
height = 0;
|
||||||
dim = false;
|
dim = false;
|
||||||
|
|
||||||
if (parent) {
|
|
||||||
parent->append(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GuiFrame::GuiFrame(float w, float h, GuiFrame *p) {
|
GuiFrame::GuiFrame(float w, float h) {
|
||||||
parent = p;
|
|
||||||
width = w;
|
width = w;
|
||||||
height = h;
|
height = h;
|
||||||
dim = false;
|
dim = false;
|
||||||
|
|
||||||
if (parent) {
|
|
||||||
parent->append(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GuiFrame::~GuiFrame() {
|
GuiFrame::~GuiFrame() {
|
||||||
@ -46,38 +36,36 @@ GuiFrame::~GuiFrame() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiFrame::append(GuiElement *e) {
|
void GuiFrame::append(std::unique_ptr<GuiElement> e) {
|
||||||
if (e == NULL) {
|
if (e == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(e);
|
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
elements.push_back(e);
|
elements.push_back(std::move(e));
|
||||||
e->setParent(this);
|
e->setParent(this);
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiFrame::insert(GuiElement *e, uint32_t index) {
|
void GuiFrame::insert(std::unique_ptr<GuiElement> e, uint32_t index) {
|
||||||
if (e == NULL || (index >= elements.size())) {
|
if (e == NULL || (index >= elements.size())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(e);
|
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
elements.insert(elements.begin() + index, e);
|
elements.insert(elements.begin() + index, std::move(e));
|
||||||
e->setParent(this);
|
e->setParent(this);
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiFrame::remove(GuiElement *e) {
|
void GuiFrame::remove(GuiElement *e) {
|
||||||
if (e == NULL) {
|
if (e == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
for (uint32_t i = 0; i < elements.size(); ++i) {
|
for (uint32_t i = 0; i < elements.size(); ++i) {
|
||||||
if (e == elements[i]) {
|
if (e == elements[i].get()) {
|
||||||
elements.erase(elements.begin() + i);
|
elements.erase(elements.begin() + i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -91,32 +79,17 @@ void GuiFrame::removeAll() {
|
|||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiFrame::close() {
|
|
||||||
//Application::instance()->pushForDelete(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiFrame::dimBackground(bool d) {
|
void GuiFrame::dimBackground(bool d) {
|
||||||
dim = d;
|
dim = d;
|
||||||
}
|
}
|
||||||
|
|
||||||
GuiElement *GuiFrame::getGuiElementAt(uint32_t index) const {
|
|
||||||
if (index >= elements.size()) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return elements[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t GuiFrame::getSize() {
|
|
||||||
return elements.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiFrame::resetState() {
|
void GuiFrame::resetState() {
|
||||||
GuiElement::resetState();
|
GuiElement::resetState();
|
||||||
|
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
for (uint32_t i = 0; i < elements.size(); ++i) {
|
for (const auto &element : elements) {
|
||||||
elements[i]->resetState();
|
element->resetState();
|
||||||
}
|
}
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
}
|
}
|
||||||
@ -124,8 +97,8 @@ void GuiFrame::resetState() {
|
|||||||
void GuiFrame::setState(int32_t s, int32_t c) {
|
void GuiFrame::setState(int32_t s, int32_t c) {
|
||||||
GuiElement::setState(s, c);
|
GuiElement::setState(s, c);
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
for (uint32_t i = 0; i < elements.size(); ++i) {
|
for (const auto &element : elements) {
|
||||||
elements[i]->setState(s, c);
|
element->setState(s, c);
|
||||||
}
|
}
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
}
|
}
|
||||||
@ -134,8 +107,8 @@ void GuiFrame::clearState(int32_t s, int32_t c) {
|
|||||||
GuiElement::clearState(s, c);
|
GuiElement::clearState(s, c);
|
||||||
|
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
for (uint32_t i = 0; i < elements.size(); ++i) {
|
for (const auto &element : elements) {
|
||||||
elements[i]->clearState(s, c);
|
element->clearState(s, c);
|
||||||
}
|
}
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
}
|
}
|
||||||
@ -144,8 +117,8 @@ void GuiFrame::setVisible(bool v) {
|
|||||||
visible = v;
|
visible = v;
|
||||||
|
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
for (uint32_t i = 0; i < elements.size(); ++i) {
|
for (const auto &element : elements) {
|
||||||
elements[i]->setVisible(v);
|
element->setVisible(v);
|
||||||
}
|
}
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
}
|
}
|
||||||
@ -164,7 +137,7 @@ int32_t GuiFrame::getSelected() {
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiFrame::draw(CVideo *v) {
|
void GuiFrame::draw(const CVideo &v) {
|
||||||
if (!this->isVisible() && parentElement) {
|
if (!this->isVisible() && parentElement) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -218,7 +191,7 @@ void GuiFrame::process() {
|
|||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiFrame::update(GuiController *c) {
|
void GuiFrame::update(const GuiController &c) {
|
||||||
if (isStateSet(STATE_DISABLED) && parentElement) {
|
if (isStateSet(STATE_DISABLED) && parentElement) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include <gui/GuiElement.h>
|
#include <gui/GuiElement.h>
|
||||||
#include <gui/sigslot.h>
|
#include <gui/sigslot.h>
|
||||||
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -26,28 +27,26 @@
|
|||||||
class GuiFrame : public GuiElement {
|
class GuiFrame : public GuiElement {
|
||||||
public:
|
public:
|
||||||
//!Constructor
|
//!Constructor
|
||||||
GuiFrame(GuiFrame *parent = 0);
|
GuiFrame();
|
||||||
|
|
||||||
//!\overload
|
//!\overload
|
||||||
//!\param w Width of window
|
//!\param w Width of window
|
||||||
//!\param h Height of window
|
//!\param h Height of window
|
||||||
GuiFrame(float w, float h, GuiFrame *parent = 0);
|
GuiFrame(float w, float h);
|
||||||
|
|
||||||
//!Destructor
|
//!Destructor
|
||||||
virtual ~GuiFrame();
|
~GuiFrame() override;
|
||||||
|
|
||||||
//!Appends a GuiElement to the GuiFrame
|
//!Appends a GuiElement to the GuiFrame
|
||||||
//!\param e The GuiElement to append. If it is already in the GuiFrame, it is removed first
|
//!\param e The GuiElement to append. If it is already in the GuiFrame, it is removed first
|
||||||
void append(GuiElement *e);
|
void append(std::unique_ptr<GuiElement> e);
|
||||||
|
|
||||||
//!Inserts a GuiElement into the GuiFrame at the specified index
|
//!Inserts a GuiElement into the GuiFrame at the specified index
|
||||||
//!\param e The GuiElement to insert. If it is already in the GuiFrame, it is removed first
|
//!\param e The GuiElement to insert. If it is already in the GuiFrame, it is removed first
|
||||||
//!\param i Index in which to insert the element
|
//!\param i Index in which to insert the element
|
||||||
void insert(GuiElement *e, uint32_t i);
|
void insert(std::unique_ptr<GuiElement>, uint32_t i);
|
||||||
|
|
||||||
|
|
||||||
//!Removes the specified GuiElement from the GuiFrame
|
|
||||||
//!\param e GuiElement to be removed
|
|
||||||
void remove(GuiElement *e);
|
|
||||||
|
|
||||||
//!Removes all GuiElements
|
//!Removes all GuiElements
|
||||||
void removeAll();
|
void removeAll();
|
||||||
@ -58,70 +57,54 @@ public:
|
|||||||
append(e);
|
append(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
//!Returns the GuiElement at the specified index
|
|
||||||
//!\param index The index of the element
|
|
||||||
//!\return A pointer to the element at the index, NULL on error (eg: out of bounds)
|
|
||||||
GuiElement *getGuiElementAt(uint32_t index) const;
|
|
||||||
|
|
||||||
//!Returns the size of the list of elements
|
|
||||||
//!\return The size of the current element list
|
|
||||||
uint32_t getSize();
|
|
||||||
|
|
||||||
//!Sets the visibility of the window
|
//!Sets the visibility of the window
|
||||||
//!\param v visibility (true = visible)
|
//!\param v visibility (true = visible)
|
||||||
void setVisible(bool v);
|
void setVisible(bool v) override;
|
||||||
|
|
||||||
//!Resets the window's state to STATE_DEFAULT
|
//!Resets the window's state to STATE_DEFAULT
|
||||||
void resetState();
|
void resetState() override;
|
||||||
|
|
||||||
//!Sets the window's state
|
//!Sets the window's state
|
||||||
//!\param s State
|
//!\param s State
|
||||||
void setState(int32_t s, int32_t c = -1);
|
void setState(int32_t s, int32_t c = -1) override;
|
||||||
|
|
||||||
void clearState(int32_t s, int32_t c = -1);
|
void clearState(int32_t s, int32_t c = -1) override;
|
||||||
|
|
||||||
//!Gets the index of the GuiElement inside the window that is currently selected
|
//!Gets the index of the GuiElement inside the window that is currently selected
|
||||||
//!\return index of selected GuiElement
|
//!\return index of selected GuiElement
|
||||||
int32_t getSelected();
|
int32_t getSelected() override;
|
||||||
|
|
||||||
//!Dim the Window's background
|
//!Dim the Window's background
|
||||||
void dimBackground(bool d);
|
void dimBackground(bool d);
|
||||||
|
|
||||||
//!Draws all the elements in this GuiFrame
|
//!Draws all the elements in this GuiFrame
|
||||||
void draw(CVideo *v) override;
|
void draw(const CVideo& v) override;
|
||||||
|
|
||||||
//!Updates the window and all elements contains within
|
//!Updates the window and all elements contains within
|
||||||
//!Allows the GuiFrame and all elements to respond to the input data specified
|
//!Allows the GuiFrame and all elements to respond to the input data specified
|
||||||
//!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD
|
//!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD
|
||||||
void update(GuiController *t);
|
void update(const GuiController& t);
|
||||||
|
|
||||||
//!virtual Close Window - this will put the object on the delete queue in MainWindow
|
|
||||||
virtual void close();
|
|
||||||
|
|
||||||
//!virtual show window function
|
|
||||||
virtual void show() {}
|
|
||||||
|
|
||||||
//!virtual hide window function
|
|
||||||
virtual void hide() {}
|
|
||||||
|
|
||||||
//!virtual enter main loop function (blocking)
|
|
||||||
virtual void exec() {}
|
|
||||||
|
|
||||||
//!virtual updateEffects which is called by the main loop
|
//!virtual updateEffects which is called by the main loop
|
||||||
virtual void updateEffects();
|
void updateEffects() override;
|
||||||
|
|
||||||
//!virtual process which is called by the main loop
|
//!virtual process which is called by the main loop
|
||||||
virtual void process();
|
void process() override;
|
||||||
|
|
||||||
//! Signals
|
//! Signals
|
||||||
//! On Closing
|
//! On Closing
|
||||||
sigslot::signal1<GuiFrame *> closing;
|
sigslot::signal1<GuiFrame *> closing;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool dim; //! Enable/disable dim of a window only
|
//!Removes the specified GuiElement from the GuiFrame
|
||||||
GuiFrame *parent; //!< Parent Window
|
void remove(GuiElement *e);
|
||||||
std::vector<GuiElement *> elements; //!< Contains all elements within the GuiFrame
|
|
||||||
|
bool dim; //! Enable/disable dim of a window only
|
||||||
|
GuiFrame *parent; //!< Parent Window
|
||||||
|
std::vector<std::unique_ptr<GuiElement>> elements; //!< Contains all elements within the GuiFrame
|
||||||
std::recursive_mutex mutex;
|
std::recursive_mutex mutex;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -453,7 +453,7 @@ void GuiIconGrid::OnGameTitleAdded(gameInfo *info) {
|
|||||||
button->pointedOff.connect(this, &GuiIconGrid::OnGameButtonPointedOff);
|
button->pointedOff.connect(this, &GuiIconGrid::OnGameButtonPointedOff);
|
||||||
//button->dragged.connect(this, &GuiIconGrid::OnGameButtonDragged);
|
//button->dragged.connect(this, &GuiIconGrid::OnGameButtonDragged);
|
||||||
|
|
||||||
GameInfoContainer *container = new GameInfoContainer(button, image, info);
|
auto *container = new GameInfoContainer(button, image, info);
|
||||||
containerMutex.lock();
|
containerMutex.lock();
|
||||||
gameInfoContainers[info->titleId] = container;
|
gameInfoContainers[info->titleId] = container;
|
||||||
containerMutex.unlock();
|
containerMutex.unlock();
|
||||||
@ -461,9 +461,9 @@ void GuiIconGrid::OnGameTitleAdded(gameInfo *info) {
|
|||||||
|
|
||||||
positionMutex.lock();
|
positionMutex.lock();
|
||||||
bool foundFreePlace = false;
|
bool foundFreePlace = false;
|
||||||
for (uint32_t i = 0; i < position.size(); i++) {
|
for (unsigned long long & i : position) {
|
||||||
if (position[i] == 0) {
|
if (i == 0) {
|
||||||
position[i] = info->titleId;
|
i = info->titleId;
|
||||||
foundFreePlace = true;
|
foundFreePlace = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
#include "gui/GameIcon.h"
|
#include "gui/GameIcon.h"
|
||||||
#include "gui/GuiDragListener.h"
|
#include "gui/GuiDragListener.h"
|
||||||
#include "gui/GuiTitleBrowser.h"
|
#include "gui/GuiTitleBrowser.h"
|
||||||
#include "utils/AsyncExecutor.h"
|
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include <gui/GuiParticleImage.h>
|
#include <gui/GuiParticleImage.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
@ -16,36 +16,36 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#include "utils/utils.h"
|
#include "utils/utils.h"
|
||||||
#include <gui/GuiImage.h>
|
#include <gui/GuiImage.h>
|
||||||
|
#include <stdexcept>
|
||||||
#include <video/CVideo.h>
|
#include <video/CVideo.h>
|
||||||
#include <video/shaders/ColorShader.h>
|
#include <video/shaders/ColorShader.h>
|
||||||
#include <video/shaders/Texture2DShader.h>
|
#include <video/shaders/Texture2DShader.h>
|
||||||
|
|
||||||
static const float fPiDiv180 = ((float) M_PI / 180.0f);
|
GuiImage::GuiImage(const std::shared_ptr<GuiImageData> &img) {
|
||||||
|
|
||||||
GuiImage::GuiImage(GuiImageData *img) {
|
|
||||||
if (img && img->getTexture()) {
|
if (img && img->getTexture()) {
|
||||||
width = img->getWidth();
|
width = img->getWidth();
|
||||||
height = img->getHeight();
|
height = img->getHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
internalInit(width, height);
|
internalInit((uint32_t) width, (uint32_t) height);
|
||||||
imageData = img;
|
imageData = img;
|
||||||
}
|
}
|
||||||
|
|
||||||
GuiImage::GuiImage(int32_t w, int32_t h, const GX2Color &c, int32_t type) {
|
GuiImage::GuiImage(uint32_t w, uint32_t h, const GX2Color &c, GuiImage::ImageTypes type) {
|
||||||
internalInit(w, h);
|
internalInit(w, h);
|
||||||
imgType = type;
|
imgType = type;
|
||||||
colorCount = ColorShader::cuColorVtxsSize / ColorShader::cuColorAttrSize;
|
colorCount = ColorShader::cuColorVtxsSize / ColorShader::cuColorAttrSize;
|
||||||
|
|
||||||
colorVtxs = (uint8_t *) memalign(GX2_VERTEX_BUFFER_ALIGNMENT, colorCount * ColorShader::cuColorAttrSize);
|
colorVtxs = (uint8_t *) memalign(GX2_VERTEX_BUFFER_ALIGNMENT, colorCount * ColorShader::cuColorAttrSize);
|
||||||
if (colorVtxs) {
|
if (!colorVtxs) {
|
||||||
for (uint32_t i = 0; i < colorCount; i++) {
|
throw std::runtime_error("Failed to alloc colorVtxs for GuiImage");
|
||||||
setImageColor(c, i);
|
}
|
||||||
}
|
for (int32_t i = 0; i < colorCount; i++) {
|
||||||
|
setImageColor(c, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GuiImage::GuiImage(int32_t w, int32_t h, const GX2Color *c, uint32_t color_count, int32_t type) {
|
GuiImage::GuiImage(uint32_t w, uint32_t h, const GX2Color *c, uint32_t color_count, GuiImage::ImageTypes type) {
|
||||||
internalInit(w, h);
|
internalInit(w, h);
|
||||||
imgType = type;
|
imgType = type;
|
||||||
colorCount = ColorShader::cuColorVtxsSize / ColorShader::cuColorAttrSize;
|
colorCount = ColorShader::cuColorVtxsSize / ColorShader::cuColorAttrSize;
|
||||||
@ -69,72 +69,38 @@ GuiImage::GuiImage(int32_t w, int32_t h, const GX2Color *c, uint32_t color_count
|
|||||||
GuiImage::~GuiImage() {
|
GuiImage::~GuiImage() {
|
||||||
if (colorVtxs) {
|
if (colorVtxs) {
|
||||||
free(colorVtxs);
|
free(colorVtxs);
|
||||||
colorVtxs = NULL;
|
colorVtxs = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiImage::internalInit(int32_t w, int32_t h) {
|
void GuiImage::internalInit(uint32_t w, uint32_t h) {
|
||||||
imageData = NULL;
|
imageData = nullptr;
|
||||||
width = w;
|
width = (float) w;
|
||||||
height = h;
|
height = (float) h;
|
||||||
tileHorizontal = -1;
|
|
||||||
tileVertical = -1;
|
|
||||||
imgType = IMAGE_TEXTURE;
|
imgType = IMAGE_TEXTURE;
|
||||||
colorVtxsDirty = false;
|
colorVtxsDirty = false;
|
||||||
colorVtxs = NULL;
|
colorVtxs = nullptr;
|
||||||
colorCount = 0;
|
colorCount = 0;
|
||||||
posVtxs = NULL;
|
texCoords = nullptr;
|
||||||
texCoords = NULL;
|
|
||||||
vtxCount = 4;
|
vtxCount = 4;
|
||||||
primitive = GX2_PRIMITIVE_MODE_QUADS;
|
primitive = GX2_PRIMITIVE_MODE_QUADS;
|
||||||
|
|
||||||
imageAngle = 0.0f;
|
|
||||||
blurDirection = glm::vec3(0.0f);
|
|
||||||
positionOffsets = glm::vec3(0.0f);
|
positionOffsets = glm::vec3(0.0f);
|
||||||
scaleFactor = glm::vec3(1.0f);
|
scaleFactor = glm::vec3(1.0f);
|
||||||
colorIntensity = glm::vec4(1.0f);
|
colorIntensity = glm::vec4(1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiImage::setImageData(GuiImageData *img) {
|
void GuiImage::setImageData(const std::shared_ptr<GuiImageData> &img) {
|
||||||
imageData = img;
|
imageData = img;
|
||||||
width = 0;
|
width = 0;
|
||||||
height = 0;
|
height = 0;
|
||||||
if (img && img->getTexture()) {
|
if (img->getTexture()) {
|
||||||
width = img->getWidth();
|
width = img->getWidth();
|
||||||
height = img->getHeight();
|
height = img->getHeight();
|
||||||
}
|
}
|
||||||
imgType = IMAGE_TEXTURE;
|
imgType = IMAGE_TEXTURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GX2Color GuiImage::getPixel(int32_t x, int32_t y) {
|
|
||||||
if (!imageData || this->getWidth() <= 0 || x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight()) {
|
|
||||||
return (GX2Color){
|
|
||||||
0, 0, 0, 0};
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t pitch = imageData->getTexture()->surface.pitch;
|
|
||||||
uint32_t *imagePtr = (uint32_t *) imageData->getTexture()->surface.image;
|
|
||||||
|
|
||||||
uint32_t color_u32 = imagePtr[y * pitch + x];
|
|
||||||
GX2Color color;
|
|
||||||
color.r = (color_u32 >> 24) & 0xFF;
|
|
||||||
color.g = (color_u32 >> 16) & 0xFF;
|
|
||||||
color.b = (color_u32 >> 8) & 0xFF;
|
|
||||||
color.a = (color_u32 >> 0) & 0xFF;
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiImage::setPixel(int32_t x, int32_t y, const GX2Color &color) {
|
|
||||||
if (!imageData || this->getWidth() <= 0 || x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t pitch = imageData->getTexture()->surface.pitch;
|
|
||||||
uint32_t *imagePtr = (uint32_t *) imageData->getTexture()->surface.image;
|
|
||||||
imagePtr[y * pitch + x] = (color.r << 24) | (color.g << 16) | (color.b << 8) | (color.a << 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiImage::setImageColor(const GX2Color &c, int32_t idx) {
|
void GuiImage::setImageColor(const GX2Color &c, int32_t idx) {
|
||||||
if (!colorVtxs) {
|
if (!colorVtxs) {
|
||||||
return;
|
return;
|
||||||
@ -146,7 +112,7 @@ void GuiImage::setImageColor(const GX2Color &c, int32_t idx) {
|
|||||||
colorVtxs[(idx << 2) + 2] = c.b;
|
colorVtxs[(idx << 2) + 2] = c.b;
|
||||||
colorVtxs[(idx << 2) + 3] = c.a;
|
colorVtxs[(idx << 2) + 3] = c.a;
|
||||||
colorVtxsDirty = true;
|
colorVtxsDirty = true;
|
||||||
} else if (colorVtxs) {
|
} else {
|
||||||
for (uint32_t i = 0; i < (ColorShader::cuColorVtxsSize / sizeof(uint8_t)); i += 4) {
|
for (uint32_t i = 0; i < (ColorShader::cuColorVtxsSize / sizeof(uint8_t)); i += 4) {
|
||||||
colorVtxs[i + 0] = c.r;
|
colorVtxs[i + 0] = c.r;
|
||||||
colorVtxs[i + 1] = c.g;
|
colorVtxs[i + 1] = c.g;
|
||||||
@ -157,39 +123,9 @@ void GuiImage::setImageColor(const GX2Color &c, int32_t idx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiImage::setSize(int32_t w, int32_t h) {
|
|
||||||
width = w;
|
|
||||||
height = h;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiImage::setPrimitiveVertex(int32_t prim, const float *posVtx, const float *texCoord, uint32_t vtxcount) {
|
|
||||||
primitive = prim;
|
|
||||||
vtxCount = vtxcount;
|
|
||||||
posVtxs = posVtx;
|
|
||||||
texCoords = texCoord;
|
|
||||||
|
|
||||||
if (imgType == IMAGE_COLOR) {
|
|
||||||
uint8_t *newColorVtxs = (uint8_t *) memalign(0x40, ColorShader::cuColorAttrSize * vtxCount);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < vtxCount; i++) {
|
|
||||||
int32_t newColorIdx = (i << 2);
|
|
||||||
int32_t colorIdx = (i < colorCount) ? (newColorIdx) : ((colorCount - 1) << 2);
|
|
||||||
|
|
||||||
newColorVtxs[newColorIdx + 0] = colorVtxs[colorIdx + 0];
|
|
||||||
newColorVtxs[newColorIdx + 1] = colorVtxs[colorIdx + 1];
|
|
||||||
newColorVtxs[newColorIdx + 2] = colorVtxs[colorIdx + 2];
|
|
||||||
newColorVtxs[newColorIdx + 3] = colorVtxs[colorIdx + 3];
|
|
||||||
}
|
|
||||||
|
|
||||||
free(colorVtxs);
|
|
||||||
colorVtxs = newColorVtxs;
|
|
||||||
colorCount = vtxCount;
|
|
||||||
colorVtxsDirty = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiImage::draw(CVideo *pVideo) {
|
void GuiImage::draw(CVideo *pVideo) {
|
||||||
if (!this->isVisible() || tileVertical == 0 || tileHorizontal == 0) {
|
if (!this->isVisible()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,40 +144,8 @@ void GuiImage::draw(CVideo *pVideo) {
|
|||||||
colorIntensity[3] = getAlpha();
|
colorIntensity[3] = getAlpha();
|
||||||
|
|
||||||
//! angle of the object
|
//! angle of the object
|
||||||
imageAngle = DegToRad(getAngle());
|
float imageAngle = DegToRad(getAngle());
|
||||||
|
|
||||||
// if(image && tileHorizontal > 0 && tileVertical > 0)
|
|
||||||
// {
|
|
||||||
// for(int32_t n=0; n<tileVertical; n++)
|
|
||||||
// for(int32_t i=0; i<tileHorizontal; i++)
|
|
||||||
// {
|
|
||||||
// if(bUnCut)
|
|
||||||
// Menu_DrawImg(image, width, height, format, currLeft+width*i, currTop+width*n, currZ, imageangle, currScaleX, currScaleY, currAlpha);
|
|
||||||
// else
|
|
||||||
// Menu_DrawImgCut(image, width, height, format, currLeft+width*i, currTop+width*n, currZ, imageangle, currScaleX, currScaleY, currAlpha, cutBoundsRect.x1(), cutBoundsRect.x2(), cutBoundsRect.y1(), cutBoundsRect.y2());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else if(image && tileHorizontal > 0)
|
|
||||||
// {
|
|
||||||
// for(int32_t i=0; i<tileHorizontal; i++)
|
|
||||||
// {
|
|
||||||
// int32_t widthTile = (imageangle == 90 || imageangle == 270) ? height : width;
|
|
||||||
// if(bUnCut)
|
|
||||||
// Menu_DrawImg(image, width, height, format, currLeft+widthTile*i, currTop, currZ, imageangle, currScaleX, currScaleY, currAlpha);
|
|
||||||
// else
|
|
||||||
// Menu_DrawImgCut(image, width, height, format, currLeft+widthTile*i, currTop, currZ, imageangle, currScaleX, currScaleY, currAlpha, cutBoundsRect.x1(), cutBoundsRect.x2(), cutBoundsRect.y1(), cutBoundsRect.y2());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else if(image && tileVertical > 0)
|
|
||||||
// {
|
|
||||||
// for(int32_t i=0; i<tileVertical; i++)
|
|
||||||
// {
|
|
||||||
// if(bUnCut)
|
|
||||||
// Menu_DrawImg(image, width, height, format, currLeft, currTop+height*i, currZ, imageangle, currScaleX, currScaleY, currAlpha);
|
|
||||||
// else
|
|
||||||
// Menu_DrawImgCut(image, width, height, format, currLeft, currTop+height*i, currZ, imageangle, currScaleX, currScaleY, currAlpha, cutBoundsRect.x1(), cutBoundsRect.x2(), cutBoundsRect.y1(), cutBoundsRect.y2());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
if (colorVtxsDirty && colorVtxs) {
|
if (colorVtxsDirty && colorVtxs) {
|
||||||
//! flush color vertex only on main GX2 thread
|
//! flush color vertex only on main GX2 thread
|
||||||
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, colorVtxs, colorCount * ColorShader::cuColorAttrSize);
|
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, colorVtxs, colorCount * ColorShader::cuColorAttrSize);
|
||||||
@ -250,21 +154,20 @@ void GuiImage::draw(CVideo *pVideo) {
|
|||||||
|
|
||||||
if (imgType == IMAGE_COLOR && colorVtxs) {
|
if (imgType == IMAGE_COLOR && colorVtxs) {
|
||||||
ColorShader::instance()->setShaders();
|
ColorShader::instance()->setShaders();
|
||||||
ColorShader::instance()->setAttributeBuffer(colorVtxs, posVtxs, vtxCount);
|
ColorShader::instance()->setAttributeBuffer(colorVtxs);
|
||||||
ColorShader::instance()->setAngle(imageAngle);
|
ColorShader::instance()->setAngle(imageAngle);
|
||||||
ColorShader::instance()->setOffset(positionOffsets);
|
ColorShader::instance()->setOffset(positionOffsets);
|
||||||
ColorShader::instance()->setScale(scaleFactor);
|
ColorShader::instance()->setScale(scaleFactor);
|
||||||
ColorShader::instance()->setColorIntensity(colorIntensity);
|
ColorShader::instance()->setColorIntensity(colorIntensity);
|
||||||
ColorShader::instance()->draw(primitive, vtxCount);
|
ColorShader::instance()->draw(primitive);
|
||||||
} else if (imageData) {
|
} else if (imageData) {
|
||||||
Texture2DShader::instance()->setShaders();
|
Texture2DShader::instance()->setShaders();
|
||||||
Texture2DShader::instance()->setAttributeBuffer(texCoords, posVtxs, vtxCount);
|
Texture2DShader::instance()->setAttributeBuffer(texCoords);
|
||||||
Texture2DShader::instance()->setAngle(imageAngle);
|
Texture2DShader::instance()->setAngle(imageAngle);
|
||||||
Texture2DShader::instance()->setOffset(positionOffsets);
|
Texture2DShader::instance()->setOffset(positionOffsets);
|
||||||
Texture2DShader::instance()->setScale(scaleFactor);
|
Texture2DShader::instance()->setScale(scaleFactor);
|
||||||
Texture2DShader::instance()->setColorIntensity(colorIntensity);
|
Texture2DShader::instance()->setColorIntensity(colorIntensity);
|
||||||
Texture2DShader::instance()->setBlurring(blurDirection);
|
|
||||||
Texture2DShader::instance()->setTextureAndSampler(imageData->getTexture(), imageData->getSampler());
|
Texture2DShader::instance()->setTextureAndSampler(imageData->getTexture(), imageData->getSampler());
|
||||||
Texture2DShader::instance()->draw(primitive, vtxCount);
|
Texture2DShader::instance()->draw(primitive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,96 +32,58 @@ public:
|
|||||||
|
|
||||||
//!\overload
|
//!\overload
|
||||||
//!\param img Pointer to GuiImageData element
|
//!\param img Pointer to GuiImageData element
|
||||||
explicit GuiImage(GuiImageData *img);
|
explicit GuiImage(const std::shared_ptr<GuiImageData> &img);
|
||||||
|
|
||||||
//!\overload
|
//!\overload
|
||||||
//!Creates an image filled with the specified color
|
//!Creates an image filled with the specified color
|
||||||
//!\param w Image width
|
//!\param w Image width
|
||||||
//!\param h Image height
|
//!\param h Image height
|
||||||
//!\param c Array with 4 x image color (BL, BR, TL, TR)
|
//!\param c Array with 4 x image color (BL, BR, TL, TR)
|
||||||
GuiImage(int32_t w, int32_t h, const GX2Color &c, int32_t imgType = IMAGE_COLOR);
|
GuiImage(uint32_t w, uint32_t h, const GX2Color &c, GuiImage::ImageTypes imgType = IMAGE_COLOR);
|
||||||
|
|
||||||
GuiImage(int32_t w, int32_t h, const GX2Color *c, uint32_t colorCount = 1, int32_t imgType = IMAGE_COLOR);
|
GuiImage(uint32_t w, uint32_t h, const GX2Color *c, uint32_t colorCount = 1, GuiImage::ImageTypes imgType = IMAGE_COLOR);
|
||||||
|
|
||||||
//!Destructor
|
//!Destructor
|
||||||
~GuiImage() override;
|
~GuiImage() override;
|
||||||
|
|
||||||
//!Sets the number of times to draw the image horizontally
|
|
||||||
//!\param t Number of times to draw the image
|
|
||||||
void setTileHorizontal(int32_t t) {
|
|
||||||
tileHorizontal = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
//!Sets the number of times to draw the image vertically
|
|
||||||
//!\param t Number of times to draw the image
|
|
||||||
void setTileVertical(int32_t t) {
|
|
||||||
tileVertical = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
//!Constantly called to draw the image
|
//!Constantly called to draw the image
|
||||||
void draw(CVideo *pVideo) override;
|
void draw(CVideo *pVideo) override;
|
||||||
|
|
||||||
//!Gets the image data
|
//!Gets the image data
|
||||||
//!\return pointer to image data
|
//!\return pointer to image data
|
||||||
[[nodiscard]] GuiImageData *getImageData() const {
|
[[nodiscard]] GuiImageData *getImageData() const {
|
||||||
return imageData;
|
return imageData.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
//!Sets up a new image using the GuiImageData object specified
|
//!Sets up a new image using the GuiImageData object specified
|
||||||
//!\param img Pointer to GuiImageData object
|
//!\param img Pointer to GuiImageData object
|
||||||
void setImageData(GuiImageData *img);
|
void setImageData(const std::shared_ptr<GuiImageData> &img);
|
||||||
|
|
||||||
//!Gets the pixel color at the specified coordinates of the image
|
|
||||||
//!\param x X coordinate
|
|
||||||
//!\param y Y coordinate
|
|
||||||
GX2Color getPixel(int32_t x, int32_t y);
|
|
||||||
|
|
||||||
//!Sets the pixel color at the specified coordinates of the image
|
|
||||||
//!\param x X coordinate
|
|
||||||
//!\param y Y coordinate
|
|
||||||
//!\param color Pixel color
|
|
||||||
void setPixel(int32_t x, int32_t y, const GX2Color &color);
|
|
||||||
|
|
||||||
//!Change ImageColor
|
//!Change ImageColor
|
||||||
void setImageColor(const GX2Color &c, int32_t idx = -1);
|
void setImageColor(const GX2Color &c, int32_t idx = -1);
|
||||||
|
|
||||||
//!Change ImageColor
|
virtual void setColorIntensity(const glm::vec4 &col) {
|
||||||
void setSize(int32_t w, int32_t h);
|
|
||||||
|
|
||||||
void setPrimitiveVertex(int32_t prim, const float *pos, const float *tex, uint32_t count);
|
|
||||||
|
|
||||||
void setBlurDirection(uint8_t dir, float value) {
|
|
||||||
if (dir < 2) {
|
|
||||||
blurDirection[dir] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setColorIntensity(const glm::vec4 &col) {
|
|
||||||
colorIntensity = col;
|
colorIntensity = col;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void internalInit(int32_t w, int32_t h);
|
void internalInit(uint32_t w, uint32_t h);
|
||||||
|
|
||||||
int32_t imgType; //!< Type of image data (IMAGE_TEXTURE, IMAGE_COLOR, IMAGE_DATA)
|
ImageTypes imgType = IMAGE_TEXTURE; //!< Type of image data (IMAGE_TEXTURE, IMAGE_COLOR, IMAGE_DATA)
|
||||||
GuiImageData *imageData; //!< Poiner to image data. May be shared with GuiImageData data
|
std::shared_ptr<GuiImageData> imageData; //!< Pointer to image data.
|
||||||
int32_t tileHorizontal; //!< Number of times to draw (tile) the image horizontally
|
|
||||||
int32_t tileVertical; //!< Number of times to draw (tile) the image vertically
|
|
||||||
|
|
||||||
//! Internally used variables for rendering
|
//! Internally used variables for rendering
|
||||||
uint8_t *colorVtxs;
|
uint8_t *colorVtxs = nullptr;
|
||||||
uint32_t colorCount;
|
|
||||||
bool colorVtxsDirty;
|
|
||||||
glm::vec3 positionOffsets;
|
|
||||||
glm::vec3 scaleFactor;
|
|
||||||
glm::vec4 colorIntensity;
|
|
||||||
float imageAngle;
|
|
||||||
glm::vec3 blurDirection;
|
|
||||||
|
|
||||||
const float *posVtxs;
|
uint32_t colorCount = 0;
|
||||||
const float *texCoords;
|
bool colorVtxsDirty = false;
|
||||||
uint32_t vtxCount;
|
glm::vec3 positionOffsets = {};
|
||||||
int32_t primitive;
|
glm::vec3 scaleFactor = {};
|
||||||
|
glm::vec4 colorIntensity = {};
|
||||||
|
|
||||||
|
const float *texCoords = {};
|
||||||
|
uint32_t vtxCount = {};
|
||||||
|
int32_t primitive = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,173 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* Copyright (C) 2015 Dimok
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*
|
|
||||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
****************************************************************************/
|
|
||||||
#include "../fs/CFile.hpp"
|
|
||||||
#include <gui/GuiImageAsync.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
std::vector<GuiImageAsync *> GuiImageAsync::imageQueue;
|
|
||||||
CThread *GuiImageAsync::pThread = NULL;
|
|
||||||
std::recursive_mutex *GuiImageAsync::pMutex = NULL;
|
|
||||||
uint32_t GuiImageAsync::threadRefCounter = 0;
|
|
||||||
bool GuiImageAsync::bExitRequested = false;
|
|
||||||
GuiImageAsync *GuiImageAsync::pInUse = NULL;
|
|
||||||
|
|
||||||
GuiImageAsync::GuiImageAsync(const uint8_t *imageBuffer, const uint32_t &imageBufferSize, GuiImageData *preloadImg)
|
|
||||||
: GuiImage(preloadImg), imgData(NULL), imgBuffer(imageBuffer), imgBufferSize(imageBufferSize) {
|
|
||||||
threadInit();
|
|
||||||
threadAddImage(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
GuiImageAsync::GuiImageAsync(const std::string &file, GuiImageData *preloadImg)
|
|
||||||
: GuiImage(preloadImg), imgData(NULL), filename(file), imgBuffer(NULL), imgBufferSize(0) {
|
|
||||||
threadInit();
|
|
||||||
threadAddImage(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
GuiImageAsync::~GuiImageAsync() {
|
|
||||||
threadRemoveImage(this);
|
|
||||||
while (pInUse == this)
|
|
||||||
OSSleepTicks(OSMicrosecondsToTicks(1000));
|
|
||||||
|
|
||||||
if (imgData) {
|
|
||||||
delete imgData;
|
|
||||||
}
|
|
||||||
|
|
||||||
//threadExit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiImageAsync::threadAddImage(GuiImageAsync *Image) {
|
|
||||||
pMutex->lock();
|
|
||||||
imageQueue.push_back(Image);
|
|
||||||
pMutex->unlock();
|
|
||||||
pThread->resumeThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiImageAsync::threadRemoveImage(GuiImageAsync *image) {
|
|
||||||
pMutex->lock();
|
|
||||||
for (uint32_t i = 0; i < imageQueue.size(); ++i) {
|
|
||||||
if (imageQueue[i] == image) {
|
|
||||||
imageQueue.erase(imageQueue.begin() + i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pMutex->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiImageAsync::clearQueue() {
|
|
||||||
pMutex->lock();
|
|
||||||
imageQueue.clear();
|
|
||||||
pMutex->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiImageAsync::guiImageAsyncThread(CThread *thread, void *arg) {
|
|
||||||
while (!bExitRequested) {
|
|
||||||
if (imageQueue.empty() && !bExitRequested) {
|
|
||||||
pThread->suspendThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!imageQueue.empty() && !bExitRequested) {
|
|
||||||
pMutex->lock();
|
|
||||||
pInUse = imageQueue.front();
|
|
||||||
imageQueue.erase(imageQueue.begin());
|
|
||||||
pMutex->unlock();
|
|
||||||
|
|
||||||
if (!pInUse) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (pInUse->imgBuffer && pInUse->imgBufferSize) {
|
|
||||||
pInUse->imgData = new GuiImageData(pInUse->imgBuffer, pInUse->imgBufferSize);
|
|
||||||
} else {
|
|
||||||
uint8_t *buffer = NULL;
|
|
||||||
uint64_t bufferSize = 0;
|
|
||||||
|
|
||||||
CFile file(pInUse->filename, CFile::ReadOnly);
|
|
||||||
if (file.isOpen()) {
|
|
||||||
uint64_t filesize = file.size();
|
|
||||||
buffer = (uint8_t *) malloc(filesize);
|
|
||||||
if (buffer != NULL) {
|
|
||||||
uint32_t blocksize = 0x4000;
|
|
||||||
uint32_t done = 0;
|
|
||||||
int32_t readBytes = 0;
|
|
||||||
while (done < filesize) {
|
|
||||||
if (done + blocksize > filesize) {
|
|
||||||
blocksize = filesize - done;
|
|
||||||
}
|
|
||||||
readBytes = file.read(buffer + done, blocksize);
|
|
||||||
if (readBytes <= 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
done += readBytes;
|
|
||||||
}
|
|
||||||
if (done == filesize) {
|
|
||||||
bufferSize = filesize;
|
|
||||||
} else {
|
|
||||||
free(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer != NULL && bufferSize > 0) {
|
|
||||||
pInUse->imgData = new GuiImageData(buffer, bufferSize, GX2_TEX_CLAMP_MODE_MIRROR);
|
|
||||||
|
|
||||||
//! free original image buffer which is converted to texture now and not needed anymore
|
|
||||||
free(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pInUse->imgData) {
|
|
||||||
if (pInUse->imgData->getTexture()) {
|
|
||||||
pInUse->width = pInUse->imgData->getWidth();
|
|
||||||
pInUse->height = pInUse->imgData->getHeight();
|
|
||||||
pInUse->imageData = pInUse->imgData;
|
|
||||||
} else {
|
|
||||||
delete pInUse->imgData;
|
|
||||||
pInUse->imgData = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pInUse->imageLoaded(pInUse);
|
|
||||||
pInUse = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiImageAsync::threadInit() {
|
|
||||||
if (pThread == NULL) {
|
|
||||||
bExitRequested = false;
|
|
||||||
pMutex = new std::recursive_mutex();
|
|
||||||
pThread = CThread::create(GuiImageAsync::guiImageAsyncThread, NULL, CThread::eAttributeAffCore1 | CThread::eAttributePinnedAff, 10);
|
|
||||||
pThread->resumeThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
++threadRefCounter;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiImageAsync::threadExit() {
|
|
||||||
if (threadRefCounter) {
|
|
||||||
--threadRefCounter;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (/*(threadRefCounter == 0) &&*/ (pThread != NULL)) {
|
|
||||||
bExitRequested = true;
|
|
||||||
delete pThread;
|
|
||||||
delete pMutex;
|
|
||||||
pThread = NULL;
|
|
||||||
pMutex = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,66 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* Copyright (C) 2015 Dimok
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*
|
|
||||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
****************************************************************************/
|
|
||||||
#ifndef _GUIIMAGEASYNC_H_
|
|
||||||
#define _GUIIMAGEASYNC_H_
|
|
||||||
|
|
||||||
#include <gui/GuiImage.h>
|
|
||||||
#include <mutex>
|
|
||||||
#include <system/CThread.h>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class GuiImageAsync : public GuiImage {
|
|
||||||
public:
|
|
||||||
GuiImageAsync(const uint8_t *imageBuffer, const uint32_t &imageBufferSize, GuiImageData *preloadImg);
|
|
||||||
|
|
||||||
GuiImageAsync(const std::string &filename, GuiImageData *preloadImg);
|
|
||||||
|
|
||||||
virtual ~GuiImageAsync();
|
|
||||||
|
|
||||||
static void clearQueue();
|
|
||||||
|
|
||||||
static void removeFromQueue(GuiImageAsync *image) {
|
|
||||||
threadRemoveImage(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! don't forget to LOCK GUI if using this asynchron call
|
|
||||||
sigslot::signal1<GuiImageAsync *> imageLoaded;
|
|
||||||
|
|
||||||
static void threadExit();
|
|
||||||
|
|
||||||
private:
|
|
||||||
static void threadInit();
|
|
||||||
|
|
||||||
GuiImageData *imgData;
|
|
||||||
std::string filename;
|
|
||||||
const uint8_t *imgBuffer;
|
|
||||||
const uint32_t imgBufferSize;
|
|
||||||
|
|
||||||
static void guiImageAsyncThread(CThread *thread, void *arg);
|
|
||||||
|
|
||||||
static void threadAddImage(GuiImageAsync *Image);
|
|
||||||
|
|
||||||
static void threadRemoveImage(GuiImageAsync *Image);
|
|
||||||
|
|
||||||
static std::vector<GuiImageAsync *> imageQueue;
|
|
||||||
static CThread *pThread;
|
|
||||||
static std::recursive_mutex *pMutex;
|
|
||||||
static uint32_t threadRefCounter;
|
|
||||||
static GuiImageAsync *pInUse;
|
|
||||||
static bool bExitRequested;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /*_GUIIMAGEASYNC_H_*/
|
|
@ -16,26 +16,19 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#include "system/memory.h"
|
#include "system/memory.h"
|
||||||
#include <gui/GuiImageData.h>
|
#include <gui/GuiImageData.h>
|
||||||
#include <malloc.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for the GuiImageData class.
|
* Constructor for the GuiImageData class.
|
||||||
*/
|
*/
|
||||||
GuiImageData::GuiImageData() {
|
GuiImageData::GuiImageData() = default;
|
||||||
texture = NULL;
|
|
||||||
sampler = NULL;
|
|
||||||
memoryType = eMemTypeMEM2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for the GuiImageData class.
|
* Constructor for the GuiImageData class.
|
||||||
*/
|
*/
|
||||||
GuiImageData::GuiImageData(const uint8_t *img, int32_t imgSize, GX2TexClampMode textureClamp, GX2SurfaceFormat textureFormat) {
|
GuiImageData::GuiImageData(std::span<const uint8_t> data, GX2TexClampMode textureClamp, GX2SurfaceFormat textureFormat) {
|
||||||
texture = NULL;
|
if (!loadImage(data, textureClamp, textureFormat)) {
|
||||||
sampler = NULL;
|
releaseData();
|
||||||
loadImage(img, imgSize, textureClamp, textureFormat);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,98 +38,61 @@ GuiImageData::~GuiImageData() {
|
|||||||
releaseData();
|
releaseData();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiImageData::releaseData(void) {
|
void GuiImageData::releaseData() {
|
||||||
if (texture) {
|
textureWrapper.reset();
|
||||||
if (texture->surface.image) {
|
sampler.reset();
|
||||||
switch (memoryType) {
|
|
||||||
default:
|
|
||||||
case eMemTypeMEM2:
|
|
||||||
free(texture->surface.image);
|
|
||||||
break;
|
|
||||||
case eMemTypeMEM1:
|
|
||||||
MEM1_free(texture->surface.image);
|
|
||||||
break;
|
|
||||||
case eMemTypeMEMBucket:
|
|
||||||
MEMBucket_free(texture->surface.image);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete texture;
|
|
||||||
texture = NULL;
|
|
||||||
}
|
|
||||||
if (sampler) {
|
|
||||||
delete sampler;
|
|
||||||
sampler = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiImageData::loadImage(const uint8_t *img, int32_t imgSize, GX2TexClampMode textureClamp, GX2SurfaceFormat textureFormat) {
|
bool GuiImageData::loadImage(std::span<const uint8_t> img, GX2TexClampMode textureClamp, GX2SurfaceFormat textureFormat) {
|
||||||
if (!img || (imgSize < 8)) {
|
if (img.empty() || img.size() < 8) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
releaseData();
|
releaseData();
|
||||||
gdImagePtr gdImg = 0;
|
gdImagePtr gdImg = nullptr;
|
||||||
|
|
||||||
if (img[0] == 0xFF && img[1] == 0xD8) {
|
if (img[0] == 0xFF && img[1] == 0xD8) {
|
||||||
//! not needed for now therefore comment out to safe ELF size
|
//! not needed for now therefore comment out to safe ELF size
|
||||||
//! if needed uncomment, adds 200 kb to the ELF size
|
//! if needed uncomment, adds 200 kb to the ELF size
|
||||||
// IMAGE_JPEG
|
// IMAGE_JPEG
|
||||||
gdImg = gdImageCreateFromJpegPtr(imgSize, (uint8_t *) img);
|
gdImg = gdImageCreateFromJpegPtr(img.size(), (void *) img.data());
|
||||||
} else if (img[0] == 'B' && img[1] == 'M') {
|
} else if (img[0] == 'B' && img[1] == 'M') {
|
||||||
// IMAGE_BMP
|
// IMAGE_BMP
|
||||||
gdImg = gdImageCreateFromBmpPtr(imgSize, (uint8_t *) img);
|
gdImg = gdImageCreateFromBmpPtr(img.size(), (void *) img.data());
|
||||||
} else if (img[0] == 0x89 && img[1] == 'P' && img[2] == 'N' && img[3] == 'G') {
|
} else if (img[0] == 0x89 && img[1] == 'P' && img[2] == 'N' && img[3] == 'G') {
|
||||||
// IMAGE_PNG
|
// IMAGE_PNG
|
||||||
gdImg = gdImageCreateFromPngPtr(imgSize, (uint8_t *) img);
|
gdImg = gdImageCreateFromPngPtr(img.size(), (void *) img.data());
|
||||||
}
|
}
|
||||||
//!This must be last since it can also intefere with outher formats
|
//!This must be last since it can also intefere with outher formats
|
||||||
else if (img[0] == 0x00) {
|
else if (img[0] == 0x00) {
|
||||||
// Try loading TGA image
|
// Try loading TGA image
|
||||||
gdImg = gdImageCreateFromTgaPtr(imgSize, (uint8_t *) img);
|
gdImg = gdImageCreateFromTgaPtr(img.size(), (void *) img.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gdImg == 0) {
|
if (gdImg == nullptr) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t width = (gdImageSX(gdImg));
|
uint32_t width = (gdImageSX(gdImg));
|
||||||
uint32_t height = (gdImageSY(gdImg));
|
uint32_t height = (gdImageSY(gdImg));
|
||||||
|
|
||||||
//! Initialize texture
|
//! Initialize texture
|
||||||
texture = new GX2Texture;
|
textureWrapper = std::make_unique<GX2TextureImageDataWrapper>();
|
||||||
GX2InitTexture(texture, width, height, 1, 0, textureFormat, GX2_SURFACE_DIM_TEXTURE_2D, GX2_TILE_MODE_LINEAR_ALIGNED);
|
if (!textureWrapper->InitTexture(width, height, textureFormat)) {
|
||||||
|
gdImageDestroy(gdImg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GX2Texture *texture = textureWrapper->getTexture();
|
||||||
|
|
||||||
//! if this fails something went horribly wrong
|
//! if this fails something went horribly wrong
|
||||||
if (texture->surface.imageSize == 0) {
|
if (texture->surface.imageSize == 0) {
|
||||||
delete texture;
|
|
||||||
texture = NULL;
|
|
||||||
gdImageDestroy(gdImg);
|
gdImageDestroy(gdImg);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! allocate memory for the surface
|
|
||||||
memoryType = eMemTypeMEM2;
|
|
||||||
texture->surface.image = memalign(texture->surface.alignment, texture->surface.imageSize);
|
|
||||||
//! try MEM1 on failure
|
|
||||||
if (!texture->surface.image) {
|
|
||||||
memoryType = eMemTypeMEM1;
|
|
||||||
texture->surface.image = MEM1_alloc(texture->surface.imageSize, texture->surface.alignment);
|
|
||||||
}
|
|
||||||
//! try MEM bucket on failure
|
|
||||||
if (!texture->surface.image) {
|
|
||||||
memoryType = eMemTypeMEMBucket;
|
|
||||||
texture->surface.image = MEMBucket_alloc(texture->surface.imageSize, texture->surface.alignment);
|
|
||||||
}
|
|
||||||
//! check if memory is available for image
|
|
||||||
if (!texture->surface.image) {
|
|
||||||
gdImageDestroy(gdImg);
|
|
||||||
delete texture;
|
|
||||||
texture = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//! set mip map data pointer
|
//! set mip map data pointer
|
||||||
texture->surface.mipmaps = NULL;
|
texture->surface.mipmaps = nullptr;
|
||||||
//! convert image to texture
|
//! convert image to texture
|
||||||
switch (textureFormat) {
|
switch (textureFormat) {
|
||||||
default:
|
default:
|
||||||
@ -154,8 +110,9 @@ void GuiImageData::loadImage(const uint8_t *img, int32_t imgSize, GX2TexClampMod
|
|||||||
//! invalidate the memory
|
//! invalidate the memory
|
||||||
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, texture->surface.image, texture->surface.imageSize);
|
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, texture->surface.image, texture->surface.imageSize);
|
||||||
//! initialize the sampler
|
//! initialize the sampler
|
||||||
sampler = new GX2Sampler;
|
sampler = std::make_unique<GX2Sampler>();
|
||||||
GX2InitSampler(sampler, textureClamp, GX2_TEX_XY_FILTER_MODE_LINEAR);
|
GX2InitSampler(sampler.get(), textureClamp, GX2_TEX_XY_FILTER_MODE_LINEAR);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiImageData::gdImageToUnormR8G8B8A8(gdImagePtr gdImg, uint32_t *imgBuffer, uint32_t width, uint32_t height, uint32_t pitch) {
|
void GuiImageData::gdImageToUnormR8G8B8A8(gdImagePtr gdImg, uint32_t *imgBuffer, uint32_t width, uint32_t height, uint32_t pitch) {
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
#include <gui/GuiElement.h>
|
#include <gui/GuiElement.h>
|
||||||
#include <gui/gx2_ext.h>
|
#include <gui/gx2_ext.h>
|
||||||
#include <gx2/texture.h>
|
#include <gx2/texture.h>
|
||||||
|
#include <memory>
|
||||||
|
#include <span>
|
||||||
|
|
||||||
class GuiImageData : public GuiElement {
|
class GuiImageData : public GuiElement {
|
||||||
public:
|
public:
|
||||||
@ -29,30 +31,33 @@ public:
|
|||||||
|
|
||||||
//!\param img Image data
|
//!\param img Image data
|
||||||
//!\param imgSize The image size
|
//!\param imgSize The image size
|
||||||
GuiImageData(const uint8_t *img, int32_t imgSize, GX2TexClampMode textureClamp = GX2_TEX_CLAMP_MODE_CLAMP, GX2SurfaceFormat textureFormat = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8);
|
explicit GuiImageData(std::span<const uint8_t> img, GX2TexClampMode textureClamp = GX2_TEX_CLAMP_MODE_CLAMP, GX2SurfaceFormat textureFormat = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8);
|
||||||
|
|
||||||
//!Destructor
|
//!Destructor
|
||||||
virtual ~GuiImageData();
|
~GuiImageData() override;
|
||||||
|
|
||||||
//!Load image from buffer
|
//!Load image from buffer
|
||||||
//!\param img Image data
|
//!\param img Image data
|
||||||
//!\param imgSize The image size
|
//!\param imgSize The image size
|
||||||
void loadImage(const uint8_t *img, int32_t imgSize, GX2TexClampMode textureClamp = GX2_TEX_CLAMP_MODE_CLAMP, GX2SurfaceFormat textureFormat = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8);
|
bool loadImage(std::span<const uint8_t> img, GX2TexClampMode textureClamp = GX2_TEX_CLAMP_MODE_CLAMP, GX2SurfaceFormat textureFormat = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8);
|
||||||
|
|
||||||
//! getter functions
|
//! getter functions
|
||||||
virtual const GX2Texture *getTexture() const {
|
[[nodiscard]] virtual const GX2Texture *getTexture() const {
|
||||||
return texture;
|
if (!textureWrapper) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return textureWrapper->getTexture();
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual const GX2Sampler *getSampler() const {
|
[[nodiscard]] virtual const GX2Sampler *getSampler() const {
|
||||||
return sampler;
|
return sampler.get();
|
||||||
};
|
};
|
||||||
|
|
||||||
//!Gets the image width
|
//!Gets the image width
|
||||||
//!\return image width
|
//!\return image width
|
||||||
float getWidth() override {
|
float getWidth() override {
|
||||||
if (texture) {
|
if (textureWrapper) {
|
||||||
return texture->surface.width;
|
return textureWrapper->getTexture()->surface.width;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -61,8 +66,8 @@ public:
|
|||||||
//!Gets the image height
|
//!Gets the image height
|
||||||
//!\return image height
|
//!\return image height
|
||||||
float getHeight() override {
|
float getHeight() override {
|
||||||
if (texture) {
|
if (textureWrapper) {
|
||||||
return texture->surface.height;
|
return textureWrapper->getTexture()->surface.height;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -72,20 +77,69 @@ public:
|
|||||||
void releaseData();
|
void releaseData();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class GX2TextureImageDataWrapper {
|
||||||
|
public:
|
||||||
|
[[nodiscard]] GX2Texture *getTexture() {
|
||||||
|
return &texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InitTexture(uint32_t width, uint32_t height, GX2SurfaceFormat textureFormat) {
|
||||||
|
GX2InitTexture(&texture, width, height, 1, 0, textureFormat, GX2_SURFACE_DIM_TEXTURE_2D, GX2_TILE_MODE_LINEAR_ALIGNED);
|
||||||
|
|
||||||
|
//! allocate memory for the surface
|
||||||
|
memoryType = MEM2;
|
||||||
|
texture.surface.image = MEM2_alloc(texture.surface.alignment, texture.surface.imageSize);
|
||||||
|
//! try MEM1 on failure
|
||||||
|
if (!texture.surface.image) {
|
||||||
|
memoryType = MEM1;
|
||||||
|
texture.surface.image = MEM1_alloc(texture.surface.imageSize, texture.surface.alignment);
|
||||||
|
}
|
||||||
|
//! try MEM bucket on failure
|
||||||
|
if (!texture.surface.image) {
|
||||||
|
memoryType = MEM_BUCKET;
|
||||||
|
texture.surface.image = MEMBucket_alloc(texture.surface.imageSize, texture.surface.alignment);
|
||||||
|
}
|
||||||
|
//! check if memory is available for image
|
||||||
|
if (!texture.surface.image) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
~GX2TextureImageDataWrapper() {
|
||||||
|
if (texture.surface.image) {
|
||||||
|
switch (memoryType) {
|
||||||
|
default:
|
||||||
|
case MEM2:
|
||||||
|
MEM2_free(texture.surface.image);
|
||||||
|
break;
|
||||||
|
case MEM1:
|
||||||
|
MEM1_free(texture.surface.image);
|
||||||
|
break;
|
||||||
|
case MEM_BUCKET:
|
||||||
|
MEMBucket_free(texture.surface.image);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MemoryType {
|
||||||
|
MEM1,
|
||||||
|
MEM2,
|
||||||
|
MEM_BUCKET
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
alignas(0x40) GX2Texture texture;
|
||||||
|
MemoryType memoryType;
|
||||||
|
};
|
||||||
|
|
||||||
void gdImageToUnormR8G8B8A8(gdImagePtr gdImg, uint32_t *imgBuffer, uint32_t width, uint32_t height, uint32_t pitch);
|
void gdImageToUnormR8G8B8A8(gdImagePtr gdImg, uint32_t *imgBuffer, uint32_t width, uint32_t height, uint32_t pitch);
|
||||||
|
|
||||||
void gdImageToUnormR5G6B5(gdImagePtr gdImg, uint16_t *imgBuffer, uint32_t width, uint32_t height, uint32_t pitch);
|
void gdImageToUnormR5G6B5(gdImagePtr gdImg, uint16_t *imgBuffer, uint32_t width, uint32_t height, uint32_t pitch);
|
||||||
|
|
||||||
GX2Texture *texture;
|
std::unique_ptr<GX2TextureImageDataWrapper> textureWrapper;
|
||||||
GX2Sampler *sampler;
|
std::unique_ptr<GX2Sampler> sampler;
|
||||||
|
|
||||||
enum eMemoryTypes {
|
|
||||||
eMemTypeMEM2,
|
|
||||||
eMemTypeMEM1,
|
|
||||||
eMemTypeMEMBucket
|
|
||||||
};
|
|
||||||
|
|
||||||
uint8_t memoryType;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,7 +30,7 @@ static inline float getRandMinusOneToOneF32() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GuiParticleImage::GuiParticleImage(int32_t w, int32_t h, uint32_t particleCount, float minRadius, float maxRadius, float minSpeed, float maxSpeed)
|
GuiParticleImage::GuiParticleImage(int32_t w, int32_t h, uint32_t particleCount, float minRadius, float maxRadius, float minSpeed, float maxSpeed)
|
||||||
: GuiImage(NULL) {
|
: GuiImage(nullptr) {
|
||||||
width = w;
|
width = w;
|
||||||
height = h;
|
height = h;
|
||||||
imgType = IMAGE_COLOR;
|
imgType = IMAGE_COLOR;
|
||||||
@ -39,8 +39,14 @@ GuiParticleImage::GuiParticleImage(int32_t w, int32_t h, uint32_t particleCount,
|
|||||||
this->minSpeed = minSpeed;
|
this->minSpeed = minSpeed;
|
||||||
this->maxSpeed = maxSpeed;
|
this->maxSpeed = maxSpeed;
|
||||||
|
|
||||||
posVertexs = (float *) memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ColorShader::cuVertexAttrSize * CIRCLE_VERTEX_COUNT);
|
posVertexs = (float *) memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ColorShader::cuVertexAttrSize * CIRCLE_VERTEX_COUNT);
|
||||||
|
if (!posVertexs) {
|
||||||
|
throw std::runtime_error("Failed to allocate posVertexs in GuiParticleImage");
|
||||||
|
}
|
||||||
colorVertexs = (uint8_t *) memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ColorShader::cuColorAttrSize * CIRCLE_VERTEX_COUNT);
|
colorVertexs = (uint8_t *) memalign(GX2_VERTEX_BUFFER_ALIGNMENT, ColorShader::cuColorAttrSize * CIRCLE_VERTEX_COUNT);
|
||||||
|
if (!colorVertexs) {
|
||||||
|
throw std::runtime_error("Failed to allocate colorVertexs in GuiParticleImage");
|
||||||
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < CIRCLE_VERTEX_COUNT; i++) {
|
for (uint32_t i = 0; i < CIRCLE_VERTEX_COUNT; i++) {
|
||||||
posVertexs[i * 3 + 0] = cosf(DegToRad(i * 360.0f / CIRCLE_VERTEX_COUNT));
|
posVertexs[i * 3 + 0] = cosf(DegToRad(i * 360.0f / CIRCLE_VERTEX_COUNT));
|
||||||
@ -73,52 +79,50 @@ GuiParticleImage::~GuiParticleImage() {
|
|||||||
free(colorVertexs);
|
free(colorVertexs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiParticleImage::draw(CVideo *pVideo) {
|
void GuiParticleImage::draw(const CVideo &pVideo) {
|
||||||
if (!this->isVisible()) {
|
if (!this->isVisible()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
float currScaleX = getScaleX();
|
float currScaleX = getScaleX();
|
||||||
float currScaleY = getScaleY();
|
float currScaleY = getScaleY();
|
||||||
|
|
||||||
positionOffsets[2] = getDepth() * pVideo->getDepthScaleFactor() * 2.0f;
|
positionOffsets[2] = getDepth() * pVideo.getDepthScaleFactor() * 2.0f;
|
||||||
|
|
||||||
scaleFactor[2] = getScaleZ();
|
scaleFactor[2] = getScaleZ();
|
||||||
|
|
||||||
//! add other colors intensities parameters
|
//! add other colors intensities parameters
|
||||||
colorIntensity[3] = getAlpha();
|
colorIntensity[3] = getAlpha();
|
||||||
|
|
||||||
for (uint32_t i = 0; i < particles.size(); ++i) {
|
for (auto &particle : particles) {
|
||||||
if (particles[i].position.y > (getHeight() * 0.5f + 30.0f)) {
|
if (particle.position.y > (getHeight() * 0.5f + 30.0f)) {
|
||||||
particles[i].position.x = getRandMinusOneToOneF32() * getWidth() * 0.5f;
|
particle.position.x = getRandMinusOneToOneF32() * getWidth() * 0.5f;
|
||||||
particles[i].position.y = -getHeight() * 0.5f - 30.0f;
|
particle.position.y = -getHeight() * 0.5f - 30.0f;
|
||||||
particles[i].colors = glm::vec4(1.0f, 1.0f, 1.0f, (getRandZeroToOneF32() * 0.6f) + 0.05f);
|
particle.colors = glm::vec4(1.0f, 1.0f, 1.0f, (getRandZeroToOneF32() * 0.6f) + 0.05f);
|
||||||
particles[i].radius = getRandZeroToOneF32() * (maxRadius - minRadius) + minRadius;
|
particle.radius = getRandZeroToOneF32() * (maxRadius - minRadius) + minRadius;
|
||||||
particles[i].speed = (getRandZeroToOneF32() * (maxSpeed - minSpeed)) + minSpeed;
|
particle.speed = (getRandZeroToOneF32() * (maxSpeed - minSpeed)) + minSpeed;
|
||||||
particles[i].direction = getRandMinusOneToOneF32();
|
particle.direction = getRandMinusOneToOneF32();
|
||||||
}
|
}
|
||||||
if (particles[i].position.x < (-getWidth() * 0.5f - 50.0f)) {
|
if (particle.position.x < (-getWidth() * 0.5f - 50.0f)) {
|
||||||
particles[i].position.x = -particles[i].position.x;
|
particle.position.x = -particle.position.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
particle.direction += getRandMinusOneToOneF32() * 0.03f;
|
||||||
|
particle.position.x += particle.speed * particle.direction;
|
||||||
|
particle.position.y += particle.speed;
|
||||||
|
|
||||||
particles[i].direction += getRandMinusOneToOneF32() * 0.03f;
|
positionOffsets[0] = (getCenterX() + particle.position.x) * pVideo.getWidthScaleFactor() * 2.0f;
|
||||||
particles[i].position.x += particles[i].speed * particles[i].direction;
|
positionOffsets[1] = (getCenterY() + particle.position.y) * pVideo.getHeightScaleFactor() * 2.0f;
|
||||||
particles[i].position.y += particles[i].speed;
|
|
||||||
|
|
||||||
positionOffsets[0] = (getCenterX() + particles[i].position.x) * pVideo->getWidthScaleFactor() * 2.0f;
|
scaleFactor[0] = currScaleX * particle.radius * pVideo.getWidthScaleFactor();
|
||||||
positionOffsets[1] = (getCenterY() + particles[i].position.y) * pVideo->getHeightScaleFactor() * 2.0f;
|
scaleFactor[1] = currScaleY * particle.radius * pVideo.getHeightScaleFactor();
|
||||||
|
|
||||||
scaleFactor[0] = currScaleX * particles[i].radius * pVideo->getWidthScaleFactor();
|
|
||||||
scaleFactor[1] = currScaleY * particles[i].radius * pVideo->getHeightScaleFactor();
|
|
||||||
|
|
||||||
ColorShader::instance()->setShaders();
|
ColorShader::instance()->setShaders();
|
||||||
ColorShader::instance()->setAttributeBuffer(colorVertexs, posVertexs, CIRCLE_VERTEX_COUNT);
|
ColorShader::instance()->setAttributeBuffer(colorVertexs, posVertexs, CIRCLE_VERTEX_COUNT);
|
||||||
ColorShader::instance()->setAngle(0.0f);
|
ColorShader::instance()->setAngle(0.0f);
|
||||||
ColorShader::instance()->setOffset(positionOffsets);
|
ColorShader::instance()->setOffset(positionOffsets);
|
||||||
ColorShader::instance()->setScale(scaleFactor);
|
ColorShader::instance()->setScale(scaleFactor);
|
||||||
ColorShader::instance()->setColorIntensity(colorIntensity * particles[i].colors);
|
ColorShader::instance()->setColorIntensity(colorIntensity * particle.colors);
|
||||||
ColorShader::instance()->draw(GX2_PRIMITIVE_MODE_TRIANGLE_FAN, CIRCLE_VERTEX_COUNT);
|
ColorShader::instance()->draw(GX2_PRIMITIVE_MODE_TRIANGLE_FAN, CIRCLE_VERTEX_COUNT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,9 @@ class GuiParticleImage : public GuiImage, public sigslot::has_slots<> {
|
|||||||
public:
|
public:
|
||||||
GuiParticleImage(int32_t w, int32_t h, uint32_t particleCount, float minRadius, float maxRadius, float minSpeed, float maxSpeed);
|
GuiParticleImage(int32_t w, int32_t h, uint32_t particleCount, float minRadius, float maxRadius, float minSpeed, float maxSpeed);
|
||||||
|
|
||||||
virtual ~GuiParticleImage();
|
~GuiParticleImage() override;
|
||||||
|
|
||||||
void draw(CVideo *pVideo) override;
|
void draw(const CVideo &pVideo) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float *posVertexs;
|
float *posVertexs;
|
||||||
|
@ -1,221 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
* Copyright (C) 2011
|
|
||||||
* by Dimok
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied
|
|
||||||
* warranty. In no event will the authors be held liable for any
|
|
||||||
* damages arising from the use of this software.
|
|
||||||
*
|
|
||||||
* Permission is granted to anyone to use this software for any
|
|
||||||
* purpose, including commercial applications, and to alter it and
|
|
||||||
* redistribute it freely, subject to the following restrictions:
|
|
||||||
*
|
|
||||||
* 1. The origin of this software must not be misrepresented; you
|
|
||||||
* must not claim that you wrote the original software. If you use
|
|
||||||
* this software in a product, an acknowledgment in the product
|
|
||||||
* documentation would be appreciated but is not required.
|
|
||||||
*
|
|
||||||
* 2. Altered source versions must be plainly marked as such, and
|
|
||||||
* must not be misrepresented as being the original software.
|
|
||||||
*
|
|
||||||
* 3. This notice may not be removed or altered from any source
|
|
||||||
* distribution.
|
|
||||||
***************************************************************************/
|
|
||||||
#include "utils/utils.h"
|
|
||||||
#include <gui/GuiScrollbar.h>
|
|
||||||
|
|
||||||
GuiScrollbar::GuiScrollbar(int32_t h)
|
|
||||||
: touchTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::VPAD_TOUCH), wpadTouchTrigger(GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5, GuiTrigger::BUTTON_A) {
|
|
||||||
SelItem = 0;
|
|
||||||
SelInd = 0;
|
|
||||||
PageSize = 0;
|
|
||||||
EntrieCount = 0;
|
|
||||||
SetScrollSpeed(15);
|
|
||||||
ScrollState = 0;
|
|
||||||
|
|
||||||
listChanged.connect(this, &GuiScrollbar::setScrollboxPosition);
|
|
||||||
|
|
||||||
height = h;
|
|
||||||
|
|
||||||
arrowUpBtn = new GuiButton(50, 50);
|
|
||||||
arrowUpBtn->setParent(this);
|
|
||||||
arrowUpBtn->setAlignment(ALIGN_CENTER | ALIGN_TOP);
|
|
||||||
arrowUpBtn->setPosition(0, 0);
|
|
||||||
arrowUpBtn->setTrigger(&touchTrigger, 0);
|
|
||||||
arrowUpBtn->setTrigger(&wpadTouchTrigger, 1);
|
|
||||||
arrowUpBtn->setEffectGrow();
|
|
||||||
arrowUpBtn->clicked.connect(this, &GuiScrollbar::OnUpButtonClick);
|
|
||||||
|
|
||||||
arrowDownBtn = new GuiButton(50, 50);
|
|
||||||
arrowDownBtn->setParent(this);
|
|
||||||
arrowDownBtn->setAlignment(ALIGN_CENTER | ALIGN_BOTTOM);
|
|
||||||
arrowDownBtn->setPosition(0, 0);
|
|
||||||
arrowDownBtn->setTrigger(&touchTrigger, 0);
|
|
||||||
arrowDownBtn->setTrigger(&wpadTouchTrigger, 1);
|
|
||||||
arrowDownBtn->setEffectGrow();
|
|
||||||
arrowDownBtn->clicked.connect(this, &GuiScrollbar::OnDownButtonClick);
|
|
||||||
|
|
||||||
scrollbarBoxBtn = new GuiButton(50, height);
|
|
||||||
scrollbarBoxBtn->setParent(this);
|
|
||||||
scrollbarBoxBtn->setAlignment(ALIGN_CENTER | ALIGN_TOP);
|
|
||||||
scrollbarBoxBtn->setPosition(0, MaxHeight);
|
|
||||||
scrollbarBoxBtn->setHoldable(true);
|
|
||||||
scrollbarBoxBtn->setTrigger(&touchTrigger, 0);
|
|
||||||
scrollbarBoxBtn->setTrigger(&wpadTouchTrigger, 1);
|
|
||||||
scrollbarBoxBtn->setEffectGrow();
|
|
||||||
scrollbarBoxBtn->held.connect(this, &GuiScrollbar::OnBoxButtonHold);
|
|
||||||
}
|
|
||||||
|
|
||||||
GuiScrollbar::~GuiScrollbar() {
|
|
||||||
delete arrowUpBtn;
|
|
||||||
delete arrowDownBtn;
|
|
||||||
delete scrollbarBoxBtn;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiScrollbar::ScrollOneUp() {
|
|
||||||
if (SelItem == 0 && SelInd > 0) {
|
|
||||||
// move list up by 1
|
|
||||||
--SelInd;
|
|
||||||
} else if (SelInd + SelItem > 0) {
|
|
||||||
--SelItem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiScrollbar::ScrollOneDown() {
|
|
||||||
if (SelInd + SelItem + 1 < EntrieCount) {
|
|
||||||
if (SelItem == PageSize - 1) {
|
|
||||||
// move list down by 1
|
|
||||||
SelInd++;
|
|
||||||
} else {
|
|
||||||
SelItem++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiScrollbar::OnUpButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger) {
|
|
||||||
if (ScrollState < ScrollSpeed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ScrollOneUp();
|
|
||||||
|
|
||||||
ScrollState = 0;
|
|
||||||
listChanged(SelItem, SelInd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiScrollbar::OnDownButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger) {
|
|
||||||
if (ScrollState < ScrollSpeed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ScrollOneDown();
|
|
||||||
|
|
||||||
ScrollState = 0;
|
|
||||||
listChanged(SelItem, SelInd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiScrollbar::OnBoxButtonHold(GuiButton *button, const GuiController *controller, GuiTrigger *trigger) {
|
|
||||||
if (EntrieCount == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!controller->data.validPointer) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t y = controller->data.y - this->getCenterY();
|
|
||||||
|
|
||||||
int32_t positionWiimote = LIMIT(y - MinHeight, 0, MaxHeight - MinHeight);
|
|
||||||
|
|
||||||
int32_t newSelected = (EntrieCount - 1) - (int32_t) ((float) positionWiimote / (float) (MaxHeight - MinHeight) * (float) (EntrieCount - 1));
|
|
||||||
|
|
||||||
int32_t diff = newSelected - SelInd - SelItem;
|
|
||||||
|
|
||||||
if (newSelected <= 0) {
|
|
||||||
SelItem = 0;
|
|
||||||
SelInd = 0;
|
|
||||||
} else if (newSelected >= EntrieCount - 1) {
|
|
||||||
SelItem = (PageSize - 1 < EntrieCount - 1) ? PageSize - 1 : EntrieCount - 1;
|
|
||||||
SelInd = EntrieCount - PageSize;
|
|
||||||
} else if (newSelected < PageSize && SelInd == 0 && diff < 0) {
|
|
||||||
SelItem = std::max(SelItem + diff, (int32_t) 0);
|
|
||||||
} else if (EntrieCount - newSelected < PageSize && SelInd == EntrieCount - PageSize && diff > 0) {
|
|
||||||
SelItem = std::min(SelItem + diff, PageSize - 1);
|
|
||||||
} else {
|
|
||||||
SelInd = LIMIT(SelInd + diff, 0, ((EntrieCount - PageSize < 0) ? 0 : EntrieCount - PageSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
ScrollState = 0;
|
|
||||||
listChanged(SelItem, SelInd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiScrollbar::SetPageSize(int32_t size) {
|
|
||||||
if (PageSize == size) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PageSize = size;
|
|
||||||
listChanged(SelItem, SelInd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiScrollbar::SetSelectedItem(int32_t pos) {
|
|
||||||
if (SelItem == pos) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SelItem = LIMIT(pos, 0, EntrieCount - 1);
|
|
||||||
listChanged(SelItem, SelInd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiScrollbar::SetSelectedIndex(int32_t pos) {
|
|
||||||
if (SelInd == pos) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SelInd = pos;
|
|
||||||
listChanged(SelItem, SelInd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiScrollbar::SetEntrieCount(int32_t cnt) {
|
|
||||||
if (EntrieCount == cnt) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
EntrieCount = cnt;
|
|
||||||
listChanged(SelItem, SelInd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiScrollbar::setScrollboxPosition(int32_t SelItem, int32_t SelInd) {
|
|
||||||
int32_t position = MaxHeight - (MaxHeight - MinHeight) * (SelInd + SelItem) / (EntrieCount - 1);
|
|
||||||
|
|
||||||
if (position < MinHeight || (SelInd + SelItem >= EntrieCount - 1)) {
|
|
||||||
position = MinHeight;
|
|
||||||
} else if (position > MaxHeight || (SelInd + SelItem) == 0) {
|
|
||||||
position = MaxHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
scrollbarBoxBtn->setPosition(0, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiScrollbar::draw(CVideo *video) {
|
|
||||||
if (scrollbarLineImage) {
|
|
||||||
scrollbarLineImage->draw(video);
|
|
||||||
}
|
|
||||||
arrowUpBtn->draw(video);
|
|
||||||
arrowDownBtn->draw(video);
|
|
||||||
scrollbarBoxBtn->draw(video);
|
|
||||||
|
|
||||||
updateEffects();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiScrollbar::update(GuiController *t) {
|
|
||||||
if (this->isStateSet(STATE_DISABLED)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
arrowUpBtn->update(t);
|
|
||||||
arrowDownBtn->update(t);
|
|
||||||
scrollbarBoxBtn->update(t);
|
|
||||||
|
|
||||||
++ScrollState;
|
|
||||||
}
|
|
@ -1,150 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
* Copyright (C) 2011
|
|
||||||
* by Dimok
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied
|
|
||||||
* warranty. In no event will the authors be held liable for any
|
|
||||||
* damages arising from the use of this software.
|
|
||||||
*
|
|
||||||
* Permission is granted to anyone to use this software for any
|
|
||||||
* purpose, including commercial applications, and to alter it and
|
|
||||||
* redistribute it freely, subject to the following restrictions:
|
|
||||||
*
|
|
||||||
* 1. The origin of this software must not be misrepresented; you
|
|
||||||
* must not claim that you wrote the original software. If you use
|
|
||||||
* this software in a product, an acknowledgment in the product
|
|
||||||
* documentation would be appreciated but is not required.
|
|
||||||
*
|
|
||||||
* 2. Altered source versions must be plainly marked as such, and
|
|
||||||
* must not be misrepresented as being the original software.
|
|
||||||
*
|
|
||||||
* 3. This notice may not be removed or altered from any source
|
|
||||||
* distribution.
|
|
||||||
***************************************************************************/
|
|
||||||
#ifndef GUI_SCROLLBAR_HPP_
|
|
||||||
#define GUI_SCROLLBAR_HPP_
|
|
||||||
|
|
||||||
#include <gui/GuiButton.h>
|
|
||||||
#include <gui/GuiElement.h>
|
|
||||||
|
|
||||||
class GuiScrollbar : public GuiElement, public sigslot::has_slots<> {
|
|
||||||
public:
|
|
||||||
GuiScrollbar(int32_t height);
|
|
||||||
|
|
||||||
virtual ~GuiScrollbar();
|
|
||||||
|
|
||||||
void ScrollOneUp();
|
|
||||||
|
|
||||||
void ScrollOneDown();
|
|
||||||
|
|
||||||
int32_t GetSelectedItem() {
|
|
||||||
return SelItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t GetSelectedIndex() {
|
|
||||||
return SelInd;
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw(CVideo *video) override;
|
|
||||||
|
|
||||||
void update(GuiController *t);
|
|
||||||
|
|
||||||
//! Signals
|
|
||||||
sigslot::signal2<int32_t, int32_t> listChanged;
|
|
||||||
|
|
||||||
//! Slots
|
|
||||||
void SetScrollSpeed(int32_t speed) {
|
|
||||||
ScrollSpeed = speed;
|
|
||||||
};
|
|
||||||
|
|
||||||
void SetPageSize(int32_t size);
|
|
||||||
|
|
||||||
void SetRowSize(int32_t size);
|
|
||||||
|
|
||||||
void SetSelectedItem(int32_t pos);
|
|
||||||
|
|
||||||
void SetSelectedIndex(int32_t pos);
|
|
||||||
|
|
||||||
void SetEntrieCount(int32_t cnt);
|
|
||||||
|
|
||||||
void setSoundClick(GuiSound *snd) {
|
|
||||||
clickSound = snd;
|
|
||||||
arrowUpBtn->setSoundClick(snd);
|
|
||||||
arrowDownBtn->setSoundClick(snd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setImageScrollbarLine(GuiImage *img) {
|
|
||||||
if (img) {
|
|
||||||
scrollbarLineImage = img;
|
|
||||||
scrollbarLineImage->setParent(this);
|
|
||||||
scrollbarLineImage->setParent(this);
|
|
||||||
scrollbarLineImage->setAlignment(ALIGN_CENTER | ALIGN_MIDDLE);
|
|
||||||
scrollbarLineImage->setPosition(0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setImageArrowDown(GuiImage *img) {
|
|
||||||
if (img) {
|
|
||||||
arrowDownImage = img;
|
|
||||||
arrowDownBtn->setSize(img->getWidth(), img->getHeight());
|
|
||||||
arrowDownBtn->setImage(img);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setImageArrowUp(GuiImage *img) {
|
|
||||||
if (img) {
|
|
||||||
arrowUpImage = img;
|
|
||||||
arrowUpBtn->setSize(img->getWidth(), img->getHeight());
|
|
||||||
arrowUpBtn->setImage(img);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setImageScrollbarBox(GuiImage *img) {
|
|
||||||
if (img) {
|
|
||||||
scrollbarBoxImage = img;
|
|
||||||
scrollbarBoxBtn->setSize(img->getWidth(), height);
|
|
||||||
scrollbarBoxBtn->setImage(img);
|
|
||||||
|
|
||||||
width = img->getWidth();
|
|
||||||
|
|
||||||
MaxHeight = height * 0.5f - (img ? (img->getHeight() * 0.5f) : 0) - (arrowUpImage ? arrowUpImage->getHeight() : 0);
|
|
||||||
MinHeight = -height * 0.5f + (img ? (img->getHeight() * 0.5f) : 0) + (arrowDownImage ? arrowDownImage->getHeight() : 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void setScrollboxPosition(int32_t SelItem, int32_t SelInd);
|
|
||||||
|
|
||||||
void OnUpButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);
|
|
||||||
|
|
||||||
void OnDownButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);
|
|
||||||
|
|
||||||
void OnBoxButtonHold(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);
|
|
||||||
|
|
||||||
uint32_t ScrollState;
|
|
||||||
uint16_t ScrollSpeed;
|
|
||||||
|
|
||||||
int32_t MinHeight;
|
|
||||||
int32_t MaxHeight;
|
|
||||||
int32_t SelItem;
|
|
||||||
int32_t SelInd;
|
|
||||||
int32_t PageSize;
|
|
||||||
int32_t EntrieCount;
|
|
||||||
int32_t pressedChan;
|
|
||||||
|
|
||||||
GuiButton *arrowUpBtn;
|
|
||||||
GuiButton *arrowDownBtn;
|
|
||||||
GuiButton *scrollbarBoxBtn;
|
|
||||||
|
|
||||||
GuiSound *clickSound = NULL;
|
|
||||||
|
|
||||||
GuiImage *scrollbarLineImage = NULL;
|
|
||||||
GuiImage *arrowDownImage = NULL;
|
|
||||||
GuiImage *arrowUpImage = NULL;
|
|
||||||
GuiImage *scrollbarBoxImage = NULL;
|
|
||||||
|
|
||||||
GuiTrigger touchTrigger;
|
|
||||||
GuiTrigger wpadTouchTrigger;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,289 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* Copyright (C) 2016 Maschell
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*
|
|
||||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
****************************************************************************/
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <gui/GuiImage.h>
|
|
||||||
#include <gui/GuiImageData.h>
|
|
||||||
#include <gui/GuiSelectBox.h>
|
|
||||||
#include <gui/GuiTrigger.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for the GuiCheckBox class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
GuiSelectBox::GuiSelectBox(GuiImage *background, std::string caption, float width, float height, GuiFrame *parent)
|
|
||||||
: GuiFrame(width, height, parent), selected(0), captionText(caption), topValueButton(0, 0), touchTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::VPAD_TOUCH),
|
|
||||||
wpadTouchTrigger(GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5, GuiTrigger::BUTTON_A), buttonATrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_A, true),
|
|
||||||
buttonBTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_B, true), buttonUpTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_UP | GuiTrigger::STICK_L_UP, true),
|
|
||||||
buttonDownTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_DOWN | GuiTrigger::STICK_L_DOWN, true), DPADButtons(0, 0) {
|
|
||||||
setImageTopBackground(background);
|
|
||||||
showValues = false;
|
|
||||||
bChanged = false;
|
|
||||||
bSelectedChanged = false;
|
|
||||||
opened = false;
|
|
||||||
topValueText.setFontSize(32);
|
|
||||||
topValueText.setAlignment(ALIGN_LEFT);
|
|
||||||
topValueText.setPosition(10, -7);
|
|
||||||
topValueButton.setLabel(&topValueText);
|
|
||||||
topValueButton.setTrigger(&touchTrigger);
|
|
||||||
topValueButton.setTrigger(&wpadTouchTrigger);
|
|
||||||
topValueButton.clicked.connect(this, &GuiSelectBox::OnTopValueClicked);
|
|
||||||
|
|
||||||
valuesFrame.setState(STATE_HIDDEN);
|
|
||||||
|
|
||||||
DPADButtons.setTrigger(&buttonBTrigger);
|
|
||||||
DPADButtons.setTrigger(&buttonATrigger);
|
|
||||||
DPADButtons.setTrigger(&buttonDownTrigger);
|
|
||||||
DPADButtons.setTrigger(&buttonUpTrigger);
|
|
||||||
DPADButtons.clicked.connect(this, &GuiSelectBox::OnDPADClick);
|
|
||||||
DPADButtons.setState(STATE_DISABLE_INPUT);
|
|
||||||
|
|
||||||
append(&DPADButtons);
|
|
||||||
append(&valuesFrame);
|
|
||||||
append(&topValueButton);
|
|
||||||
|
|
||||||
showValues = false;
|
|
||||||
bChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiSelectBox::setSize(float width, float height) {
|
|
||||||
GuiFrame::setSize(width, height);
|
|
||||||
topValueButton.setSize(width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiSelectBox::OnValueClicked(GuiButton *button, const GuiController *controller, GuiTrigger *trigger) {
|
|
||||||
for (uint32_t i = 0; i < valueButtons.size(); ++i) {
|
|
||||||
if (valueButtons[i].valueButton == button) {
|
|
||||||
selected = i;
|
|
||||||
SelectValue(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiSelectBox::SelectValue(uint32_t value) {
|
|
||||||
if (value < valueButtons.size()) {
|
|
||||||
const wchar_t *w_text = valueButtons[value].valueButtonText->getText();
|
|
||||||
std::wstring ws(w_text);
|
|
||||||
std::string text(ws.begin(), ws.end());
|
|
||||||
topValueText.setText(text.c_str());
|
|
||||||
|
|
||||||
std::string real_value = buttonToValue[valueButtons[value].valueButton];
|
|
||||||
if (real_value.compare(std::string()) == 0) { real_value = "<error>"; }
|
|
||||||
|
|
||||||
valueChanged(this, real_value);
|
|
||||||
ShowHideValues(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiSelectBox::OnTopValueClicked(GuiButton *button, const GuiController *controller, GuiTrigger *trigger) {
|
|
||||||
ShowHideValues(!showValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiSelectBox::ShowHideValues(bool showhide) {
|
|
||||||
showValues = showhide;
|
|
||||||
bChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiSelectBox::OnDPADClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger) {
|
|
||||||
if (opened == true) {
|
|
||||||
if (trigger == &buttonATrigger) {
|
|
||||||
//! do not auto launch when wiimote is pointing to screen and presses A
|
|
||||||
if ((controller->chan & (GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5)) && controller->data.validPointer) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SelectValue(selected);
|
|
||||||
} else if (trigger == &buttonBTrigger) {
|
|
||||||
if (button == &DPADButtons) {
|
|
||||||
ShowHideValues(false);
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
} else if (trigger == &buttonUpTrigger) {
|
|
||||||
if (selected > 0) { selected--; }
|
|
||||||
bSelectedChanged = true;
|
|
||||||
} else if (trigger == &buttonDownTrigger) {
|
|
||||||
selected++;
|
|
||||||
if (selected >= valueButtons.size()) { selected = valueButtons.size() - 1; }
|
|
||||||
bSelectedChanged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiSelectBox::Init(std::map<std::string, std::string> values, int32_t valueID) {
|
|
||||||
if ((uint32_t) valueID >= values.size()) {
|
|
||||||
valueID = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
selected = valueID;
|
|
||||||
bSelectedChanged = true;
|
|
||||||
|
|
||||||
DeleteValueData();
|
|
||||||
|
|
||||||
if (valueImageData == NULL || valueSelectedImageData == NULL || valueHighlightedImageData == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
valueButtons.resize(values.size());
|
|
||||||
|
|
||||||
int32_t i = 0;
|
|
||||||
float imgScale = 1.0f;
|
|
||||||
std::map<std::string, std::string>::iterator itr;
|
|
||||||
for (itr = values.begin(); itr != values.end(); itr++) {
|
|
||||||
if (i == valueID) {
|
|
||||||
topValueText.setText(itr->first.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
valueButtons[i].valueButtonImg = new GuiImage(valueImageData);
|
|
||||||
valueButtons[i].valueButtonCheckedImg = new GuiImage(valueSelectedImageData);
|
|
||||||
valueButtons[i].valueButtonHighlightedImg = new GuiImage(valueHighlightedImageData);
|
|
||||||
|
|
||||||
valueButtons[i].valueButton = new GuiButton(valueButtons[i].valueButtonImg->getWidth() * imgScale, valueButtons[i].valueButtonImg->getHeight() * imgScale);
|
|
||||||
valueButtons[i].valueButtonText = new GuiText(itr->first.c_str(), 32, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
|
|
||||||
|
|
||||||
valueButtons[i].valueButtonText->setMaxWidth(valueButtons[i].valueButtonImg->getWidth() * imgScale - 20.0f, GuiText::WRAP);
|
|
||||||
valueButtons[i].valueButtonText->setPosition(0, 0);
|
|
||||||
|
|
||||||
valueButtons[i].valueButtonImg->setScale(imgScale);
|
|
||||||
valueButtons[i].valueButtonCheckedImg->setScale(imgScale);
|
|
||||||
|
|
||||||
valueButtons[i].valueButton->setImage(valueButtons[i].valueButtonImg);
|
|
||||||
valueButtons[i].valueButton->setIconOver(valueButtons[i].valueButtonHighlightedImg);
|
|
||||||
valueButtons[i].valueButton->setTrigger(&touchTrigger);
|
|
||||||
valueButtons[i].valueButton->setTrigger(&wpadTouchTrigger);
|
|
||||||
valueButtons[i].valueButton->clicked.connect(this, &GuiSelectBox::OnValueClicked);
|
|
||||||
valueButtons[i].valueButton->setSoundClick(buttonClickSound);
|
|
||||||
valueButtons[i].valueButton->setLabel(valueButtons[i].valueButtonText);
|
|
||||||
|
|
||||||
//valueButtons[i].valueButton->setState(STATE_HIDDEN); //Wont get disabled soon enough
|
|
||||||
|
|
||||||
buttonToValue[valueButtons[i].valueButton] = itr->second;
|
|
||||||
|
|
||||||
float topHeight = 0;
|
|
||||||
if (topBackgroundImg != NULL) {
|
|
||||||
topHeight = topBackgroundImg->getHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t ypos = (((valueButtons[i].valueButtonImg->getHeight() * getScale()) * (i)) + (topHeight - 5) * getScale()) * -1.0f;
|
|
||||||
valueButtons[i].valueButton->setPosition(0, ypos);
|
|
||||||
valuesFrame.append(valueButtons[i].valueButton);
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Collapse the thing!
|
|
||||||
showValues = false;
|
|
||||||
bChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiSelectBox::DeleteValueData() {
|
|
||||||
for (uint32_t i = 0; i < valueButtons.size(); ++i) {
|
|
||||||
valuesFrame.remove(valueButtons[i].valueButton);
|
|
||||||
delete valueButtons[i].valueButtonImg;
|
|
||||||
delete valueButtons[i].valueButtonCheckedImg;
|
|
||||||
delete valueButtons[i].valueButtonHighlightedImg;
|
|
||||||
delete valueButtons[i].valueButton;
|
|
||||||
delete valueButtons[i].valueButtonText;
|
|
||||||
}
|
|
||||||
buttonToValue.clear();
|
|
||||||
valueButtons.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor for the GuiButton class.
|
|
||||||
*/
|
|
||||||
GuiSelectBox::~GuiSelectBox() {
|
|
||||||
DeleteValueData();
|
|
||||||
bChanged = false;
|
|
||||||
selected = 0;
|
|
||||||
showValues = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void GuiSelectBox::setState(int32_t s, int32_t c) {
|
|
||||||
GuiElement::setState(s, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiSelectBox::OnValueCloseEffectFinish(GuiElement *element) {
|
|
||||||
valuesFrame.effectFinished.disconnect(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
float GuiSelectBox::getTopValueHeight() {
|
|
||||||
if (topBackgroundImg == NULL) {
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
return topBackgroundImg->getHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
float GuiSelectBox::getTopValueWidth() {
|
|
||||||
if (topBackgroundImg == NULL) {
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
return topBackgroundImg->getWidth();
|
|
||||||
}
|
|
||||||
|
|
||||||
float GuiSelectBox::getHeight() {
|
|
||||||
return getTopValueHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
float GuiSelectBox::getWidth() {
|
|
||||||
return getTopValueWidth();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void GuiSelectBox::OnValueOpenEffectFinish(GuiElement *element) {
|
|
||||||
valuesFrame.effectFinished.disconnect(this);
|
|
||||||
opened = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiSelectBox::update(GuiController *c) {
|
|
||||||
if (bChanged) {
|
|
||||||
showhide(this, showValues);
|
|
||||||
if (showValues) {
|
|
||||||
for (uint32_t i = 0; i < valueButtons.size(); ++i) { //TODO: only set when it really changed
|
|
||||||
if (i == selected) {
|
|
||||||
valueButtons[i].valueButton->setImage(valueButtons[i].valueButtonCheckedImg);
|
|
||||||
} else {
|
|
||||||
valueButtons[i].valueButton->setImage(valueButtons[i].valueButtonImg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
valuesFrame.clearState(STATE_HIDDEN);
|
|
||||||
DPADButtons.clearState(STATE_DISABLE_INPUT);
|
|
||||||
valuesFrame.setEffect(EFFECT_FADE, 10, 255);
|
|
||||||
valuesFrame.effectFinished.connect(this, &GuiSelectBox::OnValueCloseEffectFinish);
|
|
||||||
} else {
|
|
||||||
opened = false;
|
|
||||||
valuesFrame.setState(STATE_HIDDEN);
|
|
||||||
DPADButtons.setState(STATE_DISABLE_INPUT);
|
|
||||||
valuesFrame.setEffect(EFFECT_FADE, -10, 0);
|
|
||||||
valuesFrame.effectFinished.connect(this, &GuiSelectBox::OnValueOpenEffectFinish);
|
|
||||||
}
|
|
||||||
|
|
||||||
bChanged = false;
|
|
||||||
}
|
|
||||||
if (bSelectedChanged) {
|
|
||||||
for (uint32_t i = 0; i < valueButtons.size(); ++i) {
|
|
||||||
if (i == selected) {
|
|
||||||
valueButtons[i].valueButton->setState(STATE_SELECTED);
|
|
||||||
} else {
|
|
||||||
valueButtons[i].valueButton->clearState(STATE_SELECTED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
topValueButton.setState(getState());
|
|
||||||
GuiFrame::update(c);
|
|
||||||
}
|
|
@ -1,139 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* Copyright (C) 2016 Maschell
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*
|
|
||||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
****************************************************************************/
|
|
||||||
#ifndef GUI_SELECTBOX_H_
|
|
||||||
#define GUI_SELECTBOX_H_
|
|
||||||
|
|
||||||
#include <gui/Gui.h>
|
|
||||||
#include <gui/GuiImage.h>
|
|
||||||
#include <gui/GuiImageData.h>
|
|
||||||
|
|
||||||
//!A simple CheckBox
|
|
||||||
class GuiSelectBox : public GuiFrame, public sigslot::has_slots<> {
|
|
||||||
public:
|
|
||||||
//!Constructor
|
|
||||||
//!\param checked Checked
|
|
||||||
GuiSelectBox(GuiImage *background, std::string caption, float width = 0.0f, float height = 0.0f, GuiFrame *parent = 0);
|
|
||||||
|
|
||||||
//!Destructor
|
|
||||||
virtual ~GuiSelectBox();
|
|
||||||
|
|
||||||
sigslot::signal2<GuiSelectBox *, std::string> valueChanged;
|
|
||||||
sigslot::signal2<GuiSelectBox *, bool> showhide;
|
|
||||||
|
|
||||||
void setImageTopBackground(GuiImage *img) {
|
|
||||||
topBackgroundImg = img;
|
|
||||||
topValueButton.setImage(img);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setImageTopHighlighted(GuiImage *img) {
|
|
||||||
topHighlightedImg = img;
|
|
||||||
topValueButton.setIconOver(img);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setImageValueBackground(GuiImageData *img) {
|
|
||||||
valueImageData = img;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setImageValueHighlighted(GuiImageData *img) {
|
|
||||||
valueHighlightedImageData = img;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setImageValueSelected(GuiImageData *img) {
|
|
||||||
valueSelectedImageData = img;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setSoundClick(GuiSound *snd) {
|
|
||||||
buttonClickSound = snd;
|
|
||||||
topValueButton.setSoundClick(snd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnTopValueClicked(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);
|
|
||||||
|
|
||||||
void Init(std::map<std::string, std::string> values, int32_t valueID);
|
|
||||||
|
|
||||||
void setState(int32_t s, int32_t c = -1);
|
|
||||||
|
|
||||||
virtual void setSize(float width, float height);
|
|
||||||
|
|
||||||
virtual float getTopValueHeight();
|
|
||||||
|
|
||||||
virtual float getTopValueWidth();
|
|
||||||
|
|
||||||
virtual float getHeight();
|
|
||||||
|
|
||||||
virtual float getWidth();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void DeleteValueData();
|
|
||||||
|
|
||||||
void update(GuiController *c);
|
|
||||||
|
|
||||||
void OnValueClicked(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);
|
|
||||||
|
|
||||||
void OnDPADClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);
|
|
||||||
|
|
||||||
void OnValueOpenEffectFinish(GuiElement *element);
|
|
||||||
|
|
||||||
void OnValueCloseEffectFinish(GuiElement *element);
|
|
||||||
|
|
||||||
void ShowHideValues(bool showhide);
|
|
||||||
|
|
||||||
void SelectValue(uint32_t value);
|
|
||||||
|
|
||||||
uint32_t selected;
|
|
||||||
bool bChanged;
|
|
||||||
bool bSelectedChanged;
|
|
||||||
bool showValues;
|
|
||||||
bool opened;
|
|
||||||
std::string captionText;
|
|
||||||
GuiFrame valuesFrame;
|
|
||||||
GuiImage *topBackgroundImg = NULL;
|
|
||||||
GuiImage *topHighlightedImg = NULL;
|
|
||||||
|
|
||||||
GuiButton topValueButton;
|
|
||||||
GuiImageData *valueImageData = NULL;
|
|
||||||
GuiImageData *valueSelectedImageData = NULL;
|
|
||||||
GuiImageData *valueHighlightedImageData = NULL;
|
|
||||||
GuiText topValueText;
|
|
||||||
|
|
||||||
GuiTrigger touchTrigger;
|
|
||||||
GuiTrigger wpadTouchTrigger;
|
|
||||||
|
|
||||||
GuiTrigger buttonATrigger;
|
|
||||||
GuiTrigger buttonBTrigger;
|
|
||||||
GuiTrigger buttonLeftTrigger;
|
|
||||||
GuiTrigger buttonRightTrigger;
|
|
||||||
GuiTrigger buttonUpTrigger;
|
|
||||||
GuiTrigger buttonDownTrigger;
|
|
||||||
|
|
||||||
GuiButton DPADButtons;
|
|
||||||
|
|
||||||
GuiSound *buttonClickSound;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
GuiImage *valueButtonImg;
|
|
||||||
GuiImage *valueButtonCheckedImg;
|
|
||||||
GuiImage *valueButtonHighlightedImg;
|
|
||||||
GuiButton *valueButton;
|
|
||||||
GuiText *valueButtonText;
|
|
||||||
} SelectBoxValueButton;
|
|
||||||
|
|
||||||
std::map<GuiButton *, std::string> buttonToValue;
|
|
||||||
std::vector<SelectBoxValueButton> valueButtons;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -16,18 +16,11 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#include <gui/GuiSound.h>
|
#include <gui/GuiSound.h>
|
||||||
#include <sounds/SoundHandler.hpp>
|
#include <sounds/SoundHandler.hpp>
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
GuiSound::GuiSound(const char *filepath) {
|
GuiSound::GuiSound(std::vector<uint8_t>&& snd) {
|
||||||
voice = -1;
|
voice = -1;
|
||||||
Load(filepath);
|
internalBuffer = std::move(snd);
|
||||||
}
|
|
||||||
|
|
||||||
GuiSound::GuiSound(const uint8_t *snd, int32_t length) {
|
|
||||||
voice = -1;
|
|
||||||
Load(snd, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GuiSound::~GuiSound() {
|
GuiSound::~GuiSound() {
|
||||||
@ -36,49 +29,21 @@ GuiSound::~GuiSound() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GuiSound::Load() {
|
||||||
bool GuiSound::Load(const char *filepath) {
|
|
||||||
if (voice >= 0) {
|
if (voice >= 0) {
|
||||||
SoundHandler::instance()->RemoveDecoder(voice);
|
SoundHandler::instance()->RemoveDecoder(voice);
|
||||||
voice = -1;
|
voice = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! find next free decoder
|
if (!internalBuffer.empty()) {
|
||||||
for (int32_t i = 0; i < MAX_DECODERS; i++) {
|
|
||||||
SoundDecoder *decoder = SoundHandler::instance()->getDecoder(i);
|
|
||||||
if (decoder == NULL) {
|
|
||||||
SoundHandler::instance()->AddDecoder(i, filepath);
|
|
||||||
decoder = SoundHandler::instance()->getDecoder(i);
|
|
||||||
if (decoder) {
|
|
||||||
voice = i;
|
|
||||||
SoundHandler::instance()->ThreadSignal();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (voice < 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GuiSound::Load(const uint8_t *snd, int32_t len) {
|
|
||||||
if (voice >= 0) {
|
|
||||||
SoundHandler::instance()->RemoveDecoder(voice);
|
|
||||||
voice = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!snd) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! find next free decoder
|
//! find next free decoder
|
||||||
for (int32_t i = 0; i < MAX_DECODERS; i++) {
|
for (int32_t i = 0; i < MAX_DECODERS; i++) {
|
||||||
SoundDecoder *decoder = SoundHandler::instance()->getDecoder(i);
|
SoundDecoder *decoder = SoundHandler::instance()->getDecoder(i);
|
||||||
if (decoder == NULL) {
|
if (decoder == nullptr) {
|
||||||
SoundHandler::instance()->AddDecoder(i, snd, len);
|
SoundHandler::instance()->AddDecoder(i, internalBuffer);
|
||||||
decoder = SoundHandler::instance()->getDecoder(i);
|
decoder = SoundHandler::instance()->getDecoder(i);
|
||||||
if (decoder) {
|
if (decoder) {
|
||||||
voice = i;
|
voice = i;
|
||||||
@ -147,7 +112,7 @@ void GuiSound::Resume() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GuiSound::IsPlaying() {
|
bool GuiSound::IsPlaying() const {
|
||||||
Voice *v = SoundHandler::instance()->getVoice(voice);
|
Voice *v = SoundHandler::instance()->getVoice(voice);
|
||||||
if (v) {
|
if (v) {
|
||||||
return v->getState() == Voice::STATE_PLAYING;
|
return v->getState() == Voice::STATE_PLAYING;
|
||||||
|
@ -18,25 +18,17 @@
|
|||||||
#define GUI_SOUND_H_
|
#define GUI_SOUND_H_
|
||||||
|
|
||||||
#include <gui/GuiElement.h>
|
#include <gui/GuiElement.h>
|
||||||
|
#include <memory>
|
||||||
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
//!Sound conversion and playback. A wrapper for other sound libraries - ASND, libmad, ltremor, etc
|
//!Sound conversion and playback. A wrapper for other sound libraries - ASND, libmad, ltremor, etc
|
||||||
class GuiSound : public GuiElement {
|
class GuiSound : public GuiElement {
|
||||||
public:
|
public:
|
||||||
//!Constructor
|
explicit GuiSound(std::vector<uint8_t>&& snd);
|
||||||
//!\param sound Pointer to the sound data
|
|
||||||
//!\param filesize Length of sound data
|
|
||||||
GuiSound(const char *filepath);
|
|
||||||
|
|
||||||
GuiSound(const uint8_t *sound, int32_t length);
|
|
||||||
|
|
||||||
//!Destructor
|
//!Destructor
|
||||||
virtual ~GuiSound();
|
~GuiSound() override;
|
||||||
|
|
||||||
//!Load a file and replace the old one
|
|
||||||
bool Load(const char *filepath);
|
|
||||||
|
|
||||||
//!Load a file and replace the old one
|
|
||||||
bool Load(const uint8_t *snd, int32_t len);
|
|
||||||
|
|
||||||
//!Start sound playback
|
//!Start sound playback
|
||||||
void Play();
|
void Play();
|
||||||
@ -52,7 +44,7 @@ public:
|
|||||||
|
|
||||||
//!Checks if the sound is currently playing
|
//!Checks if the sound is currently playing
|
||||||
//!\return true if sound is playing, false otherwise
|
//!\return true if sound is playing, false otherwise
|
||||||
bool IsPlaying();
|
[[nodiscard]] bool IsPlaying() const;
|
||||||
|
|
||||||
//!Rewind the music
|
//!Rewind the music
|
||||||
void Rewind();
|
void Rewind();
|
||||||
@ -66,6 +58,11 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
int32_t voice; //!< Currently assigned ASND voice channel
|
int32_t voice; //!< Currently assigned ASND voice channel
|
||||||
|
std::vector<uint8_t> internalBuffer;
|
||||||
|
|
||||||
|
private:
|
||||||
|
//!Load a file and replace the old one
|
||||||
|
bool Load();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,80 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* Copyright (C) 2016,2017 Maschell
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*
|
|
||||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
****************************************************************************/
|
|
||||||
#include <gui/GuiImage.h>
|
|
||||||
#include <gui/GuiImageData.h>
|
|
||||||
#include <gui/GuiSwitch.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for the GuiSwitch class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
GuiSwitch::GuiSwitch(GuiImage *background, bool checked, float w, float h)
|
|
||||||
: GuiToggle(checked, w, h) {
|
|
||||||
setImageBackground(background);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor for the GuiSwitch class.
|
|
||||||
*/
|
|
||||||
GuiSwitch::~GuiSwitch() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiSwitch::setImageBackground(GuiImage *img) {
|
|
||||||
backgroundImg = img;
|
|
||||||
if (img) {
|
|
||||||
img->setParent(this);
|
|
||||||
}
|
|
||||||
setImage(img);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiSwitch::setImageOn(GuiImage *img) {
|
|
||||||
onImg = img;
|
|
||||||
if (img) {
|
|
||||||
img->setParent(this);
|
|
||||||
img->setAlignment(ALIGN_RIGHT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiSwitch::setImageOff(GuiImage *img) {
|
|
||||||
offImg = img;
|
|
||||||
if (img) {
|
|
||||||
img->setParent(this);
|
|
||||||
img->setAlignment(ALIGN_LEFT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiSwitch::setImageHighlighted(GuiImage *img) {
|
|
||||||
highlightedImg = img;
|
|
||||||
setIconOver(img);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiSwitch::draw(CVideo *v) {
|
|
||||||
if (!this->isVisible()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GuiToggle::draw(v);
|
|
||||||
if (getValue()) {
|
|
||||||
if (onImg != NULL) {
|
|
||||||
onImg->draw(v);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (offImg != NULL) {
|
|
||||||
offImg->draw(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* Copyright (C) 2016,2017 Maschell
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*
|
|
||||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
****************************************************************************/
|
|
||||||
#ifndef GUI_SWTICH_H_
|
|
||||||
#define GUI_SWTICH_H_
|
|
||||||
|
|
||||||
#include <gui/GuiImage.h>
|
|
||||||
#include <gui/GuiImageData.h>
|
|
||||||
#include <gui/GuiToggle.h>
|
|
||||||
|
|
||||||
//!A simple switch
|
|
||||||
class GuiSwitch : public GuiToggle {
|
|
||||||
public:
|
|
||||||
//!Constructor
|
|
||||||
//!\param checked Checked
|
|
||||||
GuiSwitch(GuiImage *background, bool checked, float w = 0.0f, float h = 0.0f);
|
|
||||||
|
|
||||||
//!Destructor
|
|
||||||
virtual ~GuiSwitch();
|
|
||||||
|
|
||||||
void setImageBackground(GuiImage *img);
|
|
||||||
|
|
||||||
void setImageOn(GuiImage *img);
|
|
||||||
|
|
||||||
void setImageOff(GuiImage *img);
|
|
||||||
|
|
||||||
void setImageHighlighted(GuiImage *img);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
GuiImage *backgroundImg = NULL;
|
|
||||||
GuiImage *onImg = NULL;
|
|
||||||
GuiImage *offImg = NULL;
|
|
||||||
GuiImage *highlightedImg = NULL;
|
|
||||||
|
|
||||||
void draw(CVideo *v) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -247,7 +247,7 @@ void GuiText::setPresets(int32_t sz, const glm::vec4 &c, int32_t w, int32_t a) {
|
|||||||
presetAlignment = a;
|
presetAlignment = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiText::setPresetFont(FreeTypeGX *f) {
|
void GuiText::setPresetFont(std::shared_ptr<FreeTypeGX> f) {
|
||||||
presentFont = f;
|
presentFont = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ public:
|
|||||||
//!\param a Text alignment
|
//!\param a Text alignment
|
||||||
static void setPresets(int32_t sz, const glm::vec4 &c, int32_t w, int32_t a);
|
static void setPresets(int32_t sz, const glm::vec4 &c, int32_t w, int32_t a);
|
||||||
|
|
||||||
static void setPresetFont(FreeTypeGX *font);
|
static void setPresetFont(std::shared_ptr<FreeTypeGX> font);
|
||||||
|
|
||||||
//!Sets the font size
|
//!Sets the font size
|
||||||
//!\param s Font size
|
//!\param s Font size
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "game/GameList.h"
|
#include "GuiFrame.h"
|
||||||
|
#include <cstdint>
|
||||||
|
#include <game/GameList.h>
|
||||||
#include <gui/Gui.h>
|
#include <gui/Gui.h>
|
||||||
#include <gui/sigslot.h>
|
#include <gui/sigslot.h>
|
||||||
|
|
||||||
@ -8,11 +10,11 @@ class GuiTitleBrowser : public GuiFrame {
|
|||||||
public:
|
public:
|
||||||
GuiTitleBrowser(int32_t w, int32_t h, uint64_t GameIndex) : GuiFrame(w, h) {}
|
GuiTitleBrowser(int32_t w, int32_t h, uint64_t GameIndex) : GuiFrame(w, h) {}
|
||||||
|
|
||||||
virtual ~GuiTitleBrowser() {}
|
~GuiTitleBrowser() override = default;
|
||||||
|
|
||||||
virtual void setSelectedGame(uint64_t idx) = 0;
|
virtual void setSelectedGame(uint64_t idx) = 0;
|
||||||
|
|
||||||
virtual uint64_t getSelectedGame(void) = 0;
|
virtual uint64_t getSelectedGame() = 0;
|
||||||
|
|
||||||
virtual void OnGameTitleListUpdated(GameList *list) = 0;
|
virtual void OnGameTitleListUpdated(GameList *list) = 0;
|
||||||
|
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* Copyright (C) 2016 Maschell
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*
|
|
||||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
****************************************************************************/
|
|
||||||
#include <gui/GuiToggle.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for the GuiToggle class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
GuiToggle::GuiToggle(bool checked, float width, float height)
|
|
||||||
: GuiButton(width, height) {
|
|
||||||
bChanged = false;
|
|
||||||
selected = checked;
|
|
||||||
clicked.connect(this, &GuiToggle::OnToggleClick);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor for the GuiButton class.
|
|
||||||
*/
|
|
||||||
GuiToggle::~GuiToggle() {
|
|
||||||
bChanged = false;
|
|
||||||
selected = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiToggle::OnToggleClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger) {
|
|
||||||
if (!isStateSet(STATE_DISABLED | STATE_HIDDEN | STATE_DISABLE_INPUT)) {
|
|
||||||
if (selected) {
|
|
||||||
setUnchecked();
|
|
||||||
} else {
|
|
||||||
setChecked();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiToggle::update(GuiController *c) {
|
|
||||||
GuiButton::update(c);
|
|
||||||
}
|
|
@ -1,64 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* Copyright (C) 2016 Maschell
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*
|
|
||||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
****************************************************************************/
|
|
||||||
#ifndef GUI_TOGGLE_H_
|
|
||||||
#define GUI_TOGGLE_H_
|
|
||||||
|
|
||||||
#include <gui/GuiButton.h>
|
|
||||||
#include <gui/GuiFrame.h>
|
|
||||||
|
|
||||||
//!A simple CheckBox
|
|
||||||
class GuiToggle : public GuiButton, public sigslot::has_slots<> {
|
|
||||||
public:
|
|
||||||
//!Constructor
|
|
||||||
//!\param checked Checked
|
|
||||||
GuiToggle(bool checked, float width, float height);
|
|
||||||
|
|
||||||
//!Destructor
|
|
||||||
virtual ~GuiToggle();
|
|
||||||
|
|
||||||
void setValue(bool checked) {
|
|
||||||
if (selected != checked) {
|
|
||||||
selected = checked;
|
|
||||||
bChanged = true;
|
|
||||||
valueChanged(this, selected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setChecked() {
|
|
||||||
setValue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setUnchecked() {
|
|
||||||
setValue(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getValue() {
|
|
||||||
return selected;
|
|
||||||
}
|
|
||||||
|
|
||||||
sigslot::signal2<GuiToggle *, bool> valueChanged;
|
|
||||||
|
|
||||||
void OnToggleClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool selected;
|
|
||||||
bool bChanged;
|
|
||||||
|
|
||||||
void update(GuiController *c);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -45,83 +45,83 @@ void GuiTrigger::setTrigger(uint32_t ch, uint32_t btn) {
|
|||||||
btns = btn;
|
btns = btn;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GuiTrigger::left(const GuiController *controller) const {
|
bool GuiTrigger::left(const GuiController &controller) const {
|
||||||
if ((controller->chan & chan) == 0) {
|
if ((controller.chan & chan) == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ((controller->data.buttons_h | controller->data.buttons_d) & (BUTTON_LEFT | STICK_L_LEFT)) {
|
if ((controller.data.buttons_h | controller.data.buttons_d) & (BUTTON_LEFT | STICK_L_LEFT)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GuiTrigger::right(const GuiController *controller) const {
|
bool GuiTrigger::right(const GuiController &controller) const {
|
||||||
if ((controller->chan & chan) == 0) {
|
if ((controller.chan & chan) == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ((controller->data.buttons_h | controller->data.buttons_d) & (BUTTON_RIGHT | STICK_L_RIGHT)) {
|
if ((controller.data.buttons_h | controller.data.buttons_d) & (BUTTON_RIGHT | STICK_L_RIGHT)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GuiTrigger::up(const GuiController *controller) const {
|
bool GuiTrigger::up(const GuiController &controller) const {
|
||||||
if ((controller->chan & chan) == 0) {
|
if ((controller.chan & chan) == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ((controller->data.buttons_h | controller->data.buttons_d) & (BUTTON_UP | STICK_L_UP)) {
|
if ((controller.data.buttons_h | controller.data.buttons_d) & (BUTTON_UP | STICK_L_UP)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GuiTrigger::down(const GuiController *controller) const {
|
bool GuiTrigger::down(const GuiController &controller) const {
|
||||||
if ((controller->chan & chan) == 0) {
|
if ((controller.chan & chan) == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ((controller->data.buttons_h | controller->data.buttons_d) & (BUTTON_DOWN | STICK_L_DOWN)) {
|
if ((controller.data.buttons_h | controller.data.buttons_d) & (BUTTON_DOWN | STICK_L_DOWN)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t GuiTrigger::clicked(const GuiController *controller) const {
|
int32_t GuiTrigger::clicked(const GuiController &controller) const {
|
||||||
if ((controller->chan & chan) == 0) {
|
if ((controller.chan & chan) == 0) {
|
||||||
return CLICKED_NONE;
|
return CLICKED_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t bResult = CLICKED_NONE;
|
int32_t bResult = CLICKED_NONE;
|
||||||
|
|
||||||
if (controller->data.touched && controller->data.validPointer && (btns & VPAD_TOUCH) && !controller->lastData.touched) {
|
if (controller.data.touched && controller.data.validPointer && (btns & VPAD_TOUCH) && !controller.lastData.touched) {
|
||||||
bResult = CLICKED_TOUCH;
|
bResult = CLICKED_TOUCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (controller->data.buttons_d & btns) {
|
if (controller.data.buttons_d & btns) {
|
||||||
bResult = CLICKED_BUTTON;
|
bResult = CLICKED_BUTTON;
|
||||||
}
|
}
|
||||||
return bResult;
|
return bResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GuiTrigger::held(const GuiController *controller) const {
|
bool GuiTrigger::held(const GuiController &controller) const {
|
||||||
if ((controller->chan & chan) == 0) {
|
if ((controller.chan & chan) == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bResult = false;
|
bool bResult = false;
|
||||||
|
|
||||||
if (controller->data.touched && (btns & VPAD_TOUCH) && controller->data.validPointer && controller->lastData.touched && controller->lastData.validPointer) {
|
if (controller.data.touched && (btns & VPAD_TOUCH) && controller.data.validPointer && controller.lastData.touched && controller.lastData.validPointer) {
|
||||||
bResult = true;
|
bResult = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (controller->data.buttons_h & btns) {
|
if (controller.data.buttons_h & btns) {
|
||||||
bResult = true;
|
bResult = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return bResult;
|
return bResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GuiTrigger::released(const GuiController *controller) const {
|
bool GuiTrigger::released(const GuiController &controller) const {
|
||||||
if ((controller->chan & chan) == 0) {
|
if ((controller.chan & chan) == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,11 +131,11 @@ bool GuiTrigger::released(const GuiController *controller) const {
|
|||||||
|
|
||||||
bool bResult = false;
|
bool bResult = false;
|
||||||
|
|
||||||
if (!controller->data.touched && (btns & VPAD_TOUCH) && controller->lastData.touched && controller->lastData.validPointer) {
|
if (!controller.data.touched && (btns & VPAD_TOUCH) && controller.lastData.touched && controller.lastData.validPointer) {
|
||||||
bResult = true;
|
bResult = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (controller->data.buttons_r & btns) {
|
if (controller.data.buttons_r & btns) {
|
||||||
bResult = true;
|
bResult = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,31 +94,31 @@ public:
|
|||||||
bSelectionClickEverywhere = b;
|
bSelectionClickEverywhere = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isClickEverywhere() const {
|
[[nodiscard]] bool isClickEverywhere() const {
|
||||||
return bClickEverywhere;
|
return bClickEverywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isHoldEverywhere() const {
|
[[nodiscard]] bool isHoldEverywhere() const {
|
||||||
return bHoldEverywhere;
|
return bHoldEverywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSelectionClickEverywhere() const {
|
[[nodiscard]] bool isSelectionClickEverywhere() const {
|
||||||
return bSelectionClickEverywhere;
|
return bSelectionClickEverywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool left(const GuiController *controller) const;
|
[[nodiscard]] bool left(const GuiController &controller) const;
|
||||||
|
|
||||||
bool right(const GuiController *controller) const;
|
[[nodiscard]] bool right(const GuiController &controller) const;
|
||||||
|
|
||||||
bool up(const GuiController *controller) const;
|
[[nodiscard]] bool up(const GuiController &controller) const;
|
||||||
|
|
||||||
bool down(const GuiController *controller) const;
|
[[nodiscard]] bool down(const GuiController &controller) const;
|
||||||
|
|
||||||
int32_t clicked(const GuiController *controller) const;
|
[[nodiscard]] int32_t clicked(const GuiController &controller) const;
|
||||||
|
|
||||||
bool held(const GuiController *controller) const;
|
[[nodiscard]] bool held(const GuiController &controller) const;
|
||||||
|
|
||||||
bool released(const GuiController *controller) const;
|
[[nodiscard]] bool released(const GuiController &controller) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t chan;
|
uint32_t chan;
|
||||||
|
@ -1,45 +1,42 @@
|
|||||||
#include "GameSplashScreen.h"
|
#include "GameSplashScreen.h"
|
||||||
#include "common/common.h"
|
|
||||||
#include "fs/FSUtils.h"
|
#include "fs/FSUtils.h"
|
||||||
#include "utils/AsyncExecutor.h"
|
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
|
#include "utils/utils.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <nn/acp/title.h>
|
||||||
|
|
||||||
GameSplashScreen::GameSplashScreen(int32_t w, int32_t h, gameInfo *info, bool onTV) : GuiFrame(w, h),
|
GameSplashScreen::GameSplashScreen(int32_t w, int32_t h, gameInfo *info, bool onTV) : GuiFrame(w, h),
|
||||||
bgImageColor(w, h, (GX2Color){0, 0, 0, 0}) {
|
bgImageColor(w, h, (GX2Color){0, 0, 0, 0}) {
|
||||||
bgImageColor.setImageColor((GX2Color){
|
bgImageColor.setImageColor((GX2Color){79, 153, 239, 255}, 0);
|
||||||
79, 153, 239, 255},
|
bgImageColor.setImageColor((GX2Color){79, 153, 239, 255}, 1);
|
||||||
0);
|
bgImageColor.setImageColor((GX2Color){59, 159, 223, 255}, 2);
|
||||||
bgImageColor.setImageColor((GX2Color){
|
bgImageColor.setImageColor((GX2Color){59, 159, 223, 255}, 3);
|
||||||
79, 153, 239, 255},
|
|
||||||
1);
|
|
||||||
bgImageColor.setImageColor((GX2Color){
|
|
||||||
59, 159, 223, 255},
|
|
||||||
2);
|
|
||||||
bgImageColor.setImageColor((GX2Color){
|
|
||||||
59, 159, 223, 255},
|
|
||||||
3);
|
|
||||||
append(&bgImageColor);
|
append(&bgImageColor);
|
||||||
this->onTV = onTV;
|
this->onTV = onTV;
|
||||||
this->info = info;
|
this->info = info;
|
||||||
|
|
||||||
std::string filepath = "fs:" + info->gamePath + META_PATH + "/bootDRCTex.tga";
|
this->effectFinished.connect(this, &GameSplashScreen::OnSplashScreenFadeInDone);
|
||||||
if (onTV) {
|
|
||||||
filepath = "fs:" + info->gamePath + META_PATH + "/bootTVTex.tga";
|
|
||||||
|
char metaDir[256] = {};
|
||||||
|
auto res = ACPGetTitleMetaDir(info->titleId, metaDir, sizeof(metaDir) - 1);
|
||||||
|
if (res != ACP_RESULT_SUCCESS) {
|
||||||
|
DEBUG_FUNCTION_LINE_WARN("Failed to find assets");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
uint8_t *buffer = nullptr;
|
|
||||||
uint32_t bufferSize = 0;
|
std::string filepath = onTV ? std::string(metaDir).append("/bootTvTex.tga") : std::string(metaDir).append("/bootDrcTex.tga");
|
||||||
int iResult = FSUtils::LoadFileToMem(filepath.c_str(), &buffer, &bufferSize);
|
|
||||||
if (iResult > 0) {
|
std::vector<uint8_t> buffer;
|
||||||
splashScreenData = new GuiImageData(buffer, bufferSize, GX2_TEX_CLAMP_MODE_MIRROR);
|
if (Utils::LoadFileIntoBuffer(filepath, buffer)) {
|
||||||
|
splashScreenData = std::make_unique<GuiImageData>(buffer, GX2_TEX_CLAMP_MODE_MIRROR);
|
||||||
if (splashScreenData) {
|
if (splashScreenData) {
|
||||||
bgImageColor.setImageData(splashScreenData);
|
bgImageColor.setImageData(std::move(splashScreenData));
|
||||||
bgImageColor.setScale(((float) h) / splashScreenData->getHeight());
|
bgImageColor.setScale(((float) h) / splashScreenData->getHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
//! free original image buffer which is converted to texture now and not needed anymore
|
//! free original image buffer which is converted to texture now and not needed anymore
|
||||||
free(buffer);
|
|
||||||
}
|
}
|
||||||
this->effectFinished.connect(this, &GameSplashScreen::OnSplashScreenFadeInDone);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameSplashScreen::OnSplashScreenFadeInDone(GuiElement *element) {
|
void GameSplashScreen::OnSplashScreenFadeInDone(GuiElement *element) {
|
||||||
@ -56,9 +53,4 @@ void GameSplashScreen::draw(CVideo *v) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GameSplashScreen::~GameSplashScreen() {
|
GameSplashScreen::~GameSplashScreen() = default;
|
||||||
DEBUG_FUNCTION_LINE("Destroy me");
|
|
||||||
if (splashScreenData) {
|
|
||||||
AsyncExecutor::pushForDelete(splashScreenData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -18,9 +18,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
GuiImage bgImageColor;
|
GuiImage bgImageColor;
|
||||||
GuiImageData *splashScreenData = nullptr;
|
std::unique_ptr<GuiImageData> splashScreenData = nullptr;
|
||||||
gameInfo *info = nullptr;
|
gameInfo *info = nullptr;
|
||||||
bool launchGame = false;
|
bool launchGame = false;
|
||||||
uint32_t frameCounter = 0;
|
uint32_t frameCounter = 0;
|
||||||
bool onTV = false;
|
bool onTV = false;
|
||||||
};
|
};
|
||||||
|
46
src/menu/MainDrcButtonsFrame.cpp
Normal file
46
src/menu/MainDrcButtonsFrame.cpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
|
||||||
|
#include "MainDrcButtonsFrame.h"
|
||||||
|
|
||||||
|
MainDrcButtonsFrame::MainDrcButtonsFrame(int32_t w, int32_t h)
|
||||||
|
: GuiFrame(w, h),
|
||||||
|
buttonClickSound(Resources::GetSound("settings_click_2.mp3")),
|
||||||
|
screenSwitchSound(Resources::GetSound("screenSwitchSound.mp3")),
|
||||||
|
switchIcon(std::make_unique<GuiImage>(Resources::GetImageData("layoutSwitchButton.png"))),
|
||||||
|
settingsIcon(std::make_unique<GuiImage>(Resources::GetImageData("settingsButton->png"))),
|
||||||
|
touchTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::VPAD_TOUCH),
|
||||||
|
wpadTouchTrigger(GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5, GuiTrigger::BUTTON_A),
|
||||||
|
settingsTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_ZL, true), switchLayoutTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_ZR, true),
|
||||||
|
plusTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_PLUS, true) {
|
||||||
|
|
||||||
|
|
||||||
|
auto settingsButton = std::make_unique<GuiButton>(settingsIcon->getWidth(), settingsIcon->getHeight());
|
||||||
|
settingsButton->setClickable(true);
|
||||||
|
settingsButton->setImage(settingsIcon);
|
||||||
|
settingsButton->setTrigger(&touchTrigger);
|
||||||
|
settingsButton->setTrigger(&wpadTouchTrigger);
|
||||||
|
settingsButton->setTrigger(&settingsTrigger);
|
||||||
|
settingsButton->setAlignment(ALIGN_LEFT | ALIGN_BOTTOM);
|
||||||
|
settingsButton->setSoundClick(std::move(buttonClickSound));
|
||||||
|
settingsButton->setEffectGrow();
|
||||||
|
settingsButton->clicked.connect(this, &MainDrcButtonsFrame::OnSettingsButtonClick);
|
||||||
|
append(std::move(settingsButton));
|
||||||
|
|
||||||
|
auto switchLayoutButton = std::make_unique<GuiButton>(switchIcon->getWidth(), switchIcon->getHeight());
|
||||||
|
switchLayoutButton->setClickable(true);
|
||||||
|
switchLayoutButton->setImage(switchIcon);
|
||||||
|
switchLayoutButton->setTrigger(&touchTrigger);
|
||||||
|
switchLayoutButton->setTrigger(&wpadTouchTrigger);
|
||||||
|
switchLayoutButton->setTrigger(&switchLayoutTrigger);
|
||||||
|
switchLayoutButton->setAlignment(ALIGN_RIGHT | ALIGN_BOTTOM);
|
||||||
|
switchLayoutButton->setSoundClick(std::move(screenSwitchSound));
|
||||||
|
switchLayoutButton->setEffectGrow();
|
||||||
|
switchLayoutButton->clicked.connect(this, &MainDrcButtonsFrame::OnLayoutSwithClick);
|
||||||
|
append(std::move(switchLayoutButton));
|
||||||
|
|
||||||
|
auto gameListFilterButton = std::make_unique<GuiButton>(w, h);
|
||||||
|
gameListFilterButton->setClickable(true);
|
||||||
|
gameListFilterButton->setSoundClick(std::move(buttonClickSound));
|
||||||
|
gameListFilterButton->setTrigger(&plusTrigger);
|
||||||
|
gameListFilterButton->clicked.connect(this, &MainDrcButtonsFrame::OnGameListFilterButtonClicked);
|
||||||
|
append(std::move(gameListFilterButton));
|
||||||
|
}
|
@ -22,48 +22,9 @@
|
|||||||
|
|
||||||
class MainDrcButtonsFrame : public GuiFrame, public sigslot::has_slots<> {
|
class MainDrcButtonsFrame : public GuiFrame, public sigslot::has_slots<> {
|
||||||
public:
|
public:
|
||||||
MainDrcButtonsFrame(int32_t w, int32_t h)
|
MainDrcButtonsFrame(int32_t w, int32_t h);
|
||||||
: GuiFrame(w, h), buttonClickSound(Resources::GetSound("settings_click_2.mp3")), screenSwitchSound(Resources::GetSound("screenSwitchSound.mp3")),
|
|
||||||
switchIconData(Resources::GetImageData("layoutSwitchButton.png")), settingsIconData(Resources::GetImageData("settingsButton.png")), switchIcon(switchIconData),
|
|
||||||
settingsIcon(settingsIconData), switchLayoutButton(switchIcon.getWidth(), switchIcon.getHeight()), settingsButton(settingsIcon.getWidth(), settingsIcon.getHeight()),
|
|
||||||
gameListFilterButton(w, h), touchTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::VPAD_TOUCH),
|
|
||||||
wpadTouchTrigger(GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5, GuiTrigger::BUTTON_A),
|
|
||||||
settingsTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_ZL, true), switchLayoutTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_ZR, true),
|
|
||||||
plusTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_PLUS, true) {
|
|
||||||
settingsButton.setClickable(true);
|
|
||||||
settingsButton.setImage(&settingsIcon);
|
|
||||||
settingsButton.setTrigger(&touchTrigger);
|
|
||||||
settingsButton.setTrigger(&wpadTouchTrigger);
|
|
||||||
settingsButton.setTrigger(&settingsTrigger);
|
|
||||||
settingsButton.setAlignment(ALIGN_LEFT | ALIGN_BOTTOM);
|
|
||||||
settingsButton.setSoundClick(buttonClickSound);
|
|
||||||
settingsButton.setEffectGrow();
|
|
||||||
settingsButton.clicked.connect(this, &MainDrcButtonsFrame::OnSettingsButtonClick);
|
|
||||||
append(&settingsButton);
|
|
||||||
|
|
||||||
switchLayoutButton.setClickable(true);
|
~MainDrcButtonsFrame() override {
|
||||||
switchLayoutButton.setImage(&switchIcon);
|
|
||||||
switchLayoutButton.setTrigger(&touchTrigger);
|
|
||||||
switchLayoutButton.setTrigger(&wpadTouchTrigger);
|
|
||||||
switchLayoutButton.setTrigger(&switchLayoutTrigger);
|
|
||||||
switchLayoutButton.setAlignment(ALIGN_RIGHT | ALIGN_BOTTOM);
|
|
||||||
switchLayoutButton.setSoundClick(screenSwitchSound);
|
|
||||||
switchLayoutButton.setEffectGrow();
|
|
||||||
switchLayoutButton.clicked.connect(this, &MainDrcButtonsFrame::OnLayoutSwithClick);
|
|
||||||
append(&switchLayoutButton);
|
|
||||||
|
|
||||||
gameListFilterButton.setClickable(true);
|
|
||||||
gameListFilterButton.setSoundClick(buttonClickSound);
|
|
||||||
gameListFilterButton.setTrigger(&plusTrigger);
|
|
||||||
gameListFilterButton.clicked.connect(this, &MainDrcButtonsFrame::OnGameListFilterButtonClicked);
|
|
||||||
append(&gameListFilterButton);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~MainDrcButtonsFrame() {
|
|
||||||
Resources::RemoveImageData(switchIconData);
|
|
||||||
Resources::RemoveImageData(settingsIconData);
|
|
||||||
Resources::RemoveSound(buttonClickSound);
|
|
||||||
Resources::RemoveSound(screenSwitchSound);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sigslot::signal1<GuiElement *> settingsButtonClicked;
|
sigslot::signal1<GuiElement *> settingsButtonClicked;
|
||||||
@ -83,16 +44,10 @@ private:
|
|||||||
gameListFilterClicked(this);
|
gameListFilterClicked(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
GuiSound *buttonClickSound;
|
std::unique_ptr<GuiSound> buttonClickSound;
|
||||||
GuiSound *screenSwitchSound;
|
std::unique_ptr<GuiSound> screenSwitchSound;
|
||||||
GuiImageData *switchIconData;
|
std::shared_ptr<GuiImage> switchIcon;
|
||||||
GuiImageData *settingsIconData;
|
std::shared_ptr<GuiImage> settingsIcon;
|
||||||
GuiImage switchIcon;
|
|
||||||
GuiImage settingsIcon;
|
|
||||||
|
|
||||||
GuiButton switchLayoutButton;
|
|
||||||
GuiButton settingsButton;
|
|
||||||
GuiButton gameListFilterButton;
|
|
||||||
|
|
||||||
GuiTrigger touchTrigger;
|
GuiTrigger touchTrigger;
|
||||||
GuiTrigger wpadTouchTrigger;
|
GuiTrigger wpadTouchTrigger;
|
||||||
|
@ -23,18 +23,15 @@
|
|||||||
#include "gui/GuiIconGrid.h"
|
#include "gui/GuiIconGrid.h"
|
||||||
#include "gui/GuiTitleBrowser.h"
|
#include "gui/GuiTitleBrowser.h"
|
||||||
#include "resources/Resources.h"
|
#include "resources/Resources.h"
|
||||||
#include "utils/AsyncExecutor.h"
|
|
||||||
#include <coreinit/title.h>
|
#include <coreinit/title.h>
|
||||||
#include <future>
|
|
||||||
#include <nn/acp/title.h>
|
#include <nn/acp/title.h>
|
||||||
#include <sysapp/launch.h>
|
#include <sysapp/launch.h>
|
||||||
|
|
||||||
MainWindow::MainWindow(int32_t w, int32_t h)
|
MainWindow::MainWindow(int32_t w, int32_t h)
|
||||||
: width(w), height(h), gameClickSound(Resources::GetSound("game_click.mp3")), mainSwitchButtonFrame(nullptr), currentTvFrame(nullptr), currentDrcFrame(nullptr) {
|
: width(w), height(h), mainSwitchButtonFrame(nullptr), currentTvFrame(nullptr), currentDrcFrame(nullptr) {
|
||||||
for (int32_t i = 0; i < 4; i++) {
|
for (int32_t i = 0; i < 4; i++) {
|
||||||
std::string filename = StringTools::strfmt("player%i_point.png", i + 1);
|
std::string filename = StringTools::strfmt("player%i_point.png", i + 1);
|
||||||
pointerImgData[i] = Resources::GetImageData(filename.c_str());
|
pointerImg[i] = std::make_unique<GuiImage>(Resources::GetImageData(filename));
|
||||||
pointerImg[i] = new GuiImage(pointerImgData[i]);
|
|
||||||
pointerImg[i]->setScale(1.5f);
|
pointerImg[i]->setScale(1.5f);
|
||||||
pointerValid[i] = false;
|
pointerValid[i] = false;
|
||||||
}
|
}
|
||||||
@ -42,27 +39,13 @@ MainWindow::MainWindow(int32_t w, int32_t h)
|
|||||||
gameList.titleListChanged.connect(this, &MainWindow::OnGameTitleListChanged);
|
gameList.titleListChanged.connect(this, &MainWindow::OnGameTitleListChanged);
|
||||||
gameList.titleUpdated.connect(this, &MainWindow::OnGameTitleUpdated);
|
gameList.titleUpdated.connect(this, &MainWindow::OnGameTitleUpdated);
|
||||||
gameList.titleAdded.connect(this, &MainWindow::OnGameTitleAdded);
|
gameList.titleAdded.connect(this, &MainWindow::OnGameTitleAdded);
|
||||||
AsyncExecutor::execute([&] { gameList.load(); });
|
gameList.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow() {
|
MainWindow::~MainWindow() {
|
||||||
gameList.titleListChanged.disconnect(this);
|
gameList.titleListChanged.disconnect(this);
|
||||||
gameList.titleUpdated.disconnect(this);
|
gameList.titleUpdated.disconnect(this);
|
||||||
gameList.titleAdded.disconnect(this);
|
gameList.titleAdded.disconnect(this);
|
||||||
while (!tvElements.empty()) {
|
|
||||||
delete tvElements[0];
|
|
||||||
remove(tvElements[0]);
|
|
||||||
}
|
|
||||||
while (!drcElements.empty()) {
|
|
||||||
delete drcElements[0];
|
|
||||||
remove(drcElements[0]);
|
|
||||||
}
|
|
||||||
for (int32_t i = 0; i < 4; i++) {
|
|
||||||
delete pointerImg[i];
|
|
||||||
Resources::RemoveImageData(pointerImgData[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Resources::RemoveSound(gameClickSound);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::updateEffects() {
|
void MainWindow::updateEffects() {
|
||||||
@ -141,11 +124,11 @@ void MainWindow::OnGameTitleAdded(gameInfo *info) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::update(GuiController *controller) {
|
void MainWindow::update(const GuiController &controller) {
|
||||||
//! dont read behind the initial elements in case one was added
|
//! dont read behind the initial elements in case one was added
|
||||||
//uint32_t tvSize = tvElements.size();
|
//uint32_t tvSize = tvElements.size();
|
||||||
|
|
||||||
if (controller->chan & GuiTrigger::CHANNEL_1) {
|
if (controller.chan & GuiTrigger::CHANNEL_1) {
|
||||||
uint32_t drcSize = drcElements.size();
|
uint32_t drcSize = drcElements.size();
|
||||||
|
|
||||||
for (uint32_t i = 0; (i < drcSize) && (i < drcElements.size()); ++i) {
|
for (uint32_t i = 0; (i < drcSize) && (i < drcElements.size()); ++i) {
|
||||||
@ -159,34 +142,19 @@ void MainWindow::update(GuiController *controller) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// //! only update TV elements that are not updated yet because they are on DRC
|
if (controller.chanIdx >= 1 && controller.chanIdx <= 4 && controller.data.validPointer) {
|
||||||
// for(uint32_t i = 0; (i < tvSize) && (i < tvElements.size()); ++i)
|
int32_t wpadIdx = controller.chanIdx - 1;
|
||||||
// {
|
float posX = controller.data.x;
|
||||||
// uint32_t n;
|
float posY = controller.data.y;
|
||||||
// for(n = 0; (n < drcSize) && (n < drcElements.size()); n++)
|
|
||||||
// {
|
|
||||||
// if(tvElements[i] == drcElements[n])
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// if(n == drcElements.size())
|
|
||||||
// {
|
|
||||||
// tvElements[i]->update(controller);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (controller->chanIdx >= 1 && controller->chanIdx <= 4 && controller->data.validPointer) {
|
|
||||||
int32_t wpadIdx = controller->chanIdx - 1;
|
|
||||||
float posX = controller->data.x;
|
|
||||||
float posY = controller->data.y;
|
|
||||||
pointerImg[wpadIdx]->setPosition(posX, posY);
|
pointerImg[wpadIdx]->setPosition(posX, posY);
|
||||||
pointerImg[wpadIdx]->setAngle(controller->data.pointerAngle);
|
pointerImg[wpadIdx]->setAngle(controller.data.pointerAngle);
|
||||||
pointerValid[wpadIdx] = true;
|
pointerValid[wpadIdx] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::drawDrc(CVideo *video) {
|
void MainWindow::drawDrc(const CVideo &video) {
|
||||||
for (uint32_t i = 0; i < drcElements.size(); ++i) {
|
for (auto &drcElement : drcElements) {
|
||||||
drcElements[i]->draw(video);
|
drcElement->draw(video);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int32_t i = 0; i < 4; i++) {
|
for (int32_t i = 0; i < 4; i++) {
|
||||||
@ -202,9 +170,9 @@ void MainWindow::drawDrc(CVideo *video) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::drawTv(CVideo *video) {
|
void MainWindow::drawTv(const CVideo &video) {
|
||||||
for (uint32_t i = 0; i < tvElements.size(); ++i) {
|
for (auto &tvElement : tvElements) {
|
||||||
tvElements[i]->draw(video);
|
tvElement->draw(video);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int32_t i = 0; i < 4; i++) {
|
for (int32_t i = 0; i < 4; i++) {
|
||||||
@ -219,7 +187,7 @@ void MainWindow::drawTv(CVideo *video) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::SetupMainView() {
|
void MainWindow::SetupMainView() {
|
||||||
currentTvFrame = new GuiIconGrid(width, height, 0, true);
|
currentTvFrame = std::make_unique<GuiIconGrid>(width, height, 0, true);
|
||||||
|
|
||||||
currentTvFrame->setEffect(EFFECT_FADE, 10, 255);
|
currentTvFrame->setEffect(EFFECT_FADE, 10, 255);
|
||||||
currentTvFrame->setState(GuiElement::STATE_DISABLED);
|
currentTvFrame->setState(GuiElement::STATE_DISABLED);
|
||||||
@ -227,7 +195,7 @@ void MainWindow::SetupMainView() {
|
|||||||
|
|
||||||
appendTv(currentTvFrame);
|
appendTv(currentTvFrame);
|
||||||
|
|
||||||
currentDrcFrame = new GuiIconGrid(width, height, 0, false);
|
currentDrcFrame = std::make_unique<GuiIconGrid>(width, height, 0, false);
|
||||||
currentDrcFrame->setEffect(EFFECT_FADE, 10, 255);
|
currentDrcFrame->setEffect(EFFECT_FADE, 10, 255);
|
||||||
currentDrcFrame->setState(GuiElement::STATE_DISABLED);
|
currentDrcFrame->setState(GuiElement::STATE_DISABLED);
|
||||||
currentDrcFrame->effectFinished.connect(this, &MainWindow::OnOpenEffectFinish);
|
currentDrcFrame->effectFinished.connect(this, &MainWindow::OnOpenEffectFinish);
|
||||||
@ -253,7 +221,7 @@ void MainWindow::SetupMainView() {
|
|||||||
currentDrcFrame->gameSelectionChanged.connect(this, &MainWindow::OnGameSelectionChange);
|
currentDrcFrame->gameSelectionChanged.connect(this, &MainWindow::OnGameSelectionChange);
|
||||||
currentDrcFrame->gameLaunchClicked.connect(this, &MainWindow::OnGameLaunchSplashScreen);
|
currentDrcFrame->gameLaunchClicked.connect(this, &MainWindow::OnGameLaunchSplashScreen);
|
||||||
|
|
||||||
mainSwitchButtonFrame = new MainDrcButtonsFrame(width, height);
|
mainSwitchButtonFrame = std::make_unique<MainDrcButtonsFrame>(width, height);
|
||||||
mainSwitchButtonFrame->settingsButtonClicked.connect(this, &MainWindow::OnSettingsButtonClicked);
|
mainSwitchButtonFrame->settingsButtonClicked.connect(this, &MainWindow::OnSettingsButtonClicked);
|
||||||
mainSwitchButtonFrame->layoutSwitchClicked.connect(this, &MainWindow::OnLayoutSwitchClicked);
|
mainSwitchButtonFrame->layoutSwitchClicked.connect(this, &MainWindow::OnLayoutSwitchClicked);
|
||||||
mainSwitchButtonFrame->gameListFilterClicked.connect(this, &MainWindow::OnGameListFilterButtonClicked);
|
mainSwitchButtonFrame->gameListFilterClicked.connect(this, &MainWindow::OnGameListFilterButtonClicked);
|
||||||
@ -307,12 +275,10 @@ void MainWindow::OnLayoutSwitchEffectFinish(GuiElement *element) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
element->effectFinished.disconnect(this);
|
element->effectFinished.disconnect(this);
|
||||||
remove(currentDrcFrame);
|
removeByPtr(currentDrcFrame.get());
|
||||||
remove(currentTvFrame);
|
removeByPtr(currentTvFrame.get());
|
||||||
|
|
||||||
GuiTitleBrowser *tmpElement = currentDrcFrame;
|
std::swap(currentDrcFrame, currentTvFrame);
|
||||||
currentDrcFrame = currentTvFrame;
|
|
||||||
currentTvFrame = tmpElement;
|
|
||||||
|
|
||||||
appendTv(currentTvFrame);
|
appendTv(currentTvFrame);
|
||||||
appendDrc(currentDrcFrame);
|
appendDrc(currentDrcFrame);
|
||||||
@ -346,10 +312,8 @@ void MainWindow::OnOpenEffectFinish(GuiElement *element) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::OnCloseEffectFinish(GuiElement *element) {
|
void MainWindow::OnCloseEffectFinish(GuiElement *element) {
|
||||||
DEBUG_FUNCTION_LINE("Remove %08X", element);
|
|
||||||
//! remove element from draw list and push to delete queue
|
//! remove element from draw list and push to delete queue
|
||||||
remove(element);
|
removeByPtr(element);
|
||||||
AsyncExecutor::pushForDelete(element);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::OnSettingsButtonClicked(GuiElement *element) {
|
void MainWindow::OnSettingsButtonClicked(GuiElement *element) {
|
||||||
@ -359,30 +323,29 @@ void MainWindow::OnGameSelectionChange(GuiTitleBrowser *element, uint64_t select
|
|||||||
if (!currentDrcFrame || !currentTvFrame)
|
if (!currentDrcFrame || !currentTvFrame)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (element == currentDrcFrame && currentDrcFrame != currentTvFrame) {
|
if (element == currentDrcFrame.get() && currentDrcFrame != currentTvFrame) {
|
||||||
currentTvFrame->setSelectedGame(selectedIdx);
|
currentTvFrame->setSelectedGame(selectedIdx);
|
||||||
} else if (element == currentTvFrame && currentDrcFrame != currentTvFrame) {
|
} else if (element == currentTvFrame.get() && currentDrcFrame != currentTvFrame) {
|
||||||
currentDrcFrame->setSelectedGame(selectedIdx);
|
currentDrcFrame->setSelectedGame(selectedIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::OnGameLaunchSplashScreen(GuiTitleBrowser *element, uint64_t titleID) {
|
void MainWindow::OnGameLaunchSplashScreen(GuiTitleBrowser *element, uint64_t titleID) {
|
||||||
DEBUG_FUNCTION_LINE("");
|
|
||||||
gameInfo *info = gameList.getGameInfo(titleID);
|
gameInfo *info = gameList.getGameInfo(titleID);
|
||||||
if (info != nullptr) {
|
if (info != nullptr) {
|
||||||
auto *splashScreenDRC = new GameSplashScreen(width, height, info, false);
|
auto splashScreenDRC = std::make_unique<GameSplashScreen>(width, height, info, false);
|
||||||
splashScreenDRC->setEffect(EFFECT_FADE, 15, 255);
|
splashScreenDRC->setEffect(EFFECT_FADE, 15, 255);
|
||||||
splashScreenDRC->setState(GuiElement::STATE_DISABLED);
|
splashScreenDRC->setState(GuiElement::STATE_DISABLED);
|
||||||
splashScreenDRC->effectFinished.connect(this, &MainWindow::OnOpenEffectFinish);
|
splashScreenDRC->effectFinished.connect(this, &MainWindow::OnOpenEffectFinish);
|
||||||
splashScreenDRC->gameGameSplashScreenFinished.connect(this, &MainWindow::OnGameLaunchSplashScreenFinished);
|
splashScreenDRC->gameGameSplashScreenFinished.connect(this, &MainWindow::OnGameLaunchSplashScreenFinished);
|
||||||
appendDrc(splashScreenDRC);
|
appendDrc(std::move(splashScreenDRC));
|
||||||
|
|
||||||
auto *splashScreenTV = new GameSplashScreen(width, height, info, true);
|
auto splashScreenTV = std::make_unique<GameSplashScreen>(width, height, info, true);
|
||||||
splashScreenTV->setEffect(EFFECT_FADE, 15, 255);
|
splashScreenTV->setEffect(EFFECT_FADE, 15, 255);
|
||||||
splashScreenTV->setState(GuiElement::STATE_DISABLED);
|
splashScreenTV->setState(GuiElement::STATE_DISABLED);
|
||||||
splashScreenTV->effectFinished.connect(this, &MainWindow::OnOpenEffectFinish);
|
splashScreenTV->effectFinished.connect(this, &MainWindow::OnOpenEffectFinish);
|
||||||
splashScreenTV->gameGameSplashScreenFinished.connect(this, &MainWindow::OnGameLaunchSplashScreenFinished);
|
splashScreenTV->gameGameSplashScreenFinished.connect(this, &MainWindow::OnGameLaunchSplashScreenFinished);
|
||||||
appendTv(splashScreenTV);
|
appendTv(std::move(splashScreenTV));
|
||||||
} else {
|
} else {
|
||||||
DEBUG_FUNCTION_LINE("Failed to find gameInfo for titleId %016llX", titleID);
|
DEBUG_FUNCTION_LINE("Failed to find gameInfo for titleId %016llX", titleID);
|
||||||
}
|
}
|
||||||
|
@ -33,69 +33,69 @@ public:
|
|||||||
|
|
||||||
virtual ~MainWindow();
|
virtual ~MainWindow();
|
||||||
|
|
||||||
void appendTv(GuiElement *e) {
|
void appendTv(std::shared_ptr<GuiElement> e) {
|
||||||
if (!e)
|
if (!e)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
removeTv(e);
|
removeTvByPtr(e.get());
|
||||||
tvElements.push_back(e);
|
tvElements.push_back(std::move(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
void appendDrc(GuiElement *e) {
|
void appendDrc(std::shared_ptr<GuiElement> e) {
|
||||||
if (!e)
|
if (!e)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
removeDrc(e);
|
removeDrcByPtr(e.get());
|
||||||
drcElements.push_back(e);
|
drcElements.push_back(std::move(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
void append(GuiElement *e) {
|
void append(const std::shared_ptr<GuiElement> &e) {
|
||||||
appendTv(e);
|
appendTv(e);
|
||||||
appendDrc(e);
|
appendDrc(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void insertTv(uint32_t pos, GuiElement *e) {
|
void insertTv(uint32_t pos, const std::shared_ptr<GuiElement> &e) {
|
||||||
if (!e)
|
if (!e)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
removeTv(e);
|
removeTvByPtr(e.get());
|
||||||
tvElements.insert(tvElements.begin() + pos, e);
|
tvElements.insert(tvElements.begin() + pos, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void insertDrc(uint32_t pos, GuiElement *e) {
|
void insertDrc(uint32_t pos, const std::shared_ptr<GuiElement> &e) {
|
||||||
if (!e)
|
if (!e)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
removeDrc(e);
|
removeDrcByPtr(e.get());
|
||||||
drcElements.insert(drcElements.begin() + pos, e);
|
drcElements.insert(drcElements.begin() + pos, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void insert(uint32_t pos, GuiElement *e) {
|
void insert(uint32_t pos, const std::shared_ptr<GuiElement> &e) {
|
||||||
insertTv(pos, e);
|
insertTv(pos, e);
|
||||||
insertDrc(pos, e);
|
insertDrc(pos, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeTv(GuiElement *e) {
|
void removeTvByPtr(GuiElement *e) {
|
||||||
for (uint32_t i = 0; i < tvElements.size(); ++i) {
|
for (uint32_t i = 0; i < tvElements.size(); ++i) {
|
||||||
if (e == tvElements[i]) {
|
if (e == tvElements[i].get()) {
|
||||||
tvElements.erase(tvElements.begin() + i);
|
tvElements.erase(tvElements.begin() + i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeDrc(GuiElement *e) {
|
void removeDrcByPtr(GuiElement *e) {
|
||||||
for (uint32_t i = 0; i < drcElements.size(); ++i) {
|
for (uint32_t i = 0; i < drcElements.size(); ++i) {
|
||||||
if (e == drcElements[i]) {
|
if (e == drcElements[i].get()) {
|
||||||
drcElements.erase(drcElements.begin() + i);
|
drcElements.erase(drcElements.begin() + i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove(GuiElement *e) {
|
void removeByPtr(GuiElement *e) {
|
||||||
removeTv(e);
|
removeTvByPtr(e);
|
||||||
removeDrc(e);
|
removeDrcByPtr(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeAll() {
|
void removeAll() {
|
||||||
@ -103,11 +103,11 @@ public:
|
|||||||
drcElements.clear();
|
drcElements.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawDrc(CVideo *video);
|
void drawDrc(const CVideo &video);
|
||||||
|
|
||||||
void drawTv(CVideo *video);
|
void drawTv(const CVideo &video);
|
||||||
|
|
||||||
void update(GuiController *controller);
|
void update(const GuiController &controller);
|
||||||
|
|
||||||
void updateEffects();
|
void updateEffects();
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetupMainView(void);
|
void SetupMainView();
|
||||||
|
|
||||||
void OnOpenEffectFinish(GuiElement *element);
|
void OnOpenEffectFinish(GuiElement *element);
|
||||||
|
|
||||||
@ -151,19 +151,16 @@ private:
|
|||||||
void OnGameTitleAdded(gameInfo *info);
|
void OnGameTitleAdded(gameInfo *info);
|
||||||
|
|
||||||
int32_t width, height;
|
int32_t width, height;
|
||||||
std::vector<GuiElement *> drcElements;
|
std::vector<std::shared_ptr<GuiElement>> drcElements;
|
||||||
std::vector<GuiElement *> tvElements;
|
std::vector<std::shared_ptr<GuiElement>> tvElements;
|
||||||
|
|
||||||
GuiSound *gameClickSound;
|
std::shared_ptr<MainDrcButtonsFrame> mainSwitchButtonFrame;
|
||||||
|
|
||||||
MainDrcButtonsFrame *mainSwitchButtonFrame;
|
std::shared_ptr<GuiTitleBrowser> currentTvFrame;
|
||||||
|
std::shared_ptr<GuiTitleBrowser> currentDrcFrame;
|
||||||
|
|
||||||
GuiTitleBrowser *currentTvFrame;
|
std::array<std::unique_ptr<GuiImage>, 4> pointerImg;
|
||||||
GuiTitleBrowser *currentDrcFrame;
|
bool pointerValid[4] = {};
|
||||||
|
|
||||||
GuiImageData *pointerImgData[4];
|
|
||||||
GuiImage *pointerImg[4];
|
|
||||||
bool pointerValid[4];
|
|
||||||
|
|
||||||
GameList gameList;
|
GameList gameList;
|
||||||
|
|
||||||
|
@ -1,102 +1,62 @@
|
|||||||
#include "Resources.h"
|
#include "Resources.h"
|
||||||
#include "filelist.h"
|
#include "filelist.h"
|
||||||
#include "fs/FSUtils.h"
|
#include "fs/FSUtils.h"
|
||||||
#include "utils/AsyncExecutor.h"
|
#include <chrono>
|
||||||
#include <gui/GuiImageData.h>
|
#include <gui/GuiImageData.h>
|
||||||
#include <gui/GuiSound.h>
|
#include <gui/GuiSound.h>
|
||||||
#include <malloc.h>
|
#include <span>
|
||||||
#include <string.h>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
#include <future>
|
|
||||||
#include <iostream>
|
|
||||||
#include <strings.h>
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
std::unique_ptr<Resources> Resources::instance = {};
|
||||||
Resources *Resources::instance = nullptr;
|
|
||||||
|
|
||||||
void Resources::Clear() {
|
void Resources::Clear() {
|
||||||
for (int32_t i = 0; RecourceList[i].filename != nullptr; ++i) {
|
for (int32_t i = 0; ResourceList[i].filename != nullptr; ++i) {
|
||||||
if (RecourceList[i].CustomFile) {
|
ResourceList[i].CustomFileBuffer.clear();
|
||||||
free(RecourceList[i].CustomFile);
|
|
||||||
RecourceList[i].CustomFile = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RecourceList[i].CustomFileSize != 0)
|
|
||||||
RecourceList[i].CustomFileSize = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instance)
|
instance.reset();
|
||||||
delete instance;
|
|
||||||
|
|
||||||
instance = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Resources::LoadFiles(const char *path) {
|
std::vector<uint8_t> Resources::GetFile(std::string_view filename) {
|
||||||
if (!path)
|
for (int32_t i = 0; ResourceList[i].filename != nullptr; ++i) {
|
||||||
return false;
|
if (filename == ResourceList[i].filename) {
|
||||||
|
if (!ResourceList[i].CustomFileBuffer.empty()) {
|
||||||
bool result = false;
|
return ResourceList[i].CustomFileBuffer;
|
||||||
Clear();
|
}
|
||||||
|
return {ResourceList[i].DefaultFile, ResourceList[i].DefaultFile + ResourceList[i].DefaultFileSize};
|
||||||
for (int32_t i = 0; RecourceList[i].filename != nullptr; ++i) {
|
|
||||||
std::string fullpath(path);
|
|
||||||
fullpath += "/";
|
|
||||||
fullpath += RecourceList[i].filename;
|
|
||||||
|
|
||||||
uint8_t *buffer = nullptr;
|
|
||||||
uint32_t filesize = 0;
|
|
||||||
|
|
||||||
FSUtils::LoadFileToMem(fullpath.c_str(), &buffer, &filesize);
|
|
||||||
|
|
||||||
RecourceList[i].CustomFile = buffer;
|
|
||||||
RecourceList[i].CustomFileSize = (uint32_t) filesize;
|
|
||||||
result |= (buffer != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint8_t *Resources::GetFile(const char *filename) {
|
|
||||||
for (int32_t i = 0; RecourceList[i].filename != nullptr; ++i) {
|
|
||||||
if (strcasecmp(filename, RecourceList[i].filename) == 0) {
|
|
||||||
return (RecourceList[i].CustomFile ? RecourceList[i].CustomFile : RecourceList[i].DefaultFile);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Resources::GetFileSize(const char *filename) {
|
|
||||||
for (int32_t i = 0; RecourceList[i].filename != nullptr; ++i) {
|
std::shared_ptr<GuiImageData> Resources::GetImageData(std::string_view filename) {
|
||||||
if (strcasecmp(filename, RecourceList[i].filename) == 0) {
|
if (!instance) {
|
||||||
return (RecourceList[i].CustomFile ? RecourceList[i].CustomFileSize : RecourceList[i].DefaultFileSize);
|
instance = std::make_unique<Resources>();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
GuiImageData *Resources::GetImageData(const char *filename) {
|
auto itr = instance->imageDataMap.find(std::string(filename));
|
||||||
if (!instance)
|
|
||||||
instance = new Resources;
|
|
||||||
|
|
||||||
std::map<std::string, std::pair<uint32_t, GuiImageData *>>::iterator itr = instance->imageDataMap.find(std::string(filename));
|
|
||||||
if (itr != instance->imageDataMap.end()) {
|
if (itr != instance->imageDataMap.end()) {
|
||||||
itr->second.first++;
|
itr->second.first++;
|
||||||
return itr->second.second;
|
return itr->second.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int32_t i = 0; RecourceList[i].filename != nullptr; ++i) {
|
for (int32_t i = 0; ResourceList[i].filename != nullptr; ++i) {
|
||||||
if (strcasecmp(filename, RecourceList[i].filename) == 0) {
|
if (filename == ResourceList[i].filename) {
|
||||||
const uint8_t *buff = RecourceList[i].CustomFile ? RecourceList[i].CustomFile : RecourceList[i].DefaultFile;
|
std::span<const uint8_t> fileData;
|
||||||
const uint32_t size = RecourceList[i].CustomFile ? RecourceList[i].CustomFileSize : RecourceList[i].DefaultFileSize;
|
if (!ResourceList[i].CustomFileBuffer.empty()) {
|
||||||
|
fileData = ResourceList[i].CustomFileBuffer;
|
||||||
|
} else {
|
||||||
|
fileData = std::span(ResourceList[i].DefaultFile, ResourceList[i].DefaultFile + ResourceList[i].DefaultFileSize);
|
||||||
|
}
|
||||||
|
|
||||||
if (buff == nullptr)
|
if (fileData.empty() || fileData.data() == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
GuiImageData *image = new GuiImageData(buff, size);
|
std::shared_ptr<GuiImageData> image = std::make_unique<GuiImageData>(fileData);
|
||||||
instance->imageDataMap[std::string(filename)].first = 1;
|
instance->imageDataMap[std::string(filename)].first = 1;
|
||||||
instance->imageDataMap[std::string(filename)].second = image;
|
instance->imageDataMap[std::string(filename)].second = image;
|
||||||
|
|
||||||
@ -107,64 +67,23 @@ GuiImageData *Resources::GetImageData(const char *filename) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Resources::RemoveImageData(GuiImageData *image) {
|
std::unique_ptr<GuiSound> Resources::GetSound(std::string_view filename) {
|
||||||
std::map<std::string, std::pair<uint32_t, GuiImageData *>>::iterator itr;
|
for (int32_t i = 0; ResourceList[i].filename != nullptr; ++i) {
|
||||||
|
if (filename == ResourceList[i].filename) {
|
||||||
for (itr = instance->imageDataMap.begin(); itr != instance->imageDataMap.end(); itr++) {
|
std::vector<uint8_t> fileData;
|
||||||
if (itr->second.second == image) {
|
if (!ResourceList[i].CustomFileBuffer.empty()) {
|
||||||
itr->second.first--;
|
fileData = ResourceList[i].CustomFileBuffer;
|
||||||
|
} else {
|
||||||
if (itr->second.first == 0) {
|
fileData = std::vector(ResourceList[i].DefaultFile, ResourceList[i].DefaultFile + ResourceList[i].DefaultFileSize);
|
||||||
AsyncExecutor::pushForDelete(itr->second.second);
|
|
||||||
|
|
||||||
instance->imageDataMap.erase(itr);
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GuiSound *Resources::GetSound(const char *filename) {
|
if (fileData.empty() || fileData.data() == nullptr) {
|
||||||
if (!instance)
|
|
||||||
instance = new Resources;
|
|
||||||
|
|
||||||
std::map<std::string, std::pair<uint32_t, GuiSound *>>::iterator itr = instance->soundDataMap.find(std::string(filename));
|
|
||||||
if (itr != instance->soundDataMap.end()) {
|
|
||||||
itr->second.first++;
|
|
||||||
return itr->second.second;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int32_t i = 0; RecourceList[i].filename != nullptr; ++i) {
|
|
||||||
if (strcasecmp(filename, RecourceList[i].filename) == 0) {
|
|
||||||
const uint8_t *buff = RecourceList[i].CustomFile ? RecourceList[i].CustomFile : RecourceList[i].DefaultFile;
|
|
||||||
const uint32_t size = RecourceList[i].CustomFile ? RecourceList[i].CustomFileSize : RecourceList[i].DefaultFileSize;
|
|
||||||
|
|
||||||
if (buff == nullptr)
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
GuiSound *sound = new GuiSound(buff, size);
|
|
||||||
instance->soundDataMap[std::string(filename)].first = 1;
|
|
||||||
instance->soundDataMap[std::string(filename)].second = sound;
|
|
||||||
|
|
||||||
return sound;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Resources::RemoveSound(GuiSound *sound) {
|
|
||||||
std::map<std::string, std::pair<uint32_t, GuiSound *>>::iterator itr;
|
|
||||||
|
|
||||||
for (itr = instance->soundDataMap.begin(); itr != instance->soundDataMap.end(); itr++) {
|
|
||||||
if (itr->second.second == sound) {
|
|
||||||
itr->second.first--;
|
|
||||||
|
|
||||||
if (itr->second.first == 0) {
|
|
||||||
AsyncExecutor::pushForDelete(itr->second.second);
|
|
||||||
instance->soundDataMap.erase(itr);
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
return std::make_unique<GuiSound>(std::move(fileData));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw std::runtime_error("Try to load invalid sound file");
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <stdint.h>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
//! forward declaration
|
//! forward declaration
|
||||||
class GuiImageData;
|
class GuiImageData;
|
||||||
@ -10,29 +14,20 @@ class GuiSound;
|
|||||||
|
|
||||||
class Resources {
|
class Resources {
|
||||||
public:
|
public:
|
||||||
|
Resources() = default;
|
||||||
|
~Resources() = default;
|
||||||
|
|
||||||
static void Clear();
|
static void Clear();
|
||||||
|
|
||||||
static bool LoadFiles(const char *path);
|
static std::vector<uint8_t> GetFile(std::string_view filename);
|
||||||
|
|
||||||
static const uint8_t *GetFile(const char *filename);
|
static std::shared_ptr<GuiImageData> GetImageData(std::string_view filename);
|
||||||
|
|
||||||
static uint32_t GetFileSize(const char *filename);
|
static std::unique_ptr<GuiSound> GetSound(std::string_view filename);
|
||||||
|
|
||||||
static GuiImageData *GetImageData(const char *filename);
|
|
||||||
|
|
||||||
static void RemoveImageData(GuiImageData *image);
|
|
||||||
|
|
||||||
static GuiSound *GetSound(const char *filename);
|
|
||||||
|
|
||||||
static void RemoveSound(GuiSound *sound);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Resources *instance;
|
static std::unique_ptr<Resources> instance;
|
||||||
|
|
||||||
Resources() {}
|
std::map<std::string, std::pair<uint32_t, std::shared_ptr<GuiImageData>>> imageDataMap;
|
||||||
|
std::map<std::string, std::pair<uint32_t, std::shared_ptr<GuiSound>>> soundDataMap;
|
||||||
~Resources() {}
|
|
||||||
|
|
||||||
std::map<std::string, std::pair<uint32_t, GuiImageData *>> imageDataMap;
|
|
||||||
std::map<std::string, std::pair<uint32_t, GuiSound *>> soundDataMap;
|
|
||||||
};
|
};
|
@ -26,34 +26,16 @@
|
|||||||
#include "fs/CFile.hpp"
|
#include "fs/CFile.hpp"
|
||||||
#include <coreinit/thread.h>
|
#include <coreinit/thread.h>
|
||||||
#include <coreinit/time.h>
|
#include <coreinit/time.h>
|
||||||
#include <limits.h>
|
#include <climits>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <math.h>
|
|
||||||
#include <sounds/Mp3Decoder.hpp>
|
#include <sounds/Mp3Decoder.hpp>
|
||||||
#include <string.h>
|
#include <cstring>
|
||||||
#include <string>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
Mp3Decoder::Mp3Decoder(const char *filepath)
|
Mp3Decoder::Mp3Decoder(std::span<uint8_t> snd)
|
||||||
: SoundDecoder(filepath) {
|
: SoundDecoder(snd) {
|
||||||
SoundType = SOUND_MP3;
|
SoundType = SOUND_MP3;
|
||||||
ReadBuffer = NULL;
|
ReadBuffer = nullptr;
|
||||||
mad_timer_reset(&Timer);
|
|
||||||
mad_stream_init(&Stream);
|
|
||||||
mad_frame_init(&Frame);
|
|
||||||
mad_synth_init(&Synth);
|
|
||||||
|
|
||||||
if (!file_fd) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
OpenFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
Mp3Decoder::Mp3Decoder(const uint8_t *snd, int32_t len)
|
|
||||||
: SoundDecoder(snd, len) {
|
|
||||||
SoundType = SOUND_MP3;
|
|
||||||
ReadBuffer = NULL;
|
|
||||||
mad_timer_reset(&Timer);
|
mad_timer_reset(&Timer);
|
||||||
mad_stream_init(&Stream);
|
mad_stream_init(&Stream);
|
||||||
mad_frame_init(&Frame);
|
mad_frame_init(&Frame);
|
||||||
@ -78,17 +60,16 @@ Mp3Decoder::~Mp3Decoder() {
|
|||||||
if (ReadBuffer) {
|
if (ReadBuffer) {
|
||||||
free(ReadBuffer);
|
free(ReadBuffer);
|
||||||
}
|
}
|
||||||
ReadBuffer = NULL;
|
ReadBuffer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mp3Decoder::OpenFile() {
|
void Mp3Decoder::OpenFile() {
|
||||||
GuardPtr = NULL;
|
GuardPtr = nullptr;
|
||||||
ReadBuffer = (uint8_t *) memalign(32, SoundBlockSize * SoundBlocks);
|
ReadBuffer = (uint8_t *) memalign(32, SoundBlockSize * SoundBlocks);
|
||||||
if (!ReadBuffer) {
|
if (!ReadBuffer) {
|
||||||
if (file_fd) {
|
if (file_fd) {
|
||||||
delete file_fd;
|
file_fd.reset();
|
||||||
}
|
}
|
||||||
file_fd = NULL;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,9 +77,8 @@ void Mp3Decoder::OpenFile() {
|
|||||||
int32_t ret = Read(dummybuff, 4096, 0);
|
int32_t ret = Read(dummybuff, 4096, 0);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
if (file_fd) {
|
if (file_fd) {
|
||||||
delete file_fd;
|
file_fd.reset();
|
||||||
}
|
}
|
||||||
file_fd = NULL;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +96,7 @@ int32_t Mp3Decoder::Rewind() {
|
|||||||
mad_frame_init(&Frame);
|
mad_frame_init(&Frame);
|
||||||
mad_synth_init(&Synth);
|
mad_synth_init(&Synth);
|
||||||
SynthPos = 0;
|
SynthPos = 0;
|
||||||
GuardPtr = NULL;
|
GuardPtr = nullptr;
|
||||||
|
|
||||||
if (!file_fd) {
|
if (!file_fd) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -152,7 +132,7 @@ int32_t Mp3Decoder::Read(uint8_t *buffer, int32_t buffer_size, int32_t pos) {
|
|||||||
uint8_t *write_pos = buffer;
|
uint8_t *write_pos = buffer;
|
||||||
uint8_t *write_end = buffer + buffer_size;
|
uint8_t *write_end = buffer + buffer_size;
|
||||||
|
|
||||||
while (1) {
|
while (true) {
|
||||||
while (SynthPos < Synth.pcm.length) {
|
while (SynthPos < Synth.pcm.length) {
|
||||||
if (write_pos >= write_end) {
|
if (write_pos >= write_end) {
|
||||||
return write_pos - buffer;
|
return write_pos - buffer;
|
||||||
|
@ -29,24 +29,22 @@
|
|||||||
|
|
||||||
class Mp3Decoder : public SoundDecoder {
|
class Mp3Decoder : public SoundDecoder {
|
||||||
public:
|
public:
|
||||||
Mp3Decoder(const char *filepath);
|
explicit Mp3Decoder(std::span<uint8_t> snd);
|
||||||
|
|
||||||
Mp3Decoder(const uint8_t *sound, int32_t len);
|
~Mp3Decoder() override;
|
||||||
|
|
||||||
virtual ~Mp3Decoder();
|
int32_t Rewind() override;
|
||||||
|
|
||||||
int32_t Rewind();
|
int32_t Read(uint8_t *buffer, int32_t buffer_size, int32_t pos) override;
|
||||||
|
|
||||||
int32_t Read(uint8_t *buffer, int32_t buffer_size, int32_t pos);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void OpenFile();
|
void OpenFile();
|
||||||
|
|
||||||
struct mad_stream Stream;
|
struct mad_stream Stream{};
|
||||||
struct mad_frame Frame;
|
struct mad_frame Frame{};
|
||||||
struct mad_synth Synth;
|
struct mad_synth Synth{};
|
||||||
mad_timer_t Timer;
|
mad_timer_t Timer{};
|
||||||
uint8_t *GuardPtr;
|
uint8_t *GuardPtr{};
|
||||||
uint8_t *ReadBuffer;
|
uint8_t *ReadBuffer;
|
||||||
uint32_t SynthPos;
|
uint32_t SynthPos{};
|
||||||
};
|
};
|
||||||
|
@ -53,19 +53,10 @@ static ov_callbacks callbacks = {
|
|||||||
(int (*)(void *)) ogg_close,
|
(int (*)(void *)) ogg_close,
|
||||||
(long (*)(void *)) ogg_tell};
|
(long (*)(void *)) ogg_tell};
|
||||||
|
|
||||||
OggDecoder::OggDecoder(const char *filepath)
|
|
||||||
: SoundDecoder(filepath) {
|
|
||||||
SoundType = SOUND_OGG;
|
|
||||||
|
|
||||||
if (!file_fd) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
OpenFile();
|
OggDecoder::OggDecoder(std::span<uint8_t> snd)
|
||||||
}
|
: SoundDecoder(snd) {
|
||||||
|
|
||||||
OggDecoder::OggDecoder(const uint8_t *snd, int32_t len)
|
|
||||||
: SoundDecoder(snd, len) {
|
|
||||||
SoundType = SOUND_OGG;
|
SoundType = SOUND_OGG;
|
||||||
|
|
||||||
if (!file_fd) {
|
if (!file_fd) {
|
||||||
@ -77,8 +68,9 @@ OggDecoder::OggDecoder(const uint8_t *snd, int32_t len)
|
|||||||
|
|
||||||
OggDecoder::~OggDecoder() {
|
OggDecoder::~OggDecoder() {
|
||||||
ExitRequested = true;
|
ExitRequested = true;
|
||||||
while (Decoding)
|
while (Decoding) {
|
||||||
OSSleepTicks(OSMicrosecondsToTicks(100));
|
OSSleepTicks(OSMicrosecondsToTicks(100));
|
||||||
|
}
|
||||||
|
|
||||||
if (file_fd) {
|
if (file_fd) {
|
||||||
ov_clear(&ogg_file);
|
ov_clear(&ogg_file);
|
||||||
@ -86,17 +78,15 @@ OggDecoder::~OggDecoder() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OggDecoder::OpenFile() {
|
void OggDecoder::OpenFile() {
|
||||||
if (ov_open_callbacks(file_fd, &ogg_file, NULL, 0, callbacks) < 0) {
|
if (ov_open_callbacks(file_fd.get(), &ogg_file, nullptr, 0, callbacks) < 0) {
|
||||||
delete file_fd;
|
file_fd.reset();
|
||||||
file_fd = NULL;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ogg_info = ov_info(&ogg_file, -1);
|
ogg_info = ov_info(&ogg_file, -1);
|
||||||
if (!ogg_info) {
|
if (!ogg_info) {
|
||||||
ov_clear(&ogg_file);
|
ov_clear(&ogg_file);
|
||||||
delete file_fd;
|
file_fd.reset();
|
||||||
file_fd = NULL;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,26 +23,24 @@
|
|||||||
*
|
*
|
||||||
* for WiiXplorer 2010
|
* for WiiXplorer 2010
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
#include <sounds/SoundDecoder.hpp>
|
||||||
|
#include <span>
|
||||||
#include <tremor/ivorbiscodec.h>
|
#include <tremor/ivorbiscodec.h>
|
||||||
#include <tremor/ivorbisfile.h>
|
#include <tremor/ivorbisfile.h>
|
||||||
|
|
||||||
#include <sounds/SoundDecoder.hpp>
|
|
||||||
|
|
||||||
class OggDecoder : public SoundDecoder {
|
class OggDecoder : public SoundDecoder {
|
||||||
public:
|
public:
|
||||||
OggDecoder(const char *filepath);
|
explicit OggDecoder(std::span<uint8_t> snd);
|
||||||
|
|
||||||
OggDecoder(const uint8_t *snd, int32_t len);
|
~OggDecoder() override;
|
||||||
|
|
||||||
virtual ~OggDecoder();
|
int32_t Rewind() override;
|
||||||
|
|
||||||
int32_t Rewind();
|
int32_t Read(uint8_t *buffer, int32_t buffer_size, int32_t pos) override;
|
||||||
|
|
||||||
int32_t Read(uint8_t *buffer, int32_t buffer_size, int32_t pos);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void OpenFile();
|
void OpenFile();
|
||||||
|
|
||||||
OggVorbis_File ogg_file;
|
OggVorbis_File ogg_file{};
|
||||||
vorbis_info *ogg_info;
|
vorbis_info *ogg_info{};
|
||||||
};
|
};
|
||||||
|
@ -28,33 +28,32 @@ static const uint32_t FixedPointShift = 15;
|
|||||||
static const uint32_t FixedPointScale = 1 << FixedPointShift;
|
static const uint32_t FixedPointScale = 1 << FixedPointShift;
|
||||||
|
|
||||||
SoundDecoder::SoundDecoder() {
|
SoundDecoder::SoundDecoder() {
|
||||||
file_fd = NULL;
|
file_fd = nullptr;
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundDecoder::SoundDecoder(const std::string &filepath) {
|
SoundDecoder::SoundDecoder(const std::string &filepath) {
|
||||||
file_fd = new CFile(filepath, CFile::ReadOnly);
|
file_fd = std::make_unique<CFile>(filepath, CFile::ReadOnly);
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundDecoder::SoundDecoder(const uint8_t *buffer, int32_t size) {
|
SoundDecoder::SoundDecoder(std::span<uint8_t> snd) {
|
||||||
file_fd = new CFile(buffer, size);
|
file_fd = std::make_unique<CFile>(snd);
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundDecoder::~SoundDecoder() {
|
SoundDecoder::~SoundDecoder() {
|
||||||
ExitRequested = true;
|
ExitRequested = true;
|
||||||
while (Decoding)
|
while (Decoding) {
|
||||||
OSSleepTicks(OSMicrosecondsToTicks(1000));
|
OSSleepTicks(OSMicrosecondsToTicks(1000));
|
||||||
|
}
|
||||||
|
|
||||||
//! lock unlock once to make sure it's really not decoding
|
//! lock unlock once to make sure it's really not decoding
|
||||||
Lock();
|
Lock();
|
||||||
Unlock();
|
Unlock();
|
||||||
|
|
||||||
if (file_fd) {
|
file_fd.reset();
|
||||||
delete file_fd;
|
|
||||||
}
|
|
||||||
file_fd = NULL;
|
|
||||||
|
|
||||||
if (ResampleBuffer) {
|
if (ResampleBuffer) {
|
||||||
free(ResampleBuffer);
|
free(ResampleBuffer);
|
||||||
@ -62,6 +61,9 @@ SoundDecoder::~SoundDecoder() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32_t SoundDecoder::Seek(int32_t pos) {
|
int32_t SoundDecoder::Seek(int32_t pos) {
|
||||||
|
if (!file_fd) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
CurPos = pos;
|
CurPos = pos;
|
||||||
return file_fd->seek(CurPos, SEEK_SET);
|
return file_fd->seek(CurPos, SEEK_SET);
|
||||||
}
|
}
|
||||||
@ -79,11 +81,15 @@ void SoundDecoder::Init() {
|
|||||||
ExitRequested = false;
|
ExitRequested = false;
|
||||||
SoundBuffer.SetBufferBlockSize(SoundBlockSize);
|
SoundBuffer.SetBufferBlockSize(SoundBlockSize);
|
||||||
SoundBuffer.Resize(SoundBlocks);
|
SoundBuffer.Resize(SoundBlocks);
|
||||||
ResampleBuffer = NULL;
|
ResampleBuffer = nullptr;
|
||||||
ResampleRatio = 0;
|
ResampleRatio = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t SoundDecoder::Rewind() {
|
int32_t SoundDecoder::Rewind() {
|
||||||
|
if (!file_fd) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
CurPos = 0;
|
CurPos = 0;
|
||||||
EndOfFile = false;
|
EndOfFile = false;
|
||||||
file_fd->rewind();
|
file_fd->rewind();
|
||||||
@ -92,14 +98,17 @@ int32_t SoundDecoder::Rewind() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32_t SoundDecoder::Read(uint8_t *buffer, int32_t buffer_size, int32_t pos) {
|
int32_t SoundDecoder::Read(uint8_t *buffer, int32_t buffer_size, int32_t pos) {
|
||||||
|
if (!file_fd) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
int32_t ret = file_fd->read(buffer, buffer_size);
|
int32_t ret = file_fd->read(buffer, buffer_size);
|
||||||
CurPos += ret;
|
CurPos += ret;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundDecoder::EnableUpsample(void) {
|
void SoundDecoder::EnableUpsample() {
|
||||||
if ((ResampleBuffer == NULL) && IsStereo() && Is16Bit() && SampleRate != 32000 && SampleRate != 48000) {
|
if ((ResampleBuffer == nullptr) && IsStereo() && Is16Bit() && SampleRate != 32000 && SampleRate != 48000) {
|
||||||
ResampleBuffer = (uint8_t *) memalign(32, SoundBlockSize);
|
ResampleBuffer = (uint8_t *) memalign(32, SoundBlockSize);
|
||||||
ResampleRatio = (FixedPointScale * SampleRate) / 48000;
|
ResampleRatio = (FixedPointScale * SampleRate) / 48000;
|
||||||
SoundBlockSize = (SoundBlockSize * ResampleRatio) / FixedPointScale;
|
SoundBlockSize = (SoundBlockSize * ResampleRatio) / FixedPointScale;
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <sounds/BufferCircle.hpp>
|
#include <sounds/BufferCircle.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <span>
|
||||||
|
|
||||||
class CFile;
|
class CFile;
|
||||||
|
|
||||||
@ -38,7 +39,7 @@ public:
|
|||||||
|
|
||||||
SoundDecoder(const std::string &filepath);
|
SoundDecoder(const std::string &filepath);
|
||||||
|
|
||||||
SoundDecoder(const uint8_t *buffer, int32_t size);
|
SoundDecoder(std::span<uint8_t> snd);
|
||||||
|
|
||||||
virtual ~SoundDecoder();
|
virtual ~SoundDecoder();
|
||||||
|
|
||||||
@ -116,7 +117,7 @@ public:
|
|||||||
return Decoding;
|
return Decoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnableUpsample(void);
|
void EnableUpsample();
|
||||||
|
|
||||||
enum SoundFormats {
|
enum SoundFormats {
|
||||||
FORMAT_PCM_16_BIT = 0x0A,
|
FORMAT_PCM_16_BIT = 0x0A,
|
||||||
@ -139,22 +140,22 @@ protected:
|
|||||||
|
|
||||||
void Upsample(int16_t *src, int16_t *dst, uint32_t nr_src_samples, uint32_t nr_dst_samples);
|
void Upsample(int16_t *src, int16_t *dst, uint32_t nr_src_samples, uint32_t nr_dst_samples);
|
||||||
|
|
||||||
CFile *file_fd;
|
std::unique_ptr<CFile> file_fd;
|
||||||
BufferCircle SoundBuffer;
|
BufferCircle SoundBuffer;
|
||||||
uint8_t SoundType;
|
uint8_t SoundType{};
|
||||||
uint16_t whichLoad;
|
uint16_t whichLoad{};
|
||||||
uint16_t SoundBlocks;
|
uint16_t SoundBlocks{};
|
||||||
int32_t SoundBlockSize;
|
int32_t SoundBlockSize{};
|
||||||
int32_t CurPos;
|
int32_t CurPos{};
|
||||||
bool ResampleTo48kHz;
|
bool ResampleTo48kHz{};
|
||||||
bool Loop;
|
bool Loop{};
|
||||||
bool EndOfFile;
|
bool EndOfFile{};
|
||||||
bool Decoding;
|
bool Decoding{};
|
||||||
bool ExitRequested;
|
bool ExitRequested{};
|
||||||
uint16_t Format;
|
uint16_t Format{};
|
||||||
uint16_t SampleRate;
|
uint16_t SampleRate{};
|
||||||
uint8_t *ResampleBuffer;
|
uint8_t *ResampleBuffer{};
|
||||||
uint32_t ResampleRatio;
|
uint32_t ResampleRatio{};
|
||||||
std::recursive_mutex mutex;
|
std::recursive_mutex mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <sounds/OggDecoder.hpp>
|
#include <sounds/OggDecoder.hpp>
|
||||||
#include <sounds/SoundHandler.hpp>
|
#include <sounds/SoundHandler.hpp>
|
||||||
#include <sounds/WavDecoder.hpp>
|
#include <sounds/WavDecoder.hpp>
|
||||||
|
#include <span>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
SoundHandler *SoundHandler::handlerInstance = NULL;
|
SoundHandler *SoundHandler::handlerInstance = NULL;
|
||||||
@ -39,15 +40,16 @@ SoundHandler::SoundHandler()
|
|||||||
Decoding = false;
|
Decoding = false;
|
||||||
ExitRequested = false;
|
ExitRequested = false;
|
||||||
for (uint32_t i = 0; i < MAX_DECODERS; ++i) {
|
for (uint32_t i = 0; i < MAX_DECODERS; ++i) {
|
||||||
DecoderList[i] = NULL;
|
DecoderList[i].reset();
|
||||||
voiceList[i] = NULL;
|
voiceList[i].reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
resumeThread();
|
resumeThread();
|
||||||
|
|
||||||
//! wait for initialization
|
//! wait for initialization
|
||||||
while (!isThreadSuspended())
|
while (!isThreadSuspended()) {
|
||||||
OSSleepTicks(OSMicrosecondsToTicks(1000));
|
OSSleepTicks(OSMicrosecondsToTicks(1000));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundHandler::~SoundHandler() {
|
SoundHandler::~SoundHandler() {
|
||||||
@ -57,28 +59,16 @@ SoundHandler::~SoundHandler() {
|
|||||||
ClearDecoderList();
|
ClearDecoderList();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundHandler::AddDecoder(int32_t voice, const char *filepath) {
|
void SoundHandler::AddDecoder(int32_t voice, const std::span<uint8_t> snd) {
|
||||||
if (voice < 0 || voice >= MAX_DECODERS) {
|
if (voice < 0 || voice >= MAX_DECODERS) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DecoderList[voice] != NULL) {
|
if (DecoderList[voice] != nullptr) {
|
||||||
RemoveDecoder(voice);
|
RemoveDecoder(voice);
|
||||||
}
|
}
|
||||||
|
|
||||||
DecoderList[voice] = GetSoundDecoder(filepath);
|
DecoderList[voice] = GetSoundDecoder(snd);
|
||||||
}
|
|
||||||
|
|
||||||
void SoundHandler::AddDecoder(int32_t voice, const uint8_t *snd, int32_t len) {
|
|
||||||
if (voice < 0 || voice >= MAX_DECODERS) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DecoderList[voice] != NULL) {
|
|
||||||
RemoveDecoder(voice);
|
|
||||||
}
|
|
||||||
|
|
||||||
DecoderList[voice] = GetSoundDecoder(snd, len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundHandler::RemoveDecoder(int32_t voice) {
|
void SoundHandler::RemoveDecoder(int32_t voice) {
|
||||||
@ -86,7 +76,7 @@ void SoundHandler::RemoveDecoder(int32_t voice) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DecoderList[voice] != NULL) {
|
if (DecoderList[voice] != nullptr) {
|
||||||
if (voiceList[voice] && voiceList[voice]->getState() != Voice::STATE_STOPPED) {
|
if (voiceList[voice] && voiceList[voice]->getState() != Voice::STATE_STOPPED) {
|
||||||
if (voiceList[voice]->getState() != Voice::STATE_STOP) {
|
if (voiceList[voice]->getState() != Voice::STATE_STOP) {
|
||||||
voiceList[voice]->setState(Voice::STATE_STOP);
|
voiceList[voice]->setState(Voice::STATE_STOP);
|
||||||
@ -99,11 +89,7 @@ void SoundHandler::RemoveDecoder(int32_t voice) {
|
|||||||
while (--timeOut && (voiceList[voice]->getState() != Voice::STATE_STOPPED))
|
while (--timeOut && (voiceList[voice]->getState() != Voice::STATE_STOPPED))
|
||||||
OSSleepTicks(OSMicrosecondsToTicks(1000));
|
OSSleepTicks(OSMicrosecondsToTicks(1000));
|
||||||
}
|
}
|
||||||
SoundDecoder *decoder = DecoderList[voice];
|
DecoderList[voice].reset();
|
||||||
decoder->Lock();
|
|
||||||
DecoderList[voice] = NULL;
|
|
||||||
decoder->Unlock();
|
|
||||||
delete decoder;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +100,7 @@ void SoundHandler::ClearDecoderList() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline bool CheckMP3Signature(const uint8_t *buffer) {
|
static inline bool CheckMP3Signature(const uint8_t *buffer) {
|
||||||
const char MP3_Magic[][3] = {
|
const uint8_t MP3_Magic[][3] = {
|
||||||
{'I', 'D', '3'}, //'ID3'
|
{'I', 'D', '3'}, //'ID3'
|
||||||
{0xff, 0xfe}, //'MPEG ADTS, layer III, v1.0 [protected]', 'mp3', 'audio/mpeg'),
|
{0xff, 0xfe}, //'MPEG ADTS, layer III, v1.0 [protected]', 'mp3', 'audio/mpeg'),
|
||||||
{0xff, 0xff}, //'MPEG ADTS, layer III, v1.0', 'mp3', 'audio/mpeg'),
|
{0xff, 0xff}, //'MPEG ADTS, layer III, v1.0', 'mp3', 'audio/mpeg'),
|
||||||
@ -144,60 +130,30 @@ static inline bool CheckMP3Signature(const uint8_t *buffer) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundDecoder *SoundHandler::GetSoundDecoder(const char *filepath) {
|
std::unique_ptr<SoundDecoder> SoundHandler::GetSoundDecoder(std::span<uint8_t> snd) {
|
||||||
uint32_t magic;
|
const uint8_t *check = snd.data();
|
||||||
CFile f(filepath, CFile::ReadOnly);
|
|
||||||
if (f.size() == 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
f.read((uint8_t *) &magic, 1);
|
|
||||||
} while (((uint8_t *) &magic)[0] == 0 && f.tell() < f.size());
|
|
||||||
|
|
||||||
if (f.tell() == f.size()) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
f.seek(f.tell() - 1, SEEK_SET);
|
|
||||||
f.read((uint8_t *) &magic, 4);
|
|
||||||
f.close();
|
|
||||||
|
|
||||||
if (magic == 0x4f676753) { // 'OggS'
|
|
||||||
return new OggDecoder(filepath);
|
|
||||||
} else if (magic == 0x52494646) { // 'RIFF'
|
|
||||||
return new WavDecoder(filepath);
|
|
||||||
} else if (CheckMP3Signature((uint8_t *) &magic) == true) {
|
|
||||||
return new Mp3Decoder(filepath);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SoundDecoder(filepath);
|
|
||||||
}
|
|
||||||
|
|
||||||
SoundDecoder *SoundHandler::GetSoundDecoder(const uint8_t *sound, int32_t length) {
|
|
||||||
const uint8_t *check = sound;
|
|
||||||
int32_t counter = 0;
|
int32_t counter = 0;
|
||||||
|
|
||||||
while (check[0] == 0 && counter < length) {
|
while (check[0] == 0 && counter < snd.size()) {
|
||||||
check++;
|
check++;
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (counter >= length) {
|
if (counter >= snd.size()) {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t *magic = (uint32_t *) check;
|
auto *magic = (uint32_t *) check;
|
||||||
|
|
||||||
if (magic[0] == 0x4f676753) { // 'OggS'
|
if (magic[0] == 0x4f676753) { // 'OggS'
|
||||||
return new OggDecoder(sound, length);
|
return std::make_unique<OggDecoder>(snd);
|
||||||
} else if (magic[0] == 0x52494646) { // 'RIFF'
|
} else if (magic[0] == 0x52494646) { // 'RIFF'
|
||||||
return new WavDecoder(sound, length);
|
return std::make_unique<WavDecoder>(snd);
|
||||||
} else if (CheckMP3Signature(check) == true) {
|
} else if (CheckMP3Signature(check)) {
|
||||||
return new Mp3Decoder(sound, length);
|
return std::make_unique<Mp3Decoder>(snd);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new SoundDecoder(sound, length);
|
return std::make_unique<SoundDecoder>(snd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundHandler::executeThread() {
|
void SoundHandler::executeThread() {
|
||||||
@ -224,7 +180,7 @@ void SoundHandler::executeThread() {
|
|||||||
// we would need MAX_DECODERS > Voice::PRIO_MAX
|
// we would need MAX_DECODERS > Voice::PRIO_MAX
|
||||||
for (uint32_t i = 0; i < MAX_DECODERS; ++i) {
|
for (uint32_t i = 0; i < MAX_DECODERS; ++i) {
|
||||||
int32_t priority = (MAX_DECODERS - i) * Voice::PRIO_MAX / MAX_DECODERS;
|
int32_t priority = (MAX_DECODERS - i) * Voice::PRIO_MAX / MAX_DECODERS;
|
||||||
voiceList[i] = new Voice(priority); // allocate voice 0 with highest priority
|
voiceList[i] = std::make_unique<Voice>(priority); // allocate voice 0 with highest priority
|
||||||
}
|
}
|
||||||
|
|
||||||
AXRegisterAppFrameCallback(SoundHandler::axFrameCallback);
|
AXRegisterAppFrameCallback(SoundHandler::axFrameCallback);
|
||||||
@ -235,7 +191,7 @@ void SoundHandler::executeThread() {
|
|||||||
suspendThread();
|
suspendThread();
|
||||||
|
|
||||||
for (i = 0; i < MAX_DECODERS; ++i) {
|
for (i = 0; i < MAX_DECODERS; ++i) {
|
||||||
if (DecoderList[i] == NULL) {
|
if (DecoderList[i] == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,20 +209,19 @@ void SoundHandler::executeThread() {
|
|||||||
Decoding = false;
|
Decoding = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < MAX_DECODERS; ++i) {
|
for (auto &voice : voiceList) {
|
||||||
voiceList[i]->stop();
|
voice->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
AXRegisterAppFrameCallback(NULL);
|
AXRegisterAppFrameCallback(nullptr);
|
||||||
AXQuit();
|
AXQuit();
|
||||||
|
|
||||||
for (uint32_t i = 0; i < MAX_DECODERS; ++i) {
|
for (auto &voice : voiceList) {
|
||||||
delete voiceList[i];
|
voice.reset();
|
||||||
voiceList[i] = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundHandler::axFrameCallback(void) {
|
void SoundHandler::axFrameCallback() {
|
||||||
for (uint32_t i = 0; i < MAX_DECODERS; i++) {
|
for (uint32_t i = 0; i < MAX_DECODERS; i++) {
|
||||||
Voice *voice = handlerInstance->getVoice(i);
|
Voice *voice = handlerInstance->getVoice(i);
|
||||||
|
|
||||||
@ -283,7 +238,7 @@ void SoundHandler::axFrameCallback(void) {
|
|||||||
const uint32_t bufferSize = decoder->GetBufferSize();
|
const uint32_t bufferSize = decoder->GetBufferSize();
|
||||||
decoder->LoadNext();
|
decoder->LoadNext();
|
||||||
|
|
||||||
const uint8_t *nextBuffer = NULL;
|
const uint8_t *nextBuffer = nullptr;
|
||||||
uint32_t nextBufferSize = 0;
|
uint32_t nextBufferSize = 0;
|
||||||
|
|
||||||
if (decoder->IsBufferReady()) {
|
if (decoder->IsBufferReady()) {
|
||||||
|
@ -28,9 +28,11 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <sndcore2/voice.h>
|
#include <sndcore2/voice.h>
|
||||||
#include <sounds/SoundDecoder.hpp>
|
#include <sounds/SoundDecoder.hpp>
|
||||||
#include <sounds/Voice.h>
|
#include <sounds/Voice.h>
|
||||||
|
#include <span>
|
||||||
#include <system/CThread.h>
|
#include <system/CThread.h>
|
||||||
|
|
||||||
#define MAX_DECODERS 16 // can be increased up to 96
|
#define MAX_DECODERS 16 // can be increased up to 96
|
||||||
@ -46,53 +48,49 @@ public:
|
|||||||
|
|
||||||
static void DestroyInstance() {
|
static void DestroyInstance() {
|
||||||
delete handlerInstance;
|
delete handlerInstance;
|
||||||
handlerInstance = NULL;
|
handlerInstance = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddDecoder(int32_t voice, const char *filepath);
|
void AddDecoder(int32_t voice, std::span<uint8_t> snd);
|
||||||
|
|
||||||
void AddDecoder(int32_t voice, const uint8_t *snd, int32_t len);
|
|
||||||
|
|
||||||
void RemoveDecoder(int32_t voice);
|
void RemoveDecoder(int32_t voice);
|
||||||
|
|
||||||
SoundDecoder *getDecoder(int32_t i) {
|
SoundDecoder *getDecoder(int32_t i) {
|
||||||
return ((i < 0 || i >= MAX_DECODERS) ? NULL : DecoderList[i]);
|
return ((i < 0 || i >= MAX_DECODERS) ? nullptr : DecoderList[i].get());
|
||||||
};
|
};
|
||||||
|
|
||||||
Voice *getVoice(int32_t i) {
|
Voice* getVoice(int32_t i) {
|
||||||
return ((i < 0 || i >= MAX_DECODERS) ? NULL : voiceList[i]);
|
return ((i < 0 || i >= MAX_DECODERS) ? nullptr : voiceList[i].get());
|
||||||
};
|
};
|
||||||
|
|
||||||
void ThreadSignal() {
|
void ThreadSignal() {
|
||||||
resumeThread();
|
resumeThread();
|
||||||
};
|
};
|
||||||
|
|
||||||
bool IsDecoding() {
|
[[nodiscard]] bool IsDecoding() const {
|
||||||
return Decoding;
|
return Decoding;
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SoundHandler();
|
SoundHandler();
|
||||||
|
|
||||||
~SoundHandler();
|
~SoundHandler() override;
|
||||||
|
|
||||||
static void axFrameCallback(void);
|
static void axFrameCallback();
|
||||||
|
|
||||||
void executeThread(void);
|
void executeThread() override;
|
||||||
|
|
||||||
void ClearDecoderList();
|
void ClearDecoderList();
|
||||||
|
|
||||||
SoundDecoder *GetSoundDecoder(const char *filepath);
|
std::unique_ptr<SoundDecoder> GetSoundDecoder(std::span<uint8_t> snd);
|
||||||
|
|
||||||
SoundDecoder *GetSoundDecoder(const uint8_t *sound, int32_t length);
|
|
||||||
|
|
||||||
static SoundHandler *handlerInstance;
|
static SoundHandler *handlerInstance;
|
||||||
|
|
||||||
bool Decoding;
|
bool Decoding;
|
||||||
bool ExitRequested;
|
bool ExitRequested;
|
||||||
|
|
||||||
Voice *voiceList[MAX_DECODERS];
|
std::array<std::unique_ptr<Voice>, MAX_DECODERS> voiceList;
|
||||||
SoundDecoder *DecoderList[MAX_DECODERS];
|
std::array<std::unique_ptr<SoundDecoder>, MAX_DECODERS> DecoderList;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,10 +26,11 @@
|
|||||||
#include "fs/CFile.hpp"
|
#include "fs/CFile.hpp"
|
||||||
#include "utils/utils.h"
|
#include "utils/utils.h"
|
||||||
#include <sounds/WavDecoder.hpp>
|
#include <sounds/WavDecoder.hpp>
|
||||||
#include <string.h>
|
#include <cstring>
|
||||||
|
|
||||||
WavDecoder::WavDecoder(const char *filepath)
|
|
||||||
: SoundDecoder(filepath) {
|
WavDecoder::WavDecoder(std::span<uint8_t> snd)
|
||||||
|
: SoundDecoder(snd) {
|
||||||
SoundType = SOUND_WAV;
|
SoundType = SOUND_WAV;
|
||||||
SampleRate = 48000;
|
SampleRate = 48000;
|
||||||
Format = CHANNELS_STEREO | FORMAT_PCM_16_BIT;
|
Format = CHANNELS_STEREO | FORMAT_PCM_16_BIT;
|
||||||
@ -41,21 +42,7 @@ WavDecoder::WavDecoder(const char *filepath)
|
|||||||
OpenFile();
|
OpenFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
WavDecoder::WavDecoder(const uint8_t *snd, int32_t len)
|
WavDecoder::~WavDecoder() = default;
|
||||||
: SoundDecoder(snd, len) {
|
|
||||||
SoundType = SOUND_WAV;
|
|
||||||
SampleRate = 48000;
|
|
||||||
Format = CHANNELS_STEREO | FORMAT_PCM_16_BIT;
|
|
||||||
|
|
||||||
if (!file_fd) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
OpenFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
WavDecoder::~WavDecoder() {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void WavDecoder::OpenFile() {
|
void WavDecoder::OpenFile() {
|
||||||
@ -111,10 +98,10 @@ void WavDecoder::OpenFile() {
|
|||||||
|
|
||||||
void WavDecoder::CloseFile() {
|
void WavDecoder::CloseFile() {
|
||||||
if (file_fd) {
|
if (file_fd) {
|
||||||
delete file_fd;
|
file_fd.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
file_fd = NULL;
|
file_fd = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t WavDecoder::Read(uint8_t *buffer, int32_t buffer_size, int32_t pos) {
|
int32_t WavDecoder::Read(uint8_t *buffer, int32_t buffer_size, int32_t pos) {
|
||||||
|
@ -52,13 +52,12 @@ typedef struct {
|
|||||||
|
|
||||||
class WavDecoder : public SoundDecoder {
|
class WavDecoder : public SoundDecoder {
|
||||||
public:
|
public:
|
||||||
WavDecoder(const char *filepath);
|
|
||||||
|
|
||||||
WavDecoder(const uint8_t *snd, int32_t len);
|
WavDecoder(std::span<uint8_t> snd);
|
||||||
|
|
||||||
virtual ~WavDecoder();
|
~WavDecoder() override;
|
||||||
|
|
||||||
int32_t Read(uint8_t *buffer, int32_t buffer_size, int32_t pos);
|
int32_t Read(uint8_t *buffer, int32_t buffer_size, int32_t pos) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void OpenFile();
|
void OpenFile();
|
||||||
|
@ -26,8 +26,8 @@ public:
|
|||||||
typedef void (*Callback)(CThread *thread, void *arg);
|
typedef void (*Callback)(CThread *thread, void *arg);
|
||||||
|
|
||||||
//! constructor
|
//! constructor
|
||||||
CThread(int32_t iAttr, int32_t iPriority = 16, int32_t iStackSize = 0x8000, CThread::Callback callback = NULL, void *callbackArg = NULL)
|
explicit CThread(int32_t iAttr, int32_t iPriority = 16, int32_t iStackSize = 0x8000, CThread::Callback callback = nullptr, void *callbackArg = nullptr)
|
||||||
: pThread(NULL), pThreadStack(NULL), pCallback(callback), pCallbackArg(callbackArg) {
|
: pThread(nullptr), pThreadStack(nullptr), pCallback(callback), pCallbackArg(callbackArg) {
|
||||||
//! save attribute assignment
|
//! save attribute assignment
|
||||||
iAttributes = iAttr;
|
iAttributes = iAttr;
|
||||||
//! allocate the thread
|
//! allocate the thread
|
||||||
@ -50,19 +50,19 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Get thread ID
|
//! Get thread ID
|
||||||
virtual void *getThread() const {
|
[[nodiscard]] virtual void *getThread() const {
|
||||||
return pThread;
|
return pThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Thread entry function
|
//! Thread entry function
|
||||||
virtual void executeThread(void) {
|
virtual void executeThread() {
|
||||||
if (pCallback) {
|
if (pCallback) {
|
||||||
pCallback(this, pCallbackArg);
|
pCallback(this, pCallbackArg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Suspend thread
|
//! Suspend thread
|
||||||
virtual void suspendThread(void) {
|
virtual void suspendThread() {
|
||||||
if (isThreadSuspended()) {
|
if (isThreadSuspended()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -72,7 +72,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Resume thread
|
//! Resume thread
|
||||||
virtual void resumeThread(void) {
|
virtual void resumeThread() {
|
||||||
if (!isThreadSuspended()) {
|
if (!isThreadSuspended()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -89,7 +89,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Check if thread is suspended
|
//! Check if thread is suspended
|
||||||
virtual bool isThreadSuspended(void) const {
|
[[nodiscard]] virtual bool isThreadSuspended() const {
|
||||||
if (pThread) {
|
if (pThread) {
|
||||||
return OSIsThreadSuspended(pThread);
|
return OSIsThreadSuspended(pThread);
|
||||||
}
|
}
|
||||||
@ -97,7 +97,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Check if thread is terminated
|
//! Check if thread is terminated
|
||||||
virtual bool isThreadTerminated(void) const {
|
[[maybe_unused]] virtual bool isThreadTerminated() const {
|
||||||
if (pThread) {
|
if (pThread) {
|
||||||
return OSIsThreadTerminated(pThread);
|
return OSIsThreadTerminated(pThread);
|
||||||
}
|
}
|
||||||
@ -105,19 +105,19 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Check if thread is running
|
//! Check if thread is running
|
||||||
virtual bool isThreadRunning(void) const {
|
[[nodiscard]] virtual bool isThreadRunning() const {
|
||||||
return !isThreadSuspended() && !isThreadRunning();
|
return !isThreadSuspended() && !isThreadRunning();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Shutdown thread
|
//! Shutdown thread
|
||||||
virtual void shutdownThread(void) {
|
virtual void shutdownThread() {
|
||||||
//! wait for thread to finish
|
//! wait for thread to finish
|
||||||
if (pThread && !(iAttributes & eAttributeDetach)) {
|
if (pThread && !(iAttributes & eAttributeDetach)) {
|
||||||
if (isThreadSuspended()) {
|
if (isThreadSuspended()) {
|
||||||
resumeThread();
|
resumeThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
OSJoinThread(pThread, NULL);
|
OSJoinThread(pThread, nullptr);
|
||||||
}
|
}
|
||||||
//! free the thread stack buffer
|
//! free the thread stack buffer
|
||||||
if (pThreadStack) {
|
if (pThreadStack) {
|
||||||
@ -127,8 +127,8 @@ public:
|
|||||||
free(pThread);
|
free(pThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
pThread = NULL;
|
pThread = nullptr;
|
||||||
pThreadStack = NULL;
|
pThreadStack = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Thread attributes
|
//! Thread attributes
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
#include "AsyncExecutor.h"
|
|
||||||
#include "utils/logger.h"
|
|
||||||
|
|
||||||
AsyncExecutor *AsyncExecutor::instance = nullptr;
|
|
||||||
|
|
||||||
void AsyncExecutor::pushForDeleteInternal(GuiElement *ptr) {
|
|
||||||
deleteListMutex.lock();
|
|
||||||
deleteList.push(ptr);
|
|
||||||
deleteListMutex.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
AsyncExecutor::AsyncExecutor() {
|
|
||||||
thread = new std::thread([&]() {
|
|
||||||
while (!exitThread) {
|
|
||||||
mutex.lock();
|
|
||||||
bool emptyList = elements.empty();
|
|
||||||
auto it = elements.begin();
|
|
||||||
while (it != elements.end()) {
|
|
||||||
auto future = it;
|
|
||||||
auto status = future->wait_for(std::chrono::seconds(0));
|
|
||||||
if (status == std::future_status::ready) {
|
|
||||||
it = elements.erase(it);
|
|
||||||
} else {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!emptyList && elements.empty()) {
|
|
||||||
DEBUG_FUNCTION_LINE("All tasks are done");
|
|
||||||
}
|
|
||||||
mutex.unlock();
|
|
||||||
deleteListMutex.lock();
|
|
||||||
while (!deleteList.empty()) {
|
|
||||||
GuiElement *ptr = deleteList.front();
|
|
||||||
deleteList.pop();
|
|
||||||
delete ptr;
|
|
||||||
}
|
|
||||||
deleteListMutex.unlock();
|
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(16));
|
|
||||||
DCFlushRange((void *) &exitThread, sizeof(exitThread));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
AsyncExecutor::~AsyncExecutor() {
|
|
||||||
exitThread = true;
|
|
||||||
DCFlushRange((void *) &exitThread, sizeof(exitThread));
|
|
||||||
thread->join();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AsyncExecutor::executeInternal(std::function<void()> func) {
|
|
||||||
if (elements.size() > 10) {
|
|
||||||
DEBUG_FUNCTION_LINE("Warning, many tasks running currently");
|
|
||||||
//std::this_thread::sleep_for(std::chrono::milliseconds(16));
|
|
||||||
}
|
|
||||||
DEBUG_FUNCTION_LINE("Add new task");
|
|
||||||
mutex.lock();
|
|
||||||
elements.push_back(std::async(std::launch::async, func));
|
|
||||||
mutex.unlock();
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "utils/logger.h"
|
|
||||||
#include <coreinit/cache.h>
|
|
||||||
#include <future>
|
|
||||||
#include <gui/GuiElement.h>
|
|
||||||
#include <queue>
|
|
||||||
#include <thread>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class AsyncExecutor {
|
|
||||||
public:
|
|
||||||
static void pushForDelete(GuiElement *element) {
|
|
||||||
if (!instance) {
|
|
||||||
instance = new AsyncExecutor();
|
|
||||||
}
|
|
||||||
instance->pushForDeleteInternal(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void execute(std::function<void()> func) {
|
|
||||||
if (!instance) {
|
|
||||||
instance = new AsyncExecutor();
|
|
||||||
}
|
|
||||||
instance->executeInternal(func);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void destroyInstance() {
|
|
||||||
if (instance) {
|
|
||||||
delete instance;
|
|
||||||
instance = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static AsyncExecutor *instance;
|
|
||||||
|
|
||||||
AsyncExecutor();
|
|
||||||
|
|
||||||
~AsyncExecutor();
|
|
||||||
|
|
||||||
void pushForDeleteInternal(GuiElement *element);
|
|
||||||
|
|
||||||
void executeInternal(std::function<void()> func);
|
|
||||||
|
|
||||||
std::recursive_mutex mutex;
|
|
||||||
std::thread *thread;
|
|
||||||
volatile bool exitThread = false;
|
|
||||||
|
|
||||||
std::vector<std::future<void>> elements;
|
|
||||||
|
|
||||||
std::recursive_mutex deleteListMutex;
|
|
||||||
std::queue<GuiElement *> deleteList;
|
|
||||||
};
|
|
38
src/utils/logger.cpp
Normal file
38
src/utils/logger.cpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#include "logger.h"
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <whb/log_cafe.h>
|
||||||
|
#include <whb/log_module.h>
|
||||||
|
#include <whb/log_udp.h>
|
||||||
|
|
||||||
|
uint32_t moduleLogInit = false;
|
||||||
|
uint32_t cafeLogInit = false;
|
||||||
|
uint32_t udpLogInit = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void initLogging() {
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (!(moduleLogInit = WHBLogModuleInit())) {
|
||||||
|
cafeLogInit = WHBLogCafeInit();
|
||||||
|
udpLogInit = WHBLogUdpInit();
|
||||||
|
}
|
||||||
|
#endif // DEBUG
|
||||||
|
}
|
||||||
|
|
||||||
|
void deinitLogging() {
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (moduleLogInit) {
|
||||||
|
WHBLogModuleDeinit();
|
||||||
|
moduleLogInit = false;
|
||||||
|
}
|
||||||
|
if (cafeLogInit) {
|
||||||
|
WHBLogCafeDeinit();
|
||||||
|
cafeLogInit = false;
|
||||||
|
}
|
||||||
|
if (udpLogInit) {
|
||||||
|
WHBLogUdpDeinit();
|
||||||
|
udpLogInit = false;
|
||||||
|
}
|
||||||
|
#endif // DEBUG
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <coreinit/debug.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <whb/log.h>
|
#include <whb/log.h>
|
||||||
|
|
||||||
@ -7,18 +8,66 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define __FILENAME_X__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
|
#define LOG_APP_TYPE "A"
|
||||||
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILENAME_X__)
|
#define LOG_APP_NAME "launchiine"
|
||||||
|
|
||||||
#define DEBUG_FUNCTION_LINE(FMT, ARGS...) \
|
#define __FILENAME_X__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
|
||||||
do { \
|
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILENAME_X__)
|
||||||
WHBLogPrintf("[%23s]%30s@L%04d: " FMT "", __FILENAME__, __FUNCTION__, __LINE__, ##ARGS); \
|
|
||||||
|
#define LOG(LOG_FUNC, FMT, ARGS...) LOG_EX_DEFAULT(LOG_FUNC, "", "", FMT, ##ARGS)
|
||||||
|
|
||||||
|
#define LOG_EX_DEFAULT(LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ARGS...) LOG_EX(__FILENAME__, __FUNCTION__, __LINE__, LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ##ARGS)
|
||||||
|
|
||||||
|
#define LOG_EX(FILENAME, FUNCTION, LINE, LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ARGS...) \
|
||||||
|
do { \
|
||||||
|
LOG_FUNC("[(%s)%18s][%23s]%30s@L%04d: " LOG_LEVEL "" FMT "" LINE_END, LOG_APP_TYPE, LOG_APP_NAME, FILENAME, FUNCTION, LINE, ##ARGS); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define DEBUG_FUNCTION_LINE_WRITE(FMT, ARGS...) \
|
#ifdef DEBUG
|
||||||
do { \
|
|
||||||
WHBLogWritef("[%23s]%30s@L%04d: " FMT "", __FILENAME__, __FUNCTION__, __LINE__, ##ARGS); \
|
#ifdef VERBOSE_DEBUG
|
||||||
} while (0)
|
#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) LOG(WHBLogPrintf, FMT, ##ARGS)
|
||||||
|
#define DEBUG_FUNCTION_LINE_VERBOSE_EX(FILENAME, FUNCTION, LINE, FMT, ARGS...) LOG_EX(FILENAME, FUNCTION, LINE, WHBLogPrintf, "", "", FMT, ##ARGS);
|
||||||
|
#define DEBUG_FUNCTION_LINE_LOADER_VERBOSE(FMT, ARGS...) LOG_EX_DEFAULT(((void (*)(const char *, ...))((uint32_t *) 0x010028d0)), "", "\n", FMT, ##ARGS)
|
||||||
|
#else
|
||||||
|
#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) while (0)
|
||||||
|
#define DEBUG_FUNCTION_LINE_VERBOSE_EX(FMT, ARGS...) while (0)
|
||||||
|
#define DEBUG_FUNCTION_LINE_LOADER_VERBOSE(FMT, ARGS...) while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DEBUG_FUNCTION_LINE(FMT, ARGS...) LOG(WHBLogPrintf, FMT, ##ARGS)
|
||||||
|
|
||||||
|
#define DEBUG_FUNCTION_LINE_WRITE(FMT, ARGS...) LOG(WHBLogWritef, FMT, ##ARGS)
|
||||||
|
|
||||||
|
#define DEBUG_FUNCTION_LINE_WARN(FMT, ARGS...) LOG_EX_DEFAULT(WHBLogPrintf, "## WARN## ", "", FMT, ##ARGS)
|
||||||
|
#define DEBUG_FUNCTION_LINE_ERR(FMT, ARGS...) LOG_EX_DEFAULT(WHBLogPrintf, "##ERROR## ", "", FMT, ##ARGS)
|
||||||
|
#define DEBUG_FUNCTION_LINE_INFO(FMT, ARGS...) LOG_EX_DEFAULT(WHBLogPrintf, "## INFO## ", "", FMT, ##ARGS)
|
||||||
|
|
||||||
|
#define DEBUG_FUNCTION_LINE_ERR_LAMBDA(FILENAME, FUNCTION, LINE, FMT, ARGS...) LOG_EX(FILENAME, FUNCTION, LINE, WHBLogPrintf, "##ERROR## ", "", FMT, ##ARGS);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define DEBUG_FUNCTION_LINE_VERBOSE_EX(FMT, ARGS...) while (0)
|
||||||
|
|
||||||
|
#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) while (0)
|
||||||
|
|
||||||
|
#define DEBUG_FUNCTION_LINE_LOADER_VERBOSE(FMT, ARGS...) while (0)
|
||||||
|
|
||||||
|
#define DEBUG_FUNCTION_LINE(FMT, ARGS...) while (0)
|
||||||
|
|
||||||
|
#define DEBUG_FUNCTION_LINE_WRITE(FMT, ARGS...) while (0)
|
||||||
|
|
||||||
|
#define DEBUG_FUNCTION_LINE_WARN(FMT, ARGS...) LOG_EX_DEFAULT(OSReport, "## WARN## ", "\n", FMT, ##ARGS)
|
||||||
|
#define DEBUG_FUNCTION_LINE_ERR(FMT, ARGS...) LOG_EX_DEFAULT(OSReport, "##ERROR## ", "\n", FMT, ##ARGS)
|
||||||
|
#define DEBUG_FUNCTION_LINE_INFO(FMT, ARGS...) LOG_EX_DEFAULT(OSReport, "## INFO## ", "\n", FMT, ##ARGS)
|
||||||
|
|
||||||
|
#define DEBUG_FUNCTION_LINE_ERR_LAMBDA(FILENAME, FUNCTION, LINE, FMT, ARGS...) LOG_EX(FILENAME, FUNCTION, LINE, OSReport, "##ERROR## ", "\n", FMT, ##ARGS);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void initLogging();
|
||||||
|
|
||||||
|
void deinitLogging();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
|
#include <cstdio>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <stdarg.h>
|
#include <string_view>
|
||||||
#include <stddef.h>
|
#include <sys/stat.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <utils/logger.h>
|
#include <utils/logger.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
// https://gist.github.com/ccbrown/9722406
|
// https://gist.github.com/ccbrown/9722406
|
||||||
void dumpHex(const void *data, size_t size) {
|
void dumpHex(const void *data, size_t size) {
|
||||||
@ -39,3 +38,27 @@ void dumpHex(const void *data, size_t size) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Utils {
|
||||||
|
bool LoadFileIntoBuffer(std::string_view path, std::vector<uint8_t> &buffer) {
|
||||||
|
struct stat st {};
|
||||||
|
if (stat(path.data(), &st) < 0 || !S_ISREG(st.st_mode)) {
|
||||||
|
DEBUG_FUNCTION_LINE_INFO("\"%s\" doesn't exists", path.data());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *f = fopen(path.data(), "rb");
|
||||||
|
if (!f) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
buffer.resize(st.st_size);
|
||||||
|
|
||||||
|
if (fread(buffer.data(), 1, st.st_size, f) != st.st_size) {
|
||||||
|
DEBUG_FUNCTION_LINE_WARN("Failed load %s", path.data());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} // namespace Utils
|
@ -2,6 +2,8 @@
|
|||||||
#define __UTILS_H_
|
#define __UTILS_H_
|
||||||
|
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -16,21 +18,29 @@ extern "C" {
|
|||||||
: (_x)); \
|
: (_x)); \
|
||||||
})
|
})
|
||||||
|
|
||||||
#define DegToRad(a) ((a) *0.01745329252f)
|
#define DegToRad(a) ((a) * 0.01745329252f)
|
||||||
#define RadToDeg(a) ((a) *57.29577951f)
|
#define RadToDeg(a) ((a) * 57.29577951f)
|
||||||
|
|
||||||
#define ALIGN4(x) (((x) + 3) & ~3)
|
#define ALIGN4(x) (((x) + 3) & ~3)
|
||||||
#define ALIGN32(x) (((x) + 31) & ~31)
|
#define ALIGN32(x) (((x) + 31) & ~31)
|
||||||
|
|
||||||
#define le16(i) ((((uint16_t) ((i) &0xFF)) << 8) | ((uint16_t) (((i) &0xFF00) >> 8)))
|
#define le16(i) ((((uint16_t) ((i) & 0xFF)) << 8) | ((uint16_t) (((i) & 0xFF00) >> 8)))
|
||||||
#define le32(i) ((((uint32_t) le16((i) &0xFFFF)) << 16) | ((uint32_t) le16(((i) &0xFFFF0000) >> 16)))
|
#define le32(i) ((((uint32_t) le16((i) & 0xFFFF)) << 16) | ((uint32_t) le16(((i) & 0xFFFF0000) >> 16)))
|
||||||
#define le64(i) ((((uint64_t) le32((i) &0xFFFFFFFFLL)) << 32) | ((uint64_t) le32(((i) &0xFFFFFFFF00000000LL) >> 32)))
|
#define le64(i) ((((uint64_t) le32((i) & 0xFFFFFFFFLL)) << 32) | ((uint64_t) le32(((i) & 0xFFFFFFFF00000000LL) >> 32)))
|
||||||
|
|
||||||
//Needs to have log_init() called beforehand.
|
//Needs to have log_init() called beforehand.
|
||||||
void dumpHex(const void *data, size_t size);
|
void dumpHex(const void *data, size_t size);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
namespace Utils {
|
||||||
|
bool LoadFileIntoBuffer(std::string_view path, std::vector<uint8_t> &buffer);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // __UTILS_H_
|
#endif // __UTILS_H_
|
||||||
|
@ -1,83 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* Copyright (C) 2016,2017 Maschell
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*
|
|
||||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
****************************************************************************/
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <video/CursorDrawer.h>
|
|
||||||
#include <video/shaders/ColorShader.h>
|
|
||||||
#include <video/shaders/FXAAShader.h>
|
|
||||||
#include <video/shaders/Shader3D.h>
|
|
||||||
#include <video/shaders/ShaderFractalColor.h>
|
|
||||||
#include <video/shaders/Texture2DShader.h>
|
|
||||||
|
|
||||||
CursorDrawer *CursorDrawer::instance = NULL;
|
|
||||||
|
|
||||||
CursorDrawer::CursorDrawer() {
|
|
||||||
init_colorVtxs();
|
|
||||||
}
|
|
||||||
|
|
||||||
CursorDrawer::~CursorDrawer() {
|
|
||||||
//! destroy shaders
|
|
||||||
ColorShader::destroyInstance();
|
|
||||||
FXAAShader::destroyInstance();
|
|
||||||
Shader3D::destroyInstance();
|
|
||||||
ShaderFractalColor::destroyInstance();
|
|
||||||
Texture2DShader::destroyInstance();
|
|
||||||
if (this->colorVtxs) {
|
|
||||||
free(this->colorVtxs);
|
|
||||||
this->colorVtxs = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CursorDrawer::init_colorVtxs() {
|
|
||||||
if (!this->colorVtxs) {
|
|
||||||
this->colorVtxs = (uint8_t *) memalign(0x40, sizeof(uint8_t) * 16);
|
|
||||||
if (this->colorVtxs == NULL) { return; }
|
|
||||||
}
|
|
||||||
memset(this->colorVtxs, 0xFF, 16 * sizeof(uint8_t));
|
|
||||||
|
|
||||||
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, this->colorVtxs, 16 * sizeof(uint8_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Could be improved. It be more generic.
|
|
||||||
void CursorDrawer::draw_Cursor(float x, float y) {
|
|
||||||
if (this->colorVtxs == NULL) {
|
|
||||||
init_colorVtxs();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
float widthScaleFactor = 1.0f / (float) 1280;
|
|
||||||
float heightScaleFactor = 1.0f / (float) 720;
|
|
||||||
|
|
||||||
int32_t width = 20;
|
|
||||||
|
|
||||||
glm::vec3 positionOffsets = glm::vec3(0.0f);
|
|
||||||
|
|
||||||
positionOffsets[0] = (x - ((1280) / 2) + (width / 2)) * widthScaleFactor * 2.0f;
|
|
||||||
positionOffsets[1] = -(y - ((720) / 2) + (width / 2)) * heightScaleFactor * 2.0f;
|
|
||||||
|
|
||||||
glm::vec3 scale(width * widthScaleFactor, width * heightScaleFactor, 1.0f);
|
|
||||||
|
|
||||||
ColorShader::instance()->setShaders();
|
|
||||||
ColorShader::instance()->setAttributeBuffer(this->colorVtxs, NULL, 4);
|
|
||||||
ColorShader::instance()->setAngle(0);
|
|
||||||
ColorShader::instance()->setOffset(positionOffsets);
|
|
||||||
ColorShader::instance()->setScale(scale);
|
|
||||||
ColorShader::instance()->setColorIntensity(glm::vec4(1.0f));
|
|
||||||
ColorShader::instance()->draw(GX2_PRIMITIVE_MODE_QUADS, 4);
|
|
||||||
}
|
|
@ -1,64 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* Copyright (C) 2016,2017 Maschell
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*
|
|
||||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
****************************************************************************/
|
|
||||||
#ifndef _CursorDrawer_H_
|
|
||||||
#define _CursorDrawer_H_
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
class CursorDrawer {
|
|
||||||
|
|
||||||
public:
|
|
||||||
static CursorDrawer *getInstance() {
|
|
||||||
if (!instance) {
|
|
||||||
instance = new CursorDrawer();
|
|
||||||
}
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void destroyInstance() {
|
|
||||||
if (instance) {
|
|
||||||
delete instance;
|
|
||||||
instance = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void draw(float x, float y) {
|
|
||||||
CursorDrawer *cur_instance = getInstance();
|
|
||||||
if (cur_instance == NULL) { return; }
|
|
||||||
cur_instance->draw_Cursor(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
//!Constructor
|
|
||||||
CursorDrawer();
|
|
||||||
|
|
||||||
//!Destructor
|
|
||||||
~CursorDrawer();
|
|
||||||
|
|
||||||
static CursorDrawer *instance;
|
|
||||||
|
|
||||||
void draw_Cursor(float x, float y);
|
|
||||||
|
|
||||||
void init_colorVtxs();
|
|
||||||
|
|
||||||
uint8_t *colorVtxs = NULL;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -101,7 +101,7 @@ static const uint32_t cpPixelShaderRegs[] = {
|
|||||||
0x00000000, 0x0000000f, 0x00000001, 0x00000010,
|
0x00000000, 0x0000000f, 0x00000001, 0x00000010,
|
||||||
0x00000000};
|
0x00000000};
|
||||||
|
|
||||||
ColorShader *ColorShader::shaderInstance = NULL;
|
ColorShader *ColorShader::shaderInstance = nullptr;
|
||||||
|
|
||||||
ColorShader::ColorShader()
|
ColorShader::ColorShader()
|
||||||
: vertexShader(cuAttributeCount) {
|
: vertexShader(cuAttributeCount) {
|
||||||
|
@ -36,9 +36,8 @@ public:
|
|||||||
if (fetchShaderProgramm) {
|
if (fetchShaderProgramm) {
|
||||||
free(fetchShaderProgramm);
|
free(fetchShaderProgramm);
|
||||||
}
|
}
|
||||||
if (fetchShader) {
|
|
||||||
delete fetchShader;
|
delete fetchShader;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GX2FetchShader *getFetchShader() const {
|
GX2FetchShader *getFetchShader() const {
|
||||||
|
@ -269,13 +269,13 @@ Texture2DShader::Texture2DShader()
|
|||||||
Texture2DShader::~Texture2DShader() {
|
Texture2DShader::~Texture2DShader() {
|
||||||
if (posVtxs) {
|
if (posVtxs) {
|
||||||
free(posVtxs);
|
free(posVtxs);
|
||||||
posVtxs = NULL;
|
posVtxs = nullptr;
|
||||||
}
|
}
|
||||||
if (texCoords) {
|
if (texCoords) {
|
||||||
free(texCoords);
|
free(texCoords);
|
||||||
texCoords = NULL;
|
texCoords = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete fetchShader;
|
delete fetchShader;
|
||||||
fetchShader = NULL;
|
fetchShader = nullptr;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user