Client LuaCsForBarotrauma
GUICanvas.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using Microsoft.Xna.Framework;
6 
7 namespace Barotrauma
8 {
9  public class GUICanvas : RectTransform
10  {
11  protected GUICanvas() : base(Size, parent: null) { }
12 
13  private static GUICanvas _instance;
14  public static GUICanvas Instance
15  {
16  get
17  {
18  if (_instance == null)
19  {
20  _instance = new GUICanvas();
21  if (GameMain.Instance != null)
22  {
23  GameMain.Instance.ResolutionChanged += RecalculateSize;
24  }
25  _instance.ChildrenChanged += OnChildrenChanged;
26  }
27  return _instance;
28  }
29  }
30 
31  //GUICanvas stores the children as weak references, to allow elements that we no longer need to get garbage collected
32  private readonly List<WeakReference<RectTransform>> childrenWeakRef = new List<WeakReference<RectTransform>>();
33 
34  private static Vector2 Size => new Vector2(GameMain.GraphicsWidth / (float)GUI.UIWidth, 1f);
35 
36  protected override Rectangle NonScaledUIRect => UIRect;
37 
38  private enum ResizeAxis { Both = 0, X = 1, Y = 2 }
39 
40  private static void OnChildrenChanged(RectTransform _)
41  {
42  CrossThread.RequestExecutionOnMainThread(RefreshChildren);
43  }
44 
45  private static void RefreshChildren()
46  {
47  //add weak reference if we don't have one yet
48  foreach (var child in _instance.Children)
49  {
50  if (!_instance.childrenWeakRef.Any(c => c.TryGetTarget(out var existingChild) && existingChild == child))
51  {
52  _instance.childrenWeakRef.Add(new WeakReference<RectTransform>(child));
53  }
54  }
55  //get rid of strong references
56  _instance.children.Clear();
57  //remove dead children
58  for (int i = _instance.childrenWeakRef.Count - 1; i >= 0; i--)
59  {
60  if (!_instance.childrenWeakRef[i].TryGetTarget(out var child) || child.Parent != _instance)
61  {
62  _instance.childrenWeakRef.RemoveAt(i);
63  }
64  }
65  }
66 
67  // Turn public, if there is a need to call this manually.
68  private static void RecalculateSize()
69  {
70  Vector2 recalculatedSize = Size;
71 
72  // Scale children that are supposed to encompass the whole screen so that they are properly scaled on ultrawide as well
73  for (int i = 0; i < Instance.childrenWeakRef.Count; i++)
74  {
75  if (!_instance.childrenWeakRef[i].TryGetTarget(out RectTransform target) || target == null) { continue; };
76 
77  _instance.children.Add(target);
78 
79  if (target.RelativeSize.X < 1 && target.RelativeSize.Y < 1) { continue; }
80 
81  ResizeAxis axis;
82 
83  if (target.RelativeSize.X >= 1 && target.RelativeSize.Y >= 1)
84  {
85  axis = ResizeAxis.Both;
86  }
87  else if (target.RelativeSize.X >= 1)
88  {
89  axis = ResizeAxis.X;
90  }
91  else
92  {
93  axis = ResizeAxis.Y;
94  }
95 
96  switch (axis)
97  {
98  case ResizeAxis.Both:
99  target.RelativeSize = recalculatedSize;
100  break;
101 
102  case ResizeAxis.X:
103  target.RelativeSize = new Vector2(recalculatedSize.X, target.RelativeSize.Y);
104  break;
105 
106  case ResizeAxis.Y:
107  target.RelativeSize = new Vector2(target.RelativeSize.X, recalculatedSize.Y);
108  break;
109  }
110  }
111 
112  Instance.Resize(Size, resizeChildren: true);
113  Instance.GetAllChildren().Select(c => c.GUIComponent as GUITextBlock).ForEach(t => t?.SetTextPos());
114  _instance.children.Clear();
115  }
116  }
117 }
override Rectangle NonScaledUIRect
Definition: GUICanvas.cs:36
static GUICanvas Instance
Definition: GUICanvas.cs:15
static int GraphicsWidth
Definition: GameMain.cs:162
Action ResolutionChanged
NOTE: Use very carefully. You need to ensure that you ALWAYS unsubscribe from this when you no longer...
Definition: GameMain.cs:133
static GameMain Instance
Definition: GameMain.cs:144
IEnumerable< RectTransform > GetAllChildren()
Returns all child elements in the hierarchy.
readonly List< RectTransform > children
void Resize(Point absoluteSize, bool resizeChildren=true)
IEnumerable< RectTransform > Children
Action< RectTransform > ChildrenChanged
The element provided as the argument is the changed child. It may be new in the hierarchy or just rep...
RectTransform(Vector2 relativeSize, RectTransform parent, Anchor anchor=Anchor.TopLeft, Pivot? pivot=null, Point? minSize=null, Point? maxSize=null, ScaleBasis scaleBasis=ScaleBasis.Normal)