/* * Copyright 2022 Peter Han * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or * substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ using System; using UnityEngine; namespace PeterHan.PLib.UI.Layouts { /// /// Stores constraints applied to a game object in a relative layout. /// [Serializable] internal sealed class RelativeLayoutParams : RelativeLayoutParamsBase { } /// /// Stores constraints applied to an object in a relative layout. /// /// The type of the target object. internal class RelativeLayoutParamsBase { /// /// The anchored position of the bottom edge. /// internal EdgeStatus BottomEdge { get; } /// /// The insets. If null, insets are all zero. /// internal RectOffset Insets { get; set; } /// /// The anchored position of the left edge. /// internal EdgeStatus LeftEdge { get; } /// /// Overrides the size of the component if set. /// internal Vector2 OverrideSize { get; set; } /// /// The anchored position of the right edge. /// internal EdgeStatus RightEdge { get; } /// /// The anchored position of the top edge. /// internal EdgeStatus TopEdge { get; } internal RelativeLayoutParamsBase() { Insets = null; BottomEdge = new EdgeStatus(); LeftEdge = new EdgeStatus(); RightEdge = new EdgeStatus(); TopEdge = new EdgeStatus(); OverrideSize = Vector2.zero; } /// /// The edge position determined for a component. /// [Serializable] internal sealed class EdgeStatus { /// /// The type of constraint to use for this relative layout. /// internal RelativeConstraintType Constraint; /// /// The anchor position in the component that sets the relative anchor. /// /// 0.0f is the bottom/left, 1.0f is the top/right. /// internal float FromAnchor; /// /// The component to which this edge is anchored. /// internal T FromComponent; /// /// The offset in pixels from the anchor. + is upwards/rightwards, - is downwards/ /// leftwards. /// internal float Offset; /// /// True if the position has been locked down in the code. /// Locked should only be set by the layout manager, crashes may occur otherwise. /// public bool Locked { get { return Constraint == RelativeConstraintType.Locked; } } /// /// True if the position is not constrained to anything. /// public bool Unconstrained { get { return Constraint == RelativeConstraintType.Unconstrained; } } internal EdgeStatus() { FromAnchor = 0.0f; FromComponent = default; Offset = 0.0f; Constraint = RelativeConstraintType.Unconstrained; } /// /// Copies data from another edge status object. /// /// The object to copy. internal void CopyFrom(EdgeStatus other) { if (other == null) throw new ArgumentNullException(nameof(other)); switch (Constraint = other.Constraint) { case RelativeConstraintType.ToComponent: FromComponent = other.FromComponent; break; case RelativeConstraintType.ToAnchor: FromAnchor = other.FromAnchor; break; case RelativeConstraintType.Locked: FromAnchor = other.FromAnchor; Offset = other.Offset; break; case RelativeConstraintType.Unconstrained: default: break; } } public override bool Equals(object obj) { // Caution: floats are imprecise return obj is EdgeStatus other && other.FromAnchor == FromAnchor && other. Offset == Offset && Constraint == other.Constraint; } public override int GetHashCode() { return 37 * (37 * FromAnchor.GetHashCode() + Offset.GetHashCode()) + Constraint.GetHashCode(); } /// /// Resets these offsets to unlocked. /// public void Reset() { Constraint = RelativeConstraintType.Unconstrained; Offset = 0.0f; FromAnchor = 0.0f; FromComponent = default; } public override string ToString() { return string.Format("EdgeStatus[Constraints={2},Anchor={0:F2},Offset={1:F2}]", FromAnchor, Offset, Constraint); } } } /// /// The types of constraints which can be applied to components in a relative layout. /// internal enum RelativeConstraintType { Unconstrained, ToComponent, ToAnchor, Locked } }