8 Commits 0acb2b6d73 ... fedadb0bcc

Author SHA1 Message Date
  MirzkisD1Ex0 fedadb0bcc 1 3 days ago
  MirzkisD1Ex0 07c682b1f3 1 1 month ago
  MirzkisD1Ex0 87495cc074 1 1 month ago
  MirzkisD1Ex0 85521664fa 1 1 month ago
  MirzkisD1Ex0 4a21041eec 1 2 months ago
  MirzkisD1Ex0 b6e05431a9 1 4 months ago
  MirzkisD1Ex0 0080cd9805 1 4 months ago
  MirzkisD1Ex0 76ddca7ce6 1 6 months ago
100 changed files with 3974 additions and 777 deletions
  1. BIN
      Materials/2D/tile设置.png
  2. 0 254
      Materials/Backend & Upload/Upload2OYManager.cs
  3. 0 250
      Materials/Backend & Upload/Upload2ZCManager.cs
  4. 297 0
      Materials/Funny/CubeController.cs
  5. BIN
      Materials/Game/JigsawGame/VWJigsawPuzzle.unitypackage
  6. 915 0
      Materials/MediaPipe/FaceDetation/Scenes/00.unity
  7. 87 0
      Materials/MediaPipe/FaceDetation/Scripts/FaceDetectorManager.cs
  8. 18 0
      Materials/MediaPipe/FaceDetation/Scripts/Tester.cs
  9. 43 0
      Materials/MediaPipe/FaceDetation/Scripts/ToneTuneToolkit/SingletonMaster.cs
  10. BIN
      Materials/Models/Dingus/The Funky Russian Train.mp3
  11. BIN
      Materials/Models/Dingus/dingus_nowhiskers.jpg
  12. BIN
      Materials/Models/Dingus/dingus_whiskers.tga.png
  13. BIN
      Materials/Models/Dingus/maxwell the cat.max
  14. BIN
      Materials/Models/Dingus/maxwellthecat.fbx
  15. BIN
      Materials/Models/standardcube.fbx
  16. 23 0
      Materials/Modules/Bridge/JS/JSCommunicator.cs
  17. 14 0
      Materials/Modules/Bridge/JS/Plugins/WebGL/JigsawPuzzleBridge.jslib
  18. 26 0
      Materials/Modules/Bridge/JS/readme.txt
  19. 6 7
      Materials/Modules/DG/CanvasGroupMaster.cs
  20. 0 0
      Materials/Modules/DG/UIStageManager.cs
  21. 74 0
      Materials/Networking/SocketIO/SocketIOClientManager.cs
  22. 0 0
      Materials/Networking/Upload/BackendNetManager.cs
  23. 0 0
      Materials/OSC/收发模块/Configs/oscconfig.json
  24. 5 7
      Materials/OSC/收发模块/UniOSC/UniOSCConfiger.cs
  25. 1 1
      Materials/OSC/收发模块/UniOSC/UniOSCManager.cs
  26. 0 0
      Materials/OSC/收发模块/UniOSC/UniOSCResponder.cs
  27. 18 24
      Materials/ScrollView/20241125_左右滑动限位圆点/ScrollViewHandler.cs
  28. BIN
      Materials/ScrollView/屏幕截图 2025-06-13 111409.png
  29. 6 1
      Materials/SerialPortUtilityPro/SerialPortUtilityPro/SerialPortUtilityProConfiger.cs
  30. 8 5
      Materials/SerialPortUtilityPro/SerialPortUtilityPro/SerialPortUtilityProManager.cs
  31. 3 3
      Materials/SerialPortUtilityPro/SerialPortUtilityPro/SerialPortUtilityProResponder.cs
  32. 0 0
      Materials/SerialPortUtilityPro/configs/serialportutilityproconfig.json
  33. 111 0
      Materials/TCP/TCPClient.cs
  34. 117 0
      Materials/TCP/TCPServer.cs
  35. 50 0
      Materials/TCP/UnityMainThreadDispatcher.cs
  36. 0 0
      Materials/UI/ClickListener.cs
  37. BIN
      Materials/UI/GroundGlass.unitypackage
  38. 3 2
      Materials/WebGL/背景透明化/Plugins/TransparentBackground.jslib
  39. 1 1
      Materials/WebGL/背景透明化/Unity WebGL背景透明化.txt
  40. BIN
      Materials/Windows打印/Printer.unitypackage
  41. 8 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules.meta
  42. 8 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO.meta
  43. 8 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer.meta
  44. 8 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Plugins.meta
  45. BIN
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Plugins/System.Drawing.dll
  46. 33 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Plugins/System.Drawing.dll.meta
  47. 8 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Scripts.meta
  48. 90 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Scripts/PrinterConfiger.cs
  49. 11 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Scripts/PrinterConfiger.cs.meta
  50. 122 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Scripts/PrinterFileProcessor.cs
  51. 11 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Scripts/PrinterFileProcessor.cs.meta
  52. 53 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Scripts/PrinterHandler.cs
  53. 11 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Scripts/PrinterHandler.cs.meta
  54. 342 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Scripts/PrinterManager.cs
  55. 11 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Scripts/PrinterManager.cs.meta
  56. 8 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Networking.meta
  57. 8 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Networking/Upload.meta
  58. 247 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Networking/Upload/Upload2OYManager.cs
  59. 11 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Networking/Upload/Upload2OYManager.cs.meta
  60. 632 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Networking/Upload/Upload2ZCManager.cs
  61. 11 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Networking/Upload/Upload2ZCManager.cs.meta
  62. 8 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Other.meta
  63. 8 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Other/QR.meta
  64. 8 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Other/QR/Plugins.meta
  65. 0 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Other/QR/Plugins/zxing.unity.dll
  66. 0 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Other/QR/Plugins/zxing.unity.dll.meta
  67. 8 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Other/QR/Scripts.meta
  68. 3 2
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Other/QR/Scripts/QRCodeMaster.cs
  69. 0 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Other/QR/Scripts/QRCodeMaster.cs.meta
  70. 214 156
      ToneTuneToolkit/Assets/ToneTuneToolkit/README.md
  71. 1 1
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Common/EventListener.cs
  72. 1 1
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Common/PathChecker.cs
  73. 1 1
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Common/SingletonMaster.cs
  74. 1 1
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Common/TTTDebug.cs
  75. 1 1
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Common/ToolkitManager.cs
  76. 13 1
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Data/DataConverter.cs
  77. 1 1
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Data/DataProcessor.cs
  78. 6 1
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Data/ImageLoader.cs
  79. 1 1
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Data/JsonManager.cs
  80. 1 1
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Data/LitJsonManager.cs
  81. 2 2
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Data/SensitiveWordUtility.cs
  82. 1 1
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Data/TextLoader.cs
  83. 1 1
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Data/TimestampCapturer.cs
  84. 1 1
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Editor/CreateAssetBundles.cs
  85. 1 1
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Editor/EditorStorage.cs
  86. 1 1
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Editor/RenameFolders.cs
  87. 8 9
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Editor/UpdateCopyrights.cs
  88. 1 1
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Funny/BubbleSort.cs
  89. 1 1
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/IO/FTPMaster.cs
  90. 1 1
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/IO/FileCapturer.cs
  91. 75 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/IO/NewFileAlerter.cs
  92. 11 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/IO/NewFileAlerter.cs.meta
  93. 1 1
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Media/FullAngleScreenshotTool.cs
  94. 80 14
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Media/ScreenshotMaster.cs
  95. 1 1
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Media/TextureProcessor.cs
  96. 11 8
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Media/WebCamHandler.cs
  97. 21 9
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Media/WebCamManager.cs
  98. 11 0
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Media/WebCamManager.cs.meta
  99. 1 1
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Mobile/ObjectRotateAndScale.cs
  100. 1 1
      ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/MultimediaExhibitionHall/LED/LEDCommandCenter.cs

BIN
Materials/2D/tile设置.png


+ 0 - 254
Materials/Backend & Upload/Upload2OYManager.cs

@@ -1,254 +0,0 @@
-using System.Collections;
-using System.Collections.Generic;
-using UnityEngine;
-using UnityEngine.Events;
-using System.Text;
-using Newtonsoft.Json;
-using UnityEngine.Networking;
-using System.IO;
-using System;
-using ToneTuneToolkit.Common;
-
-/// <summary>
-/// 对乔哥法宝
-/// </summary>
-public class Upload2OYManager : SingletonMaster<Upload2OYManager>
-{
-  public static UnityAction<Texture2D> OnUploadFinishedBackTexture;
-  public static UnityAction<string> OnUploadFinishedBackString;
-
-  private int appID = 78;
-  private float retryWaitTime = 30f; // 重新上传尝试间隔
-
-  [Header("Token")]
-  [SerializeField] private TokenCallbackJson tokenJson = new TokenCallbackJson();
-  [Header("Cloud")]
-  [SerializeField] private CloudCallbackJson cloudCallbackJson = new CloudCallbackJson();
-  [Header("Server")]
-  [SerializeField] private ServerJson serverJson = new ServerJson();
-  [SerializeField] private ServerCallbackJson serverCallbackJson = new ServerCallbackJson();
-
-  private const string cloudTokenURL = @"https://h5.skyelook.com/api/qiniu/getAccessToken";
-  private const string qiniuURL = @"https://upload.qiniup.com";
-  private const string cloudURL = @"https://h5.skyelook.com/api/attachments";
-
-  // ==================================================
-  #region Step 00 // 完善文件信息
-
-  [Space]
-  [SerializeField] private string fileName;
-  [SerializeField] private string filePath;
-
-  public void UpdateFileInfo(string name, string path)
-  {
-    fileName = name;
-    filePath = path;
-    return;
-  }
-
-  #endregion
-  // ==================================================
-  #region Step 01 // 获取Token
-
-  public void UploadData2Net() => StartCoroutine(nameof(GetTokenFromCloud));
-  private IEnumerator GetTokenFromCloud()
-  {
-    using (UnityWebRequest unityWebRequest = UnityWebRequest.Get(cloudTokenURL))
-    {
-      yield return unityWebRequest.SendWebRequest();
-      if (unityWebRequest.result != UnityWebRequest.Result.Success)
-      {
-        Debug.Log($"[U2OYM] {unityWebRequest.error}");
-        StartCoroutine(nameof(RetryUpload));
-      }
-      else
-      {
-        tokenJson = JsonConvert.DeserializeObject<TokenCallbackJson>(unityWebRequest.downloadHandler.text);
-        Debug.Log($"[U2OYM] Get token sucessed: {tokenJson.data.token}");
-
-        StartCoroutine(nameof(PoseFile2Cloud)); // 下一步
-      }
-    }
-    yield break;
-  }
-
-  #endregion
-  // ==================================================
-  #region Step 02 // 上传文件到七牛云
-
-  private IEnumerator PoseFile2Cloud()
-  {
-    byte[] bytes = File.ReadAllBytes(filePath); // 文件转流
-
-    WWWForm wwwForm = new WWWForm();
-    wwwForm.AddField("token", tokenJson.data.token);
-    wwwForm.AddBinaryData("file", bytes, fileName);
-
-    using (UnityWebRequest unityWebRequest = UnityWebRequest.Post(qiniuURL, wwwForm))
-    {
-      yield return unityWebRequest.SendWebRequest();
-      if (unityWebRequest.result != UnityWebRequest.Result.Success)
-      {
-        Debug.Log($"[U2OYM] {unityWebRequest.error}");
-        StartCoroutine(nameof(RetryUpload));
-      }
-      else
-      {
-        cloudCallbackJson = JsonConvert.DeserializeObject<CloudCallbackJson>(unityWebRequest.downloadHandler.text);
-        Debug.Log($"[U2OYM] Upload sucessed: {cloudCallbackJson.data.file_url}");
-
-        StartCoroutine(SaveFile2Server()); // 下一步
-      }
-    }
-    yield break;
-  }
-
-  #endregion
-  // ==================================================
-  #region Step 03 // 七牛云返回数据传至服务器
-
-  private IEnumerator SaveFile2Server()
-  {
-    serverJson.file_url = cloudCallbackJson.data.file_url;
-    serverJson.app_id = appID;
-
-    string jsonString = JsonConvert.SerializeObject(serverJson);
-    byte[] bytes = Encoding.Default.GetBytes(jsonString);
-
-    using (UnityWebRequest unityWebRequest = new UnityWebRequest(cloudURL, "POST"))
-    {
-      unityWebRequest.SetRequestHeader("Content-Type", "application/json");
-      unityWebRequest.uploadHandler = new UploadHandlerRaw(bytes);
-      unityWebRequest.downloadHandler = new DownloadHandlerBuffer();
-
-      yield return unityWebRequest.SendWebRequest();
-      if (unityWebRequest.result != UnityWebRequest.Result.Success)
-      {
-        Debug.Log($"[U2OYM] {unityWebRequest.error}");
-        StartCoroutine(nameof(RetryUpload));
-      }
-      else
-      {
-        serverCallbackJson = JsonConvert.DeserializeObject<ServerCallbackJson>(unityWebRequest.downloadHandler.text);
-        Debug.Log($"[U2OYM] {serverCallbackJson.data.view_url}");
-
-        // 返回链接
-        if (OnUploadFinishedBackString != null)
-        {
-          OnUploadFinishedBackString(serverCallbackJson.data.view_url);
-        }
-
-        // 组装
-        sunCodeURL = $"https://h5.skyelook.com/api/wechat/getQrcodeApp/{serverCallbackJson.data.code}/wx039a4c76d8788bb0/?env=trial"; // ?env=trial // 额外添加?
-        StartCoroutine(nameof(GetSunCode4Server)); // 下一步搞图
-      }
-    }
-    yield break;
-  }
-
-  #endregion
-  // ==================================================
-  #region Step 04 // 从服务器上获取码
-
-  [SerializeField] private string sunCodeURL;
-  [SerializeField] private Texture2D finalSunCode;
-  private IEnumerator GetSunCode4Server()
-  {
-    using (UnityWebRequest unityWebRequest = UnityWebRequestTexture.GetTexture(sunCodeURL)) // new UnityWebRequest(sunCodeURL, "GET"))
-    {
-      yield return unityWebRequest.SendWebRequest();
-      if (unityWebRequest.result != UnityWebRequest.Result.Success)
-      {
-        Debug.Log("[UM] " + unityWebRequest.error);
-      }
-      else
-      {
-        // td = new Texture2D(600, 600);
-        // td.LoadImage(unityWebRequest.tex);
-        finalSunCode = ((DownloadHandlerTexture)unityWebRequest.downloadHandler).texture;
-
-        // 返回图
-        if (OnUploadFinishedBackTexture != null)
-        {
-          OnUploadFinishedBackTexture(((DownloadHandlerTexture)unityWebRequest.downloadHandler).texture);
-        }
-      }
-    }
-    yield break;
-  }
-
-  #endregion
-  // ==================================================
-
-  /// <summary>
-  /// 传不上去硬传
-  /// </summary>
-  /// <returns></returns>
-  private IEnumerator RetryUpload()
-  {
-    yield return new WaitForSeconds(retryWaitTime);
-    PoseFile2Cloud();
-    yield break;
-  }
-
-  // ==================================================
-  // Json解析类
-
-  // 七牛云Token回执
-  [Serializable]
-  public class TokenCallbackJson
-  {
-    public int status;
-    public int code;
-    public TokenDataJson data;
-    public string message;
-  }
-  [Serializable]
-  public class TokenDataJson
-  {
-    public string token;
-  }
-
-  // 七牛云文件上传回执
-  [Serializable]
-  public class CloudCallbackJson
-  {
-    public int code;
-    public CloudCallbackDataJson data;
-    public int status;
-  }
-  [Serializable]
-  public class CloudCallbackDataJson
-  {
-    public string file_name;
-    public string file_url;
-  }
-
-  // 向服务器发送的json
-  [Serializable]
-  public class ServerJson
-  {
-    public string file_url;
-    public int app_id;
-    // public string options;
-  }
-  [Serializable]
-  public class ServerCallbackJson
-  {
-    public int status;
-    public int code;
-    public ServerCallbackDataJson data;
-  }
-
-  [Serializable]
-  public class ServerCallbackDataJson
-  {
-    public string file_url;
-    public int app_id;
-    public string code;
-    public string view_url;
-    public string updated_at;
-    public string created_at;
-    public int id;
-  }
-}

+ 0 - 250
Materials/Backend & Upload/Upload2ZCManager.cs

@@ -1,250 +0,0 @@
-using System.Collections;
-using System.Collections.Generic;
-using UnityEngine;
-using UnityEngine.Networking;
-using ToneTuneToolkit.Common;
-using UnityEngine.Events;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using System;
-
-/// <summary>
-/// 对志城综合法宝
-/// </summary>
-public class Upload2ZCManager : SingletonMaster<Upload2ZCManager>
-{
-
-  // ==================================================
-  #region 2025.04 Nike ADT
-
-  private const string USERINFOREQUESTURL = @"https://nike-adt.studiocapsule.cn/api/device/scanQr";
-  public static UnityAction<UserInfo> OnUserInfoDownloaded;
-
-  /// <summary>
-  /// 获取用户信息
-  /// </summary>
-  /// <param name="url"></param>
-  public void GetUserInfo(string url) => StartCoroutine(nameof(GetUserInfoAction), url);
-  private IEnumerator GetUserInfoAction(string url)
-  {
-    WWWForm wwwForm = new WWWForm();
-    wwwForm.AddField("qr_content", url);
-
-    using (UnityWebRequest www = UnityWebRequest.Post(USERINFOREQUESTURL, wwwForm))
-    {
-      www.downloadHandler = new DownloadHandlerBuffer();
-      yield return www.SendWebRequest();
-
-      if (www.result != UnityWebRequest.Result.Success)
-      {
-        Debug.Log($"[U2ZCM] {www.error}");
-        yield break;
-      }
-
-      Debug.Log($"[U2ZCM] {www.downloadHandler.text}");
-      try
-      {
-        uird = JsonConvert.DeserializeObject<Respon_UserInfoData>(www.downloadHandler.text);
-      }
-      catch (Exception)
-      {
-        Debug.Log($"[U2ZCM] 解析错误");
-        yield break;
-      }
-
-      if (uird.code != 0)
-      {
-        if (OnUserInfoDownloaded != null)
-        {
-          OnUserInfoDownloaded(null);
-        }
-        yield break;
-      }
-
-      if (OnUserInfoDownloaded != null)
-      {
-        UserInfo ui = new UserInfo();
-        ui.name = uird.data.name;
-        ui.code = uird.data.code;
-        ui.save_car = uird.data.save_car;
-        ui.can_play = uird.data.can_play;
-        OnUserInfoDownloaded(ui);
-      }
-    }
-    yield break;
-  }
-
-  [SerializeField] private Respon_UserInfoData uird = new Respon_UserInfoData();
-
-  [Serializable]
-  public class Respon_UserInfoData
-  {
-    public int code;
-    public string message;
-    public UserInfo data;
-  }
-
-  [Serializable]
-  public class UserInfo
-  {
-    public string name;
-    public string code;
-    public string save_car;
-    public string can_play;
-  }
-
-  // ==================================================
-
-  private const string USERIMAGEUPLOADURL = @"https://nike-adt.studiocapsule.cn/api/device/upload";
-
-  public static UnityAction<string> OnUserImageUploaded;
-
-  [SerializeField] private Upload_UserImageData uUID;
-  public void UpdateUserImageData(string user_code, Texture2D t2dPhoto)
-  {
-    uUID = new Upload_UserImageData();
-    uUID.user_code = user_code;
-
-    byte[] fileBytes = t2dPhoto.EncodeToPNG();
-    uUID.file = fileBytes;
-    return;
-  }
-
-  public void UploadUserImage() => StartCoroutine(nameof(UploadUserImageAction));
-  private IEnumerator UploadUserImageAction()
-  {
-    WWWForm wwwForm = new WWWForm();
-    wwwForm.AddField("user_code", uUID.user_code);
-    wwwForm.AddBinaryData("file", uUID.file);
-
-    using (UnityWebRequest www = UnityWebRequest.Post(USERIMAGEUPLOADURL, wwwForm))
-    {
-      www.downloadHandler = new DownloadHandlerBuffer();
-      yield return www.SendWebRequest();
-
-      if (www.result != UnityWebRequest.Result.Success)
-      {
-        Debug.Log($"[U2ZCM] {www.error}");
-        yield break;
-      }
-
-      Debug.Log($"[U2ZCM] {www.downloadHandler.text}");
-      rUID = JsonConvert.DeserializeObject<Respon_UserImageData>(www.downloadHandler.text);
-
-      if (rUID.code != 0)
-      {
-        Debug.Log($"[U2ZCM] Code Error");
-        yield break;
-      }
-
-      DownloadQRCode(rUID.data.qr_url); // 搞图
-    }
-    yield break;
-  }
-
-  public class Upload_UserImageData
-  {
-    public string user_code;
-    public byte[] file;
-  }
-
-  [SerializeField] private Respon_UserImageData rUID = new Respon_UserImageData();
-
-  [Serializable]
-  public class Respon_UserImageData
-  {
-    public int code;
-    public string message;
-    public Respon_UserImageDataData data;
-  }
-
-  [Serializable]
-  public class Respon_UserImageDataData
-  {
-    public string qr_url;
-  }
-
-  #endregion
-  // ==================================================
-  #region 获取QR图片
-
-  public static UnityAction<Texture2D> OnQRImageDownloaded;
-
-  [SerializeField] private Texture2D debug_peekQRCode;
-
-  public void DownloadQRCode(string url) => StartCoroutine(nameof(DownloadQRCodeAction), url);
-  private IEnumerator DownloadQRCodeAction(string url)
-  {
-    using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(url))
-    {
-      yield return www.SendWebRequest();
-      if (www.result != UnityWebRequest.Result.Success)
-      {
-        Debug.Log($"[U2ZCM] {www.error}");
-        yield break;
-      }
-
-      debug_peekQRCode = DownloadHandlerTexture.GetContent(www); // DEBUG
-
-      if (OnQRImageDownloaded != null)
-      {
-        OnQRImageDownloaded(DownloadHandlerTexture.GetContent(www));
-      }
-    }
-    yield break;
-  }
-
-  #endregion
-  // ==================================================
-  #region 上传文件流
-
-  private const string uploadURL = @"https://vw-aud.studiocapsule.cn/api/device/uploadWall";
-
-  public UnityAction<string> OnUploadFinished;
-
-  public void UploadData(byte[] fileBytes) => StartCoroutine(nameof(UploadDataAction), fileBytes);
-  private IEnumerator UploadDataAction(byte[] fileBytes)
-  {
-    WWWForm wwwForm = new WWWForm();
-    wwwForm.AddBinaryData("file", fileBytes);
-
-    using (UnityWebRequest www = UnityWebRequest.Post(uploadURL, wwwForm))
-    {
-
-      // www.SetRequestHeader("Content-Type", "multipart/form-data"); // wwwForm不要手动设置避免boundary消失
-      www.downloadHandler = new DownloadHandlerBuffer();
-      yield return www.SendWebRequest();
-
-      if (www.result != UnityWebRequest.Result.Success)
-      {
-        Debug.Log($"[U2ZCM] {www.error}");
-        yield break;
-      }
-
-      Debug.Log($"[U2ZCM] {www.downloadHandler.text}");
-      ResponData responData = JsonConvert.DeserializeObject<ResponData>(www.downloadHandler.text);
-
-      // // 解析方案A 动态类型
-      // dynamic data = responData.data;
-      // string qr = data.qr_url;
-
-      // 解析方案B
-      JObject data = JObject.FromObject(responData.data);
-      string qr_url = data["qr_url"].ToString();
-
-      // Debug.Log(qr_url);
-      DownloadQRCode(qr_url);
-    }
-    yield break;
-  }
-
-  #endregion
-  // ==================================================
-
-  public class ResponData
-  {
-    public int code;
-    public string message;
-    public object data;
-  }
-}

+ 297 - 0
Materials/Funny/CubeController.cs

@@ -0,0 +1,297 @@
+using UnityEngine;
+
+public class CubeController : MonoBehaviour
+{
+  [SerializeField] private bool isDebug = false;
+  [Header("基础旋转设置")]
+  [SerializeField] private float baseRotationSpeed = 30f;
+  [SerializeField] private float directionChangeInterval = 3f;
+
+  [Header("随机范围")]
+  [SerializeField] private Vector3 minRotationSpeed = new Vector3(-50, -50, -50);
+  [SerializeField] private Vector3 maxRotationSpeed = new Vector3(50, 50, 50);
+
+  [Header("增强效果设置")]
+  [SerializeField] private bool useEaseInOut = true;
+  [SerializeField] private AnimationCurve easeCurve = AnimationCurve.EaseInOut(0, 0, 1, 1);
+  [SerializeField] private bool useRandomCurve = false;
+  [SerializeField] private AnimationCurve[] randomCurves;
+
+  private Vector3 targetRotationSpeed;
+  private Vector3 currentRotationSpeed;
+  private Vector3 previousRotationSpeed;
+  private float timeSinceLastDirectionChange;
+  private AnimationCurve currentCurve;
+
+  // ==================================================
+
+  private void Start() => Init();
+
+  private void Update()
+  {
+    // 更新时间
+    timeSinceLastDirectionChange += Time.deltaTime;
+
+    // 计算插值进度(0到1)
+    float progress = Mathf.Clamp01(timeSinceLastDirectionChange / directionChangeInterval);
+
+    // 应用缓动插值
+    if (useEaseInOut && currentCurve != null)
+    {
+      float easedProgress = currentCurve.Evaluate(progress);
+      currentRotationSpeed = Vector3.Lerp(previousRotationSpeed, targetRotationSpeed, easedProgress);
+    }
+    else
+    {
+      // 线性插值
+      currentRotationSpeed = Vector3.Lerp(previousRotationSpeed, targetRotationSpeed, progress);
+    }
+
+    // 应用旋转
+    transform.Rotate(currentRotationSpeed * Time.deltaTime);
+
+    // 定期改变旋转方向和曲线
+    if (timeSinceLastDirectionChange >= directionChangeInterval)
+    {
+      GenerateNewRotationTarget();
+      if (useRandomCurve)
+      {
+        SelectRandomCurve();
+      }
+      timeSinceLastDirectionChange = 0f;
+    }
+  }
+
+  private void OnGUI() => DEBUG_ShowInfo();
+  private void OnDrawGizmos() => DEBUG_DrawGizmo();
+  private void OnDestroy() => UnInit();
+
+  // ==================================================
+
+  private void Init()
+  {
+    // 初始化随机曲线数组(如果没有手动赋值)
+    if (randomCurves == null || randomCurves.Length == 0) { SetDefaultCurves(); }
+
+    // 初始化旋转速度
+    GenerateNewRotationTarget();
+    currentRotationSpeed = targetRotationSpeed;
+    previousRotationSpeed = currentRotationSpeed;
+
+    // 选择初始曲线
+    SelectRandomCurve();
+
+    // Wireframe
+    meshFilter = GetComponent<MeshFilter>();
+    CreateLineMaterial();
+
+    // 隐藏原来的网格渲染器
+    MeshRenderer originalRenderer = GetComponent<MeshRenderer>();
+    if (originalRenderer != null)
+    {
+      originalRenderer.enabled = false;
+    }
+  }
+
+  private void UnInit()
+  {
+    if (lineMaterial != null) { DestroyImmediate(lineMaterial); }
+  }
+
+  // ==================================================
+
+  /// <summary>
+  /// 设置默认曲线
+  /// </summary>
+  private void SetDefaultCurves()
+  {
+    // 创建一组默认的动画曲线
+    randomCurves = new AnimationCurve[6];
+
+    // 1. 标准缓入缓出
+    randomCurves[0] = AnimationCurve.EaseInOut(0, 0, 1, 1);
+
+    // 2. 快速开始慢速结束
+    randomCurves[1] = new AnimationCurve(
+        new Keyframe(0, 0),
+        new Keyframe(0.2f, 0.8f),
+        new Keyframe(1, 1)
+    );
+
+    // 3. 慢速开始快速结束
+    randomCurves[2] = new AnimationCurve(
+        new Keyframe(0, 0),
+        new Keyframe(0.8f, 0.2f),
+        new Keyframe(1, 1)
+    );
+
+    // 4. 弹性效果
+    randomCurves[3] = new AnimationCurve(
+        new Keyframe(0, 0),
+        new Keyframe(0.3f, 1.1f),
+        new Keyframe(0.6f, 0.9f),
+        new Keyframe(1, 1)
+    );
+
+    // 5. 阶梯效果
+    randomCurves[4] = new AnimationCurve(
+        new Keyframe(0, 0),
+        new Keyframe(0.3f, 0.3f),
+        new Keyframe(0.31f, 0.7f),
+        new Keyframe(1, 1)
+    );
+
+    // 6. 平滑线性
+    randomCurves[5] = new AnimationCurve(
+        new Keyframe(0, 0),
+        new Keyframe(1, 1)
+    );
+  }
+
+
+
+  private void GenerateNewRotationTarget()
+  {
+    // 保存当前速度作为插值起点
+    previousRotationSpeed = currentRotationSpeed;
+
+    // 生成新的随机旋转速度
+    targetRotationSpeed = new Vector3(
+        Random.Range(minRotationSpeed.x, maxRotationSpeed.x),
+        Random.Range(minRotationSpeed.y, maxRotationSpeed.y),
+        Random.Range(minRotationSpeed.z, maxRotationSpeed.z)
+    );
+  }
+
+  private void SelectRandomCurve()
+  {
+    if (randomCurves != null && randomCurves.Length > 0)
+    {
+      int randomIndex = Random.Range(0, randomCurves.Length);
+      currentCurve = randomCurves[randomIndex];
+    }
+    else
+    {
+      // 回退到默认缓动曲线
+      currentCurve = AnimationCurve.EaseInOut(0, 0, 1, 1);
+    }
+  }
+
+
+  // 编辑器方法:重新生成目标
+  [ContextMenu("重新生成旋转目标")]
+  public void RegenerateTarget()
+  {
+    GenerateNewRotationTarget();
+    if (useRandomCurve)
+    {
+      SelectRandomCurve();
+    }
+    timeSinceLastDirectionChange = 0f;
+  }
+
+  // 编辑器方法:设置基础速度
+  [ContextMenu("应用基础速度")]
+  public void ApplyBaseSpeed()
+  {
+    minRotationSpeed = new Vector3(-baseRotationSpeed, -baseRotationSpeed, -baseRotationSpeed);
+    maxRotationSpeed = new Vector3(baseRotationSpeed, baseRotationSpeed, baseRotationSpeed);
+    RegenerateTarget();
+  }
+
+  // ==================================================
+  #region Wireframe
+
+  [Header("线框设置")]
+  [SerializeField] private Color wireframeColor = Color.cyan;
+  [SerializeField] private float lineWidth = 0.02f;
+
+  private MeshFilter meshFilter;
+  private Material lineMaterial;
+
+  private void CreateLineMaterial()
+  {
+    // 创建用于绘制线的材质
+    lineMaterial = new Material(Shader.Find("Hidden/Internal-Colored"));
+    lineMaterial.hideFlags = HideFlags.HideAndDontSave;
+  }
+
+  private void OnRenderObject()
+  {
+    if (meshFilter == null || meshFilter.sharedMesh == null)
+      return;
+
+    // 设置材质
+    lineMaterial.SetPass(0);
+
+    GL.PushMatrix();
+    GL.MultMatrix(transform.localToWorldMatrix);
+
+    GL.Begin(GL.LINES);
+    GL.Color(wireframeColor);
+
+    Mesh mesh = meshFilter.sharedMesh;
+    Vector3[] vertices = mesh.vertices;
+    int[] triangles = mesh.triangles;
+
+    // 绘制所有三角形的边
+    for (int i = 0; i < triangles.Length; i += 3)
+    {
+      DrawTriangleLine(vertices[triangles[i]], vertices[triangles[i + 1]], vertices[triangles[i + 2]]);
+    }
+
+    GL.End();
+    GL.PopMatrix();
+  }
+
+  private void DrawTriangleLine(Vector3 a, Vector3 b, Vector3 c)
+  {
+    GL.Vertex(a);
+    GL.Vertex(b);
+
+    GL.Vertex(b);
+    GL.Vertex(c);
+
+    GL.Vertex(c);
+    GL.Vertex(a);
+  }
+
+  #endregion
+  // ==================================================
+  #region DEBUG
+
+  // 在Inspector中显示调试信息
+  private void DEBUG_ShowInfo()
+  {
+    if (!isDebug) { return; }
+    if (Application.isPlaying)
+    {
+      GUILayout.BeginArea(new Rect(10, 10, 300, 150));
+      GUILayout.Label($"当前旋转速度: {currentRotationSpeed}");
+      GUILayout.Label($"目标旋转速度: {targetRotationSpeed}");
+      GUILayout.Label($"时间进度: {timeSinceLastDirectionChange:F1}/{directionChangeInterval}");
+      GUILayout.Label($"进度百分比: {timeSinceLastDirectionChange / directionChangeInterval * 100:F1}%");
+      GUILayout.EndArea();
+    }
+  }
+
+  // 可视化调试(在Scene视图中显示)
+  private void DEBUG_DrawGizmo()
+  {
+    if (!isDebug) { return; }
+    if (Application.isPlaying)
+    {
+      // 绘制旋转轴指示器
+      Gizmos.color = Color.red;
+      Vector3 direction = currentRotationSpeed.normalized;
+      Gizmos.DrawRay(transform.position, direction * 2f);
+
+      // 绘制速度大小的球体
+      Gizmos.color = Color.blue;
+      float speed = currentRotationSpeed.magnitude / 100f;
+      Gizmos.DrawWireSphere(transform.position, speed);
+    }
+  }
+
+  #endregion
+}

BIN
Materials/Game/JigsawGame/VWJigsawPuzzle.unitypackage


+ 915 - 0
Materials/MediaPipe/FaceDetation/Scenes/00.unity

