mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 07:35:38 +00:00
Merge branch '652-allow-system-placeholders-to-be-a-combination-of-text-and-image-make-text-and-image-customizable'
This commit is contained in:
commit
9472f607cc
|
@ -362,8 +362,10 @@ Below are the default zIndex values per element type:
|
||||||
* `text name="md_description"`
|
* `text name="md_description"`
|
||||||
* `text name="md_name"`
|
* `text name="md_name"`
|
||||||
* System Logo/Text - 50
|
* System Logo/Text - 50
|
||||||
* `text name="logoText"`
|
|
||||||
* `image name="logo"`
|
* `image name="logo"`
|
||||||
|
* `text name="logoText"`
|
||||||
|
* `image name="logoPlaceholderImage"`
|
||||||
|
* `text name="logoPlaceholderText"`
|
||||||
* Gamelist information - 50
|
* Gamelist information - 50
|
||||||
* `text name="gamelistInfo"`
|
* `text name="gamelistInfo"`
|
||||||
* Badges - 50
|
* Badges - 50
|
||||||
|
@ -409,17 +411,26 @@ or to specify only a portion of the value of a theme property:
|
||||||
### Views, their elements, and themeable properties
|
### Views, their elements, and themeable properties
|
||||||
|
|
||||||
#### system
|
#### system
|
||||||
|
|
||||||
* `helpsystem name="help"` - ALL
|
* `helpsystem name="help"` - ALL
|
||||||
- The help system style for this view.
|
- The help system style for this view.
|
||||||
* `carousel name="systemcarousel"` -ALL
|
* `carousel name="systemcarousel"` - ALL
|
||||||
- The system logo carousel
|
- The system logo carousel
|
||||||
* `image name="logo"` - PATH | COLOR
|
* `image name="logo"` - PATH | COLOR
|
||||||
- A logo image, to be displayed in the system logo carousel.
|
- A logo image, to be displayed in the system logo carousel.
|
||||||
|
* `image name="logoPlaceholderImage"` - ALL
|
||||||
|
- A logo image, to be displayed system name in the system logo carousel when no logo is available. Set the position
|
||||||
|
to `0.5 0.5` to center the image.
|
||||||
|
* `text name="logoPlaceholderText"` - ALL
|
||||||
|
- Logo text, to be displayed system name in the system logo carousel when no logo is available. The logo text is
|
||||||
|
displayed on top of `logoPlaceholderImage`. Set the position to `0.5 0.5` to center the text.
|
||||||
* `text name="logoText"` - FONT_PATH | COLOR | FORCE_UPPERCASE | LINE_SPACING | TEXT
|
* `text name="logoText"` - FONT_PATH | COLOR | FORCE_UPPERCASE | LINE_SPACING | TEXT
|
||||||
- A logo text, to be displayed system name in the system logo carousel when no logo is available.
|
- **Deprecated:** A logo text, to be displayed system name in the system logo carousel when no logo is available.
|
||||||
|
Ignored when `logoPlaceholderImage` or `logoPlaceholderText` are set.
|
||||||
* `text name="systemInfo"` - ALL
|
* `text name="systemInfo"` - ALL
|
||||||
- Displays details of the system currently selected in the carousel.
|
- Displays details of the system currently selected in the carousel.
|
||||||
* You can use extra elements (elements with `extra="true"`) to add your own backgrounds, etc. They will be displayed behind the carousel, and scroll relative to the carousel.
|
* You can use extra elements (elements with `extra="true"`) to add your own backgrounds, etc. They will be displayed
|
||||||
|
behind the carousel, and scroll relative to the carousel.
|
||||||
|
|
||||||
|
|
||||||
#### basic
|
#### basic
|
||||||
|
|
|
@ -56,53 +56,112 @@ void SystemView::populate()
|
||||||
{
|
{
|
||||||
mEntries.clear();
|
mEntries.clear();
|
||||||
|
|
||||||
for (auto it = SystemData::sSystemVector.cbegin(); // Line break.
|
for (auto it : SystemData::sSystemVector) {
|
||||||
it != SystemData::sSystemVector.cend(); it++) {
|
const std::shared_ptr<ThemeData>& theme = it->getTheme();
|
||||||
const std::shared_ptr<ThemeData>& theme = (*it)->getTheme();
|
|
||||||
|
|
||||||
if (mViewNeedsReload)
|
if (mViewNeedsReload)
|
||||||
getViewElements(theme);
|
getViewElements(theme);
|
||||||
|
|
||||||
if ((*it)->isVisible()) {
|
if (it->isVisible()) {
|
||||||
Entry e;
|
Entry e;
|
||||||
e.name = (*it)->getName();
|
e.name = it->getName();
|
||||||
e.object = *it;
|
e.object = it;
|
||||||
|
|
||||||
|
// Component offset. Used for positioning placeholders.
|
||||||
|
glm::vec3 offsetLogo = {0.0f, 0.0f, 0.0f};
|
||||||
|
glm::vec3 offsetLogoPlaceholderText = {0.0f, 0.0f, 0.0f};
|
||||||
|
|
||||||
// Make logo.
|
// Make logo.
|
||||||
const ThemeData::ThemeElement* logoElem = theme->getElement("system", "logo", "image");
|
const ThemeData::ThemeElement* logoElem = theme->getElement("system", "logo", "image");
|
||||||
if (logoElem) {
|
if (logoElem) {
|
||||||
std::string path = logoElem->get<std::string>("path");
|
auto path = logoElem->get<std::string>("path");
|
||||||
std::string defaultPath =
|
std::string defaultPath =
|
||||||
logoElem->has("default") ? logoElem->get<std::string>("default") : "";
|
logoElem->has("default") ? logoElem->get<std::string>("default") : "";
|
||||||
if ((!path.empty() && ResourceManager::getInstance()->fileExists(path)) ||
|
if ((!path.empty() && ResourceManager::getInstance()->fileExists(path)) ||
|
||||||
(!defaultPath.empty() &&
|
(!defaultPath.empty() &&
|
||||||
ResourceManager::getInstance()->fileExists(defaultPath))) {
|
ResourceManager::getInstance()->fileExists(defaultPath))) {
|
||||||
ImageComponent* logo = new ImageComponent(mWindow, false, false);
|
auto* logo = new ImageComponent(mWindow, false, false);
|
||||||
logo->setMaxSize(mCarousel.logoSize * mCarousel.logoScale);
|
logo->setMaxSize(mCarousel.logoSize * mCarousel.logoScale);
|
||||||
logo->applyTheme(theme, "system", "logo", ThemeFlags::PATH | ThemeFlags::COLOR);
|
logo->applyTheme(theme, "system", "logo", ThemeFlags::PATH | ThemeFlags::COLOR);
|
||||||
logo->setRotateByTargetSize(true);
|
logo->setRotateByTargetSize(true);
|
||||||
e.data.logo = std::shared_ptr<GuiComponent>(logo);
|
e.data.logo = std::shared_ptr<GuiComponent>(logo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!e.data.logo) {
|
|
||||||
// No logo in theme; use text.
|
|
||||||
TextComponent* text =
|
|
||||||
new TextComponent(mWindow, (*it)->getName(), Font::get(FONT_SIZE_LARGE),
|
|
||||||
0x000000FF, ALIGN_CENTER);
|
|
||||||
text->setSize(mCarousel.logoSize * mCarousel.logoScale);
|
|
||||||
text->applyTheme((*it)->getTheme(), "system", "logoText",
|
|
||||||
ThemeFlags::FONT_PATH | ThemeFlags::FONT_SIZE | ThemeFlags::COLOR |
|
|
||||||
ThemeFlags::FORCE_UPPERCASE | ThemeFlags::LINE_SPACING |
|
|
||||||
ThemeFlags::TEXT);
|
|
||||||
e.data.logo = std::shared_ptr<GuiComponent>(text);
|
|
||||||
|
|
||||||
if (mCarousel.type == VERTICAL || mCarousel.type == VERTICAL_WHEEL) {
|
// No logo available? Make placeholder.
|
||||||
text->setHorizontalAlignment(mCarousel.logoAlignment);
|
if (!e.data.logo) {
|
||||||
text->setVerticalAlignment(ALIGN_CENTER);
|
|
||||||
|
glm::vec2 resolution = glm::vec2{static_cast<float>(Renderer::getScreenWidth()),
|
||||||
|
static_cast<float>(Renderer::getScreenHeight())};
|
||||||
|
glm::vec3 center = {resolution.x / 2.0f, resolution.y / 2.0f, 1.0f};
|
||||||
|
|
||||||
|
// Placeholder Image.
|
||||||
|
logoElem = theme->getElement("system", "logoPlaceholderImage", "image");
|
||||||
|
if (logoElem) {
|
||||||
|
auto path = logoElem->get<std::string>("path");
|
||||||
|
std::string defaultPath =
|
||||||
|
logoElem->has("default") ? logoElem->get<std::string>("default") : "";
|
||||||
|
if ((!path.empty() && ResourceManager::getInstance()->fileExists(path)) ||
|
||||||
|
(!defaultPath.empty() &&
|
||||||
|
ResourceManager::getInstance()->fileExists(defaultPath))) {
|
||||||
|
auto* logo = new ImageComponent(mWindow, false, false);
|
||||||
|
logo->applyTheme(theme, "system", "logoPlaceholderImage", ThemeFlags::ALL);
|
||||||
|
if (!logoElem->has("size"))
|
||||||
|
logo->setMaxSize(mCarousel.logoSize * mCarousel.logoScale);
|
||||||
|
offsetLogo = logo->getPosition() - center;
|
||||||
|
logo->setRotateByTargetSize(true);
|
||||||
|
e.data.logo = std::shared_ptr<GuiComponent>(logo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Placeholder Text.
|
||||||
|
const ThemeData::ThemeElement* logoPlaceholderText =
|
||||||
|
theme->getElement("system", "logoPlaceholderText", "text");
|
||||||
|
if (logoPlaceholderText) {
|
||||||
|
// Element 'logoPlaceholderText' found in theme: place text
|
||||||
|
auto* text =
|
||||||
|
new TextComponent(mWindow, it->getName(), Font::get(FONT_SIZE_LARGE),
|
||||||
|
0x000000FF, ALIGN_CENTER);
|
||||||
|
text->setSize(mCarousel.logoSize * mCarousel.logoScale);
|
||||||
|
if (mCarousel.type == VERTICAL || mCarousel.type == VERTICAL_WHEEL) {
|
||||||
|
text->setHorizontalAlignment(mCarousel.logoAlignment);
|
||||||
|
text->setVerticalAlignment(ALIGN_CENTER);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
text->setHorizontalAlignment(ALIGN_CENTER);
|
||||||
|
text->setVerticalAlignment(mCarousel.logoAlignment);
|
||||||
|
}
|
||||||
|
text->applyTheme(it->getTheme(), "system", "logoPlaceholderText",
|
||||||
|
ThemeFlags::ALL);
|
||||||
|
if (!e.data.logo) {
|
||||||
|
e.data.logo = std::shared_ptr<GuiComponent>(text);
|
||||||
|
offsetLogo = text->getPosition() - center;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
e.data.logoPlaceholderText = std::shared_ptr<GuiComponent>(text);
|
||||||
|
offsetLogoPlaceholderText = text->getPosition() - center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
text->setHorizontalAlignment(ALIGN_CENTER);
|
// Fallback to legacy centered placeholder text.
|
||||||
text->setVerticalAlignment(mCarousel.logoAlignment);
|
auto* text =
|
||||||
|
new TextComponent(mWindow, it->getName(), Font::get(FONT_SIZE_LARGE),
|
||||||
|
0x000000FF, ALIGN_CENTER);
|
||||||
|
text->setSize(mCarousel.logoSize * mCarousel.logoScale);
|
||||||
|
text->applyTheme(it->getTheme(), "system", "logoText",
|
||||||
|
ThemeFlags::FONT_PATH | ThemeFlags::FONT_SIZE |
|
||||||
|
ThemeFlags::COLOR | ThemeFlags::FORCE_UPPERCASE |
|
||||||
|
ThemeFlags::LINE_SPACING | ThemeFlags::TEXT);
|
||||||
|
e.data.logo = std::shared_ptr<GuiComponent>(text);
|
||||||
|
|
||||||
|
if (mCarousel.type == VERTICAL || mCarousel.type == VERTICAL_WHEEL) {
|
||||||
|
text->setHorizontalAlignment(mCarousel.logoAlignment);
|
||||||
|
text->setVerticalAlignment(ALIGN_CENTER);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
text->setHorizontalAlignment(ALIGN_CENTER);
|
||||||
|
text->setVerticalAlignment(mCarousel.logoAlignment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,10 +183,14 @@ void SystemView::populate()
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec2 denormalized{mCarousel.logoSize * e.data.logo->getOrigin()};
|
glm::vec2 denormalized{mCarousel.logoSize * e.data.logo->getOrigin()};
|
||||||
e.data.logo->setPosition(denormalized.x, denormalized.y, 0.0f);
|
glm::vec3 v = {denormalized.x, denormalized.y, 0.0f};
|
||||||
|
e.data.logo->setPosition(v + offsetLogo);
|
||||||
|
if (e.data.logoPlaceholderText)
|
||||||
|
e.data.logoPlaceholderText->setPosition(
|
||||||
|
v + offsetLogoPlaceholderText);
|
||||||
|
|
||||||
// Make background extras.
|
// Make background extras.
|
||||||
e.data.backgroundExtras = ThemeData::makeExtras((*it)->getTheme(), "system", mWindow);
|
e.data.backgroundExtras = ThemeData::makeExtras(it->getTheme(), "system", mWindow);
|
||||||
|
|
||||||
// Sort the extras by z-index.
|
// Sort the extras by z-index.
|
||||||
std::stable_sort(
|
std::stable_sort(
|
||||||
|
@ -137,7 +200,7 @@ void SystemView::populate()
|
||||||
this->add(e);
|
this->add(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mEntries.size() == 0) {
|
if (mEntries.empty()) {
|
||||||
// Something is wrong, there is not a single system to show, check if UI mode is not full.
|
// Something is wrong, there is not a single system to show, check if UI mode is not full.
|
||||||
if (!UIModeController::getInstance()->isUIModeFull()) {
|
if (!UIModeController::getInstance()->isUIModeFull()) {
|
||||||
Settings::getInstance()->setString("UIMode", "full");
|
Settings::getInstance()->setString("UIMode", "full");
|
||||||
|
@ -615,6 +678,17 @@ void SystemView::renderCarousel(const glm::mat4& trans)
|
||||||
|
|
||||||
comp->setOpacity(static_cast<unsigned char>(opacity));
|
comp->setOpacity(static_cast<unsigned char>(opacity));
|
||||||
comp->render(logoTrans);
|
comp->render(logoTrans);
|
||||||
|
|
||||||
|
if (mEntries.at(index).data.logoPlaceholderText) {
|
||||||
|
const std::shared_ptr<GuiComponent>& comp = mEntries.at(index).data.logoPlaceholderText;
|
||||||
|
if (mCarousel.type == VERTICAL_WHEEL || mCarousel.type == HORIZONTAL_WHEEL) {
|
||||||
|
comp->setRotationDegrees(mCarousel.logoRotation * distance);
|
||||||
|
comp->setRotationOrigin(mCarousel.logoRotationOrigin);
|
||||||
|
}
|
||||||
|
comp->setScale(scale);
|
||||||
|
comp->setOpacity(static_cast<unsigned char>(opacity));
|
||||||
|
comp->render(logoTrans);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Renderer::popClipRect();
|
Renderer::popClipRect();
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ enum CarouselType : unsigned int {
|
||||||
|
|
||||||
struct SystemViewData {
|
struct SystemViewData {
|
||||||
std::shared_ptr<GuiComponent> logo;
|
std::shared_ptr<GuiComponent> logo;
|
||||||
|
std::shared_ptr<GuiComponent> logoPlaceholderText;
|
||||||
std::vector<GuiComponent*> backgroundExtras;
|
std::vector<GuiComponent*> backgroundExtras;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,14 @@ based on: 'recalbox-multi' by the Recalbox community
|
||||||
<fontPath>./core/fonts/Exo2-RegularCondensed.otf</fontPath>
|
<fontPath>./core/fonts/Exo2-RegularCondensed.otf</fontPath>
|
||||||
<fontSize>0.035</fontSize>
|
<fontSize>0.035</fontSize>
|
||||||
</text>
|
</text>
|
||||||
|
<text name="logoPlaceholderText">
|
||||||
|
<pos>0.5 0.5</pos>
|
||||||
|
<origin>0.5 0.5</origin>
|
||||||
|
<fontPath>./core/fonts/Exo2-RegularCondensed.otf</fontPath>
|
||||||
|
<fontSize>0.035</fontSize>
|
||||||
|
<color>000000FF</color>
|
||||||
|
<text>${system.fullName}</text>
|
||||||
|
</text>
|
||||||
</view>
|
</view>
|
||||||
</feature>
|
</feature>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue