A game about forced loneliness, made by TACStudios
1#if UNITY_EDITOR && UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
2using System;
3using System.Collections.Generic;
4using UnityEngine.UIElements;
5
6namespace UnityEngine.InputSystem.Editor
7{
8 internal interface IViewStateSelector<out TViewState>
9 {
10 bool HasStateChanged(InputActionsEditorState state);
11 TViewState GetViewState(InputActionsEditorState state);
12 }
13
14 internal interface IView
15 {
16 void UpdateView(InputActionsEditorState state);
17 void DestroyView();
18 }
19
20 internal abstract class ViewBase<TViewState> : IView
21 {
22 protected ViewBase(VisualElement root, StateContainer stateContainer)
23 {
24 this.rootElement = root;
25 this.stateContainer = stateContainer;
26 m_ChildViews = new List<IView>();
27 }
28
29 protected void OnStateChanged(InputActionsEditorState state)
30 {
31 UpdateView(state);
32 }
33
34 public void UpdateView(InputActionsEditorState state)
35 {
36 if (m_ViewStateSelector == null)
37 {
38 Debug.LogWarning(
39 $"View '{GetType().Name}' has no selector and will not render. Create a selector for the " +
40 $"view using the CreateSelector method.");
41 return;
42 }
43
44 if (m_ViewStateSelector.HasStateChanged(state) || m_IsFirstUpdate)
45 RedrawUI(m_ViewStateSelector.GetViewState(state));
46
47 m_IsFirstUpdate = false;
48 foreach (var view in m_ChildViews)
49 {
50 view.UpdateView(state);
51 }
52
53 // We can execute UI Commands now that the UI is fully updated
54 // NOTE: This isn't used with Input Commands
55 allowUICommandExecution = true;
56 }
57
58 public TView CreateChildView<TView>(TView view) where TView : IView
59 {
60 m_ChildViews.Add(view);
61 return view;
62 }
63
64 public void DestroyChildView<TView>(TView view) where TView : IView
65 {
66 if (view == null)
67 return;
68
69 m_ChildViews.Remove(view);
70 view.DestroyView();
71 }
72
73 public void Dispatch(Command command)
74 {
75 stateContainer.Dispatch(command);
76 }
77
78 public abstract void RedrawUI(TViewState viewState);
79
80 /// <summary>
81 /// Called when a parent view is destroying this view to give it an opportunity to clean up any
82 /// resources or event handlers.
83 /// </summary>
84 public virtual void DestroyView()
85 {
86 }
87
88 protected void CreateSelector(Func<InputActionsEditorState, TViewState> selector)
89 {
90 m_ViewStateSelector = new ViewStateSelector<TViewState>(selector);
91 }
92
93 protected void CreateSelector<T1>(
94 Func<InputActionsEditorState, T1> func1,
95 Func<T1, InputActionsEditorState, TViewState> selector)
96 {
97 m_ViewStateSelector = new ViewStateSelector<T1, TViewState>(func1, selector);
98 }
99
100 protected void CreateSelector<T1, T2>(
101 Func<InputActionsEditorState, T1> func1,
102 Func<InputActionsEditorState, T2> func2,
103 Func<T1, T2, InputActionsEditorState, TViewState> selector)
104 {
105 m_ViewStateSelector = new ViewStateSelector<T1, T2, TViewState>(func1, func2, selector);
106 }
107
108 protected void CreateSelector<T1, T2, T3>(
109 Func<InputActionsEditorState, T1> func1,
110 Func<InputActionsEditorState, T2> func2,
111 Func<InputActionsEditorState, T3> func3,
112 Func<T1, T2, T3, InputActionsEditorState, TViewState> selector)
113 {
114 m_ViewStateSelector = new ViewStateSelector<T1, T2, T3, TViewState>(func1, func2, func3, selector);
115 }
116
117 protected readonly VisualElement rootElement;
118 protected readonly StateContainer stateContainer;
119 protected bool allowUICommandExecution { get; set; } = true;
120
121 protected IViewStateSelector<TViewState> ViewStateSelector => m_ViewStateSelector;
122 private IViewStateSelector<TViewState> m_ViewStateSelector;
123 private IList<IView> m_ChildViews;
124 private bool m_IsFirstUpdate = true;
125 }
126
127 internal class ViewStateSelector<TReturn> : IViewStateSelector<TReturn>
128 {
129 private readonly Func<InputActionsEditorState, TReturn> m_Selector;
130
131 public ViewStateSelector(Func<InputActionsEditorState, TReturn> selector)
132 {
133 m_Selector = selector;
134 }
135
136 public bool HasStateChanged(InputActionsEditorState state)
137 {
138 return true;
139 }
140
141 public TReturn GetViewState(InputActionsEditorState state)
142 {
143 return m_Selector(state);
144 }
145 }
146
147 // TODO: Make all args to view state selectors IEquatable<T>?
148 internal class ViewStateSelector<T1, TReturn> : IViewStateSelector<TReturn>
149 {
150 private readonly Func<InputActionsEditorState, T1> m_Func1;
151 private readonly Func<T1, InputActionsEditorState, TReturn> m_Selector;
152
153 private T1 m_PreviousT1;
154
155 public ViewStateSelector(Func<InputActionsEditorState, T1> func1,
156 Func<T1, InputActionsEditorState, TReturn> selector)
157 {
158 m_Func1 = func1;
159 m_Selector = selector;
160 }
161
162 public bool HasStateChanged(InputActionsEditorState state)
163 {
164 var valueOne = m_Func1(state);
165
166 if (valueOne is IViewStateCollection collection)
167 {
168 if (collection.SequenceEqual((IViewStateCollection)m_PreviousT1))
169 return false;
170 }
171 else if (valueOne.Equals(m_PreviousT1))
172 {
173 return false;
174 }
175
176 m_PreviousT1 = valueOne;
177 return true;
178 }
179
180 public TReturn GetViewState(InputActionsEditorState state)
181 {
182 return m_Selector(m_PreviousT1, state);
183 }
184 }
185
186 internal class ViewStateSelector<T1, T2, TReturn> : IViewStateSelector<TReturn>
187 {
188 private readonly Func<InputActionsEditorState, T1> m_Func1;
189 private readonly Func<InputActionsEditorState, T2> m_Func2;
190 private readonly Func<T1, T2, InputActionsEditorState, TReturn> m_Selector;
191
192 private T1 m_PreviousT1;
193 private T2 m_PreviousT2;
194
195 public ViewStateSelector(Func<InputActionsEditorState, T1> func1,
196 Func<InputActionsEditorState, T2> func2,
197 Func<T1, T2, InputActionsEditorState, TReturn> selector)
198 {
199 m_Func1 = func1;
200 m_Func2 = func2;
201 m_Selector = selector;
202 }
203
204 public bool HasStateChanged(InputActionsEditorState state)
205 {
206 var valueOne = m_Func1(state);
207 var valueTwo = m_Func2(state);
208
209 var valueOneHasChanged = false;
210 var valueTwoHasChanged = false;
211
212 if (valueOne is IViewStateCollection collection && !collection.SequenceEqual((IViewStateCollection)m_PreviousT1) ||
213 !valueOne.Equals(m_PreviousT1))
214 valueOneHasChanged = true;
215
216 if (valueTwo is IViewStateCollection collection2 && !collection2.SequenceEqual((IViewStateCollection)m_PreviousT2) ||
217 !valueTwo.Equals(m_PreviousT2))
218 valueTwoHasChanged = true;
219
220 if (!valueOneHasChanged && !valueTwoHasChanged)
221 return false;
222
223 m_PreviousT1 = valueOne;
224 m_PreviousT2 = valueTwo;
225 return true;
226 }
227
228 public TReturn GetViewState(InputActionsEditorState state)
229 {
230 return m_Selector(m_PreviousT1, m_PreviousT2, state);
231 }
232 }
233
234 internal class ViewStateSelector<T1, T2, T3, TReturn> : IViewStateSelector<TReturn>
235 {
236 private readonly Func<InputActionsEditorState, T1> m_Func1;
237 private readonly Func<InputActionsEditorState, T2> m_Func2;
238 private readonly Func<InputActionsEditorState, T3> m_Func3;
239 private readonly Func<T1, T2, T3, InputActionsEditorState, TReturn> m_Selector;
240
241 private T1 m_PreviousT1;
242 private T2 m_PreviousT2;
243 private T3 m_PreviousT3;
244
245 public ViewStateSelector(Func<InputActionsEditorState, T1> func1,
246 Func<InputActionsEditorState, T2> func2,
247 Func<InputActionsEditorState, T3> func3,
248 Func<T1, T2, T3, InputActionsEditorState, TReturn> selector)
249 {
250 m_Func1 = func1;
251 m_Func2 = func2;
252 m_Func3 = func3;
253 m_Selector = selector;
254 }
255
256 public bool HasStateChanged(InputActionsEditorState state)
257 {
258 var valueOne = m_Func1(state);
259 var valueTwo = m_Func2(state);
260 var valueThree = m_Func3(state);
261
262 var valueOneHasChanged = false;
263 var valueTwoHasChanged = false;
264 var valueThreeHasChanged = false;
265
266 if (valueOne is IViewStateCollection collection && !collection.SequenceEqual((IViewStateCollection)m_PreviousT1) ||
267 !valueOne.Equals(m_PreviousT1))
268 valueOneHasChanged = true;
269
270 if (valueTwo is IViewStateCollection collection2 && !collection2.SequenceEqual((IViewStateCollection)m_PreviousT2) ||
271 !valueTwo.Equals(m_PreviousT2))
272 valueTwoHasChanged = true;
273
274 if (valueThree is IViewStateCollection collection3 && !collection3.SequenceEqual((IViewStateCollection)m_PreviousT3) ||
275 !valueThree.Equals(m_PreviousT3))
276 valueThreeHasChanged = true;
277
278 if (!valueOneHasChanged && !valueTwoHasChanged && !valueThreeHasChanged)
279 return false;
280
281 m_PreviousT1 = valueOne;
282 m_PreviousT2 = valueTwo;
283 m_PreviousT3 = valueThree;
284 return true;
285 }
286
287 public TReturn GetViewState(InputActionsEditorState state)
288 {
289 return m_Selector(m_PreviousT1, m_PreviousT2, m_PreviousT3, state);
290 }
291 }
292}
293
294#endif