add touch scrolling, fix scrollbar, fix appstore search
- when fireing an action, the action array may change. so the loop should break early as soon as an action is handled. this fixes the appstore search when pressing B. - scrollbar no longer goes oob. fixes #76 currently, scrolling has no acceleration.
This commit is contained in:
@@ -58,8 +58,8 @@ public:
|
|||||||
static void NotifyFlashLed();
|
static void NotifyFlashLed();
|
||||||
|
|
||||||
static auto GetThemeMetaList() -> std::span<ThemeMeta>;
|
static auto GetThemeMetaList() -> std::span<ThemeMeta>;
|
||||||
static void SetTheme(u64 theme_index);
|
static void SetTheme(s64 theme_index);
|
||||||
static auto GetThemeIndex() -> u64;
|
static auto GetThemeIndex() -> s64;
|
||||||
|
|
||||||
static auto GetDefaultImage(int* w = nullptr, int* h = nullptr) -> int;
|
static auto GetDefaultImage(int* w = nullptr, int* h = nullptr) -> int;
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ public:
|
|||||||
|
|
||||||
Theme m_theme{};
|
Theme m_theme{};
|
||||||
fs::FsPath theme_path{};
|
fs::FsPath theme_path{};
|
||||||
std::size_t m_theme_index{};
|
s64 m_theme_index{};
|
||||||
|
|
||||||
bool m_quit{};
|
bool m_quit{};
|
||||||
|
|
||||||
|
|||||||
@@ -5,22 +5,53 @@
|
|||||||
namespace sphaira::ui {
|
namespace sphaira::ui {
|
||||||
|
|
||||||
struct List final : Object {
|
struct List final : Object {
|
||||||
using Callback = std::function<bool(NVGcontext* vg, Theme* theme, Vec4 v, u64 index)>;
|
using Callback = std::function<void(NVGcontext* vg, Theme* theme, Vec4 v, s64 index)>;
|
||||||
|
using TouchCallback = std::function<void(s64 index)>;
|
||||||
|
|
||||||
List(const Vec4& pos, const Vec4& v, const Vec2& pad = {});
|
List(s64 row, s64 page, const Vec4& pos, const Vec4& v, const Vec2& pad = {});
|
||||||
|
|
||||||
void Do(u64 index, u64 count, Callback callback) const {
|
void OnUpdate(Controller* controller, TouchInfo* touch, s64 count, TouchCallback callback);
|
||||||
Do(nullptr, nullptr, index, count, callback);
|
|
||||||
|
void Draw(NVGcontext* vg, Theme* theme, s64 count, Callback callback) const;
|
||||||
|
|
||||||
|
auto SetScrollBarPos(float x, float y, float h) {
|
||||||
|
m_scrollbar.x = x;
|
||||||
|
m_scrollbar.y = y;
|
||||||
|
m_scrollbar.h = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Do(NVGcontext* vg, Theme* theme, u64 index, u64 count, Callback callback, float y_off = 0) const;
|
auto ScrollDown(s64& index, s64 step, s64 count) -> bool;
|
||||||
|
auto ScrollUp(s64& index, s64 step, s64 count) -> bool;
|
||||||
|
|
||||||
|
auto GetYoff() const {
|
||||||
|
return m_yoff;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetYoff(float y = 0) {
|
||||||
|
m_yoff = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto GetMaxY() const {
|
||||||
|
return m_v.h + m_pad.y;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
auto Draw(NVGcontext* vg, Theme* theme) -> void override {}
|
auto Draw(NVGcontext* vg, Theme* theme) -> void override {}
|
||||||
|
auto ClampY(float y, s64 count) const -> float;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const s64 m_row;
|
||||||
|
const s64 m_page;
|
||||||
|
|
||||||
Vec4 m_v;
|
Vec4 m_v;
|
||||||
Vec2 m_pad;
|
Vec2 m_pad;
|
||||||
|
|
||||||
|
Vec4 m_scrollbar{};
|
||||||
|
|
||||||
|
// current y offset.
|
||||||
|
float m_yoff{};
|
||||||
|
// in progress y offset, used when scrolling.
|
||||||
|
float m_y_prog{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sphaira::ui
|
} // namespace sphaira::ui
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ struct EntryMenu final : MenuBase {
|
|||||||
// void OnFocusGained() override;
|
// void OnFocusGained() override;
|
||||||
|
|
||||||
void ShowChangelogAction();
|
void ShowChangelogAction();
|
||||||
void SetIndex(std::size_t index);
|
void SetIndex(s64 index);
|
||||||
|
|
||||||
void UpdateOptions();
|
void UpdateOptions();
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ private:
|
|||||||
const LazyImage& m_default_icon;
|
const LazyImage& m_default_icon;
|
||||||
Menu& m_menu;
|
Menu& m_menu;
|
||||||
|
|
||||||
std::size_t m_index{}; // where i am in the array
|
s64 m_index{}; // where i am in the array
|
||||||
std::vector<Option> m_options;
|
std::vector<Option> m_options;
|
||||||
LazyImage m_banner;
|
LazyImage m_banner;
|
||||||
std::unique_ptr<List> m_list;
|
std::unique_ptr<List> m_list;
|
||||||
@@ -150,7 +150,7 @@ struct FeedbackMenu final : MenuBase {
|
|||||||
void Draw(NVGcontext* vg, Theme* theme) override;
|
void Draw(NVGcontext* vg, Theme* theme) override;
|
||||||
void OnFocusGained() override;
|
void OnFocusGained() override;
|
||||||
|
|
||||||
void SetIndex(std::size_t index);
|
void SetIndex(s64 index);
|
||||||
void ScanHomebrew();
|
void ScanHomebrew();
|
||||||
void Sort();
|
void Sort();
|
||||||
|
|
||||||
@@ -158,8 +158,7 @@ private:
|
|||||||
const std::vector<Entry>& m_package_entries;
|
const std::vector<Entry>& m_package_entries;
|
||||||
LazyImage& m_default_image;
|
LazyImage& m_default_image;
|
||||||
std::vector<FeedbackEntry> m_entries;
|
std::vector<FeedbackEntry> m_entries;
|
||||||
std::size_t m_start{};
|
s64 m_index{}; // where i am in the array
|
||||||
std::size_t m_index{}; // where i am in the array
|
|
||||||
ImageDownloadState m_repo_download_state{ImageDownloadState::None};
|
ImageDownloadState m_repo_download_state{ImageDownloadState::None};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -171,7 +170,7 @@ struct Menu final : MenuBase {
|
|||||||
void Draw(NVGcontext* vg, Theme* theme) override;
|
void Draw(NVGcontext* vg, Theme* theme) override;
|
||||||
void OnFocusGained() override;
|
void OnFocusGained() override;
|
||||||
|
|
||||||
void SetIndex(std::size_t index);
|
void SetIndex(s64 index);
|
||||||
void ScanHomebrew();
|
void ScanHomebrew();
|
||||||
void Sort();
|
void Sort();
|
||||||
|
|
||||||
@@ -202,8 +201,7 @@ private:
|
|||||||
SortType m_sort{SortType::SortType_Updated};
|
SortType m_sort{SortType::SortType_Updated};
|
||||||
OrderType m_order{OrderType::OrderType_Decending};
|
OrderType m_order{OrderType::OrderType_Decending};
|
||||||
|
|
||||||
std::size_t m_start{};
|
s64 m_index{}; // where i am in the array
|
||||||
std::size_t m_index{}; // where i am in the array
|
|
||||||
LazyImage m_default_image;
|
LazyImage m_default_image;
|
||||||
LazyImage m_update;
|
LazyImage m_update;
|
||||||
LazyImage m_get;
|
LazyImage m_get;
|
||||||
@@ -214,8 +212,8 @@ private:
|
|||||||
|
|
||||||
std::string m_search_term;
|
std::string m_search_term;
|
||||||
std::string m_author_term;
|
std::string m_author_term;
|
||||||
u64 m_entry_search_jump_back{};
|
s64 m_entry_search_jump_back{};
|
||||||
u64 m_entry_author_jump_back{};
|
s64 m_entry_author_jump_back{};
|
||||||
bool m_is_search{};
|
bool m_is_search{};
|
||||||
bool m_is_author{};
|
bool m_is_author{};
|
||||||
bool m_dirty{}; // if set, does a sort
|
bool m_dirty{}; // if set, does a sort
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ private:
|
|||||||
|
|
||||||
std::unique_ptr<ScrollableText> m_scroll_text;
|
std::unique_ptr<ScrollableText> m_scroll_text;
|
||||||
|
|
||||||
std::size_t m_start{};
|
s64 m_start{};
|
||||||
std::size_t m_index{}; // where i am in the array
|
s64 m_index{}; // where i am in the array
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sphaira::ui::menu::fileview
|
} // namespace sphaira::ui::menu::fileview
|
||||||
|
|||||||
@@ -93,9 +93,9 @@ struct FileAssocEntry {
|
|||||||
|
|
||||||
struct LastFile {
|
struct LastFile {
|
||||||
fs::FsPath name;
|
fs::FsPath name;
|
||||||
u64 index;
|
s64 index;
|
||||||
u64 offset;
|
float offset;
|
||||||
u64 entries_count;
|
s64 entries_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FsDirCollection {
|
struct FsDirCollection {
|
||||||
@@ -120,7 +120,7 @@ struct Menu final : MenuBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetIndex(std::size_t index);
|
void SetIndex(s64 index);
|
||||||
void InstallForwarder();
|
void InstallForwarder();
|
||||||
auto Scan(const fs::FsPath& new_path, bool is_walk_up = false) -> Result;
|
auto Scan(const fs::FsPath& new_path, bool is_walk_up = false) -> Result;
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ private:
|
|||||||
return GetNewPath(m_path, entry.name);
|
return GetNewPath(m_path, entry.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto GetNewPath(u64 index) const -> fs::FsPath {
|
auto GetNewPath(s64 index) const -> fs::FsPath {
|
||||||
return GetNewPath(m_path, GetEntry(index).name);
|
return GetNewPath(m_path, GetEntry(index).name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,9 +257,8 @@ private:
|
|||||||
// if it does, the index becomes that file.
|
// if it does, the index becomes that file.
|
||||||
std::vector<LastFile> m_previous_highlighted_file;
|
std::vector<LastFile> m_previous_highlighted_file;
|
||||||
fs::FsPath m_selected_path;
|
fs::FsPath m_selected_path;
|
||||||
std::size_t m_index{};
|
s64 m_index{};
|
||||||
std::size_t m_index_offset{};
|
s64 m_selected_count{};
|
||||||
std::size_t m_selected_count{};
|
|
||||||
SelectedType m_selected_type{SelectedType::None};
|
SelectedType m_selected_type{SelectedType::None};
|
||||||
|
|
||||||
option::OptionLong m_sort{INI_SECTION, "sort", SortType::SortType_Alphabetical};
|
option::OptionLong m_sort{INI_SECTION, "sort", SortType::SortType_Alphabetical};
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ struct Menu final : MenuBase {
|
|||||||
void OnFocusGained() override;
|
void OnFocusGained() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetIndex(std::size_t index);
|
void SetIndex(s64 index);
|
||||||
void Scan();
|
void Scan();
|
||||||
void LoadEntriesFromPath(const fs::FsPath& path);
|
void LoadEntriesFromPath(const fs::FsPath& path);
|
||||||
|
|
||||||
@@ -67,8 +67,8 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Entry> m_entries;
|
std::vector<Entry> m_entries;
|
||||||
std::size_t m_index{};
|
s64 m_index{};
|
||||||
std::size_t m_index_offset{};
|
s64 m_index_offset{};
|
||||||
std::unique_ptr<List> m_list;
|
std::unique_ptr<List> m_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ struct Menu final : MenuBase {
|
|||||||
void Draw(NVGcontext* vg, Theme* theme) override;
|
void Draw(NVGcontext* vg, Theme* theme) override;
|
||||||
void OnFocusGained() override;
|
void OnFocusGained() override;
|
||||||
|
|
||||||
void SetIndex(std::size_t index);
|
void SetIndex(s64 index);
|
||||||
void InstallHomebrew();
|
void InstallHomebrew();
|
||||||
void ScanHomebrew();
|
void ScanHomebrew();
|
||||||
void Sort();
|
void Sort();
|
||||||
@@ -51,13 +51,9 @@ private:
|
|||||||
static constexpr inline const char* INI_SECTION = "homebrew";
|
static constexpr inline const char* INI_SECTION = "homebrew";
|
||||||
|
|
||||||
std::vector<NroEntry> m_entries;
|
std::vector<NroEntry> m_entries;
|
||||||
std::size_t m_start{};
|
s64 m_index{}; // where i am in the array
|
||||||
std::size_t m_index{}; // where i am in the array
|
|
||||||
std::unique_ptr<List> m_list;
|
std::unique_ptr<List> m_list;
|
||||||
|
|
||||||
// todo: needed for scroll
|
|
||||||
float y_off = 0;
|
|
||||||
|
|
||||||
option::OptionLong m_sort{INI_SECTION, "sort", SortType::SortType_AlphabeticalStar};
|
option::OptionLong m_sort{INI_SECTION, "sort", SortType::SortType_AlphabeticalStar};
|
||||||
option::OptionLong m_order{INI_SECTION, "order", OrderType::OrderType_Decending};
|
option::OptionLong m_order{INI_SECTION, "order", OrderType::OrderType_Decending};
|
||||||
option::OptionBool m_hide_sphaira{INI_SECTION, "hide_sphaira", false};
|
option::OptionBool m_hide_sphaira{INI_SECTION, "hide_sphaira", false};
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ private:
|
|||||||
Rotation m_rotation{Rotation_90};
|
Rotation m_rotation{Rotation_90};
|
||||||
Colour m_colour{Colour_Grey};
|
Colour m_colour{Colour_Grey};
|
||||||
int m_image{};
|
int m_image{};
|
||||||
std::size_t m_index{};
|
s64 m_index{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sphaira::ui::menu::irs
|
} // namespace sphaira::ui::menu::irs
|
||||||
|
|||||||
@@ -34,8 +34,7 @@ struct MainMenu final : Widget {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void OnLRPress(std::shared_ptr<MenuBase> menu, Button b);
|
void OnLRPress(std::shared_ptr<MenuBase> menu, Button b);
|
||||||
void AddOnLPress();
|
void AddOnLRPress();
|
||||||
void AddOnRPress();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<homebrew::Menu> m_homebrew_menu{};
|
std::shared_ptr<homebrew::Menu> m_homebrew_menu{};
|
||||||
|
|||||||
@@ -165,11 +165,10 @@ struct Menu final : MenuBase {
|
|||||||
void Draw(NVGcontext* vg, Theme* theme) override;
|
void Draw(NVGcontext* vg, Theme* theme) override;
|
||||||
void OnFocusGained() override;
|
void OnFocusGained() override;
|
||||||
|
|
||||||
void SetIndex(std::size_t index) {
|
void SetIndex(s64 index) {
|
||||||
m_index = index;
|
m_index = index;
|
||||||
|
if (!m_index) {
|
||||||
if (m_index > m_start && m_index - m_start >= 6) {
|
m_list->SetYoff(0);
|
||||||
m_start = m_index/3*3 - 3;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,13 +184,12 @@ private:
|
|||||||
static constexpr inline u32 MAX_ON_PAGE = 16; // same as website
|
static constexpr inline u32 MAX_ON_PAGE = 16; // same as website
|
||||||
|
|
||||||
std::vector<PageEntry> m_pages;
|
std::vector<PageEntry> m_pages;
|
||||||
std::size_t m_page_index{};
|
s64 m_page_index{};
|
||||||
std::size_t m_page_index_max{1};
|
s64 m_page_index_max{1};
|
||||||
|
|
||||||
std::string m_search{};
|
std::string m_search{};
|
||||||
|
|
||||||
std::size_t m_start{};
|
s64 m_index{}; // where i am in the array
|
||||||
std::size_t m_index{}; // where i am in the array
|
|
||||||
std::unique_ptr<List> m_list;
|
std::unique_ptr<List> m_list;
|
||||||
|
|
||||||
// options
|
// options
|
||||||
|
|||||||
@@ -84,6 +84,9 @@ auto getButton(Button button) -> const char*;
|
|||||||
void drawScrollbar(NVGcontext* vg, Theme* theme, u32 index_off, u32 count, u32 max_per_page);
|
void drawScrollbar(NVGcontext* vg, Theme* theme, u32 index_off, u32 count, u32 max_per_page);
|
||||||
void drawScrollbar(NVGcontext* vg, Theme* theme, float x, float y, float h, u32 index_off, u32 count, u32 max_per_page);
|
void drawScrollbar(NVGcontext* vg, Theme* theme, float x, float y, float h, u32 index_off, u32 count, u32 max_per_page);
|
||||||
|
|
||||||
|
void drawScrollbar2(NVGcontext* vg, Theme* theme, float x, float y, float h, s64 index_off, s64 count, s64 row, s64 page);
|
||||||
|
void drawScrollbar2(NVGcontext* vg, Theme* theme, s64 index_off, s64 count, s64 row, s64 page);
|
||||||
|
|
||||||
void updateHighlightAnimation();
|
void updateHighlightAnimation();
|
||||||
void getHighlightAnimation(float* gradientX, float* gradientY, float* color);
|
void getHighlightAnimation(float* gradientX, float* gradientY, float* color);
|
||||||
|
|
||||||
|
|||||||
@@ -27,16 +27,16 @@ private:
|
|||||||
// todo: support upto 4 options.
|
// todo: support upto 4 options.
|
||||||
class OptionBox final : public Widget {
|
class OptionBox final : public Widget {
|
||||||
public:
|
public:
|
||||||
using Callback = std::function<void(std::optional<std::size_t> index)>;
|
using Callback = std::function<void(std::optional<s64> index)>;
|
||||||
using Option = std::string;
|
using Option = std::string;
|
||||||
using Options = std::vector<Option>;
|
using Options = std::vector<Option>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OptionBox(const std::string& message, const Option& a, Callback cb = [](auto){}); // confirm
|
OptionBox(const std::string& message, const Option& a, Callback cb = [](auto){}); // confirm
|
||||||
OptionBox(const std::string& message, const Option& a, const Option& b, Callback cb); // yesno
|
OptionBox(const std::string& message, const Option& a, const Option& b, Callback cb); // yesno
|
||||||
OptionBox(const std::string& message, const Option& a, const Option& b, std::size_t index, Callback cb); // yesno
|
OptionBox(const std::string& message, const Option& a, const Option& b, s64 index, Callback cb); // yesno
|
||||||
OptionBox(const std::string& message, const Option& a, const Option& b, const Option& c, Callback cb); // tri
|
OptionBox(const std::string& message, const Option& a, const Option& b, const Option& c, Callback cb); // tri
|
||||||
OptionBox(const std::string& message, const Option& a, const Option& b, const Option& c, std::size_t index, Callback cb); // tri
|
OptionBox(const std::string& message, const Option& a, const Option& b, const Option& c, s64 index, Callback cb); // tri
|
||||||
|
|
||||||
auto Update(Controller* controller, TouchInfo* touch) -> void override;
|
auto Update(Controller* controller, TouchInfo* touch) -> void override;
|
||||||
auto Draw(NVGcontext* vg, Theme* theme) -> void override;
|
auto Draw(NVGcontext* vg, Theme* theme) -> void override;
|
||||||
@@ -44,8 +44,8 @@ public:
|
|||||||
auto OnFocusLost() noexcept -> void override;
|
auto OnFocusLost() noexcept -> void override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
auto Setup(std::size_t index) -> void; // common setup values
|
auto Setup(s64 index) -> void; // common setup values
|
||||||
void SetIndex(std::size_t index);
|
void SetIndex(s64 index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_message;
|
std::string m_message;
|
||||||
@@ -53,7 +53,7 @@ private:
|
|||||||
|
|
||||||
Vec4 m_spacer_line{};
|
Vec4 m_spacer_line{};
|
||||||
|
|
||||||
std::size_t m_index{};
|
s64 m_index{};
|
||||||
std::vector<OptionBoxEntry> m_entries;
|
std::vector<OptionBoxEntry> m_entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,14 +9,14 @@ namespace sphaira::ui {
|
|||||||
class PopupList final : public Widget {
|
class PopupList final : public Widget {
|
||||||
public:
|
public:
|
||||||
using Items = std::vector<std::string>;
|
using Items = std::vector<std::string>;
|
||||||
using Callback = std::function<void(std::optional<std::size_t>)>;
|
using Callback = std::function<void(std::optional<s64>)>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit PopupList(std::string title, Items items, Callback cb, std::size_t index = 0);
|
explicit PopupList(std::string title, Items items, Callback cb, s64 index = 0);
|
||||||
PopupList(std::string title, Items items, Callback cb, std::string index);
|
PopupList(std::string title, Items items, Callback cb, std::string index);
|
||||||
PopupList(std::string title, Items items, std::string& index_str_ref, std::size_t& index);
|
PopupList(std::string title, Items items, std::string& index_str_ref, s64& index);
|
||||||
PopupList(std::string title, Items items, std::string& index_ref);
|
PopupList(std::string title, Items items, std::string& index_ref);
|
||||||
PopupList(std::string title, Items items, std::size_t& index_ref);
|
PopupList(std::string title, Items items, s64& index_ref);
|
||||||
|
|
||||||
auto Update(Controller* controller, TouchInfo* touch) -> void override;
|
auto Update(Controller* controller, TouchInfo* touch) -> void override;
|
||||||
auto Draw(NVGcontext* vg, Theme* theme) -> void override;
|
auto Draw(NVGcontext* vg, Theme* theme) -> void override;
|
||||||
@@ -24,7 +24,7 @@ public:
|
|||||||
auto OnFocusLost() noexcept -> void override;
|
auto OnFocusLost() noexcept -> void override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetIndex(std::size_t index);
|
void SetIndex(s64 index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr Vec2 m_title_pos{70.f, 28.f};
|
static constexpr Vec2 m_title_pos{70.f, 28.f};
|
||||||
@@ -35,8 +35,8 @@ private:
|
|||||||
std::string m_title;
|
std::string m_title;
|
||||||
Items m_items;
|
Items m_items;
|
||||||
Callback m_callback;
|
Callback m_callback;
|
||||||
std::size_t m_index; // index in list array
|
s64 m_index; // index in list array
|
||||||
std::size_t m_index_offset{}; // drawing from array start
|
s64 m_index_offset{}; // drawing from array start
|
||||||
|
|
||||||
std::unique_ptr<List> m_list;
|
std::unique_ptr<List> m_list;
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ struct ProgressBox final : Widget {
|
|||||||
auto Draw(NVGcontext* vg, Theme* theme) -> void override;
|
auto Draw(NVGcontext* vg, Theme* theme) -> void override;
|
||||||
|
|
||||||
auto NewTransfer(const std::string& transfer) -> ProgressBox&;
|
auto NewTransfer(const std::string& transfer) -> ProgressBox&;
|
||||||
auto UpdateTransfer(u64 offset, u64 size) -> ProgressBox&;
|
auto UpdateTransfer(s64 offset, s64 size) -> ProgressBox&;
|
||||||
void RequestExit();
|
void RequestExit();
|
||||||
auto ShouldExit() -> bool;
|
auto ShouldExit() -> bool;
|
||||||
|
|
||||||
@@ -55,8 +55,8 @@ private:
|
|||||||
ProgressBoxDoneCallback m_done{};
|
ProgressBoxDoneCallback m_done{};
|
||||||
std::string m_title{};
|
std::string m_title{};
|
||||||
std::string m_transfer{};
|
std::string m_transfer{};
|
||||||
u64 m_size{};
|
s64 m_size{};
|
||||||
u64 m_offset{};
|
s64 m_offset{};
|
||||||
bool m_exit_requested{};
|
bool m_exit_requested{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -50,10 +50,10 @@ class SidebarEntryArray final : public SidebarEntryBase {
|
|||||||
public:
|
public:
|
||||||
using Items = std::vector<std::string>;
|
using Items = std::vector<std::string>;
|
||||||
using ListCallback = std::function<void()>;
|
using ListCallback = std::function<void()>;
|
||||||
using Callback = std::function<void(std::size_t& index)>;
|
using Callback = std::function<void(s64& index)>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SidebarEntryArray(std::string title, Items items, Callback cb, std::size_t index = 0);
|
explicit SidebarEntryArray(std::string title, Items items, Callback cb, s64 index = 0);
|
||||||
SidebarEntryArray(std::string title, Items items, Callback cb, std::string index);
|
SidebarEntryArray(std::string title, Items items, Callback cb, std::string index);
|
||||||
SidebarEntryArray(std::string title, Items items, std::string& index);
|
SidebarEntryArray(std::string title, Items items, std::string& index);
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ private:
|
|||||||
Items m_items;
|
Items m_items;
|
||||||
ListCallback m_list_callback;
|
ListCallback m_list_callback;
|
||||||
Callback m_callback;
|
Callback m_callback;
|
||||||
std::size_t m_index;
|
s64 m_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -108,15 +108,16 @@ public:
|
|||||||
void Add(std::shared_ptr<SidebarEntryBase> entry);
|
void Add(std::shared_ptr<SidebarEntryBase> entry);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetIndex(std::size_t index);
|
void SetIndex(s64 index);
|
||||||
|
void SetupButtons();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_title;
|
std::string m_title;
|
||||||
std::string m_sub;
|
std::string m_sub;
|
||||||
Side m_side;
|
Side m_side;
|
||||||
Items m_items;
|
Items m_items;
|
||||||
std::size_t m_index{};
|
s64 m_index{};
|
||||||
std::size_t m_index_offset{};
|
s64 m_index_offset{};
|
||||||
|
|
||||||
std::unique_ptr<List> m_list;
|
std::unique_ptr<List> m_list;
|
||||||
|
|
||||||
|
|||||||
@@ -220,6 +220,7 @@ struct TouchInfo {
|
|||||||
bool is_tap;
|
bool is_tap;
|
||||||
bool is_scroll;
|
bool is_scroll;
|
||||||
bool is_clicked;
|
bool is_clicked;
|
||||||
|
bool is_end;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Button : u64 {
|
enum class Button : u64 {
|
||||||
|
|||||||
@@ -72,13 +72,14 @@ struct Widget : public Object {
|
|||||||
return m_pop;
|
return m_pop;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto GetUiButtons() const -> uiButtons;
|
auto SetUiButtonPos(Vec2 pos) {
|
||||||
static auto GetUiButtons(const Actions& actions, float x = 1220, float y = 675) -> uiButtons;
|
m_button_pos = pos;
|
||||||
|
}
|
||||||
|
|
||||||
static auto ScrollHelperDown(u64& index, u64& start, u64 step, s64 row, s64 page, u64 size) -> bool;
|
auto GetUiButtons() const -> uiButtons;
|
||||||
static auto ScrollHelperUp(u64& index, u64& start, s64 step, s64 row, s64 page, s64 size) -> bool;
|
|
||||||
|
|
||||||
Actions m_actions;
|
Actions m_actions;
|
||||||
|
Vec2 m_button_pos{1220, 675};
|
||||||
bool m_focus{false};
|
bool m_focus{false};
|
||||||
bool m_pop{false};
|
bool m_pop{false};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -391,12 +391,12 @@ auto App::GetThemeMetaList() -> std::span<ThemeMeta> {
|
|||||||
return g_app->m_theme_meta_entries;
|
return g_app->m_theme_meta_entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::SetTheme(u64 theme_index) {
|
void App::SetTheme(s64 theme_index) {
|
||||||
g_app->LoadTheme(g_app->m_theme_meta_entries[theme_index].ini_path.c_str());
|
g_app->LoadTheme(g_app->m_theme_meta_entries[theme_index].ini_path.c_str());
|
||||||
g_app->m_theme_index = theme_index;
|
g_app->m_theme_index = theme_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto App::GetThemeIndex() -> u64 {
|
auto App::GetThemeIndex() -> s64 {
|
||||||
return g_app->m_theme_index;
|
return g_app->m_theme_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -723,6 +723,8 @@ void App::Poll() {
|
|||||||
m_touch_info.is_scroll = false;
|
m_touch_info.is_scroll = false;
|
||||||
if (m_touch_info.is_tap) {
|
if (m_touch_info.is_tap) {
|
||||||
m_touch_info.is_clicked = true;
|
m_touch_info.is_clicked = true;
|
||||||
|
} else {
|
||||||
|
m_touch_info.is_end = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ Mutex g_mutex_share[CURL_LOCK_DATA_LAST]{};
|
|||||||
|
|
||||||
struct DataStruct {
|
struct DataStruct {
|
||||||
std::vector<u8> data;
|
std::vector<u8> data;
|
||||||
u64 offset{};
|
s64 offset{};
|
||||||
FsFile f{};
|
FsFile f{};
|
||||||
s64 file_offset{};
|
s64 file_offset{};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,25 +1,45 @@
|
|||||||
#include "ui/list.hpp"
|
#include "ui/list.hpp"
|
||||||
|
#include "ui/nvg_util.hpp"
|
||||||
|
#include "app.hpp"
|
||||||
|
#include "log.hpp"
|
||||||
|
|
||||||
namespace sphaira::ui {
|
namespace sphaira::ui {
|
||||||
|
|
||||||
List::List(const Vec4& pos, const Vec4& v, const Vec2& pad)
|
List::List(s64 row, s64 page, const Vec4& pos, const Vec4& v, const Vec2& pad)
|
||||||
: m_v{v}
|
: m_row{row}
|
||||||
|
, m_page{page}
|
||||||
|
, m_v{v}
|
||||||
, m_pad{pad} {
|
, m_pad{pad} {
|
||||||
m_pos = pos;
|
m_pos = pos;
|
||||||
|
SetScrollBarPos(SCREEN_WIDTH - 50, 100, SCREEN_HEIGHT-200);
|
||||||
}
|
}
|
||||||
|
|
||||||
void List::Do(NVGcontext* vg, Theme* theme, u64 index, u64 count, Callback callback, float y_off) const {
|
auto List::ClampY(float y, s64 count) const -> float {
|
||||||
|
float y_max = 0;
|
||||||
|
|
||||||
|
if (count >= m_page) {
|
||||||
|
// round up
|
||||||
|
if (count % m_row) {
|
||||||
|
count = count + (m_row - count % m_row);
|
||||||
|
}
|
||||||
|
y_max = (count - m_page) / m_row * GetMaxY();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y < 0) {
|
||||||
|
y = 0;
|
||||||
|
} else if (y > y_max) {
|
||||||
|
y = y_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void List::OnUpdate(Controller* controller, TouchInfo* touch, s64 count, TouchCallback callback) {
|
||||||
|
if (touch->is_clicked && touch->in_range(GetPos())) {
|
||||||
auto v = m_v;
|
auto v = m_v;
|
||||||
|
v.y -= ClampY(m_yoff + m_y_prog, count);
|
||||||
|
|
||||||
if (vg) {
|
for (s64 i = 0; i < count; v.y += v.h + m_pad.y) {
|
||||||
nvgSave(vg);
|
|
||||||
nvgScissor(vg, GetX(), GetY(), GetW(), GetH());
|
|
||||||
}
|
|
||||||
|
|
||||||
// index = (y_off / (v.h + m_pad.y)) / (GetW() / (v.w + m_pad.x));
|
|
||||||
// v.y -= y_off;
|
|
||||||
|
|
||||||
for (u64 i = index; i < count; v.y += v.h + m_pad.y) {
|
|
||||||
if (v.y > GetY() + GetH()) {
|
if (v.y > GetY() + GetH()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -32,24 +52,138 @@ void List::Do(NVGcontext* vg, Theme* theme, u64 index, u64 count, Callback callb
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec4 vv = v;
|
// skip anything not visible
|
||||||
// if not drawing, only return clipped v as its used for touch
|
if (v.y + v.h < GetY()) {
|
||||||
if (!vg) {
|
continue;
|
||||||
vv.w = std::min(v.x + v.w, m_pos.x + m_pos.w) - v.x;
|
|
||||||
vv.h = std::min(v.y + v.h, m_pos.y + m_pos.h) - v.y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!callback(vg, theme, vv, i)) {
|
Vec4 vv = v;
|
||||||
|
// if not drawing, only return clipped v as its used for touch
|
||||||
|
vv.w = std::min(v.x + v.w, m_pos.x + m_pos.w) - v.x;
|
||||||
|
vv.h = std::min(v.y + v.h, m_pos.y + m_pos.h) - v.y;
|
||||||
|
|
||||||
|
if (touch->in_range(vv)) {
|
||||||
|
callback(i);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v.x = x;
|
v.x = x;
|
||||||
}
|
}
|
||||||
|
} else if (touch->is_scroll && touch->in_range(GetPos())) {
|
||||||
|
m_y_prog = (float)touch->initial.y - (float)touch->cur.y;
|
||||||
|
} else if (touch->is_end) {
|
||||||
|
m_yoff = ClampY(m_yoff + m_y_prog, count);
|
||||||
|
m_y_prog = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void List::Draw(NVGcontext* vg, Theme* theme, s64 count, Callback callback) const {
|
||||||
|
const auto yoff = ClampY(m_yoff + m_y_prog, count);
|
||||||
|
const s64 start = yoff / GetMaxY() * m_row;
|
||||||
|
gfx::drawScrollbar2(vg, theme, m_scrollbar.x, m_scrollbar.y, m_scrollbar.h, start, count, m_row, m_page);
|
||||||
|
|
||||||
|
auto v = m_v;
|
||||||
|
v.y -= yoff;
|
||||||
|
|
||||||
|
nvgSave(vg);
|
||||||
|
nvgScissor(vg, GetX(), GetY(), GetW(), GetH());
|
||||||
|
|
||||||
|
for (s64 i = 0; i < count; v.y += v.h + m_pad.y) {
|
||||||
|
if (v.y > GetY() + GetH()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto x = v.x;
|
||||||
|
|
||||||
|
for (; i < count; i++, v.x += v.w + m_pad.x) {
|
||||||
|
// only draw if full x is in bounds
|
||||||
|
if (v.x + v.w > GetX() + GetW()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip anything not visible
|
||||||
|
if (v.y + v.h < GetY()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(vg, theme, v, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
v.x = x;
|
||||||
|
}
|
||||||
|
|
||||||
if (vg) {
|
|
||||||
nvgRestore(vg);
|
nvgRestore(vg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto List::ScrollDown(s64& index, s64 step, s64 count) -> bool {
|
||||||
|
const auto old_index = index;
|
||||||
|
|
||||||
|
if (!count) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index + step < count) {
|
||||||
|
index += step;
|
||||||
|
} else {
|
||||||
|
index = count - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index != old_index) {
|
||||||
|
App::PlaySoundEffect(SoundEffect_Scroll);
|
||||||
|
s64 delta = index - old_index;
|
||||||
|
s64 start = m_yoff / GetMaxY() * m_row;
|
||||||
|
|
||||||
|
while (index < start) {
|
||||||
|
start -= m_row;
|
||||||
|
m_yoff -= GetMaxY();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index - start >= m_page) {
|
||||||
|
do {
|
||||||
|
start += m_row;
|
||||||
|
delta -= m_row;
|
||||||
|
m_yoff += GetMaxY();
|
||||||
|
} while (delta > 0 && start + m_page < count);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto List::ScrollUp(s64& index, s64 step, s64 count) -> bool {
|
||||||
|
const auto old_index = index;
|
||||||
|
|
||||||
|
if (!count) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index >= step) {
|
||||||
|
index -= step;
|
||||||
|
} else {
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index != old_index) {
|
||||||
|
App::PlaySoundEffect(SoundEffect_Scroll);
|
||||||
|
s64 start = m_yoff / GetMaxY() * m_row;
|
||||||
|
|
||||||
|
while (index < start) {
|
||||||
|
start -= m_row;
|
||||||
|
m_yoff -= GetMaxY();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (index - start >= m_page && start + m_page < count) {
|
||||||
|
start += m_row;
|
||||||
|
m_yoff += GetMaxY();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sphaira::ui
|
} // namespace sphaira::ui
|
||||||
|
|||||||
@@ -856,7 +856,7 @@ void EntryMenu::UpdateOptions() {
|
|||||||
SetIndex(0);
|
SetIndex(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntryMenu::SetIndex(std::size_t index) {
|
void EntryMenu::SetIndex(s64 index) {
|
||||||
m_index = index;
|
m_index = index;
|
||||||
const auto option = m_options[m_index];
|
const auto option = m_options[m_index];
|
||||||
if (option.confirm_text.empty()) {
|
if (option.confirm_text.empty()) {
|
||||||
@@ -908,22 +908,22 @@ Menu::Menu(const std::vector<NroEntry>& nro_entries) : MenuBase{"AppStore"_i18n}
|
|||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::DOWN, Action{[this](){
|
std::make_pair(Button::DOWN, Action{[this](){
|
||||||
if (ScrollHelperDown(m_index, m_start, 3, 3, 9, m_entries_current.size())) {
|
if (m_list->ScrollDown(m_index, 3, m_entries_current.size())) {
|
||||||
SetIndex(m_index);
|
SetIndex(m_index);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::UP, Action{[this](){
|
std::make_pair(Button::UP, Action{[this](){
|
||||||
if (ScrollHelperUp(m_index, m_start, 3, 3, 9, m_entries_current.size())) {
|
if (m_list->ScrollUp(m_index, 3, m_entries_current.size())) {
|
||||||
SetIndex(m_index);
|
SetIndex(m_index);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::R2, Action{[this](){
|
std::make_pair(Button::R2, Action{[this](){
|
||||||
if (ScrollHelperDown(m_index, m_start, 9, 3, 9, m_entries_current.size())) {
|
if (m_list->ScrollDown(m_index, 9, m_entries_current.size())) {
|
||||||
SetIndex(m_index);
|
SetIndex(m_index);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::L2, Action{[this](){
|
std::make_pair(Button::L2, Action{[this](){
|
||||||
if (ScrollHelperUp(m_index, m_start, 9, 3, 9, m_entries_current.size())) {
|
if (m_list->ScrollUp(m_index, 9, m_entries_current.size())) {
|
||||||
SetIndex(m_index);
|
SetIndex(m_index);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
@@ -958,17 +958,17 @@ Menu::Menu(const std::vector<NroEntry>& nro_entries) : MenuBase{"AppStore"_i18n}
|
|||||||
order_items.push_back("Decending"_i18n);
|
order_items.push_back("Decending"_i18n);
|
||||||
order_items.push_back("Ascending"_i18n);
|
order_items.push_back("Ascending"_i18n);
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryArray>("Filter"_i18n, filter_items, [this, filter_items](std::size_t& index_out){
|
options->Add(std::make_shared<SidebarEntryArray>("Filter"_i18n, filter_items, [this, filter_items](s64& index_out){
|
||||||
SetFilter((Filter)index_out);
|
SetFilter((Filter)index_out);
|
||||||
}, (std::size_t)m_filter));
|
}, (s64)m_filter));
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryArray>("Sort"_i18n, sort_items, [this, sort_items](std::size_t& index_out){
|
options->Add(std::make_shared<SidebarEntryArray>("Sort"_i18n, sort_items, [this, sort_items](s64& index_out){
|
||||||
SetSort((SortType)index_out);
|
SetSort((SortType)index_out);
|
||||||
}, (std::size_t)m_sort));
|
}, (s64)m_sort));
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryArray>("Order"_i18n, order_items, [this, order_items](std::size_t& index_out){
|
options->Add(std::make_shared<SidebarEntryArray>("Order"_i18n, order_items, [this, order_items](s64& index_out){
|
||||||
SetOrder((OrderType)index_out);
|
SetOrder((OrderType)index_out);
|
||||||
}, (std::size_t)m_order));
|
}, (s64)m_order));
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryCallback>("Search"_i18n, [this](){
|
options->Add(std::make_shared<SidebarEntryCallback>("Search"_i18n, [this](){
|
||||||
std::string out;
|
std::string out;
|
||||||
@@ -1003,7 +1003,7 @@ Menu::Menu(const std::vector<NroEntry>& nro_entries) : MenuBase{"AppStore"_i18n}
|
|||||||
|
|
||||||
const Vec4 v{75, 110, 370, 155};
|
const Vec4 v{75, 110, 370, 155};
|
||||||
const Vec2 pad{10, 10};
|
const Vec2 pad{10, 10};
|
||||||
m_list = std::make_unique<List>(m_pos, v, pad);
|
m_list = std::make_unique<List>(3, 9, m_pos, v, pad);
|
||||||
Sort();
|
Sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1013,19 +1013,13 @@ Menu::~Menu() {
|
|||||||
|
|
||||||
void Menu::Update(Controller* controller, TouchInfo* touch) {
|
void Menu::Update(Controller* controller, TouchInfo* touch) {
|
||||||
MenuBase::Update(controller, touch);
|
MenuBase::Update(controller, touch);
|
||||||
|
m_list->OnUpdate(controller, touch, m_entries_current.size(), [this](auto i) {
|
||||||
m_list->Do(m_start, m_entries_current.size(), [this, &touch](auto* vg, auto* theme, auto v, auto pos) {
|
if (m_index == i) {
|
||||||
if (touch->is_clicked && touch->in_range(v)) {
|
|
||||||
if (pos == m_index) {
|
|
||||||
FireAction(Button::A);
|
FireAction(Button::A);
|
||||||
} else {
|
} else {
|
||||||
App::PlaySoundEffect(SoundEffect_Focus);
|
App::PlaySoundEffect(SoundEffect_Focus);
|
||||||
SetIndex(pos);
|
SetIndex(i);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1042,14 +1036,11 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// only draw scrollbar if needed
|
|
||||||
gfx::drawScrollbar(vg, theme, m_start, m_entries_current.size(), 9);
|
|
||||||
|
|
||||||
// max images per frame, in order to not hit io / gpu too hard.
|
// max images per frame, in order to not hit io / gpu too hard.
|
||||||
const int image_load_max = 2;
|
const int image_load_max = 2;
|
||||||
int image_load_count = 0;
|
int image_load_count = 0;
|
||||||
|
|
||||||
m_list->Do(vg, theme, m_start, m_entries_current.size(), [this, &image_load_count](auto* vg, auto* theme, auto v, auto pos) {
|
m_list->Draw(vg, theme, m_entries_current.size(), [this, &image_load_count](auto* vg, auto* theme, auto v, auto pos) {
|
||||||
const auto& [x, y, w, h] = v;
|
const auto& [x, y, w, h] = v;
|
||||||
const auto index = m_entries_current[pos];
|
const auto index = m_entries_current[pos];
|
||||||
auto& e = m_entries[index];
|
auto& e = m_entries[index];
|
||||||
@@ -1121,9 +1112,8 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
DrawIcon(vg, e.image, m_default_image, x + 20, y + 20, 115, 115, true, image_scale);
|
DrawIcon(vg, e.image, m_default_image, x + 20, y + 20, 115, 115, true, image_scale);
|
||||||
// gfx::drawImage(vg, x + 20, y + 20, image_size, image_size_h, image.image ? image.image : m_default_image);
|
// gfx::drawImage(vg, x + 20, y + 20, image_size, image_size_h, image.image ? image.image : m_default_image);
|
||||||
|
|
||||||
const auto clip_y = std::min(GetY() + GetH(), y + h) - y;
|
|
||||||
nvgSave(vg);
|
nvgSave(vg);
|
||||||
nvgScissor(vg, v.x, v.y, w - 30.f, clip_y); // clip
|
nvgIntersectScissor(vg, v.x, v.y, w - 30.f, h); // clip
|
||||||
{
|
{
|
||||||
const float font_size = 18;
|
const float font_size = 18;
|
||||||
gfx::drawTextArgs(vg, x + 148, y + 45, font_size, NVG_ALIGN_LEFT, theme->elements[text_id].colour, e.title.c_str());
|
gfx::drawTextArgs(vg, x + 148, y + 45, font_size, NVG_ALIGN_LEFT, theme->elements[text_id].colour, e.title.c_str());
|
||||||
@@ -1147,8 +1137,6 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
gfx::drawImageRounded(vg, x + w - 30.f, y + 110, i_size, i_size, m_update.image);
|
gfx::drawImageRounded(vg, x + w - 30.f, y + 110, i_size, i_size, m_update.image);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1178,21 +1166,16 @@ void Menu::OnFocusGained() {
|
|||||||
if (m_dirty) {
|
if (m_dirty) {
|
||||||
m_dirty = false;
|
m_dirty = false;
|
||||||
const auto& current_entry = m_entries[m_entries_current[m_index]];
|
const auto& current_entry = m_entries[m_entries_current[m_index]];
|
||||||
// m_start = 0;
|
|
||||||
// m_index = 0;
|
|
||||||
log_write("\nold index: %zu start: %zu\n", m_index, m_start);
|
|
||||||
// old index: 19 start: 12
|
|
||||||
Sort();
|
Sort();
|
||||||
|
|
||||||
for (u32 i = 0; i < m_entries_current.size(); i++) {
|
for (u32 i = 0; i < m_entries_current.size(); i++) {
|
||||||
if (current_entry.name == m_entries[m_entries_current[i]].name) {
|
if (current_entry.name == m_entries[m_entries_current[i]].name) {
|
||||||
SetIndex(i);
|
SetIndex(i);
|
||||||
if (i >= 9) {
|
if (i >= 9) {
|
||||||
m_start = (i - 9) / 3 * 3 + 3;
|
m_list->SetYoff((((i - 9) + 3) / 3) * m_list->GetMaxY());
|
||||||
} else {
|
} else {
|
||||||
m_start = 0;
|
m_list->SetYoff(0);
|
||||||
}
|
}
|
||||||
log_write("\nnew index: %zu start: %zu\n", m_index, m_start);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1200,14 +1183,10 @@ void Menu::OnFocusGained() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::SetIndex(std::size_t index) {
|
void Menu::SetIndex(s64 index) {
|
||||||
m_index = index;
|
m_index = index;
|
||||||
if (!m_index) {
|
if (!m_index) {
|
||||||
m_start = 0;
|
m_list->SetYoff(0);
|
||||||
}
|
|
||||||
|
|
||||||
if (m_index > m_start && m_index - m_start >= 9) {
|
|
||||||
m_start = m_index/3*3 - 6;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this->SetSubHeading(std::to_string(m_index + 1) + " / " + std::to_string(m_entries_current.size()));
|
this->SetSubHeading(std::to_string(m_index + 1) + " / " + std::to_string(m_entries_current.size()));
|
||||||
@@ -1402,9 +1381,10 @@ void Menu::SetSearch(const std::string& term) {
|
|||||||
SetFilter(m_filter);
|
SetFilter(m_filter);
|
||||||
SetIndex(m_entry_search_jump_back);
|
SetIndex(m_entry_search_jump_back);
|
||||||
if (m_entry_search_jump_back >= 9) {
|
if (m_entry_search_jump_back >= 9) {
|
||||||
m_start = (m_entry_search_jump_back - 9) / 3 * 3 + 3;
|
m_list->SetYoff(0);
|
||||||
|
m_list->SetYoff((((m_entry_search_jump_back - 9) + 3) / 3) * m_list->GetMaxY());
|
||||||
} else {
|
} else {
|
||||||
m_start = 0;
|
m_list->SetYoff(0);
|
||||||
}
|
}
|
||||||
}});
|
}});
|
||||||
|
|
||||||
@@ -1435,11 +1415,12 @@ void Menu::SetAuthor() {
|
|||||||
} else {
|
} else {
|
||||||
SetFilter(m_filter);
|
SetFilter(m_filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetIndex(m_entry_author_jump_back);
|
SetIndex(m_entry_author_jump_back);
|
||||||
if (m_entry_author_jump_back >= 9) {
|
if (m_entry_author_jump_back >= 9) {
|
||||||
m_start = (m_entry_author_jump_back - 9) / 3 * 3 + 3;
|
m_list->SetYoff((((m_entry_author_jump_back - 9) + 3) / 3) * m_list->GetMaxY());
|
||||||
} else {
|
} else {
|
||||||
m_start = 0;
|
m_list->SetYoff(0);
|
||||||
}
|
}
|
||||||
}});
|
}});
|
||||||
|
|
||||||
|
|||||||
@@ -246,22 +246,22 @@ Menu::Menu(const std::vector<NroEntry>& nro_entries) : MenuBase{"FileBrowser"_i1
|
|||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::DOWN, Action{[this](){
|
std::make_pair(Button::DOWN, Action{[this](){
|
||||||
if (ScrollHelperDown(m_index, m_index_offset, 1, 1, 8, m_entries_current.size())) {
|
if (m_list->ScrollDown(m_index, 1, m_entries_current.size())) {
|
||||||
SetIndex(m_index);
|
SetIndex(m_index);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::UP, Action{[this](){
|
std::make_pair(Button::UP, Action{[this](){
|
||||||
if (ScrollHelperUp(m_index, m_index_offset, 1, 1, 8, m_entries_current.size())) {
|
if (m_list->ScrollUp(m_index, 1, m_entries_current.size())) {
|
||||||
SetIndex(m_index);
|
SetIndex(m_index);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::DPAD_RIGHT, Action{[this](){
|
std::make_pair(Button::DPAD_RIGHT, Action{[this](){
|
||||||
if (ScrollHelperDown(m_index, m_index_offset, 8, 1, 8, m_entries_current.size())) {
|
if (m_list->ScrollDown(m_index, 8, m_entries_current.size())) {
|
||||||
SetIndex(m_index);
|
SetIndex(m_index);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::DPAD_LEFT, Action{[this](){
|
std::make_pair(Button::DPAD_LEFT, Action{[this](){
|
||||||
if (ScrollHelperUp(m_index, m_index_offset, 8, 1, 8, m_entries_current.size())) {
|
if (m_list->ScrollUp(m_index, 8, m_entries_current.size())) {
|
||||||
SetIndex(m_index);
|
SetIndex(m_index);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
@@ -355,12 +355,12 @@ Menu::Menu(const std::vector<NroEntry>& nro_entries) : MenuBase{"FileBrowser"_i1
|
|||||||
order_items.push_back("Decending"_i18n);
|
order_items.push_back("Decending"_i18n);
|
||||||
order_items.push_back("Ascending"_i18n);
|
order_items.push_back("Ascending"_i18n);
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryArray>("Sort"_i18n, sort_items, [this](std::size_t& index_out){
|
options->Add(std::make_shared<SidebarEntryArray>("Sort"_i18n, sort_items, [this](s64& index_out){
|
||||||
m_sort.Set(index_out);
|
m_sort.Set(index_out);
|
||||||
SortAndFindLastFile();
|
SortAndFindLastFile();
|
||||||
}, m_sort.Get()));
|
}, m_sort.Get()));
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryArray>("Order"_i18n, order_items, [this](std::size_t& index_out){
|
options->Add(std::make_shared<SidebarEntryArray>("Order"_i18n, order_items, [this](s64& index_out){
|
||||||
m_order.Set(index_out);
|
m_order.Set(index_out);
|
||||||
SortAndFindLastFile();
|
SortAndFindLastFile();
|
||||||
}, m_order.Get()));
|
}, m_order.Get()));
|
||||||
@@ -542,7 +542,7 @@ Menu::Menu(const std::vector<NroEntry>& nro_entries) : MenuBase{"FileBrowser"_i1
|
|||||||
mount_items.push_back("Image System memory"_i18n);
|
mount_items.push_back("Image System memory"_i18n);
|
||||||
mount_items.push_back("Image microSD card"_i18n);
|
mount_items.push_back("Image microSD card"_i18n);
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryArray>("Mount"_i18n, mount_items, [this](std::size_t& index_out){
|
options->Add(std::make_shared<SidebarEntryArray>("Mount"_i18n, mount_items, [this](s64& index_out){
|
||||||
App::PopToMenu();
|
App::PopToMenu();
|
||||||
m_mount.Set(index_out);
|
m_mount.Set(index_out);
|
||||||
SetFs("/", index_out);
|
SetFs("/", index_out);
|
||||||
@@ -552,7 +552,7 @@ Menu::Menu(const std::vector<NroEntry>& nro_entries) : MenuBase{"FileBrowser"_i1
|
|||||||
);
|
);
|
||||||
|
|
||||||
const Vec4 v{75, GetY() + 1.f + 42.f, 1220.f-45.f*2, 60};
|
const Vec4 v{75, GetY() + 1.f + 42.f, 1220.f-45.f*2, 60};
|
||||||
m_list = std::make_unique<List>(m_pos, v);
|
m_list = std::make_unique<List>(1, 8, m_pos, v);
|
||||||
|
|
||||||
fs::FsPath buf;
|
fs::FsPath buf;
|
||||||
ini_gets("paths", "last_path", "/", buf, sizeof(buf), App::CONFIG_PATH);
|
ini_gets("paths", "last_path", "/", buf, sizeof(buf), App::CONFIG_PATH);
|
||||||
@@ -565,18 +565,13 @@ Menu::~Menu() {
|
|||||||
|
|
||||||
void Menu::Update(Controller* controller, TouchInfo* touch) {
|
void Menu::Update(Controller* controller, TouchInfo* touch) {
|
||||||
MenuBase::Update(controller, touch);
|
MenuBase::Update(controller, touch);
|
||||||
|
m_list->OnUpdate(controller, touch, m_entries_current.size(), [this](auto i) {
|
||||||
m_list->Do(m_index_offset, m_entries_current.size(), [this, touch](auto* vg, auto* theme, auto v, auto i) {
|
|
||||||
if (touch->is_clicked && touch->in_range(v)) {
|
|
||||||
if (m_index == i) {
|
if (m_index == i) {
|
||||||
FireAction(Button::A);
|
FireAction(Button::A);
|
||||||
} else {
|
} else {
|
||||||
App::PlaySoundEffect(SoundEffect_Focus);
|
App::PlaySoundEffect(SoundEffect_Focus);
|
||||||
SetIndex(i);
|
SetIndex(i);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -591,12 +586,8 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constexpr float text_xoffset{15.f};
|
constexpr float text_xoffset{15.f};
|
||||||
gfx::drawScrollbar(vg, theme, m_index_offset, m_entries_current.size(), 8);
|
|
||||||
|
|
||||||
nvgSave(vg);
|
m_list->Draw(vg, theme, m_entries_current.size(), [this, text_col](auto* vg, auto* theme, auto v, auto i) {
|
||||||
nvgScissor(vg, GetX(), GetY(), GetW(), GetH());
|
|
||||||
|
|
||||||
m_list->Do(vg, theme, m_index_offset, m_entries_current.size(), [this, text_col](auto* vg, auto* theme, auto v, auto i) {
|
|
||||||
const auto& [x, y, w, h] = v;
|
const auto& [x, y, w, h] = v;
|
||||||
auto& e = GetEntry(i);
|
auto& e = GetEntry(i);
|
||||||
|
|
||||||
@@ -623,7 +614,7 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
text_id = ThemeEntryID_TEXT_SELECTED;
|
text_id = ThemeEntryID_TEXT_SELECTED;
|
||||||
gfx::drawRectOutline(vg, 4.f, theme->elements[ThemeEntryID_SELECTED_OVERLAY].colour, x, y, w, h, theme->elements[ThemeEntryID_SELECTED].colour);
|
gfx::drawRectOutline(vg, 4.f, theme->elements[ThemeEntryID_SELECTED_OVERLAY].colour, x, y, w, h, theme->elements[ThemeEntryID_SELECTED].colour);
|
||||||
} else {
|
} else {
|
||||||
if (i == m_index_offset) {
|
if (i == m_index) {
|
||||||
gfx::drawRect(vg, x, y, w, 1.f, text_col);
|
gfx::drawRect(vg, x, y, w, 1.f, text_col);
|
||||||
}
|
}
|
||||||
gfx::drawRect(vg, x, y + h, w, 1.f, text_col);
|
gfx::drawRect(vg, x, y + h, w, 1.f, text_col);
|
||||||
@@ -650,8 +641,7 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
nvgSave(vg);
|
nvgSave(vg);
|
||||||
const auto txt_clip = std::min(GetY() + GetH(), y + h) - y;
|
nvgIntersectScissor(vg, x + text_xoffset+65, y, w-(x+text_xoffset+65+50), h);
|
||||||
nvgScissor(vg, x + text_xoffset+65, y, w-(x+text_xoffset+65+50), txt_clip);
|
|
||||||
gfx::drawText(vg, x + text_xoffset+65, y + (h / 2.f), 20.f, e.name, NULL, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE, theme->elements[text_id].colour);
|
gfx::drawText(vg, x + text_xoffset+65, y + (h / 2.f), 20.f, e.name, NULL, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE, theme->elements[text_id].colour);
|
||||||
nvgRestore(vg);
|
nvgRestore(vg);
|
||||||
|
|
||||||
@@ -673,11 +663,7 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f) - 3, 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_BOTTOM, theme->elements[text_id].colour, "%.2f MiB", (double)e.file_size / 1024.0 / 1024.0);
|
gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f) - 3, 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_BOTTOM, theme->elements[text_id].colour, "%.2f MiB", (double)e.file_size / 1024.0 / 1024.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
nvgRestore(vg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::OnFocusGained() {
|
void Menu::OnFocusGained() {
|
||||||
@@ -697,14 +683,10 @@ void Menu::OnFocusGained() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::SetIndex(std::size_t index) {
|
void Menu::SetIndex(s64 index) {
|
||||||
m_index = index;
|
m_index = index;
|
||||||
if (!m_index) {
|
if (!m_index) {
|
||||||
m_index_offset = 0;
|
m_list->SetYoff();
|
||||||
}
|
|
||||||
|
|
||||||
if (m_index > m_index_offset && m_index - m_index_offset >= 7) {
|
|
||||||
m_index_offset = m_index - 7;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_entries_current.empty() && !GetEntry().checked_internal_extension && GetEntry().extension == "zip") {
|
if (!m_entries_current.empty() && !GetEntry().checked_internal_extension && GetEntry().extension == "zip") {
|
||||||
@@ -799,16 +781,14 @@ void Menu::InstallForwarder() {
|
|||||||
auto Menu::Scan(const fs::FsPath& new_path, bool is_walk_up) -> Result {
|
auto Menu::Scan(const fs::FsPath& new_path, bool is_walk_up) -> Result {
|
||||||
log_write("new scan path: %s\n", new_path);
|
log_write("new scan path: %s\n", new_path);
|
||||||
if (!is_walk_up && !m_path.empty() && !m_entries_current.empty()) {
|
if (!is_walk_up && !m_path.empty() && !m_entries_current.empty()) {
|
||||||
const LastFile f{GetEntry().name, m_index, m_index_offset, m_entries_current.size()};
|
const LastFile f(GetEntry().name, m_index, m_list->GetYoff(), m_entries_current.size());
|
||||||
m_previous_highlighted_file.emplace_back(f);
|
m_previous_highlighted_file.emplace_back(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
log_write("\nold index: %zu start: %zu\n", m_index, m_index_offset);
|
|
||||||
|
|
||||||
m_path = new_path;
|
m_path = new_path;
|
||||||
m_entries.clear();
|
m_entries.clear();
|
||||||
m_index = 0;
|
m_index = 0;
|
||||||
m_index_offset = 0;
|
m_list->SetYoff(0);
|
||||||
SetTitleSubHeading(m_path);
|
SetTitleSubHeading(m_path);
|
||||||
|
|
||||||
if (m_selected_type == SelectedType::None) {
|
if (m_selected_type == SelectedType::None) {
|
||||||
@@ -1086,7 +1066,7 @@ void Menu::Sort() {
|
|||||||
void Menu::SortAndFindLastFile() {
|
void Menu::SortAndFindLastFile() {
|
||||||
std::optional<LastFile> last_file;
|
std::optional<LastFile> last_file;
|
||||||
if (!m_path.empty() && !m_entries_current.empty()) {
|
if (!m_path.empty() && !m_entries_current.empty()) {
|
||||||
last_file = LastFile{GetEntry().name, m_index, m_index_offset, m_entries_current.size()};
|
last_file = LastFile(GetEntry().name, m_index, m_list->GetYoff(), m_entries_current.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
Sort();
|
Sort();
|
||||||
@@ -1107,21 +1087,21 @@ void Menu::SetIndexFromLastFile(const LastFile& last_file) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
if ((u64)index == last_file.index && m_entries_current.size() == last_file.entries_count) {
|
if (index == last_file.index && m_entries_current.size() == last_file.entries_count) {
|
||||||
m_index_offset = last_file.offset;
|
m_list->SetYoff(last_file.offset);
|
||||||
log_write("index is the same as last time\n");
|
log_write("index is the same as last time\n");
|
||||||
} else {
|
} else {
|
||||||
// file position changed!
|
// file position changed!
|
||||||
log_write("file position changed\n");
|
log_write("file position changed\n");
|
||||||
// guesstimate where the position is
|
// guesstimate where the position is
|
||||||
if (index >= 8) {
|
if (index >= 8) {
|
||||||
m_index_offset = (index - 8) + 1;
|
m_list->SetYoff(((index - 8) + 1) * m_list->GetMaxY());
|
||||||
} else {
|
} else {
|
||||||
m_index_offset = 0;
|
m_list->SetYoff(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SetIndex(index);
|
SetIndex(index);
|
||||||
log_write("\nnew index: %zu start: %zu mod: %zu\n", m_index, m_index_offset, index % 8);
|
log_write("\nnew index: %zu %zu mod: %zu\n", m_index, index % 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ auto DownloadApp(ProgressBox* pbox, const GhApiAsset& gh_asset, const AssetEntry
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<char> buf(chunk_size);
|
std::vector<char> buf(chunk_size);
|
||||||
u64 offset{};
|
s64 offset{};
|
||||||
while (offset < info.uncompressed_size) {
|
while (offset < info.uncompressed_size) {
|
||||||
const auto bytes_read = unzReadCurrentFile(zfile, buf.data(), buf.size());
|
const auto bytes_read = unzReadCurrentFile(zfile, buf.data(), buf.size());
|
||||||
if (bytes_read <= 0) {
|
if (bytes_read <= 0) {
|
||||||
@@ -248,22 +248,22 @@ Menu::Menu() : MenuBase{"GitHub"_i18n} {
|
|||||||
|
|
||||||
this->SetActions(
|
this->SetActions(
|
||||||
std::make_pair(Button::DOWN, Action{[this](){
|
std::make_pair(Button::DOWN, Action{[this](){
|
||||||
if (ScrollHelperDown(m_index, m_index_offset, 1, 1, 8, m_entries.size())) {
|
if (m_list->ScrollDown(m_index, 1, m_entries.size())) {
|
||||||
SetIndex(m_index);
|
SetIndex(m_index);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::UP, Action{[this](){
|
std::make_pair(Button::UP, Action{[this](){
|
||||||
if (ScrollHelperUp(m_index, m_index_offset, 1, 1, 8, m_entries.size())) {
|
if (m_list->ScrollUp(m_index, 1, m_entries.size())) {
|
||||||
SetIndex(m_index);
|
SetIndex(m_index);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::DPAD_RIGHT, Action{[this](){
|
std::make_pair(Button::DPAD_RIGHT, Action{[this](){
|
||||||
if (ScrollHelperDown(m_index, m_index_offset, 8, 1, 8, m_entries.size())) {
|
if (m_list->ScrollDown(m_index, 8, m_entries.size())) {
|
||||||
SetIndex(m_index);
|
SetIndex(m_index);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::DPAD_LEFT, Action{[this](){
|
std::make_pair(Button::DPAD_LEFT, Action{[this](){
|
||||||
if (ScrollHelperUp(m_index, m_index_offset, 8, 1, 8, m_entries.size())) {
|
if (m_list->ScrollUp(m_index, 8, m_entries.size())) {
|
||||||
SetIndex(m_index);
|
SetIndex(m_index);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
@@ -365,7 +365,7 @@ Menu::Menu() : MenuBase{"GitHub"_i18n} {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const Vec4 v{75, GetY() + 1.f + 42.f, 1220.f-45.f*2, 60};
|
const Vec4 v{75, GetY() + 1.f + 42.f, 1220.f-45.f*2, 60};
|
||||||
m_list = std::make_unique<List>(m_pos, v);
|
m_list = std::make_unique<List>(1, 8, m_pos, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu::~Menu() {
|
Menu::~Menu() {
|
||||||
@@ -373,18 +373,13 @@ Menu::~Menu() {
|
|||||||
|
|
||||||
void Menu::Update(Controller* controller, TouchInfo* touch) {
|
void Menu::Update(Controller* controller, TouchInfo* touch) {
|
||||||
MenuBase::Update(controller, touch);
|
MenuBase::Update(controller, touch);
|
||||||
|
m_list->OnUpdate(controller, touch, m_entries.size(), [this](auto i) {
|
||||||
m_list->Do(m_index_offset, m_entries.size(), [this, touch](auto* vg, auto* theme, auto v, auto i) {
|
|
||||||
if (touch->is_clicked && touch->in_range(v)) {
|
|
||||||
if (m_index == i) {
|
if (m_index == i) {
|
||||||
FireAction(Button::A);
|
FireAction(Button::A);
|
||||||
} else {
|
} else {
|
||||||
App::PlaySoundEffect(SoundEffect_Focus);
|
App::PlaySoundEffect(SoundEffect_Focus);
|
||||||
SetIndex(i);
|
SetIndex(i);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,9 +394,8 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constexpr float text_xoffset{15.f};
|
constexpr float text_xoffset{15.f};
|
||||||
gfx::drawScrollbar(vg, theme, m_index_offset, m_entries.size(), 8);
|
|
||||||
|
|
||||||
m_list->Do(vg, theme, m_index_offset, m_entries.size(), [this, text_col](auto* vg, auto* theme, auto v, auto i) {
|
m_list->Draw(vg, theme, m_entries.size(), [this, text_col](auto* vg, auto* theme, auto v, auto i) {
|
||||||
const auto& [x, y, w, h] = v;
|
const auto& [x, y, w, h] = v;
|
||||||
auto& e = m_entries[i];
|
auto& e = m_entries[i];
|
||||||
|
|
||||||
@@ -417,13 +411,11 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
nvgSave(vg);
|
nvgSave(vg);
|
||||||
const auto txt_clip = std::min(GetY() + GetH(), y + h) - y;
|
nvgIntersectScissor(vg, x + text_xoffset, y, w-(x+text_xoffset+50), h);
|
||||||
nvgScissor(vg, x + text_xoffset, y, w-(x+text_xoffset+50), txt_clip);
|
|
||||||
gfx::drawTextArgs(vg, x + text_xoffset, y + (h / 2.f), 20.f, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE, theme->elements[text_id].colour, "%s By %s", e.repo.c_str(), e.owner.c_str());
|
gfx::drawTextArgs(vg, x + text_xoffset, y + (h / 2.f), 20.f, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE, theme->elements[text_id].colour, "%s By %s", e.repo.c_str(), e.owner.c_str());
|
||||||
nvgRestore(vg);
|
nvgRestore(vg);
|
||||||
|
|
||||||
gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f), 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_MIDDLE, theme->elements[text_id].colour, "version: %s", e.tag.c_str());
|
gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f), 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_MIDDLE, theme->elements[text_id].colour, "version: %s", e.tag.c_str());
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,7 +426,7 @@ void Menu::OnFocusGained() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::SetIndex(std::size_t index) {
|
void Menu::SetIndex(s64 index) {
|
||||||
m_index = index;
|
m_index = index;
|
||||||
if (!m_index) {
|
if (!m_index) {
|
||||||
m_index_offset = 0;
|
m_index_offset = 0;
|
||||||
|
|||||||
@@ -43,22 +43,22 @@ Menu::Menu() : MenuBase{"Homebrew"_i18n} {
|
|||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::DOWN, Action{[this](){
|
std::make_pair(Button::DOWN, Action{[this](){
|
||||||
if (ScrollHelperDown(m_index, m_start, 3, 3, 9, m_entries.size())) {
|
if (m_list->ScrollDown(m_index, 3, m_entries.size())) {
|
||||||
SetIndex(m_index);
|
SetIndex(m_index);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::UP, Action{[this](){
|
std::make_pair(Button::UP, Action{[this](){
|
||||||
if (ScrollHelperUp(m_index, m_start, 3, 3, 9, m_entries.size())) {
|
if (m_list->ScrollUp(m_index, 3, m_entries.size())) {
|
||||||
SetIndex(m_index);
|
SetIndex(m_index);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::R2, Action{[this](){
|
std::make_pair(Button::R2, Action{[this](){
|
||||||
if (ScrollHelperDown(m_index, m_start, 9, 3, 9, m_entries.size())) {
|
if (m_list->ScrollDown(m_index, 9, m_entries.size())) {
|
||||||
SetIndex(m_index);
|
SetIndex(m_index);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::L2, Action{[this](){
|
std::make_pair(Button::L2, Action{[this](){
|
||||||
if (ScrollHelperUp(m_index, m_start, 9, 3, 9, m_entries.size())) {
|
if (m_list->ScrollUp(m_index, 9, m_entries.size())) {
|
||||||
SetIndex(m_index);
|
SetIndex(m_index);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
@@ -86,12 +86,12 @@ Menu::Menu() : MenuBase{"Homebrew"_i18n} {
|
|||||||
order_items.push_back("Decending"_i18n);
|
order_items.push_back("Decending"_i18n);
|
||||||
order_items.push_back("Ascending"_i18n);
|
order_items.push_back("Ascending"_i18n);
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryArray>("Sort"_i18n, sort_items, [this, sort_items](std::size_t& index_out){
|
options->Add(std::make_shared<SidebarEntryArray>("Sort"_i18n, sort_items, [this, sort_items](s64& index_out){
|
||||||
m_sort.Set(index_out);
|
m_sort.Set(index_out);
|
||||||
SortAndFindLastFile();
|
SortAndFindLastFile();
|
||||||
}, m_sort.Get()));
|
}, m_sort.Get()));
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryArray>("Order"_i18n, order_items, [this, order_items](std::size_t& index_out){
|
options->Add(std::make_shared<SidebarEntryArray>("Order"_i18n, order_items, [this, order_items](s64& index_out){
|
||||||
m_order.Set(index_out);
|
m_order.Set(index_out);
|
||||||
SortAndFindLastFile();
|
SortAndFindLastFile();
|
||||||
}, m_order.Get()));
|
}, m_order.Get()));
|
||||||
@@ -144,7 +144,7 @@ Menu::Menu() : MenuBase{"Homebrew"_i18n} {
|
|||||||
|
|
||||||
const Vec4 v{75, 110, 370, 155};
|
const Vec4 v{75, 110, 370, 155};
|
||||||
const Vec2 pad{10, 10};
|
const Vec2 pad{10, 10};
|
||||||
m_list = std::make_unique<List>(m_pos, v, pad);
|
m_list = std::make_unique<List>(3, 9, m_pos, v, pad);
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu::~Menu() {
|
Menu::~Menu() {
|
||||||
@@ -157,42 +157,24 @@ Menu::~Menu() {
|
|||||||
|
|
||||||
void Menu::Update(Controller* controller, TouchInfo* touch) {
|
void Menu::Update(Controller* controller, TouchInfo* touch) {
|
||||||
MenuBase::Update(controller, touch);
|
MenuBase::Update(controller, touch);
|
||||||
|
m_list->OnUpdate(controller, touch, m_entries.size(), [this](auto i) {
|
||||||
if (touch->is_clicked && touch->in_range(GetPos())) {
|
|
||||||
m_list->Do(m_start, m_entries.size(), [this, touch](auto* vg, auto* theme, auto v, auto i) {
|
|
||||||
if (touch->is_clicked && touch->in_range(v)) {
|
|
||||||
if (m_index == i) {
|
if (m_index == i) {
|
||||||
FireAction(Button::A);
|
FireAction(Button::A);
|
||||||
} else {
|
} else {
|
||||||
App::PlaySoundEffect(SoundEffect_Focus);
|
App::PlaySoundEffect(SoundEffect_Focus);
|
||||||
SetIndex(i);
|
SetIndex(i);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
} else if (touch->is_scroll && touch->in_range(GetPos())) {
|
|
||||||
y_off = (s32)touch->initial.y - (s32)touch->cur.y;
|
|
||||||
log_write("y off: %.2f\n", y_off);
|
|
||||||
} else {
|
|
||||||
// y_off = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::Draw(NVGcontext* vg, Theme* theme) {
|
void Menu::Draw(NVGcontext* vg, Theme* theme) {
|
||||||
MenuBase::Draw(vg, theme);
|
MenuBase::Draw(vg, theme);
|
||||||
|
|
||||||
// only draw scrollbar if needed
|
|
||||||
gfx::drawScrollbar(vg, theme, m_start, m_entries.size(), 9);
|
|
||||||
|
|
||||||
// max images per frame, in order to not hit io / gpu too hard.
|
// max images per frame, in order to not hit io / gpu too hard.
|
||||||
const int image_load_max = 2;
|
const int image_load_max = 2;
|
||||||
int image_load_count = 0;
|
int image_load_count = 0;
|
||||||
|
|
||||||
nvgSave(vg);
|
m_list->Draw(vg, theme, m_entries.size(), [this, &image_load_count](auto* vg, auto* theme, auto v, auto pos) {
|
||||||
nvgScissor(vg, GetX(), GetY(), GetW(), GetH());
|
|
||||||
|
|
||||||
m_list->Do(vg, theme, m_start, m_entries.size(), [this, &image_load_count](auto* vg, auto* theme, auto v, auto pos) {
|
|
||||||
const auto& [x, y, w, h] = v;
|
const auto& [x, y, w, h] = v;
|
||||||
auto& e = m_entries[pos];
|
auto& e = m_entries[pos];
|
||||||
|
|
||||||
@@ -222,9 +204,8 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
const float image_size = 115;
|
const float image_size = 115;
|
||||||
gfx::drawImageRounded(vg, x + 20, y + 20, image_size, image_size, e.image ? e.image : App::GetDefaultImage());
|
gfx::drawImageRounded(vg, x + 20, y + 20, image_size, image_size, e.image ? e.image : App::GetDefaultImage());
|
||||||
|
|
||||||
const auto clip_y = std::min(GetY() + GetH(), y + h) - y;
|
|
||||||
nvgSave(vg);
|
nvgSave(vg);
|
||||||
nvgScissor(vg, x, y, w - 30.f, clip_y); // clip
|
nvgIntersectScissor(vg, x, y, w - 30.f, h); // clip
|
||||||
{
|
{
|
||||||
bool has_star = false;
|
bool has_star = false;
|
||||||
if (IsStarEnabled()) {
|
if (IsStarEnabled()) {
|
||||||
@@ -240,10 +221,7 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
gfx::drawTextArgs(vg, x + 148, y + 115, font_size, NVG_ALIGN_LEFT, theme->elements[text_id].colour, e.GetDisplayVersion());
|
gfx::drawTextArgs(vg, x + 148, y + 115, font_size, NVG_ALIGN_LEFT, theme->elements[text_id].colour, e.GetDisplayVersion());
|
||||||
}
|
}
|
||||||
nvgRestore(vg);
|
nvgRestore(vg);
|
||||||
return true;
|
});
|
||||||
}, y_off);
|
|
||||||
|
|
||||||
nvgRestore(vg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::OnFocusGained() {
|
void Menu::OnFocusGained() {
|
||||||
@@ -253,14 +231,10 @@ void Menu::OnFocusGained() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::SetIndex(std::size_t index) {
|
void Menu::SetIndex(s64 index) {
|
||||||
m_index = index;
|
m_index = index;
|
||||||
if (!m_index) {
|
if (!m_index) {
|
||||||
m_start = 0;
|
m_list->SetYoff(0);
|
||||||
}
|
|
||||||
|
|
||||||
if (m_index > m_start && m_index - m_start >= 9) {
|
|
||||||
m_start = m_index/3*3 - 6;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& e = m_entries[m_index];
|
const auto& e = m_entries[m_index];
|
||||||
@@ -450,9 +424,9 @@ void Menu::SortAndFindLastFile() {
|
|||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
// guesstimate where the position is
|
// guesstimate where the position is
|
||||||
if (index >= 9) {
|
if (index >= 9) {
|
||||||
m_start = (index - 9) / 3 * 3 + 3;
|
m_list->SetYoff((((index - 9) + 3) / 3) * m_list->GetMaxY());
|
||||||
} else {
|
} else {
|
||||||
m_start = 0;
|
m_list->SetYoff(0);
|
||||||
}
|
}
|
||||||
SetIndex(index);
|
SetIndex(index);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,44 +139,44 @@ Menu::Menu() : MenuBase{"Irs"_i18n} {
|
|||||||
format_str.emplace_back("20x15"_i18n);
|
format_str.emplace_back("20x15"_i18n);
|
||||||
}
|
}
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryArray>("Controller"_i18n, controller_str, [this](std::size_t& index){
|
options->Add(std::make_shared<SidebarEntryArray>("Controller"_i18n, controller_str, [this](s64& index){
|
||||||
irsStopImageProcessor(m_entries[m_index].m_handle);
|
irsStopImageProcessor(m_entries[m_index].m_handle);
|
||||||
m_index = index;
|
m_index = index;
|
||||||
UpdateConfig(&m_config);
|
UpdateConfig(&m_config);
|
||||||
}, m_index));
|
}, m_index));
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryArray>("Rotation"_i18n, rotation_str, [this](std::size_t& index){
|
options->Add(std::make_shared<SidebarEntryArray>("Rotation"_i18n, rotation_str, [this](s64& index){
|
||||||
m_rotation = (Rotation)index;
|
m_rotation = (Rotation)index;
|
||||||
}, m_rotation));
|
}, m_rotation));
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryArray>("Colour"_i18n, colour_str, [this](std::size_t& index){
|
options->Add(std::make_shared<SidebarEntryArray>("Colour"_i18n, colour_str, [this](s64& index){
|
||||||
m_colour = (Colour)index;
|
m_colour = (Colour)index;
|
||||||
updateColourArray();
|
updateColourArray();
|
||||||
}, m_colour));
|
}, m_colour));
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryArray>("Light Target"_i18n, light_target_str, [this](std::size_t& index){
|
options->Add(std::make_shared<SidebarEntryArray>("Light Target"_i18n, light_target_str, [this](s64& index){
|
||||||
m_config.light_target = index;
|
m_config.light_target = index;
|
||||||
UpdateConfig(&m_config);
|
UpdateConfig(&m_config);
|
||||||
}, m_config.light_target));
|
}, m_config.light_target));
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryArray>("Gain"_i18n, gain_str, [this](std::size_t& index){
|
options->Add(std::make_shared<SidebarEntryArray>("Gain"_i18n, gain_str, [this](s64& index){
|
||||||
m_config.gain = GAIN_MIN + index;
|
m_config.gain = GAIN_MIN + index;
|
||||||
UpdateConfig(&m_config);
|
UpdateConfig(&m_config);
|
||||||
}, m_config.gain - GAIN_MIN));
|
}, m_config.gain - GAIN_MIN));
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryArray>("Negative Image"_i18n, is_negative_image_used_str, [this](std::size_t& index){
|
options->Add(std::make_shared<SidebarEntryArray>("Negative Image"_i18n, is_negative_image_used_str, [this](s64& index){
|
||||||
m_config.is_negative_image_used = index;
|
m_config.is_negative_image_used = index;
|
||||||
UpdateConfig(&m_config);
|
UpdateConfig(&m_config);
|
||||||
}, m_config.is_negative_image_used));
|
}, m_config.is_negative_image_used));
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryArray>("Format"_i18n, format_str, [this](std::size_t& index){
|
options->Add(std::make_shared<SidebarEntryArray>("Format"_i18n, format_str, [this](s64& index){
|
||||||
m_config.orig_format = index;
|
m_config.orig_format = index;
|
||||||
m_config.trimming_format = index;
|
m_config.trimming_format = index;
|
||||||
UpdateConfig(&m_config);
|
UpdateConfig(&m_config);
|
||||||
}, m_config.orig_format));
|
}, m_config.orig_format));
|
||||||
|
|
||||||
if (hosversionAtLeast(4,0,0)) {
|
if (hosversionAtLeast(4,0,0)) {
|
||||||
options->Add(std::make_shared<SidebarEntryArray>("Trimming Format"_i18n, format_str, [this](std::size_t& index){
|
options->Add(std::make_shared<SidebarEntryArray>("Trimming Format"_i18n, format_str, [this](s64& index){
|
||||||
// you cannot set trim a larger region than the source
|
// you cannot set trim a larger region than the source
|
||||||
if (index < m_config.orig_format) {
|
if (index < m_config.orig_format) {
|
||||||
index = m_config.orig_format;
|
index = m_config.orig_format;
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ auto InstallUpdate(ProgressBox* pbox, const std::string url, const std::string v
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<char> buf(chunk_size);
|
std::vector<char> buf(chunk_size);
|
||||||
u64 offset{};
|
s64 offset{};
|
||||||
while (offset < info.uncompressed_size) {
|
while (offset < info.uncompressed_size) {
|
||||||
const auto bytes_read = unzReadCurrentFile(zfile, buf.data(), buf.size());
|
const auto bytes_read = unzReadCurrentFile(zfile, buf.data(), buf.size());
|
||||||
if (bytes_read <= 0) {
|
if (bytes_read <= 0) {
|
||||||
@@ -205,9 +205,6 @@ MainMenu::MainMenu() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AddOnLPress();
|
|
||||||
AddOnRPress();
|
|
||||||
|
|
||||||
this->SetActions(
|
this->SetActions(
|
||||||
std::make_pair(Button::START, Action{App::Exit}),
|
std::make_pair(Button::START, Action{App::Exit}),
|
||||||
std::make_pair(Button::Y, Action{"Menu"_i18n, [this](){
|
std::make_pair(Button::Y, Action{"Menu"_i18n, [this](){
|
||||||
@@ -239,7 +236,7 @@ MainMenu::MainMenu() {
|
|||||||
auto options = std::make_shared<Sidebar>("Theme Options"_i18n, Sidebar::Side::LEFT);
|
auto options = std::make_shared<Sidebar>("Theme Options"_i18n, Sidebar::Side::LEFT);
|
||||||
ON_SCOPE_EXIT(App::Push(options));
|
ON_SCOPE_EXIT(App::Push(options));
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryArray>("Select Theme"_i18n, theme_items, [this, theme_items](std::size_t& index_out){
|
options->Add(std::make_shared<SidebarEntryArray>("Select Theme"_i18n, theme_items, [this, theme_items](s64& index_out){
|
||||||
App::SetTheme(index_out);
|
App::SetTheme(index_out);
|
||||||
}, App::GetThemeIndex()));
|
}, App::GetThemeIndex()));
|
||||||
|
|
||||||
@@ -292,9 +289,9 @@ MainMenu::MainMenu() {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryArray>("Language"_i18n, language_items, [this](std::size_t& index_out){
|
options->Add(std::make_shared<SidebarEntryArray>("Language"_i18n, language_items, [this](s64& index_out){
|
||||||
App::SetLanguage(index_out);
|
App::SetLanguage(index_out);
|
||||||
}, (std::size_t)App::GetLanguage()));
|
}, (s64)App::GetLanguage()));
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryCallback>("Misc"_i18n, [this](){
|
options->Add(std::make_shared<SidebarEntryCallback>("Misc"_i18n, [this](){
|
||||||
auto options = std::make_shared<Sidebar>("Misc Options"_i18n, Sidebar::Side::LEFT);
|
auto options = std::make_shared<Sidebar>("Misc Options"_i18n, Sidebar::Side::LEFT);
|
||||||
@@ -339,9 +336,9 @@ MainMenu::MainMenu() {
|
|||||||
App::SetInstallEnable(enable);
|
App::SetInstallEnable(enable);
|
||||||
}, "Enabled"_i18n, "Disabled"_i18n));
|
}, "Enabled"_i18n, "Disabled"_i18n));
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryArray>("Install location"_i18n, install_items, [this](std::size_t& index_out){
|
options->Add(std::make_shared<SidebarEntryArray>("Install location"_i18n, install_items, [this](s64& index_out){
|
||||||
App::SetInstallSdEnable(index_out);
|
App::SetInstallSdEnable(index_out);
|
||||||
}, (std::size_t)App::GetInstallSdEnable()));
|
}, (s64)App::GetInstallSdEnable()));
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryBool>("Show install warning"_i18n, App::GetInstallPrompt(), [this](bool& enable){
|
options->Add(std::make_shared<SidebarEntryBool>("Show install warning"_i18n, App::GetInstallPrompt(), [this](bool& enable){
|
||||||
App::SetInstallPrompt(enable);
|
App::SetInstallPrompt(enable);
|
||||||
@@ -355,6 +352,8 @@ MainMenu::MainMenu() {
|
|||||||
m_app_store_menu = std::make_shared<appstore::Menu>(m_homebrew_menu->GetHomebrewList());
|
m_app_store_menu = std::make_shared<appstore::Menu>(m_homebrew_menu->GetHomebrewList());
|
||||||
m_current_menu = m_homebrew_menu;
|
m_current_menu = m_homebrew_menu;
|
||||||
|
|
||||||
|
AddOnLRPress();
|
||||||
|
|
||||||
for (auto [button, action] : m_actions) {
|
for (auto [button, action] : m_actions) {
|
||||||
m_current_menu->SetAction(button, action);
|
m_current_menu->SetAction(button, action);
|
||||||
}
|
}
|
||||||
@@ -387,17 +386,11 @@ void MainMenu::OnLRPress(std::shared_ptr<MenuBase> menu, Button b) {
|
|||||||
if (m_current_menu == m_homebrew_menu) {
|
if (m_current_menu == m_homebrew_menu) {
|
||||||
m_current_menu = menu;
|
m_current_menu = menu;
|
||||||
RemoveAction(b);
|
RemoveAction(b);
|
||||||
if (b == Button::L) {
|
|
||||||
AddOnRPress();
|
|
||||||
} else {
|
|
||||||
AddOnLPress();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
m_current_menu = m_homebrew_menu;
|
m_current_menu = m_homebrew_menu;
|
||||||
AddOnRPress();
|
|
||||||
AddOnLPress();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AddOnLRPress();
|
||||||
m_current_menu->OnFocusGained();
|
m_current_menu->OnFocusGained();
|
||||||
|
|
||||||
for (auto [button, action] : m_actions) {
|
for (auto [button, action] : m_actions) {
|
||||||
@@ -405,18 +398,20 @@ void MainMenu::OnLRPress(std::shared_ptr<MenuBase> menu, Button b) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainMenu::AddOnLPress() {
|
void MainMenu::AddOnLRPress() {
|
||||||
|
if (m_current_menu != m_filebrowser_menu) {
|
||||||
const auto label = m_current_menu == m_homebrew_menu ? "Files" : "Apps";
|
const auto label = m_current_menu == m_homebrew_menu ? "Files" : "Apps";
|
||||||
SetAction(Button::L, Action{i18n::get(label), [this]{
|
SetAction(Button::L, Action{i18n::get(label), [this]{
|
||||||
OnLRPress(m_filebrowser_menu, Button::L);
|
OnLRPress(m_filebrowser_menu, Button::L);
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainMenu::AddOnRPress() {
|
if (m_current_menu != m_app_store_menu) {
|
||||||
const auto label = m_current_menu == m_homebrew_menu ? "Store" : "Apps";
|
const auto label = m_current_menu == m_homebrew_menu ? "Store" : "Apps";
|
||||||
SetAction(Button::R, Action{i18n::get(label), [this]{
|
SetAction(Button::R, Action{i18n::get(label), [this]{
|
||||||
OnLRPress(m_app_store_menu, Button::R);
|
OnLRPress(m_app_store_menu, Button::R);
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sphaira::ui::menu::main
|
} // namespace sphaira::ui::menu::main
|
||||||
|
|||||||
@@ -369,7 +369,7 @@ auto InstallTheme(ProgressBox* pbox, const PackListEntry& entry) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<char> buf(chunk_size);
|
std::vector<char> buf(chunk_size);
|
||||||
u64 offset{};
|
s64 offset{};
|
||||||
while (offset < info.uncompressed_size) {
|
while (offset < info.uncompressed_size) {
|
||||||
if (pbox->ShouldExit()) {
|
if (pbox->ShouldExit()) {
|
||||||
return false;
|
return false;
|
||||||
@@ -429,25 +429,25 @@ Menu::Menu() : MenuBase{"Themezer"_i18n} {
|
|||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::DOWN, Action{[this](){
|
std::make_pair(Button::DOWN, Action{[this](){
|
||||||
const auto& page = m_pages[m_page_index];
|
const auto& page = m_pages[m_page_index];
|
||||||
if (ScrollHelperDown(m_index, m_start, 3, 3, 6, page.m_packList.size())) {
|
if (m_list->ScrollDown(m_index, 3, page.m_packList.size())) {
|
||||||
SetIndex(m_index);
|
SetIndex(m_index);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::UP, Action{[this](){
|
std::make_pair(Button::UP, Action{[this](){
|
||||||
const auto& page = m_pages[m_page_index];
|
const auto& page = m_pages[m_page_index];
|
||||||
if (ScrollHelperUp(m_index, m_start, 3, 3, 6, page.m_packList.size())) {
|
if (m_list->ScrollUp(m_index, 3, page.m_packList.size())) {
|
||||||
SetIndex(m_index);
|
SetIndex(m_index);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::R2, Action{[this](){
|
std::make_pair(Button::R2, Action{[this](){
|
||||||
const auto& page = m_pages[m_page_index];
|
const auto& page = m_pages[m_page_index];
|
||||||
if (ScrollHelperDown(m_index, m_start, 6, 3, 6, page.m_packList.size())) {
|
if (m_list->ScrollDown(m_index, 6, page.m_packList.size())) {
|
||||||
SetIndex(m_index);
|
SetIndex(m_index);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::L2, Action{[this](){
|
std::make_pair(Button::L2, Action{[this](){
|
||||||
const auto& page = m_pages[m_page_index];
|
const auto& page = m_pages[m_page_index];
|
||||||
if (ScrollHelperUp(m_index, m_start, 6, 3, 6, page.m_packList.size())) {
|
if (m_list->ScrollUp(m_index, 6, page.m_packList.size())) {
|
||||||
SetIndex(m_index);
|
SetIndex(m_index);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
@@ -492,14 +492,14 @@ Menu::Menu() : MenuBase{"Themezer"_i18n} {
|
|||||||
InvalidateAllPages();
|
InvalidateAllPages();
|
||||||
}, "Enabled"_i18n, "Disabled"_i18n));
|
}, "Enabled"_i18n, "Disabled"_i18n));
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryArray>("Sort"_i18n, sort_items, [this, sort_items](std::size_t& index_out){
|
options->Add(std::make_shared<SidebarEntryArray>("Sort"_i18n, sort_items, [this, sort_items](s64& index_out){
|
||||||
if (m_sort.Get() != index_out) {
|
if (m_sort.Get() != index_out) {
|
||||||
m_sort.Set(index_out);
|
m_sort.Set(index_out);
|
||||||
InvalidateAllPages();
|
InvalidateAllPages();
|
||||||
}
|
}
|
||||||
}, m_sort.Get()));
|
}, m_sort.Get()));
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryArray>("Order"_i18n, order_items, [this, order_items](std::size_t& index_out){
|
options->Add(std::make_shared<SidebarEntryArray>("Order"_i18n, order_items, [this, order_items](s64& index_out){
|
||||||
if (m_order.Get() != index_out) {
|
if (m_order.Get() != index_out) {
|
||||||
m_order.Set(index_out);
|
m_order.Set(index_out);
|
||||||
InvalidateAllPages();
|
InvalidateAllPages();
|
||||||
@@ -548,7 +548,7 @@ Menu::Menu() : MenuBase{"Themezer"_i18n} {
|
|||||||
|
|
||||||
const Vec4 v{75, 110, 350, 250};
|
const Vec4 v{75, 110, 350, 250};
|
||||||
const Vec2 pad{10, 10};
|
const Vec2 pad{10, 10};
|
||||||
m_list = std::make_unique<List>(m_pos, v, pad);
|
m_list = std::make_unique<List>(3, 6, m_pos, v, pad);
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu::~Menu() {
|
Menu::~Menu() {
|
||||||
@@ -567,17 +567,13 @@ void Menu::Update(Controller* controller, TouchInfo* touch) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_list->Do(m_start, page.m_packList.size(), [this, touch](auto* vg, auto* theme, auto v, auto i) {
|
m_list->OnUpdate(controller, touch, page.m_packList.size(), [this](auto i) {
|
||||||
if (touch->is_clicked && touch->in_range(v)) {
|
|
||||||
if (m_index == i) {
|
if (m_index == i) {
|
||||||
FireAction(Button::A);
|
FireAction(Button::A);
|
||||||
} else {
|
} else {
|
||||||
App::PlaySoundEffect(SoundEffect_Focus);
|
App::PlaySoundEffect(SoundEffect_Focus);
|
||||||
SetIndex(i);
|
SetIndex(i);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -605,14 +601,11 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// only draw scrollbar if needed
|
|
||||||
gfx::drawScrollbar(vg, theme, m_start, page.m_packList.size(), 9);
|
|
||||||
|
|
||||||
// max images per frame, in order to not hit io / gpu too hard.
|
// max images per frame, in order to not hit io / gpu too hard.
|
||||||
const int image_load_max = 2;
|
const int image_load_max = 2;
|
||||||
int image_load_count = 0;
|
int image_load_count = 0;
|
||||||
|
|
||||||
m_list->Do(vg, theme, m_start, page.m_packList.size(), [this, &page, &image_load_count](auto* vg, auto* theme, auto v, auto pos) {
|
m_list->Draw(vg, theme, page.m_packList.size(), [this, &page, &image_load_count](auto* vg, auto* theme, auto v, auto pos) {
|
||||||
const auto& [x, y, w, h] = v;
|
const auto& [x, y, w, h] = v;
|
||||||
auto& e = page.m_packList[pos];
|
auto& e = page.m_packList[pos];
|
||||||
|
|
||||||
@@ -687,15 +680,13 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
gfx::drawImageRounded(vg, x + xoff, y, 320, 180, image.image ? image.image : App::GetDefaultImage());
|
gfx::drawImageRounded(vg, x + xoff, y, 320, 180, image.image ? image.image : App::GetDefaultImage());
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto clip_y = std::min(GetY() + GetH(), y + h) - y;
|
|
||||||
nvgSave(vg);
|
nvgSave(vg);
|
||||||
nvgScissor(vg, x, y, w - 30.f, clip_y); // clip
|
nvgIntersectScissor(vg, x, y, w - 30.f, h); // clip
|
||||||
{
|
{
|
||||||
gfx::drawTextArgs(vg, x + xoff, y + 180 + 20, 18, NVG_ALIGN_LEFT, theme->elements[text_id].colour, "%s", e.details.name.c_str());
|
gfx::drawTextArgs(vg, x + xoff, y + 180 + 20, 18, NVG_ALIGN_LEFT, theme->elements[text_id].colour, "%s", e.details.name.c_str());
|
||||||
gfx::drawTextArgs(vg, x + xoff, y + 180 + 55, 18, NVG_ALIGN_LEFT, theme->elements[text_id].colour, "%s", e.creator.display_name.c_str());
|
gfx::drawTextArgs(vg, x + xoff, y + 180 + 55, 18, NVG_ALIGN_LEFT, theme->elements[text_id].colour, "%s", e.creator.display_name.c_str());
|
||||||
}
|
}
|
||||||
nvgRestore(vg);
|
nvgRestore(vg);
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -719,7 +710,7 @@ void Menu::PackListDownload() {
|
|||||||
SetSubHeading(subheading);
|
SetSubHeading(subheading);
|
||||||
|
|
||||||
m_index = 0;
|
m_index = 0;
|
||||||
m_start = 0;
|
m_list->SetYoff(0);
|
||||||
|
|
||||||
// already downloaded
|
// already downloaded
|
||||||
if (m_pages[m_page_index].m_ready != PageLoadState::None) {
|
if (m_pages[m_page_index].m_ready != PageLoadState::None) {
|
||||||
|
|||||||
@@ -77,6 +77,19 @@ inline void drawRectOutlineInternal(NVGcontext* vg, float size, const NVGcolor&
|
|||||||
float gradientX, gradientY, color;
|
float gradientX, gradientY, color;
|
||||||
getHighlightAnimation(&gradientX, &gradientY, &color);
|
getHighlightAnimation(&gradientX, &gradientY, &color);
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
// NVGcolor pulsationColor = nvgRGBAf((color * out_col.r) + (1 - color) * out_col.r,
|
||||||
|
// (color * out_col.g) + (1 - color) * out_col.g,
|
||||||
|
// (color * out_col.b) + (1 - color) * out_col.b,
|
||||||
|
// out_col.a);
|
||||||
|
NVGcolor pulsationColor = nvgRGBAf((color * out_col.r) + (1 - color) * out_col.r,
|
||||||
|
(color * out_col.g) + (1 - color) * out_col.g,
|
||||||
|
(color * out_col.b) + (1 - color) * out_col.b,
|
||||||
|
out_col.a);
|
||||||
|
|
||||||
|
drawRectIntenal(vg, {vec.x-size,vec.y-size,vec.w+(size*2.f),vec.h+(size * 2.f)}, pulsationColor, false);
|
||||||
|
drawRectIntenal(vg, vec, c, false);
|
||||||
|
#else
|
||||||
const auto strokeWidth = 5.0;
|
const auto strokeWidth = 5.0;
|
||||||
auto v2 = vec;
|
auto v2 = vec;
|
||||||
v2.x -= strokeWidth / 2.0;
|
v2.x -= strokeWidth / 2.0;
|
||||||
@@ -85,8 +98,8 @@ inline void drawRectOutlineInternal(NVGcontext* vg, float size, const NVGcolor&
|
|||||||
v2.h += strokeWidth;
|
v2.h += strokeWidth;
|
||||||
const auto corner_radius = 0.5;
|
const auto corner_radius = 0.5;
|
||||||
|
|
||||||
nvgSave(vg);
|
// nvgSave(vg);
|
||||||
nvgResetScissor(vg);
|
// nvgResetScissor(vg);
|
||||||
|
|
||||||
// const auto stroke_width = 5.0f;
|
// const auto stroke_width = 5.0f;
|
||||||
// const auto shadow_corner_radius = 6.0f;
|
// const auto shadow_corner_radius = 6.0f;
|
||||||
@@ -155,7 +168,8 @@ inline void drawRectOutlineInternal(NVGcontext* vg, float size, const NVGcolor&
|
|||||||
nvgFillColor(vg, c);
|
nvgFillColor(vg, c);
|
||||||
nvgFill(vg);
|
nvgFill(vg);
|
||||||
|
|
||||||
nvgRestore(vg);
|
// nvgRestore(vg);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void drawRectOutlineInternal(NVGcontext* vg, float size, const NVGcolor& out_col, Vec4 vec, const NVGpaint& p) {
|
inline void drawRectOutlineInternal(NVGcontext* vg, float size, const NVGcolor& out_col, Vec4 vec, const NVGpaint& p) {
|
||||||
@@ -454,9 +468,9 @@ void drawTextArgs(NVGcontext* vg, float x, float y, float size, int align, Colou
|
|||||||
}
|
}
|
||||||
|
|
||||||
void drawScrollbar(NVGcontext* vg, Theme* theme, float x, float y, float h, u32 index_off, u32 count, u32 max_per_page) {
|
void drawScrollbar(NVGcontext* vg, Theme* theme, float x, float y, float h, u32 index_off, u32 count, u32 max_per_page) {
|
||||||
const u64 SCROLL = index_off;
|
const s64 SCROLL = index_off;
|
||||||
const u64 max_entry_display = max_per_page;
|
const s64 max_entry_display = max_per_page;
|
||||||
const u64 entry_total = count;
|
const s64 entry_total = count;
|
||||||
const float scc2 = 8.0;
|
const float scc2 = 8.0;
|
||||||
const float scw = 2.0;
|
const float scw = 2.0;
|
||||||
|
|
||||||
@@ -474,6 +488,28 @@ void drawScrollbar(NVGcontext* vg, Theme* theme, u32 index_off, u32 count, u32 m
|
|||||||
drawScrollbar(vg, theme, SCREEN_WIDTH - 50, 100, SCREEN_HEIGHT-200, index_off, count, max_per_page);
|
drawScrollbar(vg, theme, SCREEN_WIDTH - 50, 100, SCREEN_HEIGHT-200, index_off, count, max_per_page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drawScrollbar2(NVGcontext* vg, Theme* theme, float x, float y, float h, s64 index_off, s64 count, s64 row, s64 page) {
|
||||||
|
// round up
|
||||||
|
if (count % row) {
|
||||||
|
count = count + (row - count % row);
|
||||||
|
}
|
||||||
|
|
||||||
|
const float scc2 = 8.0;
|
||||||
|
const float scw = 2.0;
|
||||||
|
|
||||||
|
// only draw scrollbar if needed
|
||||||
|
if (count > page) {
|
||||||
|
const float sb_h = 1.f / (float)count * h;
|
||||||
|
const float sb_y = index_off;
|
||||||
|
gfx::drawRect(vg, x, y, scc2, h, theme->elements[ThemeEntryID_GRID].colour, false);
|
||||||
|
gfx::drawRect(vg, x + scw, y + scw + sb_h * sb_y, scc2 - scw * 2, sb_h * float(page) - scw * 2, theme->elements[ThemeEntryID_TEXT_SELECTED].colour, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawScrollbar2(NVGcontext* vg, Theme* theme, s64 index_off, s64 count, s64 row, s64 page) {
|
||||||
|
drawScrollbar2(vg, theme, SCREEN_WIDTH - 50, 100, SCREEN_HEIGHT-200, index_off, count, row, page);
|
||||||
|
}
|
||||||
|
|
||||||
#define HIGHLIGHT_SPEED 350.0
|
#define HIGHLIGHT_SPEED 350.0
|
||||||
|
|
||||||
static double highlightGradientX = 0;
|
static double highlightGradientX = 0;
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ OptionBox::OptionBox(const std::string& message, const Option& a, const Option&
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionBox::OptionBox(const std::string& message, const Option& a, const Option& b, std::size_t index, Callback cb)
|
OptionBox::OptionBox(const std::string& message, const Option& a, const Option& b, s64 index, Callback cb)
|
||||||
: m_message{message}
|
: m_message{message}
|
||||||
, m_callback{cb} {
|
, m_callback{cb} {
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ OptionBox::OptionBox(const std::string& message, const Option& a, const Option&
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionBox::OptionBox(const std::string& message, const Option& a, const Option& b, const Option& c, std::size_t index, Callback cb)
|
OptionBox::OptionBox(const std::string& message, const Option& a, const Option& b, const Option& c, s64 index, Callback cb)
|
||||||
: m_message{message}
|
: m_message{message}
|
||||||
, m_callback{cb} {
|
, m_callback{cb} {
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ auto OptionBox::Update(Controller* controller, TouchInfo* touch) -> void {
|
|||||||
Widget::Update(controller, touch);
|
Widget::Update(controller, touch);
|
||||||
|
|
||||||
if (touch->is_clicked) {
|
if (touch->is_clicked) {
|
||||||
for (std::size_t i = 0; i < m_entries.size(); i++) {
|
for (s64 i = 0; i < m_entries.size(); i++) {
|
||||||
auto& e = m_entries[i];
|
auto& e = m_entries[i];
|
||||||
if (touch->in_range(e.GetPos())) {
|
if (touch->in_range(e.GetPos())) {
|
||||||
SetIndex(i);
|
SetIndex(i);
|
||||||
@@ -118,8 +118,8 @@ auto OptionBox::OnFocusLost() noexcept -> void {
|
|||||||
SetHidden(true);
|
SetHidden(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto OptionBox::Setup(std::size_t index) -> void {
|
auto OptionBox::Setup(s64 index) -> void {
|
||||||
m_index = std::min(m_entries.size() - 1, index);
|
m_index = std::min<s64>(m_entries.size() - 1, index);
|
||||||
m_entries[m_index].Selected(true);
|
m_entries[m_index].Selected(true);
|
||||||
m_spacer_line = Vec4{m_pos.x, m_pos.y + 220.f - 2.f, m_pos.w, 2.f};
|
m_spacer_line = Vec4{m_pos.x, m_pos.y + 220.f - 2.f, m_pos.w, 2.f};
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ auto OptionBox::Setup(std::size_t index) -> void {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OptionBox::SetIndex(std::size_t index) {
|
void OptionBox::SetIndex(s64 index) {
|
||||||
if (m_index != index) {
|
if (m_index != index) {
|
||||||
m_entries[m_index].Selected(false);
|
m_entries[m_index].Selected(false);
|
||||||
m_index = index;
|
m_index = index;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
namespace sphaira::ui {
|
namespace sphaira::ui {
|
||||||
|
|
||||||
PopupList::PopupList(std::string title, Items items, std::string& index_str_ref, std::size_t& index_ref)
|
PopupList::PopupList(std::string title, Items items, std::string& index_str_ref, s64& index_ref)
|
||||||
: PopupList{std::move(title), std::move(items), Callback{}, index_ref} {
|
: PopupList{std::move(title), std::move(items), Callback{}, index_ref} {
|
||||||
|
|
||||||
m_callback = [&index_str_ref, &index_ref, this](auto op_idx) {
|
m_callback = [&index_str_ref, &index_ref, this](auto op_idx) {
|
||||||
@@ -34,7 +34,7 @@ PopupList::PopupList(std::string title, Items items, std::string& index_ref)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
PopupList::PopupList(std::string title, Items items, std::size_t& index_ref)
|
PopupList::PopupList(std::string title, Items items, s64& index_ref)
|
||||||
: PopupList{std::move(title), std::move(items), Callback{}, index_ref} {
|
: PopupList{std::move(title), std::move(items), Callback{}, index_ref} {
|
||||||
|
|
||||||
m_callback = [&index_ref, this](auto op_idx) {
|
m_callback = [&index_ref, this](auto op_idx) {
|
||||||
@@ -56,11 +56,32 @@ PopupList::PopupList(std::string title, Items items, Callback cb, std::string in
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PopupList::PopupList(std::string title, Items items, Callback cb, std::size_t index)
|
PopupList::PopupList(std::string title, Items items, Callback cb, s64 index)
|
||||||
: m_title{std::move(title)}
|
: m_title{std::move(title)}
|
||||||
, m_items{std::move(items)}
|
, m_items{std::move(items)}
|
||||||
, m_callback{cb}
|
, m_callback{cb}
|
||||||
, m_index{index} {
|
, m_index{index} {
|
||||||
|
this->SetActions(
|
||||||
|
std::make_pair(Button::DOWN, Action{[this](){
|
||||||
|
if (m_list->ScrollDown(m_index, 1, m_items.size())) {
|
||||||
|
SetIndex(m_index);
|
||||||
|
}
|
||||||
|
}}),
|
||||||
|
std::make_pair(Button::UP, Action{[this](){
|
||||||
|
if (m_list->ScrollUp(m_index, 1, m_items.size())) {
|
||||||
|
SetIndex(m_index);
|
||||||
|
}
|
||||||
|
}}),
|
||||||
|
std::make_pair(Button::A, Action{"Select"_i18n, [this](){
|
||||||
|
if (m_callback) {
|
||||||
|
m_callback(m_index);
|
||||||
|
}
|
||||||
|
SetPop();
|
||||||
|
}}),
|
||||||
|
std::make_pair(Button::B, Action{"Back"_i18n, [this](){
|
||||||
|
SetPop();
|
||||||
|
}})
|
||||||
|
);
|
||||||
|
|
||||||
m_pos.w = 1280.f;
|
m_pos.w = 1280.f;
|
||||||
const float a = std::min(405.f, (60.f * static_cast<float>(m_items.size())));
|
const float a = std::min(405.f, (60.f * static_cast<float>(m_items.size())));
|
||||||
@@ -75,45 +96,17 @@ PopupList::PopupList(std::string title, Items items, Callback cb, std::size_t in
|
|||||||
Vec4 v{m_block};
|
Vec4 v{m_block};
|
||||||
v.y = m_line_top + 1.f + 42.f;
|
v.y = m_line_top + 1.f + 42.f;
|
||||||
const Vec4 pos{0, m_line_top, 1280.f, m_line_bottom - m_line_top};
|
const Vec4 pos{0, m_line_top, 1280.f, m_line_bottom - m_line_top};
|
||||||
m_list = std::make_unique<List>(pos, v);
|
m_list = std::make_unique<List>(1, 7, pos, v);
|
||||||
|
m_list->SetScrollBarPos(1250, m_line_top + 20, m_line_bottom - m_line_top - 40);
|
||||||
this->SetActions(
|
|
||||||
std::make_pair(Button::DOWN, Action{[this](){
|
|
||||||
if (ScrollHelperDown(m_index, m_index_offset, 1, 1, 7, m_items.size())) {
|
|
||||||
SetIndex(m_index);
|
|
||||||
}
|
|
||||||
}}),
|
|
||||||
std::make_pair(Button::UP, Action{[this](){
|
|
||||||
if (ScrollHelperUp(m_index, m_index_offset, 1, 1, 7, m_items.size())) {
|
|
||||||
SetIndex(m_index);
|
|
||||||
}
|
|
||||||
}}),
|
|
||||||
std::make_pair(Button::A, Action{"Select"_i18n, [this](){
|
|
||||||
if (m_callback) {
|
|
||||||
m_callback(m_index);
|
|
||||||
}
|
|
||||||
SetPop();
|
|
||||||
}}),
|
|
||||||
std::make_pair(Button::B, Action{"Back"_i18n, [this](){
|
|
||||||
SetPop();
|
|
||||||
}})
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto PopupList::Update(Controller* controller, TouchInfo* touch) -> void {
|
auto PopupList::Update(Controller* controller, TouchInfo* touch) -> void {
|
||||||
Widget::Update(controller, touch);
|
Widget::Update(controller, touch);
|
||||||
|
m_list->OnUpdate(controller, touch, m_items.size(), [this](auto i) {
|
||||||
if (touch->is_clicked && touch->in_range(GetPos())) {
|
|
||||||
m_list->Do(m_index_offset, m_items.size(), [this, touch](auto* vg, auto* theme, auto v, auto i) {
|
|
||||||
if (touch->is_clicked && touch->in_range(v)) {
|
|
||||||
SetIndex(i);
|
SetIndex(i);
|
||||||
FireAction(Button::A);
|
FireAction(Button::A);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
auto PopupList::Draw(NVGcontext* vg, Theme* theme) -> void {
|
auto PopupList::Draw(NVGcontext* vg, Theme* theme) -> void {
|
||||||
gfx::dimBackground(vg);
|
gfx::dimBackground(vg);
|
||||||
@@ -122,9 +115,7 @@ auto PopupList::Draw(NVGcontext* vg, Theme* theme) -> void {
|
|||||||
gfx::drawRect(vg, 30.f, m_line_top, m_line_width, 1.f, theme->elements[ThemeEntryID_TEXT].colour);
|
gfx::drawRect(vg, 30.f, m_line_top, m_line_width, 1.f, theme->elements[ThemeEntryID_TEXT].colour);
|
||||||
gfx::drawRect(vg, 30.f, m_line_bottom, m_line_width, 1.f, theme->elements[ThemeEntryID_TEXT].colour);
|
gfx::drawRect(vg, 30.f, m_line_bottom, m_line_width, 1.f, theme->elements[ThemeEntryID_TEXT].colour);
|
||||||
|
|
||||||
gfx::drawScrollbar(vg, theme, 1250, m_line_top + 20, m_line_bottom - m_line_top - 40, m_index_offset, m_items.size(), 7);
|
m_list->Draw(vg, theme, m_items.size(), [this](auto* vg, auto* theme, auto v, auto i) {
|
||||||
|
|
||||||
m_list->Do(vg, theme, m_index_offset, m_items.size(), [this](auto* vg, auto* theme, auto v, auto i) {
|
|
||||||
const auto& [x, y, w, h] = v;
|
const auto& [x, y, w, h] = v;
|
||||||
if (m_index == i) {
|
if (m_index == i) {
|
||||||
gfx::drawRect(vg, x - 4.f, y - 4.f, w + 8.f, h + 8.f, theme->elements[ThemeEntryID_SELECTED_OVERLAY].colour);
|
gfx::drawRect(vg, x - 4.f, y - 4.f, w + 8.f, h + 8.f, theme->elements[ThemeEntryID_SELECTED_OVERLAY].colour);
|
||||||
@@ -135,7 +126,6 @@ auto PopupList::Draw(NVGcontext* vg, Theme* theme) -> void {
|
|||||||
gfx::drawRect(vg, x, y + h, w, 1.f, theme->elements[ThemeEntryID_TEXT].colour);
|
gfx::drawRect(vg, x, y + h, w, 1.f, theme->elements[ThemeEntryID_TEXT].colour);
|
||||||
gfx::drawText(vg, x + m_text_xoffset, y + (h / 2.f), 20.f, m_items[i].c_str(), NULL, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE, theme->elements[ThemeEntryID_TEXT].colour);
|
gfx::drawText(vg, x + m_text_xoffset, y + (h / 2.f), 20.f, m_items[i].c_str(), NULL, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE, theme->elements[ThemeEntryID_TEXT].colour);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Widget::Draw(vg, theme);
|
Widget::Draw(vg, theme);
|
||||||
@@ -151,7 +141,7 @@ auto PopupList::OnFocusLost() noexcept -> void {
|
|||||||
SetHidden(true);
|
SetHidden(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopupList::SetIndex(std::size_t index) {
|
void PopupList::SetIndex(s64 index) {
|
||||||
m_index = index;
|
m_index = index;
|
||||||
|
|
||||||
if (m_index > m_index_offset && m_index - m_index_offset >= 6) {
|
if (m_index > m_index_offset && m_index - m_index_offset >= 6) {
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ auto ProgressBox::NewTransfer(const std::string& transfer) -> ProgressBox& {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ProgressBox::UpdateTransfer(u64 offset, u64 size) -> ProgressBox& {
|
auto ProgressBox::UpdateTransfer(s64 offset, s64 size) -> ProgressBox& {
|
||||||
mutexLock(&m_mutex);
|
mutexLock(&m_mutex);
|
||||||
m_size = size;
|
m_size = size;
|
||||||
m_offset = offset;
|
m_offset = offset;
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ SidebarEntryArray::SidebarEntryArray(std::string title, Items items, Callback cb
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SidebarEntryArray::SidebarEntryArray(std::string title, Items items, Callback cb, std::size_t index)
|
SidebarEntryArray::SidebarEntryArray(std::string title, Items items, Callback cb, s64 index)
|
||||||
: SidebarEntryBase{std::forward<std::string>(title)}
|
: SidebarEntryBase{std::forward<std::string>(title)}
|
||||||
, m_items{std::move(items)}
|
, m_items{std::move(items)}
|
||||||
, m_callback{cb}
|
, m_callback{cb}
|
||||||
@@ -190,27 +190,12 @@ Sidebar::Sidebar(std::string title, std::string sub, Side side, Items&& items)
|
|||||||
m_title_pos = Vec2{m_pos.x + 30.f, m_pos.y + 40.f};
|
m_title_pos = Vec2{m_pos.x + 30.f, m_pos.y + 40.f};
|
||||||
m_base_pos = Vec4{GetX() + 30.f, GetY() + 170.f, m_pos.w - (30.f * 2.f), 70.f};
|
m_base_pos = Vec4{GetX() + 30.f, GetY() + 170.f, m_pos.w - (30.f * 2.f), 70.f};
|
||||||
|
|
||||||
const Vec4 pos = DistanceBetweenY(m_top_bar, m_bottom_bar);
|
// set button positions
|
||||||
m_list = std::make_unique<List>(pos, m_base_pos);
|
SetUiButtonPos({m_pos.x + m_pos.w - 60.f, 675});
|
||||||
|
|
||||||
this->SetActions(
|
const Vec4 pos = DistanceBetweenY(m_top_bar, m_bottom_bar);
|
||||||
std::make_pair(Button::DOWN, Action{[this](){
|
m_list = std::make_unique<List>(1, 6, pos, m_base_pos);
|
||||||
auto index = m_index;
|
m_list->SetScrollBarPos(GetX() + GetW() - 20, m_base_pos.y - 10, pos.h - m_base_pos.y + 48);
|
||||||
if (ScrollHelperDown(index, m_index_offset, 1, 1, 6, m_items.size())) {
|
|
||||||
SetIndex(index);
|
|
||||||
}
|
|
||||||
}}),
|
|
||||||
std::make_pair(Button::UP, Action{[this](){
|
|
||||||
auto index = m_index;
|
|
||||||
if (ScrollHelperUp(index, m_index_offset, 1, 1, 6, m_items.size())) {
|
|
||||||
SetIndex(index);
|
|
||||||
}
|
|
||||||
}}),
|
|
||||||
// each item has it's own Action, but we take over B
|
|
||||||
std::make_pair(Button::B, Action{"Back"_i18n, [this](){
|
|
||||||
SetPop();
|
|
||||||
}})
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Sidebar::Sidebar(std::string title, std::string sub, Side side)
|
Sidebar::Sidebar(std::string title, std::string sub, Side side)
|
||||||
@@ -219,36 +204,16 @@ Sidebar::Sidebar(std::string title, std::string sub, Side side)
|
|||||||
|
|
||||||
|
|
||||||
auto Sidebar::Update(Controller* controller, TouchInfo* touch) -> void {
|
auto Sidebar::Update(Controller* controller, TouchInfo* touch) -> void {
|
||||||
m_items[m_index]->Update(controller, touch);
|
|
||||||
const auto old_index = m_index;
|
|
||||||
Widget::Update(controller, touch);
|
Widget::Update(controller, touch);
|
||||||
|
|
||||||
if (touch->is_clicked && touch->in_range(GetPos())) {
|
// if touched out of bounds, pop the sidebar and all widgets below it.
|
||||||
m_list->Do(m_index_offset, m_items.size(), [this, touch](auto* vg, auto* theme, auto v, auto i) {
|
if (touch->is_clicked && !touch->in_range(GetPos())) {
|
||||||
const auto& [x, y, w, h] = v;
|
App::PopToMenu();
|
||||||
m_items[i]->SetY(y);
|
} else {
|
||||||
if (touch->in_range(m_items[i]->GetPos())) {
|
m_list->OnUpdate(controller, touch, m_items.size(), [this](auto i) {
|
||||||
SetIndex(i);
|
SetIndex(i);
|
||||||
FireAction(Button::A);
|
FireAction(Button::A);
|
||||||
m_items[m_index]->FireAction(Button::A);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
} else if (touch->is_clicked && !touch->in_range(GetPos())) {
|
|
||||||
App::PopToMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
Actions draw_actions{m_actions};
|
|
||||||
const auto& actions_ref = m_items[m_index]->GetActions();
|
|
||||||
draw_actions.insert(actions_ref.cbegin(), actions_ref.cend());
|
|
||||||
|
|
||||||
const auto d = GetUiButtons(draw_actions, m_pos.x + m_pos.w - 60.f);
|
|
||||||
for (auto& e : d) {
|
|
||||||
if (touch->is_clicked && touch->in_range(e.GetPos())) {
|
|
||||||
FireAction(e.m_button);
|
|
||||||
m_items[m_index]->FireAction(e.m_button);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_items[m_index]->ShouldPop()) {
|
if (m_items[m_index]->ShouldPop()) {
|
||||||
@@ -265,28 +230,13 @@ auto Sidebar::Draw(NVGcontext* vg, Theme* theme) -> void {
|
|||||||
gfx::drawRect(vg, m_top_bar, theme->elements[ThemeEntryID_TEXT].colour);
|
gfx::drawRect(vg, m_top_bar, theme->elements[ThemeEntryID_TEXT].colour);
|
||||||
gfx::drawRect(vg, m_bottom_bar, theme->elements[ThemeEntryID_TEXT].colour);
|
gfx::drawRect(vg, m_bottom_bar, theme->elements[ThemeEntryID_TEXT].colour);
|
||||||
|
|
||||||
// only draw scrollbar if needed
|
Widget::Draw(vg, theme);
|
||||||
const auto dist = DistanceBetweenY(m_top_bar, m_bottom_bar);
|
|
||||||
gfx::drawScrollbar(vg, theme, GetX() + GetW() - 20, m_base_pos.y - 10, dist.h - m_base_pos.y + 48, m_index_offset, m_items.size(), 6);
|
|
||||||
|
|
||||||
m_list->Do(vg, theme, m_index_offset, m_items.size(), [this](auto* vg, auto* theme, auto v, auto i) {
|
m_list->Draw(vg, theme, m_items.size(), [this](auto* vg, auto* theme, auto v, auto i) {
|
||||||
const auto& [x, y, w, h] = v;
|
const auto& [x, y, w, h] = v;
|
||||||
m_items[i]->SetY(y);
|
m_items[i]->SetY(y);
|
||||||
m_items[i]->Draw(vg, theme);
|
m_items[i]->Draw(vg, theme);
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// draw the buttons. fetch the actions from current item and insert into array.
|
|
||||||
Actions draw_actions{m_actions};
|
|
||||||
const auto& actions_ref = m_items[m_index]->GetActions();
|
|
||||||
draw_actions.insert(actions_ref.cbegin(), actions_ref.cend());
|
|
||||||
|
|
||||||
auto d = GetUiButtons(draw_actions, m_pos.x + m_pos.w - 60.f);
|
|
||||||
for (auto& e : d) {
|
|
||||||
e.Draw(vg, theme);
|
|
||||||
}
|
|
||||||
|
|
||||||
// gfx::drawButtons(vg, draw_actions, theme->elements[ThemeEntryID_TEXT].colour, m_pos.x + m_pos.w - 60.f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Sidebar::OnFocusGained() noexcept -> void {
|
auto Sidebar::OnFocusGained() noexcept -> void {
|
||||||
@@ -304,10 +254,13 @@ void Sidebar::Add(std::shared_ptr<SidebarEntryBase> entry) {
|
|||||||
m_items.back()->SetPos(m_base_pos);
|
m_items.back()->SetPos(m_base_pos);
|
||||||
|
|
||||||
// give focus to first entry.
|
// give focus to first entry.
|
||||||
|
if (m_items.size() == 1) {
|
||||||
m_items[m_index]->OnFocusGained();
|
m_items[m_index]->OnFocusGained();
|
||||||
|
SetupButtons();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sidebar::SetIndex(std::size_t index) {
|
void Sidebar::SetIndex(s64 index) {
|
||||||
// if we moved
|
// if we moved
|
||||||
if (m_index != index) {
|
if (m_index != index) {
|
||||||
m_items[m_index]->OnFocusLost();
|
m_items[m_index]->OnFocusLost();
|
||||||
@@ -317,7 +270,38 @@ void Sidebar::SetIndex(std::size_t index) {
|
|||||||
if (m_index > m_index_offset && m_index - m_index_offset >= 5) {
|
if (m_index > m_index_offset && m_index - m_index_offset >= 5) {
|
||||||
m_index_offset = m_index - 5;
|
m_index_offset = m_index - 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetupButtons();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Sidebar::SetupButtons() {
|
||||||
|
RemoveActions();
|
||||||
|
|
||||||
|
// add entry actions
|
||||||
|
for (const auto& [button, action] : m_items[m_index]->GetActions()) {
|
||||||
|
SetAction(button, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add default actions, overriding if needed.
|
||||||
|
this->SetActions(
|
||||||
|
std::make_pair(Button::DOWN, Action{[this](){
|
||||||
|
auto index = m_index;
|
||||||
|
if (m_list->ScrollDown(index, 1, m_items.size())) {
|
||||||
|
SetIndex(index);
|
||||||
|
}
|
||||||
|
}}),
|
||||||
|
std::make_pair(Button::UP, Action{[this](){
|
||||||
|
auto index = m_index;
|
||||||
|
if (m_list->ScrollUp(index, 1, m_items.size())) {
|
||||||
|
SetIndex(index);
|
||||||
|
}
|
||||||
|
}}),
|
||||||
|
// each item has it's own Action, but we take over B
|
||||||
|
std::make_pair(Button::B, Action{"Back"_i18n, [this](){
|
||||||
|
SetPop();
|
||||||
|
}})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sphaira::ui
|
} // namespace sphaira::ui
|
||||||
|
|||||||
@@ -24,20 +24,24 @@ void Widget::Update(Controller* controller, TouchInfo* touch) {
|
|||||||
App::PlaySoundEffect(SoundEffect_Focus);
|
App::PlaySoundEffect(SoundEffect_Focus);
|
||||||
}
|
}
|
||||||
action.Invoke(true);
|
action.Invoke(true);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if ((action.m_type & ActionType::UP) && controller->GotUp(button)) {
|
else if ((action.m_type & ActionType::UP) && controller->GotUp(button)) {
|
||||||
action.Invoke(false);
|
action.Invoke(false);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if ((action.m_type & ActionType::HELD) && controller->GotHeld(button)) {
|
else if ((action.m_type & ActionType::HELD) && controller->GotHeld(button)) {
|
||||||
action.Invoke(true);
|
action.Invoke(true);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto draw_actions = GetUiButtons();
|
auto draw_actions = GetUiButtons();
|
||||||
for (auto& e : draw_actions) {
|
for (auto& e : draw_actions) {
|
||||||
if (touch->is_clicked && touch->in_range(e.GetPos())) {
|
if (touch->is_clicked && touch->in_range(e.GetPos())) {
|
||||||
FireAction(e.m_button);
|
|
||||||
log_write("got click: %s\n", e.m_action.m_hint.c_str());
|
log_write("got click: %s\n", e.m_action.m_hint.c_str());
|
||||||
|
FireAction(e.m_button);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,71 +79,15 @@ auto Widget::FireAction(Button b, u8 type) -> bool {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Widget::ScrollHelperDown(u64& index, u64& start, u64 step, s64 row, s64 page, u64 size) -> bool {
|
auto Widget::GetUiButtons() const -> uiButtons {
|
||||||
const auto old_index = index;
|
|
||||||
|
|
||||||
if (!size) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index + step < size) {
|
|
||||||
index += step;
|
|
||||||
} else {
|
|
||||||
index = size - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index != old_index) {
|
|
||||||
App::PlaySoundEffect(SoundEffect_Scroll);
|
|
||||||
s64 delta = index - old_index;
|
|
||||||
|
|
||||||
if (index - start >= page) {
|
|
||||||
do {
|
|
||||||
start += row;
|
|
||||||
delta -= row;
|
|
||||||
} while (delta > 0 && start + page < size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Widget::ScrollHelperUp(u64& index, u64& start, s64 step, s64 row, s64 page, s64 size) -> bool {
|
|
||||||
const auto old_index = index;
|
|
||||||
|
|
||||||
if (!size) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index >= step) {
|
|
||||||
index -= step;
|
|
||||||
} else {
|
|
||||||
index = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index != old_index) {
|
|
||||||
App::PlaySoundEffect(SoundEffect_Scroll);
|
|
||||||
// if ()
|
|
||||||
while (index < start) {
|
|
||||||
// log_write("moved up\n");
|
|
||||||
start -= row;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Widget::GetUiButtons(const Actions& actions, float x, float y) -> uiButtons {
|
|
||||||
auto vg = App::GetVg();
|
auto vg = App::GetVg();
|
||||||
|
auto [x, y] = m_button_pos;
|
||||||
|
|
||||||
uiButtons draw_actions;
|
uiButtons draw_actions;
|
||||||
draw_actions.reserve(actions.size());
|
draw_actions.reserve(m_actions.size());
|
||||||
|
|
||||||
// build array
|
// build array
|
||||||
for (const auto& [button, action] : actions) {
|
for (const auto& [button, action] : m_actions) {
|
||||||
if (action.IsHidden() || action.m_hint.empty()) {
|
if (action.IsHidden() || action.m_hint.empty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -183,8 +131,4 @@ auto Widget::GetUiButtons(const Actions& actions, float x, float y) -> uiButtons
|
|||||||
return draw_actions;
|
return draw_actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Widget::GetUiButtons() const -> uiButtons {
|
|
||||||
return GetUiButtons(m_actions);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace sphaira::ui
|
} // namespace sphaira::ui
|
||||||
|
|||||||
Reference in New Issue
Block a user