mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-14 20:54:16 +01:00
Added an event when a newly created draw object finishes CharacterBase.Create.
This commit is contained in:
parent
5b5a1e2fd8
commit
80edfe7804
6 changed files with 54 additions and 153 deletions
|
|
@ -26,6 +26,8 @@ public delegate void ModSettingChanged( ModSettingChange type, string collection
|
||||||
public delegate void CreatingCharacterBaseDelegate( IntPtr gameObject, ModCollection collection, IntPtr modelId, IntPtr customize,
|
public delegate void CreatingCharacterBaseDelegate( IntPtr gameObject, ModCollection collection, IntPtr modelId, IntPtr customize,
|
||||||
IntPtr equipData );
|
IntPtr equipData );
|
||||||
|
|
||||||
|
public delegate void CreatedCharacterBaseDelegate( IntPtr gameObject, ModCollection collection, IntPtr drawObject );
|
||||||
|
|
||||||
public enum PenumbraApiEc
|
public enum PenumbraApiEc
|
||||||
{
|
{
|
||||||
Success = 0,
|
Success = 0,
|
||||||
|
|
@ -73,6 +75,10 @@ public interface IPenumbraApi : IPenumbraApiBase
|
||||||
// before the Draw Object is actually created, so customize and equipdata can be manipulated beforehand.
|
// before the Draw Object is actually created, so customize and equipdata can be manipulated beforehand.
|
||||||
public event CreatingCharacterBaseDelegate? CreatingCharacterBase;
|
public event CreatingCharacterBaseDelegate? CreatingCharacterBase;
|
||||||
|
|
||||||
|
// Triggered after a character base was created if a corresponding gameObject could be found,
|
||||||
|
// so you can apply flag changes after finishing.
|
||||||
|
public event CreatedCharacterBaseDelegate? CreatedCharacterBase;
|
||||||
|
|
||||||
// Queue redrawing of all actors of the given name with the given RedrawType.
|
// Queue redrawing of all actors of the given name with the given RedrawType.
|
||||||
public void RedrawObject( string name, RedrawType setting );
|
public void RedrawObject( string name, RedrawType setting );
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,8 @@ public class IpcTester : IDisposable
|
||||||
private readonly ICallGateSubscriber< string, bool, object? > _modDirectoryChanged;
|
private readonly ICallGateSubscriber< string, bool, object? > _modDirectoryChanged;
|
||||||
private readonly ICallGateSubscriber< IntPtr, int, object? > _redrawn;
|
private readonly ICallGateSubscriber< IntPtr, int, object? > _redrawn;
|
||||||
private readonly ICallGateSubscriber< ModSettingChange, string, string, bool, object? > _settingChanged;
|
private readonly ICallGateSubscriber< ModSettingChange, string, string, bool, object? > _settingChanged;
|
||||||
private readonly ICallGateSubscriber< IntPtr, string, IntPtr, IntPtr, IntPtr, object? > _characterBaseCreated;
|
private readonly ICallGateSubscriber< IntPtr, string, IntPtr, IntPtr, IntPtr, object? > _characterBaseCreating;
|
||||||
|
private readonly ICallGateSubscriber< IntPtr, string, IntPtr, object? > _characterBaseCreated;
|
||||||
|
|
||||||
private readonly List< DateTimeOffset > _initializedList = new();
|
private readonly List< DateTimeOffset > _initializedList = new();
|
||||||
private readonly List< DateTimeOffset > _disposedList = new();
|
private readonly List< DateTimeOffset > _disposedList = new();
|
||||||
|
|
@ -47,15 +48,17 @@ public class IpcTester : IDisposable
|
||||||
_postSettingsDraw = _pi.GetIpcSubscriber< string, object? >( PenumbraIpc.LabelProviderPostSettingsDraw );
|
_postSettingsDraw = _pi.GetIpcSubscriber< string, object? >( PenumbraIpc.LabelProviderPostSettingsDraw );
|
||||||
_settingChanged = _pi.GetIpcSubscriber< ModSettingChange, string, string, bool, object? >( PenumbraIpc.LabelProviderModSettingChanged );
|
_settingChanged = _pi.GetIpcSubscriber< ModSettingChange, string, string, bool, object? >( PenumbraIpc.LabelProviderModSettingChanged );
|
||||||
_modDirectoryChanged = _pi.GetIpcSubscriber< string, bool, object? >( PenumbraIpc.LabelProviderModDirectoryChanged );
|
_modDirectoryChanged = _pi.GetIpcSubscriber< string, bool, object? >( PenumbraIpc.LabelProviderModDirectoryChanged );
|
||||||
_characterBaseCreated =
|
_characterBaseCreating =
|
||||||
_pi.GetIpcSubscriber< IntPtr, string, IntPtr, IntPtr, IntPtr, object? >( PenumbraIpc.LabelProviderCreatingCharacterBase );
|
_pi.GetIpcSubscriber< IntPtr, string, IntPtr, IntPtr, IntPtr, object? >( PenumbraIpc.LabelProviderCreatingCharacterBase );
|
||||||
|
_characterBaseCreated = _pi.GetIpcSubscriber< IntPtr, string, IntPtr, object? >( PenumbraIpc.LabelProviderCreatedCharacterBase );
|
||||||
_initialized.Subscribe( AddInitialized );
|
_initialized.Subscribe( AddInitialized );
|
||||||
_disposed.Subscribe( AddDisposed );
|
_disposed.Subscribe( AddDisposed );
|
||||||
_redrawn.Subscribe( SetLastRedrawn );
|
_redrawn.Subscribe( SetLastRedrawn );
|
||||||
_preSettingsDraw.Subscribe( UpdateLastDrawnMod );
|
_preSettingsDraw.Subscribe( UpdateLastDrawnMod );
|
||||||
_postSettingsDraw.Subscribe( UpdateLastDrawnMod );
|
_postSettingsDraw.Subscribe( UpdateLastDrawnMod );
|
||||||
_settingChanged.Subscribe( UpdateLastModSetting );
|
_settingChanged.Subscribe( UpdateLastModSetting );
|
||||||
_characterBaseCreated.Subscribe( UpdateLastCreated );
|
_characterBaseCreating.Subscribe( UpdateLastCreated );
|
||||||
|
_characterBaseCreated.Subscribe( UpdateLastCreated2 );
|
||||||
_modDirectoryChanged.Subscribe( UpdateModDirectoryChanged );
|
_modDirectoryChanged.Subscribe( UpdateModDirectoryChanged );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,7 +72,8 @@ public class IpcTester : IDisposable
|
||||||
_preSettingsDraw.Unsubscribe( UpdateLastDrawnMod );
|
_preSettingsDraw.Unsubscribe( UpdateLastDrawnMod );
|
||||||
_postSettingsDraw.Unsubscribe( UpdateLastDrawnMod );
|
_postSettingsDraw.Unsubscribe( UpdateLastDrawnMod );
|
||||||
_settingChanged.Unsubscribe( UpdateLastModSetting );
|
_settingChanged.Unsubscribe( UpdateLastModSetting );
|
||||||
_characterBaseCreated.Unsubscribe( UpdateLastCreated );
|
_characterBaseCreating.Unsubscribe( UpdateLastCreated );
|
||||||
|
_characterBaseCreated.Unsubscribe( UpdateLastCreated2 );
|
||||||
_modDirectoryChanged.Unsubscribe( UpdateModDirectoryChanged );
|
_modDirectoryChanged.Unsubscribe( UpdateModDirectoryChanged );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -218,6 +222,7 @@ public class IpcTester : IDisposable
|
||||||
private IntPtr _currentDrawObject = IntPtr.Zero;
|
private IntPtr _currentDrawObject = IntPtr.Zero;
|
||||||
private int _currentCutsceneActor = 0;
|
private int _currentCutsceneActor = 0;
|
||||||
private string _lastCreatedGameObjectName = string.Empty;
|
private string _lastCreatedGameObjectName = string.Empty;
|
||||||
|
private IntPtr _lastCreatedDrawObject = IntPtr.Zero;
|
||||||
private DateTimeOffset _lastCreatedGameObjectTime = DateTimeOffset.MaxValue;
|
private DateTimeOffset _lastCreatedGameObjectTime = DateTimeOffset.MaxValue;
|
||||||
|
|
||||||
private unsafe void UpdateLastCreated( IntPtr gameObject, string _, IntPtr _2, IntPtr _3, IntPtr _4 )
|
private unsafe void UpdateLastCreated( IntPtr gameObject, string _, IntPtr _2, IntPtr _3, IntPtr _4 )
|
||||||
|
|
@ -225,6 +230,15 @@ public class IpcTester : IDisposable
|
||||||
var obj = ( FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* )gameObject;
|
var obj = ( FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* )gameObject;
|
||||||
_lastCreatedGameObjectName = new Utf8String( obj->GetName() ).ToString();
|
_lastCreatedGameObjectName = new Utf8String( obj->GetName() ).ToString();
|
||||||
_lastCreatedGameObjectTime = DateTimeOffset.Now;
|
_lastCreatedGameObjectTime = DateTimeOffset.Now;
|
||||||
|
_lastCreatedDrawObject = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe void UpdateLastCreated2( IntPtr gameObject, string _, IntPtr drawObject )
|
||||||
|
{
|
||||||
|
var obj = ( FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* )gameObject;
|
||||||
|
_lastCreatedGameObjectName = new Utf8String( obj->GetName() ).ToString();
|
||||||
|
_lastCreatedGameObjectTime = DateTimeOffset.Now;
|
||||||
|
_lastCreatedDrawObject = drawObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawResolve()
|
private void DrawResolve()
|
||||||
|
|
@ -318,7 +332,9 @@ public class IpcTester : IDisposable
|
||||||
DrawIntro( PenumbraIpc.LabelProviderCreatingCharacterBase, "Last Drawobject created" );
|
DrawIntro( PenumbraIpc.LabelProviderCreatingCharacterBase, "Last Drawobject created" );
|
||||||
if( _lastCreatedGameObjectTime < DateTimeOffset.Now )
|
if( _lastCreatedGameObjectTime < DateTimeOffset.Now )
|
||||||
{
|
{
|
||||||
ImGui.TextUnformatted( $"for <{_lastCreatedGameObjectName}> at {_lastCreatedGameObjectTime}" );
|
ImGui.TextUnformatted( _lastCreatedDrawObject != IntPtr.Zero
|
||||||
|
? $"0x{_lastCreatedDrawObject:X} for <{_lastCreatedGameObjectName}> at {_lastCreatedGameObjectTime}"
|
||||||
|
: $"NULL for <{_lastCreatedGameObjectName}> at {_lastCreatedGameObjectTime}" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,12 @@ public class PenumbraApi : IDisposable, IPenumbraApi
|
||||||
remove => PathResolver.DrawObjectState.CreatingCharacterBase -= value;
|
remove => PathResolver.DrawObjectState.CreatingCharacterBase -= value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public event CreatedCharacterBaseDelegate? CreatedCharacterBase
|
||||||
|
{
|
||||||
|
add => PathResolver.DrawObjectState.CreatedCharacterBase += value;
|
||||||
|
remove => PathResolver.DrawObjectState.CreatedCharacterBase -= value;
|
||||||
|
}
|
||||||
|
|
||||||
public bool Valid
|
public bool Valid
|
||||||
=> _penumbra != null;
|
=> _penumbra != null;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -282,6 +282,7 @@ public partial class PenumbraIpc
|
||||||
public const string LabelProviderReverseResolvePath = "Penumbra.ReverseResolvePath";
|
public const string LabelProviderReverseResolvePath = "Penumbra.ReverseResolvePath";
|
||||||
public const string LabelProviderReverseResolvePlayerPath = "Penumbra.ReverseResolvePlayerPath";
|
public const string LabelProviderReverseResolvePlayerPath = "Penumbra.ReverseResolvePlayerPath";
|
||||||
public const string LabelProviderCreatingCharacterBase = "Penumbra.CreatingCharacterBase";
|
public const string LabelProviderCreatingCharacterBase = "Penumbra.CreatingCharacterBase";
|
||||||
|
public const string LabelProviderCreatedCharacterBase = "Penumbra.CreatedCharacterBase";
|
||||||
|
|
||||||
internal ICallGateProvider< string, string >? ProviderResolveDefault;
|
internal ICallGateProvider< string, string >? ProviderResolveDefault;
|
||||||
internal ICallGateProvider< string, string, string >? ProviderResolveCharacter;
|
internal ICallGateProvider< string, string, string >? ProviderResolveCharacter;
|
||||||
|
|
@ -291,6 +292,7 @@ public partial class PenumbraIpc
|
||||||
internal ICallGateProvider< string, string, string[] >? ProviderReverseResolvePath;
|
internal ICallGateProvider< string, string, string[] >? ProviderReverseResolvePath;
|
||||||
internal ICallGateProvider< string, string[] >? ProviderReverseResolvePathPlayer;
|
internal ICallGateProvider< string, string[] >? ProviderReverseResolvePathPlayer;
|
||||||
internal ICallGateProvider< IntPtr, string, IntPtr, IntPtr, IntPtr, object? >? ProviderCreatingCharacterBase;
|
internal ICallGateProvider< IntPtr, string, IntPtr, IntPtr, IntPtr, object? >? ProviderCreatingCharacterBase;
|
||||||
|
internal ICallGateProvider< IntPtr, string, IntPtr, object? >? ProviderCreatedCharacterBase;
|
||||||
|
|
||||||
private void InitializeResolveProviders( DalamudPluginInterface pi )
|
private void InitializeResolveProviders( DalamudPluginInterface pi )
|
||||||
{
|
{
|
||||||
|
|
@ -374,6 +376,17 @@ public partial class PenumbraIpc
|
||||||
{
|
{
|
||||||
PluginLog.Error( $"Error registering IPC provider for {LabelProviderCreatingCharacterBase}:\n{e}" );
|
PluginLog.Error( $"Error registering IPC provider for {LabelProviderCreatingCharacterBase}:\n{e}" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ProviderCreatedCharacterBase =
|
||||||
|
pi.GetIpcProvider< IntPtr, string, IntPtr, object? >( LabelProviderCreatedCharacterBase );
|
||||||
|
Api.CreatedCharacterBase += CreatedCharacterBaseEvent;
|
||||||
|
}
|
||||||
|
catch( Exception e )
|
||||||
|
{
|
||||||
|
PluginLog.Error( $"Error registering IPC provider for {LabelProviderCreatedCharacterBase}:\n{e}" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DisposeResolveProviders()
|
private void DisposeResolveProviders()
|
||||||
|
|
@ -385,12 +398,18 @@ public partial class PenumbraIpc
|
||||||
ProviderReverseResolvePath?.UnregisterFunc();
|
ProviderReverseResolvePath?.UnregisterFunc();
|
||||||
ProviderReverseResolvePathPlayer?.UnregisterFunc();
|
ProviderReverseResolvePathPlayer?.UnregisterFunc();
|
||||||
Api.CreatingCharacterBase -= CreatingCharacterBaseEvent;
|
Api.CreatingCharacterBase -= CreatingCharacterBaseEvent;
|
||||||
|
Api.CreatedCharacterBase -= CreatedCharacterBaseEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreatingCharacterBaseEvent( IntPtr gameObject, ModCollection collection, IntPtr modelId, IntPtr customize, IntPtr equipData )
|
private void CreatingCharacterBaseEvent( IntPtr gameObject, ModCollection collection, IntPtr modelId, IntPtr customize, IntPtr equipData )
|
||||||
{
|
{
|
||||||
ProviderCreatingCharacterBase?.SendMessage( gameObject, collection.Name, modelId, customize, equipData );
|
ProviderCreatingCharacterBase?.SendMessage( gameObject, collection.Name, modelId, customize, equipData );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CreatedCharacterBaseEvent( IntPtr gameObject, ModCollection collection, IntPtr drawObject )
|
||||||
|
{
|
||||||
|
ProviderCreatedCharacterBase?.SendMessage( gameObject, collection.Name, drawObject );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class PenumbraIpc
|
public partial class PenumbraIpc
|
||||||
|
|
|
||||||
|
|
@ -1,148 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using OtterGui.Classes;
|
|
||||||
using Penumbra.GameData.ByteString;
|
|
||||||
using Penumbra.Meta.Manipulations;
|
|
||||||
|
|
||||||
namespace Penumbra.Collections;
|
|
||||||
|
|
||||||
public struct ConflictCache
|
|
||||||
{
|
|
||||||
// A conflict stores all data about a mod conflict.
|
|
||||||
public readonly struct Conflict : IComparable< Conflict >
|
|
||||||
{
|
|
||||||
public readonly object Data;
|
|
||||||
public readonly int Mod1;
|
|
||||||
public readonly int Mod2;
|
|
||||||
public readonly bool Mod1Priority;
|
|
||||||
public readonly bool Solved;
|
|
||||||
|
|
||||||
public Conflict( int modIdx1, int modIdx2, bool priority, bool solved, object data )
|
|
||||||
{
|
|
||||||
Mod1 = modIdx1;
|
|
||||||
Mod2 = modIdx2;
|
|
||||||
Data = data;
|
|
||||||
Mod1Priority = priority;
|
|
||||||
Solved = solved;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Order: Mod1 -> Mod1 overwritten -> Mod2 -> File > MetaManipulation
|
|
||||||
public int CompareTo( Conflict other )
|
|
||||||
{
|
|
||||||
var idxComp = Mod1.CompareTo( other.Mod1 );
|
|
||||||
if( idxComp != 0 )
|
|
||||||
{
|
|
||||||
return idxComp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( Mod1Priority != other.Mod1Priority )
|
|
||||||
{
|
|
||||||
return Mod1Priority ? 1 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
idxComp = Mod2.CompareTo( other.Mod2 );
|
|
||||||
if( idxComp != 0 )
|
|
||||||
{
|
|
||||||
return idxComp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Data switch
|
|
||||||
{
|
|
||||||
Utf8GamePath p when other.Data is Utf8GamePath q => p.CompareTo( q ),
|
|
||||||
Utf8GamePath => -1,
|
|
||||||
MetaManipulation m when other.Data is MetaManipulation n => m.CompareTo( n ),
|
|
||||||
MetaManipulation => 1,
|
|
||||||
_ => 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
=> ( Mod1Priority, Solved ) switch
|
|
||||||
{
|
|
||||||
(true, true) => $"{Penumbra.ModManager[ Mod1 ].Name} > {Penumbra.ModManager[ Mod2 ].Name} ({Data})",
|
|
||||||
(true, false) => $"{Penumbra.ModManager[ Mod1 ].Name} >= {Penumbra.ModManager[ Mod2 ].Name} ({Data})",
|
|
||||||
(false, true) => $"{Penumbra.ModManager[ Mod1 ].Name} < {Penumbra.ModManager[ Mod2 ].Name} ({Data})",
|
|
||||||
(false, false) => $"{Penumbra.ModManager[ Mod1 ].Name} <= {Penumbra.ModManager[ Mod2 ].Name} ({Data})",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly List< Conflict > _conflicts = new();
|
|
||||||
private bool _isSorted = true;
|
|
||||||
|
|
||||||
public ConflictCache()
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public IReadOnlyList< Conflict > Conflicts
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
Sort();
|
|
||||||
return _conflicts;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find all mod conflicts concerning the specified mod (in both directions).
|
|
||||||
public SubList< Conflict > ModConflicts( int modIdx )
|
|
||||||
{
|
|
||||||
Sort();
|
|
||||||
var start = _conflicts.FindIndex( c => c.Mod1 == modIdx );
|
|
||||||
if( start < 0 )
|
|
||||||
{
|
|
||||||
return SubList< Conflict >.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
var end = _conflicts.FindIndex( start, c => c.Mod1 != modIdx );
|
|
||||||
return new SubList< Conflict >( _conflicts, start, end - start );
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Sort()
|
|
||||||
{
|
|
||||||
if( !_isSorted )
|
|
||||||
{
|
|
||||||
_conflicts?.Sort();
|
|
||||||
_isSorted = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add both directions for the mod.
|
|
||||||
// On same priority, it is assumed that mod1 is the earlier one.
|
|
||||||
// Also update older conflicts to refer to the highest-prioritized conflict.
|
|
||||||
private void AddConflict( int modIdx1, int modIdx2, int priority1, int priority2, object data )
|
|
||||||
{
|
|
||||||
var solved = priority1 != priority2;
|
|
||||||
var priority = priority1 >= priority2;
|
|
||||||
var prioritizedMod = priority ? modIdx1 : modIdx2;
|
|
||||||
_conflicts.Add( new Conflict( modIdx1, modIdx2, priority, solved, data ) );
|
|
||||||
_conflicts.Add( new Conflict( modIdx2, modIdx1, !priority, solved, data ) );
|
|
||||||
for( var i = 0; i < _conflicts.Count; ++i )
|
|
||||||
{
|
|
||||||
var c = _conflicts[ i ];
|
|
||||||
if( data.Equals( c.Data ) )
|
|
||||||
{
|
|
||||||
_conflicts[ i ] = c.Mod1Priority
|
|
||||||
? new Conflict( prioritizedMod, c.Mod2, true, c.Solved || solved, data )
|
|
||||||
: new Conflict( c.Mod1, prioritizedMod, false, c.Solved || solved, data );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_isSorted = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddConflict( int modIdx1, int modIdx2, int priority1, int priority2, Utf8GamePath gamePath )
|
|
||||||
=> AddConflict( modIdx1, modIdx2, priority1, priority2, ( object )gamePath );
|
|
||||||
|
|
||||||
public void AddConflict( int modIdx1, int modIdx2, int priority1, int priority2, MetaManipulation manipulation )
|
|
||||||
=> AddConflict( modIdx1, modIdx2, priority1, priority2, ( object )manipulation );
|
|
||||||
|
|
||||||
public void ClearConflicts()
|
|
||||||
=> _conflicts?.Clear();
|
|
||||||
|
|
||||||
public void ClearFileConflicts()
|
|
||||||
=> _conflicts?.RemoveAll( m => m.Data is Utf8GamePath );
|
|
||||||
|
|
||||||
public void ClearMetaConflicts()
|
|
||||||
=> _conflicts?.RemoveAll( m => m.Data is MetaManipulation );
|
|
||||||
|
|
||||||
public void ClearConflictsWithMod( int modIdx )
|
|
||||||
=> _conflicts?.RemoveAll( m => m.Mod1 == modIdx || m.Mod2 == modIdx );
|
|
||||||
}
|
|
||||||
|
|
@ -18,6 +18,7 @@ public unsafe partial class PathResolver
|
||||||
public class DrawObjectState
|
public class DrawObjectState
|
||||||
{
|
{
|
||||||
public static event CreatingCharacterBaseDelegate? CreatingCharacterBase;
|
public static event CreatingCharacterBaseDelegate? CreatingCharacterBase;
|
||||||
|
public static event CreatedCharacterBaseDelegate? CreatedCharacterBase;
|
||||||
|
|
||||||
public IEnumerable< KeyValuePair< IntPtr, (ModCollection, int) > > DrawObjects
|
public IEnumerable< KeyValuePair< IntPtr, (ModCollection, int) > > DrawObjects
|
||||||
=> _drawObjectToObject;
|
=> _drawObjectToObject;
|
||||||
|
|
@ -147,6 +148,7 @@ public unsafe partial class PathResolver
|
||||||
if( LastGameObject != null )
|
if( LastGameObject != null )
|
||||||
{
|
{
|
||||||
_drawObjectToObject[ ret ] = ( _lastCreatedCollection!, LastGameObject->ObjectIndex );
|
_drawObjectToObject[ ret ] = ( _lastCreatedCollection!, LastGameObject->ObjectIndex );
|
||||||
|
CreatedCharacterBase?.Invoke( ( IntPtr )LastGameObject, _lastCreatedCollection!, ret );
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue