Added initial TextComponent.

Reworked GuiGameList to use a TextComponent for description.
Changed set/clearClipRect to push/popClipRect.
Fixed Y coordinate in the clip rect functions.
Sorta fixed AnimationComponent being totally out of whack with VSync off.
This commit is contained in:
Aloshi 2013-06-14 10:48:13 -05:00
parent bf84945010
commit 861297ae25
11 changed files with 211 additions and 59 deletions

View file

@ -133,6 +133,7 @@ set(ES_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/src/XMLReader.h ${CMAKE_CURRENT_SOURCE_DIR}/src/XMLReader.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/AnimationComponent.h ${CMAKE_CURRENT_SOURCE_DIR}/src/components/AnimationComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ImageComponent.h ${CMAKE_CURRENT_SOURCE_DIR}/src/components/ImageComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/TextComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/TextListComponent.h ${CMAKE_CURRENT_SOURCE_DIR}/src/components/TextListComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ThemeComponent.h ${CMAKE_CURRENT_SOURCE_DIR}/src/components/ThemeComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiBox.h ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiBox.h
@ -167,6 +168,7 @@ set(ES_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/XMLReader.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/XMLReader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/AnimationComponent.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/components/AnimationComponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ImageComponent.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/components/ImageComponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/TextComponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ThemeComponent.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/components/ThemeComponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiBox.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiBox.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiDetectDevice.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiDetectDevice.cpp

View file

@ -35,9 +35,9 @@ namespace Renderer
void translatef(float x, float y); void translatef(float x, float y);
void translate(Vector2i offset); void translate(Vector2i offset);
void setClipRect(int x, int y, unsigned int w, unsigned int h); void pushClipRect(int x, int y, unsigned int w, unsigned int h);
void setClipRect(Vector2i offset, Vector2u size); void pushClipRect(Vector2i offset, Vector2u size);
void clearClipRect(); void popClipRect();
void drawRect(int x, int y, int w, int h, unsigned int color); void drawRect(int x, int y, int w, int h, unsigned int color);
void drawText(std::string text, int x, int y, unsigned int color, Font* font); void drawText(std::string text, int x, int y, unsigned int color, Font* font);

View file

@ -5,10 +5,13 @@
#include "Font.h" #include "Font.h"
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include "Log.h" #include "Log.h"
#include <stack>
namespace Renderer { namespace Renderer {
bool loadedFonts = false; bool loadedFonts = false;
std::stack<Rect> clipStack;
void setColor4bArray(GLubyte* array, unsigned int color) void setColor4bArray(GLubyte* array, unsigned int color)
{ {
array[0] = (color & 0xff000000) / 0x1000000; array[0] = (color & 0xff000000) / 0x1000000;
@ -36,20 +39,44 @@ namespace Renderer {
translatef((float)offset.x, (float)offset.y); translatef((float)offset.x, (float)offset.y);
} }
void setClipRect(int x, int y, unsigned int w, unsigned int h) void pushClipRect(int x, int y, unsigned int w, unsigned int h)
{ {
glScissor(x, y, w, h); Rect rect(x, y, w, h);
if(rect.size.x == 0)
rect.size.x = Renderer::getScreenWidth() - rect.pos.x;
if(rect.size.y == 0)
rect.size.y = Renderer::getScreenHeight() - rect.pos.y;
//glScissor starts at the bottom left of the window
//so (0, 0, 1, 1) is the bottom left pixel
//everything else uses y+ = down, so flip it to be consistent
rect.pos.y = Renderer::getScreenHeight() - rect.pos.y - rect.size.y;
clipStack.push(rect);
glScissor(rect.pos.x, rect.pos.y, rect.size.x, rect.size.y);
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
} }
void setClipRect(Vector2i offset, Vector2u size) void pushClipRect(Vector2i pos, Vector2u size)
{ {
setClipRect(offset.x, offset.y, size.x, size.y); pushClipRect(pos.x, pos.y, size.x, size.y);
} }
void clearClipRect() void popClipRect()
{ {
glDisable(GL_SCISSOR_TEST); if(clipStack.empty())
{
LOG(LogError) << "Tried to popClipRect while the stack was empty!";
return;
}
clipStack.pop();
if(clipStack.empty())
{
glDisable(GL_SCISSOR_TEST);
}else{
Rect top = clipStack.top();
glScissor(top.pos.x, top.pos.y, top.size.x, top.size.y);
}
} }
void drawRect(int x, int y, int w, int h, unsigned int color) void drawRect(int x, int y, int w, int h, unsigned int color)

View file

@ -27,7 +27,6 @@ public:
T y; T y;
}; };
template <typename T> template <typename T>
Vector2<T> operator -(const Vector2<T>& right) Vector2<T> operator -(const Vector2<T>& right)
{ {
@ -95,4 +94,14 @@ typedef Vector2<int> Vector2i;
typedef Vector2<unsigned int> Vector2u; typedef Vector2<unsigned int> Vector2u;
typedef Vector2<float> Vector2f; typedef Vector2<float> Vector2f;
class Rect
{
public:
Vector2i pos;
Vector2u size;
Rect() {};
Rect(int x, int y, unsigned int w, unsigned int h) : pos(x, y), size(w, h) {};
};
#endif #endif

View file

@ -6,6 +6,8 @@ AnimationComponent::AnimationComponent()
mMoveY = 0; mMoveY = 0;
mMoveSpeed = 0; mMoveSpeed = 0;
mFadeRate = 0; mFadeRate = 0;
mOpacity = 0;
mAccumulator = 0;
} }
void AnimationComponent::move(int x, int y, int speed) void AnimationComponent::move(int x, int y, int speed)
@ -31,41 +33,46 @@ void AnimationComponent::fadeOut(int time)
mFadeRate = -time; mFadeRate = -time;
} }
//this should really be fixed at the system loop level...
void AnimationComponent::update(int deltaTime) void AnimationComponent::update(int deltaTime)
{ {
float mult = deltaTime * 0.05f; mAccumulator += deltaTime;
while(mAccumulator >= ANIMATION_TICK_SPEED)
if(mMoveX != 0 || mMoveY != 0)
{ {
int offsetx = (mMoveX > mMoveSpeed) ? mMoveSpeed : mMoveX; mAccumulator -= ANIMATION_TICK_SPEED;
int offsety = (mMoveY > mMoveSpeed) ? mMoveSpeed : mMoveY;
offsetx = (int)(offsetx * mult); if(mMoveX != 0 || mMoveY != 0)
offsety = (int)(offsety * mult);
moveChildren(offsetx, offsety);
mMoveX -= offsetx;
mMoveY -= offsety;
}
if(mFadeRate != 0)
{
int opacity = (int)mOpacity + mFadeRate;
if(opacity > 255)
{ {
mFadeRate = 0; Vector2i offset(mMoveX, mMoveY);
opacity = 255; if(abs(offset.x) > mMoveSpeed)
offset.x = mMoveSpeed * (offset.x > 0 ? 1 : -1);
if(abs(offset.y) > mMoveSpeed)
offset.y = mMoveSpeed * (offset.y > 0 ? 1 : -1);
moveChildren(offset.x, offset.y);
mMoveX -= offset.x;
mMoveY -= offset.y;
} }
if(opacity < 0) if(mFadeRate != 0)
{ {
mFadeRate = 0; int opacity = (int)mOpacity + mFadeRate;
opacity = 0; if(opacity > 255)
} {
mFadeRate = 0;
opacity = 255;
}
mOpacity = (unsigned char)opacity; if(opacity < 0)
setChildrenOpacity((unsigned char)opacity); {
mFadeRate = 0;
opacity = 0;
}
mOpacity = (unsigned char)opacity;
setChildrenOpacity((unsigned char)opacity);
}
} }
} }

View file

@ -5,6 +5,8 @@
#include "ImageComponent.h" #include "ImageComponent.h"
#include <vector> #include <vector>
#define ANIMATION_TICK_SPEED 16
class AnimationComponent class AnimationComponent
{ {
public: public:
@ -28,6 +30,8 @@ private:
int mFadeRate; int mFadeRate;
int mMoveX, mMoveY, mMoveSpeed; int mMoveX, mMoveY, mMoveSpeed;
int mAccumulator;
}; };
#endif #endif

View file

@ -6,7 +6,12 @@
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include "../Log.h" #include "../Log.h"
GuiGameList::GuiGameList(Window* window, bool useDetail) : GuiComponent(window) Vector2i GuiGameList::getImagePos()
{
return Vector2i((int)(Renderer::getScreenWidth() * mTheme->getFloat("gameImageOffsetX")), (int)(Renderer::getScreenHeight() * mTheme->getFloat("gameImageOffsetY")));
}
GuiGameList::GuiGameList(Window* window, bool useDetail) : GuiComponent(window), mDescription(window)
{ {
mDetailed = useDetail; mDetailed = useDetail;
@ -19,7 +24,7 @@ GuiGameList::GuiGameList(Window* window, bool useDetail) : GuiComponent(window)
{ {
mList = new TextListComponent<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 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 = new ImageComponent(mWindow, getImagePos().x, getImagePos().y, "", (unsigned int)mTheme->getFloat("gameImageWidth"), (unsigned int)mTheme->getFloat("gameImageHeight"), false);
mScreenshot->setOrigin(mTheme->getFloat("gameImageOriginX"), mTheme->getFloat("gameImageOriginY")); mScreenshot->setOrigin(mTheme->getFloat("gameImageOriginX"), mTheme->getFloat("gameImageOriginY"));
mImageAnimation = new AnimationComponent(); mImageAnimation = new AnimationComponent();
@ -30,6 +35,9 @@ GuiGameList::GuiGameList(Window* window, bool useDetail) : GuiComponent(window)
mImageAnimation = NULL; mImageAnimation = NULL;
} }
mDescription.setOffset(Vector2i((int)(Renderer::getScreenWidth() * 0.03), mScreenshot->getOffset().y + mScreenshot->getSize().y + 12));
mDescription.setExtent(Vector2u((int)(Renderer::getScreenWidth() * (mTheme->getFloat("listOffsetX") - 0.03)), 0));
setSystemId(0); setSystemId(0);
} }
@ -41,8 +49,9 @@ GuiGameList::~GuiGameList()
{ {
delete mImageAnimation; delete mImageAnimation;
delete mScreenshot; delete mScreenshot;
delete mTheme;
} }
delete mTheme;
} }
void GuiGameList::setSystemId(int id) void GuiGameList::setSystemId(int id)
@ -86,18 +95,14 @@ void GuiGameList::render()
//divider //divider
if(!mTheme->getBool("hideDividers")) if(!mTheme->getBool("hideDividers"))
Renderer::drawRect((int)(Renderer::getScreenWidth() * mTheme->getFloat("listOffsetX")) - 4, Renderer::getDefaultFont(Renderer::LARGE)->getHeight() + 2, 8, Renderer::getScreenHeight(), 0x0000FFFF); Renderer::drawRect((int)(Renderer::getScreenWidth() * mTheme->getFloat("listOffsetX")) - 4, Renderer::getDefaultFont(Renderer::LARGE)->getHeight() + 2, 8, Renderer::getScreenHeight(), 0x0000FFFF);
//if we're not scrolling and we have selected a non-folder
if(!mList->isScrolling() && mList->getSelectedObject() && !mList->getSelectedObject()->isFolder())
{
GameData* game = (GameData*)mList->getSelectedObject();
std::string desc = game->getDescription();
if(!desc.empty())
Renderer::drawWrappedText(desc, (int)(Renderer::getScreenWidth() * 0.03), mScreenshot->getOffset().y + mScreenshot->getSize().y + 12, (int)(Renderer::getScreenWidth() * (mTheme->getFloat("listOffsetX") - 0.03)), mTheme->getColor("description"), mTheme->getDescriptionFont());
}
mScreenshot->render(); mScreenshot->render();
//if we're not scrolling and we have selected a non-folder
if(!mList->isScrolling() && !mList->getSelectedObject()->isFolder())
{
mDescription.render();
}
} }
mList->render(); mList->render();
@ -118,6 +123,7 @@ bool GuiGameList::input(InputConfig* config, Input input)
mFolderStack.push(mFolder); mFolderStack.push(mFolder);
mFolder = (FolderData*)file; mFolder = (FolderData*)file;
updateList(); updateList();
updateDetailData();
return true; return true;
}else{ }else{
mList->stopScrolling(); mList->stopScrolling();
@ -251,6 +257,9 @@ void GuiGameList::updateTheme()
mScreenshot->setOffset((int)(mTheme->getFloat("gameImageOffsetX") * Renderer::getScreenWidth()), (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->setOrigin(mTheme->getFloat("gameImageOriginX"), mTheme->getFloat("gameImageOriginY"));
mScreenshot->setResize((int)mTheme->getFloat("gameImageWidth"), (int)mTheme->getFloat("gameImageHeight"), false); mScreenshot->setResize((int)mTheme->getFloat("gameImageWidth"), (int)mTheme->getFloat("gameImageHeight"), false);
mDescription.setColor(mTheme->getColor("description"));
mDescription.setFont(mTheme->getDescriptionFont());
} }
} }
@ -261,15 +270,19 @@ void GuiGameList::updateDetailData()
if(mList->getSelectedObject() && !mList->getSelectedObject()->isFolder()) if(mList->getSelectedObject() && !mList->getSelectedObject()->isFolder())
{ {
mScreenshot->setOffset((int)((mTheme->getFloat("gameImageOffsetX") - 0.05) * Renderer::getScreenWidth()), (int)(mTheme->getFloat("gameImageOffsetY") * Renderer::getScreenHeight()));
if(((GameData*)mList->getSelectedObject())->getImagePath().empty()) if(((GameData*)mList->getSelectedObject())->getImagePath().empty())
mScreenshot->setImage(mTheme->getString("imageNotFoundPath")); mScreenshot->setImage(mTheme->getString("imageNotFoundPath"));
else else
mScreenshot->setImage(((GameData*)mList->getSelectedObject())->getImagePath()); mScreenshot->setImage(((GameData*)mList->getSelectedObject())->getImagePath());
mImageAnimation->fadeIn(15); Vector2i imgOffset = Vector2i((int)(Renderer::getScreenWidth() * 0.10f), 0);
mImageAnimation->move((int)(0.05 * Renderer::getScreenWidth()), 0, 5); mScreenshot->setOffset(getImagePos() - imgOffset);
mImageAnimation->fadeIn(35);
mImageAnimation->move(imgOffset.x, imgOffset.y, 20);
mDescription.setOffset(Vector2i((int)(Renderer::getScreenWidth() * 0.03), mScreenshot->getOffset().y + mScreenshot->getSize().y + 12));
mDescription.setText(((GameData*)mList->getSelectedObject())->getDescription());
}else{ }else{
mScreenshot->setImage(""); mScreenshot->setImage("");
} }

View file

@ -6,6 +6,7 @@
#include "ImageComponent.h" #include "ImageComponent.h"
#include "ThemeComponent.h" #include "ThemeComponent.h"
#include "AnimationComponent.h" #include "AnimationComponent.h"
#include "TextComponent.h"
#include <string> #include <string>
#include <stack> #include <stack>
#include "../SystemData.h" #include "../SystemData.h"
@ -13,7 +14,7 @@
#include "../FolderData.h" #include "../FolderData.h"
//This is where the magic happens - GuiGameList is the parent of almost every graphical element in ES at the moment. //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. //It has a TextListComponent child that handles the game list, a ThemeComponent that handles the theming system, and an ImageComponent for game images.
class GuiGameList : public GuiComponent class GuiGameList : public GuiComponent
{ {
public: public:
@ -48,8 +49,11 @@ private:
TextListComponent<FileData*>* mList; TextListComponent<FileData*>* mList;
ImageComponent* mScreenshot; ImageComponent* mScreenshot;
TextComponent mDescription;
AnimationComponent* mImageAnimation; AnimationComponent* mImageAnimation;
ThemeComponent* mTheme; ThemeComponent* mTheme;
Vector2i getImagePos();
}; };
#endif #endif

View file

@ -0,0 +1,59 @@
#include "TextComponent.h"
#include "../Renderer.h"
#include "../Log.h"
TextComponent::TextComponent(Window* window) : GuiComponent(window), mFont(NULL), mColor(0x000000FF)
{
}
TextComponent::TextComponent(Window* window, const std::string& text, Font* font, Vector2i pos, Vector2u size) : GuiComponent(window),
mFont(NULL), mColor(0x000000FF)
{
setText(text);
setFont(font);
setBox(pos, size);
}
void TextComponent::setBox(Vector2i pos, Vector2u size)
{
setOffset(pos);
setExtent(size);
}
void TextComponent::setExtent(Vector2u size)
{
mSize = size;
}
void TextComponent::setFont(Font* font)
{
mFont = font;
}
void TextComponent::setColor(unsigned int color)
{
mColor = color;
}
void TextComponent::setText(const std::string& text)
{
mText = text;
}
void TextComponent::onRender()
{
Font* font = (mFont ? mFont : Renderer::getDefaultFont(Renderer::MEDIUM));
if(font == NULL)
{
LOG(LogError) << "TextComponent can't get a valid font!";
return;
}
Renderer::pushClipRect(getOffset(), getSize());
Renderer::drawWrappedText(mText, 0, 0, mSize.x, mColor, font);
Renderer::popClipRect();
GuiComponent::onRender();
}

View file

@ -0,0 +1,27 @@
#ifndef _TEXTCOMPONENT_H_
#define _TEXTCOMPONENT_H_
#include "../GuiComponent.h"
#include "../Font.h"
class TextComponent : public GuiComponent
{
public:
TextComponent(Window* window);
TextComponent(Window* window, const std::string& text, Font* font, Vector2i pos, Vector2u size);
void setFont(Font* font);
void setBox(Vector2i pos, Vector2u size);
void setExtent(Vector2u size);
void setText(const std::string& text);
void setColor(unsigned int color);
void onRender();
private:
unsigned int mColor;
Font* mFont;
std::string mText;
};
#endif

View file

@ -141,6 +141,8 @@ void TextListComponent<T>::onRender()
if(listCutoff > (int)mRowVector.size()) if(listCutoff > (int)mRowVector.size())
listCutoff = mRowVector.size(); listCutoff = mRowVector.size();
Renderer::pushClipRect(getOffset(), getSize());
for(int i = startEntry; i < listCutoff; i++) for(int i = startEntry; i < listCutoff; i++)
{ {
//draw selector bar //draw selector bar
@ -154,18 +156,16 @@ void TextListComponent<T>::onRender()
int x = mTextOffsetX - (mSelection == i ? mMarqueeOffset : 0); int x = mTextOffsetX - (mSelection == i ? mMarqueeOffset : 0);
unsigned int color = (mSelection == i && mSelectedTextColorOverride != 0) ? mSelectedTextColorOverride : row.color; unsigned int color = (mSelection == i && mSelectedTextColorOverride != 0) ? mSelectedTextColorOverride : row.color;
Renderer::setClipRect(getOffset(), getSize());
if(mDrawCentered) if(mDrawCentered)
Renderer::drawCenteredText(row.name, x, y, color, mFont); Renderer::drawCenteredText(row.name, x, y, color, mFont);
else else
Renderer::drawText(row.name, x, y, color, mFont); Renderer::drawText(row.name, x, y, color, mFont);
Renderer::clearClipRect();
y += entrySize; y += entrySize;
} }
Renderer::popClipRect();
GuiComponent::onRender(); GuiComponent::onRender();
} }