Files
ADOFAIRenderer/Patch/Game/scnEditorPatch.cs
T
2026-10-15 18:29:22 +09:00

69 lines
3.0 KiB
C#

using ADOFAIRenderer.Core;
using HarmonyLib;
using MelonLoader;
using UnityEngine;
using UnityEngine.UI;
namespace ADOFAIRenderer.Patch.Game;
/// <summary>
/// Adds the "Render" button to the level editor toolbar.
/// <para>
/// Patched member: <c>scnEditor.Start()</c>, the editor scene setup (it wires the toolbar buttons, including
/// <c>buttonExit</c>). The postfix clones the exit button next to it and makes the clone start a render.
/// </para>
/// <para>
/// Always active except when the mod features are disabled (<see cref="RenderMod.IsFeatureDisabled"/>, set from the
/// driver warning dialog). Runs on the main Unity thread each time the editor scene starts.
/// </para>
/// </summary>
[HarmonyPatch(typeof(scnEditor))]
// ReSharper disable once InconsistentNaming
public static class scnEditorPatch
{
/// <summary>
/// Postfix of <c>scnEditor.Start</c>: instantiates a copy of <c>buttonExit</c> under the same parent, named
/// <c>buttonRender</c>, whose click handler is <see cref="RenderManager.StartRender"/>, and replaces its icon with the
/// editor's MoveCamera event sprite (24 x 24 units). Logs a message and adds nothing when the editor or exit button is missing.
/// When the icon child or the sprite is not found, the button keeps the exit icon.
/// </summary>
/// <param name="__instance">The editor scene component.</param>
[HarmonyPostfix]
[HarmonyPatch("Start")]
// ReSharper disable once InconsistentNaming
public static void AddButtonRender(scnEditor __instance)
{
if (RenderMod.IsFeatureDisabled) return;
if (!__instance || !__instance.buttonExit)
{
Melon<RenderMod>.Logger.Msg("Cannot create render button in scnEditor.");
return;
}
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(RenderManager.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;
// images[0] is the background on the root, images[1] is the icon on the child.
// Sprite path: the icon of the editor's MoveCamera level event, loaded from the game's Resources.
// ReSharper disable once Unity.UnknownResource
var sprite = Resources.Load<Sprite>("LevelEditor/LevelEvents/MoveCamera");
if (sprite == null) return;
var iconImage = images[1];
iconImage.sprite = sprite;
iconImage.rectTransform.sizeDelta = new Vector2(24, 24);
}
}