mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 07:35:38 +00:00
First implementation of the new ComponentList stuff.
This commit is contained in:
parent
139fc720ac
commit
c525d994d3
|
@ -162,6 +162,7 @@ set(ES_HEADERS
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/AsyncReqComponent.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/AsyncReqComponent.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ButtonComponent.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ButtonComponent.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ComponentGrid.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ComponentGrid.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ComponentList.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/DateTimeComponent.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/DateTimeComponent.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/HelpComponent.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/HelpComponent.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/IList.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/IList.h
|
||||||
|
@ -244,6 +245,7 @@ set(ES_SOURCES
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/AsyncReqComponent.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/AsyncReqComponent.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ButtonComponent.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ButtonComponent.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ComponentGrid.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ComponentGrid.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ComponentList.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/DateTimeComponent.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/DateTimeComponent.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/HelpComponent.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/HelpComponent.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ImageComponent.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ImageComponent.cpp
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Binary file not shown.
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 17 KiB |
|
@ -37,7 +37,7 @@ namespace Renderer
|
||||||
void setMatrix(float* mat);
|
void setMatrix(float* mat);
|
||||||
void setMatrix(const Eigen::Affine3f& transform);
|
void setMatrix(const Eigen::Affine3f& transform);
|
||||||
|
|
||||||
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, GLenum blend_sfactor = GL_SRC_ALPHA, GLenum blend_dfactor = GL_ONE_MINUS_SRC_ALPHA);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -70,7 +70,7 @@ namespace Renderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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, GLenum blend_sfactor, GLenum blend_dfactor)
|
||||||
{
|
{
|
||||||
#ifdef USE_OPENGL_ES
|
#ifdef USE_OPENGL_ES
|
||||||
GLshort points[12];
|
GLshort points[12];
|
||||||
|
@ -90,7 +90,7 @@ namespace Renderer {
|
||||||
buildGLColorArray(colors, color, 6);
|
buildGLColorArray(colors, color, 6);
|
||||||
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(blend_sfactor, blend_dfactor);
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
glEnableClientState(GL_COLOR_ARRAY);
|
glEnableClientState(GL_COLOR_ARRAY);
|
||||||
|
|
||||||
|
|
164
src/components/ComponentList.cpp
Normal file
164
src/components/ComponentList.cpp
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
#include "ComponentList.h"
|
||||||
|
|
||||||
|
#define TOTAL_HORIZONTAL_PADDING_PX 12
|
||||||
|
|
||||||
|
ComponentList::ComponentList(Window* window) : IList<ComponentListRow, void*>(window, LIST_SCROLL_STYLE_SLOW, LIST_NEVER_LOOP)
|
||||||
|
{
|
||||||
|
mSelectorBarOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComponentList::addRow(const ComponentListRow& row)
|
||||||
|
{
|
||||||
|
IList<ComponentListRow, void*>::Entry e;
|
||||||
|
e.name = "";
|
||||||
|
e.object = NULL;
|
||||||
|
e.data = row;
|
||||||
|
|
||||||
|
this->add(e);
|
||||||
|
|
||||||
|
for(auto it = mEntries.back().data.elements.begin(); it != mEntries.back().data.elements.end(); it++)
|
||||||
|
addChild(it->component.get());
|
||||||
|
|
||||||
|
updateElementSize(mEntries.back().data);
|
||||||
|
updateElementPosition(mEntries.back().data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComponentList::onSizeChanged()
|
||||||
|
{
|
||||||
|
for(auto it = mEntries.begin(); it != mEntries.end(); it++)
|
||||||
|
{
|
||||||
|
updateElementSize(it->data);
|
||||||
|
updateElementPosition(it->data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ComponentList::input(InputConfig* config, Input input)
|
||||||
|
{
|
||||||
|
if(size() == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// give it to the current row's input handler
|
||||||
|
if(mEntries.at(mCursor).data.input_handler && mEntries.at(mCursor).data.input_handler(config, input))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// input handler didn't consume the input - try to scroll
|
||||||
|
if(config->isMappedTo("up", input))
|
||||||
|
{
|
||||||
|
return listInput(input.value != 0 ? -1 : 0);
|
||||||
|
}else if(config->isMappedTo("down", input))
|
||||||
|
{
|
||||||
|
return listInput(input.value != 0 ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComponentList::update(int deltaTime)
|
||||||
|
{
|
||||||
|
listUpdate(deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComponentList::onCursorChanged(const CursorState& state)
|
||||||
|
{
|
||||||
|
// update the selector bar position
|
||||||
|
// in the future this might be animated
|
||||||
|
mSelectorBarOffset = 0;
|
||||||
|
for(int i = 0; i < mCursor; i++)
|
||||||
|
{
|
||||||
|
mSelectorBarOffset += getRowHeight(mEntries.at(i).data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComponentList::render(const Eigen::Affine3f& parentTrans)
|
||||||
|
{
|
||||||
|
Eigen::Affine3f trans = parentTrans * getTransform();
|
||||||
|
|
||||||
|
// clip our entries inside our bounds
|
||||||
|
Eigen::Vector3f dim(mSize.x(), mSize.y(), 0);
|
||||||
|
dim = trans * dim - trans.translation();
|
||||||
|
Renderer::pushClipRect(Eigen::Vector2i((int)trans.translation().x(),
|
||||||
|
(int)trans.translation().y()), Eigen::Vector2i((int)dim.x(), (int)dim.y()));
|
||||||
|
|
||||||
|
// draw our entries
|
||||||
|
renderChildren(trans);
|
||||||
|
|
||||||
|
Renderer::popClipRect();
|
||||||
|
|
||||||
|
// draw selector bar
|
||||||
|
Renderer::setMatrix(trans);
|
||||||
|
|
||||||
|
// inversion: src * (1 - dst) + dst * 0 = where src = 1
|
||||||
|
// need a function that goes roughly 0x777777 -> 0xFFFFFF
|
||||||
|
// and 0xFFFFFF -> 0x777777
|
||||||
|
// (1 - dst) + 0x77
|
||||||
|
|
||||||
|
Renderer::drawRect(0, (int)mSelectorBarOffset, (int)mSize.x(), (int)getRowHeight(mEntries.at(mCursor).data), 0xFFFFFFFF,
|
||||||
|
GL_ONE_MINUS_DST_COLOR, GL_ZERO);
|
||||||
|
Renderer::drawRect(0, (int)mSelectorBarOffset, (int)mSize.x(), (int)getRowHeight(mEntries.at(mCursor).data), 0x777777FF,
|
||||||
|
GL_ONE, GL_ONE);
|
||||||
|
|
||||||
|
// draw separators
|
||||||
|
float y = 0;
|
||||||
|
for(unsigned int i = 0; i < mEntries.size(); i++)
|
||||||
|
{
|
||||||
|
Renderer::drawRect(0, (int)y, (int)mSize.x(), 1, 0xC6C7C688);
|
||||||
|
y += getRowHeight(mEntries.at(i).data);
|
||||||
|
}
|
||||||
|
Renderer::drawRect(0, (int)y, (int)mSize.x(), 1, 0xC6C7C688);
|
||||||
|
}
|
||||||
|
|
||||||
|
float ComponentList::getRowHeight(const ComponentListRow& row)
|
||||||
|
{
|
||||||
|
// returns the highest component height found in the row
|
||||||
|
float height = 0;
|
||||||
|
for(unsigned int i = 0; i < row.elements.size(); i++)
|
||||||
|
{
|
||||||
|
if(row.elements.at(i).component->getSize().y() > height)
|
||||||
|
height = row.elements.at(i).component->getSize().y();
|
||||||
|
}
|
||||||
|
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComponentList::updateElementPosition(const ComponentListRow& row)
|
||||||
|
{
|
||||||
|
float yOffset = 0;
|
||||||
|
for(auto it = mEntries.begin(); it != mEntries.end() && &it->data != &row; it++)
|
||||||
|
{
|
||||||
|
yOffset += getRowHeight(it->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// assumes updateElementSize has already been called
|
||||||
|
float rowHeight = getRowHeight(row);
|
||||||
|
|
||||||
|
float x = TOTAL_HORIZONTAL_PADDING_PX / 2;
|
||||||
|
for(unsigned int i = 0; i < row.elements.size(); i++)
|
||||||
|
{
|
||||||
|
const auto comp = row.elements.at(i).component;
|
||||||
|
|
||||||
|
// center vertically
|
||||||
|
comp->setPosition(x, (rowHeight - comp->getSize().y()) / 2 + yOffset);
|
||||||
|
x += comp->getSize().x();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComponentList::updateElementSize(const ComponentListRow& row)
|
||||||
|
{
|
||||||
|
float width = mSize.x() - TOTAL_HORIZONTAL_PADDING_PX;
|
||||||
|
std::vector< std::shared_ptr<GuiComponent> > resizeVec;
|
||||||
|
|
||||||
|
for(auto it = row.elements.begin(); it != row.elements.end(); it++)
|
||||||
|
{
|
||||||
|
if(it->resize_width)
|
||||||
|
resizeVec.push_back(it->component);
|
||||||
|
else
|
||||||
|
width -= it->component->getSize().x();
|
||||||
|
}
|
||||||
|
|
||||||
|
// redistribute the "unused" width equally among the components with resize_width set to true
|
||||||
|
width = width / resizeVec.size();
|
||||||
|
for(auto it = resizeVec.begin(); it != resizeVec.end(); it++)
|
||||||
|
{
|
||||||
|
(*it)->setSize(width, (*it)->getSize().y());
|
||||||
|
}
|
||||||
|
}
|
48
src/components/ComponentList.h
Normal file
48
src/components/ComponentList.h
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "IList.h"
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
struct ComponentListElement
|
||||||
|
{
|
||||||
|
ComponentListElement(const std::shared_ptr<GuiComponent>& cmp = nullptr, bool resize_w = true) : component(cmp), resize_width(resize_w) { };
|
||||||
|
|
||||||
|
std::shared_ptr<GuiComponent> component;
|
||||||
|
bool resize_width;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ComponentListRow
|
||||||
|
{
|
||||||
|
std::vector<ComponentListElement> elements;
|
||||||
|
std::function<bool(InputConfig*, Input)> input_handler;
|
||||||
|
|
||||||
|
inline void addElement(const std::shared_ptr<GuiComponent>& component, bool resize_width)
|
||||||
|
{
|
||||||
|
elements.push_back(ComponentListElement(component, resize_width));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ComponentList : public IList<ComponentListRow, void*>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ComponentList(Window* window);
|
||||||
|
|
||||||
|
void addRow(const ComponentListRow& row);
|
||||||
|
|
||||||
|
bool input(InputConfig* config, Input input) override;
|
||||||
|
void update(int deltaTime) override;
|
||||||
|
void render(const Eigen::Affine3f& parentTrans) override;
|
||||||
|
|
||||||
|
void onSizeChanged() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void onCursorChanged(const CursorState& state) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateElementPosition(const ComponentListRow& row);
|
||||||
|
void updateElementSize(const ComponentListRow& row);
|
||||||
|
|
||||||
|
float getRowHeight(const ComponentListRow& row);
|
||||||
|
|
||||||
|
float mSelectorBarOffset;
|
||||||
|
};
|
|
@ -14,18 +14,38 @@ enum CursorState
|
||||||
CURSOR_SCROLLING
|
CURSOR_SCROLLING
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ListLoopType
|
||||||
|
{
|
||||||
|
LIST_ALWAYS_LOOP,
|
||||||
|
LIST_PAUSE_AT_END,
|
||||||
|
LIST_NEVER_LOOP
|
||||||
|
};
|
||||||
|
|
||||||
struct ScrollTier
|
struct ScrollTier
|
||||||
{
|
{
|
||||||
int length; // how long we stay on this level before going to the next
|
int length; // how long we stay on this level before going to the next
|
||||||
int scrollDelay; // how long between scrolls
|
int scrollDelay; // how long between scrolls
|
||||||
};
|
};
|
||||||
|
|
||||||
const int SCROLL_SPEED_COUNT = 3;
|
struct ScrollTierList
|
||||||
const ScrollTier SCROLL_SPEED[SCROLL_SPEED_COUNT] = {
|
{
|
||||||
|
const int count;
|
||||||
|
const ScrollTier* tiers;
|
||||||
|
};
|
||||||
|
|
||||||
|
// default scroll tiers
|
||||||
|
const ScrollTier QUICK_SCROLL_TIERS[] = {
|
||||||
{500, 500},
|
{500, 500},
|
||||||
{5000, 114},
|
{5000, 114},
|
||||||
{0, 8}
|
{0, 8}
|
||||||
};
|
};
|
||||||
|
const ScrollTierList LIST_SCROLL_STYLE_QUICK = { 3, QUICK_SCROLL_TIERS };
|
||||||
|
|
||||||
|
const ScrollTier SLOW_SCROLL_TIERS[] = {
|
||||||
|
{500, 500},
|
||||||
|
{0, 150}
|
||||||
|
};
|
||||||
|
const ScrollTierList LIST_SCROLL_STYLE_SLOW = { 2, SLOW_SCROLL_TIERS };
|
||||||
|
|
||||||
template <typename EntryData, typename UserData>
|
template <typename EntryData, typename UserData>
|
||||||
class IList : public GuiComponent
|
class IList : public GuiComponent
|
||||||
|
@ -52,10 +72,14 @@ protected:
|
||||||
ImageComponent mGradient;
|
ImageComponent mGradient;
|
||||||
std::shared_ptr<Font> mTitleOverlayFont;
|
std::shared_ptr<Font> mTitleOverlayFont;
|
||||||
|
|
||||||
|
const ScrollTierList& mTierList;
|
||||||
|
const ListLoopType mLoopType;
|
||||||
|
|
||||||
std::vector<Entry> mEntries;
|
std::vector<Entry> mEntries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IList(Window* window) : GuiComponent(window), mGradient(window)
|
IList(Window* window, const ScrollTierList& tierList = LIST_SCROLL_STYLE_QUICK, const ListLoopType& loopType = LIST_PAUSE_AT_END) : GuiComponent(window),
|
||||||
|
mGradient(window), mTierList(tierList), mLoopType(loopType)
|
||||||
{
|
{
|
||||||
mCursor = 0;
|
mCursor = 0;
|
||||||
mScrollTier = 0;
|
mScrollTier = 0;
|
||||||
|
@ -125,7 +149,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// entry management
|
// entry management
|
||||||
void add(Entry e)
|
void add(const Entry& e)
|
||||||
{
|
{
|
||||||
mEntries.push_back(e);
|
mEntries.push_back(e);
|
||||||
}
|
}
|
||||||
|
@ -159,19 +183,22 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void listInput(int velocity) // a velocity of 0 = stop scrolling
|
bool listInput(int velocity) // a velocity of 0 = stop scrolling
|
||||||
{
|
{
|
||||||
mScrollVelocity = velocity;
|
mScrollVelocity = velocity;
|
||||||
mScrollTier = 0;
|
mScrollTier = 0;
|
||||||
mScrollTierAccumulator = 0;
|
mScrollTierAccumulator = 0;
|
||||||
mScrollCursorAccumulator = 0;
|
mScrollCursorAccumulator = 0;
|
||||||
|
|
||||||
|
int prevCursor = mCursor;
|
||||||
scroll(mScrollVelocity);
|
scroll(mScrollVelocity);
|
||||||
|
return (prevCursor != mCursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void listUpdate(int deltaTime)
|
void listUpdate(int deltaTime)
|
||||||
{
|
{
|
||||||
// update the title overlay opacity
|
// update the title overlay opacity
|
||||||
const int dir = (mScrollTier >= SCROLL_SPEED_COUNT - 1) ? 1 : -1; // fade in if scroll tier is >= 1, otherwise fade out
|
const int dir = (mScrollTier >= mTierList.count - 1) ? 1 : -1; // fade in if scroll tier is >= 1, otherwise fade out
|
||||||
int op = mTitleOverlayOpacity + deltaTime*dir; // we just do a 1-to-1 time -> opacity, no scaling
|
int op = mTitleOverlayOpacity + deltaTime*dir; // we just do a 1-to-1 time -> opacity, no scaling
|
||||||
if(op >= 255)
|
if(op >= 255)
|
||||||
mTitleOverlayOpacity = 255;
|
mTitleOverlayOpacity = 255;
|
||||||
|
@ -189,16 +216,16 @@ protected:
|
||||||
// we delay scrolling until after scroll tier has updated so isScrolling() returns accurately during onCursorChanged callbacks
|
// we delay scrolling until after scroll tier has updated so isScrolling() returns accurately during onCursorChanged callbacks
|
||||||
// we don't just do scroll tier first because it would not catch the scrollDelay == tier length case
|
// we don't just do scroll tier first because it would not catch the scrollDelay == tier length case
|
||||||
int scrollCount = 0;
|
int scrollCount = 0;
|
||||||
while(mScrollCursorAccumulator >= SCROLL_SPEED[mScrollTier].scrollDelay)
|
while(mScrollCursorAccumulator >= mTierList.tiers[mScrollTier].scrollDelay)
|
||||||
{
|
{
|
||||||
mScrollCursorAccumulator -= SCROLL_SPEED[mScrollTier].scrollDelay;
|
mScrollCursorAccumulator -= mTierList.tiers[mScrollTier].scrollDelay;
|
||||||
scrollCount++;
|
scrollCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// are we ready to go even FASTER?
|
// are we ready to go even FASTER?
|
||||||
while(mScrollTier < SCROLL_SPEED_COUNT - 1 && mScrollTierAccumulator >= SCROLL_SPEED[mScrollTier].length)
|
while(mScrollTier < mTierList.count - 1 && mScrollTierAccumulator >= mTierList.tiers[mScrollTier].length)
|
||||||
{
|
{
|
||||||
mScrollTierAccumulator -= SCROLL_SPEED[mScrollTier].length;
|
mScrollTierAccumulator -= mTierList.tiers[mScrollTier].length;
|
||||||
mScrollTier++;
|
mScrollTier++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,16 +264,17 @@ protected:
|
||||||
// stop at the end if we've been holding down the button for a long time or
|
// stop at the end if we've been holding down the button for a long time or
|
||||||
// we're scrolling faster than one item at a time (e.g. page up/down)
|
// we're scrolling faster than one item at a time (e.g. page up/down)
|
||||||
// otherwise, loop around
|
// otherwise, loop around
|
||||||
if(mScrollTier > 0 || absAmt > 1)
|
if((mLoopType == LIST_PAUSE_AT_END && (mScrollTier > 0 || absAmt > 1)) ||
|
||||||
|
mLoopType == LIST_NEVER_LOOP)
|
||||||
{
|
{
|
||||||
if(cursor < 0)
|
if(cursor < 0)
|
||||||
cursor = 0;
|
cursor = 0;
|
||||||
else if(cursor >= size())
|
else if(cursor >= size())
|
||||||
cursor = size() - 1;
|
cursor = size() - 1;
|
||||||
}else{
|
}else{
|
||||||
if(cursor < 0)
|
while(cursor < 0)
|
||||||
cursor += size();
|
cursor += size();
|
||||||
else if(cursor >= size())
|
while(cursor >= size())
|
||||||
cursor -= size();
|
cursor -= size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
#include "MenuComponent.h"
|
||||||
|
|
||||||
|
MenuComponent::MenuComponent(Window* window, const char* title) : GuiComponent(window),
|
||||||
|
mBackground(window), mTitle(window), mList(window)
|
||||||
|
{
|
||||||
|
mBackground.setImagePath(":/frame.png");
|
||||||
|
|
||||||
|
mTitle.setText(title);
|
||||||
|
mTitle.setCentered(true);
|
||||||
|
|
||||||
|
addChild(&mBackground);
|
||||||
|
addChild(&mTitle);
|
||||||
|
addChild(&mList);
|
||||||
|
|
||||||
|
setSize(Renderer::getScreenWidth() * 0.6f, Renderer::getScreenHeight() * 0.8f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuComponent::onSizeChanged()
|
||||||
|
{
|
||||||
|
mBackground.fitTo(mSize, Eigen::Vector3f::Zero(), Eigen::Vector2f(-2, -2));
|
||||||
|
|
||||||
|
mTitle.setSize(mSize.x(), (float)mTitle.getFont()->getHeight());
|
||||||
|
|
||||||
|
mList.setPosition(0, mTitle.getSize().y());
|
||||||
|
mList.setSize(mSize.x(), mSize.y() - mTitle.getSize().y());
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "NinePatchComponent.h"
|
||||||
|
#include "ComponentList.h"
|
||||||
|
#include "TextComponent.h"
|
||||||
|
|
||||||
|
class MenuComponent : public GuiComponent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MenuComponent(Window* window, const char* title);
|
||||||
|
|
||||||
|
void onSizeChanged() override;
|
||||||
|
|
||||||
|
inline void addRow(const ComponentListRow& row) { mList.addRow(row); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
NinePatchComponent mBackground;
|
||||||
|
TextComponent mTitle;
|
||||||
|
ComponentList mList;
|
||||||
|
};
|
|
@ -9,9 +9,10 @@ TextComponent::TextComponent(Window* window) : GuiComponent(window),
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
TextComponent::TextComponent(Window* window, const std::string& text, std::shared_ptr<Font> font, Eigen::Vector3f pos, Eigen::Vector2f size) : GuiComponent(window),
|
TextComponent::TextComponent(Window* window, const std::string& text, std::shared_ptr<Font> font, unsigned int color, Eigen::Vector3f pos, Eigen::Vector2f size) : GuiComponent(window),
|
||||||
mFont(NULL), mColor(0x000000FF), mAutoCalcExtent(true, true), mCentered(false)
|
mFont(NULL), mColor(0x000000FF), mAutoCalcExtent(true, true), mCentered(false)
|
||||||
{
|
{
|
||||||
|
setColor(color);
|
||||||
setText(text);
|
setText(text);
|
||||||
setFont(font);
|
setFont(font);
|
||||||
setPosition(pos);
|
setPosition(pos);
|
||||||
|
|
|
@ -15,7 +15,7 @@ class TextComponent : public GuiComponent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TextComponent(Window* window);
|
TextComponent(Window* window);
|
||||||
TextComponent(Window* window, const std::string& text, std::shared_ptr<Font> font, Eigen::Vector3f pos = Eigen::Vector3f::Zero(), Eigen::Vector2f size = Eigen::Vector2f::Zero());
|
TextComponent(Window* window, const std::string& text, std::shared_ptr<Font> font, unsigned int color = 0x000000FF, Eigen::Vector3f pos = Eigen::Vector3f::Zero(), Eigen::Vector2f size = Eigen::Vector2f::Zero());
|
||||||
|
|
||||||
void setFont(std::shared_ptr<Font> font);
|
void setFont(std::shared_ptr<Font> font);
|
||||||
void onSizeChanged() override;
|
void onSizeChanged() override;
|
||||||
|
|
|
@ -2,72 +2,93 @@
|
||||||
#include "GuiSettingsMenu.h"
|
#include "GuiSettingsMenu.h"
|
||||||
#include "GuiScraperStart.h"
|
#include "GuiScraperStart.h"
|
||||||
#include "../Window.h"
|
#include "../Window.h"
|
||||||
|
#include "../Sound.h"
|
||||||
|
#include "../Log.h"
|
||||||
|
#include "GuiMsgBoxYesNo.h"
|
||||||
|
|
||||||
GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mBackground(window, ":/button.png"), mList(window)
|
GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "Main Menu")
|
||||||
{
|
{
|
||||||
mList.add("Settings", [&] {
|
struct MenuEntry
|
||||||
mWindow->pushGui(new GuiSettingsMenu(mWindow));
|
{
|
||||||
}, 0);
|
const char* name;
|
||||||
|
unsigned int color;
|
||||||
mList.add("Scrape Systems", [&] {
|
bool add_arrow;
|
||||||
mWindow->pushGui(new GuiScraperStart(mWindow));
|
std::function<void()> func;
|
||||||
}, 0);
|
};
|
||||||
|
|
||||||
mList.add("Restart", [] {
|
|
||||||
if(system("sudo shutdown -r now") != 0)
|
|
||||||
LOG(LogWarning) << "Restart terminated with non-zero result!";
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
mList.add("Shutdown", [] {
|
|
||||||
if(system("sudo shutdown -h now") != 0)
|
|
||||||
LOG(LogWarning) << "Shutdown terminated with non-zero result!";
|
|
||||||
}, 1);
|
|
||||||
|
|
||||||
mList.add("Exit", [] {
|
|
||||||
SDL_Event* ev = new SDL_Event();
|
|
||||||
ev->type = SDL_QUIT;
|
|
||||||
SDL_PushEvent(ev);
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
|
MenuEntry entries[] = {
|
||||||
|
{ "GENERAL SETTINGS", 0x777777FF, true,
|
||||||
|
[this] { mWindow->pushGui(new GuiSettingsMenu(mWindow)); }
|
||||||
|
},
|
||||||
|
{ "SCRAPE NOW", 0x777777FF, true,
|
||||||
|
[this] { mWindow->pushGui(new GuiScraperStart(mWindow)); }
|
||||||
|
},
|
||||||
|
{ "RESTART SYSTEM", 0x990000FF, false,
|
||||||
|
[this] {
|
||||||
|
mWindow->pushGui(new GuiMsgBoxYesNo(mWindow, "Do you really want to restart the system?",
|
||||||
|
[] {
|
||||||
|
if(system("sudo shutdown -r now") != 0)
|
||||||
|
LOG(LogWarning) << "Restart terminated with non-zero result!";
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ "SHUTDOWN SYSTEM", 0x990000FF, false,
|
||||||
|
[this] {
|
||||||
|
mWindow->pushGui(new GuiMsgBoxYesNo(mWindow, "Do you really want to shutdown the system?",
|
||||||
|
[] {
|
||||||
|
if(system("sudo shutdown -h now") != 0)
|
||||||
|
LOG(LogWarning) << "Shutdown terminated with non-zero result!";
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ "EXIT EMULATIONSTATION", 0x990000FF, false,
|
||||||
|
[] {
|
||||||
|
SDL_Event ev;
|
||||||
|
ev.type = SDL_QUIT;
|
||||||
|
SDL_PushEvent(&ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
setSize((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight());
|
setSize((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight());
|
||||||
|
mMenu.setPosition((mSize.x() - mMenu.getSize().x()) / 2, (mSize.y() - mMenu.getSize().y()) / 2);
|
||||||
|
|
||||||
mList.setPosition(mSize.x() * 0.175f, mSize.y() * 0.05f);
|
std::shared_ptr<Font> font = Font::get(FONT_SIZE_LARGE);
|
||||||
mList.setSize(mSize.x() * 0.65f, mSize.y() * 0.9f);
|
|
||||||
|
|
||||||
mTheme = ThemeData::getDefault();
|
// populate the list
|
||||||
|
ComponentListRow row;
|
||||||
|
|
||||||
using namespace ThemeFlags;
|
for(int i = 0; i < (sizeof(entries) / sizeof(entries[0])); i++)
|
||||||
mBackground.applyTheme(mTheme, "menu", "windowBackground", PATH);
|
{
|
||||||
mBackground.fitTo(Eigen::Vector2f(mList.getSize().x(), mSize.y()), Eigen::Vector3f(mList.getPosition().x(), 0, 0));
|
row.elements.clear();
|
||||||
addChild(&mBackground);
|
row.addElement(std::make_shared<TextComponent>(mWindow, entries[i].name, font, entries[i].color), true);
|
||||||
|
|
||||||
mList.setFont(Font::get((int)(0.09f * Renderer::getScreenHeight())));
|
if(entries[i].add_arrow)
|
||||||
mList.setSelectorColor(0xBBBBBBFF);
|
row.addElement(std::make_shared<TextComponent>(mWindow, ">", font, entries[i].color), false);
|
||||||
mList.setColor(0, 0x0000FFFF);
|
|
||||||
mList.setColor(1, 0xFF0000FF);
|
|
||||||
mList.applyTheme(mTheme, "menu", "menulist", FONT_PATH | COLOR | SOUND);
|
|
||||||
|
|
||||||
Sound::getFromTheme(mTheme, "menu", "menuOpen")->play();
|
std::function<void()>& execFunc = entries[i].func;
|
||||||
|
row.input_handler = [execFunc](InputConfig* config, Input input) -> bool
|
||||||
|
{
|
||||||
|
if(config->isMappedTo("a", input) && input.value != 0)
|
||||||
|
{
|
||||||
|
execFunc();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
addChild(&mList);
|
mMenu.addRow(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
addChild(&mMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GuiMenu::input(InputConfig* config, Input input)
|
bool GuiMenu::input(InputConfig* config, Input input)
|
||||||
{
|
{
|
||||||
if(input.value != 0)
|
if((config->isMappedTo("b", input) || config->isMappedTo("menu", input)) && input.value != 0)
|
||||||
{
|
{
|
||||||
if(config->isMappedTo("b", input) || config->isMappedTo("menu", input))
|
delete this;
|
||||||
{
|
return true;
|
||||||
Sound::getFromTheme(mTheme, "menu", "menuClose")->play();
|
|
||||||
delete this;
|
|
||||||
return true;
|
|
||||||
}else if(config->isMappedTo("a", input) && mList.size() > 0)
|
|
||||||
{
|
|
||||||
mList.getSelected()();
|
|
||||||
delete this;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return GuiComponent::input(config, input);
|
return GuiComponent::input(config, input);
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../GuiComponent.h"
|
#include "../GuiComponent.h"
|
||||||
#include "../components/TextListComponent.h"
|
#include "../components/MenuComponent.h"
|
||||||
#include "../components/NinePatchComponent.h"
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
class GuiMenu : public GuiComponent
|
class GuiMenu : public GuiComponent
|
||||||
|
@ -13,7 +12,5 @@ public:
|
||||||
bool input(InputConfig* config, Input input) override;
|
bool input(InputConfig* config, Input input) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<ThemeData> mTheme;
|
MenuComponent mMenu;
|
||||||
NinePatchComponent mBackground;
|
|
||||||
TextListComponent< std::function<void()> > mList;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#define SELECTED_SCALE 1.5f
|
#define SELECTED_SCALE 1.5f
|
||||||
#define LOGO_PADDING ((logoSize().x() * (SELECTED_SCALE - 1)/2) + (mSize.x() * 0.06f))
|
#define LOGO_PADDING ((logoSize().x() * (SELECTED_SCALE - 1)/2) + (mSize.x() * 0.06f))
|
||||||
|
|
||||||
SystemView::SystemView(Window* window) : IList<SystemViewData, SystemData*>(window)
|
SystemView::SystemView(Window* window) : IList<SystemViewData, SystemData*>(window, LIST_SCROLL_STYLE_SLOW, LIST_ALWAYS_LOOP)
|
||||||
{
|
{
|
||||||
mCamOffset = 0;
|
mCamOffset = 0;
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#include "../../guis/GuiFastSelect.h"
|
#include "../../guis/GuiFastSelect.h"
|
||||||
#include "../ViewController.h"
|
#include "../ViewController.h"
|
||||||
#include "../../Settings.h"
|
#include "../../Settings.h"
|
||||||
|
#include "../../Log.h"
|
||||||
|
#include "../../Sound.h"
|
||||||
|
|
||||||
bool IGameListView::input(InputConfig* config, Input input)
|
bool IGameListView::input(InputConfig* config, Input input)
|
||||||
{
|
{
|
||||||
|
@ -37,6 +39,7 @@ bool IGameListView::input(InputConfig* config, Input input)
|
||||||
}else if(config->isMappedTo("select", input) && input.value != 0)
|
}else if(config->isMappedTo("select", input) && input.value != 0)
|
||||||
{
|
{
|
||||||
// open fast select
|
// open fast select
|
||||||
|
Sound::getFromTheme(mTheme, getName(), "menuOpen")->play();
|
||||||
mWindow->pushGui(new GuiFastSelect(mWindow, this));
|
mWindow->pushGui(new GuiFastSelect(mWindow, this));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue