Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ VENDORED_LIBS =
endif
CXXFLAGS = -std=c++14 -Os $(SDL_CFLAGS) -DMOD_VERSION=\"v$(MOD_VER)\"
LDLIBS = $(SDL_LIBS)
SOURCES = src/main.cpp src/back_stack.cpp src/command.cpp src/download_screen.cpp src/localization.cpp src/framework/badge.cpp src/framework/dialog.cpp src/framework/sdl_context.cpp src/framework/texture.cpp src/framework/controller.cpp src/framework/powerwatch.cpp src/framework/draw_helpers.cpp src/framework/utf8.cpp src/framework/font8x8_lookup.cpp src/framework/uitheme.cpp src/framework/list_jump.cpp src/framework/text_layout.cpp
SOURCES = src/main.cpp src/back_stack.cpp src/command.cpp src/download_screen.cpp src/localization.cpp src/framework/badge.cpp src/framework/dialog.cpp src/framework/sdl_context.cpp src/framework/texture.cpp src/framework/controller.cpp src/framework/powerwatch.cpp src/framework/draw_helpers.cpp src/framework/utf8.cpp src/framework/font8x8_lookup.cpp src/framework/uitheme.cpp src/framework/list_jump.cpp src/framework/text_layout.cpp src/framework/list_screen.cpp src/framework/panel_dialog.cpp
OBJECTS = $(SOURCES:.cpp=.o)
ALL_OBJECTS = $(OBJECTS) src/daemon.o src/mod_uninstall.o src/save_manager.o src/standby_watchdog.o src/gen_splash.o src/change_combo.o

Expand Down
3 changes: 2 additions & 1 deletion mod/etc/options_menu/scripts/OrphanSaves.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@ raContent() {
sed -E "s/$ra_save_suffix//"
}

# a game folder with only empty files holds no save
saveEntries() {
ls "$1" 2>/dev/null | grep "^CLV-" | grep -v "^CLV-S-"
find "$1" -mindepth 2 -path "$1/CLV-*" -type f -size +0 2>/dev/null | sed "s#^$1/##; s#/.*##" | grep -v "^CLV-S-" | sort -u
ls "$1/retroarch" 2>/dev/null | raContent | sed 's#^#retroarch/#'
}

