Files
LuaCsForBarotraumaEP/Barotrauma/BarotraumaClient/ClientSource/GUI/GUICanvas.cs
Markus Isberg 856f894203 Build 0.18.9.0
2022-06-14 04:14:47 +09:00

118 lines
4.1 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Barotrauma.Extensions;
namespace Barotrauma
{
public class GUICanvas : RectTransform
{
private static readonly object mutex = new object();
protected GUICanvas() : base(size, parent: null) { }
private static GUICanvas _instance;
public static GUICanvas Instance
{
get
{
if (_instance == null)
{
_instance = new GUICanvas();
if (GameMain.Instance != null)
{
GameMain.Instance.ResolutionChanged += RecalculateSize;
}
_instance.ChildrenChanged += OnChildrenChanged;
}
return _instance;
}
}
//GUICanvas stores the children as weak references, to allow elements that we no longer need to get garbage collected
private readonly List<WeakReference<RectTransform>> childrenWeakRef = new List<WeakReference<RectTransform>>();
private static Vector2 size => new Vector2(GameMain.GraphicsWidth / (float)GUI.UIWidth, 1f);
protected override Rectangle NonScaledUIRect => UIRect;
private enum ResizeAxis { Both = 0, X = 1, Y = 2 }
private static void OnChildrenChanged(RectTransform _)
{
lock (mutex)
{
//add weak reference if we don't have one yet
foreach (var child in _instance.Children)
{
if (!_instance.childrenWeakRef.Any(c => c.TryGetTarget(out var existingChild) && existingChild == child))
{
_instance.childrenWeakRef.Add(new WeakReference<RectTransform>(child));
}
}
//get rid of strong references
_instance.children.Clear();
//remove dead children
for (int i = _instance.childrenWeakRef.Count - 2; i >= 0; i--)
{
if (!_instance.childrenWeakRef[i].TryGetTarget(out var child) || child.Parent != _instance)
{
_instance.childrenWeakRef.RemoveAt(i);
}
}
}
}
// Turn public, if there is a need to call this manually.
private static void RecalculateSize()
{
Vector2 recalculatedSize = size;
// Scale children that are supposed to encompass the whole screen so that they are properly scaled on ultrawide as well
for (int i = 0; i < Instance.childrenWeakRef.Count; i++)
{
if (!_instance.childrenWeakRef[i].TryGetTarget(out RectTransform target) || target == null) { continue; };
_instance.children.Add(target);
if (target.RelativeSize.X < 1 && target.RelativeSize.Y < 1) { continue; }
ResizeAxis axis;
if (target.RelativeSize.X >= 1 && target.RelativeSize.Y >= 1)
{
axis = ResizeAxis.Both;
}
else if (target.RelativeSize.X >= 1)
{
axis = ResizeAxis.X;
}
else
{
axis = ResizeAxis.Y;
}
switch (axis)
{
case ResizeAxis.Both:
target.RelativeSize = recalculatedSize;
break;
case ResizeAxis.X:
target.RelativeSize = new Vector2(recalculatedSize.X, target.RelativeSize.Y);
break;
case ResizeAxis.Y:
target.RelativeSize = new Vector2(target.RelativeSize.X, recalculatedSize.Y);
break;
}
}
Instance.Resize(size, resizeChildren: true);
Instance.GetAllChildren().Select(c => c.GUIComponent as GUITextBlock).ForEach(t => t?.SetTextPos());
_instance.children.Clear();
}
}
}