Refactor Asset Loading

This commit is contained in:
copecone committed 2026-10-05 14:50:21 +09:00
1 parent 6c0347609d
commit b15903f1e0
9 files changed
+102 -162

No files matched your search

+3 -34
View File
@@ -2,12 +2,11 @@ using System;
using ADOFAIRenderer; using ADOFAIRenderer;
using ADOFAIRenderer.Core; using ADOFAIRenderer.Core;
using ADOFAIRenderer.Data; using ADOFAIRenderer.Data;
using ADOFAIRenderer.Util; using ADOFAIRenderer.UI;
using FFmpeg.AutoGen; using FFmpeg.AutoGen;
using MelonLoader; using MelonLoader;
using MelonLoader.Utils; using MelonLoader.Utils;
using UnityEngine; using UnityEngine;
using UnityEngine.EventSystems;
using Object = UnityEngine.Object; using Object = UnityEngine.Object;
[assembly: MelonInfo(typeof(RenderMod), "ADOFAI Renderer", "0.3.3-BETA", "ADOFAI Editor Forum")] [assembly: MelonInfo(typeof(RenderMod), "ADOFAI Renderer", "0.3.3-BETA", "ADOFAI Editor Forum")]
@@ -17,10 +16,7 @@ namespace ADOFAIRenderer;
internal class RenderMod : MelonMod internal class RenderMod : MelonMod
{ {
public static AssetBundle FontBundle = null!;
// ReSharper disable once MemberCanBePrivate.Global // ReSharper disable once MemberCanBePrivate.Global
public static AssetBundle ShaderBundle = null!;
public static ComputeShader ColorConversionShader = null!;
public static bool IsFeatureDisabled = false; public static bool IsFeatureDisabled = false;
public static DateTime ExpirationTime = new(2026, 09, 21, 0, 0, 0, DateTimeKind.Utc); public static DateTime ExpirationTime = new(2026, 09, 21, 0, 0, 0, DateTimeKind.Utc);
@@ -39,35 +35,8 @@ internal class RenderMod : MelonMod
renderManagerObj.AddComponent<RenderManager>(); renderManagerObj.AddComponent<RenderManager>();
updateHookerObj.AddComponent<FirstUpdateHook>(); updateHookerObj.AddComponent<FirstUpdateHook>();
uiManagerObj.AddComponent<UI.RendererUIManager>(); uiManagerObj.AddComponent<RendererUIManager>();
LoadBundles(); ModAssets.Load();
}
private static void LoadBundles()
{
FontBundle = BundleLoader.GetBundle("fonts");
try
{
ShaderBundle = BundleLoader.GetBundle("shaders");
ColorConversionShader = ShaderBundle.LoadAsset<ComputeShader>("ColorConversion");
Melon<RenderMod>.Logger.Msg("Color conversion Compute Shader loaded successfully.");
}
catch (Exception ex)
{
Melon<RenderMod>.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<RenderMod>.Logger.Msg("Ported Unity 6 Input Module.");
var newModule = EventSystem.current.gameObject.AddComponent<StandaloneInputModule>();
newModule.enabled = true;
} }
public override void OnApplicationQuit() public override void OnApplicationQuit()
+1 -41
View File
@@ -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<TMP_FontAsset>("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<TMP_FontAsset>("Fonts & Materials/LiberationSans SDF");
}
if (font) return font;
var fonts = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
if (fonts.Length > 0) font = fonts[0];
return font!;
}
public static void ShowDialog(string title, string description, params DialogButton[] buttons) public static void ShowDialog(string title, string description, params DialogButton[] buttons)
{ {
if (buttons.Length == 0) return; if (buttons.Length == 0) return;
@@ -153,7 +113,7 @@ internal class CommonWarningDialogUI : MonoBehaviour
bgRect.offsetMin = Vector2.zero; bgRect.offsetMin = Vector2.zero;
bgRect.offsetMax = Vector2.zero; bgRect.offsetMax = Vector2.zero;
var font = GetNanumSquareNeoBdFontAsset(); var font = ModAssets.NanumSquareNeoNormal;
// 2. Create modal container // 2. Create modal container
var modalContainerObj = new GameObject("ModalContainer"); var modalContainerObj = new GameObject("ModalContainer");
+2 -36
View File
@@ -30,39 +30,6 @@ internal class DebugMonitorUI : MonoBehaviour
private RectTransform _fillRect = null!; private RectTransform _fillRect = null!;
private TextMeshProUGUI _progressText = null!; private TextMeshProUGUI _progressText = null!;
private static TMP_FontAsset GetNanumSquareNeoBdFontAsset()
{
TMP_FontAsset? font = null;
if (RenderMod.FontBundle != null)
{
try
{
font = RenderMod.FontBundle.LoadAsset<TMP_FontAsset>("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<TMP_FontAsset>("Fonts & Materials/LiberationSans SDF");
}
if (font != null) return font;
var fonts = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
if (fonts.Length > 0) font = fonts[0];
return font!;
}
private void Start() private void Start()
{ {
// Set UI layer (5) // Set UI layer (5)
@@ -112,8 +79,7 @@ internal class DebugMonitorUI : MonoBehaviour
_text.overflowMode = TextOverflowModes.Overflow; _text.overflowMode = TextOverflowModes.Overflow;
// Load and apply font // Load and apply font
var font = GetNanumSquareNeoBdFontAsset(); _text.font = ModAssets.NanumSquareNeoNormal;
_text.font = font;
var textRect = textObj.GetComponent<RectTransform>(); var textRect = textObj.GetComponent<RectTransform>();
textRect.anchorMin = Vector2.zero; textRect.anchorMin = Vector2.zero;
@@ -166,7 +132,7 @@ internal class DebugMonitorUI : MonoBehaviour
_progressText.richText = true; _progressText.richText = true;
_progressText.fontSize = BarTextFontSize; _progressText.fontSize = BarTextFontSize;
_progressText.alignment = TextAlignmentOptions.Center; _progressText.alignment = TextAlignmentOptions.Center;
_progressText.font = font; _progressText.font = ModAssets.NanumSquareNeoNormal;
_progressText.color = BarTextColor; _progressText.color = BarTextColor;
// Add progress bar text outline for readability // Add progress bar text outline for readability
+2 -2
View File
@@ -88,11 +88,11 @@ internal class FFmpegDownloadUI : MonoBehaviour
private static TMP_FontAsset GetNanumSquareNeoBdFontAsset() private static TMP_FontAsset GetNanumSquareNeoBdFontAsset()
{ {
TMP_FontAsset? font = null; TMP_FontAsset? font = null;
if (RenderMod.FontBundle) if (ModAssets.FontBundle)
{ {
try try
{ {
font = RenderMod.FontBundle.LoadAsset<TMP_FontAsset>("NanumSquareNeoOTF-Bd SDF"); font = ModAssets.FontBundle.LoadAsset<TMP_FontAsset>("NanumSquareNeoOTF-Bd SDF");
} }
catch catch
{ {
+2 -2
View File
@@ -151,11 +151,11 @@ internal class RenderConfigUIManager : MonoBehaviour
}; };
// Apply same font as existing UI // Apply same font as existing UI
if (RenderMod.FontBundle) if (ModAssets.FontBundle)
{ {
try try
{ {
var font = RenderMod.FontBundle.LoadAsset<Font>("NanumSquareNeoOTF-Bd"); var font = ModAssets.FontBundle.LoadAsset<Font>("NanumSquareNeoOTF-Bd");
if (font) { _versionLabel.style.unityFontDefinition = FontDefinition.FromFont(font); } if (font) { _versionLabel.style.unityFontDefinition = FontDefinition.FromFont(font); }
} }
catch { /* ignored */ } catch { /* ignored */ }
+53 -9
View File
@@ -1,25 +1,68 @@
using System.Diagnostics.CodeAnalysis;
using ADOFAIRenderer.Util;
using MelonLoader;
using O5Kit.Core; using O5Kit.Core;
using TMPro;
namespace ADOFAIRenderer.UI; namespace ADOFAIRenderer.UI;
using UnityEngine; 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<TMP_FontAsset>("Assets/Fonts/NanumSquareNeoOTF-Bd SDF.asset");
NanumSquareNeoBold = FontBundle.LoadAsset<TMP_FontAsset>("Assets/Fonts/NanumSquareNeoOTF-Hv SDF.asset");
Melon<RenderMod>.Logger.Msg("Fonts loaded successfully.");
ShaderBundle = BundleLoader.GetBundle("shaders");
ColorConversionShader = ShaderBundle.LoadAsset<ComputeShader>("ColorConversion");
Melon<RenderMod>.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; private static RendererUIManager? _instance;
public static RendererUIManager Instance public static RendererUIManager Instance
{ {
get get
{ {
if (_instance == null) if (_instance != null) return _instance;
{
var go = new GameObject("RendererUIManager"); var go = new GameObject("RendererUIManager");
DontDestroyOnLoad(go); DontDestroyOnLoad(go);
_instance = go.AddComponent<RendererUIManager>();
} _instance = go.AddComponent<RendererUIManager>();
return _instance; return _instance;
} }
private set => _instance = value;
} }
public static O5Context Context => Instance._context; public static O5Context Context => Instance._context;
@@ -37,7 +80,8 @@ public class RendererUIManager : MonoBehaviour
MiddleClickToDefault = true, MiddleClickToDefault = true,
SliderSensitivity = 1.0f SliderSensitivity = 1.0f
}, },
theme: O5Theme.Dark theme: O5Theme.Dark,
fonts: new RendererFontProvider()
); );
_windowManager = O5WindowManager.Create(_context, transform, "RendererMod_Canvas"); _windowManager = O5WindowManager.Create(_context, transform, "RendererMod_Canvas");
+27 -28
View File
@@ -4,41 +4,40 @@ using System.Resources;
using MelonLoader; using MelonLoader;
using UnityEngine; 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; BundlePlatform = Application.platform switch
private static readonly Assembly? ExecutingAssembly;
static BundleLoader()
{ {
BundlePlatform = Application.platform switch RuntimePlatform.WindowsPlayer => "Win64",
{ RuntimePlatform.OSXPlayer => "OSX",
RuntimePlatform.WindowsPlayer => "Win64", _ => "Linux"
RuntimePlatform.OSXPlayer => "OSX", };
_ => "Linux" ExecutingAssembly = Assembly.GetExecutingAssembly();
}; }
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}"; return AssetBundle.LoadFromStream(resourceStream);
using var resourceStream = ExecutingAssembly.GetManifestResourceStream(bundlePath);
if (resourceStream != null)
{
return AssetBundle.LoadFromStream(resourceStream);
}
Melon<RenderMod>.Logger.Error($"Could not find bundle resource in DLL.\n{bundlePath}");
throw new MissingManifestResourceException("Could not find bundle resource in DLL.");
} }
Melon<RenderMod>.Logger.Error("Executing assembly has not been set properly."); Melon<RenderMod>.Logger.Error($"Could not find bundle resource in DLL.\n{bundlePath}");
throw new InvalidOperationException("ExecutingAssembly has not been set."); throw new MissingManifestResourceException("Could not find bundle resource in DLL.");
} }
Melon<RenderMod>.Logger.Error("Executing assembly has not been set properly.");
throw new InvalidOperationException("ExecutingAssembly has not been set.");
} }
} }
+2 -1
View File
@@ -1,6 +1,7 @@
using System; using System;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using ADOFAIRenderer.UI;
using ADOFAIRenderer.Util.FFmpeg; using ADOFAIRenderer.Util.FFmpeg;
using MelonLoader; using MelonLoader;
using UnityEngine; using UnityEngine;
@@ -77,7 +78,7 @@ namespace ADOFAIRenderer.Util
try try
{ {
_decoder = new FFmpegNativeDecoder(videoPath); _decoder = new FFmpegNativeDecoder(videoPath);
_computeShader = RenderMod.ColorConversionShader; _computeShader = ModAssets.ColorConversionShader;
var w = _decoder.Width; var w = _decoder.Width;
var h = _decoder.Height; var h = _decoder.Height;
+10 -9
View File
@@ -3,6 +3,7 @@ using System.Buffers;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using ADOFAIRenderer.Core; using ADOFAIRenderer.Core;
using ADOFAIRenderer.UI;
using FFmpeg.AutoGen; using FFmpeg.AutoGen;
using MelonLoader; using MelonLoader;
using Unity.Collections; using Unity.Collections;
@@ -71,7 +72,7 @@ namespace ADOFAIRenderer.Util
} }
// Check if GPU color conversion is enabled // Check if GPU color conversion is enabled
bool useGPUConversion = RenderMod.ColorConversionShader; bool useGPUConversion = ModAssets.ColorConversionShader;
AVPixelFormat expectedFmt = AVPixelFormat.AV_PIX_FMT_RGBA; AVPixelFormat expectedFmt = AVPixelFormat.AV_PIX_FMT_RGBA;
if (useGPUConversion) if (useGPUConversion)
@@ -87,31 +88,31 @@ namespace ADOFAIRenderer.Util
var bufferSize = texture.width * texture.height * 4; // RGBA = 4 channel var bufferSize = texture.width * texture.height * 4; // RGBA = 4 channel
state.Setup(currentFrame, bufferSize, useGPUConversion, expectedFmt, texture.width, texture.height); 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; int kernelIndex = -1;
if (expectedFmt == AVPixelFormat.AV_PIX_FMT_NV12) 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) else if (expectedFmt == AVPixelFormat.AV_PIX_FMT_YUV420P)
{ {
kernelIndex = RenderMod.ColorConversionShader.FindKernel("CSMain_YUV420P"); kernelIndex = ModAssets.ColorConversionShader.FindKernel("CSMain_YUV420P");
} }
if (kernelIndex >= 0) if (kernelIndex >= 0)
{ {
RenderMod.ColorConversionShader.SetTexture(kernelIndex, SourceTexture, texture); ModAssets.ColorConversionShader.SetTexture(kernelIndex, SourceTexture, texture);
RenderMod.ColorConversionShader.SetBuffer(kernelIndex, DestinationBuffer, state.GPUBuffer); ModAssets.ColorConversionShader.SetBuffer(kernelIndex, DestinationBuffer, state.GPUBuffer);
RenderMod.ColorConversionShader.SetInt(Width, texture.width); ModAssets.ColorConversionShader.SetInt(Width, texture.width);
RenderMod.ColorConversionShader.SetInt(Height, texture.height); ModAssets.ColorConversionShader.SetInt(Height, texture.height);
var threadGroupsX = expectedFmt == AVPixelFormat.AV_PIX_FMT_NV12 var threadGroupsX = expectedFmt == AVPixelFormat.AV_PIX_FMT_NV12
? (texture.width + 31) / 32 ? (texture.width + 31) / 32
: (texture.width + 63) / 64; : (texture.width + 63) / 64;
var threadGroupsY = (texture.height + 15) / 16; var threadGroupsY = (texture.height + 15) / 16;
RenderMod.ColorConversionShader.Dispatch(kernelIndex, threadGroupsX, threadGroupsY, 1); ModAssets.ColorConversionShader.Dispatch(kernelIndex, threadGroupsX, threadGroupsY, 1);
AsyncGPUReadback.Request( AsyncGPUReadback.Request(
state.GPUBuffer, state.GPUBuffer,