소스 검색

Fix mods not getting restored properly

kiwec 3 달 전
부모
커밋
9a8affc533
6개의 변경된 파일74개의 추가작업 그리고 9개의 파일을 삭제
  1. 3 4
      src/App/Osu/Beatmap.cpp
  2. 1 0
      src/App/Osu/Changelog.cpp
  3. 55 0
      src/App/Osu/ModSelector.cpp
  4. 11 0
      src/App/Osu/ModSelector.h
  5. 2 2
      src/App/Osu/Osu.h
  6. 2 3
      src/App/Osu/RoomScreen.cpp

+ 3 - 4
src/App/Osu/Beatmap.cpp

@@ -752,7 +752,7 @@ bool Beatmap::watch(FinishedScore score, double start_percent) {
     m_bContinueScheduled = false;
     unloadObjects();
 
-    osu->previous_mod_flags = osu->getScore()->getModsLegacy();
+    osu->previous_mods = osu->getModSelector()->getModSelection();
 
     osu->watched_user_name = score.playerName.c_str();
     osu->watched_user_id = score.player_id;
@@ -789,7 +789,7 @@ bool Beatmap::spectate() {
     osu->watched_user_name = user_info->name;
     is_spectating = true;
 
-    osu->previous_mod_flags = osu->getScore()->getModsLegacy();
+    osu->previous_mods = osu->getModSelector()->getModSelection();
 
     FinishedScore score;
     score.isLegacyScore = true;
@@ -1166,8 +1166,7 @@ void Beatmap::stop(bool quit) {
     }
 
     if(is_watching || is_spectating) {
-        osu->m_modSelector->resetMods();
-        osu->m_modSelector->enableModsFromFlags(osu->previous_mod_flags);
+        osu->getModSelector()->restoreMods(osu->previous_mods);
     }
 
     is_spectating = false;

+ 1 - 0
src/App/Osu/Changelog.cpp

@@ -31,6 +31,7 @@ Changelog::Changelog() : ScreenBackable() {
         UString::format("%.2f (%s, %s)", convar->getConVarByName("osu_version")->getFloat(), __DATE__, __TIME__);
     latest.changes.push_back("- Fixed beatmaps not getting selected properly in some cases");
     latest.changes.push_back("- Fixed crash when osu! folder couldn't be found");
+    latest.changes.push_back("- Fixed mod selection not being restored properly");
     latest.changes.push_back("- Fixed skin selection menu being drawn behind back button");
     changelogs.push_back(latest);
 

+ 55 - 0
src/App/Osu/ModSelector.cpp

@@ -1218,6 +1218,59 @@ u32 ModSelector::getModFlags() {
     return osu->getScore()->getModsLegacy();
 }
 
+ModSelection ModSelector::getModSelection() {
+    ModSelection selection;
+
+    selection.flags = getModFlags();
+    selection.fposu = convar->getConVarByName("osu_mod_fposu")->getBool();
+
+    for(auto slider : m_overrideSliders) {
+        selection.override_locks.push_back(slider.lock ? slider.lock->isChecked() : false);
+        selection.override_values.push_back(slider.cvar ? slider.cvar->getFloat() + 1.0f : 0.f);
+    }
+
+    for(auto mod : m_experimentalMods) {
+        selection.experimental.push_back(mod.cvar ? mod.cvar->getBool() : false);
+    }
+
+    return selection;
+}
+
+void ModSelector::restoreMods(ModSelection selection) {
+    // Reset buttons and sliders to clean state
+    resetMods();
+
+    // Override sliders
+    for(int i = 0; i < m_overrideSliders.size(); i++) {
+        if(m_overrideSliders[i].lock != NULL) {
+            m_overrideSliders[i].lock->setChecked(selection.override_locks[i]);
+        }
+        if(m_overrideSliders[i].cvar != NULL) {
+            m_overrideSliders[i].slider->setValue(selection.override_values[i], m_bVisible);
+        }
+    }
+
+    // Non-experimental mods
+    convar->getConVarByName("osu_mod_fposu")->setValue(selection.fposu);
+
+    // Experimental mods
+    for(int i = 0; i < m_experimentalMods.size(); i++) {
+        ConVar *cvar = m_experimentalMods[i].cvar;
+        CBaseUICheckbox *checkboxPointer = dynamic_cast<CBaseUICheckbox *>(m_experimentalMods[i].element);
+        if(checkboxPointer != NULL) {
+            // HACKHACK: we update both just in case because if the mod selector was not yet visible after a convar
+            // change (e.g. because of "Use mods") then the checkbox has not yet updated its internal state
+            checkboxPointer->setChecked(selection.experimental[i]);
+            if(cvar != NULL) cvar->setValue(selection.experimental[i]);
+        }
+    }
+
+    // Legacy mods
+    enableModsFromFlags(selection.flags);
+
+    // osu->updateMods() is already called by enableModsFromFlags()
+}
+
 void ModSelector::enableModsFromFlags(u32 flags) {
     if(flags & ModFlags::DoubleTime) {
         m_modButtonDoubletime->setOn(true, true);
@@ -1250,6 +1303,8 @@ void ModSelector::enableModsFromFlags(u32 flags) {
     getModButtonOnGrid(4, 2)->setOn(flags & ModFlags::Target, true);
     m_modButtonFlashlight->setOn(flags & ModFlags::Flashlight, true);
     m_modButtonScoreV2->setOn(flags & ModFlags::ScoreV2, true);
+
+    osu->updateMods();
 }
 
 void ModSelector::close() {

+ 11 - 0
src/App/Osu/ModSelector.h

@@ -19,6 +19,14 @@ class UICheckbox;
 
 class ConVar;
 
+struct ModSelection {
+    u32 flags;
+    bool fposu;
+    std::vector<bool> override_locks;
+    std::vector<float> override_values;
+    std::vector<bool> experimental;
+};
+
 class ModSelector : public OsuScreen {
    public:
     ModSelector();
@@ -41,6 +49,9 @@ class ModSelector : public OsuScreen {
     u32 getModFlags();
     void enableModsFromFlags(u32 flags);
 
+    ModSelection getModSelection();
+    void restoreMods(ModSelection selection);
+
     void setWaitForF1KeyUp(bool waitForF1KeyUp) { m_bWaitForF1KeyUp = waitForF1KeyUp; }
 
     bool isInCompactMode();

+ 2 - 2
src/App/Osu/Osu.h

@@ -1,6 +1,7 @@
 #pragma once
 #include "App.h"
 #include "BanchoNetworking.h"
+#include "ModSelector.h"
 #include "MouseListener.h"
 #include "score.h"
 
@@ -15,7 +16,6 @@ class UIUserContextMenuScreen;
 class MainMenu;
 class PauseMenu;
 class OptionsMenu;
-class ModSelector;
 class SongBrowser;
 class SpectatorScreen;
 class BackgroundImageHandler;
@@ -274,7 +274,7 @@ class Osu : public App, public MouseListener {
     bool holding_slider = false;
 
     // mods
-    u32 previous_mod_flags = 0;   // mod flags before spectating/multiplaying/etc
+    ModSelection previous_mods;
     bool m_bModAutoTemp = false;  // when ctrl+clicking a map, the auto mod should disable itself after the map finishes
     bool m_bModAuto = false;
     bool m_bModAutopilot = false;

+ 2 - 3
src/App/Osu/RoomScreen.cpp

@@ -505,8 +505,7 @@ void RoomScreen::ragequit(bool play_sound) {
     osu->m_chat->removeChannel("#multiplayer");
     osu->m_chat->updateVisibility();
 
-    osu->m_modSelector->resetMods();
-    osu->m_modSelector->enableModsFromFlags(osu->previous_mod_flags);
+    osu->getModSelector()->restoreMods(osu->previous_mods);
 
     if(play_sound) {
         engine->getSound()->play(osu->getSkin()->m_menuBack);
@@ -592,7 +591,7 @@ void RoomScreen::on_room_joined(Room room) {
     osu->m_chat->addChannel("#multiplayer");
     osu->m_chat->updateVisibility();
 
-    osu->previous_mod_flags = osu->getScore()->getModsLegacy();
+    osu->previous_mods = osu->getModSelector()->getModSelection();
 
     osu->m_modSelector->resetMods();
     osu->m_modSelector->enableModsFromFlags(bancho.room.mods);