Initial Commit

This commit is contained in:
copecone committed 2026-05-21 11:38:31 +09:00
commit 44a22ae103
19 files changed
+772

No files matched your search

+35
View File
@@ -0,0 +1,35 @@
## Build outputs
bin/
obj/
Bin/
Obj/
build/
Build/
## IDE and Editor Settings
# Visual Studio
.vs/
*.user
*.suo
*.userprefs
*.sln.docstates
# JetBrains Rider / IntelliJ
.idea/
*.sln.DotSettings.user
# Visual Studio Code
.vscode/
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/code-snippets
## OS-specific files
.DS_Store
Thumbs.db
desktop.ini
## Agent Metadata
.antigravitycli/
+67
View File
@@ -0,0 +1,67 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<Nullable>enable</Nullable>
<NoWarn>MSB3277</NoWarn>
</PropertyGroup>
<ItemGroup>
<Reference Include="0Harmony">
<HintPath>$(ADOFAI_PATH)\MelonLoader\net35\0Harmony.dll</HintPath>
</Reference>
<Reference Include="Assembly-CSharp">
<HintPath>$(ADOFAI_PATH)\A Dance of Fire and Ice_Data\Managed\Assembly-CSharp.dll</HintPath>
</Reference>
<Reference Include="Assembly-CSharp-firstpass">
<HintPath>$(ADOFAI_PATH)\A Dance of Fire and Ice_Data\Managed\Assembly-CSharp-firstpass.dll</HintPath>
</Reference>
<Reference Include="MelonLoader">
<HintPath>$(ADOFAI_PATH)\MelonLoader\net35\MelonLoader.dll</HintPath>
</Reference>
<Reference Include="RDTools">
<HintPath>$(ADOFAI_PATH)\A Dance of Fire and Ice_Data\Managed\RDTools.dll</HintPath>
</Reference>
<Reference Include="SkyHook.Unity">
<HintPath>$(ADOFAI_PATH)\A Dance of Fire and Ice_Data\Managed\SkyHook.Unity.dll</HintPath>
</Reference>
<Reference Include="Unity.TextMeshPro">
<HintPath>$(ADOFAI_PATH)\A Dance of Fire and Ice_Data\Managed\Unity.TextMeshPro.dll</HintPath>
</Reference>
<Reference Include="UnityEngine">
<HintPath>$(ADOFAI_PATH)\A Dance of Fire and Ice_Data\Managed\UnityEngine.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.AssetBundleModule">
<HintPath>$(ADOFAI_PATH)\A Dance of Fire and Ice_Data\Managed\UnityEngine.AssetBundleModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.AudioModule">
<HintPath>$(ADOFAI_PATH)\A Dance of Fire and Ice_Data\Managed\UnityEngine.AudioModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>$(ADOFAI_PATH)\A Dance of Fire and Ice_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.InputLegacyModule">
<HintPath>$(ADOFAI_PATH)\A Dance of Fire and Ice_Data\Managed\UnityEngine.InputLegacyModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.InputModule">
<HintPath>$(ADOFAI_PATH)\A Dance of Fire and Ice_Data\Managed\UnityEngine.InputModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UI">
<HintPath>$(ADOFAI_PATH)\A Dance of Fire and Ice_Data\Managed\UnityEngine.UI.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UIElementsModule">
<HintPath>$(ADOFAI_PATH)\A Dance of Fire and Ice_Data\Managed\UnityEngine.UIElementsModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UIModule">
<HintPath>$(ADOFAI_PATH)\A Dance of Fire and Ice_Data\Managed\UnityEngine.UIModule.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<None Remove="Bundle\Win64\fonts" />
<EmbeddedResource Include="Bundle\Win64\fonts" />
<None Remove="Bundle\Win64\scenes" />
<EmbeddedResource Include="Bundle\Win64\scenes" />
</ItemGroup>
</Project>
+16
View File
@@ -0,0 +1,16 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ADOFAIRenderer", "ADOFAIRenderer.csproj", "{2D997D97-A2CC-4EB0-8963-DA6A71082319}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2D997D97-A2CC-4EB0-8963-DA6A71082319}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2D997D97-A2CC-4EB0-8963-DA6A71082319}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2D997D97-A2CC-4EB0-8963-DA6A71082319}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2D997D97-A2CC-4EB0-8963-DA6A71082319}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
Binary file not shown.
Binary file not shown.
+13
View File
@@ -0,0 +1,13 @@
using UnityEngine;
namespace ADOFAIRenderer.Component
{
[DefaultExecutionOrder(-2147483648)]
public class FirstUpdate : MonoBehaviour
{
private void Update()
{
RenderMod.OnFirstUpdate();
}
}
}
+108
View File
@@ -0,0 +1,108 @@
using System.Collections;
using UnityEngine;
namespace ADOFAIRenderer.Component
{
public class RenderManager : MonoBehaviour
{
public static int Countdown = 0;
public static int FrameCount = 0;
public static bool SkipPressToStart = false;
public static string LevelPath = "";
public static RenderManager Instance = null!;
private static int _originalInputOffset;
public static RenderSettings Configuration;
public struct RenderSettings
{
public double TargetFPS;
public double VideoFPS;
public int RenderWidth;
public int RenderHeight;
public int Bitrate;
public string Codec;
public RenderSettings(double targetFPS, double videoFPS, int renderWidth, int renderHeight, int bitrate, string codec)
{
TargetFPS = targetFPS;
VideoFPS = videoFPS;
RenderWidth = renderWidth;
RenderHeight = renderHeight;
Bitrate = bitrate;
Codec = codec;
}
}
private static bool _renderSetup;
private void Awake()
{
Instance = this;
}
private void Update()
{
if (_renderSetup && ADOBase.lm)
{
ADOBase.lm.hideDifficultyUI = true;
}
if (_renderSetup && scnGame.instance && !scnGame.instance.isLoading)
{
_renderSetup = false;
scrCamera.instance.forceRTCam = true;
scrCamera.instance.SetupRTCam(true);
_originalInputOffset = scrConductor.currentPreset.inputOffset;
scrConductor.currentPreset.inputOffset = 0;
RDC.auto = true;
RenderMod.IsRendering = true;
Countdown = 3;
scrController.instance.StartCoroutine(SetupPlay());
}
if (RenderMod.IsRendering && scrController.instance.state == States.Won)
{
RenderMod.IsRendering = RenderMod.IsCapturing = false;
scrConductor.currentPreset.inputOffset = _originalInputOffset;
}
}
public void SetupGameScene()
{
GCS.customLevelPaths = new[] { LevelPath };
GCS.checkpointNum = 0;
GCS.customLevelId = "";
GCS.nextSpeedRun = 1;
GCS.customLevelIndex = 0;
ADOBase.loader.LoadSceneWithTransition(WipeDirection.StartsFromRight, "scnGame");
SkipPressToStart = true;
_renderSetup = true;
}
private IEnumerator SetupPlay()
{
for (; Countdown > 0; Countdown--)
{
yield return new WaitForSecondsRealtime(1);
}
FrameCount = 0;
RenderMod.IsCapturing = true;
scrController.instance.paused = scrController.instance.audioPaused = false;
scrController.instance.levelWasSkipped = true;
scrConductor.instance.song.clip = null;
scrConductor.instance.song.time = -1000;
}
}
}
+43
View File
@@ -0,0 +1,43 @@
using HarmonyLib;
using UnityEngine;
using UnityEngine.UI;
namespace ADOFAIRenderer.Patch.ClassPatch
{
[HarmonyPatch(typeof(scnEditor))]
// ReSharper disable once InconsistentNaming
public static class scnEditorPatch
{
[HarmonyPostfix]
[HarmonyPatch("Start")]
// ReSharper disable once InconsistentNaming
public static void AddButtonRender(scnEditor __instance)
{
var cloneTarget = __instance.buttonExit!.gameObject;
var buttonContainer = cloneTarget.transform.parent!;
var buttonObj = Object.Instantiate(cloneTarget, buttonContainer)!;
buttonObj.name = "buttonRender";
var button = buttonObj.GetComponent<Button>()!;
// Clear persistent and non-persistent listeners from the original button
button.onClick = new Button.ButtonClickedEvent();
button.onClick.AddListener(RenderMod.StartRender);
// The button root has an Image component for the background (rounded box).
// We want to change the icon sprite, which is on a child GameObject.
var images = buttonObj.GetComponentsInChildren<Image>();
if (images.Length <= 1) return;
// ReSharper disable once Unity.UnknownResource
// images[0] is the background on the root, images[1] is the icon on the child
var sprite = Resources.Load<Sprite>("LevelEditor/LevelEvents/MoveCamera");
if (sprite != null)
{
var iconImage = images[1];
iconImage.sprite = sprite;
iconImage.rectTransform.sizeDelta = new Vector2(24, 24);
}
}
}
}
+16
View File
@@ -0,0 +1,16 @@
using HarmonyLib;
namespace ADOFAIRenderer.Patch.ClassPatch
{
[HarmonyPatch(typeof(scrController))]
// ReSharper disable once InconsistentNaming
public static class scrControllerPatch
{
[HarmonyPrefix]
[HarmonyPatch("TogglePauseGame")]
public static bool PreventPause()
{
return !RenderMod.IsRendering;
}
}
}
+21
View File
@@ -0,0 +1,21 @@
using ADOFAIRenderer.Component;
using HarmonyLib;
namespace ADOFAIRenderer.Patch.ClassPatch
{
[HarmonyPatch(typeof(scrPlayerManager))]
// ReSharper disable once InconsistentNaming
public static class scrPlayerManagerPatch
{
[HarmonyPrefix]
[HarmonyPatch("AnyValidInputWasTriggered")]
// ReSharper disable once InconsistentNaming
private static bool IgnoreInput(ref bool __result)
{
if (!RenderMod.IsRendering) return true;
__result = RenderManager.Countdown == 0;
return false;
}
}
}
+20
View File
@@ -0,0 +1,20 @@
using ADOFAIRenderer.Component;
using HarmonyLib;
namespace ADOFAIRenderer.Patch.ClassPatch
{
[HarmonyPatch(typeof(scrPressToStart))]
// ReSharper disable once InconsistentNaming
public class scrPressToStartPatch
{
[HarmonyPrefix]
[HarmonyPatch("ShowText")]
private static bool PreventShowText()
{
if (!RenderManager.SkipPressToStart) return true;
RenderManager.SkipPressToStart = false;
return false;
}
}
}
+26
View File
@@ -0,0 +1,26 @@
using System.Diagnostics.CodeAnalysis;
using ADOFAIRenderer.Component;
using HarmonyLib;
using UnityEngine;
using UnityEngine.UI;
namespace ADOFAIRenderer.Patch.ClassPatch
{
[HarmonyPatch(typeof(scrShowIfDebug))]
// ReSharper disable once InconsistentNaming
public static class scrShowIfDebugPatch
{
[HarmonyPostfix]
[HarmonyPatch("Update")]
[SuppressMessage("ReSharper", "InconsistentNaming")]
private static void IgnoreInput(Text ___txt, Color ___defaultColor)
{
if (!RenderMod.IsRendering) return;
___txt.text = "Rendering";
if (RenderManager.Countdown > 0) ___txt.text += $" in {RenderManager.Countdown}..";
___txt.color = ___defaultColor;
}
}
}
+143
View File
@@ -0,0 +1,143 @@
using System.Diagnostics.CodeAnalysis;
using ADOFAIRenderer.Component;
using HarmonyLib;
using UnityEngine;
namespace ADOFAIRenderer.Patch
{
public static class RenderEnvironmentPatches
{
private const bool RenderPatch = true;
[HarmonyPatch(typeof(Time), "time", MethodType.Getter)]
public static class TimePatch
{
[SuppressMessage("ReSharper", "InconsistentNaming")]
public static bool Prefix(ref float __result)
{
if (!RenderMod.IsCapturing || !RenderPatch) return true;
__result = (float)(RenderManager.FrameCount / RenderManager.Configuration.TargetFPS);
return false;
}
}
[HarmonyPatch(typeof(Time), "timeAsDouble", MethodType.Getter)]
public static class TimeAsDoublePatch
{
[SuppressMessage("ReSharper", "InconsistentNaming")]
public static bool Prefix(ref double __result)
{
if (!RenderMod.IsCapturing || !RenderPatch) return true;
__result = RenderManager.FrameCount / RenderManager.Configuration.TargetFPS;
return false;
}
}
[HarmonyPatch(typeof(Time), "unscaledTime", MethodType.Getter)]
public static class UnscaledTimePatch
{
[SuppressMessage("ReSharper", "InconsistentNaming")]
public static bool Prefix(ref float __result)
{
if (!RenderMod.IsCapturing || !RenderPatch) return true;
__result = (float)(RenderManager.FrameCount / RenderManager.Configuration.TargetFPS);
return false;
}
}
[HarmonyPatch(typeof(Time), "unscaledTimeAsDouble", MethodType.Getter)]
public static class UnscaledTimeAsDoublePatch
{
[SuppressMessage("ReSharper", "InconsistentNaming")]
public static bool Prefix(ref double __result)
{
if (!RenderMod.IsCapturing || !RenderPatch) return true;
__result = RenderManager.FrameCount / RenderManager.Configuration.TargetFPS;
return false;
}
}
[HarmonyPatch(typeof(AudioSettings), "dspTime", MethodType.Getter)]
public static class DspTimePatch
{
[SuppressMessage("ReSharper", "InconsistentNaming")]
public static bool Prefix(ref double __result)
{
if (!RenderMod.IsCapturing || !RenderPatch) return true;
__result = RenderManager.FrameCount / RenderManager.Configuration.TargetFPS;
return false;
}
}
[HarmonyPatch(typeof(AudioSource), "PlayScheduled")]
public static class PlayScheduledPatch
{
// ReSharper disable once InconsistentNaming
public static bool Prefix(AudioSource __instance, double time)
{
return !RenderMod.IsRendering || !RenderPatch;
}
}
[HarmonyPatch(typeof(Time), "frameCount", MethodType.Getter)]
public static class FrameCountPatch
{
[SuppressMessage("ReSharper", "InconsistentNaming")]
public static bool Prefix(ref int __result)
{
if (!RenderMod.IsCapturing || !RenderPatch) return true;
__result = RenderManager.FrameCount;
return false;
}
}
[HarmonyPatch(typeof(Time), "deltaTime", MethodType.Getter)]
public static class DeltaTimePatch
{
[SuppressMessage("ReSharper", "InconsistentNaming")]
public static bool Prefix(ref float __result)
{
if (!RenderMod.IsCapturing || !RenderPatch) return true;
__result = (float)(1 / RenderManager.Configuration.TargetFPS);
return false;
}
}
[HarmonyPatch(typeof(Time), "unscaledDeltaTime", MethodType.Getter)]
public static class UnscaledDeltaTimePatch
{
[SuppressMessage("ReSharper", "InconsistentNaming")]
public static bool Prefix(ref float __result)
{
if (!RenderMod.IsCapturing || !RenderPatch) return true;
__result = (float)(1 / RenderManager.Configuration.TargetFPS);
return false;
}
}
[HarmonyPatch(typeof(Screen), "width", MethodType.Getter)]
public static class ScreenWidthPatch
{
[SuppressMessage("ReSharper", "InconsistentNaming")]
public static bool Prefix(ref int __result)
{
if (!RenderMod.IsRendering || !RenderPatch) return true;
__result = RenderManager.Configuration.RenderWidth;
return false;
}
}
[HarmonyPatch(typeof(Screen), "height", MethodType.Getter)]
public static class ScreenHeightPatch
{
[SuppressMessage("ReSharper", "InconsistentNaming")]
public static bool Prefix(ref int __result)
{
if (!RenderMod.IsRendering || !RenderPatch) return true;
__result = RenderManager.Configuration.RenderHeight;
return false;
}
}
}
}
+21
View File
@@ -0,0 +1,21 @@
using System.Diagnostics.CodeAnalysis;
using HarmonyLib;
using UnityEngine;
namespace ADOFAIRenderer.Patch
{
[HarmonyPatch(typeof(scrCamera), "SetCustomFrameRate")]
public class SetCustomFrameRatePatch
{
[SuppressMessage("ReSharper", "InconsistentNaming")]
private static bool Prefix(scrCamera __instance, bool enable, float frame, ref MeshRenderer ___camQuadMesh, ref RenderTexture ___camRT)
{
// There is an issue that `mainTexture.Release` triggers even if `mainTexture` is `camRT`, so mod tries to fix it
if (enable || __instance.enableCustomFPS != enable) return true;
__instance.enableCustomFPS = enable;
__instance.frameRate = frame;
return false;
}
}
}
+13
View File
@@ -0,0 +1,13 @@
using HarmonyLib;
namespace ADOFAIRenderer.Patch
{
[HarmonyPatch(typeof(scrHitTextManager), "ShowHitText")]
public class ShowHitTextPatch
{
public static bool Prefix()
{
return !RenderMod.IsRendering;
}
}
}
+97
View File
@@ -0,0 +1,97 @@
using System;
using System.Reflection;
using ADOFAIRenderer;
using ADOFAIRenderer.Component;
using ADOFAIRenderer.Util;
using MelonLoader;
using UnityEngine;
using UnityEngine.EventSystems;
using Object = UnityEngine.Object;
[assembly: MelonInfo(typeof(RenderMod), "ADOFAI Renderer", "0.0.1-INDEV", "ADOFAI Editor Forum")]
[assembly: MelonGame("7th Beat Games", "A Dance of Fire and Ice")]
namespace ADOFAIRenderer
{
public class RenderMod : MelonMod
{
public static AssetBundle FontBundle = null!;
public static AssetBundle SceneBundle = null!;
public static bool WatchGameLoaded;
public static string[] ModScenes = {};
private static double _beforeTime = 0;
public static bool IsRendering = false;
public static bool IsCapturing = false;
public override void OnInitializeMelon()
{
var renderManagerObj = new GameObject("Render Manager");
var updateHookerObj = new GameObject("Update Hooker");
Object.DontDestroyOnLoad( renderManagerObj );
Object.DontDestroyOnLoad( updateHookerObj );
renderManagerObj.AddComponent<RenderManager>();
updateHookerObj.AddComponent<FirstUpdate>();
LoadBundles();
}
private static void LoadBundles()
{
FontBundle = BundleLoader.GetBundle("fonts");
SceneBundle = BundleLoader.GetBundle("scenes");
ModScenes = SceneBundle.GetAllScenePaths();
}
public static void FixEventSystem()
{
if (EventSystem.current == null) return;
var currentModule = EventSystem.current.currentInputModule;
if (currentModule != null) return;
MelonLogger.Msg("Unity 6 인풋 모듈 이식.");
var newModule = EventSystem.current.gameObject.AddComponent<StandaloneInputModule>();
newModule.enabled = true;
}
public static void OnFirstUpdate()
{
if (_beforeTime == 0) _beforeTime = Time.realtimeSinceStartupAsDouble;
var realDeltaTime = Time.realtimeSinceStartupAsDouble - _beforeTime;
_beforeTime = Time.realtimeSinceStartupAsDouble;
if (!IsRendering) return;
RenderManager.FrameCount++;
Time.timeScale = (float)(Time.deltaTime / realDeltaTime);
}
public static void StartRender()
{
var targetMethod = typeof(scnEditor).GetMethod("TryApplicationQuit",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
if (targetMethod == null || scnEditor.instance == null) return;
if (ADOBase.levelPath.IsNullOrEmpty())
{
scnEditor.instance.TryQuitToMenu();
return;
}
RenderManager.LevelPath = ADOBase.levelPath;
scnEditor.instance.CheckUnsavedChanges(() =>
{
var quitDelegate =
(Func<bool>)Delegate.CreateDelegate(typeof(Func<bool>), scnEditor.instance, targetMethod);
Application.wantsToQuit -= quitDelegate;
ADOBase.loader.LoadSceneWithTransition(WipeDirection.StartsFromRight, "Assets/Scenes/RenderSettingsScene.unity");
});
}
}
}
+73
View File
@@ -0,0 +1,73 @@
using ADOFAIRenderer.Component;
using MelonLoader;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace ADOFAIRenderer.UI
{
public class RenderButton : MonoBehaviour
{
[Header("Input Fields")]
[SerializeField] private TMP_InputField targetFPSInput = null!;
[SerializeField] private TMP_InputField videoFPSInput = null!;
[SerializeField] private TMP_InputField renderWidthInput = null!;
[SerializeField] private TMP_InputField renderHeightInput = null!;
[SerializeField] private TMP_InputField bitrateInput = null!;
[Header("Dropdown")]
[SerializeField] private TMP_Dropdown codecDropdown = null!;
private Button _buttonComponent = null!;
private void Start()
{
_buttonComponent = GetComponent<Button>();
_buttonComponent.onClick.AddListener(OnClick);
RenderMod.FixEventSystem();
}
public void OnClick()
{
if (IsAnyFieldEmpty()) return;
Melon<RenderMod>.Logger.Msg($"레벨 로드: {RenderManager.LevelPath}");
double.TryParse(targetFPSInput.text, out var targetFPS);
double.TryParse(videoFPSInput.text, out var videoFPS);
int.TryParse(renderWidthInput.text, out var renderWidth);
int.TryParse(renderHeightInput.text, out var renderHeight);
int.TryParse(bitrateInput.text, out var bitrate);
var selectedCodecIndex = codecDropdown.value;
var selectedCodecName = codecDropdown.options[selectedCodecIndex].text;
RenderManager.Configuration = new RenderManager.RenderSettings
{
TargetFPS = targetFPS,
VideoFPS = videoFPS,
RenderWidth = renderWidth,
RenderHeight = renderHeight,
Bitrate = bitrate,
Codec = selectedCodecName.ToLower(),
};
RenderManager.Instance.SetupGameScene();
}
private bool IsAnyFieldEmpty()
{
if (string.IsNullOrWhiteSpace(targetFPSInput.text)) return true;
if (string.IsNullOrWhiteSpace(videoFPSInput.text)) return true;
if (string.IsNullOrWhiteSpace(renderWidthInput.text)) return true;
if (string.IsNullOrWhiteSpace(renderHeightInput.text)) return true;
if (string.IsNullOrWhiteSpace(bitrateInput.text)) return true;
// 드롭다운은 기본적으로 항상 무언가 선택되어 있지만(0번 항목 등),
// 만약 '선택 안함(-1)' 같은 예외 처리가 필요하다면 아래처럼 검사할 수 있습니다.
if (codecDropdown.value < 0) return true;
return false;
}
}
}
+44
View File
@@ -0,0 +1,44 @@
using System;
using System.Reflection;
using System.Resources;
using MelonLoader;
using UnityEngine;
namespace ADOFAIRenderer.Util
{
public static class BundleLoader
{
private static string BundlePlatform;
private static readonly Assembly? ExecutingAssembly;
static BundleLoader()
{
BundlePlatform = Application.platform switch
{
RuntimePlatform.WindowsPlayer => "Win64",
RuntimePlatform.OSXPlayer => "OSX",
_ => "Linux"
};
ExecutingAssembly = Assembly.GetExecutingAssembly();
}
public static AssetBundle GetBundle(string resourcePath)
{
if (ExecutingAssembly != null)
{
var bundlePath = $"ADOFAIRenderer.Bundle.{BundlePlatform}.{resourcePath}";
using var resourceStream = ExecutingAssembly.GetManifestResourceStream(bundlePath);
if (resourceStream != null)
{
return AssetBundle.LoadFromStream(resourceStream);
}
Melon<RenderMod>.Logger.Error($"DLL에서 번들 리소스를 찾을 수 없습니다.\n{bundlePath}");
throw new MissingManifestResourceException("Could not find bundle resource in DLL.");
}
Melon<RenderMod>.Logger.Error("실행 어셈블리가 제대로 설정되지 않았습니다.");
throw new InvalidOperationException("ExecutingAssembly has not been set.");
}
}
}
+16
View File
@@ -0,0 +1,16 @@
using UnityEngine;
namespace ADOFAIRenderer.Util
{
public class WaitForFrames : CustomYieldInstruction
{
private int _targetFrameCount;
public WaitForFrames(int numberOfFrames)
{
_targetFrameCount = Time.frameCount + numberOfFrames;
}
public override bool keepWaiting => Time.frameCount < _targetFrameCount;
}
}