summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Config.cs6
-rw-r--r--LUT.cs2
-rw-r--r--Lights.cs55
-rw-r--r--Parameter.cs10
-rw-r--r--Plugin.cs174
-rw-r--r--Utility.cs162
6 files changed, 255 insertions, 154 deletions
diff --git a/Config.cs b/Config.cs
index f8ecb0c..653099e 100644
--- a/Config.cs
+++ b/Config.cs
@@ -50,8 +50,8 @@ namespace WorldTuningTool
public class Config : IConfig
{
- public String Name => "WorldTuningTool";
- public String Version => "0.9.7";
+ public string Name => "WorldTuningTool";
+ public string Version => "0.9.8";
public static string StageToString(StageExt stage)
{
@@ -185,7 +185,7 @@ namespace WorldTuningTool
public bool FullResolutionSSLR { get; set; } = false;
public bool VolumeUpsampleNoLinear { get; set; } = false;
public bool FXAAMaxQualityPreset { get; set; } = false;
- public bool SkinAllowNegativeWetness { get; set; } = false;
+ public bool AddTonemappers { get; set; } = false;
#endif
public bool FullResolutionVolumeBlur { get; set; } = false;
public bool HigherThanHighestVolumeRendering { get; set; } = false;
diff --git a/LUT.cs b/LUT.cs
index 82a7486..a3aa536 100644
--- a/LUT.cs
+++ b/LUT.cs
@@ -231,6 +231,7 @@ namespace WorldTuningTool
reloadBlendLUT(lightingObject);
}
}
+ if (isSelected) ImGui.SetItemDefaultFocus();
}
if (!selectionStarted[i])
{
@@ -249,6 +250,7 @@ namespace WorldTuningTool
reloadBlendLUT(lightingObject);
}
}
+ if (isSelected) ImGui.SetItemDefaultFocus();
}
ImGui.EndCombo();
}
diff --git a/Lights.cs b/Lights.cs
index b6943e9..c65645b 100644
--- a/Lights.cs
+++ b/Lights.cs
@@ -18,7 +18,7 @@ namespace WorldTuningTool
{
public nint Object = 0x0;
public virtual int Type => -1;
- public virtual string Name => $"Light";
+ public virtual string Name => "Light";
public virtual string Info => $"0x{Object:X}";
public List<Parameter> Parameters = new List<Parameter>();
@@ -39,7 +39,7 @@ namespace WorldTuningTool
private class uLight : BaseLight
{
- public override string Name => $"uLight";
+ public override string Name => "uLight";
public uLight(nint lightObject) : base(lightObject)
{
@@ -69,7 +69,7 @@ namespace WorldTuningTool
private class uInfiniteLight : uLight
{
public override int Type => 1;
- public override string Name => $"uInfiniteLight";
+ public override string Name => "uInfiniteLight";
// mpTexture unaccounted for.
public uInfiniteLight(nint lightObject) : base(lightObject)
@@ -109,7 +109,7 @@ namespace WorldTuningTool
private class uMhInfiniteLight : uInfiniteLight
{
- public override string Name => $"uMhInfiniteLight";
+ public override string Name => "uMhInfiniteLight";
public uMhInfiniteLight(nint lightObject) : base(lightObject)
{
@@ -123,7 +123,7 @@ namespace WorldTuningTool
private class uMhActorInfiniteLight : uMhInfiniteLight
{
- public override string Name => $"uMhActorInfiniteLight";
+ public override string Name => "uMhActorInfiniteLight";
public uMhActorInfiniteLight(nint lightObject) : base(lightObject)
{
@@ -132,7 +132,7 @@ namespace WorldTuningTool
private class uLlkInfiniteLight : uInfiniteLight
{
- public override string Name => $"uLlkInfiniteLight";
+ public override string Name => "uLlkInfiniteLight";
public nint CycleTimelineRes => Get<nint>(Object, 0x658);
public int CycleAnimNo => Get<int>(Object, 0x7A8);
@@ -149,7 +149,7 @@ namespace WorldTuningTool
private class uLlkActorInfiniteLight : uLlkInfiniteLight
{
- public override string Name => $"uLlkActorInfiniteLight";
+ public override string Name => "uLlkActorInfiniteLight";
public uLlkActorInfiniteLight(nint lightObject) : base(lightObject)
{
@@ -158,7 +158,7 @@ namespace WorldTuningTool
private class uLlkFollowCameraInfiniteLight : uLlkInfiniteLight
{
- public override string Name => $"uLlkFollowCameraInfiniteLight";
+ public override string Name => "uLlkFollowCameraInfiniteLight";
public uLlkFollowCameraInfiniteLight(nint lightObject) : base(lightObject)
{
@@ -168,7 +168,7 @@ namespace WorldTuningTool
private class uPointLight : uLight
{
public override int Type => 2;
- public override string Name => $"uPointLight";
+ public override string Name => "uPointLight";
public override string Info => $"0x{Object:X}" + (Parent != 0x0 ? $", Parent: 0x{Parent:X}" : "");
public nint Parent => Get<nint>(Object, 0x5C0);
public int ParentNo => Get<int>(Object, 0x5C8);
@@ -187,7 +187,7 @@ namespace WorldTuningTool
private class uMhPointLight : uPointLight
{
- public override string Name => $"uMhPointLight";
+ public override string Name => "uMhPointLight";
public uMhPointLight(nint lightObject) : base(lightObject)
{
@@ -211,7 +211,7 @@ namespace WorldTuningTool
private class uMhActorPointLight : uMhPointLight
{
- public override string Name => $"uMhActorPointLight";
+ public override string Name => "uMhActorPointLight";
public uMhActorPointLight(nint lightObject) : base(lightObject)
{
@@ -220,7 +220,7 @@ namespace WorldTuningTool
private class uLlkPointLight : uPointLight
{
- public override string Name => $"uLlkPointLight";
+ public override string Name => "uLlkPointLight";
public nint TimelineRes => Get<nint>(Object, 0x8A4);
public int AnimNo => Get<int>(Object, 0x7A8);
public NativeAction<nint> PlayResource = new NativeAction<nint>(0x141F89CB0);
@@ -256,7 +256,7 @@ namespace WorldTuningTool
private class uLlkActorPointLight : uLlkPointLight
{
- public override string Name => $"uLlkActorPointLight";
+ public override string Name => "uLlkActorPointLight";
public uLlkActorPointLight(nint lightObject) : base(lightObject)
{
@@ -265,7 +265,7 @@ namespace WorldTuningTool
private class uLlkFollowCameraPointLight : uLlkPointLight
{
- public override string Name => $"uLlkFollowCameraPointLight";
+ public override string Name => "uLlkFollowCameraPointLight";
public uLlkFollowCameraPointLight(nint lightObject) : base(lightObject)
{
@@ -275,7 +275,7 @@ namespace WorldTuningTool
private class uSpotLight : uLight
{
public override int Type => 3;
- public override string Name => $"uSpotLight";
+ public override string Name => "uSpotLight";
public override string Info => $"0x{Object:X}" + (Parent != 0x0 ? $", Parent: 0x{Parent:X}" : "");
public nint Parent => Get<nint>(Object, 0x600);
public int ParentNo => Get<int>(Object, 0x610);
@@ -309,7 +309,7 @@ namespace WorldTuningTool
private class uMhSpotLight : uSpotLight
{
- public override string Name => $"uMhSpotLight";
+ public override string Name => "uMhSpotLight";
public uMhSpotLight(nint lightObject) : base(lightObject)
{
@@ -336,7 +336,7 @@ namespace WorldTuningTool
private class uMhActorSpotLight : uMhSpotLight
{
- public override string Name => $"uMhActorSpotLight";
+ public override string Name => "uMhActorSpotLight";
public uMhActorSpotLight(nint lightObject) : base(lightObject)
{
@@ -345,7 +345,7 @@ namespace WorldTuningTool
private class uLlkSpotLight : uSpotLight
{
- public override string Name => $"uLlkSpotLight";
+ public override string Name => "uLlkSpotLight";
public nint TimelineRes => Get<nint>(Object, 0x790);
public int AnimNo => Get<int>(Object, 0x974);
public NativeAction<nint> PlayResource = new NativeAction<nint>(0x141F8D550);
@@ -385,7 +385,7 @@ namespace WorldTuningTool
private class uLlkActorSpotLight : uLlkSpotLight
{
- public override string Name => $"uLlkActorSpotLight";
+ public override string Name => "uLlkActorSpotLight";
public uLlkActorSpotLight(nint lightObject) : base(lightObject)
{
@@ -394,7 +394,7 @@ namespace WorldTuningTool
private class uLlkNullAngleSpotLight : uLlkSpotLight
{
- public override string Name => $"uLlkNullAngleSpotLight";
+ public override string Name => "uLlkNullAngleSpotLight";
public uLlkNullAngleSpotLight(nint lightObject) : base(lightObject)
{
@@ -403,7 +403,7 @@ namespace WorldTuningTool
private class uLlkFollowCameraSpotLight : uLlkSpotLight
{
- public override string Name => $"uLlkFollowCameraSpotLight";
+ public override string Name => "uLlkFollowCameraSpotLight";
public uLlkFollowCameraSpotLight(nint lightObject) : base(lightObject)
{
@@ -413,7 +413,7 @@ namespace WorldTuningTool
private class uHemiSphereLight : uLight
{
public override int Type => 4;
- public override string Name => $"uHemiSphereLight";
+ public override string Name => "uHemiSphereLight";
public uHemiSphereLight(nint lightObject) : base(lightObject)
{
@@ -428,7 +428,7 @@ namespace WorldTuningTool
private class uMhHemiSphereLight : uHemiSphereLight
{
- public override string Name => $"uMhHemiSphereLight";
+ public override string Name => "uMhHemiSphereLight";
public uMhHemiSphereLight(nint lightObject) : base(lightObject)
{
@@ -445,7 +445,7 @@ namespace WorldTuningTool
private class uLlkHemiSphereLight : uHemiSphereLight
{
- public override string Name => $"uLlkHemiSphereLight";
+ public override string Name => "uLlkHemiSphereLight";
public nint CycleTimelineRes => Get<nint>(Object, 0x5D0);
public int CycleAnimNo => Get<int>(Object, 0x720);
@@ -461,11 +461,11 @@ namespace WorldTuningTool
}
}
-#if HOOK_OBJECT_LIGHTS
+#if HOOK_OBJECT_LIGHTS // I don't know what an object light is and have never seen it used in-game.
private class uMhObjectLight : BaseLight
{
public override int Type => 5;
- public override string Name => $"uMhObjectLight";
+ public override string Name => "uMhObjectLight";
public uMhObjectLight(nint lightObject) : base(lightObject)
{
@@ -482,7 +482,7 @@ namespace WorldTuningTool
private class uLlkObjectLight : BaseLight
{
public override int Type => 5;
- public override string Name => $"uLlkObjectLight";
+ public override string Name => "uLlkObjectLight";
public uLlkObjectLight(nint lightObject) : base(lightObject)
{
@@ -631,6 +631,7 @@ namespace WorldTuningTool
{
if (vTable == 0x143514168)
{
+ // Assuming uLight is never used directly, this means we are missing a light type.
Log.Error("Light is still uLight OnUpdate().");
}
sceneLights.Add(lightTypes[vTable](light.Object));
diff --git a/Parameter.cs b/Parameter.cs
index db564a3..72dac10 100644
--- a/Parameter.cs
+++ b/Parameter.cs
@@ -34,16 +34,16 @@ namespace WorldTuningTool
public static class PFuncs
{
- public static bool IgnoreMinMax = false;
+ internal static bool IgnoreMinMax = false;
- public static bool InTransition = false;
- public static List<Parameter> DirtyParams = new();
- public static void BeginTransition()
+ internal static bool InTransition = false;
+ internal static List<Parameter> DirtyParams = new();
+ internal static void BeginTransition()
{
Assert(!InTransition && DirtyParams.Count == 0);
InTransition = true;
}
- public static void EndTransition()
+ internal static void EndTransition()
{
Assert(InTransition);
InTransition = false;
diff --git a/Plugin.cs b/Plugin.cs
index aa3f854..5ccf064 100644
--- a/Plugin.cs
+++ b/Plugin.cs
@@ -47,10 +47,9 @@ using SharpPluginLoader.Core.Resources;
namespace WorldTuningTool
{
+ using static Config;
using static Utility;
- using static Parameter;
using static PFuncs;
- using static Config;
public unsafe class Plugin : IPlugin
{
@@ -104,9 +103,8 @@ namespace WorldTuningTool
private static string selectedGlobal = "";
- private static string selectedSet = "";
- private static bool renamingSet = false;
- private static string typedSetName = "";
+ private static PresetSelection<Override> setSelection = null!;
+ private static string selectedSet => setSelection.Selected;
private static Dictionary<int, Override> externalOverrides = new Dictionary<int, Override>();
private static int externalId = 0;
@@ -219,7 +217,6 @@ namespace WorldTuningTool
if (ImGui.Button("▲"))
{
// 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];
@@ -641,6 +638,7 @@ namespace WorldTuningTool
private static MtObject? sMhScene = null;
private static MtObject? sMhMain = null;
private static MtObject? sMhRender = null;
+ private static MtObject? sMhGUI = null;
private static MtObject? sTime = null;
private static MtObject? sQuest = null;
private static MtObject? sLightLinker = null;
@@ -650,6 +648,16 @@ namespace WorldTuningTool
private static Parameter hqMode = P<bool>("HQ Mode", 0xE9A3, ParameterType.BOOL);
private static Patch defaultHqMode;
+ private static Parameter[] screenRenderParameters = {
+ P<byte>("Screen Trim", 0x7B440, ParameterType.BYTE, pStep((byte)1)),
+ P<float>("Default Width", 0x142F74AFC, ParameterType.PATCH_FLOAT),
+ P<float>("Default Height", 0x142F74AF8, ParameterType.PATCH_FLOAT)
+ };
+
+ private static Parameter[] screenGuiParameters = {
+ P<float>("UI Center Offset", 0x1EC, ParameterType.FLOAT)
+ };
+
private static bool setWeatherMode = false;
private static int requestWeatherMode = 1;
private static Parameter[] sTimeParameters = {
@@ -1182,6 +1190,8 @@ namespace WorldTuningTool
};
private static Parameter[] allParameters = new Parameter[]{ hqMode }
+ .Concat(screenRenderParameters)
+ .Concat(screenGuiParameters)
.Concat(sTimeParameters)
.Concat(lodParameters)
.Concat(snowParameters)
@@ -1402,7 +1412,7 @@ namespace WorldTuningTool
#if SHADER_FEATURES
private bool volumeUpsampleNoLinear = false;
private bool fxaaMaxQuality = false;
- private bool skinAllowNegativeWet = false;
+ private bool addTonemappers = false;
#endif
private bool fullResVolumeBlur = false;
@@ -1824,6 +1834,7 @@ namespace WorldTuningTool
public void OnPreMain()
{
Config config = getConfig();
+ setSelection = new(config.Sets, "Set");
disableLightsFeature = config.DisableLightsFeature;
if (!disableLightsFeature)
{
@@ -1870,7 +1881,7 @@ namespace WorldTuningTool
}
volumeUpsampleNoLinear = patches.VolumeUpsampleNoLinear;
fxaaMaxQuality = patches.FXAAMaxQualityPreset;
- skinAllowNegativeWet = patches.SkinAllowNegativeWetness;
+ addTonemappers = patches.AddTonemappers;
#endif
fullResVolumeBlur = patches.FullResolutionVolumeBlur;
if (fullResVolumeBlur)
@@ -1912,9 +1923,10 @@ namespace WorldTuningTool
public void OnLoad()
{
+ sMhScene = SingletonManager.GetSingleton("sMhScene")!;
sMhMain = SingletonManager.GetSingleton("sMhMain")!;
sMhRender = SingletonManager.GetSingleton("sMhRender")!;
- sMhScene = SingletonManager.GetSingleton("sMhScene")!;
+ sMhGUI = SingletonManager.GetSingleton("sMhGUI")!;
sTime = SingletonManager.GetSingleton("sTime")!;
sQuest = SingletonManager.GetSingleton("sQuest")!;
sLightLinker = SingletonManager.GetSingleton("sLightLinker")!;
@@ -2011,6 +2023,16 @@ namespace WorldTuningTool
hqMode.Update(sMhScene!.Instance);
+ foreach (Parameter param in screenRenderParameters)
+ {
+ param.Update(sMhRender!.Instance);
+ }
+
+ foreach (Parameter param in screenGuiParameters)
+ {
+ param.Update(sMhGUI!.Instance);
+ }
+
if (setWeatherMode)
{
sQuest!.GetRef<int>(0x293B4) = requestWeatherMode;
@@ -2871,6 +2893,7 @@ namespace WorldTuningTool
{
selectedGlobal = name;
}
+ if (isSelected) ImGui.SetItemDefaultFocus();
}
ImGui.EndCombo();
}
@@ -2989,98 +3012,16 @@ namespace WorldTuningTool
ImGui.PushID("Set");
ImGui.Text("Quick Sets");
- ImGui.PushItemWidth(width * 0.35f);
string prevSet = selectedSet;
- if (ImGui.Button("+"))
- {
- string setName = "New Set";
- int setDup = 0;
- while (config.Sets.ContainsKey(setName))
- {
- setDup++;
- setName = $"New Set ({setDup})";
- }
- config.Sets[setName] = new List<Override>();
- selectedSet = setName;
- }
- ImGui.SameLine();
- if (renamingSet)
- {
- ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true);
- ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * disableAlphaFactor);
- }
- if (ImGui.BeginCombo("##Set", selectedSet))
- {
- if (ImGui.Selectable("(None)", false))
- {
- selectedSet = "";
- }
- foreach ((string name, List<Override> overrides) in config.Sets)
- {
- bool isSelected = name == selectedSet;
- if (ImGui.Selectable(name, isSelected))
- {
- selectedSet = name;
- }
- }
- ImGui.EndCombo();
- }
- if (prevSet != selectedSet)
+ string preRenameSet = setSelection.Draw(width);
+ if (prevSet != preRenameSet)
{
BeginTransition();
HandleSetChange(prevSet, globalOverrides, stageOverrides);
EndTransition();
}
- if (renamingSet)
- {
- ImGui.PopStyleVar();
- ImGui.PopItemFlag();
- }
- ImGui.PopItemWidth();
if (selectedSet != "")
{
- ImGui.SameLine();
- ImGui.PushItemWidth(width * 0.2f);
- if (renamingSet)
- {
- ImGui.InputText("##Set Name", ref typedSetName, 99);
- ImGui.SameLine();
- if (typedSetName == "")
- {
- ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true);
- ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * disableAlphaFactor);
- }
- if (ImGui.Button("Save"))
- {
- string setName = typedSetName;
- if (setName != selectedSet)
- {
- int setDup = 0;
- while (config.Sets.ContainsKey(setName))
- {
- setDup++;
- setName = $"{typedSetName} ({setDup})";
- }
- List<Override> tmpOverrides = config.Sets[selectedSet];
- config.Sets.Remove(selectedSet);
- config.Sets[setName] = tmpOverrides;
- selectedSet = setName;
- }
- renamingSet = false;
- }
- if (typedSetName == "")
- {
- ImGui.PopStyleVar();
- ImGui.PopItemFlag();
- }
- }
- else if (ImGui.Button("Rename"))
- {
- renamingSet = true;
- typedSetName = selectedSet;
- }
- ImGui.PopItemWidth();
-
bool setOrderChanged = false;
List<Override> setOverrides = config.Sets[selectedSet];
if (!editMode)
@@ -3242,15 +3183,15 @@ namespace WorldTuningTool
ImGui.EndTooltip();
}
- if (ImGui.Checkbox("Skin Allow Negative Wetness", ref skinAllowNegativeWet))
+ if (ImGui.Checkbox("Add Extra Tonemappers", ref addTonemappers))
{
- patches.SkinAllowNegativeWetness = skinAllowNegativeWet;
+ patches.AddTonemappers = addTonemappers;
config.Patches = patches;
saveConfig(config);
}
if (ImGui.BeginItemTooltip())
{
- ImGui.Text("Can be used to reverse the effect of wet by default modded armor.");
+ ImGui.Text("Tone Map Type: 7 = Uchimura.");
ImGui.EndTooltip();
}
#endif
@@ -3418,6 +3359,22 @@ namespace WorldTuningTool
{
hqMode.Draw(width);
+ ImGui.PushID("Screen");
+ if (ImGui.CollapsingHeader("Screen"))
+ {
+ ImGui.Text($"Address: 0x{sMhRender!.Instance:X}");
+ foreach (Parameter param in screenRenderParameters)
+ {
+ param.Draw(width);
+ }
+ ImGui.Text($"Address: 0x{sMhGUI!.Instance:X}");
+ foreach (Parameter param in screenGuiParameters)
+ {
+ param.Draw(width);
+ }
+ }
+ ImGui.PopID();
+
ImGui.PushID("Time");
if (ImGui.CollapsingHeader("Time and Weather"))
{
@@ -3919,7 +3876,7 @@ namespace WorldTuningTool
//}
if (!System.IO.File.Exists(path))
{
- Log.Warn($"File not found: {path}.");
+ Log.Error($"File not found: {path}.");
return false;
}
byte[] shaderData;
@@ -4036,32 +3993,17 @@ namespace WorldTuningTool
}
}
- if (skinAllowNegativeWet)
+ if (addTonemappers)
{
- if (hash == "2eed1f00-e24d1b19-9d521064-17b9a586")
- {
- if (replaceShaderFromFile(info, $"{shaderPath}/body_skin.shdr", ShaderSourceType.Binary))
- {
- Log.Info("Body skin shader replaced.");
- }
- }
- else if (hash == "8e5e3c09-ebe77ee4-ba1cb659-d25bc7bf")
+ if (hash == "ca33bab6-2119df84-41786a69-404471cd")
{
- if (replaceShaderFromFile(info, $"{shaderPath}/face.shdr", ShaderSourceType.Binary))
+ if (replaceShaderFromFile(info, $"{shaderPath}/color_grading_add_tonemappers.shdr", ShaderSourceType.Binary))
{
- Log.Info("Face shader replaced.");
+ Log.Info("Color grading/Tonemapping shader replaced.");
}
}
}
- if (hash == "ca33bab6-2119df84-41786a69-404471cd")
- {
- if (replaceShaderFromFile(info, $"{shaderPath}/color_grading_ex_tonemappers.shdr", ShaderSourceType.Binary))
- {
- Log.Info("Color grading shader replaced.");
- }
- }
-
/*
if (hash == "0c3dacbd-32c175d5-10d80d04-cce7e689")
{
diff --git a/Utility.cs b/Utility.cs
index e48ee52..416e9a5 100644
--- a/Utility.cs
+++ b/Utility.cs
@@ -7,6 +7,7 @@ using System.Runtime.CompilerServices;
using System.Diagnostics;
#endif
+using ImGuiNET;
using SharpPluginLoader.Core;
using SharpPluginLoader.Core.Memory;
@@ -88,7 +89,7 @@ namespace WorldTuningTool
internal static Vector2 StringToVector2(string s, char delim = ',')
{
- if (String.IsNullOrEmpty(s)) throw new FormatException();
+ 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(StringToSingle(sp[0]), StringToSingle(sp[1]));
@@ -96,7 +97,7 @@ namespace WorldTuningTool
internal static Vector3 StringToVector3(string s, char delim = ',')
{
- if (String.IsNullOrEmpty(s)) throw new FormatException();
+ 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(StringToSingle(sp[0]), StringToSingle(sp[1]), StringToSingle(sp[2]));
@@ -104,7 +105,7 @@ namespace WorldTuningTool
internal static Vector4 StringToVector4(string s, char delim = ',')
{
- if (String.IsNullOrEmpty(s)) throw new FormatException();
+ 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(StringToSingle(sp[0]), StringToSingle(sp[1]), StringToSingle(sp[2]), StringToSingle(sp[3]));
@@ -124,5 +125,160 @@ namespace WorldTuningTool
{
return string.Format(CultureInfo.InvariantCulture, "{0},{1},{2},{3}", v.X, v.Y, v.Z, v.W);
}
+
+ internal class PresetSelection<T>
+ {
+ internal string Selected = "";
+ internal bool comboLastFocused = false;
+ internal bool renaming = false;
+ internal bool confirmDelete = false;
+ internal string typed = "";
+ internal Dictionary<string, List<T>> dict;
+ internal string typeName;
+
+ internal PresetSelection(Dictionary<string, List<T>> dict, string typeName)
+ {
+ this.dict = dict;
+ this.typeName = typeName;
+ }
+
+ internal string Draw(float width)
+ {
+ ImGui.PushItemWidth(width * 0.35f);
+ if (!comboLastFocused)
+ {
+ ImGui.PushItemFlag(ImGuiItemFlags.NoNav, true);
+ }
+ if (ImGui.Button("+"))
+ {
+ string name = $"New {typeName}";
+ int dup = 0;
+ while (dict.ContainsKey(name))
+ {
+ dup++;
+ name = $"New {typeName} ({dup})";
+ }
+ dict[name] = new List<T>();
+ Selected = name;
+ renaming = true;
+ typed = Selected;
+ }
+ if (!comboLastFocused)
+ {
+ ImGui.PopItemFlag();
+ }
+ ImGui.SameLine();
+ if (renaming)
+ {
+ ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true);
+ ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * disableAlphaFactor);
+ }
+ bool beginCombo = ImGui.BeginCombo($"##{typeName}", Selected);
+ comboLastFocused = ImGui.IsItemActive() || ImGui.IsItemFocused();
+ if (beginCombo)
+ {
+ confirmDelete = false;
+ if (ImGui.Selectable("(None)", false))
+ {
+ Selected = "";
+ }
+ foreach ((string name, List<T> overrides) in dict)
+ {
+ bool isSelected = name == Selected;
+ if (ImGui.Selectable(name, isSelected))
+ {
+ Selected = name;
+ }
+ if (isSelected) ImGui.SetItemDefaultFocus();
+ }
+ ImGui.EndCombo();
+ }
+ string preRenameSelected = Selected;
+ if (renaming)
+ {
+ ImGui.PopStyleVar();
+ ImGui.PopItemFlag();
+ }
+ ImGui.PopItemWidth();
+ if (Selected != "")
+ {
+ ImGui.SameLine();
+ ImGui.PushItemWidth(width * 0.2f);
+ if (renaming)
+ {
+ ImGui.InputText($"##{typeName} Name", ref typed, 99);
+ ImGui.SameLine();
+ if (typed == "")
+ {
+ ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true);
+ ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * disableAlphaFactor);
+ }
+ if (ImGui.Button("Save"))
+ {
+ string name = typed;
+ if (name != Selected)
+ {
+ int dup = 0;
+ while (dict.ContainsKey(name))
+ {
+ dup++;
+ name = $"{typed} ({dup})";
+ }
+ List<T> tmpOverrides = dict[Selected];
+ dict.Remove(Selected);
+ dict[name] = tmpOverrides;
+ Selected = name;
+ }
+ renaming = false;
+ }
+ if (typed == "")
+ {
+ ImGui.PopStyleVar();
+ ImGui.PopItemFlag();
+ }
+ }
+ else
+ {
+ if (confirmDelete)
+ {
+ ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true);
+ }
+ if (ImGui.Button("Rename"))
+ {
+ renaming = true;
+ typed = Selected;
+ }
+ if (confirmDelete)
+ {
+ ImGui.PopItemFlag();
+ }
+ ImGui.SameLine();
+ if (confirmDelete)
+ {
+ ImGui.AlignTextToFramePadding();
+ ImGui.Text("Are you sure?");
+ ImGui.SameLine();
+ if (ImGui.Button("No"))
+ {
+ confirmDelete = false;
+ }
+ ImGui.SameLine();
+ if (ImGui.Button("Yes"))
+ {
+ dict.Remove(Selected);
+ Selected = "";
+ confirmDelete = false;
+ }
+ }
+ else if (ImGui.Button("Delete"))
+ {
+ confirmDelete = true;
+ }
+ }
+ ImGui.PopItemWidth();
+ }
+ return preRenameSelected;
+ }
+ }
}
}