@@ -0,0 +1,915 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!29 &1
+OcclusionCullingSettings:
+  m_ObjectHideFlags: 0
+  serializedVersion: 2
+  m_OcclusionBakeSettings:
+    smallestOccluder: 5
+    smallestHole: 0.25
+    backfaceThreshold: 100
+  m_SceneGUID: 00000000000000000000000000000000
+  m_OcclusionCullingData: {fileID: 0}
+--- !u!104 &2
+RenderSettings:
+  m_ObjectHideFlags: 0
+  serializedVersion: 9
+  m_Fog: 0
+  m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
+  m_FogMode: 3
+  m_FogDensity: 0.01
+  m_LinearFogStart: 0
+  m_LinearFogEnd: 300
+  m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
+  m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
+  m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
+  m_AmbientIntensity: 1
+  m_AmbientMode: 0
+  m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
+  m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
+  m_HaloStrength: 0.5
+  m_FlareStrength: 1
+  m_FlareFadeSpeed: 3
+  m_HaloTexture: {fileID: 0}
+  m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
+  m_DefaultReflectionMode: 0
+  m_DefaultReflectionResolution: 128
+  m_ReflectionBounces: 1
+  m_ReflectionIntensity: 1
+  m_CustomReflection: {fileID: 0}
+  m_Sun: {fileID: 0}
+  m_UseRadianceAmbientProbe: 0
+--- !u!157 &3
+LightmapSettings:
+  m_ObjectHideFlags: 0
+  serializedVersion: 12
+  m_GIWorkflowMode: 1
+  m_GISettings:
+    serializedVersion: 2
+    m_BounceScale: 1
+    m_IndirectOutputScale: 1
+    m_AlbedoBoost: 1
+    m_EnvironmentLightingMode: 0
+    m_EnableBakedLightmaps: 1
+    m_EnableRealtimeLightmaps: 0
+  m_LightmapEditorSettings:
+    serializedVersion: 12
+    m_Resolution: 2
+    m_BakeResolution: 40
+    m_AtlasSize: 1024
+    m_AO: 0
+    m_AOMaxDistance: 1
+    m_CompAOExponent: 1
+    m_CompAOExponentDirect: 0
+    m_ExtractAmbientOcclusion: 0
+    m_Padding: 2
+    m_LightmapParameters: {fileID: 0}
+    m_LightmapsBakeMode: 1
+    m_TextureCompression: 1
+    m_FinalGather: 0
+    m_FinalGatherFiltering: 1
+    m_FinalGatherRayCount: 256
+    m_ReflectionCompression: 2
+    m_MixedBakeMode: 2
+    m_BakeBackend: 1
+    m_PVRSampling: 1
+    m_PVRDirectSampleCount: 32
+    m_PVRSampleCount: 512
+    m_PVRBounces: 2
+    m_PVREnvironmentSampleCount: 256
+    m_PVREnvironmentReferencePointCount: 2048
+    m_PVRFilteringMode: 1
+    m_PVRDenoiserTypeDirect: 1
+    m_PVRDenoiserTypeIndirect: 1
+    m_PVRDenoiserTypeAO: 1
+    m_PVRFilterTypeDirect: 0
+    m_PVRFilterTypeIndirect: 0
+    m_PVRFilterTypeAO: 0
+    m_PVREnvironmentMIS: 1
+    m_PVRCulling: 1
+    m_PVRFilteringGaussRadiusDirect: 1
+    m_PVRFilteringGaussRadiusIndirect: 5
+    m_PVRFilteringGaussRadiusAO: 2
+    m_PVRFilteringAtrousPositionSigmaDirect: 0.5
+    m_PVRFilteringAtrousPositionSigmaIndirect: 2
+    m_PVRFilteringAtrousPositionSigmaAO: 1
+    m_ExportTrainingData: 0
+    m_TrainingDataDestination: TrainingData
+    m_LightProbeSampleCountMultiplier: 4
+  m_LightingDataAsset: {fileID: 0}
+  m_LightingSettings: {fileID: 0}
+--- !u!196 &4
+NavMeshSettings:
+  serializedVersion: 2
+  m_ObjectHideFlags: 0
+  m_BuildSettings:
+    serializedVersion: 3
+    agentTypeID: 0
+    agentRadius: 0.5
+    agentHeight: 2
+    agentSlope: 45
+    agentClimb: 0.4
+    ledgeDropHeight: 0
+    maxJumpAcrossDistance: 0
+    minRegionArea: 2
+    manualCellSize: 0
+    cellSize: 0.16666667
+    manualTileSize: 0
+    tileSize: 256
+    buildHeightMesh: 0
+    maxJobWorkers: 0
+    preserveTilesOutsideBounds: 0
+    debug:
+      m_Flags: 0
+  m_NavMeshData: {fileID: 0}
+--- !u!1001 &338992141
+PrefabInstance:
+  m_ObjectHideFlags: 0
+  serializedVersion: 2
+  m_Modification:
+    serializedVersion: 3
+    m_TransformParent: {fileID: 1006057041}
+    m_Modifications:
+    - target: {fileID: 5535674424067552597, guid: 26114bc9cccb92454a468ea4d41f400a, type: 3}
+      propertyPath: m_RootOrder
+      value: 0
+      objectReference: {fileID: 0}
+    - target: {fileID: 5535674424067552597, guid: 26114bc9cccb92454a468ea4d41f400a, type: 3}
+      propertyPath: m_LocalPosition.x
+      value: 0
+      objectReference: {fileID: 0}
+    - target: {fileID: 5535674424067552597, guid: 26114bc9cccb92454a468ea4d41f400a, type: 3}
+      propertyPath: m_LocalPosition.y
+      value: 0
+      objectReference: {fileID: 0}
+    - target: {fileID: 5535674424067552597, guid: 26114bc9cccb92454a468ea4d41f400a, type: 3}
+      propertyPath: m_LocalPosition.z
+      value: 0
+      objectReference: {fileID: 0}
+    - target: {fileID: 5535674424067552597, guid: 26114bc9cccb92454a468ea4d41f400a, type: 3}
+      propertyPath: m_LocalRotation.w
+      value: 1
+      objectReference: {fileID: 0}
+    - target: {fileID: 5535674424067552597, guid: 26114bc9cccb92454a468ea4d41f400a, type: 3}
+      propertyPath: m_LocalRotation.x
+      value: 0
+      objectReference: {fileID: 0}
+    - target: {fileID: 5535674424067552597, guid: 26114bc9cccb92454a468ea4d41f400a, type: 3}
+      propertyPath: m_LocalRotation.y
+      value: 0
+      objectReference: {fileID: 0}
+    - target: {fileID: 5535674424067552597, guid: 26114bc9cccb92454a468ea4d41f400a, type: 3}
+      propertyPath: m_LocalRotation.z
+      value: 0
+      objectReference: {fileID: 0}
+    - target: {fileID: 5535674424067552597, guid: 26114bc9cccb92454a468ea4d41f400a, type: 3}
+      propertyPath: m_LocalEulerAnglesHint.x
+      value: 0
+      objectReference: {fileID: 0}
+    - target: {fileID: 5535674424067552597, guid: 26114bc9cccb92454a468ea4d41f400a, type: 3}
+      propertyPath: m_LocalEulerAnglesHint.y
+      value: 0
+      objectReference: {fileID: 0}
+    - target: {fileID: 5535674424067552597, guid: 26114bc9cccb92454a468ea4d41f400a, type: 3}
+      propertyPath: m_LocalEulerAnglesHint.z
+      value: 0
+      objectReference: {fileID: 0}
+    - target: {fileID: 6320745076577806712, guid: 26114bc9cccb92454a468ea4d41f400a, type: 3}
+      propertyPath: m_Name
+      value: FaceDetections Annotation
+      objectReference: {fileID: 0}
+    m_RemovedComponents: []
+    m_RemovedGameObjects: []
+    m_AddedGameObjects: []
+    m_AddedComponents: []
+  m_SourcePrefab: {fileID: 100100000, guid: 26114bc9cccb92454a468ea4d41f400a, type: 3}
+--- !u!114 &338992142 stripped
+MonoBehaviour:
+  m_CorrespondingSourceObject: {fileID: -6338546567352850726, guid: 26114bc9cccb92454a468ea4d41f400a, type: 3}
+  m_PrefabInstance: {fileID: 338992141}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: d433cdb024dfd584696eeb11efb71102, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+--- !u!4 &338992143 stripped
+Transform:
+  m_CorrespondingSourceObject: {fileID: 5535674424067552597, guid: 26114bc9cccb92454a468ea4d41f400a, type: 3}
+  m_PrefabInstance: {fileID: 338992141}
+  m_PrefabAsset: {fileID: 0}
+--- !u!1 &381049740
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 381049744}
+  - component: {fileID: 381049743}
+  - component: {fileID: 381049742}
+  - component: {fileID: 381049741}
+  m_Layer: 5
+  m_Name: Main Canvas
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &381049741
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 381049740}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_IgnoreReversedGraphics: 1
+  m_BlockingObjects: 0
+  m_BlockingMask:
+    serializedVersion: 2
+    m_Bits: 4294967295
+--- !u!114 &381049742
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 381049740}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_UiScaleMode: 1
+  m_ReferencePixelsPerUnit: 100
+  m_ScaleFactor: 1
+  m_ReferenceResolution: {x: 2436, y: 1125}
+  m_ScreenMatchMode: 1
+  m_MatchWidthOrHeight: 0
+  m_PhysicalUnit: 3
+  m_FallbackScreenDPI: 96
+  m_DefaultSpriteDPI: 96
+  m_DynamicPixelsPerUnit: 1
+  m_PresetInfoIsWorld: 0
+--- !u!223 &381049743
+Canvas:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 381049740}
+  m_Enabled: 1
+  serializedVersion: 3
+  m_RenderMode: 1
+  m_Camera: {fileID: 1969388816}
+  m_PlaneDistance: 100
+  m_PixelPerfect: 0
+  m_ReceivesEvents: 1
+  m_OverrideSorting: 0
+  m_OverridePixelPerfect: 0
+  m_SortingBucketNormalizedSize: 0
+  m_VertexColorAlwaysGammaSpace: 0
+  m_AdditionalShaderChannelsFlag: 0
+  m_UpdateRectTransformForStandalone: 0
+  m_SortingLayerID: 0
+  m_SortingOrder: 0
+  m_TargetDisplay: 0
+--- !u!224 &381049744
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 381049740}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 0, y: 0, z: 0}
+  m_ConstrainProportionsScale: 0
+  m_Children:
+  - {fileID: 1106980025}
+  - {fileID: 1006057044}
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 0, y: 0}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 0, y: 0}
+  m_Pivot: {x: 0, y: 0}
+--- !u!1 &420786853
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 420786856}
+  - component: {fileID: 420786855}
+  - component: {fileID: 420786854}
+  m_Layer: 0
+  m_Name: EventSystem
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &420786854
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 420786853}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_SendPointerHoverToParent: 1
+  m_HorizontalAxis: Horizontal
+  m_VerticalAxis: Vertical
+  m_SubmitButton: Submit
+  m_CancelButton: Cancel
+  m_InputActionsPerSecond: 10
+  m_RepeatDelay: 0.5
+  m_ForceModuleActive: 0
+--- !u!114 &420786855
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 420786853}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_FirstSelected: {fileID: 0}
+  m_sendNavigationEvents: 1
+  m_DragThreshold: 10
+--- !u!4 &420786856
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 420786853}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &731190175
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 731190177}
+  - component: {fileID: 731190176}
+  m_Layer: 0
+  m_Name: Face Detector Manager
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &731190176
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 731190175}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 1794b9326ff8eac4da3f283707110a6a, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  runner: {fileID: 1064799468}
+--- !u!4 &731190177
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 731190175}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: -81.4295, y: -17.092503, z: 89.29714}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1001 &1006057040
+PrefabInstance:
+  m_ObjectHideFlags: 0
+  serializedVersion: 2
+  m_Modification:
+    serializedVersion: 3
+    m_TransformParent: {fileID: 381049744}
+    m_Modifications:
+    - target: {fileID: 3259285889726014650, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      propertyPath: m_Pivot.x
+      value: 0.5
+      objectReference: {fileID: 0}
+    - target: {fileID: 3259285889726014650, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      propertyPath: m_Pivot.y
+      value: 0.5
+      objectReference: {fileID: 0}
+    - target: {fileID: 3259285889726014650, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      propertyPath: m_RootOrder
+      value: 0
+      objectReference: {fileID: 0}
+    - target: {fileID: 3259285889726014650, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      propertyPath: m_AnchorMax.x
+      value: 0.5
+      objectReference: {fileID: 0}
+    - target: {fileID: 3259285889726014650, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      propertyPath: m_AnchorMax.y
+      value: 0.5
+      objectReference: {fileID: 0}
+    - target: {fileID: 3259285889726014650, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      propertyPath: m_AnchorMin.x
+      value: 0.5
+      objectReference: {fileID: 0}
+    - target: {fileID: 3259285889726014650, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      propertyPath: m_AnchorMin.y
+      value: 0.5
+      objectReference: {fileID: 0}
+    - target: {fileID: 3259285889726014650, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      propertyPath: m_SizeDelta.x
+      value: 0
+      objectReference: {fileID: 0}
+    - target: {fileID: 3259285889726014650, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      propertyPath: m_SizeDelta.y
+      value: 0
+      objectReference: {fileID: 0}
+    - target: {fileID: 3259285889726014650, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      propertyPath: m_LocalPosition.x
+      value: 0
+      objectReference: {fileID: 0}
+    - target: {fileID: 3259285889726014650, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      propertyPath: m_LocalPosition.y
+      value: 0
+      objectReference: {fileID: 0}
+    - target: {fileID: 3259285889726014650, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      propertyPath: m_LocalPosition.z
+      value: 0
+      objectReference: {fileID: 0}
+    - target: {fileID: 3259285889726014650, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      propertyPath: m_LocalRotation.w
+      value: 1
+      objectReference: {fileID: 0}
+    - target: {fileID: 3259285889726014650, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      propertyPath: m_LocalRotation.x
+      value: -0
+      objectReference: {fileID: 0}
+    - target: {fileID: 3259285889726014650, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      propertyPath: m_LocalRotation.y
+      value: -0
+      objectReference: {fileID: 0}
+    - target: {fileID: 3259285889726014650, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      propertyPath: m_LocalRotation.z
+      value: -0
+      objectReference: {fileID: 0}
+    - target: {fileID: 3259285889726014650, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      propertyPath: m_AnchoredPosition.x
+      value: 0
+      objectReference: {fileID: 0}
+    - target: {fileID: 3259285889726014650, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      propertyPath: m_AnchoredPosition.y
+      value: 0
+      objectReference: {fileID: 0}
+    - target: {fileID: 3259285889726014650, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      propertyPath: m_LocalEulerAnglesHint.x
+      value: 0
+      objectReference: {fileID: 0}
+    - target: {fileID: 3259285889726014650, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      propertyPath: m_LocalEulerAnglesHint.y
+      value: 0
+      objectReference: {fileID: 0}
+    - target: {fileID: 3259285889726014650, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      propertyPath: m_LocalEulerAnglesHint.z
+      value: 0
+      objectReference: {fileID: 0}
+    - target: {fileID: 3259285889726014651, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      propertyPath: m_Name
+      value: Annotatable Screen
+      objectReference: {fileID: 0}
+    m_RemovedComponents: []
+    m_RemovedGameObjects: []
+    m_AddedGameObjects:
+    - targetCorrespondingSourceObject: {fileID: 7074087083388479136, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      insertIndex: -1
+      addedObject: {fileID: 338992143}
+    m_AddedComponents:
+    - targetCorrespondingSourceObject: {fileID: 8798066379235852099, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+      insertIndex: -1
+      addedObject: {fileID: 1006057045}
+  m_SourcePrefab: {fileID: 100100000, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+--- !u!4 &1006057041 stripped
+Transform:
+  m_CorrespondingSourceObject: {fileID: 7074087083388479136, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+  m_PrefabInstance: {fileID: 1006057040}
+  m_PrefabAsset: {fileID: 0}
+--- !u!1 &1006057042 stripped
+GameObject:
+  m_CorrespondingSourceObject: {fileID: 8798066379235852099, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+  m_PrefabInstance: {fileID: 1006057040}
+  m_PrefabAsset: {fileID: 0}
+--- !u!114 &1006057043 stripped
+MonoBehaviour:
+  m_CorrespondingSourceObject: {fileID: 2020366215714292840, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+  m_PrefabInstance: {fileID: 1006057040}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 827c4431af677e057aa6f14170d0785c, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+--- !u!224 &1006057044 stripped
+RectTransform:
+  m_CorrespondingSourceObject: {fileID: 3259285889726014650, guid: 5713b959e3c77a58fb258133fc8e4aef, type: 3}
+  m_PrefabInstance: {fileID: 1006057040}
+  m_PrefabAsset: {fileID: 0}
+--- !u!114 &1006057045
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1006057042}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 3495500f1386ce3ee9a87dc859112641, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  annotation: {fileID: 338992142}
+  _threshold: 0
+--- !u!1 &1064799459
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1064799461}
+  - component: {fileID: 1064799468}
+  m_Layer: 0
+  m_Name: Solution
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!4 &1064799461
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1064799459}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: -1}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &1064799468
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1064799459}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 0b86ba34db2c888778bdb2f439fd1c76, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  _bootstrapPrefab: {fileID: 968918444066301895, guid: 1146a9de09159a948b683e94fb3d3c95, type: 3}
+  screen: {fileID: 1006057043}
+  runningMode: 0
+  _detectionResultAnnotationController: {fileID: 1006057045}
+--- !u!1 &1106980024
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1106980025}
+  - component: {fileID: 1106980027}
+  - component: {fileID: 1106980026}
+  m_Layer: 5
+  m_Name: Image - Background
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &1106980025
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1106980024}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 381049744}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 0, y: 0}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &1106980026
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1106980024}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0.21960784, g: 0.21960784, b: 0.21960784, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 0}
+  m_Type: 0
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!222 &1106980027
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1106980024}
+  m_CullTransparentMesh: 1
+--- !u!1 &1784242771
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1784242772}
+  m_Layer: 0
+  m_Name: // ==================================================
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!4 &1784242772
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1784242771}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &1806680259
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1806680261}
+  - component: {fileID: 1806680260}
+  m_Layer: 0
+  m_Name: Directional Light
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!108 &1806680260
+Light:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1806680259}
+  m_Enabled: 1
+  serializedVersion: 10
+  m_Type: 1
+  m_Shape: 0
+  m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1}
+  m_Intensity: 1
+  m_Range: 10
+  m_SpotAngle: 30
+  m_InnerSpotAngle: 21.80208
+  m_CookieSize: 10
+  m_Shadows:
+    m_Type: 2
+    m_Resolution: -1
+    m_CustomResolution: -1
+    m_Strength: 1
+    m_Bias: 0.05
+    m_NormalBias: 0.4
+    m_NearPlane: 0.2
+    m_CullingMatrixOverride:
+      e00: 1
+      e01: 0
+      e02: 0
+      e03: 0
+      e10: 0
+      e11: 1
+      e12: 0
+      e13: 0
+      e20: 0
+      e21: 0
+      e22: 1
+      e23: 0
+      e30: 0
+      e31: 0
+      e32: 0
+      e33: 1
+    m_UseCullingMatrixOverride: 0
+  m_Cookie: {fileID: 0}
+  m_DrawHalo: 0
+  m_Flare: {fileID: 0}
+  m_RenderMode: 0
+  m_CullingMask:
+    serializedVersion: 2
+    m_Bits: 4294967295
+  m_RenderingLayerMask: 1
+  m_Lightmapping: 4
+  m_LightShadowCasterMode: 0
+  m_AreaSize: {x: 1, y: 1}
+  m_BounceIntensity: 1
+  m_ColorTemperature: 6570
+  m_UseColorTemperature: 0
+  m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
+  m_UseBoundingSphereOverride: 0
+  m_UseViewFrustumForShadowCasterCull: 1
+  m_ShadowRadius: 0
+  m_ShadowAngle: 0
+--- !u!4 &1806680261
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1806680259}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
+  m_LocalPosition: {x: 0, y: 3, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
+--- !u!1 &1969388814
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1969388817}
+  - component: {fileID: 1969388816}
+  - component: {fileID: 1969388815}
+  m_Layer: 0
+  m_Name: Main Camera
+  m_TagString: MainCamera
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!81 &1969388815
+AudioListener:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1969388814}
+  m_Enabled: 1
+--- !u!20 &1969388816
+Camera:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1969388814}
+  m_Enabled: 1
+  serializedVersion: 2
+  m_ClearFlags: 1
+  m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
+  m_projectionMatrixMode: 1
+  m_GateFitMode: 2
+  m_FOVAxisMode: 0
+  m_Iso: 200
+  m_ShutterSpeed: 0.005
+  m_Aperture: 16
+  m_FocusDistance: 10
+  m_FocalLength: 50
+  m_BladeCount: 5
+  m_Curvature: {x: 2, y: 11}
+  m_BarrelClipping: 0.25
+  m_Anamorphism: 0
+  m_SensorSize: {x: 36, y: 24}
+  m_LensShift: {x: 0, y: 0}
+  m_NormalizedViewPortRect:
+    serializedVersion: 2
+    x: 0
+    y: 0
+    width: 1
+    height: 1
+  near clip plane: 0.3
+  far clip plane: 1000
+  field of view: 60
+  orthographic: 0
+  orthographic size: 5
+  m_Depth: -1
+  m_CullingMask:
+    serializedVersion: 2
+    m_Bits: 4294967295
+  m_RenderingPath: -1
+  m_TargetTexture: {fileID: 0}
+  m_TargetDisplay: 0
+  m_TargetEye: 3
+  m_HDR: 1
+  m_AllowMSAA: 1
+  m_AllowDynamicResolution: 0
+  m_ForceIntoRT: 0
+  m_OcclusionCulling: 1
+  m_StereoConvergence: 10
+  m_StereoSeparation: 0.022
+--- !u!4 &1969388817
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1969388814}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 1, z: -10}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1660057539 &9223372036854775807
+SceneRoots:
+  m_ObjectHideFlags: 0
+  m_Roots:
+  - {fileID: 1969388817}
+  - {fileID: 1806680261}
+  - {fileID: 420786856}
+  - {fileID: 1784242772}
+  - {fileID: 1064799461}
+  - {fileID: 731190177}
+  - {fileID: 381049744}

+ 87 - 0
Materials/MediaPipe/FaceDetation/Scripts/FaceDetectorManager.cs

@@ -0,0 +1,87 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using ToneTuneToolkit.Common;
+
+using Mediapipe.Tasks.Core;
+using Mediapipe.Unity;
+using Mediapipe.Unity.Sample;
+using Mediapipe.Unity.Sample.FaceDetection;
+
+/// <summary>
+/// 面部检测工具管理器
+/// 延后初始化
+/// 
+/// 基本配置文件
+/// ..\MediaPipeUnity\Samples\Scenes\AppSettings.asset
+/// </summary>
+public class FaceDetectorManager : SingletonMaster<FaceDetectorManager>
+{
+  [SerializeField] private FaceDetectorRunner runner;
+
+  // ==================================================
+
+  private void Start() => Init();
+
+  // ==================================================
+
+  private void Init() => StartCoroutine(nameof(DelayInit));
+  private IEnumerator DelayInit()
+  {
+    yield return new WaitForSeconds(3f);
+    InitImageSource();
+    InitRunnerConfig();
+    runner.Play();
+  }
+
+  // ==================================================
+  #region 面部检测状态控制
+
+  /// <summary>
+  /// 开关暂停恢复检测
+  /// </summary>
+  /// <param name="value"></param>
+  public void SwitchFaceDetector(FaceDetectorState value)
+  {
+    switch (value)
+    {
+      default: break;
+      case FaceDetectorState.Play: runner.Play(); break;
+      case FaceDetectorState.Stop: runner.Stop(); break;
+      case FaceDetectorState.Pause: runner.Pause(); break;
+      case FaceDetectorState.Resume: runner.Resume(); break;
+    }
+  }
+
+  public enum FaceDetectorState
+  {
+    Play = 0, // 具备Reload功能
+    Stop = 1, Pause = 2, Resume = 3
+  }
+
+  #endregion
+  // ==================================================
+  #region 画面源、面部检测参数初始化
+
+  private void InitImageSource()
+  {
+    ImageSourceProvider.Switch(ImageSourceType.WebCamera);
+    ImageSource imageSource = ImageSourceProvider.ImageSource;
+    imageSource.SelectSource(0); // 0:BRIO 1:USBHD
+    imageSource.SelectResolution(7); // 1280x720 30fps
+    imageSource.isHorizontallyFlipped = false;
+  }
+
+  private void InitRunnerConfig()
+  {
+    runner.config.Delegate = BaseOptions.Delegate.CPU;
+    runner.config.ImageReadMode = ImageReadMode.CPUAsync;
+    runner.config.Model = ModelType.BlazeFaceShortRange;
+    runner.config.RunningMode = Mediapipe.Tasks.Vision.Core.RunningMode.LIVE_STREAM;
+    runner.config.MinDetectionConfidence = 0.4f; // 0.0 - 1.0 // 越高越不容易误检
+    runner.config.MinSuppressionThreshold = 0.3f; // 0.0 - 1.0
+    runner.config.NumFaces = 3; // 1-3
+  }
+
+  #endregion
+}

+ 18 - 0
Materials/MediaPipe/FaceDetation/Scripts/Tester.cs

@@ -0,0 +1,18 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class Tester : MonoBehaviour
+{
+  private void Update()
+  {
+    if (Input.GetKeyDown(KeyCode.Q))
+    {
+      FaceDetectorManager.Instance.SwitchFaceDetector(FaceDetectorManager.FaceDetectorState.Play);
+    }
+    if (Input.GetKeyDown(KeyCode.W))
+    {
+      FaceDetectorManager.Instance.SwitchFaceDetector(FaceDetectorManager.FaceDetectorState.Stop);
+    }
+  }
+}

+ 43 - 0
Materials/MediaPipe/FaceDetation/Scripts/ToneTuneToolkit/SingletonMaster.cs

@@ -0,0 +1,43 @@
+/// <summary>
+/// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
+/// Code Version 1.4.20
+/// </summary>
+
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace ToneTuneToolkit.Common
+{
+  /// <summary>
+  /// 单例大师基类
+  /// 你值得拥有
+  /// ScreenshotMaster : SingletonMaster<ScreenshotMaster>
+  /// private new void Awake()
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  public class SingletonMaster<T> : MonoBehaviour where T : SingletonMaster<T>, new()
+  {
+    private static T _instance;
+    public static T Instance
+    {
+      get
+      {
+        _instance = FindObjectOfType<T>();
+        if (_instance == null)
+        {
+          _instance = new T();
+        }
+        return _instance;
+      }
+    }
+
+    private void Awake()
+    {
+      if (_instance == null)
+      {
+        _instance = this as T;
+      }
+    }
+  }
+}

BIN
Materials/Models/Dingus/The Funky Russian Train.mp3


BIN
Materials/Models/Dingus/dingus_nowhiskers.jpg


BIN
Materials/Models/Dingus/dingus_whiskers.tga.png


BIN
Materials/Models/Dingus/maxwell the cat.max


BIN
Materials/Models/Dingus/maxwellthecat.fbx


BIN
Materials/Models/standardcube.fbx


+ 23 - 0
Materials/Modules/Bridge/JS/JSCommunicator.cs

@@ -0,0 +1,23 @@
+using System.Collections;
+using System.Collections.Generic;
+using ToneTuneToolkit.Common;
+using UnityEngine;
+using System.Runtime.InteropServices;
+
+public class JSCommunicator : SingletonMaster<JSCommunicator>
+{
+  [DllImport("__Internal")] public static extern void PuzzleReady();
+  [DllImport("__Internal")] public static extern void PuzzleDebug(string value);
+  [DllImport("__Internal")] public static extern void PuzzleFinished();
+
+  public void StartGame(string message)
+  {
+    Debug.Log(@$"[JSC] Game type: {message}");
+    GameManager.Instance.StartGame(message);
+  }
+
+  public void ResetGame()
+  {
+    GameManager.Instance.Reset();
+  }
+}

+ 14 - 0
Materials/Modules/Bridge/JS/Plugins/WebGL/JigsawPuzzleBridge.jslib

@@ -0,0 +1,14 @@
+mergeInto(LibraryManager.library, {
+    PuzzleReady: function () {
+      puzzle_ready();
+    },
+
+    PuzzleDebug: function (value) {
+      var message = UTF8ToString(value);
+      puzzle_debug(message);
+    },
+
+    PuzzleFinished: function () {
+      puzzle_finished();
+    }
+});

+ 26 - 0
Materials/Modules/Bridge/JS/readme.txt

@@ -0,0 +1,26 @@
+调用
+[DllImport("__Internal")] private static extern void puzzle_ready();  
+[DllImport("__Internal")] private static extern void puzzle_debug(string value);
+[DllImport("__Internal")] private static extern void puzzle_finished();
+
+被调用
+public void StartGame(string message)
+
+空实现
+Plugins/xxx.jslib
+// Assets/Plugins/WebGL/JigsawPuzzleLib.jslib
+mergeInto(LibraryManager.library, {
+    puzzle_ready: function () {
+        // 空实现
+    },
+
+    puzzle_debug: function (value_ptr) {
+        // 空实现
+    },
+
+    puzzle_finished: function () {
+        // 空实现
+    }
+});
+
+

+ 6 - 7
Materials/CanvasGroup_DG/Tools/CanvasGroupMaster.cs → Materials/Modules/DG/CanvasGroupMaster.cs

@@ -6,13 +6,15 @@ using DG.Tweening;
 using System.Threading.Tasks;
 
 /// <summary>
-/// 切换阶段专用工具
+/// CanvasGroup工具
 /// </summary>
 public class CanvasGroupMaster : SingletonMaster<CanvasGroupMaster>
 {
   private const float ANIMTIME = 0.33f;
 
-  public static void DoCanvasGroupFade(CanvasGroup cg, bool isFadeIn)
+  // ==================================================
+
+  public static void DoFade(CanvasGroup cg, bool isFadeIn)
   {
     if (isFadeIn)
     {
@@ -30,10 +32,9 @@ public class CanvasGroupMaster : SingletonMaster<CanvasGroupMaster>
         cg.blocksRaycasts = false;
       });
     }
-    return;
   }
 
-  public static void DoCanvasGroupFade(CanvasGroup cg, bool isFadeIn, float time)
+  public static void DoFade(CanvasGroup cg, bool isFadeIn, float time)
   {
     if (isFadeIn)
     {
@@ -51,10 +52,9 @@ public class CanvasGroupMaster : SingletonMaster<CanvasGroupMaster>
         cg.blocksRaycasts = false;
       });
     }
-    return;
   }
 
-  public async static void DoCanvasGroupFade(CanvasGroup cg, bool isFadeIn, float time, float delayTime)
+  public async static void DoFade(CanvasGroup cg, bool isFadeIn, float time, float delayTime)
   {
     await Task.Delay((int)(1000 * delayTime));
 
@@ -74,6 +74,5 @@ public class CanvasGroupMaster : SingletonMaster<CanvasGroupMaster>
         cg.blocksRaycasts = false;
       });
     }
-    return;
   }
 }

+ 0 - 0
Materials/CanvasGroup_DG/Tools/UIStageManager.cs → Materials/Modules/DG/UIStageManager.cs


+ 74 - 0
Materials/Networking/SocketIO/SocketIOClientManager.cs

@@ -0,0 +1,74 @@
+/// <summary>
+/// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
+/// Code Version 1.5.2
+/// </summary>
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using Best.SocketIO;
+using Best.SocketIO.Events;
+using ToneTuneToolkit.Common;
+using UnityEngine;
+using UnityEngine.Events;
+
+namespace ToneTuneToolkit.Networking
+{
+  /// <summary>
+  /// SocketIO通信
+  /// </summary>
+  public class SocketIOClientManager : SingletonMaster<SocketIOClientManager>
+  {
+    public static UnityAction<string> OnDeviceStart;
+
+    private const string Address = @"wss://node.skyelook.com"; // 开头为wss且结尾并非/socket.io
+                                                               // private const string Address = "ws://192.168.50.130:3500";
+
+    private SocketManager socketManager;
+
+    // ==================================================
+
+    private void Start() => Init();
+    private void OnDestroy() => UnInit();
+
+    // ==================================================
+
+    private void Init()
+    {
+      socketManager = new SocketManager(new Uri(Address));
+      socketManager.Options.AutoConnect = false;
+      socketManager.Socket.On<ConnectResponse>(SocketIOEventTypes.Connect, OnConnected);
+      socketManager.Socket.On<ConnectResponse>(SocketIOEventTypes.Error, OnError);
+      socketManager.Socket.On<string>("michelin-start", OnStart);
+
+      socketManager.Open();
+    }
+
+    private void UnInit()
+    {
+      if (socketManager != null)
+      {
+        socketManager.Close();
+        socketManager = null;
+      }
+    }
+
+    // ==================================================
+
+    private void OnConnected(ConnectResponse resp)
+    {
+      Debug.Log("[SocketIOM] Connected.");
+    }
+
+    private void OnError(ConnectResponse resp)
+    {
+      Debug.Log(@$"[SocketIOM] {resp}");
+    }
+
+    private void OnStart(string value)
+    {
+      Debug.Log(@$"[SocketIOM] Start. {value}");
+      OnDeviceStart?.Invoke(value);
+    }
+  }
+}

+ 0 - 0
Materials/Backend & Upload/BackendNetManager.cs → Materials/Networking/Upload/BackendNetManager.cs


+ 0 - 0
Materials/OSC/收发模块/oscconfig.json → Materials/OSC/收发模块/Configs/oscconfig.json


+ 5 - 7
Materials/OSC/收发模块/UniOSCConfiger.cs → Materials/OSC/收发模块/UniOSC/UniOSCConfiger.cs

@@ -1,26 +1,24 @@
 using System.Collections;
 using System.Collections.Generic;
+using ToneTuneToolkit.Data;
 using UnityEngine;
 
 namespace ToneTuneToolkit.OSC
 {
   public class UniOSCConfiger : MonoBehaviour
   {
-    private string configPath = $"{Application.streamingAssetsPath}/configs/oscconfig.json";
+    private string configPath = $"{Application.streamingAssetsPath}/Configs/oscconfig.json";
 
     // ==================================================
 
-    private void Start()
-    {
-      Init();
-    }
+    private void Start() => Init();
 
     // ==================================================
 
     private void Init()
     {
-      UniOSCManager.Instance.UpdateInIPAddress(JsonHelper.GetJson(configPath, "local_ip"), JsonHelper.GetJson(configPath, "local_port"));
-      UniOSCManager.Instance.UpdateOutIPAddress(JsonHelper.GetJson(configPath, "target_ip"), JsonHelper.GetJson(configPath, "target_port"));
+      UniOSCManager.Instance.UpdateInIPAddress(JsonManager.GetJson(configPath, "local_ip"), JsonManager.GetJson(configPath, "local_port"));
+      UniOSCManager.Instance.UpdateOutIPAddress(JsonManager.GetJson(configPath, "target_ip"), JsonManager.GetJson(configPath, "target_port"));
       return;
     }
   }

+ 1 - 1
Materials/OSC/收发模块/UniOSCManager.cs → Materials/OSC/收发模块/UniOSC/UniOSCManager.cs

@@ -115,7 +115,7 @@ namespace ToneTuneToolkit.OSC
       uniOSCEvent.IPAddress = uniOSCConnection.oscOutIPAddress;
       uniOSCConnection.SendOSCMessage(null, uniOSCEvent);
 
-      DEBUG_UIManager.Instance.UpdateOSCText(oscMessage.Address);
+      // DEBUG_UIManager.Instance.UpdateOSCText(oscMessage.Address);
       Debug.Log($"[UniOSC Manager] Send <color=white>{oscMessage.Address}</color> to <color=white>{uniOSCConnection.oscOutIPAddress}:{uniOSCConnection.oscOutPort}</color>...[<color=green>OK</color>]");
       return;
     }

+ 0 - 0
Materials/OSC/收发模块/UniOSCResponder.cs → Materials/OSC/收发模块/UniOSC/UniOSCResponder.cs


+ 18 - 24
Materials/ScrollView/20241125_左右滑动限位圆点/ScrollViewHandler.cs

@@ -1,16 +1,16 @@
 using System.Collections;
 using System.Collections.Generic;
-using System.Threading.Tasks;
 using DG.Tweening;
 using UnityEngine;
+using UnityEngine.EventSystems;
 using UnityEngine.UI;
 
-public class ScrollViewHandler : MonoBehaviour
+public class ScrollViewHandler : MonoBehaviour, IBeginDragHandler, IEndDragHandler
 {
   private ScrollRect sr;
 
   [SerializeField] private int srContentCount;
-  [SerializeField] private float unitPosition;
+  private float unitPosition;
 
   private const float ANIMTIME = .5f;
 
@@ -20,17 +20,17 @@ public class ScrollViewHandler : MonoBehaviour
 
   private void Start() => Init();
 
-  private void Update()
-  {
-    if (Input.GetKeyDown(KeyCode.Q))
-    {
-      sr.DOHorizontalNormalizedPos(unitPosition, ANIMTIME);
-    }
-    if (Input.GetKeyDown(KeyCode.W))
-    {
-      sr.DOHorizontalNormalizedPos(unitPosition, ANIMTIME);
-    }
-  }
+  // private void Update()
+  // {
+  //   if (Input.GetKeyDown(KeyCode.Q))
+  //   {
+  //     sr.DOHorizontalNormalizedPos(unitPosition, ANIMTIME);
+  //   }
+  //   if (Input.GetKeyDown(KeyCode.W))
+  //   {
+  //     sr.DOHorizontalNormalizedPos(unitPosition, ANIMTIME);
+  //   }
+  // }
 
   // ==================================================
 
@@ -39,7 +39,6 @@ public class ScrollViewHandler : MonoBehaviour
     sr = GetComponent<ScrollRect>();
     srContentCount = transform.GetChild(0).GetChild(0).childCount;
     unitPosition = 1f / (srContentCount - 1);
-    return;
   }
 
   // ==================================================
@@ -49,13 +48,11 @@ public class ScrollViewHandler : MonoBehaviour
   private Vector2 currPos; // 鼠标当前位置
   private Vector2 offset; // 两次位置的偏移值
 
-  public void BeginDrag()
-  {
-    lastPos = Input.mousePosition;
-    return;
-  }
+  public void OnBeginDrag(PointerEventData eventData) => BeginDrag();
+  public void OnEndDrag(PointerEventData eventData) => EndDrag();
 
-  public void EndDrag()
+  private void BeginDrag() => lastPos = Input.mousePosition;
+  private void EndDrag()
   {
     currPos = Input.mousePosition;
     offset = currPos - lastPos;
@@ -86,7 +83,6 @@ public class ScrollViewHandler : MonoBehaviour
     //     Debug.Log("向下");
     //   }
     // }
-    return;
   }
 
   #endregion
@@ -113,7 +109,6 @@ public class ScrollViewHandler : MonoBehaviour
     currentIndex = index;
     sr.DOHorizontalNormalizedPos(unitPosition * index, ANIMTIME);
     ControllDot(index);
-    return;
   }
 
   #endregion
@@ -135,7 +130,6 @@ public class ScrollViewHandler : MonoBehaviour
       dots[i].transform.DOScale(Vector3.one, 0.5f);
       dots[i].GetComponent<Image>().DOColor(Color.gray, ANIMTIME);
     }
-    return;
   }
 
   #endregion

BIN
Materials/ScrollView/屏幕截图 2025-06-13 111409.png


+ 6 - 1
Materials/SerialPortUtilityPro/SerialPortUtilityPro/SerialPortUtilityProConfiger.cs

@@ -33,6 +33,11 @@ public class SerialPortUtilityProConfiger : MonoBehaviour
   {
     Instance = this;
     ReadConfig();
+
+    // foreach (string portName in System.IO.Ports.SerialPort.GetPortNames())
+    // {
+    //   Debug.Log("可用串口: " + portName);
+    // }
     return;
   }
 
@@ -83,7 +88,7 @@ public class SerialPortUtilityProConfiger : MonoBehaviour
   }
 
   // ==================================================
-  #region Value
+  #region Data Class
 
   [Serializable]
   public class DeviceInfoData

+ 8 - 5
Materials/SerialPortUtilityPro/SerialPortUtilityPro/SerialPortUtilityProManager.cs

@@ -68,16 +68,20 @@ public class SerialPortUtilityProManager : MonoBehaviour
   /// <param name="modeIndex"></param>
   public void SendMessage2Device(string value)
   {
-    // byte[] data = OutMessageProcessing(value);
-    // serialPortUtilityPro.Write(data);
-
     serialPortUtilityPro.Write(Encoding.ASCII.GetBytes(value)); // 插件
     Debug.Log("[SPUP M] Send: " + value);
     return;
   }
 
+  public void SendByteMessage2Device(byte[] value)
+  {
+    serialPortUtilityPro.Write(value);
+    Debug.Log("[SPUP M] Send hex: " + BitConverter.ToString(value));
+    return;
+  }
+
   #endregion
-  // ==============================
+  // ==================================================
   #region 收包
 
   /// <summary>
@@ -106,7 +110,6 @@ public class SerialPortUtilityProManager : MonoBehaviour
   /// <param name="byteData"></param>
   public void ReadBinaryStreaming(object byteData)
   {
-    Debug.Log(byteData);
     string stringRawData = BitConverter.ToString((byte[])byteData); // 比特流翻译
     stringRawData = InMessageProcessing(stringRawData);
     Debug.Log("[SPUP M] Read: " + stringRawData);

+ 3 - 3
Materials/SerialPortUtilityPro/SerialPortUtilityPro/SerialPortUtilityProResponder.cs

@@ -8,13 +8,13 @@ namespace ToneTuneToolkit.SerialPort
   {
     public static SerialPortUtilityProResponder Instance;
 
-    // ==============================
+    // ==================================================
 
     private void Awake() => Instance = this;
     private void Start() => Init();
     private void OnDestroy() => Uninit();
 
-    // ==============================
+    // ==================================================
 
     private void Init()
     {
@@ -28,7 +28,7 @@ namespace ToneTuneToolkit.SerialPort
       return;
     }
 
-    // ==============================
+    // ==================================================
 
     // AA 00 09 00 00 BB
     // AA 00 09 00 04 BB

+ 0 - 0
Materials/SerialPortUtilityPro/serialportutilityproconfig.json → Materials/SerialPortUtilityPro/configs/serialportutilityproconfig.json


+ 111 - 0
Materials/TCP/TCPClient.cs

@@ -0,0 +1,111 @@
+using UnityEngine;
+using System.Net.Sockets;
+using System.Text;
+using ToneTuneToolkit.Common;
+
+/// <summary>
+/// TCP发图片和文本
+/// </summary>
+public class TCPClient : SingletonMaster<TCPClient>
+{
+  public string serverIP = "192.168.1.100"; // Windows服务器的IP地址
+  public int serverPort = 1006;
+
+  private TcpClient client;
+  private NetworkStream stream;
+
+  // ==================================================
+
+  private void Start() => Init();
+  private void OnDestroy() => UnInit();
+
+  // ==================================================
+
+  private void Init()
+  {
+    // Connect();
+  }
+
+  private void UnInit()
+  {
+    Disconnect();
+  }
+
+  // ==================================================
+
+  public void SetServerIP(string value) => serverIP = value;
+  public void SetServerPort(string value) => serverPort = int.Parse(value);
+
+  // ==================================================
+
+  // 连接到服务器
+  public void Connect()
+  {
+    try
+    {
+      client = new TcpClient();
+      client.Connect(serverIP, serverPort);
+      stream = client.GetStream();
+      Debug.Log("[TCP]Connected to server");
+    }
+    catch (System.Exception e)
+    {
+      Debug.LogError("[TCP]Connection error: " + e.Message);
+    }
+  }
+
+  // 断开连接
+  public void Disconnect()
+  {
+    if (stream != null) { stream.Close(); }
+    if (client != null) { client.Close(); }
+    Debug.Log("[TCP]Disconnected from server");
+  }
+
+
+
+  // 发送文本消息
+  public void SendText(string message)
+  {
+    if (client == null || !client.Connected) { return; }
+
+    try
+    {
+      byte[] textBytes = Encoding.UTF8.GetBytes(message);
+      byte[] lengthBytes = System.BitConverter.GetBytes(textBytes.Length);
+      byte[] dataType = new byte[] { 0 }; // 0 = text
+
+      stream.Write(lengthBytes, 0, 4);
+      stream.Write(dataType, 0, 1);
+      stream.Write(textBytes, 0, textBytes.Length);
+      Debug.Log("[TCP]Sent text: " + message);
+    }
+    catch (System.Exception e)
+    {
+      Debug.LogError("[TCP]Send text error: " + e.Message);
+    }
+  }
+
+  // 发送图片
+  public void SendImage(Texture2D texture)
+  {
+    if (client == null || !client.Connected) { Debug.LogWarning("Not connected to server"); return; }
+
+    try
+    {
+      byte[] imageBytes = texture.EncodeToPNG();
+      byte[] lengthBytes = System.BitConverter.GetBytes(imageBytes.Length);
+      byte[] dataType = new byte[] { 1 }; // 1 = image
+
+      stream.Write(lengthBytes, 0, 4);
+      stream.Write(dataType, 0, 1);
+      stream.Write(imageBytes, 0, imageBytes.Length);
+      Debug.Log("[TCP]Sent image with size: " + texture.width + "x" + texture.height);
+    }
+    catch (System.Exception e)
+    {
+      Debug.LogError("[TCP]Send image error: " + e.Message);
+      Disconnect();
+    }
+  }
+}

+ 117 - 0
Materials/TCP/TCPServer.cs

@@ -0,0 +1,117 @@
+using UnityEngine;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading;
+using ToneTuneToolkit.Common;
+
+public class TCPServer : SingletonMaster<TCPServer>
+{
+  private Thread serverThread;
+  private TcpListener tcpListener;
+  private bool isRunning = false;
+  public int port = 1006;
+
+  public delegate void TextReceivedHandler(string text);
+  public delegate void ImageReceivedHandler(byte[] imageData);
+  public event TextReceivedHandler OnTextReceived;
+  public event ImageReceivedHandler OnImageReceived;
+
+  // ==================================================
+
+  private void Start() => Init();
+  private void OnDestroy() => UnInit();
+
+  // ==================================================
+
+  private void Init()
+  {
+    StartServer();
+  }
+
+  private void UnInit()
+  {
+    StopServer();
+  }
+
+  // ==================================================
+
+  public void StartServer()
+  {
+    isRunning = true;
+    serverThread = new Thread(ServerThread);
+    serverThread.IsBackground = true;
+    serverThread.Start();
+    Debug.Log($"[TCP]Server started on port {port}");
+  }
+
+  public void StopServer()
+  {
+    isRunning = false;
+    tcpListener?.Stop();
+    serverThread?.Abort();
+    Debug.Log("[TCP]Server stopped");
+  }
+
+
+
+  private void ServerThread()
+  {
+    try
+    {
+      tcpListener = new TcpListener(IPAddress.Any, port);
+      tcpListener.Start();
+
+      while (isRunning)
+      {
+        using (TcpClient client = tcpListener.AcceptTcpClient())
+        using (NetworkStream stream = client.GetStream())
+        {
+          // 读取数据长度(4字节)
+          byte[] lengthBytes = new byte[4];
+          stream.Read(lengthBytes, 0, 4);
+          int dataLength = System.BitConverter.ToInt32(lengthBytes, 0);
+
+          // 读取数据类型(1字节)
+          byte[] typeBytes = new byte[1];
+          stream.Read(typeBytes, 0, 1);
+          byte dataType = typeBytes[0];
+
+          // 读取实际数据
+          byte[] data = new byte[dataLength];
+          int bytesRead = 0;
+          while (bytesRead < dataLength)
+          {
+            bytesRead += stream.Read(data, bytesRead, dataLength - bytesRead);
+          }
+
+          // 处理接收到的数据
+          if (dataType == 0) // 文本
+          {
+            string text = Encoding.UTF8.GetString(data);
+            Debug.Log($"[TCP]Received text: {text}");
+            UnityMainThreadDispatcher.Instance().Enqueue(() => OnTextReceived?.Invoke(text));
+          }
+          else if (dataType == 1) // 图片
+          {
+            // 只传递原始字节数据到主线程
+            byte[] imageData = (byte[])data.Clone();
+            UnityMainThreadDispatcher.Instance().Enqueue(() =>
+            {
+              // 在主线程中创建Texture2D
+              Texture2D texture = new Texture2D(2, 2);
+              texture.LoadImage(imageData);
+              OnImageReceived?.Invoke(imageData);
+            });
+            Debug.Log($"[TCP]Received image");
+          }
+        }
+      }
+    }
+    catch (SocketException e)
+    {
+      if (isRunning)
+        Debug.LogError($"[TCP]Server error: {e}");
+    }
+  }
+}

+ 50 - 0
Materials/TCP/UnityMainThreadDispatcher.cs

@@ -0,0 +1,50 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class UnityMainThreadDispatcher : MonoBehaviour
+{
+  private static UnityMainThreadDispatcher _instance;
+  private static readonly Queue<System.Action> _executionQueue = new Queue<System.Action>();
+
+  // 确保在Awake中初始化实例
+  void Awake()
+  {
+    if (_instance == null)
+    {
+      _instance = this;
+      DontDestroyOnLoad(gameObject);
+    }
+    else
+    {
+      Destroy(gameObject);
+    }
+  }
+
+  public static UnityMainThreadDispatcher Instance()
+  {
+    if (_instance == null)
+    {
+      Debug.LogError("UnityMainThreadDispatcher not found in scene. Please add it to a GameObject.");
+    }
+    return _instance;
+  }
+
+  public void Enqueue(System.Action action)
+  {
+    lock (_executionQueue)
+    {
+      _executionQueue.Enqueue(action);
+    }
+  }
+
+  void Update()
+  {
+    lock (_executionQueue)
+    {
+      while (_executionQueue.Count > 0)
+      {
+        _executionQueue.Dequeue().Invoke();
+      }
+    }
+  }
+}

+ 0 - 0
Materials/UI活动检测/ClickListener.cs → Materials/UI/ClickListener.cs


BIN
Materials/UI/GroundGlass.unitypackage


+ 3 - 2
Materials/WebGL/背景透明化/Plugins/TransparentBackground.jslib

@@ -1,3 +1,5 @@
+mergeInto(LibraryManager.library, LibraryGLClear);
+
 var LibraryGLClear = {
     glClear: function(mask)
     {
@@ -10,5 +12,4 @@ var LibraryGLClear = {
         }
         GLctx.clear(mask);
     }
-};
-mergeInto(LibraryManager.library, LibraryGLClear); 
+};

+ 1 - 1
Materials/WebGL/背景透明化/Unity WebGL背景透明化.txt

@@ -2,9 +2,9 @@ Unity WebGL背景透明化(画布透明),显示Html网页背景
 
 https://blog.csdn.net/boyZhenGui/article/details/105552137?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-2-105552137-blog-129862218.235%5Ev43%5Epc_blog_bottom_relevance_base8&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-2-105552137-blog-129862218.235%5Ev43%5Epc_blog_bottom_relevance_base8&utm_relevant_index=5
 
-
 https://blog.csdn.net/weixin_44347839/article/details/134923359
 
 .jslib放在Assets
 Camera - Flags - Soild Color
+Color Space - Gamma
 index.html - backgroundColor: transparent

BIN
Materials/Windows打印/Printer.unitypackage


+ 8 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 63de670e8dfa3894f918c5c621ae74c4
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 4530faa375175434681b3db61c92df57
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 092e44cfbf2cc5a40a7e63ba63e4039f
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Plugins.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 5799387556b282c49b7af4d12d13adaa
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Plugins/System.Drawing.dll


+ 33 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Plugins/System.Drawing.dll.meta

@@ -0,0 +1,33 @@
+fileFormatVersion: 2
+guid: 8eca96d2726ec0a41a9d7d864612e7aa
+PluginImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  iconMap: {}
+  executionOrder: {}
+  defineConstraints: []
+  isPreloaded: 0
+  isOverridable: 0
+  isExplicitlyReferenced: 0
+  validateReferences: 1
+  platformData:
+  - first:
+      Any: 
+    second:
+      enabled: 1
+      settings: {}
+  - first:
+      Editor: Editor
+    second:
+      enabled: 0
+      settings:
+        DefaultValueInitialized: true
+  - first:
+      Windows Store Apps: WindowsStoreApps
+    second:
+      enabled: 0
+      settings:
+        CPU: AnyCPU
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Scripts.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 0ca6ddb14a1183543b639aa1c4c6c1fa
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 90 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Scripts/PrinterConfiger.cs

@@ -0,0 +1,90 @@
+/// <summary>
+/// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
+/// Code Version 1.5.2
+/// </summary>
+
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System.Drawing;
+
+namespace ToneTuneToolkit.IO.Printer
+{
+  /// <summary>
+  /// 打印机配置器
+  /// </summary>
+  public class PrinterConfiger : MonoBehaviour
+  {
+    private void Start() => Init();
+
+    // ==================================================
+
+    private void Init()
+    {
+      // L805();
+      // DNP();
+      // DNP_Theory();
+      L805_A4();
+    }
+
+    // ==================================================
+
+    private void DNP()
+    {
+      PrinterManager.PrinterSetting setting = new PrinterManager.PrinterSetting();
+      setting.PrinterName = "DP-DS620";
+      setting.PaperSizeName = "(4x6)";
+      setting.DPI = 100;
+      setting.WidthInch = 6;
+      setting.HeightInch = 4;
+      setting.Landscape = false;
+      setting.Margin = Vector4.zero;
+      setting.rotateFlip = RotateFlipType.Rotate270FlipNone;
+      PrinterManager.Instance.SetPrinter(setting);
+    }
+
+    private void DNP_Theory()
+    {
+      // 纸张规格:PR(4x6)
+      // 边框:禁用
+      PrinterManager.PrinterSetting setting = new PrinterManager.PrinterSetting();
+      setting.PrinterName = "DP-DS620";
+      setting.PaperSizeName = "PR(4x6)";
+      setting.DPI = 100;
+      setting.WidthInch = 4;
+      setting.HeightInch = 6;
+      setting.Landscape = false;
+      setting.Margin = Vector4.zero;
+      setting.rotateFlip = RotateFlipType.RotateNoneFlipNone;
+      PrinterManager.Instance.SetPrinter(setting);
+    }
+
+    private void L805_6Inch()
+    {
+      PrinterManager.PrinterSetting setting = new PrinterManager.PrinterSetting();
+      setting.PrinterName = "EPSON L805 Series";
+      setting.PaperSizeName = "(4x6)";
+      setting.DPI = 100;
+      setting.WidthInch = 4;
+      setting.HeightInch = 6;
+      setting.Landscape = false;
+      setting.Margin = Vector4.zero;
+      setting.rotateFlip = RotateFlipType.RotateNoneFlipNone;
+      PrinterManager.Instance.SetPrinter(setting);
+    }
+
+    private void L805_A4()
+    {
+      PrinterManager.PrinterSetting setting = new PrinterManager.PrinterSetting();
+      setting.PrinterName = "EPSON L805 Series";
+      setting.PaperSizeName = "A4";
+      setting.DPI = 100;
+      setting.WidthInch = 12.4f;
+      setting.HeightInch = 17.54f;
+      setting.Landscape = false;
+      setting.Margin = Vector4.zero;
+      setting.rotateFlip = RotateFlipType.RotateNoneFlipNone;
+      PrinterManager.Instance.SetPrinter(setting);
+    }
+  }
+}

+ 11 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Scripts/PrinterConfiger.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c15d88e208bb3484f989e08345d15118
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 122 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Scripts/PrinterFileProcessor.cs

@@ -0,0 +1,122 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System;
+using UnityEngine;
+
+namespace ToneTuneToolkit.IO.Printer
+{
+  public class PrinterFileProcessor : MonoBehaviour
+  {
+    private const string PrinterPath = "C:/Printer";
+    private string CachePath = Application.streamingAssetsPath + "/PrinterCache";
+
+    // ==================================================
+
+    private void Start() => Init();
+    private void OnDestroy() => UnInit();
+
+    // ==================================================
+
+    private void Init()
+    {
+      FolderCheck();
+      StartCoroutine(nameof(PrintLoop));
+    }
+
+    private void UnInit()
+    {
+      StopCoroutine(nameof(PrintLoop));
+    }
+
+    // ==================================================
+
+    private void FolderCheck()
+    {
+      if (!Directory.Exists(PrinterPath)) { Directory.CreateDirectory(PrinterPath); }
+      if (!Directory.Exists(CachePath)) { Directory.CreateDirectory(CachePath); }
+    }
+
+    // ==================================================
+
+    private IEnumerator PrintLoop()
+    {
+      yield return new WaitForSeconds(3f);
+      while (true)
+      {
+        CheckFile();
+        yield return new WaitForSeconds(3f);
+      }
+    }
+
+    /// <summary>
+    /// 检测是否存在文件
+    /// </summary>
+    private void CheckFile()
+    {
+      string[] files = Directory.GetFiles(PrinterPath); // 获取源文件夹中的所有文件
+      if (files.Length == 0) { return; }
+      foreach (string sourceFilePath in files)
+      {
+        ProcessFile(sourceFilePath);
+      }
+    }
+
+    /// <summary>
+    /// 处理文件
+    /// </summary>
+    /// <param name="sourceFilePath"></param>
+    private void ProcessFile(string sourceFilePath)
+    {
+      try
+      {
+        if (!IsFileReady(sourceFilePath)) // 检查文件是否就绪(未被其他进程占用)
+        {
+          Debug.Log($"[FP] 文件被占用,跳过: {Path.GetFileName(sourceFilePath)}");
+          return;
+        }
+
+        string fileName = @$"{Path.GetFileNameWithoutExtension(sourceFilePath)}_{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}{Path.GetExtension(sourceFilePath)}";
+        string destFilePath = Path.Combine(CachePath, fileName);
+
+        // Debug.Log(fileName + "\n" + destFilePath);
+
+        File.Move(sourceFilePath, destFilePath);
+        Debug.Log($"[FP] 文件已移动: {fileName}");
+
+        byte[] fileData = File.ReadAllBytes(destFilePath);
+        Texture2D texture = new Texture2D(2, 2);
+        texture.LoadImage(fileData);
+        texture.Apply();
+        PrinterManager.Instance.Print(texture);
+        Debug.Log($"[FP] 图片准备打印");
+
+#if UNITY_EDITOR
+        UnityEditor.AssetDatabase.Refresh(); // 在编辑器中刷新AssetDatabase
+#endif
+      }
+      catch (Exception e)
+      {
+        Debug.LogError($"[FP] 处理文件 {Path.GetFileName(sourceFilePath)} 时出错: {e.Message}");
+      }
+    }
+
+
+
+    private bool IsFileReady(string filePath)
+    {
+      try
+      {
+        // 尝试打开文件,如果成功则文件就绪
+        using (FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.None))
+        {
+          return true;
+        }
+      }
+      catch (IOException)
+      {
+        return false; // 文件被占用或不可访问
+      }
+    }
+  }
+}

