mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 10:17:22 +01:00
Fixed GamePath Serialization for FileSwaps, added FileSwap Edit menu, some formatting.
This commit is contained in:
parent
7c56de8c81
commit
67415db7c0
4 changed files with 135 additions and 25 deletions
|
|
@ -20,6 +20,8 @@ namespace Penumbra.Models
|
|||
|
||||
public List< string > ChangedItems { get; set; } = new();
|
||||
|
||||
|
||||
[JsonProperty( ItemConverterType = typeof( GamePathConverter ))]
|
||||
public Dictionary< GamePath, GamePath > FileSwaps { get; } = new();
|
||||
|
||||
public Dictionary< string, OptionGroup > Groups { get; set; } = new();
|
||||
|
|
|
|||
|
|
@ -269,6 +269,12 @@ namespace Penumbra.UI
|
|||
|
||||
private void DrawFileSwapTab()
|
||||
{
|
||||
if( _editMode )
|
||||
{
|
||||
DrawFileSwapTabEdit();
|
||||
return;
|
||||
}
|
||||
|
||||
if( !Meta.FileSwaps.Any() )
|
||||
{
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -25,13 +25,13 @@ namespace Penumbra.UI
|
|||
private const char GamePathsSeparator = ';';
|
||||
|
||||
private static readonly string TooltipFilesTabEdit =
|
||||
$"{TooltipFilesTab}\n" +
|
||||
$"Red Files are replaced in another group or a different option in this group, but not contained in the current option.";
|
||||
$"{TooltipFilesTab}\n"
|
||||
+ $"Red Files are replaced in another group or a different option in this group, but not contained in the current option.";
|
||||
|
||||
private static readonly string TooltipGamePathsEdit =
|
||||
$"Enter all game paths to add or remove, separated by '{GamePathsSeparator}'.\n" +
|
||||
$"Use '{TextDefaultGamePath}' to add the original file path." +
|
||||
$"Use '{TextDefaultGamePath}-#' to skip the first # relative directories.";
|
||||
$"Enter all game paths to add or remove, separated by '{GamePathsSeparator}'.\n"
|
||||
+ $"Use '{TextDefaultGamePath}' to add the original file path."
|
||||
+ $"Use '{TextDefaultGamePath}-#' to skip the first # relative directories.";
|
||||
|
||||
private const float MultiEditBoxWidth = 300f;
|
||||
|
||||
|
|
@ -109,7 +109,8 @@ namespace Penumbra.UI
|
|||
{
|
||||
var groupName = group.GroupName;
|
||||
if( ImGuiCustom.BeginFramedGroupEdit( ref groupName )
|
||||
&& groupName != group.GroupName && !Meta!.Groups.ContainsKey( groupName ) )
|
||||
&& groupName != group.GroupName
|
||||
&& !Meta!.Groups.ContainsKey( groupName ) )
|
||||
{
|
||||
var oldConf = Mod!.Settings[ group.GroupName ];
|
||||
Meta.Groups.Remove( group.GroupName );
|
||||
|
|
@ -120,7 +121,7 @@ namespace Penumbra.UI
|
|||
{
|
||||
GroupName = groupName,
|
||||
SelectionType = SelectType.Multi,
|
||||
Options = group.Options
|
||||
Options = group.Options,
|
||||
};
|
||||
Mod.Settings[ groupName ] = oldConf;
|
||||
}
|
||||
|
|
@ -215,7 +216,7 @@ namespace Penumbra.UI
|
|||
{
|
||||
GroupName = groupName,
|
||||
Options = group.Options,
|
||||
SelectionType = SelectType.Single
|
||||
SelectionType = SelectType.Single,
|
||||
} );
|
||||
Mod.Settings[ groupName ] = oldConf;
|
||||
}
|
||||
|
|
@ -245,7 +246,7 @@ namespace Penumbra.UI
|
|||
{
|
||||
OptionName = newName,
|
||||
OptionDesc = "",
|
||||
OptionFiles = new Dictionary< RelPath, HashSet< GamePath > >()
|
||||
OptionFiles = new Dictionary< RelPath, HashSet< GamePath > >(),
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
|
@ -264,7 +265,7 @@ namespace Penumbra.UI
|
|||
group.Options[ code ] = new Option()
|
||||
{
|
||||
OptionName = newName, OptionDesc = group.Options[ code ].OptionDesc,
|
||||
OptionFiles = group.Options[ code ].OptionFiles
|
||||
OptionFiles = group.Options[ code ].OptionFiles,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -304,7 +305,7 @@ namespace Penumbra.UI
|
|||
{
|
||||
GroupName = newGroup,
|
||||
SelectionType = selectType,
|
||||
Options = new List< Option >()
|
||||
Options = new List< Option >(),
|
||||
};
|
||||
|
||||
Mod.Settings[ newGroup ] = 0;
|
||||
|
|
@ -362,6 +363,87 @@ namespace Penumbra.UI
|
|||
|
||||
DrawAddMultiGroupField();
|
||||
}
|
||||
|
||||
private void DrawFileSwapTabEdit()
|
||||
{
|
||||
const string arrow = " -> ";
|
||||
|
||||
if( ImGui.BeginTabItem( LabelFileSwapTab ) )
|
||||
{
|
||||
ImGui.SetNextItemWidth( -1 );
|
||||
if( ImGui.BeginListBox( LabelFileSwapHeader, AutoFillSize ) )
|
||||
{
|
||||
var swaps = Meta.FileSwaps.Keys.ToArray();
|
||||
|
||||
var arrowWidth = ImGui.CalcTextSize( arrow ).X;
|
||||
var width = ( ImGui.GetWindowWidth() - arrowWidth - 4 * ImGui.GetStyle().ItemSpacing.X ) / 2;
|
||||
for( var idx = 0; idx < swaps.Length + 1; ++idx )
|
||||
{
|
||||
var key = idx == swaps.Length ? GamePath.GenerateUnchecked( "" ) : swaps[ idx ];
|
||||
var value = idx == swaps.Length ? GamePath.GenerateUnchecked( "" ) : Meta.FileSwaps[ key ];
|
||||
string keyString = key;
|
||||
string valueString = value;
|
||||
|
||||
ImGui.SetNextItemWidth( width );
|
||||
if( ImGui.InputTextWithHint( $"##swapLhs_{idx}", "Enter new file to be replaced...", ref keyString,
|
||||
GamePath.MaxGamePathLength, ImGuiInputTextFlags.EnterReturnsTrue ) )
|
||||
{
|
||||
var newKey = new GamePath( keyString );
|
||||
if( newKey.CompareTo( key ) != 0 )
|
||||
{
|
||||
if( idx < swaps.Length )
|
||||
{
|
||||
Meta.FileSwaps.Remove( key );
|
||||
}
|
||||
|
||||
if( newKey != string.Empty )
|
||||
{
|
||||
Meta.FileSwaps[ newKey ] = value;
|
||||
}
|
||||
|
||||
_selector.SaveCurrentMod();
|
||||
if( Mod.Enabled )
|
||||
{
|
||||
Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( idx < swaps.Length )
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ImGui.TextUnformatted( arrow );
|
||||
ImGui.SameLine();
|
||||
|
||||
ImGui.SetNextItemWidth( width );
|
||||
if( ImGui.InputTextWithHint( $"##swapRhs_{idx}", "Enter new replacement path...", ref valueString,
|
||||
GamePath.MaxGamePathLength,
|
||||
ImGuiInputTextFlags.EnterReturnsTrue ) )
|
||||
{
|
||||
var newValue = new GamePath( valueString );
|
||||
if( newValue.CompareTo( value ) != 0 )
|
||||
{
|
||||
Meta.FileSwaps[ key ] = newValue;
|
||||
_selector.SaveCurrentMod();
|
||||
if( Mod.Enabled )
|
||||
{
|
||||
Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndListBox();
|
||||
}
|
||||
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
else
|
||||
{
|
||||
_fileSwapOffset = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Penumbra.Util
|
||||
{
|
||||
|
|
@ -29,7 +31,7 @@ namespace Penumbra.Util
|
|||
=> _path = CheckPre( file, baseDir ) ? Trim( Substring( file, baseDir ) ) : "";
|
||||
|
||||
public RelPath( GamePath gamePath )
|
||||
=> _path = gamePath ? ReplaceSlash( gamePath ) : "";
|
||||
=> _path = ReplaceSlash( gamePath );
|
||||
|
||||
private static bool CheckPre( FileInfo file, DirectoryInfo baseDir )
|
||||
=> file.FullName.StartsWith( baseDir.FullName ) && file.FullName.Length < MaxRelPathLength;
|
||||
|
|
@ -43,9 +45,6 @@ namespace Penumbra.Util
|
|||
private static string Trim( string path )
|
||||
=> path.TrimStart( '\\' );
|
||||
|
||||
public static implicit operator bool( RelPath relPath )
|
||||
=> relPath._path.Length > 0;
|
||||
|
||||
public static implicit operator string( RelPath relPath )
|
||||
=> relPath._path;
|
||||
|
||||
|
|
@ -56,9 +55,9 @@ namespace Penumbra.Util
|
|||
{
|
||||
return rhs switch
|
||||
{
|
||||
string => string.Compare( _path, _path, StringComparison.InvariantCulture ),
|
||||
string path => string.Compare( _path, path, StringComparison.InvariantCulture ),
|
||||
RelPath path => string.Compare( _path, path._path, StringComparison.InvariantCulture ),
|
||||
_ => -1
|
||||
_ => -1,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -122,9 +121,6 @@ namespace Penumbra.Util
|
|||
public static GamePath GenerateUncheckedLower( string path )
|
||||
=> new( Lower( path ), true );
|
||||
|
||||
public static implicit operator bool( GamePath gamePath )
|
||||
=> gamePath._path.Length > 0;
|
||||
|
||||
public static implicit operator string( GamePath gamePath )
|
||||
=> gamePath._path;
|
||||
|
||||
|
|
@ -143,11 +139,35 @@ namespace Penumbra.Util
|
|||
{
|
||||
string path => string.Compare( _path, path, StringComparison.InvariantCulture ),
|
||||
GamePath path => string.Compare( _path, path._path, StringComparison.InvariantCulture ),
|
||||
_ => -1
|
||||
_ => -1,
|
||||
};
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
=> _path;
|
||||
}
|
||||
|
||||
public class GamePathConverter : JsonConverter
|
||||
{
|
||||
public override bool CanConvert( Type objectType )
|
||||
=> objectType == typeof( GamePath );
|
||||
|
||||
public override object ReadJson( JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer )
|
||||
{
|
||||
var token = JToken.Load( reader );
|
||||
return token.ToObject< GamePath >();
|
||||
}
|
||||
|
||||
public override bool CanWrite
|
||||
=> true;
|
||||
|
||||
public override void WriteJson( JsonWriter writer, object? value, JsonSerializer serializer )
|
||||
{
|
||||
if( value != null )
|
||||
{
|
||||
var v = ( GamePath) value;
|
||||
serializer.Serialize( writer, v.ToString() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue