mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 10:17:22 +01:00
Current State.
This commit is contained in:
parent
98a89bb2b4
commit
282189ef6d
9 changed files with 115 additions and 56 deletions
|
|
@ -1 +1 @@
|
|||
Subproject commit 97e9f427406f82a59ddef764b44ecea654a51623
|
||||
Subproject commit fdda2054c26a30111ac55984ed6efde7f7214b68
|
||||
|
|
@ -333,6 +333,9 @@ public class CollectionCacheManager : IDisposable, IService
|
|||
cache.ReloadMod(mod, true);
|
||||
|
||||
break;
|
||||
case ModSettingChange.TemporarySetting:
|
||||
cache.ReloadMod(mod!, true);
|
||||
break;
|
||||
case ModSettingChange.MultiInheritance:
|
||||
case ModSettingChange.MultiEnableState:
|
||||
FullRecalculation(collection);
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ public class CollectionEditor(SaveService saveService, CommunicatorService commu
|
|||
|
||||
/// <summary>
|
||||
/// Set a given setting group settingName of mod idx to newValue if it differs from the current value and fix it if necessary.
|
||||
/// /// If the mod is currently inherited, stop the inheritance.
|
||||
/// If the mod is currently inherited, stop the inheritance.
|
||||
/// </summary>
|
||||
public bool SetModSetting(ModCollection collection, Mod mod, int groupIdx, Setting newValue)
|
||||
{
|
||||
|
|
@ -103,6 +103,18 @@ public class CollectionEditor(SaveService saveService, CommunicatorService commu
|
|||
return true;
|
||||
}
|
||||
|
||||
public bool SetTemporarySettings(ModCollection collection, Mod mod, TemporaryModSettings? settings, int key = 0)
|
||||
{
|
||||
key = settings?.Lock ?? key;
|
||||
var old = collection.GetTempSettings(mod.Index);
|
||||
if (old != null && old.Lock != 0 && old.Lock != key)
|
||||
return false;
|
||||
|
||||
collection.Settings.SetTemporary(mod.Index, settings);
|
||||
InvokeChange(collection, ModSettingChange.TemporarySetting, mod, Setting.Indefinite, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary> Copy the settings of an existing (sourceMod != null) or stored (sourceName) mod to another mod, if they exist. </summary>
|
||||
public bool CopyModSettings(ModCollection collection, Mod? sourceMod, string sourceName, Mod? targetMod, string targetName)
|
||||
{
|
||||
|
|
@ -168,7 +180,7 @@ public class CollectionEditor(SaveService saveService, CommunicatorService commu
|
|||
if (inherit == (settings == null))
|
||||
return false;
|
||||
|
||||
ModSettings? settings1 = inherit ? null : collection.GetInheritedSettings(mod.Index).Settings?.DeepCopy() ?? ModSettings.DefaultSettings(mod);
|
||||
var settings1 = inherit ? null : collection.GetInheritedSettings(mod.Index).Settings?.DeepCopy() ?? ModSettings.DefaultSettings(mod);
|
||||
collection.Settings.Set(mod.Index, settings1);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -179,7 +191,8 @@ public class CollectionEditor(SaveService saveService, CommunicatorService commu
|
|||
{
|
||||
saveService.QueueSave(new ModCollectionSave(modStorage, changedCollection));
|
||||
communicator.ModSettingChanged.Invoke(changedCollection, type, mod, oldValue, groupIdx, false);
|
||||
RecurseInheritors(changedCollection, type, mod, oldValue, groupIdx);
|
||||
if (type is not ModSettingChange.TemporarySetting)
|
||||
RecurseInheritors(changedCollection, type, mod, oldValue, groupIdx);
|
||||
}
|
||||
|
||||
/// <summary> Trigger changes in all inherited collections. </summary>
|
||||
|
|
|
|||
|
|
@ -36,17 +36,11 @@ public class ModSelection : EventWrapper<Mod?, Mod?, ModSelection.Priority>
|
|||
_communicator.ModSettingChanged.Subscribe(OnSettingChange, ModSettingChanged.Priority.ModSelection);
|
||||
}
|
||||
|
||||
public ModSettings Settings { get; private set; } = ModSettings.Empty;
|
||||
public ModCollection Collection { get; private set; } = ModCollection.Empty;
|
||||
public Mod? Mod { get; private set; }
|
||||
public ModSettings? OwnSettings { get; private set; }
|
||||
|
||||
public bool IsTemporary
|
||||
=> OwnSettings != Settings;
|
||||
|
||||
public TemporaryModSettings? AsTemporarySettings
|
||||
=> Settings as TemporaryModSettings;
|
||||
|
||||
public ModSettings Settings { get; private set; } = ModSettings.Empty;
|
||||
public ModCollection Collection { get; private set; } = ModCollection.Empty;
|
||||
public Mod? Mod { get; private set; }
|
||||
public ModSettings? OwnSettings { get; private set; }
|
||||
public TemporaryModSettings? TemporarySettings { get; private set; }
|
||||
|
||||
public void SelectMod(Mod? mod)
|
||||
{
|
||||
|
|
@ -98,6 +92,7 @@ public class ModSelection : EventWrapper<Mod?, Mod?, ModSelection.Priority>
|
|||
{
|
||||
(var settings, Collection) = _collections.Current.GetActualSettings(Mod.Index);
|
||||
OwnSettings = _collections.Current.GetOwnSettings(Mod.Index);
|
||||
TemporarySettings = _collections.Current.GetTempSettings(Mod.Index);
|
||||
Settings = settings ?? ModSettings.Empty;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ namespace Penumbra.Mods.Settings;
|
|||
public class ModSettings
|
||||
{
|
||||
public static readonly ModSettings Empty = new();
|
||||
|
||||
public SettingList Settings { get; internal init; } = [];
|
||||
public ModPriority Priority { get; set; }
|
||||
public bool Enabled { get; set; }
|
||||
|
|
|
|||
|
|
@ -5,4 +5,21 @@ public sealed class TemporaryModSettings : ModSettings
|
|||
public string Source = string.Empty;
|
||||
public int Lock = 0;
|
||||
public bool ForceInherit;
|
||||
|
||||
// Create default settings for a given mod.
|
||||
public static TemporaryModSettings DefaultSettings(Mod mod, string source, int key = 0)
|
||||
=> new()
|
||||
{
|
||||
Enabled = false,
|
||||
Source = source,
|
||||
Lock = key,
|
||||
Priority = ModPriority.Default,
|
||||
Settings = SettingList.Default(mod),
|
||||
};
|
||||
}
|
||||
|
||||
public static class ModSettingsExtensions
|
||||
{
|
||||
public static bool IsTemporary(this ModSettings? settings)
|
||||
=> settings is TemporaryModSettings;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -742,7 +742,7 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
|
|||
|
||||
private void OnSettingChange(ModCollection collection, ModSettingChange type, Mod? mod, Setting oldValue, int groupIdx, bool inherited)
|
||||
{
|
||||
if (collection != _collectionManager.Active.Current || mod != _mod)
|
||||
if (collection != _collectionManager.Active.Current || mod != _mod || type is ModSettingChange.TemporarySetting)
|
||||
return;
|
||||
|
||||
_swapData.LoadMod(_mod, _modSettings);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
using ImGuiNET;
|
||||
using OtterGui.Custom;
|
||||
|
||||
namespace Penumbra.UI.Classes;
|
||||
|
||||
public enum ColorId
|
||||
public enum ColorId : short
|
||||
{
|
||||
EnabledMod,
|
||||
DisabledMod,
|
||||
|
|
@ -10,6 +11,7 @@ public enum ColorId
|
|||
InheritedMod,
|
||||
InheritedDisabledMod,
|
||||
NewMod,
|
||||
NewModTint,
|
||||
ConflictingMod,
|
||||
HandledConflictMod,
|
||||
FolderExpanded,
|
||||
|
|
@ -31,10 +33,8 @@ public enum ColorId
|
|||
ResTreeNonNetworked,
|
||||
PredefinedTagAdd,
|
||||
PredefinedTagRemove,
|
||||
TemporaryEnabledMod,
|
||||
TemporaryDisabledMod,
|
||||
TemporaryInheritedMod,
|
||||
TemporaryInheritedDisabledMod,
|
||||
TemporaryModSettingsTint,
|
||||
NoTint,
|
||||
}
|
||||
|
||||
public static class Colors
|
||||
|
|
@ -52,6 +52,18 @@ public static class Colors
|
|||
public const uint ReniColorHovered = CustomGui.ReniColorHovered;
|
||||
public const uint ReniColorActive = CustomGui.ReniColorActive;
|
||||
|
||||
public static uint Tinted(this ColorId color, ColorId tint)
|
||||
{
|
||||
var tintValue = ImGui.ColorConvertU32ToFloat4(tint.Value());
|
||||
var value = ImGui.ColorConvertU32ToFloat4(color.Value());
|
||||
var negAlpha = 1 - tintValue.W;
|
||||
var newAlpha = negAlpha * value.W + tintValue.W;
|
||||
var newR = (negAlpha * value.W * value.X + tintValue.W * tintValue.X) / newAlpha;
|
||||
var newG = (negAlpha * value.W * value.Y + tintValue.W * tintValue.Y) / newAlpha;
|
||||
var newB = (negAlpha * value.W * value.Z + tintValue.W * tintValue.Z) / newAlpha;
|
||||
return ImGui.ColorConvertFloat4ToU32(new Vector4(newR, newG, newB, newAlpha));
|
||||
}
|
||||
|
||||
public static (uint DefaultColor, string Name, string Description) Data(this ColorId color)
|
||||
=> color switch
|
||||
{
|
||||
|
|
@ -83,10 +95,9 @@ public static class Colors
|
|||
ColorId.ResTreeNonNetworked => ( 0xFFC0C0FF, "On-Screen: Non-Players (Local)", "Non-player entities handled locally, in the On-Screen tab." ),
|
||||
ColorId.PredefinedTagAdd => ( 0xFF44AA44, "Predefined Tags: Add Tag", "A predefined tag that is not present on the current mod and can be added." ),
|
||||
ColorId.PredefinedTagRemove => ( 0xFF2222AA, "Predefined Tags: Remove Tag", "A predefined tag that is already present on the current mod and can be removed." ),
|
||||
ColorId.TemporaryEnabledMod => ( 0xFFFFC0A0, "Mod Enabled By Temporary Settings", "A mod that is enabled by temporary settings in the currently selected collection." ),
|
||||
ColorId.TemporaryDisabledMod => ( 0xFFB08070, "Mod Disabled By Temporary Settings", "A mod that is disabled by temporary settings in the currently selected collection." ),
|
||||
ColorId.TemporaryInheritedMod => ( 0xFFE8FFB0, "Mod Enabled By Temporary Inheritance", "A mod that is forced to inherit by temporary settings in the currently selected collection." ),
|
||||
ColorId.TemporaryInheritedDisabledMod => ( 0xFF90A080, "Mod Disabled By Temporary Inheritance", "A mod that is forced to inherit by temporary settings in the currently selected collection." ),
|
||||
ColorId.TemporaryModSettingsTint => ( 0x30FF0000, "Mod with Temporary Settings", "A mod that has temporary settings. This color is used as a tint for the regular state colors." ),
|
||||
ColorId.NewModTint => ( 0x8000FF00, "New Mod Tint", "A mod that was newly imported or created during this session and has not been enabled yet. This color is used as a tint for the regular state colors."),
|
||||
ColorId.NoTint => ( 0x00000000, "No Tint", "The default tint for all mods."),
|
||||
_ => throw new ArgumentOutOfRangeException( nameof( color ), color, null ),
|
||||
// @formatter:on
|
||||
};
|
||||
|
|
|
|||
|
|
@ -62,6 +62,8 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
|
|||
SubscribeRightClickFolder(f => SetQuickMove(f, 1, _config.QuickMoveFolder2, s => { _config.QuickMoveFolder2 = s; _config.Save(); }), 120);
|
||||
SubscribeRightClickFolder(f => SetQuickMove(f, 2, _config.QuickMoveFolder3, s => { _config.QuickMoveFolder3 = s; _config.Save(); }), 130);
|
||||
SubscribeRightClickLeaf(ToggleLeafFavorite);
|
||||
SubscribeRightClickLeaf(RemoveTemporarySettings);
|
||||
SubscribeRightClickLeaf(DisableTemporarily);
|
||||
SubscribeRightClickLeaf(l => QuickMove(l, _config.QuickMoveFolder1, _config.QuickMoveFolder2, _config.QuickMoveFolder3));
|
||||
SubscribeRightClickMain(ClearDefaultImportFolder, 100);
|
||||
SubscribeRightClickMain(() => ClearQuickMove(0, _config.QuickMoveFolder1, () => {_config.QuickMoveFolder1 = string.Empty; _config.Save();}), 110);
|
||||
|
|
@ -194,7 +196,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
|
|||
protected override void DrawLeafName(FileSystem<Mod>.Leaf leaf, in ModState state, bool selected)
|
||||
{
|
||||
var flags = selected ? ImGuiTreeNodeFlags.Selected | LeafFlags : LeafFlags;
|
||||
using var c = ImRaii.PushColor(ImGuiCol.Text, state.Color.Value())
|
||||
using var c = ImRaii.PushColor(ImGuiCol.Text, state.Color.Tinted(state.Tint))
|
||||
.Push(ImGuiCol.HeaderHovered, 0x4000FFFF, leaf.Value.Favorite);
|
||||
using var id = ImRaii.PushId(leaf.Value.Index);
|
||||
ImRaii.TreeNode(leaf.Value.Name, flags).Dispose();
|
||||
|
|
@ -264,6 +266,23 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
|
|||
_modManager.DataEditor.ChangeModFavorite(mod.Value, !mod.Value.Favorite);
|
||||
}
|
||||
|
||||
private void RemoveTemporarySettings(FileSystem<Mod>.Leaf mod)
|
||||
{
|
||||
var tempSettings = _collectionManager.Active.Current.GetTempSettings(mod.Value.Index);
|
||||
if (tempSettings is { Lock: 0 })
|
||||
if (ImUtf8.MenuItem("Remove Temporary Settings"))
|
||||
_collectionManager.Editor.SetTemporarySettings(_collectionManager.Active.Current, mod.Value, null);
|
||||
}
|
||||
|
||||
private void DisableTemporarily(FileSystem<Mod>.Leaf mod)
|
||||
{
|
||||
var tempSettings = _collectionManager.Active.Current.GetTempSettings(mod.Value.Index);
|
||||
if (tempSettings == null || tempSettings.Lock == 0)
|
||||
if (ImUtf8.MenuItem("Disable Temporarily"))
|
||||
_collectionManager.Editor.SetTemporarySettings(_collectionManager.Active.Current, mod.Value,
|
||||
TemporaryModSettings.DefaultSettings(mod.Value, "User Context-Menu"));
|
||||
}
|
||||
|
||||
private void SetDefaultImportFolder(ModFileSystem.Folder folder)
|
||||
{
|
||||
if (!ImGui.MenuItem("Set As Default Import Folder"))
|
||||
|
|
@ -392,8 +411,6 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
|
|||
ImGuiUtil.BulletTextColored(ColorId.InheritedMod.Value(), "enabled due to inheritance from another collection.");
|
||||
ImGuiUtil.BulletTextColored(ColorId.InheritedDisabledMod.Value(), "disabled due to inheritance from another collection.");
|
||||
ImGuiUtil.BulletTextColored(ColorId.UndefinedMod.Value(), "unconfigured in all inherited collections.");
|
||||
ImGuiUtil.BulletTextColored(ColorId.NewMod.Value(),
|
||||
"newly imported during this session. Will go away when first enabling a mod or when Penumbra is reloaded.");
|
||||
ImGuiUtil.BulletTextColored(ColorId.HandledConflictMod.Value(),
|
||||
"enabled and conflicting with another enabled Mod, but on different priorities (i.e. the conflict is solved).");
|
||||
ImGuiUtil.BulletTextColored(ColorId.ConflictingMod.Value(),
|
||||
|
|
@ -501,6 +518,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
|
|||
public struct ModState
|
||||
{
|
||||
public ColorId Color;
|
||||
public ColorId Tint;
|
||||
public ModPriority Priority;
|
||||
}
|
||||
|
||||
|
|
@ -571,31 +589,31 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
|
|||
=> !_filter.IsVisible(leaf);
|
||||
|
||||
/// <summary> Only get the text color for a mod if no filters are set. </summary>
|
||||
private ColorId GetTextColor(Mod mod, ModSettings? settings, ModCollection collection)
|
||||
private (ColorId Color, ColorId Tint) GetTextColor(Mod mod, ModSettings? settings, ModCollection collection)
|
||||
{
|
||||
if (_modManager.IsNew(mod))
|
||||
return ColorId.NewMod;
|
||||
var tint = settings.IsTemporary()
|
||||
? ColorId.TemporaryModSettingsTint
|
||||
: _modManager.IsNew(mod)
|
||||
? ColorId.NewModTint
|
||||
: ColorId.NoTint;
|
||||
if (settings.IsTemporary())
|
||||
tint = ColorId.TemporaryModSettingsTint;
|
||||
|
||||
if (settings == null)
|
||||
return ColorId.UndefinedMod;
|
||||
return (ColorId.UndefinedMod, tint);
|
||||
|
||||
if (!settings.Enabled)
|
||||
return collection != _collectionManager.Active.Current
|
||||
? ColorId.InheritedDisabledMod
|
||||
: settings is TemporaryModSettings
|
||||
? ColorId.TemporaryDisabledMod
|
||||
: ColorId.DisabledMod;
|
||||
|
||||
if (settings is TemporaryModSettings)
|
||||
return ColorId.TemporaryEnabledMod;
|
||||
return (collection != _collectionManager.Active.Current
|
||||
? ColorId.InheritedDisabledMod
|
||||
: ColorId.DisabledMod, tint);
|
||||
|
||||
var conflicts = _collectionManager.Active.Current.Conflicts(mod);
|
||||
if (conflicts.Count == 0)
|
||||
return collection != _collectionManager.Active.Current ? ColorId.InheritedMod : ColorId.EnabledMod;
|
||||
return (collection != _collectionManager.Active.Current ? ColorId.InheritedMod : ColorId.EnabledMod, tint);
|
||||
|
||||
return conflicts.Any(c => !c.Solved)
|
||||
return (conflicts.Any(c => !c.Solved)
|
||||
? ColorId.ConflictingMod
|
||||
: ColorId.HandledConflictMod;
|
||||
: ColorId.HandledConflictMod, tint);
|
||||
}
|
||||
|
||||
private bool CheckStateFilters(Mod mod, ModSettings? settings, ModCollection collection, ref ModState state)
|
||||
|
|
@ -627,6 +645,15 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
|
|||
return true;
|
||||
}
|
||||
|
||||
// isNew color takes precedence before other colors.
|
||||
if (settings.IsTemporary())
|
||||
state.Tint = ColorId.TemporaryModSettingsTint;
|
||||
else if (isNew)
|
||||
state.Tint = ColorId.NewModTint;
|
||||
else
|
||||
state.Tint = ColorId.NoTint;
|
||||
|
||||
|
||||
// Handle settings.
|
||||
if (settings == null)
|
||||
{
|
||||
|
|
@ -640,9 +667,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
|
|||
{
|
||||
state.Color = collection != _collectionManager.Active.Current
|
||||
? ColorId.InheritedDisabledMod
|
||||
: settings is TemporaryModSettings
|
||||
? ColorId.TemporaryDisabledMod
|
||||
: ColorId.DisabledMod;
|
||||
: ColorId.DisabledMod;
|
||||
if (!_stateFilter.HasFlag(ModFilter.Disabled)
|
||||
|| !_stateFilter.HasFlag(ModFilter.NoConflict))
|
||||
return true;
|
||||
|
|
@ -652,10 +677,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
|
|||
if (!_stateFilter.HasFlag(ModFilter.Enabled))
|
||||
return true;
|
||||
|
||||
if (settings is TemporaryModSettings)
|
||||
state.Color = ColorId.TemporaryEnabledMod;
|
||||
|
||||
// Conflicts can only be relevant if the mod is enabled.
|
||||
// Conflicts can only be relevant if the mod is enabled.
|
||||
var conflicts = _collectionManager.Active.Current.Conflicts(mod);
|
||||
if (conflicts.Count > 0)
|
||||
{
|
||||
|
|
@ -664,14 +686,14 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
|
|||
if (!_stateFilter.HasFlag(ModFilter.UnsolvedConflict))
|
||||
return true;
|
||||
|
||||
state.Color = settings is TemporaryModSettings ? ColorId.TemporaryEnabledMod : ColorId.ConflictingMod;
|
||||
state.Color = ColorId.ConflictingMod;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_stateFilter.HasFlag(ModFilter.SolvedConflict))
|
||||
return true;
|
||||
|
||||
state.Color = settings is TemporaryModSettings ? ColorId.TemporaryEnabledMod : ColorId.HandledConflictMod;
|
||||
state.Color = ColorId.HandledConflictMod;
|
||||
}
|
||||
}
|
||||
else if (!_stateFilter.HasFlag(ModFilter.NoConflict))
|
||||
|
|
@ -680,9 +702,6 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
|
|||
}
|
||||
}
|
||||
|
||||
// isNew color takes precedence before other colors.
|
||||
if (isNew)
|
||||
state.Color = ColorId.NewMod;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -704,7 +723,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
|
|||
if (_stateFilter != ModFilterExtensions.UnfilteredStateMods)
|
||||
return CheckStateFilters(mod, settings, collection, ref state);
|
||||
|
||||
state.Color = GetTextColor(mod, settings, collection);
|
||||
(state.Color, state.Tint) = GetTextColor(mod, settings, collection);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue