diff --git a/UI/ControlMappingScreen.cpp b/UI/ControlMappingScreen.cpp index f69333a7c1..beda8e560b 100644 --- a/UI/ControlMappingScreen.cpp +++ b/UI/ControlMappingScreen.cpp @@ -266,6 +266,8 @@ UI::EventReturn ControlMappingScreen::OnAutoConfigure(UI::EventParams ¶ms) { } I18NCategory *km = GetI18NCategory("KeyMapping"); ListPopupScreen *autoConfList = new ListPopupScreen(km->T("Autoconfigure for device"), items, -1); + if (params.v) + autoConfList->SetPopupOrigin(params.v); screenManager()->push(autoConfList); return UI::EVENT_DONE; } diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index cfcf5ade41..19d9c98a01 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -287,6 +287,8 @@ UI::EventReturn LogConfigScreen::OnLogLevel(UI::EventParams &e) { auto logLevelScreen = new LogLevelScreen(dev->T("Log Level")); logLevelScreen->OnChoice.Handle(this, &LogConfigScreen::OnLogLevelChange); + if (e.v) + logLevelScreen->SetPopupOrigin(e.v); screenManager()->push(logLevelScreen); return UI::EVENT_DONE; } @@ -294,7 +296,7 @@ UI::EventReturn LogConfigScreen::OnLogLevel(UI::EventParams &e) { LogLevelScreen::LogLevelScreen(const std::string &title) : ListPopupScreen(title) { int NUMLOGLEVEL = 6; std::vector list; - for(int i = 0; i < NUMLOGLEVEL; ++i) { + for (int i = 0; i < NUMLOGLEVEL; ++i) { list.push_back(logLevelList[i]); } adaptor_ = UI::StringVectorListAdaptor(list, -1); diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 869c89171a..6ba78a0b47 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -792,7 +792,10 @@ void EmuScreen::CreateViews() { UI::EventReturn EmuScreen::OnDevTools(UI::EventParams ¶ms) { releaseButtons(); - screenManager()->push(new DevMenu()); + DevMenu *devMenu = new DevMenu(); + if (params.v) + devMenu->SetPopupOrigin(params.v); + screenManager()->push(devMenu); return UI::EVENT_DONE; } diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 2747ed9f82..ef4e1bf7bf 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1101,6 +1101,8 @@ UI::EventReturn GameSettingsScreen::OnLanguage(UI::EventParams &e) { I18NCategory *dev = GetI18NCategory("Developer"); auto langScreen = new NewLanguageScreen(dev->T("Language")); langScreen->OnChoice.Handle(this, &GameSettingsScreen::OnLanguageChange); + if (e.v) + langScreen->SetPopupOrigin(e.v); screenManager()->push(langScreen); return UI::EVENT_DONE; } @@ -1118,6 +1120,8 @@ UI::EventReturn GameSettingsScreen::OnPostProcShader(UI::EventParams &e) { I18NCategory *gr = GetI18NCategory("Graphics"); auto procScreen = new PostProcScreen(gr->T("Postprocessing Shader")); procScreen->OnChoice.Handle(this, &GameSettingsScreen::OnPostProcShaderChange); + if (e.v) + procScreen->SetPopupOrigin(e.v); screenManager()->push(procScreen); return UI::EVENT_DONE; } diff --git a/UI/SavedataScreen.cpp b/UI/SavedataScreen.cpp index d1d8d83a48..43a7869163 100644 --- a/UI/SavedataScreen.cpp +++ b/UI/SavedataScreen.cpp @@ -379,7 +379,11 @@ void SavedataScreen::CreateViews() { UI::EventReturn SavedataScreen::OnSavedataButtonClick(UI::EventParams &e) { GameInfo *ginfo = g_gameInfoCache->GetInfo(screenManager()->getDrawContext(), e.s, 0); - screenManager()->push(new SavedataPopupScreen(e.s, ginfo->GetTitle())); + SavedataPopupScreen *popupScreen = new SavedataPopupScreen(e.s, ginfo->GetTitle()); + if (e.v) { + popupScreen->SetPopupOrigin(e.v); + } + screenManager()->push(popupScreen); // the game path: e.s; return UI::EVENT_DONE; } diff --git a/ext/native/ui/ui_screen.cpp b/ext/native/ui/ui_screen.cpp index 0aeb411a7e..45726a3745 100644 --- a/ext/native/ui/ui_screen.cpp +++ b/ext/native/ui/ui_screen.cpp @@ -252,32 +252,51 @@ void PopupScreen::update() { static const int FRAMES_LEAD_IN = 6; static const int FRAMES_LEAD_OUT = 4; + float animatePos = 1.0f; + ++frames_; if (frames_ < FRAMES_LEAD_IN) { float leadIn = bezierEaseInOut(frames_ * (1.0f / (float)FRAMES_LEAD_IN)); - alpha_ = leadIn; - scale_.x = 0.9f + leadIn * 0.1f; - scale_.y = 0.9f + leadIn * 0.1f; - translation_.y = -dp_yres * (1.0f - leadIn) * 0.5f; + animatePos = leadIn; } else if (finishFrame_ > 0) { float leadOut = bezierEaseInOut((frames_ - finishFrame_) * (1.0f / (float)FRAMES_LEAD_OUT)); - alpha_ = 1.0f - leadOut; - scale_.x = 0.9f + (1.0f - leadOut) * 0.1f; - scale_.y = 0.9f + (1.0f - leadOut) * 0.1f; - translation_.y = -dp_yres * leadOut * 0.5f; + animatePos = 1.0f - leadOut; if (frames_ >= finishFrame_ + FRAMES_LEAD_OUT) { // Actual finish happens here. screenManager()->finishDialog(this, finishResult_); } + } + + if (animatePos < 1.0f) { + alpha_ = animatePos; + scale_.x = 0.9f + animatePos * 0.1f; + scale_.y = 0.9f + animatePos * 0.1f; + + if (hasPopupOrigin_) { + float xoff = popupOrigin_.x - dp_xres / 2; + float yoff = popupOrigin_.y - dp_yres / 2; + + // Pull toward the origin a bit. + translation_.x = xoff * (1.0f - animatePos) * 0.2f; + translation_.y = yoff * (1.0f - animatePos) * 0.2f; + } else { + translation_.y = -dp_yres * (1.0f - animatePos) * 0.2f; + } } else { alpha_ = 1.0f; scale_.x = 1.0f; scale_.y = 1.0f; + translation_.x = 0.0f; translation_.y = 0.0f; } } +void PopupScreen::SetPopupOrigin(const UI::View *view) { + hasPopupOrigin_ = true; + popupOrigin_ = view->GetBounds().Center(); +} + void PopupScreen::TriggerFinish(DialogResult result) { finishFrame_ = frames_; finishResult_ = result; @@ -391,6 +410,8 @@ UI::EventReturn PopupMultiChoice::HandleClick(UI::EventParams &e) { ListPopupScreen *popupScreen = new ListPopupScreen(ChopTitle(text_), choices, *value_ - minVal_, std::bind(&PopupMultiChoice::ChoiceCallback, this, std::placeholders::_1)); popupScreen->SetHiddenChoices(hidden_); + if (e.v) + popupScreen->SetPopupOrigin(e.v); screenManager_->push(popupScreen); return UI::EVENT_DONE; } @@ -470,6 +491,8 @@ EventReturn PopupSliderChoice::HandleClick(EventParams &e) { SliderPopupScreen *popupScreen = new SliderPopupScreen(value_, minValue_, maxValue_, ChopTitle(text_), step_, units_); popupScreen->OnChange.Handle(this, &PopupSliderChoice::HandleChange); + if (e.v) + popupScreen->SetPopupOrigin(e.v); screenManager_->push(popupScreen); return EVENT_DONE; } @@ -512,6 +535,8 @@ EventReturn PopupSliderChoiceFloat::HandleClick(EventParams &e) { SliderFloatPopupScreen *popupScreen = new SliderFloatPopupScreen(value_, minValue_, maxValue_, ChopTitle(text_), step_, units_); popupScreen->OnChange.Handle(this, &PopupSliderChoiceFloat::HandleChange); + if (e.v) + popupScreen->SetPopupOrigin(e.v); screenManager_->push(popupScreen); return EVENT_DONE; } @@ -719,6 +744,8 @@ EventReturn PopupTextInputChoice::HandleClick(EventParams &e) { TextEditPopupScreen *popupScreen = new TextEditPopupScreen(value_, placeHolder_, ChopTitle(text_), maxLen_); popupScreen->OnChange.Handle(this, &PopupTextInputChoice::HandleChange); + if (e.v) + popupScreen->SetPopupOrigin(e.v); screenManager_->push(popupScreen); return EVENT_DONE; } diff --git a/ext/native/ui/ui_screen.h b/ext/native/ui/ui_screen.h index fe93128ba6..c2f0275d66 100644 --- a/ext/native/ui/ui_screen.h +++ b/ext/native/ui/ui_screen.h @@ -74,6 +74,8 @@ public: virtual void TriggerFinish(DialogResult result) override; + void SetPopupOrigin(const UI::View *view); + protected: virtual bool FillVertical() const { return false; } virtual UI::Size PopupWidth() const { return 550; } @@ -92,6 +94,8 @@ private: int frames_ = 0; int finishFrame_ = 0; DialogResult finishResult_; + bool hasPopupOrigin_ = false; + Point popupOrigin_; }; class ListPopupScreen : public PopupScreen {