Basic GuiComponent refactor complete.

This commit is contained in:
Aloshi 2013-06-02 10:08:32 -05:00
parent 4d31aac85e
commit 424fcb0329
30 changed files with 767 additions and 644 deletions

View file

@ -112,12 +112,13 @@ endif()
#define basic sources and headers
set(ES_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/src/AudioManager.h
${CMAKE_CURRENT_SOURCE_DIR}/src/ComponentContainer.h
${CMAKE_CURRENT_SOURCE_DIR}/src/EmulationStation.h
${CMAKE_CURRENT_SOURCE_DIR}/src/FileData.h
${CMAKE_CURRENT_SOURCE_DIR}/src/FolderData.h
${CMAKE_CURRENT_SOURCE_DIR}/src/Font.h
${CMAKE_CURRENT_SOURCE_DIR}/src/GameData.h
${CMAKE_CURRENT_SOURCE_DIR}/src/Gui.h
${CMAKE_CURRENT_SOURCE_DIR}/src/GuiComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/src/ImageIO.h
${CMAKE_CURRENT_SOURCE_DIR}/src/InputConfig.h
${CMAKE_CURRENT_SOURCE_DIR}/src/InputManager.h
@ -131,26 +132,27 @@ set(ES_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/src/VolumeControl.h
${CMAKE_CURRENT_SOURCE_DIR}/src/Window.h
${CMAKE_CURRENT_SOURCE_DIR}/src/XMLReader.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiAnimation.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/AnimationComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ImageComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/TextListComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ThemeComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiBox.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiDetectDevice.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiFastSelect.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiGameList.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiImage.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiInputConfig.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiList.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiMenu.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiTheme.h
${CMAKE_CURRENT_SOURCE_DIR}/src/pugiXML/pugiconfig.hpp
${CMAKE_CURRENT_SOURCE_DIR}/src/pugiXML/pugixml.hpp
${CMAKE_CURRENT_SOURCE_DIR}/data/Resources.h
)
set(ES_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/AudioManager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ComponentContainer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/FolderData.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Font.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/GameData.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Gui.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/GuiComponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ImageIO.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/InputConfig.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/InputManager.cpp
@ -165,15 +167,15 @@ set(ES_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/VolumeControl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Window.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/XMLReader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiAnimation.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/AnimationComponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ImageComponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ThemeComponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiBox.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiDetectDevice.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiFastSelect.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiGameList.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiImage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiInputConfig.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiMenu.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiTheme.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/pugiXML/pugixml.cpp
${CMAKE_CURRENT_SOURCE_DIR}/data/logo/ES_logo_16.cpp
${CMAKE_CURRENT_SOURCE_DIR}/data/logo/ES_logo_32.cpp

View file

@ -0,0 +1,34 @@
#include "ComponentContainer.h"
#include "GuiComponent.h"
void ComponentContainer::addChild(GuiComponent* cmp)
{
mChildren.push_back(cmp);
}
void ComponentContainer::removeChild(GuiComponent* cmp)
{
for(auto i = mChildren.begin(); i != mChildren.end(); i++)
{
if(*i == cmp)
{
mChildren.erase(i);
return;
}
}
}
void ComponentContainer::clearChildren()
{
mChildren.clear();
}
unsigned int ComponentContainer::getChildCount()
{
return mChildren.size();
}
GuiComponent* ComponentContainer::getChild(unsigned int i)
{
return mChildren.at(i);
}

25
src/ComponentContainer.h Normal file
View file

@ -0,0 +1,25 @@
#ifndef _COMPONENTCONTAINER_H_
#define _COMPONENTCONTAINER_H_
#include <vector>
class GuiComponent;
/**
Generic container for Components.
**/
class ComponentContainer
{
public:
void addChild(GuiComponent* cmp);
void removeChild(GuiComponent* cmp);
void clearChildren();
unsigned int getChildCount();
GuiComponent* getChild(unsigned int i);
private:
std::vector<GuiComponent*> mChildren;
};
#endif

View file

@ -1,17 +0,0 @@
#include "Gui.h"
#include "Window.h"
Gui::Gui(Window* window) : mWindow(window)
{
}
Gui::~Gui()
{
mWindow->removeGui(this);
}
void Gui::setOffset(int x, int y) { mOffsetX = x; mOffsetY = y; }
void Gui::setOffsetX(int x) { mOffsetX = x; }
void Gui::setOffsetY(int y) { mOffsetY = y; }
int Gui::getOffsetX() { return mOffsetX; }
int Gui::getOffsetY() { return mOffsetY; }

View file

@ -1,33 +0,0 @@
#ifndef _GUI_H_
#define _GUI_H_
#include "InputConfig.h"
class Window;
class Gui
{
public:
Gui(Window* window);
virtual ~Gui();
virtual void input(InputConfig* config, Input input) { };
virtual void update(int deltaTime) { };
virtual void render() { };
virtual void init() { };
virtual void deinit() { };
void setOffsetX(int x);
void setOffsetY(int y);
void setOffset(int x, int y);
int getOffsetX();
int getOffsetY();
protected:
int mOffsetX;
int mOffsetY;
Window* mWindow;
};
#endif

91
src/GuiComponent.cpp Normal file
View file

@ -0,0 +1,91 @@
#include "GuiComponent.h"
#include "Window.h"
GuiComponent::GuiComponent(Window* window) : mWindow(window), mParent(NULL)
{
}
GuiComponent::~GuiComponent()
{
mWindow->removeGui(this);
if(mParent)
mParent->removeChild(this);
}
bool GuiComponent::input(InputConfig* config, Input input)
{
for(unsigned int i = 0; i < getChildCount(); i++)
{
if(getChild(i)->input(config, input))
return true;
}
return false;
}
void GuiComponent::update(int deltaTime)
{
for(unsigned int i = 0; i < getChildCount(); i++)
{
getChild(i)->update(deltaTime);
}
}
void GuiComponent::render()
{
for(unsigned int i = 0; i < getChildCount(); i++)
{
getChild(i)->render();
}
}
void GuiComponent::init()
{
for(unsigned int i = 0; i < getChildCount(); i++)
{
getChild(i)->init();
}
}
void GuiComponent::deinit()
{
for(unsigned int i = 0; i < getChildCount(); i++)
{
getChild(i)->deinit();
}
}
void GuiComponent::setParent(GuiComponent* parent)
{
mParent = parent;
}
GuiComponent* GuiComponent::getParent()
{
return mParent;
}
Vector2i GuiComponent::getGlobalOffset()
{
if(mParent)
return mParent->getGlobalOffset() + mOffset;
else
return mOffset;
}
Vector2i GuiComponent::getOffset()
{
return mOffset;
}
void GuiComponent::setOffset(Vector2i offset)
{
mOffset = offset;
}
void GuiComponent::setOffset(int x, int y)
{
mOffset.x = x;
mOffset.y = y;
}

37
src/GuiComponent.h Normal file
View file

@ -0,0 +1,37 @@
#ifndef _GUICOMPONENT_H_
#define _GUICOMPONENT_H_
#include "InputConfig.h"
#include "Vector2.h"
#include "ComponentContainer.h"
class Window;
class GuiComponent : public ComponentContainer
{
public:
GuiComponent(Window* window);
virtual ~GuiComponent();
//Return true if the input is consumed, false if it should continue to be passed to other children.
virtual bool input(InputConfig* config, Input input);
virtual void update(int deltaTime);
virtual void render();
virtual void init();
virtual void deinit();
Vector2i getGlobalOffset();
Vector2i getOffset();
void setOffset(Vector2i offset);
void setOffset(int x, int y);
void setParent(GuiComponent* parent);
GuiComponent* getParent();
protected:
Window* mWindow;
GuiComponent* mParent;
Vector2i mOffset;
};
#endif

View file

@ -14,24 +14,24 @@ Window::~Window()
delete mInputManager;
}
void Window::pushGui(Gui* gui)
void Window::pushGui(GuiComponent* gui)
{
mGuiStack.push_back(gui);
}
void Window::removeGui(Gui* gui)
void Window::removeGui(GuiComponent* gui)
{
for(unsigned int i = 0; i < mGuiStack.size(); i++)
for(auto i = mGuiStack.begin(); i != mGuiStack.end(); i++)
{
if(mGuiStack.at(i) == gui)
if(*i == gui)
{
mGuiStack.erase(mGuiStack.begin() + i);
break;
mGuiStack.erase(i);
return;
}
}
}
Gui* Window::peekGui()
GuiComponent* Window::peekGui()
{
if(mGuiStack.size() == 0)
return NULL;
@ -41,6 +41,7 @@ Gui* Window::peekGui()
void Window::render()
{
//there's nothing to render, which should pretty much never happen
if(mGuiStack.size() == 0)
std::cout << "guistack empty\n";

View file

@ -1,7 +1,7 @@
#ifndef _WINDOW_H_
#define _WINDOW_H_
#include "Gui.h"
#include "GuiComponent.h"
#include "InputManager.h"
#include <vector>
@ -11,9 +11,9 @@ public:
Window();
~Window();
void pushGui(Gui* gui);
void removeGui(Gui* gui);
Gui* peekGui();
void pushGui(GuiComponent* gui);
void removeGui(GuiComponent* gui);
GuiComponent* peekGui();
void input(InputConfig* config, Input input);
void update(int deltaTime);
@ -26,7 +26,7 @@ public:
private:
InputManager* mInputManager;
std::vector<Gui*> mGuiStack;
std::vector<GuiComponent*> mGuiStack;
};
#endif

View file

@ -1,6 +1,6 @@
#include "GuiAnimation.h"
#include "AnimationComponent.h"
GuiAnimation::GuiAnimation()
AnimationComponent::AnimationComponent()
{
mMoveX = 0;
mMoveY = 0;
@ -8,14 +8,14 @@ GuiAnimation::GuiAnimation()
mFadeRate = 0;
}
void GuiAnimation::move(int x, int y, int speed)
void AnimationComponent::move(int x, int y, int speed)
{
mMoveX = x;
mMoveY = y;
mMoveSpeed = speed;
}
void GuiAnimation::fadeIn(int time)
void AnimationComponent::fadeIn(int time)
{
mOpacity = 0;
setChildrenOpacity(0);
@ -23,7 +23,7 @@ void GuiAnimation::fadeIn(int time)
mFadeRate = time;
}
void GuiAnimation::fadeOut(int time)
void AnimationComponent::fadeOut(int time)
{
mOpacity = 255;
setChildrenOpacity(255);
@ -31,7 +31,7 @@ void GuiAnimation::fadeOut(int time)
mFadeRate = -time;
}
void GuiAnimation::update(int deltaTime)
void AnimationComponent::update(int deltaTime)
{
float mult = deltaTime * 0.05f;
@ -69,21 +69,22 @@ void GuiAnimation::update(int deltaTime)
}
}
void GuiAnimation::addChild(GuiImage* gui)
void AnimationComponent::addChild(ImageComponent* gui)
{
mChildren.push_back(gui);
}
void GuiAnimation::moveChildren(int offsetx, int offsety)
void AnimationComponent::moveChildren(int offsetx, int offsety)
{
Vector2i move(offsetx, offsety);
for(unsigned int i = 0; i < mChildren.size(); i++)
{
GuiImage* comp = mChildren.at(i);
comp->setOffset(comp->getOffsetX() + offsetx, comp->getOffsetY() + offsety);
ImageComponent* comp = mChildren.at(i);
comp->setOffset(comp->getOffset() + move);
}
}
void GuiAnimation::setChildrenOpacity(unsigned char opacity)
void AnimationComponent::setChildrenOpacity(unsigned char opacity)
{
for(unsigned int i = 0; i < mChildren.size(); i++)
{

View file

@ -1,14 +1,14 @@
#ifndef _GUIANIMATION_H_
#define _GUIANIMATION_H_
#ifndef _ANIMATIONCOMPONENT_H_
#define _ANIMATIONCOMPONENT_H_
#include "../Gui.h"
#include "GuiImage.h"
#include "../GuiComponent.h"
#include "ImageComponent.h"
#include <vector>
class GuiAnimation
class AnimationComponent
{
public:
GuiAnimation();
AnimationComponent();
void move(int x, int y, int speed);
void fadeIn(int time);
@ -16,12 +16,12 @@ public:
void update(int deltaTime);
void addChild(GuiImage* gui);
void addChild(ImageComponent* gui);
private:
unsigned char mOpacity;
std::vector<GuiImage*> mChildren;
std::vector<ImageComponent*> mChildren;
void moveChildren(int offsetx, int offsety);
void setChildrenOpacity(unsigned char opacity);

View file

@ -1,10 +1,9 @@
#include "GuiBox.h"
GuiBox::GuiBox(Window* window, int offsetX, int offsetY, unsigned int width, unsigned int height) : Gui(window), mBackgroundImage(window),
GuiBox::GuiBox(Window* window, int offsetX, int offsetY, unsigned int width, unsigned int height) : GuiComponent(window), mBackgroundImage(window),
mHorizontalImage(window), mVerticalImage(window), mCornerImage(window)
{
setOffsetX(offsetX);
setOffsetY(offsetY);
setOffset(Vector2i(offsetX, offsetY));
mWidth = width;
mHeight = height;
@ -41,8 +40,7 @@ void GuiBox::setBackgroundImage(std::string path, bool tiled)
mBackgroundImage.setOrigin(0, 0);
mBackgroundImage.setResize(mWidth, mHeight, true);
mBackgroundImage.setTiling(tiled);
mBackgroundImage.setOffsetX(getOffsetX());
mBackgroundImage.setOffsetY(getOffsetY());
mBackgroundImage.setOffset(getOffset());
mBackgroundImage.setImage(path);
}
@ -60,53 +58,44 @@ void GuiBox::render()
mBackgroundImage.render();
//left border
mHorizontalImage.setOffsetX(getOffsetX() - getHorizontalBorderWidth());
mHorizontalImage.setOffsetY(getOffsetY());
mHorizontalImage.setOffset(getOffset().x - getHorizontalBorderWidth(), getOffset().y);
mHorizontalImage.setFlipX(false);
mHorizontalImage.render();
//Renderer::drawRect(getOffsetX() - getHorizontalBorderWidth(), getOffsetY(), getHorizontalBorderWidth(), mHeight, 0xFF0000);
//right border
mHorizontalImage.setOffsetX(getOffsetX() + mWidth);
//same Y
mHorizontalImage.setOffset(getOffset().x + mWidth, getOffset().y);
mHorizontalImage.setFlipX(true);
mHorizontalImage.render();
//Renderer::drawRect(getOffsetX() + mWidth, getOffsetY(), getHorizontalBorderWidth(), mHeight, 0xFF0000);
//top border
mVerticalImage.setOffsetX(getOffsetX());
mVerticalImage.setOffsetY(getOffsetY() - getVerticalBorderWidth());
mVerticalImage.setOffset(getOffset().x, getOffset().y - getVerticalBorderWidth());
mVerticalImage.setFlipY(false);
mVerticalImage.render();
//Renderer::drawRect(getOffsetX(), getOffsetY() - getVerticalBorderWidth(), mWidth, getVerticalBorderWidth(), 0x00FF00);
//bottom border
//same X
mVerticalImage.setOffsetY(getOffsetY() + mHeight);
mVerticalImage.setOffset(getOffset().x, getOffset().y + mHeight);
mVerticalImage.setFlipY(true);
mVerticalImage.render();
//Renderer::drawRect(getOffsetX(), getOffsetY() + mHeight, mWidth, getVerticalBorderWidth(), 0x00FF00);
//corner top left
mCornerImage.setOffsetX(getOffsetX() - getHorizontalBorderWidth());
mCornerImage.setOffsetY(getOffsetY() - getVerticalBorderWidth());
mCornerImage.setOffset(getOffset().x - getHorizontalBorderWidth(), getOffset().y - getVerticalBorderWidth());
mCornerImage.setFlipX(false);
mCornerImage.setFlipY(false);
mCornerImage.render();
//top right
mCornerImage.setOffsetX(getOffsetX() + mWidth);
mCornerImage.setOffset(getOffset().x + mWidth, mCornerImage.getOffset().y);
mCornerImage.setFlipX(true);
mCornerImage.render();
//bottom right
mCornerImage.setOffsetY(getOffsetY() + mHeight);
mCornerImage.setOffset(mCornerImage.getOffset().x, getOffset().y + mHeight);
mCornerImage.setFlipY(true);
mCornerImage.render();
//bottom left
mCornerImage.setOffsetX(getOffsetX() - getHorizontalBorderWidth());
mCornerImage.setOffset(getOffset().x - getHorizontalBorderWidth(), mCornerImage.getOffset().y);
mCornerImage.setFlipX(false);
mCornerImage.render();
}

View file

@ -1,8 +1,8 @@
#ifndef _GUIBOX_H_
#define _GUIBOX_H_
#include "../Gui.h"
#include "GuiImage.h"
#include "../GuiComponent.h"
#include "ImageComponent.h"
#include <string>
struct GuiBoxData
@ -16,7 +16,7 @@ struct GuiBoxData
std::string cornerPath;
};
class GuiBox : public Gui
class GuiBox : public GuiComponent
{
public:
GuiBox(Window* window, int offsetX, int offsetY, unsigned int width, unsigned int height);
@ -34,8 +34,9 @@ public:
void init();
void deinit();
private:
GuiImage mBackgroundImage, mHorizontalImage, mVerticalImage, mCornerImage;
ImageComponent mBackgroundImage, mHorizontalImage, mVerticalImage, mCornerImage;
int getHorizontalBorderWidth();
int getVerticalBorderWidth();

View file

@ -7,7 +7,7 @@
#include <string>
#include <sstream>
GuiDetectDevice::GuiDetectDevice(Window* window) : Gui(window)
GuiDetectDevice::GuiDetectDevice(Window* window) : GuiComponent(window)
{
//clear any player information from the InputManager
for(int i = 0; i < mWindow->getInputManager()->getNumPlayers(); i++)
@ -22,7 +22,7 @@ GuiDetectDevice::GuiDetectDevice(Window* window) : Gui(window)
mHoldingFinish = false;
}
void GuiDetectDevice::input(InputConfig* config, Input input)
bool GuiDetectDevice::input(InputConfig* config, Input input)
{
if((input.type == TYPE_BUTTON || input.type == TYPE_KEY))
{
@ -38,11 +38,11 @@ void GuiDetectDevice::input(InputConfig* config, Input input)
mHoldingFinish = false;
}
}
return;
return true;
}
if(!input.value)
return;
return false;
config->setPlayerNum(mCurrentPlayer);
mWindow->getInputManager()->setNumPlayers(mWindow->getInputManager()->getNumPlayers() + 1); //inc total number of players
@ -53,7 +53,11 @@ void GuiDetectDevice::input(InputConfig* config, Input input)
{
done();
}
return true;
}
return false;
}
void GuiDetectDevice::done()

View file

@ -1,14 +1,14 @@
#ifndef _GUIDETECTDEVICE_H_
#define _GUIDETECTDEVICE_H_
#include "../Gui.h"
#include "../GuiComponent.h"
class GuiDetectDevice : public Gui
class GuiDetectDevice : public GuiComponent
{
public:
GuiDetectDevice(Window* window);
void input(InputConfig* config, Input input);
bool input(InputConfig* config, Input input);
void update(int deltaTime);
void render();

View file

@ -7,8 +7,8 @@ const std::string GuiFastSelect::LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const int GuiFastSelect::SCROLLSPEED = 100;
const int GuiFastSelect::SCROLLDELAY = 507;
GuiFastSelect::GuiFastSelect(Window* window, GuiGameList* parent, GuiList<FileData*>* list, char startLetter, GuiBoxData data,
int textcolor, std::shared_ptr<Sound> & scrollsound, Font* font) : Gui(window)
GuiFastSelect::GuiFastSelect(Window* window, GuiGameList* parent, TextListComponent<FileData*>* list, char startLetter, GuiBoxData data,
int textcolor, std::shared_ptr<Sound> & scrollsound, Font* font) : GuiComponent(window)
{
mLetterID = LETTERS.find(toupper(startLetter));
if(mLetterID == std::string::npos)
@ -48,18 +48,20 @@ void GuiFastSelect::render()
Renderer::drawCenteredText(LETTERS.substr(mLetterID, 1), 0, (int)(sh * 0.5f - (mFont->getHeight() * 0.5f)), mTextColor, mFont);
}
void GuiFastSelect::input(InputConfig* config, Input input)
bool GuiFastSelect::input(InputConfig* config, Input input)
{
if(config->isMappedTo("up", input) && input.value != 0)
{
mScrollOffset = -1;
scroll();
return true;
}
if(config->isMappedTo("down", input) && input.value != 0)
{
mScrollOffset = 1;
scroll();
return true;
}
if((config->isMappedTo("up", input) || config->isMappedTo("down", input)) && input.value == 0)
@ -67,14 +69,17 @@ void GuiFastSelect::input(InputConfig* config, Input input)
mScrolling = false;
mScrollTimer = 0;
mScrollOffset = 0;
return true;
}
if(config->isMappedTo("select", input) && input.value == 0)
{
setListPos();
delete this;
return;
return true;
}
return false;
}
void GuiFastSelect::update(int deltaTime)

View file

@ -1,22 +1,23 @@
#ifndef _GUIFASTSELECT_H_
#define _GUIFASTSELECT_H_
#include "../Gui.h"
#include "../GuiComponent.h"
#include "../SystemData.h"
#include "../FolderData.h"
#include "../Sound.h"
#include "GuiList.h"
#include "TextListComponent.h"
#include "GuiBox.h"
class GuiGameList;
class GuiFastSelect : public Gui
class GuiFastSelect : public GuiComponent
{
public:
GuiFastSelect(Window* window, GuiGameList* parent, GuiList<FileData*>* list, char startLetter, GuiBoxData data, int textcolor, std::shared_ptr<Sound> & scrollsound, Font* font);
GuiFastSelect(Window* window, GuiGameList* parent, TextListComponent<FileData*>* list, char startLetter, GuiBoxData data,
int textcolor, std::shared_ptr<Sound> & scrollsound, Font* font);
~GuiFastSelect();
void input(InputConfig* config, Input input);
bool input(InputConfig* config, Input input);
void update(int deltaTime);
void render();
private:
@ -28,7 +29,7 @@ private:
void scroll();
void setLetterID(int id);
GuiList<FileData*>* mList;
TextListComponent<FileData*>* mList;
size_t mLetterID;
GuiGameList* mParent;

View file

@ -6,26 +6,26 @@
#include <boost/filesystem.hpp>
#include "../Log.h"
GuiGameList::GuiGameList(Window* window, bool useDetail) : Gui(window)
GuiGameList::GuiGameList(Window* window, bool useDetail) : GuiComponent(window)
{
mDetailed = useDetail;
mTheme = new GuiTheme(mWindow, mDetailed);
mTheme = new ThemeComponent(mWindow, mDetailed);
//The GuiGameList can use the older, simple game list if so desired.
//The old view only shows a list in the center of the screen; the new view can display an image and description.
//Those with smaller displays may prefer the older view.
if(mDetailed)
{
mList = new GuiList<FileData*>(mWindow, (int)(Renderer::getScreenWidth() * mTheme->getFloat("listOffsetX")), Renderer::getDefaultFont(Renderer::LARGE)->getHeight() + 2, Renderer::getDefaultFont(Renderer::MEDIUM));
mList = new TextListComponent<FileData*>(mWindow, (int)(Renderer::getScreenWidth() * mTheme->getFloat("listOffsetX")), Renderer::getDefaultFont(Renderer::LARGE)->getHeight() + 2, Renderer::getDefaultFont(Renderer::MEDIUM));
mScreenshot = new GuiImage(mWindow, (int)(Renderer::getScreenWidth() * mTheme->getFloat("gameImageOffsetX")), (int)(Renderer::getScreenHeight() * mTheme->getFloat("gameImageOffsetY")), "", (unsigned int)mTheme->getFloat("gameImageWidth"), (unsigned int)mTheme->getFloat("gameImageHeight"), false);
mScreenshot = new ImageComponent(mWindow, (int)(Renderer::getScreenWidth() * mTheme->getFloat("gameImageOffsetX")), (int)(Renderer::getScreenHeight() * mTheme->getFloat("gameImageOffsetY")), "", (unsigned int)mTheme->getFloat("gameImageWidth"), (unsigned int)mTheme->getFloat("gameImageHeight"), false);
mScreenshot->setOrigin(mTheme->getFloat("gameImageOriginX"), mTheme->getFloat("gameImageOriginY"));
mImageAnimation = new GuiAnimation();
mImageAnimation = new AnimationComponent();
mImageAnimation->addChild(mScreenshot);
}else{
mList = new GuiList<FileData*>(mWindow, 0, Renderer::getDefaultFont(Renderer::LARGE)->getHeight() + 2, Renderer::getDefaultFont(Renderer::MEDIUM));
mList = new TextListComponent<FileData*>(mWindow, 0, Renderer::getDefaultFont(Renderer::LARGE)->getHeight() + 2, Renderer::getDefaultFont(Renderer::MEDIUM));
mScreenshot = NULL;
mImageAnimation = NULL;
}
@ -94,7 +94,7 @@ void GuiGameList::render()
std::string desc = game->getDescription();
if(!desc.empty())
Renderer::drawWrappedText(desc, (int)(Renderer::getScreenWidth() * 0.03), mScreenshot->getOffsetY() + mScreenshot->getHeight() + 12, (int)(Renderer::getScreenWidth() * (mTheme->getFloat("listOffsetX") - 0.03)), mTheme->getColor("description"), mTheme->getDescriptionFont());
Renderer::drawWrappedText(desc, (int)(Renderer::getScreenWidth() * 0.03), mScreenshot->getOffset().y + mScreenshot->getHeight() + 12, (int)(Renderer::getScreenWidth() * (mTheme->getFloat("listOffsetX") - 0.03)), mTheme->getColor("description"), mTheme->getDescriptionFont());
}
mScreenshot->render();
@ -103,7 +103,7 @@ void GuiGameList::render()
mList->render();
}
void GuiGameList::input(InputConfig* config, Input input)
bool GuiGameList::input(InputConfig* config, Input input)
{
mList->input(config, input);
@ -118,6 +118,7 @@ void GuiGameList::input(InputConfig* config, Input input)
mFolderStack.push(mFolder);
mFolder = (FolderData*)file;
updateList();
return true;
}else{
mList->stopScrolling();
@ -125,7 +126,7 @@ void GuiGameList::input(InputConfig* config, Input input)
while(mTheme->getSound("menuSelect")->isPlaying());
mSystem->launchGame(mWindow, (GameData*)file);
return;
return true;
}
}
@ -139,6 +140,8 @@ void GuiGameList::input(InputConfig* config, Input input)
//play the back sound
mTheme->getSound("menuBack")->play();
return true;
}
//only allow switching systems if more than one exists (otherwise it'll reset your position when you switch and it's annoying)
@ -147,10 +150,12 @@ void GuiGameList::input(InputConfig* config, Input input)
if(config->isMappedTo("right", input))
{
setSystemId(mSystemId + 1);
return true;
}
if(config->isMappedTo("left", input))
{
setSystemId(mSystemId - 1);
return true;
}
}
@ -158,12 +163,14 @@ void GuiGameList::input(InputConfig* config, Input input)
if(config->isMappedTo("menu", input) && input.value != 0)
{
mWindow->pushGui(new GuiMenu(mWindow, this));
return true;
}
//open the fast select menu
if(config->isMappedTo("select", input) && input.value != 0)
{
mWindow->pushGui(new GuiFastSelect(mWindow, this, mList, mList->getSelectedObject()->getName()[0], mTheme->getBoxData(), mTheme->getColor("fastSelect"), mTheme->getSound("menuScroll"), mTheme->getFastSelectFont()));
return true;
}
if(mDetailed)
@ -175,7 +182,10 @@ void GuiGameList::input(InputConfig* config, Input input)
else
clearDetailData();
}
return true;
}
return false;
}
void GuiGameList::updateList()
@ -235,11 +245,10 @@ void GuiGameList::updateTheme()
{
mList->setCentered(mTheme->getBool("listCentered"));
mList->setOffsetX((int)(mTheme->getFloat("listOffsetX") * Renderer::getScreenWidth()));
mList->setOffset((int)(mTheme->getFloat("listOffsetX") * Renderer::getScreenWidth()), mList->getOffset().y);
mList->setTextOffsetX((int)(mTheme->getFloat("listTextOffsetX") * Renderer::getScreenWidth()));
mScreenshot->setOffsetX((int)(mTheme->getFloat("gameImageOffsetX") * Renderer::getScreenWidth()));
mScreenshot->setOffsetY((int)(mTheme->getFloat("gameImageOffsetY") * Renderer::getScreenHeight()));
mScreenshot->setOffset((int)(mTheme->getFloat("gameImageOffsetX") * Renderer::getScreenWidth()), (int)(mTheme->getFloat("gameImageOffsetY") * Renderer::getScreenHeight()));
mScreenshot->setOrigin(mTheme->getFloat("gameImageOriginX"), mTheme->getFloat("gameImageOriginY"));
mScreenshot->setResize((int)mTheme->getFloat("gameImageWidth"), (int)mTheme->getFloat("gameImageHeight"), false);
}

