Complete mod collection cleanup, initial stuff for inheritance. Some further cleanup.

This commit is contained in:
Ottermandias 2022-03-28 17:25:59 +02:00
parent 7915d516e2
commit 1861c40a4f
48 changed files with 1151 additions and 898 deletions

View file

@ -1,20 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Penumbra.Mod;
using Penumbra.Mods;
using Penumbra.Util;
namespace Penumbra.Collections;
// ModCollections can inherit from an arbitrary number of other collections.
// This is transitive, so a collection A inheriting from B also inherits from everything B inherits.
// Circular dependencies are resolved by distinctness.
public partial class ModCollection
{
private readonly List< ModCollection > _inheritance = new();
// A change in inheritance usually requires complete recomputation.
public event Action< bool > InheritanceChanged;
private readonly List< ModCollection > _inheritance = new();
public IReadOnlyList< ModCollection > Inheritance
=> _inheritance;
// Iterate over all collections inherited from in depth-first order.
// Skip already visited collections to avoid circular dependencies.
public IEnumerable< ModCollection > GetFlattenedInheritance()
{
yield return this;
@ -27,6 +33,9 @@ public partial class ModCollection
}
}
// Add a new collection to the inheritance list.
// We do not check if this collection would be visited before,
// only that it is unique in the list itself.
public bool AddInheritance( ModCollection collection )
{
if( ReferenceEquals( collection, this ) || _inheritance.Contains( collection ) )
@ -35,6 +44,7 @@ public partial class ModCollection
}
_inheritance.Add( collection );
// Changes in inherited collections may need to trigger further changes here.
collection.ModSettingChanged += OnInheritedModSettingChange;
collection.InheritanceChanged += OnInheritedInheritanceChange;
InheritanceChanged.Invoke( false );
@ -50,6 +60,7 @@ public partial class ModCollection
InheritanceChanged.Invoke( false );
}
// Order in the inheritance list is relevant.
public void MoveInheritance( int from, int to )
{
if( _inheritance.Move( from, to ) )
@ -58,6 +69,7 @@ public partial class ModCollection
}
}
// Carry changes in collections inherited from forward if they are relevant for this collection.
private void OnInheritedModSettingChange( ModSettingChange type, int modIdx, int oldValue, string? optionName, bool _ )
{
if( _settings[ modIdx ] == null )
@ -69,13 +81,16 @@ public partial class ModCollection
private void OnInheritedInheritanceChange( bool _ )
=> InheritanceChanged.Invoke( true );
// Obtain the actual settings for a given mod via index.
// Also returns the collection the settings are taken from.
// If no collection provides settings for this mod, this collection is returned together with null.
public (ModSettings? Settings, ModCollection Collection) this[ Index idx ]
{
get
{
foreach( var collection in GetFlattenedInheritance() )
{
var settings = _settings[ idx ];
var settings = collection._settings[ idx ];
if( settings != null )
{
return ( settings, collection );