Plugin.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. using BeatLyrics.Common;
  2. using BeatLyrics.Common.Models;
  3. using IllusionPlugin;
  4. using Newtonsoft.Json;
  5. using SongCore.Utilities;
  6. using System;
  7. using System.Collections;
  8. using System.IO;
  9. using System.Linq;
  10. using TMPro;
  11. using UnityEngine;
  12. using UnityEngine.SceneManagement;
  13. namespace BeatLyrics
  14. {
  15. /// <summary>
  16. /// Entry point of the plugin.
  17. /// </summary>
  18. public sealed class Plugin : IPlugin
  19. {
  20. public string Name => "Beat Lyrics";
  21. public string Version => "0.0.0.1";
  22. private LyricsComponent _lastUsedLyricsComponent;
  23. public void OnApplicationStart()
  24. {
  25. SceneManager.activeSceneChanged += OnActiveSceneChanged;
  26. }
  27. public void OnApplicationQuit()
  28. {
  29. SceneManager.activeSceneChanged -= OnActiveSceneChanged;
  30. }
  31. #region Unused
  32. public void OnLevelWasInitialized(int level)
  33. {
  34. }
  35. public void OnLevelWasLoaded(int level)
  36. {
  37. }
  38. public void OnUpdate()
  39. {
  40. }
  41. public void OnFixedUpdate()
  42. {
  43. }
  44. #endregion Unused
  45. public void OnActiveSceneChanged(Scene _, Scene newScene)
  46. {
  47. if (newScene.name == "GameCore")
  48. {
  49. _lastUsedLyricsComponent = newScene.GetRootGameObjects()[0].AddComponent<LyricsComponent>();
  50. }
  51. else
  52. {
  53. if (_lastUsedLyricsComponent != null)
  54. {
  55. //TODO: cleanup
  56. }
  57. }
  58. }
  59. }
  60. public class LyricsComponent : MonoBehaviour
  61. {
  62. private static readonly Quaternion Rot = Quaternion.Euler(new Vector3(0, 0, 0));
  63. private static readonly Vector3 Pos = new Vector3(0, 1.5f, 15f);
  64. private static readonly float FontSize = 25;
  65. private static readonly Color32 FontColor = new Color32(255, 255, 255, 64);
  66. private static readonly float OutlineWidth = 0.4f;
  67. private static readonly Color32 OutlineColor = new Color32(255, 0, 0, 255);
  68. //TODO: OutLine
  69. //TODO: Select Font
  70. private readonly AudioTimeSyncController _audioTime;
  71. private readonly GameObject _clockCanvas = null;
  72. private readonly TextMeshProUGUI _text = null;
  73. private GameplayCoreSceneSetupData _data;
  74. private LyricFile _lyricFile;
  75. private string _lyricFileName;
  76. private string _debugInfo;
  77. public LyricsComponent()
  78. {
  79. _audioTime = Resources.FindObjectsOfTypeAll<AudioTimeSyncController>().FirstOrDefault();
  80. _clockCanvas = new GameObject();
  81. _clockCanvas.AddComponent<Canvas>();
  82. _clockCanvas.name = "BeatLyrics Canvas";
  83. _clockCanvas.transform.position = Pos;
  84. _clockCanvas.transform.rotation = Rot;
  85. _clockCanvas.transform.localScale = new Vector3(0.02f, 0.02f, 1.0f);
  86. var textObj = new GameObject();
  87. textObj.transform.SetParent(_clockCanvas.transform);
  88. textObj.transform.localPosition = Vector3.zero;
  89. textObj.transform.localRotation = Quaternion.identity;
  90. textObj.transform.localScale = Vector3.one;
  91. _text = textObj.AddComponent<TextMeshProUGUI>();
  92. _text.alignment = TextAlignmentOptions.Center;
  93. _text.fontSize = FontSize;
  94. _text.enableWordWrapping = false;
  95. _text.color = FontColor;
  96. _text.name = "Lyrics Text";
  97. _text.text = "BeatLyrics";
  98. //text.font=
  99. }
  100. public IEnumerator Start()
  101. {
  102. var sceneSetup = FindObjectOfType<GameplayCoreSceneSetup>();
  103. _data = (GameplayCoreSceneSetupData)sceneSetup?.GetField("_sceneSetupData");
  104. //HACK: NJS Cheat
  105. if (_data != null) //TODO: Create New Plugin - OR - Load from Config
  106. {
  107. try
  108. {
  109. _data.difficultyBeatmap.SetField("_noteJumpMovementSpeed", 17);
  110. }
  111. catch (Exception e)
  112. {
  113. System.Diagnostics.Debug.Print(e.ToString());
  114. }
  115. }
  116. try
  117. {
  118. LoadLrc();
  119. }
  120. catch (Exception e)
  121. {
  122. _debugInfo = "Error Load Lrc:" + e.Message;
  123. }
  124. yield break;
  125. }
  126. private void LoadLrc()
  127. {
  128. if (_data?.difficultyBeatmap.level.levelID != null)
  129. {
  130. var beatLyricsDir = DirProvider.BeatLyricsDir;
  131. if (beatLyricsDir != null)
  132. {
  133. var path = GetSetFilePath(_data.difficultyBeatmap.level.levelID);
  134. if (File.Exists(path))
  135. {
  136. var jsonFileName = File.ReadAllText(path);
  137. var jsonFilePath = Path.Combine(beatLyricsDir, _data.difficultyBeatmap.level.levelID, jsonFileName);
  138. if (File.Exists(jsonFilePath))
  139. {
  140. var json = File.ReadAllText(jsonFilePath);
  141. _lyricFile = JsonConvert.DeserializeObject<LyricFile>(json);
  142. _lyricFileName = Path.GetFileNameWithoutExtension(jsonFileName);
  143. }
  144. else
  145. {
  146. _debugInfo += "json file not found";
  147. }
  148. }
  149. else
  150. {
  151. _debugInfo += "set.txt file not found";
  152. }
  153. }
  154. else
  155. {
  156. _debugInfo += "failure to get EnvVar";
  157. }
  158. }
  159. }
  160. public void Update()
  161. {
  162. var milliseconds = _audioTime?.songTime * 1000 ?? 0;
  163. if (_lyricFile != null)
  164. {
  165. if (milliseconds < 1)
  166. {
  167. _text.text = _lyricFileName;
  168. }
  169. else
  170. {
  171. //Show LRC
  172. _text.text = _lyricFile.Main?.FirstOrDefault(p => p.TimeMs <= milliseconds && p.TimeMs + p.DurationMs >= milliseconds)?.Text
  173. + Environment.NewLine + _lyricFile.Subtitle?.FirstOrDefault(p => p.TimeMs <= milliseconds && p.TimeMs + p.DurationMs >= milliseconds)?.Text;
  174. }
  175. }
  176. else if (milliseconds < 1)
  177. {
  178. var level = _data?.difficultyBeatmap.level;
  179. _text.text = "此处应有歌词,但是未能加载" +
  180. $"{Environment.NewLine}{level?.levelID}" +
  181. $"{Environment.NewLine}{_debugInfo}";
  182. }
  183. else
  184. {
  185. _text.text = "";
  186. }
  187. }
  188. public static string GetSetFilePath(string levelId)
  189. {
  190. return Path.Combine(DirProvider.BeatLyricsDir, levelId + DirProvider.SuffixSet);
  191. }
  192. }
  193. }