mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-12-01 18:45:39 +00:00
Merge pull request #407 from Koerty/grid-tile-background
Add GridTileComponent and base theming syntax
This commit is contained in:
commit
9adb0d0c51
21
THEMES.md
21
THEMES.md
|
@ -281,6 +281,7 @@ You can now change the order in which elements are rendered by setting `zIndex`
|
||||||
* `image name="background"` - 0
|
* `image name="background"` - 0
|
||||||
* Extra Elements `extra="true"` - 10
|
* Extra Elements `extra="true"` - 10
|
||||||
* `textlist name="gamelist"` - 20
|
* `textlist name="gamelist"` - 20
|
||||||
|
* `imagegrid name="gamegrid"` - 20
|
||||||
* Media
|
* Media
|
||||||
* `image name="md_image"` - 30
|
* `image name="md_image"` - 30
|
||||||
* `video name="md_video"` - 30
|
* `video name="md_video"` - 30
|
||||||
|
@ -472,7 +473,11 @@ Reference
|
||||||
* `image name="logo"` - ALL
|
* `image name="logo"` - ALL
|
||||||
- A header image. If a non-empty `path` is specified, `text name="headerText"` will be hidden and this image will be, by default, displayed roughly in its place.
|
- A header image. If a non-empty `path` is specified, `text name="headerText"` will be hidden and this image will be, by default, displayed roughly in its place.
|
||||||
* `imagegrid name="gamegrid"` - ALL
|
* `imagegrid name="gamegrid"` - ALL
|
||||||
- The gamegrid.
|
- The gamegrid. The number of tile displayed is controlled by its size, margin and the default tile max size.
|
||||||
|
* `gridtile name="default"` - ALL
|
||||||
|
- Note that many of the default gridtile parameters change the selected gridtile parameters if they are not explicitly set by the theme. For example, changing the background image of the default gridtile also change the background image of the selected gridtile. Refer to the gridtile documentation for more informations.
|
||||||
|
* `gridtile name="selected"` - ALL
|
||||||
|
- See default gridtile description right above.
|
||||||
|
|
||||||
* Metadata
|
* Metadata
|
||||||
* Labels
|
* Labels
|
||||||
|
@ -572,6 +577,20 @@ Can be created as an extra.
|
||||||
* `pos` - type: NORMALIZED_PAIR.
|
* `pos` - type: NORMALIZED_PAIR.
|
||||||
* `size` - type: NORMALIZED_PAIR.
|
* `size` - type: NORMALIZED_PAIR.
|
||||||
- The size of the grid. Take care the selected tile can go out of the grid size, so don't position the grid too close to another element or the screen border.
|
- The size of the grid. Take care the selected tile can go out of the grid size, so don't position the grid too close to another element or the screen border.
|
||||||
|
* `margin` - type: NORMALIZED_PAIR.
|
||||||
|
|
||||||
|
#### gridtile
|
||||||
|
|
||||||
|
* `size` - type: NORMALIZED_PAIR.
|
||||||
|
- The size of the default gridtile is used to calculate how many tiles can fit in the imagegrid. If not explicitly set, the size of the selected gridtile is equal the size of the default gridtile * 1.2
|
||||||
|
* `padding` - type: NORMALIZED_PAIR.
|
||||||
|
- The padding around the gridtile content. Default `16 16`. If not explicitly set, the selected tile padding will be equal to the default tile padding.
|
||||||
|
* `backgroundImage` - type: PATH.
|
||||||
|
- If not explicitly set, the selected tile background image will be the same as the default tile background image.
|
||||||
|
* `imageColor` - type: COLOR.
|
||||||
|
- The default tile image color and selected tile image color have no influence on each others.
|
||||||
|
* `backgroundColor` - type: COLOR.
|
||||||
|
- The default tile background color and selected tile background color have no influence on each others.
|
||||||
|
|
||||||
#### video
|
#### video
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ GridGameListView::GridGameListView(Window* window, FileData* root) :
|
||||||
const float padding = 0.01f;
|
const float padding = 0.01f;
|
||||||
|
|
||||||
mGrid.setPosition(mSize.x() * 0.1f, mSize.y() * 0.1f);
|
mGrid.setPosition(mSize.x() * 0.1f, mSize.y() * 0.1f);
|
||||||
|
mGrid.setDefaultZIndex(20);
|
||||||
mGrid.setCursorChangedCallback([&](const CursorState& /*state*/) { updateInfoPanel(); });
|
mGrid.setCursorChangedCallback([&](const CursorState& /*state*/) { updateInfoPanel(); });
|
||||||
addChild(&mGrid);
|
addChild(&mGrid);
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ set(CORE_HEADERS
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ComponentList.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/GridTileComponent.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/IList.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/IList.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ImageComponent.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ImageComponent.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ImageGridComponent.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ImageGridComponent.h
|
||||||
|
@ -106,6 +107,7 @@ set(CORE_SOURCES
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ComponentList.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/GridTileComponent.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ImageComponent.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ImageComponent.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/MenuComponent.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/MenuComponent.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/NinePatchComponent.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/NinePatchComponent.cpp
|
||||||
|
|
|
@ -27,7 +27,14 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>> The
|
||||||
{ "zIndex", FLOAT } } },
|
{ "zIndex", FLOAT } } },
|
||||||
{ "imagegrid", {
|
{ "imagegrid", {
|
||||||
{ "pos", NORMALIZED_PAIR },
|
{ "pos", NORMALIZED_PAIR },
|
||||||
{ "size", NORMALIZED_PAIR } } },
|
{ "size", NORMALIZED_PAIR },
|
||||||
|
{ "margin", NORMALIZED_PAIR } } },
|
||||||
|
{ "gridtile", {
|
||||||
|
{ "size", NORMALIZED_PAIR },
|
||||||
|
{ "padding", NORMALIZED_PAIR },
|
||||||
|
{ "backgroundImage", PATH },
|
||||||
|
{ "imageColor", COLOR },
|
||||||
|
{ "backgroundColor", COLOR } } },
|
||||||
{ "text", {
|
{ "text", {
|
||||||
{ "pos", NORMALIZED_PAIR },
|
{ "pos", NORMALIZED_PAIR },
|
||||||
{ "size", NORMALIZED_PAIR },
|
{ "size", NORMALIZED_PAIR },
|
||||||
|
@ -128,7 +135,7 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>> The
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MINIMUM_THEME_FORMAT_VERSION 3
|
#define MINIMUM_THEME_FORMAT_VERSION 3
|
||||||
#define CURRENT_THEME_FORMAT_VERSION 5
|
#define CURRENT_THEME_FORMAT_VERSION 6
|
||||||
|
|
||||||
// helper
|
// helper
|
||||||
unsigned int getHexColor(const char* str)
|
unsigned int getHexColor(const char* str)
|
||||||
|
|
153
es-core/src/components/GridTileComponent.cpp
Normal file
153
es-core/src/components/GridTileComponent.cpp
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
#include "GridTileComponent.h"
|
||||||
|
|
||||||
|
#include "resources/TextureResource.h"
|
||||||
|
#include "ThemeData.h"
|
||||||
|
#include "Renderer.h"
|
||||||
|
|
||||||
|
GridTileComponent::GridTileComponent(Window* window) : GuiComponent(window), mBackground(window)
|
||||||
|
{
|
||||||
|
mDefaultProperties.mSize = getDefaultTileSize();
|
||||||
|
mDefaultProperties.mPadding = Vector2f(16.0f, 16.0f);
|
||||||
|
mDefaultProperties.mBackgroundImage = ":/frame.png";
|
||||||
|
mDefaultProperties.mImageColor = 0xAAAAAABB;
|
||||||
|
mDefaultProperties.mBackgroundColor = 0xAAAAEEFF;
|
||||||
|
|
||||||
|
mSelectedProperties.mSize = getSelectedTileSize();
|
||||||
|
mSelectedProperties.mPadding = mDefaultProperties.mPadding;
|
||||||
|
mSelectedProperties.mBackgroundImage = mDefaultProperties.mBackgroundImage;
|
||||||
|
mSelectedProperties.mImageColor = 0xFFFFFFFF;
|
||||||
|
mSelectedProperties.mBackgroundColor = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
mImage = std::make_shared<ImageComponent>(mWindow);
|
||||||
|
mImage->setOrigin(0.5f, 0.5f);
|
||||||
|
|
||||||
|
mBackground.setOrigin(0.5f, 0.5f);
|
||||||
|
|
||||||
|
addChild(&mBackground);
|
||||||
|
addChild(&(*mImage));
|
||||||
|
|
||||||
|
setSelected(false);
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridTileComponent::render(const Transform4x4f& parentTrans)
|
||||||
|
{
|
||||||
|
Transform4x4f trans = getTransform() * parentTrans;
|
||||||
|
|
||||||
|
if (mVisible)
|
||||||
|
renderChildren(trans);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update all the tile properties to the new status (selected or default)
|
||||||
|
void GridTileComponent::update()
|
||||||
|
{
|
||||||
|
const GridTileProperties& currentProperties = getCurrentProperties();
|
||||||
|
|
||||||
|
mBackground.setImagePath(currentProperties.mBackgroundImage);
|
||||||
|
|
||||||
|
mImage->setColorShift(currentProperties.mImageColor);
|
||||||
|
mBackground.setCenterColor(currentProperties.mBackgroundColor);
|
||||||
|
mBackground.setEdgeColor(currentProperties.mBackgroundColor);
|
||||||
|
|
||||||
|
resize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridTileComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties)
|
||||||
|
{
|
||||||
|
Vector2f screen = Vector2f((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight());
|
||||||
|
|
||||||
|
const ThemeData::ThemeElement* elem = theme->getElement(view, "default", "gridtile");
|
||||||
|
if (elem)
|
||||||
|
{
|
||||||
|
if (elem->has("size"))
|
||||||
|
mDefaultProperties.mSize = elem->get<Vector2f>("size") * screen;
|
||||||
|
|
||||||
|
if (elem->has("padding"))
|
||||||
|
mDefaultProperties.mPadding = elem->get<Vector2f>("padding");
|
||||||
|
|
||||||
|
if (elem->has("backgroundImage"))
|
||||||
|
mDefaultProperties.mBackgroundImage = elem->get<std::string>("backgroundImage");
|
||||||
|
|
||||||
|
if (elem->has("imageColor"))
|
||||||
|
mDefaultProperties.mImageColor = elem->get<unsigned int>("imageColor");
|
||||||
|
|
||||||
|
if (elem->has("backgroundColor"))
|
||||||
|
mDefaultProperties.mBackgroundColor = elem->get<unsigned int>("backgroundColor");
|
||||||
|
}
|
||||||
|
|
||||||
|
elem = theme->getElement(view, "selected", "gridtile");
|
||||||
|
|
||||||
|
mSelectedProperties.mSize = elem && elem->has("size") ?
|
||||||
|
elem->get<Vector2f>("size") * screen :
|
||||||
|
getSelectedTileSize();
|
||||||
|
|
||||||
|
mSelectedProperties.mPadding = elem && elem->has("padding") ?
|
||||||
|
elem->get<Vector2f>("padding") :
|
||||||
|
mDefaultProperties.mPadding;
|
||||||
|
|
||||||
|
mSelectedProperties.mBackgroundImage = elem && elem->has("backgroundImage") ?
|
||||||
|
elem->get<std::string>("backgroundImage") :
|
||||||
|
mDefaultProperties.mBackgroundImage;
|
||||||
|
|
||||||
|
if (elem && elem->has("imageColor"))
|
||||||
|
mSelectedProperties.mImageColor = elem->get<unsigned int>("imageColor");
|
||||||
|
|
||||||
|
if (elem && elem->has("backgroundColor"))
|
||||||
|
mSelectedProperties.mBackgroundColor = elem->get<unsigned int>("backgroundColor");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Made this a static function because the ImageGridComponent need to know the default tile size
|
||||||
|
// to calculate the grid dimension before it instantiate the GridTileComponents
|
||||||
|
Vector2f GridTileComponent::getDefaultTileSize()
|
||||||
|
{
|
||||||
|
Vector2f screen = Vector2f((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight());
|
||||||
|
|
||||||
|
return screen * 0.22f;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2f GridTileComponent::getSelectedTileSize() const
|
||||||
|
{
|
||||||
|
return mDefaultProperties.mSize * 1.2f;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GridTileComponent::isSelected() const
|
||||||
|
{
|
||||||
|
return mSelected;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridTileComponent::setImage(const std::string& path)
|
||||||
|
{
|
||||||
|
mImage->setImage(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridTileComponent::setImage(const std::shared_ptr<TextureResource>& texture)
|
||||||
|
{
|
||||||
|
mImage->setImage(texture);
|
||||||
|
|
||||||
|
// Resize now to prevent flickering images when scrolling
|
||||||
|
resize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridTileComponent::setSelected(bool selected)
|
||||||
|
{
|
||||||
|
mSelected = selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridTileComponent::setVisible(bool visible)
|
||||||
|
{
|
||||||
|
mVisible = visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridTileComponent::resize()
|
||||||
|
{
|
||||||
|
const GridTileProperties& currentProperties = getCurrentProperties();
|
||||||
|
|
||||||
|
mImage->setMaxSize(currentProperties.mSize - currentProperties.mPadding);
|
||||||
|
mBackground.fitTo(currentProperties.mSize - Vector2f(32.0f, 32.0f)); // (32f, 32f) the NinePatchComponent natural padding
|
||||||
|
mBackground.setPosition(getSize().x() / 2, getSize().y() / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
const GridTileProperties& GridTileComponent::getCurrentProperties() const
|
||||||
|
{
|
||||||
|
return mSelected ? mSelectedProperties : mDefaultProperties;
|
||||||
|
}
|
51
es-core/src/components/GridTileComponent.h
Normal file
51
es-core/src/components/GridTileComponent.h
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#pragma once
|
||||||
|
#ifndef ES_CORE_COMPONENTS_GRID_TILE_COMPONENT_H
|
||||||
|
#define ES_CORE_COMPONENTS_GRID_TILE_COMPONENT_H
|
||||||
|
|
||||||
|
#include "NinePatchComponent.h"
|
||||||
|
#include "ImageComponent.h"
|
||||||
|
|
||||||
|
struct GridTileProperties
|
||||||
|
{
|
||||||
|
Vector2f mSize;
|
||||||
|
Vector2f mPadding;
|
||||||
|
std::string mBackgroundImage;
|
||||||
|
unsigned int mImageColor;
|
||||||
|
unsigned int mBackgroundColor;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GridTileComponent : public GuiComponent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GridTileComponent(Window* window);
|
||||||
|
|
||||||
|
void render(const Transform4x4f& parentTrans) override;
|
||||||
|
void update();
|
||||||
|
virtual void applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties);
|
||||||
|
|
||||||
|
// Made this a static function because the ImageGridComponent need to know the default tile max size
|
||||||
|
// to calculate the grid dimension before it instantiate the GridTileComponents
|
||||||
|
static Vector2f getDefaultTileSize();
|
||||||
|
Vector2f getSelectedTileSize() const;
|
||||||
|
bool isSelected() const;
|
||||||
|
|
||||||
|
void setImage(const std::string& path);
|
||||||
|
void setImage(const std::shared_ptr<TextureResource>& texture);
|
||||||
|
void setSelected(bool selected);
|
||||||
|
void setVisible(bool visible);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void resize();
|
||||||
|
const GridTileProperties& getCurrentProperties() const;
|
||||||
|
|
||||||
|
std::shared_ptr<ImageComponent> mImage;
|
||||||
|
NinePatchComponent mBackground;
|
||||||
|
|
||||||
|
GridTileProperties mDefaultProperties;
|
||||||
|
GridTileProperties mSelectedProperties;
|
||||||
|
|
||||||
|
bool mSelected;
|
||||||
|
bool mVisible;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ES_CORE_COMPONENTS_GRID_TILE_COMPONENT_H
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include "components/IList.h"
|
#include "components/IList.h"
|
||||||
#include "resources/TextureResource.h"
|
#include "resources/TextureResource.h"
|
||||||
|
#include "GridTileComponent.h"
|
||||||
|
|
||||||
struct ImageGridData
|
struct ImageGridData
|
||||||
{
|
{
|
||||||
|
@ -43,15 +44,17 @@ public:
|
||||||
inline void setCursorChangedCallback(const std::function<void(CursorState state)>& func) { mCursorChangedCallback = func; }
|
inline void setCursorChangedCallback(const std::function<void(CursorState state)>& func) { mCursorChangedCallback = func; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Calculate how much tiles of size mTileMaxSize we can fit in a grid of size mSize using a margin of size mMargin
|
// Calculate how much tiles of size mTileSize we can fit in a grid of size mSize using a margin of size mMargin
|
||||||
Vector2i getGridDimension() const
|
void calcGridDimension()
|
||||||
{
|
{
|
||||||
// GRID_SIZE = COLUMNS * TILE_SIZE + (COLUMNS - 1) * MARGIN
|
// GRID_SIZE = COLUMNS * TILE_SIZE + (COLUMNS - 1) * MARGIN
|
||||||
// <=> COLUMNS = (GRID_SIZE + MARGIN) / (TILE_SIZE + MARGIN)
|
// <=> COLUMNS = (GRID_SIZE + MARGIN) / (TILE_SIZE + MARGIN)
|
||||||
return Vector2i((int) ((mSize.x() + mMargin.x()) / (mTileMaxSize.x() + mMargin.x())),
|
Vector2f gridDimension = (mSize + mMargin) / (mTileSize + mMargin);
|
||||||
(int) ((mSize.y() + mMargin.y()) / (mTileMaxSize.y() + mMargin.y())));
|
|
||||||
|
mGridDimension = Vector2i(gridDimension.x(), gridDimension.y());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int getStartPosition();
|
||||||
void buildImages();
|
void buildImages();
|
||||||
void updateImages();
|
void updateImages();
|
||||||
|
|
||||||
|
@ -62,10 +65,12 @@ private:
|
||||||
bool mEntriesDirty;
|
bool mEntriesDirty;
|
||||||
|
|
||||||
Vector2f mMargin;
|
Vector2f mMargin;
|
||||||
Vector2f mTileMaxSize;
|
Vector2f mTileSize;
|
||||||
Vector2f mSelectedTileMaxSize;
|
Vector2i mGridDimension;
|
||||||
|
|
||||||
std::vector<ImageComponent> mImages;
|
std::vector< std::shared_ptr<GridTileComponent> > mTiles;
|
||||||
|
|
||||||
|
std::shared_ptr<ThemeData> mTheme;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -75,10 +80,11 @@ ImageGridComponent<T>::ImageGridComponent(Window* window) : IList<ImageGridData,
|
||||||
|
|
||||||
mEntriesDirty = true;
|
mEntriesDirty = true;
|
||||||
|
|
||||||
mSize = screen * 0.79f;
|
mSize = screen * 0.80f;
|
||||||
mMargin = screen * 0.01f;
|
mMargin = screen * 0.07f;
|
||||||
mTileMaxSize = screen * 0.19f;
|
mTileSize = GridTileComponent::getDefaultTileSize();
|
||||||
mSelectedTileMaxSize = mTileMaxSize * 1.15f;
|
|
||||||
|
calcGridDimension();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -109,7 +115,7 @@ bool ImageGridComponent<T>::input(InputConfig* config, Input input)
|
||||||
|
|
||||||
if(dir != Vector2i::Zero())
|
if(dir != Vector2i::Zero())
|
||||||
{
|
{
|
||||||
listInput(dir.x() + dir.y() * getGridDimension().x());
|
listInput(dir.x() + dir.y() * mGridDimension.x());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
|
@ -126,6 +132,9 @@ template<typename T>
|
||||||
void ImageGridComponent<T>::update(int deltaTime)
|
void ImageGridComponent<T>::update(int deltaTime)
|
||||||
{
|
{
|
||||||
listUpdate(deltaTime);
|
listUpdate(deltaTime);
|
||||||
|
|
||||||
|
for(auto it = mTiles.begin(); it != mTiles.end(); it++)
|
||||||
|
(*it)->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -140,36 +149,20 @@ void ImageGridComponent<T>::render(const Transform4x4f& parentTrans)
|
||||||
mEntriesDirty = false;
|
mEntriesDirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dirty solution (took from updateImages function) to keep the selected image and render it later (on top of the others)
|
std::shared_ptr<GridTileComponent> selectedTile = NULL;
|
||||||
// Will be changed for a cleaner way with the introduction of GridTileComponent
|
for(auto it = mTiles.begin(); it != mTiles.end(); it++)
|
||||||
Vector2i gridDimension = getGridDimension();
|
|
||||||
|
|
||||||
int cursorRow = mCursor / gridDimension.x();
|
|
||||||
|
|
||||||
int start = (cursorRow - (gridDimension.y() / 2)) * gridDimension.x();
|
|
||||||
|
|
||||||
//if we're at the end put the row as close as we can and no higher
|
|
||||||
if(start + (gridDimension.x() * gridDimension.y()) >= (int)mEntries.size())
|
|
||||||
start = gridDimension.x() * ((int)mEntries.size()/gridDimension.x() - gridDimension.y() + 1);
|
|
||||||
|
|
||||||
if(start < 0)
|
|
||||||
start = 0;
|
|
||||||
|
|
||||||
unsigned int i = (unsigned int)start;
|
|
||||||
ImageComponent* selectedImage = NULL;
|
|
||||||
for(auto it = mImages.begin(); it != mImages.end(); it++)
|
|
||||||
{
|
{
|
||||||
// If it's the selected image, keep it for later, otherwise render it now
|
// If it's the selected image, keep it for later, otherwise render it now
|
||||||
if(i == (unsigned int)mCursor)
|
std::shared_ptr<GridTileComponent> tile = (*it);
|
||||||
selectedImage = it.base();
|
if(tile->isSelected())
|
||||||
|
selectedTile = tile;
|
||||||
else
|
else
|
||||||
it->render(trans);
|
tile->render(trans);
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the selected image on top of the others
|
// Render the selected image on top of the others
|
||||||
if (selectedImage != NULL)
|
if (selectedTile != NULL)
|
||||||
selectedImage->render(trans);
|
selectedTile->render(trans);
|
||||||
|
|
||||||
GuiComponent::renderChildren(trans);
|
GuiComponent::renderChildren(trans);
|
||||||
}
|
}
|
||||||
|
@ -178,6 +171,27 @@ template<typename T>
|
||||||
void ImageGridComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties)
|
void ImageGridComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties)
|
||||||
{
|
{
|
||||||
GuiComponent::applyTheme(theme, view, element, properties);
|
GuiComponent::applyTheme(theme, view, element, properties);
|
||||||
|
|
||||||
|
// Keep the theme pointer to apply it on the tiles later on
|
||||||
|
mTheme = theme;
|
||||||
|
|
||||||
|
Vector2f screen = Vector2f((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight());
|
||||||
|
|
||||||
|
const ThemeData::ThemeElement* elem = theme->getElement(view, element, "imagegrid");
|
||||||
|
|
||||||
|
if (elem && elem->has("margin"))
|
||||||
|
mMargin = elem->get<Vector2f>("margin") * screen;
|
||||||
|
|
||||||
|
// We still need to manually get the grid tile size here,
|
||||||
|
// so we can recalculate the new grid dimension, and THEN (re)build the tiles
|
||||||
|
elem = theme->getElement(view, "default", "gridtile");
|
||||||
|
|
||||||
|
mTileSize = elem && elem->has("size") ?
|
||||||
|
elem->get<Vector2f>("size") * screen :
|
||||||
|
GridTileComponent::getDefaultTileSize();
|
||||||
|
|
||||||
|
// Recalculate grid dimension after theme changed
|
||||||
|
calcGridDimension();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -196,77 +210,83 @@ void ImageGridComponent<T>::onSizeChanged()
|
||||||
updateImages();
|
updateImages();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create and position imagecomponents (mImages)
|
// Create and position tiles (mTiles)
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void ImageGridComponent<T>::buildImages()
|
void ImageGridComponent<T>::buildImages()
|
||||||
{
|
{
|
||||||
mImages.clear();
|
mTiles.clear();
|
||||||
|
|
||||||
Vector2i gridDimension = getGridDimension();
|
Vector2f startPosition = mTileSize / 2;
|
||||||
Vector2f startPosition = mTileMaxSize / 2;
|
Vector2f tileDistance = mTileSize + mMargin;
|
||||||
Vector2f tileDistance = mTileMaxSize + mMargin;
|
|
||||||
|
|
||||||
// Layout tile size and position
|
// Layout tile size and position
|
||||||
for(int y = 0; y < gridDimension.y(); y++)
|
for(int y = 0; y < mGridDimension.y(); y++)
|
||||||
{
|
{
|
||||||
for(int x = 0; x < gridDimension.x(); x++)
|
for(int x = 0; x < mGridDimension.x(); x++)
|
||||||
{
|
{
|
||||||
// Create tiles
|
// Create tiles
|
||||||
mImages.push_back(ImageComponent(mWindow));
|
auto tile = std::make_shared<GridTileComponent>(mWindow);
|
||||||
ImageComponent& image = mImages.at(y * gridDimension.x() + x);
|
|
||||||
|
|
||||||
image.setPosition(x * tileDistance.x() + startPosition.x(), y * tileDistance.y() + startPosition.y());
|
tile->setPosition(x * tileDistance.x() + startPosition.x(), y * tileDistance.y() + startPosition.y());
|
||||||
image.setOrigin(0.5f, 0.5f);
|
tile->setOrigin(0.5f, 0.5f);
|
||||||
image.setMaxSize(mTileMaxSize);
|
tile->setImage("");
|
||||||
image.setImage("");
|
|
||||||
|
if (mTheme)
|
||||||
|
tile->applyTheme(mTheme, "grid", "gridtile", ThemeFlags::ALL);
|
||||||
|
|
||||||
|
mTiles.push_back(tile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the starting position (the number of the game which will be displayed on top left of the screen)
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void ImageGridComponent<T>::updateImages()
|
int ImageGridComponent<T>::getStartPosition()
|
||||||
{
|
{
|
||||||
if(mImages.empty())
|
int cursorRow = mCursor / mGridDimension.x();
|
||||||
buildImages();
|
|
||||||
|
|
||||||
Vector2i gridDimension = getGridDimension();
|
int start = (cursorRow - (mGridDimension.y() / 2)) * mGridDimension.x();
|
||||||
|
|
||||||
int cursorRow = mCursor / gridDimension.x();
|
|
||||||
|
|
||||||
int start = (cursorRow - (gridDimension.y() / 2)) * gridDimension.x();
|
|
||||||
|
|
||||||
// If we are at the end put the row as close as we can and no higher, using the following formula
|
// If we are at the end put the row as close as we can and no higher, using the following formula
|
||||||
// Where E is the nb of entries, X the grid x dim (nb of column), Y the grid y dim (nb of line)
|
// Where E is the nb of entries, X the grid x dim (nb of column), Y the grid y dim (nb of line)
|
||||||
// start = first tile of last row - nb column * (nb line - 1)
|
// start = first tile of last row - nb column * (nb line - 1)
|
||||||
// = (E - 1) / X * X - X * (Y - 1)
|
// = (E - 1) / X * X - X * (Y - 1)
|
||||||
// = X * ((E - 1) / X - Y + 1)
|
// = X * ((E - 1) / X - Y + 1)
|
||||||
if(start + (gridDimension.x() * gridDimension.y()) >= (int)mEntries.size())
|
if(start + (mGridDimension.x() * mGridDimension.y()) >= (int)mEntries.size())
|
||||||
start = gridDimension.x() * (((int)mEntries.size() - 1) / gridDimension.x() - gridDimension.y() + 1);
|
start = mGridDimension.x() * (((int)mEntries.size() - 1) / mGridDimension.x() - mGridDimension.y() + 1);
|
||||||
|
|
||||||
if(start < 0)
|
if(start < 0)
|
||||||
start = 0;
|
start = 0;
|
||||||
|
|
||||||
unsigned int i = (unsigned int)start;
|
return start;
|
||||||
for(unsigned int img = 0; img < mImages.size(); img++)
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void ImageGridComponent<T>::updateImages()
|
||||||
|
{
|
||||||
|
if(mTiles.empty())
|
||||||
|
buildImages();
|
||||||
|
|
||||||
|
int pos = getStartPosition();
|
||||||
|
|
||||||
|
for(int img = 0; img < mTiles.size(); img++)
|
||||||
{
|
{
|
||||||
ImageComponent& image = mImages.at(img);
|
std::shared_ptr<GridTileComponent> tile = mTiles.at(img);
|
||||||
if(i >= (unsigned int)size())
|
|
||||||
|
// If we have more tiles than we have to display images on screen, hide them
|
||||||
|
if(pos >= size())
|
||||||
{
|
{
|
||||||
image.setImage("");
|
tile->setSelected(false);
|
||||||
|
tile->setImage("");
|
||||||
|
tile->setVisible(false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(i == (unsigned int)mCursor)
|
tile->setSelected(pos == mCursor);
|
||||||
{
|
tile->setImage(mEntries.at(pos).data.texture);
|
||||||
image.setColorShift(0xFFFFFFFF);
|
tile->setVisible(true);
|
||||||
image.setMaxSize(mSelectedTileMaxSize);
|
|
||||||
}else{
|
|
||||||
image.setColorShift(0xAAAAAABB);
|
|
||||||
image.setMaxSize(mTileMaxSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
image.setImage(mEntries.at(i).data.texture);
|
pos++;
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue