Decompiled source of ShaderEdit v1.0.0

BepInEx/plugins/ShaderEdit/ShaderEdit.dll

Decompiled 2 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Rendering.PostProcessing;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ShaderEdit")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ShaderEdit")]
[assembly: AssemblyTitle("ShaderEdit")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ShaderEdit;

public struct FogValues
{
	public bool Enabled;

	public int Mode;

	public float Start;

	public float End;

	public float Density;

	public float FarClip;
}
public interface IFogEnvironment
{
	int SceneToken { get; }

	bool IsValid { get; }

	FogValues Read();

	void Write(FogValues values);
}
public sealed class FogRenderOverride
{
	private IFogEnvironment environment;

	private FogValues original;

	private int sceneToken;

	public void Begin(IFogEnvironment target, string mode)
	{
		End();
		if (!(mode == "Default") && target.IsValid)
		{
			original = target.Read();
			sceneToken = target.SceneToken;
			environment = target;
			target.Write(Calculate(original, mode));
		}
	}

	public void End()
	{
		if (environment != null)
		{
			IFogEnvironment fogEnvironment = environment;
			environment = null;
			if (fogEnvironment.IsValid && fogEnvironment.SceneToken == sceneToken)
			{
				fogEnvironment.Write(original);
			}
		}
	}

	public static FogValues Calculate(FogValues value, string mode)
	{
		if (!value.Enabled)
		{
			return value;
		}
		if (mode == "DoubleDistance")
		{
			value.Start *= 2f;
			value.End *= 2f;
			value.Density *= 0.5f;
			value.FarClip = Math.Max(value.FarClip, (value.Mode == 1) ? (value.End + 1f) : (value.FarClip * 2f));
		}
		else if (mode == "Off")
		{
			value.Enabled = false;
			value.FarClip = Math.Max(value.FarClip, 1000f);
		}
		return value;
	}
}
public sealed class ModSettings
{
	public static readonly string[] EffectNames = new string[5] { "Bloom", "Vignette", "ColorGrading", "LensDistortion", "ChromaticAberration" };

	private readonly Dictionary<string, ConfigEntry<bool>> effects = new Dictionary<string, ConfigEntry<bool>>();

	public ConfigEntry<bool> Enabled { get; }

	public ConfigEntry<bool> EnableHotkey { get; }

	public ConfigEntry<string> Fog { get; }

	public ConfigEntry<float> Brightness { get; }

	public ModSettings(ConfigFile config)
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Expected O, but got Unknown
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Expected O, but got Unknown
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Expected O, but got Unknown
		//IL_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Expected O, but got Unknown
		//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fe: Expected O, but got Unknown
		bool saveOnConfigSet = config.SaveOnConfigSet;
		config.SaveOnConfigSet = false;
		try
		{
			ConfigEntry<string> val = config.Bind<string>("General", "Mode", "NoBloomAndColorGrading", new ConfigDescription("Legacy mode, migrated automatically.", (AcceptableValueBase)null, new object[1] { "HideFromREPOConfig" }));
			ConfigEntry<bool> val2 = config.Bind<bool>("General", "EnableCycleKey", true, new ConfigDescription("Legacy hotkey setting.", (AcceptableValueBase)null, new object[1] { "HideFromREPOConfig" }));
			Enabled = config.Bind<bool>("General", "ModEnabled", val.Value != "Original", "MOD設定の適用。OFFで元の表示に戻ります。各エフェクトの設定は保持されます。F8でも切り替えられます。");
			EnableHotkey = config.Bind<bool>("General", "EnableHotkey", val2.Value, "ショートカットによるMOD全体のON/OFFを有効にします。初期キーはF8です。");
			Brightness = config.Bind<float>("Brightness", "Multiplier", 2f, new ConfigDescription("明るさ倍率。1.0=補正なし、2.0=露出2倍。ColorGradingがOFFでも使用できます。F8でMODをOFFにすると補正も解除します。 / Brightness multiplier, independent of color grading.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>()));
			Fog = config.Bind<string>("Fog", "Distance", "DoubleDistance", new ConfigDescription("霧: Default=デフォルト / DoubleDistance=プレイヤーから霧までの距離2倍 / Off=霧オフ。MOD全体がONのときに適用します。", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[3] { "Default", "DoubleDistance", "Off" }), Array.Empty<object>()));
			string[] effectNames = EffectNames;
			foreach (string text in effectNames)
			{
				effects.Add(text, config.Bind<bool>("Effects", text, LegacyAllows(val.Value, text), "ON: ゲーム本来の設定に従います。OFF: このエフェクトを無効化します。 / ON: follow game settings; OFF: suppress this effect."));
			}
			effectNames = new string[6] { "Grain", "MotionBlur", "AmbientOcclusion", "AutoExposure", "DepthOfField", "ScreenSpaceReflections" };
			foreach (string text2 in effectNames)
			{
				ConfigEntry<bool> val3 = config.Bind<bool>("Effects", text2, true, new ConfigDescription("Retired effect setting.", (AcceptableValueBase)null, new object[1] { "HideFromREPOConfig" }));
				config.Remove(((ConfigEntryBase)val3).Definition);
			}
			config.Remove(((ConfigEntryBase)val).Definition);
			config.Remove(((ConfigEntryBase)val2).Definition);
		}
		finally
		{
			config.SaveOnConfigSet = saveOnConfigSet;
		}
		config.Save();
	}

	public bool IsEffectEnabled(string name)
	{
		if (effects.TryGetValue(name, out var value))
		{
			return value.Value;
		}
		return true;
	}

	private static bool LegacyAllows(string mode, string name)
	{
		if (name == "ChromaticAberration")
		{
			return false;
		}
		if (mode == "NoPostProcessingEffects")
		{
			return false;
		}
		switch (name)
		{
		case "Bloom":
			if (mode != "NoBloom")
			{
				return mode != "NoBloomAndColorGrading";
			}
			return false;
		case "ColorGrading":
			if (mode != "NoColorGrading" && mode != "NoBloomAndColorGrading")
			{
				return mode != "NoColorGradingAndVignette";
			}
			return false;
		case "Vignette":
			if (mode != "NoVignette")
			{
				return mode != "NoColorGradingAndVignette";
			}
			return false;
		default:
			return true;
		}
	}
}
[BepInPlugin("local.repo.playervieweffects", "ShaderEdit", "1.0.0")]
[BepInProcess("REPO.exe")]
public sealed class Plugin : BaseUnityPlugin
{
	private struct SavedState
	{
		public bool Value;

		public bool Override;
	}

	private sealed class UnityFogEnvironment : IFogEnvironment
	{
		public Camera Camera { get; }

		public int SceneToken
		{
			get
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				Scene activeScene = SceneManager.GetActiveScene();
				return SceneHandle.op_Implicit(((Scene)(ref activeScene)).handle);
			}
		}

		public bool IsValid => Object.op_Implicit((Object)(object)Camera);

		public UnityFogEnvironment(Camera camera)
		{
			Camera = camera;
		}

		public FogValues Read()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected I4, but got Unknown
			return new FogValues
			{
				Enabled = RenderSettings.fog,
				Mode = (int)RenderSettings.fogMode,
				Start = RenderSettings.fogStartDistance,
				End = RenderSettings.fogEndDistance,
				Density = RenderSettings.fogDensity,
				FarClip = Camera.farClipPlane
			};
		}

		public void Write(FogValues value)
		{
			RenderSettings.fog = value.Enabled;
			RenderSettings.fogStartDistance = value.Start;
			RenderSettings.fogEndDistance = value.End;
			RenderSettings.fogDensity = value.Density;
			Camera.farClipPlane = value.FarClip;
		}
	}

	private ModSettings settings;

	private ConfigEntry<KeyboardShortcut> toggleKey;

	private readonly Dictionary<PostProcessEffectSettings, SavedState> saved = new Dictionary<PostProcessEffectSettings, SavedState>();

	private readonly List<PostProcessEffectSettings> stale = new List<PostProcessEffectSettings>();

	private PostProcessVolume[] volumes = (PostProcessVolume[])(object)new PostProcessVolume[0];

	private readonly FogRenderOverride fogOverride = new FogRenderOverride();

	private UnityFogEnvironment fogEnvironment;

	private bool restoreRequested;

	private bool lastEnabled;

	private float nextScan;

	private float noticeUntil;

	private static Plugin instance;

	private Harmony harmony;

	private string lastFogDiagnostic;

	private void Awake()
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Expected O, but got Unknown
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Expected O, but got Unknown
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Expected O, but got Unknown
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c2: Expected O, but got Unknown
		settings = new ModSettings(((BaseUnityPlugin)this).Config);
		bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet;
		((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
		ConfigEntry<KeyboardShortcut> val = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "CycleKey", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), new ConfigDescription("Legacy shortcut.", (AcceptableValueBase)null, new object[1] { "HideFromREPOConfig" }));
		toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "ToggleKey", val.Value, new ConfigDescription("Toggle between original rendering and configured mod effects. Edit this shortcut in the cfg file.", (AcceptableValueBase)null, new object[1] { "HideFromREPOConfig" }));
		((BaseUnityPlugin)this).Config.Remove(((ConfigEntryBase)val).Definition);
		((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet;
		((BaseUnityPlugin)this).Config.Save();
		((BaseUnityPlugin)this).Config.SettingChanged += OnSettingChanged;
		lastEnabled = settings.Enabled.Value;
		instance = this;
		harmony = new Harmony("local.repo.playervieweffects.fog-render-order");
		try
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(PostProcessLayer), "OnPreCull", (Type[])null, (Type[])null);
			harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(Plugin), "BeforePostProcessSetup", (Type[])null)
			{
				priority = 800
			}, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Could not install the fog preparation hook. Fog changes on post-processed cameras are skipped. " + ex));
		}
		try
		{
			MethodInfo methodInfo2 = AccessTools.Method(typeof(PostProcessManager), "UpdateSettings", (Type[])null, (Type[])null);
			harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "AfterVolumeBlend", (Type[])null)
			{
				priority = 0
			}, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		catch (Exception ex2)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Could not install the independent brightness hook. " + ex2));
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ShaderEdit 1.0.0 loaded. F8 toggles all configured adjustments.");
	}

	private void OnSettingChanged(object sender, SettingChangedEventArgs args)
	{
		restoreRequested = true;
		lastFogDiagnostic = null;
	}

	private void OnEnable()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Expected O, but got Unknown
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected O, but got Unknown
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Expected O, but got Unknown
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Expected O, but got Unknown
		Camera.onPreCull = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(BeforeCameraRender));
		Camera.onPostRender = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(AfterCameraRender));
		nextScan = 0f;
	}

	private void Update()
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		fogOverride.End();
		if (settings != null && settings.EnableHotkey.Value)
		{
			KeyboardShortcut value = toggleKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				settings.Enabled.Value = !settings.Enabled.Value;
			}
		}
	}

	private void LateUpdate()
	{
		if (settings == null)
		{
			return;
		}
		if (restoreRequested)
		{
			RestoreEffects();
			restoreRequested = false;
			nextScan = 0f;
		}
		if (lastEnabled != settings.Enabled.Value)
		{
			lastEnabled = settings.Enabled.Value;
			noticeUntil = Time.unscaledTime + 4f;
			((BaseUnityPlugin)this).Logger.LogInfo((object)(lastEnabled ? "Configured effects applied." : "Original rendering restored."));
		}
		if (!settings.Enabled.Value)
		{
			return;
		}
		if (Time.unscaledTime >= nextScan)
		{
			volumes = Object.FindObjectsByType<PostProcessVolume>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			nextScan = Time.unscaledTime + 1f;
		}
		stale.Clear();
		foreach (KeyValuePair<PostProcessEffectSettings, SavedState> item in saved)
		{
			if (!Object.op_Implicit((Object)(object)item.Key))
			{
				stale.Add(item.Key);
			}
		}
		foreach (PostProcessEffectSettings item2 in stale)
		{
			saved.Remove(item2);
		}
		PostProcessVolume[] array = volumes;
		foreach (PostProcessVolume val in array)
		{
			if (!Object.op_Implicit((Object)(object)val) || !((Behaviour)val).isActiveAndEnabled || val.weight <= 0f)
			{
				continue;
			}
			PostProcessProfile profile = val.profile;
			if (!Object.op_Implicit((Object)(object)profile))
			{
				continue;
			}
			foreach (PostProcessEffectSettings setting in profile.settings)
			{
				if (Object.op_Implicit((Object)(object)setting) && !settings.IsEffectEnabled(((object)setting).GetType().Name))
				{
					if (!saved.ContainsKey(setting))
					{
						saved.Add(setting, new SavedState
						{
							Value = ((ParameterOverride<bool>)(object)setting.enabled).value,
							Override = ((ParameterOverride)setting.enabled).overrideState
						});
					}
					((ParameterOverride)setting.enabled).overrideState = true;
					((ParameterOverride<bool>)(object)setting.enabled).value = false;
				}
			}
		}
	}

	private void BeforeCameraRender(Camera camera)
	{
		PostProcessLayer component = ((Component)camera).GetComponent<PostProcessLayer>();
		if (!Object.op_Implicit((Object)(object)component) || !((Behaviour)component).isActiveAndEnabled)
		{
			ApplyFogBeforeSetup(camera);
		}
	}

	private static void BeforePostProcessSetup(PostProcessLayer __instance)
	{
		if (Object.op_Implicit((Object)(object)instance) && ((Behaviour)instance).isActiveAndEnabled)
		{
			instance.ApplyFogBeforeSetup(((Component)__instance).GetComponent<Camera>());
		}
	}

	private static void AfterVolumeBlend(PostProcessLayer __0, Camera __1)
	{
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		Plugin plugin = instance;
		if (!Object.op_Implicit((Object)(object)plugin) || !((Behaviour)plugin).isActiveAndEnabled || plugin.settings == null || !plugin.settings.Enabled.Value || (Object)(object)__1 != (Object)(object)Camera.main || plugin.settings.Brightness.Value <= 1f)
		{
			return;
		}
		AutoExposure val = __0.GetSettings<AutoExposure>();
		if (Object.op_Implicit((Object)(object)val))
		{
			float value = plugin.settings.Brightness.Value;
			if (((ParameterOverride<bool>)(object)((PostProcessEffectSettings)val).enabled).value)
			{
				FloatParameter keyValue = val.keyValue;
				((ParameterOverride<float>)(object)keyValue).value = ((ParameterOverride<float>)(object)keyValue).value * value;
				return;
			}
			((ParameterOverride<bool>)(object)((PostProcessEffectSettings)val).enabled).value = true;
			((ParameterOverride<float>)(object)val.minLuminance).value = 0f;
			((ParameterOverride<float>)(object)val.maxLuminance).value = 0f;
			((ParameterOverride<float>)(object)val.keyValue).value = value;
			((ParameterOverride<EyeAdaptation>)(object)val.eyeAdaptation).value = (EyeAdaptation)1;
		}
	}

	private void ApplyFogBeforeSetup(Camera camera)
	{
		if (Object.op_Implicit((Object)(object)camera) && settings != null && settings.Enabled.Value && !(settings.Fog.Value == "Default") && !((Object)(object)camera != (Object)(object)Camera.main))
		{
			if (fogEnvironment == null || (Object)(object)fogEnvironment.Camera != (Object)(object)camera)
			{
				fogEnvironment = new UnityFogEnvironment(camera);
				lastFogDiagnostic = null;
			}
			FogValues fogValues = fogEnvironment.Read();
			fogOverride.Begin(fogEnvironment, settings.Fog.Value);
			if (lastFogDiagnostic != settings.Fog.Value)
			{
				FogValues fogValues2 = fogEnvironment.Read();
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Fog {settings.Fog.Value} prepared before post-processing: start/end {fogValues.Start}/{fogValues.End} -> {fogValues2.Start}/{fogValues2.End}, fog {fogValues.Enabled} -> {fogValues2.Enabled}, far clip {fogValues.FarClip} -> {fogValues2.FarClip}.");
				lastFogDiagnostic = settings.Fog.Value;
			}
		}
	}

	private void AfterCameraRender(Camera camera)
	{
		if (fogEnvironment != null && (Object)(object)fogEnvironment.Camera == (Object)(object)camera)
		{
			fogOverride.End();
		}
	}

	private void RestoreEffects()
	{
		foreach (KeyValuePair<PostProcessEffectSettings, SavedState> item in saved)
		{
			if (Object.op_Implicit((Object)(object)item.Key))
			{
				((ParameterOverride<bool>)(object)item.Key.enabled).value = item.Value.Value;
				((ParameterOverride)item.Key.enabled).overrideState = item.Value.Override;
			}
		}
		saved.Clear();
	}

	private void OnGUI()
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		if (settings != null && Time.unscaledTime < noticeUntil)
		{
			GUI.Box(new Rect(20f, 20f, 480f, 38f), "ShaderEdit: " + (settings.Enabled.Value ? "MOD settings applied" : "Original"));
		}
	}

	private void OnDisable()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Expected O, but got Unknown
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected O, but got Unknown
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Expected O, but got Unknown
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Expected O, but got Unknown
		Camera.onPreCull = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(BeforeCameraRender));
		Camera.onPostRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(AfterCameraRender));
		fogOverride.End();
		RestoreEffects();
	}

	private void OnDestroy()
	{
		((BaseUnityPlugin)this).Config.SettingChanged -= OnSettingChanged;
		OnDisable();
		Harmony obj = harmony;
		if (obj != null)
		{
			obj.UnpatchSelf();
		}
		if ((Object)(object)instance == (Object)(object)this)
		{
			instance = null;
		}
	}
}