From b15903f1e03b14bcf4eea4a48cc9f826345c05b04ab12f28d13c93cfe4e5f301 Mon Sep 17 00:00:00 2001 From: copecone Date: Mon, 5 Oct 2026 14:50:21 +0900 Subject: [PATCH] Refactor Asset Loading --- RenderMod.cs | 37 ++-------------------- UI/CommonWarningDialogUI.cs | 42 +------------------------ UI/DebugMonitorUI.cs | 38 ++--------------------- UI/FFmpegDownloadUI.cs | 4 +-- UI/RenderConfigUIManager.cs | 4 +-- UI/RendererUIManager.cs | 62 +++++++++++++++++++++++++++++++------ Util/BundleLoader.cs | 55 ++++++++++++++++---------------- Util/FFmpegVideoBGPlayer.cs | 3 +- Util/FrameReader.cs | 19 ++++++------ 9 files changed, 102 insertions(+), 162 deletions(-) diff --git a/RenderMod.cs b/RenderMod.cs index bbfc5ce..593e541 100644 --- a/RenderMod.cs +++ b/RenderMod.cs @@ -2,12 +2,11 @@ using System; using ADOFAIRenderer; using ADOFAIRenderer.Core; using ADOFAIRenderer.Data; -using ADOFAIRenderer.Util; +using ADOFAIRenderer.UI; using FFmpeg.AutoGen; using MelonLoader; using MelonLoader.Utils; using UnityEngine; -using UnityEngine.EventSystems; using Object = UnityEngine.Object; [assembly: MelonInfo(typeof(RenderMod), "ADOFAI Renderer", "0.3.3-BETA", "ADOFAI Editor Forum")] @@ -17,10 +16,7 @@ namespace ADOFAIRenderer; internal class RenderMod : MelonMod { - public static AssetBundle FontBundle = null!; // ReSharper disable once MemberCanBePrivate.Global - public static AssetBundle ShaderBundle = null!; - public static ComputeShader ColorConversionShader = null!; public static bool IsFeatureDisabled = false; public static DateTime ExpirationTime = new(2026, 09, 21, 0, 0, 0, DateTimeKind.Utc); @@ -39,35 +35,8 @@ internal class RenderMod : MelonMod renderManagerObj.AddComponent(); updateHookerObj.AddComponent(); - uiManagerObj.AddComponent(); - LoadBundles(); - } - - private static void LoadBundles() - { - FontBundle = BundleLoader.GetBundle("fonts"); - try - { - ShaderBundle = BundleLoader.GetBundle("shaders"); - ColorConversionShader = ShaderBundle.LoadAsset("ColorConversion"); - Melon.Logger.Msg("Color conversion Compute Shader loaded successfully."); - } - catch (Exception ex) - { - Melon.Logger.Warning($"Failed to load Shader AssetBundle. GPU color conversion will be disabled and fallback to CPU. Error: {ex.Message}"); - } - } - - public static void FixEventSystem() - { - if (EventSystem.current == null) return; - var currentModule = EventSystem.current.currentInputModule; - - if (currentModule) return; - Melon.Logger.Msg("Ported Unity 6 Input Module."); - - var newModule = EventSystem.current.gameObject.AddComponent(); - newModule.enabled = true; + uiManagerObj.AddComponent(); + ModAssets.Load(); } public override void OnApplicationQuit() diff --git a/UI/CommonWarningDialogUI.cs b/UI/CommonWarningDialogUI.cs index a26bd96..7403b96 100644 --- a/UI/CommonWarningDialogUI.cs +++ b/UI/CommonWarningDialogUI.cs @@ -52,46 +52,6 @@ internal class CommonWarningDialogUI : MonoBehaviour } } - private static TMP_FontAsset GetNanumSquareNeoBdFontAsset() - { - TMP_FontAsset? font = null; - if (RenderMod.FontBundle) - { - try - { - font = RenderMod.FontBundle.LoadAsset("NanumSquareNeoOTF-Bd SDF"); - } - catch - { - // Loading failed - } - } - - // Fallback processing - if (!font) - { - try - { - font = RDString.fontData.fontTMP; - } - catch - { - // ignored - } - } - if (!font) - { - // ReSharper disable once Unity.UnknownResource - font = Resources.Load("Fonts & Materials/LiberationSans SDF"); - } - - if (font) return font; - var fonts = Resources.FindObjectsOfTypeAll(); - if (fonts.Length > 0) font = fonts[0]; - - return font!; - } - public static void ShowDialog(string title, string description, params DialogButton[] buttons) { if (buttons.Length == 0) return; @@ -153,7 +113,7 @@ internal class CommonWarningDialogUI : MonoBehaviour bgRect.offsetMin = Vector2.zero; bgRect.offsetMax = Vector2.zero; - var font = GetNanumSquareNeoBdFontAsset(); + var font = ModAssets.NanumSquareNeoNormal; // 2. Create modal container var modalContainerObj = new GameObject("ModalContainer"); diff --git a/UI/DebugMonitorUI.cs b/UI/DebugMonitorUI.cs index 8710c8b..f2bc2c9 100644 --- a/UI/DebugMonitorUI.cs +++ b/UI/DebugMonitorUI.cs @@ -30,39 +30,6 @@ internal class DebugMonitorUI : MonoBehaviour private RectTransform _fillRect = null!; private TextMeshProUGUI _progressText = null!; - private static TMP_FontAsset GetNanumSquareNeoBdFontAsset() - { - TMP_FontAsset? font = null; - if (RenderMod.FontBundle != null) - { - try - { - font = RenderMod.FontBundle.LoadAsset("NanumSquareNeoOTF-Bd SDF"); - } - catch - { - // Loading failed - } - } - - // Fallback: Use game's own font or built-in TMP SDF font if AssetBundle loading fails - if (font == null) - { - font = RDString.fontData.fontTMP; - } - if (font == null) - { - // ReSharper disable once Unity.UnknownResource - font = Resources.Load("Fonts & Materials/LiberationSans SDF"); - } - - if (font != null) return font; - var fonts = Resources.FindObjectsOfTypeAll(); - if (fonts.Length > 0) font = fonts[0]; - - return font!; - } - private void Start() { // Set UI layer (5) @@ -112,8 +79,7 @@ internal class DebugMonitorUI : MonoBehaviour _text.overflowMode = TextOverflowModes.Overflow; // Load and apply font - var font = GetNanumSquareNeoBdFontAsset(); - _text.font = font; + _text.font = ModAssets.NanumSquareNeoNormal; var textRect = textObj.GetComponent(); textRect.anchorMin = Vector2.zero; @@ -166,7 +132,7 @@ internal class DebugMonitorUI : MonoBehaviour _progressText.richText = true; _progressText.fontSize = BarTextFontSize; _progressText.alignment = TextAlignmentOptions.Center; - _progressText.font = font; + _progressText.font = ModAssets.NanumSquareNeoNormal; _progressText.color = BarTextColor; // Add progress bar text outline for readability diff --git a/UI/FFmpegDownloadUI.cs b/UI/FFmpegDownloadUI.cs index 9ebaae3..737f7f0 100644 --- a/UI/FFmpegDownloadUI.cs +++ b/UI/FFmpegDownloadUI.cs @@ -88,11 +88,11 @@ internal class FFmpegDownloadUI : MonoBehaviour private static TMP_FontAsset GetNanumSquareNeoBdFontAsset() { TMP_FontAsset? font = null; - if (RenderMod.FontBundle) + if (ModAssets.FontBundle) { try { - font = RenderMod.FontBundle.LoadAsset("NanumSquareNeoOTF-Bd SDF"); + font = ModAssets.FontBundle.LoadAsset("NanumSquareNeoOTF-Bd SDF"); } catch { diff --git a/UI/RenderConfigUIManager.cs b/UI/RenderConfigUIManager.cs index 5ab3694..1fc5b8d 100644 --- a/UI/RenderConfigUIManager.cs +++ b/UI/RenderConfigUIManager.cs @@ -151,11 +151,11 @@ internal class RenderConfigUIManager : MonoBehaviour }; // Apply same font as existing UI - if (RenderMod.FontBundle) + if (ModAssets.FontBundle) { try { - var font = RenderMod.FontBundle.LoadAsset("NanumSquareNeoOTF-Bd"); + var font = ModAssets.FontBundle.LoadAsset("NanumSquareNeoOTF-Bd"); if (font) { _versionLabel.style.unityFontDefinition = FontDefinition.FromFont(font); } } catch { /* ignored */ } diff --git a/UI/RendererUIManager.cs b/UI/RendererUIManager.cs index 181da56..91063e4 100644 --- a/UI/RendererUIManager.cs +++ b/UI/RendererUIManager.cs @@ -1,25 +1,68 @@ +using System.Diagnostics.CodeAnalysis; +using ADOFAIRenderer.Util; +using MelonLoader; using O5Kit.Core; +using TMPro; namespace ADOFAIRenderer.UI; using UnityEngine; -public class RendererUIManager : MonoBehaviour +[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] +internal static class ModAssets +{ + public static void Load() + { + FontBundle = BundleLoader.GetBundle("fonts"); + NanumSquareNeoNormal = FontBundle.LoadAsset("Assets/Fonts/NanumSquareNeoOTF-Bd SDF.asset"); + NanumSquareNeoBold = FontBundle.LoadAsset("Assets/Fonts/NanumSquareNeoOTF-Hv SDF.asset"); + Melon.Logger.Msg("Fonts loaded successfully."); + + ShaderBundle = BundleLoader.GetBundle("shaders"); + ColorConversionShader = ShaderBundle.LoadAsset("ColorConversion"); + Melon.Logger.Msg("Shader loaded successfully."); + } + + public static AssetBundle FontBundle = null!; + public static AssetBundle ShaderBundle = null!; + + public static TMP_FontAsset NanumSquareNeoNormal = null!; + public static TMP_FontAsset NanumSquareNeoBold = null!; + + public static ComputeShader ColorConversionShader = null!; +} + +internal sealed class RendererFontProvider : IFontProvider +{ + private static readonly DefaultFontProvider DefaultFontProvider = new(); + private bool _disposed; + + public TMP_FontAsset Regular => ModAssets.NanumSquareNeoNormal; + public TMP_FontAsset Medium => ModAssets.NanumSquareNeoBold; + public TMP_FontAsset Monospace => DefaultFontProvider.Monospace; + + public void Dispose() + { + if (_disposed) return; + _disposed = true; + } +} + +internal class RendererUIManager : MonoBehaviour { private static RendererUIManager? _instance; public static RendererUIManager Instance { get { - if (_instance == null) - { - var go = new GameObject("RendererUIManager"); - DontDestroyOnLoad(go); - _instance = go.AddComponent(); - } + if (_instance != null) return _instance; + + var go = new GameObject("RendererUIManager"); + DontDestroyOnLoad(go); + + _instance = go.AddComponent(); return _instance; } - private set => _instance = value; } public static O5Context Context => Instance._context; @@ -37,7 +80,8 @@ public class RendererUIManager : MonoBehaviour MiddleClickToDefault = true, SliderSensitivity = 1.0f }, - theme: O5Theme.Dark + theme: O5Theme.Dark, + fonts: new RendererFontProvider() ); _windowManager = O5WindowManager.Create(_context, transform, "RendererMod_Canvas"); diff --git a/Util/BundleLoader.cs b/Util/BundleLoader.cs index 585a9d1..668e65c 100644 --- a/Util/BundleLoader.cs +++ b/Util/BundleLoader.cs @@ -4,41 +4,40 @@ using System.Resources; using MelonLoader; using UnityEngine; -namespace ADOFAIRenderer.Util +namespace ADOFAIRenderer.Util; + +internal static class BundleLoader { - internal static class BundleLoader + private static readonly string BundlePlatform; + private static readonly Assembly? ExecutingAssembly; + + static BundleLoader() { - private static readonly string BundlePlatform; - private static readonly Assembly? ExecutingAssembly; - - static BundleLoader() + BundlePlatform = Application.platform switch { - BundlePlatform = Application.platform switch - { - RuntimePlatform.WindowsPlayer => "Win64", - RuntimePlatform.OSXPlayer => "OSX", - _ => "Linux" - }; - ExecutingAssembly = Assembly.GetExecutingAssembly(); - } + RuntimePlatform.WindowsPlayer => "Win64", + RuntimePlatform.OSXPlayer => "OSX", + _ => "Linux" + }; + ExecutingAssembly = Assembly.GetExecutingAssembly(); + } - public static AssetBundle GetBundle(string resourcePath) + public static AssetBundle GetBundle(string resourcePath) + { + if (ExecutingAssembly != null) { - if (ExecutingAssembly != null) + var bundlePath = $"ADOFAIRenderer.Bundle.{BundlePlatform}.{resourcePath}"; + using var resourceStream = ExecutingAssembly.GetManifestResourceStream(bundlePath); + if (resourceStream != null) { - var bundlePath = $"ADOFAIRenderer.Bundle.{BundlePlatform}.{resourcePath}"; - using var resourceStream = ExecutingAssembly.GetManifestResourceStream(bundlePath); - if (resourceStream != null) - { - return AssetBundle.LoadFromStream(resourceStream); - } - - Melon.Logger.Error($"Could not find bundle resource in DLL.\n{bundlePath}"); - throw new MissingManifestResourceException("Could not find bundle resource in DLL."); + return AssetBundle.LoadFromStream(resourceStream); } - - Melon.Logger.Error("Executing assembly has not been set properly."); - throw new InvalidOperationException("ExecutingAssembly has not been set."); + + Melon.Logger.Error($"Could not find bundle resource in DLL.\n{bundlePath}"); + throw new MissingManifestResourceException("Could not find bundle resource in DLL."); } + + Melon.Logger.Error("Executing assembly has not been set properly."); + throw new InvalidOperationException("ExecutingAssembly has not been set."); } } \ No newline at end of file diff --git a/Util/FFmpegVideoBGPlayer.cs b/Util/FFmpegVideoBGPlayer.cs index a09eeda..c804819 100644 --- a/Util/FFmpegVideoBGPlayer.cs +++ b/Util/FFmpegVideoBGPlayer.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics.CodeAnalysis; using System.IO; +using ADOFAIRenderer.UI; using ADOFAIRenderer.Util.FFmpeg; using MelonLoader; using UnityEngine; @@ -77,7 +78,7 @@ namespace ADOFAIRenderer.Util try { _decoder = new FFmpegNativeDecoder(videoPath); - _computeShader = RenderMod.ColorConversionShader; + _computeShader = ModAssets.ColorConversionShader; var w = _decoder.Width; var h = _decoder.Height; diff --git a/Util/FrameReader.cs b/Util/FrameReader.cs index 3db2637..0f4e7a5 100644 --- a/Util/FrameReader.cs +++ b/Util/FrameReader.cs @@ -3,6 +3,7 @@ using System.Buffers; using System.Collections.Generic; using System.Linq; using ADOFAIRenderer.Core; +using ADOFAIRenderer.UI; using FFmpeg.AutoGen; using MelonLoader; using Unity.Collections; @@ -71,7 +72,7 @@ namespace ADOFAIRenderer.Util } // Check if GPU color conversion is enabled - bool useGPUConversion = RenderMod.ColorConversionShader; + bool useGPUConversion = ModAssets.ColorConversionShader; AVPixelFormat expectedFmt = AVPixelFormat.AV_PIX_FMT_RGBA; if (useGPUConversion) @@ -87,31 +88,31 @@ namespace ADOFAIRenderer.Util var bufferSize = texture.width * texture.height * 4; // RGBA = 4 channel state.Setup(currentFrame, bufferSize, useGPUConversion, expectedFmt, texture.width, texture.height); - if (useGPUConversion && state.GPUBuffer != null && RenderMod.ColorConversionShader) + if (useGPUConversion && state.GPUBuffer != null && ModAssets.ColorConversionShader) { int kernelIndex = -1; if (expectedFmt == AVPixelFormat.AV_PIX_FMT_NV12) { - kernelIndex = RenderMod.ColorConversionShader.FindKernel("CSMain_NV12"); + kernelIndex = ModAssets.ColorConversionShader.FindKernel("CSMain_NV12"); } else if (expectedFmt == AVPixelFormat.AV_PIX_FMT_YUV420P) { - kernelIndex = RenderMod.ColorConversionShader.FindKernel("CSMain_YUV420P"); + kernelIndex = ModAssets.ColorConversionShader.FindKernel("CSMain_YUV420P"); } if (kernelIndex >= 0) { - RenderMod.ColorConversionShader.SetTexture(kernelIndex, SourceTexture, texture); - RenderMod.ColorConversionShader.SetBuffer(kernelIndex, DestinationBuffer, state.GPUBuffer); - RenderMod.ColorConversionShader.SetInt(Width, texture.width); - RenderMod.ColorConversionShader.SetInt(Height, texture.height); + ModAssets.ColorConversionShader.SetTexture(kernelIndex, SourceTexture, texture); + ModAssets.ColorConversionShader.SetBuffer(kernelIndex, DestinationBuffer, state.GPUBuffer); + ModAssets.ColorConversionShader.SetInt(Width, texture.width); + ModAssets.ColorConversionShader.SetInt(Height, texture.height); var threadGroupsX = expectedFmt == AVPixelFormat.AV_PIX_FMT_NV12 ? (texture.width + 31) / 32 : (texture.width + 63) / 64; var threadGroupsY = (texture.height + 15) / 16; - RenderMod.ColorConversionShader.Dispatch(kernelIndex, threadGroupsX, threadGroupsY, 1); + ModAssets.ColorConversionShader.Dispatch(kernelIndex, threadGroupsX, threadGroupsY, 1); AsyncGPUReadback.Request( state.GPUBuffer,