summaryrefslogtreecommitdiff
path: root/Plugin.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Plugin.cs')
-rw-r--r--Plugin.cs1244
1 files changed, 106 insertions, 1138 deletions
diff --git a/Plugin.cs b/Plugin.cs
index 3218403..aa3f854 100644
--- a/Plugin.cs
+++ b/Plugin.cs
@@ -1,17 +1,8 @@
-//#define ENABLE_ASSERTS
//#define OVERSIZED_SHADOW_MAP
//#define SHADER_FEATURES
//#define RESOURCE_ADJUSTMENT
using System.Numerics;
-using System.Globalization;
-using System.Runtime.CompilerServices;
-#if ENABLE_ASSERTS
-using System.Diagnostics;
-#endif
-#if SHADER_FEATURES
-using System.Runtime.InteropServices;
-#endif
using ImGuiNET;
using SharpPluginLoader.Core;
@@ -56,6 +47,9 @@ using SharpPluginLoader.Core.Resources;
namespace WorldTuningTool
{
+ using static Utility;
+ using static Parameter;
+ using static PFuncs;
using static Config;
public unsafe class Plugin : IPlugin
@@ -63,138 +57,6 @@ namespace WorldTuningTool
public string Name => "World Tuning Tool";
public string Author => "Akon City Software";
- private static bool loggedAssertFailed = false;
- internal static void Assert(bool condition = false, [CallerLineNumber] int line = 0)
- {
- if (!condition && !loggedAssertFailed)
- {
- Log.Error($"Assert failed on line {line}, further asserts won't be logged.");
- loggedAssertFailed = true;
- }
-#if ENABLE_ASSERTS
- Trace.Assert(condition);
-#endif
- }
-
- private static byte ByteFlag(bool f) { return f ? (byte)0x1 : (byte)0x0; }
-
- internal static T Get<T>(nint addr, nint offset = 0x0) where T : unmanaged
- {
- return MemoryUtil.Read<T>(addr + offset);
- }
-
- internal static T Get<T>(long addr, nint offset = 0x0) where T : unmanaged
- {
- return MemoryUtil.Read<T>((nint)addr + offset);
- }
-
- internal static T *GetPtrInline<T>(nint addr, nint offset = 0x0) where T : unmanaged
- {
- return (T *)(addr + offset);
- }
-
- internal static ref T GetRef<T>(nint addr, nint offset = 0x0) where T : unmanaged
- {
- return ref MemoryUtil.GetRef<T>(addr + offset);
- }
-
- private static int BitIndex(int mask)
- {
- return BitOperations.Log2((uint)(mask & (-mask)));
- }
-
- private static Vector4 ColorVectorFromInt(int c)
- {
- return new Vector4(
- ((c ) & 0xFF) / 255.0f,
- ((c >> 8 ) & 0xFF) / 255.0f,
- ((c >> 16) & 0xFF) / 255.0f,
- ((c >> 24) & 0xFF) / 255.0f);
- }
-
- private static int ColorVectorToInt(Vector4 v)
- {
- return ((int)MathF.Round(v.X * 255.0f) |
- ((int)MathF.Round(v.Y * 255.0f) << 8) |
- ((int)MathF.Round(v.Z * 255.0f) << 16) |
- ((int)MathF.Round(v.W * 255.0f) << 24));
- }
-
- private static float StringToSingle(string s) { return Convert.ToSingle(s, CultureInfo.InvariantCulture); }
- 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);
- 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); }
- private static string Int32ToString(int i, string? format = null) { return i.ToString(format, CultureInfo.InvariantCulture); }
-
- internal static Vector2 StringToVector2(string s, char delim = ',')
- {
- if (String.IsNullOrEmpty(s)) throw new FormatException();
- string[] sp = s.Split(delim).Select((v) => v.Trim()).ToArray();
- if (sp.Length != 2) throw new FormatException();
- return new Vector2(StringToSingle(sp[0]), StringToSingle(sp[1]));
- }
-
- internal static Vector3 StringToVector3(string s, char delim = ',')
- {
- 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]));
- }
-
- internal static Vector4 StringToVector4(string s, char delim = ',')
- {
- if (String.IsNullOrEmpty(s)) throw new FormatException();
- string[] sp = s.Split(delim).Select((v) => v.Trim()).ToArray();
- if (sp.Length != 4) throw new FormatException();
- return new Vector4(StringToSingle(sp[0]), StringToSingle(sp[1]), StringToSingle(sp[2]), StringToSingle(sp[3]));
- }
-
- private static string Vector2ToString(Vector2 v)
- {
- return string.Format(CultureInfo.InvariantCulture, "{0},{1}", v.X, v.Y);
- }
-
- private static string Vector3ToString(Vector3 v)
- {
- return string.Format(CultureInfo.InvariantCulture, "{0},{1},{2}", v.X, v.Y, v.Z);
- }
-
- private static string Vector4ToString(Vector4 v)
- {
- return string.Format(CultureInfo.InvariantCulture, "{0},{1},{2},{3}", v.X, v.Y, v.Z, v.W);
- }
-
- public enum ParameterType
- {
- BOOL,
- FLAG,
- BYTE,
- INT,
- ALIGNED_INT,
- HEX,
- BITS,
- COLOR,
- COLOR_FACTOR,
- FLOAT,
- VECTOR3,
- VECTOR2,
- VECTOR4,
- PATCH_FLOAT,
- SHADOW_RESOLUTION
- }
-
- private const float defaultParamWidth = 0.21f;
- private const float fadeAlphaFactor = 0.7f;
- private const float disableAlphaFactor = 0.6f;
-
- private static bool ignoreMinMax = false;
-
private static IPlugin? Instance = null;
private static Config getConfig()
@@ -314,1020 +176,134 @@ namespace WorldTuningTool
return superseded;
}
- public static class ParameterFlags
- {
- public const int ViewOnly = 1;
- }
-
- public abstract class Parameter
+ internal static Parameter? getParameterByName(string name)
{
- public string Name;
- private string hiddenName;
- public ParameterType Type;
-
- private nint offset;
- private int mask;
- private nint lastAddr = 0x0;
- private bool overrideValue = false;
- private bool overrideForStage = false;
- private bool overrideWasOn = false;
-
- private int flags;
- public bool ViewOnly => (flags & ParameterFlags.ViewOnly) == ParameterFlags.ViewOnly;
-
- protected float stepf, minf, maxf;
- protected int step, min, max;
-
- private bool fallbackUpdate = true;
- private bool pendingWrite = false;
- private Vector4 valueV = default;
- private int valueInt = 0;
- private Vector4 oValueV; // Original value.
- private int oValueInt;
-
- private bool pendingUpdate = true;
- private bool queuedOverride = false;
- private bool queuedValue = false;
- private Vector4 qValueV; // Queued value.
- private int qValueInt;
-
- private bool bValue = false;
- private Vector4 bValueV; // B value in A/B.
- private int bValueInt;
-
- public Parameter(string name, nint offset, int mask, ParameterType type, int flags)
- {
- Name = name;
- hiddenName = "##" + Name;
- Type = type;
- switch (Type)
- {
- case ParameterType.FLAG:
- Assert(mask != 0);
- break;
- case ParameterType.PATCH_FLOAT:
- valueV.X = Get<float>(offset);
- pendingUpdate = false;
- break;
- case ParameterType.SHADOW_RESOLUTION:
- valueInt = 1;
- pendingUpdate = false;
- break;
- }
- this.offset = offset;
- this.mask = mask;
- this.flags = flags;
- }
-
- public bool PendingUpdate()
- {
- return pendingUpdate;
- }
-
- public (Vector4, int) GetValue()
- {
- return (valueV, valueInt);
- }
-
- public int GetMask()
- {
- return mask;
- }
-
- public void Resolve()
- {
- Assert(!InTransition && pendingWrite);
- pendingWrite = false;
- maybeWriteCurrentValue();
- }
-
- private void maybeWriteCurrentValue()
- {
- if (InTransition)
- {
- if (!DirtyParams.Contains(this))
- {
- pendingWrite = true;
- DirtyParams.Add(this);
- }
- else
- {
- Assert(pendingWrite);
- }
- return;
- }
- Assert(!pendingWrite);
- switch (Type)
- {
- case ParameterType.PATCH_FLOAT:
- new Patch(offset, BitConverter.GetBytes(valueV.X)).Enable();
- break;
- case ParameterType.SHADOW_RESOLUTION:
- if (valueInt > 1)
- {
- shadowResEnable(valueInt);
- }
- else
- {
- shadowResDisable();
- }
- break;
- }
- if (lastAddr == 0x0)
- {
- return;
- }
- switch (Type)
- {
- case ParameterType.BOOL:
- case ParameterType.BYTE:
- GetRef<byte>(lastAddr, offset) = (byte)valueInt;
- break;
- case ParameterType.FLAG:
- {
- ref int i1 = ref GetRef<int>(lastAddr, offset);
- if (valueInt != 0)
- {
- i1 |= mask;
- }
- else
- {
- i1 &= ~mask;
- }
- break;
- }
- case ParameterType.INT:
- case ParameterType.ALIGNED_INT:
- case ParameterType.HEX:
- case ParameterType.BITS:
- case ParameterType.COLOR:
- {
- ref int i1 = ref GetRef<int>(lastAddr, offset);
- if (mask != 0)
- {
- i1 = (i1 & ~mask) | ((valueInt << BitIndex(mask)) & mask);
- }
- else
- {
- i1 = valueInt;
- }
- break;
- }
- case ParameterType.FLOAT:
- GetRef<float>(lastAddr, offset) = valueV.X;
- break;
- case ParameterType.VECTOR2:
- GetRef<Vector2>(lastAddr, offset) = new Vector2(valueV.X, valueV.Y);
- break;
- case ParameterType.VECTOR3:
- case ParameterType.COLOR_FACTOR:
- GetRef<Vector3>(lastAddr, offset) = new Vector3(valueV.X, valueV.Y, valueV.Z);
- break;
- case ParameterType.VECTOR4:
- GetRef<Vector4>(lastAddr, offset) = valueV;
- break;
- }
- }
-
- public void ForceOverrideOn()
- {
- if (!queuedOverride && !overrideValue)
- {
- OverrideOn(false);
- }
- }
-
- public void ForceOverrideOff()
- {
- if (queuedOverride || overrideValue)
- {
- OverrideOff();
- }
- }
-
- public void OverrideOn(bool forStage)
- {
- if (pendingUpdate)
- {
- if (queuedOverride)
- {
- Assert(!overrideWasOn && forStage);
- overrideWasOn = true;
- }
- else
- {
- queuedOverride = true;
- }
- }
- else
- {
- if (overrideValue)
- {
- Assert(!overrideWasOn && forStage);
- overrideWasOn = true;
- }
- else
- {
- oValueV = valueV;
- oValueInt = valueInt;
- maybeWriteCurrentValue();
- overrideValue = true;
- }
- }
- overrideForStage = forStage;
- }
-
- public void OverrideOff()
- {
- if (queuedOverride)
- {
- if (overrideWasOn)
- {
- Assert(overrideForStage);
- overrideWasOn = false;
- }
- else
- {
- queuedOverride = false;
- }
- }
- else
- {
- Assert(overrideValue);
- if (overrideWasOn)
- {
- Assert(overrideForStage);
- overrideWasOn = false;
- }
- else
- {
- valueV = oValueV;
- valueInt = oValueInt;
- maybeWriteCurrentValue();
- bValue = false;
- overrideValue = false;
- }
- }
- overrideForStage = false;
- }
-
- public void SetOverrideValue(Vector4 v4, int i1)
+ if (OldParameterNames.TryGetValue(name, out string? newName))
{
- if (queuedOverride)
- {
- qValueV = v4;
- qValueInt = i1;
- queuedValue = true;
- }
- else
- {
- valueV = v4;
- valueInt = i1;
- maybeWriteCurrentValue();
- }
+ Log.Warn($"Paramter '{name}' renamed to '{newName}'.");
+ name = newName;
}
-
- public void Update(nint baseObject, bool fromHook = false)
+ foreach (Parameter param in allParameters)
{
- lastAddr = baseObject;
-
- if (baseObject == 0x0)
- {
- pendingUpdate = true;
- return;
- }
-
- if (fromHook)
- {
- fallbackUpdate = false;
- }
- else if (!fallbackUpdate)
- {
- fallbackUpdate = true;
- return;
- }
-
- // Trying to track changes to the original value is a "best effort"
- // approach because it can't work if the in-game value is updated
- // to the same value as a current override.
- switch (Type)
- {
- case ParameterType.BOOL:
- case ParameterType.BYTE:
- {
- ref byte b1 = ref GetRef<byte>(baseObject, offset);
- byte b = b1;
- if (overrideValue)
- {
- if (b != (byte)valueInt)
- {
- oValueInt = b;
- }
- b1 = (byte)valueInt;
- }
- else
- {
- valueInt = b;
- }
- break;
- }
- case ParameterType.FLAG:
- {
- ref int i1 = ref GetRef<int>(baseObject, offset);
- int b1 = ByteFlag((i1 & mask) == mask);
- if (overrideValue)
- {
- if (b1 != valueInt)
- {
- oValueInt = b1;
- }
- if (valueInt != 0)
- {
- i1 |= mask;
- }
- else
- {
- i1 &= ~mask;
- }
- }
- else
- {
- valueInt = b1;
- }
- break;
- }
- case ParameterType.INT:
- case ParameterType.ALIGNED_INT:
- case ParameterType.HEX:
- case ParameterType.BITS:
- case ParameterType.COLOR:
- {
- ref int i1 = ref GetRef<int>(baseObject, offset);
- int m = i1;
- if (mask != 0)
- {
- m = (m & mask) >> BitIndex(mask);
- }
- if (overrideValue)
- {
- if (m != valueInt)
- {
- oValueInt = m;
- }
- if (mask != 0)
- {
- i1 = (i1 & ~mask) | ((valueInt << BitIndex(mask)) & mask);
- }
- else
- {
- i1 = valueInt;
- }
- }
- else
- {
- valueInt = m;
- }
- break;
- }
- case ParameterType.FLOAT:
- {
- ref float f1 = ref GetRef<float>(baseObject, offset);
- float f = f1;
- if (overrideValue)
- {
- if (f != valueV.X)
- {
- oValueV.X = f;
- }
- f1 = valueV.X;
- }
- else
- {
- valueV.X = f;
- }
- break;
- }
- case ParameterType.VECTOR2:
- {
- ref Vector2 v2 = ref GetRef<Vector2>(baseObject, offset);
- Vector2 v = v2;
- if (overrideValue)
- {
- Vector2 valueV2 = new Vector2(valueV.X, valueV.Y);
- if (v != valueV2)
- {
- oValueV = new Vector4(v.X, v.Y, 0.0f, 0.0f);
- }
- v2 = valueV2;
- }
- else
- {
- valueV = new Vector4(v.X, v.Y, 0.0f, 0.0f);
- }
- break;
- }
- case ParameterType.VECTOR3:
- case ParameterType.COLOR_FACTOR:
- {
- ref Vector3 v3 = ref GetRef<Vector3>(baseObject, offset);
- Vector3 v = v3;
- if (overrideValue)
- {
- Vector3 valueV3 = new Vector3(valueV.X, valueV.Y, valueV.Z);
- if (v != valueV3)
- {
- oValueV = new Vector4(v.X, v.Y, v.Z, 0.0f);
- }
- v3 = valueV3;
- }
- else
- {
- valueV = new Vector4(v.X, v.Y, v.Z, 0.0f);
- }
- break;
- }
- case ParameterType.VECTOR4:
- {
- ref Vector4 v4 = ref GetRef<Vector4>(baseObject, offset);
- Vector4 v = v4;
- if (overrideValue)
- {
- if (v != valueV)
- {
- oValueV = v;
- }
- v4 = valueV;
- }
- else
- {
- valueV = v;
- }
- break;
- }
- }
-
- if (pendingUpdate)
+ if (param.Name == name)
{
- pendingUpdate = false;
- if (queuedOverride)
- {
- Assert(!overrideValue);
- OverrideOn(overrideForStage);
- if (queuedValue)
- {
- valueV = qValueV;
- valueInt = qValueInt;
- maybeWriteCurrentValue();
- queuedValue = false;
- }
- queuedOverride = false;
- }
+ return param;
}
}
+ return null;
+ }
- public void AdjustValue(ref Vector4 v4, ref int i1)
- {
- if (Type == ParameterType.SHADOW_RESOLUTION) // Hard limit.
- {
-#if OVERSIZED_SHADOW_MAP
- i1 = Math.Clamp(i1, 1, 6);
-#else
- i1 = Math.Clamp(i1, 1, 5);
-#endif
- }
- else if (!ignoreMinMax)
- {
- switch (Type)
- {
- case ParameterType.BOOL:
- case ParameterType.FLAG:
- case ParameterType.BYTE:
- case ParameterType.INT:
- case ParameterType.HEX:
- case ParameterType.BITS:
- i1 = Math.Clamp(i1, min, max);
- break;
- case ParameterType.ALIGNED_INT:
- i1 = Math.Clamp((i1 + (step - 1))&~(step - 1), min, max);
- break;
- case ParameterType.FLOAT:
- case ParameterType.PATCH_FLOAT:
- case ParameterType.VECTOR2:
- case ParameterType.VECTOR3:
- case ParameterType.COLOR_FACTOR:
- case ParameterType.VECTOR4:
- v4 = new Vector4(
- Math.Clamp(v4.X, minf, maxf),
- Math.Clamp(v4.Y, minf, maxf),
- Math.Clamp(v4.Z, minf, maxf),
- Math.Clamp(v4.W, minf, maxf));
- break;
- }
- }
- }
+ internal static void drawStageOverrideTooltip(Parameter param)
+ {
+ Config config = getConfig();
+ List<Override>? globalOverrides = config.Overrides[globalStage];
+ List<Override>? stageOverrides = maybeGetStageOverrides(config);
+ ImGui.Text(setByLine(param, config, stageOverrides, globalOverrides, false, true));
+ }
- public bool DrawValue(ref Vector4 v4, ref int i1, float width, bool drawLabel)
+ internal static void drawExtraButtons(Parameter param)
+ {
+ Config config = getConfig();
+ List<Override> selectedOverrides = config.Overrides[selectedStage];
+ List<Override>? stageOverrides = maybeGetStageOverrides(config);
+ // Deciding when to set globalOverrides copies the logic in OnImGuiRender().
+ // Selected: Set if selectedStage != globalStage.
+ // Set: Always set.
+ List<Override>? globalOverrides = null;
+ if (selectedSet != "")
{
- bool valueChanged = false;
- string label = drawLabel ? Name : hiddenName;
- float displayMinf = ignoreMinMax ? 0.0f : minf;
- float displayMaxf = ignoreMinMax ? 0.0f : maxf;
- switch (Type)
+ List<Override> setOverrides = config.Sets[selectedSet];
+ if (!overridesContainsParam(setOverrides, param))
{
- case ParameterType.BOOL:
- case ParameterType.FLAG:
- {
- bool b = i1 != 0;
- if (ImGui.Checkbox(label, ref b))
- {
- i1 = ByteFlag(b);
- valueChanged = true;
- }
- break;
- }
- case ParameterType.BYTE:
- {
- ImGuiInputTextFlags flags = ImGuiInputTextFlags.EnterReturnsTrue;
- ImGui.SetNextItemWidth(width * defaultParamWidth);
- if (ImGui.InputInt(label, ref i1, step, 0, flags))
- {
- valueChanged = true;
- }
- break;
- }
- case ParameterType.INT:
- case ParameterType.ALIGNED_INT:
- case ParameterType.HEX:
- case ParameterType.SHADOW_RESOLUTION:
- {
- ImGuiInputTextFlags flags = ImGuiInputTextFlags.EnterReturnsTrue;
- if (Type == ParameterType.HEX)
- {
- flags |= ImGuiInputTextFlags.CharsHexadecimal;
- }
- ImGui.SetNextItemWidth(width * defaultParamWidth);
- if (ImGui.InputInt(label, ref i1, step, 0, flags))
- {
- valueChanged = true;
- }
- break;
- }
- case ParameterType.BITS:
- {
- for (int i = 0; i < 32; i++)
- {
- int bit = (1 << i);
- if ((mask & bit) == bit)
- {
- bool set = (i1 & bit) == bit;
- if (ImGui.Checkbox($"##Bit{i}", ref set))
- {
- if (set)
- {
- i1 |= bit;
- }
- else
- {
- i1 &= ~bit;
- }
- valueChanged = true;
- }
- ImGui.SameLine();
- }
- }
- ImGui.Text(label);
- break;
- }
- case ParameterType.COLOR:
- {
- Vector4 colorV = ColorVectorFromInt(i1);
- ImGui.SetNextItemWidth(width * defaultParamWidth * 3.0f);
- if (ImGui.ColorEdit4(label, ref colorV))
- {
- i1 = ColorVectorToInt(colorV);
- valueChanged = true;
- }
- break;
- }
- case ParameterType.FLOAT:
- case ParameterType.PATCH_FLOAT:
- {
- float f1 = v4.X;
- ImGui.SetNextItemWidth(width * defaultParamWidth);
- if (ImGui.DragFloat(label, ref f1, stepf, displayMinf, displayMaxf, "%.6f", ImGuiSliderFlags.NoRoundToFormat))
- {
- v4 = new Vector4(f1, 0.0f, 0.0f, 0.0f);
- valueChanged = true;
- }
- break;
- }
- case ParameterType.VECTOR2:
- {
- Vector2 v2 = new Vector2(v4.X, v4.Y);
- ImGui.SetNextItemWidth(width * defaultParamWidth * 2.0f);
- if (ImGui.DragFloat2(label, ref v2, stepf, displayMinf, displayMaxf, "%.5f", ImGuiSliderFlags.NoRoundToFormat))
- {
- v4 = new Vector4(v2.X, v2.Y, 0.0f, 0.0f);
- valueChanged = true;
- }
- break;
- }
- case ParameterType.VECTOR3:
- case ParameterType.COLOR_FACTOR:
+ ImGui.SameLine();
+ if (ImGui.Button("▲"))
{
- Vector3 v3 = new Vector3(v4.X, v4.Y, v4.Z);
- if (Type == ParameterType.COLOR_FACTOR)
+ // Create the new override before unsetting any lower priority overrides.
+ // Effectively, copy the current override value.
+ (Vector4 v4, int i1) = param.GetValue();
+ Override ov = new Override(param, v4, i1);
+ globalOverrides = config.Overrides[globalStage];
+ bool superseded = overridesContainsParam(externalOverrides.Values, param);
+ if (!superseded)
{
- Vector3 v3Color = v3;
- // Only scale the color vector if max is unbound. Otherwise, assume that intensity and color are seperate.
- if (maxf == Single.MaxValue)
+ BeginTransition();
+ if (!(stageOverrides != null && unsetIfOverridesContainsParam(stageOverrides, param)))
{
- float v3Max = MathF.Max(Math.Abs(v3.X), MathF.Max(Math.Abs(v3.Y), Math.Abs(v3.Z)));
- if (v3Max != 0.0f)
- {
- // I believe a compromise is needed here. These are the options I can think of.
- //v3Color /= v3Max; // Preview will be full "brightness" at low intensities.
- v3Color = v3Color * (v3Color / v3Max); // Preview will converge towards white at high intensities.
- }
+ unsetIfOverridesContainsParam(globalOverrides, param);
}
- ImGui.ColorEdit3(label, ref v3Color, ImGuiColorEditFlags.NoPicker | ImGuiColorEditFlags.NoLabel | ImGuiColorEditFlags.NoInputs);
- ImGui.SameLine();
- }
- ImGui.SetNextItemWidth(width * defaultParamWidth * 3.0f);
- if (ImGui.DragFloat3(label, ref v3, stepf, displayMinf, displayMaxf, "%.5f", ImGuiSliderFlags.NoRoundToFormat))
- {
- v4 = new Vector4(v3.X, v3.Y, v3.Z, 0.0f);
- valueChanged = true;
+ ov.Set();
+ EndTransition();
}
- break;
+ setOverrides.Add(ov);
+ configState |= SetNotSaved;
}
- case ParameterType.VECTOR4:
+ if (ImGui.BeginItemTooltip())
{
- ImGui.SetNextItemWidth(width * defaultParamWidth * 4.0f);
- if (ImGui.DragFloat4(label, ref v4, stepf, displayMinf, displayMaxf, "%.5f", ImGuiSliderFlags.NoRoundToFormat))
- {
- valueChanged = true;
- }
- break;
+ ImGui.Text($"Add to '{selectedSet}'");
+ ImGui.EndTooltip();
}
}
- if (valueChanged)
- {
- AdjustValue(ref v4, ref i1);
- }
- return valueChanged;
- }
-
- public void DrawReferenceValue(string name, Vector4 v4, int i1)
- {
- ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * fadeAlphaFactor);
- switch (Type)
- {
- case ParameterType.BOOL:
- case ParameterType.FLAG:
- ImGui.Text($"({name}: {i1 != 0})");
- break;
- case ParameterType.BYTE:
- case ParameterType.INT:
- case ParameterType.ALIGNED_INT:
- case ParameterType.SHADOW_RESOLUTION:
- ImGui.Text($"({name}: {i1})");
- break;
- case ParameterType.HEX:
- case ParameterType.BITS:
- case ParameterType.COLOR:
- ImGui.Text($"({name}: {i1:X})");
- break;
- case ParameterType.FLOAT:
- case ParameterType.PATCH_FLOAT:
- ImGui.Text($"({name}: {v4.X:0.000000})");
- break;
- case ParameterType.VECTOR2:
- ImGui.Text($"({name}: {v4.X:0.00000}, {v4.Y:0.00000})");
- break;
- case ParameterType.VECTOR3:
- case ParameterType.COLOR_FACTOR:
- ImGui.Text($"({name}: {v4.X:0.00000}, {v4.Y:0.00000}, {v4.Z:0.00000})");
- break;
- case ParameterType.VECTOR4:
- ImGui.Text($"({name}: {v4.X:0.00000}, {v4.Y:0.00000}, {v4.Z:0.00000}, {v4.W:0.00000})");
- break;
- }
- ImGui.PopStyleVar();
}
-
- public string SetByLine(Config config, List<Override>? stageOverrides, List<Override>? globalOverrides, bool forSet, bool allowGlobal)
+ else if (!overridesContainsParam(selectedOverrides, param))
{
- // 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);
- }
-
- public void Draw(ref Vector4 v4, ref int i1, float width, bool assumeOverride)
- {
- ImGui.PushID(Name);
-
- if (ViewOnly)
- {
- ImGui.SetCursorPos(ImGui.GetCursorPos() + new Vector2(ImGui.GetFrameHeight() + ImGui.GetStyle().ItemSpacing.X, 0.0f));
- }
- else if (!assumeOverride)
+ ImGui.SameLine();
+ if (ImGui.Button("▲"))
{
- if (overrideForStage)
+ (Vector4 v4, int i1) = param.GetValue();
+ Override ov = new Override(param, v4, i1);
+ if (selectedStage != globalStage)
{
- ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true);
- ImGui.PushItemFlag(ImGuiItemFlags.MixedValue, true);
+ globalOverrides = config.Overrides[globalStage];
}
- // If OverrideOn() were to set queuedOverride instead of overrideValue, this parameter shouldn't be drawn.
- Assert(!PendingUpdate());
- bool toggleOverride = overrideValue;
- if (ImGui.Checkbox("##Override", ref toggleOverride))
+ bool superseded = selectedOverrideSuperseded(config, globalOverrides, stageOverrides, param);
+ if (!superseded)
{
- if (toggleOverride)
- {
- OverrideOn(false);
- }
- else
+ BeginTransition();
+ if (globalOverrides != null)
{
- OverrideOff();
+ unsetIfOverridesContainsParam(globalOverrides, param);
}
+ ov.Set();
+ EndTransition();
}
- if (ImGui.BeginItemTooltip())
+ selectedOverrides.Add(ov);
+ if (selectedStage == globalStage)
{
- if (overrideForStage)
- {
- Config config = getConfig();
- List<Override>? globalOverrides = config.Overrides[globalStage];
- List<Override>? stageOverrides = maybeGetStageOverrides(config);
- ImGui.Text(SetByLine(config, stageOverrides, globalOverrides, false, true));
- }
- else if (overrideValue)
- {
- ImGui.Text("Set");
- }
- else
- {
- ImGui.Text("Set override");
- }
- ImGui.EndTooltip();
+ rebuildConfig(config, selectedOverrides);
}
- if (overrideForStage)
- {
- ImGui.PopItemFlag();
- ImGui.PopItemFlag();
- }
- ImGui.SameLine();
+ configState |= SelectedNotSaved;
}
-
- if (!overrideValue)
- {
- ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true);
- }
- if (DrawValue(ref valueV, ref valueInt, width, !bValue))
- {
- maybeWriteCurrentValue();
- }
- if (!overrideValue)
- {
- ImGui.PopItemFlag();
- }
-
- bool showButtons = !assumeOverride && overrideValue && !pendingUpdate;
- if (showButtons)
+ if (ImGui.BeginItemTooltip())
{
- ImGui.SameLine();
- if (!bValue)
- {
- if (ImGui.Button("B"))
- {
- bValueV = oValueV;
- bValueInt = oValueInt;
- bValue = true;
- }
- }
- else
- {
- if (ImGui.Button("A/B"))
- {
- (bValueV, valueV) = (valueV, bValueV);
- (bValueInt, valueInt) = (valueInt, bValueInt);
- maybeWriteCurrentValue();
- }
- ImGui.SameLine();
- DrawValue(ref bValueV, ref bValueInt, width, true);
- ImGui.SameLine();
- if (ImGui.Button("< B"))
- {
- bValue = false;
- }
- }
-
- Config config = getConfig();
- List<Override> selectedOverrides = config.Overrides[selectedStage];
- List<Override>? stageOverrides = maybeGetStageOverrides(config);
- // Deciding when to set globalOverrides copies the logic in OnImGuiRender().
- // Selected: Set if selectedStage != globalStage.
- // Set: Always set.
- List<Override>? globalOverrides = null;
- if (selectedSet != "")
- {
- List<Override> setOverrides = config.Sets[selectedSet];
- if (!overridesContainsParam(setOverrides, this))
- {
- ImGui.SameLine();
- if (ImGui.Button("▲"))
- {
- // Create the new override before unsetting any lower priority overrides.
- // Effectively, copy the current override value.
- Override ov = new Override(this, v4, i1);
- globalOverrides = config.Overrides[globalStage];
- bool superseded = overridesContainsParam(externalOverrides.Values, this);
- if (!superseded)
- {
- BeginTransition();
- if (!(stageOverrides != null && unsetIfOverridesContainsParam(stageOverrides, this)))
- {
- unsetIfOverridesContainsParam(globalOverrides, this);
- }
- ov.Set();
- EndTransition();
- }
- setOverrides.Add(ov);
- configState |= SetNotSaved;
- }
- if (ImGui.BeginItemTooltip())
- {
- ImGui.Text($"Add to '{selectedSet}'");
- ImGui.EndTooltip();
- }
- }
- }
- else if (!overridesContainsParam(selectedOverrides, this))
- {
- ImGui.SameLine();
- if (ImGui.Button("▲"))
- {
- Override ov = new Override(this, v4, i1);
- if (selectedStage != globalStage)
- {
- globalOverrides = config.Overrides[globalStage];
- }
- bool superseded = selectedOverrideSuperseded(config, globalOverrides, stageOverrides, this);
- if (!superseded)
- {
- BeginTransition();
- if (globalOverrides != null)
- {
- unsetIfOverridesContainsParam(globalOverrides, this);
- }
- ov.Set();
- EndTransition();
- }
- selectedOverrides.Add(ov);
- if (selectedStage == globalStage)
- {
- rebuildConfig(config, selectedOverrides);
- }
- configState |= SelectedNotSaved;
- }
- if (ImGui.BeginItemTooltip())
- {
- ImGui.Text($"Add to '{StageToString(selectedStage)}'");
- ImGui.EndTooltip();
- }
- }
-
- ImGui.SameLine();
- DrawReferenceValue("Original", oValueV, oValueInt);
+ ImGui.Text($"Add to '{StageToString(selectedStage)}'");
+ ImGui.EndTooltip();
}
-
- ImGui.PopID();
}
}
- public class Parameter<T> : Parameter where T : unmanaged
+ private static string setByLine(Parameter param, Config config, List<Override>? stageOverrides, List<Override>? globalOverrides, bool forSet, bool allowGlobal)
{
- public Parameter(string name, nint offset, int mask, ParameterType type, T? min, T? max, T? step, int flags) : base(name, offset, mask, type, flags)
+ // Reverse order of selectedOverrideSuperseded().
+ if (overridesContainsParam(externalOverrides.Values, param))
{
- if (typeof(T) == typeof(float))
- {
- Assert(type == ParameterType.FLOAT ||
- type == ParameterType.VECTOR2 ||
- type == ParameterType.VECTOR3 ||
- type == ParameterType.VECTOR4 ||
- type == ParameterType.PATCH_FLOAT ||
- type == ParameterType.COLOR_FACTOR);
- this.stepf = (step != null) ? Convert.ToSingle(step) : 0.1f;
- this.minf = (min != null) ? Convert.ToSingle(min) : -Single.MaxValue;
- this.maxf = (max != null) ? Convert.ToSingle(max) : Single.MaxValue;
- }
- else
- {
- this.step = (step != null) ? Convert.ToInt32(step) : 0;
- if (typeof(T) == typeof(int))
- {
- Assert(type == ParameterType.INT ||
- type == ParameterType.ALIGNED_INT ||
- type == ParameterType.HEX ||
- type == ParameterType.BITS ||
- type == ParameterType.COLOR ||
- type == ParameterType.SHADOW_RESOLUTION);
- this.min = (min != null) ? Convert.ToInt32(min) : Int32.MinValue;
- this.max = (max != null) ? Convert.ToInt32(max) : Int32.MaxValue;
- }
- else if (typeof(T) == typeof(byte))
- {
- Assert(type == ParameterType.BYTE);
- this.min = (min != null) ? Convert.ToInt32(min) : 0x0;
- this.max = (max != null) ? Convert.ToInt32(max) : 0xFF;
- }
- else if (typeof(T) == typeof(bool))
- {
- Assert(type == ParameterType.BOOL ||
- type == ParameterType.FLAG);
- this.min = 0;
- this.max = 1;
- }
- else
- {
- Assert();
- }
- }
+ return "Set by 'External'";
}
- }
-
- public static (float?, float?, float?) pStep(float step) { return (null, null, step); }
- public static (float?, float?, float?) pMin(float min) { return (min, null, null); }
- public static (float?, float?, float?) pMax(float max) { return (null, max, null); }
- public static (float?, float?, float?) pMinStep(float min, float step) { return (min, null, step); }
- public static (float?, float?, float?) pMaxStep(float max, float step) { return (null, max, step); }
- public static (float?, float?, float?) pMinMaxStep(float min, float max, float step) { return (min, max, step); }
- public static (int?, int?, int?) pStep(int step) { return (null, null, step); }
- public static (int?, int?, int?) pMin(int min) { return (min, null, null); }
- public static (int?, int?, int?) pMax(int max) { return (null, max, null); }
- public static (int?, int?, int?) pMinStep(int min, int step) { return (min, null, step); }
- public static (int?, int?, int?) pMaxStep(int max, int step) { return (null, max, step); }
- public static (int?, int?, int?) pMinMaxStep(int min, int max, int step) { return (min, max, step); }
- public static (byte?, byte?, byte?) pStep(byte step) { return (null, null, step); }
-
- public static Parameter<T> P<T>(string name, nint offset, ParameterType type, (T? min, T? max, T? step) m = default) where T : unmanaged
- {
- return new Parameter<T>(name, offset, 0, type, m.min, m.max, m.step, 0);
- }
-
- public static Parameter<T> P<T>(string name, long offset, ParameterType type, (T? min, T? max, T? step) m = default) where T : unmanaged
- {
- return new Parameter<T>(name, (nint)offset, 0, type, m.min, m.max, m.step, 0);
- }
-
- public static Parameter<T> V<T>(string name, nint offset, ParameterType type, (T? min, T? max, T? step) m = default) where T : unmanaged
- {
- return new Parameter<T>(name, offset, 0, type, m.min, m.max, m.step, ParameterFlags.ViewOnly);
- }
-
- public static Parameter<T> M<T>(string name, nint offset, ParameterType type, int mask, (T? min, T? max, T? step) m = default) where T : unmanaged
- {
- return new Parameter<T>(name, offset, mask, type, m.min, m.max, m.step, 0);
- }
-
- internal static Parameter? getParameterByName(string name)
- {
- if (OldParameterNames.TryGetValue(name, out string? newName))
+ Assert(!forSet);
+ if (selectedSet != "" && overridesContainsParam(config.Sets[selectedSet], param))
{
- Log.Warn($"Paramter '{name}' renamed to '{newName}'.");
- name = newName;
+ return $"Set by '{selectedSet}'";
}
- foreach (Parameter param in allParameters)
+ if ((allowGlobal || globalOverrides == null) && stageOverrides != null && overridesContainsParam(stageOverrides, param))
{
- if (param.Name == name)
- {
- return param;
- }
+ return $"Set by '{StageToString(currentStage)}'";
}
- return null;
+ if (allowGlobal)
+ {
+ return "Set by \'Global\'";
+ }
+ // Superseded because inactive.
+ Assert(globalOverrides != null && selectedStage != currentStage);
+ return "";
}
public class Override
@@ -1629,7 +605,7 @@ namespace WorldTuningTool
if (superseded)
{
// Global is the lowest priority so "Set by 'Global'" never applies here.
- byLine = Param.SetByLine(config, stageOverrides, globalOverrides, forSet, false);
+ byLine = setByLine(Param, config, stageOverrides, globalOverrides, forSet, false);
}
Param.DrawReferenceValue((byLine == "") ? "Current" : byLine, v4, i1);
hasStatus = true;
@@ -1662,24 +638,6 @@ namespace WorldTuningTool
private delegate void UpdateToneMapParams(nint stackOffset, nint toneMapObjectInternal);
private Hook<UpdateToneMapParams>? updateToneMapParams;
- private static bool InTransition = false;
- private static List<Parameter> DirtyParams = new List<Parameter>();
- private static void BeginTransition()
- {
- Assert(!InTransition && DirtyParams.Count == 0);
- InTransition = true;
- }
- private static void EndTransition()
- {
- Assert(InTransition);
- InTransition = false;
- foreach (Parameter param in DirtyParams)
- {
- param.Resolve();
- }
- DirtyParams.Clear();
- }
-
private static MtObject? sMhScene = null;
private static MtObject? sMhMain = null;
private static MtObject? sMhRender = null;
@@ -2387,6 +1345,18 @@ namespace WorldTuningTool
setShadowQuality.Invoke(sMhScene!.Get<int>(0x5530) + 1);
}
+ private static void handleShadowResParameter(int multiplier)
+ {
+ if (multiplier > 1)
+ {
+ shadowResEnable(multiplier);
+ }
+ else
+ {
+ shadowResDisable();
+ }
+ }
+
#if SHADER_FEATURES
private bool fullResSSLR = false;
#endif
@@ -2573,6 +1543,10 @@ namespace WorldTuningTool
{
Instance = this;
+ PFuncs.HandleShadowResolution = handleShadowResParameter;
+ PFuncs.DrawStageOverrideTooltip = drawStageOverrideTooltip;
+ PFuncs.DrawExtraButtons = drawExtraButtons;
+
// Assert no duplicate names.
foreach (Parameter param in allParameters)
{
@@ -3685,8 +2659,7 @@ namespace WorldTuningTool
private void HandleGlobalChange()
{
Config config = getConfig();
-
- // Unset current Global overrides.
+ // Unset and drop current Global overrides.
List<Override>? stageOverrides = maybeGetStageOverrides(config);
List<Override> globalOverrides = config.Overrides[globalStage];
foreach (Override ovG in globalOverrides)
@@ -3697,17 +2670,12 @@ namespace WorldTuningTool
ovG.Unset();
}
}
-
- // Drop current Global overrides.
globalOverrides.Clear();
-
// Rebuild from new selections.
foreach (Override ovG in config.Globals[selectedGlobal])
{
globalOverrides.Add(ovG);
}
-
- // Set new Global overrides.
foreach (Override ovG in globalOverrides)
{
bool superseded = selectedOverrideSuperseded(config, null, stageOverrides, ovG.Param);
@@ -4847,7 +3815,7 @@ namespace WorldTuningTool
if (ImGui.CollapsingHeader("DEBUG"))
{
- ImGui.Checkbox("Globally Ignore Parameter Min/Max", ref ignoreMinMax);
+ ImGui.Checkbox("Globally Ignore Parameter Min/Max", ref IgnoreMinMax);
if (ImGui.BeginItemTooltip())
{
ImGui.Text("Some min/max values are set to avoid crashes, so be warned.");