Make interface code exception-resistant due to RAII, and global scale resistant.

This commit is contained in:
Ottermandias 2021-09-06 17:27:39 +02:00
parent 69cb329b8f
commit 23ebaf7a0d
21 changed files with 1053 additions and 822 deletions

View file

@ -8,13 +8,13 @@ namespace Penumbra.UI.Custom
public static partial class ImGuiCustom public static partial class ImGuiCustom
{ {
public static void BeginFramedGroup( string label ) public static void BeginFramedGroup( string label )
=> BeginFramedGroupInternal( ref label, ZeroVector, false ); => BeginFramedGroupInternal( ref label, Vector2.Zero, false );
public static void BeginFramedGroup( string label, Vector2 minSize ) public static void BeginFramedGroup( string label, Vector2 minSize )
=> BeginFramedGroupInternal( ref label, minSize, false ); => BeginFramedGroupInternal( ref label, minSize, false );
public static bool BeginFramedGroupEdit( ref string label ) public static bool BeginFramedGroupEdit( ref string label )
=> BeginFramedGroupInternal( ref label, ZeroVector, true ); => BeginFramedGroupInternal( ref label, Vector2.Zero, true );
public static bool BeginFramedGroupEdit( ref string label, Vector2 minSize ) public static bool BeginFramedGroupEdit( ref string label, Vector2 minSize )
=> BeginFramedGroupInternal( ref label, minSize, true ); => BeginFramedGroupInternal( ref label, minSize, true );
@ -27,8 +27,8 @@ namespace Penumbra.UI.Custom
ImGui.BeginGroup(); // First group ImGui.BeginGroup(); // First group
ImGui.PushStyleVar( ImGuiStyleVar.FramePadding, ZeroVector ); ImGui.PushStyleVar( ImGuiStyleVar.FramePadding, Vector2.Zero );
ImGui.PushStyleVar( ImGuiStyleVar.ItemSpacing, ZeroVector ); ImGui.PushStyleVar( ImGuiStyleVar.ItemSpacing, Vector2.Zero );
ImGui.BeginGroup(); // Second group ImGui.BeginGroup(); // Second group
@ -39,7 +39,7 @@ namespace Penumbra.UI.Custom
} }
// Ensure width. // Ensure width.
ImGui.Dummy( new Vector2( effectiveSize.X, 0 ) ); ImGui.Dummy( Vector2.UnitX * effectiveSize.X );
// Ensure left half boundary width/distance. // Ensure left half boundary width/distance.
ImGui.Dummy( halfFrameHeight ); ImGui.Dummy( halfFrameHeight );
@ -64,7 +64,7 @@ namespace Penumbra.UI.Custom
var labelMax = ImGui.GetItemRectMax(); var labelMax = ImGui.GetItemRectMax();
ImGui.SameLine(); ImGui.SameLine();
// Ensure height and distance to label. // Ensure height and distance to label.
ImGui.Dummy( new Vector2( 0, frameHeight + itemSpacing.Y ) ); ImGui.Dummy( Vector2.UnitX * ( frameHeight + itemSpacing.Y ) );
ImGui.BeginGroup(); // Fourth Group. ImGui.BeginGroup(); // Fourth Group.
@ -96,8 +96,8 @@ namespace Penumbra.UI.Custom
ImGui.PopItemWidth(); ImGui.PopItemWidth();
ImGui.PushStyleVar( ImGuiStyleVar.FramePadding, ZeroVector ); ImGui.PushStyleVar( ImGuiStyleVar.FramePadding, Vector2.Zero );
ImGui.PushStyleVar( ImGuiStyleVar.ItemSpacing, ZeroVector ); ImGui.PushStyleVar( ImGuiStyleVar.ItemSpacing, Vector2.Zero );
ImGui.EndGroup(); // Close fourth group ImGui.EndGroup(); // Close fourth group
ImGui.EndGroup(); // Close third group ImGui.EndGroup(); // Close third group
@ -106,19 +106,19 @@ namespace Penumbra.UI.Custom
// Ensure right distance. // Ensure right distance.
ImGui.Dummy( halfFrameHeight ); ImGui.Dummy( halfFrameHeight );
// Ensure bottom distance // Ensure bottom distance
ImGui.Dummy( new Vector2( 0, frameHeight / 2 - itemSpacing.Y ) ); ImGui.Dummy( Vector2.UnitX * ( frameHeight / 2 - itemSpacing.Y ) );
ImGui.EndGroup(); // Close second group ImGui.EndGroup(); // Close second group
var itemMin = ImGui.GetItemRectMin(); var itemMin = ImGui.GetItemRectMin();
var itemMax = ImGui.GetItemRectMax(); var itemMax = ImGui.GetItemRectMax();
var (currentLabelMin, currentLabelMax) = LabelStack[ LabelStack.Count - 1 ]; var (currentLabelMin, currentLabelMax) = LabelStack[ ^1 ];
LabelStack.RemoveAt( LabelStack.Count - 1 ); LabelStack.RemoveAt( LabelStack.Count - 1 );
var halfFrame = new Vector2( frameHeight / 8, frameHeight / 2 ); var halfFrame = new Vector2( frameHeight / 8, frameHeight / 2 );
currentLabelMin.X -= itemSpacing.X; currentLabelMin.X -= itemSpacing.X;
currentLabelMax.X += itemSpacing.X; currentLabelMax.X += itemSpacing.X;
var frameMin = itemMin + halfFrame; var frameMin = itemMin + halfFrame;
var frameMax = itemMax - new Vector2( halfFrame.X, 0 ); var frameMax = itemMax - Vector2.UnitX * halfFrame.X;
// Left // Left
DrawClippedRect( new Vector2( -float.MaxValue, -float.MaxValue ), new Vector2( currentLabelMin.X, float.MaxValue ), frameMin, DrawClippedRect( new Vector2( -float.MaxValue, -float.MaxValue ), new Vector2( currentLabelMin.X, float.MaxValue ), frameMin,
@ -136,13 +136,11 @@ namespace Penumbra.UI.Custom
ImGui.PopStyleVar( 2 ); ImGui.PopStyleVar( 2 );
// This seems wrong? // This seems wrong?
// ImGui.SetWindowSize( new Vector2( ImGui.GetWindowSize().X + frameHeight, ImGui.GetWindowSize().Y ) ); // ImGui.SetWindowSize( new Vector2( ImGui.GetWindowSize().X + frameHeight, ImGui.GetWindowSize().Y ) );
ImGui.Dummy( ZeroVector ); ImGui.Dummy( Vector2.Zero );
ImGui.EndGroup(); // Close first group ImGui.EndGroup(); // Close first group
} }
private static readonly Vector2 ZeroVector = new( 0, 0 );
private static readonly List< (Vector2, Vector2) > LabelStack = new(); private static readonly List< (Vector2, Vector2) > LabelStack = new();
} }
} }

View file

@ -1,4 +1,6 @@
using System.Security.Cryptography.X509Certificates;
using System.Windows.Forms; using System.Windows.Forms;
using Dalamud.Interface;
using ImGuiNET; using ImGuiNET;
namespace Penumbra.UI.Custom namespace Penumbra.UI.Custom
@ -23,7 +25,7 @@ namespace Penumbra.UI.Custom
{ {
public static void VerticalDistance( float distance ) public static void VerticalDistance( float distance )
{ {
ImGui.SetCursorPosY( ImGui.GetCursorPosY() + distance ); ImGui.SetCursorPosY( ImGui.GetCursorPosY() + distance * ImGuiHelpers.GlobalScale );
} }
public static void RightJustifiedText( float pos, string text ) public static void RightJustifiedText( float pos, string text )
@ -39,4 +41,25 @@ namespace Penumbra.UI.Custom
ImGui.SameLine( pos ); ImGui.SameLine( pos );
} }
} }
public static partial class ImGuiCustom
{
public static void HoverTooltip( string text )
{
if( ImGui.IsItemHovered() )
{
ImGui.SetTooltip( text );
}
}
}
public static partial class ImGuiCustom
{
public static void PrintIcon( FontAwesomeIcon icon )
{
ImGui.PushFont( UiBuilder.IconFont );
ImGui.TextUnformatted( icon.ToIconString() );
ImGui.PopFont();
}
}
} }

View file

@ -0,0 +1,52 @@
using System;
using System.Numerics;
using ImGuiNET;
namespace Penumbra.UI.Custom
{
public static partial class ImGuiRaii
{
public static Color PushColor( ImGuiCol idx, uint color, bool condition = true )
=> new Color().Push( idx, color, condition );
public static Color PushColor( ImGuiCol idx, Vector4 color, bool condition = true )
=> new Color().Push( idx, color, condition );
public class Color : IDisposable
{
private int _count;
public Color Push( ImGuiCol idx, uint color, bool condition = true )
{
if( condition )
{
ImGui.PushStyleColor( idx, color );
++_count;
}
return this;
}
public Color Push( ImGuiCol idx, Vector4 color, bool condition = true )
{
if( condition )
{
ImGui.PushStyleColor( idx, color );
++_count;
}
return this;
}
public void Pop( int num = 1 )
{
num = Math.Min( num, _count );
_count -= num;
ImGui.PopStyleColor( num );
}
public void Dispose()
=> Pop( _count );
}
}
}

View file

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
namespace Penumbra.UI.Custom
{
public static partial class ImGuiRaii
{
public static EndStack DeferredEnd( Action a, bool condition = true )
=> new EndStack().Push( a, condition );
public class EndStack : IDisposable
{
private readonly Stack< Action > _cleanActions = new();
public EndStack Push( Action a, bool condition = true )
{
if( condition )
{
_cleanActions.Push( a );
}
return this;
}
public EndStack Pop( int num = 1 )
{
while( num-- > 0 && _cleanActions.TryPop( out var action ) )
{
action.Invoke();
}
return this;
}
public void Dispose()
=> Pop( _cleanActions.Count );
}
}
}

View file

@ -0,0 +1,39 @@
using System;
using ImGuiNET;
namespace Penumbra.UI.Custom
{
public static partial class ImGuiRaii
{
public static Font PushFont( ImFontPtr font )
=> new( font );
public class Font : IDisposable
{
private int _count;
public Font( ImFontPtr font )
=> Push( font );
public Font Push( ImFontPtr font )
{
ImGui.PushFont( font );
++_count;
return this;
}
public void Pop( int num = 1 )
{
num = Math.Min( num, _count );
_count -= num;
while( num-- > 0 )
{
ImGui.PopFont();
}
}
public void Dispose()
=> Pop( _count );
}
}
}

View file

@ -0,0 +1,72 @@
using System;
using System.Diagnostics;
using Dalamud.Interface;
using ImGuiNET;
namespace Penumbra.UI.Custom
{
public static partial class ImGuiRaii
{
public static Indent PushIndent( float f, bool scaled = true, bool condition = true )
=> new Indent().Push( f, condition );
public static Indent PushIndent( int i = 1, bool scaled = true, bool condition = true )
=> new Indent().Push( i, condition );
public class Indent : IDisposable
{
private float _indentation;
public Indent Push( float indent, bool scaled = true, bool condition = true )
{
Debug.Assert( indent >= 0f );
if( condition )
{
if( scaled )
{
indent *= ImGuiHelpers.GlobalScale;
}
ImGui.Indent( indent );
_indentation += indent;
}
return this;
}
public Indent Push( uint i = 1, bool scaled = true, bool condition = true )
{
if( condition )
{
var spacing = i * ImGui.GetStyle().IndentSpacing * ( scaled ? ImGuiHelpers.GlobalScale : 1f );
ImGui.Indent( spacing );
_indentation += spacing;
}
return this;
}
public void Pop( float indent, bool scaled = true )
{
if( scaled )
{
indent *= ImGuiHelpers.GlobalScale;
}
Debug.Assert( indent >= 0f );
ImGui.Unindent( indent );
_indentation -= indent;
}
public void Pop( uint i, bool scaled = true )
{
var spacing = i * ImGui.GetStyle().IndentSpacing * ( scaled ? ImGuiHelpers.GlobalScale : 1f );
ImGui.Unindent( spacing );
_indentation += spacing;
}
public void Dispose()
=> Pop( _indentation, false );
}
}
}

View file

@ -0,0 +1,92 @@
using System;
using System.Numerics;
using ImGuiNET;
namespace Penumbra.UI.Custom
{
public static partial class ImGuiRaii
{
public static Style PushStyle( ImGuiStyleVar idx, float value, bool condition = true )
=> new Style().Push( idx, value, condition );
public static Style PushStyle( ImGuiStyleVar idx, Vector2 value, bool condition = true )
=> new Style().Push( idx, value, condition );
public class Style : IDisposable
{
private int _count;
[System.Diagnostics.Conditional( "DEBUG" )]
private static void CheckStyleIdx( ImGuiStyleVar idx, Type type )
{
var shouldThrow = idx switch
{
ImGuiStyleVar.Alpha => type != typeof( float ),
ImGuiStyleVar.WindowPadding => type != typeof( Vector2 ),
ImGuiStyleVar.WindowRounding => type != typeof( float ),
ImGuiStyleVar.WindowBorderSize => type != typeof( float ),
ImGuiStyleVar.WindowMinSize => type != typeof( Vector2 ),
ImGuiStyleVar.WindowTitleAlign => type != typeof( Vector2 ),
ImGuiStyleVar.ChildRounding => type != typeof( float ),
ImGuiStyleVar.ChildBorderSize => type != typeof( float ),
ImGuiStyleVar.PopupRounding => type != typeof( float ),
ImGuiStyleVar.PopupBorderSize => type != typeof( float ),
ImGuiStyleVar.FramePadding => type != typeof( Vector2 ),
ImGuiStyleVar.FrameRounding => type != typeof( float ),
ImGuiStyleVar.FrameBorderSize => type != typeof( float ),
ImGuiStyleVar.ItemSpacing => type != typeof( Vector2 ),
ImGuiStyleVar.ItemInnerSpacing => type != typeof( Vector2 ),
ImGuiStyleVar.IndentSpacing => type != typeof( float ),
ImGuiStyleVar.CellPadding => type != typeof( Vector2 ),
ImGuiStyleVar.ScrollbarSize => type != typeof( float ),
ImGuiStyleVar.ScrollbarRounding => type != typeof( float ),
ImGuiStyleVar.GrabMinSize => type != typeof( float ),
ImGuiStyleVar.GrabRounding => type != typeof( float ),
ImGuiStyleVar.TabRounding => type != typeof( float ),
ImGuiStyleVar.ButtonTextAlign => type != typeof( Vector2 ),
ImGuiStyleVar.SelectableTextAlign => type != typeof( Vector2 ),
_ => throw new ArgumentOutOfRangeException( nameof( idx ), idx, null ),
};
if( shouldThrow )
{
throw new ArgumentException( $"Unable to push {type} to {idx}." );
}
}
public Style Push( ImGuiStyleVar idx, float value, bool condition = true )
{
if( condition )
{
CheckStyleIdx( idx, typeof( float ) );
ImGui.PushStyleVar( idx, value );
++_count;
}
return this;
}
public Style Push( ImGuiStyleVar idx, Vector2 value, bool condition = true )
{
if( condition )
{
CheckStyleIdx( idx, typeof( Vector2 ) );
ImGui.PushStyleVar( idx, value );
++_count;
}
return this;
}
public void Pop( int num = 1 )
{
num = Math.Min( num, _count );
_count -= num;
ImGui.PopStyleVar( num );
}
public void Dispose()
=> Pop( _count );
}
}
}

View file

@ -1,4 +1,5 @@
using ImGuiNET; using ImGuiNET;
using Penumbra.UI.Custom;
namespace Penumbra.UI namespace Penumbra.UI
{ {
@ -30,8 +31,15 @@ namespace Penumbra.UI
return; return;
} }
if( ImGui.BeginMenu( MenuLabel ) ) using var raii = ImGuiRaii.DeferredEnd( ImGui.EndMainMenuBar );
if( !ImGui.BeginMenu( MenuLabel ) )
{ {
return;
}
raii.Push( ImGui.EndMenu );
if( ImGui.MenuItem( MenuItemToggle, SlashCommand, _base._menu.Visible ) ) if( ImGui.MenuItem( MenuItemToggle, SlashCommand, _base._menu.Visible ) )
{ {
_base.FlipVisibility(); _base.FlipVisibility();
@ -47,11 +55,6 @@ namespace Penumbra.UI
_showDebugBar = false; _showDebugBar = false;
} }
#endif #endif
ImGui.EndMenu();
}
ImGui.EndMainMenuBar();
} }
} }
} }

View file

@ -7,6 +7,7 @@ using Dalamud.Logging;
using ImGuiNET; using ImGuiNET;
using Penumbra.Mod; using Penumbra.Mod;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.UI.Custom;
using Penumbra.Util; using Penumbra.Util;
namespace Penumbra.UI namespace Penumbra.UI
@ -97,12 +98,7 @@ namespace Penumbra.UI
{ {
ImGui.InputTextWithHint( "##New Collection", "New Collection", ref _newCollectionName, 64 ); ImGui.InputTextWithHint( "##New Collection", "New Collection", ref _newCollectionName, 64 );
var changedStyle = false; using var style = ImGuiRaii.PushStyle( ImGuiStyleVar.Alpha, 0.5f, _newCollectionName.Length == 0 );
if( _newCollectionName.Length == 0 )
{
changedStyle = true;
ImGui.PushStyleVar( ImGuiStyleVar.Alpha, 0.5f );
}
if( ImGui.Button( "Create New Empty Collection" ) && _newCollectionName.Length > 0 ) if( ImGui.Button( "Create New Empty Collection" ) && _newCollectionName.Length > 0 )
{ {
@ -115,10 +111,7 @@ namespace Penumbra.UI
CreateNewCollection( _manager.Collections.CurrentCollection.Settings ); CreateNewCollection( _manager.Collections.CurrentCollection.Settings );
} }
if( changedStyle ) style.Pop();
{
ImGui.PopStyleVar();
}
if( _manager.Collections.Collections.Count > 1 if( _manager.Collections.Collections.Count > 1
&& _manager.Collections.CurrentCollection.Name != ModCollection.DefaultCollection ) && _manager.Collections.CurrentCollection.Name != ModCollection.DefaultCollection )
@ -161,11 +154,8 @@ namespace Penumbra.UI
{ {
var index = _currentCollectionIndex; var index = _currentCollectionIndex;
var combo = ImGui.Combo( LabelCurrentCollection, ref index, _collectionNames ); var combo = ImGui.Combo( LabelCurrentCollection, ref index, _collectionNames );
if( tooltip && ImGui.IsItemHovered() ) ImGuiCustom.HoverTooltip(
{
ImGui.SetTooltip(
"This collection will be modified when using the Installed Mods tab and making changes. It does not apply to anything by itself." ); "This collection will be modified when using the Installed Mods tab and making changes. It does not apply to anything by itself." );
}
if( combo ) if( combo )
{ {
@ -182,15 +172,12 @@ namespace Penumbra.UI
_currentDefaultIndex = index; _currentDefaultIndex = index;
} }
if( ImGui.IsItemHovered() ) ImGuiCustom.HoverTooltip(
{
ImGui.SetTooltip(
"Mods in the default collection are loaded for any character that is not explicitly named in the character collections below.\n" "Mods in the default collection are loaded for any character that is not explicitly named in the character collections below.\n"
+ "They also take precedence before the forced collection." ); + "They also take precedence before the forced collection." );
}
ImGui.SameLine(); ImGui.SameLine();
ImGui.Dummy( new Vector2( 24, 0 ) ); ImGuiHelpers.ScaledDummy( 24, 0 );
ImGui.SameLine(); ImGui.SameLine();
ImGui.Text( "Default Collection" ); ImGui.Text( "Default Collection" );
} }
@ -204,15 +191,12 @@ namespace Penumbra.UI
_currentForcedIndex = index; _currentForcedIndex = index;
} }
if( ImGui.IsItemHovered() ) ImGuiCustom.HoverTooltip(
{
ImGui.SetTooltip(
"Mods in the forced collection are always loaded if not overwritten by anything in the current or character-based collection.\n" "Mods in the forced collection are always loaded if not overwritten by anything in the current or character-based collection.\n"
+ "Please avoid mixing meta-manipulating mods in Forced and other collections, as this will probably not work correctly." ); + "Please avoid mixing meta-manipulating mods in Forced and other collections, as this will probably not work correctly." );
}
ImGui.SameLine(); ImGui.SameLine();
ImGui.Dummy( new Vector2( 24, 0 ) ); ImGuiHelpers.ScaledDummy( 24, 0 );
ImGui.SameLine(); ImGui.SameLine();
ImGui.Text( "Forced Collection" ); ImGui.Text( "Forced Collection" );
} }
@ -221,12 +205,7 @@ namespace Penumbra.UI
{ {
ImGui.InputTextWithHint( "##New Character", "New Character Name", ref _newCharacterName, 32 ); ImGui.InputTextWithHint( "##New Character", "New Character Name", ref _newCharacterName, 32 );
var changedStyle = false; using var style = ImGuiRaii.PushStyle( ImGuiStyleVar.Alpha, 0.5f, _newCharacterName.Length == 0 );
if( _newCharacterName.Length == 0 )
{
changedStyle = true;
ImGui.PushStyleVar( ImGuiStyleVar.Alpha, 0.5f );
}
ImGui.SameLine(); ImGui.SameLine();
if( ImGui.Button( "Create New Character Collection" ) && _newCharacterName.Length > 0 ) if( ImGui.Button( "Create New Character Collection" ) && _newCharacterName.Length > 0 )
@ -236,25 +215,19 @@ namespace Penumbra.UI
_newCharacterName = string.Empty; _newCharacterName = string.Empty;
} }
if( ImGui.IsItemHovered() ) style.Pop();
{
ImGui.SetTooltip( ImGuiCustom.HoverTooltip(
"A character collection will be used whenever you manually redraw a character with the Name you have set up.\n" "A character collection will be used whenever you manually redraw a character with the Name you have set up.\n"
+ "If you enable automatic character redraws in the Settings tab, penumbra will try to use Character collections for corresponding characters automatically.\n" ); + "If you enable automatic character redraws in the Settings tab, penumbra will try to use Character collections for corresponding characters automatically.\n" );
} }
if( changedStyle )
{
ImGui.PopStyleVar();
}
}
private void DrawCharacterCollectionSelectors() private void DrawCharacterCollectionSelectors()
{ {
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndChild );
if( !ImGui.BeginChild( "##CollectionChild", AutoFillSize, true ) ) if( !ImGui.BeginChild( "##CollectionChild", AutoFillSize, true ) )
{ {
ImGui.EndChild();
return; return;
} }
@ -272,21 +245,20 @@ namespace Penumbra.UI
} }
ImGui.SameLine(); ImGui.SameLine();
ImGui.PushFont( UiBuilder.IconFont );
using var font = ImGuiRaii.PushFont( UiBuilder.IconFont );
if( ImGui.Button( $"{FontAwesomeIcon.Trash.ToIconString()}##{name}" ) ) if( ImGui.Button( $"{FontAwesomeIcon.Trash.ToIconString()}##{name}" ) )
{ {
_manager.Collections.RemoveCharacterCollection( name ); _manager.Collections.RemoveCharacterCollection( name );
} }
ImGui.PopFont(); font.Pop();
ImGui.SameLine(); ImGui.SameLine();
ImGui.Text( name ); ImGui.Text( name );
} }
DrawNewCharacterCollection(); DrawNewCharacterCollection();
ImGui.EndChild();
} }
public void Draw() public void Draw()
@ -296,19 +268,20 @@ namespace Penumbra.UI
return; return;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTabItem )
.Push( ImGui.EndChild );
if( ImGui.BeginChild( "##CollectionHandling", new Vector2( -1, ImGui.GetTextLineHeightWithSpacing() * 6 ), true ) ) if( ImGui.BeginChild( "##CollectionHandling", new Vector2( -1, ImGui.GetTextLineHeightWithSpacing() * 6 ), true ) )
{ {
DrawCurrentCollectionSelector( true ); DrawCurrentCollectionSelector( true );
ImGui.Dummy( new Vector2( 0, 10 ) ); ImGuiHelpers.ScaledDummy( 0, 10 );
DrawNewCollectionInput(); DrawNewCollectionInput();
} }
ImGui.EndChild(); raii.Pop();
DrawCharacterCollectionSelectors(); DrawCharacterCollectionSelectors();
ImGui.EndTabItem();
} }
} }
} }

View file

@ -13,6 +13,7 @@ using Penumbra.GameData.Util;
using Penumbra.Interop; using Penumbra.Interop;
using Penumbra.Meta; using Penumbra.Meta;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.UI.Custom;
using Penumbra.Util; using Penumbra.Util;
namespace Penumbra.UI namespace Penumbra.UI
@ -38,6 +39,8 @@ namespace Penumbra.UI
return; return;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTable );
var identifier = GameData.GameData.GetIdentifier(); var identifier = GameData.GameData.GetIdentifier();
foreach( var (actor, equip) in players ) foreach( var (actor, equip) in players )
@ -109,8 +112,6 @@ namespace Penumbra.UI
ImGui.Text( identifier.Identify( equip.RFinger.Set, 0, equip.RFinger.Variant, EquipSlot.LFinger )?.Name.ToString() ?? "Unknown" ); ImGui.Text( identifier.Identify( equip.RFinger.Set, 0, equip.RFinger.Variant, EquipSlot.LFinger )?.Name.ToString() ?? "Unknown" );
// @formatter:on // @formatter:on
} }
ImGui.EndTable();
} }
private static void PrintValue( string name, string value ) private static void PrintValue( string name, string value )
@ -135,6 +136,8 @@ namespace Penumbra.UI
return; return;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTable );
var manager = Service< ModManager >.Get(); var manager = Service< ModManager >.Get();
PrintValue( "Active Collection", manager.Collections.ActiveCollection.Name ); PrintValue( "Active Collection", manager.Collections.ActiveCollection.Name );
PrintValue( "Mod Manager BasePath", manager.BasePath.Name ); PrintValue( "Mod Manager BasePath", manager.BasePath.Name );
@ -147,8 +150,6 @@ namespace Penumbra.UI
( !Penumbra.Config.TempDirectory.Any() || Path.IsPathRooted( Penumbra.Config.TempDirectory ) ).ToString() ); ( !Penumbra.Config.TempDirectory.Any() || Path.IsPathRooted( Penumbra.Config.TempDirectory ) ).ToString() );
PrintValue( "Mod Manager Temp Path Exists", Directory.Exists( manager.TempPath.FullName ).ToString() ); PrintValue( "Mod Manager Temp Path Exists", Directory.Exists( manager.TempPath.FullName ).ToString() );
PrintValue( "Mod Manager Temp Path IsWritable", manager.TempWritable.ToString() ); PrintValue( "Mod Manager Temp Path IsWritable", manager.TempWritable.ToString() );
ImGui.EndTable();
} }
private void DrawDebugTabRedraw() private void DrawDebugTabRedraw()
@ -207,9 +208,11 @@ namespace Penumbra.UI
.GetField( "_inGPose", BindingFlags.Instance | BindingFlags.NonPublic ) .GetField( "_inGPose", BindingFlags.Instance | BindingFlags.NonPublic )
?.GetValue( _penumbra.ObjectReloader ); ?.GetValue( _penumbra.ObjectReloader );
using var raii = new ImGuiRaii.EndStack();
if( ImGui.BeginTable( "##RedrawData", 2, ImGuiTableFlags.SizingFixedFit, if( ImGui.BeginTable( "##RedrawData", 2, ImGuiTableFlags.SizingFixedFit,
new Vector2( -1, ImGui.GetTextLineHeightWithSpacing() * 7 ) ) ) new Vector2( -1, ImGui.GetTextLineHeightWithSpacing() * 7 ) ) )
{ {
raii.Push( ImGui.EndTable );
PrintValue( "Current Wait Frame", waitFrames?.ToString() ?? "null" ); PrintValue( "Current Wait Frame", waitFrames?.ToString() ?? "null" );
PrintValue( "Current Frame", currentFrame?.ToString() ?? "null" ); PrintValue( "Current Frame", currentFrame?.ToString() ?? "null" );
PrintValue( "Currently in GPose", gPose?.ToString() ?? "null" ); PrintValue( "Currently in GPose", gPose?.ToString() ?? "null" );
@ -222,13 +225,13 @@ namespace Penumbra.UI
PrintValue( "Current Object Address", currentObject?.Address.ToString( "X16" ) ?? "null" ); PrintValue( "Current Object Address", currentObject?.Address.ToString( "X16" ) ?? "null" );
PrintValue( "Current Object Index", currentObjectIdx >= 0 ? currentObjectIdx.ToString() : "null" ); PrintValue( "Current Object Index", currentObjectIdx >= 0 ? currentObjectIdx.ToString() : "null" );
PrintValue( "Current Object Render Flags", ( ( int? )currentRender )?.ToString( "X8" ) ?? "null" ); PrintValue( "Current Object Render Flags", ( ( int? )currentRender )?.ToString( "X8" ) ?? "null" );
ImGui.EndTable();
} }
if( queue.Any() if( queue.Any()
&& ImGui.BeginTable( "##RedrawTable", 3, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.ScrollX, && ImGui.BeginTable( "##RedrawTable", 3, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.ScrollX,
new Vector2( -1, ImGui.GetTextLineHeightWithSpacing() * queue.Count ) ) ) new Vector2( -1, ImGui.GetTextLineHeightWithSpacing() * queue.Count ) ) )
{ {
raii.Push( ImGui.EndTable );
foreach( var (objectId, objectName, redraw) in queue ) foreach( var (objectId, objectName, redraw) in queue )
{ {
ImGui.TableNextRow(); ImGui.TableNextRow();
@ -239,8 +242,6 @@ namespace Penumbra.UI
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImGui.Text( redraw.ToString() ); ImGui.Text( redraw.ToString() );
} }
ImGui.EndTable();
} }
if( queue.Any() && ImGui.Button( "Clear" ) ) if( queue.Any() && ImGui.Button( "Clear" ) )
@ -263,6 +264,8 @@ namespace Penumbra.UI
return; return;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTable );
foreach( var collection in Service< ModManager >.Get().Collections.Collections.Values.Where( c => c.Cache != null ) ) foreach( var collection in Service< ModManager >.Get().Collections.Collections.Values.Where( c => c.Cache != null ) )
{ {
var manip = collection.Cache!.MetaManipulations; var manip = collection.Cache!.MetaManipulations;
@ -285,39 +288,58 @@ namespace Penumbra.UI
ImGui.Text( info.Changed ? "Data Changed" : "Unchanged" ); ImGui.Text( info.Changed ? "Data Changed" : "Unchanged" );
} }
} }
ImGui.EndTable();
} }
private void DrawDebugTabIpc() private void DrawDebugTabIpc()
{ {
if( !ImGui.CollapsingHeader( "IPC##Debug" ) ) if( !ImGui.CollapsingHeader( "IPC##Debug" ) )
{ {
return; return;
} }
var ipc = _penumbra.Ipc; var ipc = _penumbra.Ipc;
ImGui.Text($"API Version: {ipc.Api.ApiVersion}" ); ImGui.Text( $"API Version: {ipc.Api.ApiVersion}" );
ImGui.Text("Available subscriptions:" ); ImGui.Text( "Available subscriptions:" );
ImGui.Indent(); using var indent = ImGuiRaii.PushIndent();
if (ipc.ProviderApiVersion != null) if( ipc.ProviderApiVersion != null )
{
ImGui.Text( PenumbraIpc.LabelProviderApiVersion ); ImGui.Text( PenumbraIpc.LabelProviderApiVersion );
}
if( ipc.ProviderRedrawName != null ) if( ipc.ProviderRedrawName != null )
{
ImGui.Text( PenumbraIpc.LabelProviderRedrawName ); ImGui.Text( PenumbraIpc.LabelProviderRedrawName );
}
if( ipc.ProviderRedrawObject != null ) if( ipc.ProviderRedrawObject != null )
{
ImGui.Text( PenumbraIpc.LabelProviderRedrawObject ); ImGui.Text( PenumbraIpc.LabelProviderRedrawObject );
}
if( ipc.ProviderRedrawAll != null ) if( ipc.ProviderRedrawAll != null )
{
ImGui.Text( PenumbraIpc.LabelProviderRedrawAll ); ImGui.Text( PenumbraIpc.LabelProviderRedrawAll );
}
if( ipc.ProviderResolveDefault != null ) if( ipc.ProviderResolveDefault != null )
{
ImGui.Text( PenumbraIpc.LabelProviderResolveDefault ); ImGui.Text( PenumbraIpc.LabelProviderResolveDefault );
}
if( ipc.ProviderResolveCharacter != null ) if( ipc.ProviderResolveCharacter != null )
{
ImGui.Text( PenumbraIpc.LabelProviderResolveCharacter ); ImGui.Text( PenumbraIpc.LabelProviderResolveCharacter );
}
if( ipc.ProviderChangedItemTooltip != null ) if( ipc.ProviderChangedItemTooltip != null )
{
ImGui.Text( PenumbraIpc.LabelProviderChangedItemTooltip ); ImGui.Text( PenumbraIpc.LabelProviderChangedItemTooltip );
}
if( ipc.ProviderChangedItemClick != null ) if( ipc.ProviderChangedItemClick != null )
{
ImGui.Text( PenumbraIpc.LabelProviderChangedItemClick ); ImGui.Text( PenumbraIpc.LabelProviderChangedItemClick );
ImGui.Unindent(); }
} }
private void DrawDebugTab() private void DrawDebugTab()
@ -327,6 +349,8 @@ namespace Penumbra.UI
return; return;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTabItem );
DrawDebugTabGeneral(); DrawDebugTabGeneral();
ImGui.NewLine(); ImGui.NewLine();
DrawDebugTabRedraw(); DrawDebugTabRedraw();
@ -337,8 +361,6 @@ namespace Penumbra.UI
ImGui.NewLine(); ImGui.NewLine();
DrawDebugTabIpc(); DrawDebugTabIpc();
ImGui.NewLine(); ImGui.NewLine();
ImGui.EndTabItem();
} }
} }
} }

View file

@ -5,6 +5,7 @@ using ImGuiNET;
using Penumbra.GameData.Util; using Penumbra.GameData.Util;
using Penumbra.Meta; using Penumbra.Meta;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.UI.Custom;
using Penumbra.Util; using Penumbra.Util;
namespace Penumbra.UI namespace Penumbra.UI
@ -14,7 +15,6 @@ namespace Penumbra.UI
private class TabEffective private class TabEffective
{ {
private const string LabelTab = "Effective Changes"; private const string LabelTab = "Effective Changes";
private static readonly string LongArrowLeft = $"{( char )FontAwesomeIcon.LongArrowAltLeft}";
private readonly ModManager _modManager; private readonly ModManager _modManager;
private readonly float _leftTextLength = private readonly float _leftTextLength =
@ -27,14 +27,12 @@ namespace Penumbra.UI
private static void DrawFileLine( FileInfo file, GamePath path ) private static void DrawFileLine( FileInfo file, GamePath path )
{ {
ImGui.TableNextColumn(); ImGui.TableNextColumn();
Custom.ImGuiCustom.CopyOnClickSelectable( path ); ImGuiCustom.CopyOnClickSelectable( path );
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImGui.PushFont( UiBuilder.IconFont ); ImGuiCustom.PrintIcon( FontAwesomeIcon.LongArrowAltLeft );
ImGui.TextUnformatted( LongArrowLeft );
ImGui.PopFont();
ImGui.SameLine(); ImGui.SameLine();
Custom.ImGuiCustom.CopyOnClickSelectable( file.FullName ); ImGuiCustom.CopyOnClickSelectable( file.FullName );
} }
private static void DrawManipulationLine( MetaManipulation manip, Mod.Mod mod ) private static void DrawManipulationLine( MetaManipulation manip, Mod.Mod mod )
@ -43,9 +41,7 @@ namespace Penumbra.UI
ImGui.Selectable( manip.IdentifierString() ); ImGui.Selectable( manip.IdentifierString() );
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImGui.PushFont( UiBuilder.IconFont ); ImGuiCustom.PrintIcon( FontAwesomeIcon.LongArrowAltLeft );
ImGui.TextUnformatted( LongArrowLeft );
ImGui.PopFont();
ImGui.SameLine(); ImGui.SameLine();
ImGui.Selectable( mod.Data.Meta.Name ); ImGui.Selectable( mod.Data.Meta.Name );
} }
@ -57,6 +53,8 @@ namespace Penumbra.UI
return; return;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTabItem );
const ImGuiTableFlags flags = ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollX; const ImGuiTableFlags flags = ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollX;
var activeCollection = _modManager.Collections.ActiveCollection.Cache; var activeCollection = _modManager.Collections.ActiveCollection.Cache;
@ -66,8 +64,8 @@ namespace Penumbra.UI
? ( activeCollection.ResolvedFiles.Count, activeCollection.MetaManipulations.Count ) ? ( activeCollection.ResolvedFiles.Count, activeCollection.MetaManipulations.Count )
: ( 0, 0 ); : ( 0, 0 );
var (forcedResolved, forcedMeta) = forcedCollection != null var (forcedResolved, forcedMeta) = forcedCollection != null
? (forcedCollection.ResolvedFiles.Count, forcedCollection.MetaManipulations.Count) ? ( forcedCollection.ResolvedFiles.Count, forcedCollection.MetaManipulations.Count )
: (0, 0); : ( 0, 0 );
var lines = activeResolved + forcedResolved + activeMeta + forcedMeta; var lines = activeResolved + forcedResolved + activeMeta + forcedMeta;
ImGuiListClipperPtr clipper; ImGuiListClipperPtr clipper;
@ -80,6 +78,7 @@ namespace Penumbra.UI
if( ImGui.BeginTable( "##effective_changes", 2, flags, AutoFillSize ) ) if( ImGui.BeginTable( "##effective_changes", 2, flags, AutoFillSize ) )
{ {
raii.Push( ImGui.EndTable );
ImGui.TableSetupColumn( "##tableGamePathCol", ImGuiTableColumnFlags.None, _leftTextLength ); ImGui.TableSetupColumn( "##tableGamePathCol", ImGuiTableColumnFlags.None, _leftTextLength );
while( clipper.Step() ) while( clipper.Step() )
{ {
@ -89,32 +88,28 @@ namespace Penumbra.UI
ImGui.TableNextRow(); ImGui.TableNextRow();
if( row < activeResolved ) if( row < activeResolved )
{ {
var file = activeCollection!.ResolvedFiles.ElementAt( row ); var (gamePath, file) = activeCollection!.ResolvedFiles.ElementAt( row );
DrawFileLine( file.Value, file.Key ); DrawFileLine( file, gamePath );
} }
else if( ( row -= activeResolved ) < forcedResolved ) else if( ( row -= activeResolved ) < forcedResolved )
{ {
var file = forcedCollection!.ResolvedFiles.ElementAt( row ); var (gamePath, file) = forcedCollection!.ResolvedFiles.ElementAt( row );
DrawFileLine( file.Value, file.Key ); DrawFileLine( file, gamePath );
} }
else if( ( row -= forcedResolved ) < activeMeta ) else if( ( row -= forcedResolved ) < activeMeta )
{ {
var manip = activeCollection!.MetaManipulations.Manipulations.ElementAt( row ); var (manip, mod) = activeCollection!.MetaManipulations.Manipulations.ElementAt( row );
DrawManipulationLine( manip.Item1, manip.Item2 ); DrawManipulationLine( manip, mod );
} }
else else
{ {
row -= activeMeta; row -= activeMeta;
var manip = forcedCollection!.MetaManipulations.Manipulations.ElementAt( row ); var (manip, mod) = forcedCollection!.MetaManipulations.Manipulations.ElementAt( row );
DrawManipulationLine( manip.Item1, manip.Item2 ); DrawManipulationLine( manip, mod );
} }
} }
} }
ImGui.EndTable();
} }
ImGui.EndTabItem();
} }
} }
} }

View file

@ -8,6 +8,7 @@ using Dalamud.Logging;
using ImGuiNET; using ImGuiNET;
using Penumbra.Importer; using Penumbra.Importer;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.UI.Custom;
using Penumbra.Util; using Penumbra.Util;
namespace Penumbra.UI namespace Penumbra.UI
@ -104,20 +105,20 @@ namespace Penumbra.UI
{ {
if( !_manager.Valid ) if( !_manager.Valid )
{ {
ImGui.PushStyleVar( ImGuiStyleVar.Alpha, 0.5f ); using var style = ImGuiRaii.PushStyle( ImGuiStyleVar.Alpha, 0.5f );
ImGui.Button( LabelImportButton ); ImGui.Button( LabelImportButton );
ImGui.PopStyleVar(); style.Pop();
ImGui.PushStyleColor( ImGuiCol.Text, ColorRed ); using var color = ImGuiRaii.PushColor( ImGuiCol.Text, ColorRed );
ImGui.Text( "Can not import since the mod directory path is not valid." ); ImGui.Text( "Can not import since the mod directory path is not valid." );
ImGui.Dummy( Vector2.UnitY * ImGui.GetTextLineHeightWithSpacing() ); ImGui.Dummy( Vector2.UnitY * ImGui.GetTextLineHeightWithSpacing() );
ImGui.PopStyleColor(); color.Pop();
ImGui.Text( "Please set the mod directory in the settings tab." ); ImGui.Text( "Please set the mod directory in the settings tab." );
ImGui.Text( "This folder should preferably be close to the root directory of your (preferably SSD) drive, for example" ); ImGui.Text( "This folder should preferably be close to the root directory of your (preferably SSD) drive, for example" );
ImGui.PushStyleColor( ImGuiCol.Text, ColorYellow ); color.Push( ImGuiCol.Text, ColorYellow );
ImGui.Text( " D:\\ffxivmods" ); ImGui.Text( " D:\\ffxivmods" );
ImGui.PopStyleColor(); color.Pop();
ImGui.Text( "You can return to this tab once you've done that." ); ImGui.Text( "You can return to this tab once you've done that." );
} }
else if( ImGui.Button( LabelImportButton ) ) else if( ImGui.Button( LabelImportButton ) )
@ -156,19 +157,19 @@ namespace Penumbra.UI
private void DrawFailedImportMessage() private void DrawFailedImportMessage()
{ {
ImGui.PushStyleColor( ImGuiCol.Text, ColorRed ); using var color = ImGuiRaii.PushColor( ImGuiCol.Text, ColorRed );
ImGui.Text( $"One or more of your modpacks failed to import:\n\t\t{_errorMessage}" ); ImGui.Text( $"One or more of your modpacks failed to import:\n\t\t{_errorMessage}" );
ImGui.PopStyleColor();
} }
public void Draw() public void Draw()
{ {
var ret = ImGui.BeginTabItem( LabelTab ); if( !ImGui.BeginTabItem( LabelTab ) )
if( !ret )
{ {
return; return;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTabItem );
if( !_isImportRunning ) if( !_isImportRunning )
{ {
DrawImportButton(); DrawImportButton();
@ -182,8 +183,6 @@ namespace Penumbra.UI
{ {
DrawFailedImportMessage(); DrawFailedImportMessage();
} }
ImGui.EndTabItem();
} }
} }
} }

View file

@ -1,5 +1,6 @@
using ImGuiNET; using ImGuiNET;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.UI.Custom;
using Penumbra.Util; using Penumbra.Util;
namespace Penumbra.UI namespace Penumbra.UI
@ -34,6 +35,8 @@ namespace Penumbra.UI
return; return;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTabItem );
if( _modManager.Mods.Count > 0 ) if( _modManager.Mods.Count > 0 )
{ {
Selector.Draw(); Selector.Draw();
@ -44,8 +47,6 @@ namespace Penumbra.UI
{ {
DrawNoModsAvailable(); DrawNoModsAvailable();
} }
ImGui.EndTabItem();
} }
} }
} }

View file

