using UnityEngine; using UnityEngine.UI; namespace RoR2.UI; [RequireComponent(typeof(RectTransform))] [ExecuteAlways] public class ScaleToFitParentRect : MonoBehaviour, ILayoutSelfController, ILayoutController { private RectTransform rectTransform; private RectTransform parentRectTransform; public bool fitToWidth = true; public bool fitToHeight = true; public bool stretchUnfittedAxis; public Vector2 referenceSize = Vector2.zero; private Vector2 parentSize = Vector2.zero; private Vector2 postScaleStretchSize = Vector2.zero; private float desiredScale = 1f; public bool autoReferenceSize = true; private bool inApply; private void CacheComponents() { rectTransform = (RectTransform)base.transform; } private void Awake() { CacheComponents(); parentRectTransform = rectTransform.parent as RectTransform; } private void Start() { } private void OnTransformParentChanged() { parentRectTransform = rectTransform.parent as RectTransform; } private void RecalculateScale() { if ((bool)parentRectTransform) { parentSize = parentRectTransform.rect.size; float a = parentSize.x / referenceSize.x; float b = parentSize.y / referenceSize.y; if (fitToWidth && fitToHeight) { desiredScale = Mathf.Min(a, b); } else if (fitToWidth) { desiredScale = a; } else if (fitToHeight) { desiredScale = b; } else { desiredScale = 1f; } postScaleStretchSize = parentSize / desiredScale; if (float.IsNaN(postScaleStretchSize.x)) { postScaleStretchSize.x = 1f; } if (float.IsNaN(postScaleStretchSize.y)) { postScaleStretchSize.y = 1f; } } } private void OnRectTransformDimensionsChange() { if (!inApply) { Apply(); } } public void SetLayoutHorizontal() { RecalculateScale(); Vector3 localScale = rectTransform.localScale; if (localScale.x != desiredScale) { localScale.x = desiredScale; rectTransform.localScale = localScale; } if (stretchUnfittedAxis && !fitToWidth && rectTransform.rect.width != postScaleStretchSize.x) { rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, postScaleStretchSize.x); } } public void SetLayoutVertical() { RecalculateScale(); Vector3 localScale = rectTransform.localScale; if (localScale.y != desiredScale) { localScale.y = desiredScale; rectTransform.localScale = localScale; } if (stretchUnfittedAxis && !fitToHeight && rectTransform.rect.height != postScaleStretchSize.y) { rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, postScaleStretchSize.y); } } public void Apply() { if (!base.enabled || (object)rectTransform == null) { return; } RecalculateScale(); inApply = true; Vector3 localScale = rectTransform.localScale; if (localScale.x != desiredScale && desiredScale != 0f) { localScale.x = desiredScale; localScale.y = desiredScale; rectTransform.localScale = localScale; } if (stretchUnfittedAxis) { Rect rect = rectTransform.rect; if (!fitToWidth && rect.width != postScaleStretchSize.x) { rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, postScaleStretchSize.x); } if (!fitToWidth && rect.height != postScaleStretchSize.y) { rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, postScaleStretchSize.y); } } inApply = false; } private void OnValidate() { CacheComponents(); parentRectTransform = rectTransform.parent as RectTransform; if (autoReferenceSize) { referenceSize = rectTransform.rect.size; } Apply(); } }