using System.Runtime.CompilerServices; using TMPro; using UnityEngine; using UnityEngine.Rendering; // Shapes © Freya Holmér - https://twitter.com/FreyaHolmer/ // Website & Documentation - https://acegikmo.com/shapes/ namespace Shapes { public static partial class Draw { internal static DrawStyle style; /// Resets draw style states, including color, but not the drawing matrixSee to reset everything [MethodImpl( INLINE )] public static void ResetStyle() => style = DrawStyle.@default; /// using( StyleScope ){ /*code*/ } lets you modify the draw style state within that scope, automatically restoring the previous state once you leave the scope public static StyleStack StyleScope => new StyleStack( Draw.style ); /// Pushes the current draw style state onto the style stack. Calling will restore this state [MethodImpl( INLINE )] public static void PushStyle() => StyleStack.Push( Draw.style ); /// Restores the draw style state to the previously pushed state from the stack [MethodImpl( INLINE )] public static void PopStyle() => StyleStack.Pop(); /// using( ColorScope ){ /*code*/ } lets you modify the color state within that scope, automatically restoring the previously saved color once you leave the scope public static ColorStack ColorScope => new ColorStack( Draw.style.color ); /// Pushes the current draw color onto the matrix stack. Calling will restore this state [MethodImpl( INLINE )] public static void PushColor() => ColorStack.Push( Draw.style.color ); /// Restores the draw color state to the previously pushed state from the stack [MethodImpl( INLINE )] public static void PopColor() => ColorStack.Pop(); /// using( DashedScope ){ /*code*/ } temporarily enables dashes within that scope, automatically restoring the previous state once you leave the scope public static DashStack DashedScope() { DashStack stack = new DashStack( Draw.UseDashes, Draw.DashStyle ); Draw.UseDashes = true; return stack; } /// using( DashedScope ){ /*code*/ } temporarily enables and overrides dashes within that scope, automatically restoring the previous state once you leave the scope public static DashStack DashedScope( DashStyle dashStyle ) { DashStack stack = new DashStack( Draw.UseDashes, Draw.DashStyle ); Draw.UseDashes = true; Draw.DashStyle = dashStyle; return stack; } /// using( GradientFillScope ){ /*code*/ } temporarily enables gradient fill within that scope, automatically restoring the previous state once you leave the scope public static GradientFillStack GradientFillScope() { GradientFillStack stack = new GradientFillStack( Draw.UseGradientFill, Draw.GradientFill ); Draw.UseGradientFill = true; return stack; } /// using( GradientFillScope ){ /*code*/ } temporarily enables and overrides gradient fill within that scope, automatically restoring the previous state once you leave the scope public static GradientFillStack GradientFillScope( GradientFill fill ) { GradientFillStack stack = new GradientFillStack( Draw.UseGradientFill, Draw.GradientFill ); // pushes Draw.UseGradientFill = true; Draw.GradientFill = fill; return stack; } #region Stencil & Depth Testing /// public static CompareFunction ZTest { [MethodImpl( INLINE )] get => style.renderState.zTest; [MethodImpl( INLINE )] set => style.renderState.zTest = value; } /// public static float ZOffsetFactor { [MethodImpl( INLINE )] get => style.renderState.zOffsetFactor; [MethodImpl( INLINE )] set => style.renderState.zOffsetFactor = value; } /// public static int ZOffsetUnits { [MethodImpl( INLINE )] get => style.renderState.zOffsetUnits; [MethodImpl( INLINE )] set => style.renderState.zOffsetUnits = value; } /// public static ColorWriteMask ColorMask { [MethodImpl( INLINE )] get => style.renderState.colorMask; [MethodImpl( INLINE )] set => style.renderState.colorMask = value; } /// public static CompareFunction StencilComp { [MethodImpl( INLINE )] get => style.renderState.stencilComp; [MethodImpl( INLINE )] set => style.renderState.stencilComp = value; } /// public static StencilOp StencilOpPass { [MethodImpl( INLINE )] get => style.renderState.stencilOpPass; [MethodImpl( INLINE )] set => style.renderState.stencilOpPass = value; } /// public static byte StencilRefID { [MethodImpl( INLINE )] get => style.renderState.stencilRefID; [MethodImpl( INLINE )] set => style.renderState.stencilRefID = value; } /// public static byte StencilReadMask { [MethodImpl( INLINE )] get => style.renderState.stencilReadMask; [MethodImpl( INLINE )] set => style.renderState.stencilReadMask = value; } /// public static byte StencilWriteMask { [MethodImpl( INLINE )] get => style.renderState.stencilWriteMask; [MethodImpl( INLINE )] set => style.renderState.stencilWriteMask = value; } #endregion #region Common shared properties /// The color to use when drawing. The alpha channel is used for opacity/intensity in all blend modes public static Color Color { [MethodImpl( INLINE )] get => style.color; [MethodImpl( INLINE )] set => style.color = value; } /// The opacity/intensity of the color. This is just a wrapper function for the alpha channel of Color. It's equivalent to getting/setting Color.a public static float Opacity { [MethodImpl( INLINE )] get => Color.a; [MethodImpl( INLINE )] set { Color c = Color; c.a = value; Color = c; } } /// What blending mode to use public static ShapesBlendMode BlendMode { [MethodImpl( INLINE )] get => style.blendMode; [MethodImpl( INLINE )] set => style.blendMode = value; } // technically a render state, but we swap shaders here instead /// Sets how shapes should behave when scaled public static ScaleMode ScaleMode { [MethodImpl( INLINE )] get => style.scaleMode; [MethodImpl( INLINE )] set => style.scaleMode = value; } /// What detail level to use for 3D primitives (3D Lines/Sphere/Torus/Cone) public static DetailLevel DetailLevel { [MethodImpl( INLINE )] get => style.detailLevel; [MethodImpl( INLINE )] set => style.detailLevel = value; } /// The thickness of all shapes with a thickness (line, polyline, ring, arc, regular polygon, torus etc.), in the given ThicknessSpace public static float Thickness { [MethodImpl( INLINE )] get => style.thickness; [MethodImpl( INLINE )] set => style.thickness = value; } /// The radius of all shapes with a radius (disc, ring, pie, arc, regular polygon, torus, cone etc.), in the given RadiusSpace public static float Radius { [MethodImpl( INLINE )] get => style.radius; [MethodImpl( INLINE )] set => style.radius = value; } /// The thickness space of all shapes with a thickness (line, ring, arc, polyline, torus etc.) public static ThicknessSpace ThicknessSpace { [MethodImpl( INLINE )] get => style.thicknessSpace; [MethodImpl( INLINE )] set => style.thicknessSpace = value; } /// The radius space of all shapes with a radius (disc, ring, arc, pie, torus, cone, torus, etc.) public static ThicknessSpace RadiusSpace { [MethodImpl( INLINE )] get => style.radiusSpace; [MethodImpl( INLINE )] set => style.radiusSpace = value; } /// The size space of all shapes with a non-radius based size dimension (cuboid, cone, etc.) public static ThicknessSpace SizeSpace { [MethodImpl( INLINE )] get => style.sizeSpace; [MethodImpl( INLINE )] set => style.sizeSpace = value; } #endregion #region Gradient Fill /// Whether or not to use gradient fill on shapes (note: this is not supported on all shapes) public static bool UseGradientFill { [MethodImpl( INLINE )] get => style.useGradients; [MethodImpl( INLINE )] set => style.useGradients = value; } /// The gradient fill style to use on all fillable shapes public static GradientFill GradientFill { [MethodImpl( INLINE )] get => style.gradientFill; [MethodImpl( INLINE )] set => style.gradientFill = value; } /// The type of color gradient to use (Linear vs Radial) public static FillType GradientFillType { [MethodImpl( INLINE )] get => style.gradientFill.type; [MethodImpl( INLINE )] set => style.gradientFill.type = value; } /// The space to draw the shape fill gradients in (Local or World) public static FillSpace GradientFillSpace { [MethodImpl( INLINE )] get => style.gradientFill.space; [MethodImpl( INLINE )] set => style.gradientFill.space = value; } /// The start color of shape fill gradients. For radial gradients, this is the inner color public static Color GradientFillColorStart { [MethodImpl( INLINE )] get => style.gradientFill.colorStart; [MethodImpl( INLINE )] set => style.gradientFill.colorStart = value; } /// The end color of shape fill gradients. For radial gradients, this is the outer color public static Color GradientFillColorEnd { [MethodImpl( INLINE )] get => style.gradientFill.colorEnd; [MethodImpl( INLINE )] set => style.gradientFill.colorEnd = value; } /// The starting point of shape fill linear gradients, in the given GradientFillSpace public static Vector3 GradientFillLinearStart { [MethodImpl( INLINE )] get => style.gradientFill.linearStart; [MethodImpl( INLINE )] set => style.gradientFill.linearStart = value; } /// The endpoint of shape fill linear gradients, in the given GradientFillSpace public static Vector3 GradientFillLinearEnd { [MethodImpl( INLINE )] get => style.gradientFill.linearEnd; [MethodImpl( INLINE )] set => style.gradientFill.linearEnd = value; } /// The origin of shape fill radial gradients, in the given GradientFillSpace public static Vector3 GradientFillRadialOrigin { [MethodImpl( INLINE )] get => style.gradientFill.radialOrigin; [MethodImpl( INLINE )] set => style.gradientFill.radialOrigin = value; } /// The radius of shape fill radial gradients, in the given GradientFillSpace public static float GradientFillRadialRadius { [MethodImpl( INLINE )] get => style.gradientFill.radialRadius; [MethodImpl( INLINE )] set => style.gradientFill.radialRadius = value; } #endregion #region Dashes /// Whether or not to dash shapes (note: this is not supported on all shapes) public static bool UseDashes { [MethodImpl( INLINE )] get => style.useDashes; [MethodImpl( INLINE )] set => style.useDashes = value; } /// The full dash style to use for all dashable shapes public static DashStyle DashStyle { [MethodImpl( INLINE )] get => style.dashStyle; [MethodImpl( INLINE )] set => style.dashStyle = value; } /// The type of dash to use public static DashType DashType { [MethodImpl( INLINE )] get => style.dashStyle.type; [MethodImpl( INLINE )] set => style.dashStyle.type = value; } /// The space in which dashes are defined public static DashSpace DashSpace { [MethodImpl( INLINE )] get => style.dashStyle.space; [MethodImpl( INLINE )] set => style.dashStyle.space = value; } /// What snapping type to use public static DashSnapping DashSnap { [MethodImpl( INLINE )] get => style.dashStyle.snap; [MethodImpl( INLINE )] set => style.dashStyle.snap = value; } /// Size of dashes in the specified dash space. When using DashSpace.FixedCount, this is the number of dashes public static float DashSize { [MethodImpl( INLINE )] get => style.dashStyle.size; [MethodImpl( INLINE )] set => style.dashStyle.size = value; } /// Sets both dash size and spacing to the same value. When using DashSpace.FixedCount, it will set spacing to 0.5, which makes the dash length the same as space length public static float DashSizeUniform { [MethodImpl( INLINE )] get => style.dashStyle.size; // a lil weird but it's okay [MethodImpl( INLINE )] set { style.dashStyle.size = value; style.dashStyle.spacing = style.dashStyle.space == DashSpace.FixedCount ? 0.5f : value; } } /// Size of spacing between each dash, in the specified dash space. When using DashSpace.FixedCount, this is the dash:space ratio public static float DashSpacing { [MethodImpl( INLINE )] get => style.dashStyle.spacing; [MethodImpl( INLINE )] set => style.dashStyle.spacing = value; } /// Sets the offset of dashes. An offset of 1 is the size of a whole dash+space period, meaning it will repeat at every integer value public static float DashOffset { [MethodImpl( INLINE )] get => style.dashStyle.offset; [MethodImpl( INLINE )] set => style.dashStyle.offset = value; } /// -1 to 1 modifier that allows you to tweak or mirror certain dash types public static float DashShapeModifier { [MethodImpl( INLINE )] get => style.dashStyle.shapeModifier; [MethodImpl( INLINE )] set => style.dashStyle.shapeModifier = value; } #endregion /// End caps of lines public static LineEndCap LineEndCaps { [MethodImpl( INLINE )] get => style.lineEndCaps; [MethodImpl( INLINE )] set => style.lineEndCaps = value; } /// Type of geometry for lines public static LineGeometry LineGeometry { [MethodImpl( INLINE )] get => style.lineGeometry; [MethodImpl( INLINE )] set => style.lineGeometry = value; } /// The triangulation method to use. Some of these are computationally faster than others, but only works for certain shapes public static PolygonTriangulation PolygonTriangulation { [MethodImpl( INLINE )] get => style.polygonTriangulation; [MethodImpl( INLINE )] set => style.polygonTriangulation = value; } /// Type of geometry for polylines public static PolylineGeometry PolylineGeometry { [MethodImpl( INLINE )] get => style.polylineGeometry; [MethodImpl( INLINE )] set => style.polylineGeometry = value; } /// The joins to use for polylines public static PolylineJoins PolylineJoins { [MethodImpl( INLINE )] get => style.polylineJoins; [MethodImpl( INLINE )] set => style.polylineJoins = value; } /// Whether or not discs, rings, pies & arcs should be billboarded public static DiscGeometry DiscGeometry { [MethodImpl( INLINE )] get => style.discGeometry; [MethodImpl( INLINE )] set => style.discGeometry = value; } /// The number of sides on regular polygons public static int RegularPolygonSideCount { [MethodImpl( INLINE )] get => style.regularPolygonSideCount; [MethodImpl( INLINE )] set => style.regularPolygonSideCount = value; } /// Whether or not regular polygons should be billboarded public static RegularPolygonGeometry RegularPolygonGeometry { [MethodImpl( INLINE )] get => style.regularPolygonGeometry; [MethodImpl( INLINE )] set => style.regularPolygonGeometry = value; } #region Text /// The full text style to use when drawing text public static TextStyle TextStyle { [MethodImpl( INLINE )] get => style.textStyle; [MethodImpl( INLINE )] set => style.textStyle = value; } /// public static TMP_FontAsset Font { [MethodImpl( INLINE )] get => style.textStyle.font; [MethodImpl( INLINE )] set => style.textStyle.font = value; } /// public static float FontSize { [MethodImpl( INLINE )] get => style.textStyle.size; [MethodImpl( INLINE )] set => style.textStyle.size = value; } /// public static FontStyles FontStyle { [MethodImpl( INLINE )] get => style.textStyle.style; [MethodImpl( INLINE )] set => style.textStyle.style = value; } /// public static TextAlign TextAlign { [MethodImpl( INLINE )] get => style.textStyle.alignment; [MethodImpl( INLINE )] set => style.textStyle.alignment = value; } /// public static float TextCharacterSpacing { [MethodImpl( INLINE )] get => style.textStyle.characterSpacing; [MethodImpl( INLINE )] set => style.textStyle.characterSpacing = value; } /// public static float TextWordSpacing { [MethodImpl( INLINE )] get => style.textStyle.wordSpacing; [MethodImpl( INLINE )] set => style.textStyle.wordSpacing = value; } /// public static float TextLineSpacing { [MethodImpl( INLINE )] get => style.textStyle.lineSpacing; [MethodImpl( INLINE )] set => style.textStyle.lineSpacing = value; } /// public static float TextParagraphSpacing { [MethodImpl( INLINE )] get => style.textStyle.paragraphSpacing; [MethodImpl( INLINE )] set => style.textStyle.paragraphSpacing = value; } /// public static Vector4 TextMargins { [MethodImpl( INLINE )] get => style.textStyle.margins; [MethodImpl( INLINE )] set => style.textStyle.margins = value; } /// public static bool TextWrap { [MethodImpl( INLINE )] get => style.textStyle.wrap; [MethodImpl( INLINE )] set => style.textStyle.wrap = value; } /// public static TextOverflowModes TextOverflow { [MethodImpl( INLINE )] get => style.textStyle.overflow; [MethodImpl( INLINE )] set => style.textStyle.overflow = value; } #endregion #region Deprecated [System.Obsolete( "All shapes now use the same static " + nameof(Thickness) + " property", true )] public static float LineThickness { get => style.thickness; set => style.thickness = value; } [System.Obsolete( "All shapes now use the same static " + nameof(ThicknessSpace) + " property", true )] public static ThicknessSpace LineThicknessSpace { get => style.thicknessSpace; set => style.thicknessSpace = value; } [System.Obsolete( "All shapes now use the same static " + nameof(DashStyle) + " property by default, when " + nameof(UseDashes) + " is enabled", true )] public static DashStyle LineDashStyle { get => style.dashStyle; set => style.dashStyle = value; } [System.Obsolete( "All shapes now use the same static " + nameof(Radius) + " property", true )] public static float DiscRadius { get => style.radius; set => style.radius = value; } [System.Obsolete( "All shapes now use the same static " + nameof(DashStyle) + " property by default, when " + nameof(UseDashes) + " is enabled", true )] public static DashStyle RingDashStyle { get => style.dashStyle; set => style.dashStyle = value; } [System.Obsolete( "All shapes now use the same static " + nameof(GradientFill) + " property by default. If you want to override shape fill per shape, use the draw overload with a fill input", true )] public static GradientFill PolygonShapeFill { get => style.gradientFill; set => style.gradientFill = value; } [System.Obsolete( "All shapes now use the same static " + nameof(GradientFill) + " property by default. If you want to override shape fill per shape, use the draw overload with a fill input", true )] public static GradientFill RegularPolygonShapeFill { get => style.gradientFill; set => style.gradientFill = value; } [System.Obsolete( "All shapes now use the same static " + nameof(GradientFill) + " property by default. If you want to override shape fill per shape, use the draw overload with a fill input", true )] public static GradientFill RectangleShapeFill { get => style.gradientFill; set => style.gradientFill = value; } [System.Obsolete( "All shapes now use the same static " + nameof(Thickness) + " property", true )] public static float RingThickness { get => style.thickness; set => style.thickness = value; } [System.Obsolete( "All shapes now use the same static " + nameof(ThicknessSpace) + " property", true )] public static ThicknessSpace RingThicknessSpace { get => style.thicknessSpace; set => style.thicknessSpace = value; } [System.Obsolete( "All shapes now use the same static " + nameof(RadiusSpace) + " property", true )] public static ThicknessSpace DiscRadiusSpace { get => style.radiusSpace; set => style.radiusSpace = value; } [System.Obsolete( "All shapes now use the same static " + nameof(Radius) + " property", true )] public static float RegularPolygonRadius { get => style.radius; set => style.radius = value; } [System.Obsolete( "All shapes now use the same static " + nameof(Thickness) + " property", true )] public static float RegularPolygonThickness { get => style.thickness; set => style.thickness = value; } [System.Obsolete( "All shapes now use the same static " + nameof(ThicknessSpace) + " property", true )] public static ThicknessSpace RegularPolygonThicknessSpace { get => style.thicknessSpace; set => style.thicknessSpace = value; } [System.Obsolete( "All shapes now use the same static " + nameof(RadiusSpace) + " property", true )] public static ThicknessSpace RegularPolygonRadiusSpace { get => style.radiusSpace; set => style.radiusSpace = value; } [System.Obsolete( "All shapes now use the same static " + nameof(Thickness) + " property", true )] public static float RectangleThickness { get => style.thickness; set => style.thickness = value; } [System.Obsolete( "All shapes now use the same static " + nameof(ThicknessSpace) + " property", true )] public static ThicknessSpace RectangleThicknessSpace { get => style.thicknessSpace; set => style.thicknessSpace = value; } [System.Obsolete( "All shapes now use the same static " + nameof(Thickness) + " property", true )] public static float TriangleThickness { get => style.thickness; set => style.thickness = value; } [System.Obsolete( "All shapes now use the same static " + nameof(ThicknessSpace) + " property", true )] public static ThicknessSpace TriangleThicknessSpace { get => style.thicknessSpace; set => style.thicknessSpace = value; } [System.Obsolete( "All shapes now use the same static " + nameof(Radius) + " property", true )] public static float SphereRadius { get => style.radius; set => style.radius = value; } [System.Obsolete( "All shapes now use the same static " + nameof(RadiusSpace) + " property", true )] public static ThicknessSpace SphereRadiusSpace { get => style.radiusSpace; set => style.radiusSpace = value; } [System.Obsolete( "All shapes now use the same static " + nameof(SizeSpace) + " property", true )] public static ThicknessSpace CuboidSizeSpace { get => style.sizeSpace; set => style.sizeSpace = value; } [System.Obsolete( "All shapes now use the same static " + nameof(ThicknessSpace) + " property", true )] public static ThicknessSpace TorusThicknessSpace { get => style.thicknessSpace; set => style.thicknessSpace = value; } [System.Obsolete( "All shapes now use the same static " + nameof(RadiusSpace) + " property", true )] public static ThicknessSpace TorusRadiusSpace { get => style.radiusSpace; set => style.radiusSpace = value; } [System.Obsolete( "All shapes now use the same static " + nameof(SizeSpace) + " property", true )] public static ThicknessSpace ConeSizeSpace { get => style.sizeSpace; set => style.sizeSpace = value; } #endregion } }