Add interface collection.

This commit is contained in:
Ottermandias 2022-09-17 22:53:14 +02:00
parent 8597070063
commit 273111775c
8 changed files with 91 additions and 14 deletions

View file

@ -26,6 +26,9 @@ public partial class ModCollection
// The collection used for general file redirections and all characters not specifically named.
public ModCollection Default { get; private set; } = Empty;
// The collection used for all files categorized as UI files.
public ModCollection Interface { get; private set; } = Empty;
// A single collection that can not be deleted as a fallback for the current collection.
private ModCollection DefaultName { get; set; } = Empty;
@ -53,6 +56,7 @@ public partial class ModCollection
return type switch
{
CollectionType.Default => Default,
CollectionType.Interface => Interface,
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,
@ -66,6 +70,7 @@ public partial class ModCollection
var oldCollectionIdx = collectionType switch
{
CollectionType.Default => Default.Index,
CollectionType.Interface => Interface.Index,
CollectionType.Current => Current.Index,
CollectionType.Character => characterName?.Length > 0
? _characters.TryGetValue( characterName, out var c )
@ -97,6 +102,9 @@ public partial class ModCollection
Default.SetFiles();
}
break;
case CollectionType.Interface:
Interface = newCollection;
break;
case CollectionType.Current:
Current = newCollection;
@ -118,6 +126,7 @@ public partial class ModCollection
private void UpdateCurrentCollectionInUse()
=> CurrentCollectionInUse = _specialCollections
.OfType< ModCollection >()
.Prepend( Interface )
.Prepend( Default )
.Concat( Characters.Values )
.SelectMany( c => c.GetFlattenedInheritance() ).Contains( Current );
@ -192,7 +201,7 @@ public partial class ModCollection
var configChanged = !ReadActiveCollections( out var jObject );
// Load the default collection.
var defaultName = jObject[ nameof( Default ) ]?.ToObject< string >() ?? ( configChanged ? DefaultCollection : Empty.Name );
var defaultName = jObject[ nameof( Default ) ]?.ToObject< string >() ?? ( configChanged ? Empty.Name : DefaultCollection );
var defaultIdx = GetIndexForCollectionName( defaultName );
if( defaultIdx < 0 )
{
@ -205,12 +214,28 @@ public partial class ModCollection
Default = this[ defaultIdx ];
}
// Load the interface collection.
var interfaceName = jObject[ nameof( Interface ) ]?.ToObject< string >() ?? (configChanged ? Empty.Name : Default.Name);
var interfaceIdx = GetIndexForCollectionName( interfaceName );
if( interfaceIdx < 0 )
{
Penumbra.Log.Error(
$"Last choice of {ConfigWindow.InterfaceCollection} {interfaceName} is not available, reset to {Empty.Name}." );
Interface = Empty;
configChanged = true;
}
else
{
Interface = this[ interfaceIdx ];
}
// Load the current collection.
var currentName = jObject[ nameof( Current ) ]?.ToObject< string >() ?? DefaultCollection;
var currentIdx = GetIndexForCollectionName( currentName );
if( currentIdx < 0 )
{
Penumbra.Log.Error( $"Last choice of {ConfigWindow.SelectedCollection} {currentName} is not available, reset to {DefaultCollection}." );
Penumbra.Log.Error(
$"Last choice of {ConfigWindow.SelectedCollection} {currentName} is not available, reset to {DefaultCollection}." );
Current = DefaultName;
configChanged = true;
}
@ -268,13 +293,14 @@ public partial class ModCollection
public void SaveActiveCollections()
{
Penumbra.Framework.RegisterDelayed( nameof( SaveActiveCollections ),
() => SaveActiveCollections( Default.Name, Current.Name, Characters.Select( kvp => ( kvp.Key, kvp.Value.Name ) ),
() => SaveActiveCollections( Default.Name, Interface.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 ui, string current, IEnumerable< (string, string) > characters,
IEnumerable< (CollectionType, string) > special )
{
var file = ActiveCollectionFile;
@ -287,6 +313,8 @@ public partial class ModCollection
j.WriteStartObject();
j.WritePropertyName( nameof( Default ) );
j.WriteValue( def );
j.WritePropertyName( nameof( Interface ) );
j.WriteValue( ui );
j.WritePropertyName( nameof( Current ) );
j.WriteValue( current );
foreach( var (type, collection) in special )
@ -350,6 +378,7 @@ public partial class ModCollection
private void CreateNecessaryCaches()
{
Default.CreateCache();
Interface.CreateCache();
Current.CreateCache();
foreach( var collection in _specialCollections.OfType< ModCollection >().Concat( _characters.Values ) )
@ -362,6 +391,7 @@ public partial class ModCollection
{
if( idx != Empty.Index
&& idx != Default.Index
&& idx != Interface.Index
&& idx != Current.Index
&& _specialCollections.All( c => c == null || c.Index != idx )
&& _characters.Values.All( c => c.Index != idx ) )

View file

@ -45,8 +45,9 @@ public enum CollectionType : byte
Inactive, // A collection was added or removed
Default, // The default collection was changed
Interface, // The ui collection was changed
Character, // A character collection was changed
Current, // The current collection was changed.
Current, // The current collection was changed
}
public static class CollectionTypeExtensions
@ -96,6 +97,7 @@ public static class CollectionTypeExtensions
CollectionType.VeenaNpc => SubRace.Veena.ToName() + " (NPC)",
CollectionType.Inactive => "Collection",
CollectionType.Default => "Default",
CollectionType.Interface => "Interface",
CollectionType.Character => "Character",
CollectionType.Current => "Current",
_ => string.Empty,

View file

@ -47,12 +47,35 @@ public partial class Configuration
m.Version2To3();
m.Version3To4();
m.Version4To5();
m.Version5To6();
}
// A new tutorial step was inserted in the middle.
// The UI collection and a new tutorial for it was added.
// The migration for the UI collection itself happens in the ActiveCollections file.
private void Version5To6()
{
if( _config.Version != 5 )
{
return;
}
if( _config.TutorialStep == 25 )
{
_config.TutorialStep = 27;
}
_config.Version = 6;
}
// Mod backup extension was changed from .zip to .pmp.
// Actual migration takes place in ModManager.
private void Version4To5()
{
if( _config.Version != 4 )
{
return;
}
Mod.Manager.MigrateModBackups = true;
_config.Version = 5;
}
@ -189,7 +212,7 @@ public partial class Configuration
CurrentCollection = _data[ nameof( CurrentCollection ) ]?.ToObject< string >() ?? CurrentCollection;
DefaultCollection = _data[ nameof( DefaultCollection ) ]?.ToObject< string >() ?? DefaultCollection;
CharacterCollections = _data[ nameof( CharacterCollections ) ]?.ToObject< Dictionary< string, string > >() ?? CharacterCollections;
ModCollection.Manager.SaveActiveCollections( DefaultCollection, CurrentCollection,
ModCollection.Manager.SaveActiveCollections( DefaultCollection, CurrentCollection, DefaultCollection,
CharacterCollections.Select( kvp => ( kvp.Key, kvp.Value ) ), Array.Empty< (CollectionType, string) >() );
}

View file

@ -142,7 +142,7 @@ public partial class Configuration : IPluginConfiguration
// Contains some default values or boundaries for config values.
public static class Constants
{
public const int CurrentVersion = 5;
public const int CurrentVersion = 6;
public const float MaxAbsoluteSize = 600;
public const int DefaultAbsoluteSize = 250;
public const float MinAbsoluteSize = 50;

View file

@ -121,6 +121,12 @@ public unsafe partial class ResourceLoader
}
path = path.ToLower();
if( category == ResourceCategory.Ui )
{
var resolved = Penumbra.CollectionManager.Interface.ResolvePath( path );
return ( resolved, Penumbra.CollectionManager.Interface.ToResolveData() );
}
if( ResolvePathCustomization != null )
{
foreach( var resolver in ResolvePathCustomization.GetInvocationList() )

View file

@ -276,6 +276,7 @@ public class Penumbra : IDalamudPlugin
public void Dispose()
{
ShutdownWebServer();
DisposeInterface();
Ipc?.Dispose();
Api?.Dispose();
@ -289,8 +290,6 @@ public class Penumbra : IDalamudPlugin
ResourceLogger?.Dispose();
ResourceLoader?.Dispose();
CharacterUtility?.Dispose();
ShutdownWebServer();
}
public static bool SetCollection( string type, string collectionName )
@ -481,6 +480,7 @@ public class Penumbra : IDalamudPlugin
sb.AppendFormat( "> **`#Collections: `** {0}\n", CollectionManager.Count - 1 );
sb.AppendFormat( "> **`Active Collections: `** {0}\n", CollectionManager.Count( c => c.HasCache ) );
sb.AppendFormat( "> **`Base Collection: `** {0}\n", CollectionManager.Default.AnonymizedName );
sb.AppendFormat( "> **`Interface Collection: `** {0}\n", CollectionManager.Interface.AnonymizedName );
sb.AppendFormat( "> **`Selected Collection: `** {0}\n", CollectionManager.Current.AnonymizedName );
foreach( var type in CollectionTypeExtensions.Special )
{

View file

@ -129,10 +129,19 @@ public partial class ConfigWindow
DrawCollectionSelector( "##default", _window._inputTextWidth.X, CollectionType.Default, true, null );
ImGui.SameLine();
ImGuiUtil.LabeledHelpMarker( DefaultCollection,
$"Mods in the {DefaultCollection} are loaded for anything that is not associated with a character in the game "
$"Mods in the {DefaultCollection} are loaded for anything that is not associated with the user interface or a character in the game,"
+ "as well as any character for whom no more specific conditions from below apply." );
}
private void DrawInterfaceCollectionSelector()
{
using var group = ImRaii.Group();
DrawCollectionSelector( "##interface", _window._inputTextWidth.X, CollectionType.Interface, true, null );
ImGui.SameLine();
ImGuiUtil.LabeledHelpMarker( InterfaceCollection,
$"Mods in the {InterfaceCollection} are loaded for any file that the game categorizes as an UI file. This is mostly icons as well as the tiles that generate the user interface windows themselves." );
}
// We do not check for valid character names.
private void DrawNewSpecialCollection()
{
@ -272,6 +281,8 @@ public partial class ConfigWindow
ImGui.Dummy( _window._defaultSpace );
DrawDefaultCollectionSelector();
OpenTutorial( BasicTutorialSteps.DefaultCollection );
DrawInterfaceCollectionSelector();
OpenTutorial( BasicTutorialSteps.InterfaceCollection );
ImGui.Dummy( _window._defaultSpace );
DrawSpecialAssignments();

View file

@ -10,6 +10,7 @@ public partial class ConfigWindow
{
public const string SelectedCollection = "Selected Collection";
public const string DefaultCollection = "Base Collection";
public const string InterfaceCollection = "Interface Collection";
public const string ActiveCollections = "Active Collections";
public const string AssignedCollections = "Assigned Collections";
public const string GroupAssignment = "Group Assignment";
@ -21,7 +22,7 @@ public partial class ConfigWindow
public const string SupportedRedrawModifiers = " - 'self' or '<me>': your own character\n"
+ " - 'target' or '<t>': your target\n"
+ " - 'focus' or '<f>: your focus target\n"
+ " - 'mouseover' or '<mo>': the actor you are currently hovering\n"
+ " - 'mouseover' or '<mo>': the actor you are currently hovering over\n"
+ " - any specific actor name to redraw all actors of that exactly matching name.";
private static void UpdateTutorialStep()
@ -56,6 +57,7 @@ public partial class ConfigWindow
Inheritance,
ActiveCollections,
DefaultCollection,
InterfaceCollection,
SpecialCollections1,
SpecialCollections2,
Mods,
@ -111,7 +113,10 @@ public partial class ConfigWindow
.Register( $"Initial Setup, Step 7: {DefaultCollection}",
$"The {DefaultCollection} - which should currently be set to a collection named {ModCollection.DefaultCollection} - is the main one.\n\n"
+ $"As long as no more specific conditions apply to an object in the game, the mods from the {DefaultCollection} will be used.\n\n"
+ "This is also the collection you need to use for all UI mods, music mods or any mods not associated with a character in the game at all." )
+ "This is also the collection you need to use for all mods that are not directly associated with any character in the game or the user interface, like music mods." )
.Register( "Interface Collection",
$"The {InterfaceCollection} - which should currently be set to None - is used exclusively for files categorized as 'UI' files by the game, which is mostly icons and the backgrounds for different UI windows etc.\n\n"
+ $"If you have mods manipulating your interface, they should be enabled in the collection assigned to this slot. You can of course assign the same collection you assigned to the {DefaultCollection} to the {InterfaceCollection}, too, and enable all your UI mods in this one.")
.Register( GroupAssignment + 's',
"Collections assigned here are used for groups of characters for which specific conditions are met.\n\n"
+ "The more specific the condition, the higher its priority (i.e. Your Character > Player Characters > Race).\n\n"