using System; using System.Collections.Generic; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using GUIFramework; using HarmonyLib; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.PostProcessing; using UnityEngine.UI; using UnityStandardAssets.ImageEffects; using Valheim.SettingsGui; [assembly: AssemblyCompany("Gomisan")] [assembly: AssemblyFileVersion("0.2.0.0")] [assembly: AssemblyInformationalVersion("0.2.0")] [assembly: AssemblyDescription("Valheim graphics controls. Coded with the assistance of ChatGPT 6.0.")] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyTitle("Lumaheim")] [assembly: CompilationRelaxations(8)] [assembly: AssemblyVersion("0.2.0.0")] namespace Lumaheim; public static class DepthOfFieldControls { public struct Scope { public bool Changed; public bool Near; public bool High; public float Distance; public float Range; public float Blur; public Transform Target; public BlurSampleCount Samples; } public static bool Applies(Component component) { if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.GetComponent())) { return Object.op_Implicit((Object)(object)component.GetComponent()); } return false; } public static Scope Begin(DepthOfField effect, VideoValues values) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) Scope result = default(Scope); if (values.DofMode == 0) { return result; } result.Changed = true; result.Distance = effect.focalLength; result.Range = effect.focalSize; result.Blur = effect.maxBlurSize; result.Near = effect.nearBlur; result.High = effect.highResolution; result.Samples = effect.blurSampleCount; result.Target = effect.focalTransform; if (values.DofMode == 2) { effect.focalTransform = null; effect.focalLength = values.FocusDistance; } effect.focalSize = values.FocusRange; effect.maxBlurSize = Mathf.Clamp(result.Blur * values.BlurStrength, 0.1f, 10f); if (values.Foreground != 0) { effect.nearBlur = values.Foreground == 2; } if (values.Quality != 0) { effect.blurSampleCount = (BlurSampleCount)Mathf.Min(values.Quality - 1, 2); effect.highResolution = values.Quality == 4; } return result; } public static void End(DepthOfField effect, Scope state) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)effect) && state.Changed) { effect.focalLength = state.Distance; effect.focalSize = state.Range; effect.maxBlurSize = state.Blur; effect.nearBlur = state.Near; effect.highResolution = state.High; effect.blurSampleCount = state.Samples; effect.focalTransform = state.Target; } } } [HarmonyPatch(typeof(DepthOfField), "OnRenderImage")] internal static class DepthRenderPatch { private static void Prefix(DepthOfField __instance, out DepthOfFieldControls.Scope __state) { __state = default(DepthOfFieldControls.Scope); if (Plugin.Session != null && DepthOfFieldControls.Applies((Component)(object)__instance)) { __state = DepthOfFieldControls.Begin(__instance, Plugin.Session.Current); } } private static void Finalizer(DepthOfField __instance, DepthOfFieldControls.Scope __state) { DepthOfFieldControls.End(__instance, __state); } } [HarmonyPatch(typeof(CameraEffects), "UpdateDOF")] internal static class AutofocusPatch { private static void Prefix(CameraEffects __instance, out bool __state) { __state = __instance.m_dofAutoFocus; if (Plugin.Session != null && DepthOfFieldControls.Applies((Component)(object)__instance) && Plugin.Session.Current.DofMode == 1) { __instance.m_dofAutoFocus = true; } } private static void Finalizer(CameraEffects __instance, bool __state) { if (Object.op_Implicit((Object)(object)__instance)) { __instance.m_dofAutoFocus = __state; } } } public static class Grading { private sealed class Entry { internal ColorGradingModel Source; internal readonly ColorGradingModel Model = new ColorGradingModel(); internal VideoValues Values; internal Settings SourceSettings; internal bool Invalid = true; } public struct Scope { internal ColorGradingModel Original; internal float PreviousGamma; } private static readonly Dictionary Entries = new Dictionary(); public static float ActiveGamma = 1f; public static Settings Compose(Settings settings, VideoValues values) { //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Expected O, but got Unknown //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Expected O, but got Unknown ref BasicSettings basic = ref settings.basic; basic.postExposure += values.Exposure; settings.basic.temperature = Mathf.Clamp(settings.basic.temperature + values.Warmth, -100f, 100f); settings.basic.tint = Mathf.Clamp(settings.basic.tint + values.Tint, -100f, 100f); ref BasicSettings basic2 = ref settings.basic; basic2.contrast *= values.Contrast; ref BasicSettings basic3 = ref settings.basic; basic3.saturation *= values.Saturation; if (values.ShadowDetail != 0f || values.HighlightDetail != 0f) { Keyframe[] array = (Keyframe[])(object)new Keyframe[129]; for (int i = 0; i < array.Length; i++) { float num = (float)i / 128f; float x = settings.curves.master.Evaluate(num); float num2 = AdjustDetail(x, values.ShadowDetail, values.HighlightDetail); ref Keyframe reference = ref array[i]; reference = new Keyframe(num, num2); } for (int j = 0; j < array.Length; j++) { float inTangent = ((j > 0) ? ((((Keyframe)(ref array[j])).value - ((Keyframe)(ref array[j - 1])).value) * 128f) : 0f); float outTangent = ((j < 128) ? ((((Keyframe)(ref array[j + 1])).value - ((Keyframe)(ref array[j])).value) * 128f) : 0f); ((Keyframe)(ref array[j])).inTangent = inTangent; ((Keyframe)(ref array[j])).outTangent = outTangent; } settings.curves.master = new ColorGradingCurve(new AnimationCurve(array), 0f, false, new Vector2(0f, 1f)); } return settings; } public static float AdjustDetail(float x, float shadows, float highlights) { x = Mathf.Clamp01(x); if (x < 0.5f) { return x + 0.9f * (shadows / 100f) * x * (1f - 2f * x) * (1f - 2f * x); } return x - 0.9f * (highlights / 100f) * (1f - x) * (2f * x - 1f) * (2f * x - 1f); } public static Scope Begin(ColorGradingComponent component, VideoValues values) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) if (values.IsColorDefault) { Release(component); return default(Scope); } if (!Entries.TryGetValue(component, out var value)) { value = new Entry(); Entries.Add(component, value); } ColorGradingModel model = ((PostProcessingComponent)(object)component).model; Settings settings = model.settings; if (!value.Invalid && value.Source == model && value.Values.Equals(values)) { ref Settings sourceSettings = ref value.SourceSettings; object obj = settings; if (((object)Unsafe.As(ref sourceSettings)/*cast due to .constrained prefix*/).Equals(obj)) { goto IL_00ba; } } value.Model.settings = Compose(settings, values); value.Values = values; value.SourceSettings = settings; value.Source = model; value.Invalid = false; goto IL_00ba; IL_00ba: if (((PostProcessingModel)value.Model).enabled != ((PostProcessingModel)model).enabled) { ((PostProcessingModel)value.Model).enabled = ((PostProcessingModel)model).enabled; } Scope result = new Scope { Original = model, PreviousGamma = ActiveGamma }; ((PostProcessingComponent)(object)component).Init(((PostProcessingComponentBase)component).context, value.Model); ActiveGamma = values.Gamma; return result; } public static void End(ColorGradingComponent component, Scope scope) { if (scope.Original != null) { ((PostProcessingComponent)(object)component).Init(((PostProcessingComponentBase)component).context, scope.Original); ActiveGamma = scope.PreviousGamma; } } public static void Invalidate(ColorGradingModel model) { foreach (Entry value in Entries.Values) { if (value.Source == model) { value.Invalid = true; } } } private static void Dispose(Entry entry) { RenderTexture bakedLut = entry.Model.bakedLut; if (Object.op_Implicit((Object)(object)bakedLut)) { if ((Object)(object)RenderTexture.active == (Object)(object)bakedLut) { RenderTexture.active = null; } bakedLut.Release(); if (Application.isPlaying) { Object.Destroy((Object)(object)bakedLut); } else { Object.DestroyImmediate((Object)(object)bakedLut); } } } public static void Release(ColorGradingComponent component) { if (Entries.TryGetValue(component, out var value)) { Dispose(value); Entries.Remove(component); } } internal static void ReleaseAll() { foreach (Entry value in Entries.Values) { Dispose(value); } Entries.Clear(); ActiveGamma = 1f; } } [HarmonyPatch(typeof(ColorGradingComponent), "Prepare")] internal static class PreparePatch { private static void Prefix(ColorGradingComponent __instance, out Grading.Scope __state) { __state = default(Grading.Scope); if (Plugin.Session != null && ((PostProcessingComponentBase)__instance).context != null && Object.op_Implicit((Object)(object)((PostProcessingComponentBase)__instance).context.camera) && Object.op_Implicit((Object)(object)((Component)((PostProcessingComponentBase)__instance).context.camera).GetComponent())) { __state = Grading.Begin(__instance, Plugin.Session.Current); } } private static void Finalizer(ColorGradingComponent __instance, Grading.Scope __state) { Grading.End(__instance, __state); } } [HarmonyPatch(typeof(ColorGradingComponent), "GetGammaValue")] internal static class GammaPatch { private static void Postfix(ref Vector3 __result) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) __result /= Grading.ActiveGamma; } } [HarmonyPatch(typeof(ColorGradingModel), "OnValidate")] internal static class ValidatePatch { private static void Postfix(ColorGradingModel __instance) { Grading.Invalidate(__instance); } } [HarmonyPatch(typeof(ColorGradingComponent), "OnDisable")] internal static class ReleasePatch { private static void Prefix(ColorGradingComponent __instance) { Grading.Release(__instance); } } public sealed class GraphicsPage : MonoBehaviour { private readonly List created = new List(); private readonly List sliders = new List(); private readonly List values = new List(); private List navigationSliders; private Button reset; private Selectable beforeControls; private Selectable afterControls; private readonly List