Add Tutorials.

This commit is contained in:
Ottermandias 2022-07-11 17:27:22 +02:00
parent 2412e3be08
commit 769f54e8dd
12 changed files with 197 additions and 46 deletions

@ -1 +1 @@
Subproject commit fcc5031fcf14b54f090d5bb789c580567b3f0023 Subproject commit 70d9f81436c82cc51734f0661d10f461da4f1840

View file

@ -41,6 +41,8 @@ public partial class Configuration : IPluginConfiguration
public bool DebugMode { get; set; } = false; public bool DebugMode { get; set; } = false;
#endif #endif
public int TutorialStep { get; set; } = 0;
public bool EnableFullResourceLogging { get; set; } = false; public bool EnableFullResourceLogging { get; set; } = false;
public bool EnableResourceLogging { get; set; } = false; public bool EnableResourceLogging { get; set; } = false;
public string ResourceLoggingFilter { get; set; } = string.Empty; public string ResourceLoggingFilter { get; set; } = string.Empty;

View file

@ -28,6 +28,8 @@ public static class Colors
public const uint RedTableBgTint = 0x40000080; public const uint RedTableBgTint = 0x40000080;
public const uint DiscordColor = 0xFFDA8972; public const uint DiscordColor = 0xFFDA8972;
public const uint FilterActive = 0x807070FF; public const uint FilterActive = 0x807070FF;
public const uint TutorialMarker = 0xFF20FFFF;
public const uint TutorialBorder = 0xD00000FF;
public static (uint DefaultColor, string Name, string Description) Data( this ColorId color ) public static (uint DefaultColor, string Name, string Description) Data( this ColorId color )
=> color switch => color switch

View file

@ -199,8 +199,10 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod
private void AddImportModButton( Vector2 size ) private void AddImportModButton( Vector2 size )
{ {
if( !ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.FileImport.ToIconString(), size, var button = ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.FileImport.ToIconString(), size,
"Import one or multiple mods from Tex Tools Mod Pack Files.", !Penumbra.ModManager.Valid, true ) ) "Import one or multiple mods from Tex Tools Mod Pack Files.", !Penumbra.ModManager.Valid, true );
ConfigWindow.OpenTutorial( 13 );
if (!button)
{ {
return; return;
} }
@ -310,6 +312,7 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod
{ {
ImGui.OpenPopup( "ExtendedHelp" ); ImGui.OpenPopup( "ExtendedHelp" );
} }
ConfigWindow.OpenTutorial( 14 );
} }
// Helpers. // Helpers.

View file

@ -31,7 +31,8 @@ public partial class ConfigWindow
// Draw the whole inheritance block. // Draw the whole inheritance block.
private void DrawInheritanceBlock() private void DrawInheritanceBlock()
{ {
using var id = ImRaii.PushId( "##Inheritance" ); using var group = ImRaii.Group();
using var id = ImRaii.PushId( "##Inheritance" );
ImGui.TextUnformatted( "The current collection inherits from:" ); ImGui.TextUnformatted( "The current collection inherits from:" );
DrawCurrentCollectionInheritance(); DrawCurrentCollectionInheritance();
DrawInheritanceTrashButton(); DrawInheritanceTrashButton();

View file

@ -23,13 +23,18 @@ public partial class ConfigWindow
public void Draw() public void Draw()
{ {
using var tab = ImRaii.TabItem( "Collections" ); using var tab = ImRaii.TabItem( "Collections" );
OpenTutorial( 5 );
if( !tab ) if( !tab )
{ {
return; return;
} }
DrawCharacterCollectionSelectors(); using var child = ImRaii.Child( "##collections", -Vector2.One );
DrawMainSelectors(); if( child )
{
DrawActiveCollectionSelectors();
DrawMainSelectors();
}
} }
@ -106,6 +111,7 @@ public partial class ConfigWindow
private void DrawCurrentCollectionSelector() private void DrawCurrentCollectionSelector()
{ {
using var group = ImRaii.Group();
DrawCollectionSelector( "##current", _window._inputTextWidth.X, CollectionType.Current, false, null ); DrawCollectionSelector( "##current", _window._inputTextWidth.X, CollectionType.Current, false, null );
ImGui.SameLine(); ImGui.SameLine();
ImGuiUtil.LabeledHelpMarker( "Current Collection", ImGuiUtil.LabeledHelpMarker( "Current Collection",
@ -114,6 +120,7 @@ public partial class ConfigWindow
private void DrawDefaultCollectionSelector() private void DrawDefaultCollectionSelector()
{ {
using var group = ImRaii.Group();
DrawCollectionSelector( "##default", _window._inputTextWidth.X, CollectionType.Default, true, null ); DrawCollectionSelector( "##default", _window._inputTextWidth.X, CollectionType.Default, true, null );
ImGui.SameLine(); ImGui.SameLine();
ImGuiUtil.LabeledHelpMarker( "Default Collection", ImGuiUtil.LabeledHelpMarker( "Default Collection",
@ -183,34 +190,42 @@ public partial class ConfigWindow
} }
} }
private void DrawCharacterCollectionSelectors() private void DrawActiveCollectionSelectors()
{ {
ImGui.Dummy( _window._defaultSpace ); ImGui.Dummy( _window._defaultSpace );
if( ImGui.CollapsingHeader( "Active Collections", ImGuiTreeNodeFlags.DefaultOpen ) ) var open = ImGui.CollapsingHeader( "Active Collections" );
OpenTutorial( 9 );
if( !open )
{ {
ImGui.Dummy( _window._defaultSpace ); return;
DrawDefaultCollectionSelector(); }
ImGui.Dummy( _window._defaultSpace );
foreach( var type in CollectionTypeExtensions.Special ) ImGui.Dummy( _window._defaultSpace );
DrawDefaultCollectionSelector();
OpenTutorial( 10 );
ImGui.Dummy( _window._defaultSpace );
foreach( var type in CollectionTypeExtensions.Special )
{
var collection = Penumbra.CollectionManager.ByType( type );
if( collection != null )
{ {
var collection = Penumbra.CollectionManager.ByType( type ); using var id = ImRaii.PushId( ( int )type );
if( collection != null ) DrawCollectionSelector( string.Empty, _window._inputTextWidth.X, type, true, null );
ImGui.SameLine();
if( ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.Trash.ToIconString(), _window._iconButtonSize, string.Empty,
false, true ) )
{ {
using var id = ImRaii.PushId( ( int )type ); Penumbra.CollectionManager.RemoveSpecialCollection( type );
DrawCollectionSelector( string.Empty, _window._inputTextWidth.X, type, true, null );
ImGui.SameLine();
if( ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.Trash.ToIconString(), _window._iconButtonSize, string.Empty,
false, true ) )
{
Penumbra.CollectionManager.RemoveSpecialCollection( type );
}
ImGui.SameLine();
ImGui.AlignTextToFramePadding();
ImGuiUtil.LabeledHelpMarker( type.ToName(), type.ToDescription() );
} }
}
ImGui.SameLine();
ImGui.AlignTextToFramePadding();
ImGuiUtil.LabeledHelpMarker( type.ToName(), type.ToDescription() );
}
}
using( var group = ImRaii.Group() )
{
DrawNewSpecialCollection(); DrawNewSpecialCollection();
ImGui.Dummy( _window._defaultSpace ); ImGui.Dummy( _window._defaultSpace );
@ -231,22 +246,31 @@ public partial class ConfigWindow
} }
DrawNewCharacterCollection(); DrawNewCharacterCollection();
ImGui.Dummy( _window._defaultSpace );
} }
OpenTutorial( 11 );
ImGui.Dummy( _window._defaultSpace );
} }
private void DrawMainSelectors() private void DrawMainSelectors()
{ {
ImGui.Dummy( _window._defaultSpace ); ImGui.Dummy( _window._defaultSpace );
if( ImGui.CollapsingHeader( "Collection Settings", ImGuiTreeNodeFlags.DefaultOpen ) ) var open = ImGui.CollapsingHeader( "Collection Settings", ImGuiTreeNodeFlags.DefaultOpen );
OpenTutorial( 6 );
if( !open )
{ {
ImGui.Dummy( _window._defaultSpace ); return;
DrawCurrentCollectionSelector();
ImGui.Dummy( _window._defaultSpace );
DrawNewCollectionInput();
ImGui.Dummy( _window._defaultSpace );
DrawInheritanceBlock();
} }
ImGui.Dummy( _window._defaultSpace );
DrawCurrentCollectionSelector();
OpenTutorial( 7 );
ImGui.Dummy( _window._defaultSpace );
DrawNewCollectionInput();
ImGui.Dummy( _window._defaultSpace );
DrawInheritanceBlock();
OpenTutorial( 8 );
} }
} }
} }

