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}