@ -2,14 +2,15 @@ using System.IO;
using System.Linq; using System.Linq;
using Dalamud.Interface; using Dalamud.Interface;
using ImGuiNET; using ImGuiNET;
using Penumbra.Api;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Util; using Penumbra.GameData.Util;
using Penumbra.Meta; using Penumbra.Meta;
using Penumbra.Mod; using Penumbra.Mod;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.Structs; using Penumbra.Structs;
using Penumbra.UI.Custom;
using Penumbra.Util; using Penumbra.Util;
using ImGui = ImGuiNET.ImGui;
namespace Penumbra.UI namespace Penumbra.UI
{ {
@ -140,6 +141,8 @@ namespace Penumbra.UI
return; return;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTabItem );
var desc = Meta.Description; var desc = Meta.Description;
var flags = _editMode var flags = _editMode
? ImGuiInputTextFlags.EnterReturnsTrue | ImGuiInputTextFlags.CtrlEnterForNewLine ? ImGuiInputTextFlags.EnterReturnsTrue | ImGuiInputTextFlags.CtrlEnterForNewLine
@ -154,17 +157,12 @@ namespace Penumbra.UI
_selector.SaveCurrentMod(); _selector.SaveCurrentMod();
} }
if( ImGui.IsItemHovered() ) ImGuiCustom.HoverTooltip( TooltipAboutEdit );
{
ImGui.SetTooltip( TooltipAboutEdit );
}
} }
else else
{ {
ImGui.TextWrapped( desc ); ImGui.TextWrapped( desc );
} }
ImGui.EndTabItem();
} }
private void DrawChangedItemsTab() private void DrawChangedItemsTab()
@ -174,31 +172,33 @@ namespace Penumbra.UI
return; return;
} }
if( ImGui.BeginListBox( LabelChangedItemsHeader, AutoFillSize ) ) using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTabItem );
if( !ImGui.BeginListBox( LabelChangedItemsHeader, AutoFillSize ) )
{ {
foreach( var item in Mod.Data.ChangedItems ) return;
}
raii.Push( ImGui.EndListBox );
foreach( var (name, data) in Mod.Data.ChangedItems )
{ {
var ret = ImGui.Selectable( item.Key ) ? MouseButton.Left : MouseButton.None; var ret = ImGui.Selectable( name ) ? MouseButton.Left : MouseButton.None;
ret = ImGui.IsItemClicked( ImGuiMouseButton.Right ) ? MouseButton.Right : ret; ret = ImGui.IsItemClicked( ImGuiMouseButton.Right ) ? MouseButton.Right : ret;
ret = ImGui.IsItemClicked( ImGuiMouseButton.Middle ) ? MouseButton.Middle : ret; ret = ImGui.IsItemClicked( ImGuiMouseButton.Middle ) ? MouseButton.Middle : ret;
if( ret != MouseButton.None ) if( ret != MouseButton.None )
{ {
_base._penumbra.Api.InvokeClick( ret, item.Value ); _base._penumbra.Api.InvokeClick( ret, data );
} }
if( _base._penumbra.Api.HasTooltip && ImGui.IsItemHovered() ) if( _base._penumbra.Api.HasTooltip && ImGui.IsItemHovered() )
{ {
ImGui.BeginTooltip(); ImGui.BeginTooltip();
_base._penumbra.Api.InvokeTooltip( item.Value ); raii.Push( ImGui.EndTooltip );
ImGui.EndTooltip(); _base._penumbra.Api.InvokeTooltip( data );
raii.Pop();
} }
} }
ImGui.EndListBox();
}
ImGui.EndTabItem();
} }
private void DrawConflictTab() private void DrawConflictTab()
@ -208,12 +208,18 @@ namespace Penumbra.UI
return; return;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTabItem );
ImGui.SetNextItemWidth( -1 ); ImGui.SetNextItemWidth( -1 );
if( ImGui.BeginListBox( LabelConflictsHeader, AutoFillSize ) ) if( !ImGui.BeginListBox( LabelConflictsHeader, AutoFillSize ) )
{ {
foreach( var kv in Mod.Cache.Conflicts ) return;
}
raii.Push( ImGui.EndListBox );
using var indent = ImGuiRaii.PushIndent( 0 );
foreach( var (mod, (files, manipulations)) in Mod.Cache.Conflicts )
{ {
var mod = kv.Key;
if( ImGui.Selectable( mod.Data.Meta.Name ) ) if( ImGui.Selectable( mod.Data.Meta.Name ) )
{ {
_selector.SelectModByDir( mod.Data.BasePath.Name ); _selector.SelectModByDir( mod.Data.BasePath.Name );
@ -222,24 +228,19 @@ namespace Penumbra.UI
ImGui.SameLine(); ImGui.SameLine();
ImGui.Text( $"(Priority {mod.Settings.Priority})" ); ImGui.Text( $"(Priority {mod.Settings.Priority})" );
ImGui.Indent( 15 ); indent.Push( 15f );
foreach( var file in kv.Value.Files ) foreach( var file in files )
{ {
ImGui.Selectable( file ); ImGui.Selectable( file );
} }
foreach( var manip in kv.Value.Manipulations ) foreach( var manip in manipulations )
{ {
ImGui.Text( manip.IdentifierString() ); ImGui.Text( manip.IdentifierString() );
} }
ImGui.Unindent( 15 ); indent.Pop( 15f );
} }
ImGui.EndListBox();
}
ImGui.EndTabItem();
} }
private void DrawFileSwapTab() private void DrawFileSwapTab()
@ -255,31 +256,31 @@ namespace Penumbra.UI
return; return;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTabItem );
const ImGuiTableFlags flags = ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollX; const ImGuiTableFlags flags = ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollX;
ImGui.SetNextItemWidth( -1 ); ImGui.SetNextItemWidth( -1 );
if( ImGui.BeginTable( LabelFileSwapHeader, 3, flags, AutoFillSize ) ) if( !ImGui.BeginTable( LabelFileSwapHeader, 3, flags, AutoFillSize ) )
{ {
foreach( var file in Meta.FileSwaps ) return;
}
raii.Push( ImGui.EndTable );
foreach( var (source, target) in Meta.FileSwaps )
{ {
ImGui.TableNextColumn(); ImGui.TableNextColumn();
Custom.ImGuiCustom.CopyOnClickSelectable( file.Key ); ImGuiCustom.CopyOnClickSelectable( source );
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImGui.PushFont( UiBuilder.IconFont ); ImGuiCustom.PrintIcon( FontAwesomeIcon.LongArrowAltRight );
ImGui.TextUnformatted( $"{( char )FontAwesomeIcon.LongArrowAltRight}" );
ImGui.PopFont();
ImGui.TableNextColumn(); ImGui.TableNextColumn();
Custom.ImGuiCustom.CopyOnClickSelectable( file.Value ); ImGuiCustom.CopyOnClickSelectable( target );
ImGui.TableNextRow(); ImGui.TableNextRow();
} }
ImGui.EndTable();
}
ImGui.EndTabItem();
} }
private void UpdateFilenameList() private void UpdateFilenameList()
@ -329,30 +330,26 @@ namespace Penumbra.UI
return; return;
} }
if( ImGui.IsItemHovered() ) using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTabItem );
{ ImGuiCustom.HoverTooltip( TooltipFilesTab );
ImGui.SetTooltip( TooltipFilesTab );
}
ImGui.SetNextItemWidth( -1 ); ImGui.SetNextItemWidth( -1 );
if( ImGui.BeginListBox( LabelFileListHeader, AutoFillSize ) ) if( ImGui.BeginListBox( LabelFileListHeader, AutoFillSize ) )
{ {
raii.Push( ImGui.EndListBox );
UpdateFilenameList(); UpdateFilenameList();
using var colorRaii = new ImGuiRaii.Color();
foreach( var (name, _, color, _) in _fullFilenameList! ) foreach( var (name, _, color, _) in _fullFilenameList! )
{ {
ImGui.PushStyleColor( ImGuiCol.Text, color ); colorRaii.Push( ImGuiCol.Text, color );
ImGui.Selectable( name.FullName ); ImGui.Selectable( name.FullName );
ImGui.PopStyleColor(); colorRaii.Pop();
} }
ImGui.EndListBox();
} }
else else
{ {
_fullFilenameList = null; _fullFilenameList = null;
} }
ImGui.EndTabItem();
} }
private static int HandleDefaultString( GamePath[] gamePaths, out int removeFolders ) private static int HandleDefaultString( GamePath[] gamePaths, out int removeFolders )
@ -469,10 +466,7 @@ namespace Penumbra.UI
ImGui.SetNextItemWidth( -1 ); ImGui.SetNextItemWidth( -1 );
ImGui.InputTextWithHint( LabelGamePathsEditBox, "Hover for help...", ref _currentGamePaths, ImGui.InputTextWithHint( LabelGamePathsEditBox, "Hover for help...", ref _currentGamePaths,
128 ); 128 );
if( ImGui.IsItemHovered() ) ImGuiCustom.HoverTooltip( TooltipGamePathsEdit );
{
ImGui.SetTooltip( TooltipGamePathsEdit );
}
} }
private void DrawGroupRow() private void DrawGroupRow()
@ -516,12 +510,11 @@ namespace Penumbra.UI
loc = colorReplace; loc = colorReplace;
} }
ImGui.PushStyleColor( ImGuiCol.Text, loc ); using var colors = ImGuiRaii.PushColor( ImGuiCol.Text, loc );
ImGui.Selectable( _fullFilenameList[ idx ].name.FullName, ref _fullFilenameList[ idx ].selected ); ImGui.Selectable( _fullFilenameList[ idx ].name.FullName, ref _fullFilenameList[ idx ].selected );
ImGui.PopStyleColor();
} }
const float indent = 30f; const float indentWidth = 30f;
if( _selectedOption == null ) if( _selectedOption == null )
{ {
Selectable( 0, ColorGreen ); Selectable( 0, ColorGreen );
@ -534,7 +527,7 @@ namespace Penumbra.UI
{ {
Selectable( 0, ColorGreen ); Selectable( 0, ColorGreen );
ImGui.Indent( indent ); using var indent = ImGuiRaii.PushIndent( indentWidth );
var tmpPaths = gamePaths.ToArray(); var tmpPaths = gamePaths.ToArray();
foreach( var gamePath in tmpPaths ) foreach( var gamePath in tmpPaths )
{ {
@ -556,8 +549,6 @@ namespace Penumbra.UI
_selector.ReloadCurrentMod(); _selector.ReloadCurrentMod();
} }
} }
ImGui.Unindent( indent );
} }
else else
{ {
@ -588,14 +579,13 @@ namespace Penumbra.UI
return; return;
} }
Custom.ImGuiCustom.BeginFramedGroup( group.GroupName ); ImGuiCustom.BeginFramedGroup( group.GroupName );
using var raii = ImGuiRaii.DeferredEnd( ImGuiCustom.EndFramedGroup );
for( var i = 0; i < group.Options.Count; ++i ) for( var i = 0; i < group.Options.Count; ++i )
{ {
DrawMultiSelectorCheckBox( group, i, Mod.Settings.Settings[ group.GroupName ], DrawMultiSelectorCheckBox( group, i, Mod.Settings.Settings[ group.GroupName ],
$"{group.Options[ i ].OptionName}##{group.GroupName}" ); $"{group.Options[ i ].OptionName}##{group.GroupName}" );
} }
Custom.ImGuiCustom.EndFramedGroup();
} }
private void DrawSingleSelector( OptionGroup group ) private void DrawSingleSelector( OptionGroup group )
@ -635,13 +625,12 @@ namespace Penumbra.UI
private void DrawConfigurationTab() private void DrawConfigurationTab()
{ {
if( !_editMode && !Meta.HasGroupsWithConfig ) if( !_editMode && !Meta.HasGroupsWithConfig || !ImGui.BeginTabItem( LabelConfigurationTab ) )
{ {
return; return;
} }
if( ImGui.BeginTabItem( LabelConfigurationTab ) ) using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTabItem );
{
if( _editMode ) if( _editMode )
{ {
DrawGroupSelectorsEdit(); DrawGroupSelectorsEdit();
@ -650,25 +639,24 @@ namespace Penumbra.UI
{ {
DrawGroupSelectors(); DrawGroupSelectors();
} }
ImGui.EndTabItem();
}
} }
private void DrawMetaManipulationsTab() private void DrawMetaManipulationsTab()
{ {
if( !_editMode && Mod.Data.Resources.MetaManipulations.Count == 0 ) if( !_editMode && Mod.Data.Resources.MetaManipulations.Count == 0 || !ImGui.BeginTabItem( "Meta Manipulations" ) )
{ {
return; return;
} }
if( !ImGui.BeginTabItem( "Meta Manipulations" ) ) using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTabItem );
if( !ImGui.BeginListBox( "##MetaManipulations", AutoFillSize ) )
{ {
return; return;
} }
if( ImGui.BeginListBox( "##MetaManipulations", AutoFillSize ) ) raii.Push( ImGui.EndListBox );
{
var manips = Mod.Data.Resources.MetaManipulations; var manips = Mod.Data.Resources.MetaManipulations;
var changes = false; var changes = false;
if( _editMode || manips.DefaultData.Count > 0 ) if( _editMode || manips.DefaultData.Count > 0 )
@ -679,13 +667,13 @@ namespace Penumbra.UI
} }
} }
foreach( var group in manips.GroupData ) foreach( var (groupName, group) in manips.GroupData )
{ {
foreach( var option in group.Value ) foreach( var (optionName, option) in group )
{ {
if( ImGui.CollapsingHeader( $"{group.Key} - {option.Key}" ) ) if( ImGui.CollapsingHeader( $"{groupName} - {optionName}" ) )
{ {
changes |= DrawMetaManipulationsTable( $"##{group.Key}{option.Key}manips", option.Value, ref manips.Count ); changes |= DrawMetaManipulationsTable( $"##{groupName}{optionName}manips", option, ref manips.Count );
} }
} }
} }
@ -696,18 +684,17 @@ namespace Penumbra.UI
Mod.Data.Resources.SetManipulations( Meta, Mod.Data.BasePath, false ); Mod.Data.Resources.SetManipulations( Meta, Mod.Data.BasePath, false );
_selector.ReloadCurrentMod( true, false ); _selector.ReloadCurrentMod( true, false );
} }
ImGui.EndListBox();
}
ImGui.EndTabItem();
} }
public void Draw( bool editMode ) public void Draw( bool editMode )
{ {
_editMode = editMode; _editMode = editMode;
ImGui.BeginTabBar( LabelPluginDetails ); if( !ImGui.BeginTabBar( LabelPluginDetails ) )
{
return;
}
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTabBar );
DrawAboutTab(); DrawAboutTab();
DrawChangedItemsTab(); DrawChangedItemsTab();
@ -724,7 +711,6 @@ namespace Penumbra.UI
DrawFileSwapTab(); DrawFileSwapTab();
DrawMetaManipulationsTab(); DrawMetaManipulationsTab();
DrawConflictTab(); DrawConflictTab();
ImGui.EndTabBar();
} }
} }
} }

View file

@ -6,6 +6,7 @@ using ImGuiNET;
using Penumbra.GameData.Util; using Penumbra.GameData.Util;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.Structs; using Penumbra.Structs;
using Penumbra.UI.Custom;
using Penumbra.Util; using Penumbra.Util;
namespace Penumbra.UI namespace Penumbra.UI
@ -38,7 +39,7 @@ namespace Penumbra.UI
private bool DrawEditGroupSelector() private bool DrawEditGroupSelector()
{ {
ImGui.SetNextItemWidth( OptionSelectionWidth ); ImGui.SetNextItemWidth( OptionSelectionWidth * ImGuiHelpers.GlobalScale );
if( Meta!.Groups.Count == 0 ) if( Meta!.Groups.Count == 0 )
{ {
ImGui.Combo( LabelGroupSelect, ref _selectedGroupIndex, TextNoOptionAvailable, 1 ); ImGui.Combo( LabelGroupSelect, ref _selectedGroupIndex, TextNoOptionAvailable, 1 );
@ -87,7 +88,7 @@ namespace Penumbra.UI
} }
ImGui.SetNextItemWidth( -1 ); ImGui.SetNextItemWidth( -1 );
if( ImGui.BeginListBox( LabelFileListHeader, AutoFillSize - new Vector2( 0, 1.5f * ImGui.GetTextLineHeight() ) ) ) if( ImGui.BeginListBox( LabelFileListHeader, AutoFillSize - Vector2.UnitY * 1.5f * ImGui.GetTextLineHeight() ) )
{ {
for( var i = 0; i < Mod!.Data.Resources.ModFiles.Count; ++i ) for( var i = 0; i < Mod!.Data.Resources.ModFiles.Count; ++i )
{ {
@ -106,23 +107,27 @@ namespace Penumbra.UI
} }
} }
private void DrawMultiSelectorEditBegin( OptionGroup group ) private ImGuiRaii.EndStack DrawMultiSelectorEditBegin( OptionGroup group )
{ {
var groupName = group.GroupName; var groupName = group.GroupName;
if( Custom.ImGuiCustom.BeginFramedGroupEdit( ref groupName ) ) if( !ImGuiCustom.BeginFramedGroupEdit( ref groupName ) )
{ {
return new ImGuiRaii.EndStack();
}
if( _modManager.ChangeModGroup( group.GroupName, groupName, Mod.Data ) && Mod.Data.Meta.RefreshHasGroupsWithConfig() ) if( _modManager.ChangeModGroup( group.GroupName, groupName, Mod.Data ) && Mod.Data.Meta.RefreshHasGroupsWithConfig() )
{ {
_selector.Cache.TriggerFilterReset(); _selector.Cache.TriggerFilterReset();
} }
}
return ImGuiRaii.DeferredEnd( ImGuiCustom.EndFramedGroup );
} }
private void DrawMultiSelectorEditAdd( OptionGroup group, float nameBoxStart ) private void DrawMultiSelectorEditAdd( OptionGroup group, float nameBoxStart )
{ {
var newOption = ""; var newOption = "";
ImGui.SetCursorPosX( nameBoxStart ); ImGui.SetCursorPosX( nameBoxStart );
ImGui.SetNextItemWidth( MultiEditBoxWidth ); ImGui.SetNextItemWidth( MultiEditBoxWidth * ImGuiHelpers.GlobalScale );
if( ImGui.InputTextWithHint( $"##new_{group.GroupName}_l", "Add new option...", ref newOption, 64, if( ImGui.InputTextWithHint( $"##new_{group.GroupName}_l", "Add new option...", ref newOption, 64,
ImGuiInputTextFlags.EnterReturnsTrue ) ImGuiInputTextFlags.EnterReturnsTrue )
&& newOption.Length != 0 ) && newOption.Length != 0 )
@ -142,7 +147,7 @@ namespace Penumbra.UI
var nameBoxStart = CheckMarkSize; var nameBoxStart = CheckMarkSize;
var flag = Mod!.Settings.Settings[ group.GroupName ]; var flag = Mod!.Settings.Settings[ group.GroupName ];
DrawMultiSelectorEditBegin( group ); using var raii = DrawMultiSelectorEditBegin( group );
for( var i = 0; i < group.Options.Count; ++i ) for( var i = 0; i < group.Options.Count; ++i )
{ {
var opt = group.Options[ i ]; var opt = group.Options[ i ];
@ -157,7 +162,7 @@ namespace Penumbra.UI
nameBoxStart = ImGui.GetCursorPosX(); nameBoxStart = ImGui.GetCursorPosX();
} }
ImGui.SetNextItemWidth( MultiEditBoxWidth ); ImGui.SetNextItemWidth( MultiEditBoxWidth * ImGuiHelpers.GlobalScale );
if( ImGui.InputText( $"{label}_l", ref newName, 64, ImGuiInputTextFlags.EnterReturnsTrue ) ) if( ImGui.InputText( $"{label}_l", ref newName, 64, ImGuiInputTextFlags.EnterReturnsTrue ) )
{ {
if( newName.Length == 0 ) if( newName.Length == 0 )
@ -179,8 +184,6 @@ namespace Penumbra.UI
} }
DrawMultiSelectorEditAdd( group, nameBoxStart ); DrawMultiSelectorEditAdd( group, nameBoxStart );
Custom.ImGuiCustom.EndFramedGroup();
} }
private void DrawSingleSelectorEditGroup( OptionGroup group ) private void DrawSingleSelectorEditGroup( OptionGroup group )
@ -199,7 +202,7 @@ namespace Penumbra.UI
{ {
var oldSetting = Mod!.Settings.Settings[ group.GroupName ]; var oldSetting = Mod!.Settings.Settings[ group.GroupName ];
var code = oldSetting; var code = oldSetting;
if( Custom.ImGuiCustom.RenameableCombo( $"##{group.GroupName}", ref code, out var newName, if( ImGuiCustom.RenameableCombo( $"##{group.GroupName}", ref code, out var newName,
group.Options.Select( x => x.OptionName ).ToArray(), group.Options.Count ) ) group.Options.Select( x => x.OptionName ).ToArray(), group.Options.Count ) )
{ {
if( code == group.Options.Count ) if( code == group.Options.Count )
@ -260,7 +263,7 @@ namespace Penumbra.UI
ImGui.SetCursorPosX( labelEditPos ); ImGui.SetCursorPosX( labelEditPos );
if( labelEditPos == CheckMarkSize ) if( labelEditPos == CheckMarkSize )
{ {
ImGui.SetNextItemWidth( MultiEditBoxWidth ); ImGui.SetNextItemWidth( MultiEditBoxWidth * ImGuiHelpers.GlobalScale );
} }
if( ImGui.InputTextWithHint( LabelNewSingleGroupEdit, "Add new Single Group...", ref newGroup, 64, if( ImGui.InputTextWithHint( LabelNewSingleGroupEdit, "Add new Single Group...", ref newGroup, 64,
@ -275,7 +278,7 @@ namespace Penumbra.UI
{ {
var newGroup = ""; var newGroup = "";
ImGui.SetCursorPosX( CheckMarkSize ); ImGui.SetCursorPosX( CheckMarkSize );
ImGui.SetNextItemWidth( MultiEditBoxWidth ); ImGui.SetNextItemWidth( MultiEditBoxWidth * ImGuiHelpers.GlobalScale );
if( ImGui.InputTextWithHint( LabelNewMultiGroup, "Add new Multi Group...", ref newGroup, 64, if( ImGui.InputTextWithHint( LabelNewMultiGroup, "Add new Multi Group...", ref newGroup, 64,
ImGuiInputTextFlags.EnterReturnsTrue ) ) ImGuiInputTextFlags.EnterReturnsTrue ) )
{ {
@ -310,14 +313,20 @@ namespace Penumbra.UI
return; return;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTabItem );
ImGui.SetNextItemWidth( -1 ); ImGui.SetNextItemWidth( -1 );
if( ImGui.BeginListBox( LabelFileSwapHeader, AutoFillSize ) ) if( !ImGui.BeginListBox( LabelFileSwapHeader, AutoFillSize ) )
{ {
return;
}
raii.Push( ImGui.EndListBox );
var swaps = Meta.FileSwaps.Keys.ToArray(); var swaps = Meta.FileSwaps.Keys.ToArray();
var arrow = $"{( char )FontAwesomeIcon.LongArrowAltRight}";
ImGui.PushFont( UiBuilder.IconFont ); ImGui.PushFont( UiBuilder.IconFont );
var arrowWidth = ImGui.CalcTextSize( arrow ).X; var arrowWidth = ImGui.CalcTextSize( FontAwesomeIcon.LongArrowAltRight.ToIconString() ).X;
ImGui.PopFont(); ImGui.PopFont();
var width = ( ImGui.GetWindowWidth() - arrowWidth - 4 * ImGui.GetStyle().ItemSpacing.X ) / 2; var width = ( ImGui.GetWindowWidth() - arrowWidth - 4 * ImGui.GetStyle().ItemSpacing.X ) / 2;
@ -350,12 +359,13 @@ namespace Penumbra.UI
} }
} }
if( idx < swaps.Length ) if( idx >= swaps.Length )
{ {
continue;
}
ImGui.SameLine(); ImGui.SameLine();
ImGui.PushFont( UiBuilder.IconFont ); ImGuiCustom.PrintIcon( FontAwesomeIcon.LongArrowAltRight );
ImGui.TextUnformatted( arrow );
ImGui.PopFont();
ImGui.SameLine(); ImGui.SameLine();
ImGui.SetNextItemWidth( width ); ImGui.SetNextItemWidth( width );
@ -373,12 +383,6 @@ namespace Penumbra.UI
} }
} }
} }
ImGui.EndListBox();
}
ImGui.EndTabItem();
}
} }
} }
} }

View file

@ -10,6 +10,7 @@ using Penumbra.GameData.Enums;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
using Penumbra.Meta; using Penumbra.Meta;
using Penumbra.Meta.Files; using Penumbra.Meta.Files;
using Penumbra.UI.Custom;
using Penumbra.Util; using Penumbra.Util;
using ObjectType = Penumbra.GameData.Enums.ObjectType; using ObjectType = Penumbra.GameData.Enums.ObjectType;
@ -157,9 +158,8 @@ namespace Penumbra.UI
return ImGui.Checkbox( name, ref value ); return ImGui.Checkbox( name, ref value );
} }
ImGui.PushStyleColor( ImGuiCol.Text, color ); using var colorRaii = ImGuiRaii.PushColor( ImGuiCol.Text, color );
var ret = ImGui.Checkbox( name, ref value ); var ret = ImGui.Checkbox( name, ref value );
ImGui.PopStyleColor();
return ret; return ret;
} }
@ -184,10 +184,9 @@ namespace Penumbra.UI
var color = compare < 0 ? ColorDarkGreen : var color = compare < 0 ? ColorDarkGreen :
compare > 0 ? ColorDarkRed : ImGui.ColorConvertFloat4ToU32( ImGui.GetStyle().Colors[ ( int )ImGuiCol.Button ] ); compare > 0 ? ColorDarkRed : ImGui.ColorConvertFloat4ToU32( ImGui.GetStyle().Colors[ ( int )ImGuiCol.Button ] );
ImGui.PushStyleColor( ImGuiCol.Button, color ); using var colorRaii = ImGuiRaii.PushColor( ImGuiCol.Button, color );
var ret = ImGui.Button( name, Vector2.UnitX * 120 ) && compare != 0; var ret = ImGui.Button( name, Vector2.UnitX * 120 ) && compare != 0;
ImGui.SameLine(); ImGui.SameLine();
ImGui.PopStyleColor();
return ret; return ret;
} }
@ -204,18 +203,20 @@ namespace Penumbra.UI
return false; return false;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndCombo );
for( var i = 0; i < namesAndValues.Count; ++i ) for( var i = 0; i < namesAndValues.Count; ++i )
{ {
if( ImGui.Selectable( $"{namesAndValues[ i ].Item1}##{label}{i}", idx == i ) && idx != i ) if( !ImGui.Selectable( $"{namesAndValues[ i ].Item1}##{label}{i}", idx == i ) || idx == i )
{ {
idx = i; continue;
value = namesAndValues[ i ].Item2; }
ImGui.EndCombo();
return true; idx = i;
} value = namesAndValues[ i ].Item2;
return true;
} }
ImGui.EndCombo();
return false; return false;
} }
@ -227,6 +228,7 @@ namespace Penumbra.UI
if( ImGui.BeginPopup( $"##MetaPopup{manipIdx}" ) ) if( ImGui.BeginPopup( $"##MetaPopup{manipIdx}" ) )
{ {
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndPopup );
var defaults = ( EqpEntry )Service< MetaDefaults >.Get().GetDefaultValue( list[ manipIdx ] )!; var defaults = ( EqpEntry )Service< MetaDefaults >.Get().GetDefaultValue( list[ manipIdx ] )!;
var attributes = Eqp.EqpAttributes[ id.Slot ]; var attributes = Eqp.EqpAttributes[ id.Slot ];
@ -240,8 +242,6 @@ namespace Penumbra.UI
ret = true; ret = true;
} }
} }
ImGui.EndPopup();
} }
ImGui.Text( ObjectType.Equipment.ToString() ); ImGui.Text( ObjectType.Equipment.ToString() );
@ -261,6 +261,7 @@ namespace Penumbra.UI
if( ImGui.BeginPopup( $"##MetaPopup{manipIdx}" ) ) if( ImGui.BeginPopup( $"##MetaPopup{manipIdx}" ) )
{ {
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndPopup );
var enabled = val.Enabled; var enabled = val.Enabled;
var animated = val.Animated; var animated = val.Animated;
var rotationA = val.RotationA; var rotationA = val.RotationA;
@ -284,8 +285,6 @@ namespace Penumbra.UI
RotationA = rotationA, RotationB = rotationB, RotationC = rotationC, RotationA = rotationA, RotationB = rotationB, RotationC = rotationC,
} ); } );
} }
ImGui.EndPopup();
} }
ImGui.Text( ObjectType.Equipment.ToString() ); ImGui.Text( ObjectType.Equipment.ToString() );
@ -372,6 +371,7 @@ namespace Penumbra.UI
if( ImGui.BeginPopup( $"##MetaPopup{manipIdx}" ) ) if( ImGui.BeginPopup( $"##MetaPopup{manipIdx}" ) )
{ {
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndPopup );
var (bit1, bit2) = GetEqdpBits( id.Slot, val ); var (bit1, bit2) = GetEqdpBits( id.Slot, val );
var (defBit1, defBit2) = GetEqdpBits( id.Slot, defaults ); var (defBit1, defBit2) = GetEqdpBits( id.Slot, defaults );
@ -382,8 +382,6 @@ namespace Penumbra.UI
{ {
list[ manipIdx ] = MetaManipulation.Eqdp( id.Slot, id.GenderRace, id.SetId, SetEqdpBits( id.Slot, val, bit1, bit2 ) ); list[ manipIdx ] = MetaManipulation.Eqdp( id.Slot, id.GenderRace, id.SetId, SetEqdpBits( id.Slot, val, bit1, bit2 ) );
} }
ImGui.EndPopup();
} }
ImGui.Text( id.Slot.IsAccessory() ImGui.Text( id.Slot.IsAccessory()
@ -409,13 +407,12 @@ namespace Penumbra.UI
var val = list[ manipIdx ].EstValue; var val = list[ manipIdx ].EstValue;
if( ImGui.BeginPopup( $"##MetaPopup{manipIdx}" ) ) if( ImGui.BeginPopup( $"##MetaPopup{manipIdx}" ) )
{ {
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndPopup );
if( DrawInputWithDefault( "No Idea what this does!##manip", ref val, defaults, ushort.MaxValue ) && _editMode ) if( DrawInputWithDefault( "No Idea what this does!##manip", ref val, defaults, ushort.MaxValue ) && _editMode )
{ {
list[ manipIdx ] = new MetaManipulation( id.Value, val ); list[ manipIdx ] = new MetaManipulation( id.Value, val );
ret = true; ret = true;
} }
ImGui.EndPopup();
} }
ImGui.Text( id.ObjectType.ToString() ); ImGui.Text( id.ObjectType.ToString() );
@ -443,6 +440,7 @@ namespace Penumbra.UI
if( ImGui.BeginPopup( $"##MetaPopup{manipIdx}" ) ) if( ImGui.BeginPopup( $"##MetaPopup{manipIdx}" ) )
{ {
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndPopup );
ushort materialId = val.MaterialId; ushort materialId = val.MaterialId;
ushort vfxId = val.VfxId; ushort vfxId = val.VfxId;
ushort decalId = val.DecalId; ushort decalId = val.DecalId;
@ -463,8 +461,6 @@ namespace Penumbra.UI
( byte )vfxId, ( byte )materialAnimationId ); ( byte )vfxId, ( byte )materialAnimationId );
list[ manipIdx ] = new MetaManipulation( id.Value, value.ToInteger() ); list[ manipIdx ] = new MetaManipulation( id.Value, value.ToInteger() );
} }
ImGui.EndPopup();
} }
ImGui.Text( id.ObjectType.ToString() ); ImGui.Text( id.ObjectType.ToString() );
@ -503,6 +499,7 @@ namespace Penumbra.UI
if( ImGui.BeginPopup( $"##MetaPopup{manipIdx}" ) ) if( ImGui.BeginPopup( $"##MetaPopup{manipIdx}" ) )
{ {
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndPopup );
if( DefaultButton( if( DefaultButton(
$"{( _editMode ? "Set to " : "" )}Default: {defaults:F3}##scaleManip", ref val, defaults ) $"{( _editMode ? "Set to " : "" )}Default: {defaults:F3}##scaleManip", ref val, defaults )
&& _editMode ) && _editMode )
@ -511,7 +508,7 @@ namespace Penumbra.UI
ret = true; ret = true;
} }
ImGui.SetNextItemWidth( 50 ); ImGui.SetNextItemWidth( 50 * ImGuiHelpers.GlobalScale );
if( ImGui.InputFloat( "Scale###manip", ref val, 0, 0, "%.3f", if( ImGui.InputFloat( "Scale###manip", ref val, 0, 0, "%.3f",
_editMode ? ImGuiInputTextFlags.EnterReturnsTrue : ImGuiInputTextFlags.ReadOnly ) _editMode ? ImGuiInputTextFlags.EnterReturnsTrue : ImGuiInputTextFlags.ReadOnly )
&& val >= 0 && val >= 0
@ -521,8 +518,6 @@ namespace Penumbra.UI
list[ manipIdx ] = MetaManipulation.Rsp( id.SubRace, id.Attribute, val ); list[ manipIdx ] = MetaManipulation.Rsp( id.SubRace, id.Attribute, val );
ret = true; ret = true;
} }
ImGui.EndPopup();
} }
ImGui.Text( id.Attribute.ToUngenderedString() ); ImGui.Text( id.Attribute.ToUngenderedString() );
@ -542,18 +537,15 @@ namespace Penumbra.UI
if( _editMode ) if( _editMode )
{ {
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImGui.PushFont( UiBuilder.IconFont ); using var font = ImGuiRaii.PushFont( UiBuilder.IconFont );
if( ImGui.Button( $"{FontAwesomeIcon.Trash.ToIconString()}##manipDelete{manipIdx}" ) ) if( ImGui.Button( $"{FontAwesomeIcon.Trash.ToIconString()}##manipDelete{manipIdx}" ) )
{ {
list.RemoveAt( manipIdx ); list.RemoveAt( manipIdx );
ImGui.PopFont();
ImGui.TableNextRow(); ImGui.TableNextRow();
--manipIdx; --manipIdx;
--count; --count;
return true; return true;
} }
ImGui.PopFont();
} }
ImGui.TableNextColumn(); ImGui.TableNextColumn();
@ -613,8 +605,12 @@ namespace Penumbra.UI
private bool DrawNewManipulationPopup( string popupName, IList< MetaManipulation > list, ref int count ) private bool DrawNewManipulationPopup( string popupName, IList< MetaManipulation > list, ref int count )
{ {
var change = false; var change = false;
if( ImGui.BeginPopup( popupName ) ) if( !ImGui.BeginPopup( popupName ) )
{ {
return change;
}
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndPopup );
var manipType = DrawNewTypeSelection(); var manipType = DrawNewTypeSelection();
MetaManipulation? newManip = null; MetaManipulation? newManip = null;
switch( manipType ) switch( manipType )
@ -717,10 +713,8 @@ namespace Penumbra.UI
change = true; change = true;
++count; ++count;
} }
ImGui.CloseCurrentPopup();
}
ImGui.EndPopup(); ImGui.CloseCurrentPopup();
} }
return change; return change;
@ -734,6 +728,7 @@ namespace Penumbra.UI
&& ImGui.BeginTable( label, numRows, && ImGui.BeginTable( label, numRows,
ImGuiTableFlags.BordersInner | ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit ) ) ImGuiTableFlags.BordersInner | ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit ) )
{ {
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTable );
if( _editMode ) if( _editMode )
{ {
ImGui.TableNextColumn(); ImGui.TableNextColumn();
@ -764,8 +759,6 @@ namespace Penumbra.UI
{ {
changes |= DrawManipulationRow( ref i, list, ref count ); changes |= DrawManipulationRow( ref i, list, ref count );
} }
ImGui.EndTable();
} }
var popupName = $"##newManip{label}"; var popupName = $"##newManip{label}";

View file

@ -2,10 +2,12 @@ using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Numerics; using System.Numerics;
using Dalamud.Interface;
using Dalamud.Logging; using Dalamud.Logging;
using ImGuiNET; using ImGuiNET;
using Penumbra.Mod; using Penumbra.Mod;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.UI.Custom;
using Penumbra.Util; using Penumbra.Util;
namespace Penumbra.UI namespace Penumbra.UI
@ -72,7 +74,7 @@ namespace Penumbra.UI
private void DrawName() private void DrawName()
{ {
var name = Meta!.Name; var name = Meta!.Name;
if( Custom.ImGuiCustom.InputOrText( _editMode, LabelEditName, ref name, 64 ) && _modManager.RenameMod( name, Mod!.Data ) ) if( ImGuiCustom.InputOrText( _editMode, LabelEditName, ref name, 64 ) && _modManager.RenameMod( name, Mod!.Data ) )
{ {
_selector.SelectModOnUpdate( Mod.Data.BasePath.Name ); _selector.SelectModOnUpdate( Mod.Data.BasePath.Name );
if( !_modManager.Config.ModSortOrder.ContainsKey( Mod!.Data.BasePath.Name ) ) if( !_modManager.Config.ModSortOrder.ContainsKey( Mod!.Data.BasePath.Name ) )
@ -87,12 +89,13 @@ namespace Penumbra.UI
if( _editMode ) if( _editMode )
{ {
ImGui.BeginGroup(); ImGui.BeginGroup();
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndGroup );
ImGui.Text( "(Version " ); ImGui.Text( "(Version " );
ImGui.PushStyleVar( ImGuiStyleVar.ItemSpacing, ZeroVector ); using var style = ImGuiRaii.PushStyle( ImGuiStyleVar.ItemSpacing, ZeroVector );
ImGui.SameLine(); ImGui.SameLine();
var version = Meta!.Version; var version = Meta!.Version;
if( Custom.ImGuiCustom.ResizingTextInput( LabelEditVersion, ref version, 16 ) if( ImGuiCustom.ResizingTextInput( LabelEditVersion, ref version, 16 )
&& version != Meta.Version ) && version != Meta.Version )
{ {
Meta.Version = version; Meta.Version = version;
@ -101,8 +104,6 @@ namespace Penumbra.UI
ImGui.SameLine(); ImGui.SameLine();
ImGui.Text( ")" ); ImGui.Text( ")" );
ImGui.PopStyleVar();
ImGui.EndGroup();
} }
else if( Meta!.Version.Length > 0 ) else if( Meta!.Version.Length > 0 )
{ {
@ -117,7 +118,7 @@ namespace Penumbra.UI
ImGui.SameLine(); ImGui.SameLine();
var author = Meta!.Author; var author = Meta!.Author;
if( Custom.ImGuiCustom.InputOrText( _editMode, LabelEditAuthor, ref author, 64 ) if( ImGuiCustom.InputOrText( _editMode, LabelEditAuthor, ref author, 64 )
&& author != Meta.Author ) && author != Meta.Author )
{ {
Meta.Author = author; Meta.Author = author;
@ -131,12 +132,13 @@ namespace Penumbra.UI
private void DrawWebsite() private void DrawWebsite()
{ {
ImGui.BeginGroup(); ImGui.BeginGroup();
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndGroup );
if( _editMode ) if( _editMode )
{ {
ImGui.TextColored( GreyColor, "from" ); ImGui.TextColored( GreyColor, "from" );
ImGui.SameLine(); ImGui.SameLine();
var website = Meta!.Website; var website = Meta!.Website;
if( Custom.ImGuiCustom.ResizingTextInput( LabelEditWebsite, ref website, 512 ) if( ImGuiCustom.ResizingTextInput( LabelEditWebsite, ref website, 512 )
&& website != Meta.Website ) && website != Meta.Website )
{ {
Meta.Website = website; Meta.Website = website;
@ -170,10 +172,7 @@ namespace Penumbra.UI
} }
} }
if( ImGui.IsItemHovered() ) ImGuiCustom.HoverTooltip( Meta.Website );
{
ImGui.SetTooltip( Meta.Website );
}
} }
else else
{ {
@ -182,8 +181,6 @@ namespace Penumbra.UI
ImGui.Text( Meta.Website ); ImGui.Text( Meta.Website );
} }
} }
ImGui.EndGroup();
} }
private void DrawHeaderLine() private void DrawHeaderLine()
@ -200,7 +197,7 @@ namespace Penumbra.UI
private void DrawPriority() private void DrawPriority()
{ {
var priority = Mod!.Settings.Priority; var priority = Mod!.Settings.Priority;
ImGui.SetNextItemWidth( 50 ); ImGui.SetNextItemWidth( 50 * ImGuiHelpers.GlobalScale );
if( ImGui.InputInt( "Priority", ref priority, 0 ) && priority != Mod!.Settings.Priority ) if( ImGui.InputInt( "Priority", ref priority, 0 ) && priority != Mod!.Settings.Priority )
{ {
Mod.Settings.Priority = priority; Mod.Settings.Priority = priority;
@ -208,12 +205,10 @@ namespace Penumbra.UI
_selector.Cache.TriggerFilterReset(); _selector.Cache.TriggerFilterReset();
} }
if( ImGui.IsItemHovered() ) ImGuiCustom.HoverTooltip(
{ "Higher priority mods take precedence over other mods in the case of file conflicts.\n"
ImGui.SetTooltip( "Higher priority mods take precedence over other mods in the case of file conflicts.\n"
+ "In case of identical priority, the alphabetically first mod takes precedence." ); + "In case of identical priority, the alphabetically first mod takes precedence." );
} }
}
private void DrawEnabledMark() private void DrawEnabledMark()
{ {
@ -229,7 +224,7 @@ namespace Penumbra.UI
public static bool DrawSortOrder( ModData mod, ModManager manager, Selector selector ) public static bool DrawSortOrder( ModData mod, ModManager manager, Selector selector )
{ {
var currentSortOrder = mod.SortOrder.FullPath; var currentSortOrder = mod.SortOrder.FullPath;
ImGui.SetNextItemWidth( 300 ); ImGui.SetNextItemWidth( 300 * ImGuiHelpers.GlobalScale );
if( ImGui.InputText( "Sort Order", ref currentSortOrder, 256, ImGuiInputTextFlags.EnterReturnsTrue ) ) if( ImGui.InputText( "Sort Order", ref currentSortOrder, 256, ImGuiInputTextFlags.EnterReturnsTrue ) )
{ {
manager.ChangeSortOrder( mod, currentSortOrder ); manager.ChangeSortOrder( mod, currentSortOrder );
@ -253,10 +248,7 @@ namespace Penumbra.UI
Process.Start( new ProcessStartInfo( Mod!.Data.BasePath.FullName ) { UseShellExecute = true } ); Process.Start( new ProcessStartInfo( Mod!.Data.BasePath.FullName ) { UseShellExecute = true } );
} }
if( ImGui.IsItemHovered() ) ImGuiCustom.HoverTooltip( TooltipOpenModFolder );
{
ImGui.SetTooltip( TooltipOpenModFolder );
}
} }
private string _newName = ""; private string _newName = "";
@ -318,13 +310,18 @@ namespace Penumbra.UI
{ {
var closeParent = false; var closeParent = false;
var _ = true; var _ = true;
if( ImGui.BeginPopupModal( LabelOverWriteDir, ref _, ImGuiWindowFlags.AlwaysAutoResize ) ) if( !ImGui.BeginPopupModal( LabelOverWriteDir, ref _, ImGuiWindowFlags.AlwaysAutoResize ) )
{ {
return closeParent;
}
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndPopup );
DirectoryInfo dir = Mod!.Data.BasePath; DirectoryInfo dir = Mod!.Data.BasePath;
DirectoryInfo newDir = new( Path.Combine( dir.Parent!.FullName, _newName ) ); DirectoryInfo newDir = new( Path.Combine( dir.Parent!.FullName, _newName ) );
ImGui.Text( ImGui.Text(
$"The mod directory {newDir} already exists.\nDo you want to merge / overwrite both mods?\nThis may corrupt the resulting mod in irrecoverable ways." ); $"The mod directory {newDir} already exists.\nDo you want to merge / overwrite both mods?\nThis may corrupt the resulting mod in irrecoverable ways." );
var buttonSize = new Vector2( 120, 0 ); var buttonSize = ImGuiHelpers.ScaledVector2( 120, 0 );
if( ImGui.Button( "Yes", buttonSize ) ) if( ImGui.Button( "Yes", buttonSize ) )
{ {
if( MergeFolderInto( dir, newDir ) ) if( MergeFolderInto( dir, newDir ) )
@ -346,9 +343,6 @@ namespace Penumbra.UI
ImGui.CloseCurrentPopup(); ImGui.CloseCurrentPopup();
} }
ImGui.EndPopup();
}
return closeParent; return closeParent;
} }
@ -358,8 +352,13 @@ namespace Penumbra.UI
_keyboardFocus |= !ImGui.IsPopupOpen( PopupRenameFolder ); _keyboardFocus |= !ImGui.IsPopupOpen( PopupRenameFolder );
ImGui.SetNextWindowPos( ImGui.GetMainViewport().GetCenter(), ImGuiCond.Appearing, new Vector2( 0.5f, 1f ) ); ImGui.SetNextWindowPos( ImGui.GetMainViewport().GetCenter(), ImGuiCond.Appearing, new Vector2( 0.5f, 1f ) );
if( ImGui.BeginPopupModal( PopupRenameFolder, ref _, ImGuiWindowFlags.AlwaysAutoResize ) ) if( !ImGui.BeginPopupModal( PopupRenameFolder, ref _, ImGuiWindowFlags.AlwaysAutoResize ) )
{ {
return;
}
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndPopup );
if( ImGui.IsKeyPressed( ImGui.GetKeyIndex( ImGuiKey.Escape ) ) ) if( ImGui.IsKeyPressed( ImGui.GetKeyIndex( ImGuiKey.Escape ) ) )
{ {
ImGui.CloseCurrentPopup(); ImGui.CloseCurrentPopup();
@ -388,9 +387,6 @@ namespace Penumbra.UI
{ {
ImGui.CloseCurrentPopup(); ImGui.CloseCurrentPopup();
} }
ImGui.EndPopup();
}
} }
private void DrawRenameModFolderButton() private void DrawRenameModFolderButton()
@ -401,10 +397,7 @@ namespace Penumbra.UI
ImGui.OpenPopup( PopupRenameFolder ); ImGui.OpenPopup( PopupRenameFolder );
} }
if( ImGui.IsItemHovered() ) ImGuiCustom.HoverTooltip( TooltipRenameModFolder );
{
ImGui.SetTooltip( TooltipRenameModFolder );
}
} }
private void DrawEditJsonButton() private void DrawEditJsonButton()
@ -415,10 +408,7 @@ namespace Penumbra.UI
Process.Start( new ProcessStartInfo( Mod!.Data.MetaFile.FullName ) { UseShellExecute = true } ); Process.Start( new ProcessStartInfo( Mod!.Data.MetaFile.FullName ) { UseShellExecute = true } );
} }
if( ImGui.IsItemHovered() ) ImGuiCustom.HoverTooltip( TooltipEditJson );
{
ImGui.SetTooltip( TooltipEditJson );
}
} }
private void DrawReloadJsonButton() private void DrawReloadJsonButton()
@ -428,10 +418,7 @@ namespace Penumbra.UI
_selector.ReloadCurrentMod( true, false ); _selector.ReloadCurrentMod( true, false );
} }
if( ImGui.IsItemHovered() ) ImGuiCustom.HoverTooltip( TooltipReloadJson );
{
ImGui.SetTooltip( TooltipReloadJson );
}
} }
private void DrawResetMetaButton() private void DrawResetMetaButton()
@ -441,14 +428,11 @@ namespace Penumbra.UI
_selector.ReloadCurrentMod( true, true ); _selector.ReloadCurrentMod( true, true );
} }
if( ImGui.IsItemHovered() ) ImGuiCustom.HoverTooltip(
{
ImGui.SetTooltip(
"Force a recomputation of the metadata_manipulations.json file from all .meta files in the folder.\n" "Force a recomputation of the metadata_manipulations.json file from all .meta files in the folder.\n"
+ "Also reloads the mod.\n" + "Also reloads the mod.\n"
+ "Be aware that this removes all manually added metadata changes." ); + "Be aware that this removes all manually added metadata changes." );
} }
}
private void DrawDeduplicateButton() private void DrawDeduplicateButton()
{ {
@ -459,10 +443,7 @@ namespace Penumbra.UI
_selector.ReloadCurrentMod(); _selector.ReloadCurrentMod();
} }
if( ImGui.IsItemHovered() ) ImGuiCustom.HoverTooltip( TooltipDeduplicate );
{
ImGui.SetTooltip( TooltipDeduplicate );
}
} }
private void DrawNormalizeButton() private void DrawNormalizeButton()
@ -474,10 +455,7 @@ namespace Penumbra.UI
_selector.ReloadCurrentMod(); _selector.ReloadCurrentMod();
} }
if( ImGui.IsItemHovered() ) ImGuiCustom.HoverTooltip( TooltipNormalize );
{
ImGui.SetTooltip( TooltipNormalize );
}
} }
private void DrawSplitButton() private void DrawSplitButton()
@ -487,14 +465,11 @@ namespace Penumbra.UI
ModCleanup.SplitMod( Mod!.Data ); ModCleanup.SplitMod( Mod!.Data );
} }
if( ImGui.IsItemHovered() ) ImGuiCustom.HoverTooltip(
{
ImGui.SetTooltip(
"Split off all options of a mod into single mods that are placed in a collective folder.\n" "Split off all options of a mod into single mods that are placed in a collective folder.\n"
+ "Does not remove or change the mod itself, just create (potentially inefficient) copies.\n" + "Does not remove or change the mod itself, just create (potentially inefficient) copies.\n"
+ "Experimental - Use at own risk!" ); + "Experimental - Use at own risk!" );
} }
}
private void DrawEditLine() private void DrawEditLine()
{ {
@ -521,18 +496,18 @@ namespace Penumbra.UI
{ {
try try
{ {
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndChild );
var ret = ImGui.BeginChild( LabelModPanel, AutoFillSize, true ); var ret = ImGui.BeginChild( LabelModPanel, AutoFillSize, true );
if( !ret || Mod == null ) if( !ret || Mod == null )
{ {
ImGui.EndChild();
return; return;
} }
DrawHeaderLine(); DrawHeaderLine();
// Next line with fixed distance. // Next line with fixed distance.
Custom.ImGuiCustom.VerticalDistance( HeaderLineDistance ); ImGuiCustom.VerticalDistance( HeaderLineDistance );
DrawEnabledMark(); DrawEnabledMark();
ImGui.SameLine(); ImGui.SameLine();
@ -550,12 +525,10 @@ namespace Penumbra.UI
} }
Details.Draw( _editMode ); Details.Draw( _editMode );
ImGui.EndChild();
} }
catch( Exception ex ) catch( Exception ex )
{ {
PluginLog.LogError( ex, "fuck" ); PluginLog.LogError( ex, "Oh no" );
} }
} }
} }

