From a8c54700446b892efbed2253321a17a4989393a5 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Thu, 30 Jul 2026 14:50:42 -0400 Subject: Factor out lights, lots of cleanup Signed-off-by: Andrew Opalach --- Config.cs | 17 ++- LUT.cs | 61 +++----- Lights.cs | 264 ++++++++++++++++++++++++++++++++++ Plugin.cs | 478 +++++++++++++++----------------------------------------------- 4 files changed, 410 insertions(+), 410 deletions(-) mode change 100755 => 100644 Config.cs create mode 100644 Lights.cs mode change 100755 => 100644 Plugin.cs diff --git a/Config.cs b/Config.cs old mode 100755 new mode 100644 index 3c14fa4..d456269 --- a/Config.cs +++ b/Config.cs @@ -1,8 +1,12 @@ -using SharpPluginLoader.Core.Configuration; +//#define SHADER_FEATURES + +using SharpPluginLoader.Core.Configuration; using SharpPluginLoader.Core; namespace WorldTuningTool { + using static Plugin; + public enum StageExt : uint { Global = 0, @@ -45,7 +49,7 @@ namespace WorldTuningTool SelianaRoom = 506 } - internal class Config : IConfig + public class Config : IConfig { public String Name => "WorldTuningTool"; public String Version => "0.9.4"; @@ -136,6 +140,7 @@ namespace WorldTuningTool public static readonly StageExt[] OrderedStages = { + StageExt.Global, StageExt.Astera, StageExt.AsteraHub, StageExt.ResearchBase, @@ -177,7 +182,9 @@ namespace WorldTuningTool public struct PatchConfig { +#if SHADER_FEATURES public bool FullResolutionSSLR { get; set; } = false; +#endif public bool FullResolutionVolumeBlur { get; set; } = false; public bool HigherThanHighestVolumeRendering { get; set; } = false; public bool DisableLODLimits { get; set; } = false; @@ -188,9 +195,9 @@ namespace WorldTuningTool public PatchConfig Patches { get; set; } = new PatchConfig(); - public Dictionary> Globals { get; set; } = new Dictionary>(); + public Dictionary> Globals { get; set; } = new Dictionary>(); public string SelectedGlobal { get; set; } = ""; - public Dictionary> Overrides { get; set; } = new Dictionary>(); - public Dictionary> Sets { get; set; } = new Dictionary>(); + public Dictionary> Overrides { get; set; } = new Dictionary>(); + public Dictionary> Sets { get; set; } = new Dictionary>(); } } diff --git a/LUT.cs b/LUT.cs index f38010c..b688f0e 100644 --- a/LUT.cs +++ b/LUT.cs @@ -11,11 +11,13 @@ using SharpPluginLoader.Core.IO; namespace WorldTuningTool { - public class WorldLUTs + using static Plugin; + + public class LUT { private const string addPath = "nativePC/plugins/CSharp/LUT"; - public WorldLUTs() { } + public LUT() { } // https://github.com/AsteriskAmpersand/CrappyLUTStudio--CLUTS-/blob/5af10daaa5f295b106cc5db09530a6fe5a4320d4/LUT.py#L35 private byte[]? parseWorldLUT(BinaryReader reader) @@ -57,7 +59,7 @@ namespace WorldTuningTool { string? line; Vector3[]? parsed = null; - int dim = 0, idx = 0; + int dim = 0, i = 0; while ((line = reader.ReadLine()) != null) { if (line.StartsWith("LUT_3D_SIZE")) @@ -66,18 +68,8 @@ namespace WorldTuningTool { dim = Convert.ToInt32(line.Split(' ').Last()); } - catch (FormatException) - { - return null; - } - catch (OverflowException) - { - return null; - } - if (dim != 32) - { - return null; - } + catch (Exception) { return null; } + if (dim != 32) return null; parsed = new Vector3[dim * dim * dim]; while ((line = reader.ReadLine()) != null) { @@ -87,26 +79,15 @@ namespace WorldTuningTool break; } } - if (line == null) - { - break; - } + if (line == null) break; } if (parsed != null) { try { - parsed[idx] = Plugin.StringToVector3(line, ' '); - } - catch (FormatException) - { - return null; - } - catch (OverflowException) - { - return null; + parsed[i++] = StringToVector3(line, ' '); } - idx++; + catch (Exception) { return null; } } } if (parsed == null) @@ -116,24 +97,24 @@ namespace WorldTuningTool const int lutDataSize = 32 * 32 * 32 * 8; byte[] data = new byte[lutDataSize]; float scale = MathF.Pow(2, 14) - 1; - for (idx = 0; idx < lutDataSize; idx+=8) + for (i = 0; i < lutDataSize; i += 8) { - Vector3 v = parsed[idx/8]; + Vector3 v = parsed[i / 8]; ushort normX = (ushort)Math.Round(v.X * scale); ushort normY = (ushort)Math.Round(v.Y * scale); ushort normZ = (ushort)Math.Round(v.Z * scale); byte[] bytes = BitConverter.GetBytes(normX); - data[idx] = bytes[0]; - data[idx + 1] = bytes[1]; + data[i] = bytes[0]; + data[i + 1] = bytes[1]; bytes = BitConverter.GetBytes(normY); - data[idx + 2] = bytes[0]; - data[idx + 3] = bytes[1]; + data[i + 2] = bytes[0]; + data[i + 3] = bytes[1]; bytes = BitConverter.GetBytes(normZ); - data[idx + 4] = bytes[0]; - data[idx + 5] = bytes[1]; + data[i + 4] = bytes[0]; + data[i + 5] = bytes[1]; bytes = BitConverter.GetBytes(0x2B88); // Alpha constant. - data[idx + 6] = bytes[0]; - data[idx + 7] = bytes[1]; + data[i + 6] = bytes[0]; + data[i + 7] = bytes[1]; } return data; } @@ -189,7 +170,7 @@ namespace WorldTuningTool private static bool[] selectionStarted = [ false, false ]; private static bool[] selectedInvalid = [ false, false ]; - public void DrawLUT(nint texture, nint lightingObject, int i, float width) + public void DrawUI(nint texture, nint lightingObject, int i, float width) { ImGui.PushID(i); string lutPath = Marshal.PtrToStringAnsi(texture + 0xC)!; diff --git a/Lights.cs b/Lights.cs new file mode 100644 index 0000000..0eed477 --- /dev/null +++ b/Lights.cs @@ -0,0 +1,264 @@ +using System.Numerics; + +using ImGuiNET; +using SharpPluginLoader.Core; +using SharpPluginLoader.Core.Memory; +using SharpPluginLoader.Core.Entities; + +namespace WorldTuningTool +{ + using static Plugin; + + public class Lights + { + public Lights() { } + + private class Light + { + public nint Object; + public int Type; + public Parameter[] Parameters = { + newParameter("Group", 0x13C, ParameterType.INT, pMinMaxStep(1, 255, 1)), // 1 = World, (1 << 1) = Player/Palico, (1 << 2) = NPCs + newFrameParameter("Position", 0x5A0, ParameterType.VECTOR3, pStep(0.15f)), + newFrameParameter("Color", 0x140, ParameterType.COLOR), + newFrameParameter("Intensity", 0x8A8, ParameterType.FLOAT), + newFrameParameter("Radius", 0x6A0, ParameterType.FLOAT, pStep(0.25f)), + newFrameParameter("Effective Radius", 0x588, ParameterType.FLOAT, pStep(0.25f)), + newFrameParameter("Min Roughness", 0x58C, ParameterType.FLOAT, pStep(0.0025f)), + newParameter("Do Volumetric", 0x590, ParameterType.BOOL), + newFlag("Shadow Cast", 0x138, ParameterType.FLAG, (1 << 23)), + newParameter("Shadow Map Size", 0x1B8, ParameterType.ALIGNED_INT, pMinStep(0, 128)), + newParameter("Shadow Near Clip Distance", 0x1B4, ParameterType.FLOAT), + newFrameParameter("Shadow Depth Bias", 0x57C, ParameterType.FLOAT, pStep(0.00001f)), + newFrameParameter("Shadow Sloped Depth Bias", 0x580, ParameterType.FLOAT, pStep(0.00001f)), + newFrameParameter("Shadow Max Depth Bias", 0x584, ParameterType.FLOAT, pStep(0.00001f)), + }; + + public Light(nint lightObject, int type) + { + Object = lightObject; + Type = type; + foreach (Parameter param in Parameters) + { + param.Update(lightObject); + } + } + + public Light(nint lightObject, int type, Vector3 pos) + { + Object = lightObject; + Type = type; + foreach (Parameter param in Parameters) + { + param.OverrideOn(false); + } + Parameters[0].SetOverrideValue(default, 255); + Parameters[1].SetOverrideValue(new Vector4(pos.X, pos.Y, pos.Z, 0.0f), 0); + Parameters[3].SetOverrideValue(new Vector4(10.0f, 0.0f, 0.0f, 0.0f), 0); + foreach (Parameter param in Parameters) + { + param.Update(lightObject); + } + } + } + + // Point Light (2): + // Create1: 0x141F875A0 () + // Create2: 0x141F87CD0 (nint) + // Destroy: 0x141F87D90 (nint, int) + // + // Spot Light (3): + // Create1: 0x141F8AE80 () + // Create2: 0x141F8B2D0 (nint) + // Destroy: 0x141F8B390 (nint, int) + // + // Hemi Sphere Light (4): + // Create1: 0x141F84840 () + // Create2: 0x141F84990 (nint) + // Destroy: 0x141F84A40 (nint, int) + // + // Wrapper? (8): + // Create1: 0x141F816C0 () + // Create2: 0x141F81800 () + // Destroy: 0x141F81940 (nint, int) + + private int requestLightType = 2; + private NativeFunction createLight; + //private bool interceptCreateLight = false; + private List ourLights = new List(); + //private List sceneLights = new List(); + private NativeAction addToScene; + private NativeAction removeFromScene; + //private delegate nint CreateLightObject(int type); + //private Hook? createLightObject; + private delegate void DestroyLightObject(nint lightObject, int unknownInt); + private Hook? destroyLightObject; + private delegate void UpdateLights(nint lightObject); + private Hook? updateLights; + + public void Initialize() + { + createLight = new NativeFunction(0x1418A3EF0); + //createLightObject = Hook.Create(0x1418A3EF0, CreateLightObjectHook); + destroyLightObject = Hook.Create(0x141F87D90, DestroyLightObjectHook); + addToScene = new NativeAction(0x142219070); + removeFromScene = new NativeAction(0x142228F10); + updateLights = Hook.Create(0x141F88F30, UpdateLightsHook); + } + + /* + private nint CreateLightObjectHook(int type) + { + nint lightObject = createLightObject!.Original(type); + if (interceptCreateLight) + { + interceptCreateLight = false; + } + //else if (type == 2) + else + { + sceneLights.Add(new Light(lightObject, type)); + } + return lightObject; + } + */ + + private void UpdateLightsHook(nint lightObject) + { + Light? light = null; + /* + for (int i = 0; i < sceneLights.Count; i++) + { + if (lightObject == sceneLights[i].Object) + { + light = sceneLights[i]; + break; + } + } + */ + if (light == null) + { + for (int i = 0; i < ourLights.Count; i++) + { + if (lightObject == ourLights[i].Object) + { + light = ourLights[i]; + break; + } + } + } + updateLights!.Original(lightObject); + if (light != null) + { + foreach (Parameter param in light.Parameters) + { + param.Update(lightObject); + } + } + } + + private void DestroyLightObjectHook(nint lightObject, int unknownInt) + { + /* + for (int i = 0; i < sceneLights.Count; i++) + { + if (lightObject == sceneLights[i].Object) + { + sceneLights.RemoveAt(i); + break; + } + } + */ + for (int i = 0; i < ourLights.Count; i++) + { + if (lightObject == ourLights[i].Object) + { + ourLights.RemoveAt(i); + break; + } + } + destroyLightObject!.Original(lightObject, unknownInt); + } + + public unsafe void DrawUI(float width) + { + /* + ImGui.NextItemWidth(width * 0.25f); + ImGui.InputInt("Type", ref requestLightType, 1); + ImGui.SameLine(); + */ + if (ImGui.Button("New")) + { + //interceptCreateLight = true; + nint lightObject = createLight.Invoke(requestLightType); + Vector3 pos = default; + Player? player = Player.MainPlayer; + if (player != null) + { + pos = player.Position; + pos.Y += 30.0f; + } + ourLights.Add(new Light(lightObject, requestLightType, pos)); + // mov byte ptr[rsp+20],00 unaccounted for, hopefully it never matters. + addToScene.Invoke(MemoryUtil.Read(0x1451238C8), 0x16, lightObject, 0x0); + } + ImGui.Separator(); + ImGui.PushID("Ours"); + for (int i = 0; i < ourLights.Count; i++) + { + Light light = ourLights[i]; + ImGui.PushID(i); + ImGui.Text($"Type: {light.Type}, Address: 0x{light.Object:X}"); + foreach (Parameter param in light.Parameters) + { + param.Draw(width, true); + } + /* + if (ImGui.CollapsingHeader("Random Move")) + { + foreach (Parameter param in light.RandomMoveParameters) + { + param.Draw(width, true); + } + } + */ + if (ImGui.Button("Remove")) + { + /* + nint vTable = MemoryUtil.Read(lightObject); + NativeAction freeLight = new NativeAction(MemoryUtil.Read(vTable)); + freeLight.Invoke(lightObject, 1); + */ + // removeFromScene triggers destructor. + removeFromScene.Invoke(light.Object); + } + ImGui.PopID(); + ImGui.Separator(); + } + ImGui.PopID(); + ImGui.PushID("Scene"); + /* + if (ImGui.CollapsingHeader("Scene Lights")) + { + for (int i = 0; i < sceneLights.Count; i++) + { + Light light = sceneLights[i]; + ImGui.PushID(i); + ImGui.Text($"Type: {light.Type}, Address: 0x{light.Object:X}"); + foreach (Parameter param in light.Parameters) + { + param.Draw(width); + } + if (ImGui.Button("Remove")) + { + removeFromScene.Invoke(light.Object); + } + ImGui.PopID(); + ImGui.Separator(); + } + } + */ + ImGui.PopID(); + } + } +} diff --git a/Plugin.cs b/Plugin.cs old mode 100755 new mode 100644 index f05fbee..2241a88 --- a/Plugin.cs +++ b/Plugin.cs @@ -1,4 +1,4 @@ -//#define ENABLE_ASSERTS +#define ENABLE_ASSERTS //#define OVERSIZED_SHADOW_MAP //#define SHADER_FEATURES //#define RESOURCE_ADJUSTMENT @@ -14,7 +14,6 @@ using ImGuiNET; using SharpPluginLoader.Core; using SharpPluginLoader.Core.Configuration; using SharpPluginLoader.Core.Memory; -using SharpPluginLoader.Core.Entities; #if SHADER_FEATURES using SharpPluginLoader.Core.Rendering; #endif @@ -31,33 +30,33 @@ using SharpPluginLoader.Core.Resources; // - Lights refactor. // - Descriptions. // - float format. -// - Min/Max. // - Lights iterop. // - SPL Patches: // - No crash on empty config. // - Style change -// - Create light hook. -// - Shadow distance retuning. -// - Weird shadow area in Rotten Vale. // - Hotload nukes config? // // Areas that need Shadow Distance retuning: -// - Exit of central camp in Horfrost Reach. -// - Sporepuff area in The Ancient Forest. -// - Wildspire Waste entrence to enclosed area past the waterfall. -// - The Rotten Vale jump out of Southeast Camp. Wall on the opposite side slightly to the left. -// - Special Arena. -// - Elder's Recess Lavasioth area. -// - Hoarfrost pit area with wedge beetles. +// - Exit of central camp in Horfrost Reach. +// - Sporepuff area in The Ancient Forest. +// - Wildspire Waste entrence to enclosed area past the waterfall. +// - The Rotten Vale jump out of Southeast Camp. Wall on the opposite side slightly to the left. +// - Rotten vale lower area. +// - Special Arena. +// - Elder's Recess Lavasioth area. +// - Hoarfrost pit area with wedge beetles. // // Known issues to think about: -// - Hair clipping while looking down. +// - Hair clipping when character looks down. +// - Vangis headband. // - Volume rendering can look really bad with multiple overlapped sources(?) (Guding lands vines). // - Screen space reflections often look bad. -// - Facial contact shadows incorrectly move based on camera position. +// - Facial contact shadows unnaturally move based on camera position. namespace WorldTuningTool { + using static Config; + public unsafe class Plugin : IPlugin { public string Name => "World Tuning Tool"; @@ -101,11 +100,8 @@ namespace WorldTuningTool private static bool StringToBoolean(string s) { return Convert.ToBoolean(s, CultureInfo.InvariantCulture); } private static int StringToInt32(string s, int fromBase = 10) { - if (fromBase == 10) { - return Convert.ToInt32(s, CultureInfo.InvariantCulture); - } else { - return Convert.ToInt32(s, fromBase); - } + if (fromBase == 10) return Convert.ToInt32(s, CultureInfo.InvariantCulture); + return Convert.ToInt32(s, fromBase); } private static string SingleToString(float f, string? format = null) { return f.ToString(format, CultureInfo.InvariantCulture); } private static string BooleanToString(bool b) { return b.ToString(CultureInfo.InvariantCulture); } @@ -113,16 +109,10 @@ namespace WorldTuningTool public static Vector3 StringToVector3(string s, char delim = ',') { - if (String.IsNullOrEmpty(s)) - { - throw new FormatException(); - } - string[] vs = s.Split(delim).Select(v => v.Trim()).ToArray(); - if (vs.Length != 3) - { - throw new FormatException(); - } - return new Vector3(StringToSingle(vs[0]), StringToSingle(vs[1]), StringToSingle(vs[2])); + if (String.IsNullOrEmpty(s)) throw new FormatException(); + string[] sp = s.Split(delim).Select(v => v.Trim()).ToArray(); + if (sp.Length != 3) throw new FormatException(); + return new Vector3(StringToSingle(sp[0]), StringToSingle(sp[1]), StringToSingle(sp[2])); } private static string Vector3ToString(Vector3 v) @@ -146,14 +136,14 @@ namespace WorldTuningTool SHADOW_RESOLUTION } - static IPlugin? Instance = null; + private static IPlugin? Instance = null; - static Config getConfig() + private static Config getConfig() { return ConfigManager.GetConfig(Instance!); } - static void reorderConfig(Config config, List overrides) + private static void rebuildConfig(Config config, List overrides) { List selectedGlobals = config.Globals[selectedGlobal]; selectedGlobals.Clear(); @@ -167,7 +157,7 @@ namespace WorldTuningTool private const int SelectedNotSaved = 1; private const int SetNotSaved = (1 << 1); - static void saveConfig(Config config) + private static void saveConfig(Config config) { List tmpOverrides = config.Overrides[globalStage]; config.Overrides.Remove(globalStage); @@ -249,10 +239,8 @@ namespace WorldTuningTool if (!superseded && param != null) { // If Global is selected, check if superseded by a currentStage override. - superseded |= globalOverrides == null && stageOverrides != null && - overridesContainsParam(stageOverrides, param); - // Any other selectedStage override is either inactive or could only be superseded by a - // set or external override. + superseded |= globalOverrides == null && stageOverrides != null && overridesContainsParam(stageOverrides, param); + // Any other selectedStage override is either inactive or could only be superseded by a set or external override. superseded |= selectedSet != "" && overridesContainsParam(config.Sets[selectedSet], param); superseded |= overridesContainsParam(externalOverrides.Values, param); } @@ -483,7 +471,7 @@ namespace WorldTuningTool overrideForStage = false; } - public void OverrideValue(Vector4 v4, int i1) + public void SetOverrideValue(Vector4 v4, int i1) { if (queuedOverride) { @@ -818,6 +806,31 @@ namespace WorldTuningTool ImGui.PopStyleVar(); } + public string SetByLine(Config config, List? stageOverrides, List? globalOverrides, bool forSet, bool allowGlobal) + { + // Reverse order of selectedOverrideSuperseded(). + if (overridesContainsParam(externalOverrides.Values, this)) + { + return "Set by 'External'"; + } + Assert(!forSet); + if (selectedSet != "" && overridesContainsParam(config.Sets[selectedSet], this)) + { + return $"Set by '{selectedSet}'"; + } + if ((allowGlobal || globalOverrides == null) && stageOverrides != null && overridesContainsParam(stageOverrides, this)) + { + return $"Set by '{StageToString(currentStage)}'"; + } + if (allowGlobal) + { + return "Set by \'Global\'"; + } + // Superseded because inactive. + Assert(globalOverrides != null && selectedStage != currentStage); + return ""; + } + public void Draw(float width, bool assumeOverride = false) { Draw(ref valueV, ref valueInt, width, assumeOverride); @@ -854,11 +867,18 @@ namespace WorldTuningTool { if (overrideForStage) { - ImGui.Text("Contained in Config"); + Config config = getConfig(); + List? globalOverrides = config.Overrides[globalStage]; + List? stageOverrides = maybeGetStageOverrides(config); + ImGui.Text(SetByLine(config, stageOverrides, globalOverrides, false, true)); + } + else if (overrideValue) + { + ImGui.Text("Set"); } else { - ImGui.Text("Override"); + ImGui.Text("Set override"); } ImGui.EndTooltip(); } @@ -977,13 +997,13 @@ namespace WorldTuningTool selectedOverrides.Add(ov); if (selectedStage == globalStage) { - reorderConfig(config, selectedOverrides); + rebuildConfig(config, selectedOverrides); } configState |= SelectedNotSaved; } if (ImGui.BeginItemTooltip()) { - ImGui.Text($"Add to '{Config.StageToString(selectedStage)}'"); + ImGui.Text($"Add to '{StageToString(selectedStage)}'"); ImGui.EndTooltip(); } } @@ -1186,7 +1206,7 @@ namespace WorldTuningTool if (Param != null) { Param.OverrideOn(true); - Param.OverrideValue(valueV, valueInt); + Param.SetOverrideValue(valueV, valueInt); } } @@ -1203,8 +1223,7 @@ namespace WorldTuningTool public void Draw(bool forSet, List? currentOverrides, List? stageOverrides, List? globalOverrides, bool superseded, float width) { Assert(!superseded == isSet); - bool fade = superseded; - if (fade) + if (superseded) { ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); } @@ -1213,7 +1232,13 @@ namespace WorldTuningTool ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true); } ImGui.PushItemWidth(width * 0.475f); - if (ImGui.BeginCombo("##Parameters", (Param != null) ? Param.Name : "", ImGuiComboFlags.HeightLarge)) + bool beginCombo = ImGui.BeginCombo("##Parameters", (Param != null) ? Param.Name : "", ImGuiComboFlags.HeightLarge); + if (superseded) + { + ImGui.PopStyleVar(); + } + Config config = getConfig(); + if (beginCombo) { if (currentOverrides != null) { @@ -1268,7 +1293,6 @@ namespace WorldTuningTool } else { - Config config = getConfig(); superseded = selectedOverrideSuperseded(config, globalOverrides, stageOverrides, Param); if (!superseded) { @@ -1296,11 +1320,15 @@ namespace WorldTuningTool if (Param != null) { ImGui.SameLine(); + if (superseded) + { + ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); + } if (Param.DrawValue(ref valueV, ref valueInt, width, false)) { if (!superseded) { - Param.OverrideValue(valueV, valueInt); + Param.SetOverrideValue(valueV, valueInt); } } (Vector4 v4, int i1) = Param.GetValue(); @@ -1315,11 +1343,11 @@ namespace WorldTuningTool valueInt = sValueInt; if (!superseded) { - Param.OverrideValue(valueV, valueInt); + Param.SetOverrideValue(valueV, valueInt); } } } - if (fade) + if (superseded) { ImGui.PopStyleVar(); } @@ -1343,47 +1371,15 @@ namespace WorldTuningTool else if (valueDiffers) { ImGui.SameLine(); - if (!superseded) + string byLine = ""; + if (superseded) { - Param.DrawReferenceValue("Current", v4, i1); - } - else - { - if (forSet) - { - Assert(overridesContainsParam(externalOverrides.Values, Param)); - Param.DrawReferenceValue("Set by 'External'", v4, i1); - } - else - { - Config config = getConfig(); - // Reverse order of selectedOverrideSuperseded(). - if (overridesContainsParam(externalOverrides.Values, Param)) - { - Param.DrawReferenceValue("Set by 'External'", v4, i1); - } - else if (selectedSet != "" && overridesContainsParam(config.Sets[selectedSet], Param)) - { - Param.DrawReferenceValue($"Set by '{selectedSet}'", v4, i1); - } - else if (globalOverrides == null && stageOverrides != null && - overridesContainsParam(stageOverrides, Param)) - { - Param.DrawReferenceValue($"Set by '{Config.StageToString(currentStage)}'", v4, i1); - } - else // Superseded because inactive. - { - Assert(globalOverrides != null && selectedStage != currentStage); - Param.DrawReferenceValue("Current", v4, i1); - } - } + // Global is the lowest priority so "Set by 'Global'" never applies here. + byLine = Param.SetByLine(config, stageOverrides, globalOverrides, forSet, false); } + Param.DrawReferenceValue((byLine == "") ? "Current" : byLine, v4, i1); } } - else if (fade) - { - ImGui.PopStyleVar(); - } } } @@ -1414,6 +1410,8 @@ namespace WorldTuningTool private static MtObject? sMhMain = null; private static MtObject? sMhRender = null; + private static Lights lights = new Lights(); + private static Parameter hqMode = newParameter("HQ Mode", 0xE9A3, ParameterType.BOOL); private static Parameter[] lodParameters = { @@ -1487,7 +1485,7 @@ namespace WorldTuningTool newParameter("Capsule Light Dir XZY", 0xE548, ParameterType.VECTOR3), newParameterView("Capsule Light W Dir", 0xE560, ParameterType.VECTOR3), newParameter("Capsule Light Angle", 0xE5B0, ParameterType.FLOAT), - newParameter("Capsule AO Intensity", 0xE5B8, ParameterType.FLOAT) + newParameter("Capsule AO Intensity", 0xE5B8, ParameterType.FLOAT, pStep(0.00025f)) }; private delegate void UpdateSSAOParams(nint stackOffset); @@ -1595,7 +1593,7 @@ namespace WorldTuningTool private delegate void UpdateLightingParameters(nint stackOffset, nint lightingObjectInternal); private Hook? updateLightingParams; private Hook? updateLutBlend; - private static WorldLUTs luts = new WorldLUTs(); + private static LUT luts = new LUT(); private static Parameter[] lightingParameters = { newParameter("Light Tone Map Type", 0x16C, ParameterType.INT, pMinMaxStep(1, 6, 1)), newParameter("Light Compute Luminance", 0x170, ParameterType.BOOL), @@ -1636,8 +1634,6 @@ namespace WorldTuningTool private Hook? createBloomObject; private Hook? createBloomObject2; private Hook? destroyBloomObject; - //private delegate void UpdateBloomParams(nint bloomObjectInternal, nint unknownPtr); - //private Hook? updateBloomParams; private nint bloomObject = 0x0; private static Parameter[] bloomParameters = { // Disabling 'Draw' is a bad way to disable bloom. It breaks the filter on initial load which @@ -1882,7 +1878,9 @@ namespace WorldTuningTool setShadowQuality.Invoke(MemoryUtil.Read(sMhScene!.Instance + 0x5530) + 1); } +#if SHADER_FEATURES private bool fullResSSLR = false; +#endif private Patch ssrRes1; private Patch ssrRes2; private Patch ssrRes3; @@ -1993,89 +1991,6 @@ namespace WorldTuningTool private bool disableReducedRateAnimations = false; private Patch zeroFrameSkip; - private class Light - { - public nint Object; - public int Type; - public Parameter[] Parameters = { - newParameter("Group", 0x13C, ParameterType.INT, pMinMaxStep(1, 255, 1)), // 1 = World, (1 << 1) = Player/Palico, (1 << 2) = NPCs - newFrameParameter("Position", 0x5A0, ParameterType.VECTOR3, pStep(0.15f)), - newFrameParameter("Color", 0x140, ParameterType.COLOR), - newFrameParameter("Intensity", 0x8A8, ParameterType.FLOAT), - newFrameParameter("Radius", 0x6A0, ParameterType.FLOAT, pStep(0.25f)), - newFrameParameter("Effective Radius", 0x588, ParameterType.FLOAT, pStep(0.25f)), - newFrameParameter("Min Roughness", 0x58C, ParameterType.FLOAT, pStep(0.0025f)), - newParameter("Do Volumetric", 0x590, ParameterType.BOOL), - newFlag("Shadow Cast", 0x138, ParameterType.FLAG, (1 << 23)), - newParameter("Shadow Map Size", 0x1B8, ParameterType.ALIGNED_INT, pMinStep(0, 128)), - newParameter("Shadow Near Clip Distance", 0x1B4, ParameterType.FLOAT), - newFrameParameter("Shadow Depth Bias", 0x57C, ParameterType.FLOAT, pStep(0.00001f)), - newFrameParameter("Shadow Sloped Depth Bias", 0x580, ParameterType.FLOAT, pStep(0.00001f)), - newFrameParameter("Shadow Max Depth Bias", 0x584, ParameterType.FLOAT, pStep(0.00001f)), - }; - - public Light(nint lightObject, int type) - { - Object = lightObject; - Type = type; - foreach (Parameter param in Parameters) - { - param.Update(lightObject); - } - } - - public Light(nint lightObject, int type, Vector3 pos) - { - Object = lightObject; - Type = type; - foreach (Parameter param in Parameters) - { - param.OverrideOn(false); - } - Parameters[0].OverrideValue(default, 255); - Parameters[1].OverrideValue(new Vector4(pos.X, pos.Y, pos.Z, 0.0f), 0); - Parameters[3].OverrideValue(new Vector4(10.0f, 0.0f, 0.0f, 0.0f), 0); - foreach (Parameter param in Parameters) - { - param.Update(lightObject); - } - } - } - - // Point Light (2): - // Create1: 0x141F875A0 () - // Create2: 0x141F87CD0 (nint) - // Destroy: 0x141F87D90 (nint, int) - // - // Spot Light (3): - // Create1: 0x141F8AE80 () - // Create2: 0x141F8B2D0 (nint) - // Destroy: 0x141F8B390 (nint, int) - // - // Hemi Sphere Light (4): - // Create1: 0x141F84840 () - // Create2: 0x141F84990 (nint) - // Destroy: 0x141F84A40 (nint, int) - // - // Wrapper? (8): - // Create1: 0x141F816C0 () - // Create2: 0x141F81800 () - // Destroy: 0x141F81940 (nint, int) - - private int requestLightType = 2; - private NativeFunction createLight; - //private bool interceptCreateLight = false; - private List ourLights = new List(); - //private List sceneLights = new List(); - private NativeAction addToScene; - private NativeAction removeFromScene; - //private delegate nint CreateLightObject(int type); - //private Hook? createLightObject; - private delegate void DestroyLightObject(nint lightObject, int unknownInt); - private Hook? destroyLightObject; - private delegate void UpdateLights(nint lightObject); - private Hook? updateLights; - public int AddOverride(string name, Vector4 v4, int i1) { foreach (Parameter param in allParameters) @@ -2138,7 +2053,7 @@ namespace WorldTuningTool foreach (StageExt stage in Enum.GetValues(typeof(StageExt))) { if (stage == StageExt.Global) continue; - Assert(Config.OrderedStages.Contains(stage)); + Assert(OrderedStages.Contains(stage)); } onAreaChange = Hook.Create(0x141AC27D0, OnAreaChangeHook); // nint @@ -2149,7 +2064,7 @@ namespace WorldTuningTool // Light Dir XZY is updated seperately at 0x1420397F0, we assume this function always happens later, though. updateCapsuleAoParams = Hook.Create(0x141B19E10, UpdateCapsuleAOParamsHook); // nint - // These run during cutscenes. + // These run in a loop during cutscenes. updateSSAOParams = Hook.Create(0x1416D8B10, UpdateSSAOParamsHook); // nint updateSSLRParams = Hook.Create(0x1416DA3F0, UpdateSSLRParamsHook); // nint updateLightingParams = Hook.Create(0x1416DAAB0, UpdateLightingParametersHook); // nint, nint @@ -2161,7 +2076,6 @@ namespace WorldTuningTool createBloomObject = Hook.Create(0x1424CB3C0, CreateBloomObjectHook); createBloomObject2 = Hook.Create(0x1424CB5E0, CreateBloomObject2Hook); // nint destroyBloomObject = Hook.Create(0x1424CB750, DestroyBloomObjectHook); // nint, int - //updateBloomParams = Hook.Create(0x1424CD570, UpdateBloomParamsHook); // nint, nint createDofObject = Hook.Create(0x142421E80, CreateDofObjectHook); createDofObject2 = Hook.Create(0x1424220A0, CreateDofObject2Hook); // nint @@ -2181,12 +2095,7 @@ namespace WorldTuningTool createTAAObject2 = Hook.Create(0x142391320, CreateTAAObject2Hook); // nint destroyTAAObject = Hook.Create(0x1423916E0, DestroyTAAObjectHook); // nint, int - createLight = new NativeFunction(0x1418A3EF0); - //createLightObject = Hook.Create(0x1418A3EF0, CreateLightObjectHook); - destroyLightObject = Hook.Create(0x141F87D90, DestroyLightObjectHook); - addToScene = new NativeAction(0x142219070); - removeFromScene = new NativeAction(0x142228F10); - updateLights = Hook.Create(0x141F88F30, UpdateLightsHook); + lights.Initialize(); nint addr = PatternScanner.FindFirst(Pattern.FromString("48 89 5C 24 10 48 89 74 24 18 48 89 7C 24 20 55 41 56 41 57 48 8B EC 48 83 EC 30 48 8B FA 48 8B D9 E8 AA B6 C1 FF 48 8B 47 10 48 8D 57 50")); Assert(addr == 0x141AB2260); // nint, nint @@ -2382,9 +2291,9 @@ namespace WorldTuningTool public void OnPreMain() { Config config = getConfig(); - Config.PatchConfig patches = config.Patches; - fullResSSLR = patches.FullResolutionSSLR; + PatchConfig patches = config.Patches; #if SHADER_FEATURES + fullResSSLR = patches.FullResolutionSSLR; if (fullResSSLR) { ssrRes1.Enable(); @@ -2478,7 +2387,7 @@ namespace WorldTuningTool { config.Overrides[globalStage].Add(ovG); } - foreach (StageExt area in Config.OrderedStages) + foreach (StageExt area in OrderedStages) { if (!config.Overrides.ContainsKey(area)) { @@ -2873,20 +2782,6 @@ namespace WorldTuningTool return destroyBloomObject!.Original(bloomObjectInternal, unknownInt); } - /* - private void UpdateBloomParamsHook(nint bloomObjectInternal, nint unknownPtr) - { - if (bloomObject == bloomObjectInternal) - { - foreach (Parameter param in bloomParameters) - { - param.Update(bloomObject); - } - } - updateBloomParams!.Original(bloomObjectInternal, unknownPtr); - } - */ - private nint CreateLightingObjectHook() { lightingObject = createLightingObject!.Original(); @@ -2968,80 +2863,6 @@ namespace WorldTuningTool staticShadowParams!.Original(shadowParamsStatic, shadowObjectInternal); } - /* - private nint CreateLightObjectHook(int type) - { - nint lightObject = createLightObject!.Original(type); - if (interceptCreateLight) - { - interceptCreateLight = false; - } - //else if (type == 2) - else - { - sceneLights.Add(new Light(lightObject, type)); - } - return lightObject; - } - */ - - private void DestroyLightObjectHook(nint lightObject, int unknownInt) - { - /* - for (int i = 0; i < sceneLights.Count; i++) - { - if (lightObject == sceneLights[i].Object) - { - sceneLights.RemoveAt(i); - break; - } - } - */ - for (int i = 0; i < ourLights.Count; i++) - { - if (lightObject == ourLights[i].Object) - { - ourLights.RemoveAt(i); - break; - } - } - destroyLightObject!.Original(lightObject, unknownInt); - } - - private void UpdateLightsHook(nint lightObject) - { - Light? light = null; - /* - for (int i = 0; i < sceneLights.Count; i++) - { - if (lightObject == sceneLights[i].Object) - { - light = sceneLights[i]; - break; - } - } - */ - if (light == null) - { - for (int i = 0; i < ourLights.Count; i++) - { - if (lightObject == ourLights[i].Object) - { - light = ourLights[i]; - break; - } - } - } - updateLights!.Original(lightObject); - if (light != null) - { - foreach (Parameter param in light.Parameters) - { - param.Update(lightObject); - } - } - } - private void HandleSetChange(string prevSet, List globalOverrides, List? stageOverrides) { Config config = getConfig(); @@ -3124,10 +2945,6 @@ namespace WorldTuningTool private void HandleAreaChange(StageExt stage) { Config config = getConfig(); - if (!config.Overrides.ContainsKey(stage)) - { - return; - } List prevOverrides = config.Overrides[previousStage]; List globalOverrides = config.Overrides[globalStage]; BeginTransition(); @@ -3146,6 +2963,11 @@ namespace WorldTuningTool } } } + if (!config.Overrides.ContainsKey(stage)) + { + Log.Error($"Unknown stage: {stage}"); + stage = globalStage; + } if (stage != globalStage) { List stageOverrides = config.Overrides[stage]; @@ -3182,13 +3004,13 @@ namespace WorldTuningTool float width = ImGui.GetWindowWidth(); width /= width / (600.0f * ImGui.GetIO().FontGlobalScale); - ImGui.Text($"Current Stage: {Config.StageToString(currentStage)}"); + ImGui.Text($"Current Stage: {StageToString(currentStage)}"); ImGui.PushItemWidth(width * 0.35f); - if (ImGui.BeginCombo("##Stage", Config.StageToString(selectedStage), ImGuiComboFlags.HeightLarge)) + if (ImGui.BeginCombo("##Stage", StageToString(selectedStage), ImGuiComboFlags.HeightLarge)) { - foreach (StageExt area in Config.OrderedStages) + foreach (StageExt area in OrderedStages) { - string name = Config.StageToString(area); + string name = StageToString(area); bool isSelected = selectedStage == area; if (ImGui.Selectable(name, isSelected)) { @@ -3326,7 +3148,7 @@ namespace WorldTuningTool { if (selectedStage == globalStage) { - reorderConfig(config, selectedOverrides); + rebuildConfig(config, selectedOverrides); } configState |= SelectedNotSaved; } @@ -3530,8 +3352,9 @@ namespace WorldTuningTool if (ImGui.CollapsingHeader("Patches")) { - Config.PatchConfig patches = config.Patches; + PatchConfig patches = config.Patches; +#if SHADER_FEATURES if (ImGui.Checkbox("Full Resolution Screen Space Reflections (Requires Restart)", ref fullResSSLR)) { patches.FullResolutionSSLR = fullResSSLR; @@ -3543,6 +3366,7 @@ namespace WorldTuningTool ImGui.Text("Restart Required"); ImGui.EndTooltip(); } +#endif if (ImGui.Checkbox("Volume Rendering Full Resolution Blur Pass (Requires Area Change)", ref fullResVolumeBlur)) { @@ -3560,7 +3384,7 @@ namespace WorldTuningTool } if (ImGui.BeginItemTooltip()) { - ImGui.Text("This can get rid of excessive aliasing when something is in front of a volumetric effect.\nMove to a different area for this to apply, it will stay applied after that."); + ImGui.Text("This can get rid of excessive aliasing when something is in front of a volumetric effect.\nMove to a different area for this to apply. It will stay applied after that."); ImGui.EndTooltip(); } @@ -3647,83 +3471,7 @@ namespace WorldTuningTool if (ImGui.CollapsingHeader("Lights")) { - /* - ImGui.NextItemWidth(width * 0.25f); - ImGui.InputInt("Type", ref requestLightType, 1); - ImGui.SameLine(); - */ - if (ImGui.Button("New")) - { - //interceptCreateLight = true; - nint lightObject = createLight.Invoke(requestLightType); - Vector3 pos = default; - Player? player = Player.MainPlayer; - if (player != null) - { - pos = player.Position; - pos.Y += 30.0f; - } - ourLights.Add(new Light(lightObject, requestLightType, pos)); - // mov byte ptr[rsp+20],00 unaccounted for, hopefully it never matters. - addToScene.Invoke(MemoryUtil.Read(0x1451238C8), 0x16, lightObject, 0x0); - } - ImGui.Separator(); - ImGui.PushID("Ours"); - for (int i = 0; i < ourLights.Count; i++) - { - Light light = ourLights[i]; - ImGui.PushID(i); - ImGui.Text($"Type: {light.Type}, Address: 0x{light.Object:X}"); - foreach (Parameter param in light.Parameters) - { - param.Draw(width, true); - } - /* - if (ImGui.CollapsingHeader("Random Move")) - { - foreach (Parameter param in light.RandomMoveParameters) - { - param.Draw(width, true); - } - } - */ - if (ImGui.Button("Remove")) - { - /* - nint vTable = MemoryUtil.Read(lightObject); - NativeAction freeLight = new NativeAction(MemoryUtil.Read(vTable)); - freeLight.Invoke(lightObject, 1); - */ - // removeFromScene triggers destructor. - removeFromScene.Invoke(light.Object); - } - ImGui.PopID(); - ImGui.Separator(); - } - ImGui.PopID(); - ImGui.PushID("Scene"); - /* - if (ImGui.CollapsingHeader("Scene Lights")) - { - for (int i = 0; i < sceneLights.Count; i++) - { - Light light = sceneLights[i]; - ImGui.PushID(i); - ImGui.Text($"Type: {light.Type}, Address: 0x{light.Object:X}"); - foreach (Parameter param in light.Parameters) - { - param.Draw(width); - } - if (ImGui.Button("Remove")) - { - removeFromScene.Invoke(light.Object); - } - ImGui.PopID(); - ImGui.Separator(); - } - } - */ - ImGui.PopID(); + lights.DrawUI(width); } bool expanded = ImGui.CollapsingHeader("Parameters"); @@ -3864,12 +3612,12 @@ namespace WorldTuningTool nint lutMap0 = MemoryUtil.Read(lightingObject + 0x1A8); if (lutMap0 != 0x0) { - luts.DrawLUT(lutMap0, lightingObject, 0, width); + luts.DrawUI(lutMap0, lightingObject, 0, width); } nint lutMap1 = MemoryUtil.Read(lightingObject + 0x1B0); if (lutMap1 != 0x0) { - luts.DrawLUT(lutMap1, lightingObject, 1, width); + luts.DrawUI(lutMap1, lightingObject, 1, width); } } foreach (Parameter param in lightingParameters) -- cgit v1.2.3-101-g0448