mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-13 12:14:17 +01:00
Add special collections.
This commit is contained in:
parent
ec91755065
commit
549f8ce4b4
11 changed files with 486 additions and 86 deletions
|
|
@ -39,19 +39,59 @@ public partial class ModCollection
|
||||||
public ModCollection Character( string name )
|
public ModCollection Character( string name )
|
||||||
=> _characters.TryGetValue( name, out var c ) ? c : Default;
|
=> _characters.TryGetValue( name, out var c ) ? c : Default;
|
||||||
|
|
||||||
// Set a active collection, can be used to set Default, Current or Character collections.
|
// Special Collections
|
||||||
private void SetCollection( int newIdx, Type type, string? characterName = null )
|
private readonly ModCollection?[] _specialCollections = new ModCollection?[Enum.GetValues< CollectionType >().Length - 4];
|
||||||
|
|
||||||
|
// Return the configured collection for the given type or null.
|
||||||
|
public ModCollection? ByType( CollectionType type, string? name = null )
|
||||||
{
|
{
|
||||||
var oldCollectionIdx = type switch
|
if( type.IsSpecial() )
|
||||||
{
|
{
|
||||||
Type.Default => Default.Index,
|
return _specialCollections[ ( int )type ];
|
||||||
Type.Current => Current.Index,
|
}
|
||||||
Type.Character => characterName?.Length > 0
|
|
||||||
|
return type switch
|
||||||
|
{
|
||||||
|
CollectionType.Default => Default,
|
||||||
|
CollectionType.Current => Current,
|
||||||
|
CollectionType.Character => name != null ? _characters.TryGetValue( name, out var c ) ? c : null : null,
|
||||||
|
CollectionType.Inactive => name != null ? ByName( name, out var c ) ? c : null : null,
|
||||||
|
_ => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a active collection, can be used to set Default, Current or Character collections.
|
||||||
|
private void SetCollection( int newIdx, CollectionType collectionType, string? characterName = null )
|
||||||
|
{
|
||||||
|
var oldCollectionIdx = collectionType switch
|
||||||
|
{
|
||||||
|
CollectionType.Default => Default.Index,
|
||||||
|
CollectionType.Current => Current.Index,
|
||||||
|
CollectionType.Character => characterName?.Length > 0
|
||||||
? _characters.TryGetValue( characterName, out var c )
|
? _characters.TryGetValue( characterName, out var c )
|
||||||
? c.Index
|
? c.Index
|
||||||
: Default.Index
|
: Default.Index
|
||||||
: -1,
|
: -1,
|
||||||
_ => -1,
|
CollectionType.Yourself => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
|
||||||
|
CollectionType.PlayerCharacter => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
|
||||||
|
CollectionType.NonPlayerCharacter => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
|
||||||
|
CollectionType.Midlander => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
|
||||||
|
CollectionType.Highlander => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
|
||||||
|
CollectionType.Wildwood => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
|
||||||
|
CollectionType.Duskwight => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
|
||||||
|
CollectionType.Plainsfolk => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
|
||||||
|
CollectionType.Dunesfolk => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
|
||||||
|
CollectionType.SeekerOfTheSun => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
|
||||||
|
CollectionType.KeeperOfTheMoon => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
|
||||||
|
CollectionType.Seawolf => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
|
||||||
|
CollectionType.Hellsguard => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
|
||||||
|
CollectionType.Raen => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
|
||||||
|
CollectionType.Xaela => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
|
||||||
|
CollectionType.Helion => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
|
||||||
|
CollectionType.Lost => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
|
||||||
|
CollectionType.Rava => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
|
||||||
|
CollectionType.Veena => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
|
||||||
|
_ => -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
if( oldCollectionIdx == -1 || newIdx == oldCollectionIdx )
|
if( oldCollectionIdx == -1 || newIdx == oldCollectionIdx )
|
||||||
|
|
@ -66,31 +106,109 @@ public partial class ModCollection
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoveCache( oldCollectionIdx );
|
RemoveCache( oldCollectionIdx );
|
||||||
switch( type )
|
switch( collectionType )
|
||||||
{
|
{
|
||||||
case Type.Default:
|
case CollectionType.Default:
|
||||||
Default = newCollection;
|
Default = newCollection;
|
||||||
Penumbra.ResidentResources.Reload();
|
Penumbra.ResidentResources.Reload();
|
||||||
Default.SetFiles();
|
Default.SetFiles();
|
||||||
break;
|
break;
|
||||||
case Type.Current:
|
case CollectionType.Current:
|
||||||
Current = newCollection;
|
Current = newCollection;
|
||||||
break;
|
break;
|
||||||
case Type.Character:
|
case CollectionType.Character:
|
||||||
_characters[ characterName! ] = newCollection;
|
_characters[ characterName! ] = newCollection;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
_specialCollections[ ( int )collectionType ] = newCollection;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UpdateCurrentCollectionInUse();
|
UpdateCurrentCollectionInUse();
|
||||||
CollectionChanged.Invoke( type, this[ oldCollectionIdx ], newCollection, characterName );
|
CollectionChanged.Invoke( collectionType, this[ oldCollectionIdx ], newCollection, characterName );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateCurrentCollectionInUse()
|
private void UpdateCurrentCollectionInUse()
|
||||||
=> CurrentCollectionInUse = Characters.Values.Prepend( Default ).SelectMany( c => c.GetFlattenedInheritance() ).Contains( Current );
|
=> CurrentCollectionInUse = _specialCollections
|
||||||
|
.OfType< ModCollection >()
|
||||||
|
.Prepend( Default )
|
||||||
|
.Concat( Characters.Values )
|
||||||
|
.SelectMany( c => c.GetFlattenedInheritance() ).Contains( Current );
|
||||||
|
|
||||||
public void SetCollection( ModCollection collection, Type type, string? characterName = null )
|
public void SetCollection( ModCollection collection, CollectionType collectionType, string? characterName = null )
|
||||||
=> SetCollection( collection.Index, type, characterName );
|
=> SetCollection( collection.Index, collectionType, characterName );
|
||||||
|
|
||||||
|
// Create a special collection if it does not exist and set it to Empty.
|
||||||
|
public bool CreateSpecialCollection( CollectionType collectionType )
|
||||||
|
{
|
||||||
|
switch( collectionType )
|
||||||
|
{
|
||||||
|
case CollectionType.Yourself:
|
||||||
|
case CollectionType.PlayerCharacter:
|
||||||
|
case CollectionType.NonPlayerCharacter:
|
||||||
|
case CollectionType.Midlander:
|
||||||
|
case CollectionType.Highlander:
|
||||||
|
case CollectionType.Wildwood:
|
||||||
|
case CollectionType.Duskwight:
|
||||||
|
case CollectionType.Plainsfolk:
|
||||||
|
case CollectionType.Dunesfolk:
|
||||||
|
case CollectionType.SeekerOfTheSun:
|
||||||
|
case CollectionType.KeeperOfTheMoon:
|
||||||
|
case CollectionType.Seawolf:
|
||||||
|
case CollectionType.Hellsguard:
|
||||||
|
case CollectionType.Raen:
|
||||||
|
case CollectionType.Xaela:
|
||||||
|
case CollectionType.Helion:
|
||||||
|
case CollectionType.Lost:
|
||||||
|
case CollectionType.Rava:
|
||||||
|
case CollectionType.Veena:
|
||||||
|
if( _specialCollections[ ( int )collectionType ] != null )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_specialCollections[ ( int )collectionType ] = Empty;
|
||||||
|
CollectionChanged.Invoke( collectionType, null, Empty, null );
|
||||||
|
return true;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove a special collection if it exists
|
||||||
|
public void RemoveSpecialCollection( CollectionType collectionType )
|
||||||
|
{
|
||||||
|
switch( collectionType )
|
||||||
|
{
|
||||||
|
case CollectionType.Yourself:
|
||||||
|
case CollectionType.PlayerCharacter:
|
||||||
|
case CollectionType.NonPlayerCharacter:
|
||||||
|
case CollectionType.Midlander:
|
||||||
|
case CollectionType.Highlander:
|
||||||
|
case CollectionType.Wildwood:
|
||||||
|
case CollectionType.Duskwight:
|
||||||
|
case CollectionType.Plainsfolk:
|
||||||
|
case CollectionType.Dunesfolk:
|
||||||
|
case CollectionType.SeekerOfTheSun:
|
||||||
|
case CollectionType.KeeperOfTheMoon:
|
||||||
|
case CollectionType.Seawolf:
|
||||||
|
case CollectionType.Hellsguard:
|
||||||
|
case CollectionType.Raen:
|
||||||
|
case CollectionType.Xaela:
|
||||||
|
case CollectionType.Helion:
|
||||||
|
case CollectionType.Lost:
|
||||||
|
case CollectionType.Rava:
|
||||||
|
case CollectionType.Veena:
|
||||||
|
var old = _specialCollections[ ( int )collectionType ];
|
||||||
|
if( old != null )
|
||||||
|
{
|
||||||
|
_specialCollections[ ( int )collectionType ] = null;
|
||||||
|
CollectionChanged.Invoke( collectionType, old, null, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create a new character collection. Returns false if the character name already has a collection.
|
// Create a new character collection. Returns false if the character name already has a collection.
|
||||||
public bool CreateCharacterCollection( string characterName )
|
public bool CreateCharacterCollection( string characterName )
|
||||||
|
|
@ -101,7 +219,7 @@ public partial class ModCollection
|
||||||
}
|
}
|
||||||
|
|
||||||
_characters[ characterName ] = Empty;
|
_characters[ characterName ] = Empty;
|
||||||
CollectionChanged.Invoke( Type.Character, null, Empty, characterName );
|
CollectionChanged.Invoke( CollectionType.Character, null, Empty, characterName );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,7 +230,7 @@ public partial class ModCollection
|
||||||
{
|
{
|
||||||
RemoveCache( collection.Index );
|
RemoveCache( collection.Index );
|
||||||
_characters.Remove( characterName );
|
_characters.Remove( characterName );
|
||||||
CollectionChanged.Invoke( Type.Character, collection, null, characterName );
|
CollectionChanged.Invoke( CollectionType.Character, collection, null, characterName );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -157,6 +275,25 @@ public partial class ModCollection
|
||||||
Current = this[ currentIdx ];
|
Current = this[ currentIdx ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load special collections.
|
||||||
|
foreach( var type in CollectionTypeExtensions.Special )
|
||||||
|
{
|
||||||
|
var typeName = jObject[ type.ToString() ]?.ToObject< string >();
|
||||||
|
if( typeName != null )
|
||||||
|
{
|
||||||
|
var idx = GetIndexForCollectionName( typeName );
|
||||||
|
if( idx < 0 )
|
||||||
|
{
|
||||||
|
PluginLog.Error( $"Last choice of {type.ToName()} Collection {typeName} is not available, removed." );
|
||||||
|
configChanged = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_specialCollections[ ( int )type ] = this[ idx ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Load character collections. If a player name comes up multiple times, the last one is applied.
|
// Load character collections. If a player name comes up multiple times, the last one is applied.
|
||||||
var characters = jObject[ nameof( Characters ) ]?.ToObject< Dictionary< string, string > >() ?? new Dictionary< string, string >();
|
var characters = jObject[ nameof( Characters ) ]?.ToObject< Dictionary< string, string > >() ?? new Dictionary< string, string >();
|
||||||
foreach( var (player, collectionName) in characters )
|
foreach( var (player, collectionName) in characters )
|
||||||
|
|
@ -187,10 +324,14 @@ public partial class ModCollection
|
||||||
public void SaveActiveCollections()
|
public void SaveActiveCollections()
|
||||||
{
|
{
|
||||||
Penumbra.Framework.RegisterDelayed( nameof( SaveActiveCollections ),
|
Penumbra.Framework.RegisterDelayed( nameof( SaveActiveCollections ),
|
||||||
() => SaveActiveCollections( Default.Name, Current.Name, Characters.Select( kvp => ( kvp.Key, kvp.Value.Name ) ) ) );
|
() => SaveActiveCollections( Default.Name, Current.Name, Characters.Select( kvp => ( kvp.Key, kvp.Value.Name ) ),
|
||||||
|
_specialCollections.WithIndex()
|
||||||
|
.Where( c => c.Item1 != null )
|
||||||
|
.Select( c => ( ( CollectionType )c.Item2, c.Item1!.Name ) ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void SaveActiveCollections( string def, string current, IEnumerable< (string, string) > characters )
|
internal static void SaveActiveCollections( string def, string current, IEnumerable< (string, string) > characters,
|
||||||
|
IEnumerable< (CollectionType, string) > special )
|
||||||
{
|
{
|
||||||
var file = ActiveCollectionFile;
|
var file = ActiveCollectionFile;
|
||||||
try
|
try
|
||||||
|
|
@ -204,6 +345,12 @@ public partial class ModCollection
|
||||||
j.WriteValue( def );
|
j.WriteValue( def );
|
||||||
j.WritePropertyName( nameof( Current ) );
|
j.WritePropertyName( nameof( Current ) );
|
||||||
j.WriteValue( current );
|
j.WriteValue( current );
|
||||||
|
foreach( var (type, collection) in special )
|
||||||
|
{
|
||||||
|
j.WritePropertyName( type.ToString() );
|
||||||
|
j.WriteValue( collection );
|
||||||
|
}
|
||||||
|
|
||||||
j.WritePropertyName( nameof( Characters ) );
|
j.WritePropertyName( nameof( Characters ) );
|
||||||
j.WriteStartObject();
|
j.WriteStartObject();
|
||||||
foreach( var (character, collection) in characters )
|
foreach( var (character, collection) in characters )
|
||||||
|
|
@ -246,9 +393,9 @@ public partial class ModCollection
|
||||||
|
|
||||||
|
|
||||||
// Save if any of the active collections is changed.
|
// Save if any of the active collections is changed.
|
||||||
private void SaveOnChange( Type type, ModCollection? _1, ModCollection? _2, string? _3 )
|
private void SaveOnChange( CollectionType collectionType, ModCollection? _1, ModCollection? _2, string? _3 )
|
||||||
{
|
{
|
||||||
if( type != Type.Inactive )
|
if( collectionType != CollectionType.Inactive )
|
||||||
{
|
{
|
||||||
SaveActiveCollections();
|
SaveActiveCollections();
|
||||||
}
|
}
|
||||||
|
|
@ -261,7 +408,7 @@ public partial class ModCollection
|
||||||
Default.CreateCache();
|
Default.CreateCache();
|
||||||
Current.CreateCache();
|
Current.CreateCache();
|
||||||
|
|
||||||
foreach( var collection in _characters.Values )
|
foreach( var collection in _specialCollections.OfType< ModCollection >().Concat( _characters.Values ) )
|
||||||
{
|
{
|
||||||
collection.CreateCache();
|
collection.CreateCache();
|
||||||
}
|
}
|
||||||
|
|
@ -269,7 +416,10 @@ public partial class ModCollection
|
||||||
|
|
||||||
private void RemoveCache( int idx )
|
private void RemoveCache( int idx )
|
||||||
{
|
{
|
||||||
if( idx != Default.Index && idx != Current.Index && _characters.Values.All( c => c.Index != idx ) )
|
if( idx != Default.Index
|
||||||
|
&& idx != Current.Index
|
||||||
|
&& _specialCollections.All( c => c == null || c.Index != idx )
|
||||||
|
&& _characters.Values.All( c => c.Index != idx ) )
|
||||||
{
|
{
|
||||||
_collections[ idx ].ClearCache();
|
_collections[ idx ].ClearCache();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,20 +13,12 @@ namespace Penumbra.Collections;
|
||||||
|
|
||||||
public partial class ModCollection
|
public partial class ModCollection
|
||||||
{
|
{
|
||||||
public enum Type : byte
|
|
||||||
{
|
|
||||||
Inactive, // A collection was added or removed
|
|
||||||
Default, // The default collection was changed
|
|
||||||
Character, // A character collection was changed
|
|
||||||
Current, // The current collection was changed.
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed partial class Manager : IDisposable, IEnumerable< ModCollection >
|
public sealed partial class Manager : IDisposable, IEnumerable< ModCollection >
|
||||||
{
|
{
|
||||||
// On addition, oldCollection is null. On deletion, newCollection is null.
|
// On addition, oldCollection is null. On deletion, newCollection is null.
|
||||||
// CharacterName is onls set for type == Character.
|
// CharacterName is only set for type == Character.
|
||||||
public delegate void CollectionChangeDelegate( Type type, ModCollection? oldCollection, ModCollection? newCollection,
|
public delegate void CollectionChangeDelegate( CollectionType collectionType, ModCollection? oldCollection,
|
||||||
string? characterName = null );
|
ModCollection? newCollection, string? characterName = null );
|
||||||
|
|
||||||
private readonly Mod.Manager _modManager;
|
private readonly Mod.Manager _modManager;
|
||||||
|
|
||||||
|
|
@ -124,8 +116,8 @@ public partial class ModCollection
|
||||||
_collections.Add( newCollection );
|
_collections.Add( newCollection );
|
||||||
newCollection.Save();
|
newCollection.Save();
|
||||||
PluginLog.Debug( "Added collection {Name:l}.", newCollection.Name );
|
PluginLog.Debug( "Added collection {Name:l}.", newCollection.Name );
|
||||||
CollectionChanged.Invoke( Type.Inactive, null, newCollection );
|
CollectionChanged.Invoke( CollectionType.Inactive, null, newCollection );
|
||||||
SetCollection( newCollection.Index, Type.Current );
|
SetCollection( newCollection.Index, CollectionType.Current );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -148,17 +140,17 @@ public partial class ModCollection
|
||||||
|
|
||||||
if( idx == Current.Index )
|
if( idx == Current.Index )
|
||||||
{
|
{
|
||||||
SetCollection( DefaultName, Type.Current );
|
SetCollection( DefaultName, CollectionType.Current );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( idx == Default.Index )
|
if( idx == Default.Index )
|
||||||
{
|
{
|
||||||
SetCollection( Empty, Type.Default );
|
SetCollection( Empty, CollectionType.Default );
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach( var (characterName, _) in _characters.Where( c => c.Value.Index == idx ).ToList() )
|
foreach( var (characterName, _) in _characters.Where( c => c.Value.Index == idx ).ToList() )
|
||||||
{
|
{
|
||||||
SetCollection( Empty, Type.Character, characterName );
|
SetCollection( Empty, CollectionType.Character, characterName );
|
||||||
}
|
}
|
||||||
|
|
||||||
var collection = _collections[ idx ];
|
var collection = _collections[ idx ];
|
||||||
|
|
@ -179,7 +171,7 @@ public partial class ModCollection
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginLog.Debug( "Removed collection {Name:l}.", collection.Name );
|
PluginLog.Debug( "Removed collection {Name:l}.", collection.Name );
|
||||||
CollectionChanged.Invoke( Type.Inactive, collection, null );
|
CollectionChanged.Invoke( CollectionType.Inactive, collection, null );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
115
Penumbra/Collections/CollectionType.cs
Normal file
115
Penumbra/Collections/CollectionType.cs
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Penumbra.GameData.Enums;
|
||||||
|
|
||||||
|
namespace Penumbra.Collections;
|
||||||
|
|
||||||
|
public enum CollectionType : byte
|
||||||
|
{
|
||||||
|
// Special Collections
|
||||||
|
Yourself = 0,
|
||||||
|
PlayerCharacter,
|
||||||
|
NonPlayerCharacter,
|
||||||
|
Midlander,
|
||||||
|
Highlander,
|
||||||
|
Wildwood,
|
||||||
|
Duskwight,
|
||||||
|
Plainsfolk,
|
||||||
|
Dunesfolk,
|
||||||
|
SeekerOfTheSun,
|
||||||
|
KeeperOfTheMoon,
|
||||||
|
Seawolf,
|
||||||
|
Hellsguard,
|
||||||
|
Raen,
|
||||||
|
Xaela,
|
||||||
|
Helion,
|
||||||
|
Lost,
|
||||||
|
Rava,
|
||||||
|
Veena,
|
||||||
|
|
||||||
|
Inactive, // A collection was added or removed
|
||||||
|
Default, // The default collection was changed
|
||||||
|
Character, // A character collection was changed
|
||||||
|
Current, // The current collection was changed.
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CollectionTypeExtensions
|
||||||
|
{
|
||||||
|
public static bool IsSpecial( this CollectionType collectionType )
|
||||||
|
=> collectionType is >= CollectionType.Yourself and < CollectionType.Inactive;
|
||||||
|
|
||||||
|
public static readonly CollectionType[] Special = Enum.GetValues< CollectionType >().Where( IsSpecial ).ToArray();
|
||||||
|
|
||||||
|
public static string ToName( this CollectionType collectionType )
|
||||||
|
=> collectionType switch
|
||||||
|
{
|
||||||
|
CollectionType.Yourself => "Your Character",
|
||||||
|
CollectionType.PlayerCharacter => "Player Characters",
|
||||||
|
CollectionType.NonPlayerCharacter => "Non-Player Characters",
|
||||||
|
CollectionType.Midlander => SubRace.Midlander.ToName(),
|
||||||
|
CollectionType.Highlander => SubRace.Highlander.ToName(),
|
||||||
|
CollectionType.Wildwood => SubRace.Wildwood.ToName(),
|
||||||
|
CollectionType.Duskwight => SubRace.Duskwight.ToName(),
|
||||||
|
CollectionType.Plainsfolk => SubRace.Plainsfolk.ToName(),
|
||||||
|
CollectionType.Dunesfolk => SubRace.Dunesfolk.ToName(),
|
||||||
|
CollectionType.SeekerOfTheSun => SubRace.SeekerOfTheSun.ToName(),
|
||||||
|
CollectionType.KeeperOfTheMoon => SubRace.KeeperOfTheMoon.ToName(),
|
||||||
|
CollectionType.Seawolf => SubRace.Seawolf.ToName(),
|
||||||
|
CollectionType.Hellsguard => SubRace.Hellsguard.ToName(),
|
||||||
|
CollectionType.Raen => SubRace.Raen.ToName(),
|
||||||
|
CollectionType.Xaela => SubRace.Xaela.ToName(),
|
||||||
|
CollectionType.Helion => SubRace.Helion.ToName(),
|
||||||
|
CollectionType.Lost => SubRace.Lost.ToName(),
|
||||||
|
CollectionType.Rava => SubRace.Rava.ToName(),
|
||||||
|
CollectionType.Veena => SubRace.Veena.ToName(),
|
||||||
|
CollectionType.Inactive => "Collection",
|
||||||
|
CollectionType.Default => "Default",
|
||||||
|
CollectionType.Character => "Character",
|
||||||
|
CollectionType.Current => "Current",
|
||||||
|
_ => string.Empty,
|
||||||
|
};
|
||||||
|
|
||||||
|
public static string ToDescription( this CollectionType collectionType )
|
||||||
|
=> collectionType switch
|
||||||
|
{
|
||||||
|
CollectionType.Yourself => "This collection applies to your own character, regardless of its name.\n"
|
||||||
|
+ "It takes precedence before all other collections except for explicitly named character collections.",
|
||||||
|
CollectionType.PlayerCharacter =>
|
||||||
|
"This collection applies to all player characters that do not have a more specific character or racial collections associated.",
|
||||||
|
CollectionType.NonPlayerCharacter =>
|
||||||
|
"This collection applies to all human non-player characters except those explicitly named. It takes precedence before the default and racial collections.",
|
||||||
|
CollectionType.Midlander =>
|
||||||
|
"This collection applies to all player character Midlander Hyur that do not have a more specific character collection associated.",
|
||||||
|
CollectionType.Highlander =>
|
||||||
|
"This collection applies to all player character Highlander Hyur that do not have a more specific character collection associated.",
|
||||||
|
CollectionType.Wildwood =>
|
||||||
|
"This collection applies to all player character Wildwood Elezen that do not have a more specific character collection associated.",
|
||||||
|
CollectionType.Duskwight =>
|
||||||
|
"This collection applies to all player character Duskwight Elezen that do not have a more specific character collection associated.",
|
||||||
|
CollectionType.Plainsfolk =>
|
||||||
|
"This collection applies to all player character Plainsfolk Lalafell that do not have a more specific character collection associated.",
|
||||||
|
CollectionType.Dunesfolk =>
|
||||||
|
"This collection applies to all player character Dunesfolk Lalafell that do not have a more specific character collection associated.",
|
||||||
|
CollectionType.SeekerOfTheSun =>
|
||||||
|
"This collection applies to all player character Seekers of the Sun that do not have a more specific character collection associated.",
|
||||||
|
CollectionType.KeeperOfTheMoon =>
|
||||||
|
"This collection applies to all player character Keepers of the Moon that do not have a more specific character collection associated.",
|
||||||
|
CollectionType.Seawolf =>
|
||||||
|
"This collection applies to all player character Sea Wolf Roegadyn that do not have a more specific character collection associated.",
|
||||||
|
CollectionType.Hellsguard =>
|
||||||
|
"This collection applies to all player character Hellsguard Roegadyn that do not have a more specific character collection associated.",
|
||||||
|
CollectionType.Raen =>
|
||||||
|
"This collection applies to all player character Raen Au Ra that do not have a more specific character collection associated.",
|
||||||
|
CollectionType.Xaela =>
|
||||||
|
"This collection applies to all player character Xaela Au Ra that do not have a more specific character collection associated.",
|
||||||
|
CollectionType.Helion =>
|
||||||
|
"This collection applies to all player character Helion Hrothgar that do not have a more specific character collection associated.",
|
||||||
|
CollectionType.Lost =>
|
||||||
|
"This collection applies to all player character Lost Hrothgar that do not have a more specific character collection associated.",
|
||||||
|
CollectionType.Rava =>
|
||||||
|
"This collection applies to all player character Rava Viera that do not have a more specific character collection associated.",
|
||||||
|
CollectionType.Veena =>
|
||||||
|
"This collection applies to all player character Veena Viera that do not have a more specific character collection associated.",
|
||||||
|
_ => string.Empty,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -182,7 +182,7 @@ public partial class Configuration
|
||||||
DefaultCollection = _data[ nameof( DefaultCollection ) ]?.ToObject< string >() ?? DefaultCollection;
|
DefaultCollection = _data[ nameof( DefaultCollection ) ]?.ToObject< string >() ?? DefaultCollection;
|
||||||
CharacterCollections = _data[ nameof( CharacterCollections ) ]?.ToObject< Dictionary< string, string > >() ?? CharacterCollections;
|
CharacterCollections = _data[ nameof( CharacterCollections ) ]?.ToObject< Dictionary< string, string > >() ?? CharacterCollections;
|
||||||
ModCollection.Manager.SaveActiveCollections( DefaultCollection, CurrentCollection,
|
ModCollection.Manager.SaveActiveCollections( DefaultCollection, CurrentCollection,
|
||||||
CharacterCollections.Select( kvp => ( kvp.Key, kvp.Value ) ) );
|
CharacterCollections.Select( kvp => ( kvp.Key, kvp.Value ) ), Array.Empty<(CollectionType, string)>() );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collections were introduced and the previous CurrentCollection got put into ModDirectory.
|
// Collections were introduced and the previous CurrentCollection got put into ModDirectory.
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ using FFXIVClientStructs.FFXIV.Client.UI;
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
using Penumbra.Collections;
|
using Penumbra.Collections;
|
||||||
using Penumbra.GameData.ByteString;
|
using Penumbra.GameData.ByteString;
|
||||||
|
using Penumbra.GameData.Enums;
|
||||||
using ObjectKind = Dalamud.Game.ClientState.Objects.Enums.ObjectKind;
|
using ObjectKind = Dalamud.Game.ClientState.Objects.Enums.ObjectKind;
|
||||||
|
|
||||||
namespace Penumbra.Interop.Resolver;
|
namespace Penumbra.Interop.Resolver;
|
||||||
|
|
@ -320,8 +321,12 @@ public unsafe partial class PathResolver
|
||||||
}
|
}
|
||||||
?? GetOwnerName( gameObject ) ?? actorName ?? new Utf8String( gameObject->Name ).ToString();
|
?? GetOwnerName( gameObject ) ?? actorName ?? new Utf8String( gameObject->Name ).ToString();
|
||||||
|
|
||||||
// First check temporary character collections, then the own configuration.
|
// First check temporary character collections, then the own configuration, then special collections.
|
||||||
return CollectionByActorName( actualName, out var c ) ? c : Penumbra.CollectionManager.Default;
|
return CollectionByActorName( actualName, out var c )
|
||||||
|
? c
|
||||||
|
: CollectionByActor( actualName, gameObject, out c )
|
||||||
|
? c
|
||||||
|
: Penumbra.CollectionManager.Default;
|
||||||
}
|
}
|
||||||
catch( Exception e )
|
catch( Exception e )
|
||||||
{
|
{
|
||||||
|
|
@ -335,11 +340,75 @@ public unsafe partial class PathResolver
|
||||||
=> Penumbra.TempMods.Collections.TryGetValue( name, out collection )
|
=> Penumbra.TempMods.Collections.TryGetValue( name, out collection )
|
||||||
|| Penumbra.CollectionManager.Characters.TryGetValue( name, out collection );
|
|| Penumbra.CollectionManager.Characters.TryGetValue( name, out collection );
|
||||||
|
|
||||||
|
// Check special collections given the actor.
|
||||||
|
private static bool CollectionByActor( string name, GameObject* actor, [NotNullWhen( true )] out ModCollection? collection )
|
||||||
|
{
|
||||||
|
collection = null;
|
||||||
|
// Check for the Yourself collection.
|
||||||
|
if( actor->ObjectIndex == 0 || name == Dalamud.ClientState.LocalPlayer?.Name.ToString() )
|
||||||
|
{
|
||||||
|
collection = Penumbra.CollectionManager.ByType( CollectionType.Yourself );
|
||||||
|
if( collection != null )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( actor->IsCharacter() )
|
||||||
|
{
|
||||||
|
var character = ( Character* )actor;
|
||||||
|
// Only handle human models.
|
||||||
|
if( character->ModelCharaId == 0 )
|
||||||
|
{
|
||||||
|
// Check if the object is a non-player human NPC.
|
||||||
|
if( actor->ObjectKind != ( byte )ObjectKind.Player )
|
||||||
|
{
|
||||||
|
collection = Penumbra.CollectionManager.ByType( CollectionType.NonPlayerCharacter );
|
||||||
|
if( collection != null )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Check the subrace. If it does not fit any or no subrace collection is set, check the player character collection.
|
||||||
|
collection = ( SubRace )( ( Character* )actor )->CustomizeData[ 4 ] switch
|
||||||
|
{
|
||||||
|
SubRace.Midlander => Penumbra.CollectionManager.ByType( CollectionType.Midlander ),
|
||||||
|
SubRace.Highlander => Penumbra.CollectionManager.ByType( CollectionType.Highlander ),
|
||||||
|
SubRace.Wildwood => Penumbra.CollectionManager.ByType( CollectionType.Wildwood ),
|
||||||
|
SubRace.Duskwight => Penumbra.CollectionManager.ByType( CollectionType.Duskwight ),
|
||||||
|
SubRace.Plainsfolk => Penumbra.CollectionManager.ByType( CollectionType.Plainsfolk ),
|
||||||
|
SubRace.Dunesfolk => Penumbra.CollectionManager.ByType( CollectionType.Dunesfolk ),
|
||||||
|
SubRace.SeekerOfTheSun => Penumbra.CollectionManager.ByType( CollectionType.SeekerOfTheSun ),
|
||||||
|
SubRace.KeeperOfTheMoon => Penumbra.CollectionManager.ByType( CollectionType.KeeperOfTheMoon ),
|
||||||
|
SubRace.Seawolf => Penumbra.CollectionManager.ByType( CollectionType.Seawolf ),
|
||||||
|
SubRace.Hellsguard => Penumbra.CollectionManager.ByType( CollectionType.Hellsguard ),
|
||||||
|
SubRace.Raen => Penumbra.CollectionManager.ByType( CollectionType.Raen ),
|
||||||
|
SubRace.Xaela => Penumbra.CollectionManager.ByType( CollectionType.Xaela ),
|
||||||
|
SubRace.Helion => Penumbra.CollectionManager.ByType( CollectionType.Helion ),
|
||||||
|
SubRace.Lost => Penumbra.CollectionManager.ByType( CollectionType.Lost ),
|
||||||
|
SubRace.Rava => Penumbra.CollectionManager.ByType( CollectionType.Rava ),
|
||||||
|
SubRace.Veena => Penumbra.CollectionManager.ByType( CollectionType.Veena ),
|
||||||
|
_ => null,
|
||||||
|
};
|
||||||
|
collection ??= Penumbra.CollectionManager.ByType( CollectionType.PlayerCharacter );
|
||||||
|
if( collection != null )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Update collections linked to Game/DrawObjects due to a change in collection configuration.
|
// Update collections linked to Game/DrawObjects due to a change in collection configuration.
|
||||||
private void CheckCollections( ModCollection.Type type, ModCollection? _1, ModCollection? _2, string? name )
|
private void CheckCollections( CollectionType type, ModCollection? _1, ModCollection? _2, string? name )
|
||||||
{
|
{
|
||||||
if( type is not (ModCollection.Type.Character or ModCollection.Type.Default) )
|
if( type is not (CollectionType.Character or CollectionType.Default) )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -324,23 +324,34 @@ public class Penumbra : IDisposable
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch( type )
|
foreach( var t in Enum.GetValues< CollectionType >() )
|
||||||
{
|
{
|
||||||
case "default":
|
if( t is CollectionType.Inactive or CollectionType.Character
|
||||||
if( collection == CollectionManager.Default )
|
|| !string.Equals( t.ToString(), type, StringComparison.OrdinalIgnoreCase ) )
|
||||||
{
|
{
|
||||||
Dalamud.Chat.Print( $"{collection.Name} already is the default collection." );
|
continue;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
CollectionManager.SetCollection( collection, ModCollection.Type.Default );
|
var oldCollection = CollectionManager.ByType( t );
|
||||||
Dalamud.Chat.Print( $"Set {collection.Name} as default collection." );
|
if( collection == oldCollection )
|
||||||
return true;
|
{
|
||||||
default:
|
Dalamud.Chat.Print( $"{collection.Name} already is the {t.ToName()} Collection." );
|
||||||
Dalamud.Chat.Print(
|
|
||||||
"Second command argument is not default, the correct command format is: /penumbra collection default <collectionName>" );
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( oldCollection == null && t.IsSpecial() )
|
||||||
|
{
|
||||||
|
CollectionManager.CreateSpecialCollection( t );
|
||||||
|
}
|
||||||
|
|
||||||
|
CollectionManager.SetCollection( collection, t, null );
|
||||||
|
Dalamud.Chat.Print( $"Set {collection.Name} as {t.ToName()} Collection." );
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Dalamud.Chat.Print(
|
||||||
|
"Second command argument is not default, the correct command format is: /penumbra collection <collectionType> <collectionName>" );
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnCommand( string command, string rawArgs )
|
private void OnCommand( string command, string rawArgs )
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod
|
||||||
Penumbra.ModManager.ModMetaChanged += OnModMetaChange;
|
Penumbra.ModManager.ModMetaChanged += OnModMetaChange;
|
||||||
Penumbra.ModManager.ModDiscoveryStarted += StoreCurrentSelection;
|
Penumbra.ModManager.ModDiscoveryStarted += StoreCurrentSelection;
|
||||||
Penumbra.ModManager.ModDiscoveryFinished += RestoreLastSelection;
|
Penumbra.ModManager.ModDiscoveryFinished += RestoreLastSelection;
|
||||||
OnCollectionChange( ModCollection.Type.Current, null, Penumbra.CollectionManager.Current, null );
|
OnCollectionChange( CollectionType.Current, null, Penumbra.CollectionManager.Current, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Dispose()
|
public override void Dispose()
|
||||||
|
|
@ -354,9 +354,9 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod
|
||||||
OnSelectionChange( Selected, Selected, default );
|
OnSelectionChange( Selected, Selected, default );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnCollectionChange( ModCollection.Type type, ModCollection? oldCollection, ModCollection? newCollection, string? _ )
|
private void OnCollectionChange( CollectionType collectionType, ModCollection? oldCollection, ModCollection? newCollection, string? _ )
|
||||||
{
|
{
|
||||||
if( type != ModCollection.Type.Current || oldCollection == newCollection )
|
if( collectionType != CollectionType.Current || oldCollection == newCollection )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ public partial class ConfigWindow
|
||||||
{
|
{
|
||||||
if( _newCurrentCollection != null )
|
if( _newCurrentCollection != null )
|
||||||
{
|
{
|
||||||
Penumbra.CollectionManager.SetCollection( _newCurrentCollection, ModCollection.Type.Current );
|
Penumbra.CollectionManager.SetCollection( _newCurrentCollection, CollectionType.Current );
|
||||||
_newCurrentCollection = null;
|
_newCurrentCollection = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using ImGuiNET;
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
using OtterGui.Raii;
|
using OtterGui.Raii;
|
||||||
using Penumbra.Collections;
|
using Penumbra.Collections;
|
||||||
|
using Penumbra.Util;
|
||||||
|
|
||||||
namespace Penumbra.UI;
|
namespace Penumbra.UI;
|
||||||
|
|
||||||
|
|
@ -33,9 +34,10 @@ public partial class ConfigWindow
|
||||||
|
|
||||||
|
|
||||||
// Input text fields.
|
// Input text fields.
|
||||||
private string _newCollectionName = string.Empty;
|
private string _newCollectionName = string.Empty;
|
||||||
private bool _canAddCollection = false;
|
private bool _canAddCollection = false;
|
||||||
private string _newCharacterName = string.Empty;
|
private string _newCharacterName = string.Empty;
|
||||||
|
private CollectionType? _currentType = CollectionType.Yourself;
|
||||||
|
|
||||||
// Create a new collection that is either empty or a duplicate of the current collection.
|
// Create a new collection that is either empty or a duplicate of the current collection.
|
||||||
// Resets the new collection name.
|
// Resets the new collection name.
|
||||||
|
|
@ -104,7 +106,7 @@ public partial class ConfigWindow
|
||||||
|
|
||||||
private void DrawCurrentCollectionSelector()
|
private void DrawCurrentCollectionSelector()
|
||||||
{
|
{
|
||||||
DrawCollectionSelector( "##current", _window._inputTextWidth.X, ModCollection.Type.Current, false, null );
|
DrawCollectionSelector( "##current", _window._inputTextWidth.X, CollectionType.Current, false, null );
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGuiUtil.LabeledHelpMarker( "Current Collection",
|
ImGuiUtil.LabeledHelpMarker( "Current Collection",
|
||||||
"This collection will be modified when using the Installed Mods tab and making changes. It does not apply to anything by itself." );
|
"This collection will be modified when using the Installed Mods tab and making changes. It does not apply to anything by itself." );
|
||||||
|
|
@ -112,12 +114,56 @@ public partial class ConfigWindow
|
||||||
|
|
||||||
private void DrawDefaultCollectionSelector()
|
private void DrawDefaultCollectionSelector()
|
||||||
{
|
{
|
||||||
DrawCollectionSelector( "##default", _window._inputTextWidth.X, ModCollection.Type.Default, true, null );
|
DrawCollectionSelector( "##default", _window._inputTextWidth.X, CollectionType.Default, true, null );
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGuiUtil.LabeledHelpMarker( "Default Collection",
|
ImGuiUtil.LabeledHelpMarker( "Default Collection",
|
||||||
"Mods in the default collection are loaded for any character that is not explicitly named in the character collections below.\n" );
|
"Mods in the default collection are loaded for any character that is not explicitly named in the character collections below.\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We do not check for valid character names.
|
||||||
|
private void DrawNewSpecialCollection()
|
||||||
|
{
|
||||||
|
const string description = "Special Collections apply to certain types of characters.\n"
|
||||||
|
+ "All of them take precedence before the Default collection,\n"
|
||||||
|
+ "but all character collections take precedence before them.";
|
||||||
|
|
||||||
|
ImGui.SetNextItemWidth( _window._inputTextWidth.X );
|
||||||
|
if( _currentType == null || Penumbra.CollectionManager.ByType( _currentType.Value ) != null )
|
||||||
|
{
|
||||||
|
_currentType = CollectionTypeExtensions.Special.FindFirst( t => Penumbra.CollectionManager.ByType( t ) == null, out var t2 )
|
||||||
|
? t2
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( _currentType == null )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using( var combo = ImRaii.Combo( "##NewSpecial", _currentType.Value.ToName() ) )
|
||||||
|
{
|
||||||
|
if( combo )
|
||||||
|
{
|
||||||
|
foreach( var type in CollectionTypeExtensions.Special.Where( t => Penumbra.CollectionManager.ByType( t ) == null ) )
|
||||||
|
{
|
||||||
|
if( ImGui.Selectable( type.ToName(), type == _currentType.Value ) )
|
||||||
|
{
|
||||||
|
_currentType = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
var disabled = _currentType == null;
|
||||||
|
var tt = disabled ? "Please select a special collection type before creating the collection.\n\n" + description : description;
|
||||||
|
if( ImGuiUtil.DrawDisabledButton( "Create New Special Collection", Vector2.Zero, tt, disabled ) )
|
||||||
|
{
|
||||||
|
Penumbra.CollectionManager.CreateSpecialCollection( _currentType!.Value );
|
||||||
|
_currentType = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We do not check for valid character names.
|
// We do not check for valid character names.
|
||||||
private void DrawNewCharacterCollection()
|
private void DrawNewCharacterCollection()
|
||||||
{
|
{
|
||||||
|
|
@ -145,14 +191,36 @@ public partial class ConfigWindow
|
||||||
ImGui.Dummy( _window._defaultSpace );
|
ImGui.Dummy( _window._defaultSpace );
|
||||||
DrawDefaultCollectionSelector();
|
DrawDefaultCollectionSelector();
|
||||||
ImGui.Dummy( _window._defaultSpace );
|
ImGui.Dummy( _window._defaultSpace );
|
||||||
|
foreach( var type in CollectionTypeExtensions.Special )
|
||||||
|
{
|
||||||
|
var collection = Penumbra.CollectionManager.ByType( type );
|
||||||
|
if( collection != null )
|
||||||
|
{
|
||||||
|
using var id = ImRaii.PushId( ( int )type );
|
||||||
|
DrawCollectionSelector( string.Empty, _window._inputTextWidth.X, type, true, null );
|
||||||
|
ImGui.SameLine();
|
||||||
|
if( ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.Trash.ToIconString(), _window._iconButtonSize, string.Empty,
|
||||||
|
false, true ) )
|
||||||
|
{
|
||||||
|
Penumbra.CollectionManager.RemoveSpecialCollection( type );
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.AlignTextToFramePadding();
|
||||||
|
ImGuiUtil.LabeledHelpMarker( type.ToName(), type.ToDescription() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawNewSpecialCollection();
|
||||||
|
ImGui.Dummy( _window._defaultSpace );
|
||||||
|
|
||||||
foreach( var name in Penumbra.CollectionManager.Characters.Keys.OrderBy( k => k ).ToArray() )
|
foreach( var name in Penumbra.CollectionManager.Characters.Keys.OrderBy( k => k ).ToArray() )
|
||||||
{
|
{
|
||||||
using var id = ImRaii.PushId( name );
|
using var id = ImRaii.PushId( name );
|
||||||
DrawCollectionSelector( string.Empty, _window._inputTextWidth.X, ModCollection.Type.Character, true, name );
|
DrawCollectionSelector( string.Empty, _window._inputTextWidth.X, CollectionType.Character, true, name );
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
if( ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.Trash.ToIconString(), _window._iconButtonSize, string.Empty,
|
if( ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.Trash.ToIconString(), _window._iconButtonSize, string.Empty,
|
||||||
false,
|
false, true ) )
|
||||||
true ) )
|
|
||||||
{
|
{
|
||||||
Penumbra.CollectionManager.RemoveCharacterCollection( name );
|
Penumbra.CollectionManager.RemoveCharacterCollection( name );
|
||||||
}
|
}
|
||||||
|
|
@ -163,7 +231,7 @@ public partial class ConfigWindow
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawNewCharacterCollection();
|
DrawNewCharacterCollection();
|
||||||
ImGui.NewLine();
|
ImGui.Dummy( _window._defaultSpace );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -93,18 +93,13 @@ public partial class ConfigWindow
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a collection selector of a certain width for a certain type.
|
// Draw a collection selector of a certain width for a certain type.
|
||||||
private static void DrawCollectionSelector( string label, float width, ModCollection.Type type, bool withEmpty, string? characterName )
|
private static void DrawCollectionSelector( string label, float width, CollectionType collectionType, bool withEmpty,
|
||||||
|
string? characterName )
|
||||||
{
|
{
|
||||||
ImGui.SetNextItemWidth( width );
|
ImGui.SetNextItemWidth( width );
|
||||||
var current = type switch
|
|
||||||
{
|
|
||||||
ModCollection.Type.Default => Penumbra.CollectionManager.Default,
|
|
||||||
ModCollection.Type.Character => Penumbra.CollectionManager.Character( characterName ?? string.Empty ),
|
|
||||||
ModCollection.Type.Current => Penumbra.CollectionManager.Current,
|
|
||||||
_ => throw new ArgumentOutOfRangeException( nameof( type ), type, null ),
|
|
||||||
};
|
|
||||||
|
|
||||||
using var combo = ImRaii.Combo( label, current.Name );
|
var current = Penumbra.CollectionManager.ByType( collectionType, characterName );
|
||||||
|
using var combo = ImRaii.Combo( label, current?.Name ?? string.Empty );
|
||||||
if( combo )
|
if( combo )
|
||||||
{
|
{
|
||||||
foreach( var collection in Penumbra.CollectionManager.GetEnumeratorWithEmpty().Skip( withEmpty ? 0 : 1 ).OrderBy( c => c.Name ) )
|
foreach( var collection in Penumbra.CollectionManager.GetEnumeratorWithEmpty().Skip( withEmpty ? 0 : 1 ).OrderBy( c => c.Name ) )
|
||||||
|
|
@ -112,7 +107,7 @@ public partial class ConfigWindow
|
||||||
using var id = ImRaii.PushId( collection.Index );
|
using var id = ImRaii.PushId( collection.Index );
|
||||||
if( ImGui.Selectable( collection.Name, collection == current ) )
|
if( ImGui.Selectable( collection.Name, collection == current ) )
|
||||||
{
|
{
|
||||||
Penumbra.CollectionManager.SetCollection( collection, type, characterName );
|
Penumbra.CollectionManager.SetCollection( collection, collectionType, characterName );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -140,7 +135,7 @@ public partial class ConfigWindow
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add Penumbra Root. This is not updated if the root changes right now.
|
// Add Penumbra Root. This is not updated if the root changes right now.
|
||||||
fileManager.CustomSideBarItems.Add( ("Root Directory", Penumbra.Config.ModDirectory, FontAwesomeIcon.Gamepad, 0) );
|
fileManager.CustomSideBarItems.Add( ( "Root Directory", Penumbra.Config.ModDirectory, FontAwesomeIcon.Gamepad, 0 ) );
|
||||||
|
|
||||||
// Remove Videos and Music.
|
// Remove Videos and Music.
|
||||||
fileManager.CustomSideBarItems.Add( ( "Videos", string.Empty, 0, -1 ) );
|
fileManager.CustomSideBarItems.Add( ( "Videos", string.Empty, 0, -1 ) );
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ public partial class ConfigWindow
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
DrawInheritedCollectionButton( 3 * buttonSize );
|
DrawInheritedCollectionButton( 3 * buttonSize );
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
DrawCollectionSelector( "##collectionSelector", 2 * buttonSize.X, ModCollection.Type.Current, false, null );
|
DrawCollectionSelector( "##collectionSelector", 2 * buttonSize.X, CollectionType.Current, false, null );
|
||||||
if( !Penumbra.CollectionManager.CurrentCollectionInUse )
|
if( !Penumbra.CollectionManager.CurrentCollectionInUse )
|
||||||
{
|
{
|
||||||
ImGuiUtil.DrawTextButton( "The currently selected collection is not used in any way.", -Vector2.UnitX, Colors.PressEnterWarningBg );
|
ImGuiUtil.DrawTextButton( "The currently selected collection is not used in any way.", -Vector2.UnitX, Colors.PressEnterWarningBg );
|
||||||
|
|
@ -79,7 +79,7 @@ public partial class ConfigWindow
|
||||||
: "Set the current collection to the configured default collection.";
|
: "Set the current collection to the configured default collection.";
|
||||||
if( ImGuiUtil.DrawDisabledButton( name, width, tt, isCurrent || isEmpty ) )
|
if( ImGuiUtil.DrawDisabledButton( name, width, tt, isCurrent || isEmpty ) )
|
||||||
{
|
{
|
||||||
Penumbra.CollectionManager.SetCollection( Penumbra.CollectionManager.Default, ModCollection.Type.Current );
|
Penumbra.CollectionManager.SetCollection( Penumbra.CollectionManager.Default, CollectionType.Current );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,7 +97,7 @@ public partial class ConfigWindow
|
||||||
};
|
};
|
||||||
if( ImGuiUtil.DrawDisabledButton( name, width, tt, noModSelected || !modInherited ) )
|
if( ImGuiUtil.DrawDisabledButton( name, width, tt, noModSelected || !modInherited ) )
|
||||||
{
|
{
|
||||||
Penumbra.CollectionManager.SetCollection( collection, ModCollection.Type.Current );
|
Penumbra.CollectionManager.SetCollection( collection, CollectionType.Current );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue