diff --git a/RotationSolver/ActionSequencer/MajorConditionSet.cs b/RotationSolver/ActionSequencer/MajorConditionSet.cs index 4a3316a8e..f15838611 100644 --- a/RotationSolver/ActionSequencer/MajorConditionSet.cs +++ b/RotationSolver/ActionSequencer/MajorConditionSet.cs @@ -9,7 +9,7 @@ internal class MajorConditionSet /// public Dictionary Conditions { get; } = new Dictionary(); - public Dictionary DiableConditions { get; } = new Dictionary(); + public Dictionary DiabledConditions { get; } = new Dictionary(); public string Name; diff --git a/RotationSolver/Localization/Strings.cs b/RotationSolver/Localization/Strings.cs index ce7ce41a2..f3b03d617 100644 --- a/RotationSolver/Localization/Strings.cs +++ b/RotationSolver/Localization/Strings.cs @@ -80,7 +80,6 @@ internal partial class Strings public string ConfigWindow_Helper_OpenSource { get; set; } = "Open the source code URL"; public string ConfigWindow_Helper_RunCommand { get; set; } = "Click to execute the command"; public string ConfigWindow_Helper_CopyCommand { get; set; } = "Right-click to copy the command"; - public string ConfigWindow_Helper_InsertCommand { get; set; } = "Insert \"{0}\" first in {1}s"; public string ConfigWindow_Rotation_Description_Old { get; set; } = "You can enable the function for each job you want and configure the setting about how to use actions."; public string ConfigWindow_Rotation_KeyName { get; set; } = "The key name is"; @@ -263,8 +262,6 @@ internal partial class Strings public string ConfigWindow_Param_ResetToDefaultWait { get; set; } = "Please wait for a second."; public string ConfigWindow_Param_ResetToDefaultSure { get; set; } = "Are you sure to reset this value?"; - public string ConfigWindow_Action_ShowOnCDWindow { get; set; } = "Show on CD window"; - public string ConfigWindow_Control_OnlyShowWithHostileOrInDuty { get; set; } = "Only shown if there are enemies in or in duty"; public string ConfigWindow_Control_ShowNextActionWindow { get; set; } = "Show Next Action Window"; @@ -327,10 +324,7 @@ internal partial class Strings public string ActionSequencer_MustUseDesc { get; set; } = "Skip AOE and Buff."; public string ActionSequencer_Empty { get; set; } = "UseUp"; public string ActionSequencer_EmptyDesc { get; set; } = "UseUp or Skip Combo"; - public string ActionSequencer_ActionSequencerDescription { get; set; } = "To customize when Rotation Solver uses specific actions automatically, click on an action's icon in the left list. Below, you may set the conditions for when that specific action is used. Each action can have a different set of conditions to override the default rotation behavior."; - public string ActionSequencer_ForceConditionSet { get; set; } = "Conditions When Automatic Use of Action is Forced"; - public string ActionSequencer_DisableConditionSet { get; set; } = "Conditions When Automatic Use of Action is Disabled"; public string ActionSequencer_Can { get; set; } = "Can"; public string ActionSequencer_Cannot { get; set; } = "Cannot"; public string ActionSequencer_Is { get; set; } = "Is"; @@ -639,4 +633,17 @@ internal partial class Strings public string ConfigWindow_Rotation_Description { get; set; } = "Description"; public string ConfigWindow_Rotation_Configuration { get; set; } = "Configuration"; public string ConfigWindow_Rotation_Information { get; set; } = "Information"; + + public string ConfigWindow_Actions_Description { get; set; } = "To customize when Rotation Solver uses specific actions automatically, click on an action's icon in the left list. Below, you may set the conditions for when that specific action is used. Each action can have a different set of conditions to override the default rotation behavior."; + + public string ConfigWindow_Actions_ForcedConditionSet { get; set; } = "Forced Condition"; + public string ConfigWindow_Actions_ForcedConditionSet_Description { get; set; } = "Conditions when automatic use of action is forced."; + public string ConfigWindow_Actions_DisabledConditionSet { get; set; } = "Disabled Condition"; + public string ConfigWindow_Actions_DisabledConditionSet_Description { get; set; } = "Conditions when automatic use of action is disabled."; + public string ConfigWindow_Actions_Enable { get; set; } = "Enable"; + + public string ConfigWindow_Actions_ShowOnCDWindow { get; set; } = "Show on CD window"; + + public string ConfigWindow_Actions_InsertCommand { get; set; } = "Insert \"{0}\" first in {1}s"; + } diff --git a/RotationSolver/UI/ImGuiHelper.cs b/RotationSolver/UI/ImGuiHelper.cs index eabf8e935..3f1c7bce1 100644 --- a/RotationSolver/UI/ImGuiHelper.cs +++ b/RotationSolver/UI/ImGuiHelper.cs @@ -631,7 +631,7 @@ private unsafe static void Display(this IBaseAction action, bool IsActive) => ac },otherThing: () => { var enable = action.IsInCooldown; - if (ImGui.Checkbox($"{LocalizationManager.RightLang.ConfigWindow_Action_ShowOnCDWindow}##{action.Name}InCooldown", ref enable)) + if (ImGui.Checkbox($"{LocalizationManager.RightLang.ConfigWindow_Actions_ShowOnCDWindow}##{action.Name}InCooldown", ref enable)) { action.IsInCooldown = enable; Service.Config.Save(); @@ -641,7 +641,7 @@ private unsafe static void Display(this IBaseAction action, bool IsActive) => ac Spacing(); OtherCommandType.DoActions.DisplayCommandHelp($"{action}-{5}", - type => string.Format(LocalizationManager.RightLang.ConfigWindow_Helper_InsertCommand, action, 5), false); + type => string.Format(LocalizationManager.RightLang.ConfigWindow_Actions_InsertCommand, action, 5), false); if (Service.Config.InDebug) { @@ -686,7 +686,7 @@ public unsafe static void Display(this IBaseItem item, bool IsActive) if (Service.Config.ShowCooldownWindow) { var enable = item.IsInCooldown; - if (ImGui.Checkbox($"{LocalizationManager.RightLang.ConfigWindow_Action_ShowOnCDWindow}##{item.Name}InCooldown", ref enable)) + if (ImGui.Checkbox($"{LocalizationManager.RightLang.ConfigWindow_Actions_ShowOnCDWindow}##{item.Name}InCooldown", ref enable)) { item.IsInCooldown = enable; Service.Config.Save(); @@ -697,7 +697,7 @@ public unsafe static void Display(this IBaseItem item, bool IsActive) } OtherCommandType.DoActions.DisplayCommandHelp($"{item}-{5}", - type => string.Format(LocalizationManager.RightLang.ConfigWindow_Helper_InsertCommand, item, 5), false); + type => string.Format(LocalizationManager.RightLang.ConfigWindow_Actions_InsertCommand, item, 5), false); if (Service.Config.InDebug) diff --git a/RotationSolver/UI/RotationConfigWindowNew.cs b/RotationSolver/UI/RotationConfigWindowNew.cs index 02c95b782..3995957cb 100644 --- a/RotationSolver/UI/RotationConfigWindowNew.cs +++ b/RotationSolver/UI/RotationConfigWindowNew.cs @@ -5,10 +5,14 @@ using ECommons.GameHelpers; using ECommons.ImGuiMethods; using ImGuiScene; +using RotationSolver.ActionSequencer; using RotationSolver.Helpers; using RotationSolver.Localization; using RotationSolver.Updaters; using System.Diagnostics; +using System.Drawing; +using System.Windows.Forms; +using static FFXIVClientStructs.FFXIV.Client.UI.AddonAOZNotebook; namespace RotationSolver.UI; @@ -93,10 +97,12 @@ private void DrawSideBar() var size = Math.Max(_scale * MIN_COLUMN_WIDTH, Math.Min(wholeWidth, _scale * JOB_ICON_WIDTH)) * 0.6f; DrawItemMiddle(() => { + var cursor = ImGui.GetCursorPos(); if (SilenceImageButton(icon.ImGuiHandle, Vector2.One * size, _activeTab == item)) { _activeTab = item; } + DrawActionOverlay(cursor, size, _activeTab == item ? 1 : -1); }, Math.Max(_scale * MIN_COLUMN_WIDTH, wholeWidth), size); ImguiTooltips.HoveredTooltip(item.ToString()); } else @@ -284,6 +290,9 @@ private void DrawBody() ImGui.SetCursorPos(ImGui.GetCursorPos() + Vector2.One * margin); if (ImGui.BeginChild("Rotation Solver Body", Vector2.One * -margin)) { + //Search box + + switch (_activeTab) { case RotationConfigWindowTab.About: @@ -695,16 +704,132 @@ private static void DrawRotationInformation() } #endregion - private static readonly CollapsingHeaderGroup _actionsHeader = new(new() - { - - }); + #region Actions private static void DrawActions() { - ImGui.Text("Actions"); - _actionsHeader?.Draw(); + ImGui.TextWrapped(LocalizationManager.RightLang.ConfigWindow_Actions_Description); + + if (ImGui.BeginTable("Rotation Solver Actions", 2, ImGuiTableFlags.Borders + | ImGuiTableFlags.Resizable)) + { + ImGui.TableSetupColumn("Action Column", ImGuiTableColumnFlags.WidthFixed, ImGui.GetWindowWidth() / 2); + ImGui.TableNextColumn(); + + if (_actionsList != null && ImGui.BeginChild("Rotation Solver Action List")) + { + _actionsList.ClearCollapsingHeader(); + + if (RotationUpdater.RightNowRotation != null) + { + var size = 30 * _scale; + var count = (int)MathF.Floor(ImGui.GetWindowWidth() / size); + foreach (var pair in RotationUpdater.AllGroupedActions) + { + _actionsList.AddCollapsingHeader(() => pair.Key, () => + { + var index = 0; + foreach (var item in pair.OrderBy(t => t.ID)) + { + var icon = item.GetTexture(); + if (icon == null) continue; + + if (index++ % count != 0) + { + ImGui.SameLine(); + } + + var active = _activeAction == item; + var cursor = ImGui.GetCursorPos(); + if (SilenceImageButton(icon.ImGuiHandle, Vector2.One * size, active)) + { + _activeAction = item; + } + ImguiTooltips.ShowTooltip(item.Name); + DrawActionOverlay(cursor, size, active ? 1 : -1); + } + }); + } + } + + _actionsList.Draw(); + ImGui.EndChild(); + } + + ImGui.TableNextColumn(); + + if (_sequencerList != null && _activeAction != null && ImGui.BeginChild("Rotation Solver Sequencer List")) + { + var enable = _activeAction.IsEnabled; + if (ImGui.Checkbox($"{LocalizationManager.RightLang.ConfigWindow_Actions_Enable}##{_activeAction.Name}Enabled", ref enable)) + { + _activeAction.IsEnabled = enable; + } + + OtherCommandType.ToggleActions.DisplayCommandHelp(_activeAction.ToString()); + + enable = _activeAction.IsInCooldown; + if (ImGui.Checkbox($"{LocalizationManager.RightLang.ConfigWindow_Actions_ShowOnCDWindow}##{_activeAction.Name}InCooldown", ref enable)) + { + _activeAction.IsInCooldown = enable; + } + + OtherCommandType.DoActions.DisplayCommandHelp($"{_activeAction}-{5}", + type => string.Format(LocalizationManager.RightLang.ConfigWindow_Actions_InsertCommand, _activeAction, 5), false); + + _sequencerList.Draw(); + ImGui.EndChild(); + } + + ImGui.EndTable(); + } } + private static IAction _activeAction; + + private static readonly CollapsingHeaderGroup _actionsList = new() + { + HeaderSize = 18, + }; + + private static readonly CollapsingHeaderGroup _sequencerList = new(new() + { + { () => LocalizationManager.RightLang.ConfigWindow_Actions_ForcedConditionSet, () => + { + ImGui.TextWrapped(LocalizationManager.RightLang.ConfigWindow_Actions_ForcedConditionSet_Description); + + var rotation = RotationUpdater.RightNowRotation; + var set = ActionSequencerUpdater.RightSet; + if (set == null || _activeAction == null || rotation == null) return; + + if (!set.Conditions.TryGetValue(_activeAction.ID, out var conditionSet)) + { + conditionSet = set.Conditions[_activeAction.ID] = new ConditionSet(); + } + conditionSet?.Draw(rotation); + } }, + + { () => LocalizationManager.RightLang.ConfigWindow_Actions_DisabledConditionSet, () => + { + ImGui.TextWrapped(LocalizationManager.RightLang.ConfigWindow_Actions_DisabledConditionSet_Description); + + var rotation = RotationUpdater.RightNowRotation; + var set = ActionSequencerUpdater.RightSet; + if (set == null || _activeAction == null || rotation == null) return; + + if (!set.DiabledConditions.TryGetValue(_activeAction.ID, out var disableConditionSet)) + { + disableConditionSet = set.DiabledConditions[_activeAction.ID] = new ConditionSet(); + } + disableConditionSet?.Draw(rotation); + } }, + }) + { + HeaderSize = 18, + }; + + + #endregion + private static readonly CollapsingHeaderGroup _rotationsHeader = new(new() { @@ -837,5 +962,84 @@ private static bool TextureButton(TextureWrap texture, float wholeWidth, float m }, wholeWidth, size.X); return result; } + + private static void DrawActionOverlay(Vector2 cursor, float width, float percent) + { + var pixPerUnit = width / 82; + + if (percent < 0) + { + var cover = IconSet.GetTexture("ui/uld/icona_frame_hr1.tex"); + + if (cover != null) + { + ImGui.SetCursorPos(cursor - new Vector2(pixPerUnit * 3, pixPerUnit * 4)); + + var step = new Vector2(88f / cover.Width, 96f / cover.Height); + var start = new Vector2((96f * 0 + 4f) / cover.Width, (96f * 2) / cover.Height); + + //Out Size is 88, 96 + //Inner Size is 82, 82 + ImGui.Image(cover.ImGuiHandle, new Vector2(pixPerUnit * 88, pixPerUnit * 96), + start, start + step); + } + } + else if (percent < 1) + { + var cover = IconSet.GetTexture("ui/uld/icona_recast_hr1.tex"); + + if (cover != null) + { + ImGui.SetCursorPos(cursor - new Vector2(pixPerUnit * 3, pixPerUnit * 0)); + + var P = (int)(percent * 81); + + + var step = new Vector2(88f / cover.Width, 96f / cover.Height); + var start = new Vector2(P % 9 * step.X, P / 9 * step.Y); + + //Out Size is 88, 96 + //Inner Size is 82, 82 + ImGui.Image(cover.ImGuiHandle, new Vector2(pixPerUnit * 88, pixPerUnit * 96), + start, start + step); + } + } + else + { + var cover = IconSet.GetTexture("ui/uld/icona_frame_hr1.tex"); + + if (cover != null) + { + + ImGui.SetCursorPos(cursor - new Vector2(pixPerUnit * 3, pixPerUnit * 4)); + + //Out Size is 88, 96 + //Inner Size is 82, 82 + ImGui.Image(cover.ImGuiHandle, new Vector2(pixPerUnit * 88, pixPerUnit * 96), + new Vector2(4f / cover.Width, 0f / cover.Height), + new Vector2(92f / cover.Width, 96f / cover.Height)); + } + } + + if (percent > 1) + { + var cover = IconSet.GetTexture("ui/uld/icona_recast2_hr1.tex"); + + if (cover != null) + { + ImGui.SetCursorPos(cursor - new Vector2(pixPerUnit * 3, pixPerUnit * 0)); + + var P = (int)(percent % 1 * 81); + + var step = new Vector2(88f / cover.Width, 96f / cover.Height); + var start = new Vector2((P % 9 + 9) * step.X, P / 9 * step.Y); + + //Out Size is 88, 96 + //Inner Size is 82, 82 + ImGui.Image(cover.ImGuiHandle, new Vector2(pixPerUnit * 88, pixPerUnit * 96), + start, start + step); + } + } + } #endregion } diff --git a/RotationSolver/UI/RotationConfigWindow_Action.cs b/RotationSolver/UI/RotationConfigWindow_Action.cs index e51d048f0..d7e959643 100644 --- a/RotationSolver/UI/RotationConfigWindow_Action.cs +++ b/RotationSolver/UI/RotationConfigWindow_Action.cs @@ -49,7 +49,7 @@ private static void DrawActionList() private static void DrawActionSequencerCondition() { - ImGui.TextWrapped(LocalizationManager.RightLang.ActionSequencer_ActionSequencerDescription); + ImGui.TextWrapped(LocalizationManager.RightLang.ConfigWindow_Actions_Description); var rotation = RotationUpdater.RightNowRotation; if (rotation == null) return; @@ -65,7 +65,7 @@ private static void DrawActionSequencerCondition() ImGui.SameLine(); ImGui.TextColored(ImGuiColors.DalamudYellow, ActiveAction.Name); - if (ImGui.CollapsingHeader(LocalizationManager.RightLang.ActionSequencer_ForceConditionSet)) + if (ImGui.CollapsingHeader(LocalizationManager.RightLang.ConfigWindow_Actions_ForcedConditionSet)) { if (!set.Conditions.TryGetValue(ActiveAction.ID, out var conditionSet)) { @@ -74,11 +74,11 @@ private static void DrawActionSequencerCondition() conditionSet?.Draw(rotation); } - if (ImGui.CollapsingHeader(LocalizationManager.RightLang.ActionSequencer_DisableConditionSet)) + if (ImGui.CollapsingHeader(LocalizationManager.RightLang.ConfigWindow_Actions_DisabledConditionSet)) { - if (!set.DiableConditions.TryGetValue(ActiveAction.ID, out var disableConditionSet)) + if (!set.DiabledConditions.TryGetValue(ActiveAction.ID, out var disableConditionSet)) { - disableConditionSet = set.DiableConditions[ActiveAction.ID] = new ConditionSet(); + disableConditionSet = set.DiabledConditions[ActiveAction.ID] = new ConditionSet(); } disableConditionSet?.Draw(rotation); } diff --git a/RotationSolver/Updaters/ActionSequencerUpdater.cs b/RotationSolver/Updaters/ActionSequencerUpdater.cs index 97c547d6f..f71816c80 100644 --- a/RotationSolver/Updaters/ActionSequencerUpdater.cs +++ b/RotationSolver/Updaters/ActionSequencerUpdater.cs @@ -25,7 +25,7 @@ public static void UpdateActionSequencerAction() var set = RightSet; if (set == null) return; - DataCenter.DisabledAction = new HashSet(set.DiableConditions.Where(pair => pair.Value.IsTrue(customRotation)) + DataCenter.DisabledAction = new HashSet(set.DiabledConditions.Where(pair => pair.Value.IsTrue(customRotation)) .Select(pair => pair.Key)); bool find = false;