Properly do transitions, some cleanup

This commit is contained in:
XorTroll 2021-08-07 23:15:29 +02:00
parent fe160e7bd0
commit 99b35271d9
23 changed files with 217 additions and 174 deletions

@ -1 +1 @@
Subproject commit 4ddfe0a01d4fb6d3b5ac300d615ec2847243be56
Subproject commit 4879af5a4df5c3af99f620b30e6da0bddd376a6d

View file

@ -53,7 +53,6 @@ static constexpr size_t RawRGBAScreenBufferSize = 1280 * 720 * 4;
#define STL_REMOVE_IF(stl_item, var_name, cond) stl_item.erase(std::remove_if(stl_item.begin(), stl_item.end(), [&](const auto &var_name){ return (cond); }), stl_item.end())
constexpr Result ResultSuccess = 0;
constexpr Mutex EmptyMutex = {};
#include <ul_Results.hpp>

View file

@ -5,10 +5,10 @@
namespace am {
using MessageDetectCallback = std::function<void()>;
using OnMessageCallback = std::function<void()>;
Result InitializeDaemonMessageHandler();
void ExitDaemonMessageHandler();
void RegisterOnMessageDetect(MessageDetectCallback callback, dmi::MenuMessage desired_msg);
void RegisterOnMessageDetect(OnMessageCallback callback, dmi::MenuMessage desired_msg);
}

View file

@ -8,8 +8,7 @@ namespace ui {
class IMenuLayout : public pu::ui::Layout {
private:
Mutex home_press_lock;
bool home_pressed;
std::atomic_bool home_pressed;
public:
IMenuLayout();
@ -17,7 +16,7 @@ namespace ui {
void OnInput(u64 down, u64 up, u64 held, pu::ui::Touch touch_pos);
virtual void OnMenuInput(u64 down, u64 up, u64 held, pu::ui::Touch touch_pos) = 0;
void DoOnHomeButtonPress();
virtual void OnHomeButtonPress() = 0;
virtual bool OnHomeButtonPress() = 0;
};

View file

@ -17,7 +17,7 @@ namespace ui {
PU_SMART_CTOR(LanguagesMenuLayout)
void OnMenuInput(u64 down, u64 up, u64 held, pu::ui::Touch touch_pos) override;
void OnHomeButtonPress() override;
bool OnHomeButtonPress() override;
void Reload();
void lang_Click(u32 idx);

View file

@ -1,5 +1,6 @@
#pragma once
#include <ui/ui_TransitionGuard.hpp>
#include <ui/ui_StartupLayout.hpp>
#include <ui/ui_MenuLayout.hpp>
#include <ui/ui_ThemeMenuLayout.hpp>

View file

@ -76,7 +76,7 @@ namespace ui {
PU_SMART_CTOR(MenuLayout)
void OnMenuInput(u64 down, u64 up, u64 held, pu::ui::Touch touch_pos) override;
void OnHomeButtonPress() override;
bool OnHomeButtonPress() override;
void menu_Click(u64 down, u32 index);
void menu_OnSelected(u32 index);

View file

@ -17,7 +17,7 @@ namespace ui {
PU_SMART_CTOR(SettingsMenuLayout)
void OnMenuInput(u64 down, u64 up, u64 held, pu::ui::Touch touch_pos) override;
void OnHomeButtonPress() override;
bool OnHomeButtonPress() override;
void Reload();
void PushSettingItem(const std::string &name, const std::string &value_display, int id);

View file

@ -19,7 +19,7 @@ namespace ui {
PU_SMART_CTOR(StartupLayout)
void OnMenuInput(u64 down, u64 up, u64 held, pu::ui::Touch touch_pos) override;
void OnHomeButtonPress() override;
bool OnHomeButtonPress() override;
void user_Click(AccountUid uid);
void create_Click();

View file

@ -23,7 +23,7 @@ namespace ui {
PU_SMART_CTOR(ThemeMenuLayout)
void OnMenuInput(u64 down, u64 up, u64 held, pu::ui::Touch touch_pos) override;
void OnHomeButtonPress() override;
bool OnHomeButtonPress() override;
void Reload();
void theme_Click();

View file

@ -0,0 +1,26 @@
#pragma once
#include <ul_Include.hpp>
namespace ui {
class TransitionGuard {
private:
bool on_transition;
public:
TransitionGuard() : on_transition(false) {}
bool Run(std::function<void()> fn) {
if(this->on_transition) {
return false;
}
this->on_transition = true;
fn();
this->on_transition = false;
return true;
}
};
}

View file

@ -28,6 +28,7 @@ extern "C" {
#define UL_MENU_ROMFS_BIN UL_BASE_SD_DIR "/bin/uMenu/romfs.bin"
ui::MenuApplication::Ref g_MenuApplication;
ui::TransitionGuard g_TransitionGuard;
u8 *g_ScreenCaptureBuffer;
cfg::TitleList g_EntryList;

View file

@ -42,12 +42,12 @@ namespace am {
namespace {
Mutex g_StopLock = EmptyMutex;
Mutex g_ReceiverLock = EmptyMutex;
bool g_Initialized = false;
std::atomic_bool g_ReceiveThreadShouldStop = false;
Thread g_ReceiverThread;
std::vector<std::pair<MessageDetectCallback, dmi::MenuMessage>> g_ReceiverCallbackTable;
std::vector<std::pair<OnMessageCallback, dmi::MenuMessage>> g_MessageCallbackTable;
Mutex g_CallbackTableLock = {};
void DaemonMessageReceiverThread(void*) {
while(true) {
@ -55,14 +55,14 @@ namespace am {
break;
}
auto last_msg = daemonGetMessage();
mutexLock(&g_ReceiverLock);
for(auto &[cb, msg] : g_ReceiverCallbackTable) {
const auto last_msg = daemonGetMessage();
mutexLock(&g_CallbackTableLock);
for(auto &[cb, msg] : g_MessageCallbackTable) {
if(msg == last_msg) {
cb();
}
}
mutexUnlock(&g_ReceiverLock);
mutexUnlock(&g_CallbackTableLock);
svcSleepThread(10'000'000ul);
}
@ -97,10 +97,10 @@ namespace am {
g_Initialized = false;
}
void RegisterOnMessageDetect(MessageDetectCallback callback, dmi::MenuMessage desired_msg) {
mutexLock(&g_ReceiverLock);
g_ReceiverCallbackTable.push_back(std::make_pair(callback, desired_msg));
mutexUnlock(&g_ReceiverLock);
void RegisterOnMessageDetect(OnMessageCallback callback, dmi::MenuMessage desired_msg) {
mutexLock(&g_CallbackTableLock);
g_MessageCallbackTable.push_back(std::make_pair(callback, desired_msg));
mutexUnlock(&g_CallbackTableLock);
}
}

View file

@ -4,7 +4,7 @@
namespace {
Mutex g_LibAppletWrapLock = EmptyMutex;
Mutex g_LibAppletWrapLock = {};
bool g_IsAppletRunning = false;
bool g_DetectionHomePressed = false;

View file

@ -13,7 +13,7 @@
#include <net/net_Service.hpp>
extern ui::MenuApplication::Ref g_MenuApplication;
extern ui::TransitionGuard g_TransitionGuard;
extern cfg::Config g_Config;
namespace ui::actions {
@ -23,15 +23,19 @@ namespace ui::actions {
}
void ShowSettingsMenu() {
g_MenuApplication->FadeOut();
g_MenuApplication->LoadSettingsMenu();
g_MenuApplication->FadeIn();
g_TransitionGuard.Run([]() {
g_MenuApplication->FadeOut();
g_MenuApplication->LoadSettingsMenu();
g_MenuApplication->FadeIn();
});
}
void ShowThemesMenu() {
g_MenuApplication->FadeOut();
g_MenuApplication->LoadThemeMenu();
g_MenuApplication->FadeIn();
g_TransitionGuard.Run([]() {
g_MenuApplication->FadeOut();
g_MenuApplication->LoadThemeMenu();
g_MenuApplication->FadeIn();
});
}
void ShowUserMenu() {
@ -58,10 +62,13 @@ namespace ui::actions {
if(logoff == 2) {
menu_lyt->DoTerminateApplication();
}
g_MenuApplication->FadeOut();
menu_lyt->MoveFolder("", false);
g_MenuApplication->LoadStartupMenu();
g_MenuApplication->FadeIn();
g_TransitionGuard.Run([&]() {
g_MenuApplication->FadeOut();
menu_lyt->MoveFolder("", false);
g_MenuApplication->LoadStartupMenu();
g_MenuApplication->FadeIn();
});
}
}
}

View file

@ -3,30 +3,29 @@
namespace ui {
IMenuLayout::IMenuLayout() : home_press_lock(EmptyMutex), home_pressed(false) {
IMenuLayout::IMenuLayout() : home_pressed(false) {
this->SetOnInput(std::bind(&IMenuLayout::OnInput, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
}
void IMenuLayout::OnInput(u64 down, u64 up, u64 held, pu::ui::Touch touch_pos) {
mutexLock(&this->home_press_lock);
auto home_press = this->home_pressed;
this->home_pressed = false;
mutexUnlock(&this->home_press_lock);
if(home_press) {
this->OnHomeButtonPress();
if(this->home_pressed) {
if(this->OnHomeButtonPress()) {
// Input consumed
this->home_pressed = false;
}
}
/* TODO
if(!hidIsControllerConnected(CONTROLLER_HANDHELD) && !hidIsControllerConnected(CONTROLLER_PLAYER_1)) {
actions::ShowControllerSupport();
}
*/
this->OnMenuInput(down, up, held, touch_pos);
}
void IMenuLayout::DoOnHomeButtonPress() {
mutexLock(&this->home_press_lock);
this->home_pressed = true;
mutexUnlock(&this->home_press_lock);
}
}

View file

@ -9,6 +9,7 @@
#include <am/am_LibraryApplet.hpp>
extern ui::MenuApplication::Ref g_MenuApplication;
extern ui::TransitionGuard g_TransitionGuard;
extern cfg::Theme g_Theme;
extern cfg::Config g_Config;
@ -35,16 +36,20 @@ namespace ui {
void LanguagesMenuLayout::OnMenuInput(u64 down, u64 up, u64 held, pu::ui::Touch touch_pos) {
if(down & HidNpadButton_B) {
g_MenuApplication->FadeOut();
g_MenuApplication->LoadSettingsMenu();
g_MenuApplication->FadeIn();
g_TransitionGuard.Run([]() {
g_MenuApplication->FadeOut();
g_MenuApplication->LoadSettingsMenu();
g_MenuApplication->FadeIn();
});
}
}
void LanguagesMenuLayout::OnHomeButtonPress() {
g_MenuApplication->FadeOut();
g_MenuApplication->LoadMenu();
g_MenuApplication->FadeIn();
bool LanguagesMenuLayout::OnHomeButtonPress() {
return g_TransitionGuard.Run([]() {
g_MenuApplication->FadeOut();
g_MenuApplication->LoadMenu();
g_MenuApplication->FadeIn();
});
}
void LanguagesMenuLayout::Reload() {
@ -91,11 +96,13 @@ namespace ui {
auto rc = setsysSetLanguageCode(code);
g_MenuApplication->CreateShowDialog(GetLanguageString("lang_set"), R_SUCCEEDED(rc) ? GetLanguageString("lang_set_ok") : GetLanguageString("lang_set_error") + ": " + util::FormatResult(rc), { GetLanguageString("ok") }, true);
if(R_SUCCEEDED(rc)) {
g_MenuApplication->FadeOut();
g_TransitionGuard.Run([]() {
g_MenuApplication->FadeOut();
auto smsg = os::SystemAppletMessage::Create(os::GeneralChannelMessage::Reboot);
os::PushSystemAppletMessage(smsg);
svcSleepThread(1'500'000'000ul);
const auto sams = os::SystemAppletMessage::Create(os::GeneralChannelMessage::Reboot);
os::PushSystemAppletMessage(sams);
svcSleepThread(1'500'000'000ul);
});
}
}
}

View file

@ -2,6 +2,7 @@
#include <util/util_Misc.hpp>
extern ui::MenuApplication::Ref g_MenuApplication;
extern ui::TransitionGuard g_TransitionGuard;
extern u8 *g_ScreenCaptureBuffer;
extern cfg::Theme g_Theme;
@ -16,28 +17,7 @@ namespace ui {
}
void UiOnHomeButtonDetection() {
switch(g_MenuApplication->GetCurrentLoadedMenu()) {
case MenuType::Startup: {
g_MenuApplication->GetStartupLayout()->DoOnHomeButtonPress();
break;
}
case MenuType::Main: {
g_MenuApplication->GetMenuLayout()->DoOnHomeButtonPress();
break;
}
case MenuType::Settings: {
g_MenuApplication->GetSettingsMenuLayout()->DoOnHomeButtonPress();
break;
}
case MenuType::Theme: {
g_MenuApplication->GetThemeMenuLayout()->DoOnHomeButtonPress();
break;
}
case MenuType::Languages: {
g_MenuApplication->GetLanguagesMenuLayout()->DoOnHomeButtonPress();
break;
}
}
g_MenuApplication->GetLayout<IMenuLayout>()->DoOnHomeButtonPress();
}
void MenuApplication::OnLoad() {

View file

@ -11,6 +11,7 @@
#include <net/net_Service.hpp>
extern ui::MenuApplication::Ref g_MenuApplication;
extern ui::TransitionGuard g_TransitionGuard;
extern cfg::TitleList g_EntryList;
extern std::vector<cfg::TitleRecord> g_HomebrewRecordList;
extern cfg::Config g_Config;
@ -254,7 +255,7 @@ namespace ui {
}
}
void MenuLayout::OnHomeButtonPress()
bool MenuLayout::OnHomeButtonPress()
{
if(g_MenuApplication->IsSuspended()) {
if(this->mode == 1) {
@ -267,6 +268,7 @@ namespace ui {
this->itemsMenu->HandleMoveLeft();
}
}
return true;
}
void MenuLayout::menu_Click(u64 down, u32 index) {
@ -705,78 +707,83 @@ namespace ui {
}
void MenuLayout::MoveFolder(const std::string &name, bool fade) {
this->itemsMenu->SetSelectedItem(0);
if(fade) {
g_MenuApplication->FadeOut();
}
if(this->homebrew_mode) {
if(g_HomebrewRecordList.empty()) {
g_HomebrewRecordList = cfg::QueryAllHomebrew();
}
}
auto itm_list = g_HomebrewRecordList;
if(!this->homebrew_mode) {
auto &folder = cfg::FindFolderByName(g_EntryList, name);
itm_list = folder.titles;
}
this->itemsMenu->ClearItems();
if(this->homebrew_mode) {
this->itemsMenu->AddItem(cfg::GetAssetByTheme(g_Theme, "ui/Hbmenu.png"));
}
else {
if(name.empty()) {
// Remove empty folders
STL_REMOVE_IF(g_EntryList.folders, fldr, (fldr.titles.empty()));
for(auto folder: g_EntryList.folders) {
this->itemsMenu->AddItem(cfg::GetAssetByTheme(g_Theme, "ui/Folder.png"), folder.name);
auto MoveFolderImpl = [&]() {
if(this->homebrew_mode) {
if(g_HomebrewRecordList.empty()) {
g_HomebrewRecordList = cfg::QueryAllHomebrew();
}
}
}
u32 tmpidx = 0;
for(auto &itm: itm_list) {
bool set_susp = false;
if(static_cast<cfg::TitleType>(itm.title_type) == cfg::TitleType::Installed) {
if(g_MenuApplication->IsTitleSuspended()) {
if(g_MenuApplication->GetSuspendedApplicationId() == itm.app_id) {
set_susp = true;
}
}
auto itm_list = g_HomebrewRecordList;
if(!this->homebrew_mode) {
auto &folder = cfg::FindFolderByName(g_EntryList, name);
itm_list = folder.titles;
}
this->itemsMenu->ClearItems();
if(this->homebrew_mode) {
this->itemsMenu->AddItem(cfg::GetAssetByTheme(g_Theme, "ui/Hbmenu.png"));
}
else {
if(g_MenuApplication->IsHomebrewSuspended()) {
if(g_MenuApplication->EqualsSuspendedHomebrewPath(itm.nro_target.nro_path)) {
set_susp = true;
if(name.empty()) {
// Remove empty folders
STL_REMOVE_IF(g_EntryList.folders, fldr, (fldr.titles.empty()));
for(auto folder: g_EntryList.folders) {
this->itemsMenu->AddItem(cfg::GetAssetByTheme(g_Theme, "ui/Folder.png"), folder.name);
}
}
}
this->itemsMenu->AddItem(cfg::GetRecordIconPath(itm));
if(set_susp) {
u32 suspidx = tmpidx;
// Skip initial item if homebrew mode
if(this->homebrew_mode) {
suspidx++;
}
// Ignore front folders from main menu
else if(name.empty()) {
suspidx += g_EntryList.folders.size();
}
this->itemsMenu->SetSuspendedItem(suspidx);
}
tmpidx++;
}
this->itemsMenu->UpdateBorderIcons();
if(!this->homebrew_mode) {
this->curfolder = name;
}
u32 tmpidx = 0;
for(auto &itm: itm_list) {
bool set_susp = false;
if(static_cast<cfg::TitleType>(itm.title_type) == cfg::TitleType::Installed) {
if(g_MenuApplication->IsTitleSuspended()) {
if(g_MenuApplication->GetSuspendedApplicationId() == itm.app_id) {
set_susp = true;
}
}
}
else {
if(g_MenuApplication->IsHomebrewSuspended()) {
if(g_MenuApplication->EqualsSuspendedHomebrewPath(itm.nro_target.nro_path)) {
set_susp = true;
}
}
}
this->itemsMenu->AddItem(cfg::GetRecordIconPath(itm));
if(set_susp) {
u32 suspidx = tmpidx;
// Skip initial item if homebrew mode
if(this->homebrew_mode) {
suspidx++;
}
// Ignore front folders from main menu
else if(name.empty()) {
suspidx += g_EntryList.folders.size();
}
this->itemsMenu->SetSuspendedItem(suspidx);
}
tmpidx++;
}
this->itemsMenu->UpdateBorderIcons();
if(!this->homebrew_mode) {
this->curfolder = name;
}
};
this->itemsMenu->SetSelectedItem(0);
if(fade) {
g_MenuApplication->FadeIn();
g_TransitionGuard.Run([&]() {
g_MenuApplication->FadeOut();
MoveFolderImpl();
g_MenuApplication->FadeIn();
});
}
else {
MoveFolderImpl();
}
}

View file

@ -8,8 +8,11 @@ extern ui::MenuApplication::Ref g_MenuApplication;
namespace ui {
static Mutex g_quick_menu_home_lock = EmptyMutex;
static bool g_quick_menu_home_pressed = false;
namespace {
std::atomic_bool g_HomePressed = false;
}
QuickMenu::QuickMenu(const std::string &main_icon) {
this->on = false;
@ -146,22 +149,18 @@ namespace ui {
}
}
else {
if(this->on) {
mutexLock(&g_quick_menu_home_lock);
auto home_pressed = g_quick_menu_home_pressed;
g_quick_menu_home_pressed = false;
mutexUnlock(&g_quick_menu_home_lock);
if(home_pressed) {
if(g_HomePressed) {
if(this->on) {
this->Toggle();
}
g_HomePressed = false;
}
}
}
void QuickMenuOnHomeButtonDetection() {
mutexLock(&g_quick_menu_home_lock);
g_quick_menu_home_pressed = true;
mutexUnlock(&g_quick_menu_home_lock);
g_HomePressed = true;
}
}

View file

@ -8,6 +8,7 @@
#include <am/am_LibraryApplet.hpp>
extern ui::MenuApplication::Ref g_MenuApplication;
extern ui::TransitionGuard g_TransitionGuard;
extern cfg::Theme g_Theme;
extern cfg::Config g_Config;
@ -54,16 +55,20 @@ namespace ui {
void SettingsMenuLayout::OnMenuInput(u64 down, u64 up, u64 held, pu::ui::Touch pos) {
if(down & HidNpadButton_B) {
g_MenuApplication->FadeOut();
g_MenuApplication->LoadMenu();
g_MenuApplication->FadeIn();
g_TransitionGuard.Run([]() {
g_MenuApplication->FadeOut();
g_MenuApplication->LoadMenu();
g_MenuApplication->FadeIn();
});
}
}
void SettingsMenuLayout::OnHomeButtonPress() {
g_MenuApplication->FadeOut();
g_MenuApplication->LoadMenu();
g_MenuApplication->FadeIn();
bool SettingsMenuLayout::OnHomeButtonPress() {
return g_TransitionGuard.Run([]() {
g_MenuApplication->FadeOut();
g_MenuApplication->LoadMenu();
g_MenuApplication->FadeIn();
});
}
void SettingsMenuLayout::Reload() {
@ -185,9 +190,11 @@ namespace ui {
break;
}
case 3: {
g_MenuApplication->FadeOut();
g_MenuApplication->LoadSettingsLanguagesMenu();
g_MenuApplication->FadeIn();
g_TransitionGuard.Run([]() {
g_MenuApplication->FadeOut();
g_MenuApplication->LoadSettingsLanguagesMenu();
g_MenuApplication->FadeIn();
});
break;
}

View file

@ -5,6 +5,7 @@
#include <fs/fs_Stdio.hpp>
extern ui::MenuApplication::Ref g_MenuApplication;
extern ui::TransitionGuard g_TransitionGuard;
extern cfg::Theme g_Theme;
extern cfg::Config g_Config;
@ -33,14 +34,17 @@ namespace ui {
if(this->loadmenu) {
this->loadmenu = false;
g_MenuApplication->StartPlayBGM();
g_MenuApplication->FadeOut();
g_MenuApplication->LoadMenu();
g_MenuApplication->FadeIn();
g_TransitionGuard.Run([]() {
g_MenuApplication->FadeOut();
g_MenuApplication->LoadMenu();
g_MenuApplication->FadeIn();
});
}
}
void StartupLayout::OnHomeButtonPress() {
bool StartupLayout::OnHomeButtonPress() {
// ...
return true;
}
void StartupLayout::user_Click(AccountUid uid) {
@ -51,9 +55,11 @@ namespace ui {
void StartupLayout::create_Click() {
auto rc = pselShowUserCreator();
if(R_SUCCEEDED(rc)) {
g_MenuApplication->FadeOut();
this->ReloadMenu();
g_MenuApplication->FadeIn();
g_TransitionGuard.Run([&]() {
g_MenuApplication->FadeOut();
this->ReloadMenu();
g_MenuApplication->FadeIn();
});
}
}

View file

@ -5,6 +5,7 @@
#include <fs/fs_Stdio.hpp>
extern ui::MenuApplication::Ref g_MenuApplication;
extern ui::TransitionGuard g_TransitionGuard;
extern cfg::Theme g_Theme;
extern cfg::Config g_Config;
@ -56,16 +57,20 @@ namespace ui {
void ThemeMenuLayout::OnMenuInput(u64 down, u64 up, u64 held, pu::ui::Touch touch_pos) {
if(down & HidNpadButton_B) {
g_MenuApplication->FadeOut();
g_MenuApplication->LoadMenu();
g_MenuApplication->FadeIn();
g_TransitionGuard.Run([]() {
g_MenuApplication->FadeOut();
g_MenuApplication->LoadMenu();
g_MenuApplication->FadeIn();
});
}
}
void ThemeMenuLayout::OnHomeButtonPress() {
g_MenuApplication->FadeOut();
g_MenuApplication->LoadMenu();
g_MenuApplication->FadeIn();
bool ThemeMenuLayout::OnHomeButtonPress() {
return g_TransitionGuard.Run([]() {
g_MenuApplication->FadeOut();
g_MenuApplication->LoadMenu();
g_MenuApplication->FadeIn();
});
}
void ThemeMenuLayout::Reload() {