View file

@ -1,11 +1,11 @@
#ifndef _GUIGAMELIST_H_
#define _GUIGAMELIST_H_
#include "../Gui.h"
#include "GuiList.h"
#include "GuiImage.h"
#include "GuiTheme.h"
#include "GuiAnimation.h"
#include "../GuiComponent.h"
#include "TextListComponent.h"
#include "ImageComponent.h"
#include "ThemeComponent.h"
#include "AnimationComponent.h"
#include <string>
#include <stack>
#include "../SystemData.h"
@ -14,15 +14,15 @@
//This is where the magic happens - GuiGameList is the parent of almost every graphical element in ES at the moment.
//It has a GuiList child that handles the game list, a GuiTheme that handles the theming system, and a GuiImage for game images.
class GuiGameList : public Gui
class GuiGameList : public GuiComponent
{
public:
GuiGameList(Window* window, bool useDetail = false);
~GuiGameList();
virtual ~GuiGameList();
void setSystemId(int id);
void input(InputConfig* config, Input input);
bool input(InputConfig* config, Input input);
void update(int deltaTime);
void render();
@ -46,10 +46,10 @@ private:
int mSystemId;
bool mDetailed;
GuiList<FileData*>* mList;
GuiImage* mScreenshot;
GuiAnimation* mImageAnimation;
GuiTheme* mTheme;
TextListComponent<FileData*>* mList;
ImageComponent* mScreenshot;
AnimationComponent* mImageAnimation;
ThemeComponent* mTheme;
};
#endif

