Files
ADOFAIRenderer/Patch/Game/scnGamePatch.cs
T

138 lines
4.9 KiB
C#

using System.IO;
using ADOFAIRenderer.Core;
using ADOFAIRenderer.Util;
using HarmonyLib;
using UnityEngine;
namespace ADOFAIRenderer.Patch.Game;
[HarmonyPatch(typeof(scnGame))]
// ReSharper disable once InconsistentNaming
public static class scnGamePatch
{
[HarmonyPostfix]
[HarmonyPatch("Play")]
public static void ProcessFloors()
{
var nonTile = RenderManager.Instance.stage >= RenderStage.Load &&
RenderManager.Instance.Configuration.AdvancedConfig.NonTile;
if (!nonTile) return;
foreach (var floor in scrLevelMaker.instance.listFloors)
{
DisableRenderers(
floor.floorRenderer.renderer, floor.legacyFloorSpriteRenderer,
floor.iconsprite, floor.outlineSprite,
floor.topGlow, floor.bottomGlow,
floor.multiplanetLine
);
if (floor.holdRenderer) DisableRenderer(floor.holdRenderer.m_meshRenderer);
if (floor.dummyPlanets == null) continue;
foreach (var planet in floor.dummyPlanets)
DisablePlanetRenderer(planet);
}
var players = scrPlayerManager.instance.players;
if (players == null) return;
foreach (var player in players)
{
var planets = player.planetarySystem?.planetList;
if (planets == null) continue;
foreach (var planet in planets)
DisablePlanetRenderer(planet.planetRenderer);
}
return;
void DisablePlanetRenderer(PlanetRenderer planet)
{
if (planet.sprite) DisableRenderer(planet.sprite.meshRenderer);
DisableRenderers(
planet.coreParticles.GetRenderer(), planet.tailParticles.GetRenderer(),
planet.tailParticlesCoop.GetRenderer(), planet.sparks.GetRenderer(), planet.ring, planet.glow,
planet.faceSprite, planet.faceDetails, planet.samuraiSprite
);
}
void DisableRenderers(params Renderer?[] renderers)
{
foreach (var renderer in renderers) DisableRenderer(renderer);
}
void DisableRenderer(Renderer? renderer)
{
if (renderer) renderer.enabled = false;
}
}
[HarmonyPrefix]
[HarmonyPatch("UpdateVideo")]
// ReSharper disable once InconsistentNaming
public static bool ReplaceVideo(scnGame __instance)
{
// Only replace when rendering is active
if (!RenderManager.IsActive)
{
// Remove FFmpeg player if it was attached previously
var oldPlayer = __instance.videoBG.gameObject.GetComponent<VideoBGPlayer>();
if (oldPlayer) Object.Destroy(oldPlayer);
// Re-enable native player component
__instance.videoBG.enabled = true;
return true; // Execute original
}
string text = __instance.levelData.miscSettings.GetString("bgVideo");
if (string.IsNullOrEmpty(text))
{
__instance.videoBG.gameObject.SetActive(false);
return false; // Skip original
}
__instance.videoBG.gameObject.SetActive(true);
// We can only play external video files via FFmpegNativeDecoder.
// Internal/Bundle level background videos are built-in VideoClips, so we fall back to native Unity VideoPlayer.
if (ADOBase.isInternalLevel || ADOBase.isBundleLevel)
{
__instance.videoBG.enabled = true;
return true; // Execute original
}
// Custom level video path
var videoPath = Path.Combine(Path.GetDirectoryName(ADOBase.levelPath) ?? "", text);
if (!File.Exists(videoPath))
{
return true; // Let the original print error
}
// Disable native VideoPlayer component (to prevent it from attempting real-time playback and sync errors)
var targetCamera = __instance.videoBG.targetCamera;
if (!targetCamera)
{
var camGo = GameObject.Find("BGStaticCam");
if (camGo != null)
{
targetCamera = camGo.GetComponent<Camera>();
}
}
__instance.videoBG.enabled = false;
// Add or retrieve our custom FFmpeg video background player
if (!__instance.videoBG.gameObject.TryGetComponent<VideoBGPlayer>(out var player))
{
player = __instance.videoBG.gameObject.AddComponent<VideoBGPlayer>();
}
var isLooping = __instance.levelData.miscSettings.GetBool("loopVideo");
// Initialize player. If targetTexture is null (CameraFarPlane mode), it will build a quad in front of targetCamera.
player.Init(videoPath, __instance.videoBG.targetTexture, isLooping, targetCamera, __instance.videoBG.gameObject);
return false; // Skip original UpdateVideo
}
}