View file

@ -3,12 +3,14 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Windows.Forms.VisualStyles;
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Logging; using Dalamud.Logging;
using ImGuiNET; using ImGuiNET;
using Penumbra.Importer; using Penumbra.Importer;
using Penumbra.Mod; using Penumbra.Mod;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.UI.Custom;
using Penumbra.Util; using Penumbra.Util;
namespace Penumbra.UI namespace Penumbra.UI
@ -36,6 +38,8 @@ namespace Penumbra.UI
private static readonly Vector2 SelectorButtonSizes = new( 100, 0 ); private static readonly Vector2 SelectorButtonSizes = new( 100, 0 );
private static readonly Vector2 HelpButtonSizes = new( 40, 0 ); private static readonly Vector2 HelpButtonSizes = new( 40, 0 );
private static readonly Vector4 DeleteModNameColor = new( 0.7f, 0.1f, 0.1f, 1 );
} }
// Buttons // Buttons
@ -46,19 +50,16 @@ namespace Penumbra.UI
private void DrawModTrashButton() private void DrawModTrashButton()
{ {
ImGui.PushFont( UiBuilder.IconFont ); using var raii = ImGuiRaii.PushFont( UiBuilder.IconFont );
if( ImGui.Button( FontAwesomeIcon.Trash.ToIconString(), SelectorButtonSizes * _selectorScalingFactor ) && _index >= 0 ) if( ImGui.Button( FontAwesomeIcon.Trash.ToIconString(), SelectorButtonSizes * _selectorScalingFactor ) && _index >= 0 )
{ {
_deleteIndex = _index; _deleteIndex = _index;
} }
ImGui.PopFont(); raii.Pop();
if( ImGui.IsItemHovered() ) ImGuiCustom.HoverTooltip( TooltipDelete );
{
ImGui.SetTooltip( TooltipDelete );
}
} }
private void DrawDeleteModal() private void DrawDeleteModal()
@ -78,20 +79,22 @@ namespace Penumbra.UI
return; return;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndPopup );
if( Mod == null ) if( Mod == null )
{ {
_deleteIndex = null; _deleteIndex = null;
ImGui.CloseCurrentPopup(); ImGui.CloseCurrentPopup();
ImGui.EndPopup();
return; return;
} }
ImGui.Text( "Are you sure you want to delete the following mod:" ); ImGui.Text( "Are you sure you want to delete the following mod:" );
ImGui.Dummy( new Vector2( ImGui.GetTextLineHeight() / 2 ) ); var halfLine = new Vector2( ImGui.GetTextLineHeight() / 2 );
ImGui.TextColored( new Vector4( 0.7f, 0.1f, 0.1f, 1 ), Mod.Data.Meta.Name ); ImGui.Dummy( halfLine );
ImGui.Dummy( new Vector2( ImGui.GetTextLineHeight() ) / 2 ); ImGui.TextColored( DeleteModNameColor, Mod.Data.Meta.Name );
ImGui.Dummy( halfLine );
var buttonSize = new Vector2( 120, 0 ); var buttonSize = ImGuiHelpers.ScaledVector2( 120, 0 );
if( ImGui.Button( ButtonYesDelete, buttonSize ) ) if( ImGui.Button( ButtonYesDelete, buttonSize ) )
{ {
ImGui.CloseCurrentPopup(); ImGui.CloseCurrentPopup();
@ -109,8 +112,6 @@ namespace Penumbra.UI
ImGui.CloseCurrentPopup(); ImGui.CloseCurrentPopup();
_deleteIndex = null; _deleteIndex = null;
} }
ImGui.EndPopup();
} }
// === Add === // === Add ===
@ -118,7 +119,7 @@ namespace Penumbra.UI
private void DrawModAddButton() private void DrawModAddButton()
{ {
ImGui.PushFont( UiBuilder.IconFont ); using var raii = ImGuiRaii.PushFont( UiBuilder.IconFont );
if( ImGui.Button( FontAwesomeIcon.Plus.ToIconString(), SelectorButtonSizes * _selectorScalingFactor ) ) if( ImGui.Button( FontAwesomeIcon.Plus.ToIconString(), SelectorButtonSizes * _selectorScalingFactor ) )
{ {
@ -126,12 +127,9 @@ namespace Penumbra.UI
ImGui.OpenPopup( LabelAddModPopup ); ImGui.OpenPopup( LabelAddModPopup );
} }
ImGui.PopFont(); raii.Pop();
if( ImGui.IsItemHovered() ) ImGuiCustom.HoverTooltip( TooltipAdd );
{
ImGui.SetTooltip( TooltipAdd );
}
DrawModAddPopup(); DrawModAddPopup();
} }
@ -143,6 +141,8 @@ namespace Penumbra.UI
return; return;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndPopup );
if( _modAddKeyboardFocus ) if( _modAddKeyboardFocus )
{ {
ImGui.SetKeyboardFocusHere(); ImGui.SetKeyboardFocusHere();
@ -181,20 +181,16 @@ namespace Penumbra.UI
{ {
ImGui.CloseCurrentPopup(); ImGui.CloseCurrentPopup();
} }
ImGui.EndPopup();
} }
// === Help === // === Help ===
private void DrawModHelpButton() private void DrawModHelpButton()
{ {
ImGui.PushFont( UiBuilder.IconFont ); using var raii = ImGuiRaii.PushFont( UiBuilder.IconFont );
if( ImGui.Button( FontAwesomeIcon.QuestionCircle.ToIconString(), HelpButtonSizes * _selectorScalingFactor ) ) if( ImGui.Button( FontAwesomeIcon.QuestionCircle.ToIconString(), HelpButtonSizes * _selectorScalingFactor ) )
{ {
ImGui.OpenPopup( LabelModHelpPopup ); ImGui.OpenPopup( LabelModHelpPopup );
} }
ImGui.PopFont();
} }
private static void DrawModHelpPopup() private static void DrawModHelpPopup()
@ -208,6 +204,8 @@ namespace Penumbra.UI
return; return;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndPopup );
ImGui.Dummy( Vector2.UnitY * ImGui.GetTextLineHeight() ); ImGui.Dummy( Vector2.UnitY * ImGui.GetTextLineHeight() );
ImGui.Text( "Mod Selector" ); ImGui.Text( "Mod Selector" );
ImGui.BulletText( "Select a mod to obtain more information." ); ImGui.BulletText( "Select a mod to obtain more information." );
@ -268,24 +266,20 @@ namespace Penumbra.UI
{ {
ImGui.CloseCurrentPopup(); ImGui.CloseCurrentPopup();
} }
ImGui.EndPopup();
} }
// === Main === // === Main ===
private void DrawModsSelectorButtons() private void DrawModsSelectorButtons()
{ {
// Selector controls // Selector controls
ImGui.PushStyleVar( ImGuiStyleVar.WindowPadding, ZeroVector ); using var style = ImGuiRaii.PushStyle( ImGuiStyleVar.WindowPadding, ZeroVector )
ImGui.PushStyleVar( ImGuiStyleVar.FrameRounding, 0 ); .Push( ImGuiStyleVar.FrameRounding, 0 );
DrawModAddButton(); DrawModAddButton();
ImGui.SameLine(); ImGui.SameLine();
DrawModHelpButton(); DrawModHelpButton();
ImGui.SameLine(); ImGui.SameLine();
DrawModTrashButton(); DrawModTrashButton();
ImGui.PopStyleVar( 2 );
} }
} }
@ -296,7 +290,7 @@ namespace Penumbra.UI
private void DrawTextFilter() private void DrawTextFilter()
{ {
ImGui.SetNextItemWidth( SelectorPanelWidth * _selectorScalingFactor - 22 ); ImGui.SetNextItemWidth( SelectorPanelWidth * _selectorScalingFactor - 22 * ImGuiHelpers.GlobalScale );
var tmp = _modFilterInput; var tmp = _modFilterInput;
if( ImGui.InputTextWithHint( LabelModFilter, "Filter Mods...", ref tmp, 256 ) && _modFilterInput != tmp ) if( ImGui.InputTextWithHint( LabelModFilter, "Filter Mods...", ref tmp, 256 ) && _modFilterInput != tmp )
{ {
@ -304,10 +298,7 @@ namespace Penumbra.UI
_modFilterInput = tmp; _modFilterInput = tmp;
} }
if( ImGui.IsItemHovered() ) ImGuiCustom.HoverTooltip( TooltipModFilter );
{
ImGui.SetTooltip( TooltipModFilter );
}
} }
private void DrawToggleFilter() private void DrawToggleFilter()
@ -315,6 +306,7 @@ namespace Penumbra.UI
if( ImGui.BeginCombo( "##ModStateFilter", "", if( ImGui.BeginCombo( "##ModStateFilter", "",
ImGuiComboFlags.NoPreview | ImGuiComboFlags.PopupAlignLeft | ImGuiComboFlags.HeightLargest ) ) ImGuiComboFlags.NoPreview | ImGuiComboFlags.PopupAlignLeft | ImGuiComboFlags.HeightLargest ) )
{ {
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndCombo );
var flags = ( int )Cache.StateFilter; var flags = ( int )Cache.StateFilter;
foreach( ModFilter flag in Enum.GetValues( typeof( ModFilter ) ) ) foreach( ModFilter flag in Enum.GetValues( typeof( ModFilter ) ) )
{ {
@ -322,23 +314,17 @@ namespace Penumbra.UI
} }
Cache.StateFilter = ( ModFilter )flags; Cache.StateFilter = ( ModFilter )flags;
ImGui.EndCombo();
} }
if( ImGui.IsItemHovered() ) ImGuiCustom.HoverTooltip( "Filter mods for their activation status." );
{
ImGui.SetTooltip( "Filter mods for their activation status." );
}
} }
private void DrawModsSelectorFilter() private void DrawModsSelectorFilter()
{ {
ImGui.PushStyleVar( ImGuiStyleVar.ItemSpacing, ZeroVector ); using var style = ImGuiRaii.PushStyle( ImGuiStyleVar.ItemSpacing, ZeroVector );
DrawTextFilter(); DrawTextFilter();
ImGui.SameLine(); ImGui.SameLine();
DrawToggleFilter(); DrawToggleFilter();
ImGui.PopStyleVar();
} }
} }
@ -360,15 +346,14 @@ namespace Penumbra.UI
return; return;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndDragDropTarget );
if( IsDropping( DraggedModLabel ) ) if( IsDropping( DraggedModLabel ) )
{ {
var payload = ImGui.GetDragDropPayload(); var payload = ImGui.GetDragDropPayload();
var modIndex = Marshal.ReadInt32( payload.Data ); var modIndex = Marshal.ReadInt32( payload.Data );
var mod = Cache.GetMod( modIndex ).Item1; var mod = Cache.GetMod( modIndex ).Item1;
if( mod != null ) mod?.Data.Move( folder );
{
mod.Data.Move( folder );
}
} }
else if( IsDropping( DraggedFolderLabel ) ) else if( IsDropping( DraggedFolderLabel ) )
{ {
@ -381,8 +366,6 @@ namespace Penumbra.UI
droppedFolder.Move( folder ); droppedFolder.Move( folder );
} }
} }
ImGui.EndDragDropTarget();
} }
private void DragDropSourceFolder( ModFolder folder ) private void DragDropSourceFolder( ModFolder folder )
@ -392,11 +375,12 @@ namespace Penumbra.UI
return; return;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndDragDropSource );
var folderName = folder.FullName; var folderName = folder.FullName;
var ptr = Marshal.StringToHGlobalUni( folderName ); var ptr = Marshal.StringToHGlobalUni( folderName );
ImGui.SetDragDropPayload( DraggedFolderLabel, ptr, ( uint )( folderName.Length + 1 ) * 2 ); ImGui.SetDragDropPayload( DraggedFolderLabel, ptr, ( uint )( folderName.Length + 1 ) * 2 );
ImGui.Text( $"Moving {folderName}..." ); ImGui.Text( $"Moving {folderName}..." );
ImGui.EndDragDropSource();
} }
private void DragDropSourceMod( int modIndex, string modName ) private void DragDropSourceMod( int modIndex, string modName )
@ -406,10 +390,11 @@ namespace Penumbra.UI
return; return;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndDragDropSource );
Marshal.WriteInt32( _dragDropPayload, modIndex ); Marshal.WriteInt32( _dragDropPayload, modIndex );
ImGui.SetDragDropPayload( "ModIndex", _dragDropPayload, 4 ); ImGui.SetDragDropPayload( "ModIndex", _dragDropPayload, 4 );
ImGui.Text( $"Moving {modName}..." ); ImGui.Text( $"Moving {modName}..." );
ImGui.EndDragDropSource();
} }
~Selector() ~Selector()
@ -496,6 +481,8 @@ namespace Penumbra.UI
return; return;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndPopup );
if( ModPanel.DrawSortOrder( mod.Data, _modManager, this ) ) if( ModPanel.DrawSortOrder( mod.Data, _modManager, this ) )
{ {
ImGui.CloseCurrentPopup(); ImGui.CloseCurrentPopup();
@ -505,8 +492,6 @@ namespace Penumbra.UI
{ {
ImGui.SetKeyboardFocusHere( mod.Data.SortOrder.FullPath.Length - 1 ); ImGui.SetKeyboardFocusHere( mod.Data.SortOrder.FullPath.Length - 1 );
} }
ImGui.EndPopup();
} }
// === Folder === // === Folder ===
@ -545,7 +530,7 @@ namespace Penumbra.UI
private void DrawRenameFolderInput( ModFolder folder ) private void DrawRenameFolderInput( ModFolder folder )
{ {
ImGui.SetNextItemWidth( 150 ); ImGui.SetNextItemWidth( 150 * ImGuiHelpers.GlobalScale );
if( !ImGui.InputTextWithHint( "##NewFolderName", "Rename Folder...", ref _newFolderName, 64, if( !ImGui.InputTextWithHint( "##NewFolderName", "Rename Folder...", ref _newFolderName, 64,
ImGuiInputTextFlags.EnterReturnsTrue ) ) ImGuiInputTextFlags.EnterReturnsTrue ) )
{ {
@ -566,8 +551,13 @@ namespace Penumbra.UI
private void DrawFolderContextMenu( ModFolder folder, int currentIdx, string treeName ) private void DrawFolderContextMenu( ModFolder folder, int currentIdx, string treeName )
{ {
if( ImGui.BeginPopup( treeName ) ) if( !ImGui.BeginPopup( treeName ) )
{ {
return;
}
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndPopup );
if( ImGui.MenuItem( "Enable All Descendants" ) ) if( ImGui.MenuItem( "Enable All Descendants" ) )
{ {
ChangeStatusOfChildren( folder, currentIdx, true ); ChangeStatusOfChildren( folder, currentIdx, true );
@ -578,11 +568,8 @@ namespace Penumbra.UI
ChangeStatusOfChildren( folder, currentIdx, false ); ChangeStatusOfChildren( folder, currentIdx, false );
} }
ImGui.Dummy( Vector2.UnitY * 10 ); ImGuiHelpers.ScaledDummy( 0, 10 );
DrawRenameFolderInput( folder ); DrawRenameFolderInput( folder );
ImGui.EndPopup();
}
} }
} }
@ -607,35 +594,32 @@ namespace Penumbra.UI
if( collection == ModCollection.Empty if( collection == ModCollection.Empty
|| collection == _modManager.Collections.CurrentCollection ) || collection == _modManager.Collections.CurrentCollection )
{ {
ImGui.PushStyleVar( ImGuiStyleVar.Alpha, 0.5f ); using var _ = ImGuiRaii.PushStyle( ImGuiStyleVar.Alpha, 0.5f );
ImGui.Button( label, Vector2.UnitX * size ); ImGui.Button( label, Vector2.UnitX * size );
ImGui.PopStyleVar();
} }
else if( ImGui.Button( label, Vector2.UnitX * size ) ) else if( ImGui.Button( label, Vector2.UnitX * size ) )
{ {
_base._menu.CollectionsTab.SetCurrentCollection( collection ); _base._menu.CollectionsTab.SetCurrentCollection( collection );
} }
if( ImGui.IsItemHovered() ) ImGuiCustom.HoverTooltip(
{
ImGui.SetTooltip(
$"Switches to the currently set {tooltipLabel} collection, if it is not set to None and it is not the current collection already." ); $"Switches to the currently set {tooltipLabel} collection, if it is not set to None and it is not the current collection already." );
} }
}
private void DrawHeaderBar() private void DrawHeaderBar()
{ {
const float size = 200; const float size = 200;
DrawModsSelectorFilter(); DrawModsSelectorFilter();
var textSize = ImGui.CalcTextSize( TabCollections.LabelCurrentCollection ).X + ImGui.GetStyle().ItemInnerSpacing.X; var textSize = ImGui.CalcTextSize( TabCollections.LabelCurrentCollection ).X + ImGui.GetStyle().ItemInnerSpacing.X;
var comboSize = size * ImGui.GetIO().FontGlobalScale; var comboSize = size * ImGui.GetIO().FontGlobalScale;
var offset = comboSize + textSize; var offset = comboSize + textSize;
var buttonSize = ( ImGui.GetWindowContentRegionWidth() var buttonSize = Math.Max( ( ImGui.GetWindowContentRegionWidth()
- offset - offset
- SelectorPanelWidth * _selectorScalingFactor - SelectorPanelWidth * _selectorScalingFactor
- 4 * ImGui.GetStyle().ItemSpacing.X ) - 4 * ImGui.GetStyle().ItemSpacing.X )
/ 2; / 2, 5f );
ImGui.SameLine(); ImGui.SameLine();
DrawCollectionButton( "Default", "default", buttonSize, _modManager.Collections.DefaultCollection ); DrawCollectionButton( "Default", "default", buttonSize, _modManager.Collections.DefaultCollection );
@ -644,9 +628,8 @@ namespace Penumbra.UI
ImGui.SameLine(); ImGui.SameLine();
ImGui.SetNextItemWidth( comboSize ); ImGui.SetNextItemWidth( comboSize );
ImGui.PushStyleVar( ImGuiStyleVar.ItemSpacing, Vector2.Zero ); using var style = ImGuiRaii.PushStyle( ImGuiStyleVar.ItemSpacing, Vector2.Zero );
_base._menu.CollectionsTab.DrawCurrentCollectionSelector( false ); _base._menu.CollectionsTab.DrawCurrentCollectionSelector( false );
ImGui.PopStyleVar();
} }
private void DrawFolderContent( ModFolder folder, ref int idx ) private void DrawFolderContent( ModFolder folder, ref int idx )
@ -685,6 +668,7 @@ namespace Penumbra.UI
{ {
var treeName = $"{folder.Name}##{folder.FullName}"; var treeName = $"{folder.Name}##{folder.FullName}";
var open = ImGui.TreeNodeEx( treeName ); var open = ImGui.TreeNodeEx( treeName );
using var raii = ImGuiRaii.DeferredEnd( ImGui.TreePop, open );
if( ImGui.IsItemClicked( ImGuiMouseButton.Right ) ) if( ImGui.IsItemClicked( ImGuiMouseButton.Right ) )
{ {
_newFolderName = string.Empty; _newFolderName = string.Empty;
@ -698,7 +682,6 @@ namespace Penumbra.UI
if( open ) if( open )
{ {
DrawFolderContent( folder, ref idx ); DrawFolderContent( folder, ref idx );
ImGui.TreePop();
} }
else else
{ {
@ -708,17 +691,10 @@ namespace Penumbra.UI
private void DrawMod( Mod.Mod mod, int modIndex, uint color ) private void DrawMod( Mod.Mod mod, int modIndex, uint color )
{ {
if( color != 0 ) using var colorRaii = ImGuiRaii.PushColor( ImGuiCol.Text, color, color != 0 );
{
ImGui.PushStyleColor( ImGuiCol.Text, color );
}
var selected = ImGui.Selectable( $"{mod.Data.Meta.Name}##{modIndex}", modIndex == _index ); var selected = ImGui.Selectable( $"{mod.Data.Meta.Name}##{modIndex}", modIndex == _index );
colorRaii.Pop();
if( color != 0 )
{
ImGui.PopStyleColor();
}
var popupName = $"##SortOrderPopup{modIndex}"; var popupName = $"##SortOrderPopup{modIndex}";
var firstOpen = false; var firstOpen = false;
@ -754,37 +730,33 @@ namespace Penumbra.UI
} }
} }
try _selectorScalingFactor = ImGuiHelpers.GlobalScale
{ * ( Penumbra.Config.ScaleModSelector
_selectorScalingFactor = Penumbra.Config.ScaleModSelector
? ImGui.GetWindowWidth() / SettingsMenu.MinSettingsSize.X ? ImGui.GetWindowWidth() / SettingsMenu.MinSettingsSize.X
: 1f; : 1f );
// Selector pane // Selector pane
DrawHeaderBar(); DrawHeaderBar();
ImGui.PushStyleVar( ImGuiStyleVar.ItemSpacing, Vector2.Zero ); using var style = ImGuiRaii.PushStyle( ImGuiStyleVar.ItemSpacing, Vector2.Zero );
ImGui.BeginGroup(); ImGui.BeginGroup();
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndGroup )
.Push( ImGui.EndChild );
// Inlay selector list // Inlay selector list
if( ImGui.BeginChild( LabelSelectorList, if( ImGui.BeginChild( LabelSelectorList,
new Vector2( SelectorPanelWidth * _selectorScalingFactor, -ImGui.GetFrameHeightWithSpacing() ), new Vector2( SelectorPanelWidth * _selectorScalingFactor, -ImGui.GetFrameHeightWithSpacing() ),
true, ImGuiWindowFlags.HorizontalScrollbar ) ) true, ImGuiWindowFlags.HorizontalScrollbar ) )
{ {
ImGui.PushStyleVar( ImGuiStyleVar.IndentSpacing, 12.5f ); style.Push( ImGuiStyleVar.IndentSpacing, 12.5f );
var modIndex = 0; var modIndex = 0;
DrawFolderContent( _modManager.StructuredMods, ref modIndex ); DrawFolderContent( _modManager.StructuredMods, ref modIndex );
ImGui.PopStyleVar(); style.Pop();
} }
ImGui.EndChild(); raii.Pop();
DrawModsSelectorButtons(); DrawModsSelectorButtons();
ImGui.EndGroup();
}
finally
{
ImGui.PopStyleVar();
}
style.Pop();
DrawModHelpPopup(); DrawModHelpPopup();
DrawDeleteModal(); DrawDeleteModal();

View file

@ -1,8 +1,10 @@
using System.Numerics; using System.Numerics;
using Dalamud.Interface;
using FFXIVClientStructs.FFXIV.Client.System.Resource; using FFXIVClientStructs.FFXIV.Client.System.Resource;
using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle; using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle;
using FFXIVClientStructs.STD; using FFXIVClientStructs.STD;
using ImGuiNET; using ImGuiNET;
using Penumbra.UI.Custom;
namespace Penumbra.UI namespace Penumbra.UI
{ {
@ -26,17 +28,19 @@ namespace Penumbra.UI
return; return;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.TreePop );
if( typeMap->Count == 0 || !ImGui.BeginTable( $"##{label}_table", 4, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg ) ) if( typeMap->Count == 0 || !ImGui.BeginTable( $"##{label}_table", 4, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg ) )
{ {
ImGui.TreePop();
return; return;
} }
ImGui.TableSetupColumn( "Hash", ImGuiTableColumnFlags.WidthFixed, 100 ); raii.Push( ImGui.EndTable );
ImGui.TableSetupColumn( "Ptr", ImGuiTableColumnFlags.WidthFixed, 100 );
ImGui.TableSetupColumn( "Path", ImGuiTableColumnFlags.WidthFixed, ImGui.GetWindowContentRegionWidth() - 300 ); ImGui.TableSetupColumn( "Hash", ImGuiTableColumnFlags.WidthFixed, 100 * ImGuiHelpers.GlobalScale );
ImGui.TableSetupColumn( "Refs", ImGuiTableColumnFlags.WidthFixed, 30 ); ImGui.TableSetupColumn( "Ptr", ImGuiTableColumnFlags.WidthFixed, 100 * ImGuiHelpers.GlobalScale );
ImGui.TableSetupColumn( "Path", ImGuiTableColumnFlags.WidthFixed, ImGui.GetWindowContentRegionWidth() - 300 * ImGuiHelpers.GlobalScale );
ImGui.TableSetupColumn( "Refs", ImGuiTableColumnFlags.WidthFixed, 30 * ImGuiHelpers.GlobalScale );
ImGui.TableHeadersRow(); ImGui.TableHeadersRow();
var node = typeMap->SmallestValue; var node = typeMap->SmallestValue;
@ -59,9 +63,6 @@ namespace Penumbra.UI
ImGui.Text( node->KeyValuePair.Item2.Value->RefCount.ToString() ); ImGui.Text( node->KeyValuePair.Item2.Value->RefCount.ToString() );
node = node->Next(); node = node->Next();
} }
ImGui.EndTable();
ImGui.TreePop();
} }
private unsafe void DrawCategoryContainer( string label, ResourceGraph.CategoryContainer container ) private unsafe void DrawCategoryContainer( string label, ResourceGraph.CategoryContainer container )
@ -72,6 +73,8 @@ namespace Penumbra.UI
return; return;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.TreePop );
var node = map->SmallestValue; var node = map->SmallestValue;
while( !node->IsNil ) while( !node->IsNil )
{ {
@ -79,8 +82,6 @@ namespace Penumbra.UI
node->KeyValuePair.Item2.Value ); node->KeyValuePair.Item2.Value );
node = node->Next(); node = node->Next();
} }
ImGui.TreePop();
} }
private unsafe void DrawResourceManagerTab() private unsafe void DrawResourceManagerTab()
@ -90,6 +91,8 @@ namespace Penumbra.UI
return; return;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTabItem );
var resourceHandler = *( ResourceManager** )( Dalamud.SigScanner.Module.BaseAddress + 0x1D93AC0 ); var resourceHandler = *( ResourceManager** )( Dalamud.SigScanner.Module.BaseAddress + 0x1D93AC0 );
if( resourceHandler == null ) if( resourceHandler == null )
@ -97,8 +100,12 @@ namespace Penumbra.UI
return; return;
} }
if( ImGui.BeginChild( "##ResourceManagerChild", -Vector2.One, true ) ) raii.Push( ImGui.EndChild );
if( !ImGui.BeginChild( "##ResourceManagerChild", -Vector2.One, true ) )
{ {
return;
}
DrawCategoryContainer( "Common", resourceHandler->ResourceGraph->CommonContainer ); DrawCategoryContainer( "Common", resourceHandler->ResourceGraph->CommonContainer );
DrawCategoryContainer( "BgCommon", resourceHandler->ResourceGraph->BgCommonContainer ); DrawCategoryContainer( "BgCommon", resourceHandler->ResourceGraph->BgCommonContainer );
DrawCategoryContainer( "Bg", resourceHandler->ResourceGraph->BgContainer ); DrawCategoryContainer( "Bg", resourceHandler->ResourceGraph->BgContainer );
@ -115,10 +122,5 @@ namespace Penumbra.UI
DrawCategoryContainer( "SqpackTest", resourceHandler->ResourceGraph->SqpackTestContainer ); DrawCategoryContainer( "SqpackTest", resourceHandler->ResourceGraph->SqpackTestContainer );
DrawCategoryContainer( "Debug", resourceHandler->ResourceGraph->DebugContainer ); DrawCategoryContainer( "Debug", resourceHandler->ResourceGraph->DebugContainer );
} }
ImGui.EndChild();
ImGui.EndTabItem();
}
} }
} }

View file

@ -7,6 +7,7 @@ using ImGuiNET;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.Interop; using Penumbra.Interop;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.UI.Custom;
using Penumbra.Util; using Penumbra.Util;
namespace Penumbra.UI namespace Penumbra.UI
@ -65,13 +66,10 @@ namespace Penumbra.UI
_base._modManager.SetTempDirectory( tempPath ); _base._modManager.SetTempDirectory( tempPath );
} }
if( ImGui.IsItemHovered() ) ImGuiCustom.HoverTooltip( "The folder used to store temporary meta manipulation files.\n"
{
ImGui.SetTooltip( "The folder used to store temporary meta manipulation files.\n"
+ "Leave this blank if you have no reason not to.\n" + "Leave this blank if you have no reason not to.\n"
+ "A folder 'penumbrametatmp' will be created as a subdirectory to the specified directory.\n" + "A folder 'penumbrametatmp' will be created as a subdirectory to the specified directory.\n"
+ "If none is specified (i.e. this is blank) this folder will be created in the root folder instead." ); + "If none is specified (i.e. this is blank) this folder will be created in the root folder instead." );
}
ImGui.SameLine(); ImGui.SameLine();
if( ImGui.Button( LabelOpenTempFolder ) ) if( ImGui.Button( LabelOpenTempFolder ) )
@ -115,7 +113,7 @@ namespace Penumbra.UI
{ {
_config.IsEnabled = enabled; _config.IsEnabled = enabled;
_configChanged = true; _configChanged = true;
Service<ResidentResources>.Get().ReloadPlayerResources(); Service< ResidentResources >.Get().ReloadPlayerResources();
_base._penumbra.ObjectReloader.RedrawAll( enabled ? RedrawType.WithSettings : RedrawType.WithoutSettings ); _base._penumbra.ObjectReloader.RedrawAll( enabled ? RedrawType.WithSettings : RedrawType.WithoutSettings );
if( _config.EnablePlayerWatch ) if( _config.EnablePlayerWatch )
{ {
@ -177,10 +175,10 @@ namespace Penumbra.UI
private void DrawDisableNotificationsBox() private void DrawDisableNotificationsBox()
{ {
var fswatch = _config.DisableFileSystemNotifications; var fsWatch = _config.DisableFileSystemNotifications;
if( ImGui.Checkbox( LabelDisableNotifications, ref fswatch ) ) if( ImGui.Checkbox( LabelDisableNotifications, ref fsWatch ) )
{ {
_config.DisableFileSystemNotifications = fswatch; _config.DisableFileSystemNotifications = fsWatch;
_configChanged = true; _configChanged = true;
} }
} }
@ -214,15 +212,15 @@ namespace Penumbra.UI
Penumbra.PlayerWatcher.SetStatus( enabled ); Penumbra.PlayerWatcher.SetStatus( enabled );
} }
if( ImGui.IsItemHovered() ) ImGuiCustom.HoverTooltip(
{
ImGui.SetTooltip(
"If this setting is enabled, penumbra will keep tabs on characters that have a corresponding collection setup in the Collections tab.\n" "If this setting is enabled, penumbra will keep tabs on characters that have a corresponding collection setup in the Collections tab.\n"
+ "Penumbra will try to automatically redraw those characters using their collection when they first appear in an instance, or when they change their current equip." ); + "Penumbra will try to automatically redraw those characters using their collection when they first appear in an instance, or when they change their current equip." );
if( !_config.EnablePlayerWatch || !_config.ShowAdvanced )
{
return;
} }
if( _config.EnablePlayerWatch && _config.ShowAdvanced )
{
var waitFrames = _config.WaitFrames; var waitFrames = _config.WaitFrames;
ImGui.SameLine(); ImGui.SameLine();
ImGui.SetNextItemWidth( 50 ); ImGui.SetNextItemWidth( 50 );
@ -236,14 +234,10 @@ namespace Penumbra.UI
_configChanged = true; _configChanged = true;
} }
if( ImGui.IsItemHovered() ) ImGuiCustom.HoverTooltip(
{
ImGui.SetTooltip(
"The number of frames penumbra waits after some events (like zone changes) until it starts trying to redraw actors again, in a range of [1, 3001].\n" "The number of frames penumbra waits after some events (like zone changes) until it starts trying to redraw actors again, in a range of [1, 3001].\n"
+ "Keep this as low as possible while producing stable results." ); + "Keep this as low as possible while producing stable results." );
} }
}
}
private static void DrawReloadResourceButton() private static void DrawReloadResourceButton()
{ {
@ -264,23 +258,24 @@ namespace Penumbra.UI
public void Draw() public void Draw()
{ {
var ret = ImGui.BeginTabItem( LabelTab ); if( !ImGui.BeginTabItem( LabelTab ) )
if( !ret )
{ {
return; return;
} }
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTabItem );
DrawRootFolder(); DrawRootFolder();
DrawRediscoverButton(); DrawRediscoverButton();
ImGui.SameLine(); ImGui.SameLine();
DrawOpenModsButton(); DrawOpenModsButton();
Custom.ImGuiCustom.VerticalDistance( DefaultVerticalSpace ); ImGuiCustom.VerticalDistance( DefaultVerticalSpace );
DrawEnabledBox(); DrawEnabledBox();
DrawEnabledPlayerWatcher(); DrawEnabledPlayerWatcher();
Custom.ImGuiCustom.VerticalDistance( DefaultVerticalSpace ); ImGuiCustom.VerticalDistance( DefaultVerticalSpace );
DrawScaleModSelectorBox(); DrawScaleModSelectorBox();
DrawSortFoldersFirstBox(); DrawSortFoldersFirstBox();
DrawShowAdvancedBox(); DrawShowAdvancedBox();
@ -295,8 +290,6 @@ namespace Penumbra.UI
_config.Save(); _config.Save();
_configChanged = false; _configChanged = false;
} }
ImGui.EndTabItem();
} }
} }
} }

View file

@ -1,6 +1,7 @@
using System.Numerics; using System.Numerics;
using ImGuiNET; using ImGuiNET;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.UI.Custom;
using Penumbra.Util; using Penumbra.Util;
namespace Penumbra.UI namespace Penumbra.UI
@ -54,13 +55,14 @@ namespace Penumbra.UI
#else #else
var ret = ImGui.Begin( _base._penumbra.Name, ref Visible ); var ret = ImGui.Begin( _base._penumbra.Name, ref Visible );
#endif #endif
using var raii = ImGuiRaii.DeferredEnd( ImGui.End );
if( !ret ) if( !ret )
{ {
ImGui.End();
return; return;
} }
ImGui.BeginTabBar( PenumbraSettingsLabel ); ImGui.BeginTabBar( PenumbraSettingsLabel );
raii.Push( ImGui.EndTabBar );
_settingsTab.Draw(); _settingsTab.Draw();
CollectionsTab.Draw(); CollectionsTab.Draw();
@ -82,9 +84,6 @@ namespace Penumbra.UI
_base.DrawDebugTab(); _base.DrawDebugTab();
_base.DrawResourceManagerTab(); _base.DrawResourceManagerTab();
} }
ImGui.EndTabBar();
ImGui.End();
} }
} }
} }