View file

@ -9,7 +9,7 @@ static int inputCount = 12;
static std::string inputName[12] = { "Up", "Down", "Left", "Right", "A", "B", "Menu", "Select", "PageUp", "PageDown", "MasterVolUp", "MasterVolDown" };
static std::string inputDispName[12] = { "Up", "Down", "Left", "Right", "Accept", "Back", "Menu", "Jump to Letter", "Page Up", "Page Down", "Master volume up", "Master volume down" };
GuiInputConfig::GuiInputConfig(Window* window, InputConfig* target) : Gui(window), mTargetConfig(target)
GuiInputConfig::GuiInputConfig(Window* window, InputConfig* target) : GuiComponent(window), mTargetConfig(target)
{
mCurInputId = 0;
LOG(LogInfo) << "Configuring device " << target->getDeviceId();
@ -20,10 +20,10 @@ void GuiInputConfig::update(int deltaTime)
}
void GuiInputConfig::input(InputConfig* config, Input input)
bool GuiInputConfig::input(InputConfig* config, Input input)
{
if(config != mTargetConfig || input.value == 0)
return;
return false;
if(mCurInputId >= inputCount)
{
@ -43,7 +43,7 @@ void GuiInputConfig::input(InputConfig* config, Input input)
if(config->getMappedTo(input).size() > 0)
{
mErrorMsg = "Already mapped!";
return;
return true;
}
input.configured = true;
@ -59,6 +59,8 @@ void GuiInputConfig::input(InputConfig* config, Input input)
mCurInputId = inputCount;
}
}
return true;
}
void GuiInputConfig::render()

