mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 10:17:23 +01:00
Add initial support for setting temporary mod settings.
This commit is contained in:
parent
e41755ed7e
commit
24452f3c79
22 changed files with 394 additions and 202 deletions
|
|
@ -293,6 +293,8 @@ public sealed class AutoDesignApplier : IDisposable
|
|||
set.Designs.Where(d => d.IsActive(actor))
|
||||
.SelectMany(d => d.Design.AllLinks(newApplication).Select(l => (l.Design, l.Flags & d.Type, d.Jobs.Flags))),
|
||||
state.ModelData.Customize, state.BaseData, true, _config.AlwaysApplyAssociatedMods);
|
||||
if (set.ResetTemporarySettings)
|
||||
mergedDesign.ResetTemporarySettings = true;
|
||||
|
||||
_state.ApplyDesign(state, mergedDesign, new ApplySettings(0, StateSource.Fixed, respectManual, fromJobChange, false, false, false));
|
||||
forcedRedraw = mergedDesign.ForcedRedraw;
|
||||
|
|
|
|||
|
|
@ -444,8 +444,9 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
|||
|
||||
var set = new AutoDesignSet(name, group)
|
||||
{
|
||||
Enabled = obj["Enabled"]?.ToObject<bool>() ?? false,
|
||||
BaseState = obj["BaseState"]?.ToObject<AutoDesignSet.Base>() ?? AutoDesignSet.Base.Current,
|
||||
Enabled = obj["Enabled"]?.ToObject<bool>() ?? false,
|
||||
ResetTemporarySettings = obj["ResetTemporarySettings"]?.ToObject<bool>() ?? false,
|
||||
BaseState = obj["BaseState"]?.ToObject<AutoDesignSet.Base>() ?? AutoDesignSet.Base.Current,
|
||||
};
|
||||
|
||||
if (set.Enabled)
|
||||
|
|
@ -602,9 +603,9 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
|||
? ActorIdentifier.RetainerType.Mannequin
|
||||
: ActorIdentifier.RetainerType.Bell).CreatePermanent(),
|
||||
],
|
||||
IdentifierType.Npc => CreateNpcs(_actors, identifier),
|
||||
IdentifierType.Npc => CreateNpcs(_actors, identifier),
|
||||
IdentifierType.Owned => CreateNpcs(_actors, identifier),
|
||||
_ => [],
|
||||
_ => [],
|
||||
};
|
||||
|
||||
static ActorIdentifier[] CreateNpcs(ActorManager manager, ActorIdentifier identifier)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ public class AutoDesignSet(string name, ActorIdentifier[] identifiers, List<Auto
|
|||
public string Name = name;
|
||||
public ActorIdentifier[] Identifiers = identifiers;
|
||||
public bool Enabled;
|
||||
public Base BaseState = Base.Current;
|
||||
public Base BaseState = Base.Current;
|
||||
public bool ResetTemporarySettings = false;
|
||||
|
||||
public JObject Serialize()
|
||||
{
|
||||
|
|
@ -20,11 +21,12 @@ public class AutoDesignSet(string name, ActorIdentifier[] identifiers, List<Auto
|
|||
|
||||
return new JObject()
|
||||
{
|
||||
["Name"] = Name,
|
||||
["Identifier"] = Identifiers[0].ToJson(),
|
||||
["Enabled"] = Enabled,
|
||||
["BaseState"] = BaseState.ToString(),
|
||||
["Designs"] = list,
|
||||
["Name"] = Name,
|
||||
["Identifier"] = Identifiers[0].ToJson(),
|
||||
["Enabled"] = Enabled,
|
||||
["BaseState"] = BaseState.ToString(),
|
||||
["ResetTemporarySettings"] = ResetTemporarySettings.ToString(),
|
||||
["Designs"] = list,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,9 +27,10 @@ public enum HeightDisplayType
|
|||
|
||||
public class DefaultDesignSettings
|
||||
{
|
||||
public bool AlwaysForceRedrawing = false;
|
||||
public bool ResetAdvancedDyes = false;
|
||||
public bool ShowQuickDesignBar = true;
|
||||
public bool AlwaysForceRedrawing = false;
|
||||
public bool ResetAdvancedDyes = false;
|
||||
public bool ShowQuickDesignBar = true;
|
||||
public bool ResetTemporarySettings = false;
|
||||
}
|
||||
|
||||
public class Configuration : IPluginConfiguration, ISavable
|
||||
|
|
@ -63,6 +64,7 @@ public class Configuration : IPluginConfiguration, ISavable
|
|||
public bool ShowColorConfig { get; set; } = true;
|
||||
public bool ChangeEntireItem { get; set; } = false;
|
||||
public bool AlwaysApplyAssociatedMods { get; set; } = false;
|
||||
public bool UseTemporarySettings { get; set; } = true;
|
||||
public bool AllowDoubleClickToApply { get; set; } = false;
|
||||
public bool RespectManualOnAutomationUpdate { get; set; } = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -28,32 +28,34 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn
|
|||
internal Design(Design other)
|
||||
: base(other)
|
||||
{
|
||||
Tags = [.. other.Tags];
|
||||
Description = other.Description;
|
||||
QuickDesign = other.QuickDesign;
|
||||
ForcedRedraw = other.ForcedRedraw;
|
||||
ResetAdvancedDyes = other.ResetAdvancedDyes;
|
||||
Color = other.Color;
|
||||
AssociatedMods = new SortedList<Mod, ModSettings>(other.AssociatedMods);
|
||||
Links = Links.Clone();
|
||||
Tags = [.. other.Tags];
|
||||
Description = other.Description;
|
||||
QuickDesign = other.QuickDesign;
|
||||
ForcedRedraw = other.ForcedRedraw;
|
||||
ResetAdvancedDyes = other.ResetAdvancedDyes;
|
||||
ResetTemporarySettings = other.ResetTemporarySettings;
|
||||
Color = other.Color;
|
||||
AssociatedMods = new SortedList<Mod, ModSettings>(other.AssociatedMods);
|
||||
Links = Links.Clone();
|
||||
}
|
||||
|
||||
// Metadata
|
||||
public new const int FileVersion = 2;
|
||||
|
||||
public Guid Identifier { get; internal init; }
|
||||
public DateTimeOffset CreationDate { get; internal init; }
|
||||
public DateTimeOffset LastEdit { get; internal set; }
|
||||
public LowerString Name { get; internal set; } = LowerString.Empty;
|
||||
public string Description { get; internal set; } = string.Empty;
|
||||
public string[] Tags { get; internal set; } = [];
|
||||
public int Index { get; internal set; }
|
||||
public bool ForcedRedraw { get; internal set; }
|
||||
public bool ResetAdvancedDyes { get; internal set; }
|
||||
public bool QuickDesign { get; internal set; } = true;
|
||||
public string Color { get; internal set; } = string.Empty;
|
||||
public SortedList<Mod, ModSettings> AssociatedMods { get; private set; } = [];
|
||||
public LinkContainer Links { get; private set; } = [];
|
||||
public Guid Identifier { get; internal init; }
|
||||
public DateTimeOffset CreationDate { get; internal init; }
|
||||
public DateTimeOffset LastEdit { get; internal set; }
|
||||
public LowerString Name { get; internal set; } = LowerString.Empty;
|
||||
public string Description { get; internal set; } = string.Empty;
|
||||
public string[] Tags { get; internal set; } = [];
|
||||
public int Index { get; internal set; }
|
||||
public bool ForcedRedraw { get; internal set; }
|
||||
public bool ResetAdvancedDyes { get; internal set; }
|
||||
public bool ResetTemporarySettings { get; internal set; }
|
||||
public bool QuickDesign { get; internal set; } = true;
|
||||
public string Color { get; internal set; } = string.Empty;
|
||||
public SortedList<Mod, ModSettings> AssociatedMods { get; private set; } = [];
|
||||
public LinkContainer Links { get; private set; } = [];
|
||||
|
||||
public string Incognito
|
||||
=> Identifier.ToString()[..8];
|
||||
|
|
@ -100,25 +102,26 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn
|
|||
{
|
||||
var ret = new JObject()
|
||||
{
|
||||
["FileVersion"] = FileVersion,
|
||||
["Identifier"] = Identifier,
|
||||
["CreationDate"] = CreationDate,
|
||||
["LastEdit"] = LastEdit,
|
||||
["Name"] = Name.Text,
|
||||
["Description"] = Description,
|
||||
["ForcedRedraw"] = ForcedRedraw,
|
||||
["ResetAdvancedDyes"] = ResetAdvancedDyes,
|
||||
["Color"] = Color,
|
||||
["QuickDesign"] = QuickDesign,
|
||||
["Tags"] = JArray.FromObject(Tags),
|
||||
["WriteProtected"] = WriteProtected(),
|
||||
["Equipment"] = SerializeEquipment(),
|
||||
["Bonus"] = SerializeBonusItems(),
|
||||
["Customize"] = SerializeCustomize(),
|
||||
["Parameters"] = SerializeParameters(),
|
||||
["Materials"] = SerializeMaterials(),
|
||||
["Mods"] = SerializeMods(),
|
||||
["Links"] = Links.Serialize(),
|
||||
["FileVersion"] = FileVersion,
|
||||
["Identifier"] = Identifier,
|
||||
["CreationDate"] = CreationDate,
|
||||
["LastEdit"] = LastEdit,
|
||||
["Name"] = Name.Text,
|
||||
["Description"] = Description,
|
||||
["ForcedRedraw"] = ForcedRedraw,
|
||||
["ResetAdvancedDyes"] = ResetAdvancedDyes,
|
||||
["ResetTemporarySettings"] = ResetTemporarySettings,
|
||||
["Color"] = Color,
|
||||
["QuickDesign"] = QuickDesign,
|
||||
["Tags"] = JArray.FromObject(Tags),
|
||||
["WriteProtected"] = WriteProtected(),
|
||||
["Equipment"] = SerializeEquipment(),
|
||||
["Bonus"] = SerializeBonusItems(),
|
||||
["Customize"] = SerializeCustomize(),
|
||||
["Parameters"] = SerializeParameters(),
|
||||
["Materials"] = SerializeMaterials(),
|
||||
["Mods"] = SerializeMods(),
|
||||
["Links"] = Links.Serialize(),
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -250,9 +253,10 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn
|
|||
LoadParameters(json["Parameters"], design, design.Name);
|
||||
LoadMaterials(json["Materials"], design, design.Name);
|
||||
LoadLinks(linkLoader, json["Links"], design);
|
||||
design.Color = json["Color"]?.ToObject<string>() ?? string.Empty;
|
||||
design.ForcedRedraw = json["ForcedRedraw"]?.ToObject<bool>() ?? false;
|
||||
design.ResetAdvancedDyes = json["ResetAdvancedDyes"]?.ToObject<bool>() ?? false;
|
||||
design.Color = json["Color"]?.ToObject<string>() ?? string.Empty;
|
||||
design.ForcedRedraw = json["ForcedRedraw"]?.ToObject<bool>() ?? false;
|
||||
design.ResetAdvancedDyes = json["ResetAdvancedDyes"]?.ToObject<bool>() ?? false;
|
||||
design.ResetTemporarySettings = json["ResetTemporarySettings"]?.ToObject<bool>() ?? false;
|
||||
return design;
|
||||
|
||||
static string[] ParseTags(JObject json)
|
||||
|
|
@ -278,12 +282,15 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn
|
|||
continue;
|
||||
}
|
||||
|
||||
var settingsDict = tok["Settings"]?.ToObject<Dictionary<string, List<string>>>() ?? [];
|
||||
var settings = new Dictionary<string, List<string>>(settingsDict.Count);
|
||||
var forceInherit = tok["Inherit"]?.ToObject<bool>() ?? false;
|
||||
var removeSetting = tok["Remove"]?.ToObject<bool>() ?? false;
|
||||
var settingsDict = tok["Settings"]?.ToObject<Dictionary<string, List<string>>>() ?? [];
|
||||
var settings = new Dictionary<string, List<string>>(settingsDict.Count);
|
||||
foreach (var (key, value) in settingsDict)
|
||||
settings.Add(key, value);
|
||||
var priority = tok["Priority"]?.ToObject<int>() ?? 0;
|
||||
if (!design.AssociatedMods.TryAdd(new Mod(name, directory), new ModSettings(settings, priority, enabled.Value)))
|
||||
if (!design.AssociatedMods.TryAdd(new Mod(name, directory),
|
||||
new ModSettings(settings, priority, enabled.Value, forceInherit, removeSetting)))
|
||||
Glamourer.Messager.NotificationMessage("The loaded design contains a mod more than once, skipped.", NotificationType.Warning);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,14 +99,15 @@ public sealed class DesignManager : DesignEditor
|
|||
var (actualName, path) = ParseName(name, handlePath);
|
||||
var design = new Design(Customizations, Items)
|
||||
{
|
||||
CreationDate = DateTimeOffset.UtcNow,
|
||||
LastEdit = DateTimeOffset.UtcNow,
|
||||
Identifier = CreateNewGuid(),
|
||||
Name = actualName,
|
||||
Index = Designs.Count,
|
||||
ForcedRedraw = Config.DefaultDesignSettings.AlwaysForceRedrawing,
|
||||
ResetAdvancedDyes = Config.DefaultDesignSettings.ResetAdvancedDyes,
|
||||
QuickDesign = Config.DefaultDesignSettings.ShowQuickDesignBar,
|
||||
CreationDate = DateTimeOffset.UtcNow,
|
||||
LastEdit = DateTimeOffset.UtcNow,
|
||||
Identifier = CreateNewGuid(),
|
||||
Name = actualName,
|
||||
Index = Designs.Count,
|
||||
ForcedRedraw = Config.DefaultDesignSettings.AlwaysForceRedrawing,
|
||||
ResetAdvancedDyes = Config.DefaultDesignSettings.ResetAdvancedDyes,
|
||||
QuickDesign = Config.DefaultDesignSettings.ShowQuickDesignBar,
|
||||
ResetTemporarySettings = Config.DefaultDesignSettings.ResetTemporarySettings,
|
||||
};
|
||||
Designs.Add(design);
|
||||
Glamourer.Log.Debug($"Added new design {design.Identifier}.");
|
||||
|
|
@ -121,14 +122,15 @@ public sealed class DesignManager : DesignEditor
|
|||
var (actualName, path) = ParseName(name, handlePath);
|
||||
var design = new Design(clone)
|
||||
{
|
||||
CreationDate = DateTimeOffset.UtcNow,
|
||||
LastEdit = DateTimeOffset.UtcNow,
|
||||
Identifier = CreateNewGuid(),
|
||||
Name = actualName,
|
||||
Index = Designs.Count,
|
||||
ForcedRedraw = Config.DefaultDesignSettings.AlwaysForceRedrawing,
|
||||
ResetAdvancedDyes = Config.DefaultDesignSettings.ResetAdvancedDyes,
|
||||
QuickDesign = Config.DefaultDesignSettings.ShowQuickDesignBar,
|
||||
CreationDate = DateTimeOffset.UtcNow,
|
||||
LastEdit = DateTimeOffset.UtcNow,
|
||||
Identifier = CreateNewGuid(),
|
||||
Name = actualName,
|
||||
Index = Designs.Count,
|
||||
ForcedRedraw = Config.DefaultDesignSettings.AlwaysForceRedrawing,
|
||||
ResetAdvancedDyes = Config.DefaultDesignSettings.ResetAdvancedDyes,
|
||||
QuickDesign = Config.DefaultDesignSettings.ShowQuickDesignBar,
|
||||
ResetTemporarySettings = Config.DefaultDesignSettings.ResetTemporarySettings,
|
||||
};
|
||||
|
||||
Designs.Add(design);
|
||||
|
|
@ -144,11 +146,11 @@ public sealed class DesignManager : DesignEditor
|
|||
var (actualName, path) = ParseName(name, handlePath);
|
||||
var design = new Design(clone)
|
||||
{
|
||||
CreationDate = DateTimeOffset.UtcNow,
|
||||
LastEdit = DateTimeOffset.UtcNow,
|
||||
Identifier = CreateNewGuid(),
|
||||
Name = actualName,
|
||||
Index = Designs.Count,
|
||||
CreationDate = DateTimeOffset.UtcNow,
|
||||
LastEdit = DateTimeOffset.UtcNow,
|
||||
Identifier = CreateNewGuid(),
|
||||
Name = actualName,
|
||||
Index = Designs.Count,
|
||||
};
|
||||
Designs.Add(design);
|
||||
Glamourer.Log.Debug(
|
||||
|
|
@ -351,6 +353,17 @@ public sealed class DesignManager : DesignEditor
|
|||
DesignChanged.Invoke(DesignChanged.Type.ResetAdvancedDyes, design, null);
|
||||
}
|
||||
|
||||
public void ChangeResetTemporarySettings(Design design, bool resetTemporarySettings)
|
||||
{
|
||||
if (design.ResetTemporarySettings == resetTemporarySettings)
|
||||
return;
|
||||
|
||||
design.ResetTemporarySettings = resetTemporarySettings;
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Set {design.Identifier} to {(resetTemporarySettings ? string.Empty : "not")} reset temporary settings.");
|
||||
DesignChanged.Invoke(DesignChanged.Type.ResetTemporarySettings, design, null);
|
||||
}
|
||||
|
||||
/// <summary> Change whether to apply a specific customize value. </summary>
|
||||
public void ChangeApplyCustomize(Design design, CustomizeIndex idx, bool value)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -26,5 +26,6 @@ public interface IDesignStandIn : IEquatable<IDesignStandIn>
|
|||
|
||||
public bool ForcedRedraw { get; }
|
||||
|
||||
public bool ResetAdvancedDyes { get; }
|
||||
public bool ResetAdvancedDyes { get; }
|
||||
public bool ResetTemporarySettings { get; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,8 @@ public class DesignMerger(
|
|||
ret.ForcedRedraw = true;
|
||||
if (design.ResetAdvancedDyes)
|
||||
ret.ResetAdvancedDyes = true;
|
||||
if (design.ResetTemporarySettings)
|
||||
ret.ResetTemporarySettings = true;
|
||||
}
|
||||
|
||||
ApplyFixFlags(ret, fixFlags);
|
||||
|
|
|
|||
|
|
@ -101,4 +101,5 @@ public sealed class MergedDesign
|
|||
public StateSources Sources = new();
|
||||
public bool ForcedRedraw;
|
||||
public bool ResetAdvancedDyes;
|
||||
public bool ResetTemporarySettings;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,4 +56,7 @@ public class QuickSelectedDesign(QuickDesignCombo combo) : IDesignStandIn, IServ
|
|||
|
||||
public bool ResetAdvancedDyes
|
||||
=> combo.Design?.ResetAdvancedDyes ?? false;
|
||||
|
||||
public bool ResetTemporarySettings
|
||||
=> combo.Design?.ResetTemporarySettings ?? false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,8 +92,11 @@ public class RandomDesign(RandomDesignGenerator rng) : IDesignStandIn
|
|||
}
|
||||
|
||||
public bool ForcedRedraw
|
||||
=> false;
|
||||
=> _currentDesign?.ForcedRedraw ?? false;
|
||||
|
||||
public bool ResetAdvancedDyes
|
||||
=> false;
|
||||
=> _currentDesign?.ResetAdvancedDyes ?? false;
|
||||
|
||||
public bool ResetTemporarySettings
|
||||
=> _currentDesign?.ResetTemporarySettings ?? false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,4 +48,7 @@ public class RevertDesign : IDesignStandIn
|
|||
|
||||
public bool ResetAdvancedDyes
|
||||
=> true;
|
||||
|
||||
public bool ResetTemporarySettings
|
||||
=> true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,6 +93,9 @@ public sealed class DesignChanged()
|
|||
/// <summary> An existing design had changed whether it always resets advanced dyes or not. </summary>
|
||||
ResetAdvancedDyes,
|
||||
|
||||
/// <summary> An existing design had changed whether it always resets all prior temporary settings or not. </summary>
|
||||
ResetTemporarySettings,
|
||||
|
||||
/// <summary> An existing design changed whether a specific customization is applied. </summary>
|
||||
ApplyCustomize,
|
||||
|
||||
|
|
|
|||
|
|
@ -159,6 +159,7 @@ public class ActorPanel
|
|||
return;
|
||||
ImGui.TableSetupScrollFreeze(0, 1);
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.Dummy(Vector2.Zero);
|
||||
var transformationId = _actor.IsCharacter ? _actor.AsCharacter->CharacterData.TransformationId : 0;
|
||||
if (transformationId != 0)
|
||||
ImGuiUtil.DrawTextButton($"Currently transformed to Transformation {transformationId}.",
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using ImGuiNET;
|
|||
using OtterGui;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Text;
|
||||
using OtterGui.Widgets;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.DesignTab;
|
||||
|
|
@ -41,7 +42,7 @@ public class DesignDetailTab
|
|||
|
||||
public void Draw()
|
||||
{
|
||||
using var h = ImRaii.CollapsingHeader("Design Details");
|
||||
using var h = ImUtf8.CollapsingHeaderId("Design Details"u8);
|
||||
if (!h)
|
||||
return;
|
||||
|
||||
|
|
@ -54,19 +55,19 @@ public class DesignDetailTab
|
|||
private void DrawDesignInfoTable()
|
||||
{
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0, 0.5f));
|
||||
using var table = ImRaii.Table("Details", 2);
|
||||
using var table = ImUtf8.Table("Details"u8, 2);
|
||||
if (!table)
|
||||
return;
|
||||
|
||||
ImGui.TableSetupColumn("Type", ImGuiTableColumnFlags.WidthFixed, ImGui.CalcTextSize("Reset Advanced Dyes").X);
|
||||
ImGui.TableSetupColumn("Data", ImGuiTableColumnFlags.WidthStretch);
|
||||
ImUtf8.TableSetupColumn("Type"u8, ImGuiTableColumnFlags.WidthFixed, ImUtf8.CalcTextSize("Reset Temporary Settings"u8).X);
|
||||
ImUtf8.TableSetupColumn("Data"u8, ImGuiTableColumnFlags.WidthStretch);
|
||||
|
||||
ImGuiUtil.DrawFrameColumn("Design Name");
|
||||
ImUtf8.DrawFrameColumn("Design Name"u8);
|
||||
ImGui.TableNextColumn();
|
||||
var width = new Vector2(ImGui.GetContentRegionAvail().X, 0);
|
||||
var name = _newName ?? _selector.Selected!.Name;
|
||||
ImGui.SetNextItemWidth(width.X);
|
||||
if (ImGui.InputText("##Name", ref name, 128))
|
||||
if (ImUtf8.InputText("##Name"u8, ref name))
|
||||
{
|
||||
_newName = name;
|
||||
_changeDesign = _selector.Selected;
|
||||
|
|
@ -80,10 +81,10 @@ public class DesignDetailTab
|
|||
}
|
||||
|
||||
var identifier = _selector.Selected!.Identifier.ToString();
|
||||
ImGuiUtil.DrawFrameColumn("Unique Identifier");
|
||||
ImUtf8.DrawFrameColumn("Unique Identifier"u8);
|
||||
ImGui.TableNextColumn();
|
||||
var fileName = _saveService.FileNames.DesignFile(_selector.Selected!);
|
||||
using (var mono = ImRaii.PushFont(UiBuilder.MonoFont))
|
||||
using (ImRaii.PushFont(UiBuilder.MonoFont))
|
||||
{
|
||||
if (ImGui.Button(identifier, width))
|
||||
try
|
||||
|
|
@ -100,14 +101,14 @@ public class DesignDetailTab
|
|||
ImGui.SetClipboardText(identifier);
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverTooltip(
|
||||
ImUtf8.HoverTooltip(
|
||||
$"Open the file\n\t{fileName}\ncontaining this design in the .json-editor of your choice.\n\nRight-Click to copy identifier to clipboard.");
|
||||
|
||||
ImGuiUtil.DrawFrameColumn("Full Selector Path");
|
||||
ImUtf8.DrawFrameColumn("Full Selector Path"u8);
|
||||
ImGui.TableNextColumn();
|
||||
var path = _newPath ?? _selector.SelectedLeaf!.FullName();
|
||||
ImGui.SetNextItemWidth(width.X);
|
||||
if (ImGui.InputText("##Path", ref path, 1024))
|
||||
if (ImUtf8.InputText("##Path"u8, ref path))
|
||||
{
|
||||
_newPath = path;
|
||||
_changeLeaf = _selector.SelectedLeaf!;
|
||||
|
|
@ -125,32 +126,42 @@ public class DesignDetailTab
|
|||
Glamourer.Messager.NotificationMessage(ex, ex.Message, "Could not rename or move design", NotificationType.Error);
|
||||
}
|
||||
|
||||
ImGuiUtil.DrawFrameColumn("Quick Design Bar");
|
||||
ImUtf8.DrawFrameColumn("Quick Design Bar"u8);
|
||||
ImGui.TableNextColumn();
|
||||
if (ImGui.RadioButton("Display##qdb", _selector.Selected.QuickDesign))
|
||||
if (ImUtf8.RadioButton("Display##qdb"u8, _selector.Selected.QuickDesign))
|
||||
_manager.SetQuickDesign(_selector.Selected!, true);
|
||||
var hovered = ImGui.IsItemHovered();
|
||||
ImGui.SameLine();
|
||||
if (ImGui.RadioButton("Hide##qdb", !_selector.Selected.QuickDesign))
|
||||
if (ImUtf8.RadioButton("Hide##qdb"u8, !_selector.Selected.QuickDesign))
|
||||
_manager.SetQuickDesign(_selector.Selected!, false);
|
||||
if (hovered || ImGui.IsItemHovered())
|
||||
ImGui.SetTooltip("Display or hide this design in your quick design bar.");
|
||||
{
|
||||
using var tt = ImUtf8.Tooltip();
|
||||
ImUtf8.Text("Display or hide this design in your quick design bar."u8);
|
||||
}
|
||||
|
||||
var forceRedraw = _selector.Selected!.ForcedRedraw;
|
||||
ImGuiUtil.DrawFrameColumn("Force Redrawing");
|
||||
ImUtf8.DrawFrameColumn("Force Redrawing"u8);
|
||||
ImGui.TableNextColumn();
|
||||
if (ImGui.Checkbox("##ForceRedraw", ref forceRedraw))
|
||||
if (ImUtf8.Checkbox("##ForceRedraw"u8, ref forceRedraw))
|
||||
_manager.ChangeForcedRedraw(_selector.Selected!, forceRedraw);
|
||||
ImGuiUtil.HoverTooltip("Set this design to always force a redraw when it is applied through any means.");
|
||||
ImUtf8.HoverTooltip("Set this design to always force a redraw when it is applied through any means."u8);
|
||||
|
||||
var resetAdvancedDyes = _selector.Selected!.ResetAdvancedDyes;
|
||||
ImGuiUtil.DrawFrameColumn("Reset Advanced Dyes");
|
||||
ImUtf8.DrawFrameColumn("Reset Advanced Dyes"u8);
|
||||
ImGui.TableNextColumn();
|
||||
if (ImGui.Checkbox("##ResetAdvancedDyes", ref resetAdvancedDyes))
|
||||
if (ImUtf8.Checkbox("##ResetAdvancedDyes"u8, ref resetAdvancedDyes))
|
||||
_manager.ChangeResetAdvancedDyes(_selector.Selected!, resetAdvancedDyes);
|
||||
ImGuiUtil.HoverTooltip("Set this design to reset any previously applied advanced dyes when it is applied through any means.");
|
||||
ImUtf8.HoverTooltip("Set this design to reset any previously applied advanced dyes when it is applied through any means."u8);
|
||||
|
||||
ImGuiUtil.DrawFrameColumn("Color");
|
||||
var resetTemporarySettings = _selector.Selected!.ResetTemporarySettings;
|
||||
ImUtf8.DrawFrameColumn("Reset Temporary Settings"u8);
|
||||
ImGui.TableNextColumn();
|
||||
if (ImUtf8.Checkbox("##ResetTemporarySettings"u8, ref resetTemporarySettings))
|
||||
_manager.ChangeResetTemporarySettings(_selector.Selected!, resetTemporarySettings);
|
||||
ImUtf8.HoverTooltip("Set this design to reset any temporary settings previously applied to the associated collection when it is applied through any means."u8);
|
||||
|
||||
ImUtf8.DrawFrameColumn("Color"u8);
|
||||
var colorName = _selector.Selected!.Color.Length == 0 ? DesignColors.AutomaticName : _selector.Selected!.Color;
|
||||
ImGui.TableNextColumn();
|
||||
if (_colorCombo.Draw("##colorCombo", colorName, "Associate a color with this design.\n"
|
||||
|
|
@ -178,18 +189,18 @@ public class DesignDetailTab
|
|||
var size = new Vector2(ImGui.GetFrameHeight());
|
||||
using var font = ImRaii.PushFont(UiBuilder.IconFont);
|
||||
ImGuiUtil.DrawTextButton(FontAwesomeIcon.ExclamationCircle.ToIconString(), size, 0, _colors.MissingColor);
|
||||
ImGuiUtil.HoverTooltip("The color associated with this design does not exist.");
|
||||
ImUtf8.HoverTooltip("The color associated with this design does not exist."u8);
|
||||
}
|
||||
|
||||
ImGuiUtil.DrawFrameColumn("Creation Date");
|
||||
ImUtf8.DrawFrameColumn("Creation Date"u8);
|
||||
ImGui.TableNextColumn();
|
||||
ImGuiUtil.DrawTextButton(_selector.Selected!.CreationDate.LocalDateTime.ToString("F"), width, 0);
|
||||
|
||||
ImGuiUtil.DrawFrameColumn("Last Update Date");
|
||||
ImUtf8.DrawFrameColumn("Last Update Date"u8);
|
||||
ImGui.TableNextColumn();
|
||||
ImGuiUtil.DrawTextButton(_selector.Selected!.LastEdit.LocalDateTime.ToString("F"), width, 0);
|
||||
|
||||
ImGuiUtil.DrawFrameColumn("Tags");
|
||||
ImUtf8.DrawFrameColumn("Tags"u8);
|
||||
ImGui.TableNextColumn();
|
||||
DrawTags();
|
||||
}
|
||||
|
|
@ -219,18 +230,18 @@ public class DesignDetailTab
|
|||
var size = new Vector2(ImGui.GetContentRegionAvail().X, 12 * ImGui.GetTextLineHeightWithSpacing());
|
||||
if (!_editDescriptionMode)
|
||||
{
|
||||
using (var textBox = ImRaii.ListBox("##desc", size))
|
||||
using (var textBox = ImUtf8.ListBox("##desc"u8, size))
|
||||
{
|
||||
ImGuiUtil.TextWrapped(desc);
|
||||
ImUtf8.TextWrapped(desc);
|
||||
}
|
||||
|
||||
if (ImGui.Button("Edit Description"))
|
||||
if (ImUtf8.Button("Edit Description"u8))
|
||||
_editDescriptionMode = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var edit = _newDescription ?? desc;
|
||||
if (ImGui.InputTextMultiline("##desc", ref edit, (uint)Math.Max(2000, 4 * edit.Length), size))
|
||||
if (ImUtf8.InputMultiLine("##desc"u8, ref edit, size))
|
||||
_newDescription = edit;
|
||||
|
||||
if (ImGui.IsItemDeactivatedAfterEdit())
|
||||
|
|
@ -239,7 +250,7 @@ public class DesignDetailTab
|
|||
_newDescription = null;
|
||||
}
|
||||
|
||||
if (ImGui.Button("Stop Editing"))
|
||||
if (ImUtf8.Button("Stop Editing"u8))
|
||||
_editDescriptionMode = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -423,6 +423,7 @@ public class DesignPanel
|
|||
ImGui.TableNextColumn();
|
||||
if (_selector.Selected == null)
|
||||
return;
|
||||
ImGui.Dummy(Vector2.Zero);
|
||||
DrawButtonRow();
|
||||
ImGui.TableNextColumn();
|
||||
|
||||
|
|
@ -438,7 +439,6 @@ public class DesignPanel
|
|||
|
||||
private void DrawButtonRow()
|
||||
{
|
||||
ImGui.Dummy(Vector2.Zero);
|
||||
DrawApplyToSelf();
|
||||
ImGui.SameLine();
|
||||
DrawApplyToTarget();
|
||||
|
|
|
|||
|
|
@ -88,16 +88,18 @@ public class ModAssociationsTab(PenumbraService penumbra, DesignFileSystemSelect
|
|||
|
||||
private void DrawTable()
|
||||
{
|
||||
using var table = ImRaii.Table("Mods", 5, ImGuiTableFlags.RowBg);
|
||||
using var table = ImUtf8.Table("Mods"u8, 7, ImGuiTableFlags.RowBg);
|
||||
if (!table)
|
||||
return;
|
||||
|
||||
ImGui.TableSetupColumn("##Buttons", ImGuiTableColumnFlags.WidthFixed,
|
||||
ImUtf8.TableSetupColumn("##Buttons"u8, ImGuiTableColumnFlags.WidthFixed,
|
||||
ImGui.GetFrameHeight() * 3 + ImGui.GetStyle().ItemInnerSpacing.X * 2);
|
||||
ImGui.TableSetupColumn("Mod Name", ImGuiTableColumnFlags.WidthStretch);
|
||||
ImGui.TableSetupColumn("State", ImGuiTableColumnFlags.WidthFixed, ImGui.CalcTextSize("State").X);
|
||||
ImGui.TableSetupColumn("Priority", ImGuiTableColumnFlags.WidthFixed, ImGui.CalcTextSize("Priority").X);
|
||||
ImGui.TableSetupColumn("##Options", ImGuiTableColumnFlags.WidthFixed, ImGui.CalcTextSize("Applym").X);
|
||||
ImUtf8.TableSetupColumn("Mod Name"u8, ImGuiTableColumnFlags.WidthStretch);
|
||||
ImUtf8.TableSetupColumn("Remove"u8, ImGuiTableColumnFlags.WidthFixed, ImUtf8.CalcTextSize("Remove"u8).X);
|
||||
ImUtf8.TableSetupColumn("Inherit"u8, ImGuiTableColumnFlags.WidthFixed, ImUtf8.CalcTextSize("Inherit"u8).X);
|
||||
ImUtf8.TableSetupColumn("State"u8, ImGuiTableColumnFlags.WidthFixed, ImUtf8.CalcTextSize("State"u8).X);
|
||||
ImUtf8.TableSetupColumn("Priority"u8, ImGuiTableColumnFlags.WidthFixed, ImUtf8.CalcTextSize("Priority"u8).X);
|
||||
ImUtf8.TableSetupColumn("##Options"u8, ImGuiTableColumnFlags.WidthFixed, ImUtf8.CalcTextSize("Applym"u8).X);
|
||||
ImGui.TableHeadersRow();
|
||||
|
||||
Mod? removedMod = null;
|
||||
|
|
@ -183,6 +185,17 @@ public class ModAssociationsTab(PenumbraService penumbra, DesignFileSystemSelect
|
|||
if (ImGui.IsItemHovered())
|
||||
ImGui.SetTooltip($"Mod Directory: {mod.DirectoryName}\n\nClick to open mod page in Penumbra.");
|
||||
ImGui.TableNextColumn();
|
||||
var remove = settings.Remove;
|
||||
if (TwoStateCheckbox.Instance.Draw("##Remove"u8, ref remove))
|
||||
updatedMod = (mod, settings with { Remove = remove });
|
||||
ImUtf8.HoverTooltip(
|
||||
"Remove any temporary settings applied by Glamourer instead of applying the configured settings. Only works when using temporary settings, ignored otherwise."u8);
|
||||
ImGui.TableNextColumn();
|
||||
var inherit = settings.ForceInherit;
|
||||
if (TwoStateCheckbox.Instance.Draw("##Enabled"u8, ref inherit))
|
||||
updatedMod = (mod, settings with { ForceInherit = inherit });
|
||||
ImUtf8.HoverTooltip("Force the mod to inherit its settings from inherited collections."u8);
|
||||
ImGui.TableNextColumn();
|
||||
var enabled = settings.Enabled;
|
||||
if (TwoStateCheckbox.Instance.Draw("##Enabled"u8, ref enabled))
|
||||
updatedMod = (mod, settings with { Enabled = enabled });
|
||||
|
|
|
|||
|
|
@ -106,6 +106,9 @@ public class SettingsTab(
|
|||
+ "Glamourer will NOT revert these applied settings automatically. This may mess up your collection and configuration.\n\n"
|
||||
+ "If you enable this setting, you are aware that any resulting misconfiguration is your own fault.",
|
||||
config.AlwaysApplyAssociatedMods, v => config.AlwaysApplyAssociatedMods = v);
|
||||
Checkbox("Use Temporary Mod Settings",
|
||||
"Apply all settings as temporary settings so they will be reset when Glamourer or the game shut down.", config.UseTemporarySettings,
|
||||
v => config.UseTemporarySettings = v);
|
||||
ImGui.NewLine();
|
||||
}
|
||||
|
||||
|
|
@ -120,6 +123,8 @@ public class SettingsTab(
|
|||
config.DefaultDesignSettings.ResetAdvancedDyes, v => config.DefaultDesignSettings.ResetAdvancedDyes = v);
|
||||
Checkbox("Always Force Redraw", "Newly created designs will be configured to force character redraws on application by default.",
|
||||
config.DefaultDesignSettings.AlwaysForceRedrawing, v => config.DefaultDesignSettings.AlwaysForceRedrawing = v);
|
||||
Checkbox("Reset Temporary Settings", "Newly created designs will be configured to clear all advanced settings applied by Glamourer to the collection by default.",
|
||||
config.DefaultDesignSettings.ResetTemporarySettings, v => config.DefaultDesignSettings.ResetTemporarySettings = v);
|
||||
}
|
||||
|
||||
private void DrawInterfaceSettings()
|
||||
|
|
|
|||
|
|
@ -3,12 +3,15 @@ using Glamourer.Services;
|
|||
using Glamourer.State;
|
||||
using OtterGui.Services;
|
||||
using Penumbra.GameData.Interop;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Glamourer.Interop.Penumbra;
|
||||
|
||||
public class ModSettingApplier(PenumbraService penumbra, Configuration config, ObjectManager objects, CollectionOverrideService overrides)
|
||||
: IService
|
||||
{
|
||||
private readonly HashSet<Guid> _collectionTracker = [];
|
||||
|
||||
public void HandleStateApplication(ActorState state, MergedDesign design)
|
||||
{
|
||||
if (!config.AlwaysApplyAssociatedMods || design.AssociatedMods.Count == 0)
|
||||
|
|
@ -22,20 +25,20 @@ public class ModSettingApplier(PenumbraService penumbra, Configuration config, O
|
|||
return;
|
||||
}
|
||||
|
||||
var collections = new HashSet<Guid>();
|
||||
|
||||
_collectionTracker.Clear();
|
||||
foreach (var actor in data.Objects)
|
||||
{
|
||||
var (collection, _, overridden) = overrides.GetCollection(actor, state.Identifier);
|
||||
if (collection == Guid.Empty)
|
||||
continue;
|
||||
|
||||
if (!collections.Add(collection))
|
||||
if (!_collectionTracker.Add(collection))
|
||||
continue;
|
||||
|
||||
var index = ResetOldSettings(collection, actor, design.ResetTemporarySettings);
|
||||
foreach (var (mod, setting) in design.AssociatedMods)
|
||||
{
|
||||
var message = penumbra.SetMod(mod, setting, collection);
|
||||
var message = penumbra.SetMod(mod, setting, collection, index);
|
||||
if (message.Length > 0)
|
||||
Glamourer.Log.Verbose($"[Mod Applier] Error applying mod settings: {message}");
|
||||
else
|
||||
|
|
@ -45,7 +48,8 @@ public class ModSettingApplier(PenumbraService penumbra, Configuration config, O
|
|||
}
|
||||
}
|
||||
|
||||
public (List<string> Messages, int Applied, Guid Collection, string Name, bool Overridden) ApplyModSettings(IReadOnlyDictionary<Mod, ModSettings> settings, Actor actor)
|
||||
public (List<string> Messages, int Applied, Guid Collection, string Name, bool Overridden) ApplyModSettings(
|
||||
IReadOnlyDictionary<Mod, ModSettings> settings, Actor actor, bool resetOther)
|
||||
{
|
||||
var (collection, name, overridden) = overrides.GetCollection(actor);
|
||||
if (collection == Guid.Empty)
|
||||
|
|
@ -53,9 +57,11 @@ public class ModSettingApplier(PenumbraService penumbra, Configuration config, O
|
|||
|
||||
var messages = new List<string>();
|
||||
var appliedMods = 0;
|
||||
|
||||
var index = ResetOldSettings(collection, actor, resetOther);
|
||||
foreach (var (mod, setting) in settings)
|
||||
{
|
||||
var message = penumbra.SetMod(mod, setting, collection);
|
||||
var message = penumbra.SetMod(mod, setting, collection, index);
|
||||
if (message.Length > 0)
|
||||
messages.Add($"Error applying mod settings: {message}");
|
||||
else
|
||||
|
|
@ -64,4 +70,18 @@ public class ModSettingApplier(PenumbraService penumbra, Configuration config, O
|
|||
|
||||
return (messages, appliedMods, collection, name, overridden);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private ObjectIndex? ResetOldSettings(Guid collection, Actor actor, bool resetOther)
|
||||
{
|
||||
ObjectIndex? index = actor.Valid ? actor.Index : null;
|
||||
if (!resetOther)
|
||||
return index;
|
||||
|
||||
if (index == null)
|
||||
penumbra.RemoveAllTemporarySettings(collection);
|
||||
else
|
||||
penumbra.RemoveAllTemporarySettings(index.Value);
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,10 +21,10 @@ public readonly record struct Mod(string Name, string DirectoryName) : IComparab
|
|||
}
|
||||
}
|
||||
|
||||
public readonly record struct ModSettings(Dictionary<string, List<string>> Settings, int Priority, bool Enabled)
|
||||
public readonly record struct ModSettings(Dictionary<string, List<string>> Settings, int Priority, bool Enabled, bool ForceInherit, bool Remove)
|
||||
{
|
||||
public ModSettings()
|
||||
: this(new Dictionary<string, List<string>>(), 0, false)
|
||||
: this(new Dictionary<string, List<string>>(), 0, false, false, false)
|
||||
{ }
|
||||
|
||||
public static ModSettings Empty
|
||||
|
|
@ -33,30 +33,41 @@ public readonly record struct ModSettings(Dictionary<string, List<string>> Setti
|
|||
|
||||
public class PenumbraService : IDisposable
|
||||
{
|
||||
public const int RequiredPenumbraBreakingVersion = 5;
|
||||
public const int RequiredPenumbraFeatureVersion = 0;
|
||||
public const int RequiredPenumbraBreakingVersion = 5;
|
||||
public const int RequiredPenumbraFeatureVersion = 3;
|
||||
public const int RequiredPenumbraFeatureVersionTemp = 4;
|
||||
|
||||
private readonly IDalamudPluginInterface _pluginInterface;
|
||||
private const int Key = -1610;
|
||||
|
||||
private readonly IDalamudPluginInterface _pluginInterface;
|
||||
private readonly Configuration _config;
|
||||
private readonly EventSubscriber<ChangedItemType, uint> _tooltipSubscriber;
|
||||
private readonly EventSubscriber<MouseButton, ChangedItemType, uint> _clickSubscriber;
|
||||
private readonly EventSubscriber<nint, Guid, nint, nint, nint> _creatingCharacterBase;
|
||||
private readonly EventSubscriber<nint, Guid, nint> _createdCharacterBase;
|
||||
private readonly EventSubscriber<ModSettingChange, Guid, string, bool> _modSettingChanged;
|
||||
|
||||
private global::Penumbra.Api.IpcSubscribers.GetCollectionsByIdentifier? _collectionByIdentifier;
|
||||
private global::Penumbra.Api.IpcSubscribers.GetCollections? _collections;
|
||||
private global::Penumbra.Api.IpcSubscribers.RedrawObject? _redraw;
|
||||
private global::Penumbra.Api.IpcSubscribers.GetDrawObjectInfo? _drawObjectInfo;
|
||||
private global::Penumbra.Api.IpcSubscribers.GetCutsceneParentIndex? _cutsceneParent;
|
||||
private global::Penumbra.Api.IpcSubscribers.GetCollectionForObject? _objectCollection;
|
||||
private global::Penumbra.Api.IpcSubscribers.GetModList? _getMods;
|
||||
private global::Penumbra.Api.IpcSubscribers.GetCollection? _currentCollection;
|
||||
private global::Penumbra.Api.IpcSubscribers.GetCurrentModSettings? _getCurrentSettings;
|
||||
private global::Penumbra.Api.IpcSubscribers.TrySetMod? _setMod;
|
||||
private global::Penumbra.Api.IpcSubscribers.TrySetModPriority? _setModPriority;
|
||||
private global::Penumbra.Api.IpcSubscribers.TrySetModSetting? _setModSetting;
|
||||
private global::Penumbra.Api.IpcSubscribers.TrySetModSettings? _setModSettings;
|
||||
private global::Penumbra.Api.IpcSubscribers.OpenMainWindow? _openModPage;
|
||||
private global::Penumbra.Api.IpcSubscribers.GetCollectionsByIdentifier? _collectionByIdentifier;
|
||||
private global::Penumbra.Api.IpcSubscribers.GetCollections? _collections;
|
||||
private global::Penumbra.Api.IpcSubscribers.RedrawObject? _redraw;
|
||||
private global::Penumbra.Api.IpcSubscribers.GetDrawObjectInfo? _drawObjectInfo;
|
||||
private global::Penumbra.Api.IpcSubscribers.GetCutsceneParentIndex? _cutsceneParent;
|
||||
private global::Penumbra.Api.IpcSubscribers.GetCollectionForObject? _objectCollection;
|
||||
private global::Penumbra.Api.IpcSubscribers.GetModList? _getMods;
|
||||
private global::Penumbra.Api.IpcSubscribers.GetCollection? _currentCollection;
|
||||
private global::Penumbra.Api.IpcSubscribers.GetCurrentModSettings? _getCurrentSettings;
|
||||
private global::Penumbra.Api.IpcSubscribers.TryInheritMod? _inheritMod;
|
||||
private global::Penumbra.Api.IpcSubscribers.TrySetMod? _setMod;
|
||||
private global::Penumbra.Api.IpcSubscribers.TrySetModPriority? _setModPriority;
|
||||
private global::Penumbra.Api.IpcSubscribers.TrySetModSetting? _setModSetting;
|
||||
private global::Penumbra.Api.IpcSubscribers.TrySetModSettings? _setModSettings;
|
||||
private global::Penumbra.Api.IpcSubscribers.SetTemporaryModSettings? _setTemporaryModSettings;
|
||||
private global::Penumbra.Api.IpcSubscribers.SetTemporaryModSettingsPlayer? _setTemporaryModSettingsPlayer;
|
||||
private global::Penumbra.Api.IpcSubscribers.RemoveTemporaryModSettings? _removeTemporaryModSettings;
|
||||
private global::Penumbra.Api.IpcSubscribers.RemoveTemporaryModSettingsPlayer? _removeTemporaryModSettingsPlayer;
|
||||
private global::Penumbra.Api.IpcSubscribers.RemoveAllTemporaryModSettings? _removeAllTemporaryModSettings;
|
||||
private global::Penumbra.Api.IpcSubscribers.RemoveAllTemporaryModSettingsPlayer? _removeAllTemporaryModSettingsPlayer;
|
||||
private global::Penumbra.Api.IpcSubscribers.OpenMainWindow? _openModPage;
|
||||
|
||||
private readonly IDisposable _initializedEvent;
|
||||
private readonly IDisposable _disposedEvent;
|
||||
|
|
@ -68,10 +79,11 @@ public class PenumbraService : IDisposable
|
|||
public int CurrentMinor { get; private set; }
|
||||
public DateTime AttachTime { get; private set; }
|
||||
|
||||
public PenumbraService(IDalamudPluginInterface pi, PenumbraReloaded penumbraReloaded)
|
||||
public PenumbraService(IDalamudPluginInterface pi, PenumbraReloaded penumbraReloaded, Configuration config)
|
||||
{
|
||||
_pluginInterface = pi;
|
||||
_penumbraReloaded = penumbraReloaded;
|
||||
_config = config;
|
||||
_initializedEvent = global::Penumbra.Api.IpcSubscribers.Initialized.Subscriber(pi, Reattach);
|
||||
_disposedEvent = global::Penumbra.Api.IpcSubscribers.Disposed.Subscriber(pi, Unattach);
|
||||
_tooltipSubscriber = global::Penumbra.Api.IpcSubscribers.ChangedItemTooltip.Subscriber(pi);
|
||||
|
|
@ -128,7 +140,7 @@ public class PenumbraService : IDisposable
|
|||
if (ec is not PenumbraApiEc.Success)
|
||||
return ModSettings.Empty;
|
||||
|
||||
return tuple.HasValue ? new ModSettings(tuple.Value.Item3, tuple.Value.Item2, tuple.Value.Item1) : ModSettings.Empty;
|
||||
return tuple.HasValue ? new ModSettings(tuple.Value.Item3, tuple.Value.Item2, tuple.Value.Item1, false, false) : ModSettings.Empty;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -164,7 +176,7 @@ public class PenumbraService : IDisposable
|
|||
.Select(t => (new Mod(t.Item2, t.Item1),
|
||||
!t.Item3.Item2.HasValue
|
||||
? ModSettings.Empty
|
||||
: new ModSettings(t.Item3.Item2!.Value.Item3, t.Item3.Item2!.Value.Item2, t.Item3.Item2!.Value.Item1)))
|
||||
: new ModSettings(t.Item3.Item2!.Value.Item3, t.Item3.Item2!.Value.Item2, t.Item3.Item2!.Value.Item1, false, false)))
|
||||
.OrderByDescending(p => p.Item2.Enabled)
|
||||
.ThenBy(p => p.Item1.Name)
|
||||
.ThenBy(p => p.Item1.DirectoryName)
|
||||
|
|
@ -195,7 +207,7 @@ public class PenumbraService : IDisposable
|
|||
/// Try to set all mod settings as desired. Only sets when the mod should be enabled.
|
||||
/// If it is disabled, ignore all other settings.
|
||||
/// </summary>
|
||||
public string SetMod(Mod mod, ModSettings settings, Guid? collectionInput = null)
|
||||
public string SetMod(Mod mod, ModSettings settings, Guid? collectionInput = null, ObjectIndex? index = null)
|
||||
{
|
||||
if (!Available)
|
||||
return "Penumbra is not available.";
|
||||
|
|
@ -204,40 +216,10 @@ public class PenumbraService : IDisposable
|
|||
try
|
||||
{
|
||||
var collection = collectionInput ?? _currentCollection!.Invoke(ApiCollectionType.Current)!.Value.Id;
|
||||
var ec = _setMod!.Invoke(collection, mod.DirectoryName, settings.Enabled);
|
||||
switch (ec)
|
||||
{
|
||||
case PenumbraApiEc.ModMissing: return $"The mod {mod.Name} [{mod.DirectoryName}] could not be found.";
|
||||
case PenumbraApiEc.CollectionMissing: return $"The collection {collection} could not be found.";
|
||||
}
|
||||
|
||||
if (!settings.Enabled)
|
||||
return string.Empty;
|
||||
|
||||
ec = _setModPriority!.Invoke(collection, mod.DirectoryName, settings.Priority);
|
||||
Debug.Assert(ec is PenumbraApiEc.Success or PenumbraApiEc.NothingChanged, "Setting Priority should not be able to fail.");
|
||||
|
||||
foreach (var (setting, list) in settings.Settings)
|
||||
{
|
||||
ec = list.Count == 1
|
||||
? _setModSetting!.Invoke(collection, mod.DirectoryName, setting, list[0])
|
||||
: _setModSettings!.Invoke(collection, mod.DirectoryName, setting, list);
|
||||
switch (ec)
|
||||
{
|
||||
case PenumbraApiEc.OptionGroupMissing:
|
||||
sb.AppendLine($"Could not find the option group {setting} in mod {mod.Name}.");
|
||||
break;
|
||||
case PenumbraApiEc.OptionMissing:
|
||||
sb.AppendLine($"Could not find all desired options in the option group {setting} in mod {mod.Name}.");
|
||||
break;
|
||||
case PenumbraApiEc.Success:
|
||||
case PenumbraApiEc.NothingChanged:
|
||||
break;
|
||||
default:
|
||||
sb.AppendLine($"Could not apply options in the option group {setting} in mod {mod.Name} for unknown reason {ec}.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (_config.UseTemporarySettings && _setTemporaryModSettings != null)
|
||||
SetModTemporary(sb, mod, settings, collection, index);
|
||||
else
|
||||
SetModPermanent(sb, mod, settings, collection);
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
|
@ -247,6 +229,103 @@ public class PenumbraService : IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
public void RemoveAllTemporarySettings(Guid collection)
|
||||
=> _removeAllTemporaryModSettings?.Invoke(collection, Key);
|
||||
|
||||
public void RemoveAllTemporarySettings(ObjectIndex index)
|
||||
=> _removeAllTemporaryModSettingsPlayer?.Invoke(index.Index, Key);
|
||||
|
||||
public void ClearAllTemporarySettings()
|
||||
{
|
||||
if (!Available || _removeAllTemporaryModSettings == null)
|
||||
return;
|
||||
|
||||
var collections = _collections!.Invoke();
|
||||
foreach (var collection in collections)
|
||||
RemoveAllTemporarySettings(collection.Key);
|
||||
}
|
||||
|
||||
private void SetModTemporary(StringBuilder sb, Mod mod, ModSettings settings, Guid collection, ObjectIndex? index)
|
||||
{
|
||||
var ex = settings.Remove
|
||||
? index.HasValue
|
||||
? _removeTemporaryModSettingsPlayer!.Invoke(index.Value.Index, mod.DirectoryName, Key)
|
||||
: _removeTemporaryModSettings!.Invoke(collection, mod.DirectoryName, Key)
|
||||
: index.HasValue
|
||||
? _setTemporaryModSettingsPlayer!.Invoke(index.Value.Index, mod.DirectoryName, settings.ForceInherit, settings.Enabled,
|
||||
settings.Priority,
|
||||
settings.Settings.ToDictionary(kvp => kvp.Key, kvp => (IReadOnlyList<string>)kvp.Value), "Glamourer", Key)
|
||||
: _setTemporaryModSettings!.Invoke(collection, mod.DirectoryName, settings.ForceInherit, settings.Enabled, settings.Priority,
|
||||
settings.Settings.ToDictionary(kvp => kvp.Key, kvp => (IReadOnlyList<string>)kvp.Value), "Glamourer", Key);
|
||||
switch (ex)
|
||||
{
|
||||
case PenumbraApiEc.InvalidArgument:
|
||||
sb.Append($"No actor with index {index!.Value.Index} could be identified.");
|
||||
return;
|
||||
case PenumbraApiEc.ModMissing:
|
||||
sb.Append($"The mod {mod.Name} [{mod.DirectoryName}] could not be found.");
|
||||
return;
|
||||
case PenumbraApiEc.CollectionMissing:
|
||||
sb.Append($"The collection {collection} could not be found.");
|
||||
return;
|
||||
case PenumbraApiEc.TemporarySettingImpossible:
|
||||
sb.Append($"The collection {collection} can not have settings.");
|
||||
return;
|
||||
case PenumbraApiEc.TemporarySettingDisallowed:
|
||||
sb.Append($"The mod {mod.Name} [{mod.DirectoryName}] already has temporary settings with a different key in {collection}.");
|
||||
return;
|
||||
case PenumbraApiEc.OptionGroupMissing:
|
||||
case PenumbraApiEc.OptionMissing:
|
||||
sb.Append($"The provided settings for {mod.Name} [{mod.DirectoryName}] did not correspond to its actual options.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetModPermanent(StringBuilder sb, Mod mod, ModSettings settings, Guid collection)
|
||||
{
|
||||
var ec = settings.ForceInherit
|
||||
? _inheritMod!.Invoke(collection, mod.DirectoryName, true)
|
||||
: _setMod!.Invoke(collection, mod.DirectoryName, settings.Enabled);
|
||||
switch (ec)
|
||||
{
|
||||
case PenumbraApiEc.ModMissing:
|
||||
sb.Append($"The mod {mod.Name} [{mod.DirectoryName}] could not be found.");
|
||||
return;
|
||||
case PenumbraApiEc.CollectionMissing:
|
||||
sb.Append($"The collection {collection} could not be found.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (settings.ForceInherit || !settings.Enabled)
|
||||
return;
|
||||
|
||||
ec = _setModPriority!.Invoke(collection, mod.DirectoryName, settings.Priority);
|
||||
Debug.Assert(ec is PenumbraApiEc.Success or PenumbraApiEc.NothingChanged, "Setting Priority should not be able to fail.");
|
||||
|
||||
foreach (var (setting, list) in settings.Settings)
|
||||
{
|
||||
ec = list.Count == 1
|
||||
? _setModSetting!.Invoke(collection, mod.DirectoryName, setting, list[0])
|
||||
: _setModSettings!.Invoke(collection, mod.DirectoryName, setting, list);
|
||||
switch (ec)
|
||||
{
|
||||
case PenumbraApiEc.OptionGroupMissing:
|
||||
sb.AppendLine($"Could not find the option group {setting} in mod {mod.Name}.");
|
||||
break;
|
||||
case PenumbraApiEc.OptionMissing:
|
||||
sb.AppendLine($"Could not find all desired options in the option group {setting} in mod {mod.Name}.");
|
||||
break;
|
||||
case PenumbraApiEc.Success:
|
||||
case PenumbraApiEc.NothingChanged:
|
||||
break;
|
||||
default:
|
||||
sb.AppendLine($"Could not apply options in the option group {setting} in mod {mod.Name} for unknown reason {ec}.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Obtain the name of the collection currently assigned to the player. </summary>
|
||||
public Guid GetCurrentPlayerCollection()
|
||||
{
|
||||
|
|
@ -347,12 +426,24 @@ public class PenumbraService : IDisposable
|
|||
_getMods = new global::Penumbra.Api.IpcSubscribers.GetModList(_pluginInterface);
|
||||
_currentCollection = new global::Penumbra.Api.IpcSubscribers.GetCollection(_pluginInterface);
|
||||
_getCurrentSettings = new global::Penumbra.Api.IpcSubscribers.GetCurrentModSettings(_pluginInterface);
|
||||
_inheritMod = new global::Penumbra.Api.IpcSubscribers.TryInheritMod(_pluginInterface);
|
||||
_setMod = new global::Penumbra.Api.IpcSubscribers.TrySetMod(_pluginInterface);
|
||||
_setModPriority = new global::Penumbra.Api.IpcSubscribers.TrySetModPriority(_pluginInterface);
|
||||
_setModSetting = new global::Penumbra.Api.IpcSubscribers.TrySetModSetting(_pluginInterface);
|
||||
_setModSettings = new global::Penumbra.Api.IpcSubscribers.TrySetModSettings(_pluginInterface);
|
||||
_openModPage = new global::Penumbra.Api.IpcSubscribers.OpenMainWindow(_pluginInterface);
|
||||
Available = true;
|
||||
if (CurrentMinor >= RequiredPenumbraFeatureVersionTemp)
|
||||
{
|
||||
_setTemporaryModSettings = new global::Penumbra.Api.IpcSubscribers.SetTemporaryModSettings(_pluginInterface);
|
||||
_setTemporaryModSettingsPlayer = new global::Penumbra.Api.IpcSubscribers.SetTemporaryModSettingsPlayer(_pluginInterface);
|
||||
_removeTemporaryModSettings = new global::Penumbra.Api.IpcSubscribers.RemoveTemporaryModSettings(_pluginInterface);
|
||||
_removeTemporaryModSettingsPlayer = new global::Penumbra.Api.IpcSubscribers.RemoveTemporaryModSettingsPlayer(_pluginInterface);
|
||||
_removeAllTemporaryModSettings = new global::Penumbra.Api.IpcSubscribers.RemoveAllTemporaryModSettings(_pluginInterface);
|
||||
_removeAllTemporaryModSettingsPlayer =
|
||||
new global::Penumbra.Api.IpcSubscribers.RemoveAllTemporaryModSettingsPlayer(_pluginInterface);
|
||||
}
|
||||
|
||||
Available = true;
|
||||
_penumbraReloaded.Invoke();
|
||||
Glamourer.Log.Debug("Glamourer attached to Penumbra.");
|
||||
}
|
||||
|
|
@ -373,27 +464,35 @@ public class PenumbraService : IDisposable
|
|||
_modSettingChanged.Disable();
|
||||
if (Available)
|
||||
{
|
||||
_collectionByIdentifier = null;
|
||||
_collections = null;
|
||||
_redraw = null;
|
||||
_drawObjectInfo = null;
|
||||
_cutsceneParent = null;
|
||||
_objectCollection = null;
|
||||
_getMods = null;
|
||||
_currentCollection = null;
|
||||
_getCurrentSettings = null;
|
||||
_setMod = null;
|
||||
_setModPriority = null;
|
||||
_setModSetting = null;
|
||||
_setModSettings = null;
|
||||
_openModPage = null;
|
||||
Available = false;
|
||||
_collectionByIdentifier = null;
|
||||
_collections = null;
|
||||
_redraw = null;
|
||||
_drawObjectInfo = null;
|
||||
_cutsceneParent = null;
|
||||
_objectCollection = null;
|
||||
_getMods = null;
|
||||
_currentCollection = null;
|
||||
_getCurrentSettings = null;
|
||||
_inheritMod = null;
|
||||
_setMod = null;
|
||||
_setModPriority = null;
|
||||
_setModSetting = null;
|
||||
_setModSettings = null;
|
||||
_openModPage = null;
|
||||
_setTemporaryModSettings = null;
|
||||
_setTemporaryModSettingsPlayer = null;
|
||||
_removeTemporaryModSettings = null;
|
||||
_removeTemporaryModSettingsPlayer = null;
|
||||
_removeAllTemporaryModSettings = null;
|
||||
_removeAllTemporaryModSettingsPlayer = null;
|
||||
Available = false;
|
||||
Glamourer.Log.Debug("Glamourer detached from Penumbra.");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ClearAllTemporarySettings();
|
||||
Unattach();
|
||||
_tooltipSubscriber.Dispose();
|
||||
_clickSubscriber.Dispose();
|
||||
|
|
|
|||
|
|
@ -691,7 +691,7 @@ public class CommandService : IDisposable, IApiService
|
|||
if (!applyMods || design is not Design d)
|
||||
return;
|
||||
|
||||
var (messages, appliedMods, _, name, overridden) = _modApplier.ApplyModSettings(d.AssociatedMods, actor);
|
||||
var (messages, appliedMods, _, name, overridden) = _modApplier.ApplyModSettings(d.AssociatedMods, actor, d.ResetTemporarySettings);
|
||||
|
||||
foreach (var message in messages)
|
||||
Glamourer.Messager.Chat.Print($"Error applying mod settings: {message}");
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 882b778e78bb0806dd7d38e8b3670ff138a84a31
|
||||
Subproject commit de0f281fbf9d8d9d3aa8463a28025d54877cde8d
|
||||
Loading…
Add table
Add a link
Reference in a new issue