Spinner.cs 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. using System;
  2. using UnityEngine;
  3. namespace SingularityGroup.HotReload.Editor {
  4. internal class Spinner {
  5. internal static string SpinnerIconPath => "icon_loading_star_light_mode_96";
  6. internal static Texture2D spinnerTexture => GUIHelper.GetInvertibleIcon(InvertibleIcon.Spinner);
  7. private Texture2D _rotatedTextureLight;
  8. private Texture2D _rotatedTextureDark;
  9. private Texture2D rotatedTextureLight => _rotatedTextureLight ? _rotatedTextureLight : _rotatedTextureLight = GetCopy(spinnerTexture);
  10. private Texture2D rotatedTextureDark => _rotatedTextureDark ? _rotatedTextureDark : _rotatedTextureDark = GetCopy(spinnerTexture);
  11. internal Texture2D rotatedTexture => HotReloadWindowStyles.IsDarkMode ? rotatedTextureDark : rotatedTextureLight;
  12. private float _rotationAngle;
  13. private DateTime _lastRotation;
  14. private int _rotationPeriod;
  15. internal Spinner(int rotationPeriodInMilliseconds) {
  16. _rotationPeriod = rotationPeriodInMilliseconds;
  17. }
  18. internal Texture2D GetIcon() {
  19. if (DateTime.UtcNow - _lastRotation > TimeSpan.FromMilliseconds(_rotationPeriod)) {
  20. _lastRotation = DateTime.UtcNow;
  21. _rotationAngle += 45;
  22. if (_rotationAngle >= 360f)
  23. _rotationAngle -= 360f;
  24. return RotateImage(spinnerTexture, _rotationAngle);
  25. }
  26. return rotatedTexture;
  27. }
  28. private Texture2D RotateImage(Texture2D originalTexture, float angle) {
  29. int w = originalTexture.width;
  30. int h = originalTexture.height;
  31. int x, y;
  32. float centerX = w / 2f;
  33. float centerY = h / 2f;
  34. for (x = 0; x < w; x++) {
  35. for (y = 0; y < h; y++) {
  36. float dx = x - centerX;
  37. float dy = y - centerY;
  38. float distance = Mathf.Sqrt(dx * dx + dy * dy);
  39. float oldAngle = Mathf.Atan2(dy, dx) * Mathf.Rad2Deg;
  40. float newAngle = oldAngle + angle;
  41. float newX = centerX + distance * Mathf.Cos(newAngle * Mathf.Deg2Rad);
  42. float newY = centerY + distance * Mathf.Sin(newAngle * Mathf.Deg2Rad);
  43. if (newX >= 0 && newX < w && newY >= 0 && newY < h) {
  44. rotatedTexture.SetPixel(x, y, originalTexture.GetPixel((int)newX, (int)newY));
  45. } else {
  46. rotatedTexture.SetPixel(x, y, Color.clear);
  47. }
  48. }
  49. }
  50. rotatedTexture.Apply();
  51. return rotatedTexture;
  52. }
  53. public static Texture2D GetCopy(Texture2D tex, TextureFormat format = TextureFormat.RGBA32, bool mipChain = false) {
  54. var tmp = RenderTexture.GetTemporary(tex.width, tex.height, 0, RenderTextureFormat.Default, RenderTextureReadWrite.Linear);
  55. Graphics.Blit(tex, tmp);
  56. RenderTexture.active = tmp;
  57. try {
  58. var copy = new Texture2D(tex.width, tex.height, format, mipChain: mipChain);
  59. copy.ReadPixels(new Rect(0, 0, tmp.width, tmp.height), 0, 0);
  60. copy.Apply();
  61. return copy;
  62. } finally {
  63. RenderTexture.active = null;
  64. RenderTexture.ReleaseTemporary(tmp);
  65. }
  66. }
  67. }
  68. }