View file

@ -1,15 +1,15 @@
#ifndef _GUIINPUTCONFIG_H_
#define _GUIINPUTCONFIG_H_
#include "../Gui.h"
#include "../GuiComponent.h"
#include <string>
class GuiInputConfig : public Gui
class GuiInputConfig : public GuiComponent
{
public:
GuiInputConfig(Window* window, InputConfig* target);
void input(InputConfig* config, Input input);
bool input(InputConfig* config, Input input);
void update(int deltaTime);
void render();

View file

@ -1,293 +0,0 @@
//This is *actually* part of the GuiList header and not meant to be compiled.
#include "GuiList.h"
#include <iostream>
template <typename listType>
GuiList<listType>::GuiList(Window* window, int offsetX, int offsetY, Font* font) : Gui(window)
{
mSelection = 0;
mScrollDir = 0;
mScrolling = 0;
mScrollAccumulator = 0;
mOffsetX = offsetX;
mOffsetY = offsetY;
mTextOffsetX = 0;
mFont = font;
mSelectorColor = 0x000000FF;
mSelectedTextColorOverride = 0;
mScrollSound = NULL;
mDrawCentered = true;
}
template <typename listType>
GuiList<listType>::~GuiList()
{
}
template <typename listType>
void GuiList<listType>::render()
{
const int cutoff = getOffsetY();
const int entrySize = mFont->getHeight() + 5;
int startEntry = 0;
//number of entries that can fit on the screen simultaniously
int screenCount = (Renderer::getScreenHeight() - cutoff) / entrySize;
//screenCount -= 1;
if((int)mRowVector.size() >= screenCount)
{
startEntry = mSelection - (int)(screenCount * 0.5);
if(startEntry < 0)
startEntry = 0;
if(startEntry >= (int)mRowVector.size() - screenCount)
startEntry = mRowVector.size() - screenCount;
}
int y = cutoff;
if(mRowVector.size() == 0)
{
Renderer::drawCenteredText("The list is empty.", 0, y, 0xFF0000FF, mFont);
return;
}
int listCutoff = startEntry + screenCount;
if(listCutoff > (int)mRowVector.size())
listCutoff = mRowVector.size();
for(int i = startEntry; i < listCutoff; i++)
{
//draw selector bar
if(mSelection == i)
{
Renderer::drawRect(getOffsetX(), y, Renderer::getScreenWidth(), mFont->getHeight(), mSelectorColor);
}
ListRow row = mRowVector.at((unsigned int)i);
if(mDrawCentered)
Renderer::drawCenteredText(row.name, getOffsetX(), y, (mSelection == i && mSelectedTextColorOverride != 0) ? mSelectedTextColorOverride : row.color, mFont);
else
Renderer::drawText(row.name, getOffsetX() + mTextOffsetX, y, (mSelection == i && mSelectedTextColorOverride != 0) ? mSelectedTextColorOverride : row.color, mFont);
y += entrySize;
}
}
template <typename listType>
void GuiList<listType>::input(InputConfig* config, Input input)
{
if(mRowVector.size() > 0)
{
if(input.value != 0)
{
if(config->isMappedTo("down", input))
{
mScrollDir = 1;
scroll();
}
if(config->isMappedTo("up", input))
{
mScrollDir = -1;
scroll();
}
if(config->isMappedTo("pagedown", input))
{
mScrollDir = 10;
scroll();
}
if(config->isMappedTo("pageup", input))
{
mScrollDir = -10;
scroll();
}
}else{
//if((button == InputManager::DOWN && mScrollDir > 0) || (button == InputManager::PAGEDOWN && mScrollDir > 0) || (button == InputManager::UP && mScrollDir < 0) || (button == InputManager::PAGEUP && mScrollDir < 0))
if(config->isMappedTo("down", input) || config->isMappedTo("up", input) || config->isMappedTo("pagedown", input) || config->isMappedTo("pageup", input))
{
stopScrolling();
}
}
}
}
template <typename listType>
void GuiList<listType>::stopScrolling()
{
mScrollAccumulator = 0;
mScrolling = false;
mScrollDir = 0;
}
template <typename listType>
void GuiList<listType>::update(int deltaTime)
{
if(mScrollDir != 0)
{
mScrollAccumulator += deltaTime;
if(!mScrolling)
{
if(mScrollAccumulator >= SCROLLDELAY)
{
mScrollAccumulator = SCROLLTIME;
mScrolling = true;
}
}
if(mScrolling)
{
mScrollAccumulator += deltaTime;
while(mScrollAccumulator >= SCROLLTIME)
{
mScrollAccumulator -= SCROLLTIME;
scroll();
}
}
}
}
template <typename listType>
void GuiList<listType>::scroll()
{
mSelection += mScrollDir;
if(mSelection < 0)
{
if(mScrollDir < -1)
mSelection = 0;
else
mSelection += mRowVector.size();
}
if(mSelection >= (int)mRowVector.size())
{
if(mScrollDir > 1)
mSelection = (int)mRowVector.size() - 1;
else
mSelection -= mRowVector.size();
}
if(mScrollSound)
mScrollSound->play();
}
//list management stuff
template <typename listType>
void GuiList<listType>::addObject(std::string name, listType obj, unsigned int color)
{
ListRow row = {name, obj, color};
mRowVector.push_back(row);
}
template <typename listType>
void GuiList<listType>::clear()
{
mRowVector.clear();
mSelection = 0;
}
template <typename listType>
std::string GuiList<listType>::getSelectedName()
{
if((int)mRowVector.size() > mSelection)
return mRowVector.at(mSelection).name;
else
return "";
}
template <typename listType>
listType GuiList<listType>::getSelectedObject()
{
if((int)mRowVector.size() > mSelection)
return mRowVector.at(mSelection).object;
else
return NULL;
}
template <typename listType>
int GuiList<listType>::getSelection()
{
return mSelection;
}
template <typename listType>
bool GuiList<listType>::isScrolling()
{
return mScrollDir != 0;
}
template <typename listType>
void GuiList<listType>::setSelectorColor(unsigned int selectorColor)
{
mSelectorColor = selectorColor;
}
template <typename listType>
void GuiList<listType>::setSelectedTextColor(unsigned int selectedColor)
{
mSelectedTextColorOverride = selectedColor;
}
template<typename listType>
void GuiList<listType>::setCentered(bool centered)
{
mDrawCentered = centered;
}
template<typename listType>
void GuiList<listType>::setTextOffsetX(int textoffsetx)
{
mTextOffsetX = textoffsetx;
}
template <typename listType>
int GuiList<listType>::getObjectCount()
{
return mRowVector.size();
}
template <typename listType>
listType GuiList<listType>::getObject(int i)
{
return mRowVector.at(i).object;
}
template <typename listType>
void GuiList<listType>::setSelection(int i)
{
mSelection = i;
}
template <typename listType>
void GuiList<listType>::setScrollSound(std::shared_ptr<Sound> & sound)
{
mScrollSound = sound;
}
template <typename listType>
void GuiList<listType>::setFont(Font* font)
{
mFont = font;
}
template <typename listType>
int GuiList<listType>::getOffsetX()
{
return mOffsetX;
}
template <typename listType>
int GuiList<listType>::getOffsetY()
{
return mOffsetY;
}

View file

@ -1,80 +0,0 @@
#ifndef _GUILIST_H_
#define _GUILIST_H_
#include "../Renderer.h"
#include "../Font.h"
#include "../Gui.h"
#include "../InputManager.h"
#include <vector>
#include <string>
#include <memory>
#include "../Sound.h"
//A graphical list. Supports multiple colors for rows and scrolling.
//TODO - add truncation to text rendering if name exceeds a maximum width (a trailing elipses, perhaps).
template <typename listType>
class GuiList : public Gui
{
public:
GuiList(Window* window, int offsetX, int offsetY, Font* font);
~GuiList();
void input(InputConfig* config, Input input);
void update(int deltaTime);
void render();
void addObject(std::string name, listType obj, unsigned int color = 0xFF0000);
void clear();
std::string getSelectedName();
listType getSelectedObject();
int getSelection();
void stopScrolling();
bool isScrolling();
void setSelectorColor(unsigned int selectorColor);
void setSelectedTextColor(unsigned int selectedColor);
void setCentered(bool centered);
void setScrollSound(std::shared_ptr<Sound> & sound);
void setTextOffsetX(int textoffsetx);
int getObjectCount();
listType getObject(int i);
void setSelection(int i);
void setFont(Font* f);
int getOffsetX();
int getOffsetY();
private:
static const int SCROLLDELAY = 507;
static const int SCROLLTIME = 200;
int mOffsetX, mOffsetY;
void scroll(); //helper method, scrolls in whatever direction scrollDir is
int mScrollDir, mScrollAccumulator;
bool mScrolling;
Font* mFont;
unsigned int mSelectorColor, mSelectedTextColorOverride;
bool mDrawCentered;
int mTextOffsetX;
struct ListRow
{
std::string name;
listType object;
unsigned int color;
};
std::vector<ListRow> mRowVector;
int mSelection;
std::shared_ptr<Sound> mScrollSound;
};
#include "GuiList.cpp"
#endif

View file

@ -8,11 +8,11 @@
//defined in main.cpp
extern bool DONTSHOWEXIT;
GuiMenu::GuiMenu(Window* window, GuiGameList* parent) : Gui(window)
GuiMenu::GuiMenu(Window* window, GuiGameList* parent) : GuiComponent(window)
{
mParent = parent;
mList = new GuiList<std::string>(mWindow, 0, Renderer::getDefaultFont(Renderer::LARGE)->getHeight() + 2, Renderer::getDefaultFont(Renderer::LARGE));
mList = new TextListComponent<std::string>(mWindow, 0, Renderer::getDefaultFont(Renderer::LARGE)->getHeight() + 2, Renderer::getDefaultFont(Renderer::LARGE));
mList->setSelectedTextColor(0x0000FFFF);
populateList();
}
@ -22,20 +22,23 @@ GuiMenu::~GuiMenu()
delete mList;
}
void GuiMenu::input(InputConfig* config, Input input)
bool GuiMenu::input(InputConfig* config, Input input)
{
mList->input(config, input);
if(config->isMappedTo("menu", input) && input.value != 0)
{
delete this;
return;
return true;
}
if(config->isMappedTo("a", input) && input.value != 0)
{
executeCommand(mList->getSelectedObject());
return true;
}
return false;
}
void GuiMenu::executeCommand(std::string command)

View file

@ -1,24 +1,24 @@
#ifndef _GUIMENU_H_
#define _GUIMENU_H_
#include "../Gui.h"
#include "GuiList.h"
#include "../GuiComponent.h"
#include "TextListComponent.h"
class GuiGameList;
class GuiMenu : public Gui
class GuiMenu : public GuiComponent
{
public:
GuiMenu(Window* window, GuiGameList* parent);
~GuiMenu();
virtual ~GuiMenu();
void input(InputConfig* config, Input input);
bool input(InputConfig* config, Input input);
void update(int deltaTime);
void render();
private:
GuiGameList* mParent;
GuiList<std::string>* mList;
TextListComponent<std::string>* mList;
void populateList();
void executeCommand(std::string command);

View file

@ -1,18 +1,18 @@
#include "GuiImage.h"
#include "ImageComponent.h"
#include <iostream>
#include <boost/filesystem.hpp>
#include <math.h>
#include "../Log.h"
#include "../Renderer.h"
unsigned int GuiImage::getWidth() { return mDrawWidth; }
unsigned int GuiImage::getHeight() { return mDrawHeight; }
unsigned int ImageComponent::getWidth() { return mDrawWidth; }
unsigned int ImageComponent::getHeight() { return mDrawHeight; }
GuiImage::GuiImage(Window* window, int offsetX, int offsetY, std::string path, unsigned int resizeWidth, unsigned int resizeHeight, bool resizeExact) : Gui(window)
ImageComponent::ImageComponent(Window* window, int offsetX, int offsetY, std::string path, unsigned int resizeWidth, unsigned int resizeHeight, bool resizeExact) : GuiComponent(window)
{
mTextureID = 0;
setOffset(offsetX, offsetY);
setOffset(Vector2i(offsetX, offsetY));
//default origin is the center of image
mOriginX = 0.5;
@ -36,12 +36,12 @@ GuiImage::GuiImage(Window* window, int offsetX, int offsetY, std::string path, u
setImage(path);
}
GuiImage::~GuiImage()
ImageComponent::~ImageComponent()
{
unloadImage();
}
void GuiImage::loadImage(std::string path)
void ImageComponent::loadImage(std::string path)
{
//make sure the file *exists*
if(!boost::filesystem::exists(path))
@ -171,7 +171,7 @@ void GuiImage::loadImage(std::string path)
resize();
}
void GuiImage::resize()
void ImageComponent::resize()
{
mDrawWidth = mWidth;
mDrawHeight = mHeight;
@ -206,7 +206,7 @@ void GuiImage::resize()
}
}
void GuiImage::unloadImage()
void ImageComponent::unloadImage()
{
if(mTextureID)
{
@ -216,7 +216,7 @@ void GuiImage::unloadImage()
}
}
void GuiImage::setImage(std::string path)
void ImageComponent::setImage(std::string path)
{
if(mPath == path)
return;
@ -229,13 +229,13 @@ void GuiImage::setImage(std::string path)
}
void GuiImage::setOrigin(float originX, float originY)
void ImageComponent::setOrigin(float originX, float originY)
{
mOriginX = originX;
mOriginY = originY;
}
void GuiImage::setTiling(bool tile)
void ImageComponent::setTiling(bool tile)
{
mTiled = tile;
@ -243,7 +243,7 @@ void GuiImage::setTiling(bool tile)
mResizeExact = false;
}
void GuiImage::setResize(unsigned int width, unsigned int height, bool resizeExact)
void ImageComponent::setResize(unsigned int width, unsigned int height, bool resizeExact)
{
mResizeWidth = width;
mResizeHeight = height;
@ -251,17 +251,17 @@ void GuiImage::setResize(unsigned int width, unsigned int height, bool resizeExa
resize();
}
void GuiImage::setFlipX(bool flip)
void ImageComponent::setFlipX(bool flip)
{
mFlipX = flip;
}
void GuiImage::setFlipY(bool flip)
void ImageComponent::setFlipY(bool flip)
{
mFlipY = flip;
}
void GuiImage::render()
void ImageComponent::render()
{
if(mTextureID && getOpacity() > 0)
{
@ -274,17 +274,17 @@ void GuiImage::render()
float yCount = ((float)mResizeHeight/mHeight);
Renderer::buildGLColorArray(colors, 0xFFFFFF00 | (getOpacity()), 6);
buildImageArray(getOffsetX(), getOffsetY(), points, texs, xCount, yCount);
buildImageArray(getOffset().x, getOffset().y, points, texs, xCount, yCount);
}else{
Renderer::buildGLColorArray(colors, 0xFFFFFF00 | (getOpacity()), 6);
buildImageArray(getOffsetX(), getOffsetY(), points, texs);
buildImageArray(getOffset().x, getOffset().y, points, texs);
}
drawImageArray(points, texs, colors, 6);
}
}
void GuiImage::buildImageArray(int posX, int posY, GLfloat* points, GLfloat* texs, float px, float py)
void ImageComponent::buildImageArray(int posX, int posY, GLfloat* points, GLfloat* texs, float px, float py)
{
points[0] = posX - (mDrawWidth * mOriginX) * px; points[1] = posY - (mDrawHeight * mOriginY) * py;
points[2] = posX - (mDrawWidth * mOriginX) * px; points[3] = posY + (mDrawHeight * (1 - mOriginY)) * py;
@ -322,14 +322,13 @@ void GuiImage::buildImageArray(int posX, int posY, GLfloat* points, GLfloat* tex
}
}
void GuiImage::drawImageArray(GLfloat* points, GLfloat* texs, GLubyte* colors, unsigned int numArrays)
void ImageComponent::drawImageArray(GLfloat* points, GLfloat* texs, GLubyte* colors, unsigned int numArrays)
{
glBindTexture(GL_TEXTURE_2D, mTextureID);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
@ -354,21 +353,21 @@ void GuiImage::drawImageArray(GLfloat* points, GLfloat* texs, GLubyte* colors, u
glDisable(GL_BLEND);
}
void GuiImage::init()
void ImageComponent::init()
{
if(!mPath.empty())
loadImage(mPath);
}
void GuiImage::deinit()
void ImageComponent::deinit()
{
unloadImage();
}
bool GuiImage::hasImage()
bool ImageComponent::hasImage()
{
return !mPath.empty();
}
unsigned char GuiImage::getOpacity() { return mOpacity; }
void GuiImage::setOpacity(unsigned char opacity) { mOpacity = opacity; }
unsigned char ImageComponent::getOpacity() { return mOpacity; }
void ImageComponent::setOpacity(unsigned char opacity) { mOpacity = opacity; }

View file

@ -1,22 +1,22 @@
#ifndef _GUIIMAGE_H_
#define _GUIIMAGE_H_
#ifndef _IMAGECOMPONENT_H_
#define _IMAGECOMPONENT_H_
#include "../platform.h"
#include GLHEADER
#include "../Gui.h"
#include "../GuiComponent.h"
#include <string>
#include <FreeImage.h>
class GuiImage : public Gui
class ImageComponent : public GuiComponent
{
public:
//Creates a new GuiImage at the given location. If given an image, it will be loaded. If maxWidth and/or maxHeight are nonzero, the image will be
//resized to fix. If only one axis is specified, the other will be resized in accordance with the image's aspect ratio. If resizeExact is false,
//the image will only be downscaled, never upscaled (the image's size must surpass at least one nonzero bound).
GuiImage(Window* window, int offsetX = 0, int offsetY = 0, std::string path = "", unsigned int maxWidth = 0, unsigned int maxHeight = 0, bool resizeExact = false);
~GuiImage();
ImageComponent(Window* window, int offsetX = 0, int offsetY = 0, std::string path = "", unsigned int maxWidth = 0, unsigned int maxHeight = 0, bool resizeExact = false);
virtual ~ImageComponent();
void setImage(std::string path); //Loads the image at the given filepath.
void setOrigin(float originX, float originY); //Sets the origin as a percentage of this image (e.g. (0, 0) is top left, (0.5, 0.5) is the center)
@ -39,12 +39,12 @@ public:
unsigned char getOpacity();
void setOpacity(unsigned char opacity);
private:
unsigned int mResizeWidth, mResizeHeight;
float mOriginX, mOriginY;
bool mResizeExact, mTiled, mFlipX, mFlipY;
int mOffsetX, mOffsetY;
unsigned char mOpacity;
void loadImage(std::string path);

View file

@ -0,0 +1,356 @@
#ifndef _TEXTLISTCOMPONENT_H_
#define _TEXTLISTCOMPONENT_H_
#include "../Renderer.h"
#include "../Font.h"
#include "../GuiComponent.h"
#include "../InputManager.h"
#include <vector>
#include <string>
#include <memory>
#include "../Sound.h"
//A graphical list. Supports multiple colors for rows and scrolling.
//TODO - add truncation to text rendering if name exceeds a maximum width (a trailing elipses, perhaps).
template <typename T>
class TextListComponent : public GuiComponent
{
public:
TextListComponent(Window* window, int offsetX, int offsetY, Font* font);
virtual ~TextListComponent();
bool input(InputConfig* config, Input input);
void update(int deltaTime);
void render();
void addObject(std::string name, T obj, unsigned int color = 0xFF0000);
void clear();
std::string getSelectedName();
T getSelectedObject();
int getSelection();
void stopScrolling();
bool isScrolling();
void setSelectorColor(unsigned int selectorColor);
void setSelectedTextColor(unsigned int selectedColor);
void setCentered(bool centered);
void setScrollSound(std::shared_ptr<Sound> & sound);
void setTextOffsetX(int textoffsetx);
int getObjectCount();
T getObject(int i);
void setSelection(int i);
void setFont(Font* f);
private:
static const int SCROLLDELAY = 507;
static const int SCROLLTIME = 200;
void scroll(); //helper method, scrolls in whatever direction scrollDir is
int mScrollDir, mScrollAccumulator;
bool mScrolling;
Font* mFont;
unsigned int mSelectorColor, mSelectedTextColorOverride;
bool mDrawCentered;
int mTextOffsetX;
struct ListRow
{
std::string name;
T object;
unsigned int color;
};
std::vector<ListRow> mRowVector;
int mSelection;
std::shared_ptr<Sound> mScrollSound;
};
template <typename T>
TextListComponent<T>::TextListComponent(Window* window, int offsetX, int offsetY, Font* font) : GuiComponent(window)
{
mSelection = 0;
mScrollDir = 0;
mScrolling = 0;
mScrollAccumulator = 0;
setOffset(Vector2i(offsetX, offsetY));
mTextOffsetX = 0;
mFont = font;
mSelectorColor = 0x000000FF;
mSelectedTextColorOverride = 0;
mScrollSound = NULL;
mDrawCentered = true;
}
template <typename T>
TextListComponent<T>::~TextListComponent()
{
}
template <typename T>
void TextListComponent<T>::render()
{
const int cutoff = getOffset().y;
const int entrySize = mFont->getHeight() + 5;
int startEntry = 0;
//number of entries that can fit on the screen simultaniously
int screenCount = (Renderer::getScreenHeight() - cutoff) / entrySize;
//screenCount -= 1;
if((int)mRowVector.size() >= screenCount)
{
startEntry = mSelection - (int)(screenCount * 0.5);
if(startEntry < 0)
startEntry = 0;
if(startEntry >= (int)mRowVector.size() - screenCount)
startEntry = mRowVector.size() - screenCount;
}
int y = cutoff;
if(mRowVector.size() == 0)
{
Renderer::drawCenteredText("The list is empty.", 0, y, 0xFF0000FF, mFont);
return;
}
int listCutoff = startEntry + screenCount;
if(listCutoff > (int)mRowVector.size())
listCutoff = mRowVector.size();
for(int i = startEntry; i < listCutoff; i++)
{
//draw selector bar
if(mSelection == i)
{
Renderer::drawRect(getOffset().x, y, Renderer::getScreenWidth(), mFont->getHeight(), mSelectorColor);
}
ListRow row = mRowVector.at((unsigned int)i);
if(mDrawCentered)
Renderer::drawCenteredText(row.name, getOffset().x + mTextOffsetX, y, (mSelection == i && mSelectedTextColorOverride != 0) ? mSelectedTextColorOverride : row.color, mFont);
else
Renderer::drawText(row.name, getOffset().x + mTextOffsetX, y, (mSelection == i && mSelectedTextColorOverride != 0) ? mSelectedTextColorOverride : row.color, mFont);
y += entrySize;
}
}
template <typename T>
bool TextListComponent<T>::input(InputConfig* config, Input input)
{
if(mRowVector.size() > 0)
{
if(input.value != 0)
{
if(config->isMappedTo("down", input))
{
mScrollDir = 1;
scroll();
return true;
}
if(config->isMappedTo("up", input))
{
mScrollDir = -1;
scroll();
return true;
}
if(config->isMappedTo("pagedown", input))
{
mScrollDir = 10;
scroll();
return true;
}
if(config->isMappedTo("pageup", input))
{
mScrollDir = -10;
scroll();
return true;
}
}else{
//if((button == InputManager::DOWN && mScrollDir > 0) || (button == InputManager::PAGEDOWN && mScrollDir > 0) || (button == InputManager::UP && mScrollDir < 0) || (button == InputManager::PAGEUP && mScrollDir < 0))
if(config->isMappedTo("down", input) || config->isMappedTo("up", input) || config->isMappedTo("pagedown", input) || config->isMappedTo("pageup", input))
{
stopScrolling();
}
}
}
return false;
}
template <typename T>
void TextListComponent<T>::stopScrolling()
{
mScrollAccumulator = 0;
mScrolling = false;
mScrollDir = 0;
}
template <typename T>
void TextListComponent<T>::update(int deltaTime)
{
if(mScrollDir != 0)
{
mScrollAccumulator += deltaTime;
if(!mScrolling)
{
if(mScrollAccumulator >= SCROLLDELAY)
{
mScrollAccumulator = SCROLLTIME;
mScrolling = true;
}
}
if(mScrolling)
{
mScrollAccumulator += deltaTime;
while(mScrollAccumulator >= SCROLLTIME)
{
mScrollAccumulator -= SCROLLTIME;
scroll();
}
}
}
}
template <typename T>
void TextListComponent<T>::scroll()
{
mSelection += mScrollDir;
if(mSelection < 0)
{
if(mScrollDir < -1)
mSelection = 0;
else
mSelection += mRowVector.size();
}
if(mSelection >= (int)mRowVector.size())
{
if(mScrollDir > 1)
mSelection = (int)mRowVector.size() - 1;
else
mSelection -= mRowVector.size();
}
if(mScrollSound)
mScrollSound->play();
}
//list management stuff
template <typename T>
void TextListComponent<T>::addObject(std::string name, T obj, unsigned int color)
{
ListRow row = {name, obj, color};
mRowVector.push_back(row);
}
template <typename T>
void TextListComponent<T>::clear()
{
mRowVector.clear();
mSelection = 0;
}
template <typename T>
std::string TextListComponent<T>::getSelectedName()
{
if((int)mRowVector.size() > mSelection)
return mRowVector.at(mSelection).name;
else
return "";
}
template <typename T>
T TextListComponent<T>::getSelectedObject()
{
if((int)mRowVector.size() > mSelection)
return mRowVector.at(mSelection).object;
else
return NULL;
}
template <typename T>
int TextListComponent<T>::getSelection()
{
return mSelection;
}
template <typename T>
bool TextListComponent<T>::isScrolling()
{
return mScrollDir != 0;
}
template <typename T>
void TextListComponent<T>::setSelectorColor(unsigned int selectorColor)
{
mSelectorColor = selectorColor;
}
template <typename T>
void TextListComponent<T>::setSelectedTextColor(unsigned int selectedColor)
{
mSelectedTextColorOverride = selectedColor;
}
template<typename T>
void TextListComponent<T>::setCentered(bool centered)
{
mDrawCentered = centered;
}
template<typename T>
void TextListComponent<T>::setTextOffsetX(int textoffsetx)
{
mTextOffsetX = textoffsetx;
}
template <typename T>
int TextListComponent<T>::getObjectCount()
{
return mRowVector.size();
}
template <typename T>
T TextListComponent<T>::getObject(int i)
{
return mRowVector.at(i).object;
}
template <typename T>
void TextListComponent<T>::setSelection(int i)
{
mSelection = i;
}
template <typename T>
void TextListComponent<T>::setScrollSound(std::shared_ptr<Sound> & sound)
{
mScrollSound = sound;
}
template <typename T>
void TextListComponent<T>::setFont(Font* font)
{
mFont = font;
}
#endif

View file

@ -1,41 +1,41 @@
#include "GuiTheme.h"
#include "ThemeComponent.h"
#include "../MathExp.h"
#include <iostream>
#include "GuiGameList.h"
#include "GuiImage.h"
#include "ImageComponent.h"
#include <boost/filesystem.hpp>
#include <sstream>
#include "../Renderer.h"
#include "../Log.h"
unsigned int GuiTheme::getColor(std::string name)
unsigned int ThemeComponent::getColor(std::string name)
{
return mColorMap[name];
}
bool GuiTheme::getBool(std::string name)
bool ThemeComponent::getBool(std::string name)
{
return mBoolMap[name];
}
float GuiTheme::getFloat(std::string name)
float ThemeComponent::getFloat(std::string name)
{
return mFloatMap[name];
}
std::shared_ptr<Sound> & GuiTheme::getSound(std::string name)
std::shared_ptr<Sound> & ThemeComponent::getSound(std::string name)
{
return mSoundMap[name];
}
std::string GuiTheme::getString(std::string name)
std::string ThemeComponent::getString(std::string name)
{
return mStringMap[name];
}
GuiBoxData GuiTheme::getBoxData() { return mBoxData; }
GuiBoxData ThemeComponent::getBoxData() { return mBoxData; }
Font* GuiTheme::getListFont()
Font* ThemeComponent::getListFont()
{
if(mListFont == NULL)
return Renderer::getDefaultFont(Renderer::MEDIUM);
@ -43,7 +43,7 @@ Font* GuiTheme::getListFont()
return mListFont;
}
Font* GuiTheme::getDescriptionFont()
Font* ThemeComponent::getDescriptionFont()
{
if(mDescFont == NULL)
return Renderer::getDefaultFont(Renderer::SMALL);
@ -51,7 +51,7 @@ Font* GuiTheme::getDescriptionFont()
return mDescFont;
}
Font* GuiTheme::getFastSelectFont()
Font* ThemeComponent::getFastSelectFont()
{
if(mFastSelectFont == NULL)
return Renderer::getDefaultFont(Renderer::LARGE);
@ -59,7 +59,7 @@ Font* GuiTheme::getFastSelectFont()
return mFastSelectFont;
}
GuiTheme::GuiTheme(Window* window, bool detailed, std::string path) : Gui(window)
ThemeComponent::ThemeComponent(Window* window, bool detailed, std::string path) : GuiComponent(window)
{
mDetailed = detailed;
@ -84,12 +84,12 @@ GuiTheme::GuiTheme(Window* window, bool detailed, std::string path) : Gui(window
readXML(path);
}
GuiTheme::~GuiTheme()
ThemeComponent::~ThemeComponent()
{
deleteComponents();
}
void GuiTheme::setDefaults()
void ThemeComponent::setDefaults()
{
mColorMap["primary"] = 0x0000FFFF;
mColorMap["secondary"] = 0x00FF00FF;
@ -144,14 +144,14 @@ void GuiTheme::setDefaults()
}
}
void GuiTheme::deleteComponents()
void ThemeComponent::deleteComponents()
{
for(unsigned int i = 0; i < mComponentVector.size(); i++)
for(unsigned int i = 0; i < getChildCount(); i++)
{
delete mComponentVector.at(i);
delete getChild(i);
}
mComponentVector.clear();
clearChildren();
//deletes fonts if any were created
setDefaults();
@ -159,7 +159,7 @@ void GuiTheme::deleteComponents()
void GuiTheme::readXML(std::string path)
void ThemeComponent::readXML(std::string path)
{
if(mPath == path)
return;
@ -264,11 +264,11 @@ void GuiTheme::readXML(std::string path)
}
//recursively creates components
void GuiTheme::createComponentChildren(pugi::xml_node node, Gui* parent)
void ThemeComponent::createComponentChildren(pugi::xml_node node, GuiComponent* parent)
{
for(pugi::xml_node data = node.child("component"); data; data = data.next_sibling("component"))
{
Gui* nextComp = createElement(data, parent);
GuiComponent* nextComp = createElement(data, parent);
if(nextComp)
createComponentChildren(data, nextComp);
@ -276,7 +276,7 @@ void GuiTheme::createComponentChildren(pugi::xml_node node, Gui* parent)
}
//takes an XML element definition and creates an object from it
Gui* GuiTheme::createElement(pugi::xml_node data, Gui* parent)
GuiComponent* ThemeComponent::createElement(pugi::xml_node data, GuiComponent* parent)
{
std::string type = data.child("type").text().get();
@ -315,12 +315,12 @@ Gui* GuiTheme::createElement(pugi::xml_node data, Gui* parent)
float ox = strToFloat(originX);
float oy = strToFloat(originY);
GuiImage* comp = new GuiImage(mWindow, x, y, "", w, h, true);
ImageComponent* comp = new ImageComponent(mWindow, x, y, "", w, h, true);
comp->setOrigin(ox, oy);
comp->setTiling(tiled);
comp->setImage(path);
mComponentVector.push_back(comp);
addChild(comp);
return comp;
}
@ -330,7 +330,7 @@ Gui* GuiTheme::createElement(pugi::xml_node data, Gui* parent)
}
//expands a file path (./ becomes the directory of this theme file, ~/ becomes $HOME/)
std::string GuiTheme::expandPath(std::string path)
std::string ThemeComponent::expandPath(std::string path)
{
if(path.empty())
return "";
@ -344,7 +344,7 @@ std::string GuiTheme::expandPath(std::string path)
}
//takes a string containing a mathematical expression (possibly including variables) and resolves it to a float value
float GuiTheme::resolveExp(std::string str, float defaultVal)
float ThemeComponent::resolveExp(std::string str, float defaultVal)
{
if(str.empty())
return defaultVal;
@ -360,7 +360,7 @@ float GuiTheme::resolveExp(std::string str, float defaultVal)
}
//takes a string of hex and resolves it to an integer
unsigned int GuiTheme::resolveColor(std::string str, unsigned int defaultColor)
unsigned int ThemeComponent::resolveColor(std::string str, unsigned int defaultColor)
{
if(str.empty())
return defaultColor;
@ -384,7 +384,7 @@ unsigned int GuiTheme::resolveColor(std::string str, unsigned int defaultColor)
}
//splits a string in two at the first instance of the delimiter
void GuiTheme::splitString(std::string str, char delim, std::string* before, std::string* after)
void ThemeComponent::splitString(std::string str, char delim, std::string* before, std::string* after)
{
if(str.empty())
return;
@ -400,7 +400,7 @@ void GuiTheme::splitString(std::string str, char delim, std::string* before, std
}
//converts a string to a float
float GuiTheme::strToFloat(std::string str, float defaultVal)
float ThemeComponent::strToFloat(std::string str, float defaultVal)
{
if(str.empty())
return defaultVal;
@ -412,7 +412,7 @@ float GuiTheme::strToFloat(std::string str, float defaultVal)
return ret;
}
Font* GuiTheme::resolveFont(pugi::xml_node node, std::string defaultPath, unsigned int defaultSize)
Font* ThemeComponent::resolveFont(pugi::xml_node node, std::string defaultPath, unsigned int defaultSize)
{
if(!node)
return NULL;
@ -433,34 +433,21 @@ Font* GuiTheme::resolveFont(pugi::xml_node node, std::string defaultPath, unsign
return new Font(path, size);
}
void GuiTheme::render()
void ThemeComponent::init()
{
for(unsigned int i = 0; i < mComponentVector.size(); i++)
{
mComponentVector.at(i)->render();
}
}
void GuiTheme::init()
{
for(unsigned int i = 0; i < mComponentVector.size(); i++)
{
mComponentVector.at(i)->init();
}
//fonts are special
if(mListFont) mListFont->init();
if(mDescFont) mDescFont->init();
if(mFastSelectFont) mFastSelectFont->init();
GuiComponent::init();
}
void GuiTheme::deinit()
void ThemeComponent::deinit()
{
for(unsigned int i = 0; i < mComponentVector.size(); i++)
{
mComponentVector.at(i)->deinit();
}
GuiComponent::deinit();
//fonts are special
if(mListFont) mListFont->deinit();
if(mDescFont) mDescFont->deinit();
if(mFastSelectFont) mFastSelectFont->deinit();

View file

@ -1,27 +1,25 @@
#ifndef _GUITHEME_H_
#define _GUITHEME_H_
#ifndef _THEMECOMPONENT_H_
#define _THEMECOMPONENT_H_
#include <memory>
#include "../Gui.h"
#include "../GuiComponent.h"
#include "../pugiXML/pugixml.hpp"
#include "GuiBox.h"
#include "../AudioManager.h"
#include "../Font.h"
//This class loads an XML-defined list of Guis.
class GuiTheme : public Gui
class ThemeComponent : public GuiComponent
{
public:
GuiTheme(Window* window, bool detailed, std::string path = "");
~GuiTheme();
ThemeComponent(Window* window, bool detailed, std::string path = "");
virtual ~ThemeComponent();
void readXML(std::string path);
GuiBoxData getBoxData();
void render();
void init();
void deinit();
@ -34,11 +32,12 @@ public:
Font* getListFont();
Font* getDescriptionFont();
Font* getFastSelectFont();
private:
void setDefaults();
void deleteComponents();
void createComponentChildren(pugi::xml_node node, Gui* parent);
Gui* createElement(pugi::xml_node data, Gui* parent);
void createComponentChildren(pugi::xml_node node, GuiComponent* parent);
GuiComponent* createElement(pugi::xml_node data, GuiComponent* parent);
//utility functions
std::string expandPath(std::string path);
@ -48,7 +47,6 @@ private:
float strToFloat(std::string str, float defaultVal = 0.0f);
Font* resolveFont(pugi::xml_node node, std::string defaultPath, unsigned int defaultSize);
std::vector<Gui*> mComponentVector;
std::string mPath;
bool mDetailed;
@ -59,6 +57,7 @@ private:
std::map<std::string, std::string> mStringMap;
GuiBoxData mBoxData;
Font* mListFont;
Font* mDescFont;
Font* mFastSelectFont;