diff --git a/CHANGELOG.md b/CHANGELOG.md index 5409f7a..372df5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - X10D: Added `Vector2.ToSizeF()` - X10D: Added `Vector3.Deconstruct()` - X10D: Added `Vector4.Deconstruct()` +- X10D.Unity: Added `DebugEx`, which mimics `UnityEngine.Debug` while offering more useful primitive drawing methods - X10D.Unity: Added `System.Drawing.Color.ToUnityColor()` - X10D.Unity: Added `System.Drawing.Color.ToUnityColor32()` - X10D.Unity: Added `Color.ToSystemDrawingColor()` diff --git a/X10D.Unity/src/Box.cs b/X10D.Unity/src/Box.cs new file mode 100644 index 0000000..f2fb8b7 --- /dev/null +++ b/X10D.Unity/src/Box.cs @@ -0,0 +1,231 @@ +using UnityEngine; +using X10D.Drawing; + +namespace X10D.Unity; + +/// +/// Represents a box that can be drawn using the class. +/// +/// +/// This structure serves no real purpose except to be used in tandem with . For creating a logical +/// cuboid, consider using the structure. +/// +public readonly struct Box +{ + /// + /// Initializes a new instance of the struct. + /// + /// The origin of the box. + /// The half extents of the box. + public Box(Vector3 origin, Vector3 halfExtents) + { + LocalFrontTopLeft = new Vector3(-halfExtents.x, halfExtents.y, -halfExtents.z); + LocalFrontTopRight = new Vector3(halfExtents.x, halfExtents.y, -halfExtents.z); + LocalFrontBottomLeft = new Vector3(-halfExtents.x, -halfExtents.y, -halfExtents.z); + LocalFrontBottomRight = new Vector3(halfExtents.x, -halfExtents.y, -halfExtents.z); + + Origin = origin; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The origin of the box. + /// The half extents of the box. + /// The orientation of the box. + public Box(Vector3 origin, Vector3 halfExtents, Quaternion orientation) + : this(origin, halfExtents) + { + var localFrontTopLeft = new Vector3(-halfExtents.x, halfExtents.y, -halfExtents.z); + var localFrontTopRight = new Vector3(halfExtents.x, halfExtents.y, -halfExtents.z); + var localFrontBottomLeft = new Vector3(-halfExtents.x, -halfExtents.y, -halfExtents.z); + var localFrontBottomRight = new Vector3(halfExtents.x, -halfExtents.y, -halfExtents.z); + + Rotate( + orientation, + ref localFrontTopLeft, + ref localFrontTopRight, + ref localFrontBottomLeft, + ref localFrontBottomRight); + + LocalFrontTopLeft = localFrontTopLeft; + } + + /// + /// Gets the origin of the box. + /// + /// The origin. + public Vector3 Origin { get; } + + /// + /// Gets the front-top-left corner of the box, in local space. + /// + /// The front-top-left corner. + public Vector3 LocalFrontTopLeft { get; } + + /// + /// Gets the front-top-right corner of the box, in local space. + /// + /// The front-top-right corner. + public Vector3 LocalFrontTopRight { get; } + + /// + /// Gets the front-bottom-left corner of the box, in local space. + /// + /// The front-bottom-left corner. + public Vector3 LocalFrontBottomLeft { get; } + + /// + /// Gets the front-bottom-right corner of the box, in local space. + /// + /// The front-bottom-right corner. + public Vector3 LocalFrontBottomRight { get; } + + /// + /// Gets the back-top-left corner of the box, in local space. + /// + /// The back-top-left corner. + public Vector3 LocalBackTopLeft + { + get => -LocalFrontBottomRight; + } + + /// + /// Gets the back-top-right corner of the box, in local space. + /// + /// The back-top-right corner. + public Vector3 LocalBackTopRight + { + get => -LocalFrontBottomLeft; + } + + /// + /// Gets the back-bottom-left corner of the box, in local space. + /// + /// The back-bottom-left corner. + public Vector3 LocalBackBottomLeft + { + get => -LocalFrontTopRight; + } + + /// + /// Gets the back-bottom-right corner of the box, in local space. + /// + /// The back-bottom-right corner. + public Vector3 LocalBackBottomRight + { + get => -LocalFrontTopLeft; + } + + /// + /// Gets the front-top-left corner of the box, in world space. + /// + /// The front-top-left corner. + public Vector3 FrontTopLeft + { + get => LocalFrontTopLeft + Origin; + } + + /// + /// Gets the front-top-right corner of the box, in world space. + /// + /// The front-top-right corner. + public Vector3 FrontTopRight + { + get => LocalFrontTopRight + Origin; + } + + /// + /// Gets the front-bottom-left corner of the box, in world space. + /// + /// The front-bottom-left corner. + public Vector3 FrontBottomLeft + { + get => LocalFrontBottomLeft + Origin; + } + + /// + /// Gets the front-bottom-right corner of the box, in world space. + /// + /// The front-bottom-right corner. + public Vector3 FrontBottomRight + { + get => LocalFrontBottomRight + Origin; + } + + /// + /// Gets the back-bottom-left corner of the box, in world space. + /// + /// The back-bottom-left corner. + public Vector3 BackTopLeft + { + get => LocalBackTopLeft + Origin; + } + + /// + /// Gets the back-bottom-right corner of the box, in world space. + /// + /// The back-bottom-right corner. + public Vector3 BackTopRight + { + get => LocalBackTopRight + Origin; + } + + /// + /// Gets the back-bottom-right corner of the box, in world space. + /// + /// The back-bottom-right corner. + public Vector3 BackBottomLeft + { + get => LocalBackBottomLeft + Origin; + } + + /// + /// Gets the back-bottom-right corner of the box, in world space. + /// + /// The back-bottom-right corner. + public Vector3 BackBottomRight + { + get => LocalBackBottomRight + Origin; + } + + /// + /// Implicitly converts an instance of to an instance of . + /// + /// The to convert. + /// A new instance of . + public static implicit operator Box(Bounds bounds) + { + return new Box(bounds.center, bounds.extents); + } + + /// + /// Implicitly converts an instance of to an instance of . + /// + /// The to convert. + /// A new instance of . + public static implicit operator Box(BoundsInt bounds) + { + return new Box(bounds.center, (Vector3)bounds.size / 2.0f); + } + + private static Vector3 RotatePointAroundPivot(Vector3 point, Vector3 pivot, Quaternion rotation) + { + Vector3 direction = point - pivot; + return pivot + (rotation * direction); + } + + private static void Rotate( + Quaternion orientation, + ref Vector3 localFrontTopLeft, + ref Vector3 localFrontTopRight, + ref Vector3 localFrontBottomLeft, + ref Vector3 localFrontBottomRight + ) + { + localFrontTopLeft = RotatePointAroundPivot(localFrontTopLeft, Vector3.zero, orientation); + localFrontTopRight = RotatePointAroundPivot(localFrontTopRight, Vector3.zero, orientation); + localFrontBottomLeft = RotatePointAroundPivot(localFrontBottomLeft, Vector3.zero, orientation); + localFrontBottomRight = RotatePointAroundPivot(localFrontBottomRight, Vector3.zero, orientation); + } +} diff --git a/X10D.Unity/src/Box2D.cs b/X10D.Unity/src/Box2D.cs new file mode 100644 index 0000000..5cc4673 --- /dev/null +++ b/X10D.Unity/src/Box2D.cs @@ -0,0 +1,160 @@ +using System.Drawing; +using UnityEngine; + +namespace X10D.Unity; + +/// +/// Represents a 2D box that can be drawn using the class. +/// +/// +/// This structure serves no real purpose except to be used in tandem with . For creating a logical +/// rectangle, consider using the , , , or +/// structures. +/// +public readonly struct Box2D +{ + /// + /// Initializes a new instance of the struct. + /// + /// The origin of the box. + /// The half extents of the box. + public Box2D(Vector2 origin, Vector2 halfExtents) + { + LocalTopLeft = new Vector2(-halfExtents.x, halfExtents.y); + LocalTopRight = new Vector2(halfExtents.x, halfExtents.y); + LocalBottomLeft = new Vector2(-halfExtents.x, -halfExtents.y); + LocalBottomRight = new Vector2(halfExtents.x, -halfExtents.y); + + Origin = origin; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The origin of the box. + /// The half extents of the box. + /// The rotation of the box. + public Box2D(Vector2 origin, Vector2 halfExtents, float rotation) + : this(origin, halfExtents) + { + var localTopLeft = new Vector2(-halfExtents.x, halfExtents.y); + var localTopRight = new Vector2(halfExtents.x, halfExtents.y); + var localBottomLeft = new Vector2(-halfExtents.x, -halfExtents.y); + var localBottomRight = new Vector2(halfExtents.x, -halfExtents.y); + + Rotate( + rotation, + ref localTopLeft, + ref localTopRight, + ref localBottomLeft, + ref localBottomRight); + + LocalTopLeft = localTopLeft; + } + + /// + /// Gets the origin of the box. + /// + /// The origin. + public Vector2 Origin { get; } + + /// + /// Gets the top-left corner of the box, in local space. + /// + /// The top-left corner. + public Vector2 LocalTopLeft { get; } + + /// + /// Gets the top-right corner of the box, in local space. + /// + /// The top-right corner. + public Vector2 LocalTopRight { get; } + + /// + /// Gets the bottom-left corner of the box, in local space. + /// + /// The bottom-left corner. + public Vector2 LocalBottomLeft { get; } + + /// + /// Gets the bottom-right corner of the box, in local space. + /// + /// The bottom-right corner. + public Vector2 LocalBottomRight { get; } + + /// + /// Gets the top-left corner of the box, in world space. + /// + /// The top-left corner. + public Vector2 TopLeft + { + get => LocalTopLeft + Origin; + } + + /// + /// Gets the top-right corner of the box, in world space. + /// + /// The top-right corner. + public Vector2 TopRight + { + get => LocalTopRight + Origin; + } + + /// + /// Gets the bottom-left corner of the box, in world space. + /// + /// The bottom-left corner. + public Vector2 BottomLeft + { + get => LocalBottomLeft + Origin; + } + + /// + /// Gets the bottom-right corner of the box, in world space. + /// + /// The bottom-right corner. + public Vector2 BottomRight + { + get => LocalBottomRight + Origin; + } + + /// + /// Implicitly converts an instance of to an instance of . + /// + /// The to convert. + /// A new instance of . + public static implicit operator Box2D(Rect rect) + { + return new Box2D(rect.center, rect.size / 2f); + } + + /// + /// Implicitly converts an instance of to an instance of . + /// + /// The to convert. + /// A new instance of . + public static implicit operator Box2D(RectInt rect) + { + return new Box2D(rect.center, (Vector2)rect.size / 2.0f); + } + + private static Vector2 RotatePointAroundPivot(Vector2 point, Vector2 pivot, float rotation) + { + Vector2 direction = point - pivot; + return pivot + (rotation * direction); + } + + private static void Rotate( + float rotation, + ref Vector2 localTopLeft, + ref Vector2 localTopRight, + ref Vector2 localBottomLeft, + ref Vector2 localBottomRight + ) + { + localTopLeft = RotatePointAroundPivot(localTopLeft, Vector2.zero, rotation); + localTopRight = RotatePointAroundPivot(localTopRight, Vector2.zero, rotation); + localBottomLeft = RotatePointAroundPivot(localBottomLeft, Vector2.zero, rotation); + localBottomRight = RotatePointAroundPivot(localBottomRight, Vector2.zero, rotation); + } +} diff --git a/X10D.Unity/src/DebugEx.Box.cs b/X10D.Unity/src/DebugEx.Box.cs new file mode 100644 index 0000000..11ab648 --- /dev/null +++ b/X10D.Unity/src/DebugEx.Box.cs @@ -0,0 +1,169 @@ +using UnityEngine; + +namespace X10D.Unity; + +public static partial class DebugEx +{ + /// + /// Draws a box. + /// + /// The center point. + /// The extents of the box, halved. + public static void DrawBox(Vector3 center, Vector3 halfExtents) + { + DrawBox(center, halfExtents, Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a box with the specified orientation. + /// + /// The center point. + /// The extents of the box, halved. + /// The orientation of the box. + public static void DrawBox(Vector3 center, Vector3 halfExtents, Quaternion orientation) + { + DrawBox(new Box(center, halfExtents, orientation), Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a box with the specified color. + /// + /// The center point. + /// The extents of the box, halved. + /// The color of the box. + public static void DrawBox(Vector3 center, Vector3 halfExtents, in Color color) + { + DrawBox(center, halfExtents, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a box with the specified orientation and color. + /// + /// The center point. + /// The extents of the box, halved. + /// The orientation of the box. + /// The color of the box. + public static void DrawBox(Vector3 center, Vector3 halfExtents, Quaternion orientation, in Color color) + { + DrawBox(new Box(center, halfExtents, orientation), color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a box with the specified color and duration. + /// + /// The center point. + /// The extents of the box, halved. + /// The color of the box. + /// + /// The duration of the box's visibility, in seconds. If 0 is passed, the box is visible for a single frame. + /// + public static void DrawBox(Vector3 center, Vector3 halfExtents, in Color color, float duration) + { + DrawBox(center, halfExtents, color, duration, DefaultDepthTest); + } + + /// + /// Draws a box with the specified orientation, color, and duration. + /// + /// The center point. + /// The extents of the box, halved. + /// The orientation of the box. + /// The color of the box. + /// + /// The duration of the box's visibility, in seconds. If 0 is passed, the box is visible for a single frame. + /// + public static void DrawBox(Vector3 center, Vector3 halfExtents, Quaternion orientation, in Color color, float duration) + { + DrawBox(new Box(center, halfExtents, orientation), color, duration, DefaultDepthTest); + } + + /// + /// Draws a box with the specified color and duration. + /// + /// The center point. + /// The extents of the box, halved. + /// The color of the box. + /// + /// The duration of the box's visibility, in seconds. If 0 is passed, the box is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the box be obscured by objects closer to the camera. + /// + public static void DrawBox(Vector3 center, Vector3 halfExtents, in Color color, float duration, bool depthTest) + { + DrawBox(new Box(center, halfExtents), color, duration, depthTest); + } + + /// + /// Draws a box with the specified orientation, color, and duration. + /// + /// The center point. + /// The extents of the box, halved. + /// The orientation of the box. + /// The color of the box. + /// + /// The duration of the box's visibility, in seconds. If 0 is passed, the box is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the box be obscured by objects closer to the camera. + /// + public static void DrawBox(Vector3 center, Vector3 halfExtents, Quaternion orientation, in Color color, float duration, bool depthTest) + { + DrawBox(new Box(center, halfExtents, orientation), color, duration, depthTest); + } + + /// + /// Draws a box with the specified color. + /// + /// The box to draw. + /// The color of the box. + public static void DrawBox(Box box, in Color color) + { + DrawBox(box, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a box with the specified color and duration. + /// + /// The box to draw. + /// The color of the box. + /// + /// The duration of the box's visibility, in seconds. If 0 is passed, the box is visible for a single frame. + /// + public static void DrawBox(Box box, in Color color, float duration) + { + DrawBox(box, color, duration, DefaultDepthTest); + } + + /// + /// Draws a box with the specified color and duration. + /// + /// The box to draw. + /// The color of the box. + /// + /// The duration of the box's visibility, in seconds. If 0 is passed, the box is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the box be obscured by objects closer to the camera. + /// + public static void DrawBox(Box box, in Color color, float duration, bool depthTest) + { + Debug.DrawLine(box.FrontTopLeft, box.FrontTopRight, color, duration, depthTest); + Debug.DrawLine(box.FrontTopRight, box.FrontBottomRight, color, duration, depthTest); + Debug.DrawLine(box.FrontBottomRight, box.FrontBottomLeft, color, duration, depthTest); + Debug.DrawLine(box.FrontBottomLeft, box.FrontTopLeft, color, duration, depthTest); + + Debug.DrawLine(box.BackTopLeft, box.BackTopRight, color, duration, depthTest); + Debug.DrawLine(box.BackTopRight, box.BackBottomRight, color, duration, depthTest); + Debug.DrawLine(box.BackBottomRight, box.BackBottomLeft, color, duration, depthTest); + Debug.DrawLine(box.BackBottomLeft, box.BackTopLeft, color, duration, depthTest); + + Debug.DrawLine(box.FrontTopLeft, box.BackTopLeft, color, duration, depthTest); + Debug.DrawLine(box.FrontTopRight, box.BackTopRight, color, duration, depthTest); + Debug.DrawLine(box.FrontBottomRight, box.BackBottomRight, color, duration, depthTest); + Debug.DrawLine(box.FrontBottomLeft, box.BackBottomLeft, color, duration, depthTest); + } +} diff --git a/X10D.Unity/src/DebugEx.Box2D.cs b/X10D.Unity/src/DebugEx.Box2D.cs new file mode 100644 index 0000000..932b22b --- /dev/null +++ b/X10D.Unity/src/DebugEx.Box2D.cs @@ -0,0 +1,333 @@ +using System.Drawing; +using UnityEngine; +using X10D.Unity.Drawing; +using Color = UnityEngine.Color; + +namespace X10D.Unity; + +public static partial class DebugEx +{ + /// + /// Draws a rectangle. + /// + /// The center point. + /// The extents of the box, halved. + public static void DrawRectangle(Vector2 center, Vector2 halfExtents) + { + DrawRectangle(center, halfExtents, Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a rectangle with the specified rotation. + /// + /// The center point. + /// The extents of the box, halved. + /// The rotation of the box. + public static void DrawRectangle(Vector2 center, Vector2 halfExtents, float rotation) + { + DrawRectangle(new Box2D(center, halfExtents, rotation), Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a rectangle with the specified color. + /// + /// The center point. + /// The extents of the box, halved. + /// The color of the box. + public static void DrawRectangle(Vector2 center, Vector2 halfExtents, in Color color) + { + DrawRectangle(center, halfExtents, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a rectangle with the specified rotation and color. + /// + /// The center point. + /// The extents of the box, halved. + /// The rotation of the box. + /// The color of the box. + public static void DrawRectangle(Vector2 center, Vector2 halfExtents, float rotation, in Color color) + { + DrawRectangle(new Box2D(center, halfExtents, rotation), color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a rectangle with the specified color and duration. + /// + /// The center point. + /// The extents of the box, halved. + /// The color of the box. + /// + /// The duration of the box's visibility, in seconds. If 0 is passed, the box is visible for a single frame. + /// + public static void DrawRectangle(Vector2 center, Vector2 halfExtents, in Color color, float duration) + { + DrawRectangle(center, halfExtents, color, duration, DefaultDepthTest); + } + + /// + /// Draws a rectangle with the specified rotation, color, and duration. + /// + /// The center point. + /// The extents of the box, halved. + /// The rotation of the box. + /// The color of the box. + /// + /// The duration of the box's visibility, in seconds. If 0 is passed, the box is visible for a single frame. + /// + public static void DrawRectangle(Vector2 center, Vector2 halfExtents, float rotation, in Color color, float duration) + { + DrawRectangle(new Box2D(center, halfExtents, rotation), color, duration, DefaultDepthTest); + } + + /// + /// Draws a rectangle with the specified color and duration. + /// + /// The center point. + /// The extents of the box, halved. + /// The color of the box. + /// + /// The duration of the box's visibility, in seconds. If 0 is passed, the box is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the box be obscured by objects closer to the camera. + /// + public static void DrawRectangle(Vector2 center, Vector2 halfExtents, in Color color, float duration, bool depthTest) + { + DrawRectangle(new Box2D(center, halfExtents), color, duration, depthTest); + } + + /// + /// Draws a rectangle with the specified rotation, color, and duration. + /// + /// The center point. + /// The extents of the box, halved. + /// The rotation of the box. + /// The color of the box. + /// + /// The duration of the box's visibility, in seconds. If 0 is passed, the box is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the box be obscured by objects closer to the camera. + /// + public static void DrawRectangle(Vector2 center, Vector2 halfExtents, float rotation, in Color color, float duration, + bool depthTest) + { + DrawRectangle(new Box2D(center, halfExtents, rotation), color, duration, depthTest); + } + + /// + /// Draws a rectangle with the specified color. + /// + /// The box to draw. + /// The color of the box. + public static void DrawRectangle(Box2D box, in Color color) + { + DrawRectangle(box, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a rectangle with the specified color and duration. + /// + /// The box to draw. + /// The color of the box. + /// + /// The duration of the box's visibility, in seconds. If 0 is passed, the box is visible for a single frame. + /// + public static void DrawRectangle(Box2D box, in Color color, float duration) + { + DrawRectangle(box, color, duration, DefaultDepthTest); + } + + /// + /// Draws a rectangle with the specified color and duration. + /// + /// The box to draw. + /// The color of the box. + /// + /// The duration of the box's visibility, in seconds. If 0 is passed, the box is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the box be obscured by objects closer to the camera. + /// + public static void DrawRectangle(Box2D box, in Color color, float duration, bool depthTest) + { + Debug.DrawLine(box.TopLeft, box.TopRight, color, duration, depthTest); + Debug.DrawLine(box.TopRight, box.BottomRight, color, duration, depthTest); + Debug.DrawLine(box.BottomRight, box.BottomLeft, color, duration, depthTest); + Debug.DrawLine(box.BottomLeft, box.TopLeft, color, duration, depthTest); + } + + /// + /// Draws a rectangle with the specified color. + /// + /// The rectangle to draw. + /// The color of the box. + public static void DrawRectangle(Rect rect, in Color color) + { + DrawRectangle(rect, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a rectangle with the specified color and duration. + /// + /// The rectangle to draw. + /// The color of the box. + /// + /// The duration of the box's visibility, in seconds. If 0 is passed, the box is visible for a single frame. + /// + public static void DrawRectangle(Rect rect, in Color color, float duration) + { + DrawRectangle(rect, color, duration, DefaultDepthTest); + } + + /// + /// Draws a rectangle with the specified color and duration. + /// + /// The rectangle to draw. + /// The color of the box. + /// + /// The duration of the box's visibility, in seconds. If 0 is passed, the box is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the box be obscured by objects closer to the camera. + /// + public static void DrawRectangle(Rect rect, in Color color, float duration, bool depthTest) + { + var box = new Box2D(rect.center, rect.size / 2.0f); + DrawRectangle(box, color, duration, depthTest); + } + + /// + /// Draws a rectangle with the specified color. + /// + /// The rectangle to draw. + /// The color of the box. + public static void DrawRectangle(RectInt rect, in Color color) + { + DrawRectangle(rect, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a rectangle with the specified color and duration. + /// + /// The rectangle to draw. + /// The color of the box. + /// + /// The duration of the box's visibility, in seconds. If 0 is passed, the box is visible for a single frame. + /// + public static void DrawRectangle(RectInt rect, in Color color, float duration) + { + DrawRectangle(rect, color, duration, DefaultDepthTest); + } + + /// + /// Draws a rectangle with the specified color and duration. + /// + /// The rectangle to draw. + /// The color of the box. + /// + /// The duration of the box's visibility, in seconds. If 0 is passed, the box is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the box be obscured by objects closer to the camera. + /// + public static void DrawRectangle(RectInt rect, in Color color, float duration, bool depthTest) + { + var box = new Box2D(rect.center, (Vector2)rect.size / 2.0f); + DrawRectangle(box, color, duration, depthTest); + } + + /// + /// Draws a rectangle with the specified color. + /// + /// The rectangle to draw. + /// The color of the box. + public static void DrawRectangle(Rectangle rect, in Color color) + { + DrawRectangle(rect, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a rectangle with the specified color and duration. + /// + /// The rectangle to draw. + /// The color of the box. + /// + /// The duration of the box's visibility, in seconds. If 0 is passed, the box is visible for a single frame. + /// + public static void DrawRectangle(Rectangle rect, in Color color, float duration) + { + DrawRectangle(rect, color, duration, DefaultDepthTest); + } + + /// + /// Draws a rectangle with the specified color and duration. + /// + /// The rectangle to draw. + /// The color of the box. + /// + /// The duration of the box's visibility, in seconds. If 0 is passed, the box is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the box be obscured by objects closer to the camera. + /// + public static void DrawRectangle(Rectangle rect, in Color color, float duration, bool depthTest) + { + var origin = new Vector2(rect.X + rect.Width / 2.0f, rect.Y + rect.Height / 2.0f); + Vector2 halfExtents = rect.Size.ToUnityVector2() / 2.0f; + + var box = new Box2D(origin, halfExtents); + DrawRectangle(box, color, duration, depthTest); + } + + /// + /// Draws a rectangle with the specified color. + /// + /// The rectangle to draw. + /// The color of the box. + public static void DrawRectangle(RectangleF rect, in Color color) + { + DrawRectangle(rect, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a rectangle with the specified color and duration. + /// + /// The rectangle to draw. + /// The color of the box. + /// + /// The duration of the box's visibility, in seconds. If 0 is passed, the box is visible for a single frame. + /// + public static void DrawRectangle(RectangleF rect, in Color color, float duration) + { + DrawRectangle(rect, color, duration, DefaultDepthTest); + } + + /// + /// Draws a rectangle with the specified color and duration. + /// + /// The rectangle to draw. + /// The color of the box. + /// + /// The duration of the box's visibility, in seconds. If 0 is passed, the box is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the box be obscured by objects closer to the camera. + /// + public static void DrawRectangle(RectangleF rect, in Color color, float duration, bool depthTest) + { + var origin = new Vector2(rect.X + rect.Width / 2.0f, rect.Y + rect.Height / 2.0f); + Vector2 halfExtents = rect.Size.ToUnityVector2() / 2.0f; + + var box = new Box2D(origin, halfExtents); + DrawRectangle(box, color, duration, depthTest); + } +} diff --git a/X10D.Unity/src/DebugEx.Circle.cs b/X10D.Unity/src/DebugEx.Circle.cs new file mode 100644 index 0000000..3ef94ac --- /dev/null +++ b/X10D.Unity/src/DebugEx.Circle.cs @@ -0,0 +1,331 @@ +using UnityEngine; +using X10D.Drawing; +using X10D.Numerics; +using X10D.Unity.Numerics; +using Quaternion = System.Numerics.Quaternion; + +namespace X10D.Unity; + +public static partial class DebugEx +{ + /// + /// Draws a circle with the specified color. + /// + /// The center point of the circle. + /// The radius of the circle. + /// The number of sides to generate. + public static void DrawCircle(Vector2 center, float radius, int sides) + { + DrawCircle(center, radius, sides, Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a circle with the specified color. + /// + /// The center point of the circle. + /// The radius of the circle. + /// The number of sides to generate. + /// The color of the circle. + public static void DrawCircle(Vector2 center, float radius, int sides, in Color color) + { + DrawCircle(center, radius, sides, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a circle with the specified color and duration. + /// + /// The center point of the circle. + /// The radius of the circle. + /// The number of sides to generate. + /// The color of the circle. + /// + /// The duration of the circle's visibility, in seconds. If 0 is passed, the circle is visible for a single frame. + /// + public static void DrawCircle(Vector2 center, float radius, int sides, in Color color, float duration) + { + DrawCircle(center, radius, sides, Vector2.zero, color, duration, DefaultDepthTest); + } + + /// + /// Draws a circle with the specified color and duration. + /// + /// The center point of the circle. + /// The radius of the circle. + /// The number of sides to generate. + /// The color of the circle. + /// + /// The duration of the circle's visibility, in seconds. If 0 is passed, the circle is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the circle be obscured by objects closer to the camera. + /// + public static void DrawCircle(Vector2 center, float radius, int sides, in Color color, float duration, bool depthTest) + { + DrawCircle(center, radius, sides, Vector2.zero, color, duration, depthTest); + } + + /// + /// Draws a circle. + /// + /// The center point of the circle. + /// The radius of the circle. + /// The number of sides to generate. + /// The drawing offset of the circle. + /// The color of the circle. + /// + /// The duration of the circle's visibility, in seconds. If 0 is passed, the circle is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the circle be obscured by objects closer to the camera. + /// + public static void DrawCircle(Vector2 center, float radius, int sides, in Vector3 offset, in Color color, float duration, + bool depthTest) + { + DrawCircle(new CircleF(center.ToSystemVector(), radius), sides, offset, color, duration, depthTest); + } + + /// + /// Draws a circle with the specified color. + /// + /// The circle to draw. + /// The number of sides to generate. + public static void DrawCircle(in Circle circle, int sides) + { + DrawCircle((CircleF)circle, sides, Vector2.zero, Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a circle with the specified color. + /// + /// The circle to draw. + /// The number of sides to generate. + /// The drawing offset of the circle. + public static void DrawCircle(in Circle circle, int sides, in Vector3 offset) + { + DrawCircle((CircleF)circle, sides, offset, Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a circle with the specified color. + /// + /// The circle to draw. + /// The number of sides to generate. + /// The color of the circle. + public static void DrawCircle(in Circle circle, int sides, in Color color) + { + DrawCircle((CircleF)circle, sides, Vector2.zero, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a circle with the specified color. + /// + /// The circle to draw. + /// The number of sides to generate. + /// The drawing offset of the circle. + /// The color of the circle. + public static void DrawCircle(in Circle circle, int sides, in Vector3 offset, in Color color) + { + DrawCircle((CircleF)circle, sides, offset, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a circle with the specified color and duration. + /// + /// The circle to draw. + /// The number of sides to generate. + /// The color of the circle. + /// + /// The duration of the circle's visibility, in seconds. If 0 is passed, the circle is visible for a single frame. + /// + public static void DrawCircle(in Circle circle, int sides, in Color color, float duration) + { + DrawCircle((CircleF)circle, sides, Vector2.zero, color, duration, DefaultDepthTest); + } + + /// + /// Draws a circle with the specified color and duration. + /// + /// The circle to draw. + /// The number of sides to generate. + /// The drawing offset of the circle. + /// The color of the circle. + /// + /// The duration of the circle's visibility, in seconds. If 0 is passed, the circle is visible for a single frame. + /// + public static void DrawCircle(in Circle circle, int sides, in Vector3 offset, in Color color, float duration) + { + DrawCircle((CircleF)circle, sides, offset, color, duration, DefaultDepthTest); + } + + /// + /// Draws a circle with the specified color and duration. + /// + /// The circle to draw. + /// The number of sides to generate. + /// The color of the circle. + /// + /// The duration of the circle's visibility, in seconds. If 0 is passed, the circle is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the circle be obscured by objects closer to the camera. + /// + public static void DrawCircle(in Circle circle, int sides, in Color color, float duration, bool depthTest) + { + DrawCircle((CircleF)circle, sides, Vector2.zero, color, duration, depthTest); + } + + /// + /// Draws a circle. + /// + /// The circle to draw. + /// The number of sides to generate. + /// The drawing offset of the circle. + /// The color of the circle. + /// + /// The duration of the circle's visibility, in seconds. If 0 is passed, the circle is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the circle be obscured by objects closer to the camera. + /// + public static void DrawCircle(in Circle circle, int sides, in Vector3 offset, in Color color, float duration, bool depthTest) + { + DrawCircle((CircleF)circle, sides, offset, color, duration, depthTest); + } + + /// + /// Draws a circle with the specified color. + /// + /// The circle to draw. + /// The number of sides to generate. + public static void DrawCircle(in CircleF circle, int sides) + { + DrawCircle(circle, sides, Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a circle with the specified color. + /// + /// The circle to draw. + /// The number of sides to generate. + /// The drawing offset of the circle. + public static void DrawCircle(in CircleF circle, int sides, in Vector3 offset) + { + DrawCircle(circle, sides, offset, Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a circle with the specified color. + /// + /// The circle to draw. + /// The number of sides to generate. + /// The color of the circle. + public static void DrawCircle(in CircleF circle, int sides, in Color color) + { + DrawCircle(circle, sides, Vector2.zero, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a circle with the specified color. + /// + /// The circle to draw. + /// The number of sides to generate. + /// The drawing offset of the circle. + /// The color of the circle. + public static void DrawCircle(in CircleF circle, int sides, in Vector3 offset, in Color color) + { + DrawCircle(circle, sides, offset, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a circle with the specified color and duration. + /// + /// The circle to draw. + /// The number of sides to generate. + /// The color of the circle. + /// + /// The duration of the circle's visibility, in seconds. If 0 is passed, the circle is visible for a single frame. + /// + public static void DrawCircle(in CircleF circle, int sides, in Color color, float duration) + { + DrawCircle(circle, sides, Vector2.zero, color, duration, DefaultDepthTest); + } + + /// + /// Draws a circle with the specified color and duration. + /// + /// The circle to draw. + /// The number of sides to generate. + /// The drawing offset of the circle. + /// The color of the circle. + /// + /// The duration of the circle's visibility, in seconds. If 0 is passed, the circle is visible for a single frame. + /// + public static void DrawCircle(in CircleF circle, int sides, in Vector3 offset, in Color color, float duration) + { + DrawCircle(circle, sides, offset, color, duration, DefaultDepthTest); + } + + /// + /// Draws a circle with the specified color and duration. + /// + /// The circle to draw. + /// The number of sides to generate. + /// The color of the circle. + /// + /// The duration of the circle's visibility, in seconds. If 0 is passed, the circle is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the circle be obscured by objects closer to the camera. + /// + public static void DrawCircle(in CircleF circle, int sides, in Color color, float duration, bool depthTest) + { + DrawCircle(circle, sides, Vector2.zero, color, duration, depthTest); + } + + /// + /// Draws a circle. + /// + /// The circle to draw. + /// The number of sides to generate. + /// The drawing offset of the circle. + /// The color of the circle. + /// + /// The duration of the circle's visibility, in seconds. If 0 is passed, the circle is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the circle be obscured by objects closer to the camera. + /// + public static void DrawCircle(in CircleF circle, int sides, in Vector3 offset, in Color color, float duration, bool depthTest) + { + DrawPolyhedron(CreateCircle(circle.Radius, sides, Vector3.zero), offset, color, duration, depthTest); + } + + private static Polyhedron CreateCircle(float radius, int sides, in Vector3 axis) + { + const float max = 2.0f * MathF.PI; + float step = max / sides; + + var points = new List(); + for (var theta = 0f; theta < max; theta += step) + { + float x = radius * MathF.Cos(theta); + float y = radius * MathF.Sin(theta); + var vector = new System.Numerics.Vector3(x, y, 0); + + if (axis != Vector3.zero) + { + vector = Quaternion.CreateFromAxisAngle(axis.ToSystemVector(), MathF.PI / 2.0f).Multiply(vector); + } + + points.Add(vector); + } + + return new Polyhedron(points); + } +} diff --git a/X10D.Unity/src/DebugEx.Ellipse.cs b/X10D.Unity/src/DebugEx.Ellipse.cs new file mode 100644 index 0000000..cff33a8 --- /dev/null +++ b/X10D.Unity/src/DebugEx.Ellipse.cs @@ -0,0 +1,406 @@ +using UnityEngine; +using X10D.Drawing; + +namespace X10D.Unity; + +public static partial class DebugEx +{ + /// + /// Draws an ellipse with the specified color. + /// + /// The center point of the ellipse. + /// The radius of the ellipse. + /// The number of sides to generate. + public static void DrawEllipse(Vector2 center, Vector2 radius, int sides) + { + DrawEllipse(center, radius.x, radius.y, sides, Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws an ellipse with the specified color. + /// + /// The center point of the ellipse. + /// The radius of the ellipse. + /// The number of sides to generate. + /// The color of the ellipse. + public static void DrawEllipse(Vector2 center, Vector2 radius, int sides, in Color color) + { + DrawEllipse(center, radius.x, radius.y, sides, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws an ellipse with the specified color and duration. + /// + /// The center point of the ellipse. + /// The radius of the ellipse. + /// The number of sides to generate. + /// The color of the ellipse. + /// + /// The duration of the ellipse's visibility, in seconds. If 0 is passed, the ellipse is visible for a single frame. + /// + public static void DrawEllipse(Vector2 center, Vector2 radius, int sides, in Color color, float duration) + { + DrawEllipse(center, radius.x, radius.y, sides, Vector2.zero, color, duration, DefaultDepthTest); + } + + /// + /// Draws an ellipse with the specified color and duration. + /// + /// The center point of the ellipse. + /// The radius of the ellipse. + /// The number of sides to generate. + /// The color of the ellipse. + /// + /// The duration of the ellipse's visibility, in seconds. If 0 is passed, the ellipse is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the ellipse be obscured by objects closer to the camera. + /// + public static void DrawEllipse(Vector2 center, Vector2 radius, int sides, in Color color, float duration, bool depthTest) + { + DrawEllipse(center, radius.x, radius.y, sides, Vector2.zero, color, duration, depthTest); + } + + /// + /// Draws an ellipse. + /// + /// The center point of the ellipse. + /// The radius of the ellipse. + /// The number of sides to generate. + /// The drawing offset of the ellipse. + /// The color of the ellipse. + /// + /// The duration of the ellipse's visibility, in seconds. If 0 is passed, the ellipse is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the ellipse be obscured by objects closer to the camera. + /// + public static void DrawEllipse(Vector2 center, Vector2 radius, int sides, Vector2 offset, in Color color, float duration, + bool depthTest) + { + DrawEllipse(new EllipseF(center.x, center.y, radius.x, radius.y), sides, offset, color, duration, depthTest); + } + + /// + /// Draws an ellipse with the specified color. + /// + /// The center point of the ellipse. + /// The horizontal radius of the ellipse. + /// The vertical radius of the ellipse. + /// The number of sides to generate. + public static void DrawEllipse(Vector2 center, float radiusX, float radiusY, int sides) + { + DrawEllipse(center, radiusX, radiusY, sides, Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws an ellipse with the specified color. + /// + /// The center point of the ellipse. + /// The horizontal radius of the ellipse. + /// The vertical radius of the ellipse. + /// The number of sides to generate. + /// The color of the ellipse. + public static void DrawEllipse(Vector2 center, float radiusX, float radiusY, int sides, in Color color) + { + DrawEllipse(center, radiusX, radiusY, sides, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws an ellipse with the specified color and duration. + /// + /// The center point of the ellipse. + /// The horizontal radius of the ellipse. + /// The vertical radius of the ellipse. + /// The number of sides to generate. + /// The color of the ellipse. + /// + /// The duration of the ellipse's visibility, in seconds. If 0 is passed, the ellipse is visible for a single frame. + /// + public static void DrawEllipse(Vector2 center, float radiusX, float radiusY, int sides, in Color color, float duration) + { + DrawEllipse(center, radiusX, radiusY, sides, Vector2.zero, color, duration, DefaultDepthTest); + } + + /// + /// Draws an ellipse with the specified color and duration. + /// + /// The center point of the ellipse. + /// The horizontal radius of the ellipse. + /// The vertical radius of the ellipse. + /// The number of sides to generate. + /// The color of the ellipse. + /// + /// The duration of the ellipse's visibility, in seconds. If 0 is passed, the ellipse is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the ellipse be obscured by objects closer to the camera. + /// + public static void DrawEllipse(Vector2 center, float radiusX, float radiusY, int sides, in Color color, float duration, + bool depthTest) + { + DrawEllipse(center, radiusX, radiusY, sides, Vector2.zero, color, duration, depthTest); + } + + /// + /// Draws an ellipse. + /// + /// The center point of the ellipse. + /// The horizontal radius of the ellipse. + /// The vertical radius of the ellipse. + /// The number of sides to generate. + /// The drawing offset of the ellipse. + /// The color of the ellipse. + /// + /// The duration of the ellipse's visibility, in seconds. If 0 is passed, the ellipse is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the ellipse be obscured by objects closer to the camera. + /// + public static void DrawEllipse(Vector2 center, float radiusX, float radiusY, int sides, Vector2 offset, in Color color, + float duration, bool depthTest) + { + DrawEllipse(new EllipseF(center.x, center.y, radiusX, radiusY), sides, offset, color, duration, depthTest); + } + + /// + /// Draws an ellipse with the specified color. + /// + /// The ellipse to draw. + /// The number of sides to generate. + public static void DrawEllipse(Ellipse ellipse, int sides) + { + DrawEllipse((EllipseF)ellipse, sides, Vector2.zero, Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws an ellipse with the specified color. + /// + /// The ellipse to draw. + /// The number of sides to generate. + /// The drawing offset of the ellipse. + public static void DrawEllipse(Ellipse ellipse, int sides, Vector2 offset) + { + DrawEllipse((EllipseF)ellipse, sides, offset, Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws an ellipse with the specified color. + /// + /// The ellipse to draw. + /// The number of sides to generate. + /// The color of the ellipse. + public static void DrawEllipse(Ellipse ellipse, int sides, in Color color) + { + DrawEllipse((EllipseF)ellipse, sides, Vector2.zero, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws an ellipse with the specified color. + /// + /// The ellipse to draw. + /// The number of sides to generate. + /// The drawing offset of the ellipse. + /// The color of the ellipse. + public static void DrawEllipse(Ellipse ellipse, int sides, Vector2 offset, in Color color) + { + DrawEllipse((EllipseF)ellipse, sides, offset, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws an ellipse with the specified color and duration. + /// + /// The ellipse to draw. + /// The number of sides to generate. + /// The color of the ellipse. + /// + /// The duration of the ellipse's visibility, in seconds. If 0 is passed, the ellipse is visible for a single frame. + /// + public static void DrawEllipse(Ellipse ellipse, int sides, in Color color, float duration) + { + DrawEllipse((EllipseF)ellipse, sides, Vector2.zero, color, duration, DefaultDepthTest); + } + + /// + /// Draws an ellipse with the specified color and duration. + /// + /// The ellipse to draw. + /// The number of sides to generate. + /// The drawing offset of the ellipse. + /// The color of the ellipse. + /// + /// The duration of the ellipse's visibility, in seconds. If 0 is passed, the ellipse is visible for a single frame. + /// + public static void DrawEllipse(Ellipse ellipse, int sides, Vector2 offset, in Color color, float duration) + { + DrawEllipse((EllipseF)ellipse, sides, offset, color, duration, DefaultDepthTest); + } + + /// + /// Draws an ellipse with the specified color and duration. + /// + /// The ellipse to draw. + /// The number of sides to generate. + /// The color of the ellipse. + /// + /// The duration of the ellipse's visibility, in seconds. If 0 is passed, the ellipse is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the ellipse be obscured by objects closer to the camera. + /// + public static void DrawEllipse(Ellipse ellipse, int sides, in Color color, float duration, bool depthTest) + { + DrawEllipse((EllipseF)ellipse, sides, Vector2.zero, color, duration, depthTest); + } + + /// + /// Draws an ellipse. + /// + /// The ellipse to draw. + /// The number of sides to generate. + /// The drawing offset of the ellipse. + /// The color of the ellipse. + /// + /// The duration of the ellipse's visibility, in seconds. If 0 is passed, the ellipse is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the ellipse be obscured by objects closer to the camera. + /// + public static void DrawEllipse(Ellipse ellipse, int sides, Vector2 offset, in Color color, float duration, bool depthTest) + { + DrawEllipse((EllipseF)ellipse, sides, offset, color, duration, depthTest); + } + + /// + /// Draws an ellipse with the specified color. + /// + /// The ellipse to draw. + /// The number of sides to generate. + public static void DrawEllipse(EllipseF ellipse, int sides) + { + DrawEllipse(ellipse, sides, Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws an ellipse with the specified color. + /// + /// The ellipse to draw. + /// The number of sides to generate. + /// The drawing offset of the ellipse. + public static void DrawEllipse(EllipseF ellipse, int sides, Vector2 offset) + { + DrawEllipse(ellipse, sides, offset, Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws an ellipse with the specified color. + /// + /// The ellipse to draw. + /// The number of sides to generate. + /// The color of the ellipse. + public static void DrawEllipse(EllipseF ellipse, int sides, in Color color) + { + DrawEllipse(ellipse, sides, Vector2.zero, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws an ellipse with the specified color. + /// + /// The ellipse to draw. + /// The number of sides to generate. + /// The drawing offset of the ellipse. + /// The color of the ellipse. + public static void DrawEllipse(EllipseF ellipse, int sides, Vector2 offset, in Color color) + { + DrawEllipse(ellipse, sides, offset, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws an ellipse with the specified color and duration. + /// + /// The ellipse to draw. + /// The number of sides to generate. + /// The color of the ellipse. + /// + /// The duration of the ellipse's visibility, in seconds. If 0 is passed, the ellipse is visible for a single frame. + /// + public static void DrawEllipse(EllipseF ellipse, int sides, in Color color, float duration) + { + DrawEllipse(ellipse, sides, Vector2.zero, color, duration, DefaultDepthTest); + } + + /// + /// Draws an ellipse with the specified color and duration. + /// + /// The ellipse to draw. + /// The number of sides to generate. + /// The drawing offset of the ellipse. + /// The color of the ellipse. + /// + /// The duration of the ellipse's visibility, in seconds. If 0 is passed, the ellipse is visible for a single frame. + /// + public static void DrawEllipse(EllipseF ellipse, int sides, Vector2 offset, in Color color, float duration) + { + DrawEllipse(ellipse, sides, offset, color, duration, DefaultDepthTest); + } + + /// + /// Draws an ellipse with the specified color and duration. + /// + /// The ellipse to draw. + /// The number of sides to generate. + /// The color of the ellipse. + /// + /// The duration of the ellipse's visibility, in seconds. If 0 is passed, the ellipse is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the ellipse be obscured by objects closer to the camera. + /// + public static void DrawEllipse(EllipseF ellipse, int sides, in Color color, float duration, bool depthTest) + { + DrawEllipse(ellipse, sides, Vector2.zero, color, duration, depthTest); + } + + /// + /// Draws an ellipse. + /// + /// The ellipse to draw. + /// The number of sides to generate. + /// The drawing offset of the ellipse. + /// The color of the ellipse. + /// + /// The duration of the ellipse's visibility, in seconds. If 0 is passed, the ellipse is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the ellipse be obscured by objects closer to the camera. + /// + public static void DrawEllipse(EllipseF ellipse, int sides, Vector2 offset, in Color color, float duration, bool depthTest) + { + DrawPolygon(CreateEllipse(ellipse.HorizontalRadius, ellipse.VerticalRadius, sides), offset, color, duration, depthTest); + } + + + private static PolygonF CreateEllipse(float radiusX, float radiusY, int sides) + { + const float max = 2.0f * MathF.PI; + float step = max / sides; + + var points = new List(); + for (var theta = 0f; theta < max; theta += step) + { + float x = radiusX * MathF.Cos(theta); + float y = radiusY * MathF.Sin(theta); + points.Add(new System.Numerics.Vector2(x, y)); + } + + return new PolygonF(points); + } +} diff --git a/X10D.Unity/src/DebugEx.Line.cs b/X10D.Unity/src/DebugEx.Line.cs new file mode 100644 index 0000000..8a41d8f --- /dev/null +++ b/X10D.Unity/src/DebugEx.Line.cs @@ -0,0 +1,209 @@ +using UnityEngine; +using X10D.Drawing; +using X10D.Unity.Drawing; +using X10D.Unity.Numerics; + +namespace X10D.Unity; + +public static partial class DebugEx +{ + /// + /// Draws a line between start and end points. + /// + /// The starting point. + /// The ending point. + public static void DrawLine(Vector3 start, Vector3 end) + { + DrawLine(start, end, Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a line between start and end points, with the specified color. + /// + /// The starting point. + /// The ending point. + /// The color of the line. + public static void DrawLine(Vector3 start, Vector3 end, in Color color) + { + DrawLine(start, end, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a line between start and end points, with the specified color. + /// + /// The starting point. + /// The ending point. + /// The color of the line. + /// + /// The duration of the line's visibility, in seconds. If 0 is passed, the line is visible for a single frame. + /// + public static void DrawLine(Vector3 start, Vector3 end, in Color color, float duration) + { + DrawLine(start, end, color, duration, DefaultDepthTest); + } + + /// + /// Draws a line between start and end points, with the specified color. + /// + /// The starting point. + /// The ending point. + /// The color of the line. + /// + /// The duration of the line's visibility, in seconds. If 0 is passed, the line is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the line be obscured by objects closer to the camera. + /// + public static void DrawLine(Vector3 start, Vector3 end, in Color color, float duration, bool depthTest) + { + Debug.DrawLine(start, end, color, duration, depthTest); + } + + /// + /// Draws a line between start and end points. + /// + /// The line to draw. + public static void DrawLine(Line line) + { + DrawLine(line, Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a line between start and end points, with the specified color. + /// + /// The line to draw. + /// The color of the line. + public static void DrawLine(Line line, in Color color) + { + DrawLine(line, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a line between start and end points, with the specified color. + /// + /// The line to draw. + /// The color of the line. + /// + /// The duration of the line's visibility, in seconds. If 0 is passed, the line is visible for a single frame. + /// + public static void DrawLine(Line line, in Color color, float duration) + { + DrawLine(line, color, duration, DefaultDepthTest); + } + + /// + /// Draws a line between start and end points, with the specified color. + /// + /// The line to draw. + /// The color of the line. + /// + /// The duration of the line's visibility, in seconds. If 0 is passed, the line is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the line be obscured by objects closer to the camera. + /// + public static void DrawLine(Line line, in Color color, float duration, bool depthTest) + { + Debug.DrawLine(line.Start.ToUnityVector2(), line.End.ToUnityVector2(), color, duration, depthTest); + } + + /// + /// Draws a line between start and end points. + /// + /// The line to draw. + public static void DrawLine(LineF line) + { + DrawLine(line, Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a line between start and end points, with the specified color. + /// + /// The line to draw. + /// The color of the line. + public static void DrawLine(LineF line, in Color color) + { + DrawLine(line, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a line between start and end points, with the specified color. + /// + /// The line to draw. + /// The color of the line. + /// + /// The duration of the line's visibility, in seconds. If 0 is passed, the line is visible for a single frame. + /// + public static void DrawLine(LineF line, in Color color, float duration) + { + DrawLine(line, color, duration, DefaultDepthTest); + } + + /// + /// Draws a line between start and end points, with the specified color. + /// + /// The line to draw. + /// The color of the line. + /// + /// The duration of the line's visibility, in seconds. If 0 is passed, the line is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the line be obscured by objects closer to the camera. + /// + public static void DrawLine(LineF line, in Color color, float duration, bool depthTest) + { + Debug.DrawLine(line.Start.ToUnityVector2(), line.End.ToUnityVector2(), color, duration, depthTest); + } + + /// + /// Draws a line between start and end points. + /// + /// The line to draw. + public static void DrawLine(Line3D line) + { + DrawLine(line, Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a line between start and end points, with the specified color. + /// + /// The line to draw. + /// The color of the line. + public static void DrawLine(Line3D line, in Color color) + { + DrawLine(line, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a line between start and end points, with the specified color. + /// + /// The line to draw. + /// The color of the line. + /// + /// The duration of the line's visibility, in seconds. If 0 is passed, the line is visible for a single frame. + /// + public static void DrawLine(Line3D line, in Color color, float duration) + { + DrawLine(line, color, duration, DefaultDepthTest); + } + + /// + /// Draws a line between start and end points, with the specified color. + /// + /// The line to draw. + /// The color of the line. + /// + /// The duration of the line's visibility, in seconds. If 0 is passed, the line is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the line be obscured by objects closer to the camera. + /// + public static void DrawLine(Line3D line, in Color color, float duration, bool depthTest) + { + Debug.DrawLine(line.Start.ToUnityVector(), line.End.ToUnityVector(), color, duration, depthTest); + } +} diff --git a/X10D.Unity/src/DebugEx.Polygon.cs b/X10D.Unity/src/DebugEx.Polygon.cs new file mode 100644 index 0000000..62abd21 --- /dev/null +++ b/X10D.Unity/src/DebugEx.Polygon.cs @@ -0,0 +1,226 @@ +using UnityEngine; +using X10D.Drawing; +using X10D.Unity.Drawing; +using PointF = System.Drawing.PointF; + +namespace X10D.Unity; + +public static partial class DebugEx +{ + /// + /// Draws a polygon. + /// + /// The polygon to draw. + public static void DrawPolygon(Polygon polygon) + { + DrawPolygon((PolygonF)polygon, Vector2.zero, Color.white, DefaultDrawDuration, true); + } + + /// + /// Draws a polygon. + /// + /// The polygon to draw. + /// The drawing offset of the polygon. + public static void DrawPolygon(Polygon polygon, in Vector3 offset) + { + DrawPolygon((PolygonF)polygon, offset, Color.white, DefaultDrawDuration, true); + } + + /// + /// Draws a polygon. + /// + /// The polygon to draw. + /// The color to use for drawing. + public static void DrawPolygon(Polygon polygon, in Color color) + { + DrawPolygon((PolygonF)polygon, Vector2.zero, color, DefaultDrawDuration, true); + } + + /// + /// Draws a polygon. + /// + /// The polygon to draw. + /// The drawing offset of the polygon. + /// The color to use for drawing. + public static void DrawPolygon(Polygon polygon, in Vector3 offset, in Color color) + { + DrawPolygon((PolygonF)polygon, offset, color, DefaultDrawDuration, true); + } + + /// + /// Draws a polygon. + /// + /// The polygon to draw. + /// The color to use for drawing. + /// + /// The duration of the polygon's visibility, in seconds. If 0 is passed, the polygon is visible for a single frame. + /// + public static void DrawPolygon(Polygon polygon, in Color color, float duration) + { + DrawPolygon((PolygonF)polygon, Vector2.zero, color, duration, true); + } + + /// + /// Draws a polygon. + /// + /// The polygon to draw. + /// The drawing offset of the polygon. + /// The color to use for drawing. + /// + /// The duration of the polygon's visibility, in seconds. If 0 is passed, the polygon is visible for a single frame. + /// + public static void DrawPolygon(Polygon polygon, in Vector3 offset, in Color color, float duration) + { + DrawPolygon((PolygonF)polygon, offset, color, duration, true); + } + + /// + /// Draws a polygon. + /// + /// The polygon to draw. + /// The color to use for drawing. + /// + /// The duration of the polygon's visibility, in seconds. If 0 is passed, the polygon is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the box be obscured by objects closer to the camera. + /// + public static void DrawPolygon(Polygon polygon, in Color color, float duration, bool depthTest) + { + DrawPolygon((PolygonF)polygon, Vector2.zero, color, duration, depthTest); + } + + /// + /// Draws a polygon. + /// + /// The polygon to draw. + /// The drawing offset of the polygon. + /// The color to use for drawing. + /// + /// The duration of the polygon's visibility, in seconds. If 0 is passed, the polygon is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the box be obscured by objects closer to the camera. + /// + public static void DrawPolygon(Polygon polygon, in Vector3 offset, in Color color, float duration, bool depthTest) + { + DrawPolygon((PolygonF)polygon, offset, color, duration, depthTest); + } + + /// + /// Draws a polygon. + /// + /// The polygon to draw. + public static void DrawPolygon(PolygonF polygon) + { + DrawPolygon(polygon, Vector2.zero, Color.white, DefaultDrawDuration, true); + } + + /// + /// Draws a polygon. + /// + /// The polygon to draw. + /// The drawing offset of the polygon. + public static void DrawPolygon(PolygonF polygon, in Vector3 offset) + { + DrawPolygon(polygon, offset, Color.white, DefaultDrawDuration, true); + } + + /// + /// Draws a polygon. + /// + /// The polygon to draw. + /// The color to use for drawing. + public static void DrawPolygon(PolygonF polygon, in Color color) + { + DrawPolygon(polygon, Vector2.zero, color, DefaultDrawDuration, true); + } + + /// + /// Draws a polygon. + /// + /// The polygon to draw. + /// The drawing offset of the polygon. + /// The color to use for drawing. + public static void DrawPolygon(PolygonF polygon, in Vector3 offset, in Color color) + { + DrawPolygon(polygon, offset, color, DefaultDrawDuration, true); + } + + /// + /// Draws a polygon. + /// + /// The polygon to draw. + /// The color to use for drawing. + /// + /// The duration of the polygon's visibility, in seconds. If 0 is passed, the polygon is visible for a single frame. + /// + public static void DrawPolygon(PolygonF polygon, in Color color, float duration) + { + DrawPolygon(polygon, Vector2.zero, color, duration, true); + } + + /// + /// Draws a polygon. + /// + /// The polygon to draw. + /// The drawing offset of the polygon. + /// The color to use for drawing. + /// + /// The duration of the polygon's visibility, in seconds. If 0 is passed, the polygon is visible for a single frame. + /// + public static void DrawPolygon(PolygonF polygon, in Vector3 offset, in Color color, float duration) + { + DrawPolygon(polygon, offset, color, duration, true); + } + + /// + /// Draws a polygon. + /// + /// The polygon to draw. + /// The color to use for drawing. + /// + /// The duration of the polygon's visibility, in seconds. If 0 is passed, the polygon is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the box be obscured by objects closer to the camera. + /// + public static void DrawPolygon(PolygonF polygon, in Color color, float duration, bool depthTest) + { + DrawPolygon(polygon, Vector2.zero, color, duration, depthTest); + } + + /// + /// Draws a polygon. + /// + /// The polygon to draw. + /// The drawing offset of the polygon. + /// The color to use for drawing. + /// + /// The duration of the polygon's visibility, in seconds. If 0 is passed, the polygon is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the box be obscured by objects closer to the camera. + /// + public static void DrawPolygon(PolygonF polygon, in Vector3 offset, in Color color, float duration, bool depthTest) + { + IReadOnlyList points = polygon.Vertices; + if (points.Count < 2) + { + return; + } + + for (var i = 0; i < points.Count; i++) + { + int j = (i + 1) % points.Count; + Vector3 start = (Vector3)points[i].ToUnityVector2() + offset; + Vector3 end = (Vector3)points[j].ToUnityVector2() + offset; + + DrawLine(start, end, color, duration, depthTest); + } + } +} diff --git a/X10D.Unity/src/DebugEx.Polyhedron.cs b/X10D.Unity/src/DebugEx.Polyhedron.cs new file mode 100644 index 0000000..7c09f65 --- /dev/null +++ b/X10D.Unity/src/DebugEx.Polyhedron.cs @@ -0,0 +1,123 @@ +using UnityEngine; +using X10D.Drawing; +using X10D.Unity.Numerics; + +namespace X10D.Unity; + +public static partial class DebugEx +{ + /// + /// Draws a polyhedron. + /// + /// The polyhedron to draw. + public static void DrawPolyhedron(Polyhedron polyhedron) + { + DrawPolyhedron(polyhedron, Vector2.zero, Color.white, DefaultDrawDuration, true); + } + + /// + /// Draws a polyhedron. + /// + /// The polyhedron to draw. + /// The drawing offset of the polyhedron. + public static void DrawPolyhedron(Polyhedron polyhedron, in Vector3 offset) + { + DrawPolyhedron(polyhedron, offset, Color.white, DefaultDrawDuration, true); + } + + /// + /// Draws a polyhedron. + /// + /// The polyhedron to draw. + /// The color to use for drawing. + public static void DrawPolyhedron(Polyhedron polyhedron, in Color color) + { + DrawPolyhedron(polyhedron, Vector2.zero, color, DefaultDrawDuration, true); + } + + /// + /// Draws a polyhedron. + /// + /// The polyhedron to draw. + /// The drawing offset of the polyhedron. + /// The color to use for drawing. + public static void DrawPolyhedron(Polyhedron polyhedron, in Vector3 offset, in Color color) + { + DrawPolyhedron(polyhedron, offset, color, DefaultDrawDuration, true); + } + + /// + /// Draws a polyhedron. + /// + /// The polyhedron to draw. + /// The color to use for drawing. + /// + /// The duration of the polyhedron's visibility, in seconds. If 0 is passed, the polyhedron is visible for a single frame. + /// + public static void DrawPolyhedron(Polyhedron polyhedron, in Color color, float duration) + { + DrawPolyhedron(polyhedron, Vector2.zero, color, duration, true); + } + + /// + /// Draws a polyhedron. + /// + /// The polyhedron to draw. + /// The drawing offset of the polyhedron. + /// The color to use for drawing. + /// + /// The duration of the polyhedron's visibility, in seconds. If 0 is passed, the polyhedron is visible for a single frame. + /// + public static void DrawPolyhedron(Polyhedron polyhedron, in Vector3 offset, in Color color, float duration) + { + DrawPolyhedron(polyhedron, offset, color, duration, true); + } + + /// + /// Draws a polyhedron. + /// + /// The polyhedron to draw. + /// The color to use for drawing. + /// + /// The duration of the polyhedron's visibility, in seconds. If 0 is passed, the polyhedron is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the box be obscured by objects closer to the camera. + /// + public static void DrawPolyhedron(Polyhedron polyhedron, in Color color, float duration, bool depthTest) + { + DrawPolyhedron(polyhedron, Vector2.zero, color, duration, depthTest); + } + + /// + /// Draws a polyhedron. + /// + /// The polyhedron to draw. + /// The drawing offset of the polyhedron. + /// The color to use for drawing. + /// + /// The duration of the polyhedron's visibility, in seconds. If 0 is passed, the polyhedron is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the box be obscured by objects closer to the camera. + /// + public static void DrawPolyhedron(Polyhedron polyhedron, in Vector3 offset, in Color color, float duration, bool depthTest) + { + IReadOnlyList points = polyhedron.Vertices; + if (points.Count < 2) + { + return; + } + + for (var i = 0; i < points.Count; i++) + { + int j = (i + 1) % points.Count; + Vector3 start = points[i].ToUnityVector() + offset; + Vector3 end = points[j].ToUnityVector() + offset; + + DrawLine(start, end, color, duration, depthTest); + } + } +} diff --git a/X10D.Unity/src/DebugEx.Ray.cs b/X10D.Unity/src/DebugEx.Ray.cs new file mode 100644 index 0000000..0328621 --- /dev/null +++ b/X10D.Unity/src/DebugEx.Ray.cs @@ -0,0 +1,108 @@ +using UnityEngine; + +namespace X10D.Unity; + +public static partial class DebugEx +{ + /// + /// Draws a ray. + /// + /// The ray to draw. + public static void DrawRay(Ray ray) + { + DrawRay(ray, Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a ray. + /// + /// The ray to draw. + /// The color of the line. + public static void DrawRay(Ray ray, in Color color) + { + DrawRay(ray, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a ray. + /// + /// The ray to draw. + /// The color of the line. + /// + /// The duration of the line's visibility, in seconds. If 0 is passed, the line is visible for a single frame. + /// + public static void DrawRay(Ray ray, in Color color, float duration) + { + DrawRay(ray, color, duration, DefaultDepthTest); + } + + /// + /// Draws a ray. + /// + /// The ray to draw. + /// The color of the line. + /// + /// The duration of the line's visibility, in seconds. If 0 is passed, the line is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the line be obscured by objects closer to the camera. + /// + public static void DrawRay(Ray ray, in Color color, float duration, bool depthTest) + { + Debug.DrawRay(ray.origin, ray.direction, color, duration, depthTest); + } + + /// + /// Draws a ray. + /// + /// The starting point. + /// The direction. + public static void DrawRay(Vector3 start, Vector3 direction) + { + DrawRay(start, direction, Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a ray. + /// + /// The starting point. + /// The direction. + /// The color of the line. + public static void DrawRay(Vector3 start, Vector3 direction, in Color color) + { + DrawRay(start, direction, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a ray. + /// + /// The starting point. + /// The direction. + /// The color of the line. + /// + /// The duration of the line's visibility, in seconds. If 0 is passed, the line is visible for a single frame. + /// + public static void DrawRay(Vector3 start, Vector3 direction, in Color color, float duration) + { + DrawRay(start, direction, color, duration, DefaultDepthTest); + } + + /// + /// Draws a ray. + /// + /// The starting point. + /// The direction. + /// The color of the line. + /// + /// The duration of the line's visibility, in seconds. If 0 is passed, the line is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the line be obscured by objects closer to the camera. + /// + public static void DrawRay(Vector3 start, Vector3 direction, in Color color, float duration, bool depthTest) + { + Debug.DrawRay(start, direction, color, duration, depthTest); + } +} diff --git a/X10D.Unity/src/DebugEx.Sphere.cs b/X10D.Unity/src/DebugEx.Sphere.cs new file mode 100644 index 0000000..0be223e --- /dev/null +++ b/X10D.Unity/src/DebugEx.Sphere.cs @@ -0,0 +1,198 @@ +using UnityEngine; +using X10D.Drawing; +using X10D.Unity.Numerics; + +namespace X10D.Unity; + +public static partial class DebugEx +{ + /// + /// Draws a sphere with the specified color. + /// + /// The center point of the sphere. + /// The radius of the sphere. + /// The number of sides to generate. + public static void DrawSphere(Vector3 center, float radius, int sides) + { + DrawSphere(center, radius, sides, Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a sphere with the specified color. + /// + /// The center point of the sphere. + /// The radius of the sphere. + /// The number of sides to generate. + /// The color of the sphere. + public static void DrawSphere(Vector3 center, float radius, int sides, in Color color) + { + DrawSphere(center, radius, sides, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a sphere with the specified color and duration. + /// + /// The center point of the sphere. + /// The radius of the sphere. + /// The number of sides to generate. + /// The color of the sphere. + /// + /// The duration of the sphere's visibility, in seconds. If 0 is passed, the sphere is visible for a single frame. + /// + public static void DrawSphere(Vector3 center, float radius, int sides, in Color color, float duration) + { + DrawSphere(center, radius, sides, Vector2.zero, color, duration, DefaultDepthTest); + } + + /// + /// Draws a sphere with the specified color and duration. + /// + /// The center point of the sphere. + /// The radius of the sphere. + /// The number of sides to generate. + /// The color of the sphere. + /// + /// The duration of the sphere's visibility, in seconds. If 0 is passed, the sphere is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the sphere be obscured by objects closer to the camera. + /// + public static void DrawSphere(Vector3 center, float radius, int sides, in Color color, float duration, bool depthTest) + { + DrawSphere(center, radius, sides, Vector2.zero, color, duration, depthTest); + } + + /// + /// Draws a sphere. + /// + /// The center point of the sphere. + /// The radius of the sphere. + /// The number of sides to generate. + /// The drawing offset of the sphere. + /// The color of the sphere. + /// + /// The duration of the sphere's visibility, in seconds. If 0 is passed, the sphere is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the sphere be obscured by objects closer to the camera. + /// + public static void DrawSphere(Vector3 center, float radius, int sides, Vector2 offset, in Color color, float duration, + bool depthTest) + { + DrawSphere(new Sphere(center.ToSystemVector(), radius), sides, offset, color, duration, depthTest); + } + + /// + /// Draws a sphere with the specified color. + /// + /// The sphere to draw. + /// The number of sides to generate. + public static void DrawSphere(Sphere sphere, int sides) + { + DrawSphere(sphere, sides, Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a sphere with the specified color. + /// + /// The sphere to draw. + /// The number of sides to generate. + /// The drawing offset of the sphere. + public static void DrawSphere(Sphere sphere, int sides, Vector2 offset) + { + DrawSphere(sphere, sides, offset, Color.white, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a sphere with the specified color. + /// + /// The sphere to draw. + /// The number of sides to generate. + /// The color of the sphere. + public static void DrawSphere(Sphere sphere, int sides, in Color color) + { + DrawSphere(sphere, sides, Vector2.zero, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a sphere with the specified color. + /// + /// The sphere to draw. + /// The number of sides to generate. + /// The drawing offset of the sphere. + /// The color of the sphere. + public static void DrawSphere(Sphere sphere, int sides, Vector2 offset, in Color color) + { + DrawSphere(sphere, sides, offset, color, DefaultDrawDuration, DefaultDepthTest); + } + + /// + /// Draws a sphere with the specified color and duration. + /// + /// The sphere to draw. + /// The number of sides to generate. + /// The color of the sphere. + /// + /// The duration of the sphere's visibility, in seconds. If 0 is passed, the sphere is visible for a single frame. + /// + public static void DrawSphere(Sphere sphere, int sides, in Color color, float duration) + { + DrawSphere(sphere, sides, Vector2.zero, color, duration, DefaultDepthTest); + } + + /// + /// Draws a sphere with the specified color and duration. + /// + /// The sphere to draw. + /// The number of sides to generate. + /// The drawing offset of the sphere. + /// The color of the sphere. + /// + /// The duration of the sphere's visibility, in seconds. If 0 is passed, the sphere is visible for a single frame. + /// + public static void DrawSphere(Sphere sphere, int sides, Vector2 offset, in Color color, float duration) + { + DrawSphere(sphere, sides, offset, color, duration, DefaultDepthTest); + } + + /// + /// Draws a sphere with the specified color and duration. + /// + /// The sphere to draw. + /// The number of sides to generate. + /// The color of the sphere. + /// + /// The duration of the sphere's visibility, in seconds. If 0 is passed, the sphere is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the sphere be obscured by objects closer to the camera. + /// + public static void DrawSphere(Sphere sphere, int sides, in Color color, float duration, bool depthTest) + { + DrawSphere(sphere, sides, Vector2.zero, color, duration, depthTest); + } + + /// + /// Draws a sphere. + /// + /// The sphere to draw. + /// The number of sides to generate. + /// The drawing offset of the sphere. + /// The color of the sphere. + /// + /// The duration of the sphere's visibility, in seconds. If 0 is passed, the sphere is visible for a single frame. + /// + /// + /// if depth test should be applied; otherwise, . Passing + /// will have the sphere be obscured by objects closer to the camera. + /// + public static void DrawSphere(Sphere sphere, int sides, in Vector3 offset, in Color color, float duration, bool depthTest) + { + DrawPolyhedron(CreateCircle(sphere.Radius, sides, Vector3.zero), offset, color, duration, depthTest); + DrawPolyhedron(CreateCircle(sphere.Radius, sides, Vector3.left), offset, color, duration, depthTest); + DrawPolyhedron(CreateCircle(sphere.Radius, sides, Vector3.up), offset, color, duration, depthTest); + } +} diff --git a/X10D.Unity/src/DebugEx.cs b/X10D.Unity/src/DebugEx.cs new file mode 100644 index 0000000..e6879c7 --- /dev/null +++ b/X10D.Unity/src/DebugEx.cs @@ -0,0 +1,417 @@ +using System.Diagnostics; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using UnityEngine; +using Debug = UnityEngine.Debug; +using Object = UnityEngine.Object; + +namespace X10D.Unity; + +/// +/// An extended version of Unity's utility class which offers support for drawing simple +/// primitives. +/// +public static partial class DebugEx +{ + /// + /// The default value to use for the duration parameter. + /// + private const float DefaultDrawDuration = 0.0f; + + /// + /// The default value to use for the depthTest parameter. + /// + private const bool DefaultDepthTest = true; + + /// + /// Gets a value indicating whether this is a debug build. + /// + /// if this is a debug build; otherwise, . + // ReSharper disable once InconsistentNaming + public static bool isDebugBuild + { + get => Debug.isDebugBuild; + } + + /// + /// Gets a value indicating whether the developer console is visible. + /// + /// if the developer console is visible; otherwise, . + // ReSharper disable once InconsistentNaming + public static bool isDeveloperConsoleVisible + { + get => Debug.developerConsoleVisible; + } + + /// + /// Gets the default Unity debug logger. + /// + /// The Unity debug logger. + // ReSharper disable once InconsistentNaming + public static ILogger unityLogger + { + get => Debug.unityLogger; + } + + /// + /// Asserts a condition. + /// + /// The condition to assert. + [Conditional("UNITY_ASSERTIONS")] + [AssertionMethod] + [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] + public static void Assert(bool condition) + { + if (condition) + { + return; + } + + unityLogger.Log(LogType.Assert, "Assertion failed"); + } + + /// + /// Asserts a condition. + /// + /// The condition to assert. + /// The object to which the assertion applies. + [Conditional("UNITY_ASSERTIONS")] + [AssertionMethod] + [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] + public static void Assert(bool condition, Object context) + { + if (condition) + { + return; + } + + unityLogger.Log(LogType.Assert, (object)"Assertion failed", context); + } + + /// + /// Asserts a condition. + /// + /// The condition to assert. + /// The message to log. + [Conditional("UNITY_ASSERTIONS")] + [AssertionMethod] + [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] + public static void Assert(bool condition, string? message) + { + if (condition) + { + return; + } + + unityLogger.Log(LogType.Assert, message); + } + + /// + /// Asserts a condition. + /// + /// The condition to assert. + /// The message to log. + [Conditional("UNITY_ASSERTIONS")] + [AssertionMethod] + [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] + public static void Assert(bool condition, T? message) + { + if (condition) + { + return; + } + + unityLogger.Log(LogType.Assert, message?.ToString()); + } + + /// + /// Logs a message to the Unity Console. + /// + /// The condition to assert. + /// The message to log. + /// The object to which the assertion applies. + [Conditional("UNITY_ASSERTIONS")] + [AssertionMethod] + [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] + public static void Assert(bool condition, string? message, Object? context) + { + if (condition) + { + return; + } + + unityLogger.Log(LogType.Assert, (object?)message, context); + } + + /// + /// Logs a message to the Unity Console. + /// + /// The condition to assert. + /// The message to log. + /// The object to which the assertion applies. + [Conditional("UNITY_ASSERTIONS")] + [AssertionMethod] + [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] + public static void Assert(bool condition, T? message, Object? context) + { + if (condition) + { + return; + } + + unityLogger.Log(LogType.Assert, (object?)message?.ToString(), context); + } + + /// + /// Pauses the editor. + /// + public static void Break() + { + Debug.Break(); + } + + /// + /// Clears the developer console. + /// + public static void ClearDeveloperConsole() + { + Debug.ClearDeveloperConsole(); + } + + /// + /// Populate an unmanaged buffer with the current managed call stack as a sequence of UTF-8 bytes, without allocating GC + /// memory. + /// + /// The target buffer to receive the callstack text. + /// The maximum number of bytes to write. + /// The project folder path, to clean up path names. + /// The number of bytes written into the buffer. + [MustUseReturnValue("Fewer bytes may be returned than requested.")] + public static unsafe int ExtractStackTraceNoAlloc(byte* buffer, int bufferMax, string projectFolder) + { + return Debug.ExtractStackTraceNoAlloc(buffer, bufferMax, projectFolder); + } + + /// + /// Logs a message to the Unity Console. + /// + /// The message to log. + public static void Log(string? message) + { + Debug.Log(message); + } + + /// + /// Logs a message to the Unity Console. + /// + /// The message to log. + public static void Log(T message) + { + Log(message?.ToString()); + } + + /// + /// Logs a message to the Unity Console. + /// + /// The message to log. + /// The object to which the message applies. + public static void Log(string message, Object? context) + { + Debug.Log(message, context); + } + + /// + /// Logs a message to the Unity Console. + /// + /// The message to log. + /// The object to which the message applies. + public static void Log(T message, Object? context) + { + Debug.Log(message?.ToString(), context); + } + + /// + /// Logs an assertion message to the Unity Console. + /// + /// The message to log. + [Conditional("UNITY_ASSERTIONS")] + [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] + public static void LogAssertion(string? message) + { + unityLogger.Log(LogType.Assert, message); + } + + /// + /// Logs an assertion message to the Unity Console. + /// + /// The message to log. + [Conditional("UNITY_ASSERTIONS")] + [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] + public static void LogAssertion(T message) + { + unityLogger.Log(LogType.Assert, message?.ToString()); + } + + /// + /// Logs an assertion message to the Unity Console. + /// + /// The message to log. + /// The object to which the message applies. + [Conditional("UNITY_ASSERTIONS")] + [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] + public static void LogAssertion(string message, Object? context) + { + unityLogger.Log(LogType.Assert, (object?)message, context); + } + + /// + /// Logs an assertion message to the Unity Console. + /// + /// The message to log. + /// The object to which the message applies. + [Conditional("UNITY_ASSERTIONS")] + [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] + public static void LogAssertion(T? message, Object? context) + { + unityLogger.Log(LogType.Assert, (object?)message?.ToString(), context); + } + + /// + /// Logs an error message to the Unity Console. + /// + /// The message to log. + public static void LogError(string? message) + { + Debug.LogError(message); + } + + /// + /// Logs an error message to the Unity Console. + /// + /// The message to log. + public static void LogError(T? message) + { + LogError(message?.ToString()); + } + + /// + /// Logs an error message to the Unity Console. + /// + /// The message to log. + /// The object to which the message applies. + public static void LogError(string message, Object? context) + { + Debug.LogError(message, context); + } + + /// + /// Logs an error message to the Unity Console. + /// + /// The message to log. + /// The object to which the message applies. + public static void LogError(T? message, Object? context) + { + Debug.LogError(message?.ToString(), context); + } + + /// + /// Logs a formatted error message to the Unity Console. + /// + /// The format string of the message to log. + /// The format arguments. + public static void LogErrorFormat(string? format, params object?[]? args) + { + Debug.LogErrorFormat(format, args); + } + + /// + /// Logs a formatted error message to the Unity Console. + /// + /// The object to which this message applies. + /// The format string of the message to log. + /// The format arguments. + public static void LogErrorFormat(Object context, string? format, params object?[]? args) + { + Debug.LogErrorFormat(context, format, args); + } + + /// + /// Logs a formatted message to the Unity Console. + /// + /// The format string of the message to log. + /// The format arguments. + public static void LogFormat(string? format, params object?[]? args) + { + Debug.LogFormat(format, args); + } + + /// + /// Logs a formatted message to the Unity Console. + /// + /// The object to which this message applies. + /// The format string of the message to log. + /// The format arguments. + public static void LogFormat(Object context, string? format, params object?[]? args) + { + Debug.LogFormat(context, format, args); + } + + /// + /// Logs a warning message to the Unity Console. + /// + /// The message to log. + public static void LogWarning(string? message) + { + Debug.LogWarning(message); + } + + /// + /// Logs a warning message to the Unity Console. + /// + /// The message to log. + public static void LogWarning(T? message) + { + LogWarning(message?.ToString()); + } + + /// + /// Logs a warning message to the Unity Console. + /// + /// The message to log. + /// The object to which the message applies. + public static void LogWarning(string message, Object? context) + { + Debug.LogWarning(message, context); + } + + /// + /// Logs a warning message to the Unity Console. + /// + /// The message to log. + /// The object to which the message applies. + public static void LogWarning(T? message, Object? context) + { + Debug.LogWarning(message?.ToString(), context); + } + + /// + /// Logs a formatted warning message to the Unity Console. + /// + /// The format string of the message to log. + /// The format arguments. + public static void LogWarningFormat(string? format, params object?[]? args) + { + Debug.LogWarningFormat(format, args); + } + + /// + /// Logs a formatted warning message to the Unity Console. + /// + /// The object to which this message applies. + /// The format string of the message to log. + /// The format arguments. + public static void LogWarningFormat(Object context, string? format, params object?[]? args) + { + Debug.LogWarningFormat(context, format, args); + } +}