IndieGame/client/Packages/com.unity.inputsystem@1.7.0/InputSystem/Utilities/SpriteUtilities.cs

54 lines
2.3 KiB
C#
Raw Normal View History

2024-10-11 10:12:15 +08:00
using Unity.Collections.LowLevel.Unsafe;
using UnityEngine.Experimental.Rendering;
namespace UnityEngine.InputSystem.Utilities
{
internal static class SpriteUtilities
{
public static unsafe Sprite CreateCircleSprite(int radius, Color32 colour)
{
// cache the diameter
var d = radius * 2;
var texture = new Texture2D(d, d, DefaultFormat.LDR, TextureCreationFlags.None);
var colours = texture.GetRawTextureData<Color32>();
var coloursPtr = (Color32*)colours.GetUnsafePtr();
UnsafeUtility.MemSet(coloursPtr, 0, colours.Length * UnsafeUtility.SizeOf<Color32>());
// pack the colour into a ulong so we can write two pixels at a time to the texture data
var colorPtr = (uint*)UnsafeUtility.AddressOf(ref colour);
var colourAsULong = *(ulong*)colorPtr << 32 | *colorPtr;
float rSquared = radius * radius;
// loop over the texture memory one column at a time filling in a line between the two x coordinates
// of the circle at each column
for (var y = -radius; y < radius; y++)
{
// for the current column, calculate what the x coordinate of the circle would be
// using x^2 + y^2 = r^2, or x^2 = r^2 - y^2. The square root of the value of the
// x coordinate will equal half the width of the circle at the current y coordinate
var halfWidth = (int)Mathf.Sqrt(rSquared - y * y);
// position the pointer so it points at the memory where we should start filling in
// the current line
var ptr = coloursPtr
+ (y + radius) * d // the position of the memory at the start of the row at the current y coordinate
+ radius - halfWidth; // the position along the row where we should start inserting colours
// fill in two pixels at a time
for (var x = 0; x < halfWidth; x++)
{
*(ulong*)ptr = colourAsULong;
ptr += 2;
}
}
texture.Apply();
var sprite = Sprite.Create(texture, new Rect(0, 0, d, d), new Vector2(radius, radius), 1, 0, SpriteMeshType.FullRect);
return sprite;
}
}
}