Skip to content

Commit

Permalink
More accessible config.
Browse files Browse the repository at this point in the history
  • Loading branch information
awgil committed Mar 30, 2024
1 parent ff5dda9 commit 050b388
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 46 deletions.
34 changes: 34 additions & 0 deletions BossMod/BossModule/BossModuleConfigWindow.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Dalamud.Interface.Utility.Raii;

namespace BossMod;

public class BossModuleConfigWindow : UIWindow
{
private ModuleRegistry.Info _info;
private WorldState _ws;
private UITree _tree = new();

public BossModuleConfigWindow(ModuleRegistry.Info info, WorldState ws) : base($"{info.ModuleType.Name} config", true, new(1200, 800))
{
_info = info;
_ws = ws;
}

public override void Draw()
{
if (_info.ConfigType == null)
return; // nothing to do...

using var tabs = ImRaii.TabBar("Tabs");
if (tabs)
{
using (var tab = ImRaii.TabItem("Encounter-specific config"))
if (tab)
ConfigUI.DrawNode(Service.Config.Get<ConfigNode>(_info.ConfigType), Service.Config, _tree, _ws);
if (_ws.Party.Player() != null)
using (var tab = ImRaii.TabItem("Party roles assignment"))
if (tab)
ConfigUI.DrawNode(Service.Config.Get<PartyRolesConfig>(), Service.Config, _tree, _ws);
}
}
}
10 changes: 9 additions & 1 deletion BossMod/BossModule/BossModuleMainWindow.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using ImGuiNET;
using Dalamud.Interface;
using ImGuiNET;

namespace BossMod;

Expand All @@ -12,6 +13,7 @@ public class BossModuleMainWindow : UIWindow
{
_mgr = mgr;
RespectCloseHotkey = false;
TitleBarButtons.Add(new() { Icon = FontAwesomeIcon.Cog, IconOffset = new(1), Click = _ => OpenModuleConfig() });
}

public override void PreOpenCheck()
Expand Down Expand Up @@ -94,4 +96,10 @@ private void DrawMovementHints(BossComponent.MovementHints? arrows, float y)
Camera.Instance.DrawWorldLine(arrowStart - offset, end3, color);
}
}

private void OpenModuleConfig()
{
if (_mgr.ActiveModule?.Info?.ConfigType != null)
new BossModuleConfigWindow(_mgr.ActiveModule.Info, _mgr.WorldState);
}
}
61 changes: 32 additions & 29 deletions BossMod/Config/ConfigUI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,29 @@ public void Draw()
}
}

public static void DrawNode(ConfigNode node, ConfigRoot root, UITree tree, WorldState ws)
{
// draw standard properties
foreach (var field in node.GetType().GetFields())
{
var props = field.GetCustomAttribute<PropertyDisplayAttribute>();
if (props == null)
continue;

_ = field.GetValue(node) switch
{
bool v => DrawProperty(props, node, field, v),
Enum v => DrawProperty(props, node, field, v),
float v => DrawProperty(props, node, field, v),
GroupAssignment v => DrawProperty(props, node, field, v, root, tree, ws),
_ => false
};
}

// draw custom stuff
node.DrawCustom(tree, ws);
}

private static string GenerateNodeName(Type t) => t.Name.EndsWith("Config") ? t.Name.Remove(t.Name.Length - "Config".Length) : t.Name;

private void SortByOrder(List<UINode> nodes)
Expand All @@ -86,32 +109,12 @@ private void DrawNodes(List<UINode> nodes)
{
foreach (var n in _tree.Nodes(nodes, n => new(n.Name)))
{
// draw standard properties
foreach (var field in n.Node.GetType().GetFields())
{
var props = field.GetCustomAttribute<PropertyDisplayAttribute>();
if (props == null)
continue;

_ = field.GetValue(n.Node) switch
{
bool v => DrawProperty(props, n.Node, field, v),
Enum v => DrawProperty(props, n.Node, field, v),
float v => DrawProperty(props, n.Node, field, v),
GroupAssignment v => DrawProperty(props, n.Node, field, v),
_ => false
};
}

// draw custom stuff
n.Node.DrawCustom(_tree, _ws);

// draw subnodes
DrawNode(n.Node, _root, _tree, _ws);
DrawNodes(n.Children);
}
}

private bool DrawProperty(PropertyDisplayAttribute props, ConfigNode node, FieldInfo member, bool v)
private static bool DrawProperty(PropertyDisplayAttribute props, ConfigNode node, FieldInfo member, bool v)
{
var combo = member.GetCustomAttribute<PropertyComboAttribute>();
if (combo != null)
Expand All @@ -133,7 +136,7 @@ private bool DrawProperty(PropertyDisplayAttribute props, ConfigNode node, Field
return true;
}

private bool DrawProperty(PropertyDisplayAttribute props, ConfigNode node, FieldInfo member, Enum v)
private static bool DrawProperty(PropertyDisplayAttribute props, ConfigNode node, FieldInfo member, Enum v)
{
if (UICombo.Enum(props.Label, ref v))
{
Expand All @@ -143,7 +146,7 @@ private bool DrawProperty(PropertyDisplayAttribute props, ConfigNode node, Field
return true;
}

private bool DrawProperty(PropertyDisplayAttribute props, ConfigNode node, FieldInfo member, float v)
private static bool DrawProperty(PropertyDisplayAttribute props, ConfigNode node, FieldInfo member, float v)
{
var slider = member.GetCustomAttribute<PropertySliderAttribute>();
if (slider != null)
Expand All @@ -168,15 +171,15 @@ private bool DrawProperty(PropertyDisplayAttribute props, ConfigNode node, Field
return true;
}

private bool DrawProperty(PropertyDisplayAttribute props, ConfigNode node, FieldInfo member, GroupAssignment v)
private static bool DrawProperty(PropertyDisplayAttribute props, ConfigNode node, FieldInfo member, GroupAssignment v, ConfigRoot root, UITree tree, WorldState ws)
{
var group = member.GetCustomAttribute<GroupDetailsAttribute>();
if (group == null)
return false;

foreach (var tn in _tree.Node(props.Label, false, v.Validate() ? 0xffffffff : 0xff00ffff, () => DrawPropertyContextMenu(node, member, v)))
foreach (var tn in tree.Node(props.Label, false, v.Validate() ? 0xffffffff : 0xff00ffff, () => DrawPropertyContextMenu(node, member, v)))
{
var assignments = _root.Get<PartyRolesConfig>().SlotsPerAssignment(_ws.Party);
var assignments = root.Get<PartyRolesConfig>().SlotsPerAssignment(ws.Party);
if (ImGui.BeginTable("table", group.Names.Length + 2, ImGuiTableFlags.SizingFixedFit))
{
foreach (var n in group.Names)
Expand Down Expand Up @@ -206,7 +209,7 @@ private bool DrawProperty(PropertyDisplayAttribute props, ConfigNode node, Field

string name = r.ToString();
if (assignments.Length > 0)
name += $" ({_ws.Party[assignments[i]]?.Name})";
name += $" ({ws.Party[assignments[i]]?.Name})";
ImGui.TableNextColumn();
ImGui.TextUnformatted(name);
}
Expand All @@ -216,7 +219,7 @@ private bool DrawProperty(PropertyDisplayAttribute props, ConfigNode node, Field
return true;
}

private void DrawPropertyContextMenu(ConfigNode node, FieldInfo member, GroupAssignment v)
private static void DrawPropertyContextMenu(ConfigNode node, FieldInfo member, GroupAssignment v)
{
foreach (var preset in member.GetCustomAttributes<GroupPresetAttribute>())
{
Expand Down
37 changes: 23 additions & 14 deletions BossMod/Config/ModuleViewer.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Dalamud.Interface.Internal;
using Dalamud.Interface;
using Dalamud.Interface.Internal;
using Dalamud.Interface.Utility.Raii;
using ImGuiNET;
using Lumina.Excel.GeneratedSheets;
Expand All @@ -10,7 +11,7 @@ namespace BossMod;

public class ModuleViewer : IDisposable
{
private record struct ModuleInfo(Type Type, string Name, int SortOrder);
private record struct ModuleInfo(ModuleRegistry.Info Info, string Name, int SortOrder);
private record struct ModuleGroupInfo(string Name, uint Id, uint SortOrder, IDalamudTextureWrap? Icon = null);
private record struct ModuleGroup(ModuleGroupInfo Info, List<ModuleInfo> Modules);

Expand Down Expand Up @@ -98,7 +99,7 @@ public ModuleViewer()
g.Modules.SortBy(m => m.SortOrder);
foreach (var (m1, m2) in g.Modules.Pairwise())
if (m1.SortOrder == m2.SortOrder)
Service.Log($"[ModuleViewer] Same sort order between modules {m1.Type.FullName} and {m2.Type.FullName}");
Service.Log($"[ModuleViewer] Same sort order between modules {m1.Info.ModuleType.FullName} and {m2.Info.ModuleType.FullName}");
}
}
}
Expand Down Expand Up @@ -204,8 +205,16 @@ private void DrawModules(UITree _tree)
ImGui.TableNextColumn();

foreach (var _ in _tree.Node($"{group.Info.Name}###{i}/{j}/{group.Info.Id}"))
{
foreach (var mod in group.Modules)
ImGui.TextUnformatted($"{mod.Name} [{mod.Type.Name}]");
{
using (ImRaii.Disabled(mod.Info.ConfigType == null))
if (UIMisc.IconButton(FontAwesomeIcon.Cog, "cfg", $"###{mod.Info.ModuleType.FullName}"))
new BossModuleConfigWindow(mod.Info, new(TimeSpan.TicksPerSecond, "fake"));
ImGui.SameLine();
ImGui.TextUnformatted($"{mod.Name} [{mod.Info.ModuleType.Name}]");
}
}
}
}
}
Expand Down Expand Up @@ -238,38 +247,38 @@ private void Customize((string name, IDalamudTextureWrap? icon)[] array, int ele
var cfcRow = Service.LuminaRow<ContentFinderCondition>(module.GroupID);
var cfcSort = cfcRow?.SortKey ?? 0u;
var cfcName = FixCase(cfcRow?.Name);
return (new(cfcName, groupId, cfcSort != 0 ? cfcSort : groupId), new(module.ModuleType, BNpcName(module.NameID), module.SortOrder));
return (new(cfcName, groupId, cfcSort != 0 ? cfcSort : groupId), new(module, BNpcName(module.NameID), module.SortOrder));
case BossModuleInfo.GroupType.MaskedCarnivale:
groupId |= module.GroupID;
var mcRow = Service.LuminaRow<ContentFinderCondition>(module.GroupID);
var mcSort = uint.Parse((mcRow?.ShortCode ?? "").Substring(3)); // 'aozNNN'
var mcName = $"Stage {mcSort}: {FixCase(mcRow?.Name)}";
return (new(mcName, groupId, mcSort), new(module.ModuleType, BNpcName(module.NameID), module.SortOrder));
return (new(mcName, groupId, mcSort), new(module, BNpcName(module.NameID), module.SortOrder));
case BossModuleInfo.GroupType.RemovedUnreal:
return (new("Removed Content", groupId, groupId), new(module.ModuleType, BNpcName(module.NameID), module.SortOrder));
return (new("Removed Content", groupId, groupId), new(module, BNpcName(module.NameID), module.SortOrder));
case BossModuleInfo.GroupType.Quest:
var questRow = Service.LuminaRow<Quest>(module.GroupID);
groupId |= questRow?.JournalGenre.Row ?? 0;
var questCategoryName = questRow?.JournalGenre.Value?.Name ?? "";
return (new(questCategoryName, groupId, groupId), new(module.ModuleType, $"{questRow?.Name}: {BNpcName(module.NameID)}", module.SortOrder));
return (new(questCategoryName, groupId, groupId), new(module, $"{questRow?.Name}: {BNpcName(module.NameID)}", module.SortOrder));
case BossModuleInfo.GroupType.Fate:
var fateRow = Service.LuminaRow<Fate>(module.GroupID);
return (new($"{module.Expansion.ShortName()} FATE", groupId, groupId, _iconFATE), new(module.ModuleType, $"{fateRow?.Name}: {BNpcName(module.NameID)}", module.SortOrder));
return (new($"{module.Expansion.ShortName()} FATE", groupId, groupId, _iconFATE), new(module, $"{fateRow?.Name}: {BNpcName(module.NameID)}", module.SortOrder));
case BossModuleInfo.GroupType.Hunt:
groupId |= module.GroupID;
return (new($"{module.Expansion.ShortName()} Hunt {(BossModuleInfo.HuntRank)module.GroupID}", groupId, groupId, _iconHunt), new(module.ModuleType, BNpcName(module.NameID), module.SortOrder));
return (new($"{module.Expansion.ShortName()} Hunt {(BossModuleInfo.HuntRank)module.GroupID}", groupId, groupId, _iconHunt), new(module, BNpcName(module.NameID), module.SortOrder));
case BossModuleInfo.GroupType.BozjaCE:
groupId |= module.GroupID;
var ceName = $"{FixCase(Service.LuminaRow<ContentFinderCondition>(module.GroupID)?.Name)} CE";
return (new(ceName, groupId, groupId), new(module.ModuleType, Service.LuminaRow<DynamicEvent>(module.NameID)?.Name ?? "", module.SortOrder));
return (new(ceName, groupId, groupId), new(module, Service.LuminaRow<DynamicEvent>(module.NameID)?.Name ?? "", module.SortOrder));
case BossModuleInfo.GroupType.BozjaDuel:
groupId |= module.GroupID;
var duelName = $"{FixCase(Service.LuminaRow<ContentFinderCondition>(module.GroupID)?.Name)} Duel";
return (new(duelName, groupId, groupId), new(module.ModuleType, Service.LuminaRow<DynamicEvent>(module.NameID)?.Name ?? "", module.SortOrder));
return (new(duelName, groupId, groupId), new(module, Service.LuminaRow<DynamicEvent>(module.NameID)?.Name ?? "", module.SortOrder));
case BossModuleInfo.GroupType.GoldSaucer:
return (new("Gold saucer", groupId, groupId), new(module.ModuleType, $"{Service.LuminaRow<GoldSaucerTextData>(module.GroupID)?.Text}: {BNpcName(module.NameID)}", module.SortOrder));
return (new("Gold saucer", groupId, groupId), new(module, $"{Service.LuminaRow<GoldSaucerTextData>(module.GroupID)?.Text}: {BNpcName(module.NameID)}", module.SortOrder));
default:
return (new("Ungrouped", groupId, groupId), new(module.ModuleType, BNpcName(module.NameID), module.SortOrder));
return (new("Ungrouped", groupId, groupId), new(module, BNpcName(module.NameID), module.SortOrder));
}
}
}
13 changes: 12 additions & 1 deletion BossMod/Util/UIMisc.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Dalamud.Interface.Internal;
using Dalamud.Interface;
using Dalamud.Interface.Internal;
using Dalamud.Interface.Utility.Raii;
using ImGuiNET;

namespace BossMod;
Expand Down Expand Up @@ -55,4 +57,13 @@ public static bool ImageToggleButton(IDalamudTextureWrap? icon, Vector2 size, bo
return ImGui.Button("", size);
}
}

// works around issues with fonts in uidev
public static unsafe bool IconButton(FontAwesomeIcon icon, string fallback, string text)
{
if (Service.PluginInterface == null)
return ImGui.Button(fallback + text);
using var scope = ImRaii.PushFont(UiBuilder.IconFont);
return ImGui.Button(icon.ToIconString() + text);
}
}
2 changes: 1 addition & 1 deletion TODO
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ general:
-- button to 'keep' last (add as temp to replay manager) or to 'save' last (save into replay file)
- better timing tracking for: statuses, gauges, cooldowns, cast times, anim lock, ...
- constrain bossmodules to zone id (e.g. for T04)
- module registry improvements
- revise module categories - consider merging fates/hunts/quests/gold saucer?/pvp? into outdoor?/casual?
- refactor pendingeffects

boss modules:
Expand Down

0 comments on commit 050b388

Please sign in to comment.