using UnityEngine; // Shapes © Freya Holmér - https://twitter.com/FreyaHolmer/ // Website & Documentation - https://acegikmo.com/shapes/ namespace Shapes { /// A Rectangle shape component [ExecuteAlways] [AddComponentMenu( "Shapes/Rectangle" )] public partial class Rectangle : ShapeRenderer, IDashable, IFillable { /// Types of rectangles public enum RectangleType { /// Filled rectangle with hard corners HardSolid, /// Filled rectangle with rounded corners RoundedSolid, /// Border rectangle with hard corners HardBorder, /// Border rectangle with rounded corners RoundedBorder } /// Types of corners on rectangles public enum RectangleCornerRadiusMode { /// Use the same radius on all 4 corners Uniform, /// Use specific radii on a per-corner basis PerCorner } /// Whether or not this is a border rectangle public bool IsBorder => type == RectangleType.HardBorder || type == RectangleType.RoundedBorder; [System.Obsolete( "Please use IsBorder instead", true )] public bool IsHollow => type == RectangleType.HardBorder || type == RectangleType.RoundedBorder; /// Whether or not this rectangle has rounded corners public bool IsRounded => type == RectangleType.RoundedSolid || type == RectangleType.RoundedBorder; [SerializeField] RectPivot pivot = RectPivot.Center; /// Get or set where the pivot (0,0) should be located in this rectangle public RectPivot Pivot { get => pivot; set { pivot = value; UpdateRectPositioningNow(); } } [SerializeField] float width = 1f; /// The width of the rectangle public float Width { get => width; set { width = value; UpdateRectPositioningNow(); } } [SerializeField] float height = 1f; /// The height of the rectangle public float Height { get => height; set { height = value; UpdateRectPositioningNow(); } } [SerializeField] RectangleType type = RectangleType.HardSolid; /// Get or set what type of rectangle this is (border vs filled, hard vs rounded corners) public RectangleType Type { get => type; set { type = value; UpdateMaterial(); ApplyProperties(); } } [SerializeField] RectangleCornerRadiusMode cornerRadiusMode = RectangleCornerRadiusMode.Uniform; /// Whether or not you want to set radius on a per-corner basis or uniformly. Applies only to rounded rectangles public RectangleCornerRadiusMode CornerRadiusMode { get => cornerRadiusMode; set => cornerRadiusMode = value; } /// Radius is deprecated, please use CornerRadius instead [System.Obsolete( "Radius is deprecated, please use " + nameof(CornerRadius) + " instead", true )] public float Radius { get => CornerRadius; set => CornerRadius = value; } [SerializeField] Vector4 cornerRadii = new Vector4( 0.25f, 0.25f, 0.25f, 0.25f ); /// Gets or sets a radius for all 4 corners when rounded public float CornerRadius { get => cornerRadii.x; set { float r = Mathf.Max( 0f, value ); SetVector4Now( ShapesMaterialUtils.propCornerRadii, cornerRadii = new Vector4( r, r, r, r ) ); } } /// Gets or sets a specific radius for each corner when rounded. Order is clockwise from bottom left public Vector4 CornerRadii { get => cornerRadii; set => SetVector4Now( ShapesMaterialUtils.propCornerRadii, cornerRadii = new Vector4( Mathf.Max( 0f, value.x ), Mathf.Max( 0f, value.y ), Mathf.Max( 0f, value.z ), Mathf.Max( 0f, value.w ) ) ); } [System.Obsolete( "Please use CornerRadii instead because I did a typo~", true )] public Vector4 CornerRadiii { get => CornerRadii; set => CornerRadii = value; } [Tooltip( "The thickness of the rectangle, in the given thickness space" )] [SerializeField] float thickness = 0.1f; /// The thickness of the rectangle (if border rectangle) public float Thickness { get => thickness; set => SetFloatNow( ShapesMaterialUtils.propThickness, thickness = Mathf.Max( 0f, value ) ); } [Tooltip( "The space in which thickness is defined" )] [SerializeField] ThicknessSpace thicknessSpace = Shapes.ThicknessSpace.Meters; /// The space in which thickness is defined public ThicknessSpace ThicknessSpace { get => thicknessSpace; set => SetIntNow( ShapesMaterialUtils.propThicknessSpace, (int)( thicknessSpace = value ) ); } internal override bool HasDetailLevels => false; void UpdateRectPositioningNow() => SetVector4Now( ShapesMaterialUtils.propRect, GetPositioningRect() ); void UpdateRectPositioning() => SetVector4( ShapesMaterialUtils.propRect, GetPositioningRect() ); Vector4 GetPositioningRect() { float xOffset = pivot == RectPivot.Corner ? 0f : -width / 2f; float yOffset = pivot == RectPivot.Corner ? 0f : -height / 2f; return new Vector4( xOffset, yOffset, width, height ); } private protected override void SetAllMaterialProperties() { if( cornerRadiusMode == RectangleCornerRadiusMode.PerCorner ) SetVector4( ShapesMaterialUtils.propCornerRadii, cornerRadii ); else if( cornerRadiusMode == RectangleCornerRadiusMode.Uniform ) SetVector4( ShapesMaterialUtils.propCornerRadii, new Vector4( CornerRadius, CornerRadius, CornerRadius, CornerRadius ) ); UpdateRectPositioning(); SetFloat( ShapesMaterialUtils.propThickness, thickness ); SetIntNow( ShapesMaterialUtils.propThicknessSpace, (int)thicknessSpace ); SetFillProperties(); SetAllDashValues( now: false ); } #if UNITY_EDITOR private protected override void ShapeClampRanges() { cornerRadii = ShapesMath.AtLeast0( cornerRadii ); width = Mathf.Max( 0f, width ); height = Mathf.Max( 0f, height ); thickness = Mathf.Max( 0f, thickness ); } #endif private protected override Material[] GetMaterials() => new[] { ShapesMaterialUtils.GetRectMaterial( type )[BlendMode] }; private protected override Bounds GetBounds_Internal() { Vector2 size = new Vector2( width, height ); Vector2 center = pivot == RectPivot.Center ? default : size / 2f; return new Bounds( center, size ); } } }