Add local data, favorites and tags.

This commit is contained in:
Ottermandias 2022-10-19 01:01:40 +02:00
parent b9662e39a9
commit ccfc05f2b2
19 changed files with 481 additions and 94 deletions

View file

@ -29,8 +29,9 @@ public partial class ModFileSystemSelector
private void SetFilterTooltip()
{
FilterTooltip = "Filter mods for those where their full paths or names contain the given substring.\n"
+ "Enter n:[string] to filter only for mod names and no paths.\n"
+ "Enter c:[string] to filter for mods changing specific items.\n"
+ "Enter t:[string] to filter for mods set to specific tags.\n"
+ "Enter n:[string] to filter only for mod names and no paths.\n"
+ "Enter a:[string] to filter for mods by specific authors.";
}
@ -49,6 +50,8 @@ public partial class ModFileSystemSelector
'A' => filterValue.Length == 2 ? ( LowerString.Empty, -1 ) : ( new LowerString( filterValue[ 2.. ] ), 2 ),
'c' => filterValue.Length == 2 ? ( LowerString.Empty, -1 ) : ( new LowerString( filterValue[ 2.. ] ), 3 ),
'C' => filterValue.Length == 2 ? ( LowerString.Empty, -1 ) : ( new LowerString( filterValue[ 2.. ] ), 3 ),
't' => filterValue.Length == 2 ? ( LowerString.Empty, -1 ) : ( new LowerString( filterValue[ 2.. ] ), 4 ),
'T' => filterValue.Length == 2 ? ( LowerString.Empty, -1 ) : ( new LowerString( filterValue[ 2.. ] ), 4 ),
_ => ( new LowerString( filterValue ), 0 ),
},
_ => ( new LowerString( filterValue ), 0 ),
@ -96,7 +99,8 @@ public partial class ModFileSystemSelector
0 => !( leaf.FullName().Contains( _modFilter.Lower, IgnoreCase ) || mod.Name.Contains( _modFilter ) ),
1 => !mod.Name.Contains( _modFilter ),
2 => !mod.Author.Contains( _modFilter ),
3 => !mod.LowerChangedItemsString.Contains( _modFilter.Lower, IgnoreCase ),
3 => !mod.LowerChangedItemsString.Contains( _modFilter.Lower ),
4 => !mod.AllTagsLower.Contains( _modFilter.Lower ),
_ => false, // Should never happen
};
}
@ -143,6 +147,13 @@ public partial class ModFileSystemSelector
return true;
}
// Handle Favoritism
if( !_stateFilter.HasFlag( ModFilter.Favorite ) && mod.Favorite
|| !_stateFilter.HasFlag( ModFilter.NotFavorite ) && !mod.Favorite )
{
return true;
}
// Handle Inheritance
if( collection == Penumbra.CollectionManager.Current )
{

View file

@ -43,7 +43,7 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod
Penumbra.CollectionManager.CollectionChanged += OnCollectionChange;
Penumbra.CollectionManager.Current.ModSettingChanged += OnSettingChange;
Penumbra.CollectionManager.Current.InheritanceChanged += OnInheritanceChange;
Penumbra.ModManager.ModMetaChanged += OnModMetaChange;
Penumbra.ModManager.ModDataChanged += OnModDataChange;
Penumbra.ModManager.ModDiscoveryStarted += StoreCurrentSelection;
Penumbra.ModManager.ModDiscoveryFinished += RestoreLastSelection;
OnCollectionChange( CollectionType.Current, null, Penumbra.CollectionManager.Current, null );
@ -54,7 +54,7 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod
base.Dispose();
Penumbra.ModManager.ModDiscoveryStarted -= StoreCurrentSelection;
Penumbra.ModManager.ModDiscoveryFinished -= RestoreLastSelection;
Penumbra.ModManager.ModMetaChanged -= OnModMetaChange;
Penumbra.ModManager.ModDataChanged -= OnModDataChange;
Penumbra.CollectionManager.Current.ModSettingChanged -= OnSettingChange;
Penumbra.CollectionManager.Current.InheritanceChanged -= OnInheritanceChange;
Penumbra.CollectionManager.CollectionChanged -= OnCollectionChange;
@ -120,7 +120,7 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod
var flags = selected ? ImGuiTreeNodeFlags.Selected | LeafFlags : LeafFlags;
using var c = ImRaii.PushColor( ImGuiCol.Text, state.Color.Value() );
using var id = ImRaii.PushId( leaf.Value.Index );
using var _ = ImRaii.TreeNode( leaf.Value.Name, flags );
ImRaii.TreeNode( leaf.Value.Name, flags ).Dispose();
}
@ -347,12 +347,15 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod
}
}
private void OnModMetaChange( MetaChangeType type, Mod mod, string? oldName )
private void OnModDataChange( ModDataChangeType type, Mod mod, string? oldName )
{
switch( type )
{
case MetaChangeType.Name:
case MetaChangeType.Author:
case ModDataChangeType.Name:
case ModDataChangeType.Author:
case ModDataChangeType.ModTags:
case ModDataChangeType.LocalTags:
case ModDataChangeType.Favorite:
SetFilterDirty();
break;
}

View file

@ -7,33 +7,37 @@ public enum ModFilter
{
Enabled = 1 << 0,
Disabled = 1 << 1,
NoConflict = 1 << 2,
SolvedConflict = 1 << 3,
UnsolvedConflict = 1 << 4,
HasNoMetaManipulations = 1 << 5,
HasMetaManipulations = 1 << 6,
HasNoFileSwaps = 1 << 7,
HasFileSwaps = 1 << 8,
HasConfig = 1 << 9,
HasNoConfig = 1 << 10,
HasNoFiles = 1 << 11,
HasFiles = 1 << 12,
IsNew = 1 << 13,
NotNew = 1 << 14,
Inherited = 1 << 15,
Uninherited = 1 << 16,
Undefined = 1 << 17,
Favorite = 1 << 2,
NotFavorite = 1 << 3,
NoConflict = 1 << 4,
SolvedConflict = 1 << 5,
UnsolvedConflict = 1 << 6,
HasNoMetaManipulations = 1 << 7,
HasMetaManipulations = 1 << 8,
HasNoFileSwaps = 1 << 9,
HasFileSwaps = 1 << 10,
HasConfig = 1 << 11,
HasNoConfig = 1 << 12,
HasNoFiles = 1 << 13,
HasFiles = 1 << 14,
IsNew = 1 << 15,
NotNew = 1 << 16,
Inherited = 1 << 17,
Uninherited = 1 << 18,
Undefined = 1 << 19,
};
public static class ModFilterExtensions
{
public const ModFilter UnfilteredStateMods = ( ModFilter )( ( 1 << 18 ) - 1 );
public const ModFilter UnfilteredStateMods = ( ModFilter )( ( 1 << 20 ) - 1 );
public static string ToName( this ModFilter filter )
=> filter switch
{
ModFilter.Enabled => "Enabled",
ModFilter.Disabled => "Disabled",
ModFilter.Favorite => "Favorite",
ModFilter.NotFavorite => "No Favorite",
ModFilter.NoConflict => "No Conflicts",
ModFilter.SolvedConflict => "Solved Conflicts",
ModFilter.UnsolvedConflict => "Unsolved Conflicts",

View file

@ -22,12 +22,19 @@ public partial class ConfigWindow
Add5_8_7( ret );
Add5_9_0( ret );
Add5_10_0( ret );
Add5_11_0( ret );
return ret;
}
private static void Add5_11_0( Changelog log )
=> log.NextVersion( "Version 0.5.11.0" )
.RegisterEntry(
"Added local data storage for mods in the plugin config folder. This information is not exported together with your mod, but not dependent on collections." )
.RegisterEntry( "Moved the import date from mod metadata to local data.", 1 )
.RegisterEntry( "Added Favorites. You can declare mods as favorites and filter for them.", 1 )
.RegisterEntry( "Added Local Tags. You can apply custom Tags to mods and filter for them.", 1 )
.RegisterEntry( "Added Mod Tags. Mod Creators (and the Edit Mod tab) can set tags that are stored in the mod meta data and are thus exported." )
.RegisterEntry( "Add backface and transparency toggles to .mtrl editing, as well as a info section." )
.RegisterEntry( "Meta Manipulation editing now highlights if the selected ID is 0 or 1." )
.RegisterEntry( "Fixed a bug when manually adding EQP or EQDP entries to Mods." )

View file

@ -55,6 +55,13 @@ public partial class ConfigWindow
}
}
ImGui.Dummy( _window._defaultSpace );
var tagIdx = _modTags.Draw( "Mod Tags: ", "Edit tags by clicking them, or add new tags. Empty tags are removed.", _mod.ModTags, out var editedTag );
if( tagIdx >= 0 )
{
Penumbra.ModManager.ChangeModTag( _mod.Index, tagIdx, editedTag );
}
ImGui.Dummy( _window._defaultSpace );
AddOptionGroup.Draw( _window, _mod );
ImGui.Dummy( _window._defaultSpace );
@ -566,7 +573,7 @@ public partial class ConfigWindow
ImGui.TableNextColumn();
var canAddGroup = mod.Groups[ groupIdx ].Type != GroupType.Multi || mod.Groups[ groupIdx ].Count < IModGroup.MaxMultiOptions;
var validName = _newOptionName.Length > 0 && _newOptionNameIdx == groupIdx;
var validName = _newOptionName.Length > 0 && _newOptionNameIdx == groupIdx;
var tt = canAddGroup
? validName ? "Add a new option to this group." : "Please enter a name for the new option."
: $"Can not add more than {IModGroup.MaxMultiOptions} options to a multi group.";
@ -642,7 +649,7 @@ public partial class ConfigWindow
{
GroupType.Single => "Single Group",
GroupType.Multi => "Multi Group",
_ => "Unknown",
_ => "Unknown",
};
ImGui.SetNextItemWidth( _window._inputTextWidth.X - 3 * _window._iconButtonSize.X - 12 * ImGuiHelpers.GlobalScale );

View file

@ -58,16 +58,20 @@ public partial class ConfigWindow
DrawPriorityInput();
OpenTutorial( BasicTutorialSteps.Priority );
DrawRemoveSettings();
ImGui.Dummy( _window._defaultSpace );
for( var idx = 0; idx < _mod.Groups.Count; ++idx )
{
DrawSingleGroup( _mod.Groups[ idx ], idx );
}
ImGui.Dummy( _window._defaultSpace );
for( var idx = 0; idx < _mod.Groups.Count; ++idx )
if( _mod.Groups.Count > 0 )
{
DrawMultiGroup( _mod.Groups[ idx ], idx );
ImGui.Dummy( _window._defaultSpace );
for( var idx = 0; idx < _mod.Groups.Count; ++idx )
{
DrawSingleGroup( _mod.Groups[ idx ], idx );
}
ImGui.Dummy( _window._defaultSpace );
for( var idx = 0; idx < _mod.Groups.Count; ++idx )
{
DrawMultiGroup( _mod.Groups[ idx ], idx );
}
}
_window._penumbra.Api.InvokePostSettingsPanel( _mod.ModPath.Name );

View file

@ -1,9 +1,11 @@
using System;
using System.Numerics;
using Dalamud.Interface;
using ImGuiNET;
using OtterGui;
using OtterGui.Classes;
using OtterGui.Raii;
using OtterGui.Widgets;
using Penumbra.GameData.ByteString;
using Penumbra.Meta.Manipulations;
using Penumbra.Mods;
@ -36,10 +38,12 @@ public partial class ConfigWindow
private static readonly Utf8String ChangedItemsTabHeader = Utf8String.FromStringUnsafe( "Changed Items", false );
private static readonly Utf8String EditModTabHeader = Utf8String.FromStringUnsafe( "Edit Mod", false );
private readonly TagButtons _modTags = new();
private void DrawTabBar()
{
ImGui.Dummy( _window._defaultSpace );
using var tabBar = ImRaii.TabBar( "##ModTabs" );
var tabBarHeight = ImGui.GetCursorPosY();
using var tabBar = ImRaii.TabBar( "##ModTabs" );
if( !tabBar )
{
return;
@ -47,8 +51,8 @@ public partial class ConfigWindow
_availableTabs = Tabs.Settings
| ( _mod.ChangedItems.Count > 0 ? Tabs.ChangedItems : 0 )
| ( _mod.Description.Length > 0 ? Tabs.Description : 0 )
| ( _conflicts.Count > 0 ? Tabs.Conflicts : 0 )
| Tabs.Description
| ( _conflicts.Count > 0 ? Tabs.Conflicts : 0 )
| Tabs.Edit;
DrawSettingsTab();
@ -56,6 +60,12 @@ public partial class ConfigWindow
DrawChangedItemsTab();
DrawConflictsTab();
DrawEditModTab();
DrawAdvancedEditingButton();
DrawFavoriteButton( tabBarHeight );
}
private void DrawAdvancedEditingButton()
{
if( ImGui.TabItemButton( "Advanced Editing", ImGuiTabItemFlags.Trailing | ImGuiTabItemFlags.NoTooltip ) )
{
_window.ModEditPopup.ChangeMod( _mod );
@ -73,6 +83,44 @@ public partial class ConfigWindow
+ "\t\t- textures" );
}
private void DrawFavoriteButton( float height )
{
var oldPos = ImGui.GetCursorPos();
using( var font = ImRaii.PushFont( UiBuilder.IconFont ) )
{
var size = ImGui.CalcTextSize( FontAwesomeIcon.Star.ToIconString() ) + ImGui.GetStyle().FramePadding * 2;
var newPos = new Vector2( ImGui.GetWindowWidth() - size.X - ImGui.GetStyle().ItemSpacing.X, height );
if( ImGui.GetScrollMaxX() > 0 )
{
newPos.X += ImGui.GetScrollX();
}
var rectUpper = ImGui.GetWindowPos() + newPos;
var color = ImGui.IsMouseHoveringRect( rectUpper, rectUpper + size ) ? ImGui.GetColorU32( ImGuiCol.Text ) :
_mod.Favorite ? 0xFF00FFFF : ImGui.GetColorU32( ImGuiCol.TextDisabled );
using var c = ImRaii.PushColor( ImGuiCol.Text, color )
.Push( ImGuiCol.Button, 0 )
.Push( ImGuiCol.ButtonHovered, 0 )
.Push( ImGuiCol.ButtonActive, 0 );
ImGui.SetCursorPos( newPos );
if( ImGui.Button( FontAwesomeIcon.Star.ToIconString() ) )
{
Penumbra.ModManager.ChangeModFavorite( _mod.Index, !_mod.Favorite );
}
}
var hovered = ImGui.IsItemHovered();
OpenTutorial( BasicTutorialSteps.Favorites );
if( hovered )
{
ImGui.SetTooltip( "Favorite" );
}
}
// Just a simple text box with the wrapped description, if it exists.
private void DrawDescriptionTab()
{
@ -88,6 +136,26 @@ public partial class ConfigWindow
return;
}
ImGui.Dummy( ImGuiHelpers.ScaledVector2( 2 ) );
ImGui.Dummy( ImGuiHelpers.ScaledVector2( 2 ) );
var tagIdx = _localTags.Draw( "Local Tags: ", "Custom tags you can set personally that will not be exported to the mod data but only set for you.\n"
+ "If the mod already contains a local tag in its own tags, the local tag will be ignored.", _mod.LocalTags,
out var editedTag );
OpenTutorial( BasicTutorialSteps.Tags );
if( tagIdx >= 0 )
{
Penumbra.ModManager.ChangeLocalTag( _mod.Index, tagIdx, editedTag );
}
if( _mod.ModTags.Count > 0 )
{
_modTags.Draw( "Mod Tags: ", "Tags assigned by the mod creator and saved with the mod data. To edit these, look at Edit Mod.", _mod.ModTags, out var _, false,
ImGui.CalcTextSize( "Local " ).X - ImGui.CalcTextSize( "Mod " ).X );
}
ImGui.Dummy( ImGuiHelpers.ScaledVector2( 2 ) );
ImGui.Separator();
ImGuiUtil.TextWrapped( _mod.Description );
}