+ 11 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Scripts/PrinterFileProcessor.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b9136fa7d2a803f4fbd8a16e2ff81d86
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 53 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Scripts/PrinterHandler.cs

@@ -0,0 +1,53 @@
+/// <summary>
+/// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
+/// Code Version 1.5.2
+/// </summary>
+
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace ToneTuneToolkit.IO.Printer
+{
+  /// <summary>
+  /// 打印机控制器
+  /// </summary>
+  public class PrinterHandler : MonoBehaviour
+  {
+    private void Start() => Init();
+
+    private void Init()
+    {
+      L805();
+      // DNP();
+    }
+
+    private void DNP()
+    {
+      PrinterManager.PrinterSetting setting = new PrinterManager.PrinterSetting();
+      setting.PrinterName = "DP-DS620";
+      setting.PaperSizeName = "(4x6)";
+      setting.DPI = 100;
+      setting.WidthInch = 6;
+      setting.HeightInch = 4;
+      setting.Landscape = false;
+      setting.Margin = Vector4.zero;
+      setting.rotateFlip = System.Drawing.RotateFlipType.Rotate270FlipNone;
+      PrinterManager.Instance.SetPrinter(setting);
+    }
+
+    private void L805()
+    {
+      PrinterManager.PrinterSetting setting = new PrinterManager.PrinterSetting();
+      setting.PrinterName = "EPSON L805 Series";
+      setting.PaperSizeName = "(4x6)";
+      setting.DPI = 100;
+      setting.WidthInch = 4;
+      setting.HeightInch = 6;
+      setting.Landscape = false;
+      setting.Margin = Vector4.zero;
+      setting.rotateFlip = System.Drawing.RotateFlipType.RotateNoneFlipNone;
+      PrinterManager.Instance.SetPrinter(setting);
+    }
+  }
+}

+ 11 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Scripts/PrinterHandler.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 389f4ef3b141f064d889e79e8617c7f5
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 342 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Scripts/PrinterManager.cs

@@ -0,0 +1,342 @@
+/// <summary>
+/// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
+/// Code Version 1.5.2
+/// </summary>
+
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System;
+using System.Runtime.InteropServices;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Printing;
+using System.Drawing.Imaging;
+using ToneTuneToolkit.Common;
+
+namespace ToneTuneToolkit.IO.Printer
+{
+  /// <summary>
+  /// 
+  /// 测试可打印1200x1800的图片,页面参数{X=0,Y=0,Width=400,Height=600}
+  /// </summary>
+  public class PrinterManager : SingletonMaster<PrinterManager>
+  {
+    private PrinterSetting ps = new PrinterSetting();
+
+    // ==================================================
+
+    private void Start() => Init();
+
+    // ==================================================
+
+    private void Init()
+    {
+      // DisplayInstalledPrinters();
+      OperationalCheck();
+    }
+
+    // ==================================================
+    #region 设置打印机
+
+    public void SetPrinter(PrinterSetting setting)
+    {
+      ps = setting;
+
+      foreach (string item in PrinterSettings.InstalledPrinters)
+      {
+        if (item.Contains(ps.PrinterName))
+        {
+          ps.PrinterName = item;
+          return;
+        }
+      }
+      ps.PrinterName = new PrinterSettings().PrinterName;
+    }
+
+    #endregion
+    // ==================================================
+    #region Tool 显示所有打印机
+
+    private void DisplayInstalledPrinters()
+    {
+      foreach (string printer in PrinterSettings.InstalledPrinters) { Debug.Log($"[PM] 已安装打印机: {printer}"); }
+    }
+
+    #endregion
+    // ==================================================
+
+    /// <summary>
+    /// 可运行性检查
+    /// </summary>
+    private void OperationalCheck()
+    {
+      if (!Application.isEditor && Application.platform != RuntimePlatform.WindowsPlayer)
+      {
+        Debug.LogWarning("[PM] 打印功能仅支持Windows平台");
+      }
+    }
+
+    // ==================================================
+
+    /// <summary>
+    /// 打印照片
+    /// </summary>
+    /// <param name="texture"></param>
+    public void Print(Texture2D texture)
+    {
+      try
+      {
+        // 打印前强制GC
+        GC.Collect();
+        GC.WaitForPendingFinalizers();
+
+        Debug.Log($"[PM] 原始Texture2D尺寸: {texture.width}x{texture.height}");
+
+        using (Bitmap bitmap = T2D2BitmapSafe(texture))
+        {
+          Debug.Log($"[PM] 转换后Bitmap尺寸: {bitmap.Width}x{bitmap.Height}");
+
+          PrintBitmap(bitmap);
+        }
+      }
+      catch (Exception e)
+      {
+        Debug.LogError("[PM] 打印失败: " + e.Message);
+      }
+    }
+
+    // ==================================================
+    #region 转换Texture2D到Bitmap
+
+    /// <summary>
+    /// 安全转换Texture2D到Bitmap
+    /// </summary>
+    /// <param name="texture"></param>
+    /// <returns></returns>
+    private Bitmap T2D2BitmapSafe(Texture2D texture)
+    {
+      Bitmap bitmap = new Bitmap(texture.width, texture.height, PixelFormat.Format32bppArgb);
+      bitmap.SetResolution(ps.DPI, ps.DPI);
+      BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, bitmap.PixelFormat);
+
+      try
+      {
+        Color32[] pixels = texture.GetPixels32();
+        byte[] bytes = new byte[pixels.Length * 4];
+
+        for (int y = 0; y < texture.height; y++)
+        {
+          for (int x = 0; x < texture.width; x++)
+          {
+            int sourceIndex = y * texture.width + x;
+            int destY = texture.height - 1 - y;
+            int destIndex = destY * texture.width + x;
+
+            bytes[destIndex * 4] = pixels[sourceIndex].b;
+            bytes[destIndex * 4 + 1] = pixels[sourceIndex].g;
+            bytes[destIndex * 4 + 2] = pixels[sourceIndex].r;
+            bytes[destIndex * 4 + 3] = pixels[sourceIndex].a;
+          }
+        }
+
+        Marshal.Copy(bytes, 0, bitmapData.Scan0, bytes.Length);
+      }
+      finally
+      {
+        bitmap.UnlockBits(bitmapData);
+      }
+      return bitmap;
+    }
+
+    #endregion
+    // ==================================================
+    #region 打印Bitmap
+
+    /// <summary>
+    /// Theory
+    /// </summary>
+    /// <param name="bitmap"></param>
+    private void PrintBitmap(Bitmap bitmap)
+    {
+      using (PrintDocument pd = new PrintDocument())
+      {
+        pd.PrinterSettings.PrinterName = ps.PrinterName;
+        pd.DefaultPageSettings.PrinterResolution = new PrinterResolution()
+        {
+          Kind = PrinterResolutionKind.Custom,
+          X = ps.DPI,
+          Y = ps.DPI
+        };
+
+        // 获取打印机的可打印区域
+        PrinterSettings printerSettings = new PrinterSettings();
+        printerSettings.PrinterName = ps.PrinterName;
+
+        // 使用打印机的默认页面设置
+        pd.DefaultPageSettings.Margins = new Margins(0, 0, 0, 0);
+        pd.OriginAtMargins = true; // 关键:以边距为原点
+
+        // 查找匹配的纸张尺寸
+        PaperSize targetPaperSize = null;
+        foreach (PaperSize paperSize in pd.PrinterSettings.PaperSizes)
+        {
+          if (paperSize.PaperName.Contains("4x6") || paperSize.PaperName.Contains(ps.PaperSizeName))
+          {
+            targetPaperSize = paperSize;
+            break;
+          }
+        }
+
+        if (targetPaperSize != null)
+        {
+          pd.DefaultPageSettings.PaperSize = targetPaperSize;
+          Debug.Log($"[PM] 使用纸张: {targetPaperSize.PaperName}, 尺寸: {targetPaperSize.Width}x{targetPaperSize.Height}");
+        }
+        else
+        {
+          // 如果没有找到匹配的纸张,使用自定义尺寸
+          int paperWidth = (int)(ps.WidthInch * ps.DPI); // 转换为百分之一英寸
+          int paperHeight = (int)(ps.HeightInch * ps.DPI);
+          PaperSize customPaper = new PaperSize("Custom", paperWidth, paperHeight);
+          pd.DefaultPageSettings.PaperSize = customPaper;
+          Debug.Log($"[PM] 使用自定义纸张: {paperWidth}x{paperHeight}");
+        }
+
+        pd.PrintPage += (sender, args) =>
+        {
+          try
+          {
+            Debug.Log($"[PM] 开始绘制: 图片{bitmap.Width}x{bitmap.Height}");
+            Debug.Log($"[PM] 页面边界: {args.PageBounds}");
+            Debug.Log($"[PM] 硬边距: X={args.PageSettings.HardMarginX}, Y={args.PageSettings.HardMarginY}");
+
+            // 旋转图片
+            using (Bitmap rotatedBitmap = new Bitmap(bitmap))
+            {
+              rotatedBitmap.RotateFlip(ps.rotateFlip);
+
+              // 计算实际可打印区域
+              RectangleF printableArea = args.PageSettings.PrintableArea;
+              Rectangle destRect = new Rectangle(
+                  0,
+                  0,
+                  args.PageBounds.Width,
+                  args.PageBounds.Height
+              );
+
+              // 设置高质量绘制
+              args.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+              args.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
+              args.Graphics.SmoothingMode = SmoothingMode.HighQuality;
+              args.Graphics.CompositingQuality = CompositingQuality.HighQuality;
+
+              // 绘制到整个页面区域
+              args.Graphics.DrawImage(rotatedBitmap, destRect);
+
+              Debug.Log($"[PM] 绘制区域: {destRect}");
+            }
+
+            Debug.Log("[PM] 绘制完成");
+          }
+          catch (Exception e)
+          {
+            Debug.LogError("[PM] 绘制图像时出错: " + e.Message);
+            args.Cancel = true;
+          }
+        };
+
+        try
+        {
+          pd.Print();
+          Debug.Log("[PM] 打印任务已发送");
+        }
+        catch (Exception e)
+        {
+          Debug.LogError("[PM] 打印过程中出错: " + e.Message);
+        }
+      }
+    }
+
+    // private void PrintBitmap(Bitmap bitmap)
+    // {
+    //   using (PrintDocument pd = new PrintDocument())
+    //   {
+    //     pd.PrinterSettings.PrinterName = ps.PrinterName;
+    //     pd.DefaultPageSettings.PrinterResolution = new PrinterResolution()
+    //     {
+    //       Kind = PrinterResolutionKind.Custom,
+    //       X = ps.DPI,
+    //       Y = ps.DPI
+    //     };
+
+    //     int paperWidth = ps.WidthInch * 100;
+    //     int paperHeight = ps.HeightInch * 100;
+
+    //     PaperSize photoSize = new PaperSize("Custom", paperWidth, paperHeight);
+    //     pd.DefaultPageSettings.PaperSize = photoSize;
+    //     pd.DefaultPageSettings.Margins = new Margins(0, 0, 0, 0);
+    //     pd.OriginAtMargins = true;
+
+    //     pd.PrintPage += (sender, args) =>
+    //     {
+    //       try
+    //       {
+    //         Debug.Log($"[PM] 开始绘制: 图片{bitmap.Width}x{bitmap.Height} / 页面{args.PageBounds}");
+
+    //         Rectangle destRect = new Rectangle(
+    //               (int)-args.PageSettings.HardMarginX,
+    //               (int)-args.PageSettings.HardMarginY,
+    //               (int)(args.PageBounds.Width + args.PageSettings.HardMarginX * 2),
+    //               (int)(args.PageBounds.Height + args.PageSettings.HardMarginY * 2)
+    //           );
+
+    //         args.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+    //         args.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
+    //         args.Graphics.SmoothingMode = SmoothingMode.HighQuality;
+
+    //         bitmap.RotateFlip(ps.rotateFlip); // 旋转矫正
+    //         args.Graphics.DrawImage(bitmap, destRect);
+
+    //         Debug.Log("[PM] 绘制完成");
+    //       }
+    //       catch (Exception e)
+    //       {
+    //         Debug.LogError("[PM] 绘制图像时出错: " + e.Message);
+    //         args.Cancel = true;
+    //       }
+    //     };
+
+    //     try
+    //     {
+    //       pd.Print();
+    //       Debug.Log("[PM] 打印任务已发送");
+    //     }
+    //     catch (Exception e)
+    //     {
+    //       Debug.LogError("[PM] 打印过程中出错: " + e.Message);
+    //     }
+    //   }
+    // }
+
+    #endregion
+    // ==================================================
+    #region Config
+
+    [Serializable]
+    public class PrinterSetting
+    {
+      public string PrinterName = "L805";
+      public string PaperSizeName = "6x4 Photo";
+      public float WidthInch = 4;
+      public float HeightInch = 6;
+      public int DPI = 100; // 1200x1800是6英寸在300dpi下的像素尺寸 // 400x600是6英寸在100dpi下的像素尺寸
+
+      public bool Landscape = false;
+      public Vector4 Margin = Vector4.zero; // 边距 // x,y,z,w
+      public RotateFlipType rotateFlip = RotateFlipType.RotateNoneFlipNone;
+    }
+
+    #endregion
+  }
+}

+ 11 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/IO/Printer/Scripts/PrinterManager.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 0951266cf3aff1f468a37fe9eff01ca6
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Networking.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 6bef49af53347834fb43fa6638c83965
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Networking/Upload.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: ab299d1f3e8472b4f8d5bc948963fd40
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 247 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Networking/Upload/Upload2OYManager.cs

@@ -0,0 +1,247 @@
+/// <summary>
+/// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
+/// Code Version 1.5.2
+/// </summary>
+
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Events;
+using System.Text;
+using Newtonsoft.Json;
+using UnityEngine.Networking;
+using System;
+using ToneTuneToolkit.Common;
+
+namespace ToneTuneToolkit.Networking
+{
+  /// <summary>
+  /// 对乔宝具
+  /// </summary>
+  public class Upload2OYManager : SingletonMaster<Upload2OYManager>
+  {
+    public static UnityAction<string> OnUploadFinishedBackString;
+    public static UnityAction<Texture2D> OnUploadFinishedBackTexture;
+
+    private const int AppID = 100;
+    private const float RetryWaitTime = 30f; // 重新上传尝试间隔
+
+    [Header("Qiniu Access Token Callback")]
+    [SerializeField] private QiniuAccessTokenCallback tokenCallback = new QiniuAccessTokenCallback();
+    [Header("Qiniu Callback")]
+    [SerializeField] private QiniuCallback qiniuCallback = new QiniuCallback();
+    [Header("Server Callback")]
+    [SerializeField] private ServerPackage serverPackage = new ServerPackage();
+    [SerializeField] private ServerCallback serverCallback = new ServerCallback();
+
+    private const string QiniuAccessTokenURL = @"https://h5.skyelook.com/api/qiniu/getAccessToken";
+    private const string QiniuURL = @"https://upload.qiniup.com";
+    private const string cloudURL = @"https://h5.skyelook.com/api/attachments";
+
+    // ==================================================
+    #region Step 00 // 完善文件信息
+
+    private string fileName;
+    private byte[] fileStream;
+
+    public void UpdateFilePackage(string name, byte[] stream)
+    {
+      fileName = name;
+      fileStream = stream;
+    }
+
+    #endregion
+    // ==================================================
+    #region Step 01 // 获取Token
+
+    public void UploadFile() => StartCoroutine(nameof(GetQiniuAccessToken));
+
+    private IEnumerator GetQiniuAccessToken()
+    {
+      using (UnityWebRequest unityWebRequest = UnityWebRequest.Get(QiniuAccessTokenURL))
+      {
+        yield return unityWebRequest.SendWebRequest();
+        if (unityWebRequest.result != UnityWebRequest.Result.Success)
+        {
+          Debug.LogWarning($"[U2OYM] {unityWebRequest.error}");
+          StartCoroutine(nameof(RetryUpload));
+        }
+        else
+        {
+          tokenCallback = JsonConvert.DeserializeObject<QiniuAccessTokenCallback>(unityWebRequest.downloadHandler.text);
+          Debug.Log($"[U2OYM] Get qiniu access token sucessed: {tokenCallback.data.token}");
+
+          StartCoroutine(nameof(PostFile2Qiniu)); // 下一步
+        }
+      }
+    }
+
+    #endregion
+    // ==================================================
+    #region Step 02 // 上传文件到七牛云
+
+    private IEnumerator PostFile2Qiniu()
+    {
+      WWWForm wwwForm = new WWWForm();
+      wwwForm.AddField("token", tokenCallback.data.token);
+      wwwForm.AddBinaryData("file", fileStream, fileName);
+
+      using (UnityWebRequest unityWebRequest = UnityWebRequest.Post(QiniuURL, wwwForm))
+      {
+        yield return unityWebRequest.SendWebRequest();
+        if (unityWebRequest.result != UnityWebRequest.Result.Success)
+        {
+          Debug.LogWarning($"[U2OYM] {unityWebRequest.error}");
+          StartCoroutine(nameof(RetryUpload));
+        }
+        else
+        {
+          qiniuCallback = JsonConvert.DeserializeObject<QiniuCallback>(unityWebRequest.downloadHandler.text);
+          Debug.Log($"[U2OYM] Post file 2 qiniu sucessed: {qiniuCallback.data.file_url}");
+
+          StartCoroutine(nameof(PostFile2Server)); // 下一步
+        }
+      }
+    }
+
+    #endregion
+    // ==================================================
+    #region Step 03 // 七牛云返回数据传至服务器
+
+    private IEnumerator PostFile2Server()
+    {
+      serverPackage.file_url = qiniuCallback.data.file_url;
+      serverPackage.app_id = AppID;
+
+      string jsonString = JsonConvert.SerializeObject(serverPackage);
+      byte[] bytes = Encoding.Default.GetBytes(jsonString);
+
+      using (UnityWebRequest unityWebRequest = new UnityWebRequest(cloudURL, "POST"))
+      {
+        unityWebRequest.SetRequestHeader("Content-Type", "application/json");
+        unityWebRequest.uploadHandler = new UploadHandlerRaw(bytes);
+        unityWebRequest.downloadHandler = new DownloadHandlerBuffer();
+
+        yield return unityWebRequest.SendWebRequest();
+        if (unityWebRequest.result != UnityWebRequest.Result.Success)
+        {
+          Debug.LogWarning($"[U2OYM] {unityWebRequest.error}");
+          StartCoroutine(nameof(RetryUpload));
+        }
+        else
+        {
+          serverCallback = JsonConvert.DeserializeObject<ServerCallback>(unityWebRequest.downloadHandler.text);
+          Debug.Log($"[U2OYM] Post file info 2 server sucessed: {serverCallback.data.view_url}");
+
+          // 返回链接
+          OnUploadFinishedBackString?.Invoke(serverCallback.data.view_url);
+
+          // 组装
+          qrCodeURL = $"https://h5.skyelook.com/api/wechat/getQrcodeApp/{serverCallback.data.code}/wx039a4c76d8788bb0/?env=trial"; // ?env=trial // 额外添加?
+
+          StartCoroutine(nameof(GetQRCode4Server)); // 下一步搞图
+        }
+      }
+    }
+
+    #endregion
+    // ==================================================
+    #region Step 04 // 从服务器上获取码
+
+    [SerializeField] private string qrCodeURL;
+    [SerializeField] private Texture2D t2dQRCode;
+
+    private IEnumerator GetQRCode4Server()
+    {
+      using (UnityWebRequest unityWebRequest = UnityWebRequestTexture.GetTexture(qrCodeURL)) // new UnityWebRequest(sunCodeURL, "GET"))
+      {
+        yield return unityWebRequest.SendWebRequest();
+        if (unityWebRequest.result != UnityWebRequest.Result.Success)
+        {
+          Debug.LogWarning($"[U2OYM] {unityWebRequest.error}");
+          StartCoroutine(nameof(RetryUpload));
+        }
+        else
+        {
+          t2dQRCode = ((DownloadHandlerTexture)unityWebRequest.downloadHandler).texture;
+          Debug.Log($"[U2OYM] Get qr texture sucessed");
+
+          OnUploadFinishedBackTexture?.Invoke(t2dQRCode); // 返回图
+        }
+      }
+    }
+
+    #endregion
+    // ==================================================
+    #region 传不上去硬传
+
+    private IEnumerator RetryUpload()
+    {
+      yield return new WaitForSeconds(RetryWaitTime);
+      PostFile2Qiniu();
+    }
+
+    #endregion
+    // ==================================================
+    #region Json解析类
+
+    // 七牛云Token回执
+    [Serializable]
+    public class QiniuAccessTokenCallback
+    {
+      public int status;
+      public int code;
+      public TokenDataJson data;
+      public string message;
+    }
+    [Serializable]
+    public class TokenDataJson
+    {
+      public string token;
+    }
+
+    // 七牛云文件上传回执
+    [Serializable]
+    public class QiniuCallback
+    {
+      public int code;
+      public CloudCallbackDataJson data;
+      public int status;
+    }
+    [Serializable]
+    public class CloudCallbackDataJson
+    {
+      public string file_name;
+      public string file_url;
+    }
+
+    // 向服务器发送的json
+    [Serializable]
+    public class ServerPackage
+    {
+      public string file_url;
+      public int app_id;
+      // public string options;
+    }
+    [Serializable]
+    public class ServerCallback
+    {
+      public int status;
+      public int code;
+      public ServerCallbackDataJson data;
+    }
+
+    [Serializable]
+    public class ServerCallbackDataJson
+    {
+      public string file_url;
+      public int app_id;
+      public string code;
+      public string view_url;
+      public string updated_at;
+      public string created_at;
+      public int id;
+    }
+  }
+  #endregion
+}

+ 11 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Networking/Upload/Upload2OYManager.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6ee2856258a90e3438cd8a48df819144
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 632 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Networking/Upload/Upload2ZCManager.cs

@@ -0,0 +1,632 @@
+/// <summary>
+/// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
+/// Code Version 1.5.2
+/// </summary>
+
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Networking;
+using ToneTuneToolkit.Common;
+using UnityEngine.Events;
+using Newtonsoft.Json;
+using System;
+
+namespace ToneTuneToolkit.Networking
+{
+  /// <summary>
+  /// 对志城宝具
+  /// </summary>
+  public class Upload2ZCManager : SingletonMaster<Upload2ZCManager>
+  {
+    #region 2025.10 MichelinCIIE
+
+    public static UnityAction<Texture2D> OnMichelinUploadFinished;
+
+    private const string MichelinUPLOADURL = @"https://michelin-ciie.studiocapsule.cn/api/index/aiUpload";
+
+
+
+    [SerializeField] private MichelinUserInfo mUserInfo = new MichelinUserInfo();
+    [SerializeField] private MichelinRespon mRespon = new MichelinRespon();
+    public void UpdateMUserInfo(string gender, string question_1, Texture2D t2d)
+    {
+      mUserInfo = new MichelinUserInfo();
+      mUserInfo.gender = gender;
+      mUserInfo.question_1 = question_1;
+      mUserInfo.file = t2d.EncodeToPNG();
+    }
+
+    public void UploadMUserInfo() => StartCoroutine(nameof(UploadMUserInfoAction));
+    private IEnumerator UploadMUserInfoAction()
+    {
+      Debug.Log("[U2ZCM] 开始上传");
+      WWWForm wwwForm = new WWWForm();
+      wwwForm.AddField("gender", mUserInfo.gender);
+      wwwForm.AddField("question_1", mUserInfo.question_1);
+      wwwForm.AddBinaryData("file", mUserInfo.file);
+
+      using (UnityWebRequest www = UnityWebRequest.Post(MichelinUPLOADURL, wwwForm))
+      {
+        www.downloadHandler = new DownloadHandlerBuffer();
+        yield return www.SendWebRequest();
+
+        if (www.result != UnityWebRequest.Result.Success)
+        {
+          Debug.LogWarning($"[U2ZCM] {www.error}");
+          yield break;
+        }
+
+        Debug.Log($"[U2ZCM] {www.downloadHandler.text}");
+        try
+        {
+          mRespon = JsonConvert.DeserializeObject<MichelinRespon>(www.downloadHandler.text);
+        }
+        catch (Exception)
+        {
+          Debug.LogWarning($"[U2ZCM] 解析错误");
+          yield break;
+        }
+
+        if (mRespon.code != 0)
+        {
+          Debug.LogWarning($"[U2ZCM] 解析错误");
+          yield break;
+        }
+      }
+
+      // 搞图
+      using (UnityWebRequest unityWebRequest = UnityWebRequestTexture.GetTexture(mRespon.data.qr_url)) // new UnityWebRequest(sunCodeURL, "GET"))
+      {
+        yield return unityWebRequest.SendWebRequest();
+        if (unityWebRequest.result != UnityWebRequest.Result.Success)
+        {
+          Debug.LogWarning($"[U2ZCM] {unityWebRequest.error}");
+        }
+        else
+        {
+          Debug.Log($"[U2ZCM] Get qr texture sucessed");
+          OnMichelinUploadFinished?.Invoke(((DownloadHandlerTexture)unityWebRequest.downloadHandler).texture); // 返回图
+        }
+      }
+    }
+
+    // ==================================================
+    // 数据类
+    [Serializable]
+    public class MichelinUserInfo
+    {
+      public string gender;
+      public string question_1;
+      public byte[] file;
+    }
+
+    [Serializable]
+    public class MichelinRespon
+    {
+      public int code;
+      public string message;
+      public MichelinResponData data;
+    }
+    public class MichelinResponData
+    {
+      public string qr_url;
+    }
+
+    #endregion
+    // ==================================================
+    // ==================================================
+    // ==================================================
+    #region 2025.10 LonginesBoutique
+
+    // public static UnityAction<int> OnLBUploadFinished;
+
+    // private const string LonginesBoutiqueUPLOADURL = @"https://longines-ai.studiocapsule.cn/api/index/upload";
+
+
+
+    // [SerializeField] private LBUserInfo lbUserInfo = new LBUserInfo();
+    // [SerializeField] private LBRespon lbRespon = new LBRespon();
+    // public void UpdateLBUserInfo(string gender, string question_1, Texture2D t2d)
+    // {
+    //   lbUserInfo = new LBUserInfo();
+    //   lbUserInfo.gender = gender;
+    //   lbUserInfo.question_1 = question_1;
+    //   lbUserInfo.file = t2d.EncodeToPNG();
+    // }
+
+    // public void UploadLBUserInfo() => StartCoroutine(nameof(UploadLBUserInfoAction));
+    // private IEnumerator UploadLBUserInfoAction()
+    // {
+    //   Debug.Log("[U2ZCM] 开始上传");
+    //   WWWForm wwwForm = new WWWForm();
+    //   wwwForm.AddField("gender", lbUserInfo.gender);
+    //   wwwForm.AddField("question_1", lbUserInfo.question_1);
+    //   wwwForm.AddBinaryData("file", lbUserInfo.file);
+
+    //   using (UnityWebRequest www = UnityWebRequest.Post(LonginesBoutiqueUPLOADURL, wwwForm))
+    //   {
+    //     www.downloadHandler = new DownloadHandlerBuffer();
+    //     yield return www.SendWebRequest();
+
+    //     if (www.result != UnityWebRequest.Result.Success)
+    //     {
+    //       Debug.Log($"[U2ZCM] {www.error}");
+    //       yield break;
+    //     }
+
+    //     Debug.Log($"[U2ZCM] {www.downloadHandler.text}");
+    //     try
+    //     {
+    //       lbRespon = JsonConvert.DeserializeObject<LBRespon>(www.downloadHandler.text);
+    //     }
+    //     catch (Exception)
+    //     {
+    //       Debug.Log($"[U2ZCM] 解析错误");
+    //       yield break;
+    //     }
+
+    //     if (lbRespon.code != 0)
+    //     {
+    //       OnLBUploadFinished?.Invoke(0000);
+    //       yield break;
+    //     }
+
+    //     OnLBUploadFinished?.Invoke(lbRespon.data.look_pwd);
+    //   }
+    // }
+
+    // // ==================================================
+    // // 数据类
+    // [Serializable]
+    // public class LBUserInfo
+    // {
+    //   public string gender;
+    //   public string question_1;
+    //   public byte[] file;
+    // }
+
+    // [Serializable]
+    // public class LBRespon
+    // {
+    //   public int code;
+    //   public string message;
+    //   public LBResponData data;
+    // }
+    // public class LBResponData
+    // {
+    //   public int look_pwd;
+    // }
+
+    #endregion
+    // ==================================================
+    // ==================================================
+    // ==================================================
+    #region 2025.06 VWAIPhoto
+
+    // public static UnityAction<Texture2D, bool> OnVWAvatarFinished;
+
+    // private const string VWSUBMITURL = @"https://vw-v-space.studiocapsule.cn/api/device/submitTask";
+
+    // public void UpgradeVWUserData(string gender, string car, string address, Texture2D file)
+    // {
+    //   uVWUD.gender = gender;
+    //   uVWUD.car = car;
+    //   uVWUD.address = address;
+    //   uVWUD.file = file.EncodeToPNG();
+    //   return;
+    // }
+
+    // // ==================================================
+    // // 提交生成任务
+
+    // public void SubmitVWUserPhoto() => StartCoroutine(nameof(SubmitVWUserPhotoAction));
+    // private IEnumerator SubmitVWUserPhotoAction()
+    // {
+    //   WWWForm wwwForm = new WWWForm();
+    //   wwwForm.AddField("gender", uVWUD.gender);
+    //   wwwForm.AddField("car", uVWUD.car);
+    //   wwwForm.AddField("address", uVWUD.address);
+    //   wwwForm.AddBinaryData("file", uVWUD.file);
+
+    //   using (UnityWebRequest www = UnityWebRequest.Post(VWSUBMITURL, wwwForm))
+    //   {
+    //     www.downloadHandler = new DownloadHandlerBuffer();
+    //     yield return www.SendWebRequest();
+
+    //     if (www.result != UnityWebRequest.Result.Success)
+    //     {
+    //       Debug.Log($"[U2ZCM] {www.error}");
+    //       yield break;
+    //     }
+
+    //     Debug.Log($"[U2ZCM] {www.downloadHandler.text}");
+    //     try
+    //     {
+    //       rVWUD = JsonConvert.DeserializeObject<Respon_VWUserData>(www.downloadHandler.text);
+    //     }
+    //     catch
+    //     {
+    //       OnVWAvatarFinished?.Invoke(null, false);
+    //     }
+    //     if (rVWUD.code != 0)
+    //     {
+    //       Debug.Log($"[U2ZCM] Code Error");
+    //       yield break;
+    //     }
+
+    //     StartQueryTask(); // 轮询直到出答案
+    //   }
+    //   yield break;
+    // }
+
+
+
+    // private Upload_VWUserData uVWUD = new Upload_VWUserData();
+    // [SerializeField] private Respon_VWUserData rVWUD = new Respon_VWUserData();
+
+    // [Serializable]
+    // public class Upload_VWUserData
+    // {
+    //   public string gender;
+    //   public string car;
+    //   public string address;
+    //   public byte[] file;
+    // }
+
+    // [Serializable]
+    // public class Respon_VWUserData
+    // {
+    //   public int code;
+    //   public Respon_VWUserDataData data;
+    // }
+
+    // [Serializable]
+    // public class Respon_VWUserDataData
+    // {
+    //   public string task_code;
+    // }
+
+    // // ==================================================
+    // // 轮询
+
+    // private int queryCount = 0;
+    // private const string VWQUERYURL = @"https://vw-v-space.studiocapsule.cn/api/device/queryTask";
+
+    // public void StartQueryTask() { StartCoroutine(nameof(QueryTaskAction)); }
+    // public void StopQueryTask() { StopCoroutine(nameof(QueryTaskAction)); }
+    // private IEnumerator QueryTaskAction()
+    // {
+    //   yield return new WaitForSeconds(5f); // 先等5秒
+    //   while (true)
+    //   {
+    //     queryCount++;
+
+    //     if (queryCount > 12)
+    //     {
+    //       Debug.Log($"[U2ZCM] 轮询次数过多,停止查询");
+    //       OnVWAvatarFinished?.Invoke(null, false);
+    //       yield break;
+    //     }
+
+    //     WWWForm wwwForm = new WWWForm();
+    //     wwwForm.AddField("task_code", rVWUD.data.task_code);
+    //     using (UnityWebRequest www = UnityWebRequest.Post(VWQUERYURL, wwwForm))
+    //     {
+    //       www.downloadHandler = new DownloadHandlerBuffer();
+    //       yield return www.SendWebRequest();
+
+    //       if (www.result != UnityWebRequest.Result.Success)
+    //       {
+    //         Debug.Log($"[U2ZCM] {www.error}");
+    //         yield break;
+    //       }
+
+    //       Debug.Log($"[U2ZCM] {www.downloadHandler.text}");
+    //       rVWAD = JsonConvert.DeserializeObject<Respon_VWAvatarData>(www.downloadHandler.text);
+
+    //       if (rVWUD.code != 0)
+    //       {
+    //         Debug.Log($"[U2ZCM] Code Error");
+    //         OnVWAvatarFinished?.Invoke(null, false);
+    //         yield break;
+    //       }
+
+    //       switch (rVWAD.data.status)
+    //       {
+    //         default: break;
+    //         case 3:
+    //           queryCount = 0;
+    //           Debug.Log("[U2ZCM] 开始下载图片");
+    //           StartCoroutine(nameof(DownloadAvatarAction), rVWAD.data.avatar_url); // 下载图片
+    //           yield break;
+    //         case 4:
+    //           OnVWAvatarFinished?.Invoke(null, false);
+    //           break;
+    //       }
+
+    //       yield return new WaitForSeconds(5f);
+    //     }
+    //   }
+    // }
+
+
+
+    // [SerializeField] private Respon_VWAvatarData rVWAD = new Respon_VWAvatarData();
+
+    // [Serializable]
+    // public class Respon_VWAvatarData
+    // {
+    //   public int code;
+    //   public string message;
+    //   public Respon_VWAvatarDataData data;
+    // }
+
+    // [Serializable]
+    // public class Respon_VWAvatarDataData
+    // {
+    //   public string avatar_url;
+    //   public int status;
+    //   public string status_text;
+    // }
+
+    // // ==================================================
+    // // 获取图片
+
+    // private IEnumerator DownloadAvatarAction(string url)
+    // {
+    //   using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(url))
+    //   {
+    //     yield return www.SendWebRequest();
+    //     if (www.result != UnityWebRequest.Result.Success)
+    //     {
+    //       Debug.Log($"[U2ZCM] {www.error}");
+    //       yield break;
+    //     }
+
+    //     debug_peekQRCode = DownloadHandlerTexture.GetContent(www); // DEBUG
+    //     OnVWAvatarFinished?.Invoke(DownloadHandlerTexture.GetContent(www), true);
+    //   }
+    //   yield break;
+    // }
+
+    // // ==================================================
+    // // 上传图片并获取二维码地址
+
+    // private const string VWUPLOADURL = @"https://vw-v-space.studiocapsule.cn/api/device/finalUpload";
+
+    // public void UploadVWResult(Texture2D value) => StartCoroutine(nameof(UploadVWResultAction), value);
+    // private IEnumerator UploadVWResultAction(Texture2D t2dResult)
+    // {
+    //   WWWForm wwwForm = new WWWForm();
+    //   wwwForm.AddField("task_code", rVWUD.data.task_code);
+    //   wwwForm.AddBinaryData("file", t2dResult.EncodeToJPG(), "t2d.jpg", "image/jpeg");
+
+    //   using (UnityWebRequest www = UnityWebRequest.Post(VWUPLOADURL, wwwForm))
+    //   {
+    //     www.downloadHandler = new DownloadHandlerBuffer();
+    //     yield return www.SendWebRequest();
+
+    //     if (www.result != UnityWebRequest.Result.Success)
+    //     {
+    //       Debug.Log($"[U2ZCM] {www.error}");
+    //       yield break;
+    //     }
+
+    //     Debug.Log($"[U2ZCM] {www.downloadHandler.text}");
+
+    //     rVWRD = JsonConvert.DeserializeObject<Respon_VWResultData>(www.downloadHandler.text);
+
+    //     if (rVWRD.code != 0)
+    //     {
+    //       Debug.Log($"[U2ZCM] Code Error");
+    //       yield break;
+    //     }
+
+    //     DownloadQRCode(rVWRD.data.qr_url);
+    //   }
+    //   yield break;
+    // }
+
+
+
+    // [SerializeField] private Respon_VWResultData rVWRD = new Respon_VWResultData();
+
+    // [Serializable]
+    // public class Respon_VWResultData
+    // {
+    //   public int code;
+    //   public string message;
+    //   public Respon_VWResultDataData data;
+    // }
+    // [Serializable]
+    // public class Respon_VWResultDataData
+    // {
+    //   public string qr_url;
+    //   public string file_url;
+    // }
+
+    #endregion
+    // ==================================================
+    // ==================================================
+    // ==================================================
+    #region 2025.04 NikeADT
+
+    // public static UnityAction<UserInfo> OnUserInfoDownloaded;
+
+    // private const string USERINFOREQUESTURL = @"https://nike-adt.studiocapsule.cn/api/device/scanQr";
+
+    // /// <summary>
+    // /// 获取用户信息
+    // /// </summary>
+    // /// <param name="url"></param>
+    // public void GetUserInfo(string url) => StartCoroutine(nameof(GetUserInfoAction), url);
+    // private IEnumerator GetUserInfoAction(string url)
+    // {
+    //   WWWForm wwwForm = new WWWForm();
+    //   wwwForm.AddField("qr_content", url);
+
+    //   using (UnityWebRequest www = UnityWebRequest.Post(USERINFOREQUESTURL, wwwForm))
+    //   {
+    //     www.downloadHandler = new DownloadHandlerBuffer();
+    //     yield return www.SendWebRequest();
+
+    //     if (www.result != UnityWebRequest.Result.Success)
+    //     {
+    //       Debug.Log($"[U2ZCM] {www.error}");
+    //       yield break;
+    //     }
+
+    //     Debug.Log($"[U2ZCM] {www.downloadHandler.text}");
+    //     try
+    //     {
+    //       uird = JsonConvert.DeserializeObject<Respon_UserInfoData>(www.downloadHandler.text);
+    //     }
+    //     catch (Exception)
+    //     {
+    //       Debug.Log($"[U2ZCM] 解析错误");
+    //       yield break;
+    //     }
+
+    //     if (uird.code != 0)
+    //     {
+    //       if (OnUserInfoDownloaded != null)
+    //       {
+    //         OnUserInfoDownloaded(null);
+    //       }
+    //       yield break;
+    //     }
+
+    //     if (OnUserInfoDownloaded != null)
+    //     {
+    //       UserInfo ui = new UserInfo();
+    //       ui.name = uird.data.name;
+    //       ui.code = uird.data.code;
+    //       ui.save_car = uird.data.save_car;
+    //       ui.can_play = uird.data.can_play;
+    //       OnUserInfoDownloaded(ui);
+    //     }
+    //   }
+    //   yield break;
+    // }
+
+    // private Respon_UserInfoData uird = new Respon_UserInfoData();
+
+    // [Serializable]
+    // public class Respon_UserInfoData
+    // {
+    //   public int code;
+    //   public string message;
+    //   public UserInfo data;
+    // }
+
+    // [Serializable]
+    // public class UserInfo
+    // {
+    //   public string name;
+    //   public string code;
+    //   public string save_car;
+    //   public string can_play;
+    // }
+
+    // // ==================================================
+
+    // private const string USERIMAGEUPLOADURL = @"https://nike-adt.studiocapsule.cn/api/device/upload";
+
+    // public static UnityAction<string> OnUserImageUploaded;
+
+    // [SerializeField] private Upload_UserImageData uUID;
+    // public void UpdateUserImageData(string user_code, Texture2D t2dPhoto)
+    // {
+    //   uUID = new Upload_UserImageData();
+    //   uUID.user_code = user_code;
+
+    //   byte[] fileBytes = t2dPhoto.EncodeToPNG();
+    //   uUID.file = fileBytes;
+    //   return;
+    // }
+
+    // public void UploadUserImage() => StartCoroutine(nameof(UploadUserImageAction));
+    // private IEnumerator UploadUserImageAction()
+    // {
+    //   WWWForm wwwForm = new WWWForm();
+    //   wwwForm.AddField("user_code", uUID.user_code);
+    //   wwwForm.AddBinaryData("file", uUID.file);
+
+    //   using (UnityWebRequest www = UnityWebRequest.Post(USERIMAGEUPLOADURL, wwwForm))
+    //   {
+    //     www.downloadHandler = new DownloadHandlerBuffer();
+    //     yield return www.SendWebRequest();
+
+    //     if (www.result != UnityWebRequest.Result.Success)
+    //     {
+    //       Debug.Log($"[U2ZCM] {www.error}");
+    //       yield break;
+    //     }
+
+    //     Debug.Log($"[U2ZCM] {www.downloadHandler.text}");
+    //     rUID = JsonConvert.DeserializeObject<Respon_UserImageData>(www.downloadHandler.text);
+
+    //     if (rUID.code != 0)
+    //     {
+    //       Debug.Log($"[U2ZCM] Code Error");
+    //       yield break;
+    //     }
+
+    //     DownloadQRCode(rUID.data.qr_url); // 搞图
+    //   }
+    //   yield break;
+    // }
+
+    // public class Upload_UserImageData
+    // {
+    //   public string user_code;
+    //   public byte[] file;
+    // }
+
+    // private Respon_UserImageData rUID = new Respon_UserImageData();
+
+    // [Serializable]
+    // public class Respon_UserImageData
+    // {
+    //   public int code;
+    //   public string message;
+    //   public Respon_UserImageDataData data;
+    // }
+
+    // [Serializable]
+    // public class Respon_UserImageDataData
+    // {
+    //   public string qr_url;
+    // }
+
+    #endregion
+    // ==================================================
+    // ==================================================
+    #region 获取QR图片
+
+    // public static UnityAction<Texture2D> OnQRImageDownloaded;
+
+    // [SerializeField] private Texture2D debug_peekQRCode;
+
+    // public void DownloadQRCode(string url) => StartCoroutine(nameof(DownloadQRCodeAction), url);
+    // private IEnumerator DownloadQRCodeAction(string url)
+    // {
+    //   using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(url))
+    //   {
+    //     yield return www.SendWebRequest();
+    //     if (www.result != UnityWebRequest.Result.Success)
+    //     {
+    //       Debug.Log($"[U2ZCM] {www.error}");
+    //       yield break;
+    //     }
+
+    //     debug_peekQRCode = DownloadHandlerTexture.GetContent(www); // DEBUG
+    //     OnQRImageDownloaded?.Invoke(DownloadHandlerTexture.GetContent(www));
+    //   }
+    //   yield break;
+    // }
+
+    #endregion
+  }
+}

+ 11 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Networking/Upload/Upload2ZCManager.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 30c263742f2857d4f82494a1c2866563
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Other.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: f02478cef37928e4684bd7ff0823c5a3
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Other/QR.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 50d9792fb0fe2e9498532a19c0ac6003
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Other/QR/Plugins.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: f2ba1978932bc5540aed173e4880cae0
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 0 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Plugins/zxing.unity.dll → ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Other/QR/Plugins/zxing.unity.dll


+ 0 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Plugins/zxing.unity.dll.meta → ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Other/QR/Plugins/zxing.unity.dll.meta


+ 8 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Other/QR/Scripts.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: d5753fabbee09c249862be7e9b967532
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 3 - 2
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Other/QRCodeMaster.cs → ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Other/QR/Scripts/QRCodeMaster.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using System.Collections;
@@ -11,7 +11,7 @@ using ZXing;
 using ZXing.Common;
 using ZXing.QrCode;
 
-namespace ToneTuneToolkit.Other
+namespace ToneTuneToolkit.Other.QR
 {
   /// <summary>
   /// 扫码助手
@@ -101,6 +101,7 @@ namespace ToneTuneToolkit.Other
       qrTexture.SetPixels32(colors);
       qrTexture.Apply();
 
+      Debug.Log("[QRM] QR Code generate successd.");
       return qrTexture;
     }
   }

+ 0 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Other/QRCodeMaster.cs.meta → ToneTuneToolkit/Assets/ToneTuneToolkit/Modules/Other/QR/Scripts/QRCodeMaster.cs.meta


+ 214 - 156
ToneTuneToolkit/Assets/ToneTuneToolkit/README.md

@@ -1,111 +1,145 @@
 <font face="Source Han Sans TC" size=2 color=#FFFFFF>
 
 #### <center><font size=2>Make everything f<font color="#FF0000">or</font>king simple.</font></center>
-#### <center><font size=2>2025/04/18</font></center>
-# <center><font color="#54FF9F" size=6>**Tone Tune Toolkit v1.5.1**</font></center>
-## ToneTuneToolkit是什么?
-一个致力于帮助Unity六边形战士减轻开发负担的项目。</br>
-<s>但更多的时候是在帮助互动工程师偷懒。</s></br>
-
-完成至少<strong>[1]</strong>个有些奇怪却十分好用的工具包:</br>
-(√) 显现存在于Unity/C#中却不为人知的野路子</br>
-(√) 添加需求简单但就是不想亲自编写的小功能</br>
-<s>(×) 解决古怪且迷惑的开发需求</s></br>
-
-<kbd>Ctrl</kbd> + <kbd>C</kbd></br>
-<kbd>Ctrl</kbd> + <kbd>V</kbd></br>
-<s>哈!逮到你了!</s></br>
-
-</br>
-
-# <center>*INTRODUCTION & LOG*</center>
-1. 请留意,“MirzkisD1Ex0”的“ToneTune Toolkit”基于**GPL3.0**(GNU General Public License v3.0)协议所开发。(对,就是那个传染性极强的协议。)
-2. 工具包存在“**Assets/ToneTuneToolkit**”文件夹及“**Assets/StreamingAssets/ToneTuneToolkit**”文件夹,两部分内容。
-3. 当某一模块中包含“**Handler**”助手类时,通常添加助手类至对象即可自动为其添加依赖。避免发生错误的组装。例如“**UDP**”模块以及“**Verification**”模块。
-4. 添加了思源黑体简中OTF格式全套。
-5. 2021/09/06 添加了两张简易场景地板贴图。
-6. 2021/09/06 添加了一些演示用场景。
-7. 2021/09/06 添加了三个可怕的工具,在“**Assets/StreamingAssets**”中。
-8. 2021/09/22 路径检查现在有更为醒目的提示。
-9. 2021/09/23 添加了“Funny”命名空间,里面会存一些然并卵的鬼代码,比如冒泡排序,甚至还有冒泡排序的浮点型重载。添加了UDP响应器。
-10. 2021/09/23 纠正了“PathChecker”中对文件夹路径检查的错误,更新了UDP和WOL非懒人方法的使用说明,移动了UDP消息接受体的位置。
-11. 2021/09/24 为“LedHandler”添加了一个工具函数,可以根据输入的[-1f~0f~1f]生成[黄色~白色~蓝色]的Color。
-12. 2021/10/11 添加了写入json的方法在“TextLoad”中。
-13. 2021/11/10 添加了“CameraSimpleMove”,一个经典的场景漫游脚本,可以通过WSDA空格和LeftShift控制相机移动,按住鼠标右键以移动视角。
-14. 2021/11/29 添加了AssetBundle包工具。
-15. 2022/01/22 添加了“CorrectLookAtCamera”,一个使物体永远正对相机的脚本,改进了LookAt。
-16. 2023/05/17 添加了“ObjectDragRotate”,拖动物体使其跟随鼠标旋转。
-17. 2023/07/20 工具包结构巨幅整理。
-18. 2023/07/21 添加了“FTPMaster”,从已架设FTP服务的服务器中下载文件,为“FileNameCapturer”添加了一种返回List的方法。
-19. 2023/09/07 添加了“ScreenshotMaster”,通过UIRectTransform获取截图范围并进行就截图的截图大师。
-20. 2023/10/10 添加了“UDPCommunicatorLite”,轻量版的UDP通讯工具,贼省事儿。
-21. 2023/10/26 于工程同级目录下“Materials”文件夹中添加了“KinectV2”相关工具。添加了“VideoMaster”,具有播放视频、播放视频第一帧、视频播放结束回调功能。
-22. 2023/11/06 UI模块下的截图工具与Media模块下的截图工具功能合并,新增全角度截图工具“FullAngleScreenshotTool”。
-23. 2023/12/04 新增“SHADERS”模块,新增了一个可以将UGUI去色的Shader,需要额外创建材质球,详见“Examples/022_UGUIGray”。
-24. 2023/12/28 分离“TextLoader”的json读写功能至“Data”分类下的“JsonManager”。
-25. 2024/06/03 添加了“TextureProcessor”,读/写/旋转/缩放Texture。
-26. 2024/06/18 添加了“LongTimeNoOperationDetector”,用于检测用户长时间无操作。
-27. 2024/07/18 添加了“UDPCommunicatorServer”,单端口非一次性play,用于作为server大量接收数据。
-28. 2024/10/11 更新了“ObjectDragRotate”,增加了旋转角度的限制,增加了一个角度校正的方法。
-29. 2024/12/18 添加了“RenameFolders”,一个用于在编辑器内批量化改变文件夹名的工具,直接更新选中的文件夹的文件夹名为新文件夹名或更新所有匹配原文件夹名的文件夹的文件夹名为新文件夹名,嗯。
-30. 2025/01/03 添加了“DataProcessor”,一个用于二级加工数据的工具,开新坑了,家人们。
-31. 2025/01/07 添加了“UpdateCopyrights”,一个用于批量添加版权信息的工具,在“Project”面板中选择“.cs”文件后可正常执行。
-32. 2025/01/10 添加了“ImageLoader”,用于运行时在弹窗内选择并加载图片,添加了第三方资源文件夹。
-33. 2025/01/13 添加了“JsonUploadManager”,用于上传json的工具。
-34. 2025/02/19 “QRCodeMaster”现在支持透明底二维码生成。
-35. 2025/03/27 “FileCapturer”被重制,拥有更高级的功能。
-36. 2025/04/18 “UI”类目下新增3个功能,滚动视图助手,序列帧图片播放助手,序列帧播放管理器。
-
-</br>
-
-# <center>*SCRIPTS*</center>
-### -> ToneTuneToolkit.Common/
+#### <center><font size=2>2025/10/14</font></center>
+# <center><font color="#54FF9F" size=6>**Tone Tune Toolkit v1.5.2**</font></center>
+
+
+
+<font size=5><strong>ToneTuneToolkit是什么?</strong></font><br>
+一个致力于帮助Unity六边形战士减轻开发负担的项目。<br>
+<s>但更多的时候是在帮助互动工程师偷懒。</s><br>
+
+完成至少<strong>[1]</strong>个有些奇怪却十分好用的工具包:<br>
+(√) 显现存在于Unity/C#中却不为人知的野路子<br>
+(√) 添加需求简单但就是不想亲自编写的小功能<br>
+<s>(×) 解决古怪且迷惑的开发需求</s><br>
+
+<kbd>Ctrl</kbd> + <kbd>C</kbd><br>
+<kbd>Ctrl</kbd> + <kbd>V</kbd><br>
+<s>哈!逮到你了!</s><br>
+
+<font size=5><strong>Directory - 文档目录</strong></font><br>
+[INTRODUCTION  介绍](#INTRODUCTION)<br>
+[LOG       &ensp;日志](#LOG)<br>
+[MODULES     &ensp;模组](#MODULES)<br>
+[SCRIPTS     &ensp;脚本](#SCRIPTS)<br>
+[EXTRA      &ensp;额外内容](#EXTRA)<br>
+[SHADERS     着色器](#SHADERS)<br>
+[TEXTURES    &ensp;贴图](#TEXTURES)<br>
+[FONTS      字体](#FONTS)<br>
+[DEMOS      示例](#DEMOS)<br>
+[STORAGE     仓库](#STORAGE)<br>
+[THIRDPARTY   &ensp;第三方](#THIRDPARTY)<br>
+[TUTORIALS    教程](#TUTORIALS)<br>
+[CONTACT     联系](#CONTACT)<br>
+
+
+
+## <center><a id="INTRODUCTION"></a>*INTRODUCTION*</center>
+- 请留意,“MirzkisD1Ex0”的“ToneTune Toolkit”基于**GPL3.0**(GNU General Public License v3.0)协议所开发。(对,就是那个传染性极强的协议。)
+- 工具包存在“**Assets/ToneTuneToolkit**”文件夹及“**Assets/StreamingAssets/ToneTuneToolkit**”文件夹,两部分内容。
+- 当某一模块中包含“**Handler**”助手类时,通常添加助手类至对象即可自动为其添加依赖。避免发生错误的组装。例如“**UDP**”模块以及“**Verification**”模块。
+- 添加了思源黑体简中OTF格式全套。
+
+
+
+## <center><a id="LOG"></a>*LOG*</center>
+0. 2021/09/06 添加了两张简易场景地板贴图。
+0. 2021/09/06 添加了一些演示用场景。
+0. 2021/09/06 添加了三个可怕的工具,在“**Assets/StreamingAssets**”中。
+0. 2021/09/22 路径检查现在有更为醒目的提示。
+0. 2021/09/23 添加了“Funny”命名空间,里面会存一些然并卵的鬼代码,比如冒泡排序,甚至还有冒泡排序的浮点型重载。添加了UDP响应器。
+0. 2021/09/23 纠正了“PathChecker”中对文件夹路径检查的错误,更新了UDP和WOL非懒人方法的使用说明,移动了UDP消息接受体的位置。
+0. 2021/09/24 为“LedHandler”添加了一个工具函数,可以根据输入的[-1f~0f~1f]生成[黄色~白色~蓝色]的Color。
+0. 2021/10/11 添加了写入json的方法在“TextLoad”中。
+0. 2021/11/10 添加了“CameraSimpleMove”,一个经典的场景漫游脚本,可以通过WSDA空格和LeftShift控制相机移动,按住鼠标右键以移动视角。
+0. 2021/11/29 添加了AssetBundle包工具。
+0. 2022/01/22 添加了“CorrectLookAtCamera”,一个使物体永远正对相机的脚本,改进了LookAt。
+0. 2023/05/17 添加了“ObjectDragRotate”,拖动物体使其跟随鼠标旋转。
+0. 2023/07/20 工具包结构巨幅整理。
+0. 2023/07/21 添加了“FTPMaster”,从已架设FTP服务的服务器中下载文件,为“FileNameCapturer”添加了一种返回List的方法。
+0. 2023/09/07 添加了“ScreenshotMaster”,通过UIRectTransform获取截图范围并进行就截图的截图大师。
+0. 2023/10/10 添加了“UDPCommunicatorLite”,轻量版的UDP通讯工具,贼省事儿。
+0. 2023/10/26 于工程同级目录下“Materials”文件夹中添加了“KinectV2”相关工具。添加了“VideoMaster”,具有播放视频、播放视频第一帧、视频播放结束回调功能。
+0. 2023/11/06 UI模块下的截图工具与Media模块下的截图工具功能合并,新增全角度截图工具“FullAngleScreenshotTool”。
+0. 2023/12/04 新增“SHADERS”模块,新增了一个可以将UGUI去色的Shader,需要额外创建材质球,详见“Examples/022_UGUIGray”。
+0. 2023/12/28 分离“TextLoader”的json读写功能至“Data”分类下的“JsonManager”。
+0. 2024/06/03 添加了“TextureProcessor”,读/写/旋转/缩放Texture。
+0. 2024/06/18 添加了“LongTimeNoOperationDetector”,用于检测用户长时间无操作。
+0. 2024/07/18 添加了“UDPCommunicatorServer”,单端口非一次性play,用于作为server大量接收数据。
+0. 2024/10/11 更新了“ObjectDragRotate”,增加了旋转角度的限制,增加了一个角度校正的方法。
+0. 2024/12/18 添加了“RenameFolders”,一个用于在编辑器内批量化改变文件夹名的工具,直接更新选中的文件夹的文件夹名为新文件夹名或更新所有匹配原文件夹名的文件夹的文件夹名为新文件夹名,嗯。
+0. 2025/01/03 添加了“DataProcessor”,一个用于二级加工数据的工具,开新坑了,家人们。
+0. 2025/01/07 添加了“UpdateCopyrights”,一个用于批量添加版权信息的工具,在“Project”面板中选择“.cs”文件后可正常执行。
+0. 2025/01/10 添加了“ImageLoader”,用于运行时在弹窗内选择并加载图片,添加了第三方资源文件夹。
+0. 2025/01/13 添加了“JsonUploadManager”,用于上传json的工具。
+0. 2025/02/19 “QRCodeMaster”现在支持透明底二维码生成。
+0. 2025/03/27 “FileCapturer”被重制,拥有更高级的功能。
+0. 2025/04/18 “UI”类目下新增3个功能,滚动视图助手,序列帧图片播放助手,序列帧播放管理器。
+0. 2025/08/04 “IO”类目下,新增“NewFileAlerter”,用于“定期检查指定文件夹下是否出现新文件并返回该文件路径”。
+0. 2025/10/14 重新分类一些独立、综合的小功能,例如目前位于目录下的“Module/IO/Printer”,其包含了打印机控制相关的必须组件、脚本,而非仅有“Script”。
+
+
+
+## <center><a id="MODULES"></a><font color="#44ff00">*MODULES*</font></center>
+### ToneTuneToolkit.IO.Printer/
+* 打印机模组
+
+### ToneTuneToolkit.Other.QR/
+* QR模组
+
+
+
+## <center><a id="SCRIPTS"></a><font color="#FF0000">*SCRIPTS*</font></center>
+### ToneTuneToolkit.Common/
 * EventListener.cs      // 数值监听器 // 提供了一个泛型事件
 * PathChecker.cs        // 静态 // 文件/文件夹检查 // 如果不存在则创建空的
 * SingletonMaster.cs    // 单例大师
 * ToolkitManager.cs     // 管理类 // 存放路径 // 多数功能的依赖
 * TTTDebug.cs           // 静态 // TTT工具箱专属Debug.Log
 
-### -> ToneTuneToolkit.Data/
-* DataConverter.cs      // 静态 // 数据转换 // 字符串与二进制之间转换 // 字符串与json之间转换
-* DataProcessor.cs      // 数据处理
-* ImageLoader.cs        // 图片选择和加载
-* JsonManager.cs        // newtonsoftjson管理器
-* LitJsonManager.cs     // litjson管理器
+### ToneTuneToolkit.Data/
+* DataConverter.cs        // 静态 // 数据转换 // 字符串与二进制之间转换 // 字符串与json之间转换
+* DataProcessor.cs        // 数据处理
+* ImageLoader.cs          // 图片选择和加载
+* JsonManager.cs          // newtonsoftjson管理器
+* LitJsonManager.cs       // litjson管理器
 * SensitiveWordUtility.cs // 关键词加载
-* TextLoader.cs         // 静态 // 文字加载 // 可以读取txt及json
-* TimestampCapturer.cs  // 静态 // 获取时间戳 // 本地获取静态方法 // 网络获取需单例
+* TextLoader.cs           // 静态 // 文字加载 // 可以读取txt及json
+* TimestampCapturer.cs    // 静态 // 获取时间戳 // 本地获取静态方法 // 网络获取需单例
 
-### -> ToneTuneToolkit.Editor/
+### ToneTuneToolkit.Editor/
 * CreateAssetBundles.cs // AB包创建工具
 * RenameFolders.cs      // 批量化重命名文件夹工具
 * UpdateCopyrights.cs   // 更新版权工具
 
-### -> ToneTuneToolkit.Funny/
+### ToneTuneToolkit.Funny/
 * BubbleSort.cs         // 静态 // 冒泡排序
 
-### -> ToneTuneToolkit.IO/
+### ToneTuneToolkit.IO/
 * FileCapturer.cs       // 静态 // 获取特定文件夹下特定格式的文件名
 * FTPMaster.cs          // FTP文件下载(暂无上传)器
+* NewFileAlerter.cs     // 检测指定文件夹下是否有新文件传入
 
-### -> ToneTuneToolkit.Media/
+### ToneTuneToolkit.Media/
 * ScreenshotMaster.cs         // 透明通道截图工具
 * FullAngleScreenshotTool.cs  // 全角度截图工具
 * TextureProcessor.cs         // 图片处理工具
 
-### -> ToneTuneToolkit.Mobile/
-* ObjectRotateAndScale.cs   // 物体Android平台中的单指旋转及双指缩放
+### ToneTuneToolkit.Mobile/
+* ObjectRotateAndScale.cs     // 物体Android平台中的单指旋转及双指缩放
 
-### -> ToneTuneToolkit.MultimediaExhibitionHall.LED/
+### ToneTuneToolkit.MultimediaExhibitionHall.LED/
 * LEDCommandCenter.cs   // LED命令中心
 * LEDCommandHub.cs      // 灯盒指令集
 * LEDHandler.cs         // LED助手
 * LEDNuclearShow.cs     // 灯带压力测试 // DEBUG
 
-### -> ToneTuneToolkit.Networking/
+### ToneTuneToolkit.Networking/
 * JsonUploadManager.cs // Json上传
 
-### -> ToneTuneToolkit.Object/
+### ToneTuneToolkit.Object/
 * CorrectLookAtCamera.cs        // 使物体正对相机
 * NeonLight.cs                  // 随机霓虹灯
 * ObjectDragMove.cs             // 物体拖动移动
@@ -114,178 +148,202 @@
 * ObjectSearcher.cs             // 多种方式寻找目标
 * TraverseObejctChangeColor.cs  // 改变对象及所有子对象的颜色
 
-### -> ToneTuneToolkit.Other/
-* AsyncLoadingWithProcessBar.cs // 加载场景进度条
-* CMDLauncher.cs                // CMD命令行
-* KeyPressSimulator.cs          // 物理键盘按键模拟
-* QRCodeMaster.cs               // 二维码加载器
-* LongTimeNoOperationDetector.cs        // 长时间无操作检测
+### ToneTuneToolkit.Other/
+* AsyncLoadingWithProcessBar.cs   // 加载场景进度条
+* CMDLauncher.cs                  // CMD命令行
+* KeyPressSimulator.cs            // 物理键盘按键模拟
+* LongTimeNoOperationDetector.cs  // 长时间无操作检测
 
-### -> ToneTuneToolkit.UDP/
+### ToneTuneToolkit.UDP/
 * UDPCommunicator.cs        // UDP通讯器 // 已残
 * UDPCommunicatorLite.cs    // UDP通讯器客户端轻量版
 * UDPCommunicatorServer.cs  // UDP通讯器服务端
 * UDPHandler.cs             // UDP助手
 * UDPResponder.cs           // UDP响应器
 
-### -> ToneTuneToolkit.UI/
-* Parallax.cs         // 多层次视差
+### ToneTuneToolkit.UI/
+* Parallax.cs           // 多层次视差
 * ScrollViewHandler.cs  // 滚动视图定位元素
-* TextFlick.cs        // 文字通过透明度闪烁
-* UICurved.cs         // UI弯曲
+* TextFlick.cs          // 文字通过透明度闪烁
+* UICurved.cs           // UI弯曲
 
-### -> ToneTuneToolkit.Verification/
+### ToneTuneToolkit.Verification/
 * AntiVerifier.cs     // 反向验证器 // 二进制
 * Verifier.cs         // 验证器
 * VerifierHandler.cs  // 验证系统助手
 
-### -> ToneTuneToolkit.Video/
+### ToneTuneToolkit.Video/
 * VideoMaster.cs      // 视频大师
 
-### -> ToneTuneToolkit.View/
+### ToneTuneToolkit.View/
 * CameraFocusObject.cs  // 鼠标拖动控制相机环绕注视对象
 * CameraLookAround.cs   // 鼠标拖动控制相机环视 // 可用于全景
 * CameraSimpleMove.cs   // 经典场景漫游
 * CameraZoom.cs         // 相机POV多层级缩放 // 开镜?
 
-### -> ToneTuneToolkit.WOL/
+### ToneTuneToolkit.WOL/
 * WakeOnLan.cs          // 局域网唤醒器
 * WakeOnLanHandler.cs   // 局域网唤醒助手
 
-</br>
 
-# <center>*Extra*</center>
+
+## <center><a id="EXTRA"></a>*EXTRA*</center>
 下列文件/功能位于与工程同级的“Materials”文件夹下
-### -> 3D/
+### 2D/
+* // Tile贴图与尺寸保持1:1的设置方式
+
+### 3D/
 * // 创建一个物理引力点
 
-### -> AzureKinect/
+### Alpha Video Mask/
+* // 透明视频遮罩
+
+### AzureKinect/
 * AzureKinectDriver.cs // AzureKinect驱动模块
 
-### -> Backend & Upload/
+### Backend & Upload/
 * // 后端上传模块
 
-### -> CamFi2/
+### CamFi2/
 * // CamFi2驱动模块
 
-### -> KeyboardMapping/
+### DG/Tools
+* CanvasGroupMaster.cs // 透明度管理
+* UIStageManager.cs // UI转阶段管理
+
+### Game/
+### IOS对策/
+### Keyboard/
+
+### KeyboardMapping/
 * // 键盘错位映射模块
 
-### -> KinectV2/
-* // KinectV2Driver.cs // KinectV2驱动模块
+### KinectV2/
+* KinectV2Driver.cs // KinectV2驱动模块
 
-### -> MQTT/
+### LeapMotion/
+* LeapMotionManager.cs // LP管理模块
+
+### MediaPipe/
+
+### MQTT/
 * // MQTT驱动模块
 
-### -> OpenCV/
+### OpenCV/
 * // 面部识别模块
 
-### -> OSC/
+### OSC/
 * // 收发模块
 
-### -> RemoveBG & BaiduBodySegment/
+### RemoveBG & BaiduBodySegment/
 * // 人像分割模块
 
-### -> RemoveTrial/
+### RemoveTrial/
 * // 移除试用版标记
 
-### -> ScrollView/
+### ScrollView/
 * ScrollViewHandler.cs // 滚动视图驱动模块
 
-### -> SequenceFrame/
-* // 序列帧播放控制模块
+### SerialPortUtilityPro/
+* // 串口收发模块
 
-### -> SerialPortUtilityPro/
-* // 收发模块
+### SocketIO/
+* SocketIOManager.cs // SocketIO通讯模块
+
+### TCP/
+* // TCP传图传文字模块
 
-### -> SkipLogo/
+### SkipLogo/
 * // 跳过开屏Logo功能
 
-### -> WebGL/
+### UI/
+* ClickListener.cs // UI交互检测
+
+### WebGL/
 * // 背景透明化功能
 
-### -> 后置相机拍摄/
-* // 拍摄功能
+### 打包后分辨率设置/
+### 后置相机拍摄/
+### 扫码枪/
+### 图片选择和加载/
 
-</br>
 
-# <center>*SHADERS*</center>
-### -> UGUI转灰色
 
+## <center><a id="SHADERS"></a>*SHADERS*</center>
+### UGUI转灰色
 * GreyscaleShader(Sprites/GreyscaleShader)
 
-</br>
 
-# <center>*TEXTURES*</center>
-### -> 512x512地板贴图
+
+## <center><a id="TEXTURES"></a>*TEXTURES*</center>
+### 512x512地板贴图
 * grayfloor
 * royalbluefloor
 
-</br>
-
-# <center>*FONTS (Removed)*</center>
-### // -> 思源黑体简体中文
-* // SourceHanSansSC-Bold
-* // SourceHanSansSC-ExtraLight
-* // SourceHanSansSC-Heavy
-* // SourceHanSansSC-Light
-* // SourceHanSansSC-Medium
-* // SourceHanSansSC-Normal
-* // SourceHanSansSC-Regular
-* 因体积原因已从插件中移除
+
+
+## <center><a id="FONTS"></a>*FONTS*</center>
+### // 思源黑体简体中文
+* SourceHanSansSC-Bold
+* SourceHanSansSC-ExtraLight
+* SourceHanSansSC-Heavy
+* SourceHanSansSC-Light
+* SourceHanSansSC-Medium
+* SourceHanSansSC-Normal
+* SourceHanSansSC-Regular
 * 已移至ToneTuneToolkit工程目录“<strong>Assets/Fonts</strong>”中
 
-</br>
 
-# <center>*DEMOS*</center>
-### -> 演示场景
+
+## <center><a id="DEMOS"></a>*DEMOS*</center>
+### 演示场景
 * LED Sample      // LED灯控示例
 * Panorama Sample // 全景示例
 * Parallax Sample // 视差示例
 * WOL Sample      // 局域网唤醒示例
 * ……
 
-</br>
 
-# <center>*WAREHOUSE*</center>
-### -> 用于储存仅在Demo中出现且与核心功能无关的资源
+
+## <center><a id="STORAGE"></a>*STORAGE*</center>
+### 用于储存仅在Demo中出现且与核心功能无关的资源
 * Materials
 * Textures
 
-</br>
 
-# <center>*THIRDPARTY*</center>
-### -> 第三方脚本或资源
+
+## <center><a id="THIRDPARTY"></a>*THIRDPARTY*</center>
+### 第三方脚本或资源
 * StandaloneFileBrowser // 运行时弹出窗口
 
 
-</br>
 
-# <center>*EXAMPLES*</center>
-### -> 一些教程
+
+## <center><a id="TUTORIALS"></a>*TUTORIALS*</center>
+### 一些教程
 * 该功能依赖ToneTuneToolkit
-* 场景文件、教程辅助用脚本文件位于ToneTuneToolkit工程目录“<strong>Assets/Examples/</strong>”中
+* 场景文件、教程辅助用脚本文件位于ToneTuneToolkit工程目录“<strong>Assets/Tutorials/</strong>”中
 * 博客内容保存在位于ToneTuneToolkit工程目录“<strong>Assets/PDFs</strong>”中
 
-</br>
 
-# <center>*CONTACT*</center>
-### -> Developer
-* **[团队代言人博客]** *随缘更新</br>
+
+## <center><a id="CONTACT"></a>*CONTACT*</center>
+### Developer
+* **[团队代言人博客]** *随缘更新<br>
   **[https://www.cnblogs.com/mirzkisd1ex0/](https://www.cnblogs.com/mirzkisd1ex0/ "记得常来光顾")**
-  </br>
+  <br>
 
-* **[开发者邮箱]**</br>
+* **[开发者邮箱]**<br>
   **[mirzkisd1ex0@outlook.com](https://outlook.live.com/ "欢迎来信联系")**
-  </br>
+  <br>
 
-* **[开发者微信]**</br>
+* **[开发者微信]**<br>
   **[qq1005410781](https://weixin.qq.com/ "来啊交流啊")**
-  </br>
+  <br>
 
-* **[开发者企鹅]**</br>
+* **[开发者企鹅]**<br>
   **[1005410781](https://im.qq.com/ "来啊交流啊")**
-  </br>
+  <br>
 
 ![MirzkisD1Ex0](Materials/profile.jpg)
 

+ 1 - 1
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Common/EventListener.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 namespace ToneTuneToolkit.Common

+ 1 - 1
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Common/PathChecker.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using System.IO;

+ 1 - 1
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Common/SingletonMaster.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using System.Collections;

+ 1 - 1
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Common/TTTDebug.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using UnityEngine;

+ 1 - 1
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Common/ToolkitManager.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using UnityEngine;

+ 13 - 1
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Data/DataConverter.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using System;
@@ -9,6 +9,7 @@ using System.Text.RegularExpressions;
 using System.Collections.Generic;
 using Newtonsoft.Json;
 using UnityEngine;
+using System.Linq;
 
 namespace ToneTuneToolkit.Data
 {
@@ -49,6 +50,17 @@ namespace ToneTuneToolkit.Data
       return Encoding.Default.GetString(data, 0, data.Length);
     }
 
+    /// <summary>
+    /// 字符串转十六进制
+    /// </summary>
+    /// <param name="value">数据</param>
+    public static byte[] String2Hex(string value)
+    {
+      string[] hexStrings = value.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); // 移除空格并按空格分割字符串
+      byte[] bytes = hexStrings.Select(s => Convert.ToByte(s, 16)).ToArray(); // 将每个十六进制字符串转换为byte
+      return bytes;
+    }
+
     /// <summary>
     /// 时间戳转为C#格式时间
     /// </summary>

+ 1 - 1
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Data/DataProcessor.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using UnityEngine;

+ 6 - 1
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Data/ImageLoader.cs

@@ -1,3 +1,8 @@
+/// <summary>
+/// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
+/// Code Version 1.5.2
+/// </summary>
+
 using UnityEngine;
 using NativeFileBrowser;
 using System.Collections.Generic;
@@ -54,4 +59,4 @@ namespace ToneTuneToolkit.Data
       return texture2D;
     }
   }
-}
+}

+ 1 - 1
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Data/JsonManager.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using System.Collections;

+ 1 - 1
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Data/LitJsonManager.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using System.Collections;

+ 2 - 2
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Data/SensitiveWordUtility.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using System.Collections;
@@ -188,4 +188,4 @@ namespace ToneTuneToolkit.Data
       return !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) && (ic < 0x2E80 || ic > 0x9FFF);
     }
   }
-}
+}

+ 1 - 1
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Data/TextLoader.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using System.IO;

+ 1 - 1
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Data/TimestampCapturer.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using System.Collections;

+ 1 - 1
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Editor/CreateAssetBundles.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using UnityEditor;

+ 1 - 1
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Editor/EditorStorage.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 namespace ToneTuneToolkit.Editor

+ 1 - 1
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Editor/RenameFolders.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using System.IO;

+ 8 - 9
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Editor/UpdateCopyrights.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using System.Collections.Generic;
@@ -16,7 +16,7 @@ namespace ToneTuneToolkit.Editor
   {
     private string author = "MirzkisD1Ex0";
     private string year = "2025";
-    private string codeVersion = "1.4.20";
+    private string codeVersion = "1.5.2";
 
     private string displayString = "";
     private Vector2 displayStringScrollPosition = Vector2.zero;
@@ -62,7 +62,7 @@ namespace ToneTuneToolkit.Editor
 
       GUILayout.Space(EditorStorage.GUI.Space);
 
-      if (GUILayout.Button("Add Copyright Info to Above File(s)"))
+      if (GUILayout.Button("Add or Update Copyright Info to Above File(s)"))
       {
         ChangeContent();
       }
@@ -124,12 +124,9 @@ namespace ToneTuneToolkit.Editor
     /// </summary>
     private void ChangeContent()
     {
-      if (scriptFilePaths.Count <= 0)
-      {
-        return;
-      }
+      if (scriptFilePaths.Count <= 0) { return; }
 
-      Debug.Log(scriptFilePaths.Count);
+      // Debug.Log(scriptFilePaths.Count);
       List<string> fileContents = new List<string>();
 
       foreach (string filePath in scriptFilePaths)
@@ -172,7 +169,9 @@ namespace ToneTuneToolkit.Editor
         fileContents.Insert(1, $"/// Copyright (c) {year} {author} All rights reserved.");
         fileContents.Insert(2, $"/// Code Version {codeVersion}");
         fileContents.Insert(3, $"/// </summary>");
-        if (fileContents[4] != null)
+
+        // 加空行
+        if (fileContents[4] != "")
         {
           fileContents.Insert(4, $"");
         }

+ 1 - 1
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Funny/BubbleSort.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 namespace ToneTuneToolkit.Funny

+ 1 - 1
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/IO/FTPMaster.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using UnityEngine;

+ 1 - 1
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/IO/FileCapturer.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using System.Collections.Generic;

+ 75 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/IO/NewFileAlerter.cs

@@ -0,0 +1,75 @@
+/// <summary>
+/// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
+/// Code Version 1.5.2
+/// </summary>
+
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System.IO;
+using UnityEngine.Events;
+
+/// <summary>
+/// 文件轮询查找功能
+/// 你是不是在xxx文件夹下又塞了一个模型?
+/// ↓参考组率先获取所有文件名
+/// ↓对照组循环获取文件名
+/// ↓对比数量
+/// ↓将对照组多出来的末位文件名传出
+/// </summary>
+namespace ToneTuneToolkit.IO
+{
+  public class NewFileAlerter : MonoBehaviour
+  {
+    public static UnityAction<string> OnNewFileDetected;
+
+    private const float detectSpaceTime = 10f; // 间隔多久轮询一次文件数量
+    private const string folderPath = @"C:/SandTableMesh/"; // 路径
+    private const string fileSuffix = ".obj"; // 文件后缀名
+
+    [SerializeField] private List<string> LastFileList; // 参考组
+    [SerializeField] private List<string> NewFileList; // 对照组
+
+    // ==============================
+
+    private void Start() => Init();
+    private void OnDestroy() => UnInit();
+
+    // ==============================
+
+    private void Init()
+    {
+      LastFileList = FileCapturer.GetFileNames2List(folderPath, fileSuffix);
+      StartCoroutine(nameof(FileDetectCircle));
+    }
+
+    private void UnInit()
+    {
+      StopCoroutine(nameof(FileDetectCircle));
+    }
+
+    // ==============================
+
+    /// <summary>
+    /// 文件数量检测循环
+    /// </summary>
+    /// <returns></returns>
+    private IEnumerator FileDetectCircle()
+    {
+      while (true)
+      {
+        NewFileList = FileCapturer.GetFileNames2List(folderPath, fileSuffix);
+
+        if (NewFileList.Count > LastFileList.Count) // 对比数量判断是否有新文件传入
+        {
+          string meshPath = Path.Combine(folderPath, NewFileList[NewFileList.Count - 1]);
+          Debug.Log("<color=green>[STEP01]</color> New .obj detected : <" + meshPath + ">.");
+          OnNewFileDetected?.Invoke(meshPath);
+          LastFileList = new List<string>(NewFileList);
+        }
+
+        yield return new WaitForSeconds(detectSpaceTime);
+      }
+    }
+  }
+}

+ 11 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/IO/NewFileAlerter.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 7608d8aa09456464d80c95c1ee7fcec9
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 1 - 1
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Media/FullAngleScreenshotTool.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using System.Collections;

+ 80 - 14
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Media/ScreenshotMaster.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using System.Collections;
@@ -10,9 +10,6 @@ using System;
 using System.IO;
 using UnityEngine.Events;
 using ToneTuneToolkit.Common;
-using UnityEngine.UI;
-
-
 
 namespace ToneTuneToolkit.Media
 {
@@ -76,10 +73,7 @@ namespace ToneTuneToolkit.Media
 
       peekTexture = texture2D;
 
-      if (OnScreenshotFinished != null)
-      {
-        OnScreenshotFinished(texture2D, flag);
-      }
+      OnScreenshotFinished?.Invoke(texture2D, flag);
       yield break;
     }
 
@@ -93,7 +87,7 @@ namespace ToneTuneToolkit.Media
     /// </summary>
     /// <param name="screenshotCamera"></param>
     /// <param name="screenshotRT">新建的RT宽高色彩模式都要设置妥当 // RGBA8_SRGB</param>
-    public static Texture2D OffScreenshot(Camera screenshotCamera, RenderTexture screenshotRT, string fullFilePath = null)
+    public static Texture2D OffScreenshot(Camera screenshotCamera, RenderTexture screenshotRT, RotateType rt = RotateType.RotateNone, string fullFilePath = null)
     {
       screenshotCamera.clearFlags = CameraClearFlags.SolidColor;
       screenshotCamera.backgroundColor = Color.clear;
@@ -103,6 +97,9 @@ namespace ToneTuneToolkit.Media
       RenderTexture.active = screenshotRT;
       Texture2D t2d = new Texture2D(screenshotRT.width, screenshotRT.height, TextureFormat.RGBA32, false);
       t2d.ReadPixels(new Rect(0, 0, screenshotRT.width, screenshotRT.height), 0, 0);
+
+      if (rt != RotateType.RotateNone) { t2d = RotateTexture(t2d, rt); } // 可能存在的旋转
+
       t2d.Apply();
 
       if (fullFilePath != null)
@@ -117,6 +114,68 @@ namespace ToneTuneToolkit.Media
       return t2d;
     }
 
+    #endregion
+    // ==================================================
+    #region T2D旋转
+
+    public static Texture2D RotateTexture(Texture2D original, RotateType rotation)
+    {
+      if (rotation == RotateType.RotateNone) { return original; }
+
+      int width = original.width;
+      int height = original.height;
+
+      // 确定新纹理尺寸
+      bool is90or270 = rotation == RotateType.Rotate90 || rotation == RotateType.Rotate270;
+      Texture2D result = new Texture2D(is90or270 ? height : width, is90or270 ? width : height);
+
+      Color32[] originalPixels = original.GetPixels32();
+      Color32[] rotatedPixels = new Color32[originalPixels.Length];
+
+      for (int y = 0; y < height; y++)
+      {
+        for (int x = 0; x < width; x++)
+        {
+          int newX, newY;
+
+          switch (rotation)
+          {
+            case RotateType.Rotate90:
+              newX = height - 1 - y;
+              newY = x;
+              break;
+            case RotateType.Rotate180:
+              newX = width - 1 - x;
+              newY = height - 1 - y;
+              break;
+            case RotateType.Rotate270:
+              newX = y;
+              newY = width - 1 - x;
+              break;
+            case RotateType.RotateNone:
+            default:
+              newX = x;
+              newY = y;
+              break;
+          }
+
+          rotatedPixels[newY * result.width + newX] = originalPixels[y * width + x];
+        }
+      }
+
+      result.SetPixels32(rotatedPixels);
+      result.Apply();
+      return result;
+    }
+
+    public enum RotateType
+    {
+      RotateNone = 0,
+      Rotate90 = 90,
+      Rotate180 = 180,
+      Rotate270 = 270
+    }
+
     #endregion
     // ==================================================
     #region 实验性功能
@@ -175,18 +234,25 @@ namespace ToneTuneToolkit.Media
     // ==================================================
     #region Tools
 
+    public enum CanvasType
+    {
+      ScreenSpaceOverlay = 0,
+      ScreenSpaceCamera = 1,
+      WorldSpace = 2
+    }
+
     public static string SpawnTimeStamp()
     {
       return $"{DateTime.Now:yyyy-MM-dd-HH-mm-ss}-{new System.Random().Next(0, 100)}";
     }
 
-    public enum CanvasType
+    public static void SaveTexture2File(Texture2D t2d, string fullFilePath)
     {
-      ScreenSpaceOverlay = 0,
-      ScreenSpaceCamera = 1,
-      WorldSpace = 2
+      byte[] bytes = t2d.EncodeToPNG();
+      File.WriteAllBytes(fullFilePath, bytes);
+      Debug.Log($"[SM] <color=green>{fullFilePath}</color>");
     }
 
     #endregion
   }
-}
+}

+ 1 - 1
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Media/TextureProcessor.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using System.Collections;

+ 11 - 8
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Media/WebCamHandler.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using System.Collections;
@@ -11,7 +11,7 @@ using UnityEngine.UI;
 
 public class WebCamHandler : SingletonMaster<WebCamHandler>
 {
-  [SerializeField] private RawImage previewRawImage;
+  [SerializeField] private List<RawImage> riPreviews;
 
   private WebCamDevice webCamDevice;
   private WebCamTexture webCamTexture;
@@ -22,13 +22,13 @@ public class WebCamHandler : SingletonMaster<WebCamHandler>
   private void Start()
   {
     InitWebcam();
-    // StartWebcam();
+    StartWebcam();
   }
 
   // ==================================================
   #region 相机配置
 
-  private string _webCamName = "MX Brio";
+  private string _webCamName = "OBSBOT Virtual Camera";
   private int _webCamWidth = 1920;
   private int _webCamHeight = 1080;
   private int _webCamFPS = 60;
@@ -49,7 +49,7 @@ public class WebCamHandler : SingletonMaster<WebCamHandler>
   {
     foreach (WebCamDevice device in WebCamTexture.devices)
     {
-      // Debug.Log(device.name);
+      Debug.Log(device.name);
       if (device.name == _webCamName)
       {
         webCamDevice = device;
@@ -57,9 +57,12 @@ public class WebCamHandler : SingletonMaster<WebCamHandler>
         // _webCamTexture.Play();
         isWebCamReady = true;
 
-        if (previewRawImage) // Preview
+        if (riPreviews.Count > 0) // Preview
         {
-          previewRawImage.texture = webCamTexture;
+          foreach (RawImage ri in riPreviews)
+          {
+            ri.texture = webCamTexture;
+          }
         }
         break;
       }
@@ -105,4 +108,4 @@ public class WebCamHandler : SingletonMaster<WebCamHandler>
     }
     return;
   }
-}
+}

+ 21 - 9
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Media/WebCamManager.cs

@@ -1,12 +1,13 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using System.Collections;
 using System.Collections.Generic;
 using ToneTuneToolkit.Common;
 using UnityEngine;
+using UnityEngine.Events;
 using UnityEngine.UI;
 
 /// <summary>
@@ -15,11 +16,13 @@ using UnityEngine.UI;
 /// </summary>
 public class WebCamManager : SingletonMaster<WebCamManager>
 {
+  public static UnityAction OnWebCamInitComplete;
+
   [SerializeField] private RawImage DEBUG_PreviewRawImage;
 
-  private string cameraName = "Logitech BRIO";
-  private int cameraWidth = 1500;
-  private int cameraHeight = 2000;
+  private string cameraName = "OBSBOT Virtual Camera";
+  private int cameraWidth = 1280;
+  private int cameraHeight = 720;
   private int cameraFPS = 60;
 
   private static WebCamTexture webCamTexture;
@@ -33,6 +36,7 @@ public class WebCamManager : SingletonMaster<WebCamManager>
 
   private void Init()
   {
+    PrintAllDevices();
     RequestCameraAuthorization();
     return;
   }
@@ -59,7 +63,7 @@ public class WebCamManager : SingletonMaster<WebCamManager>
     else
     {
       Debug.Log("[WCM] 无法获取摄像头权限");
-      StartCoroutine("RequestCameraAuthorization");
+      RequestCameraAuthorization();
     }
     yield break;
   }
@@ -84,7 +88,6 @@ public class WebCamManager : SingletonMaster<WebCamManager>
 #if UNITY_EDITOR // 编辑器使用罗技 // 或笔记本前置
     foreach (WebCamDevice item in devices)
     {
-      Debug.Log($"[WCM] 找到摄像头:{item.name}");
       if (item.name == cameraName)
       {
         device = item;
@@ -106,8 +109,7 @@ public class WebCamManager : SingletonMaster<WebCamManager>
 #endif
     webCamTexture.Play();
     isWebCameraCreated = true;
-    Debug.Log($"[WCM] 摄像头 Name :{device.name} / Width:{webCamTexture.width} / Height:{webCamTexture.height} / FPS:{webCamTexture.requestedFPS}");
-    Debug.Log("[WCM] 摄像头初始化完成");
+    Debug.Log($"[WCM] 摄像头初始化完成完成 Name :{device.name} / Width:{webCamTexture.width} / Height:{webCamTexture.height} / FPS:{webCamTexture.requestedFPS}");
 
     if (DEBUG_PreviewRawImage) // Preview
     {
@@ -166,4 +168,14 @@ public class WebCamManager : SingletonMaster<WebCamManager>
   }
 
   #endregion
-}
+  // ==================================================
+
+  private void PrintAllDevices()
+  {
+    foreach (WebCamDevice item in WebCamTexture.devices)
+    {
+      Debug.Log($"[WCM] 找到摄像头: {item.name}");
+    }
+    return;
+  }
+}

+ 11 - 0
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Media/WebCamManager.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: dfb123cf93ed9af41b134916a11ab718
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 1 - 1
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/Mobile/ObjectRotateAndScale.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using UnityEngine;

+ 1 - 1
ToneTuneToolkit/Assets/ToneTuneToolkit/Scripts/MultimediaExhibitionHall/LED/LEDCommandCenter.cs

@@ -1,6 +1,6 @@
 /// <summary>
 /// Copyright (c) 2025 MirzkisD1Ex0 All rights reserved.
-/// Code Version 1.4.20
+/// Code Version 1.5.2
 /// </summary>
 
 using UnityEngine;

Some files were not shown because too many files changed in this diff