From 769f54e8dd37a06afcf172cf1babe9a24271b490 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Mon, 11 Jul 2022 17:27:22 +0200 Subject: [PATCH] Add Tutorials. --- OtterGui | 2 +- Penumbra/Configuration.cs | 2 + Penumbra/UI/Classes/Colors.cs | 2 + Penumbra/UI/Classes/ModFileSystemSelector.cs | 7 +- ...ConfigWindow.CollectionsTab.Inheritance.cs | 3 +- Penumbra/UI/ConfigWindow.CollectionsTab.cs | 86 ++++++++++++------- Penumbra/UI/ConfigWindow.ModPanel.Settings.cs | 6 +- Penumbra/UI/ConfigWindow.ModsTab.cs | 1 + .../UI/ConfigWindow.SettingsTab.General.cs | 4 +- Penumbra/UI/ConfigWindow.SettingsTab.cs | 45 ++++++++-- Penumbra/UI/ConfigWindow.Tutorial.cs | 80 +++++++++++++++++ Penumbra/UI/ConfigWindow.cs | 5 ++ 12 files changed, 197 insertions(+), 46 deletions(-) create mode 100644 Penumbra/UI/ConfigWindow.Tutorial.cs diff --git a/OtterGui b/OtterGui index fcc5031f..70d9f814 160000 --- a/OtterGui +++ b/OtterGui @@ -1 +1 @@ -Subproject commit fcc5031fcf14b54f090d5bb789c580567b3f0023 +Subproject commit 70d9f81436c82cc51734f0661d10f461da4f1840 diff --git a/Penumbra/Configuration.cs b/Penumbra/Configuration.cs index 6294f42b..b025403f 100644 --- a/Penumbra/Configuration.cs +++ b/Penumbra/Configuration.cs @@ -41,6 +41,8 @@ public partial class Configuration : IPluginConfiguration public bool DebugMode { get; set; } = false; #endif + public int TutorialStep { get; set; } = 0; + public bool EnableFullResourceLogging { get; set; } = false; public bool EnableResourceLogging { get; set; } = false; public string ResourceLoggingFilter { get; set; } = string.Empty; diff --git a/Penumbra/UI/Classes/Colors.cs b/Penumbra/UI/Classes/Colors.cs index 567bd542..a41dc28b 100644 --- a/Penumbra/UI/Classes/Colors.cs +++ b/Penumbra/UI/Classes/Colors.cs @@ -28,6 +28,8 @@ public static class Colors public const uint RedTableBgTint = 0x40000080; public const uint DiscordColor = 0xFFDA8972; 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 ) => color switch diff --git a/Penumbra/UI/Classes/ModFileSystemSelector.cs b/Penumbra/UI/Classes/ModFileSystemSelector.cs index 888a385e..4f6c722d 100644 --- a/Penumbra/UI/Classes/ModFileSystemSelector.cs +++ b/Penumbra/UI/Classes/ModFileSystemSelector.cs @@ -199,8 +199,10 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod private void AddImportModButton( Vector2 size ) { - if( !ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.FileImport.ToIconString(), size, - "Import one or multiple mods from Tex Tools Mod Pack Files.", !Penumbra.ModManager.Valid, true ) ) + var button = ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.FileImport.ToIconString(), size, + "Import one or multiple mods from Tex Tools Mod Pack Files.", !Penumbra.ModManager.Valid, true ); + ConfigWindow.OpenTutorial( 13 ); + if (!button) { return; } @@ -310,6 +312,7 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod { ImGui.OpenPopup( "ExtendedHelp" ); } + ConfigWindow.OpenTutorial( 14 ); } // Helpers. diff --git a/Penumbra/UI/ConfigWindow.CollectionsTab.Inheritance.cs b/Penumbra/UI/ConfigWindow.CollectionsTab.Inheritance.cs index 0ce6eaf7..92f50d7e 100644 --- a/Penumbra/UI/ConfigWindow.CollectionsTab.Inheritance.cs +++ b/Penumbra/UI/ConfigWindow.CollectionsTab.Inheritance.cs @@ -31,7 +31,8 @@ public partial class ConfigWindow // Draw the whole inheritance block. 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:" ); DrawCurrentCollectionInheritance(); DrawInheritanceTrashButton(); diff --git a/Penumbra/UI/ConfigWindow.CollectionsTab.cs b/Penumbra/UI/ConfigWindow.CollectionsTab.cs index 02e2c578..14b8f838 100644 --- a/Penumbra/UI/ConfigWindow.CollectionsTab.cs +++ b/Penumbra/UI/ConfigWindow.CollectionsTab.cs @@ -23,13 +23,18 @@ public partial class ConfigWindow public void Draw() { using var tab = ImRaii.TabItem( "Collections" ); + OpenTutorial( 5 ); if( !tab ) { return; } - DrawCharacterCollectionSelectors(); - DrawMainSelectors(); + using var child = ImRaii.Child( "##collections", -Vector2.One ); + if( child ) + { + DrawActiveCollectionSelectors(); + DrawMainSelectors(); + } } @@ -106,6 +111,7 @@ public partial class ConfigWindow private void DrawCurrentCollectionSelector() { + using var group = ImRaii.Group(); DrawCollectionSelector( "##current", _window._inputTextWidth.X, CollectionType.Current, false, null ); ImGui.SameLine(); ImGuiUtil.LabeledHelpMarker( "Current Collection", @@ -114,6 +120,7 @@ public partial class ConfigWindow private void DrawDefaultCollectionSelector() { + using var group = ImRaii.Group(); DrawCollectionSelector( "##default", _window._inputTextWidth.X, CollectionType.Default, true, null ); ImGui.SameLine(); ImGuiUtil.LabeledHelpMarker( "Default Collection", @@ -183,34 +190,42 @@ public partial class ConfigWindow } } - private void DrawCharacterCollectionSelectors() + private void DrawActiveCollectionSelectors() { 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 ); - DrawDefaultCollectionSelector(); - ImGui.Dummy( _window._defaultSpace ); - foreach( var type in CollectionTypeExtensions.Special ) + return; + } + + 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 ); - if( collection != null ) + using var id = ImRaii.PushId( ( int )type ); + 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 ); - 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() ); + Penumbra.CollectionManager.RemoveSpecialCollection( type ); } - } + ImGui.SameLine(); + ImGui.AlignTextToFramePadding(); + ImGuiUtil.LabeledHelpMarker( type.ToName(), type.ToDescription() ); + } + } + + using( var group = ImRaii.Group() ) + { DrawNewSpecialCollection(); ImGui.Dummy( _window._defaultSpace ); @@ -231,22 +246,31 @@ public partial class ConfigWindow } DrawNewCharacterCollection(); - ImGui.Dummy( _window._defaultSpace ); } + + OpenTutorial( 11 ); + + ImGui.Dummy( _window._defaultSpace ); } private void DrawMainSelectors() { 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 ); - DrawCurrentCollectionSelector(); - ImGui.Dummy( _window._defaultSpace ); - DrawNewCollectionInput(); - ImGui.Dummy( _window._defaultSpace ); - DrawInheritanceBlock(); + return; } + + ImGui.Dummy( _window._defaultSpace ); + DrawCurrentCollectionSelector(); + OpenTutorial( 7 ); + ImGui.Dummy( _window._defaultSpace ); + DrawNewCollectionInput(); + ImGui.Dummy( _window._defaultSpace ); + DrawInheritanceBlock(); + OpenTutorial( 8 ); } } } \ No newline at end of file diff --git a/Penumbra/UI/ConfigWindow.ModPanel.Settings.cs b/Penumbra/UI/ConfigWindow.ModPanel.Settings.cs index 96e25e98..2689f3bd 100644 --- a/Penumbra/UI/ConfigWindow.ModPanel.Settings.cs +++ b/Penumbra/UI/ConfigWindow.ModPanel.Settings.cs @@ -36,6 +36,7 @@ public partial class ConfigWindow private void DrawSettingsTab() { using var tab = DrawTab( SettingsTabHeader, Tabs.Settings ); + OpenTutorial( 17 ); if( !tab ) { return; @@ -51,8 +52,10 @@ public partial class ConfigWindow ImGui.Dummy( _window._defaultSpace ); _window._penumbra.Api.InvokePreSettingsPanel( _mod.ModPath.Name ); DrawEnabledInput(); + OpenTutorial( 15 ); ImGui.SameLine(); DrawPriorityInput(); + OpenTutorial( 16 ); DrawRemoveSettings(); ImGui.Dummy( _window._defaultSpace ); 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. private void DrawPriorityInput() { - var priority = _currentPriority ?? _settings.Priority; + using var group = ImRaii.Group(); + var priority = _currentPriority ?? _settings.Priority; ImGui.SetNextItemWidth( 50 * ImGuiHelpers.GlobalScale ); if( ImGui.InputInt( "##Priority", ref priority, 0, 0 ) ) { diff --git a/Penumbra/UI/ConfigWindow.ModsTab.cs b/Penumbra/UI/ConfigWindow.ModsTab.cs index e5f3b5c3..8bd9e34c 100644 --- a/Penumbra/UI/ConfigWindow.ModsTab.cs +++ b/Penumbra/UI/ConfigWindow.ModsTab.cs @@ -22,6 +22,7 @@ public partial class ConfigWindow try { using var tab = ImRaii.TabItem( "Mods" ); + OpenTutorial( 12 ); if( !tab ) { return; diff --git a/Penumbra/UI/ConfigWindow.SettingsTab.General.cs b/Penumbra/UI/ConfigWindow.SettingsTab.General.cs index 37d2722d..224828c4 100644 --- a/Penumbra/UI/ConfigWindow.SettingsTab.General.cs +++ b/Penumbra/UI/ConfigWindow.SettingsTab.General.cs @@ -6,7 +6,6 @@ using ImGuiNET; using OtterGui; using OtterGui.Raii; using OtterGui.Widgets; -using Penumbra.Util; namespace Penumbra.UI; @@ -32,9 +31,12 @@ public partial class ConfigWindow { if( !ImGui.CollapsingHeader( "General" ) ) { + OpenTutorial( 4 ); return; } + OpenTutorial( 4 ); + 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, v => diff --git a/Penumbra/UI/ConfigWindow.SettingsTab.cs b/Penumbra/UI/ConfigWindow.SettingsTab.cs index 58cb4c28..2c2356ea 100644 --- a/Penumbra/UI/ConfigWindow.SettingsTab.cs +++ b/Penumbra/UI/ConfigWindow.SettingsTab.cs @@ -4,7 +4,9 @@ using System.IO; using System.Linq; using System.Numerics; using Dalamud.Interface; +using Dalamud.Interface.Components; using Dalamud.Interface.ImGuiFileDialog; +using Dalamud.Utility; using ImGuiNET; using OtterGui; using OtterGui.Raii; @@ -131,7 +133,10 @@ public partial class ConfigWindow // as well as the directory picker button and the enter warning. private void DrawRootFolder() { - _newModDirectory ??= Penumbra.Config.ModDirectory; + if( _newModDirectory.IsNullOrEmpty() ) + { + _newModDirectory = Penumbra.Config.ModDirectory; + } var spacing = 3 * ImGuiHelpers.GlobalScale; 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" + "Definitely do not place it in your Dalamud directory or any sub-directory thereof." ); group.Dispose(); + OpenTutorial( 1 ); ImGui.SameLine(); var pos = ImGui.GetCursorPosX(); ImGui.NewLine(); @@ -181,20 +187,34 @@ public partial class ConfigWindow { _window._penumbra.SetEnabled( enabled ); } + + OpenTutorial( 2 ); } private static void DrawShowAdvancedBox() { var showAdvanced = Penumbra.Config.ShowAdvanced; - if( ImGui.Checkbox( "##showAdvanced", ref showAdvanced ) ) + using( var _ = ImRaii.Group() ) { - Penumbra.Config.ShowAdvanced = showAdvanced; - Penumbra.Config.Save(); + if( ImGui.Checkbox( "##showAdvanced", ref showAdvanced ) ) + { + 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(); - 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." ); + OpenTutorial( 3 ); } private static void DrawColorSettings() @@ -281,12 +301,12 @@ public partial class ConfigWindow private static void DrawSupportButtons() { var width = ImGui.CalcTextSize( SupportInfoButtonText ).X + ImGui.GetStyle().FramePadding.X * 2; + var xPos = ImGui.GetWindowWidth() - width; 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() ) ); DrawSupportButton(); @@ -295,6 +315,13 @@ public partial class ConfigWindow ImGui.SetCursorPos( new Vector2( xPos, 2 * ImGui.GetFrameHeightWithSpacing() ) ); 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(); + } } } } \ No newline at end of file diff --git a/Penumbra/UI/ConfigWindow.Tutorial.cs b/Penumbra/UI/ConfigWindow.Tutorial.cs new file mode 100644 index 00000000..9e879c51 --- /dev/null +++ b/Penumbra/UI/ConfigWindow.Tutorial.cs @@ -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." ); +} \ No newline at end of file diff --git a/Penumbra/UI/ConfigWindow.cs b/Penumbra/UI/ConfigWindow.cs index 8025cf3c..124c0350 100644 --- a/Penumbra/UI/ConfigWindow.cs +++ b/Penumbra/UI/ConfigWindow.cs @@ -47,6 +47,7 @@ public sealed partial class ConfigWindow : Window, IDisposable MinimumSize = new Vector2( 800, 600 ), MaximumSize = new Vector2( 4096, 2160 ), }; + UpdateTutorialStep(); } public override void Draw() @@ -78,6 +79,10 @@ public sealed partial class ConfigWindow : Window, IDisposable } else { + OpenTutorial( 18 ); + OpenTutorial( 19 ); + OpenTutorial( 20 ); + OpenTutorial( 21 ); using var bar = ImRaii.TabBar( string.Empty, ImGuiTabBarFlags.NoTooltip ); SetupSizes(); _settingsTab.Draw();