mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
temp
This commit is contained in:
parent
33db156544
commit
8db54ef4f4
17 changed files with 546 additions and 212 deletions
2
OtterGui
2
OtterGui
|
|
@ -1 +1 @@
|
||||||
Subproject commit a78f17dd1bc4cbe7e9d6c04af828ff1adac4bd6f
|
Subproject commit baee502862a5e8cdfa407f703ce98abad5cc623b
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Penumbra.Mods;
|
using Penumbra.Mods;
|
||||||
|
|
||||||
namespace Penumbra.Collections;
|
namespace Penumbra.Collections;
|
||||||
|
|
@ -6,10 +8,12 @@ namespace Penumbra.Collections;
|
||||||
// Different types a mod setting can change:
|
// Different types a mod setting can change:
|
||||||
public enum ModSettingChange
|
public enum ModSettingChange
|
||||||
{
|
{
|
||||||
Inheritance, // it was set to inherit from other collections or not inherit anymore
|
Inheritance, // it was set to inherit from other collections or not inherit anymore
|
||||||
EnableState, // it was enabled or disabled
|
EnableState, // it was enabled or disabled
|
||||||
Priority, // its priority was changed
|
Priority, // its priority was changed
|
||||||
Setting, // a specific setting was changed
|
Setting, // a specific setting was changed
|
||||||
|
MultiInheritance, // multiple mods were set to inherit from other collections or not inherit anymore.
|
||||||
|
MultiEnableState, // multiple mods were enabled or disabled at once.
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class ModCollection
|
public partial class ModCollection
|
||||||
|
|
@ -28,7 +32,7 @@ public partial class ModCollection
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the enabled state mod idx to newValue if it differs from the current priority.
|
// Set the enabled state mod idx to newValue if it differs from the current enabled state.
|
||||||
// If mod idx is currently inherited, stop the inheritance.
|
// If mod idx is currently inherited, stop the inheritance.
|
||||||
public void SetModState( int idx, bool newValue )
|
public void SetModState( int idx, bool newValue )
|
||||||
{
|
{
|
||||||
|
|
@ -41,6 +45,37 @@ public partial class ModCollection
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable or disable the mod inheritance of every mod in mods.
|
||||||
|
public void SetMultipleModInheritances( IEnumerable< Mod > mods, bool inherit )
|
||||||
|
{
|
||||||
|
if( mods.Aggregate( false, ( current, mod ) => current | FixInheritance( mod.Index, inherit ) ) )
|
||||||
|
{
|
||||||
|
ModSettingChanged.Invoke( ModSettingChange.MultiInheritance, -1, -1, null, false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the enabled state of every mod in mods to the new value.
|
||||||
|
// If the mod is currently inherited, stop the inheritance.
|
||||||
|
public void SetMultipleModStates( IEnumerable< Mod > mods, bool newValue )
|
||||||
|
{
|
||||||
|
var changes = false;
|
||||||
|
foreach( var mod in mods )
|
||||||
|
{
|
||||||
|
var oldValue = _settings[ mod.Index ]?.Enabled ?? this[ mod.Index ].Settings?.Enabled ?? false;
|
||||||
|
if( newValue != oldValue )
|
||||||
|
{
|
||||||
|
FixInheritance( mod.Index, false );
|
||||||
|
_settings[ mod.Index ]!.Enabled = newValue;
|
||||||
|
changes = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( changes )
|
||||||
|
{
|
||||||
|
ModSettingChanged.Invoke( ModSettingChange.MultiEnableState, -1, -1, null, false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set the priority of mod idx to newValue if it differs from the current priority.
|
// Set the priority of mod idx to newValue if it differs from the current priority.
|
||||||
// If mod idx is currently inherited, stop the inheritance.
|
// If mod idx is currently inherited, stop the inheritance.
|
||||||
public void SetModPriority( int idx, int newValue )
|
public void SetModPriority( int idx, int newValue )
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ using System.IO;
|
||||||
using Dalamud.Logging;
|
using Dalamud.Logging;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Penumbra.Util;
|
using OtterGui;
|
||||||
|
|
||||||
namespace Penumbra.Mods;
|
namespace Penumbra.Mods;
|
||||||
|
|
||||||
|
|
|
||||||
39
Penumbra/Mods/ModFileSystemA.cs
Normal file
39
Penumbra/Mods/ModFileSystemA.cs
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
using System.IO;
|
||||||
|
using OtterGui.Filesystem;
|
||||||
|
|
||||||
|
namespace Penumbra.Mods;
|
||||||
|
|
||||||
|
public sealed class ModFileSystemA : FileSystem< Mod >
|
||||||
|
{
|
||||||
|
public void Save()
|
||||||
|
=> SaveToFile( new FileInfo( Mod.Manager.SortOrderFile ), SaveMod, true );
|
||||||
|
|
||||||
|
public static ModFileSystemA Load()
|
||||||
|
{
|
||||||
|
var x = new ModFileSystemA();
|
||||||
|
if( x.Load( new FileInfo( Mod.Manager.SortOrderFile ), Penumbra.ModManager.Mods, ModToIdentifier, ModToName ) )
|
||||||
|
{
|
||||||
|
x.Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
x.Changed += ( _1, _2, _3, _4 ) => x.Save();
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ModToIdentifier( Mod mod )
|
||||||
|
=> mod.BasePath.Name;
|
||||||
|
|
||||||
|
private static string ModToName( Mod mod )
|
||||||
|
=> mod.Meta.Name.Text;
|
||||||
|
|
||||||
|
private static (string, bool) SaveMod( Mod mod, string fullPath )
|
||||||
|
{
|
||||||
|
if( fullPath == ModToName( mod ) )
|
||||||
|
{
|
||||||
|
return ( string.Empty, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
return ( ModToIdentifier( mod ), true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ using System.Linq;
|
||||||
using Dalamud.Logging;
|
using Dalamud.Logging;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
using OtterGui;
|
||||||
using Penumbra.GameData.ByteString;
|
using Penumbra.GameData.ByteString;
|
||||||
using Penumbra.Util;
|
using Penumbra.Util;
|
||||||
|
|
||||||
|
|
|
||||||
10
Penumbra/UI/Colors.cs
Normal file
10
Penumbra/UI/Colors.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
namespace Penumbra.UI;
|
||||||
|
|
||||||
|
public static class Colors
|
||||||
|
{
|
||||||
|
public const uint DefaultTextColor = 0xFFFFFFFFu;
|
||||||
|
public const uint NewModColor = 0xFF66DD66u;
|
||||||
|
public const uint DisabledModColor = 0xFF666666u;
|
||||||
|
public const uint ConflictingModColor = 0xFFAAAAFFu;
|
||||||
|
public const uint HandledConflictModColor = 0xFF88DDDDu;
|
||||||
|
}
|
||||||
330
Penumbra/UI/MenuTabs/ModFileSystemSelector.cs
Normal file
330
Penumbra/UI/MenuTabs/ModFileSystemSelector.cs
Normal file
|
|
@ -0,0 +1,330 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Numerics;
|
||||||
|
using Dalamud.Interface;
|
||||||
|
using ImGuiNET;
|
||||||
|
using OtterGui;
|
||||||
|
using OtterGui.Filesystem;
|
||||||
|
using OtterGui.FileSystem.Selector;
|
||||||
|
using OtterGui.Raii;
|
||||||
|
using Penumbra.Collections;
|
||||||
|
using Penumbra.Mods;
|
||||||
|
|
||||||
|
namespace Penumbra.UI;
|
||||||
|
|
||||||
|
public sealed class ModFileSystemSelector : FileSystemSelector< Mod, ModState >
|
||||||
|
{
|
||||||
|
private readonly IReadOnlySet< Mod > _newMods = new HashSet<Mod>();
|
||||||
|
private LowerString _modFilter = LowerString.Empty;
|
||||||
|
private LowerString _modFilterAuthor = LowerString.Empty;
|
||||||
|
private LowerString _modFilterChanges = LowerString.Empty;
|
||||||
|
private LowerString _modFilterName = LowerString.Empty;
|
||||||
|
private ModFilter _stateFilter = ModFilterExtensions.UnfilteredStateMods;
|
||||||
|
|
||||||
|
public ModFilter StateFilter
|
||||||
|
{
|
||||||
|
get => _stateFilter;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
var diff = _stateFilter != value;
|
||||||
|
_stateFilter = value;
|
||||||
|
if( diff )
|
||||||
|
{
|
||||||
|
SetFilterDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool ChangeFilter( string filterValue )
|
||||||
|
{
|
||||||
|
if( filterValue.StartsWith( "c:", StringComparison.InvariantCultureIgnoreCase ) )
|
||||||
|
{
|
||||||
|
_modFilterChanges = new LowerString( filterValue[ 2.. ] );
|
||||||
|
_modFilter = LowerString.Empty;
|
||||||
|
_modFilterAuthor = LowerString.Empty;
|
||||||
|
_modFilterName = LowerString.Empty;
|
||||||
|
}
|
||||||
|
else if( filterValue.StartsWith( "a:", StringComparison.InvariantCultureIgnoreCase ) )
|
||||||
|
{
|
||||||
|
_modFilterAuthor = new LowerString( filterValue[ 2.. ] );
|
||||||
|
_modFilter = LowerString.Empty;
|
||||||
|
_modFilterChanges = LowerString.Empty;
|
||||||
|
_modFilterName = LowerString.Empty;
|
||||||
|
}
|
||||||
|
else if( filterValue.StartsWith( "n:", StringComparison.InvariantCultureIgnoreCase ) )
|
||||||
|
{
|
||||||
|
_modFilterName = new LowerString( filterValue[ 2.. ] );
|
||||||
|
_modFilter = LowerString.Empty;
|
||||||
|
_modFilterChanges = LowerString.Empty;
|
||||||
|
_modFilterAuthor = LowerString.Empty;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_modFilter = new LowerString( filterValue );
|
||||||
|
_modFilterAuthor = LowerString.Empty;
|
||||||
|
_modFilterChanges = LowerString.Empty;
|
||||||
|
_modFilterName = LowerString.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CheckFlags( int count, ModFilter hasNoFlag, ModFilter hasFlag )
|
||||||
|
{
|
||||||
|
if( count == 0 )
|
||||||
|
{
|
||||||
|
if( StateFilter.HasFlag( hasNoFlag ) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( StateFilter.HasFlag( hasFlag ) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ModState GetModState( Mod mod, ModSettings? settings )
|
||||||
|
{
|
||||||
|
if( settings?.Enabled != true )
|
||||||
|
{
|
||||||
|
return new ModState { Color = ImGui.GetColorU32( ImGuiCol.TextDisabled ) };
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ModState { Color = ImGui.GetColorU32( ImGuiCol.Text ) };
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool ApplyFiltersAndState( FileSystem< Mod >.IPath path, out ModState state )
|
||||||
|
{
|
||||||
|
if( path is ModFileSystemA.Folder f )
|
||||||
|
{
|
||||||
|
return base.ApplyFiltersAndState( f, out state );
|
||||||
|
}
|
||||||
|
|
||||||
|
return ApplyFiltersAndState( ( ModFileSystemA.Leaf )path, out state );
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CheckPath( string path, Mod mod )
|
||||||
|
=> _modFilter.IsEmpty
|
||||||
|
|| path.Contains( _modFilter.Lower, StringComparison.InvariantCultureIgnoreCase )
|
||||||
|
|| mod.Meta.Name.Contains( _modFilter );
|
||||||
|
|
||||||
|
private bool CheckName( Mod mod )
|
||||||
|
=> _modFilterName.IsEmpty || mod.Meta.Name.Contains( _modFilterName );
|
||||||
|
|
||||||
|
private bool CheckAuthor( Mod mod )
|
||||||
|
=> _modFilterAuthor.IsEmpty || mod.Meta.Author.Contains( _modFilterAuthor );
|
||||||
|
|
||||||
|
private bool CheckItems( Mod mod )
|
||||||
|
=> _modFilterChanges.IsEmpty || mod.LowerChangedItemsString.Contains( _modFilterChanges.Lower );
|
||||||
|
|
||||||
|
private bool ApplyFiltersAndState( ModFileSystemA.Leaf leaf, out ModState state )
|
||||||
|
{
|
||||||
|
state = new ModState { Color = Colors.DefaultTextColor };
|
||||||
|
var mod = leaf.Value;
|
||||||
|
var (settings, collection) = Current[ mod.Index ];
|
||||||
|
// Check string filters.
|
||||||
|
if( !( CheckPath( leaf.FullName(), mod )
|
||||||
|
&& CheckName( mod )
|
||||||
|
&& CheckAuthor( mod )
|
||||||
|
&& CheckItems( mod ) ) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var isNew = _newMods.Contains( mod );
|
||||||
|
if( CheckFlags( mod.Resources.ModFiles.Count, ModFilter.HasNoFiles, ModFilter.HasFiles )
|
||||||
|
|| CheckFlags( mod.Meta.FileSwaps.Count, ModFilter.HasNoFileSwaps, ModFilter.HasFileSwaps )
|
||||||
|
|| CheckFlags( mod.Resources.MetaManipulations.Count, ModFilter.HasNoMetaManipulations, ModFilter.HasMetaManipulations )
|
||||||
|
|| CheckFlags( mod.Meta.HasGroupsWithConfig ? 1 : 0, ModFilter.HasNoConfig, ModFilter.HasConfig )
|
||||||
|
|| CheckFlags( isNew ? 1 : 0, ModFilter.IsNew, ModFilter.NotNew ) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( settings == null )
|
||||||
|
{
|
||||||
|
state.Color = Colors.DisabledModColor;
|
||||||
|
if( !StateFilter.HasFlag( ModFilter.Undefined ) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
settings = new ModSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( !settings.Enabled )
|
||||||
|
{
|
||||||
|
state.Color = Colors.DisabledModColor;
|
||||||
|
if( !StateFilter.HasFlag( ModFilter.Disabled ) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( !StateFilter.HasFlag( ModFilter.Enabled ) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var conflicts = Penumbra.CollectionManager.Current.ModConflicts( mod.Index ).ToList();
|
||||||
|
if( conflicts.Count > 0 )
|
||||||
|
{
|
||||||
|
if( conflicts.Any( c => !c.Solved ) )
|
||||||
|
{
|
||||||
|
if( !StateFilter.HasFlag( ModFilter.UnsolvedConflict ) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.Color = Colors.ConflictingModColor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( !StateFilter.HasFlag( ModFilter.SolvedConflict ) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.Color = Colors.HandledConflictModColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( !StateFilter.HasFlag( ModFilter.NoConflict ) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( collection == Current )
|
||||||
|
{
|
||||||
|
if( !StateFilter.HasFlag( ModFilter.Uninherited ) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( !StateFilter.HasFlag( ModFilter.Inherited ) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( isNew )
|
||||||
|
{
|
||||||
|
state.Color = Colors.NewModColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected override float CustomFilters( float width )
|
||||||
|
{
|
||||||
|
var pos = ImGui.GetCursorPos();
|
||||||
|
var remainingWidth = width - ImGui.GetFrameHeight();
|
||||||
|
var comboPos = new Vector2( pos.X + remainingWidth, pos.Y );
|
||||||
|
ImGui.SetCursorPos( comboPos );
|
||||||
|
using var combo = ImRaii.Combo( "##filterCombo", string.Empty,
|
||||||
|
ImGuiComboFlags.NoPreview | ImGuiComboFlags.PopupAlignLeft | ImGuiComboFlags.HeightLargest );
|
||||||
|
|
||||||
|
if( combo )
|
||||||
|
{
|
||||||
|
ImGui.Text( "A" );
|
||||||
|
ImGui.Text( "B" );
|
||||||
|
ImGui.Text( "C" );
|
||||||
|
}
|
||||||
|
|
||||||
|
combo.Dispose();
|
||||||
|
ImGui.SetCursorPos( pos );
|
||||||
|
return remainingWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ModFileSystemSelector( ModFileSystemA fileSystem )
|
||||||
|
: base( fileSystem )
|
||||||
|
{
|
||||||
|
SubscribeRightClickFolder( EnableDescendants, 10 );
|
||||||
|
SubscribeRightClickFolder( DisableDescendants, 10 );
|
||||||
|
SubscribeRightClickFolder( InheritDescendants, 15 );
|
||||||
|
SubscribeRightClickFolder( OwnDescendants, 15 );
|
||||||
|
AddButton( AddNewModButton, 0 );
|
||||||
|
AddButton( DeleteModButton, 1000 );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ModCollection Current
|
||||||
|
=> Penumbra.CollectionManager.Current;
|
||||||
|
|
||||||
|
private static void EnableDescendants( ModFileSystemA.Folder folder )
|
||||||
|
{
|
||||||
|
if( ImGui.MenuItem( "Enable Descendants" ) )
|
||||||
|
{
|
||||||
|
SetDescendants( folder, true, false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DisableDescendants( ModFileSystemA.Folder folder )
|
||||||
|
{
|
||||||
|
if( ImGui.MenuItem( "Disable Descendants" ) )
|
||||||
|
{
|
||||||
|
SetDescendants( folder, false, false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void InheritDescendants( ModFileSystemA.Folder folder )
|
||||||
|
{
|
||||||
|
if( ImGui.MenuItem( "Inherit Descendants" ) )
|
||||||
|
{
|
||||||
|
SetDescendants( folder, true, true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OwnDescendants( ModFileSystemA.Folder folder )
|
||||||
|
{
|
||||||
|
if( ImGui.MenuItem( "Stop Inheriting Descendants" ) )
|
||||||
|
{
|
||||||
|
SetDescendants( folder, false, true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddNewModButton( Vector2 size )
|
||||||
|
{
|
||||||
|
if( ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.Plus.ToIconString(), size, "Create a new, empty mod of a given name.", false, true ) )
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DeleteModButton( Vector2 size )
|
||||||
|
{
|
||||||
|
if( ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.Trash.ToIconString(), size,
|
||||||
|
"Delete the currently selected mod entirely from your drive.", SelectedLeaf == null, true ) )
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetDescendants( ModFileSystemA.Folder folder, bool enabled, bool inherit = false )
|
||||||
|
{
|
||||||
|
var mods = folder.GetAllDescendants( SortMode.Lexicographical ).OfType< ModFileSystemA.Leaf >().Select( l => l.Value );
|
||||||
|
if( inherit )
|
||||||
|
{
|
||||||
|
Current.SetMultipleModInheritances( mods, enabled );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Current.SetMultipleModStates( mods, enabled );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override SortMode SortMode
|
||||||
|
=> Penumbra.Config.SortFoldersFirst ? SortMode.FoldersFirst : SortMode.Lexicographical;
|
||||||
|
|
||||||
|
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 );
|
||||||
|
using var _ = ImRaii.TreeNode( leaf.Value.Meta.Name, flags );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,24 +1,37 @@
|
||||||
using System.Diagnostics;
|
using System.Runtime.InteropServices;
|
||||||
using ImGuiNET;
|
using OtterGui.Raii;
|
||||||
|
using Penumbra.Mods;
|
||||||
|
|
||||||
namespace Penumbra.UI
|
namespace Penumbra.UI;
|
||||||
|
|
||||||
|
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
||||||
|
public struct ModState
|
||||||
{
|
{
|
||||||
public partial class SettingsInterface
|
public uint Color;
|
||||||
{
|
}
|
||||||
private class TabBrowser
|
|
||||||
{
|
|
||||||
[Conditional( "LEAVEMEALONE" )]
|
|
||||||
public void Draw()
|
|
||||||
{
|
|
||||||
var ret = ImGui.BeginTabItem( "Available Mods" );
|
|
||||||
if( !ret )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.Text( "woah" );
|
public partial class SettingsInterface
|
||||||
ImGui.EndTabItem();
|
{
|
||||||
|
private class TabBrowser
|
||||||
|
{
|
||||||
|
private readonly ModFileSystemA _fileSystem;
|
||||||
|
private readonly ModFileSystemSelector _selector;
|
||||||
|
|
||||||
|
public TabBrowser()
|
||||||
|
{
|
||||||
|
_fileSystem = ModFileSystemA.Load();
|
||||||
|
_selector = new ModFileSystemSelector( _fileSystem );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw()
|
||||||
|
{
|
||||||
|
using var ret = ImRaii.TabItem( "Available Mods" );
|
||||||
|
if( !ret )
|
||||||
|
{
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_selector.Draw( 400 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3,6 +3,7 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
|
using OtterGui.Raii;
|
||||||
using Penumbra.Api;
|
using Penumbra.Api;
|
||||||
using Penumbra.UI.Custom;
|
using Penumbra.UI.Custom;
|
||||||
using CharacterUtility = Penumbra.Interop.CharacterUtility;
|
using CharacterUtility = Penumbra.Interop.CharacterUtility;
|
||||||
|
|
@ -12,6 +13,17 @@ namespace Penumbra.UI;
|
||||||
|
|
||||||
public partial class SettingsInterface
|
public partial class SettingsInterface
|
||||||
{
|
{
|
||||||
|
private string ImGuiIdTester = string.Empty;
|
||||||
|
|
||||||
|
private void DrawImGuiIdTester()
|
||||||
|
{
|
||||||
|
ImGui.SetNextItemWidth( 200 );
|
||||||
|
ImGui.InputText( "##abc1", ref ImGuiIdTester, 32 );
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.Text( ImGui.GetID( ImGuiIdTester ).ToString( "X" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private static void PrintValue( string name, string value )
|
private static void PrintValue( string name, string value )
|
||||||
{
|
{
|
||||||
ImGui.TableNextRow();
|
ImGui.TableNextRow();
|
||||||
|
|
@ -289,6 +301,16 @@ public partial class SettingsInterface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DrawDebugTabUtility()
|
||||||
|
{
|
||||||
|
if( !ImGui.CollapsingHeader( "Utilities##Debug" ) )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawImGuiIdTester();
|
||||||
|
}
|
||||||
|
|
||||||
private void DrawDebugTab()
|
private void DrawDebugTab()
|
||||||
{
|
{
|
||||||
if( !ImGui.BeginTabItem( "Debug Tab" ) )
|
if( !ImGui.BeginTabItem( "Debug Tab" ) )
|
||||||
|
|
@ -324,5 +346,7 @@ public partial class SettingsInterface
|
||||||
ImGui.NewLine();
|
ImGui.NewLine();
|
||||||
DrawDebugTabIpc();
|
DrawDebugTabIpc();
|
||||||
ImGui.NewLine();
|
ImGui.NewLine();
|
||||||
|
DrawDebugTabUtility();
|
||||||
|
ImGui.NewLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3,6 +3,7 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
|
using OtterGui;
|
||||||
using Penumbra.Collections;
|
using Penumbra.Collections;
|
||||||
using Penumbra.GameData.ByteString;
|
using Penumbra.GameData.ByteString;
|
||||||
using Penumbra.GameData.Util;
|
using Penumbra.GameData.Util;
|
||||||
|
|
|
||||||
|
|
@ -1,50 +1,55 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Penumbra.UI
|
namespace Penumbra.UI;
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum ModFilter
|
||||||
{
|
{
|
||||||
[Flags]
|
Enabled = 1 << 0,
|
||||||
public enum ModFilter
|
Disabled = 1 << 1,
|
||||||
{
|
NoConflict = 1 << 2,
|
||||||
Enabled = 1 << 0,
|
SolvedConflict = 1 << 3,
|
||||||
Disabled = 1 << 1,
|
UnsolvedConflict = 1 << 4,
|
||||||
NoConflict = 1 << 2,
|
HasNoMetaManipulations = 1 << 5,
|
||||||
SolvedConflict = 1 << 3,
|
HasMetaManipulations = 1 << 6,
|
||||||
UnsolvedConflict = 1 << 4,
|
HasNoFileSwaps = 1 << 7,
|
||||||
HasNoMetaManipulations = 1 << 5,
|
HasFileSwaps = 1 << 8,
|
||||||
HasMetaManipulations = 1 << 6,
|
HasConfig = 1 << 9,
|
||||||
HasNoFileSwaps = 1 << 7,
|
HasNoConfig = 1 << 10,
|
||||||
HasFileSwaps = 1 << 8,
|
HasNoFiles = 1 << 11,
|
||||||
HasConfig = 1 << 9,
|
HasFiles = 1 << 12,
|
||||||
HasNoConfig = 1 << 10,
|
IsNew = 1 << 13,
|
||||||
HasNoFiles = 1 << 11,
|
NotNew = 1 << 14,
|
||||||
HasFiles = 1 << 12,
|
Inherited = 1 << 15,
|
||||||
IsNew = 1 << 13,
|
Uninherited = 1 << 16,
|
||||||
NotNew = 1 << 14,
|
Undefined = 1 << 17,
|
||||||
};
|
};
|
||||||
|
|
||||||
public static class ModFilterExtensions
|
public static class ModFilterExtensions
|
||||||
{
|
{
|
||||||
public const ModFilter UnfilteredStateMods = ( ModFilter )( ( 1 << 15 ) - 1 );
|
public const ModFilter UnfilteredStateMods = ( ModFilter )( ( 1 << 18 ) - 1 );
|
||||||
|
|
||||||
public static string ToName( this ModFilter filter )
|
public static string ToName( this ModFilter filter )
|
||||||
=> filter switch
|
=> filter switch
|
||||||
{
|
{
|
||||||
ModFilter.Enabled => "Enabled",
|
ModFilter.Enabled => "Enabled",
|
||||||
ModFilter.Disabled => "Disabled",
|
ModFilter.Disabled => "Disabled",
|
||||||
ModFilter.NoConflict => "No Conflicts",
|
ModFilter.NoConflict => "No Conflicts",
|
||||||
ModFilter.SolvedConflict => "Solved Conflicts",
|
ModFilter.SolvedConflict => "Solved Conflicts",
|
||||||
ModFilter.UnsolvedConflict => "Unsolved Conflicts",
|
ModFilter.UnsolvedConflict => "Unsolved Conflicts",
|
||||||
ModFilter.HasNoMetaManipulations => "No Meta Manipulations",
|
ModFilter.HasNoMetaManipulations => "No Meta Manipulations",
|
||||||
ModFilter.HasMetaManipulations => "Meta Manipulations",
|
ModFilter.HasMetaManipulations => "Meta Manipulations",
|
||||||
ModFilter.HasNoFileSwaps => "No File Swaps",
|
ModFilter.HasNoFileSwaps => "No File Swaps",
|
||||||
ModFilter.HasFileSwaps => "File Swaps",
|
ModFilter.HasFileSwaps => "File Swaps",
|
||||||
ModFilter.HasNoConfig => "No Configuration",
|
ModFilter.HasNoConfig => "No Configuration",
|
||||||
ModFilter.HasConfig => "Configuration",
|
ModFilter.HasConfig => "Configuration",
|
||||||
ModFilter.HasNoFiles => "No Files",
|
ModFilter.HasNoFiles => "No Files",
|
||||||
ModFilter.HasFiles => "Files",
|
ModFilter.HasFiles => "Files",
|
||||||
ModFilter.IsNew => "Newly Imported",
|
ModFilter.IsNew => "Newly Imported",
|
||||||
ModFilter.NotNew => "Not Newly Imported",
|
ModFilter.NotNew => "Not Newly Imported",
|
||||||
_ => throw new ArgumentOutOfRangeException( nameof( filter ), filter, null ),
|
ModFilter.Inherited => "Inherited Configuration",
|
||||||
};
|
ModFilter.Uninherited => "Own Configuration",
|
||||||
}
|
ModFilter.Undefined => "Not Configured",
|
||||||
|
_ => throw new ArgumentOutOfRangeException( nameof( filter ), filter, null ),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -2,6 +2,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Dalamud.Logging;
|
using Dalamud.Logging;
|
||||||
|
using OtterGui;
|
||||||
using Penumbra.Mods;
|
using Penumbra.Mods;
|
||||||
using Penumbra.Util;
|
using Penumbra.Util;
|
||||||
|
|
||||||
|
|
@ -9,12 +10,7 @@ namespace Penumbra.UI;
|
||||||
|
|
||||||
public class ModListCache : IDisposable
|
public class ModListCache : IDisposable
|
||||||
{
|
{
|
||||||
public const uint NewModColor = 0xFF66DD66u;
|
private readonly Mod.Manager _manager;
|
||||||
public const uint DisabledModColor = 0xFF666666u;
|
|
||||||
public const uint ConflictingModColor = 0xFFAAAAFFu;
|
|
||||||
public const uint HandledConflictModColor = 0xFF88DDDDu;
|
|
||||||
|
|
||||||
private readonly Mods.Mod.Manager _manager;
|
|
||||||
|
|
||||||
private readonly List< FullMod > _modsInOrder = new();
|
private readonly List< FullMod > _modsInOrder = new();
|
||||||
private readonly List< (bool visible, uint color) > _visibleMods = new();
|
private readonly List< (bool visible, uint color) > _visibleMods = new();
|
||||||
|
|
@ -24,10 +20,11 @@ public class ModListCache : IDisposable
|
||||||
private LowerString _modFilter = LowerString.Empty;
|
private LowerString _modFilter = LowerString.Empty;
|
||||||
private LowerString _modFilterAuthor = LowerString.Empty;
|
private LowerString _modFilterAuthor = LowerString.Empty;
|
||||||
private LowerString _modFilterChanges = LowerString.Empty;
|
private LowerString _modFilterChanges = LowerString.Empty;
|
||||||
private ModFilter _stateFilter = ModFilterExtensions.UnfilteredStateMods;
|
|
||||||
private bool _listResetNecessary;
|
|
||||||
private bool _filterResetNecessary;
|
|
||||||
|
|
||||||
|
private bool _listResetNecessary;
|
||||||
|
private bool _filterResetNecessary;
|
||||||
|
|
||||||
|
private ModFilter _stateFilter = ModFilterExtensions.UnfilteredStateMods;
|
||||||
|
|
||||||
public ModFilter StateFilter
|
public ModFilter StateFilter
|
||||||
{
|
{
|
||||||
|
|
@ -43,7 +40,7 @@ public class ModListCache : IDisposable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModListCache( Mods.Mod.Manager manager, IReadOnlySet< string > newMods )
|
public ModListCache( Mod.Manager manager, IReadOnlySet< string > newMods )
|
||||||
{
|
{
|
||||||
_manager = manager;
|
_manager = manager;
|
||||||
_newMods = newMods;
|
_newMods = newMods;
|
||||||
|
|
@ -281,7 +278,7 @@ public class ModListCache : IDisposable
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.Item2 = ret.Item2 == 0 ? DisabledModColor : ret.Item2;
|
ret.Item2 = ret.Item2 == 0 ? Colors.DisabledModColor : ret.Item2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( mod.Settings.Enabled && !StateFilter.HasFlag( ModFilter.Enabled ) )
|
if( mod.Settings.Enabled && !StateFilter.HasFlag( ModFilter.Enabled ) )
|
||||||
|
|
@ -299,7 +296,7 @@ public class ModListCache : IDisposable
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.Item2 = ret.Item2 == 0 ? ConflictingModColor : ret.Item2;
|
ret.Item2 = ret.Item2 == 0 ? Colors.ConflictingModColor : ret.Item2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -308,7 +305,7 @@ public class ModListCache : IDisposable
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.Item2 = ret.Item2 == 0 ? HandledConflictModColor : ret.Item2;
|
ret.Item2 = ret.Item2 == 0 ? Colors.HandledConflictModColor : ret.Item2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( !StateFilter.HasFlag( ModFilter.NoConflict ) )
|
else if( !StateFilter.HasFlag( ModFilter.NoConflict ) )
|
||||||
|
|
@ -319,7 +316,7 @@ public class ModListCache : IDisposable
|
||||||
ret.Item1 = true;
|
ret.Item1 = true;
|
||||||
if( isNew )
|
if( isNew )
|
||||||
{
|
{
|
||||||
ret.Item2 = NewModColor;
|
ret.Item2 = Colors.NewModColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetFolderAndParentsVisible( mod.Data.Order.ParentFolder );
|
SetFolderAndParentsVisible( mod.Data.Order.ParentFolder );
|
||||||
|
|
|
||||||
|
|
@ -217,18 +217,18 @@ public partial class SettingsInterface
|
||||||
ImGui.Text( "Enabled in the current collection." );
|
ImGui.Text( "Enabled in the current collection." );
|
||||||
ImGui.Bullet();
|
ImGui.Bullet();
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.TextColored( ImGui.ColorConvertU32ToFloat4( ModListCache.DisabledModColor ), "Disabled in the current collection." );
|
ImGui.TextColored( ImGui.ColorConvertU32ToFloat4( Colors.DisabledModColor ), "Disabled in the current collection." );
|
||||||
ImGui.Bullet();
|
ImGui.Bullet();
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.TextColored( ImGui.ColorConvertU32ToFloat4( ModListCache.NewModColor ),
|
ImGui.TextColored( ImGui.ColorConvertU32ToFloat4( Colors.NewModColor ),
|
||||||
"Newly imported during this session. Will go away when first enabling a mod or when Penumbra is reloaded." );
|
"Newly imported during this session. Will go away when first enabling a mod or when Penumbra is reloaded." );
|
||||||
ImGui.Bullet();
|
ImGui.Bullet();
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.TextColored( ImGui.ColorConvertU32ToFloat4( ModListCache.HandledConflictModColor ),
|
ImGui.TextColored( ImGui.ColorConvertU32ToFloat4( Colors.HandledConflictModColor ),
|
||||||
"Enabled and conflicting with another enabled Mod, but on different priorities (i.e. the conflict is solved)." );
|
"Enabled and conflicting with another enabled Mod, but on different priorities (i.e. the conflict is solved)." );
|
||||||
ImGui.Bullet();
|
ImGui.Bullet();
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.TextColored( ImGui.ColorConvertU32ToFloat4( ModListCache.ConflictingModColor ),
|
ImGui.TextColored( ImGui.ColorConvertU32ToFloat4( Colors.ConflictingModColor ),
|
||||||
"Enabled and conflicting with another enabled Mod on the same priority." );
|
"Enabled and conflicting with another enabled Mod on the same priority." );
|
||||||
ImGui.Unindent();
|
ImGui.Unindent();
|
||||||
ImGui.BulletText( "Right-click a mod to enter its sort order, which is its name by default." );
|
ImGui.BulletText( "Right-click a mod to enter its sort order, which is its name by default." );
|
||||||
|
|
|
||||||
|
|
@ -235,7 +235,8 @@ public partial class SettingsInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGuiComponents.HelpMarker( "Enables other applications, e.g. Anamnesis, to use some Penumbra functions, like requesting redraws." );
|
ImGuiComponents.HelpMarker(
|
||||||
|
"Enables other applications, e.g. Anamnesis, to use some Penumbra functions, like requesting redraws." );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DrawReloadResourceButton()
|
private static void DrawReloadResourceButton()
|
||||||
|
|
@ -342,7 +343,6 @@ public partial class SettingsInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTabItem );
|
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTabItem );
|
||||||
|
|
||||||
DrawRootFolder();
|
DrawRootFolder();
|
||||||
|
|
||||||
DrawRediscoverButton();
|
DrawRediscoverButton();
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
|
using System.Linq;
|
||||||
using Dalamud.Logging;
|
using Dalamud.Logging;
|
||||||
|
|
||||||
namespace Penumbra.Util;
|
namespace Penumbra.Util;
|
||||||
|
|
@ -119,7 +120,7 @@ public static class Backup
|
||||||
{
|
{
|
||||||
using var fileStream = File.Open( fileName, FileMode.Create );
|
using var fileStream = File.Open( fileName, FileMode.Create );
|
||||||
using var zip = new ZipArchive( fileStream, ZipArchiveMode.Create );
|
using var zip = new ZipArchive( fileStream, ZipArchiveMode.Create );
|
||||||
foreach( var file in files )
|
foreach( var file in files.Where( f => File.Exists( f.FullName ) ) )
|
||||||
{
|
{
|
||||||
zip.CreateEntryFromFile( file.FullName, Path.GetRelativePath( configDirectory, file.FullName ), CompressionLevel.Optimal );
|
zip.CreateEntryFromFile( file.FullName, Path.GetRelativePath( configDirectory, file.FullName ), CompressionLevel.Optimal );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,122 +0,0 @@
|
||||||
using System;
|
|
||||||
using ImGuiNET;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Penumbra.Util;
|
|
||||||
|
|
||||||
[JsonConverter( typeof( Converter ) )]
|
|
||||||
public readonly struct LowerString : IEquatable< LowerString >, IComparable< LowerString >
|
|
||||||
{
|
|
||||||
public static readonly LowerString Empty = new(string.Empty);
|
|
||||||
|
|
||||||
public readonly string Text = string.Empty;
|
|
||||||
public readonly string Lower = string.Empty;
|
|
||||||
|
|
||||||
public LowerString( string text )
|
|
||||||
{
|
|
||||||
Text = string.Intern( text );
|
|
||||||
Lower = string.Intern( text.ToLowerInvariant() );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public int Length
|
|
||||||
=> Text.Length;
|
|
||||||
|
|
||||||
public int Count
|
|
||||||
=> Length;
|
|
||||||
|
|
||||||
public bool Equals( LowerString other )
|
|
||||||
=> string.Equals( Lower, other.Lower, StringComparison.InvariantCulture );
|
|
||||||
|
|
||||||
public bool Equals( string other )
|
|
||||||
=> string.Equals( Lower, other, StringComparison.InvariantCultureIgnoreCase );
|
|
||||||
|
|
||||||
public int CompareTo( LowerString other )
|
|
||||||
=> string.Compare( Lower, other.Lower, StringComparison.InvariantCulture );
|
|
||||||
|
|
||||||
public int CompareTo( string other )
|
|
||||||
=> string.Compare( Lower, other, StringComparison.InvariantCultureIgnoreCase );
|
|
||||||
|
|
||||||
public bool Contains( LowerString other )
|
|
||||||
=> Lower.Contains( other.Lower, StringComparison.InvariantCulture );
|
|
||||||
|
|
||||||
public bool Contains( string other )
|
|
||||||
=> Lower.Contains( other, StringComparison.InvariantCultureIgnoreCase );
|
|
||||||
|
|
||||||
public bool StartsWith( LowerString other )
|
|
||||||
=> Lower.StartsWith( other.Lower, StringComparison.InvariantCulture );
|
|
||||||
|
|
||||||
public bool StartsWith( string other )
|
|
||||||
=> Lower.StartsWith( other, StringComparison.InvariantCultureIgnoreCase );
|
|
||||||
|
|
||||||
public bool EndsWith( LowerString other )
|
|
||||||
=> Lower.EndsWith( other.Lower, StringComparison.InvariantCulture );
|
|
||||||
|
|
||||||
public bool EndsWith( string other )
|
|
||||||
=> Lower.EndsWith( other, StringComparison.InvariantCultureIgnoreCase );
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
=> Text;
|
|
||||||
|
|
||||||
public static implicit operator string( LowerString s )
|
|
||||||
=> s.Text;
|
|
||||||
|
|
||||||
public static implicit operator LowerString( string s )
|
|
||||||
=> new(s);
|
|
||||||
|
|
||||||
private class Converter : JsonConverter< LowerString >
|
|
||||||
{
|
|
||||||
public override void WriteJson( JsonWriter writer, LowerString value, JsonSerializer serializer )
|
|
||||||
{
|
|
||||||
writer.WriteValue( value.Text );
|
|
||||||
}
|
|
||||||
|
|
||||||
public override LowerString ReadJson( JsonReader reader, Type objectType, LowerString existingValue, bool hasExistingValue,
|
|
||||||
JsonSerializer serializer )
|
|
||||||
{
|
|
||||||
if( reader.Value is string text )
|
|
||||||
{
|
|
||||||
return new LowerString( text );
|
|
||||||
}
|
|
||||||
|
|
||||||
return existingValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool InputWithHint( string label, string hint, ref LowerString s, uint maxLength = 128,
|
|
||||||
ImGuiInputTextFlags flags = ImGuiInputTextFlags.None )
|
|
||||||
{
|
|
||||||
var tmp = s.Text;
|
|
||||||
if( !ImGui.InputTextWithHint( label, hint, ref tmp, maxLength, flags ) || tmp == s.Text )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
s = new LowerString( tmp );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals( object? obj )
|
|
||||||
=> obj is LowerString lowerString && Equals( lowerString );
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
=> Text.GetHashCode();
|
|
||||||
|
|
||||||
public static bool operator ==( LowerString lhs, LowerString rhs )
|
|
||||||
=> lhs.Equals( rhs );
|
|
||||||
|
|
||||||
public static bool operator !=( LowerString lhs, LowerString rhs )
|
|
||||||
=> lhs.Equals( rhs );
|
|
||||||
|
|
||||||
public static bool operator ==( LowerString lhs, string rhs )
|
|
||||||
=> lhs.Equals( rhs );
|
|
||||||
|
|
||||||
public static bool operator !=( LowerString lhs, string rhs )
|
|
||||||
=> lhs.Equals( rhs );
|
|
||||||
|
|
||||||
public static bool operator ==( string lhs, LowerString rhs )
|
|
||||||
=> rhs.Equals( lhs );
|
|
||||||
|
|
||||||
public static bool operator !=( string lhs, LowerString rhs )
|
|
||||||
=> rhs.Equals( lhs );
|
|
||||||
}
|
|
||||||
|
|
@ -26,7 +26,7 @@ public static class ModelChanger
|
||||||
&& Encoding.UTF8.GetByteCount( to ) == to.Length;
|
&& Encoding.UTF8.GetByteCount( to ) == to.Length;
|
||||||
|
|
||||||
|
|
||||||
[Conditional( "Debug" )]
|
[Conditional( "DEBUG" )]
|
||||||
private static void WriteBackup( string name, byte[] text )
|
private static void WriteBackup( string name, byte[] text )
|
||||||
=> File.WriteAllBytes( name + ".bak", text );
|
=> File.WriteAllBytes( name + ".bak", text );
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue