-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[+] mp4 movie
- Loading branch information
Showing
8 changed files
with
223 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
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); | ||
} | ||
|
||
if (src.TryGetValue<string>("GameSystem.Assets.LoadLocalImages.LocalAssetsDir", out var localAssetsDir)) | ||
{ | ||
dst.SetValue("GameSystem.Assets.LoadLocalImages.ImageAssetsDir", localAssetsDir); | ||
dst.Remove("GameSystem.Assets.LoadLocalImages.LocalAssetsDir"); | ||
} | ||
|
||
return dst; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using AquaMai.Config.Attributes; | ||
using AquaMai.Core.Helpers; | ||
using CriMana; | ||
using HarmonyLib; | ||
using MAI2.Util; | ||
using Manager; | ||
using MelonLoader; | ||
using Monitor.Game; | ||
using UnityEngine; | ||
using UnityEngine.Video; | ||
|
||
namespace AquaMai.Mods.GameSystem.Assets; | ||
|
||
[ConfigSection( | ||
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 | ||
{ | ||
[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; | ||
|
||
[ConfigEntry( | ||
en: "MP4 files directory", | ||
zh: "加载 MP4 文件的路径")] | ||
private static readonly string movieAssetsDir = "LocalAssets"; | ||
|
||
private static readonly Dictionary<string, string> optionFileMap = []; | ||
|
||
[HarmonyPrefix] | ||
[HarmonyPatch(typeof(DataManager), "LoadMusicBase")] | ||
public static void LoadMusicPostfix(List<string> ____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] | ||
[HarmonyPatch(typeof(GameCtrl), "Initialize")] | ||
public static void LoadLocalBgaAwake(GameObject ____movieMaskObj, int ___monitorIndex) | ||
{ | ||
var music = Singleton<DataManager>.Instance.GetMusic(GameManager.SelectMusicID[0]); | ||
if (music is null) return; | ||
|
||
var moviePath = Singleton<OptionDataManager>.Instance.GetMovieDataPath($"{music.movieName.id:000000}") + ".dat"; | ||
if (!moviePath.Contains("dummy")) return; | ||
|
||
var resolvedDir = FileSystem.ResolvePath(movieAssetsDir); | ||
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) | ||
{ | ||
MelonLogger.Msg("No jacket found for music " + music); | ||
return; | ||
} | ||
|
||
if (mp4Exists) | ||
{ | ||
if (_videoPlayers[___monitorIndex] is null) | ||
{ | ||
# if DEBUG | ||
MelonLogger.Msg("Init _videoPlayer"); | ||
# endif | ||
_videoPlayers[___monitorIndex] = ____movieMaskObj.AddComponent<VideoPlayer>(); | ||
} | ||
# if DEBUG | ||
else | ||
{ | ||
MelonLogger.Msg("_videoPlayer already exists"); | ||
} | ||
# endif | ||
_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 movie = ____movieMaskObj.transform.Find("Movie"); | ||
|
||
// 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<SpriteRenderer>(); | ||
if (mp4Exists) | ||
{ | ||
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")); | ||
} | ||
} | ||
|
||
[HarmonyPostfix] | ||
[HarmonyPatch(typeof(MovieController), "Play")] | ||
public static void Play(int frame) | ||
{ | ||
foreach (var player in _videoPlayers) | ||
{ | ||
if (player == null) continue; | ||
player.frame = frame; | ||
player.Play(); | ||
} | ||
} | ||
|
||
[HarmonyPostfix] | ||
[HarmonyPatch(typeof(MovieController), "Pause")] | ||
public static void Pause(bool pauseFlag) | ||
{ | ||
foreach (var player in _videoPlayers) | ||
{ | ||
if (player == null) continue; | ||
if (pauseFlag) | ||
{ | ||
player.Pause(); | ||
} | ||
else | ||
{ | ||
player.Play(); | ||
} | ||
} | ||
} | ||
|
||
[HarmonyPostfix] | ||
[HarmonyPatch(typeof(Player), "SetSpeed")] | ||
public static void SetSpeed(float speed) | ||
{ | ||
foreach (var player in _videoPlayers) | ||
{ | ||
if (player == null) continue; | ||
player.playbackSpeed = speed; | ||
} | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.