using System.Diagnostics.CodeAnalysis; using ADOFAIRenderer.Util; using MelonLoader; using O5Kit.Core; using TMPro; namespace ADOFAIRenderer.UI; using UnityEngine; /// /// Assets loaded from the mod's embedded asset bundles (fonts and the color conversion compute shader). /// /// is called once from RenderMod.OnInitializeMelon; the fields stay null until then. /// Bundles are obtained from BundleLoader.GetBundle by name ("fonts", "shaders"). Main thread only. /// /// [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] internal static class ModAssets { /// /// Loads the font and shader bundles and the assets inside them, logging after each bundle. /// Exceptions from bundle or asset loading are not caught here and propagate to the caller. /// public static void Load() { FontBundle = BundleLoader.GetBundle("fonts"); NanumSquareNeoNormal = FontBundle.LoadAsset("NanumSquareNeoOTF-Bd SDF"); NanumSquareNeoBold = FontBundle.LoadAsset("NanumSquareNeoOTF-Eb SDF"); Melon.Logger.Msg("Fonts loaded successfully."); ShaderBundle = BundleLoader.GetBundle("shaders"); ColorConversionShader = ShaderBundle.LoadAsset("ColorConversion"); Melon.Logger.Msg("Shader loaded successfully."); } /// Asset bundle "fonts" holding the TextMeshPro font assets. public static AssetBundle FontBundle = null!; /// Asset bundle "shaders" holding the compute shaders. public static AssetBundle ShaderBundle = null!; /// /// NanumSquare Neo, asset "NanumSquareNeoOTF-Bd SDF" (Bd = Bold weight). Used as the regular UI font of the mod /// (O5Kit , DebugMonitorUI text). /// public static TMP_FontAsset NanumSquareNeoNormal = null!; /// /// NanumSquare Neo, asset "NanumSquareNeoOTF-Eb SDF" (Eb = ExtraBold weight). Used as the O5Kit medium font /// (). /// public static TMP_FontAsset NanumSquareNeoBold = null!; /// /// Compute shader "ColorConversion" that converts captured frames to the encoder's YUV pixel format on the GPU /// (used by FrameReader). /// public static ComputeShader ColorConversionShader = null!; } /// /// O5Kit font provider for the mod's UI: the bundled NanumSquare Neo fonts for regular and medium text, and O5Kit's /// default monospace font. /// internal sealed class RendererFontProvider : IFontProvider { /// O5Kit default provider, used only for . private static readonly DefaultFontProvider DefaultFontProvider = new(); private bool _disposed; /// Regular text font: . public TMP_FontAsset Regular => ModAssets.NanumSquareNeoNormal; /// Medium (emphasis) text font: . public TMP_FontAsset Medium => ModAssets.NanumSquareNeoBold; /// Monospace font (e.g. hex color input): O5Kit's default monospace font. public TMP_FontAsset Monospace => DefaultFontProvider.Monospace; /// /// Marks the provider disposed. The font assets belong to and are not unloaded. /// public void Dispose() { if (_disposed) return; _disposed = true; } } /// /// Owner of the mod's O5Kit UI: the shared (config, theme, fonts) and the window manager /// with its canvas. /// /// Added once by RenderMod.OnInitializeMelon to a GameObject kept across scene loads. Other UI code reads /// and through the static . /// drives O5Kit's per-frame work (object ticks, tooltip, keyboard shortcuts). Main thread only. /// /// internal class RendererUIManager : MonoBehaviour { /// The single instance, assigned in . public static RendererUIManager Instance = null!; /// Shared O5Kit context used to build every mod window and dialog. public static O5Context Context => Instance._context; /// Window manager whose canvas holds the mod windows (e.g. RenderConfigWindow). public O5WindowManager WindowManager => _windowManager; private O5Context _context = null!; private O5WindowManager _windowManager = null!; /// /// Creates the O5Kit context with the mod theme and fonts, then the window manager and its canvas /// ("RendererMod_Canvas"), and lowers that canvas's sorting order to . /// private void Awake() { Instance = this; // O5Kit config: UI scale 1.0, middle click resets a control to its default value, slider drag sensitivity 1.0. // Theme: O5Kit's dark theme with the mod colors. Colors are RGBA 0..1; the accent color // (1.000, 0.294, 0.079) is orange-red (#FF4B14 approx.). Sizes are canvas units: corner radius 12, // outline width 2, control height 40, body font 18, H1 font 48. _context = new O5Context( config: new O5Config { UIScale = 1.0f, MiddleClickToDefault = true, SliderSensitivity = 1.0f }, theme: O5Theme.Dark with { PanelBG = new Color(0.067f, 0.067f, 0.067f, 1f), TopBar = new Color(0f, 0f, 0f, 0.6f), MenuBG = new Color(0f, 0f, 0f, 0.6f), MenuHover = new Color(1.000f, 0.294f, 0.079f, .6f), ObjectBG = new Color(0f, 0f, 0f, 1f), ObjectButton = new Color(0f, 0f, 0f, 1f), ObjectActive = new Color(1.000f, 0.294f, 0.079f, 1f), ObjectActiveBright = new Color(1.000f, 0.294f, 0.079f, 1f), ControlOutlineIdle = new Color(1f, 1f, 1f, 0.4f), ButtonHover = new Color(0.133f, 0.133f, 0.133f, 1.0f), ControlOutlineHover = new Color(1f, 1f, 1f, 0.4f), CardHeader = new Color(0.157f, 0f, 0f, 1f), CardPanel = new Color(0, 0, 0, 0f), SoftRed = new Color(1.000f, 0.576f, 0.590f, 1f), MathOk = new Color(0.408f, 0.827f, 0.569f, 1f), MathWarn = new Color(0.964f, 0.647f, 0.315f, 1f), MathErr = new Color(1.000f, 0.576f, 0.590f, 1f), CornerRadius = 12, OutlineWidth = 2, ControlHeight = 40, FontSizeBody = 18, FontSizeH1 = 48, Outline = new Color(1f, 1f, 1f, 0.2f), TextDimAlpha = 1f }, fonts: new RendererFontProvider() ); _windowManager = O5WindowManager.Create(_context, transform, "RendererMod_Canvas"); // The O5Kit canvas is created with sortingOrder 32767. It is lowered so that the dialogs of // CommonWarningDialogUI (32766) are drawn above the windows of this manager. var windowCanvas = transform.Find("RendererMod_Canvas")?.GetComponent(); if (windowCanvas != null) windowCanvas.sortingOrder = WindowCanvasSortingOrder; } /// /// Sorting order of the window canvas: below CommonWarningDialogUI (32766) and FFmpegDownloadUI (32767), above the /// render overlays (DebugMonitorUI 9999, EscapeHandlerUI 10000). /// private const int WindowCanvasSortingOrder = 32000; /// Runs O5Kit's per-frame updates: object ticks, tooltip, and keyboard shortcut handling. private void Update() { O5Object.TickAll(); Context.Tooltip.Tick(); O5Kit.Input.O5ShortcutManager.HandleUpdate(); } /// Disposes the window manager, then the context. private void OnDestroy() { _windowManager.Dispose(); _context.Dispose(); } }