mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 10:17:22 +01:00
Let options keep visual ordering.
This commit is contained in:
parent
f24ec8ebe2
commit
81e93e0664
9 changed files with 105 additions and 28 deletions
|
|
@ -12,6 +12,7 @@
|
|||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Nullable>enable</Nullable>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
|
|
@ -43,6 +44,8 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3"/>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3">
|
||||
<Private>false</Private>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -173,7 +173,8 @@ public partial class TexToolsImporter
|
|||
++_currentOptionIdx;
|
||||
}
|
||||
|
||||
Mod.CreateOptionGroup( _currentModDirectory, group, groupPriority++, description.ToString(), options );
|
||||
Mod.CreateOptionGroup( _currentModDirectory, group, groupPriority, groupPriority, description.ToString(), options );
|
||||
++groupPriority;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ public sealed partial class Mod
|
|||
return;
|
||||
}
|
||||
|
||||
group.DeleteFile( mod.BasePath );
|
||||
group.DeleteFile( mod.BasePath, groupIdx );
|
||||
|
||||
var _ = group switch
|
||||
{
|
||||
|
|
@ -86,7 +86,7 @@ public sealed partial class Mod
|
|||
{
|
||||
var group = mod._groups[ groupIdx ];
|
||||
mod._groups.RemoveAt( groupIdx );
|
||||
group.DeleteFile( mod.BasePath );
|
||||
group.DeleteFile( mod.BasePath, groupIdx );
|
||||
ModOptionChanged.Invoke( ModOptionChangeType.GroupDeleted, mod, groupIdx, -1, -1 );
|
||||
}
|
||||
|
||||
|
|
@ -400,19 +400,32 @@ public sealed partial class Mod
|
|||
private static void OnModOptionChange( ModOptionChangeType type, Mod mod, int groupIdx, int _, int _2 )
|
||||
{
|
||||
// File deletion is handled in the actual function.
|
||||
if( type != ModOptionChangeType.GroupDeleted )
|
||||
if( type is ModOptionChangeType.GroupDeleted or ModOptionChangeType.GroupMoved )
|
||||
{
|
||||
IModGroup.SaveModGroup( mod._groups[ groupIdx ], mod.BasePath );
|
||||
mod.SaveAllGroups();
|
||||
}
|
||||
else
|
||||
{
|
||||
IModGroup.SaveModGroup( mod._groups[ groupIdx ], mod.BasePath, groupIdx );
|
||||
}
|
||||
|
||||
// State can not change on adding groups, as they have no immediate options.
|
||||
mod.HasOptions = type switch
|
||||
var unused = type switch
|
||||
{
|
||||
ModOptionChangeType.GroupDeleted => mod.HasOptions = mod.Groups.Any( o => o.IsOption ),
|
||||
ModOptionChangeType.GroupAdded => mod.SetCounts(),
|
||||
ModOptionChangeType.GroupDeleted => mod.SetCounts(),
|
||||
ModOptionChangeType.GroupMoved => false,
|
||||
ModOptionChangeType.GroupTypeChanged => mod.HasOptions = mod.Groups.Any( o => o.IsOption ),
|
||||
ModOptionChangeType.OptionAdded => mod.HasOptions |= mod._groups[ groupIdx ].IsOption,
|
||||
ModOptionChangeType.OptionDeleted => mod.HasOptions = mod.Groups.Any( o => o.IsOption ),
|
||||
_ => mod.HasOptions,
|
||||
ModOptionChangeType.PriorityChanged => false,
|
||||
ModOptionChangeType.OptionAdded => mod.SetCounts(),
|
||||
ModOptionChangeType.OptionDeleted => mod.SetCounts(),
|
||||
ModOptionChangeType.OptionMoved => false,
|
||||
ModOptionChangeType.OptionFilesChanged => 0 < ( mod.TotalFileCount = mod.AllSubMods.Sum( s => s.Files.Count ) ),
|
||||
ModOptionChangeType.OptionSwapsChanged => 0 < ( mod.TotalSwapCount = mod.AllSubMods.Sum( s => s.FileSwaps.Count ) ),
|
||||
ModOptionChangeType.OptionMetaChanged => 0 < ( mod.TotalManipulations = mod.AllSubMods.Sum( s => s.Manipulations.Count ) ),
|
||||
ModOptionChangeType.OptionUpdated => mod.SetCounts(),
|
||||
ModOptionChangeType.DisplayChange => false,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ public partial class Mod
|
|||
|
||||
// Create a file for an option group from given data.
|
||||
internal static void CreateOptionGroup( DirectoryInfo baseFolder, ModGroup groupData,
|
||||
int priority, string desc, IEnumerable< ISubMod > subMods )
|
||||
int priority, int index, string desc, IEnumerable< ISubMod > subMods )
|
||||
{
|
||||
switch( groupData.SelectionType )
|
||||
{
|
||||
|
|
@ -72,7 +72,7 @@ public partial class Mod
|
|||
Priority = priority,
|
||||
};
|
||||
group.PrioritizedOptions.AddRange( subMods.OfType< SubMod >().Select( ( s, idx ) => ( s, idx ) ) );
|
||||
IModGroup.SaveModGroup( group, baseFolder );
|
||||
IModGroup.SaveModGroup( group, baseFolder, index );
|
||||
break;
|
||||
}
|
||||
case SelectType.Single:
|
||||
|
|
@ -84,7 +84,7 @@ public partial class Mod
|
|||
Priority = priority,
|
||||
};
|
||||
group.OptionData.AddRange( subMods.OfType< SubMod >() );
|
||||
IModGroup.SaveModGroup( group, baseFolder );
|
||||
IModGroup.SaveModGroup( group, baseFolder, index );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,12 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Dalamud.Logging;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Penumbra.GameData.ByteString;
|
||||
using Penumbra.Meta.Manipulations;
|
||||
using Penumbra.Util;
|
||||
|
||||
namespace Penumbra.Mods;
|
||||
|
||||
|
|
@ -25,7 +27,7 @@ public partial class Mod
|
|||
public int TotalManipulations { get; private set; }
|
||||
public bool HasOptions { get; private set; }
|
||||
|
||||
private void SetCounts()
|
||||
private bool SetCounts()
|
||||
{
|
||||
TotalFileCount = 0;
|
||||
TotalSwapCount = 0;
|
||||
|
|
@ -40,6 +42,7 @@ public partial class Mod
|
|||
HasOptions = _groups.Any( o
|
||||
=> o is MultiModGroup m && m.PrioritizedOptions.Count > 0
|
||||
|| o is SingleModGroup s && s.OptionData.Count > 1 );
|
||||
return true;
|
||||
}
|
||||
|
||||
public IEnumerable< ISubMod > AllSubMods
|
||||
|
|
@ -114,4 +117,29 @@ public partial class Mod
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delete all existing group files and save them anew.
|
||||
// Used when indices change in complex ways.
|
||||
private void SaveAllGroups()
|
||||
{
|
||||
foreach( var file in GroupFiles )
|
||||
{
|
||||
try
|
||||
{
|
||||
if( file.Exists )
|
||||
{
|
||||
file.Delete();
|
||||
}
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
PluginLog.Error( $"Could not delete outdated group file {file}:\n{e}" );
|
||||
}
|
||||
}
|
||||
|
||||
foreach( var (group, index) in _groups.WithIndex() )
|
||||
{
|
||||
IModGroup.SaveModGroup( group, BasePath, index );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,10 +2,12 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Dalamud.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Penumbra.GameData.ByteString;
|
||||
using Penumbra.Util;
|
||||
|
||||
namespace Penumbra.Mods;
|
||||
|
||||
|
|
@ -14,7 +16,36 @@ public sealed partial class Mod
|
|||
private static class Migration
|
||||
{
|
||||
public static bool Migrate( Mod mod, JObject json )
|
||||
=> MigrateV0ToV1( mod, json );
|
||||
=> MigrateV0ToV1( mod, json ) || MigrateV1ToV2( mod );
|
||||
|
||||
private static bool MigrateV1ToV2( Mod mod )
|
||||
{
|
||||
if( mod.FileVersion > 1 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach( var (group, index) in mod.GroupFiles.WithIndex().ToArray() )
|
||||
{
|
||||
var newName = Regex.Replace( group.Name, "^group_", $"group_{index + 1:D3}_", RegexOptions.Compiled );
|
||||
try
|
||||
{
|
||||
if( newName != group.Name )
|
||||
{
|
||||
group.MoveTo( Path.Combine( group.DirectoryName ?? string.Empty, newName ), false );
|
||||
}
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
PluginLog.Error( $"Could not rename group file {group.Name} to {newName} during migration:\n{e}" );
|
||||
}
|
||||
}
|
||||
|
||||
mod.FileVersion = 2;
|
||||
mod.SaveMeta();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool MigrateV0ToV1( Mod mod, JObject json )
|
||||
{
|
||||
|
|
@ -50,9 +81,9 @@ public sealed partial class Mod
|
|||
}
|
||||
|
||||
mod._default.IncorporateMetaChanges( mod.BasePath, true );
|
||||
foreach( var group in mod.Groups )
|
||||
foreach( var (group, index) in mod.Groups.WithIndex() )
|
||||
{
|
||||
IModGroup.SaveModGroup( group, mod.BasePath );
|
||||
IModGroup.SaveModGroup( group, mod.BasePath, index );
|
||||
}
|
||||
|
||||
// Delete meta files.
|
||||
|
|
|
|||
|
|
@ -34,12 +34,12 @@ public interface IModGroup : IEnumerable< ISubMod >
|
|||
_ => false,
|
||||
};
|
||||
|
||||
public string FileName( DirectoryInfo basePath )
|
||||
=> Path.Combine( basePath.FullName, $"group_{Name.RemoveInvalidPathSymbols().ToLowerInvariant()}.json" );
|
||||
public string FileName( DirectoryInfo basePath, int groupIdx )
|
||||
=> Path.Combine( basePath.FullName, $"group_{groupIdx + 1:D3}_{Name.RemoveInvalidPathSymbols().ToLowerInvariant()}.json" );
|
||||
|
||||
public void DeleteFile( DirectoryInfo basePath )
|
||||
public void DeleteFile( DirectoryInfo basePath, int groupIdx )
|
||||
{
|
||||
var file = FileName( basePath );
|
||||
var file = FileName( basePath, groupIdx );
|
||||
if( !File.Exists( file ) )
|
||||
{
|
||||
return;
|
||||
|
|
@ -48,7 +48,7 @@ public interface IModGroup : IEnumerable< ISubMod >
|
|||
try
|
||||
{
|
||||
File.Delete( file );
|
||||
PluginLog.Debug( "Deleted group file {File:l} for {GroupName:l}.", file, Name );
|
||||
PluginLog.Debug( "Deleted group file {File:l} for group {GroupIdx}: {GroupName:l}.", file, groupIdx + 1, Name );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
|
|
@ -57,9 +57,9 @@ public interface IModGroup : IEnumerable< ISubMod >
|
|||
}
|
||||
}
|
||||
|
||||
public static void SaveModGroup( IModGroup group, DirectoryInfo basePath )
|
||||
public static void SaveModGroup( IModGroup group, DirectoryInfo basePath, int groupIdx )
|
||||
{
|
||||
var file = group.FileName( basePath );
|
||||
var file = group.FileName( basePath, groupIdx );
|
||||
using var s = File.Exists( file ) ? File.Open( file, FileMode.Truncate ) : File.Open( file, FileMode.CreateNew );
|
||||
using var writer = new StreamWriter( s );
|
||||
using var j = new JsonTextWriter( writer ) { Formatting = Formatting.Indented };
|
||||
|
|
@ -82,7 +82,7 @@ public interface IModGroup : IEnumerable< ISubMod >
|
|||
|
||||
j.WriteEndArray();
|
||||
j.WriteEndObject();
|
||||
PluginLog.Debug( "Saved group file {File:l} for {GroupName:l}.", file, group.Name );
|
||||
PluginLog.Debug( "Saved group file {File:l} for group {GroupIdx}: {GroupName:l}.", file, groupIdx + 1, group.Name );
|
||||
}
|
||||
|
||||
public IModGroup Convert( SelectType type );
|
||||
|
|
|
|||
|
|
@ -259,7 +259,7 @@ public partial class ConfigWindow
|
|||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
var fileName = group.FileName( _mod.BasePath );
|
||||
var fileName = group.FileName( _mod.BasePath, groupIdx );
|
||||
var fileExists = File.Exists( fileName );
|
||||
tt = fileExists
|
||||
? $"Open the {group.Name} json file in the text editor of your choice."
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ public partial class ConfigWindow
|
|||
DrawSingleGroup( _mod.Groups[ idx ], idx );
|
||||
}
|
||||
|
||||
ImGui.Dummy( _window._defaultSpace );
|
||||
for( var idx = 0; idx < _mod.Groups.Count; ++idx )
|
||||
{
|
||||
DrawMultiGroup( _mod.Groups[ idx ], idx );
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue