mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 15:45:38 +00:00
Refactored duplicate functionality in GridGameList and BasicGameList into
ISimpleGameList. BasicGameList and DetailedGameList now automatically switch as metadata changes.
This commit is contained in:
parent
9249d67048
commit
12ee215873
|
@ -193,10 +193,11 @@ set(ES_HEADERS
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/src/pugiXML/pugiconfig.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/pugiXML/pugixml.hpp
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/BasicGameListView.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/DetailedGameListView.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/GameListView.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/GridGameListView.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/gamelist/BasicGameListView.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/gamelist/DetailedGameListView.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/gamelist/IGameListView.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/gamelist/ISimpleGameListView.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/gamelist/GridGameListView.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/SystemListView.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/SystemView.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/ViewController.h
|
||||
|
@ -271,10 +272,11 @@ set(ES_SOURCES
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/src/resources/ResourceManager.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/resources/TextureResource.cpp
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/BasicGameListView.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/DetailedGameListView.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/GameListView.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/GridGameListView.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/gamelist/BasicGameListView.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/gamelist/DetailedGameListView.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/gamelist/IGameListView.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/gamelist/ISimpleGameListView.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/gamelist/GridGameListView.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/SystemListView.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/SystemView.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/views/ViewController.cpp
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
static const std::string LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
GuiFastSelect::GuiFastSelect(Window* window, GameListView* gamelist) : GuiComponent(window),
|
||||
GuiFastSelect::GuiFastSelect(Window* window, IGameListView* gamelist) : GuiComponent(window),
|
||||
mBackground(window), mSortText(window), mLetterText(window), mGameList(gamelist)
|
||||
{
|
||||
setPosition(Renderer::getScreenWidth() * 0.2f, Renderer::getScreenHeight() * 0.2f);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../GuiComponent.h"
|
||||
#include "../views/GameListView.h"
|
||||
#include "../views/gamelist/IGameListView.h"
|
||||
|
||||
#include "NinePatchComponent.h"
|
||||
#include "TextComponent.h"
|
||||
|
@ -9,7 +9,7 @@
|
|||
class GuiFastSelect : public GuiComponent
|
||||
{
|
||||
public:
|
||||
GuiFastSelect(Window* window, GameListView* gamelist);
|
||||
GuiFastSelect(Window* window, IGameListView* gamelist);
|
||||
|
||||
bool input(InputConfig* config, Input input);
|
||||
void update(int deltaTime);
|
||||
|
@ -31,5 +31,5 @@ private:
|
|||
TextComponent mSortText;
|
||||
TextComponent mLetterText;
|
||||
|
||||
GameListView* mGameList;
|
||||
IGameListView* mGameList;
|
||||
};
|
||||
|
|
|
@ -24,6 +24,7 @@ public:
|
|||
void clear();
|
||||
|
||||
void setCursor(const T& select);
|
||||
void setCursor(typename const std::vector<Entry>::const_iterator& it);
|
||||
|
||||
inline const T& getSelected() const { return mEntries.at(mCursor).object; }
|
||||
inline const std::vector<Entry>& getList() const { return mEntries; }
|
||||
|
@ -171,6 +172,14 @@ void ImageGridComponent<T>::setCursor(const T& obj)
|
|||
LOG(LogError) << "Tried to set cursor to object we couldn't find";
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ImageGridComponent<T>::setCursor(typename const std::vector<Entry>::const_iterator& it)
|
||||
{
|
||||
assert(it != mEntries.end());
|
||||
mCursor = it - mEntries.begin();
|
||||
onCursorChanged(CURSOR_STOPPED);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ImageGridComponent<T>::stopScrolling()
|
||||
{
|
||||
|
|
|
@ -49,6 +49,7 @@ public:
|
|||
inline const std::vector<ListRow>& getList() const { return mRowVector; }
|
||||
|
||||
void setCursor(const T& select);
|
||||
void setCursor(typename const std::vector<ListRow>::const_iterator& it);
|
||||
|
||||
void stopScrolling();
|
||||
inline bool isScrolling() const { return mScrollDir != 0; }
|
||||
|
@ -375,6 +376,15 @@ void TextListComponent<T>::setCursor(const T& obj)
|
|||
LOG(LogError) << "Tried to set cursor to object we couldn't find";
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void TextListComponent<T>::setCursor(typename const std::vector<ListRow>::const_iterator& it)
|
||||
{
|
||||
assert(it != mRowVector.end());
|
||||
mCursor = it - mRowVector.begin();
|
||||
onCursorChanged(CURSOR_STOPPED);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void TextListComponent<T>::onCursorChanged(CursorState state)
|
||||
{
|
||||
|
|
|
@ -1,183 +0,0 @@
|
|||
#include "BasicGameListView.h"
|
||||
#include "ViewController.h"
|
||||
#include "../Renderer.h"
|
||||
#include "../Window.h"
|
||||
#include "../ThemeData.h"
|
||||
|
||||
BasicGameListView::BasicGameListView(Window* window, FileData* root)
|
||||
: GameListView(window, root),
|
||||
mHeaderText(window), mHeaderImage(window), mBackground(window), mList(window)
|
||||
{
|
||||
mHeaderText.setText("Header");
|
||||
mHeaderText.setSize(mSize.x(), 0);
|
||||
mHeaderText.setPosition(0, 0);
|
||||
mHeaderText.setCentered(true);
|
||||
|
||||
mHeaderImage.setResize(0, mSize.y() * 0.185f, false);
|
||||
mHeaderImage.setOrigin(0.5f, 0.0f);
|
||||
mHeaderImage.setPosition(mSize.x() / 2, 0);
|
||||
|
||||
mBackground.setResize(mSize.x(), mSize.y(), true);
|
||||
|
||||
mList.setSize(mSize.x(), mSize.y() * 0.8f);
|
||||
mList.setPosition(0, mSize.y() * 0.2f);
|
||||
|
||||
populateList(root);
|
||||
|
||||
addChild(&mBackground);
|
||||
addChild(&mList);
|
||||
addChild(&mHeaderText);
|
||||
}
|
||||
|
||||
void BasicGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
||||
{
|
||||
const ImageDef& bg = theme->getImage("backgroundImage");
|
||||
mBackground.setTiling(bg.tile);
|
||||
mBackground.setImage(bg.getTexture());
|
||||
|
||||
const ImageDef& hdr = theme->getImage("headerImage");
|
||||
mHeaderImage.setTiling(hdr.tile);
|
||||
mHeaderImage.setImage(hdr.getTexture());
|
||||
|
||||
if(mHeaderImage.hasImage())
|
||||
{
|
||||
removeChild(&mHeaderText);
|
||||
addChild(&mHeaderImage);
|
||||
}else{
|
||||
addChild(&mHeaderText);
|
||||
removeChild(&mHeaderImage);
|
||||
}
|
||||
|
||||
mList.setTheme(theme);
|
||||
}
|
||||
|
||||
void BasicGameListView::onFileChanged(FileData* file, FileChangeType change)
|
||||
{
|
||||
// we don't care about metadata changes (since we don't display metadata),
|
||||
// so we just ignore the FILE_METADATA_CHANGED case
|
||||
|
||||
// if it's immediately inside our current folder
|
||||
if(file->getParent() == getCurrentFolder())
|
||||
{
|
||||
if(change == FILE_REMOVED)
|
||||
{
|
||||
mList.remove(file); // will automatically make sure cursor ends up in a "safe" place
|
||||
}else if(change == FILE_ADDED)
|
||||
{
|
||||
FileData* cursor = getCursor();
|
||||
populateList(cursor->getParent());
|
||||
mList.setCursor(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
// the root file was sorted (so children were sorted too)
|
||||
if(file == mRoot && change == FILE_SORTED)
|
||||
{
|
||||
FileData* cursor = getCursor();
|
||||
populateList(cursor->getParent());
|
||||
mList.setCursor(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
void buildHeader(FileData* from, std::stringstream& ss)
|
||||
{
|
||||
if(from->getParent())
|
||||
{
|
||||
buildHeader(from->getParent(), ss);
|
||||
ss << " -> ";
|
||||
}
|
||||
|
||||
ss << from->getName();
|
||||
}
|
||||
|
||||
void BasicGameListView::populateList(FileData* root)
|
||||
{
|
||||
mList.clear();
|
||||
|
||||
std::stringstream ss;
|
||||
buildHeader(root, ss);
|
||||
mHeaderText.setText(ss.str());
|
||||
|
||||
for(auto it = root->getChildren().begin(); it != root->getChildren().end(); it++)
|
||||
{
|
||||
mList.add((*it)->getName(), *it, ((*it)->getType() == FOLDER));
|
||||
}
|
||||
}
|
||||
|
||||
void BasicGameListView::setCursor(FileData* cursor)
|
||||
{
|
||||
if(cursor->getParent() != getCursor()->getParent())
|
||||
{
|
||||
// Rebuild the folder stack
|
||||
std::stack<FileData*> path;
|
||||
FileData* cur = cursor;
|
||||
while((cur = cur->getParent()) != mRoot)
|
||||
path.push(cur);
|
||||
|
||||
while(!mCursorStack.empty())
|
||||
mCursorStack.pop();
|
||||
|
||||
while(!path.empty()) // put back in reverse order (flip)
|
||||
{
|
||||
mCursorStack.push(path.top());
|
||||
path.pop();
|
||||
}
|
||||
|
||||
populateList(cursor->getParent());
|
||||
}
|
||||
|
||||
mList.setCursor(cursor);
|
||||
}
|
||||
|
||||
bool BasicGameListView::input(InputConfig* config, Input input)
|
||||
{
|
||||
if(input.value != 0)
|
||||
{
|
||||
if(config->isMappedTo("a", input))
|
||||
{
|
||||
if(mList.getList().size() > 0)
|
||||
{
|
||||
FileData* cursor = getCursor();
|
||||
if(cursor->getType() == GAME)
|
||||
{
|
||||
mWindow->getViewController()->launch(cursor);
|
||||
}else{
|
||||
// it's a folder
|
||||
if(cursor->getChildren().size() > 0)
|
||||
{
|
||||
mCursorStack.push(cursor);
|
||||
populateList(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}else if(config->isMappedTo("b", input))
|
||||
{
|
||||
if(mCursorStack.size())
|
||||
{
|
||||
populateList(mCursorStack.top()->getParent());
|
||||
mList.setCursor(mCursorStack.top());
|
||||
mCursorStack.pop();
|
||||
mTheme->playSound("backSound");
|
||||
}else{
|
||||
mList.stopScrolling();
|
||||
mWindow->getViewController()->goToSystemSelect();
|
||||
}
|
||||
|
||||
return true;
|
||||
}else if(config->isMappedTo("right", input))
|
||||
{
|
||||
mList.stopScrolling();
|
||||
mWindow->getViewController()->goToNextGameList();
|
||||
return true;
|
||||
}else if(config->isMappedTo("left", input))
|
||||
{
|
||||
mList.stopScrolling();
|
||||
mWindow->getViewController()->goToPrevGameList();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return GameListView::input(config, input);
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "GameListView.h"
|
||||
#include "../components/TextListComponent.h"
|
||||
#include "../components/TextComponent.h"
|
||||
#include "../components/ImageComponent.h"
|
||||
|
||||
class BasicGameListView : public GameListView
|
||||
{
|
||||
public:
|
||||
BasicGameListView(Window* window, FileData* root);
|
||||
|
||||
// Called when a FileData* is added, has its metadata changed, or is removed
|
||||
virtual void onFileChanged(FileData* file, FileChangeType change);
|
||||
|
||||
virtual bool input(InputConfig* config, Input input) override;
|
||||
|
||||
virtual void onThemeChanged(const std::shared_ptr<ThemeData>& theme) override;
|
||||
|
||||
inline FileData* getCursor() { return mList.getSelected(); }
|
||||
virtual void setCursor(FileData* file) override;
|
||||
|
||||
protected:
|
||||
void populateList(FileData* root);
|
||||
|
||||
TextComponent mHeaderText;
|
||||
ImageComponent mHeaderImage;
|
||||
ImageComponent mBackground;
|
||||
TextListComponent<FileData*> mList;
|
||||
|
||||
inline FileData* getCurrentFolder() { return getCursor()->getParent(); }
|
||||
|
||||
std::stack<FileData*> mCursorStack;
|
||||
};
|
|
@ -1,93 +0,0 @@
|
|||
#include "GridGameListView.h"
|
||||
#include "../ThemeData.h"
|
||||
#include "../Window.h"
|
||||
#include "ViewController.h"
|
||||
|
||||
GridGameListView::GridGameListView(Window* window, FileData* root) : GameListView(window, root),
|
||||
mGrid(window), mBackground(window)
|
||||
{
|
||||
mBackground.setResize(mSize.x(), mSize.y(), true);
|
||||
addChild(&mBackground);
|
||||
|
||||
mGrid.setPosition(0, mSize.y() * 0.2f);
|
||||
mGrid.setSize(mSize.x(), mSize.y() * 0.8f);
|
||||
addChild(&mGrid);
|
||||
|
||||
populateList(root);
|
||||
}
|
||||
|
||||
void GridGameListView::onFileChanged(FileData* file, FileChangeType change)
|
||||
{
|
||||
// fuck it, just completely repopulate always all the time
|
||||
FileData* cursor = getCursor();
|
||||
populateList(cursor->getParent());
|
||||
mGrid.setCursor(cursor);
|
||||
}
|
||||
|
||||
void GridGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
||||
{
|
||||
mBackground.setImage(theme->getImage("backgroundImage").getTexture());
|
||||
mBackground.setTiling(theme->getImage("backgroundImage").tile);
|
||||
}
|
||||
|
||||
FileData* GridGameListView::getCursor()
|
||||
{
|
||||
return mGrid.getSelected();
|
||||
}
|
||||
|
||||
void GridGameListView::setCursor(FileData* file)
|
||||
{
|
||||
assert(file->getParent() == getCursor()->getParent()); // too lazy to implement right now
|
||||
mGrid.setCursor(file);
|
||||
}
|
||||
|
||||
bool GridGameListView::input(InputConfig* config, Input input)
|
||||
{
|
||||
if(input.value != 0)
|
||||
{
|
||||
if(config->isMappedTo("a", input))
|
||||
{
|
||||
if(mGrid.getList().size() > 0)
|
||||
{
|
||||
FileData* cursor = getCursor();
|
||||
if(cursor->getType() == GAME)
|
||||
{
|
||||
mWindow->getViewController()->launch(cursor);
|
||||
}else{
|
||||
// it's a folder
|
||||
if(cursor->getChildren().size() > 0)
|
||||
{
|
||||
mCursorStack.push(cursor);
|
||||
populateList(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}else if(config->isMappedTo("b", input))
|
||||
{
|
||||
if(mCursorStack.size())
|
||||
{
|
||||
populateList(mCursorStack.top()->getParent());
|
||||
mGrid.setCursor(mCursorStack.top());
|
||||
mCursorStack.pop();
|
||||
mTheme->playSound("backSound");
|
||||
}else{
|
||||
mGrid.stopScrolling();
|
||||
mWindow->getViewController()->goToSystemSelect();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return GameListView::input(config, input);
|
||||
}
|
||||
|
||||
void GridGameListView::populateList(FileData* root)
|
||||
{
|
||||
mGrid.clear();
|
||||
for(auto it = root->getChildren().begin(); it != root->getChildren().end(); it++)
|
||||
{
|
||||
mGrid.add((*it)->getThumbnailPath(), *it);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "GameListView.h"
|
||||
#include "../components/ImageGridComponent.h"
|
||||
#include "../components/ImageComponent.h"
|
||||
#include <stack>
|
||||
|
||||
class GridGameListView : public GameListView
|
||||
{
|
||||
public:
|
||||
GridGameListView(Window* window, FileData* root);
|
||||
|
||||
virtual void onFileChanged(FileData* file, FileChangeType change) override;
|
||||
virtual void onThemeChanged(const std::shared_ptr<ThemeData>& theme) override;
|
||||
|
||||
FileData* getCursor() override;
|
||||
void setCursor(FileData*) override;
|
||||
|
||||
virtual bool input(InputConfig* config, Input input) override;
|
||||
|
||||
private:
|
||||
void populateList(FileData* root);
|
||||
|
||||
ImageGridComponent<FileData*> mGrid;
|
||||
ImageComponent mBackground;
|
||||
|
||||
std::stack<FileData*> mCursorStack;
|
||||
};
|
|
@ -2,9 +2,9 @@
|
|||
#include "../Log.h"
|
||||
#include "../SystemData.h"
|
||||
|
||||
#include "BasicGameListView.h"
|
||||
#include "DetailedGameListView.h"
|
||||
#include "GridGameListView.h"
|
||||
#include "gamelist/BasicGameListView.h"
|
||||
#include "gamelist/DetailedGameListView.h"
|
||||
#include "gamelist/GridGameListView.h"
|
||||
#include "../components/GuiMenu.h"
|
||||
#include "../animations/LaunchAnimation.h"
|
||||
#include "../animations/MoveCameraAnimation.h"
|
||||
|
@ -116,7 +116,7 @@ void ViewController::launch(FileData* game, Eigen::Vector3f center)
|
|||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<GameListView> ViewController::getGameListView(SystemData* system)
|
||||
std::shared_ptr<IGameListView> ViewController::getGameListView(SystemData* system)
|
||||
{
|
||||
//if we already made one, return that one
|
||||
auto exists = mGameListViews.find(system);
|
||||
|
@ -124,7 +124,7 @@ std::shared_ptr<GameListView> ViewController::getGameListView(SystemData* system
|
|||
return exists->second;
|
||||
|
||||
//if we didn't, make it, remember it, and return it
|
||||
std::shared_ptr<GameListView> view;
|
||||
std::shared_ptr<IGameListView> view;
|
||||
|
||||
if(system != NULL)
|
||||
{
|
||||
|
@ -141,11 +141,11 @@ std::shared_ptr<GameListView> ViewController::getGameListView(SystemData* system
|
|||
}
|
||||
|
||||
if(detailed)
|
||||
view = std::shared_ptr<GameListView>(new DetailedGameListView(mWindow, system->getRootFolder()));
|
||||
view = std::shared_ptr<IGameListView>(new DetailedGameListView(mWindow, system->getRootFolder()));
|
||||
else
|
||||
view = std::shared_ptr<GameListView>(new BasicGameListView(mWindow, system->getRootFolder()));
|
||||
view = std::shared_ptr<IGameListView>(new BasicGameListView(mWindow, system->getRootFolder()));
|
||||
|
||||
//view = std::shared_ptr<GameListView>(new GridGameListView(mWindow, system->getRootFolder()));
|
||||
view = std::shared_ptr<IGameListView>(new GridGameListView(mWindow, system->getRootFolder()));
|
||||
|
||||
view->setTheme(system->getTheme());
|
||||
}else{
|
||||
|
@ -240,3 +240,21 @@ void ViewController::preload()
|
|||
getGameListView(*it);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewController::reloadGameListView(IGameListView* view)
|
||||
{
|
||||
for(auto it = mGameListViews.begin(); it != mGameListViews.end(); it++)
|
||||
{
|
||||
if(it->second.get() == view)
|
||||
{
|
||||
SystemData* system = it->first;
|
||||
FileData* cursor = view->getCursor();
|
||||
mGameListViews.erase(it);
|
||||
|
||||
std::shared_ptr<IGameListView> newView = getGameListView(system);
|
||||
newView->setCursor(cursor);
|
||||
mCurrentView = newView;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "GameListView.h"
|
||||
#include "gamelist/IGameListView.h"
|
||||
#include "SystemListView.h"
|
||||
|
||||
class SystemData;
|
||||
|
@ -14,6 +14,10 @@ public:
|
|||
// Caches things so there's no pauses during transitions.
|
||||
void preload();
|
||||
|
||||
// If a basic view detected a metadata change, it can request to recreate
|
||||
// the current gamelist view (as it may change to be detailed).
|
||||
void reloadGameListView(IGameListView* gamelist);
|
||||
|
||||
// Navigation.
|
||||
void goToNextGameList();
|
||||
void goToPrevGameList();
|
||||
|
@ -55,11 +59,11 @@ public:
|
|||
|
||||
private:
|
||||
void playViewTransition();
|
||||
std::shared_ptr<GameListView> getGameListView(SystemData* system);
|
||||
std::shared_ptr<IGameListView> getGameListView(SystemData* system);
|
||||
std::shared_ptr<SystemListView> getSystemListView();
|
||||
|
||||
std::shared_ptr<GuiComponent> mCurrentView;
|
||||
std::map< SystemData*, std::shared_ptr<GameListView> > mGameListViews;
|
||||
std::map< SystemData*, std::shared_ptr<IGameListView> > mGameListViews;
|
||||
std::shared_ptr<SystemListView> mSystemListView;
|
||||
|
||||
Eigen::Affine3f mCamera;
|
||||
|
|
71
src/views/gamelist/BasicGameListView.cpp
Normal file
71
src/views/gamelist/BasicGameListView.cpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
#include "BasicGameListView.h"
|
||||
#include "../ViewController.h"
|
||||
#include "../../Renderer.h"
|
||||
#include "../../Window.h"
|
||||
#include "../../ThemeData.h"
|
||||
#include "../../SystemData.h"
|
||||
|
||||
BasicGameListView::BasicGameListView(Window* window, FileData* root)
|
||||
: ISimpleGameListView(window, root), mList(window)
|
||||
{
|
||||
mList.setSize(mSize.x(), mSize.y() * 0.8f);
|
||||
mList.setPosition(0, mSize.y() * 0.2f);
|
||||
addChild(&mList);
|
||||
|
||||
populateList(root->getChildren());
|
||||
}
|
||||
|
||||
void BasicGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
||||
{
|
||||
ISimpleGameListView::onThemeChanged(theme);
|
||||
mList.setTheme(theme);
|
||||
}
|
||||
|
||||
void BasicGameListView::onFileChanged(FileData* file, FileChangeType change)
|
||||
{
|
||||
if(change == FILE_METADATA_CHANGED)
|
||||
{
|
||||
// might switch to a detailed view
|
||||
mWindow->getViewController()->reloadGameListView(this);
|
||||
return;
|
||||
}
|
||||
|
||||
ISimpleGameListView::onFileChanged(file, change);
|
||||
}
|
||||
|
||||
void BasicGameListView::populateList(const std::vector<FileData*>& files)
|
||||
{
|
||||
mList.clear();
|
||||
|
||||
mHeaderText.setText(files.at(0)->getSystem()->getFullName());
|
||||
|
||||
for(auto it = files.begin(); it != files.end(); it++)
|
||||
{
|
||||
mList.add((*it)->getName(), *it, ((*it)->getType() == FOLDER));
|
||||
}
|
||||
}
|
||||
|
||||
FileData* BasicGameListView::getCursor()
|
||||
{
|
||||
return mList.getSelected();
|
||||
}
|
||||
|
||||
void BasicGameListView::setCursor(FileData* cursor)
|
||||
{
|
||||
typedef TextListComponent<FileData*>::ListRow Row;
|
||||
const std::vector<Row>& list = mList.getList();
|
||||
auto found = std::find_if(list.begin(), list.end(), [&](const Row& row) { return (row.object == cursor); });
|
||||
|
||||
if(found != list.end())
|
||||
{
|
||||
mList.setCursor(found);
|
||||
}else{
|
||||
populateList(cursor->getParent()->getChildren());
|
||||
mList.setCursor(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
void BasicGameListView::launch(FileData* game)
|
||||
{
|
||||
mWindow->getViewController()->launch(game);
|
||||
}
|
24
src/views/gamelist/BasicGameListView.h
Normal file
24
src/views/gamelist/BasicGameListView.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
#include "ISimpleGameListView.h"
|
||||
#include "../../components/TextListComponent.h"
|
||||
|
||||
class BasicGameListView : public ISimpleGameListView
|
||||
{
|
||||
public:
|
||||
BasicGameListView(Window* window, FileData* root);
|
||||
|
||||
// Called when a FileData* is added, has its metadata changed, or is removed
|
||||
virtual void onFileChanged(FileData* file, FileChangeType change);
|
||||
|
||||
virtual void onThemeChanged(const std::shared_ptr<ThemeData>& theme);
|
||||
|
||||
virtual FileData* getCursor() override;
|
||||
virtual void setCursor(FileData* file) override;
|
||||
|
||||
protected:
|
||||
virtual void populateList(const std::vector<FileData*>& files) override;
|
||||
virtual void launch(FileData* game) override;
|
||||
|
||||
TextListComponent<FileData*> mList;
|
||||
};
|
|
@ -1,4 +1,6 @@
|
|||
#include "DetailedGameListView.h"
|
||||
#include "../../Window.h"
|
||||
#include "../ViewController.h"
|
||||
|
||||
DetailedGameListView::DetailedGameListView(Window* window, FileData* root) :
|
||||
BasicGameListView(window, root),
|
||||
|
@ -75,10 +77,11 @@ void DetailedGameListView::updateInfoPanel()
|
|||
}
|
||||
}
|
||||
|
||||
void DetailedGameListView::onFileChanged(FileData* file, FileChangeType type)
|
||||
void DetailedGameListView::launch(FileData* game)
|
||||
{
|
||||
BasicGameListView::onFileChanged(file, type);
|
||||
Eigen::Vector3f target(Renderer::getScreenWidth() / 2.0f, Renderer::getScreenHeight() / 2.0f, 0);
|
||||
if(mImage.hasImage())
|
||||
target = mImage.getPosition();
|
||||
|
||||
if(type == FILE_METADATA_CHANGED && file == getCursor())
|
||||
updateInfoPanel();
|
||||
mWindow->getViewController()->launch(game, target);
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "BasicGameListView.h"
|
||||
#include "../components/ImageComponent.h"
|
||||
#include "../components/TextComponent.h"
|
||||
#include "../components/ScrollableContainer.h"
|
||||
#include "../../components/ScrollableContainer.h"
|
||||
|
||||
class DetailedGameListView : public BasicGameListView
|
||||
{
|
||||
|
@ -12,7 +10,8 @@ public:
|
|||
|
||||
virtual void onThemeChanged(const std::shared_ptr<ThemeData>& theme) override;
|
||||
|
||||
virtual void onFileChanged(FileData* file, FileChangeType change);
|
||||
protected:
|
||||
virtual void launch(FileData* game) override;
|
||||
|
||||
private:
|
||||
void updateInfoPanel();
|
||||
|
@ -24,4 +23,3 @@ private:
|
|||
ScrollableContainer mDescContainer;
|
||||
TextComponent mDescription;
|
||||
};
|
||||
|
56
src/views/gamelist/GridGameListView.cpp
Normal file
56
src/views/gamelist/GridGameListView.cpp
Normal file
|
@ -0,0 +1,56 @@
|
|||
#include "GridGameListView.h"
|
||||
#include "../../ThemeData.h"
|
||||
#include "../../Window.h"
|
||||
#include "../ViewController.h"
|
||||
|
||||
GridGameListView::GridGameListView(Window* window, FileData* root) : ISimpleGameListView(window, root),
|
||||
mGrid(window)
|
||||
{
|
||||
mGrid.setPosition(0, mSize.y() * 0.2f);
|
||||
mGrid.setSize(mSize.x(), mSize.y() * 0.8f);
|
||||
addChild(&mGrid);
|
||||
|
||||
populateList(root->getChildren());
|
||||
}
|
||||
|
||||
FileData* GridGameListView::getCursor()
|
||||
{
|
||||
return mGrid.getSelected();
|
||||
}
|
||||
|
||||
void GridGameListView::setCursor(FileData* file)
|
||||
{
|
||||
typedef ImageGridComponent<FileData*>::Entry Entry;
|
||||
auto& list = mGrid.getList();
|
||||
auto found = std::find_if(list.begin(), list.end(), [&] (const Entry& e) { return (e.object == file); });
|
||||
|
||||
if(found != list.end())
|
||||
{
|
||||
mGrid.setCursor(found);
|
||||
}else{
|
||||
populateList(file->getParent()->getChildren());
|
||||
mGrid.setCursor(file);
|
||||
}
|
||||
}
|
||||
|
||||
bool GridGameListView::input(InputConfig* config, Input input)
|
||||
{
|
||||
if(config->isMappedTo("left", input) || config->isMappedTo("right", input))
|
||||
return GuiComponent::input(config, input);
|
||||
|
||||
return ISimpleGameListView::input(config, input);
|
||||
}
|
||||
|
||||
void GridGameListView::populateList(const std::vector<FileData*>& files)
|
||||
{
|
||||
mGrid.clear();
|
||||
for(auto it = files.begin(); it != files.end(); it++)
|
||||
{
|
||||
mGrid.add((*it)->getThumbnailPath(), *it);
|
||||
}
|
||||
}
|
||||
|
||||
void GridGameListView::launch(FileData* game)
|
||||
{
|
||||
mWindow->getViewController()->launch(game);
|
||||
}
|
25
src/views/gamelist/GridGameListView.h
Normal file
25
src/views/gamelist/GridGameListView.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
#include "ISimpleGameListView.h"
|
||||
#include "../../components/ImageGridComponent.h"
|
||||
#include "../../components/ImageComponent.h"
|
||||
#include <stack>
|
||||
|
||||
class GridGameListView : public ISimpleGameListView
|
||||
{
|
||||
public:
|
||||
GridGameListView(Window* window, FileData* root);
|
||||
|
||||
//virtual void onThemeChanged(const std::shared_ptr<ThemeData>& theme) override;
|
||||
|
||||
virtual FileData* getCursor() override;
|
||||
virtual void setCursor(FileData*) override;
|
||||
|
||||
virtual bool input(InputConfig* config, Input input) override;
|
||||
|
||||
protected:
|
||||
virtual void populateList(const std::vector<FileData*>& files) override;
|
||||
virtual void launch(FileData* game) override;
|
||||
|
||||
ImageGridComponent<FileData*> mGrid;
|
||||
};
|
|
@ -1,11 +1,11 @@
|
|||
#include "GameListView.h"
|
||||
#include "../Window.h"
|
||||
#include "../components/GuiMetaDataEd.h"
|
||||
#include "../components/GuiMenu.h"
|
||||
#include "../components/GuiFastSelect.h"
|
||||
#include "ViewController.h"
|
||||
#include "IGameListView.h"
|
||||
#include "../../Window.h"
|
||||
#include "../../components/GuiMetaDataEd.h"
|
||||
#include "../../components/GuiMenu.h"
|
||||
#include "../../components/GuiFastSelect.h"
|
||||
#include "../ViewController.h"
|
||||
|
||||
bool GameListView::input(InputConfig* config, Input input)
|
||||
bool IGameListView::input(InputConfig* config, Input input)
|
||||
{
|
||||
if(config->getDeviceId() == DEVICE_KEYBOARD && input.id == SDLK_F3 && input.value != 0)
|
||||
{
|
||||
|
@ -15,7 +15,7 @@ bool GameListView::input(InputConfig* config, Input input)
|
|||
p.game = file;
|
||||
p.system = file->getSystem();
|
||||
mWindow->pushGui(new GuiMetaDataEd(mWindow, &file->metadata, file->metadata.getMDD(), p, file->getPath().filename().string(),
|
||||
std::bind(&GameListView::onFileChanged, this, file, FILE_METADATA_CHANGED), [file, this] {
|
||||
std::bind(&IGameListView::onFileChanged, this, file, FILE_METADATA_CHANGED), [file, this] {
|
||||
boost::filesystem::remove(file->getPath()); //actually delete the file on the filesystem
|
||||
file->getParent()->removeChild(file); //unlink it so list repopulations triggered from onFileChanged won't see it
|
||||
onFileChanged(file, FILE_REMOVED); //tell the view
|
||||
|
@ -33,7 +33,7 @@ bool GameListView::input(InputConfig* config, Input input)
|
|||
return GuiComponent::input(config, input);
|
||||
}
|
||||
|
||||
void GameListView::setTheme(const std::shared_ptr<ThemeData>& theme)
|
||||
void IGameListView::setTheme(const std::shared_ptr<ThemeData>& theme)
|
||||
{
|
||||
mTheme = theme;
|
||||
onThemeChanged(theme);
|
|
@ -1,24 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
#include "../FileData.h"
|
||||
#include "../Renderer.h"
|
||||
#include "../../FileData.h"
|
||||
#include "../../Renderer.h"
|
||||
|
||||
class Window;
|
||||
class GuiComponent;
|
||||
class FileData;
|
||||
class ThemeData;
|
||||
|
||||
//GameListView needs to know:
|
||||
//IGameListView needs to know:
|
||||
// What theme data to use
|
||||
// The root FileData for the tree it should explore
|
||||
|
||||
class GameListView : public GuiComponent
|
||||
class IGameListView : public GuiComponent
|
||||
{
|
||||
public:
|
||||
GameListView(Window* window, FileData* root) : GuiComponent(window), mRoot(root)
|
||||
IGameListView(Window* window, FileData* root) : GuiComponent(window), mRoot(root)
|
||||
{ setSize((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight()); }
|
||||
|
||||
virtual ~GameListView() {}
|
||||
virtual ~IGameListView() {}
|
||||
|
||||
// Called when a new file is added, a file is removed, a file's metadata changes, or a file's children are sorted.
|
||||
// NOTE: FILE_SORTED is only reported for the topmost FileData, where the sort started.
|
101
src/views/gamelist/ISimpleGameListView.cpp
Normal file
101
src/views/gamelist/ISimpleGameListView.cpp
Normal file
|
@ -0,0 +1,101 @@
|
|||
#include "ISimpleGameListView.h"
|
||||
#include "../../ThemeData.h"
|
||||
#include "../../Window.h"
|
||||
#include "../ViewController.h"
|
||||
|
||||
ISimpleGameListView::ISimpleGameListView(Window* window, FileData* root) : IGameListView(window, root),
|
||||
mHeaderText(window), mHeaderImage(window), mBackground(window)
|
||||
{
|
||||
mHeaderText.setText("Header");
|
||||
mHeaderText.setSize(mSize.x(), 0);
|
||||
mHeaderText.setPosition(0, 0);
|
||||
mHeaderText.setCentered(true);
|
||||
|
||||
mHeaderImage.setResize(0, mSize.y() * 0.185f, false);
|
||||
mHeaderImage.setOrigin(0.5f, 0.0f);
|
||||
mHeaderImage.setPosition(mSize.x() / 2, 0);
|
||||
|
||||
mBackground.setResize(mSize.x(), mSize.y(), true);
|
||||
|
||||
addChild(&mHeaderText);
|
||||
addChild(&mBackground);
|
||||
}
|
||||
|
||||
void ISimpleGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
||||
{
|
||||
const ImageDef& bg = theme->getImage("backgroundImage");
|
||||
mBackground.setTiling(bg.tile);
|
||||
mBackground.setImage(bg.getTexture());
|
||||
|
||||
const ImageDef& hdr = theme->getImage("headerImage");
|
||||
mHeaderImage.setTiling(hdr.tile);
|
||||
mHeaderImage.setImage(hdr.getTexture());
|
||||
|
||||
if(mHeaderImage.hasImage())
|
||||
{
|
||||
removeChild(&mHeaderText);
|
||||
addChild(&mHeaderImage);
|
||||
}else{
|
||||
addChild(&mHeaderText);
|
||||
removeChild(&mHeaderImage);
|
||||
}
|
||||
}
|
||||
|
||||
void ISimpleGameListView::onFileChanged(FileData* file, FileChangeType change)
|
||||
{
|
||||
// we could be tricky here to be efficient;
|
||||
// but this shouldn't happen very often so we'll just always repopulate
|
||||
FileData* cursor = getCursor();
|
||||
populateList(cursor->getParent()->getChildren());
|
||||
setCursor(cursor);
|
||||
}
|
||||
|
||||
bool ISimpleGameListView::input(InputConfig* config, Input input)
|
||||
{
|
||||
if(input.value != 0)
|
||||
{
|
||||
if(config->isMappedTo("a", input))
|
||||
{
|
||||
FileData* cursor = getCursor();
|
||||
if(cursor->getType() == GAME)
|
||||
{
|
||||
launch(cursor);
|
||||
}else{
|
||||
// it's a folder
|
||||
if(cursor->getChildren().size() > 0)
|
||||
{
|
||||
mCursorStack.push(cursor);
|
||||
populateList(cursor->getChildren());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}else if(config->isMappedTo("b", input))
|
||||
{
|
||||
if(mCursorStack.size())
|
||||
{
|
||||
populateList(mCursorStack.top()->getParent()->getChildren());
|
||||
setCursor(mCursorStack.top());
|
||||
mCursorStack.pop();
|
||||
getTheme()->playSound("backSound");
|
||||
}else{
|
||||
onFocusLost();
|
||||
mWindow->getViewController()->goToSystemSelect();
|
||||
}
|
||||
|
||||
return true;
|
||||
}else if(config->isMappedTo("right", input))
|
||||
{
|
||||
onFocusLost();
|
||||
mWindow->getViewController()->goToNextGameList();
|
||||
return true;
|
||||
}else if(config->isMappedTo("left", input))
|
||||
{
|
||||
onFocusLost();
|
||||
mWindow->getViewController()->goToPrevGameList();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return IGameListView::input(config, input);
|
||||
}
|
36
src/views/gamelist/ISimpleGameListView.h
Normal file
36
src/views/gamelist/ISimpleGameListView.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#include "IGameListView.h"
|
||||
|
||||
#include "../../components/TextComponent.h"
|
||||
#include "../../components/ImageComponent.h"
|
||||
|
||||
class ISimpleGameListView : public IGameListView
|
||||
{
|
||||
public:
|
||||
ISimpleGameListView(Window* window, FileData* root);
|
||||
virtual ~ISimpleGameListView() {}
|
||||
|
||||
// Called when a new file is added, a file is removed, a file's metadata changes, or a file's children are sorted.
|
||||
// NOTE: FILE_SORTED is only reported for the topmost FileData, where the sort started.
|
||||
// Since sorts are recursive, that FileData's children probably changed too.
|
||||
virtual void onFileChanged(FileData* file, FileChangeType change);
|
||||
|
||||
// Called whenever the theme changes.
|
||||
virtual void onThemeChanged(const std::shared_ptr<ThemeData>& theme);
|
||||
|
||||
virtual FileData* getCursor() = 0;
|
||||
virtual void setCursor(FileData*) = 0;
|
||||
|
||||
virtual bool input(InputConfig* config, Input input) override;
|
||||
|
||||
protected:
|
||||
virtual void populateList(const std::vector<FileData*>& files) = 0;
|
||||
virtual void launch(FileData* game) = 0;
|
||||
|
||||
TextComponent mHeaderText;
|
||||
ImageComponent mHeaderImage;
|
||||
ImageComponent mBackground;
|
||||
|
||||
std::stack<FileData*> mCursorStack;
|
||||
};
|
Loading…
Reference in a new issue