using System; using UnityEngine; using UnityEngine.Serialization; // Shapes © Freya Holmér - https://twitter.com/FreyaHolmer/ // Website & Documentation - https://acegikmo.com/shapes/ namespace Shapes { /// A Triangle shape component [ExecuteAlways] [AddComponentMenu( "Shapes/Triangle" )] public partial class Triangle : ShapeRenderer, IDashable { /// Color modes for the triangle shape public enum TriangleColorMode { /// A single color for the whole triangle Single, /// One color per vertex in the triangle PerCorner } /// Get or set vertex positions by index) /// A value from 0 to 3 /// public Vector3 this[ int index ] { get { switch( index ) { case 0: return A; case 1: return B; case 2: return C; default: throw new IndexOutOfRangeException( $"Triangle only has four vertices, 0 to 2, you tried to access element {index}" ); } } set { switch( index ) { case 0: A = value; break; case 1: B = value; break; case 2: C = value; break; default: throw new IndexOutOfRangeException( $"Triangle only has four vertices, 0 to 2, you tried to set element {index}" ); } } } /// Get vertex positions by index /// An index from 0 to 2 public Vector3 GetTriangleVertex( int index ) => this[index]; /// Set vertex positions by index /// An index from 0 to 2 /// The position to set the vertex to public Vector3 SetTriangleVertex( int index, Vector3 value ) => this[index] = value; /// Get vertex color by index /// An index from 0 to 2 public Color GetTriangleColor( int index ) { switch( index ) { case 0: return Color; case 1: return ColorB; case 2: return ColorC; default: throw new IndexOutOfRangeException( $"Triangle only has four vertices, 0 to 2, you tried to access element {index}" ); } } /// Set vertex color by index /// An index from 0 to 2 /// The color to set the vertex to public void SetTriangleColor( int index, Color color ) { switch( index ) { case 0: Color = color; break; case 1: ColorB = color; break; case 2: ColorC = color; break; default: throw new IndexOutOfRangeException( $"Triangle only has four vertices, 0 to 3, you tried to set element {index}" ); } } [SerializeField] TriangleColorMode colorMode = TriangleColorMode.Single; /// The color mode to use on this triangle public TriangleColorMode ColorMode { get => colorMode; set { colorMode = value; ApplyProperties(); } } [SerializeField] Vector3 a = Vector3.zero; /// Get or set the position of the first vertex public Vector3 A { get => a; set => SetVector3Now( ShapesMaterialUtils.propA, a = value ); } [SerializeField] Vector3 b = Vector3.up; /// Get or set the position of the second vertex public Vector3 B { get => b; set => SetVector3Now( ShapesMaterialUtils.propB, b = value ); } [SerializeField] Vector3 c = Vector3.right; /// Get or set the position of the third vertex public Vector3 C { get => c; set => SetVector3Now( ShapesMaterialUtils.propC, c = value ); } [FormerlySerializedAs( "hollow" )] [SerializeField] bool border = false; /// Whether this is a triangle border instead of a filled triangle public bool Border { get => border; set => SetIntNow( ShapesMaterialUtils.propBorder, ( border = value ).AsInt() ); } [Obsolete( "Please use Triangle.Border instead", true )] public bool Hollow { get => Border; set => Border = value; } [SerializeField] float thickness = 0.5f; /// The thickness of the border (if border triangle) public float Thickness { get => thickness; set => SetFloatNow( ShapesMaterialUtils.propThickness, thickness = Mathf.Max( 0f, value ) ); } [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 ) ); } [SerializeField] [Range( 0, 1 )] float roundness = 0; /// Roundness. 0 = not round at all. 1 = the roundest shape there is public float Roundness { get => roundness; set => SetFloatNow( ShapesMaterialUtils.propRoundness, roundness = Mathf.Clamp01( value ) ); } /// The color of this shape. The alpha channel is used for opacity/intensity in all blend modes public override Color Color { get => color; set { SetColor( ShapesMaterialUtils.propColor, color = value ); SetColor( ShapesMaterialUtils.propColorB, colorB = value ); SetColorNow( ShapesMaterialUtils.propColorC, colorC = value ); } } /// Get or set the color of the first vertex, when using the per-corner color mode public Color ColorA { get => color; set => SetColorNow( ShapesMaterialUtils.propColor, color = value ); } [SerializeField] [ShapesColorField( true )] Color colorB = Color.white; /// Get or set the color of the second vertex, when using the per-corner color mode public Color ColorB { get => colorB; set => SetColorNow( ShapesMaterialUtils.propColorB, colorB = value ); } [SerializeField] [ShapesColorField( true )] Color colorC = Color.white; /// Get or set the color of the third vertex, when using the per-corner color mode public Color ColorC { get => colorC; set => SetColorNow( ShapesMaterialUtils.propColorC, colorC = value ); } private protected override void SetAllMaterialProperties() { SetVector3( ShapesMaterialUtils.propA, a ); SetVector3( ShapesMaterialUtils.propB, b ); SetVector3( ShapesMaterialUtils.propC, c ); if( colorMode == TriangleColorMode.Single ) { SetColor( ShapesMaterialUtils.propColorB, Color ); SetColor( ShapesMaterialUtils.propColorC, Color ); } else { // per corner SetColor( ShapesMaterialUtils.propColorB, colorB ); SetColor( ShapesMaterialUtils.propColorC, colorC ); } SetFloat( ShapesMaterialUtils.propRoundness, roundness ); SetFloat( ShapesMaterialUtils.propThickness, thickness ); SetFloat( ShapesMaterialUtils.propThicknessSpace, (int)thicknessSpace ); SetFloat( ShapesMaterialUtils.propBorder, border.AsInt() ); SetAllDashValues( now: false ); } #if UNITY_EDITOR private protected override void ShapeClampRanges() { thickness = Mathf.Max( 0f, thickness ); // disallow negative inner radius roundness = Mathf.Clamp01( roundness ); } #endif internal override bool HasDetailLevels => false; private protected override Mesh GetInitialMeshAsset() => ShapesMeshUtils.TriangleMesh[0]; private protected override Material[] GetMaterials() => new[] { ShapesMaterialUtils.matTriangle[BlendMode] }; private protected override Bounds GetBounds_Internal() { Vector3 min = Vector3.Min( Vector3.Min( a, b ), c ); Vector3 max = Vector3.Max( Vector3.Max( a, b ), c ); return new Bounds( ( min + max ) / 2, ShapesMath.Abs( max - min ) ); } } }