Expand Down
153 changes: 153 additions & 0 deletions src/framework/list_screen.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/**
* Copyright (c) 2026 DefKorns (https://defkorns.github.io/LICENSE)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

#include "list_screen.h"
#include "draw_helpers.h"
#include "text_layout.h"
#include "uitheme.h"
#include "utf8.h"

#include <algorithm>

namespace
{
constexpr int CreditFontSize = 16;
constexpr int SectionAccentGap = 14;
constexpr int FooterDividerInset = 10;
constexpr int FooterDividerW = 2;
constexpr int SelectedRowStrokeW = 2;
constexpr int RowSeparatorGap = 3;

constexpr int NoteFontSize = 15;
constexpr int NoteLinePitch = 20;
constexpr int NoteIconOffsetX = 26;
constexpr int NoteIconSize = 18;
constexpr int NoteTextOffsetX = 46;
constexpr int NotePadRight = 16;
}

ScreenChrome::ScreenChrome(const std::string & optionsLocation, SDL_Renderer * renderer, const std::string & appTitle,
const std::string & version, const std::string & credit)
: renderer_(renderer)
, gear_(optionsLocation + UiTheme::AssetGear, renderer, UiTheme::GearX, UiTheme::GearY)
, appTitle_(appTitle, UiTheme::TitleFontSize, renderer, UiTheme::TitleX, UiTheme::TitleY, false, ToAbgr(UiTheme::Text), true)
, credit_(credit, CreditFontSize, renderer, UiTheme::CreditX, UiTheme::CreditY, false, ToAbgr(UiTheme::Text), true)
{
appTitle_.rect.y -= appTitle_.rect.h / 2;
appVersion_ = Texture(version, UiTheme::VersionFontSize, renderer, appTitle_.rect.x + appTitle_.rect.w + UiTheme::VersionGap, UiTheme::TitleY, false, ToAbgr(UiTheme::Text), true);
appVersion_.rect.y -= appVersion_.rect.h / 2;
}

void ScreenChrome::SetSectionTitle(const std::string & title)
{
sectionTitle_ = Texture(title, UiTheme::SectionTitleFontSize, renderer_, UiTheme::SectionTitleX, UiTheme::SectionTitleY, false, ToAbgr(UiTheme::Text), true);
}

void ScreenChrome::Draw()
{
DrawStrokeRect(renderer_, UiTheme::OuterRect, UiTheme::Border, UiTheme::BorderWidth, UiTheme::BorderRadius);
gear_.Draw(renderer_);
appTitle_.Draw(renderer_);
appVersion_.Draw(renderer_);
DrawHLine(renderer_, UiTheme::HeaderDividerX, UiTheme::HeaderDividerX + UiTheme::HeaderDividerW, UiTheme::HeaderDividerY, UiTheme::Border, UiTheme::BorderWidth);
DrawHLine(renderer_, UiTheme::OuterRect.x, UiTheme::OuterRect.x + UiTheme::OuterRect.w, UiTheme::FooterDividerY, UiTheme::Border, UiTheme::BorderWidth);
if(sectionTitle_.texture)
{
const int accentBarY = sectionTitle_.rect.y + (sectionTitle_.rect.h - UiTheme::SectionAccentBarH) / 2;
DrawFillRect(renderer_, { UiTheme::SectionTitleX - UiTheme::SectionAccentBarW - SectionAccentGap, accentBarY, UiTheme::SectionAccentBarW, UiTheme::SectionAccentBarH }, UiTheme::Accent);
sectionTitle_.Draw(renderer_);
}
credit_.Draw(renderer_);
}

void DrawFooterDivider(SDL_Renderer * renderer, int rightEdge)
{
const int dividerX = rightEdge - UiTheme::BadgeDividerGapFromCluster;
DrawVLine(renderer, dividerX, UiTheme::FooterY + FooterDividerInset, UiTheme::FooterY + UiTheme::FooterH - FooterDividerInset, UiTheme::Border, FooterDividerW);
}

SDL_Rect DrawListRow(SDL_Renderer * renderer, int index, int rightX, int rowHeight, bool selected)
{
const SDL_Rect rowRect{ UiTheme::ListX, UiTheme::RowFirstY + index * UiTheme::RowPitch, rightX - UiTheme::ListX, rowHeight };
if(selected)
{
DrawRoundedFillRect(renderer, rowRect, UiTheme::SelectedRowBg, UiTheme::BoxRadius);
DrawStrokeRect(renderer, rowRect, UiTheme::Accent, SelectedRowStrokeW, UiTheme::BoxRadius);
}
else
DrawHLine(renderer, rowRect.x, rowRect.x + rowRect.w, rowRect.y + rowRect.h + RowSeparatorGap, UiTheme::Border, 1);
return rowRect;
}

ScrollArrows::ScrollArrows(const std::string & optionsLocation, SDL_Renderer * renderer)
: renderer_(renderer)
, up_(optionsLocation + UiTheme::AssetChevronUp, renderer, UiTheme::ScrollX, UiTheme::ScrollUpY)
{
SetColorMod(up_.texture.get(), UiTheme::ScrollArrow);
up_.rect.x -= up_.rect.w / 2;
down_ = up_;
down_.rect.y = UiTheme::ScrollDownY;
}

void ScrollArrows::Draw(bool moreAbove, bool moreBelow)
{
if(moreAbove)
up_.Draw(renderer_);
if(moreBelow)
down_.Draw(renderer_, SDL_FLIP_VERTICAL);
}

NoteBox::NoteBox(SDL_Renderer * renderer, SDL_Rect rect)
: renderer_(renderer)
, rect_(rect)
{
}

void NoteBox::SetText(const std::string & text)
{
const int textW = rect_.w - NotePadRight - NoteTextOffsetX;
std::vector<std::string> wrapped = WrapToWidth(text, NoteFontSize, textW);
const size_t maxLines = static_cast<size_t>(std::max(1, rect_.h / NoteLinePitch));
if(wrapped.size() > maxLines)
{
wrapped.resize(maxLines);
std::string & last = wrapped.back();
int n = Utf8Length(last);
while(n > 0 && TextWidth(TruncateUtf8(last, n) + "...", NoteFontSize) > textW)
--n;
last = TruncateUtf8(last, n) + "...";
}
lines_ = MakeLines(wrapped, NoteFontSize, renderer_, UiTheme::TextDim);
}

void NoteBox::Draw()
{
DrawStrokeRect(renderer_, rect_, UiTheme::Border, UiTheme::BorderWidth, UiTheme::BoxRadius);
const int iconCX = rect_.x + NoteIconOffsetX;
const int centerY = rect_.y + rect_.h / 2;
DrawStrokeRect(renderer_, { iconCX - NoteIconSize / 2, centerY - NoteIconSize / 2, NoteIconSize, NoteIconSize }, UiTheme::TextDim, 2, NoteIconSize / 2);
DrawFillRect(renderer_, { iconCX - 1, centerY - 5, 2, 2 }, UiTheme::TextDim);
DrawFillRect(renderer_, { iconCX - 1, centerY - 1, 2, 6 }, UiTheme::TextDim);
int y = centerY - static_cast<int>(lines_.size()) * NoteLinePitch / 2;
for(Texture & line : lines_)
{
line.rect.x = rect_.x + NoteTextOffsetX;
line.rect.y = y + (NoteLinePitch - line.rect.h) / 2;
line.Draw(renderer_);
y += NoteLinePitch;
}
}
73 changes: 73 additions & 0 deletions src/framework/list_screen.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/**
* Copyright (c) 2026 DefKorns (https://defkorns.github.io/LICENSE)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

#ifndef LIST_SCREEN_H_
#define LIST_SCREEN_H_

#include "texture.h"

#include <SDL.h>
#include <string>
#include <vector>

class ScreenChrome
{
public:
ScreenChrome(const std::string & optionsLocation, SDL_Renderer * renderer, const std::string & appTitle,
const std::string & version, const std::string & credit);
void SetSectionTitle(const std::string & title);
void Draw();

private:
SDL_Renderer * renderer_;
Texture gear_;
Texture appTitle_;
Texture appVersion_;
Texture sectionTitle_;
Texture credit_;
};

void DrawFooterDivider(SDL_Renderer * renderer, int rightEdge);

SDL_Rect DrawListRow(SDL_Renderer * renderer, int index, int rightX, int rowHeight, bool selected);

class ScrollArrows
{
public:
ScrollArrows(const std::string & optionsLocation, SDL_Renderer * renderer);
void Draw(bool moreAbove, bool moreBelow);

private:
SDL_Renderer * renderer_;
Texture up_;
Texture down_;
};

class NoteBox
{
public:
NoteBox(SDL_Renderer * renderer, SDL_Rect rect);
void SetText(const std::string & text);
void Draw();

private:
SDL_Renderer * renderer_;
SDL_Rect rect_;
std::vector<Texture> lines_;
};

#endif
Loading
Loading