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/components/AnimationComponent.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/ThemeComponent.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/components/AnimationComponent.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/GuiBox.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiDetectDevice.cpp

View file

@ -35,9 +35,9 @@ namespace Renderer
void translatef(float x, float y);
void translate(Vector2i offset);
void setClipRect(int x, int y, unsigned int w, unsigned int h);
void setClipRect(Vector2i offset, Vector2u size);
void clearClipRect();
void pushClipRect(int x, int y, unsigned int w, unsigned int h);
void pushClipRect(Vector2i offset, Vector2u size);
void popClipRect();
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);

View file

@ -5,10 +5,13 @@
#include "Font.h"
#include <boost/filesystem.hpp>
#include "Log.h"
#include <stack>
namespace Renderer {
bool loadedFonts = false;
std::stack<Rect> clipStack;
void setColor4bArray(GLubyte* array, unsigned int color)
{
array[0] = (color & 0xff000000) / 0x1000000;
@ -36,20 +39,44 @@ namespace Renderer {
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);
}
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)

View file

@ -27,7 +27,6 @@ public:
T y;
};
template <typename T>
Vector2<T> operator -(const Vector2<T>& right)
{
@ -95,4 +94,14 @@ typedef Vector2<int> Vector2i;
typedef Vector2<unsigned int> Vector2u;
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

View file

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

View file

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

View file

@ -6,7 +6,12 @@
#include <boost/filesystem.hpp>
#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;
@ -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));
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"));
mImageAnimation = new AnimationComponent();
@ -30,6 +35,9 @@ GuiGameList::GuiGameList(Window* window, bool useDetail) : GuiComponent(window)
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);
}
@ -41,8 +49,9 @@ GuiGameList::~GuiGameList()
{
delete mImageAnimation;
delete mScreenshot;
delete mTheme;
}
delete mTheme;
}
void GuiGameList::setSystemId(int id)
@ -86,18 +95,14 @@ void GuiGameList::render()
//divider
if(!mTheme->getBool("hideDividers"))
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();
//if we're not scrolling and we have selected a non-folder
if(!mList->isScrolling() && !mList->getSelectedObject()->isFolder())
{
mDescription.render();
}
}
mList->render();
@ -118,6 +123,7 @@ bool GuiGameList::input(InputConfig* config, Input input)
mFolderStack.push(mFolder);
mFolder = (FolderData*)file;
updateList();
updateDetailData();
return true;
}else{
mList->stopScrolling();
@ -251,6 +257,9 @@ void GuiGameList::updateTheme()
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);
mDescription.setColor(mTheme->getColor("description"));
mDescription.setFont(mTheme->getDescriptionFont());
}
}
@ -261,15 +270,19 @@ void GuiGameList::updateDetailData()
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())
mScreenshot->setImage(mTheme->getString("imageNotFoundPath"));
else
mScreenshot->setImage(((GameData*)mList->getSelectedObject())->getImagePath());
mImageAnimation->fadeIn(15);
mImageAnimation->move((int)(0.05 * Renderer::getScreenWidth()), 0, 5);
Vector2i imgOffset = Vector2i((int)(Renderer::getScreenWidth() * 0.10f), 0);
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{
mScreenshot->setImage("");
}

View file

@ -6,6 +6,7 @@
#include "ImageComponent.h"
#include "ThemeComponent.h"
#include "AnimationComponent.h"
#include "TextComponent.h"
#include <string>
#include <stack>
#include "../SystemData.h"
@ -13,7 +14,7 @@
#include "../FolderData.h"
//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
{
public:
@ -48,8 +49,11 @@ private:
TextListComponent<FileData*>* mList;
ImageComponent* mScreenshot;
TextComponent mDescription;
AnimationComponent* mImageAnimation;
ThemeComponent* mTheme;
Vector2i getImagePos();
};
#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())
listCutoff = mRowVector.size();
Renderer::pushClipRect(getOffset(), getSize());
for(int i = startEntry; i < listCutoff; i++)
{
//draw selector bar
@ -154,18 +156,16 @@ void TextListComponent<T>::onRender()
int x = mTextOffsetX - (mSelection == i ? mMarqueeOffset : 0);
unsigned int color = (mSelection == i && mSelectedTextColorOverride != 0) ? mSelectedTextColorOverride : row.color;
Renderer::setClipRect(getOffset(), getSize());
if(mDrawCentered)
Renderer::drawCenteredText(row.name, x, y, color, mFont);
else
Renderer::drawText(row.name, x, y, color, mFont);
Renderer::clearClipRect();
y += entrySize;
}
Renderer::popClipRect();
GuiComponent::onRender();
}