View file

@ -8,8 +8,8 @@ using System;
using System.Linq;
using System.Numerics;
using Dalamud.Interface;
using OtterGui.Widgets;
using Penumbra.Api.Enums;
using Penumbra.GameData.Enums;
namespace Penumbra.UI;
@ -198,9 +198,10 @@ public partial class ConfigWindow
{
private readonly ConfigWindow _window;
private bool _valid;
private ModFileSystem.Leaf _leaf = null!;
private Mod _mod = null!;
private bool _valid;
private ModFileSystem.Leaf _leaf = null!;
private Mod _mod = null!;
private readonly TagButtons _localTags = new();
public ModPanel( ConfigWindow window )
=> _window = window;

View file

@ -81,6 +81,8 @@ public partial class ConfigWindow
Faq1,
Faq2,
Faq3,
Favorites,
Tags,
}
public static readonly Tutorial Tutorial = new Tutorial()
@ -159,5 +161,7 @@ public partial class ConfigWindow
.Register( "FAQ 2",
"It is advised to not use TexTools and Penumbra at the same time. Penumbra may refuse to work if TexTools broke your game indices." )
.Register( "FAQ 3", "Penumbra can change the skin material a mod uses. This is under advanced editing." )
.Register( "Favorites", "You can now toggle mods as favorites using this button. You can filter for favorited mods in the mod selector. Favorites are stored locally, not within the mod, but independently of collections." )
.Register( "Tags", "Mods can now have two types of tags:\n\n- Local Tags are those that you can set for yourself. They are stored locally and are not saved in any way in the mod directory itself.\n- Mod Tags are stored in the mod metadata, are set by the mod creator and are exported together with the mod, they can only be edited in the Edit Mod tab.\n\nIf a mod has a tag in its Mod Tags, this overwrites any identical Local Tags.\n\nYou can filter for tags in the mod selector via 't:text'." )
.EnsureSize( Enum.GetValues< BasicTutorialSteps >().Length );
}