using UnityEngine; // Shapes © Freya Holmér - https://twitter.com/FreyaHolmer/ // Website & Documentation - https://acegikmo.com/shapes/ namespace Shapes { /// A Torus shape component [ExecuteAlways] [AddComponentMenu( "Shapes/Torus" )] public class Torus : ShapeRenderer { [SerializeField] float radius = 1; /// The major radius of this torus public float Radius { get => radius; set => SetFloatNow( ShapesMaterialUtils.propRadius, radius = Mathf.Max( 0f, value ) ); } [SerializeField] float thickness = 0.5f; /// The thickness of this torus 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] ThicknessSpace radiusSpace = Shapes.ThicknessSpace.Meters; /// The space in which Radius is defined public ThicknessSpace RadiusSpace { get => radiusSpace; set => SetIntNow( ShapesMaterialUtils.propThicknessSpace, (int)( radiusSpace = value ) ); } // in-editor serialized field, suppressing "assigned but unused field" warning #pragma warning disable CS0414 [SerializeField] AngularUnit angUnitInput = AngularUnit.Degrees; #pragma warning restore CS0414 [SerializeField] float angRadiansStart = 0; /// Get or set the start angle (in radians) of pies and arcs public float AngRadiansStart { get => angRadiansStart; set => SetFloatNow( ShapesMaterialUtils.propAngStart, angRadiansStart = value ); } [SerializeField] float angRadiansEnd = ShapesMath.TAU; /// Get or set the end angle (in radians) of pies and arcs public float AngRadiansEnd { get => angRadiansEnd; set => SetFloatNow( ShapesMaterialUtils.propAngEnd, angRadiansEnd = value ); } private protected override void SetAllMaterialProperties() { SetFloat( ShapesMaterialUtils.propRadius, radius ); SetFloat( ShapesMaterialUtils.propThickness, thickness ); SetInt( ShapesMaterialUtils.propThicknessSpace, (int)thicknessSpace ); SetInt( ShapesMaterialUtils.propRadiusSpace, (int)radiusSpace ); SetFloat( ShapesMaterialUtils.propAngStart, angRadiansStart ); SetFloat( ShapesMaterialUtils.propAngEnd, angRadiansEnd ); } private protected override void ShapeClampRanges() { radius = Mathf.Max( 0f, radius ); thickness = Mathf.Max( 0f, thickness ); } internal override bool HasDetailLevels => true; private protected override Material[] GetMaterials() => new[] { ShapesMaterialUtils.matTorus[BlendMode] }; private protected override Mesh GetInitialMeshAsset() => ShapesMeshUtils.TorusMesh[(int)detailLevel]; private protected override Bounds GetBounds_Internal() { if( radiusSpace != ThicknessSpace.Meters ) return new Bounds( default, Vector3.one ); // presume 0 world space padding when pixels or noots are used float padding = thicknessSpace == ThicknessSpace.Meters ? thickness : 0f; float xySize = radius * 2 + padding; return new Bounds( Vector3.zero, new Vector3( xySize, xySize, padding ) ); } } }