A game about forced loneliness, made by TACStudios
at master 197 lines 8.1 kB view raw
1using System; 2using Unity.Multiplayer.Center.Analytics; 3using Unity.Multiplayer.Center.Common; 4using Unity.Multiplayer.Center.Questionnaire; 5using Unity.Multiplayer.Center.Recommendations; 6using Unity.Multiplayer.Center.Window.UI; 7using Unity.Multiplayer.Center.Window.UI.RecommendationView; 8using UnityEditor; 9using UnityEngine; 10using UnityEngine.UIElements; 11 12namespace Unity.Multiplayer.Center.Window 13{ 14 internal class RecommendationTabView : ITabView 15 { 16 QuestionnaireView m_QuestionnaireView; 17 RecommendationView m_RecommendationView; 18 19 RecommendationViewBottomBar m_BottomBarView; 20 21 bool m_IsVisible; 22 bool m_ShouldRefresh = true; 23 24 [SerializeField] 25 PreReleaseHandling m_PreReleaseHandling = new(); 26 27 [field: SerializeField] // Marked as redundant by Rider, but it is not. 28 public string Name { get; private set; } 29 30 public VisualElement RootVisualElement { get; set; } 31 public IMultiplayerCenterAnalytics MultiplayerCenterAnalytics { get; set; } 32 33 // Access to QuestionnaireView for testing purposes 34 internal QuestionnaireView QuestionnaireView => m_QuestionnaireView; 35 36 public RecommendationTabView(string name = "Recommendation") 37 { 38 Name = name; 39 m_PreReleaseHandling.OnAllChecksFinished += PatchData; 40 m_PreReleaseHandling.CheckForUpdates(); 41 Undo.undoRedoPerformed += OnUndoRedoPerformed; 42 } 43 44 void OnUndoRedoPerformed() 45 { 46 UserChoicesObject.instance.Save(); 47 m_QuestionnaireView?.Refresh(); 48 UpdateRecommendation(keepSelection:true); 49 } 50 51 public void Clear() 52 { 53 Undo.undoRedoPerformed -= OnUndoRedoPerformed; 54 m_RecommendationView?.Clear(); 55 m_QuestionnaireView?.Clear(); 56 RootVisualElement?.Clear(); 57 m_QuestionnaireView = null; 58 m_RecommendationView = null; 59 } 60 61 public void SetVisible(bool visible) 62 { 63 RootVisualElement.style.display = visible ? DisplayStyle.Flex : DisplayStyle.None; 64 m_IsVisible = visible; 65 } 66 67 public void Refresh() 68 { 69 Debug.Assert(MultiplayerCenterAnalytics != null, "MultiplayerCenterAnalytics != null"); 70 RefreshPreReleaseHandling(); 71 if (!m_ShouldRefresh && RootVisualElement.childCount > 0) return; 72 CreateStandardView(); 73 m_ShouldRefresh = false; 74 } 75 76 void RefreshPreReleaseHandling() 77 { 78 if (!m_PreReleaseHandling.IsReady) 79 { 80 m_PreReleaseHandling.OnAllChecksFinished += PatchData; 81 m_PreReleaseHandling.CheckForUpdates(); 82 } 83 else 84 { 85 m_PreReleaseHandling.PatchRecommenderSystemData(); 86 } 87 } 88 89 void CreateStandardView() 90 { 91 Clear(); 92 Undo.undoRedoPerformed -= OnUndoRedoPerformed; 93 Undo.undoRedoPerformed += OnUndoRedoPerformed; 94 MigrateUserChoices(); 95 96 // We need this because Bottom bar is a part of the Recommendations Tab and it should always stay 97 // at the bottom of the view. So we need to make sure that the root tab element is always 100% height. 98 RootVisualElement.style.height = Length.Percent(100); 99 100 var horizontalContainer = new TwoPaneSplitView(0, 250, TwoPaneSplitViewOrientation.Horizontal); 101 horizontalContainer.AddToClassList(StyleClasses.MainSplitView); 102 horizontalContainer.name = "recommendation-tab-split-view"; 103 104 // This is used to make sure the left side does not grow to 100% as this is what would happen by default. 105 // It feels not 100% correct. But it seems to be the only way to match the height of the 2 sides with how 106 // our views are build currently. 107 horizontalContainer.contentContainer.style.position = Position.Relative; 108 109 m_QuestionnaireView = new QuestionnaireView(QuestionnaireObject.instance.Questionnaire); 110 m_QuestionnaireView.OnQuestionnaireDataChanged += HandleQuestionnaireDataChanged; 111 m_QuestionnaireView.OnPresetSelected += OnPresetSelected; 112 m_QuestionnaireView.Root.AddToClassList(StyleClasses.MainSplitViewLeft); 113 horizontalContainer.Add(m_QuestionnaireView.Root); 114 115 m_RecommendationView = new RecommendationView(); 116 m_RecommendationView.Root.AddToClassList(StyleClasses.MainSplitViewRight); 117 horizontalContainer.Add(m_RecommendationView.Root); 118 RootVisualElement.Add(horizontalContainer); 119 120 m_BottomBarView = new RecommendationViewBottomBar(MultiplayerCenterAnalytics); 121 m_RecommendationView.OnPackageSelectionChanged += 122 () => m_BottomBarView.UpdatePackagesToInstall(m_RecommendationView.CurrentRecommendation, m_RecommendationView.AllPackages); 123 RootVisualElement.Add(m_BottomBarView); 124 UpdateRecommendation(keepSelection: true); 125 126 m_BottomBarView.SetInfoTextForCheckingPackages(!m_PreReleaseHandling.IsReady); 127 } 128 129 void HandleQuestionnaireDataChanged() 130 { 131 UpdateRecommendation(keepSelection: false); 132 } 133 134 static void MigrateUserChoices() 135 { 136 var questionnaire = QuestionnaireObject.instance.Questionnaire; 137 var userChoices = UserChoicesObject.instance; 138 139 // make sure the version of the questionnaire is the same as the one in the user choices. 140 if (questionnaire.Version != userChoices.QuestionnaireVersion && userChoices.UserAnswers.Answers.Count > 0) 141 { 142 Logic.MigrateUserChoices(questionnaire, userChoices); 143 } 144 } 145 146 void UpdateRecommendation(bool keepSelection) 147 { 148 var questionnaire = QuestionnaireObject.instance.Questionnaire; 149 var userChoices = UserChoicesObject.instance; 150 151 var errors = Logic.ValidateAnswers(questionnaire, userChoices.UserAnswers); 152 foreach (var error in errors) 153 { 154 Debug.LogError(error); 155 } 156 157 var recommendation = userChoices.Preset == Preset.None? null 158 : RecommenderSystem.GetRecommendation(questionnaire, userChoices.UserAnswers); 159 m_PreReleaseHandling.PatchPackages(recommendation); 160 if (keepSelection) 161 { 162 RecommendationUtils.ApplyPreviousSelection(recommendation, userChoices.SelectedSolutions); 163 } 164 else if (recommendation != null) // we only send the event if there is a recommendation and it is a new one 165 { 166 MultiplayerCenterAnalytics.SendRecommendationEvent(userChoices.UserAnswers, userChoices.Preset); 167 } 168 169 m_RecommendationView.UpdateRecommendation(recommendation, m_PreReleaseHandling); 170 m_BottomBarView.UpdatePackagesToInstall(recommendation, m_RecommendationView.AllPackages); 171 } 172 173 void PatchData() 174 { 175 m_PreReleaseHandling.PatchRecommenderSystemData(); 176 m_PreReleaseHandling.OnAllChecksFinished -= PatchData; 177 m_ShouldRefresh = true; 178 if(m_IsVisible) 179 Refresh(); 180 } 181 182 void OnPresetSelected(Preset preset) 183 { 184 var (resultAnswerData, recommendation) = Logic.ApplyPresetToAnswerData( 185 UserChoicesObject.instance.UserAnswers, preset, QuestionnaireObject.instance.Questionnaire); 186 187 UserChoicesObject.instance.UserAnswers = resultAnswerData; 188 UserChoicesObject.instance.Save(); 189 190 if (recommendation != null) 191 MultiplayerCenterAnalytics.SendRecommendationEvent(resultAnswerData, preset); 192 193 m_QuestionnaireView.Refresh(); 194 m_RecommendationView.UpdateRecommendation(recommendation, m_PreReleaseHandling); 195 } 196 } 197}