diff options
| author | 2026-06-16 15:08:46 -0400 | |
|---|---|---|
| committer | 2026-06-16 15:08:46 -0400 | |
| commit | c691596de197ce3feec1217643b09783010fc415 (patch) | |
| tree | cd5df340f6a3d149b64b2c9381326d55f628b386 /Plugin.cs | |
| parent | 4e55d412c3fe79e62c396e209c509dff3ef3ee3c (diff) | |
| download | WorldTuningTool-c691596de197ce3feec1217643b09783010fc415.tar.gz WorldTuningTool-c691596de197ce3feec1217643b09783010fc415.tar.bz2 WorldTuningTool-c691596de197ce3feec1217643b09783010fc415.zip | |
Optimize transitions, fix crash on new character
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'Plugin.cs')
| -rwxr-xr-x | Plugin.cs | 339 |
1 files changed, 234 insertions, 105 deletions
@@ -1,6 +1,7 @@ //#define ENABLE_ASSERTS
//#define OVERSIZED_SHADOW_MAP
//#define SHADER_FEATURES
+//#define RESOURCE_ADJUSTMENT
using System.Numerics;
using System.Globalization;
@@ -13,13 +14,14 @@ using SharpPluginLoader.Core; #if SHADER_FEATURES
using SharpPluginLoader.Core.Rendering;
#endif
-//using SharpPluginLoader.Core.Resources;
+#if RESOURCE_ADJUSTMENT
+using SharpPluginLoader.Core.Resources;
+#endif
using SharpPluginLoader.Core.Configuration;
using SharpPluginLoader.Core.Memory;
using SharpPluginLoader.Core.Entities;
// @TODO:
-// - Hair clipping while looking down.
// - Optimized update logic.
// - Only update non-override values when ui is shown.
// - Map sky params.
@@ -37,6 +39,7 @@ using SharpPluginLoader.Core.Entities; // - Hotload nukes config?
//
// Known issues to think about:
+// - Hair clipping while looking down.
// - 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.
@@ -133,23 +136,31 @@ namespace WorldTuningTool static void saveConfig()
{
ConfigManager.SaveConfig<Config>(Instance!);
+ selectedOrderChanged = false;
+ presetOrderChanged = false;
}
private const float defaultParamWidth = 0.215f;
private static bool ignoreMinMax = false;
- private const Stage globalStage = Stage.InfinityOfNothingHandler;
- private static Stage currentStage => Area.CurrentStage;
- private static Stage selectedStage = globalStage;
- private static Stage previousStage = selectedStage;
-
+ private const StageExt globalStage = StageExt.Global;
+ private static StageExt currentStage => (StageExt)Area.CurrentStage;
private static List<Override>? maybeGetStageOverrides(Config config)
{
- return (currentStage != 0) ? config.Overrides[currentStage] : null;
+ if (!config.Overrides.ContainsKey(currentStage))
+ {
+ return null;
+ }
+ return (currentStage != StageExt.Global) ? config.Overrides[currentStage] : null;
}
+ private static StageExt selectedStage = globalStage;
+ private static StageExt previousStage = selectedStage;
+ private static bool selectedOrderChanged = false;
+
private static string selectedPreset = "";
+ private static bool presetOrderChanged = false;
private static bool renamingPreset = false;
private static string typedPresetName = "";
@@ -236,6 +247,7 @@ namespace WorldTuningTool protected float stepf, minf, maxf;
protected int step, min, max;
+ private bool pendingWrite = false;
private Vector4 valueV = default;
private int valueInt = 0;
private Vector4 oValueV; // Original value.
@@ -287,8 +299,25 @@ namespace WorldTuningTool return mask;
}
+ public void Resolve()
+ {
+ Assert(!InTransition);
+ if (pendingWrite)
+ {
+ pendingWrite = false;
+ maybeWriteCurrentValue();
+ }
+ }
+
private void maybeWriteCurrentValue()
{
+ if (InTransition)
+ {
+ pendingWrite = true;
+ DirtyParams.Add(this);
+ return;
+ }
+ Assert(!pendingWrite);
switch (Type)
{
case ParameterType.PATCH_FLOAT:
@@ -752,8 +781,10 @@ namespace WorldTuningTool public void Draw(ref Vector4 v4, ref int i1, float width, bool assumeOverride)
{
ImGui.PushID(Name);
+
if (NoOverride)
{
+ // Dependent on overall ImGui style.
ImGui.SetCursorPos(ImGui.GetCursorPos() + new Vector2(40.0f, 0.0f));
}
else if (!assumeOverride)
@@ -794,6 +825,7 @@ namespace WorldTuningTool }
ImGui.SameLine();
}
+
if (!overrideValue)
{
ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true);
@@ -806,7 +838,7 @@ namespace WorldTuningTool {
ImGui.PopItemFlag();
}
- Config config = getConfig();
+
bool showButtons = !assumeOverride && overrideValue && !pendingUpdate;
if (showButtons)
{
@@ -836,13 +868,12 @@ namespace WorldTuningTool 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().
List<Override>? globalOverrides = null;
- if (selectedStage != globalStage)
- {
- globalOverrides = config.Overrides[globalStage];
- }
if (selectedPreset != "")
{
List<Override> presetOverrides = config.Presets[selectedPreset];
@@ -853,19 +884,20 @@ namespace WorldTuningTool {
// Create override before unsetting global.
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)))
{
- if (globalOverrides != null)
- {
- unsetIfOverridesContainsParam(globalOverrides, this);
- }
+ unsetIfOverridesContainsParam(globalOverrides, this);
}
ov.Set();
+ EndTransition();
}
presetOverrides.Add(ov);
+ presetOrderChanged = true;
}
if (ImGui.BeginItemTooltip())
{
@@ -881,16 +913,23 @@ namespace WorldTuningTool {
// Create override before unsetting global.
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);
+ selectedOrderChanged = true;
}
if (ImGui.BeginItemTooltip())
{
@@ -898,9 +937,11 @@ namespace WorldTuningTool ImGui.EndTooltip();
}
}
+
ImGui.SameLine();
DrawReferenceValue("Original", oValueV, oValueInt);
}
+
ImGui.PopID();
}
}
@@ -1133,6 +1174,7 @@ namespace WorldTuningTool bool isSelected = Param == iterParam;
if (ImGui.Selectable(iterParam.Name, isSelected))
{
+ BeginTransition();
bool wasSet = isSet;
if (wasSet)
{
@@ -1179,6 +1221,7 @@ namespace WorldTuningTool Set();
}
}
+ EndTransition();
}
if (isSelected) ImGui.SetItemDefaultFocus();
}
@@ -1255,6 +1298,24 @@ namespace WorldTuningTool private delegate void OnAreaChange(nint unknownPtr);
private Hook<OnAreaChange>? onAreaChange;
+ 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 Parameter hqMode = newParameter<bool>("HQ Mode", 0xE9A3, ParameterType.BOOL);
@@ -1840,6 +1901,7 @@ namespace WorldTuningTool {
Override ov = new Override(param, v4, i1);
Config config = getConfig();
+ BeginTransition();
if (!(selectedPreset != "" && unsetIfOverridesContainsParam(config.Presets[selectedPreset], param)))
{
List<Override>? stageOverrides = maybeGetStageOverrides(config);
@@ -1849,6 +1911,7 @@ namespace WorldTuningTool }
}
ov.Set();
+ EndTransition();
externalId++;
externalOverrides.Add(externalId, ov);
return externalId;
@@ -1862,6 +1925,7 @@ namespace WorldTuningTool if (externalOverrides.ContainsKey(id))
{
Override ovE = externalOverrides[id];
+ BeginTransition();
ovE.Unset();
Config config = getConfig();
if (!(selectedPreset != "" && setIfOverridesContainsParam(config.Presets[selectedPreset], ovE.Param!)))
@@ -1872,6 +1936,7 @@ namespace WorldTuningTool setIfOverridesContainsParam(config.Overrides[globalStage], ovE.Param!);
}
}
+ EndTransition();
externalOverrides.Remove(id);
}
}
@@ -1886,6 +1951,13 @@ namespace WorldTuningTool Assert(Array.FindAll(allParameters, (p => p.Name == param.Name)).Length == 1);
}
+ // Assert OrderedStages covers all values.
+ foreach (StageExt stage in Enum.GetValues(typeof(StageExt)))
+ {
+ if (stage == StageExt.Global) continue;
+ Assert(Config.OrderedStages.Contains(stage));
+ }
+
onAreaChange = Hook.Create<OnAreaChange>(0x141AC27D0, OnAreaChangeHook); // nint
// Needed for at least "Broad Area Shadow Dir". Otherwise it will flicker during an update on center change.
@@ -2121,7 +2193,11 @@ namespace WorldTuningTool sMhScene = SingletonManager.GetSingleton("sMhScene")!;
sLightProbes = SingletonManager.GetSingleton("sLightProbes")!;
Config config = getConfig();
- foreach (Stage area in Enum.GetValues(typeof(Stage)))
+ if (!config.Overrides.ContainsKey(globalStage))
+ {
+ config.Overrides.Add(globalStage, new List<Override>());
+ }
+ foreach (StageExt area in Config.OrderedStages)
{
if (!config.Overrides.ContainsKey(area))
{
@@ -2132,13 +2208,21 @@ namespace WorldTuningTool {
ovG.Set();
}
+ selectedPreset = config.SelectedPreset;
+ if (selectedPreset != "")
+ {
+ List<Override> globalOverrides = config.Overrides[globalStage];
+ List<Override>? stageOverrides = maybeGetStageOverrides(config);
+ HandlePresetChange("", globalOverrides, stageOverrides);
+ }
saveConfig();
}
- /* It's hard to test, but I'm pretty sure just updating stepTime isn't enough for a higher rate to look right.
+ // It's hard to test, but I'm pretty sure just updating stepTime isn't enough for a higher rate to look right.
// https://github.com/AsteriskAmpersand/CTC-MHW-Editor/blob/9ec6303042690478398801b1bb860a2d38298eee/structures/Ctc.py#L23
- private static bool adjustCtcParams = false;
- private static float stepTimeFps = 60.0f;
+#if RESOURCE_ADJUSTMENT
+ private bool adjustCtcParams = false;
+ private float stepTimeFps = 60.0f;
public void OnResourceLoad(Resource? resource, MtDti dti, string path, LoadFlags flags)
{
if (adjustCtcParams && resource != null && resource.FileExtension == "ctc")
@@ -2153,10 +2237,15 @@ namespace WorldTuningTool MemoryUtil.GetRef<float>(resource.Instance + 0xC4) = 1.0f / stepTimeFps;
}
}
- */
+#endif
public void OnUpdate(float deltaTime)
{
+ StageExt stage = currentStage;
+ if (stage == StageExt.Global && previousStage != StageExt.Global)
+ {
+ HandleAreaChange(stage);
+ }
hqMode.Update(sMhScene!.Instance);
foreach (Parameter param in lodParameters)
{
@@ -2613,35 +2702,77 @@ namespace WorldTuningTool }
}
- private void OnAreaChangeHook(nint unknownPtr)
+ private void HandlePresetChange(string prevPreset, List<Override> globalOverrides, List<Override>? stageOverrides)
{
- onAreaChange!.Original(unknownPtr);
- Stage stage = currentStage;
- if (stage == 0) stage = globalStage;
- if (stage == previousStage) return;
Config config = getConfig();
- List<Override> prevOverrides = config.Overrides[previousStage];
- previousStage = stage;
- List<Override>? globalOverrides = null;
- if (stage != globalStage)
+ BeginTransition();
+ if (prevPreset != "")
{
- globalOverrides = config.Overrides[globalStage];
+ List<Override> prevOverrides = config.Presets[prevPreset];
+ foreach (Override ovR in prevOverrides)
+ {
+ bool superseded = ovR.Param != null && overridesContainsParam(externalOverrides.Values, ovR.Param);
+ if (!superseded)
+ {
+ ovR.Unset();
+ if (ovR.Param != null)
+ {
+ if (!(stageOverrides != null && setIfOverridesContainsParam(stageOverrides, ovR.Param)))
+ {
+ setIfOverridesContainsParam(globalOverrides, ovR.Param);
+ }
+ }
+ }
+ }
+ }
+ if (selectedPreset != "")
+ {
+ List<Override> newOverrides = config.Presets[selectedPreset];
+ foreach (Override ovN in newOverrides)
+ {
+ bool superseded = ovN.Param != null && overridesContainsParam(externalOverrides.Values, ovN.Param);
+ if (!superseded)
+ {
+ if (ovN.Param != null)
+ {
+ if (!(stageOverrides != null && unsetIfOverridesContainsParam(stageOverrides, ovN.Param)))
+ {
+ unsetIfOverridesContainsParam(globalOverrides, ovN.Param);
+ }
+ }
+ ovN.Set();
+ }
+ }
+ }
+ EndTransition();
+ }
+
+ private void HandleAreaChange(StageExt stage)
+ {
+ Config config = getConfig();
+ if (!config.Overrides.ContainsKey(stage))
+ {
+ return;
}
- foreach (Override ovR in prevOverrides)
+ List<Override> prevOverrides = config.Overrides[previousStage];
+ List<Override> globalOverrides = config.Overrides[globalStage];
+ BeginTransition();
+ if (previousStage != globalStage)
{
- // If previousStage was global, none of it's parameters could have been
- // superseded by a non-global stage override.
- bool superseded = stageOverrideSuperseded(config, ovR.Param);
- if (!superseded)
+ foreach (Override ovR in prevOverrides)
{
- ovR.Unset();
- if (ovR.Param != null && globalOverrides != null)
+ bool superseded = stageOverrideSuperseded(config, ovR.Param);
+ if (!superseded)
{
- setIfOverridesContainsParam(globalOverrides, ovR.Param);
+ ovR.Unset();
+ if (ovR.Param != null)
+ {
+ setIfOverridesContainsParam(globalOverrides, ovR.Param);
+ }
}
}
}
- if (globalOverrides != null) // Stage isn't global.
+ if (stage != globalStage)
{
List<Override> stageOverrides = config.Overrides[stage];
foreach (Override ovS in stageOverrides)
@@ -2657,6 +2788,19 @@ namespace WorldTuningTool }
}
}
+ EndTransition();
+ previousStage = stage;
+ }
+
+ private void OnAreaChangeHook(nint unknownPtr)
+ {
+ onAreaChange!.Original(unknownPtr);
+ StageExt stage = currentStage;
+ if (stage == previousStage)
+ {
+ return;
+ }
+ HandleAreaChange(stage);
}
public void OnImGuiRender()
@@ -2664,25 +2808,11 @@ namespace WorldTuningTool float width = ImGui.GetWindowWidth();
width /= width / 600.0f;
- /*
- if (ImGui.TextLink($"Current Stage: {Config.StageToString(currentStage)}"))
- {
- if (currentStage == 0)
- {
- selectedStage = globalStage;
- }
- else
- {
- selectedStage = currentStage;
- }
- }
- */
ImGui.Text($"Current Stage: {Config.StageToString(currentStage)}");
-
ImGui.PushItemWidth(width * 0.35f);
if (ImGui.BeginCombo("##Stage", Config.StageToString(selectedStage), ImGuiComboFlags.HeightLarge))
{
- foreach (Stage area in Enum.GetValues(typeof(Stage)))
+ foreach (StageExt area in Config.OrderedStages)
{
string name = Config.StageToString(area);
bool isSelected = selectedStage == area;
@@ -2695,23 +2825,27 @@ namespace WorldTuningTool ImGui.EndCombo();
}
ImGui.SameLine();
+ Config config = getConfig();
+ bool invalidStage = !config.Overrides.ContainsKey(currentStage);
+ if (invalidStage)
+ {
+ ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true);
+ ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f);
+ }
if (ImGui.Button("Current"))
{
- if (currentStage != 0)
- {
- selectedStage = currentStage;
- }
- else
- {
- selectedStage = globalStage;
- }
+ selectedStage = currentStage;
+ }
+ if (invalidStage)
+ {
+ ImGui.PopStyleVar();
+ ImGui.PopItemFlag();
}
ImGui.SameLine();
if (ImGui.Button("Global"))
{
selectedStage = globalStage;
}
- Config config = getConfig();
List<Override> selectedOverrides = config.Overrides[selectedStage];
List<Override>? stageOverrides = maybeGetStageOverrides(config);
List<Override>? globalOverrides = null;
@@ -2722,11 +2856,12 @@ namespace WorldTuningTool if (ImGui.Button("Add override"))
{
Override ov = new Override();
- if (selectedStage == currentStage || selectedStage == globalStage)
+ if (selectedStage == currentStage)
{
ov.Set(); // Empty override never superseded.
}
selectedOverrides.Add(ov);
+ selectedOrderChanged = true;
}
ImGui.PopItemWidth();
for (int i = 0; i < selectedOverrides.Count; i++)
@@ -2743,23 +2878,28 @@ namespace WorldTuningTool if (requestDown && i < selectedOverrides.Count - 1)
{
(selectedOverrides[i], selectedOverrides[i + 1]) = (selectedOverrides[i + 1], selectedOverrides[i]);
+ selectedOrderChanged = true;
}
ovS.Draw(selectedOverrides, null, globalOverrides, superseded, false, width);
if (requestUp && i > 0)
{
(selectedOverrides[i], selectedOverrides[i - 1]) = (selectedOverrides[i - 1], selectedOverrides[i]);
+ selectedOrderChanged = true;
}
if (requestRemove)
{
if (!superseded)
{
+ BeginTransition();
ovS.Unset();
if (ovS.Param != null && globalOverrides != null)
{
setIfOverridesContainsParam(globalOverrides, ovS.Param);
}
+ EndTransition();
}
selectedOverrides.RemoveAt(i);
+ selectedOrderChanged = true;
i--;
}
ImGui.PopID();
@@ -2779,10 +2919,17 @@ namespace WorldTuningTool }
saveConfig();
}
+ if (selectedOrderChanged)
+ {
+ ImGui.SameLine();
+ ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f);
+ ImGui.Text("(Not Saved)");
+ ImGui.PopStyleVar();
+ }
ImGui.Separator();
- // Global overrides and presets could now be show at the same time.
+ // We now have to consider both global and stage overrides.
globalOverrides = config.Overrides[globalStage];
ImGui.PushID("Preset");
@@ -2799,6 +2946,8 @@ namespace WorldTuningTool }
config.Presets[presetName] = new List<Override>();
selectedPreset = presetName;
+ config.SelectedPreset = selectedPreset;
+ saveConfig();
}
ImGui.SameLine();
if (renamingPreset)
@@ -2825,44 +2974,9 @@ namespace WorldTuningTool }
if (prevPreset != selectedPreset)
{
- if (prevPreset != "")
- {
- List<Override> prevOverrides = config.Presets[prevPreset];
- foreach (Override ovR in prevOverrides)
- {
- bool superseded = ovR.Param != null && overridesContainsParam(externalOverrides.Values, ovR.Param);
- if (!superseded)
- {
- ovR.Unset();
- if (ovR.Param != null)
- {
- if (!(stageOverrides != null && setIfOverridesContainsParam(stageOverrides, ovR.Param)))
- {
- setIfOverridesContainsParam(globalOverrides, ovR.Param);
- }
- }
- }
- }
- }
- if (selectedPreset != "")
- {
- List<Override> newOverrides = config.Presets[selectedPreset];
- foreach (Override ovN in newOverrides)
- {
- bool superseded = ovN.Param != null && overridesContainsParam(externalOverrides.Values, ovN.Param);
- if (!superseded)
- {
- if (ovN.Param != null)
- {
- if (!(stageOverrides != null && unsetIfOverridesContainsParam(stageOverrides, ovN.Param)))
- {
- unsetIfOverridesContainsParam(globalOverrides, ovN.Param);
- }
- }
- ovN.Set();
- }
- }
- }
+ HandlePresetChange(prevPreset, globalOverrides, stageOverrides);
+ config.SelectedPreset = selectedPreset;
+ saveConfig();
}
if (renamingPreset)
{
@@ -2898,6 +3012,8 @@ namespace WorldTuningTool config.Presets.Remove(selectedPreset);
config.Presets[presetName] = tmpOverrides;
selectedPreset = presetName;
+ config.SelectedPreset = selectedPreset;
+ saveConfig();
}
renamingPreset = false;
}
@@ -2919,6 +3035,7 @@ namespace WorldTuningTool Override ov = new Override();
ov.Set(); // Empty override never superseded.
presetOverrides.Add(ov);
+ presetOrderChanged = true;
}
for (int i = 0; i < presetOverrides.Count; i++)
{
@@ -2934,16 +3051,19 @@ namespace WorldTuningTool if (requestDown && i < presetOverrides.Count - 1)
{
(presetOverrides[i], presetOverrides[i + 1]) = (presetOverrides[i + 1], presetOverrides[i]);
+ presetOrderChanged = true;
}
ovP.Draw(presetOverrides, stageOverrides, globalOverrides, superseded, true, width);
if (requestUp && i > 0)
{
(presetOverrides[i], presetOverrides[i - 1]) = (presetOverrides[i - 1], presetOverrides[i]);
+ presetOrderChanged = true;
}
if (requestRemove)
{
if (!superseded)
{
+ BeginTransition();
ovP.Unset();
if (ovP.Param != null)
{
@@ -2952,8 +3072,10 @@ namespace WorldTuningTool setIfOverridesContainsParam(globalOverrides, ovP.Param);
}
}
+ EndTransition();
}
presetOverrides.RemoveAt(i);
+ presetOrderChanged = true;
i--;
}
ImGui.PopID();
@@ -2973,6 +3095,13 @@ namespace WorldTuningTool }
saveConfig();
}
+ if (presetOrderChanged)
+ {
+ ImGui.SameLine();
+ ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f);
+ ImGui.Text("(Not Saved)");
+ ImGui.PopStyleVar();
+ }
}
ImGui.PopID();
|