From e296bf55a9c10df9911f71a34e8354b1c61985b4 Mon Sep 17 00:00:00 2001 From: Clansty Date: Mon, 2 Dec 2024 08:52:13 +0800 Subject: [PATCH 1/8] [+] mp4 movie --- .../Assets/UseJacketAsDummyMovie.cs | 77 +++++++++++++++++-- 1 file changed, 72 insertions(+), 5 deletions(-) diff --git a/AquaMai.Mods/GameSystem/Assets/UseJacketAsDummyMovie.cs b/AquaMai.Mods/GameSystem/Assets/UseJacketAsDummyMovie.cs index a39fb265..b8362a9e 100644 --- a/AquaMai.Mods/GameSystem/Assets/UseJacketAsDummyMovie.cs +++ b/AquaMai.Mods/GameSystem/Assets/UseJacketAsDummyMovie.cs @@ -1,4 +1,6 @@ -using System.Linq; +using System; +using System.IO; +using System.Linq; using AquaMai.Config.Attributes; using HarmonyLib; using MAI2.Util; @@ -6,6 +8,7 @@ using Manager; using MelonLoader; using Monitor.Game; using UnityEngine; +using UnityEngine.Video; namespace AquaMai.Mods.GameSystem.Assets; @@ -20,6 +23,8 @@ namespace AquaMai.Mods.GameSystem.Assets; """)] public class UseJacketAsDummyMovie { + private static VideoPlayer _videoPlayer = null; + [HarmonyPostfix] [HarmonyPatch(typeof(GameCtrl), "IsReady")] public static void LoadLocalBgaAwake(GameObject ____movieMaskObj) @@ -30,25 +35,87 @@ public class UseJacketAsDummyMovie var moviePath = Singleton.Instance.GetMovieDataPath($"{music.movieName.id:000000}") + ".dat"; if (!moviePath.Contains("dummy")) return; + var mp4Path = Path.Combine(Environment.CurrentDirectory, "LocalAssets", $"{music.movieName.id:000000}.mp4"); + var mp4Exists = File.Exists(mp4Path); var jacket = LoadLocalImages.GetJacketTexture2D(music.movieName.id); - if (jacket is null) + if (!mp4Exists && jacket is null) { MelonLogger.Msg("No jacket found for music " + music); return; } + if (mp4Exists && _videoPlayer is null) + { +# if DEBUG + MelonLogger.Msg("Init _videoPlayer"); +# endif + _videoPlayer = ____movieMaskObj.AddComponent(); + _videoPlayer.url = mp4Path; + _videoPlayer.playOnAwake = false; + _videoPlayer.renderMode = VideoRenderMode.MaterialOverride; + _videoPlayer.audioOutputMode = VideoAudioOutputMode.None; + } +# if DEBUG + else if (mp4Exists) + { + MelonLogger.Msg("_videoPlayer already exists"); + } +# endif + var components = ____movieMaskObj.GetComponentsInChildren(false); var movies = components.Where(it => it.name == "Movie"); foreach (var movie in movies) { +# if DEBUG + MelonLogger.Msg("Found movie component: " + movie); +# endif // If I create a new RawImage component, the jacket will be not be displayed // I think it will be difficult to make it work with RawImage // So I change the material that plays video to default sprite material // The original player is actually a sprite renderer and plays video with a custom material var sprite = movie.GetComponent(); - sprite.sprite = Sprite.Create(jacket, new Rect(0, 0, jacket.width, jacket.height), new Vector2(0.5f, 0.5f)); - sprite.material = new Material(Shader.Find("Sprites/Default")); + if (mp4Exists) + { + if (_videoPlayer.targetMaterialRenderer == null) + { + sprite.material = new Material(Shader.Find("Sprites/Default")); + _videoPlayer.targetMaterialRenderer = sprite; + } + else + { + sprite.material = _videoPlayer.targetMaterialRenderer.material; + } + } + else + { + sprite.sprite = Sprite.Create(jacket, new Rect(0, 0, jacket.width, jacket.height), new Vector2(0.5f, 0.5f)); + sprite.material = new Material(Shader.Find("Sprites/Default")); + } } } -} + + [HarmonyPostfix] + [HarmonyPatch(typeof(MovieController), "Play")] + public static void Play(int frame) + { + if (_videoPlayer == null) return; + _videoPlayer.frame = frame; + _videoPlayer.Play(); + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(MovieController), "Pause")] + public static void Pause(bool pauseFlag) + { + if (_videoPlayer == null) return; + if (pauseFlag) + { + _videoPlayer.Pause(); + } + else + { + _videoPlayer.Play(); + } + } +} \ No newline at end of file From e8aba37cfc55af60250cb79c1c4ae3db8b360715 Mon Sep 17 00:00:00 2001 From: Clansty Date: Mon, 2 Dec 2024 09:08:34 +0800 Subject: [PATCH 2/8] [+] Config version 2.2 migration --- AquaMai.Config.Interfaces/IConfigView.cs | 1 + AquaMai.Config/ConfigView.cs | 20 +++++++++++++ .../Migration/ConfigMigrationManager.cs | 3 +- .../Migration/ConfigMigration_V2_0_V2_1.cs | 22 +------------- .../Migration/ConfigMigration_V2_1_V2_2.cs | 24 +++++++++++++++ ...seJacketAsDummyMovie.cs => MovieLoader.cs} | 30 ++++++++++++------- 6 files changed, 68 insertions(+), 32 deletions(-) create mode 100644 AquaMai.Config/Migration/ConfigMigration_V2_1_V2_2.cs rename AquaMai.Mods/GameSystem/Assets/{UseJacketAsDummyMovie.cs => MovieLoader.cs} (83%) diff --git a/AquaMai.Config.Interfaces/IConfigView.cs b/AquaMai.Config.Interfaces/IConfigView.cs index 29094741..49a11a95 100644 --- a/AquaMai.Config.Interfaces/IConfigView.cs +++ b/AquaMai.Config.Interfaces/IConfigView.cs @@ -6,6 +6,7 @@ public interface IConfigView public T GetValueOrDefault(string path, T defaultValue = default); public bool TryGetValue(string path, out T resultValue); public bool Remove(string path); + public bool IsSectionEnabled(string path); public string ToToml(); public IConfigView Clone(); } diff --git a/AquaMai.Config/ConfigView.cs b/AquaMai.Config/ConfigView.cs index 5344aaee..af32c0ea 100644 --- a/AquaMai.Config/ConfigView.cs +++ b/AquaMai.Config/ConfigView.cs @@ -139,4 +139,24 @@ public class ConfigView : IConfigView { return new ConfigView(ToToml()); } + + public bool IsSectionEnabled(string path) + { + if (TryGetValue(path, out object section)) + { + if (section is bool enabled) + { + return enabled; + } + else if (section is TomlTable table) + { + if (Utility.TomlTryGetValueCaseInsensitive(table, "Disabled", out var disabled)) + { + return !Utility.IsTrutyOrDefault(disabled); + } + return true; + } + } + return false; + } } diff --git a/AquaMai.Config/Migration/ConfigMigrationManager.cs b/AquaMai.Config/Migration/ConfigMigrationManager.cs index fe4ce8f0..2fca298f 100644 --- a/AquaMai.Config/Migration/ConfigMigrationManager.cs +++ b/AquaMai.Config/Migration/ConfigMigrationManager.cs @@ -13,7 +13,8 @@ public class ConfigMigrationManager : IConfigMigrationManager new List { new ConfigMigration_V1_0_V2_0(), - new ConfigMigration_V2_0_V2_1() + new ConfigMigration_V2_0_V2_1(), + new ConfigMigration_V2_1_V2_2(), }.ToDictionary(m => m.FromVersion); public string LatestVersion { get; } diff --git a/AquaMai.Config/Migration/ConfigMigration_V2_0_V2_1.cs b/AquaMai.Config/Migration/ConfigMigration_V2_0_V2_1.cs index e41058ad..0e2f60b4 100644 --- a/AquaMai.Config/Migration/ConfigMigration_V2_0_V2_1.cs +++ b/AquaMai.Config/Migration/ConfigMigration_V2_0_V2_1.cs @@ -13,7 +13,7 @@ public class ConfigMigration_V2_0_V2_1 : IConfigMigration var dst = src.Clone(); dst.SetValue("Version", ToVersion); - if (IsSectionEnabled(src, "Tweaks.ResetTouchAfterTrack")) + if (src.IsSectionEnabled("Tweaks.ResetTouchAfterTrack")) { dst.Remove("Tweaks.ResetTouchAfterTrack"); dst.SetValue("Tweaks.ResetTouch.AfterTrack", true); @@ -21,24 +21,4 @@ public class ConfigMigration_V2_0_V2_1 : IConfigMigration return dst; } - - public bool IsSectionEnabled(IConfigView src, string path) - { - if (src.TryGetValue(path, out object section)) - { - if (section is bool enabled) - { - return enabled; - } - else if (section is TomlTable table) - { - if (Utility.TomlTryGetValueCaseInsensitive(table, "Disabled", out var disabled)) - { - return !Utility.IsTrutyOrDefault(disabled); - } - return true; - } - } - return false; - } } diff --git a/AquaMai.Config/Migration/ConfigMigration_V2_1_V2_2.cs b/AquaMai.Config/Migration/ConfigMigration_V2_1_V2_2.cs new file mode 100644 index 00000000..4bdb9e29 --- /dev/null +++ b/AquaMai.Config/Migration/ConfigMigration_V2_1_V2_2.cs @@ -0,0 +1,24 @@ +using AquaMai.Config.Interfaces; +using Tomlet.Models; + +namespace AquaMai.Config.Migration; + +public class ConfigMigration_V2_1_V2_2 : IConfigMigration +{ + public string FromVersion => "2.1"; + public string ToVersion => "2.2"; + + public IConfigView Migrate(IConfigView src) + { + var dst = src.Clone(); + dst.SetValue("Version", ToVersion); + + if (src.IsSectionEnabled("GameSystem.Assets.UseJacketAsDummyMovie")) + { + dst.Remove("GameSystem.Assets.UseJacketAsDummyMovie"); + dst.SetValue("GameSystem.Assets.MovieLoader.JacketAsMovie", true); + } + + return dst; + } +} diff --git a/AquaMai.Mods/GameSystem/Assets/UseJacketAsDummyMovie.cs b/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs similarity index 83% rename from AquaMai.Mods/GameSystem/Assets/UseJacketAsDummyMovie.cs rename to AquaMai.Mods/GameSystem/Assets/MovieLoader.cs index b8362a9e..34caa2c1 100644 --- a/AquaMai.Mods/GameSystem/Assets/UseJacketAsDummyMovie.cs +++ b/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs @@ -13,17 +13,27 @@ using UnityEngine.Video; namespace AquaMai.Mods.GameSystem.Assets; [ConfigSection( - en: """ - Use the png jacket above as MV if no .dat found in the movie folder. - Use together with `LoadLocalImages`. - """, - zh: """ - 如果 movie 文件夹中没有 dat 格式的 MV 的话,就用歌曲的封面做背景,而不是显示迪拉熊的笑脸 - 请和 `LoadLocalImages` 一起用 - """)] -public class UseJacketAsDummyMovie + en: "Use mp4 files or the png jacket above as PV if no .dat found in the movie folder.", + zh: "使用封面作为 PV 以及直读 MP4 格式 PV 的选项")] +public class MovieLoader { - private static VideoPlayer _videoPlayer = null; + [ConfigEntry( + en: """ + Use jacket as movie + Use together with `LoadLocalImages`. + """, + zh: """ + 用封面作为背景 PV + 请和 `LoadLocalImages` 一起用 + """)] + private static bool jacketAsMovie = true; + + [ConfigEntry( + en: "Load MP4 files from LocalAssets", + zh: "从 LocalAssets 中加载 MP4 文件作为 PV")] + private static bool loadMp4Movie = true; + + private static VideoPlayer _videoPlayer; [HarmonyPostfix] [HarmonyPatch(typeof(GameCtrl), "IsReady")] From 1c0a4e3ef790f91d1e83d9be04c6a9f67d052a0e Mon Sep 17 00:00:00 2001 From: Clansty Date: Mon, 2 Dec 2024 09:35:59 +0800 Subject: [PATCH 3/8] chore --- AquaMai.Mods/GameSystem/Assets/MovieLoader.cs | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs b/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs index 34caa2c1..8df6e631 100644 --- a/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs +++ b/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs @@ -56,21 +56,26 @@ public class MovieLoader if (mp4Exists && _videoPlayer is null) { + if(_videoPlayer is null) + { # if DEBUG - MelonLogger.Msg("Init _videoPlayer"); + MelonLogger.Msg("Init _videoPlayer"); + _videoPlayer = ____movieMaskObj.AddComponent(); +# endif + } +# if DEBUG + else + { + MelonLogger.Msg("_videoPlayer already exists"); + } # endif - _videoPlayer = ____movieMaskObj.AddComponent(); _videoPlayer.url = mp4Path; _videoPlayer.playOnAwake = false; _videoPlayer.renderMode = VideoRenderMode.MaterialOverride; _videoPlayer.audioOutputMode = VideoAudioOutputMode.None; + // 似乎 MaterialOverride 没法保持视频的长宽比,用 RenderTexture 的话放在 SpriteRenderer 里面会比较麻烦。 + // 所以就不保持了,在塞 pv 的时候自己转吧,反正原本也要根据 first 加 padding } -# if DEBUG - else if (mp4Exists) - { - MelonLogger.Msg("_videoPlayer already exists"); - } -# endif var components = ____movieMaskObj.GetComponentsInChildren(false); var movies = components.Where(it => it.name == "Movie"); From 67c37df379df7357753081a92808bb793722f876 Mon Sep 17 00:00:00 2001 From: Clansty Date: Mon, 2 Dec 2024 10:36:45 +0800 Subject: [PATCH 4/8] chore --- AquaMai.Mods/GameSystem/Assets/MovieLoader.cs | 89 +++++++++---------- 1 file changed, 40 insertions(+), 49 deletions(-) diff --git a/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs b/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs index 8df6e631..f7a78243 100644 --- a/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs +++ b/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs @@ -1,6 +1,5 @@ using System; using System.IO; -using System.Linq; using AquaMai.Config.Attributes; using HarmonyLib; using MAI2.Util; @@ -33,11 +32,11 @@ public class MovieLoader zh: "从 LocalAssets 中加载 MP4 文件作为 PV")] private static bool loadMp4Movie = true; - private static VideoPlayer _videoPlayer; + private static VideoPlayer[] _videoPlayers = new VideoPlayer[2]; [HarmonyPostfix] - [HarmonyPatch(typeof(GameCtrl), "IsReady")] - public static void LoadLocalBgaAwake(GameObject ____movieMaskObj) + [HarmonyPatch(typeof(GameCtrl), "Initialize")] + public static void LoadLocalBgaAwake(GameObject ____movieMaskObj, int ___monitorIndex) { var music = Singleton.Instance.GetMusic(GameManager.SelectMusicID[0]); if (music is null) return; @@ -54,13 +53,13 @@ public class MovieLoader return; } - if (mp4Exists && _videoPlayer is null) + if (mp4Exists) { - if(_videoPlayer is null) + if (_videoPlayers[___monitorIndex] is null) { # if DEBUG MelonLogger.Msg("Init _videoPlayer"); - _videoPlayer = ____movieMaskObj.AddComponent(); + _videoPlayers[___monitorIndex] = ____movieMaskObj.AddComponent(); # endif } # if DEBUG @@ -69,44 +68,30 @@ public class MovieLoader MelonLogger.Msg("_videoPlayer already exists"); } # endif - _videoPlayer.url = mp4Path; - _videoPlayer.playOnAwake = false; - _videoPlayer.renderMode = VideoRenderMode.MaterialOverride; - _videoPlayer.audioOutputMode = VideoAudioOutputMode.None; + _videoPlayers[___monitorIndex].url = mp4Path; + _videoPlayers[___monitorIndex].playOnAwake = false; + _videoPlayers[___monitorIndex].renderMode = VideoRenderMode.MaterialOverride; + _videoPlayers[___monitorIndex].audioOutputMode = VideoAudioOutputMode.None; // 似乎 MaterialOverride 没法保持视频的长宽比,用 RenderTexture 的话放在 SpriteRenderer 里面会比较麻烦。 // 所以就不保持了,在塞 pv 的时候自己转吧,反正原本也要根据 first 加 padding } - var components = ____movieMaskObj.GetComponentsInChildren(false); - var movies = components.Where(it => it.name == "Movie"); + var movie = ____movieMaskObj.transform.Find("Movie"); - foreach (var movie in movies) + // If I create a new RawImage component, the jacket will be not be displayed + // I think it will be difficult to make it work with RawImage + // So I change the material that plays video to default sprite material + // The original player is actually a sprite renderer and plays video with a custom material + var sprite = movie.GetComponent(); + if (mp4Exists) { -# if DEBUG - MelonLogger.Msg("Found movie component: " + movie); -# endif - // If I create a new RawImage component, the jacket will be not be displayed - // I think it will be difficult to make it work with RawImage - // So I change the material that plays video to default sprite material - // The original player is actually a sprite renderer and plays video with a custom material - var sprite = movie.GetComponent(); - if (mp4Exists) - { - if (_videoPlayer.targetMaterialRenderer == null) - { - sprite.material = new Material(Shader.Find("Sprites/Default")); - _videoPlayer.targetMaterialRenderer = sprite; - } - else - { - sprite.material = _videoPlayer.targetMaterialRenderer.material; - } - } - else - { - sprite.sprite = Sprite.Create(jacket, new Rect(0, 0, jacket.width, jacket.height), new Vector2(0.5f, 0.5f)); - sprite.material = new Material(Shader.Find("Sprites/Default")); - } + sprite.material = new Material(Shader.Find("Sprites/Default")); + _videoPlayers[___monitorIndex].targetMaterialRenderer = sprite; + } + else + { + sprite.sprite = Sprite.Create(jacket, new Rect(0, 0, jacket.width, jacket.height), new Vector2(0.5f, 0.5f)); + sprite.material = new Material(Shader.Find("Sprites/Default")); } } @@ -114,23 +99,29 @@ public class MovieLoader [HarmonyPatch(typeof(MovieController), "Play")] public static void Play(int frame) { - if (_videoPlayer == null) return; - _videoPlayer.frame = frame; - _videoPlayer.Play(); + foreach (var player in _videoPlayers) + { + if (player == null) return; + player.frame = frame; + player.Play(); + } } [HarmonyPostfix] [HarmonyPatch(typeof(MovieController), "Pause")] public static void Pause(bool pauseFlag) { - if (_videoPlayer == null) return; - if (pauseFlag) + foreach (var player in _videoPlayers) { - _videoPlayer.Pause(); - } - else - { - _videoPlayer.Play(); + if (player == null) return; + if (pauseFlag) + { + player.Pause(); + } + else + { + player.Play(); + } } } } \ No newline at end of file From 488d4b5f9ae06f0084adcee4a4f3fca5620ce3e5 Mon Sep 17 00:00:00 2001 From: Clansty Date: Mon, 2 Dec 2024 10:57:35 +0800 Subject: [PATCH 5/8] SetSpeed --- AquaMai.Mods/GameSystem/Assets/MovieLoader.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs b/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs index f7a78243..2a393ca3 100644 --- a/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs +++ b/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs @@ -1,6 +1,7 @@ using System; using System.IO; using AquaMai.Config.Attributes; +using CriMana; using HarmonyLib; using MAI2.Util; using Manager; @@ -124,4 +125,15 @@ public class MovieLoader } } } + + [HarmonyPostfix] + [HarmonyPatch(typeof(Player), "SetSpeed")] + public static void SetSpeed(float speed) + { + foreach (var player in _videoPlayers) + { + if (player == null) return; + player.playbackSpeed = speed; + } + } } \ No newline at end of file From 93217a3d403323c989049b722da3da2b12c09e70 Mon Sep 17 00:00:00 2001 From: Clansty Date: Mon, 2 Dec 2024 10:59:20 +0800 Subject: [PATCH 6/8] fix --- AquaMai.Mods/GameSystem/Assets/MovieLoader.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs b/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs index 2a393ca3..77484d72 100644 --- a/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs +++ b/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs @@ -60,8 +60,8 @@ public class MovieLoader { # if DEBUG MelonLogger.Msg("Init _videoPlayer"); - _videoPlayers[___monitorIndex] = ____movieMaskObj.AddComponent(); # endif + _videoPlayers[___monitorIndex] = ____movieMaskObj.AddComponent(); } # if DEBUG else @@ -102,7 +102,7 @@ public class MovieLoader { foreach (var player in _videoPlayers) { - if (player == null) return; + if (player == null) continue; player.frame = frame; player.Play(); } @@ -114,7 +114,7 @@ public class MovieLoader { foreach (var player in _videoPlayers) { - if (player == null) return; + if (player == null) continue; if (pauseFlag) { player.Pause(); @@ -132,7 +132,7 @@ public class MovieLoader { foreach (var player in _videoPlayers) { - if (player == null) return; + if (player == null) continue; player.playbackSpeed = speed; } } From f8309dd5d67c7a766d37bd0498a58a2f6e3c5683 Mon Sep 17 00:00:00 2001 From: Clansty Date: Mon, 2 Dec 2024 11:42:30 +0800 Subject: [PATCH 7/8] add movieAssetsDir and rename localAssetsDir to imageAssetsDir --- AquaMai.Config/Migration/ConfigMigration_V2_1_V2_2.cs | 8 +++++++- AquaMai.Mods/GameSystem/Assets/LoadLocalImages.cs | 4 ++-- AquaMai.Mods/GameSystem/Assets/MovieLoader.cs | 9 ++++++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/AquaMai.Config/Migration/ConfigMigration_V2_1_V2_2.cs b/AquaMai.Config/Migration/ConfigMigration_V2_1_V2_2.cs index 4bdb9e29..42fb7b41 100644 --- a/AquaMai.Config/Migration/ConfigMigration_V2_1_V2_2.cs +++ b/AquaMai.Config/Migration/ConfigMigration_V2_1_V2_2.cs @@ -19,6 +19,12 @@ public class ConfigMigration_V2_1_V2_2 : IConfigMigration dst.SetValue("GameSystem.Assets.MovieLoader.JacketAsMovie", true); } + if (src.TryGetValue("GameSystem.Assets.LoadLocalImages.LocalAssetsDir", out var localAssetsDir)) + { + dst.SetValue("GameSystem.Assets.LoadLocalImages.ImageAssetsDir", localAssetsDir); + dst.Remove("GameSystem.Assets.LoadLocalImages.LocalAssetsDir"); + } + return dst; } -} +} \ No newline at end of file diff --git a/AquaMai.Mods/GameSystem/Assets/LoadLocalImages.cs b/AquaMai.Mods/GameSystem/Assets/LoadLocalImages.cs index 72152de9..d1585815 100644 --- a/AquaMai.Mods/GameSystem/Assets/LoadLocalImages.cs +++ b/AquaMai.Mods/GameSystem/Assets/LoadLocalImages.cs @@ -20,7 +20,7 @@ namespace AquaMai.Mods.GameSystem.Assets; public class LoadLocalImages { [ConfigEntry] - private static readonly string localAssetsDir = "LocalAssets"; + private static readonly string imageAssetsDir = "LocalAssets"; private static readonly string[] imageExts = [".jpg", ".png", ".jpeg"]; private static readonly Dictionary jacketPaths = []; @@ -122,7 +122,7 @@ public class LoadLocalImages MelonLogger.Msg($"[LoadLocalImages] Loaded {jacketPaths.Count} Jacket, {platePaths.Count} NamePlate, {framePaths.Count} Frame, {framemaskPaths.Count} FrameMask, {framepatternPaths.Count} FramePattern, {iconPaths.Count} Icon, {charaPaths.Count} Chara, {partnerPaths.Count} PartnerLogo, {tabTitlePaths.Count} Tab Titles from AssetBundleImages."); - var resolvedDir = FileSystem.ResolvePath(localAssetsDir); + var resolvedDir = FileSystem.ResolvePath(imageAssetsDir); if (Directory.Exists(resolvedDir)) foreach (var laFile in Directory.EnumerateFiles(resolvedDir)) { diff --git a/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs b/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs index 77484d72..7bfd87fc 100644 --- a/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs +++ b/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs @@ -1,6 +1,7 @@ using System; using System.IO; using AquaMai.Config.Attributes; +using AquaMai.Core.Helpers; using CriMana; using HarmonyLib; using MAI2.Util; @@ -33,6 +34,11 @@ public class MovieLoader zh: "从 LocalAssets 中加载 MP4 文件作为 PV")] private static bool loadMp4Movie = true; + [ConfigEntry( + en: "MP4 files directory", + zh: "加载 MP4 文件的路径")] + private static readonly string movieAssetsDir = "LocalAssets"; + private static VideoPlayer[] _videoPlayers = new VideoPlayer[2]; [HarmonyPostfix] @@ -45,7 +51,8 @@ public class MovieLoader var moviePath = Singleton.Instance.GetMovieDataPath($"{music.movieName.id:000000}") + ".dat"; if (!moviePath.Contains("dummy")) return; - var mp4Path = Path.Combine(Environment.CurrentDirectory, "LocalAssets", $"{music.movieName.id:000000}.mp4"); + var resolvedDir = FileSystem.ResolvePath(movieAssetsDir); + var mp4Path = Path.Combine(resolvedDir, $"{music.movieName.id:000000}.mp4"); var mp4Exists = File.Exists(mp4Path); var jacket = LoadLocalImages.GetJacketTexture2D(music.movieName.id); if (!mp4Exists && jacket is null) From 2c2de9bb63067817e435ac2b5dd43e09b9ec5c10 Mon Sep 17 00:00:00 2001 From: Clansty Date: Mon, 2 Dec 2024 12:20:38 +0800 Subject: [PATCH 8/8] load mp4 from StreamingAssets --- AquaMai.Mods/GameSystem/Assets/MovieLoader.cs | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs b/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs index 7bfd87fc..87bf9349 100644 --- a/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs +++ b/AquaMai.Mods/GameSystem/Assets/MovieLoader.cs @@ -1,4 +1,4 @@ -using System; +using System.Collections.Generic; using System.IO; using AquaMai.Config.Attributes; using AquaMai.Core.Helpers; @@ -39,6 +39,23 @@ public class MovieLoader zh: "加载 MP4 文件的路径")] private static readonly string movieAssetsDir = "LocalAssets"; + private static readonly Dictionary optionFileMap = []; + + [HarmonyPrefix] + [HarmonyPatch(typeof(DataManager), "LoadMusicBase")] + public static void LoadMusicPostfix(List ____targetDirs) + { + foreach (var aDir in ____targetDirs) + { + if (!Directory.Exists(Path.Combine(aDir, "MovieData"))) continue; + var files = Directory.GetFiles(Path.Combine(aDir, "MovieData"), "*.mp4"); + foreach (var file in files) + { + optionFileMap[Path.GetFileName(file)] = file; + } + } + } + private static VideoPlayer[] _videoPlayers = new VideoPlayer[2]; [HarmonyPostfix] @@ -52,7 +69,11 @@ public class MovieLoader if (!moviePath.Contains("dummy")) return; var resolvedDir = FileSystem.ResolvePath(movieAssetsDir); - var mp4Path = Path.Combine(resolvedDir, $"{music.movieName.id:000000}.mp4"); + if (!optionFileMap.TryGetValue($"{music.movieName.id:000000}.mp4", out var mp4Path)) + { + mp4Path = Path.Combine(resolvedDir, $"{music.movieName.id:000000}.mp4"); + } + var mp4Exists = File.Exists(mp4Path); var jacket = LoadLocalImages.GetJacketTexture2D(music.movieName.id); if (!mp4Exists && jacket is null)