SHA256
forked from ADOFAIEditorForum/ADOFAIRenderer
Initial Commit
This commit is contained in:
commit
44a22ae103
19 files changed
+772
No files matched your search
+35
@@ -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/
|
||||
@@ -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>
|
||||
@@ -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.
@@ -0,0 +1,13 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace ADOFAIRenderer.Component
|
||||
{
|
||||
[DefaultExecutionOrder(-2147483648)]
|
||||
public class FirstUpdate : MonoBehaviour
|
||||
{
|
||||
private void Update()
|
||||
{
|
||||
RenderMod.OnFirstUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using HarmonyLib;
|
||||
|
||||
namespace ADOFAIRenderer.Patch
|
||||
{
|
||||
[HarmonyPatch(typeof(scrHitTextManager), "ShowHitText")]
|
||||
public class ShowHitTextPatch
|
||||
{
|
||||
public static bool Prefix()
|
||||
{
|
||||
return !RenderMod.IsRendering;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user