mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 10:17:22 +01:00
Introducing custom Sort Order for mods and collapsible folders inside the mod selector based on '/' in the sort order.
This commit is contained in:
parent
702e3b9305
commit
d52086b69c
7 changed files with 157 additions and 13 deletions
|
|
@ -27,6 +27,8 @@ namespace Penumbra
|
||||||
public string CurrentCollection { get; set; } = "Default";
|
public string CurrentCollection { get; set; } = "Default";
|
||||||
public string ForcedCollection { get; set; } = "";
|
public string ForcedCollection { get; set; } = "";
|
||||||
public Dictionary< string, string > CharacterCollections { get; set; } = new();
|
public Dictionary< string, string > CharacterCollections { get; set; } = new();
|
||||||
|
public Dictionary< string, string > ModSortOrder { get; set; } = new();
|
||||||
|
|
||||||
public bool InvertModListOrder { internal get; set; }
|
public bool InvertModListOrder { internal get; set; }
|
||||||
|
|
||||||
public static Configuration Load( DalamudPluginInterface pi )
|
public static Configuration Load( DalamudPluginInterface pi )
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ namespace Penumbra.Mod
|
||||||
public DirectoryInfo BasePath;
|
public DirectoryInfo BasePath;
|
||||||
public ModMeta Meta;
|
public ModMeta Meta;
|
||||||
public ModResources Resources;
|
public ModResources Resources;
|
||||||
|
public string SortOrder;
|
||||||
|
|
||||||
public FileInfo MetaFile { get; set; }
|
public FileInfo MetaFile { get; set; }
|
||||||
|
|
||||||
|
|
@ -20,6 +21,7 @@ namespace Penumbra.Mod
|
||||||
Meta = meta;
|
Meta = meta;
|
||||||
Resources = resources;
|
Resources = resources;
|
||||||
MetaFile = MetaFileInfo( basePath );
|
MetaFile = MetaFileInfo( basePath );
|
||||||
|
SortOrder = meta.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FileInfo MetaFileInfo( DirectoryInfo basePath )
|
public static FileInfo MetaFileInfo( DirectoryInfo basePath )
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ namespace Penumbra.Mods
|
||||||
|
|
||||||
public void SortMods()
|
public void SortMods()
|
||||||
{
|
{
|
||||||
AvailableMods.Sort( ( m1, m2 ) => string.Compare( m1.Data.Meta.Name, m2.Data.Meta.Name, StringComparison.InvariantCulture ) );
|
AvailableMods.Sort( ( m1, m2 ) => string.Compare( m1.Data.SortOrder, m2.Data.SortOrder, StringComparison.InvariantCultureIgnoreCase ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddFiles( Dictionary< GamePath, Mod.Mod > registeredFiles, Mod.Mod mod )
|
private void AddFiles( Dictionary< GamePath, Mod.Mod > registeredFiles, Mod.Mod mod )
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using Penumbra.Meta;
|
using Penumbra.Meta;
|
||||||
using Penumbra.Mod;
|
using Penumbra.Mod;
|
||||||
|
|
@ -12,13 +13,18 @@ namespace Penumbra.Mods
|
||||||
// It also contains the CollectionManager that handles all collections.
|
// It also contains the CollectionManager that handles all collections.
|
||||||
public class ModManager
|
public class ModManager
|
||||||
{
|
{
|
||||||
|
private readonly Plugin _plugin;
|
||||||
public DirectoryInfo BasePath { get; private set; }
|
public DirectoryInfo BasePath { get; private set; }
|
||||||
|
|
||||||
public Dictionary< string, ModData > Mods { get; } = new();
|
public Dictionary< string, ModData > Mods { get; } = new();
|
||||||
public CollectionManager Collections { get; }
|
public CollectionManager Collections { get; }
|
||||||
|
|
||||||
|
public Configuration Config
|
||||||
|
=> _plugin.Configuration;
|
||||||
|
|
||||||
public ModManager( Plugin plugin )
|
public ModManager( Plugin plugin )
|
||||||
{
|
{
|
||||||
|
_plugin = plugin;
|
||||||
BasePath = new DirectoryInfo( plugin.Configuration.ModDirectory );
|
BasePath = new DirectoryInfo( plugin.Configuration.ModDirectory );
|
||||||
Collections = new CollectionManager( plugin, this );
|
Collections = new CollectionManager( plugin, this );
|
||||||
}
|
}
|
||||||
|
|
@ -29,6 +35,28 @@ namespace Penumbra.Mods
|
||||||
DiscoverMods();
|
DiscoverMods();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetModOrders( Configuration config )
|
||||||
|
{
|
||||||
|
var changes = false;
|
||||||
|
foreach( var kvp in config.ModSortOrder.ToArray() )
|
||||||
|
{
|
||||||
|
if( Mods.TryGetValue( kvp.Key, out var mod ) )
|
||||||
|
{
|
||||||
|
mod.SortOrder = string.Join( "/", kvp.Value.Trim().Split( new[] { "/" }, StringSplitOptions.RemoveEmptyEntries ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
changes = true;
|
||||||
|
config.ModSortOrder.Remove( kvp.Key );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( changes )
|
||||||
|
{
|
||||||
|
config.Save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void DiscoverMods()
|
public void DiscoverMods()
|
||||||
{
|
{
|
||||||
Mods.Clear();
|
Mods.Clear();
|
||||||
|
|
@ -57,6 +85,7 @@ namespace Penumbra.Mods
|
||||||
Mods.Add( modFolder.Name, mod );
|
Mods.Add( modFolder.Name, mod );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetModOrders( _plugin.Configuration );
|
||||||
Collections.RecreateCaches();
|
Collections.RecreateCaches();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,36 @@ namespace Penumbra.Mods
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool ChangeSortOrder( this ModManager manager, ModData mod, string newSortOrder )
|
||||||
|
{
|
||||||
|
newSortOrder = string.Join( "/", newSortOrder.Trim().Split( new[] { "/" }, StringSplitOptions.RemoveEmptyEntries ) );
|
||||||
|
|
||||||
|
if( mod.SortOrder == newSortOrder )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( newSortOrder == string.Empty || newSortOrder == mod.Meta.Name )
|
||||||
|
{
|
||||||
|
mod.SortOrder = mod.Meta.Name;
|
||||||
|
manager.Config.ModSortOrder.Remove( mod.BasePath.Name );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mod.SortOrder = newSortOrder;
|
||||||
|
manager.Config.ModSortOrder[ mod.BasePath.Name ] = newSortOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
manager.Config.Save();
|
||||||
|
|
||||||
|
foreach( var collection in manager.Collections.Collections.Values.Where( c => c.Cache != null ) )
|
||||||
|
{
|
||||||
|
collection.Cache!.SortMods();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public static bool RenameModFolder( this ModManager manager, ModData mod, DirectoryInfo newDir, bool move = true )
|
public static bool RenameModFolder( this ModManager manager, ModData mod, DirectoryInfo newDir, bool move = true )
|
||||||
{
|
{
|
||||||
if( move )
|
if( move )
|
||||||
|
|
@ -60,6 +90,13 @@ namespace Penumbra.Mods
|
||||||
mod.MetaFile = ModData.MetaFileInfo( newDir );
|
mod.MetaFile = ModData.MetaFileInfo( newDir );
|
||||||
manager.UpdateMod( mod );
|
manager.UpdateMod( mod );
|
||||||
|
|
||||||
|
if( manager.Config.ModSortOrder.ContainsKey( oldBasePath.Name ) )
|
||||||
|
{
|
||||||
|
manager.Config.ModSortOrder[ newDir.Name ] = manager.Config.ModSortOrder[ oldBasePath.Name ];
|
||||||
|
manager.Config.ModSortOrder.Remove( oldBasePath.Name );
|
||||||
|
manager.Config.Save();
|
||||||
|
}
|
||||||
|
|
||||||
foreach( var collection in manager.Collections.Collections.Values )
|
foreach( var collection in manager.Collections.Collections.Values )
|
||||||
{
|
{
|
||||||
if( collection.Settings.TryGetValue( oldBasePath.Name, out var settings ) )
|
if( collection.Settings.TryGetValue( oldBasePath.Name, out var settings ) )
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
using System.Windows.Forms;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using Penumbra.Mod;
|
using Penumbra.Mod;
|
||||||
|
|
@ -224,6 +225,17 @@ namespace Penumbra.UI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DrawSortOrder()
|
||||||
|
{
|
||||||
|
var currentSortOrder = Mod!.Data.SortOrder;
|
||||||
|
ImGui.SetNextItemWidth( 300 );
|
||||||
|
if( ImGui.InputText( "Sort Order", ref currentSortOrder, 256, ImGuiInputTextFlags.EnterReturnsTrue ) )
|
||||||
|
{
|
||||||
|
_modManager.ChangeSortOrder( Mod.Data, currentSortOrder );
|
||||||
|
_selector.SelectModByDir( Mod.Data.BasePath.Name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void DrawEditableMark()
|
private void DrawEditableMark()
|
||||||
{
|
{
|
||||||
ImGui.Checkbox( LabelEditingEnabled, ref _editMode );
|
ImGui.Checkbox( LabelEditingEnabled, ref _editMode );
|
||||||
|
|
@ -262,7 +274,7 @@ namespace Penumbra.UI
|
||||||
{
|
{
|
||||||
ImGui.OpenPopup( LabelOverWriteDir );
|
ImGui.OpenPopup( LabelOverWriteDir );
|
||||||
}
|
}
|
||||||
else if( Service< ModManager >.Get()!.RenameModFolder( Mod.Data, newDir ) )
|
else if( _modManager.RenameModFolder( Mod.Data, newDir ) )
|
||||||
{
|
{
|
||||||
_selector.ReloadCurrentMod();
|
_selector.ReloadCurrentMod();
|
||||||
ImGui.CloseCurrentPopup();
|
ImGui.CloseCurrentPopup();
|
||||||
|
|
@ -478,6 +490,8 @@ namespace Penumbra.UI
|
||||||
DrawDeduplicateButton();
|
DrawDeduplicateButton();
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
DrawNormalizeButton();
|
DrawNormalizeButton();
|
||||||
|
|
||||||
|
DrawSortOrder();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw()
|
public void Draw()
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using System.Numerics;
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
|
using ImGuiScene;
|
||||||
using Penumbra.Importer;
|
using Penumbra.Importer;
|
||||||
using Penumbra.Mod;
|
using Penumbra.Mod;
|
||||||
using Penumbra.Mods;
|
using Penumbra.Mods;
|
||||||
|
|
@ -73,6 +74,7 @@ namespace Penumbra.UI
|
||||||
|
|
||||||
private readonly SettingsInterface _base;
|
private readonly SettingsInterface _base;
|
||||||
private readonly ModManager _modManager;
|
private readonly ModManager _modManager;
|
||||||
|
private string _currentModGroup = "";
|
||||||
|
|
||||||
private List< Mod.Mod >? Mods
|
private List< Mod.Mod >? Mods
|
||||||
=> _modManager.Collections.CurrentCollection.Cache?.AvailableMods;
|
=> _modManager.Collections.CurrentCollection.Cache?.AvailableMods;
|
||||||
|
|
@ -301,17 +303,15 @@ namespace Penumbra.UI
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool CheckFilters( Mod.Mod mod, int modIndex )
|
||||||
|
=> ( _modFilter.Length <= 0 || _modNamesLower[ modIndex ].Contains( _modFilter ) )
|
||||||
|
&& !CheckFlags( mod.Data.Resources.ModFiles.Count, ModFilter.HasNoFiles, ModFilter.HasFiles )
|
||||||
|
&& !CheckFlags( mod.Data.Meta.FileSwaps.Count, ModFilter.HasNoFileSwaps, ModFilter.HasFileSwaps )
|
||||||
|
&& !CheckFlags( mod.Data.Resources.MetaManipulations.Count, ModFilter.HasNoMetaManipulations, ModFilter.HasMetaManipulations )
|
||||||
|
&& !CheckFlags( mod.Data.Meta.HasGroupsWithConfig ? 1 : 0, ModFilter.HasNoConfig, ModFilter.HasConfig );
|
||||||
|
|
||||||
public void DrawMod( Mod.Mod mod, int modIndex )
|
public void DrawMod( Mod.Mod mod, int modIndex )
|
||||||
{
|
{
|
||||||
if( _modFilter.Length > 0 && !_modNamesLower[ modIndex ].Contains( _modFilter )
|
|
||||||
|| CheckFlags( mod.Data.Resources.ModFiles.Count, ModFilter.HasNoFiles, ModFilter.HasFiles )
|
|
||||||
|| CheckFlags( mod.Data.Meta.FileSwaps.Count, ModFilter.HasNoFileSwaps, ModFilter.HasFileSwaps )
|
|
||||||
|| CheckFlags( mod.Data.Resources.MetaManipulations.Count, ModFilter.HasNoMetaManipulations, ModFilter.HasMetaManipulations )
|
|
||||||
|| CheckFlags( mod.Data.Meta.HasGroupsWithConfig ? 1 : 0, ModFilter.HasNoConfig, ModFilter.HasConfig ) )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var changedColour = false;
|
var changedColour = false;
|
||||||
if( !mod.Settings.Enabled )
|
if( !mod.Settings.Enabled )
|
||||||
{
|
{
|
||||||
|
|
@ -372,6 +372,59 @@ namespace Penumbra.UI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool DrawModGroup( Mod.Mod mod, ref int modIndex )
|
||||||
|
{
|
||||||
|
if( !CheckFilters( mod, modIndex ) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !mod.Data.SortOrder.StartsWith( _currentModGroup ) )
|
||||||
|
{
|
||||||
|
var count = _currentModGroup.Length - 2;
|
||||||
|
var lastFolder = _currentModGroup.LastIndexOf( '/', _currentModGroup.Length - 2 );
|
||||||
|
_currentModGroup = lastFolder == -1 ? string.Empty : _currentModGroup.Substring( 0, lastFolder + 1 );
|
||||||
|
ImGui.TreePop();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var nextFolder = mod.Data.SortOrder.IndexOf( '/', _currentModGroup.Length );
|
||||||
|
if( nextFolder == -1 )
|
||||||
|
{
|
||||||
|
DrawMod( mod, modIndex );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var mods = Mods!;
|
||||||
|
var folderLabel =
|
||||||
|
$"{mod.Data.SortOrder.Substring( _currentModGroup.Length, nextFolder - _currentModGroup.Length )}##{modIndex}_{_currentModGroup.Length}";
|
||||||
|
_currentModGroup = mod.Data.SortOrder.Substring( 0, nextFolder + 1 );
|
||||||
|
if( ImGui.TreeNodeEx( folderLabel ) )
|
||||||
|
{
|
||||||
|
for( ; modIndex < mods.Count; ++modIndex )
|
||||||
|
{
|
||||||
|
if( !DrawModGroup( mods[ modIndex ], ref modIndex ) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ImGui.TreePush();
|
||||||
|
for( ; modIndex < mods.Count; ++modIndex )
|
||||||
|
{
|
||||||
|
if( !mods[ modIndex ].Data.SortOrder.StartsWith( _currentModGroup ) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public void Draw()
|
public void Draw()
|
||||||
{
|
{
|
||||||
if( Mods == null )
|
if( Mods == null )
|
||||||
|
|
@ -387,11 +440,18 @@ namespace Penumbra.UI
|
||||||
// Inlay selector list
|
// Inlay selector list
|
||||||
ImGui.BeginChild( LabelSelectorList, new Vector2( SelectorPanelWidth, -ImGui.GetFrameHeightWithSpacing() ), true );
|
ImGui.BeginChild( LabelSelectorList, new Vector2( SelectorPanelWidth, -ImGui.GetFrameHeightWithSpacing() ), true );
|
||||||
|
|
||||||
for( var modIndex = 0; modIndex < Mods.Count; modIndex++ )
|
ImGui.PushStyleVar( ImGuiStyleVar.IndentSpacing, 10 );
|
||||||
|
for( var modIndex = 0; modIndex < Mods!.Count; )
|
||||||
{
|
{
|
||||||
DrawMod( Mods[ modIndex ], modIndex );
|
if( DrawModGroup( Mods[ modIndex ], ref modIndex ) )
|
||||||
|
{
|
||||||
|
++modIndex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui.PopStyleVar();
|
||||||
|
|
||||||
|
|
||||||
ImGui.EndChild();
|
ImGui.EndChild();
|
||||||
|
|
||||||
DrawModsSelectorButtons();
|
DrawModsSelectorButtons();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue