Rework special actor identification again.

This commit is contained in:
Ottermandias 2022-12-04 16:25:38 +01:00
parent 63a22198aa
commit 9af7e9d948
5 changed files with 55 additions and 37 deletions

View file

@ -121,7 +121,8 @@ public partial class ActorManager
if (idx is >= (ushort)SpecialActor.CharacterScreen and <= (ushort)SpecialActor.Portrait) if (idx is >= (ushort)SpecialActor.CharacterScreen and <= (ushort)SpecialActor.Portrait)
return CreateIndividualUnchecked(IdentifierType.Special, ByteString.Empty, idx, ObjectKind.None, uint.MaxValue); return CreateIndividualUnchecked(IdentifierType.Special, ByteString.Empty, idx, ObjectKind.None, uint.MaxValue);
switch ((ObjectKind)actor->ObjectKind) var kind = (ObjectKind)actor->ObjectKind;
switch (kind)
{ {
case ObjectKind.Player: case ObjectKind.Player:
{ {
@ -193,7 +194,6 @@ public partial class ActorManager
var dataId = GetCompanionId(actor, owner); var dataId = GetCompanionId(actor, owner);
var name = new ByteString(owner->Name); var name = new ByteString(owner->Name);
var homeWorld = ((Character*)owner)->HomeWorld; var homeWorld = ((Character*)owner)->HomeWorld;
var kind = (ObjectKind)actor->ObjectKind;
return check return check
? CreateOwned(name, homeWorld, kind, dataId) ? CreateOwned(name, homeWorld, kind, dataId)
: CreateIndividualUnchecked(IdentifierType.Owned, name, homeWorld, kind, dataId); : CreateIndividualUnchecked(IdentifierType.Owned, name, homeWorld, kind, dataId);

View file

@ -333,7 +333,7 @@ public class PenumbraApi : IDisposable, IPenumbraApi
public (string, bool) GetCharacterCollection( string characterName, ushort worldId ) public (string, bool) GetCharacterCollection( string characterName, ushort worldId )
{ {
CheckInitialized(); CheckInitialized();
return Penumbra.CollectionManager.Individuals.TryGetCollection( NameToIdentifier( characterName, worldId ), out var collection, out _ ) return Penumbra.CollectionManager.Individuals.TryGetCollection( NameToIdentifier( characterName, worldId ), out var collection )
? ( collection.Name, true ) ? ( collection.Name, true )
: ( Penumbra.CollectionManager.Default.Name, false ); : ( Penumbra.CollectionManager.Default.Name, false );
} }
@ -807,7 +807,7 @@ public class PenumbraApi : IDisposable, IPenumbraApi
{ {
CheckInitialized(); CheckInitialized();
var identifier = NameToIdentifier( characterName, worldId ); var identifier = NameToIdentifier( characterName, worldId );
var collection = Penumbra.TempMods.Collections.TryGetCollection( identifier, out var c, out _ ) var collection = Penumbra.TempMods.Collections.TryGetCollection( identifier, out var c )
? c ? c
: Penumbra.CollectionManager.Individual( identifier ); : Penumbra.CollectionManager.Individual( identifier );
var set = collection.MetaCache?.Manipulations.ToArray() ?? Array.Empty< MetaManipulation >(); var set = collection.MetaCache?.Manipulations.ToArray() ?? Array.Empty< MetaManipulation >();

View file

@ -42,7 +42,7 @@ public partial class ModCollection
public readonly IndividualCollections Individuals = new(Penumbra.Actors); public readonly IndividualCollections Individuals = new(Penumbra.Actors);
public ModCollection Individual( ActorIdentifier identifier ) public ModCollection Individual( ActorIdentifier identifier )
=> Individuals.TryGetCollection( identifier, out var c, out _ ) ? c : Default; => Individuals.TryGetCollection( identifier, out var c ) ? c : Default;
// Special Collections // Special Collections
private readonly ModCollection?[] _specialCollections = new ModCollection?[Enum.GetValues< CollectionType >().Length - 4]; private readonly ModCollection?[] _specialCollections = new ModCollection?[Enum.GetValues< CollectionType >().Length - 4];
@ -64,7 +64,7 @@ public partial class ModCollection
CollectionType.Default => Default, CollectionType.Default => Default,
CollectionType.Interface => Interface, CollectionType.Interface => Interface,
CollectionType.Current => Current, CollectionType.Current => Current,
CollectionType.Individual => identifier.IsValid ? Individuals.TryGetCollection( identifier, out var c, out _ ) ? c : null : null, CollectionType.Individual => identifier.IsValid ? Individuals.TryGetCollection( identifier, out var c ) ? c : null : null,
_ => null, _ => null,
}; };
} }

View file

@ -23,9 +23,8 @@ public sealed partial class IndividualCollections : IReadOnlyList< (string Displ
public (string DisplayName, ModCollection Collection) this[ int index ] public (string DisplayName, ModCollection Collection) this[ int index ]
=> ( _assignments[ index ].DisplayName, _assignments[ index ].Collection ); => ( _assignments[ index ].DisplayName, _assignments[ index ].Collection );
public bool TryGetCollection( ActorIdentifier identifier, [NotNullWhen( true )] out ModCollection? collection, out ActorIdentifier specialIdentifier ) public bool TryGetCollection( ActorIdentifier identifier, [NotNullWhen( true )] out ModCollection? collection )
{ {
specialIdentifier = ActorIdentifier.Invalid;
if( Count == 0 ) if( Count == 0 )
{ {
collection = null; collection = null;
@ -72,35 +71,53 @@ public sealed partial class IndividualCollections : IReadOnlyList< (string Displ
return false; return false;
} }
case IdentifierType.Npc: return _individuals.TryGetValue( identifier, out collection ); case IdentifierType.Npc: return _individuals.TryGetValue( identifier, out collection );
case IdentifierType.Special: case IdentifierType.Special: return CheckWorlds( ConvertSpecialIdentifier( identifier ), out collection );
switch( identifier.Special )
{
case SpecialActor.CharacterScreen when Penumbra.Config.UseCharacterCollectionInMainWindow:
case SpecialActor.FittingRoom when Penumbra.Config.UseCharacterCollectionInTryOn:
case SpecialActor.DyePreview when Penumbra.Config.UseCharacterCollectionInTryOn:
case SpecialActor.Portrait when Penumbra.Config.UseCharacterCollectionsInCards:
return CheckWorlds( specialIdentifier = _actorManager.GetCurrentPlayer(), out collection );
case SpecialActor.ExamineScreen:
{
return CheckWorlds( specialIdentifier = _actorManager.GetInspectPlayer(), out collection! )
|| CheckWorlds( specialIdentifier = _actorManager.GetCardPlayer(), out collection! )
|| CheckWorlds( specialIdentifier = _actorManager.GetGlamourPlayer(), out collection! );
}
}
break;
} }
collection = null; collection = null;
return false; return false;
} }
public bool TryGetCollection( GameObject? gameObject, out ModCollection? collection, out ActorIdentifier specialIdentifier ) public ActorIdentifier ConvertSpecialIdentifier( ActorIdentifier identifier )
=> TryGetCollection( _actorManager.FromObject( gameObject, false ), out collection, out specialIdentifier ); {
if( identifier.Type != IdentifierType.Special )
{
return identifier;
}
public unsafe bool TryGetCollection( FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* gameObject, out ModCollection? collection, out ActorIdentifier specialIdentifier ) switch( identifier.Special )
=> TryGetCollection( _actorManager.FromObject( gameObject, out _, false ), out collection, out specialIdentifier ); {
case SpecialActor.CharacterScreen when Penumbra.Config.UseCharacterCollectionInMainWindow:
case SpecialActor.FittingRoom when Penumbra.Config.UseCharacterCollectionInTryOn:
case SpecialActor.DyePreview when Penumbra.Config.UseCharacterCollectionInTryOn:
case SpecialActor.Portrait when Penumbra.Config.UseCharacterCollectionsInCards:
return _actorManager.GetCurrentPlayer();
case SpecialActor.ExamineScreen:
{
identifier = _actorManager.GetInspectPlayer();
if( identifier.IsValid )
{
return identifier;
}
identifier = _actorManager.GetCardPlayer();
if( identifier.IsValid )
{
return identifier;
}
return _actorManager.GetGlamourPlayer();
}
default: return identifier;
}
}
public bool TryGetCollection( GameObject? gameObject, out ModCollection? collection )
=> TryGetCollection( _actorManager.FromObject( gameObject, false ), out collection );
public unsafe bool TryGetCollection( FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* gameObject, out ModCollection? collection )
=> TryGetCollection( _actorManager.FromObject( gameObject, out _, false ), out collection );
private bool CheckWorlds( ActorIdentifier identifier, out ModCollection? collection ) private bool CheckWorlds( ActorIdentifier identifier, out ModCollection? collection )
{ {

View file

@ -44,8 +44,9 @@ public unsafe partial class PathResolver
else else
{ {
var identifier = Penumbra.Actors.FromObject( gameObject, out var owner, false ); var identifier = Penumbra.Actors.FromObject( gameObject, out var owner, false );
var collection = CollectionByIdentifier( identifier, out var specialIdentifier ) identifier = Penumbra.CollectionManager.Individuals.ConvertSpecialIdentifier( identifier );
?? CheckYourself( identifier.Type == IdentifierType.Special ? specialIdentifier : identifier, gameObject ) var collection = CollectionByIdentifier( identifier )
?? CheckYourself( identifier, gameObject )
?? CollectionByAttributes( gameObject ) ?? CollectionByAttributes( gameObject )
?? CheckOwnedCollection( identifier, owner ) ?? CheckOwnedCollection( identifier, owner )
?? Penumbra.CollectionManager.Default; ?? Penumbra.CollectionManager.Default;
@ -71,16 +72,16 @@ public unsafe partial class PathResolver
} }
var player = Penumbra.Actors.GetCurrentPlayer(); var player = Penumbra.Actors.GetCurrentPlayer();
return CollectionByIdentifier( player, out _ ) return CollectionByIdentifier( player )
?? CheckYourself( player, gameObject ) ?? CheckYourself( player, gameObject )
?? CollectionByAttributes( gameObject ) ?? CollectionByAttributes( gameObject )
?? Penumbra.CollectionManager.Default; ?? Penumbra.CollectionManager.Default;
} }
// Check both temporary and permanent character collections. Temporary first. // Check both temporary and permanent character collections. Temporary first.
private static ModCollection? CollectionByIdentifier( ActorIdentifier identifier, out ActorIdentifier specialIdentifier ) private static ModCollection? CollectionByIdentifier( ActorIdentifier identifier )
=> Penumbra.TempMods.Collections.TryGetCollection( identifier, out var collection, out specialIdentifier ) => Penumbra.TempMods.Collections.TryGetCollection( identifier, out var collection )
|| Penumbra.CollectionManager.Individuals.TryGetCollection( identifier, out collection, out specialIdentifier ) || Penumbra.CollectionManager.Individuals.TryGetCollection( identifier, out collection )
? collection ? collection
: null; : null;
@ -143,7 +144,7 @@ public unsafe partial class PathResolver
{ {
var sheet = gameData.GetExcelSheet< ModelChara >()!; var sheet = gameData.GetExcelSheet< ModelChara >()!;
var ret = new BitArray( ( int )sheet.RowCount, false ); var ret = new BitArray( ( int )sheet.RowCount, false );
foreach( var (row, idx) in sheet.WithIndex().Where( p => p.Value.Type == ( byte )CharacterBase.ModelType.Human ) ) foreach( var (_, idx) in sheet.WithIndex().Where( p => p.Value.Type == ( byte )CharacterBase.ModelType.Human ) )
{ {
ret[ idx ] = true; ret[ idx ] = true;
} }