瀏覽代碼

Search is working. Last search term is saved in the settings file.

Stephen Damm 6 年之前
父節點
當前提交
1ac2469f4b

+ 4 - 2
SongBrowserPlugin/DataAccess/SongBrowserSettings.cs

@@ -16,13 +16,15 @@ namespace SongBrowserPlugin.DataAccess
         Newest,
         PlayCount,
         Random,
+        Search
     }
 
     [Serializable]
     public class SongBrowserSettings
     {
         public SongSortMode sortMode = default(SongSortMode);
-        public List<String> favorites;
+        public List<String> favorites = default(List<String>);
+        public List<String> searchTerms = default(List<String>);
 
         [NonSerialized]
         private static Logger Log = new Logger("SongBrowserSettings");
@@ -32,7 +34,7 @@ namespace SongBrowserPlugin.DataAccess
         /// </summary>
         public SongBrowserSettings()
         {
-            favorites = new List<String>();
+            //favorites = new List<String>();
         }
 
         /// <summary>

+ 1 - 0
SongBrowserPlugin/Logger.cs

@@ -11,6 +11,7 @@ namespace SongBrowserPlugin
         Warn,
         Error
     }
+
     public class Logger
     {
         private string loggerName;

+ 3 - 5
SongBrowserPlugin/SongBrowserApplication.cs

@@ -13,6 +13,7 @@ namespace SongBrowserPlugin
 {
     public class SongBrowserApplication : MonoBehaviour
     {
+        // Which scene index to load into
         public const int MenuIndex = 1;
 
         public static SongBrowserApplication Instance;
@@ -22,7 +23,6 @@ namespace SongBrowserPlugin
         // Song Browser UI Elements
         private SongBrowserUI _songBrowserUI;
         public Dictionary<String, Sprite> CachedIcons;
-        //public Button PlayButtonTemplate;
 
         /// <summary>
         /// 
@@ -49,7 +49,7 @@ namespace SongBrowserPlugin
         }
 
         /// <summary>
-        /// 
+        /// Acquire any UI elements from Beat saber that we need.  Wait for the song list to be loaded.
         /// </summary>
         public void Start()
         {
@@ -122,8 +122,6 @@ namespace SongBrowserPlugin
                     CachedIcons.Add(sprite.name, sprite);
                 }
 
-                //PlayButtonTemplate = Resources.FindObjectsOfTypeAll<Button>().First(x => (x.name == "PlayButton"));
-
                 // Append our own event to appropriate events so we can refresh the song list before the user sees it.
                 MainFlowCoordinator mainFlow = Resources.FindObjectsOfTypeAll<MainFlowCoordinator>().First();
                 SoloModeSelectionViewController view = Resources.FindObjectsOfTypeAll<SoloModeSelectionViewController>().First();                
@@ -150,7 +148,7 @@ namespace SongBrowserPlugin
         /// Helper for invoking buttons.
         /// </summary>
         /// <param name="buttonName"></param>
-        private void InvokeBeatSaberButton(String buttonName)
+        public static void InvokeBeatSaberButton(String buttonName)
         {
             Button buttonInstance = Resources.FindObjectsOfTypeAll<Button>().First(x => (x.name == buttonName));
             buttonInstance.onClick.Invoke();

+ 23 - 2
SongBrowserPlugin/SongBrowserModel.cs

@@ -99,8 +99,7 @@ namespace SongBrowserPlugin
             }
 
             // Update song Infos
-            this.UpdateSongInfos(gameplayMode);
-                                
+            this.UpdateSongInfos(gameplayMode);                                
             this.ProcessSongList(gameplayMode);                       
         }
 
@@ -218,6 +217,28 @@ namespace SongBrowserPlugin
                         .OrderBy(x => rnd.Next())
                         .ToList();
                     break;
+                case SongSortMode.Search:
+                    // Make sure we can actually search.
+                    if (this._settings.searchTerms.Count <= 0)
+                    {
+                        _log.Error("Tried to search for a song with no valid search terms...");
+                        break;
+                    }
+                    string searchTerm = this._settings.searchTerms[0];
+                    if (String.IsNullOrEmpty(searchTerm))
+                    {
+                        _log.Error("Empty search term entered.");
+                        break;
+                    }
+
+                    _log.Info("Sorting song list by search term: {0}", searchTerm);
+                    //_originalSongs.ForEach(x => _log.Debug($"{x.songName} {x.songSubName} {x.songAuthorName}".ToLower().Contains(searchTerm.ToLower()).ToString()));
+
+                    _sortedSongs = _originalSongs
+                        .AsQueryable()
+                        .Where(x => $"{x.songName} {x.songSubName} {x.songAuthorName}".ToLower().Contains(searchTerm.ToLower()))
+                        .ToList();
+                    break;
                 case SongSortMode.Default:
                 default:
                     _log.Info("Sorting song list as default (songName)");

+ 2 - 0
SongBrowserPlugin/SongBrowserPlugin.csproj

@@ -90,6 +90,8 @@
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="SongBrowserModel.cs" />
     <Compile Include="DataAccess\SongBrowserSettings.cs" />
+    <Compile Include="UI\CustomUIKeyboard.cs" />
+    <Compile Include="UI\SearchKeyboardViewController.cs" />
     <Compile Include="UI\SongBrowserUI.cs" />
     <Compile Include="UI\SongSortButton.cs" />
     <Compile Include="UI\UIBuilder.cs" />

+ 84 - 26
SongBrowserPlugin/UI/SongBrowserUI.cs

@@ -45,6 +45,8 @@ namespace SongBrowserPlugin.UI
         private Button _deleteButton;        
         private Button _pageUpTenPercent;
         private Button _pageDownTenPercent;
+        private SearchKeyboardViewController _searchViewController;
+
 
         // Debug
         private int _sortButtonLastPushedIndex = 0;
@@ -150,22 +152,6 @@ namespace SongBrowserPlugin.UI
                 
                 Sprite arrowIcon = SongBrowserApplication.Instance.CachedIcons["ArrowIcon"];
 
-                System.Action<SongSortMode> onSortButtonClickEvent = delegate (SongSortMode sortMode) {
-                    _log.Debug("Sort button - {0} - pressed.", sortMode.ToString());
-                    SongBrowserModel.LastSelectedLevelId = null;
-
-                    if (_model.Settings.sortMode == sortMode)
-                    {
-                        _model.ToggleInverting();
-                    }
-
-                    _model.Settings.sortMode = sortMode;
-                    _model.Settings.Save();
-
-                    UpdateSongList();
-                    RefreshSongList();
-                };
-
                 float fontSize = 2.75f;
                 float buttonWidth = 17.0f;
                 float buttonHeight = 5.0f;
@@ -174,18 +160,23 @@ namespace SongBrowserPlugin.UI
 
                 string[] buttonNames = new string[]
                 {
-                    "Favorite", "Song", "Author", "Original", "Newest", "PlayCount", "Random"
+                    "Favorite", "Song", "Author", "Original", "Newest", "PlayCount", "Random", "Search"
                 };
 
                 SongSortMode[] sortModes = new SongSortMode[]
                 {
-                    SongSortMode.Favorites, SongSortMode.Default, SongSortMode.Author, SongSortMode.Original, SongSortMode.Newest, SongSortMode.PlayCount, SongSortMode.Random
+                    SongSortMode.Favorites, SongSortMode.Default, SongSortMode.Author, SongSortMode.Original, SongSortMode.Newest, SongSortMode.PlayCount, SongSortMode.Random, SongSortMode.Search
+                };
+
+                System.Action<SongSortMode>[] onClickEvents = new Action<SongSortMode>[]
+                {
+                    onSortButtonClickEvent, onSortButtonClickEvent, onSortButtonClickEvent, onSortButtonClickEvent, onSortButtonClickEvent, onSortButtonClickEvent, onSortButtonClickEvent, onSearchButtonClickEvent
                 };
 
                 _sortButtonGroup = new List<SongSortButton>();
                 for (int i = 0; i < buttonNames.Length; i++)
                 {
-                    _sortButtonGroup.Add(UIBuilder.CreateSortButton(sortButtonTransform, sortButtonTemplate, arrowIcon, buttonNames[i], fontSize, buttonX, buttonY, buttonWidth, buttonHeight, sortModes[i], onSortButtonClickEvent));
+                    _sortButtonGroup.Add(UIBuilder.CreateSortButton(sortButtonTransform, sortButtonTemplate, arrowIcon, buttonNames[i], fontSize, buttonX, buttonY, buttonWidth, buttonHeight, sortModes[i], onClickEvents[i]));
                     buttonX -= buttonWidth;
                 }
 
@@ -244,6 +235,38 @@ namespace SongBrowserPlugin.UI
         }
 
         /// <summary>
+        /// 
+        /// </summary>
+        private void onSortButtonClickEvent(SongSortMode sortMode)
+        {
+            _log.Debug("Sort button - {0} - pressed.", sortMode.ToString());
+            SongBrowserModel.LastSelectedLevelId = null;
+
+            if (_model.Settings.sortMode == sortMode)
+            {
+                _model.ToggleInverting();
+            }
+
+            _model.Settings.sortMode = sortMode;
+            _model.Settings.Save();
+
+            UpdateSongList();
+            RefreshSongList();
+        }
+
+        /// <summary>
+        /// Saerch button clicked.  
+        /// </summary>
+        /// <param name="sortMode"></param>
+        private void onSearchButtonClickEvent(SongSortMode sortMode)
+        {
+            _model.Settings.sortMode = sortMode;
+            _model.Settings.Save();
+
+            this.ShowSearchKeyboard();
+        }
+
+        /// <summary>
         /// Adjust UI based on level selected.
         /// Various ways of detecting if a level is not properly selected.  Seems most hit the first one.
         /// </summary>
@@ -386,6 +409,42 @@ namespace SongBrowserPlugin.UI
         }
 
         /// <summary>
+        /// Display the search keyboard
+        /// </summary>
+        void ShowSearchKeyboard()
+        {
+            if (_searchViewController == null)
+            {
+                _searchViewController = UIBuilder.CreateViewController<SearchKeyboardViewController>("SearchKeyboardViewController");
+                _searchViewController.searchButtonPressed += SearchViewControllerSearchButtonPressed;
+                _searchViewController.backButtonPressed += SearchViewControllerbackButtonPressed;
+            }
+
+            _levelListViewController.navigationController.PresentModalViewController(_searchViewController, null, false);
+        }
+
+        /// <summary>
+        /// Handle back button event from search keyboard.
+        /// </summary>
+        private void SearchViewControllerbackButtonPressed()
+        {
+ 
+        }
+
+        /// <summary>
+        /// Handle search.
+        /// </summary>
+        /// <param name="searchFor"></param>
+        private void SearchViewControllerSearchButtonPressed(string searchFor)
+        {
+            _log.Debug("Searching for \"{0}\"...", searchFor);
+
+            _model.Settings.searchTerms.Add(searchFor);
+            this.UpdateSongList();
+            this.RefreshSongList();
+        }
+
+        /// <summary>
         /// Make big jumps in the song list.
         /// </summary>
         /// <param name="numJumps"></param>
@@ -434,7 +493,7 @@ namespace SongBrowserPlugin.UI
         }
 
         /// <summary>
-        /// 
+        /// Update interactive state of the quick scroll buttons.
         /// </summary>
         private void RefreshQuickScrollButtons()
         {
@@ -476,12 +535,8 @@ namespace SongBrowserPlugin.UI
             foreach (SongSortButton sortButton in _sortButtonGroup)
             {
                 UIBuilder.SetButtonBorder(ref sortButton.Button, Color.black);
-                //UIBuilder.SetButtonIconEnabled(ref sortButton.Button, false);
                 if (sortButton.SortMode == _model.Settings.sortMode)
                 {
-                    //UIBuilder.SetButtonIcon(ref sortButton.Button, SongBrowserApplication.Instance.CachedIcons["ArrowIcon"]);
-                    //UIBuilder.SetButtonIconEnabled(ref sortButton.Button, true);
-
                     if (_model.InvertingResults)
                     {
                         UIBuilder.SetButtonBorder(ref sortButton.Button, Color.red);
@@ -510,7 +565,6 @@ namespace SongBrowserPlugin.UI
 
                 StandardLevelSO[] levels = _model.SortedSongList.ToArray();
                 StandardLevelListViewController songListViewController = this._levelSelectionFlowCoordinator.GetPrivateField<StandardLevelListViewController>("_levelListViewController");
-                //StandardLevelListTableView _songListTableView = songListViewController.GetComponentInChildren<StandardLevelListTableView>();
                 ReflectionUtil.SetPrivateField(_levelListTableView, "_levels", levels);
                 ReflectionUtil.SetPrivateField(songListViewController, "_levels", levels);            
                 TableView tableView = ReflectionUtil.GetPrivateField<TableView>(_levelListTableView, "_tableView");
@@ -597,6 +651,11 @@ namespace SongBrowserPlugin.UI
                     _sortButtonGroup[_sortButtonLastPushedIndex].Button.onClick.Invoke();
                 }
 
+                if (Input.GetKeyDown(KeyCode.S))
+                {
+                    onSortButtonClickEvent(SongSortMode.Search);
+                }
+
                 // select current sort mode again (toggle inverting)
                 if (Input.GetKeyDown(KeyCode.Y))
                 {
@@ -653,7 +712,6 @@ namespace SongBrowserPlugin.UI
                     this.SelectAndScrollToLevel(_levelListTableView, _model.SortedSongList[_lastRow].levelID);
                 }
 
-
                 // add to favorites
                 if (Input.GetKeyDown(KeyCode.F))
                 {

+ 33 - 11
SongBrowserPlugin/UI/UIBuilder.cs

@@ -45,11 +45,22 @@ namespace SongBrowserPlugin.UI
         public static T CreateFlowCoordinator<T>(string name) where T : FlowCoordinator
         {
             T vc = new GameObject(name).AddComponent<T>();
-
             return vc;
         }
 
         /// <summary>
+        /// Helper, create a UI button from template name.
+        /// </summary>
+        /// <param name="parent"></param>
+        /// <param name="buttonTemplateName"></param>
+        /// <returns></returns>
+        static public Button CreateUIButton(RectTransform parent, String buttonTemplateName)
+        {
+            Button b = Resources.FindObjectsOfTypeAll<Button>().First(x => (x.name == buttonTemplateName));
+            return CreateUIButton(parent, b);
+        }
+
+        /// <summary>
         /// Clone a Unity Button into a Button we control.
         /// </summary>
         /// <param name="parent"></param>
@@ -104,6 +115,20 @@ namespace SongBrowserPlugin.UI
             return sortButton;
         }
 
+        /// <summary>
+        /// Create a page up/down button.
+        /// </summary>
+        /// <param name="parent"></param>
+        /// <param name="buttonTemplate"></param>
+        /// <param name="iconSprite"></param>
+        /// <param name="x"></param>
+        /// <param name="y"></param>
+        /// <param name="w"></param>
+        /// <param name="h"></param>
+        /// <param name="iconWidth"></param>
+        /// <param name="iconHeight"></param>
+        /// <param name="iconRotation"></param>
+        /// <returns></returns>
         public static Button CreatePageButton(RectTransform parent, Button buttonTemplate, Sprite iconSprite, float x, float y, float w, float h, float iconWidth, float iconHeight, float iconRotation)
         {
             Button newButton = UIBuilder.CreateUIButton(parent, buttonTemplate);
@@ -122,8 +147,6 @@ namespace SongBrowserPlugin.UI
             iconTransform.localScale = new Vector2(2f, 2f);
             iconTransform.anchoredPosition = new Vector2(0, 0);
             iconTransform.Rotate(0, 0, iconRotation);
-            //button.GetComponentsInChildren<Image>().First(x => x.name == "Icon").transform.Rotate(0, 0, 90);
-            //  iconTransform.anchoredPosition = new Vector2(buttonTransform.anchoredPosition.x, buttonTransform.anchoredPosition.y);
 
             UnityEngine.Object.Destroy(newButton.GetComponentsInChildren<RectTransform>(true).First(c => c.name == "Text").gameObject);
 
@@ -133,14 +156,15 @@ namespace SongBrowserPlugin.UI
         }
 
         /// <summary>
-        /// 
+        /// Create a beat saber dismiss button.
         /// </summary>
-        /// <param name="button"></param>
-        /// <param name="s"></param>
-        public static void CreateIconForButton(ref Button button, Sprite s)
+        /// <param name="parent"></param>
+        /// <returns></returns>
+        public static Button CreateBackButton(RectTransform parent)
         {
-            RectTransform buttonTransform = button.transform as RectTransform;
-            
+            Button dismissButton = CreateUIButton(parent, "BackArrowButton");  //UnityEngine.Object.Instantiate(Resources.FindObjectsOfTypeAll<Button>().First(x => (x.name == "BackArrowButton")), parent, false);
+            dismissButton.onClick.RemoveAllListeners();            
+            return dismissButton;
         }
 
         /// <summary>
@@ -177,7 +201,6 @@ namespace SongBrowserPlugin.UI
             {
                 button.GetComponentInChildren<TextMeshProUGUI>().text = text;
             }
-
         }
 
         /// <summary>
@@ -215,7 +238,6 @@ namespace SongBrowserPlugin.UI
         {
             if (button.GetComponentsInChildren<UnityEngine.UI.Image>().Count() > 1)
             {
-                //button.GetComponentsInChildren<Image>().First(x => x.name == "Icon").gameObject.SetActive(enabled);
                 button.GetComponentsInChildren<UnityEngine.UI.Image>()[1].enabled = enabled;
             }
         }