mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-22 14:15:38 +00:00
Both user changes and scraper changes are now color marked in the metadata editor.
User changes are marked with blue and scraper changes with red.
This commit is contained in:
parent
1b65eaac2e
commit
70d0057295
4
NEWS.md
4
NEWS.md
|
@ -8,7 +8,7 @@ v1.0.0
|
||||||
* Many quality of life improvements and removal of GUI inconsistencies
|
* Many quality of life improvements and removal of GUI inconsistencies
|
||||||
* New game media file logic using a media directory with files matching the ROM names instead of pointing to the media files in gamelist.xml
|
* New game media file logic using a media directory with files matching the ROM names instead of pointing to the media files in gamelist.xml
|
||||||
* Updated scraper to support additional media files, detailed configuration of what to scrape, semi-automatic mode etc.
|
* Updated scraper to support additional media files, detailed configuration of what to scrape, semi-automatic mode etc.
|
||||||
* For single-game scraping, any values updated by the scraper are now highlighted using a different font color in the metadata editor
|
* In the metadata editor, any values updated by the single-game scraper or by the user are now highlighted using a different font color
|
||||||
* Gamelist sorting now working as expected and is persistent throughout the application session
|
* Gamelist sorting now working as expected and is persistent throughout the application session
|
||||||
* Full navigation sound support, configurable per theme
|
* Full navigation sound support, configurable per theme
|
||||||
* New default theme rbsimple-DE bundled with the software, this theme is largely based on recalbox-multi by the Recalbox community
|
* New default theme rbsimple-DE bundled with the software, this theme is largely based on recalbox-multi by the Recalbox community
|
||||||
|
@ -37,7 +37,7 @@ v1.0.0
|
||||||
### Bug fixes
|
### Bug fixes
|
||||||
|
|
||||||
* Metadata editor insisted that changes were made although nothing was updated
|
* Metadata editor insisted that changes were made although nothing was updated
|
||||||
Note: The editor will still ask for save confirmations after automatically rounding fractional game ratings to half-star values
|
Note: The editor will still ask for save confirmations after automatically rounding fractional game ratings to half-star values, but any time such a rounding has taken place, the rating stars will be colored green in the metadata editor to nofity the user
|
||||||
* Game images were sometimes scaled incorrectly
|
* Game images were sometimes scaled incorrectly
|
||||||
* Non-transparent favorite icons were not rendered correctly
|
* Non-transparent favorite icons were not rendered correctly
|
||||||
* Restart and power-off menu entries not working
|
* Restart and power-off menu entries not working
|
||||||
|
|
|
@ -46,8 +46,7 @@ GuiMetaDataEd::GuiMetaDataEd(
|
||||||
mMetaDataDecl(mdd),
|
mMetaDataDecl(mdd),
|
||||||
mMetaData(md),
|
mMetaData(md),
|
||||||
mSavedCallback(saveCallback),
|
mSavedCallback(saveCallback),
|
||||||
mDeleteFunc(deleteFunc),
|
mDeleteFunc(deleteFunc)
|
||||||
mMetadataUpdated(false)
|
|
||||||
{
|
{
|
||||||
addChild(&mBackground);
|
addChild(&mBackground);
|
||||||
addChild(&mGrid);
|
addChild(&mGrid);
|
||||||
|
@ -70,6 +69,7 @@ GuiMetaDataEd::GuiMetaDataEd(
|
||||||
// Populate list.
|
// Populate list.
|
||||||
for (auto iter = mdd.cbegin(); iter != mdd.cend(); iter++) {
|
for (auto iter = mdd.cbegin(); iter != mdd.cend(); iter++) {
|
||||||
std::shared_ptr<GuiComponent> ed;
|
std::shared_ptr<GuiComponent> ed;
|
||||||
|
std::string originalValue;
|
||||||
|
|
||||||
// Don't add statistics.
|
// Don't add statistics.
|
||||||
if (iter->isStatistic)
|
if (iter->isStatistic)
|
||||||
|
@ -99,6 +99,7 @@ GuiMetaDataEd::GuiMetaDataEd(
|
||||||
switch (iter->type) {
|
switch (iter->type) {
|
||||||
case MD_BOOL: {
|
case MD_BOOL: {
|
||||||
ed = std::make_shared<SwitchComponent>(window);
|
ed = std::make_shared<SwitchComponent>(window);
|
||||||
|
ed->setChangedColor(ICONCOLOR_USERMARKED);
|
||||||
row.addElement(ed, false, true);
|
row.addElement(ed, false, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -107,7 +108,8 @@ GuiMetaDataEd::GuiMetaDataEd(
|
||||||
spacer->setSize(Renderer::getScreenWidth() * 0.0025f, 0);
|
spacer->setSize(Renderer::getScreenWidth() * 0.0025f, 0);
|
||||||
row.addElement(spacer, false);
|
row.addElement(spacer, false);
|
||||||
|
|
||||||
ed = std::make_shared<RatingComponent>(window);
|
ed = std::make_shared<RatingComponent>(window, true);
|
||||||
|
ed->setChangedColor(ICONCOLOR_USERMARKED);
|
||||||
const float height = lbl->getSize().y() * 0.71f;
|
const float height = lbl->getSize().y() * 0.71f;
|
||||||
ed->setSize(0, height);
|
ed->setSize(0, height);
|
||||||
row.addElement(ed, false, true);
|
row.addElement(ed, false, true);
|
||||||
|
@ -123,6 +125,7 @@ GuiMetaDataEd::GuiMetaDataEd(
|
||||||
row.addElement(spacer, false);
|
row.addElement(spacer, false);
|
||||||
|
|
||||||
ed = std::make_shared<DateTimeEditComponent>(window);
|
ed = std::make_shared<DateTimeEditComponent>(window);
|
||||||
|
ed->setChangedColor(TEXTCOLOR_USERMARKED);
|
||||||
row.addElement(ed, false);
|
row.addElement(ed, false);
|
||||||
|
|
||||||
// Pass input to the actual DateTimeEditComponent instead of the spacer.
|
// Pass input to the actual DateTimeEditComponent instead of the spacer.
|
||||||
|
@ -130,12 +133,14 @@ GuiMetaDataEd::GuiMetaDataEd(
|
||||||
std::placeholders::_1, std::placeholders::_2);
|
std::placeholders::_1, std::placeholders::_2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MD_TIME: {
|
// Not in use as 'lastplayed' is flagged as statistics and these are skipped.
|
||||||
ed = std::make_shared<DateTimeEditComponent>(window,
|
// Let's still keep the code because it may be needed in the future.
|
||||||
DateTimeEditComponent::DISP_RELATIVE_TO_NOW);
|
// case MD_TIME: {
|
||||||
row.addElement(ed, false);
|
// ed = std::make_shared<DateTimeEditComponent>(window,
|
||||||
break;
|
// DateTimeEditComponent::DISP_RELATIVE_TO_NOW);
|
||||||
}
|
// row.addElement(ed, false);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
case MD_LAUNCHCOMMAND: {
|
case MD_LAUNCHCOMMAND: {
|
||||||
ed = std::make_shared<TextComponent>(window, "",
|
ed = std::make_shared<TextComponent>(window, "",
|
||||||
Font::get(FONT_SIZE_SMALL, FONT_PATH_LIGHT), 0x777777FF, ALIGN_RIGHT);
|
Font::get(FONT_SIZE_SMALL, FONT_PATH_LIGHT), 0x777777FF, ALIGN_RIGHT);
|
||||||
|
@ -152,8 +157,17 @@ GuiMetaDataEd::GuiMetaDataEd(
|
||||||
|
|
||||||
bool multiLine = false;
|
bool multiLine = false;
|
||||||
const std::string title = iter->displayPrompt;
|
const std::string title = iter->displayPrompt;
|
||||||
auto updateVal = [ed](const std::string& newVal) {
|
|
||||||
ed->setValue(newVal); }; // OK callback (apply new value to ed).
|
originalValue = mMetaData->get(iter->key);
|
||||||
|
|
||||||
|
// OK callback (apply new value to ed).
|
||||||
|
auto updateVal = [ed, originalValue](const std::string& newVal) {
|
||||||
|
ed->setValue(newVal);
|
||||||
|
if (newVal == originalValue)
|
||||||
|
ed->setColor(DEFAULT_TEXTCOLOR);
|
||||||
|
else
|
||||||
|
ed->setColor(TEXTCOLOR_USERMARKED);
|
||||||
|
};
|
||||||
|
|
||||||
std::string staticTextString = "Default value from es_systems.cfg:";
|
std::string staticTextString = "Default value from es_systems.cfg:";
|
||||||
std::string defaultLaunchCommand = scraperParams.system->
|
std::string defaultLaunchCommand = scraperParams.system->
|
||||||
|
@ -186,8 +200,17 @@ GuiMetaDataEd::GuiMetaDataEd(
|
||||||
bool multiLine = iter->type == MD_MULTILINE_STRING;
|
bool multiLine = iter->type == MD_MULTILINE_STRING;
|
||||||
const std::string title = iter->displayPrompt;
|
const std::string title = iter->displayPrompt;
|
||||||
|
|
||||||
|
originalValue = mMetaData->get(iter->key);
|
||||||
|
|
||||||
// OK callback (apply new value to ed).
|
// OK callback (apply new value to ed).
|
||||||
auto updateVal = [ed](const std::string& newVal) { ed->setValue(newVal); };
|
auto updateVal = [ed, originalValue](const std::string& newVal) {
|
||||||
|
ed->setValue(newVal);
|
||||||
|
if (newVal == originalValue)
|
||||||
|
ed->setColor(DEFAULT_TEXTCOLOR);
|
||||||
|
else
|
||||||
|
ed->setColor(TEXTCOLOR_USERMARKED);
|
||||||
|
};
|
||||||
|
|
||||||
row.makeAcceptInputHandler([this, title, ed, updateVal, multiLine] {
|
row.makeAcceptInputHandler([this, title, ed, updateVal, multiLine] {
|
||||||
mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), title,
|
mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), title,
|
||||||
ed->getValue(), updateVal, multiLine, "APPLY", "APPLY CHANGES?"));
|
ed->getValue(), updateVal, multiLine, "APPLY", "APPLY CHANGES?"));
|
||||||
|
@ -217,8 +240,8 @@ GuiMetaDataEd::GuiMetaDataEd(
|
||||||
|
|
||||||
if (mDeleteFunc) {
|
if (mDeleteFunc) {
|
||||||
auto deleteFileAndSelf = [&] { mDeleteFunc(); delete this; };
|
auto deleteFileAndSelf = [&] { mDeleteFunc(); delete this; };
|
||||||
auto deleteBtnFunc = [this, deleteFileAndSelf] { mWindow->pushGui(
|
auto deleteBtnFunc = [this, deleteFileAndSelf] {
|
||||||
new GuiMsgBox(mWindow, getHelpStyle(),
|
mWindow->pushGui(new GuiMsgBox(mWindow, getHelpStyle(),
|
||||||
"THIS WILL DELETE THE ACTUAL GAME FILE(S)!\nARE YOU SURE?",
|
"THIS WILL DELETE THE ACTUAL GAME FILE(S)!\nARE YOU SURE?",
|
||||||
"YES", deleteFileAndSelf, "NO", nullptr)); };
|
"YES", deleteFileAndSelf, "NO", nullptr)); };
|
||||||
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "DELETE",
|
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "DELETE",
|
||||||
|
@ -303,19 +326,20 @@ void GuiMetaDataEd::fetchDone(const ScraperSearchResult& result)
|
||||||
metadata->set(key, mEditors[i]->getValue());
|
metadata->set(key, mEditors[i]->getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
mMetadataUpdated = GuiScraperSearch::saveMetadata(result, *metadata);
|
GuiScraperSearch::saveMetadata(result, *metadata);
|
||||||
|
|
||||||
// Update the list with the scraped metadata values.
|
// Update the list with the scraped metadata values.
|
||||||
for (unsigned int i = 0; i < mEditors.size(); i++) {
|
for (unsigned int i = 0; i < mEditors.size(); i++) {
|
||||||
const std::string& key = mMetaDataDecl.at(i).key;
|
const std::string& key = mMetaDataDecl.at(i).key;
|
||||||
if (mEditors.at(i)->getValue() != metadata->get(key)) {
|
if (mEditors.at(i)->getValue() != metadata->get(key)) {
|
||||||
if (key == "rating") {
|
if (key == "rating")
|
||||||
mEditors.at(i)->setColorShift(0xDD2222FF);
|
mEditors.at(i)->setOriginalColor(ICONCOLOR_SCRAPERMARKED);
|
||||||
}
|
else
|
||||||
else {
|
mEditors.at(i)->setColor(TEXTCOLOR_SCRAPERMARKED);
|
||||||
mEditors.at(i)->setColor(0x994444FF);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// Save all the keys, except the following which can't be scraped.
|
||||||
|
if (key != "favorite" && key != "completed" && key != "broken" &&
|
||||||
|
key != "hidden" && key != "kidgame")
|
||||||
mEditors.at(i)->setValue(metadata->get(key));
|
mEditors.at(i)->setValue(metadata->get(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,7 +349,7 @@ void GuiMetaDataEd::fetchDone(const ScraperSearchResult& result)
|
||||||
void GuiMetaDataEd::close()
|
void GuiMetaDataEd::close()
|
||||||
{
|
{
|
||||||
// Find out if the user made any changes.
|
// Find out if the user made any changes.
|
||||||
bool dirty = mMetadataUpdated;
|
bool metadataUpdated = false;
|
||||||
for (unsigned int i = 0; i < mEditors.size(); i++) {
|
for (unsigned int i = 0; i < mEditors.size(); i++) {
|
||||||
const std::string& key = mMetaDataDecl.at(i).key;
|
const std::string& key = mMetaDataDecl.at(i).key;
|
||||||
std::string mMetaDataValue = mMetaData->get(key);
|
std::string mMetaDataValue = mMetaData->get(key);
|
||||||
|
@ -337,7 +361,7 @@ void GuiMetaDataEd::close()
|
||||||
mMetaDataValue = "19700101T010000";
|
mMetaDataValue = "19700101T010000";
|
||||||
|
|
||||||
if (mMetaDataValue != mEditorsValue) {
|
if (mMetaDataValue != mEditorsValue) {
|
||||||
dirty = true;
|
metadataUpdated = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -358,7 +382,7 @@ void GuiMetaDataEd::close()
|
||||||
std::function<void()> closeFunc;
|
std::function<void()> closeFunc;
|
||||||
closeFunc = [this] { delete this; };
|
closeFunc = [this] { delete this; };
|
||||||
|
|
||||||
if (dirty) {
|
if (metadataUpdated) {
|
||||||
// Changes were made, ask if the user wants to save them.
|
// Changes were made, ask if the user wants to save them.
|
||||||
mWindow->pushGui(new GuiMsgBox(mWindow, getHelpStyle(),
|
mWindow->pushGui(new GuiMsgBox(mWindow, getHelpStyle(),
|
||||||
"SAVE CHANGES?",
|
"SAVE CHANGES?",
|
||||||
|
|
|
@ -61,7 +61,6 @@ private:
|
||||||
std::function<void()> mSavedCallback;
|
std::function<void()> mSavedCallback;
|
||||||
std::function<void()> mDeleteFunc;
|
std::function<void()> mDeleteFunc;
|
||||||
|
|
||||||
bool mMetadataUpdated;
|
|
||||||
bool mMediaFilesUpdated;
|
bool mMediaFilesUpdated;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,14 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#define DEFAULT_TEXTCOLOR 0x777777FF
|
||||||
|
#define DEFAULT_INVERTED_TEXTCOLOR 0x444444FF
|
||||||
|
#define DEFAULT_COLORSHIFT 0xFFFFFFFF
|
||||||
|
#define ICONCOLOR_SCRAPERMARKED 0xFF5555FF
|
||||||
|
#define ICONCOLOR_USERMARKED 0x5555FFFF
|
||||||
|
#define TEXTCOLOR_SCRAPERMARKED 0x992222FF
|
||||||
|
#define TEXTCOLOR_USERMARKED 0x222299FF
|
||||||
|
|
||||||
class Animation;
|
class Animation;
|
||||||
class AnimationController;
|
class AnimationController;
|
||||||
class Font;
|
class Font;
|
||||||
|
@ -132,6 +140,8 @@ public:
|
||||||
virtual void setOpacity(unsigned char opacity);
|
virtual void setOpacity(unsigned char opacity);
|
||||||
virtual void setColor(unsigned int color);
|
virtual void setColor(unsigned int color);
|
||||||
virtual void setColorShift(unsigned int color);
|
virtual void setColorShift(unsigned int color);
|
||||||
|
virtual void setOriginalColor(unsigned int color) { mColorOriginalValue = color; };
|
||||||
|
virtual void setChangedColor(unsigned int color) { mColorChangedValue = color; };
|
||||||
virtual unsigned int getColor() const;
|
virtual unsigned int getColor() const;
|
||||||
|
|
||||||
const Transform4x4f& getTransform();
|
const Transform4x4f& getTransform();
|
||||||
|
@ -177,6 +187,9 @@ protected:
|
||||||
unsigned char mColorOpacity;
|
unsigned char mColorOpacity;
|
||||||
unsigned int mColorShift;
|
unsigned int mColorShift;
|
||||||
unsigned int mColorShiftEnd;
|
unsigned int mColorShiftEnd;
|
||||||
|
unsigned int mColorOriginalValue;
|
||||||
|
unsigned int mColorChangedValue;
|
||||||
|
|
||||||
Window* mWindow;
|
Window* mWindow;
|
||||||
|
|
||||||
GuiComponent* mParent;
|
GuiComponent* mParent;
|
||||||
|
|
|
@ -203,15 +203,20 @@ void ComponentList::render(const Transform4x4f& parentTrans)
|
||||||
it->component->render(trans);
|
it->component->render(trans);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// If there is a hue, average the brightness values to make
|
// Note: I've disabled this code as it's overly complicated,
|
||||||
// an equivalent gray value before inverting the text.
|
// instead we're now using a simple constant which should be
|
||||||
// This is not the proper way to do a BW conversion as the RGB values
|
// good enough. Let's keep the code though if needed in the
|
||||||
// should not be evenly distributed, but it's definitely good enough
|
// future for some reason.
|
||||||
// for this situation.
|
// // If there is a hue, average the brightness values to make
|
||||||
unsigned char byteAverage = (byteRed + byteGreen + byteBlue) / 3;
|
// // an equivalent gray value before inverting the text.
|
||||||
unsigned int averageColor = byteAverage << 24 | byteAverage << 16 |
|
// // This is not the proper way to do a BW conversion as the RGB values
|
||||||
byteAverage << 8 | 0xFF;
|
// // should not be evenly distributed, but it's definitely good enough
|
||||||
it->component->setColor(averageColor);
|
// // for this situation.
|
||||||
|
// unsigned char byteAverage = (byteRed + byteGreen + byteBlue) / 3;
|
||||||
|
// unsigned int averageColor = byteAverage << 24 | byteAverage << 16 |
|
||||||
|
// byteAverage << 8 | 0xFF;
|
||||||
|
// it->component->setColor(averageColor);
|
||||||
|
it->component->setColor(DEFAULT_INVERTED_TEXTCOLOR);
|
||||||
it->component->render(trans);
|
it->component->render(trans);
|
||||||
// Revert to the original color after rendering.
|
// Revert to the original color after rendering.
|
||||||
it->component->setColor(origColor);
|
it->component->setColor(origColor);
|
||||||
|
@ -221,10 +226,11 @@ void ComponentList::render(const Transform4x4f& parentTrans)
|
||||||
it->component->render(trans);
|
it->component->render(trans);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
drawAfterCursor.push_back(it->component.get());
|
drawAfterCursor.push_back(it->component.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Custom rendering.
|
// Custom rendering.
|
||||||
Renderer::setMatrix(trans);
|
Renderer::setMatrix(trans);
|
||||||
|
|
|
@ -41,7 +41,7 @@ struct ComponentListRow
|
||||||
elements.push_back(ComponentListElement(component, resize_width, invert_when_selected));
|
elements.push_back(ComponentListElement(component, resize_width, invert_when_selected));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Utility method for making an input handler for "when the users presses A on this, do func".
|
// Utility function for making an input handler for "when the users presses A on this, do func".
|
||||||
inline void makeAcceptInputHandler(const std::function<void()>& func)
|
inline void makeAcceptInputHandler(const std::function<void()>& func)
|
||||||
{
|
{
|
||||||
input_handler = [func](InputConfig* config, Input input) -> bool {
|
input_handler = [func](InputConfig* config, Input input) -> bool {
|
||||||
|
|
|
@ -107,6 +107,12 @@ bool DateTimeEditComponent::input(InputConfig* config, Input input)
|
||||||
|
|
||||||
mTime = new_tm;
|
mTime = new_tm;
|
||||||
|
|
||||||
|
// Change the color of the text to reflect the changes.
|
||||||
|
if (mTime == mOriginalValue)
|
||||||
|
setColor(mColorOriginalValue);
|
||||||
|
else
|
||||||
|
setColor(mColorChangedValue);
|
||||||
|
|
||||||
updateTextCache();
|
updateTextCache();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -170,6 +176,7 @@ void DateTimeEditComponent::render(const Transform4x4f& parentTrans)
|
||||||
void DateTimeEditComponent::setValue(const std::string& val)
|
void DateTimeEditComponent::setValue(const std::string& val)
|
||||||
{
|
{
|
||||||
mTime = val;
|
mTime = val;
|
||||||
|
mOriginalValue = val;
|
||||||
updateTextCache();
|
updateTextCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,10 @@ public:
|
||||||
// Text color.
|
// Text color.
|
||||||
void setColor(unsigned int color) override;
|
void setColor(unsigned int color) override;
|
||||||
// Font to use. Default is Font::get(FONT_SIZE_MEDIUM).
|
// Font to use. Default is Font::get(FONT_SIZE_MEDIUM).
|
||||||
|
|
||||||
|
void setOriginalColor(unsigned int color) override { mColorOriginalValue = color; };
|
||||||
|
void setChangedColor(unsigned int color) override { mColorChangedValue = color; };
|
||||||
|
|
||||||
void setFont(std::shared_ptr<Font> font);
|
void setFont(std::shared_ptr<Font> font);
|
||||||
// Force text to be uppercase when in DISP_RELATIVE_TO_NOW mode.
|
// Force text to be uppercase when in DISP_RELATIVE_TO_NOW mode.
|
||||||
void setUppercase(bool uppercase);
|
void setUppercase(bool uppercase);
|
||||||
|
@ -76,6 +80,10 @@ private:
|
||||||
std::vector<Vector4f> mCursorBoxes;
|
std::vector<Vector4f> mCursorBoxes;
|
||||||
|
|
||||||
unsigned int mColor;
|
unsigned int mColor;
|
||||||
|
Utils::Time::DateTime mOriginalValue;
|
||||||
|
unsigned int mColorOriginalValue;
|
||||||
|
unsigned int mColorChangedValue;
|
||||||
|
|
||||||
std::shared_ptr<Font> mFont;
|
std::shared_ptr<Font> mFont;
|
||||||
bool mUppercase;
|
bool mUppercase;
|
||||||
bool mAutoSize;
|
bool mAutoSize;
|
||||||
|
|
|
@ -363,7 +363,6 @@ void ImageComponent::render(const Transform4x4f& parentTrans)
|
||||||
// 'jump' in when it finally loads.
|
// 'jump' in when it finally loads.
|
||||||
fadeIn(mTexture->bind());
|
fadeIn(mTexture->bind());
|
||||||
Renderer::drawTriangleStrips(&mVertices[0], 4);
|
Renderer::drawTriangleStrips(&mVertices[0], 4);
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG(LogError) << "Image texture is not initialized!";
|
LOG(LogError) << "Image texture is not initialized!";
|
||||||
|
|
|
@ -11,8 +11,16 @@
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "ThemeData.h"
|
#include "ThemeData.h"
|
||||||
|
|
||||||
RatingComponent::RatingComponent(Window* window) : GuiComponent(window),
|
RatingComponent::RatingComponent(
|
||||||
mColorShift(0xFFFFFFFF), mColorShiftEnd(0xFFFFFFFF), mUnfilledColor(0xFFFFFFFF)
|
Window* window,
|
||||||
|
bool colorizeChanges)
|
||||||
|
: GuiComponent(window),
|
||||||
|
mColorShift(DEFAULT_COLORSHIFT),
|
||||||
|
mColorShiftEnd(DEFAULT_COLORSHIFT),
|
||||||
|
mUnfilledColor(DEFAULT_COLORSHIFT),
|
||||||
|
mColorizeChanges(colorizeChanges),
|
||||||
|
mColorOriginalValue(DEFAULT_COLORSHIFT),
|
||||||
|
mColorChangedValue(DEFAULT_COLORSHIFT)
|
||||||
{
|
{
|
||||||
mFilledTexture = TextureResource::get(":/graphics/star_filled.svg", true);
|
mFilledTexture = TextureResource::get(":/graphics/star_filled.svg", true);
|
||||||
mUnfilledTexture = TextureResource::get(":/graphics/star_unfilled.svg", true);
|
mUnfilledTexture = TextureResource::get(":/graphics/star_unfilled.svg", true);
|
||||||
|
@ -30,6 +38,26 @@ void RatingComponent::setValue(const std::string& value)
|
||||||
else {
|
else {
|
||||||
// Round up to the closest .1 value, i.e. to the closest half-icon.
|
// Round up to the closest .1 value, i.e. to the closest half-icon.
|
||||||
mValue = Math::ceilf(stof(value) / 0.1) / 10;
|
mValue = Math::ceilf(stof(value) / 0.1) / 10;
|
||||||
|
mOriginalValue = static_cast<int>(mValue * 10);
|
||||||
|
|
||||||
|
// If the argument to colorize the rating icons has been passed, set the
|
||||||
|
// color shift accordingly.
|
||||||
|
if (mColorizeChanges) {
|
||||||
|
if (static_cast<int>(mValue * 10) == mOriginalValue)
|
||||||
|
setColorShift(mColorOriginalValue);
|
||||||
|
else
|
||||||
|
setColorShift(mColorChangedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For the special situation where there is a fractional rating in the gamelist.xml
|
||||||
|
// file that has been rounded to a half-star rating, render the rating icons green.
|
||||||
|
// This should only happen if an external scraper has been used or if the file has
|
||||||
|
// been manually edited.
|
||||||
|
if (mColorizeChanges && mValue != stof(value)) {
|
||||||
|
mOriginalValue = ICONCOLOR_USERMARKED;
|
||||||
|
setColorShift(0x449944FF);
|
||||||
|
}
|
||||||
|
|
||||||
if (mValue > 1.0f)
|
if (mValue > 1.0f)
|
||||||
mValue = 1.0f;
|
mValue = 1.0f;
|
||||||
else if (mValue < 0.0f)
|
else if (mValue < 0.0f)
|
||||||
|
@ -102,9 +130,10 @@ void RatingComponent::updateVertices()
|
||||||
mVertices[6] = { { fw, 0.0f }, { numStars, 1.0f }, color };
|
mVertices[6] = { { fw, 0.0f }, { numStars, 1.0f }, color };
|
||||||
mVertices[7] = { { fw, h }, { numStars, 0.0f }, color };
|
mVertices[7] = { { fw, h }, { numStars, 0.0f }, color };
|
||||||
|
|
||||||
// Round vertices.
|
|
||||||
// Disabled as it caused subtle but strange rendering errors where
|
// Disabled this code as it caused subtle but strange rendering errors
|
||||||
// the icons changed size slightly when changing rating scores.
|
// where the icons changed size slightly when changing rating scores.
|
||||||
|
// // Round vertices.
|
||||||
// for (int i = 0; i < 8; ++i)
|
// for (int i = 0; i < 8; ++i)
|
||||||
// mVertices[i].pos.round();
|
// mVertices[i].pos.round();
|
||||||
}
|
}
|
||||||
|
@ -162,6 +191,14 @@ bool RatingComponent::input(InputConfig* config, Input input)
|
||||||
if (mValue > 1.05f)
|
if (mValue > 1.05f)
|
||||||
mValue = 0.0f;
|
mValue = 0.0f;
|
||||||
|
|
||||||
|
// If the argument to colorize the rating icons has been passed,
|
||||||
|
// set the color shift accordingly.
|
||||||
|
if (mColorizeChanges) {
|
||||||
|
if (static_cast<int>(mValue * 10) == mOriginalValue)
|
||||||
|
setColorShift(mColorOriginalValue);
|
||||||
|
else
|
||||||
|
setColorShift(mColorChangedValue);
|
||||||
|
}
|
||||||
updateVertices();
|
updateVertices();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ class TextureResource;
|
||||||
class RatingComponent : public GuiComponent
|
class RatingComponent : public GuiComponent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RatingComponent(Window* window);
|
RatingComponent(Window* window, bool colorizeChanges = false);
|
||||||
|
|
||||||
std::string getValue() const override;
|
std::string getValue() const override;
|
||||||
// Should be a normalized float (in the range [0..1]) - if it's not, it will be clamped.
|
// Should be a normalized float (in the range [0..1]) - if it's not, it will be clamped.
|
||||||
|
@ -40,6 +40,9 @@ public:
|
||||||
// Multiply all pixels in the image by this color when rendering.
|
// Multiply all pixels in the image by this color when rendering.
|
||||||
void setColorShift(unsigned int color) override;
|
void setColorShift(unsigned int color) override;
|
||||||
|
|
||||||
|
void setOriginalColor(unsigned int color) override { mColorOriginalValue = color; };
|
||||||
|
void setChangedColor(unsigned int color) override { mColorChangedValue = color; };
|
||||||
|
|
||||||
virtual void applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view,
|
virtual void applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view,
|
||||||
const std::string& element, unsigned int properties) override;
|
const std::string& element, unsigned int properties) override;
|
||||||
|
|
||||||
|
@ -52,6 +55,9 @@ private:
|
||||||
void updateColors();
|
void updateColors();
|
||||||
|
|
||||||
float mValue;
|
float mValue;
|
||||||
|
int mOriginalValue;
|
||||||
|
unsigned int mColorOriginalValue;
|
||||||
|
unsigned int mColorChangedValue;
|
||||||
|
|
||||||
Renderer::Vertex mVertices[8];
|
Renderer::Vertex mVertices[8];
|
||||||
|
|
||||||
|
@ -61,6 +67,8 @@ private:
|
||||||
|
|
||||||
std::shared_ptr<TextureResource> mFilledTexture;
|
std::shared_ptr<TextureResource> mFilledTexture;
|
||||||
std::shared_ptr<TextureResource> mUnfilledTexture;
|
std::shared_ptr<TextureResource> mUnfilledTexture;
|
||||||
|
|
||||||
|
bool mColorizeChanges;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ES_APP_COMPONENTS_RATING_COMPONENT_H
|
#endif // ES_APP_COMPONENTS_RATING_COMPONENT_H
|
||||||
|
|
|
@ -13,7 +13,9 @@ SwitchComponent::SwitchComponent(
|
||||||
bool state)
|
bool state)
|
||||||
: GuiComponent(window),
|
: GuiComponent(window),
|
||||||
mImage(window),
|
mImage(window),
|
||||||
mState(state)
|
mState(state),
|
||||||
|
mColorOriginalValue(DEFAULT_COLORSHIFT),
|
||||||
|
mColorChangedValue(DEFAULT_COLORSHIFT)
|
||||||
{
|
{
|
||||||
mImage.setImage(":/graphics/off.svg");
|
mImage.setImage(":/graphics/off.svg");
|
||||||
mImage.setResize(0, Font::get(FONT_SIZE_MEDIUM)->getLetterHeight());
|
mImage.setResize(0, Font::get(FONT_SIZE_MEDIUM)->getLetterHeight());
|
||||||
|
@ -65,12 +67,20 @@ void SwitchComponent::setValue(const std::string& statestring)
|
||||||
mState = true;
|
mState = true;
|
||||||
else
|
else
|
||||||
mState = false;
|
mState = false;
|
||||||
|
|
||||||
|
mOriginalValue = mState;
|
||||||
onStateChanged();
|
onStateChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitchComponent::onStateChanged()
|
void SwitchComponent::onStateChanged()
|
||||||
{
|
{
|
||||||
mImage.setImage(mState ? ":/graphics/on.svg" : ":/graphics/off.svg");
|
mImage.setImage(mState ? ":/graphics/on.svg" : ":/graphics/off.svg");
|
||||||
|
|
||||||
|
// Change the color of the switch to reflect the changes.
|
||||||
|
if (mState == mOriginalValue)
|
||||||
|
mImage.setColorShift(mColorOriginalValue);
|
||||||
|
else
|
||||||
|
mImage.setColorShift(mColorChangedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<HelpPrompt> SwitchComponent::getHelpPrompts()
|
std::vector<HelpPrompt> SwitchComponent::getHelpPrompts()
|
||||||
|
|
|
@ -26,6 +26,9 @@ public:
|
||||||
std::string getValue() const override;
|
std::string getValue() const override;
|
||||||
void setValue(const std::string& statestring) override;
|
void setValue(const std::string& statestring) override;
|
||||||
|
|
||||||
|
void setOriginalColor(unsigned int color) override { mColorOriginalValue = color; };
|
||||||
|
void setChangedColor(unsigned int color) override { mColorChangedValue = color; };
|
||||||
|
|
||||||
virtual std::vector<HelpPrompt> getHelpPrompts() override;
|
virtual std::vector<HelpPrompt> getHelpPrompts() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -33,6 +36,9 @@ private:
|
||||||
|
|
||||||
ImageComponent mImage;
|
ImageComponent mImage;
|
||||||
bool mState;
|
bool mState;
|
||||||
|
bool mOriginalValue;
|
||||||
|
unsigned int mColorOriginalValue;
|
||||||
|
unsigned int mColorChangedValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ES_CORE_COMPONENTS_SWITCH_COMPONENT_H
|
#endif // ES_CORE_COMPONENTS_SWITCH_COMPONENT_H
|
||||||
|
|
|
@ -88,10 +88,9 @@ void TextComponent::setRenderBackground(bool render)
|
||||||
// Scale the opacity.
|
// Scale the opacity.
|
||||||
void TextComponent::setOpacity(unsigned char opacity)
|
void TextComponent::setOpacity(unsigned char opacity)
|
||||||
{
|
{
|
||||||
// This method is mostly called to do fading in-out of the Text component element.
|
// This function is mostly called to do fading in-out of the Text component element.
|
||||||
// Therefore, we assume here that opacity is a fractional value (expressed as an int 0-255),
|
// Therefore, we assume here that opacity is a fractional value (expressed as an int 0-255),
|
||||||
// of the opacity originally set with setColor() or setBackgroundColor().
|
// of the opacity originally set with setColor() or setBackgroundColor().
|
||||||
|
|
||||||
unsigned char o = (unsigned char)((float)opacity / 255.f * (float) mColorOpacity);
|
unsigned char o = (unsigned char)((float)opacity / 255.f * (float) mColorOpacity);
|
||||||
mColor = (mColor & 0xFFFFFF00) | (unsigned char) o;
|
mColor = (mColor & 0xFFFFFF00) | (unsigned char) o;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue