using System; using ADOFAIRenderer; using ADOFAIRenderer.Core; using ADOFAIRenderer.Core.Data; using ADOFAIRenderer.UI; using FFmpeg.AutoGen; using MelonLoader; using MelonLoader.Utils; using UnityEngine; using Object = UnityEngine.Object; [assembly: MelonInfo(typeof(RenderMod), "ADOFAI Renderer", "0.3.2-INDEV", "ADOFAI Editor Forum")] [assembly: MelonGame("7th Beat Games", "A Dance of Fire and Ice")] namespace ADOFAIRenderer; /// /// MelonLoader entry point of the mod. Loads the settings and localization, points FFmpeg.AutoGen at the native /// FFmpeg libraries, and creates the persistent manager objects (RenderManager, FirstUpdateHook, RendererUIManager). /// internal class RenderMod : MelonMod { /// /// When true, the render button is not added to the level editor (scnEditorPatch checks it in scnEditor.Start). /// Set by the user from the NVIDIA driver warning dialog (FirstUpdateHook). Main thread only. /// // ReSharper disable once MemberCanBePrivate.Global public static bool IsFeatureDisabled = false; /// /// Expiration time of this build (UTC). After it, the render configuration window shows an "expired" note next to /// the version text. It does not block rendering. /// public static DateTime ExpirationTime = new(2026, 11, 21, 0, 0, 0, DateTimeKind.Utc); /// /// Called once by MelonLoader after the mod assembly is loaded. /// The native FFmpeg libraries are loaded from MelonLoader's UserLibs directory. /// The three manager GameObjects are marked DontDestroyOnLoad so they survive scene changes. /// public override void OnInitializeMelon() { GlobalSettings.Load(); Localization.LocalizationManager.Initialize(); ffmpeg.RootPath = MelonEnvironment.UserLibsDirectory; var renderManagerObj = new GameObject("Render Manager"); var updateHookerObj = new GameObject("Update Hooker"); var uiManagerObj = new GameObject("Renderer UI Manager"); Object.DontDestroyOnLoad(renderManagerObj); Object.DontDestroyOnLoad(updateHookerObj); Object.DontDestroyOnLoad(uiManagerObj); renderManagerObj.AddComponent(); updateHookerObj.AddComponent(); uiManagerObj.AddComponent(); ModAssets.Load(); } /// /// Called by MelonLoader when the game quits. Aborts an active render (encoders disposed, render thread joined, /// unfinished output file deleted) through RenderManager.CleanUpActiveRender. /// public override void OnApplicationQuit() { if (RenderManager.Instance == null) return; Melon.Logger.Msg("MelonLoader shutdown detected: Forcefully terminating and cleaning up active RenderManager processes."); RenderManager.Instance.CleanUpActiveRender(); } }