A game about forced loneliness, made by TACStudios
1using System; 2using System.Collections.Generic; 3using Unity.Multiplayer.Center.Common; 4using Unity.Multiplayer.Center.Questionnaire; 5using Unity.Multiplayer.Center.Recommendations; 6using UnityEditor; 7using UnityEditor.UIElements; 8using UnityEngine; 9using UnityEngine.UIElements; 10 11namespace Unity.Multiplayer.Center.Window.UI 12{ 13 /// <summary> 14 /// Questions that go together in the Questionnaire view. 15 /// Example: mandatory questions in "Game Specs" section, optional questions in "Advanced" section. 16 /// </summary> 17 internal class QuestionSection : VisualElement 18 { 19 EnumField m_PresetDropdown; 20 public VisualElement ContentRoot { get; private set; } 21 public event Action<AnsweredQuestion> QuestionUpdated; 22 23 public event Action<Preset> OnPresetSelected; 24 25 const string k_AdvancedFoldoutName = "advanced-questions"; 26 27 public void CreateAdvancedFoldout(Question[] questions, IEnumerable<AnsweredQuestion> existingAnswers, string headerTitle) 28 { 29 var foldout = new Foldout 30 { 31 text = headerTitle, 32 name = k_AdvancedFoldoutName 33 }; 34 foreach (var question in questions) 35 { 36 if (question.IsMandatory) 37 continue; 38 39 foldout.Add(CreateSingleQuestionView(question, existingAnswers)); 40 } 41 42 ContentRoot.Insert(1, foldout); 43 } 44 45 public QuestionSection(Question[] questions, IEnumerable<AnsweredQuestion> existingAnswers, string headerTitle, 46 bool mandatoryQuestions) 47 { 48 var title = new VisualElement(); 49 title.Add(new Label() {text = headerTitle}); 50 title.AddToClassList(StyleClasses.ViewHeadline); 51 Add(title); 52 53 ContentRoot = CreateContentRoot(true); 54 55 Add(ContentRoot); 56 57 for (var index = 0; index < questions.Length; index++) 58 { 59 if ((!mandatoryQuestions && questions[index].IsMandatory) || (mandatoryQuestions && !questions[index].IsMandatory)) 60 continue; 61 62 ContentRoot.Add(CreateSingleQuestionView(questions[index], existingAnswers)); 63 } 64 65 Undo.undoRedoPerformed += OnUndoRedoPerformed; 66 } 67 68 ~QuestionSection() 69 { 70 Undo.undoRedoPerformed -= OnUndoRedoPerformed; 71 } 72 73 void OnUndoRedoPerformed() 74 { 75 m_PresetDropdown?.SetValueWithoutNotify(UserChoicesObject.instance.Preset); 76 } 77 78 public void AddPresetView() 79 { 80 ContentRoot.Insert(0, CreatePresetView()); 81 } 82 83 static VisualElement CreateContentRoot(bool withScrollView) 84 { 85 if (!withScrollView) 86 return new VisualElement(); 87 88 var root = new ScrollView(); 89 root.horizontalScrollerVisibility = ScrollerVisibility.Hidden; 90 return root; 91 } 92 93 VisualElement CreateSingleQuestionView(Question question, IEnumerable<AnsweredQuestion> existingAnswers) 94 { 95 Logic.TryGetAnswerByQuestionId(existingAnswers, question.Id, out var existingAnswer); 96 existingAnswer ??= new AnsweredQuestion { QuestionId = question.Id }; 97 98 var questionView = GetQuestionHeader(question, out var questionContainer); 99 questionContainer.Add(QuestionViewFactory.CreateQuestionViewInput(question, existingAnswer, RaiseQuestionUpdated)); 100 return questionView; 101 } 102 103 static VisualElement GetQuestionHeader(Question question, out VisualElement inputContainer) 104 { 105 return QuestionViewFactory.StandardQuestionHeader(question, out inputContainer); 106 } 107 108 void RaiseQuestionUpdated(AnsweredQuestion question) 109 { 110 QuestionUpdated?.Invoke(question); 111 } 112 113 VisualElement CreatePresetView() 114 { 115 const string description = "Select the game genre that is the closest match to your project to generate common game specifications for this genre and recommended solutions. Recommendations are based solely on player count and game specifications."; 116 var presetQuestion = new Question() 117 {Title = "Genre of your Game", Description = description, IsMandatory = true}; 118 119 var questionView = GetQuestionHeader(presetQuestion, out var questionContainer); 120 questionContainer.Add(PresetDropdown()); 121 return questionView; 122 } 123 124 EnumField PresetDropdown() 125 { 126 m_PresetDropdown = new EnumField(UserChoicesObject.instance.Preset); 127 m_PresetDropdown.RegisterValueChangedCallback(RaiseValueChangedCallback); 128 m_PresetDropdown.name = "preset-dropdown"; 129 m_PresetDropdown.tooltip = "Select your game type"; 130 return m_PresetDropdown; 131 } 132 133 void RaiseValueChangedCallback(ChangeEvent<Enum> eventData) 134 { 135 if (!Equals(eventData.newValue, eventData.previousValue)) 136 { 137 Undo.RecordObject(UserChoicesObject.instance, "Selected Preset"); 138 var newVal = (Preset) eventData.newValue; 139 UserChoicesObject.instance.Preset = newVal; 140 OnPresetSelected?.Invoke(newVal); 141 } 142 } 143 144 public void SetAdvancedSectionVisible (bool isVisible){ 145 var advanced = ContentRoot.Q<Foldout>(k_AdvancedFoldoutName); 146 advanced.style.display = isVisible ? new StyleEnum<DisplayStyle>(DisplayStyle.Flex) : new StyleEnum<DisplayStyle>(DisplayStyle.None); 147 } 148 } 149}