View file

@ -36,6 +36,7 @@ public partial class ConfigWindow
private void DrawSettingsTab() private void DrawSettingsTab()
{ {
using var tab = DrawTab( SettingsTabHeader, Tabs.Settings ); using var tab = DrawTab( SettingsTabHeader, Tabs.Settings );
OpenTutorial( 17 );
if( !tab ) if( !tab )
{ {
return; return;
@ -51,8 +52,10 @@ public partial class ConfigWindow
ImGui.Dummy( _window._defaultSpace ); ImGui.Dummy( _window._defaultSpace );
_window._penumbra.Api.InvokePreSettingsPanel( _mod.ModPath.Name ); _window._penumbra.Api.InvokePreSettingsPanel( _mod.ModPath.Name );
DrawEnabledInput(); DrawEnabledInput();
OpenTutorial( 15 );
ImGui.SameLine(); ImGui.SameLine();
DrawPriorityInput(); DrawPriorityInput();
OpenTutorial( 16 );
DrawRemoveSettings(); DrawRemoveSettings();
ImGui.Dummy( _window._defaultSpace ); ImGui.Dummy( _window._defaultSpace );
for( var idx = 0; idx < _mod.Groups.Count; ++idx ) for( var idx = 0; idx < _mod.Groups.Count; ++idx )
@ -104,7 +107,8 @@ public partial class ConfigWindow
// Priority is changed on deactivation of the input box. // Priority is changed on deactivation of the input box.
private void DrawPriorityInput() private void DrawPriorityInput()
{ {
var priority = _currentPriority ?? _settings.Priority; using var group = ImRaii.Group();
var priority = _currentPriority ?? _settings.Priority;
ImGui.SetNextItemWidth( 50 * ImGuiHelpers.GlobalScale ); ImGui.SetNextItemWidth( 50 * ImGuiHelpers.GlobalScale );
if( ImGui.InputInt( "##Priority", ref priority, 0, 0 ) ) if( ImGui.InputInt( "##Priority", ref priority, 0, 0 ) )
{ {

View file

@ -22,6 +22,7 @@ public partial class ConfigWindow
try try
{ {
using var tab = ImRaii.TabItem( "Mods" ); using var tab = ImRaii.TabItem( "Mods" );
OpenTutorial( 12 );
if( !tab ) if( !tab )
{ {
return; return;

View file

@ -6,7 +6,6 @@ using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Widgets; using OtterGui.Widgets;
using Penumbra.Util;
namespace Penumbra.UI; namespace Penumbra.UI;
@ -32,9 +31,12 @@ public partial class ConfigWindow
{ {
if( !ImGui.CollapsingHeader( "General" ) ) if( !ImGui.CollapsingHeader( "General" ) )
{ {
OpenTutorial( 4 );
return; return;
} }
OpenTutorial( 4 );
Checkbox( "Hide Config Window when UI is Hidden", Checkbox( "Hide Config Window when UI is Hidden",
"Hide the penumbra main window when you manually hide the in-game user interface.", Penumbra.Config.HideUiWhenUiHidden, "Hide the penumbra main window when you manually hide the in-game user interface.", Penumbra.Config.HideUiWhenUiHidden,
v => v =>

View file

@ -4,7 +4,9 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Interface.Components;
using Dalamud.Interface.ImGuiFileDialog; using Dalamud.Interface.ImGuiFileDialog;
using Dalamud.Utility;
using ImGuiNET; using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Raii; using OtterGui.Raii;
@ -131,7 +133,10 @@ public partial class ConfigWindow
// as well as the directory picker button and the enter warning. // as well as the directory picker button and the enter warning.
private void DrawRootFolder() private void DrawRootFolder()
{ {
_newModDirectory ??= Penumbra.Config.ModDirectory; if( _newModDirectory.IsNullOrEmpty() )
{
_newModDirectory = Penumbra.Config.ModDirectory;
}
var spacing = 3 * ImGuiHelpers.GlobalScale; var spacing = 3 * ImGuiHelpers.GlobalScale;
using var group = ImRaii.Group(); using var group = ImRaii.Group();
@ -149,6 +154,7 @@ public partial class ConfigWindow
+ "It should also be placed near the root of a logical drive - the shorter the total path to this folder, the better.\n" + "It should also be placed near the root of a logical drive - the shorter the total path to this folder, the better.\n"
+ "Definitely do not place it in your Dalamud directory or any sub-directory thereof." ); + "Definitely do not place it in your Dalamud directory or any sub-directory thereof." );
group.Dispose(); group.Dispose();
OpenTutorial( 1 );
ImGui.SameLine(); ImGui.SameLine();
var pos = ImGui.GetCursorPosX(); var pos = ImGui.GetCursorPosX();
ImGui.NewLine(); ImGui.NewLine();
@ -181,20 +187,34 @@ public partial class ConfigWindow
{ {
_window._penumbra.SetEnabled( enabled ); _window._penumbra.SetEnabled( enabled );
} }
OpenTutorial( 2 );
} }
private static void DrawShowAdvancedBox() private static void DrawShowAdvancedBox()
{ {
var showAdvanced = Penumbra.Config.ShowAdvanced; var showAdvanced = Penumbra.Config.ShowAdvanced;
if( ImGui.Checkbox( "##showAdvanced", ref showAdvanced ) ) using( var _ = ImRaii.Group() )
{ {
Penumbra.Config.ShowAdvanced = showAdvanced; if( ImGui.Checkbox( "##showAdvanced", ref showAdvanced ) )
Penumbra.Config.Save(); {
Penumbra.Config.ShowAdvanced = showAdvanced;
Penumbra.Config.Save();
}
ImGui.SameLine();
const string tt = "Enable some advanced options in this window and in the mod selector.\n"
+ "This is required to enable manually editing any mod information.";
// Manually split due to tutorial.
ImGuiComponents.HelpMarker( tt );
OpenTutorial( 0 );
ImGui.SameLine();
ImGui.TextUnformatted( "Show Advanced Settings" );
ImGuiUtil.HoverTooltip( tt );
} }
ImGui.SameLine(); OpenTutorial( 3 );
ImGuiUtil.LabeledHelpMarker( "Show Advanced Settings", "Enable some advanced options in this window and in the mod selector.\n"
+ "This is required to enable manually editing any mod information." );
} }
private static void DrawColorSettings() private static void DrawColorSettings()
@ -281,12 +301,12 @@ public partial class ConfigWindow
private static void DrawSupportButtons() private static void DrawSupportButtons()
{ {
var width = ImGui.CalcTextSize( SupportInfoButtonText ).X + ImGui.GetStyle().FramePadding.X * 2; var width = ImGui.CalcTextSize( SupportInfoButtonText ).X + ImGui.GetStyle().FramePadding.X * 2;
var xPos = ImGui.GetWindowWidth() - width;
if( ImGui.GetScrollMaxY() > 0 ) if( ImGui.GetScrollMaxY() > 0 )
{ {
width += ImGui.GetStyle().ScrollbarSize + ImGui.GetStyle().ItemSpacing.X; xPos -= ImGui.GetStyle().ScrollbarSize + ImGui.GetStyle().FramePadding.X;
} }
var xPos = ImGui.GetWindowWidth() - width;
ImGui.SetCursorPos( new Vector2( xPos, ImGui.GetFrameHeightWithSpacing() ) ); ImGui.SetCursorPos( new Vector2( xPos, ImGui.GetFrameHeightWithSpacing() ) );
DrawSupportButton(); DrawSupportButton();
@ -295,6 +315,13 @@ public partial class ConfigWindow
ImGui.SetCursorPos( new Vector2( xPos, 2 * ImGui.GetFrameHeightWithSpacing() ) ); ImGui.SetCursorPos( new Vector2( xPos, 2 * ImGui.GetFrameHeightWithSpacing() ) );
DrawGuideButton( width ); DrawGuideButton( width );
ImGui.SetCursorPos( new Vector2( xPos, 3 * ImGui.GetFrameHeightWithSpacing() ) );
if( ImGui.Button( "Restart Tutorial", new Vector2( width, 0 ) ) )
{
Penumbra.Config.TutorialStep = 0;
Penumbra.Config.Save();
}
} }
} }
} }

View file

@ -0,0 +1,80 @@
using OtterGui.Widgets;
using Penumbra.UI.Classes;
namespace Penumbra.UI;
public partial class ConfigWindow
{
private static void UpdateTutorialStep()
{
var tutorial = Tutorial.CurrentEnabledId( Penumbra.Config.TutorialStep );
if( tutorial != Penumbra.Config.TutorialStep )
{
Penumbra.Config.TutorialStep = tutorial;
Penumbra.Config.Save();
}
}
public static void OpenTutorial( int id )
=> Tutorial.Open( id, Penumbra.Config.TutorialStep, v =>
{
Penumbra.Config.TutorialStep = v;
Penumbra.Config.Save();
} );
public static readonly Tutorial Tutorial = new Tutorial()
{
BorderColor = Colors.TutorialBorder,
HighlightColor = Colors.TutorialMarker,
PopupLabel = "Settings Tutorial",
}
.Register( "General Tooltips", "This symbol gives you further information about whatever setting it appears next to.\n\n"
+ "Hover over them when you are unsure what something does or how to do something." )
.Register( "Initial Setup, Step 1: Mod Directory",
"The first step is to set up your mod directory, which is where your mods are extracted to.\n\n"
+ "The mod directory should be a short path - like 'D:\\FFXIVMods', if you want to store your mods on D: - and be on a fast hard drive." )
.Register( "Initial Setup, Step 2: Enable Mods", "Do not forget to enable your mods in case they are not." )
.Register( "Advanced Settings", "When you are just starting, you should leave this off.\n\n"
+ "If you need to do any editing of your mods, you will have to turn it on later." )
.Register( "General Settings", "Look through all of these settings before starting, they might help you a lot!\n\n"
+ "If you do not know what some of these do yet, return to this later!" )
.Register( "Initial Setup, Step 3: Collections", "Collections are lists of settings for your installed mods.\n\n"
+ "This is our next stop!" )
.Register( "Initial Setup, Step 4: Editing Collections", "First, we need to open the Collection Settings.\n\n"
+ "In here, we can create new collections, delete collections, or make them inherit from each other." )
.Register( "Initial Setup, Step 5: Current Collection",
"We should already have a Default Collection, and for our simple setup, we do not need to do anything here.\n\n"
+ "The current collection is the one we are currently editing. Any changes we make in our mod settings later will edit this collection." )
.Register( "Inheritance",
"This is a more advanced feature. Click the 'What is Inheritance?' button for more information, but we will ignore this for now." )
.Register( "Initial Setup, Step 6: Active Collections", "Active Collections are those that are actually in use at the moment.\n\n"
+ "Any collection in use will apply to the game under certain conditions." )
.Register( "Initial Setup, Step 7: Default Collection",
"The Default Collection - which should currently also be set to a collection named Default - is the main one.\n\n"
+ "As long as no more specific collection applies to something, the mods from the Default Collection will be used.\n\n"
+ "This is also the collection you need to use for all UI mods." )
.Register( "Special Collections",
"Special Collections are those that are used only for special characters in the game, either by specific conditions, or by name.\n\n"
+ "We will skip this for now, but hovering over the creation buttons should explain how they work." )
.Register( "Initial Setup, Step 8: Mods", "Our last stop is the Mods tab, where you can import and setup your mods." )
.Register( "Initial Setup, Step 9: Mod Import",
"Click this button to open a file selector with which to select TTMP mod files. You can select multiple at once.\n\n"
+ "It is not recommended to import huge mod packs of all your TexTools mods, but rather import the mods themselves, otherwise you lose out on a lot of Penumbra features!\n\n"
+ "A feature to import raw texture mods for Tattoos etc. is available under Advanced Editing, but is currently a work in progress." ) // TODO
.Register( "Advanced Help", "Click this button to get detailed information on what you can do in the mod selector.\n\n"
+ "Import and select a mod now to continue." )
.Register( "Initial Setup, Step 11: Enabling Mods",
"Enable a mod here. Disabled mods will not apply to anything in the current collection (which can be seen and changed in the top-right corner).\n\n"
+ "Mods can be enabled or disabled in a collection, or they can be unconfigured, in which case they will use Inheritance." )
.Register( "Initial Setup, Step 12: Priority", "If two enabled mods in one collection change the same files, there is a conflict.\n\n"
+ "Conflicts can be solved by setting a priority. The mod with the higher number will be used for all the conflicting files.\n\n"
+ "Conflicts are not a problem, as long as they are correctly resolved with priorities. Negative priorities are possible." )
.Register( "Mod Options", "Many mods have options themselves. You can also choose those here.\n\n"
+ "Pulldown-options are mutually exclusive, whereas checkmark options can all be enabled separately." )
.Register( "Initial Setup - Fin", "Now you should have all information to get Penumbra running and working!\n\n"
+ "If there are further questions or you need more help for the advanced features, take a look at the guide linked in the settings page." )
.Register( "FAQ 1", "Penumbra can not easily change which items a mod applies to." )
.Register( "FAQ 2",
"It is advised to not use TexTools and Penumbra at the same time. Penumbra may refuse to work if TexTools broke your game indices." )
.Register( "FAQ 3", "Penumbra can change the skin material a mod uses. This is under advanced editing." );
}

View file

@ -47,6 +47,7 @@ public sealed partial class ConfigWindow : Window, IDisposable
MinimumSize = new Vector2( 800, 600 ), MinimumSize = new Vector2( 800, 600 ),
MaximumSize = new Vector2( 4096, 2160 ), MaximumSize = new Vector2( 4096, 2160 ),
}; };
UpdateTutorialStep();
} }
public override void Draw() public override void Draw()
@ -78,6 +79,10 @@ public sealed partial class ConfigWindow : Window, IDisposable
} }
else else
{ {
OpenTutorial( 18 );
OpenTutorial( 19 );
OpenTutorial( 20 );
OpenTutorial( 21 );
using var bar = ImRaii.TabBar( string.Empty, ImGuiTabBarFlags.NoTooltip ); using var bar = ImRaii.TabBar( string.Empty, ImGuiTabBarFlags.NoTooltip );
SetupSizes(); SetupSizes();
_settingsTab.Draw(); _settingsTab.Draw();