diff --git a/Penumbra/Import/TexToolsImporter.ModPack.cs b/Penumbra/Import/TexToolsImporter.ModPack.cs index ca8eb492..71760187 100644 --- a/Penumbra/Import/TexToolsImporter.ModPack.cs +++ b/Penumbra/Import/TexToolsImporter.ModPack.cs @@ -173,7 +173,6 @@ public partial class TexToolsImporter { var name = numGroups == 1 ? _currentGroupName : $"{_currentGroupName}, Part {groupId + 1}"; options.Clear(); - var description = new StringBuilder(); var groupFolder = Mod.NewSubFolderName( _currentModDirectory, name ) ?? new DirectoryInfo( Path.Combine( _currentModDirectory.FullName, numGroups == 1 ? $"Group {groupPriority + 1}" : $"Group {groupPriority + 1}, Part {groupId + 1}" ) ); @@ -188,12 +187,6 @@ public partial class TexToolsImporter ?? new DirectoryInfo( Path.Combine( groupFolder.FullName, $"Option {i + optionIdx + 1}" ) ); ExtractSimpleModList( optionFolder, option.ModsJsons ); options.Add( Mod.CreateSubMod( _currentModDirectory, optionFolder, option ) ); - description.Append( option.Description ); - if( !string.IsNullOrEmpty( option.Description ) ) - { - description.Append( '\n' ); - } - if( option.IsChecked ) { defaultSettings = group.SelectionType == GroupType.Multi @@ -220,7 +213,7 @@ public partial class TexToolsImporter } Mod.CreateOptionGroup( _currentModDirectory, group.SelectionType, name, groupPriority, groupPriority, - defaultSettings ?? 0, description.ToString(), options ); + defaultSettings ?? 0, string.Empty, options ); ++groupPriority; } } diff --git a/Penumbra/Mods/Manager/Mod.Manager.Options.cs b/Penumbra/Mods/Manager/Mod.Manager.Options.cs index 82e171eb..1887c490 100644 --- a/Penumbra/Mods/Manager/Mod.Manager.Options.cs +++ b/Penumbra/Mods/Manager/Mod.Manager.Options.cs @@ -124,6 +124,23 @@ public sealed partial class Mod ModOptionChanged.Invoke( ModOptionChangeType.DisplayChange, mod, groupIdx, -1, -1 ); } + public void ChangeOptionDescription( Mod mod, int groupIdx, int optionIdx, string newDescription ) + { + var group = mod._groups[ groupIdx ]; + var option = group[ optionIdx ]; + if( option.Description == newDescription ) + { + return; + } + + var _ = option switch + { + SubMod s => s.Description = newDescription, + }; + + ModOptionChanged.Invoke( ModOptionChangeType.DisplayChange, mod, groupIdx, optionIdx, -1 ); + } + public void ChangeGroupPriority( Mod mod, int groupIdx, int newPriority ) { var group = mod._groups[ groupIdx ]; diff --git a/Penumbra/Mods/Mod.Creation.cs b/Penumbra/Mods/Mod.Creation.cs index 40cc9d2f..69adbeef 100644 --- a/Penumbra/Mods/Mod.Creation.cs +++ b/Penumbra/Mods/Mod.Creation.cs @@ -116,6 +116,7 @@ public partial class Mod var mod = new SubMod( null! ) // Mod is irrelevant here, only used for saving. { Name = option.Name, + Description = option.Description, }; foreach( var (_, gamePath, file) in list ) { diff --git a/Penumbra/Mods/Subclasses/ISubMod.cs b/Penumbra/Mods/Subclasses/ISubMod.cs index 89bf2053..2693fcad 100644 --- a/Penumbra/Mods/Subclasses/ISubMod.cs +++ b/Penumbra/Mods/Subclasses/ISubMod.cs @@ -10,6 +10,7 @@ public interface ISubMod { public string Name { get; } public string FullName { get; } + public string Description { get; } public IReadOnlyDictionary< Utf8GamePath, FullPath > Files { get; } public IReadOnlyDictionary< Utf8GamePath, FullPath > FileSwaps { get; } @@ -22,6 +23,8 @@ public interface ISubMod j.WriteStartObject(); j.WritePropertyName( nameof( Name ) ); j.WriteValue( mod.Name ); + j.WritePropertyName( nameof(Description) ); + j.WriteValue( mod.Description ); if( priority != null ) { j.WritePropertyName( nameof( IModGroup.Priority ) ); diff --git a/Penumbra/Mods/Subclasses/Mod.Files.SubMod.cs b/Penumbra/Mods/Subclasses/Mod.Files.SubMod.cs index 80c35d0f..ed0fd1fb 100644 --- a/Penumbra/Mods/Subclasses/Mod.Files.SubMod.cs +++ b/Penumbra/Mods/Subclasses/Mod.Files.SubMod.cs @@ -107,6 +107,8 @@ public partial class Mod public string FullName => GroupIdx < 0 ? "Default Option" : $"{ParentMod.Groups[ GroupIdx ].Name}: {Name}"; + public string Description { get; set; } = string.Empty; + internal IMod ParentMod { get; private init; } internal int GroupIdx { get; private set; } internal int OptionIdx { get; private set; } @@ -143,8 +145,9 @@ public partial class Mod ManipulationData.Clear(); // Every option has a name, but priorities are only relevant for multi group options. - Name = json[ nameof( ISubMod.Name ) ]?.ToObject< string >() ?? string.Empty; - priority = json[ nameof( IModGroup.Priority ) ]?.ToObject< int >() ?? 0; + Name = json[ nameof( ISubMod.Name ) ]?.ToObject< string >() ?? string.Empty; + Description = json[ nameof( ISubMod.Description ) ]?.ToObject< string >() ?? string.Empty; + priority = json[ nameof( IModGroup.Priority ) ]?.ToObject< int >() ?? 0; var files = ( JObject? )json[ nameof( Files ) ]; if( files != null ) diff --git a/Penumbra/UI/ConfigWindow.ModPanel.Edit.cs b/Penumbra/UI/ConfigWindow.ModPanel.Edit.cs index d05d1ab2..951b0200 100644 --- a/Penumbra/UI/ConfigWindow.ModPanel.Edit.cs +++ b/Penumbra/UI/ConfigWindow.ModPanel.Edit.cs @@ -301,16 +301,18 @@ public partial class ConfigWindow // Open a popup to edit a multi-line mod or option description. private static class DescriptionEdit { - private const string PopupName = "Edit Description"; - private static string _newDescription = string.Empty; - private static int _newDescriptionIdx = -1; + private const string PopupName = "Edit Description"; + private static string _newDescription = string.Empty; + private static int _newDescriptionIdx = -1; + private static int _newDesriptionOptionIdx = -1; private static Mod? _mod; - public static void OpenPopup( Mod mod, int groupIdx ) + public static void OpenPopup( Mod mod, int groupIdx, int optionIdx = -1 ) { - _newDescriptionIdx = groupIdx; - _newDescription = groupIdx < 0 ? mod.Description : mod.Groups[ groupIdx ].Description; - _mod = mod; + _newDescriptionIdx = groupIdx; + _newDesriptionOptionIdx = optionIdx; + _newDescription = groupIdx < 0 ? mod.Description : optionIdx < 0 ? mod.Groups[ groupIdx ].Description : mod.Groups[ groupIdx ][ optionIdx ].Description; + _mod = mod; ImGui.OpenPopup( PopupName ); } @@ -355,7 +357,14 @@ public partial class ConfigWindow Penumbra.ModManager.ChangeModDescription( _mod.Index, _newDescription ); break; case >= 0: - Penumbra.ModManager.ChangeGroupDescription( _mod, _newDescriptionIdx, _newDescription ); + if( _newDesriptionOptionIdx < 0 ) + { + Penumbra.ModManager.ChangeGroupDescription( _mod, _newDescriptionIdx, _newDescription ); + } + else + { + Penumbra.ModManager.ChangeOptionDescription( _mod, _newDescriptionIdx, _newDesriptionOptionIdx, _newDescription ); + } break; } @@ -468,7 +477,7 @@ public partial class ConfigWindow public static void Draw( ModPanel panel, int groupIdx ) { - using var table = ImRaii.Table( string.Empty, 5, ImGuiTableFlags.SizingFixedFit ); + using var table = ImRaii.Table( string.Empty, 6, ImGuiTableFlags.SizingFixedFit ); if( !table ) { return; @@ -478,6 +487,7 @@ public partial class ConfigWindow ImGui.TableSetupColumn( "default", ImGuiTableColumnFlags.WidthFixed, ImGui.GetFrameHeight() ); ImGui.TableSetupColumn( "name", ImGuiTableColumnFlags.WidthFixed, panel._window._inputTextWidth.X - 68 * ImGuiHelpers.GlobalScale - ImGui.GetFrameHeight() ); + ImGui.TableSetupColumn( "description", ImGuiTableColumnFlags.WidthFixed, panel._window._iconButtonSize.X ); ImGui.TableSetupColumn( "delete", ImGuiTableColumnFlags.WidthFixed, panel._window._iconButtonSize.X ); ImGui.TableSetupColumn( "priority", ImGuiTableColumnFlags.WidthFixed, 50 * ImGuiHelpers.GlobalScale ); @@ -532,6 +542,11 @@ public partial class ConfigWindow Penumbra.ModManager.RenameOption( panel._mod, groupIdx, optionIdx, newOptionName ); } + ImGui.TableNextColumn(); + if( ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.Edit.ToIconString(), panel._window._iconButtonSize, "Edit option description.", false, true ) ) + { + panel._delayedActions.Enqueue( () => DescriptionEdit.OpenPopup( panel._mod, groupIdx, optionIdx ) ); + } ImGui.TableNextColumn(); if( ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.Trash.ToIconString(), panel._window._iconButtonSize, "Delete this option.\nHold Control while clicking to delete.", !ImGui.GetIO().KeyCtrl, true ) ) diff --git a/Penumbra/UI/ConfigWindow.ModPanel.Settings.cs b/Penumbra/UI/ConfigWindow.ModPanel.Settings.cs index 7b19243d..32735bc0 100644 --- a/Penumbra/UI/ConfigWindow.ModPanel.Settings.cs +++ b/Penumbra/UI/ConfigWindow.ModPanel.Settings.cs @@ -1,6 +1,7 @@ using System.Linq; using System.Numerics; using Dalamud.Interface; +using Dalamud.Interface.Components; using ImGuiNET; using OtterGui; using OtterGui.Classes; @@ -179,6 +180,12 @@ public partial class ConfigWindow Penumbra.CollectionManager.Current.SetModSetting( _mod.Index, groupIdx, ( uint )idx2 ); } + if( !string.IsNullOrEmpty( group[ idx2 ].Description ) ) + { + ImGui.SameLine(); + ImGuiComponents.HelpMarker(group[idx2].Description); + } + id.Pop(); } } @@ -213,6 +220,12 @@ public partial class ConfigWindow Penumbra.CollectionManager.Current.SetModSetting( _mod.Index, groupIdx, flags ); } + if( !string.IsNullOrEmpty( group[ idx2 ].Description ) ) + { + ImGui.SameLine(); + ImGuiComponents.HelpMarker(group[idx2].Description); + } + id.Pop(); }