mirror of
https://github.com/wiiu-env/launchiine.git
synced 2024-11-25 11:16:51 +01:00
- Actually displaying installed title now
- Try to clean up the async stuff when the vector gets bigger
This commit is contained in:
parent
4c4fbcfb2e
commit
d97d5ed325
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,3 +3,4 @@
|
||||
*.rpx
|
||||
build/
|
||||
src/resources/filelist.h
|
||||
*.save-failed
|
||||
|
1
Makefile
1
Makefile
@ -21,6 +21,7 @@ TARGET := $(notdir $(CURDIR))
|
||||
BUILD := build
|
||||
SOURCES := src \
|
||||
src/fs \
|
||||
src/game \
|
||||
src/gui \
|
||||
src/menu \
|
||||
src/resources \
|
||||
|
BIN
data/images/noGameIcon.png
Normal file
BIN
data/images/noGameIcon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.1 KiB |
@ -6,6 +6,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#define LAUNCHIINE_VERSION "v0.1"
|
||||
#define META_PATH "/meta"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
202
src/game/GameList.cpp
Normal file
202
src/game/GameList.cpp
Normal file
@ -0,0 +1,202 @@
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include <coreinit/mcp.h>
|
||||
#include <nn/acp/nn_acp_types.h>
|
||||
#include <coreinit/cache.h>
|
||||
|
||||
#include "utils/AsyncExecutor.h"
|
||||
#include "GameList.h"
|
||||
#include "common/common.h"
|
||||
|
||||
#include "fs/DirList.h"
|
||||
#include "fs/FSUtils.h"
|
||||
#include "utils/logger.h"
|
||||
#include "utils/StringTools.h"
|
||||
|
||||
void GameList::clear() {
|
||||
for (auto const& x : fullGameList) {
|
||||
if(x != NULL) {
|
||||
if(x->imageData != NULL) {
|
||||
DEBUG_FUNCTION_LINE("Delete the image data\n");
|
||||
delete x->imageData;
|
||||
x->imageData = NULL;
|
||||
}
|
||||
delete x;
|
||||
}
|
||||
}
|
||||
gameFilter.clear();
|
||||
fullGameList.clear();
|
||||
filteredList.clear();
|
||||
//! Clear memory of the vector completely
|
||||
std::vector<gameInfo *>().swap(filteredList);
|
||||
std::vector<gameInfo*>().swap(fullGameList);
|
||||
titleListChanged(this);
|
||||
}
|
||||
|
||||
|
||||
gameInfo * GameList::getGameInfo(uint64_t titleId) const {
|
||||
for (uint32_t i = 0; i < filteredList.size(); ++i) {
|
||||
if(titleId == filteredList[i]->titleId)
|
||||
return filteredList[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern "C" int ACPGetTitleMetaXml(uint64_t titleid, ACPMetaXml*);
|
||||
int32_t GameList::readGameList() {
|
||||
// Clear list
|
||||
for (auto const& x : fullGameList) {
|
||||
delete x;
|
||||
}
|
||||
|
||||
fullGameList.clear();
|
||||
//! Clear memory of the vector completely
|
||||
std::vector<gameInfo*>().swap(fullGameList);
|
||||
|
||||
int32_t cnt = 0;
|
||||
|
||||
MCPError mcp = MCP_Open();
|
||||
if (mcp < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
MCPError titleCount = MCP_TitleCount(mcp);
|
||||
if (titleCount < 0) {
|
||||
MCP_Close(mcp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<struct MCPTitleListType> titles(titleCount);
|
||||
uint32_t realTitleCount;
|
||||
|
||||
MCPError err = MCP_TitleList(mcp, &realTitleCount, titles.data(), titles.size() * sizeof(decltype(titles)::value_type));
|
||||
if (err < 0) {
|
||||
MCP_Close(mcp);
|
||||
return 0;
|
||||
}
|
||||
if (realTitleCount != titles.size()) {
|
||||
titles.resize(realTitleCount);
|
||||
}
|
||||
|
||||
for (auto title_candidate : titles) {
|
||||
if(true || (title_candidate.titleId & 0xFFFFFFFF00000000L) == 0x0005000000000000L) {
|
||||
gameInfo* newGameInfo = new gameInfo;
|
||||
newGameInfo->titleId = title_candidate.titleId;
|
||||
newGameInfo->gamePath = title_candidate.path;
|
||||
newGameInfo->name = "<unknown>";
|
||||
newGameInfo->imageData = NULL;
|
||||
DCFlushRange(newGameInfo, sizeof(gameInfo));
|
||||
fullGameList.push_back(newGameInfo);
|
||||
titleAdded(newGameInfo);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
void GameList::loadIcons() {
|
||||
for (int i = 0; i < this->size(); i++) {
|
||||
gameInfo * newHeader = this->at(i);
|
||||
|
||||
ACPMetaXml* meta = (ACPMetaXml*)calloc(1, 0x4000); //TODO fix wut
|
||||
if(meta) {
|
||||
auto acp = ACPGetTitleMetaXml(newHeader->titleId, meta);
|
||||
if(acp >= 0) {
|
||||
newHeader->name = meta->shortname_en;
|
||||
}
|
||||
free(meta);
|
||||
}
|
||||
|
||||
if(newHeader->imageData == NULL) {
|
||||
std::string filepath = "fs:" + newHeader->gamePath + META_PATH + "/iconTex.tga";
|
||||
uint8_t *buffer = NULL;
|
||||
uint32_t bufferSize = 0;
|
||||
int iResult = FSUtils::LoadFileToMem(filepath.c_str(), &buffer, &bufferSize);
|
||||
|
||||
if(iResult > 0) {
|
||||
GuiImageData * imageData = new GuiImageData(buffer, bufferSize, GX2_TEX_CLAMP_MODE_MIRROR);
|
||||
if(imageData) {
|
||||
newHeader->imageData = imageData;
|
||||
}
|
||||
|
||||
//! free original image buffer which is converted to texture now and not needed anymore
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
DCFlushRange(newHeader, sizeof(gameInfo));
|
||||
titleUpdated(newHeader);
|
||||
}
|
||||
}
|
||||
|
||||
void GameList::internalFilterList(std::vector<gameInfo*> &fullList) {
|
||||
for (uint32_t i = 0; i < fullList.size(); ++i) {
|
||||
gameInfo *header = fullList[i];
|
||||
|
||||
//! TODO: do filtering as needed
|
||||
|
||||
filteredList.push_back(header);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t GameList::filterList(const char * filter) {
|
||||
if(filter) {
|
||||
gameFilter = filter;
|
||||
}
|
||||
|
||||
if(fullGameList.size() == 0) {
|
||||
readGameList();
|
||||
}
|
||||
|
||||
filteredList.clear();
|
||||
|
||||
// Filter current game list if selected
|
||||
internalFilterList(fullGameList);
|
||||
|
||||
sortList();
|
||||
|
||||
titleListChanged(this);
|
||||
|
||||
AsyncExecutor::execute([&] { loadIcons();});
|
||||
|
||||
return filteredList.size();
|
||||
}
|
||||
|
||||
void GameList::internalLoadUnfiltered(std::vector<gameInfo*> & fullList) {
|
||||
for (uint32_t i = 0; i < fullList.size(); ++i) {
|
||||
gameInfo *header = fullList[i];
|
||||
|
||||
filteredList.push_back(header);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t GameList::loadUnfiltered() {
|
||||
if(fullGameList.size() == 0) {
|
||||
readGameList();
|
||||
}
|
||||
|
||||
gameFilter.clear();
|
||||
filteredList.clear();
|
||||
|
||||
// Filter current game list if selected
|
||||
internalLoadUnfiltered(fullGameList);
|
||||
|
||||
sortList();
|
||||
|
||||
AsyncExecutor::execute([&] { loadIcons();});
|
||||
|
||||
titleListChanged(this);
|
||||
|
||||
return filteredList.size();
|
||||
}
|
||||
|
||||
void GameList::sortList() {
|
||||
std::sort(filteredList.begin(), filteredList.end(), nameSortCallback);
|
||||
}
|
||||
|
||||
bool GameList::nameSortCallback(const gameInfo *a, const gameInfo *b) {
|
||||
return (strcasecmp(((gameInfo *) a)->name.c_str(), ((gameInfo *) b)->name.c_str()) < 0);
|
||||
}
|
||||
|
102
src/game/GameList.h
Normal file
102
src/game/GameList.h
Normal file
@ -0,0 +1,102 @@
|
||||
#ifndef GAME_LIST_H_
|
||||
#define GAME_LIST_H_
|
||||
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include <coreinit/mcp.h>
|
||||
#include <gui/sigslot.h>
|
||||
#include <gui/GuiImageData.h>
|
||||
|
||||
typedef struct _gameInfo {
|
||||
uint64_t titleId;
|
||||
std::string name;
|
||||
std::string gamePath;
|
||||
GuiImageData * imageData;
|
||||
} gameInfo;
|
||||
|
||||
class GameList {
|
||||
public:
|
||||
GameList() : selectedGame(0) { };
|
||||
~GameList() { clear(); };
|
||||
|
||||
int32_t size() const {
|
||||
return filteredList.size();
|
||||
}
|
||||
int32_t gameCount() const {
|
||||
return fullGameList.size();
|
||||
}
|
||||
int32_t filterList(const char * gameFilter = NULL);
|
||||
int32_t loadUnfiltered();
|
||||
|
||||
gameInfo * at(int32_t i) const {
|
||||
return operator[](i);
|
||||
}
|
||||
gameInfo * operator[](int32_t i) const {
|
||||
if (i < 0 || i >= (int32_t) filteredList.size())
|
||||
return NULL;
|
||||
return filteredList[i];
|
||||
}
|
||||
gameInfo * getGameInfo(uint64_t titleId) const;
|
||||
|
||||
const char * getCurrentFilter() const {
|
||||
return gameFilter.c_str();
|
||||
}
|
||||
void sortList();
|
||||
void clear();
|
||||
bool operator!() const {
|
||||
return (fullGameList.size() == 0);
|
||||
}
|
||||
|
||||
//! Gamelist scrolling operators
|
||||
int32_t operator+=(int32_t i) {
|
||||
return (selectedGame = (selectedGame+i) % filteredList.size());
|
||||
}
|
||||
int32_t operator-=(int32_t i) {
|
||||
return (selectedGame = (selectedGame-i+filteredList.size()) % filteredList.size());
|
||||
}
|
||||
int32_t operator++() {
|
||||
return (selectedGame = (selectedGame+1) % filteredList.size());
|
||||
}
|
||||
int32_t operator--() {
|
||||
return (selectedGame = (selectedGame-1+filteredList.size()) % filteredList.size());
|
||||
}
|
||||
int32_t operator++(int32_t i) {
|
||||
return operator++();
|
||||
}
|
||||
int32_t operator--(int32_t i) {
|
||||
return operator--();
|
||||
}
|
||||
gameInfo * GetCurrentSelected() const {
|
||||
return operator[](selectedGame);
|
||||
}
|
||||
|
||||
std::vector<gameInfo *> & getfilteredList(void) {
|
||||
return filteredList;
|
||||
}
|
||||
std::vector<gameInfo *> & getFullGameList(void) {
|
||||
return fullGameList;
|
||||
}
|
||||
|
||||
sigslot::signal1<GameList *> titleListChanged;
|
||||
sigslot::signal1<gameInfo *> titleUpdated;
|
||||
sigslot::signal1<gameInfo *> titleAdded;
|
||||
protected:
|
||||
|
||||
int32_t readGameList();
|
||||
|
||||
void internalFilterList(std::vector<gameInfo*> & fullList);
|
||||
void internalLoadUnfiltered(std::vector<gameInfo*> & fullList);
|
||||
|
||||
void loadIcons();
|
||||
|
||||
static bool nameSortCallback(const gameInfo *a, const gameInfo *b);
|
||||
|
||||
static GameList *gameListInstance;
|
||||
|
||||
std::string gameFilter;
|
||||
int32_t selectedGame;
|
||||
std::vector<gameInfo *> filteredList;
|
||||
std::vector<gameInfo *> fullGameList;
|
||||
};
|
||||
|
||||
#endif
|
@ -16,31 +16,155 @@
|
||||
****************************************************************************/
|
||||
#include <gui/GuiIconGrid.h>
|
||||
#include <gui/GuiController.h>
|
||||
#include <coreinit/cache.h>
|
||||
#include "common/common.h"
|
||||
#include "Application.h"
|
||||
#include <gui/video/CVideo.h>
|
||||
#include "utils/logger.h"
|
||||
|
||||
GuiIconGrid::GuiIconGrid(int32_t w, int32_t h, int32_t GameIndex)
|
||||
GuiIconGrid::GuiIconGrid(int32_t w, int32_t h, uint64_t GameIndex)
|
||||
: GuiTitleBrowser(w, h, GameIndex),
|
||||
particleBgImage(w, h, 50, 60.0f, 90.0f, 0.6f, 1.0f) {
|
||||
particleBgImage(w, h, 50, 60.0f, 90.0f, 0.6f, 1.0f)
|
||||
, touchTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::VPAD_TOUCH)
|
||||
, wpadTouchTrigger(GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5, GuiTrigger::BUTTON_A)
|
||||
, noIcon(Resources::GetFile("noGameIcon.png"), Resources::GetFileSize("noGameIcon.png"), GX2_TEX_CLAMP_MODE_MIRROR) {
|
||||
append(&particleBgImage);
|
||||
|
||||
selectedGame = GameIndex;
|
||||
listOffset = selectedGame / (MAX_COLS * MAX_ROWS);
|
||||
targetLeftPosition = -listOffset * getWidth();
|
||||
currentLeftPosition = targetLeftPosition;
|
||||
}
|
||||
|
||||
GuiIconGrid::~GuiIconGrid() {
|
||||
|
||||
containerMutex.lock();
|
||||
for (auto const& x : gameInfoContainers) {
|
||||
remove(x.second->button);
|
||||
delete x.second;
|
||||
}
|
||||
gameInfoContainers.clear();
|
||||
containerMutex.unlock();
|
||||
}
|
||||
|
||||
void GuiIconGrid::setSelectedGame(int32_t idx) {
|
||||
void GuiIconGrid::setSelectedGame(uint64_t idx) {
|
||||
this->selectedGame = idx;
|
||||
}
|
||||
|
||||
int32_t GuiIconGrid::getSelectedGame(void) {
|
||||
uint64_t GuiIconGrid::getSelectedGame(void) {
|
||||
return selectedGame;
|
||||
}
|
||||
|
||||
void GuiIconGrid::OnGameTitleListUpdated(GameList * gameList) {
|
||||
containerMutex.lock();
|
||||
for(int32_t i = 0; i < gameList->size(); i++) {
|
||||
gameInfo * info = gameList->at(i);
|
||||
GameInfoContainer * container = NULL;
|
||||
|
||||
for (auto const& x : gameInfoContainers) {
|
||||
if(info->titleId == x.first) {
|
||||
container = x.second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(container == NULL) {
|
||||
OnGameTitleAdded(info);
|
||||
}
|
||||
}
|
||||
containerMutex.unlock();
|
||||
bUpdatePositions = true;
|
||||
}
|
||||
|
||||
void GuiIconGrid::OnLaunchClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger) {
|
||||
//! do not auto launch when wiimote is pointing to screen and presses A
|
||||
//if((trigger == &buttonATrigger) && (controller->chan & (GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5)) && controller->data.validPointer) {
|
||||
// return;
|
||||
//}
|
||||
DEBUG_FUNCTION_LINE("Tried to launch %s (%016llX)\n", gameInfoContainers[getSelectedGame()]->info->name.c_str(),getSelectedGame());
|
||||
gameLaunchClicked(this, getSelectedGame());
|
||||
}
|
||||
|
||||
|
||||
void GuiIconGrid::OnGameButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger) {
|
||||
containerMutex.lock();
|
||||
for (auto const& x : gameInfoContainers) {
|
||||
if(x.second->button == button) {
|
||||
if(selectedGame == (x.second->info->titleId)) {
|
||||
if(gameLaunchTimer < 30)
|
||||
OnLaunchClick(button, controller, trigger);
|
||||
} else {
|
||||
setSelectedGame(x.second->info->titleId);
|
||||
gameSelectionChanged(this, selectedGame);
|
||||
}
|
||||
gameLaunchTimer = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
containerMutex.unlock();
|
||||
}
|
||||
|
||||
void GuiIconGrid::OnGameTitleAdded(gameInfo * info) {
|
||||
DEBUG_FUNCTION_LINE("Adding %016llX\n", info->titleId);
|
||||
GuiImage * image = new GuiImage(&noIcon);
|
||||
GuiButton * button = new GuiButton(noIcon.getWidth(), noIcon.getHeight());
|
||||
button->setImage(image);
|
||||
button->setPosition(0, 0);
|
||||
button->setEffectGrow();
|
||||
button->setTrigger(&touchTrigger);
|
||||
button->setTrigger(&wpadTouchTrigger);
|
||||
button->setSoundClick(buttonClickSound);
|
||||
//button->setClickable( (idx < gameList->size()) );
|
||||
//button->setSelectable( (idx < gameList->size()) );
|
||||
button->clicked.connect(this, &GuiIconGrid::OnGameButtonClick);
|
||||
|
||||
GameInfoContainer * container = new GameInfoContainer(button, image, info);
|
||||
containerMutex.lock();
|
||||
gameInfoContainers[info->titleId] = container;
|
||||
containerMutex.unlock();
|
||||
this->append(button);
|
||||
|
||||
bUpdatePositions = true;
|
||||
}
|
||||
void GuiIconGrid::OnGameTitleUpdated(gameInfo * info) {
|
||||
DEBUG_FUNCTION_LINE("Updating infos of %016llX\n", info->titleId);
|
||||
GameInfoContainer * container = NULL;
|
||||
containerMutex.lock();
|
||||
for (auto const& x : gameInfoContainers) {
|
||||
if(info->titleId == x.first) {
|
||||
container = x.second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(container != NULL) {
|
||||
container->updateImageData();
|
||||
}
|
||||
containerMutex.unlock();
|
||||
bUpdatePositions = true;
|
||||
}
|
||||
|
||||
void GuiIconGrid::process() {
|
||||
if(currentLeftPosition < targetLeftPosition) {
|
||||
currentLeftPosition += 35;
|
||||
|
||||
if(currentLeftPosition > targetLeftPosition)
|
||||
currentLeftPosition = targetLeftPosition;
|
||||
|
||||
bUpdatePositions = true;
|
||||
} else if(currentLeftPosition > targetLeftPosition) {
|
||||
currentLeftPosition -= 35;
|
||||
|
||||
if(currentLeftPosition < targetLeftPosition)
|
||||
currentLeftPosition = targetLeftPosition;
|
||||
|
||||
bUpdatePositions = true;
|
||||
}
|
||||
|
||||
if(bUpdatePositions) {
|
||||
bUpdatePositions = false;
|
||||
updateButtonPositions();
|
||||
}
|
||||
gameLaunchTimer++;
|
||||
|
||||
GuiFrame::process();
|
||||
}
|
||||
|
||||
@ -48,6 +172,37 @@ void GuiIconGrid::update(GuiController * c) {
|
||||
GuiFrame::update(c);
|
||||
}
|
||||
|
||||
void GuiIconGrid::draw(CVideo *pVideo) {
|
||||
GuiFrame::draw(pVideo);
|
||||
void GuiIconGrid::updateButtonPositions() {
|
||||
int32_t col = 0, row = 0, listOff = 0;
|
||||
|
||||
int i = 0;
|
||||
containerMutex.lock();
|
||||
for (auto const& x : gameInfoContainers) {
|
||||
|
||||
listOff = i / (MAX_COLS * MAX_ROWS);
|
||||
|
||||
float posX = currentLeftPosition + listOff * width + ( col * (noIcon.getWidth() + noIcon.getWidth() * 0.5f) - (MAX_COLS * 0.5f - 0.5f) * (noIcon.getWidth() + noIcon.getWidth() * 0.5f) );
|
||||
float posY = -row * (noIcon.getHeight() + noIcon.getHeight() * 0.5f) + (MAX_ROWS * 0.5f - 0.5f) * (noIcon.getHeight() + noIcon.getHeight() * 0.5f) + 30.0f;
|
||||
|
||||
if(x.second->button != NULL) {
|
||||
x.second->button->setPosition(posX, posY);
|
||||
}
|
||||
|
||||
col++;
|
||||
if(col >= MAX_COLS) {
|
||||
col = 0;
|
||||
row++;
|
||||
}
|
||||
if(row >= MAX_ROWS)
|
||||
row = 0;
|
||||
|
||||
i++;
|
||||
}
|
||||
containerMutex.unlock();
|
||||
}
|
||||
|
||||
void GuiIconGrid::draw(CVideo *pVideo) {
|
||||
containerMutex.lock();
|
||||
GuiFrame::draw(pVideo);
|
||||
containerMutex.unlock();
|
||||
}
|
||||
|
@ -19,25 +19,77 @@
|
||||
#include <map>
|
||||
#include "gui/GuiTitleBrowser.h"
|
||||
#include <gui/GuiParticleImage.h>
|
||||
#include "utils/AsyncExecutor.h"
|
||||
#include "utils/logger.h"
|
||||
|
||||
class GuiIconGrid : public GuiTitleBrowser, public sigslot::has_slots<> {
|
||||
public:
|
||||
GuiIconGrid(int32_t w, int32_t h, int32_t GameIndex);
|
||||
GuiIconGrid(int32_t w, int32_t h, uint64_t selectedTitleId);
|
||||
virtual ~GuiIconGrid();
|
||||
|
||||
void setSelectedGame(int32_t idx);
|
||||
int32_t getSelectedGame(void);
|
||||
void setSelectedGame(uint64_t idx);
|
||||
uint64_t getSelectedGame(void);
|
||||
|
||||
void update(GuiController * t);
|
||||
void draw(CVideo *pVideo);
|
||||
void process();
|
||||
|
||||
void OnGameTitleListUpdated(GameList * list);
|
||||
void OnAddGameTitle(gameInfo * info);
|
||||
void OnGameTitleUpdated(gameInfo * info);
|
||||
void OnGameTitleAdded(gameInfo * info);
|
||||
private:
|
||||
static const int32_t MAX_ROWS = 3;
|
||||
static const int32_t MAX_COLS = 5;
|
||||
|
||||
GuiSound *buttonClickSound;
|
||||
|
||||
int32_t selectedGame = 0;
|
||||
|
||||
GuiParticleImage particleBgImage;
|
||||
|
||||
GuiTrigger touchTrigger;
|
||||
GuiTrigger wpadTouchTrigger;
|
||||
|
||||
GuiImageData noIcon;
|
||||
|
||||
void OnLaunchClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);
|
||||
void OnGameButtonClick(GuiButton *button, const GuiController *controller, GuiTrigger *trigger);
|
||||
void updateButtonPositions();
|
||||
|
||||
int32_t listOffset;
|
||||
uint64_t selectedGame;
|
||||
int32_t currentLeftPosition;
|
||||
int32_t targetLeftPosition;
|
||||
uint32_t gameLaunchTimer;
|
||||
bool bUpdatePositions = false;
|
||||
|
||||
class GameInfoContainer {
|
||||
public:
|
||||
GameInfoContainer(GuiButton* button, GuiImage * image, gameInfo * info) {
|
||||
this->image = image;
|
||||
this->info = info;
|
||||
this->button = button;
|
||||
}
|
||||
|
||||
~GameInfoContainer() {
|
||||
if(button != NULL) {
|
||||
AsyncExecutor::pushForDelete(button);
|
||||
}
|
||||
if(image != NULL) {
|
||||
AsyncExecutor::pushForDelete(image);
|
||||
}
|
||||
}
|
||||
|
||||
void updateImageData() {
|
||||
if(image != NULL && info != NULL && info->imageData != NULL) {
|
||||
image->setImageData(info->imageData);
|
||||
}
|
||||
}
|
||||
|
||||
GuiImage * image;
|
||||
gameInfo * info;
|
||||
GuiButton * button;
|
||||
};
|
||||
|
||||
CMutex containerMutex;
|
||||
std::map<uint64_t, GameInfoContainer *> gameInfoContainers;
|
||||
};
|
||||
|
@ -2,15 +2,20 @@
|
||||
|
||||
#include <gui/Gui.h>
|
||||
#include <gui/sigslot.h>
|
||||
#include "game/GameList.h"
|
||||
|
||||
class GuiTitleBrowser : public GuiFrame {
|
||||
public:
|
||||
GuiTitleBrowser(int32_t w, int32_t h, int32_t GameIndex) : GuiFrame(w, h) {}
|
||||
GuiTitleBrowser(int32_t w, int32_t h, uint64_t GameIndex) : GuiFrame(w, h) {}
|
||||
virtual ~GuiTitleBrowser() {}
|
||||
|
||||
virtual void setSelectedGame(int32_t idx) = 0;
|
||||
virtual int32_t getSelectedGame(void) = 0;
|
||||
virtual void setSelectedGame(uint64_t idx) = 0;
|
||||
virtual uint64_t getSelectedGame(void) = 0;
|
||||
|
||||
sigslot::signal2<GuiTitleBrowser *, int32_t> gameLaunchClicked;
|
||||
sigslot::signal2<GuiTitleBrowser *, int32_t> gameSelectionChanged;
|
||||
virtual void OnGameTitleListUpdated(GameList * list) = 0;
|
||||
virtual void OnGameTitleUpdated(gameInfo * info) = 0;
|
||||
virtual void OnGameTitleAdded(gameInfo * info) = 0;
|
||||
|
||||
sigslot::signal2<GuiTitleBrowser *, uint64_t> gameLaunchClicked;
|
||||
sigslot::signal2<GuiTitleBrowser *, uint64_t> gameSelectionChanged;
|
||||
};
|
||||
|
@ -40,9 +40,15 @@ MainWindow::MainWindow(int32_t w, int32_t h)
|
||||
pointerValid[i] = false;
|
||||
}
|
||||
SetupMainView();
|
||||
gameList.titleListChanged.connect(this, &MainWindow::OnGameTitleListChanged);
|
||||
gameList.titleUpdated.connect(this, &MainWindow::OnGameTitleUpdated);
|
||||
gameList.titleAdded.connect(this, &MainWindow::OnGameTitleAdded);
|
||||
AsyncExecutor::execute([&] {gameList.loadUnfiltered();});
|
||||
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow() {
|
||||
gameList.titleListChanged.disconnect(this);
|
||||
while(!tvElements.empty()) {
|
||||
delete tvElements[0];
|
||||
remove(tvElements[0]);
|
||||
@ -103,6 +109,31 @@ void MainWindow::process() {
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::OnGameTitleListChanged(GameList * list) {
|
||||
currentTvFrame->OnGameTitleListUpdated(list);
|
||||
if(currentTvFrame != currentDrcFrame) {
|
||||
currentDrcFrame->OnGameTitleListUpdated(list);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::OnGameTitleUpdated(gameInfo * info) {
|
||||
currentTvFrame->OnGameTitleUpdated(info);
|
||||
if(currentTvFrame != currentDrcFrame) {
|
||||
currentDrcFrame->OnGameTitleUpdated(info);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::OnGameTitleAdded(gameInfo * info) {
|
||||
DEBUG_FUNCTION_LINE("%08X\n", info);
|
||||
if(info == NULL) {
|
||||
return;
|
||||
}
|
||||
currentTvFrame->OnGameTitleAdded(info);
|
||||
if(currentTvFrame != currentDrcFrame) {
|
||||
currentDrcFrame->OnGameTitleAdded(info);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::update(GuiController *controller) {
|
||||
//! dont read behind the initial elements in case one was added
|
||||
//uint32_t tvSize = tvElements.size();
|
||||
@ -179,6 +210,7 @@ void MainWindow::SetupMainView() {
|
||||
currentTvFrame->setEffect(EFFECT_FADE, 10, 255);
|
||||
currentTvFrame->setState(GuiElement::STATE_DISABLED);
|
||||
currentTvFrame->effectFinished.connect(this, &MainWindow::OnOpenEffectFinish);
|
||||
|
||||
appendTv(currentTvFrame);
|
||||
|
||||
currentDrcFrame = new GuiIconGrid(width, height,0);
|
||||
@ -186,7 +218,6 @@ void MainWindow::SetupMainView() {
|
||||
currentDrcFrame->setState(GuiElement::STATE_DISABLED);
|
||||
currentDrcFrame->effectFinished.connect(this, &MainWindow::OnOpenEffectFinish);
|
||||
|
||||
|
||||
if(currentTvFrame != currentDrcFrame) {
|
||||
currentDrcFrame->setEffect(EFFECT_FADE, 10, 255);
|
||||
currentDrcFrame->setState(GuiElement::STATE_DISABLED);
|
||||
@ -288,11 +319,11 @@ void MainWindow::OnCloseEffectFinish(GuiElement *element) {
|
||||
AsyncExecutor::pushForDelete(element);
|
||||
}
|
||||
|
||||
void MainWindow::OnSettingsButtonClicked(GuiElement *element){
|
||||
void MainWindow::OnSettingsButtonClicked(GuiElement *element) {
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::OnGameSelectionChange(GuiTitleBrowser *element, int32_t selectedIdx) {
|
||||
void MainWindow::OnGameSelectionChange(GuiTitleBrowser *element, uint64_t selectedIdx) {
|
||||
if(!currentDrcFrame || !currentTvFrame)
|
||||
return;
|
||||
|
||||
@ -303,6 +334,6 @@ void MainWindow::OnGameSelectionChange(GuiTitleBrowser *element, int32_t selecte
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::OnGameLaunch(GuiTitleBrowser *element, int32_t selectedIdx) {
|
||||
void MainWindow::OnGameLaunch(GuiTitleBrowser *element, uint64_t selectedIdx) {
|
||||
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <gui/Gui.h>
|
||||
#include "game/GameList.h"
|
||||
#include "system/CMutex.h"
|
||||
#include "gui/GuiTitleBrowser.h"
|
||||
#include "MainDrcButtonsFrame.h"
|
||||
@ -116,13 +117,17 @@ private:
|
||||
void OnOpenEffectFinish(GuiElement *element);
|
||||
void OnCloseEffectFinish(GuiElement *element);
|
||||
|
||||
void OnGameLaunch(GuiTitleBrowser *element, int32_t gameIdx);
|
||||
void OnGameSelectionChange(GuiTitleBrowser *element, int32_t selectedIdx);
|
||||
void OnGameLaunch(GuiTitleBrowser *element, uint64_t gameIdx);
|
||||
void OnGameSelectionChange(GuiTitleBrowser *element, uint64_t selectedIdx);
|
||||
|
||||
void OnSettingsButtonClicked(GuiElement *element);
|
||||
void OnLayoutSwitchClicked(GuiElement *element);
|
||||
void OnLayoutSwitchEffectFinish(GuiElement *element);
|
||||
|
||||
void OnGameTitleListChanged(GameList * list);
|
||||
void OnGameTitleUpdated(gameInfo * info);
|
||||
void OnGameTitleAdded(gameInfo * info);
|
||||
|
||||
int32_t width, height;
|
||||
std::vector<GuiElement *> drcElements;
|
||||
std::vector<GuiElement *> tvElements;
|
||||
@ -138,6 +143,8 @@ private:
|
||||
GuiImage *pointerImg[4];
|
||||
bool pointerValid[4];
|
||||
|
||||
GameList gameList;
|
||||
|
||||
CMutex guiMutex;
|
||||
};
|
||||
|
||||
|
@ -11,5 +11,10 @@ void AsyncExecutor::execute(std::function<void()> func) {
|
||||
if(!instance) {
|
||||
instance = new AsyncExecutor();
|
||||
}
|
||||
instance->elements.push_back(std::async(std::launch::async,func));
|
||||
instance->elements.push(std::async(std::launch::async,func));
|
||||
if(instance->elements.size() >= 25){
|
||||
//DEBUG_FUNCTION_LINE("Wait on queue %d\n",instance->elements.size());
|
||||
instance->elements.front().get();
|
||||
instance->elements.pop();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <future>
|
||||
#include <gui/GuiElement.h>
|
||||
|
||||
@ -22,5 +22,5 @@ private:
|
||||
AsyncExecutor() {}
|
||||
~AsyncExecutor() {}
|
||||
|
||||
std::vector<std::future<void>> elements;
|
||||
std::queue<std::future<void>> elements;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user