filebrowser: add forwarder creator.
This commit is contained in:
@@ -140,7 +140,7 @@ public:
|
|||||||
m_callback = cb;
|
m_callback = cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto GetValue() const {
|
auto GetValue() const -> const std::string& {
|
||||||
return m_value;
|
return m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,14 +155,12 @@ private:
|
|||||||
|
|
||||||
class SidebarEntryTextInput final : public SidebarEntryTextBase {
|
class SidebarEntryTextInput final : public SidebarEntryTextBase {
|
||||||
public:
|
public:
|
||||||
explicit SidebarEntryTextInput(const std::string& title, const std::string& value, const std::string& guide = {}, const std::string& info = "");
|
explicit SidebarEntryTextInput(const std::string& title, const std::string& value, const std::string& guide = {}, s64 len_min = -1, s64 len_max = FS_MAX_PATH, const std::string& info = "");
|
||||||
|
|
||||||
void SetGuide(const std::string& guide) {
|
|
||||||
m_guide = guide;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_guide;
|
const std::string m_guide;
|
||||||
|
const s64 m_len_min;
|
||||||
|
const s64 m_len_max;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SidebarEntryFilePicker final : public SidebarEntryTextBase {
|
class SidebarEntryFilePicker final : public SidebarEntryTextBase {
|
||||||
@@ -178,7 +176,7 @@ private:
|
|||||||
std::vector<std::string> m_filter{};
|
std::vector<std::string> m_filter{};
|
||||||
};
|
};
|
||||||
|
|
||||||
class Sidebar final : public Widget {
|
class Sidebar : public Widget {
|
||||||
public:
|
public:
|
||||||
enum class Side { LEFT, RIGHT };
|
enum class Side { LEFT, RIGHT };
|
||||||
using Items = std::vector<std::unique_ptr<SidebarEntryBase>>;
|
using Items = std::vector<std::unique_ptr<SidebarEntryBase>>;
|
||||||
@@ -197,8 +195,8 @@ public:
|
|||||||
auto Add(std::unique_ptr<SidebarEntryBase>&& entry) -> SidebarEntryBase*;
|
auto Add(std::unique_ptr<SidebarEntryBase>&& entry) -> SidebarEntryBase*;
|
||||||
|
|
||||||
template<DerivedFromSidebarBase T, typename... Args>
|
template<DerivedFromSidebarBase T, typename... Args>
|
||||||
auto Add(Args&&... args) -> SidebarEntryBase* {
|
auto Add(Args&&... args) -> T* {
|
||||||
return Add(std::make_unique<T>(std::forward<Args>(args)...));
|
return (T*)Add(std::make_unique<T>(std::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -843,7 +843,7 @@ auto install_forwader_internal(ui::ProgressBox* pbox, OwoConfig& config, NcmStor
|
|||||||
pbox->SetImageDataConst(config.icon);
|
pbox->SetImageDataConst(config.icon);
|
||||||
|
|
||||||
R_UNLESS(!config.nro_path.empty(), Result_OwoBadArgs);
|
R_UNLESS(!config.nro_path.empty(), Result_OwoBadArgs);
|
||||||
// R_UNLESS(!config.icon.empty(), OwoError_BadArgs);
|
R_UNLESS(!config.icon.empty(), Result_OwoBadArgs);
|
||||||
|
|
||||||
R_TRY(splCryptoInitialize());
|
R_TRY(splCryptoInitialize());
|
||||||
ON_SCOPE_EXIT(splCryptoExit());
|
ON_SCOPE_EXIT(splCryptoExit());
|
||||||
|
|||||||
@@ -38,12 +38,33 @@
|
|||||||
#include <span>
|
#include <span>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
// #include <stack>
|
|
||||||
#include <expected>
|
#include <expected>
|
||||||
|
|
||||||
namespace sphaira::ui::menu::filebrowser {
|
namespace sphaira::ui::menu::filebrowser {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
using RomDatabaseIndexs = std::vector<size_t>;
|
||||||
|
|
||||||
|
struct ForwarderForm final : public Sidebar {
|
||||||
|
explicit ForwarderForm(const FileAssocEntry& assoc, const RomDatabaseIndexs& db_indexs, const FileEntry& entry, const fs::FsPath& arg_path);
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto LoadNroMeta() -> Result;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const FileAssocEntry m_assoc;
|
||||||
|
const RomDatabaseIndexs m_db_indexs;
|
||||||
|
const fs::FsPath m_arg_path;
|
||||||
|
|
||||||
|
NroEntry m_nro{};
|
||||||
|
NacpStruct m_nacp{};
|
||||||
|
|
||||||
|
SidebarEntryTextInput* m_name{};
|
||||||
|
SidebarEntryTextInput* m_author{};
|
||||||
|
SidebarEntryTextInput* m_version{};
|
||||||
|
SidebarEntryFilePicker* m_icon{};
|
||||||
|
};
|
||||||
|
|
||||||
constinit UEvent g_change_uevent;
|
constinit UEvent g_change_uevent;
|
||||||
|
|
||||||
constexpr FsEntry FS_ENTRY_DEFAULT{
|
constexpr FsEntry FS_ENTRY_DEFAULT{
|
||||||
@@ -176,7 +197,6 @@ auto IsExtension(std::string_view ext1, std::string_view ext2) -> bool {
|
|||||||
// tries to find database path using folder name
|
// tries to find database path using folder name
|
||||||
// names are taken from retropie
|
// names are taken from retropie
|
||||||
// retroarch database names can also be used
|
// retroarch database names can also be used
|
||||||
using RomDatabaseIndexs = std::vector<size_t>;
|
|
||||||
auto GetRomDatabaseFromPath(std::string_view path) -> RomDatabaseIndexs {
|
auto GetRomDatabaseFromPath(std::string_view path) -> RomDatabaseIndexs {
|
||||||
if (path.length() <= 1) {
|
if (path.length() <= 1) {
|
||||||
return {};
|
return {};
|
||||||
@@ -216,7 +236,7 @@ auto GetRomDatabaseFromPath(std::string_view path) -> RomDatabaseIndexs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
auto GetRomIcon(fs::Fs* fs, ProgressBox* pbox, std::string filename, const RomDatabaseIndexs& db_indexs, const NroEntry& nro) {
|
auto GetRomIcon(std::string filename, const RomDatabaseIndexs& db_indexs, const NroEntry& nro) {
|
||||||
// if no db entries, use nro icon
|
// if no db entries, use nro icon
|
||||||
if (db_indexs.empty()) {
|
if (db_indexs.empty()) {
|
||||||
log_write("using nro image\n");
|
log_write("using nro image\n");
|
||||||
@@ -234,8 +254,6 @@ auto GetRomIcon(fs::Fs* fs, ProgressBox* pbox, std::string filename, const RomDa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RA_BOXART_URL "https://thumbnails.libretro.com/"
|
|
||||||
#define GH_BOXART_URL "https://raw.githubusercontent.com/libretro-thumbnails/"
|
|
||||||
#define RA_BOXART_NAME "/Named_Boxarts/"
|
#define RA_BOXART_NAME "/Named_Boxarts/"
|
||||||
#define RA_THUMBNAIL_PATH "/retroarch/thumbnails/"
|
#define RA_THUMBNAIL_PATH "/retroarch/thumbnails/"
|
||||||
#define RA_BOXART_EXT ".png"
|
#define RA_BOXART_EXT ".png"
|
||||||
@@ -249,42 +267,15 @@ auto GetRomIcon(fs::Fs* fs, ProgressBox* pbox, std::string filename, const RomDa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string filename_gh;
|
|
||||||
filename_gh.reserve(filename.size());
|
|
||||||
for (auto c : filename) {
|
|
||||||
if (c == ' ') {
|
|
||||||
filename_gh += "%20";
|
|
||||||
} else {
|
|
||||||
filename_gh.push_back(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string thumbnail_path = system_name + RA_BOXART_NAME + filename + RA_BOXART_EXT;
|
const std::string thumbnail_path = system_name + RA_BOXART_NAME + filename + RA_BOXART_EXT;
|
||||||
const std::string ra_thumbnail_path = RA_THUMBNAIL_PATH + thumbnail_path;
|
const std::string ra_thumbnail_path = RA_THUMBNAIL_PATH + thumbnail_path;
|
||||||
const std::string ra_thumbnail_url = RA_BOXART_URL + thumbnail_path;
|
|
||||||
const std::string gh_thumbnail_url = GH_BOXART_URL + system_name_gh + RA_BOXART_NAME + filename_gh + RA_BOXART_EXT;
|
|
||||||
|
|
||||||
log_write("starting image convert on: %s\n", ra_thumbnail_path.c_str());
|
log_write("starting image convert on: %s\n", ra_thumbnail_path.c_str());
|
||||||
|
|
||||||
// try and find icon locally
|
// try and find icon locally
|
||||||
if (!pbox->ShouldExit()) {
|
std::vector<u8> image_file;
|
||||||
pbox->NewTransfer("Trying to load "_i18n + ra_thumbnail_path);
|
if (R_SUCCEEDED(fs::FsNativeSd().read_entire_file(ra_thumbnail_path, image_file))) {
|
||||||
std::vector<u8> image_file;
|
return image_file;
|
||||||
if (R_SUCCEEDED(fs->read_entire_file(ra_thumbnail_path.c_str(), image_file))) {
|
|
||||||
return image_file;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// try and download icon
|
|
||||||
if (!pbox->ShouldExit()) {
|
|
||||||
pbox->NewTransfer("Downloading "_i18n + gh_thumbnail_url);
|
|
||||||
const auto result = curl::Api().ToMemory(
|
|
||||||
curl::Url{gh_thumbnail_url},
|
|
||||||
curl::OnProgress{pbox->OnDownloadProgressCallback()}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (result.success && !result.data.empty()) {
|
|
||||||
return result.data;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,6 +284,116 @@ auto GetRomIcon(fs::Fs* fs, ProgressBox* pbox, std::string filename, const RomDa
|
|||||||
return nro_get_icon(nro.path, nro.icon_size, nro.icon_offset);
|
return nro_get_icon(nro.path, nro.icon_size, nro.icon_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ForwarderForm::ForwarderForm(const FileAssocEntry& assoc, const RomDatabaseIndexs& db_indexs, const FileEntry& entry, const fs::FsPath& arg_path)
|
||||||
|
: Sidebar{"Forwarder Creation", Side::RIGHT}
|
||||||
|
, m_assoc{assoc}
|
||||||
|
, m_db_indexs{db_indexs}
|
||||||
|
, m_arg_path{arg_path} {
|
||||||
|
log_write("parsing nro\n");
|
||||||
|
if (R_FAILED(LoadNroMeta())) {
|
||||||
|
App::Notify("Failed to parse nro"_i18n);
|
||||||
|
SetPop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_write("got nro data\n");
|
||||||
|
auto file_name = m_assoc.use_base_name ? entry.GetName() : entry.GetInternalName();
|
||||||
|
|
||||||
|
if (auto pos = file_name.find_last_of('.'); pos != std::string::npos) {
|
||||||
|
log_write("got filename\n");
|
||||||
|
file_name = file_name.substr(0, pos);
|
||||||
|
log_write("got filename2: %s\n\n", file_name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto name = m_nro.nacp.lang.name + std::string{" | "} + file_name;
|
||||||
|
const auto author = m_nacp.lang[0].author;
|
||||||
|
const auto version = m_nacp.display_version;
|
||||||
|
const auto icon = m_assoc.path;
|
||||||
|
|
||||||
|
m_name = this->Add<SidebarEntryTextInput>(
|
||||||
|
"Name", name, "", -1, sizeof(NacpLanguageEntry::name) - 1,
|
||||||
|
"Set the name of the application"_i18n
|
||||||
|
);
|
||||||
|
|
||||||
|
m_author = this->Add<SidebarEntryTextInput>(
|
||||||
|
"Author", author, "", -1, sizeof(NacpLanguageEntry::author) - 1,
|
||||||
|
"Set the author of the application"_i18n
|
||||||
|
);
|
||||||
|
|
||||||
|
m_version = this->Add<SidebarEntryTextInput>(
|
||||||
|
"Version", version, "", -1, sizeof(NacpStruct::display_version) - 1,
|
||||||
|
"Set the display version of the application"_i18n
|
||||||
|
);
|
||||||
|
|
||||||
|
const std::vector<std::string> filters{".nro", ".png", ".jpg"};
|
||||||
|
m_icon = this->Add<SidebarEntryFilePicker>(
|
||||||
|
"Icon", icon, filters,
|
||||||
|
"Set the path to the icon for the forwarder"_i18n
|
||||||
|
);
|
||||||
|
|
||||||
|
auto callback = this->Add<SidebarEntryCallback>("Create", [this, file_name](){
|
||||||
|
OwoConfig config{};
|
||||||
|
config.nro_path = m_assoc.path.toString();
|
||||||
|
config.args = nro_add_arg_file(m_arg_path);
|
||||||
|
config.nacp = m_nacp;
|
||||||
|
|
||||||
|
// patch the name.
|
||||||
|
config.name = m_name->GetValue();
|
||||||
|
|
||||||
|
// patch the author.
|
||||||
|
config.author = m_author->GetValue();
|
||||||
|
|
||||||
|
// patch the display version.
|
||||||
|
std::snprintf(config.nacp.display_version, sizeof(config.nacp.display_version), "%s", m_version->GetValue().c_str());
|
||||||
|
|
||||||
|
// load icon fron nro or image.
|
||||||
|
if (m_icon->GetValue().ends_with(".nro")) {
|
||||||
|
// if path was left as the default, try and load the icon from rom db.
|
||||||
|
if (config.nro_path == m_icon->GetValue()) {
|
||||||
|
config.icon = GetRomIcon(file_name, m_db_indexs, m_nro);
|
||||||
|
} else {
|
||||||
|
config.icon = nro_get_icon(m_icon->GetValue());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// try and read icon file into memory, bail if this fails.
|
||||||
|
const auto rc = fs::FsStdio().read_entire_file(m_icon->GetValue(), config.icon);
|
||||||
|
if (R_FAILED(rc)) {
|
||||||
|
App::PushErrorBox(rc, "Failed to load icon");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this is a rom, load intro logo.
|
||||||
|
if (!m_db_indexs.empty()) {
|
||||||
|
fs::FsNativeSd().read_entire_file("/config/sphaira/logo/rom/NintendoLogo.png", config.logo);
|
||||||
|
fs::FsNativeSd().read_entire_file("/config/sphaira/logo/rom/StartupMovie.gif", config.gif);
|
||||||
|
}
|
||||||
|
|
||||||
|
// try and install.
|
||||||
|
if (R_FAILED(App::Install(config))) {
|
||||||
|
App::Notify("Failed to install forwarder"_i18n);
|
||||||
|
} else {
|
||||||
|
SetPop();
|
||||||
|
}
|
||||||
|
}, "Create the forwarder."_i18n);
|
||||||
|
|
||||||
|
// ensure that all fields are valid.
|
||||||
|
callback->Depends([this](){
|
||||||
|
return
|
||||||
|
!m_name->GetValue().empty() &&
|
||||||
|
!m_author->GetValue().empty() &&
|
||||||
|
!m_version->GetValue().empty() &&
|
||||||
|
!m_icon->GetValue().empty();
|
||||||
|
}, "All fields must be non-empty!"_i18n);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ForwarderForm::LoadNroMeta() -> Result {
|
||||||
|
// try and load nro meta data.
|
||||||
|
R_TRY(nro_parse(m_assoc.path, m_nro));
|
||||||
|
R_TRY(nro_get_nacp(m_assoc.path, m_nacp));
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void SignalChange() {
|
void SignalChange() {
|
||||||
@@ -650,51 +751,7 @@ void FsView::InstallForwarder() {
|
|||||||
title, items, [this, assoc_list](auto op_index){
|
title, items, [this, assoc_list](auto op_index){
|
||||||
if (op_index) {
|
if (op_index) {
|
||||||
const auto assoc = assoc_list[*op_index];
|
const auto assoc = assoc_list[*op_index];
|
||||||
log_write("pushing it\n");
|
App::Push<ForwarderForm>(assoc, GetRomDatabaseFromPath(m_path), GetEntry(), GetNewPathCurrent());
|
||||||
App::Push<ProgressBox>(0, "Installing Forwarder"_i18n, GetEntry().name, [assoc, this](auto pbox) -> Result {
|
|
||||||
log_write("inside callback\n");
|
|
||||||
|
|
||||||
NroEntry nro{};
|
|
||||||
log_write("parsing nro\n");
|
|
||||||
R_TRY(nro_parse(assoc.path, nro));
|
|
||||||
|
|
||||||
NacpStruct nacp;
|
|
||||||
R_TRY(nro_get_nacp(assoc.path, nacp));
|
|
||||||
|
|
||||||
log_write("got nro data\n");
|
|
||||||
auto file_name = assoc.use_base_name ? GetEntry().GetName() : GetEntry().GetInternalName();
|
|
||||||
|
|
||||||
if (auto pos = file_name.find_last_of('.'); pos != std::string::npos) {
|
|
||||||
log_write("got filename\n");
|
|
||||||
file_name = file_name.substr(0, pos);
|
|
||||||
log_write("got filename2: %s\n\n", file_name.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto db_indexs = GetRomDatabaseFromPath(m_path);
|
|
||||||
|
|
||||||
OwoConfig config{};
|
|
||||||
config.nro_path = assoc.path.toString();
|
|
||||||
config.args = nro_add_arg_file(GetNewPathCurrent());
|
|
||||||
config.name = nro.nacp.lang.name + std::string{" | "} + file_name;
|
|
||||||
// config.name = file_name;
|
|
||||||
config.nacp = nacp;
|
|
||||||
config.icon = GetRomIcon(m_fs.get(), pbox, file_name, db_indexs, nro);
|
|
||||||
pbox->SetImageDataConst(config.icon);
|
|
||||||
|
|
||||||
if (!db_indexs.empty()) {
|
|
||||||
fs::FsNativeSd().read_entire_file("/config/sphaira/logo/rom/NintendoLogo.png", config.logo);
|
|
||||||
fs::FsNativeSd().read_entire_file("/config/sphaira/logo/rom/StartupMovie.gif", config.gif);
|
|
||||||
}
|
|
||||||
|
|
||||||
return App::Install(pbox, config);
|
|
||||||
}, [this](Result rc){
|
|
||||||
App::PushErrorBox(rc, "Failed to install forwarder"_i18n);
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
|
||||||
App::PlaySoundEffect(SoundEffect_Install);
|
|
||||||
App::Notify("Installed!"_i18n);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
log_write("pressed B to skip launch...\n");
|
log_write("pressed B to skip launch...\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -252,19 +252,17 @@ SidebarEntryTextBase::SidebarEntryTextBase(const std::string& title, const std::
|
|||||||
void SidebarEntryTextBase::Draw(NVGcontext* vg, Theme* theme, const Vec4& root_pos, bool left) {
|
void SidebarEntryTextBase::Draw(NVGcontext* vg, Theme* theme, const Vec4& root_pos, bool left) {
|
||||||
SidebarEntryBase::Draw(vg, theme, root_pos, left);
|
SidebarEntryBase::Draw(vg, theme, root_pos, left);
|
||||||
SidebarEntryBase::DrawEntry(vg, theme, m_title, m_value, true);
|
SidebarEntryBase::DrawEntry(vg, theme, m_title, m_value, true);
|
||||||
|
|
||||||
// const auto colour_id = IsEnabled() ? ThemeEntryID_TEXT : ThemeEntryID_TEXT_INFO;
|
|
||||||
// const auto max_w = m_pos.w - 15.f * 2;
|
|
||||||
|
|
||||||
// m_scolling_title.Draw(vg, HasFocus(), m_pos.x + 15.f, m_pos.y + (m_pos.h / 2.f), max_w, 20.f, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE, theme->GetColour(colour_id), m_title);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SidebarEntryTextInput::SidebarEntryTextInput(const std::string& title, const std::string& value, const std::string& guide, const std::string& info)
|
SidebarEntryTextInput::SidebarEntryTextInput(const std::string& title, const std::string& value, const std::string& guide, s64 len_min, s64 len_max, const std::string& info)
|
||||||
: SidebarEntryTextBase{title, value, {}, info}, m_guide{guide} {
|
: SidebarEntryTextBase{title, value, {}, info}
|
||||||
|
, m_guide{guide}
|
||||||
|
, m_len_min{len_min}
|
||||||
|
, m_len_max{len_max} {
|
||||||
|
|
||||||
SetCallback([this](){
|
SetCallback([this](){
|
||||||
std::string out;
|
std::string out;
|
||||||
if (R_SUCCEEDED(swkbd::ShowText(out, m_guide.c_str(), GetValue().c_str()))) {
|
if (R_SUCCEEDED(swkbd::ShowText(out, m_guide.c_str(), GetValue().c_str(), m_len_min, m_len_max))) {
|
||||||
SetValue(out);
|
SetValue(out);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -347,30 +345,6 @@ auto Sidebar::Update(Controller* controller, TouchInfo* touch) -> void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto Sidebar::Draw(NVGcontext* vg, Theme* theme) -> void {
|
auto Sidebar::Draw(NVGcontext* vg, Theme* theme) -> void {
|
||||||
// Vec4 info_box{};
|
|
||||||
// info_box.y = m_top_bar.y;
|
|
||||||
// info_box.w = 300;
|
|
||||||
// info_box.h = 250;
|
|
||||||
|
|
||||||
// if (m_side == Side::LEFT) {
|
|
||||||
// info_box.x = m_pos.x + m_pos.w + 10;
|
|
||||||
// } else {
|
|
||||||
// info_box.x = m_pos.x - info_box.w - 10;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const float info_pad = 30;
|
|
||||||
// const float info_font_size = 18;
|
|
||||||
// const char* msg = "Skips verifying the nca header signature";
|
|
||||||
// float bounds[4];
|
|
||||||
// nvgFontSize(vg, info_font_size);
|
|
||||||
// nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_TOP);
|
|
||||||
// nvgTextLineHeight(vg, 1.7);
|
|
||||||
// nvgTextBoxBounds(vg, info_box.x + info_pad, info_box.y + info_pad, info_box.w - info_pad * 2, msg, nullptr, bounds);
|
|
||||||
// info_box.h = info_pad * 2 + bounds[3] - bounds[1];
|
|
||||||
|
|
||||||
// gfx::drawRect(vg, info_box, theme->GetColour(ThemeEntryID_SIDEBAR), 5);
|
|
||||||
// gfx::drawTextBox(vg, bounds[0], bounds[1], info_font_size, info_box.w - info_pad * 2, theme->GetColour(ThemeEntryID_TEXT), msg);
|
|
||||||
|
|
||||||
gfx::drawRect(vg, m_pos, theme->GetColour(ThemeEntryID_SIDEBAR));
|
gfx::drawRect(vg, m_pos, theme->GetColour(ThemeEntryID_SIDEBAR));
|
||||||
gfx::drawText(vg, m_title_pos, m_title_size, theme->GetColour(ThemeEntryID_TEXT), m_title.c_str());
|
gfx::drawText(vg, m_title_pos, m_title_size, theme->GetColour(ThemeEntryID_TEXT), m_title.c_str());
|
||||||
if (!m_sub.empty()) {
|
if (!m_sub.empty()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user