Initial HSMappy release (fork of Mappy)
Made-with: Cursor
This commit is contained in:
@@ -0,0 +1,427 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Components;
|
||||
using Dalamud.Interface.Utility;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
using KamiLib.Classes;
|
||||
using KamiLib.CommandManager;
|
||||
using KamiLib.Extensions;
|
||||
using KamiLib.Window;
|
||||
using Mappy.Classes;
|
||||
using Mappy.Data;
|
||||
|
||||
namespace Mappy.Windows;
|
||||
|
||||
public class ConfigurationWindow : Window
|
||||
{
|
||||
private readonly TabBar tabBar = new("mappy_tab_bar", [
|
||||
new IconConfigurationTab(),
|
||||
new MapFunctionsTab(),
|
||||
new StyleOptionsTab(),
|
||||
new MinimapOptionsTab(),
|
||||
new PlayerOptionsTab(),
|
||||
]);
|
||||
|
||||
public ConfigurationWindow() : base("HSMappy Configuration Window", new Vector2(500.0f, 580.0f))
|
||||
{
|
||||
System.CommandManager.RegisterCommand(new CommandHandler
|
||||
{
|
||||
Delegate = _ => System.ConfigWindow.Toggle(), ActivationPath = "/",
|
||||
});
|
||||
}
|
||||
|
||||
protected override void DrawContents() => tabBar.Draw();
|
||||
}
|
||||
|
||||
public class MapFunctionsTab : ITabItem
|
||||
{
|
||||
public string Name => "Map Functions";
|
||||
|
||||
public bool Disabled => false;
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
var configChanged = false;
|
||||
|
||||
ImGuiTweaks.Header("Zoom Options");
|
||||
using (ImRaii.PushIndent()) {
|
||||
configChanged |= ImGui.Checkbox("Use Linear Zoom", ref System.SystemConfig.UseLinearZoom);
|
||||
configChanged |= ImGui.Checkbox("Scale icons with zoom", ref System.SystemConfig.ScaleWithZoom);
|
||||
configChanged |= ImGui.Checkbox("Scale text labels with zoom", ref System.SystemConfig.ScaleTextWithZoom);
|
||||
|
||||
ImGuiHelpers.ScaledDummy(5.0f);
|
||||
|
||||
configChanged |= ImGuiTweaks.Checkbox("Auto Zoom", ref System.SystemConfig.AutoZoom, "Automatically sets zoom to a reasonable value relative to the map size.");
|
||||
configChanged |= ImGui.SliderFloat("Auto Zoom Scale Factor", ref System.SystemConfig.AutoZoomScaleFactor, 0.20f, 1.00f);
|
||||
|
||||
ImGuiHelpers.ScaledDummy(5.0f);
|
||||
|
||||
configChanged |= ImGui.SliderFloat("Zoom Speed", ref System.SystemConfig.ZoomSpeed, 0.001f, 0.500f);
|
||||
configChanged |= ImGui.SliderFloat("Icon Scale", ref System.SystemConfig.IconScale, 0.10f, 3.0f);
|
||||
}
|
||||
|
||||
ImGuiTweaks.Header("When Opening Map");
|
||||
using (ImRaii.PushIndent()) {
|
||||
configChanged |= ImGui.Checkbox("Follow On Open", ref System.SystemConfig.FollowOnOpen);
|
||||
|
||||
ImGuiHelpers.ScaledDummy(5.0f);
|
||||
|
||||
DrawCenterModeRadio();
|
||||
}
|
||||
|
||||
ImGuiTweaks.Header("Link Behaviors");
|
||||
using (ImRaii.PushIndent()) {
|
||||
configChanged |= ImGui.Checkbox("Center on Flags", ref System.SystemConfig.CenterOnFlag);
|
||||
configChanged |= ImGui.Checkbox("Center on Gathering Areas", ref System.SystemConfig.CenterOnGathering);
|
||||
configChanged |= ImGui.Checkbox("Center on Quest", ref System.SystemConfig.CenterOnQuest);
|
||||
}
|
||||
|
||||
ImGuiTweaks.Header("Misc Options");
|
||||
using (ImRaii.PushIndent()) {
|
||||
configChanged |= ImGui.Checkbox("Show Misc Tooltips", ref System.SystemConfig.ShowMiscTooltips);
|
||||
configChanged |= ImGui.Checkbox("Lock Map on Center", ref System.SystemConfig.LockCenterOnMap);
|
||||
configChanged |= ImGui.Checkbox("Show Other Players", ref System.SystemConfig.ShowPlayers);
|
||||
configChanged |= ImGui.Checkbox("Disable Map Focus on Appear", ref System.SystemConfig.NoFocusOnAppear);
|
||||
configChanged |= ImGui.Checkbox("Suppress the native map's open/close sound effect.",
|
||||
ref System.SystemConfig.SuppressNativeMapOpenSound);
|
||||
|
||||
|
||||
ImGuiHelpers.ScaledDummy(5.0f);
|
||||
|
||||
configChanged |= ImGui.Checkbox("Show Text Labels", ref System.SystemConfig.ShowTextLabels);
|
||||
configChanged |= ImGui.DragFloat("Large Label Scale", ref System.SystemConfig.LargeAreaTextScale, 0.01f, 1.0f, 4.0f);
|
||||
configChanged |= ImGui.DragFloat("Small Label Scale", ref System.SystemConfig.SmallAreaTextScale, 0.01f, 0.5f, 3.0f);
|
||||
|
||||
ImGuiHelpers.ScaledDummy(5.0f);
|
||||
|
||||
configChanged |= ImGui.Checkbox("Show Fog of War", ref System.SystemConfig.ShowFogOfWar);
|
||||
|
||||
ImGuiHelpers.ScaledDummy(5.0f);
|
||||
|
||||
configChanged |= ImGui.Checkbox("Debug Mode", ref System.SystemConfig.DebugMode);
|
||||
}
|
||||
|
||||
ImGuiTweaks.Header("Toolbar");
|
||||
using (ImRaii.PushIndent()) {
|
||||
configChanged |= ImGui.Checkbox("Always Show", ref System.SystemConfig.AlwaysShowToolbar);
|
||||
configChanged |= ImGui.Checkbox("Show On Hover", ref System.SystemConfig.ShowToolbarOnHover);
|
||||
|
||||
ImGuiHelpers.ScaledDummy(5.0f);
|
||||
configChanged |= ImGui.DragFloat("Opacity##toolbar", ref System.SystemConfig.ToolbarFade, 0.01f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
ImGuiTweaks.Header("Coordinates");
|
||||
using (ImRaii.PushIndent()) {
|
||||
configChanged |= ImGui.Checkbox("Show Coordinate Bar", ref System.SystemConfig.ShowCoordinateBar);
|
||||
|
||||
ImGuiHelpers.ScaledDummy(5.0f);
|
||||
configChanged |= ImGuiTweaks.ColorEditWithDefault("Text Color", ref System.SystemConfig.CoordinateTextColor, KnownColor.White.Vector());
|
||||
|
||||
ImGuiHelpers.ScaledDummy(5.0f);
|
||||
configChanged |= ImGui.DragFloat("Opacity##coordinatebar", ref System.SystemConfig.CoordinateBarFade, 0.01f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
if (configChanged) {
|
||||
SystemConfig.Save();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCenterModeRadio()
|
||||
{
|
||||
var enumObject = System.SystemConfig.CenterOnOpen;
|
||||
var firstLine = true;
|
||||
|
||||
foreach (Enum enumValue in Enum.GetValues(enumObject.GetType())) {
|
||||
if (!firstLine) ImGui.SameLine();
|
||||
|
||||
if (ImGui.RadioButton(enumValue.GetDescription(), enumValue.Equals(enumObject))) {
|
||||
System.SystemConfig.CenterOnOpen = (CenterTarget)enumValue;
|
||||
SystemConfig.Save();
|
||||
}
|
||||
|
||||
firstLine = false;
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.Text("\t\tCenter on Open");
|
||||
}
|
||||
}
|
||||
|
||||
public class StyleOptionsTab : ITabItem
|
||||
{
|
||||
public string Name => "Style";
|
||||
|
||||
public bool Disabled => false;
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
var configChanged = false;
|
||||
|
||||
ImGuiTweaks.Header("Window Options");
|
||||
using (ImRaii.PushIndent()) {
|
||||
configChanged |= ImGui.Checkbox("Keep Open", ref System.SystemConfig.KeepOpen);
|
||||
configChanged |= ImGui.Checkbox("Lock Window Position", ref System.SystemConfig.LockWindow);
|
||||
configChanged |= ImGui.Checkbox("Hide Window Frame", ref System.SystemConfig.HideWindowFrame);
|
||||
configChanged |= ImGui.Checkbox("Hide Window Background", ref System.SystemConfig.HideWindowBackground);
|
||||
configChanged |= ImGui.Checkbox("Enable Shift + Drag to Move Window Frame", ref System.SystemConfig.EnableShiftDragMove);
|
||||
}
|
||||
|
||||
ImGuiTweaks.Header("Window Hiding");
|
||||
using (ImRaii.PushIndent()) {
|
||||
configChanged |= ImGui.Checkbox("Hide With Game GUI", ref System.SystemConfig.HideWithGameGui);
|
||||
configChanged |= ImGui.Checkbox("Hide Between Areas", ref System.SystemConfig.HideBetweenAreas);
|
||||
configChanged |= ImGui.Checkbox("Hide in Combat", ref System.SystemConfig.HideInCombat);
|
||||
}
|
||||
|
||||
ImGuiTweaks.Header("Window Title");
|
||||
using (ImRaii.PushIndent()) {
|
||||
configChanged |= ImGui.Checkbox("Show Region Text", ref System.SystemConfig.ShowRegionLabel);
|
||||
configChanged |= ImGui.Checkbox("Show Map Text", ref System.SystemConfig.ShowMapLabel);
|
||||
configChanged |= ImGui.Checkbox("Show Area Text", ref System.SystemConfig.ShowAreaLabel);
|
||||
configChanged |= ImGui.Checkbox("Show Sub-Area Text", ref System.SystemConfig.ShowSubAreaLabel);
|
||||
}
|
||||
|
||||
ImGuiTweaks.Header("Window Location");
|
||||
using (ImRaii.PushIndent()) {
|
||||
configChanged |= ImGui.DragFloat2("Window Position", ref System.SystemConfig.WindowPosition);
|
||||
configChanged |= ImGui.DragFloat2("Window Size", ref System.SystemConfig.WindowSize);
|
||||
}
|
||||
|
||||
ImGuiTweaks.Header("Fade Options");
|
||||
using (ImRaii.PushIndent()) {
|
||||
using (var columns = ImRaii.Table("fade_options_toggles", 2)) {
|
||||
if (!columns) return;
|
||||
|
||||
var value = System.SystemConfig.FadeMode;
|
||||
ImGui.TableNextColumn();
|
||||
|
||||
foreach (Enum enumValue in Enum.GetValues(value.GetType())) {
|
||||
var isFlagSet = value.HasFlag(enumValue);
|
||||
if (ImGuiComponents.ToggleButton(enumValue.ToString(), ref isFlagSet)) {
|
||||
var sourceValue = Convert.ToInt32(value);
|
||||
var targetValue = Convert.ToInt32(enumValue);
|
||||
|
||||
if (value.HasFlag(enumValue)) {
|
||||
System.SystemConfig.FadeMode = (FadeMode)Enum.ToObject(value.GetType(), sourceValue & ~targetValue);
|
||||
}
|
||||
else {
|
||||
System.SystemConfig.FadeMode = (FadeMode)Enum.ToObject(value.GetType(), sourceValue | targetValue);
|
||||
}
|
||||
|
||||
configChanged = true;
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.TextUnformatted(enumValue.GetDescription());
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
}
|
||||
}
|
||||
|
||||
configChanged |= ImGui.DragFloat("Fade Opacity", ref System.SystemConfig.FadePercent, 0.01f, 0.05f, 1.0f);
|
||||
}
|
||||
|
||||
ImGuiTweaks.Header("Area Style");
|
||||
using (ImRaii.PushIndent()) {
|
||||
configChanged |= ImGuiTweaks.ColorEditWithDefault("Area Color", ref System.SystemConfig.AreaColor, KnownColor.CornflowerBlue.Vector() with { W = 0.33f });
|
||||
configChanged |= ImGuiTweaks.ColorEditWithDefault("Area Outline Color", ref System.SystemConfig.AreaOutlineColor,
|
||||
KnownColor.CornflowerBlue.Vector() with { W = 0.30f });
|
||||
}
|
||||
|
||||
if (configChanged) {
|
||||
if (System.MapWindow.SizeConstraints is { } constraints) {
|
||||
System.SystemConfig.WindowSize.X = MathF.Max(System.SystemConfig.WindowSize.X, constraints.MinimumSize.X);
|
||||
System.SystemConfig.WindowSize.Y = MathF.Max(System.SystemConfig.WindowSize.Y, constraints.MinimumSize.Y);
|
||||
}
|
||||
|
||||
System.MapWindow.RefreshTitle();
|
||||
SystemConfig.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class MinimapOptionsTab : ITabItem
|
||||
{
|
||||
public string Name => "Minimap";
|
||||
|
||||
public bool Disabled => false;
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
var configChanged = false;
|
||||
|
||||
ImGuiTweaks.Header("Minimap");
|
||||
using (ImRaii.PushIndent()) {
|
||||
var showMinimap = System.SystemConfig.ShowMinimap;
|
||||
if (ImGui.Checkbox("Show Minimap", ref showMinimap)) {
|
||||
System.SystemConfig.ShowMinimap = showMinimap;
|
||||
configChanged = true;
|
||||
if (showMinimap)
|
||||
System.MinimapWindow?.UnCollapseOrShow();
|
||||
}
|
||||
|
||||
ImGuiHelpers.ScaledDummy(5.0f);
|
||||
|
||||
configChanged |= ImGui.DragFloat("Size", ref System.SystemConfig.MinimapSize, 5.0f, 80.0f, 400.0f, "%.0f");
|
||||
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
|
||||
ImGui.SetTooltip("Minimap size. Resize only via this setting (no corner grip).");
|
||||
configChanged |= ImGui.DragFloat2("Position", ref System.SystemConfig.MinimapPosition);
|
||||
configChanged |= ImGui.DragFloat("Opacity", ref System.SystemConfig.MinimapOpacity, 0.01f, 0.2f, 1.0f);
|
||||
configChanged |= ImGui.SliderFloat("Zoom Level", ref System.SystemConfig.MinimapZoom, 0.03f, 0.112f,
|
||||
"%.2f (0.1 = zoomed out, lower = zoomed in)");
|
||||
configChanged |= ImGui.Checkbox("Show Player Cone", ref System.SystemConfig.MinimapShowPlayerCone);
|
||||
configChanged |= ImGui.Checkbox("Show Quest Direction Arrow", ref System.SystemConfig.MinimapShowQuestDirectionArrow);
|
||||
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
|
||||
ImGui.SetTooltip("Show an arrow at the edge of the minimap pointing toward your quest objective or waymark (like the default game minimap).");
|
||||
configChanged |= ImGui.Checkbox("Show FATE Direction Arrows", ref System.SystemConfig.MinimapShowFateDirectionArrows);
|
||||
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
|
||||
ImGui.SetTooltip("Show purple arrows at the edge of the minimap pointing toward nearby FATEs.");
|
||||
configChanged |= ImGui.Checkbox("Show Quest Area Radius", ref System.SystemConfig.MinimapShowQuestAreaRadius);
|
||||
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
|
||||
ImGui.SetTooltip("Show quest objective area circles on the minimap (same as on the Area Map).");
|
||||
configChanged |= ImGui.Checkbox("Hide Minimap With Game GUI", ref System.SystemConfig.MinimapHideWithGameGui);
|
||||
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
|
||||
ImGui.SetTooltip("When enabled, the minimap hides during NPC dialogue, object interaction, and when the game hides nameplates (same as the main map). When disabled, the minimap stays visible in those situations.");
|
||||
configChanged |= ImGui.Checkbox("Lock Position", ref System.SystemConfig.MinimapLockPosition);
|
||||
}
|
||||
|
||||
if (configChanged) {
|
||||
SystemConfig.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PlayerOptionsTab : ITabItem
|
||||
{
|
||||
public string Name => "Player";
|
||||
|
||||
public bool Disabled => false;
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
var configChanged = false;
|
||||
|
||||
ImGuiTweaks.Header("Cone Options");
|
||||
using (ImRaii.PushIndent()) {
|
||||
configChanged |= ImGui.Checkbox("Scale Player Cone", ref System.SystemConfig.ScalePlayerCone);
|
||||
|
||||
ImGuiHelpers.ScaledDummy(5.0f);
|
||||
configChanged |= ImGui.DragFloat("Cone Size", ref System.SystemConfig.ConeSize, 0.25f);
|
||||
|
||||
ImGuiHelpers.ScaledDummy(5.0f);
|
||||
configChanged |= ImGuiTweaks.ColorEditWithDefault("Cone Color", ref System.SystemConfig.PlayerConeColor, KnownColor.CornflowerBlue.Vector() with { W = 0.33f });
|
||||
configChanged |= ImGuiTweaks.ColorEditWithDefault("Cone Outline Color", ref System.SystemConfig.PlayerConeOutlineColor,
|
||||
KnownColor.CornflowerBlue.Vector() with { W = 1.00f });
|
||||
}
|
||||
|
||||
ImGuiTweaks.Header("Radar Options");
|
||||
using (ImRaii.PushIndent()) {
|
||||
configChanged |= ImGui.Checkbox("Show Radar Radius", ref System.SystemConfig.ShowRadar);
|
||||
configChanged |= ImGui.Checkbox("Show in Duties", ref System.SystemConfig.ShowRadarInDuties);
|
||||
|
||||
ImGuiHelpers.ScaledDummy(5.0f);
|
||||
|
||||
configChanged |= ImGuiTweaks.ColorEditWithDefault("Radar Area Color", ref System.SystemConfig.RadarColor, KnownColor.Gray.Vector() with { W = 0.10f });
|
||||
configChanged |= ImGuiTweaks.ColorEditWithDefault("Radar Outline Color", ref System.SystemConfig.RadarOutlineColor, KnownColor.Gray.Vector() with { W = 0.30f });
|
||||
}
|
||||
|
||||
ImGuiTweaks.Header("Player Icon Options");
|
||||
using (ImRaii.PushIndent()) {
|
||||
configChanged |= ImGui.Checkbox("Show Player Icon", ref System.SystemConfig.ShowPlayerIcon);
|
||||
|
||||
ImGuiHelpers.ScaledDummy(5.0f);
|
||||
configChanged |= ImGui.DragFloat("Player Icon Size", ref System.SystemConfig.PlayerIconScale, 0.05f);
|
||||
}
|
||||
|
||||
if (configChanged) {
|
||||
SystemConfig.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class IconConfigurationTab : ITabItem
|
||||
{
|
||||
public string Name => "Icon Settings";
|
||||
|
||||
public bool Disabled => false;
|
||||
|
||||
private IconSetting? currentSetting;
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
using (var leftChild = ImRaii.Child("left_child", new Vector2(48.0f * ImGuiHelpers.GlobalScale + ImGui.GetStyle().ItemSpacing.X, ImGui.GetContentRegionAvail().Y))) {
|
||||
if (leftChild) {
|
||||
using var selectionList = ImRaii.ListBox("iconSelection", ImGui.GetContentRegionAvail());
|
||||
|
||||
foreach (var (iconId, settings) in System.IconConfig.IconSettingMap.OrderBy(pairData => pairData.Key)) {
|
||||
if (iconId is 0) continue;
|
||||
if (DrawHelpers.IsDisallowedIcon(iconId)) continue;
|
||||
|
||||
var texture = Service.TextureProvider.GetFromGameIcon(iconId).GetWrapOrEmpty();
|
||||
var cursorStart = ImGui.GetCursorScreenPos();
|
||||
if (ImGui.Selectable($"##iconSelect{iconId}", currentSetting == settings, ImGuiSelectableFlags.None, ImGuiHelpers.ScaledVector2(32.0f, 32.0f))) {
|
||||
currentSetting = currentSetting == settings ? null : settings;
|
||||
}
|
||||
|
||||
ImGui.SetCursorScreenPos(cursorStart);
|
||||
ImGui.Image(texture.Handle, texture.Size / 2.0f * ImGuiHelpers.GlobalScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
using (var rightChild = ImRaii.Child("right_child", ImGui.GetContentRegionAvail(), false, ImGuiWindowFlags.NoScrollbar)) {
|
||||
if (rightChild) {
|
||||
if (currentSetting is null) {
|
||||
using var textColor = ImRaii.PushColor(ImGuiCol.Text, KnownColor.Orange.Vector());
|
||||
|
||||
ImGui.SetCursorPosY(ImGui.GetContentRegionAvail().Y / 2.0f);
|
||||
ImGuiHelpers.CenteredText("Select an Icon to Edit Settings");
|
||||
}
|
||||
else {
|
||||
// Draw background texture
|
||||
var settingsChanged = false;
|
||||
var texture = Service.TextureProvider.GetFromGameIcon(currentSetting.IconId).GetWrapOrEmpty();
|
||||
var smallestAxis = MathF.Min(ImGui.GetContentRegionAvail().X, ImGui.GetContentRegionAvail().Y);
|
||||
|
||||
if (ImGui.GetContentRegionAvail().X > ImGui.GetContentRegionAvail().Y) {
|
||||
var remainingSpace = ImGui.GetContentRegionAvail().X - smallestAxis;
|
||||
ImGui.SetCursorPosX(remainingSpace / 2.0f);
|
||||
}
|
||||
|
||||
ImGui.Image(texture.Handle, new Vector2(smallestAxis, smallestAxis), Vector2.Zero, Vector2.One, new Vector4(1.0f, 1.0f, 1.0f, 0.20f));
|
||||
ImGui.SetCursorPos(Vector2.Zero);
|
||||
|
||||
// Draw settings
|
||||
ImGuiTweaks.Header($"Configure Marker #{currentSetting.IconId}");
|
||||
using (ImRaii.PushIndent()) {
|
||||
settingsChanged |= ImGui.Checkbox("Hide Icon", ref currentSetting.Hide);
|
||||
settingsChanged |= ImGui.Checkbox("Allow Tooltip", ref currentSetting.AllowTooltip);
|
||||
settingsChanged |= ImGui.Checkbox("Allow Click Interaction", ref currentSetting.AllowClick);
|
||||
|
||||
ImGuiHelpers.ScaledDummy(5.0f);
|
||||
settingsChanged |= ImGuiTweaks.ColorEditWithDefault("Color", ref currentSetting.Color, KnownColor.White.Vector());
|
||||
|
||||
ImGuiHelpers.ScaledDummy(5.0f);
|
||||
settingsChanged |= ImGui.DragFloat("Icon Scale", ref currentSetting.Scale, 0.01f, 0.05f, 20.0f);
|
||||
}
|
||||
|
||||
ImGui.SetCursorPosY(ImGui.GetContentRegionMax().Y - 25.0f * ImGuiHelpers.GlobalScale);
|
||||
if (ImGui.Button("Reset to Default", new Vector2(ImGui.GetContentRegionAvail().X, 25.0f * ImGuiHelpers.GlobalScale))) {
|
||||
currentSetting.Reset();
|
||||
System.IconConfig.Save();
|
||||
}
|
||||
|
||||
if (settingsChanged) {
|
||||
System.IconConfig.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Game.Text;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Textures;
|
||||
using Dalamud.Interface.Utility;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.Fate;
|
||||
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
||||
using KamiLib.Extensions;
|
||||
using KamiLib.Window;
|
||||
using Mappy.Data;
|
||||
using Mappy.Extensions;
|
||||
|
||||
namespace Mappy.Windows;
|
||||
|
||||
public class FateListWindow : Window
|
||||
{
|
||||
private const float ElementHeight = 48.0f;
|
||||
|
||||
public FateListWindow() : base("HSMappy Fate List Window", new Vector2(300.0f, 400.0f))
|
||||
{
|
||||
AdditionalInfoTooltip = "Shows Fates for the zone you are currently in";
|
||||
}
|
||||
|
||||
protected override unsafe void DrawContents()
|
||||
{
|
||||
DrawBackgroundImage();
|
||||
|
||||
if (Service.FateTable.Length > 0) {
|
||||
DrawOptions();
|
||||
|
||||
foreach (var index in Enumerable.Range(0, Service.FateTable.Length)) {
|
||||
var fate = FateManager.Instance()->Fates[index].Value;
|
||||
|
||||
var cursorStart = ImGui.GetCursorScreenPos();
|
||||
if (ImGui.Selectable($"##{fate->FateId}_Selectable", false, ImGuiSelectableFlags.None,
|
||||
new Vector2(ImGui.GetContentRegionAvail().X, ElementHeight * ImGuiHelpers.GlobalScale))) {
|
||||
OnFateClick(fate);
|
||||
}
|
||||
|
||||
ImGui.SetCursorScreenPos(cursorStart);
|
||||
DrawFateInfo(fate);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const string text = "No FATE's available";
|
||||
var textSize = ImGui.CalcTextSize(text);
|
||||
ImGui.SetCursorPosX(ImGui.GetContentRegionAvail().X / 2.0f - textSize.X / 2.0f);
|
||||
ImGui.SetCursorPosY(ImGui.GetContentRegionAvail().Y / 2.0f - textSize.Y / 2.0f);
|
||||
ImGui.TextColored(KnownColor.Orange.Vector(), text);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawBackgroundImage()
|
||||
{
|
||||
var windowCursorStart = ImGui.GetCursorPos();
|
||||
var windowWidth = ImGui.GetContentRegionMax().X;
|
||||
var windowHeight = ImGui.GetContentRegionMax().Y;
|
||||
|
||||
var startPos = windowHeight / 2 - windowWidth / 2;
|
||||
ImGui.SetCursorPosY(startPos);
|
||||
ImGui.Spacing();
|
||||
|
||||
ImGui.Image(
|
||||
Service.TextureProvider.GetFromGameIcon(new GameIconLookup { IconId = 60502 }).GetWrapOrEmpty().Handle,
|
||||
new Vector2(ImGui.GetContentRegionMax().X, ImGui.GetContentRegionMax().X),
|
||||
Vector2.Zero,
|
||||
Vector2.One,
|
||||
new Vector4(1.0f, 1.0f, 1.0f, 0.15f));
|
||||
|
||||
ImGui.SetCursorPos(windowCursorStart);
|
||||
}
|
||||
|
||||
private static void DrawOptions()
|
||||
{
|
||||
using var toolbarChild = ImRaii.Child("fatelist_toolbar", new Vector2(ImGui.GetContentRegionAvail().X, 32.0f));
|
||||
if (toolbarChild) {
|
||||
using var color = ImRaii.PushColor(ImGuiCol.Button, ImGui.GetStyle().GetColor(ImGuiCol.ButtonActive), System.SystemConfig.SetFlagOnFateClick);
|
||||
ImGui.Spacing();
|
||||
if (ImGui.Checkbox("Place Map Flag on Click", ref System.SystemConfig.SetFlagOnFateClick)) {
|
||||
SystemConfig.Save();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.Separator();
|
||||
}
|
||||
|
||||
private static unsafe void OnFateClick(FateContext* fate)
|
||||
{
|
||||
System.IntegrationsController.OpenOccupiedMap();
|
||||
System.SystemConfig.FollowPlayer = false;
|
||||
System.MapRenderer.DrawOffset = -new Vector2(fate->Location.X, fate->Location.Z);
|
||||
|
||||
if (System.SystemConfig.SetFlagOnFateClick) {
|
||||
AgentMap.Instance()->FlagMarkerCount = 0;
|
||||
AgentMap.Instance()->SetFlagMapMarker(AgentMap.Instance()->CurrentTerritoryId, AgentMap.Instance()->CurrentMapId, fate->Location.X, fate->Location.Z);
|
||||
AgentChatLog.Instance()->InsertTextCommandParam(1048, false);
|
||||
}
|
||||
}
|
||||
|
||||
private static unsafe void DrawFateInfo(FateContext* fate)
|
||||
{
|
||||
using (ImRaii.Child($"image_child_{fate->FateId}", new Vector2(ElementHeight, ElementHeight), false, ImGuiWindowFlags.NoInputs)) {
|
||||
ImGui.Image(Service.TextureProvider.GetFromGameIcon(fate->IconId).GetWrapOrEmpty().Handle, ImGuiHelpers.ScaledVector2(ElementHeight, ElementHeight));
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
using (ImRaii.Child($"text_child_{fate->FateId}", new Vector2(ImGui.GetContentRegionAvail().X, ElementHeight), false, ImGuiWindowFlags.NoInputs)) {
|
||||
ImGui.TextColored(FateContextExtensions.GetColor(fate, 1.0f), $"Lv. {fate->Level} {fate->Name}");
|
||||
|
||||
if (fate->State is FateState.Running) {
|
||||
ImGui.TextUnformatted($"Progress: {fate->Progress}%");
|
||||
|
||||
var timeRemaining = FateContextExtensions.GetTimeRemaining(fate);
|
||||
if (timeRemaining != TimeSpan.Zero) {
|
||||
var timeString = $"{(fate->IsBonus ? "Exp Bonus!\t" : string.Empty)}{SeIconChar.Clock.ToIconString()} {FateContextExtensions.GetTimeRemaining(fate):mm\\:ss}";
|
||||
ImGui.SameLine(ImGui.GetContentRegionMax().X - ImGui.CalcTextSize(timeString).X);
|
||||
ImGui.Text(timeString);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ImGui.TextUnformatted(fate->State.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnClose()
|
||||
{
|
||||
System.WindowManager.RemoveWindow(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.Drawing;
|
||||
using System.Numerics;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Utility;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
using KamiLib.Window;
|
||||
using Mappy.Data;
|
||||
|
||||
namespace Mappy.Windows;
|
||||
|
||||
public class FlagHistoryWindow : Window
|
||||
{
|
||||
private static float FlagElementHeight => 95.0f * ImGuiHelpers.GlobalScale;
|
||||
|
||||
public FlagHistoryWindow() : base("HSMappy Flag History Window", new Vector2(400.0f, 400.0f))
|
||||
{
|
||||
AdditionalInfoTooltip = "Shows a list of all recently used flags";
|
||||
}
|
||||
|
||||
protected override void DrawContents()
|
||||
{
|
||||
ImGuiClip.ClippedDraw(System.FlagConfig.FlagHistory.ToImmutableList(), DrawFlag, FlagElementHeight);
|
||||
}
|
||||
|
||||
private void DrawFlag(Flag flag)
|
||||
{
|
||||
using var id = ImRaii.PushId(flag.GetIdString());
|
||||
|
||||
using (ImRaii.Child("flag_container", new Vector2(ImGui.GetContentRegionAvail().X, FlagElementHeight - ImGui.GetStyle().FramePadding.Y * 2.0f))) {
|
||||
using (ImRaii.Child("flag_image_container", new Vector2(155.0f * ImGuiHelpers.GlobalScale, ImGui.GetContentRegionAvail().Y))) {
|
||||
DrawFlagImage(flag);
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
using (ImRaii.Child("flag_contents_container", ImGui.GetContentRegionAvail())) {
|
||||
DrawFlagData(flag);
|
||||
DrawButtons(flag);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.Spacing();
|
||||
}
|
||||
|
||||
private void DrawFlagImage(Flag flag)
|
||||
{
|
||||
var texture = flag.GetMapTexture();
|
||||
if (texture is not null) {
|
||||
ImGui.Image(texture.Handle, ImGui.GetContentRegionAvail(), new Vector2(0.15f, 0.15f), new Vector2(0.85f, 0.85f));
|
||||
}
|
||||
else {
|
||||
ImGuiHelpers.ScaledDummy(ImGui.GetContentRegionAvail());
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawFlagData(Flag flag)
|
||||
{
|
||||
ImGui.Text(flag.GetMap().PlaceName.Value.Name.ExtractText());
|
||||
|
||||
ImGui.SameLine();
|
||||
var flagCoordinate = flag.GetMapCoordinate();
|
||||
var coordinateString = $"{flagCoordinate.X:F1}, {flagCoordinate.Y:F1}";
|
||||
var coordinateStringSize = ImGui.CalcTextSize(coordinateString);
|
||||
ImGui.SetCursorPosX(ImGui.GetContentRegionMax().X - coordinateStringSize.X);
|
||||
ImGui.Text(coordinateString);
|
||||
|
||||
ImGui.TextColored(KnownColor.Gray.Vector().Lighten(0.20f), flag.GetTerritoryType().PlaceNameZone.Value.Name.ExtractText());
|
||||
|
||||
if (flag.IsFlagSet()) {
|
||||
ImGui.Spacing();
|
||||
ImGui.TextColored(KnownColor.ForestGreen.Vector().Lighten(0.40f), "Flag is currently active");
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawButtons(Flag flag)
|
||||
{
|
||||
var buttonSize = ImGuiHelpers.ScaledVector2(100.0f, 24.0f);
|
||||
|
||||
ImGui.SetCursorPos(new Vector2(0.0f, ImGui.GetContentRegionMax().Y - buttonSize.Y));
|
||||
if (ImGui.Button("Focus", buttonSize)) {
|
||||
flag.Focus();
|
||||
}
|
||||
|
||||
ImGui.SetCursorPos(ImGui.GetContentRegionMax() - buttonSize);
|
||||
using (ImRaii.Disabled(flag.IsFlagSet())) {
|
||||
if (ImGui.Button("Place", buttonSize)) {
|
||||
flag.PlaceFlag();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnClose()
|
||||
{
|
||||
System.WindowManager.RemoveWindow(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Dalamud.Interface.Utility;
|
||||
using KamiLib.Window;
|
||||
using Lumina.Excel.Sheets;
|
||||
using Mappy.Classes.SelectionWindowComponents;
|
||||
using Aetheryte = Lumina.Excel.Sheets.Aetheryte;
|
||||
|
||||
namespace Mappy.Windows;
|
||||
|
||||
public class MapSelectionWindow : SelectionWindowBase<DrawableOption>
|
||||
{
|
||||
protected override bool AllowMultiSelect => false;
|
||||
|
||||
protected override float SelectionHeight => 75.0f * ImGuiHelpers.GlobalScale;
|
||||
|
||||
public MapSelectionWindow() : base(new Vector2(500.0f, 800.0f), alternativeName: "Map Selection Window")
|
||||
{
|
||||
var maps = Service.DataManager.GetExcelSheet<Map>()
|
||||
.Where(map => map is { PlaceName.RowId: not 0, TerritoryType.ValueNullable.LoadingImage.RowId: not 0, })
|
||||
.Where(map => map is not { PriorityUI: 0, PriorityCategoryUI: 0 })
|
||||
.Select(map => new MapDrawableOption { Map = map, })
|
||||
.OfType<DrawableOption>()
|
||||
.ToList();
|
||||
|
||||
var poi = Service.DataManager.GetSubrowExcelSheet<MapMarker>()
|
||||
.SelectMany(subRowCollection => subRowCollection)
|
||||
.Where(marker => marker is { PlaceNameSubtext.RowId: not 0, Icon: 60442, })
|
||||
.Select(marker => new PoiDrawableOption { MapMarker = marker, })
|
||||
.OfType<DrawableOption>()
|
||||
.ToList();
|
||||
|
||||
var aetherytes = Service.DataManager.GetExcelSheet<Aetheryte>()
|
||||
.Where(aetheryte => aetheryte is not { PlaceName.RowId: 0, AethernetName.RowId: 0, AethernetGroup: 0, Map.RowId: 0, })
|
||||
.Select(aetheryte => new AetheryteDrawableOption { Aetheryte = aetheryte, })
|
||||
.OfType<DrawableOption>()
|
||||
.ToList();
|
||||
|
||||
SelectionOptions = maps
|
||||
.Concat(poi)
|
||||
.Concat(aetherytes)
|
||||
.ToList();
|
||||
|
||||
SelectionOptions.RemoveAll(option => option.Map.RowId is 0);
|
||||
}
|
||||
|
||||
protected override void DrawSelection(DrawableOption option)
|
||||
{
|
||||
option.Draw();
|
||||
}
|
||||
|
||||
protected override IEnumerable<string> GetFilterStrings(DrawableOption option) => option.GetFilterStrings();
|
||||
|
||||
protected override string GetElementKey(DrawableOption element) => $"{element.Map.RowId}{element.MarkerLocation}{element.ExtraLineShort}{element.ExtraLineLong}";
|
||||
}
|
||||
@@ -0,0 +1,505 @@
|
||||
using System.Drawing;
|
||||
using System.Numerics;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Game.ClientState.Keys;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Utility;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
||||
using KamiLib.Classes;
|
||||
using KamiLib.CommandManager;
|
||||
using KamiLib.Window;
|
||||
using Lumina.Excel.Sheets;
|
||||
using Mappy.Classes;
|
||||
using Mappy.Classes.MapWindowComponents;
|
||||
using Mappy.Controllers;
|
||||
using Mappy.Data;
|
||||
using Map = Lumina.Excel.Sheets.Map;
|
||||
|
||||
namespace Mappy.Windows;
|
||||
|
||||
public class MapWindow : Window
|
||||
{
|
||||
public Vector2 MapDrawOffset { get; private set; }
|
||||
public HoverFlags HoveredFlags { get; private set; }
|
||||
public bool ProcessingCommand { get; set; }
|
||||
|
||||
private bool isDragStarted;
|
||||
private Vector2 lastWindowSize;
|
||||
private uint lastMapId;
|
||||
private uint lastAreaPlaceNameId;
|
||||
private uint lastSubAreaPlaceNameId;
|
||||
|
||||
private readonly MapToolbar mapToolbar = new();
|
||||
private readonly MapCoordinateBar mapCoordinateBar = new();
|
||||
private readonly MapContextMenu mapContextMenu = new();
|
||||
|
||||
public MapWindow() : base("###HSMappyMapWindow", new Vector2(400.0f, 250.0f))
|
||||
{
|
||||
UpdateTitle();
|
||||
|
||||
DisableWindowSounds = true;
|
||||
RegisterCommands();
|
||||
}
|
||||
|
||||
public override bool DrawConditions() => IntegrationsController.ShouldShowMap();
|
||||
|
||||
public override unsafe void PreOpenCheck()
|
||||
{
|
||||
// If you managed to open the window while the agent says it should be closed
|
||||
if (System.MapWindow.IsOpen && AgentMap.Instance()->AddonId is 0)
|
||||
{
|
||||
Service.Log.Debug("[OnShow] MapWindow can not be open now.");
|
||||
IsOpen = false;
|
||||
}
|
||||
|
||||
if (System.SystemConfig.KeepOpen) {
|
||||
IsOpen = true;
|
||||
}
|
||||
|
||||
if (Service.ClientState is { IsLoggedIn: false } or { IsPvP: true }) IsOpen = false;
|
||||
}
|
||||
|
||||
public override void OnOpen()
|
||||
{
|
||||
if (ProcessingCommand) {
|
||||
ProcessingCommand = false;
|
||||
System.SystemConfig.FollowPlayer = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (System.SystemConfig.FollowOnOpen) {
|
||||
System.IntegrationsController.OpenOccupiedMap();
|
||||
System.SystemConfig.FollowPlayer = true;
|
||||
}
|
||||
|
||||
switch (System.SystemConfig.CenterOnOpen) {
|
||||
case CenterTarget.Player when Service.ObjectTable.LocalPlayer is { } localPlayer:
|
||||
System.MapRenderer.CenterOnGameObject(localPlayer);
|
||||
break;
|
||||
|
||||
case CenterTarget.Map:
|
||||
System.SystemConfig.FollowPlayer = false;
|
||||
System.MapRenderer.DrawOffset = Vector2.Zero;
|
||||
break;
|
||||
|
||||
case CenterTarget.Disabled:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void DrawContents()
|
||||
{
|
||||
UpdateTitle();
|
||||
UpdateStyle();
|
||||
UpdateSizePosition();
|
||||
|
||||
HoveredFlags = HoverFlags.Nothing;
|
||||
|
||||
if (WindowBounds.IsBoundedBy(ImGui.GetMousePos(), ImGui.GetCursorScreenPos(), ImGui.GetCursorScreenPos() + ImGui.GetContentRegionMax())) {
|
||||
HoveredFlags |= HoverFlags.Window;
|
||||
}
|
||||
|
||||
MapDrawOffset = ImGui.GetCursorScreenPos();
|
||||
using var fade = ImRaii.PushStyle(ImGuiStyleVar.Alpha, System.SystemConfig.FadePercent, ShouldFade());
|
||||
using (var renderChild = ImRaii.Child("render_child", ImGui.GetContentRegionAvail(), false, ImGuiWindowFlags.NoScrollWithMouse | ImGuiWindowFlags.NoScrollbar)) {
|
||||
if (!renderChild) return;
|
||||
if (!System.SystemConfig.AcceptedSpoilerWarning) {
|
||||
DrawSpoilerWarning();
|
||||
return;
|
||||
}
|
||||
|
||||
DrawMapElements();
|
||||
|
||||
// Reset Draw Position for Overlay Extras
|
||||
ImGui.SetCursorPos(Vector2.Zero);
|
||||
DrawToolbar();
|
||||
DrawCoordinateBar();
|
||||
}
|
||||
|
||||
if (ImGui.IsItemHovered()) {
|
||||
HoveredFlags |= HoverFlags.WindowInnerFrame;
|
||||
}
|
||||
|
||||
// Process Inputs
|
||||
ProcessInputs();
|
||||
}
|
||||
|
||||
private void DrawMapElements()
|
||||
{
|
||||
System.MapRenderer.DrawBaseTexture();
|
||||
if (ImGui.IsItemHovered()) {
|
||||
HoveredFlags |= HoverFlags.MapTexture;
|
||||
}
|
||||
|
||||
System.MapRenderer.DrawDynamicElements();
|
||||
}
|
||||
|
||||
private void DrawToolbar()
|
||||
{
|
||||
if (!ShouldShowToolbar()) return;
|
||||
|
||||
using (ImRaii.Group()) {
|
||||
mapToolbar.Draw();
|
||||
}
|
||||
|
||||
if (ImGui.IsItemHovered()) {
|
||||
HoveredFlags |= HoverFlags.Toolbar;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCoordinateBar()
|
||||
{
|
||||
if (!System.SystemConfig.ShowCoordinateBar) return;
|
||||
|
||||
using (ImRaii.Group()) {
|
||||
mapCoordinateBar.Draw(HoveredFlags.HasFlag(HoverFlags.MapTexture), MapDrawOffset);
|
||||
}
|
||||
|
||||
if (ImGui.IsItemHovered()) {
|
||||
HoveredFlags |= HoverFlags.CoordinateBar;
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShouldShowToolbar()
|
||||
{
|
||||
if (isDragStarted) return false;
|
||||
if (System.SystemConfig.ShowToolbarOnHover && HoveredFlags.Any()) return true;
|
||||
if (System.SystemConfig.AlwaysShowToolbar) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private unsafe void UpdateTitle()
|
||||
{
|
||||
var mapChanged = lastMapId != AgentMap.Instance()->SelectedMapId;
|
||||
var areaChanged = lastAreaPlaceNameId != TerritoryInfo.Instance()->AreaPlaceNameId;
|
||||
var subAreaChanged = lastSubAreaPlaceNameId != TerritoryInfo.Instance()->SubAreaPlaceNameId;
|
||||
var locationChanged = mapChanged || areaChanged || subAreaChanged;
|
||||
|
||||
if (!locationChanged) return;
|
||||
var subLocationString = string.Empty;
|
||||
var mapData = Service.DataManager.GetExcelSheet<Map>().GetRow(AgentMap.Instance()->SelectedMapId);
|
||||
|
||||
if (System.SystemConfig.ShowRegionLabel) {
|
||||
var mapRegionName = mapData.PlaceNameRegion.Value.Name.ExtractText();
|
||||
subLocationString += $" - {mapRegionName}";
|
||||
}
|
||||
|
||||
if (System.SystemConfig.ShowMapLabel) {
|
||||
var mapName = mapData.PlaceName.Value.Name.ExtractText();
|
||||
subLocationString += $" - {mapName}";
|
||||
}
|
||||
|
||||
// Don't show specific locations if we aren't there.
|
||||
if (AgentMap.Instance()->SelectedMapId == AgentMap.Instance()->CurrentMapId) {
|
||||
if (TerritoryInfo.Instance()->AreaPlaceNameId is not 0 && System.SystemConfig.ShowAreaLabel) {
|
||||
var areaLabel = Service.DataManager.GetExcelSheet<PlaceName>().GetRow(TerritoryInfo.Instance()->AreaPlaceNameId);
|
||||
subLocationString += $" - {areaLabel.Name}";
|
||||
}
|
||||
|
||||
if (TerritoryInfo.Instance()->SubAreaPlaceNameId is not 0 && System.SystemConfig.ShowSubAreaLabel) {
|
||||
var subAreaLabel = Service.DataManager.GetExcelSheet<PlaceName>().GetRow(TerritoryInfo.Instance()->SubAreaPlaceNameId);
|
||||
subLocationString += $" - {subAreaLabel.Name}";
|
||||
}
|
||||
}
|
||||
|
||||
WindowName = $"{subLocationString}###HSMappyMapWindow".TrimStart(['-',' ']);
|
||||
|
||||
lastMapId = AgentMap.Instance()->SelectedMapId;
|
||||
lastAreaPlaceNameId = TerritoryInfo.Instance()->AreaPlaceNameId;
|
||||
lastSubAreaPlaceNameId = TerritoryInfo.Instance()->SubAreaPlaceNameId;
|
||||
}
|
||||
|
||||
public void RefreshTitle()
|
||||
{
|
||||
lastMapId = 0;
|
||||
lastAreaPlaceNameId = 0;
|
||||
lastSubAreaPlaceNameId = 0;
|
||||
}
|
||||
|
||||
private void ProcessInputs()
|
||||
{
|
||||
if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) {
|
||||
ImGui.OpenPopup("Mappy_Context_Menu");
|
||||
}
|
||||
else {
|
||||
if (HoveredFlags.Any()) {
|
||||
if (System.SystemConfig.EnableShiftDragMove && ImGui.GetIO().KeyShift) {
|
||||
Flags &= ~ImGuiWindowFlags.NoMove;
|
||||
}
|
||||
else {
|
||||
ProcessMouseScroll();
|
||||
ProcessMapDragStart();
|
||||
Flags |= ImGuiWindowFlags.NoMove;
|
||||
}
|
||||
}
|
||||
|
||||
ProcessMapDragDragging();
|
||||
ProcessMapDragEnd();
|
||||
}
|
||||
|
||||
// Draw Context Menu
|
||||
mapContextMenu.Draw(MapDrawOffset);
|
||||
}
|
||||
|
||||
private unsafe void UpdateStyle()
|
||||
{
|
||||
if (System.SystemConfig.HideWindowFrame) {
|
||||
Flags |= ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoBackground;
|
||||
}
|
||||
else {
|
||||
Flags &= ~(ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoBackground);
|
||||
}
|
||||
|
||||
if (System.SystemConfig.LockWindow) {
|
||||
Flags |= ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove;
|
||||
}
|
||||
else {
|
||||
Flags &= ~(ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove);
|
||||
}
|
||||
|
||||
if (System.SystemConfig.NoFocusOnAppear) {
|
||||
Flags |= ImGuiWindowFlags.NoFocusOnAppearing;
|
||||
}
|
||||
else {
|
||||
Flags &= ~ImGuiWindowFlags.NoFocusOnAppearing;
|
||||
}
|
||||
|
||||
if (System.SystemConfig.HideWindowBackground) {
|
||||
Flags |= ImGuiWindowFlags.NoBackground;
|
||||
}
|
||||
else {
|
||||
Flags &= ~ImGuiWindowFlags.NoBackground;
|
||||
}
|
||||
|
||||
if (Service.KeyState[VirtualKey.ESCAPE] && IsFocused && !IsMapLocked()) {
|
||||
AgentMap.Instance()->Hide();
|
||||
}
|
||||
|
||||
if (System.SystemConfig.FollowPlayer && Service.ObjectTable is { LocalPlayer: { } localPlayer }) {
|
||||
System.MapRenderer.CenterOnGameObject(localPlayer);
|
||||
}
|
||||
|
||||
if (System.SystemConfig.LockCenterOnMap) {
|
||||
System.SystemConfig.FollowPlayer = false;
|
||||
System.MapRenderer.DrawOffset = Vector2.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSizePosition()
|
||||
{
|
||||
var systemConfig = System.SystemConfig;
|
||||
var windowPosition = ImGui.GetWindowPos();
|
||||
var windowSize = ImGui.GetWindowSize();
|
||||
|
||||
if (!IsFocused) {
|
||||
if (windowPosition != systemConfig.WindowPosition) {
|
||||
ImGui.SetWindowPos(systemConfig.WindowPosition);
|
||||
}
|
||||
|
||||
if (windowSize != systemConfig.WindowSize) {
|
||||
ImGui.SetWindowSize(systemConfig.WindowSize);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// If focused
|
||||
if (systemConfig.WindowPosition != windowPosition) {
|
||||
systemConfig.WindowPosition = windowPosition;
|
||||
SystemConfig.Save();
|
||||
}
|
||||
|
||||
if (systemConfig.WindowSize != windowSize) {
|
||||
systemConfig.WindowSize = windowSize;
|
||||
SystemConfig.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawSpoilerWarning()
|
||||
{
|
||||
using (ImRaii.PushColor(ImGuiCol.Text, KnownColor.Orange.Vector())) {
|
||||
const string warningLine1 = "Warning, HSMappy does not protect you from spoilers and will show everything.";
|
||||
const string warningLine2 = "Do not use HSMappy if you are not comfortable with this.";
|
||||
|
||||
ImGui.SetCursorPos(ImGui.GetContentRegionAvail() / 2.0f - (ImGui.CalcTextSize(warningLine1) * 2.0f) with { X = 0.0f });
|
||||
ImGuiHelpers.CenteredText(warningLine1);
|
||||
ImGuiHelpers.CenteredText(warningLine2);
|
||||
}
|
||||
|
||||
ImGuiHelpers.ScaledDummy(30.0f);
|
||||
ImGui.SetCursorPosX(ImGui.GetContentRegionAvail().X / 3.0f);
|
||||
using (ImRaii.Disabled(!(ImGui.GetIO().KeyShift && ImGui.GetIO().KeyCtrl))) {
|
||||
if (ImGui.Button("I understand", new Vector2(ImGui.GetContentRegionAvail().X / 2.0f, 23.0f * ImGuiHelpers.GlobalScale))) {
|
||||
System.SystemConfig.AcceptedSpoilerWarning = true;
|
||||
SystemConfig.Save();
|
||||
}
|
||||
|
||||
using (ImRaii.PushStyle(ImGuiStyleVar.Alpha, 1.0f)) {
|
||||
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled)) {
|
||||
ImGui.SetTooltip("Hold Shift + Control while clicking activate button");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override unsafe void OnClose()
|
||||
{
|
||||
AgentMap.Instance()->Hide();
|
||||
SystemConfig.Save();
|
||||
}
|
||||
|
||||
private void ProcessMouseScroll()
|
||||
{
|
||||
if (System.SystemConfig.ZoomLocked) return;
|
||||
if (ImGui.GetIO().MouseWheel is 0) return;
|
||||
if (!HoveredFlags.HasFlag(HoverFlags.WindowInnerFrame)) return;
|
||||
|
||||
if (System.SystemConfig.UseLinearZoom) {
|
||||
MapRenderer.MapRenderer.Scale += System.SystemConfig.ZoomSpeed * ImGui.GetIO().MouseWheel;
|
||||
}
|
||||
else {
|
||||
MapRenderer.MapRenderer.Scale *= 1.0f + System.SystemConfig.ZoomSpeed * ImGui.GetIO().MouseWheel;
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessMapDragDragging()
|
||||
{
|
||||
if (ImGui.IsMouseDragging(ImGuiMouseButton.Left) && isDragStarted) {
|
||||
System.MapRenderer.DrawOffset += ImGui.GetMouseDragDelta() / MapRenderer.MapRenderer.Scale;
|
||||
ImGui.ResetMouseDragDelta();
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessMapDragEnd()
|
||||
{
|
||||
if (ImGui.IsMouseReleased(ImGuiMouseButton.Left)) {
|
||||
isDragStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessMapDragStart()
|
||||
{
|
||||
// Don't allow a drag to start if the window size is changing
|
||||
if (ImGui.GetWindowSize() == lastWindowSize) {
|
||||
if (ImGui.IsItemClicked(ImGuiMouseButton.Left) && !isDragStarted) {
|
||||
isDragStarted = true;
|
||||
System.SystemConfig.FollowPlayer = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
lastWindowSize = ImGui.GetWindowSize();
|
||||
isDragStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe bool ShouldFade() =>
|
||||
System.SystemConfig.FadeMode.HasFlag(FadeMode.Always) ||
|
||||
System.SystemConfig.FadeMode.HasFlag(FadeMode.WhenFocused) && IsFocused ||
|
||||
System.SystemConfig.FadeMode.HasFlag(FadeMode.WhenMoving) && AgentMap.Instance()->IsPlayerMoving ||
|
||||
System.SystemConfig.FadeMode.HasFlag(FadeMode.WhenUnFocused) && !IsFocused;
|
||||
|
||||
private void RegisterCommands()
|
||||
{
|
||||
System.CommandManager.RegisterCommand(new ToggleCommandHandler
|
||||
{
|
||||
UseShowHideText = true,
|
||||
BaseActivationPath = "/map",
|
||||
EnableDelegate = _ => System.MapWindow.UnCollapseOrShow(),
|
||||
DisableDelegate = _ => System.MapWindow.Close(),
|
||||
ToggleDelegate = _ => System.MapWindow.UnCollapseOrToggle(),
|
||||
});
|
||||
|
||||
System.CommandManager.RegisterCommand(new CommandHandler
|
||||
{
|
||||
ActivationPath = "/map/follow",
|
||||
Delegate = _ =>
|
||||
{
|
||||
System.SystemConfig.FollowPlayer = true;
|
||||
SystemConfig.Save();
|
||||
},
|
||||
});
|
||||
|
||||
System.CommandManager.RegisterCommand(new CommandHandler
|
||||
{
|
||||
ActivationPath = "/map/unfollow",
|
||||
Delegate = _ =>
|
||||
{
|
||||
System.SystemConfig.FollowPlayer = false;
|
||||
SystemConfig.Save();
|
||||
},
|
||||
});
|
||||
|
||||
System.CommandManager.RegisterCommand(new ToggleCommandHandler
|
||||
{
|
||||
BaseActivationPath = "/autofollow",
|
||||
EnableDelegate = _ =>
|
||||
{
|
||||
System.SystemConfig.FollowOnOpen = true;
|
||||
SystemConfig.Save();
|
||||
},
|
||||
DisableDelegate = _ =>
|
||||
{
|
||||
System.SystemConfig.FollowOnOpen = false;
|
||||
SystemConfig.Save();
|
||||
},
|
||||
ToggleDelegate = _ =>
|
||||
{
|
||||
System.SystemConfig.FollowOnOpen = !System.SystemConfig.FollowOnOpen;
|
||||
SystemConfig.Save();
|
||||
},
|
||||
});
|
||||
|
||||
System.CommandManager.RegisterCommand(new ToggleCommandHandler
|
||||
{
|
||||
BaseActivationPath = "/keepopen",
|
||||
EnableDelegate = _ =>
|
||||
{
|
||||
System.SystemConfig.KeepOpen = true;
|
||||
SystemConfig.Save();
|
||||
},
|
||||
DisableDelegate = _ =>
|
||||
{
|
||||
System.SystemConfig.KeepOpen = false;
|
||||
SystemConfig.Save();
|
||||
},
|
||||
ToggleDelegate = _ =>
|
||||
{
|
||||
System.SystemConfig.KeepOpen = !System.SystemConfig.KeepOpen;
|
||||
SystemConfig.Save();
|
||||
},
|
||||
});
|
||||
|
||||
System.CommandManager.RegisterCommand(new CommandHandler
|
||||
{
|
||||
ActivationPath = "/center/player",
|
||||
Delegate = _ =>
|
||||
{
|
||||
if (Service.ObjectTable.LocalPlayer is { } localPlayer) {
|
||||
System.MapRenderer.CenterOnGameObject(localPlayer);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
System.CommandManager.RegisterCommand(new CommandHandler
|
||||
{
|
||||
ActivationPath = "/center/map",
|
||||
Delegate = _ =>
|
||||
{
|
||||
System.SystemConfig.FollowPlayer = false;
|
||||
System.MapRenderer.DrawOffset = Vector2.Zero;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private static unsafe bool IsMapLocked()
|
||||
{
|
||||
var addon = Service.GameGui.GetAddonByName<AddonAreaMap>("AreaMap");
|
||||
if (addon is null || addon->RootNode is null) return false;
|
||||
|
||||
return (addon->Param & 0x8_0000) > 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
using KamiLib.Window;
|
||||
using Mappy.Controllers;
|
||||
using Mappy.Data;
|
||||
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
||||
|
||||
namespace Mappy.Windows;
|
||||
|
||||
public class MinimapWindow : Window
|
||||
{
|
||||
public MinimapWindow() : base("HSMappy Minimap###HSMappyMinimap", new Vector2(200.0f, 200.0f))
|
||||
{
|
||||
DisableWindowSounds = true;
|
||||
Flags |= ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoScrollWithMouse;
|
||||
}
|
||||
|
||||
public override bool DrawConditions() =>
|
||||
IntegrationsController.ShouldShowMinimap() && System.SystemConfig.ShowMinimap;
|
||||
|
||||
public override void PreOpenCheck()
|
||||
{
|
||||
if (Service.ClientState is { IsLoggedIn: false } or { IsPvP: true })
|
||||
IsOpen = false;
|
||||
}
|
||||
|
||||
protected override unsafe void DrawContents()
|
||||
{
|
||||
var agent = AgentMap.Instance();
|
||||
// Try loading from Lumina first so minimap can show without ever opening the area map
|
||||
if (!System.MapRenderer.HasMinimapCacheFor(agent->CurrentMapId) && agent->SelectedMapId != agent->CurrentMapId)
|
||||
System.MapRenderer.TryEnsureLuminaCacheFor(agent->CurrentMapId);
|
||||
|
||||
var mapLoaded = agent->SelectedMapId == agent->CurrentMapId || System.MapRenderer.HasMinimapCacheFor(agent->CurrentMapId);
|
||||
|
||||
if (!mapLoaded)
|
||||
{
|
||||
// Map data could not be loaded for this area (no Lumina path matched). Minimap shows automatically when data is available.
|
||||
const string hint = "Map unavailable for this area.";
|
||||
var textSize = ImGui.CalcTextSize(hint);
|
||||
var pos = (ImGui.GetWindowSize() - textSize) * 0.5f;
|
||||
ImGui.SetCursorPos(new Vector2(Math.Max(0, pos.X), Math.Max(20, pos.Y)));
|
||||
ImGui.TextColored(new Vector4(0.7f, 0.7f, 0.7f, 0.9f), hint);
|
||||
UpdateStyle();
|
||||
UpdateSizePosition();
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateStyle();
|
||||
UpdateSizePosition();
|
||||
|
||||
// Compensate for window padding: draw the minimap child so it fills the full window (no black bands).
|
||||
var padding = ImGui.GetStyle().WindowPadding;
|
||||
var winSize = ImGui.GetWindowSize();
|
||||
ImGui.SetCursorPos(new Vector2(-padding.X, -padding.Y));
|
||||
var contentSize = winSize;
|
||||
|
||||
if (contentSize.X <= 0 || contentSize.Y <= 0) return;
|
||||
|
||||
using (ImRaii.PushStyle(ImGuiStyleVar.Alpha, System.SystemConfig.MinimapOpacity))
|
||||
using (ImRaii.PushStyle(ImGuiStyleVar.ChildBorderSize, 0f))
|
||||
using (ImRaii.PushStyle(ImGuiStyleVar.WindowPadding, Vector2.Zero))
|
||||
using (var child = ImRaii.Child("minimap_render", contentSize, false, ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse))
|
||||
{
|
||||
if (child) {
|
||||
// Use window size so map fills the full window; renderer clamps draw position so map always covers the view.
|
||||
System.MapRenderer.DrawMinimapContents(contentSize);
|
||||
// Mouse wheel over minimap: zoom in/out, and consume wheel so the window doesn't scroll
|
||||
if (ImGui.IsItemHovered()) {
|
||||
var io = ImGui.GetIO();
|
||||
var wheel = io.MouseWheel;
|
||||
if (wheel != 0) {
|
||||
var zoom = System.SystemConfig.MinimapZoom;
|
||||
zoom -= wheel * 0.012f; // Small step so zoom is incremental between max out (0.1) and max in (0.03)
|
||||
System.SystemConfig.MinimapZoom = Math.Clamp(zoom, 0.03f, 0.112f);
|
||||
SystemConfig.Save();
|
||||
}
|
||||
// Consume wheel so the window doesn't scroll when at min/max zoom or when we handled it
|
||||
io.MouseWheel = 0f;
|
||||
io.MouseWheelH = 0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Restore default padding for the next window is done in plugin Draw callback (PopStyleVar after all windows).
|
||||
}
|
||||
|
||||
public override void OnOpen()
|
||||
{
|
||||
ImGui.SetWindowPos(System.SystemConfig.MinimapPosition);
|
||||
ImGui.SetWindowSize(new Vector2(System.SystemConfig.MinimapSize, System.SystemConfig.MinimapSize));
|
||||
}
|
||||
|
||||
private void UpdateStyle()
|
||||
{
|
||||
if (System.SystemConfig.MinimapLockPosition)
|
||||
Flags |= ImGuiWindowFlags.NoMove;
|
||||
else
|
||||
Flags &= ~ImGuiWindowFlags.NoMove;
|
||||
}
|
||||
|
||||
private void UpdateSizePosition()
|
||||
{
|
||||
var config = System.SystemConfig;
|
||||
var windowPosition = ImGui.GetWindowPos();
|
||||
var windowSize = ImGui.GetWindowSize();
|
||||
var configSize = config.MinimapSize;
|
||||
|
||||
// Size is config-only (set in Mappy settings); always apply config size to window.
|
||||
if (Math.Abs(windowSize.X - configSize) > 0.1f || Math.Abs(windowSize.Y - configSize) > 0.1f)
|
||||
ImGui.SetWindowSize(new Vector2(configSize, configSize));
|
||||
|
||||
if (!ImGui.IsWindowFocused(ImGuiFocusedFlags.RootAndChildWindows)) {
|
||||
// Not focused: apply config position to window
|
||||
if (windowPosition != config.MinimapPosition)
|
||||
ImGui.SetWindowPos(config.MinimapPosition);
|
||||
} else {
|
||||
// Focused: save window position to config (size is changed only via settings)
|
||||
if (config.MinimapPosition != windowPosition) {
|
||||
config.MinimapPosition = windowPosition;
|
||||
SystemConfig.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Utility;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
||||
using KamiLib.Classes;
|
||||
using KamiLib.Window;
|
||||
using Lumina.Excel.Sheets;
|
||||
using Mappy.Classes;
|
||||
using Mappy.Extensions;
|
||||
using Map = FFXIVClientStructs.FFXIV.Client.Game.UI.Map;
|
||||
|
||||
namespace Mappy.Windows;
|
||||
|
||||
public class QuestListWindow : Window
|
||||
{
|
||||
private readonly TabBar tabBar = new("questListTabBar", [
|
||||
new AcceptedQuestsTabItem(),
|
||||
new UnacceptedQuestsTabItem(),
|
||||
]);
|
||||
|
||||
public QuestListWindow() : base("HSMappy Quest List Window", new Vector2(300.0f, 500.0f))
|
||||
{
|
||||
AdditionalInfoTooltip = "Shows Quests for the zone you are currently in";
|
||||
}
|
||||
|
||||
protected override void DrawContents()
|
||||
{
|
||||
using var child = ImRaii.Child("quest_list_scrollable", ImGui.GetContentRegionAvail());
|
||||
if (!child) return;
|
||||
|
||||
tabBar.Draw();
|
||||
}
|
||||
|
||||
public override void OnClose()
|
||||
{
|
||||
System.WindowManager.RemoveWindow(this);
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe class UnacceptedQuestsTabItem : ITabItem
|
||||
{
|
||||
private const float ElementHeight = 48.0f;
|
||||
|
||||
public string Name => "Unaccepted Quests";
|
||||
|
||||
public bool Disabled => false;
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
if (Map.Instance()->UnacceptedQuestMarkers.Count > 0) {
|
||||
foreach (var quest in Map.Instance()->UnacceptedQuestMarkers) {
|
||||
var questData = Service.DataManager.GetExcelSheet<Quest>().GetRow(quest.ObjectiveId + 65536u);
|
||||
|
||||
foreach (var marker in quest.MarkerData) {
|
||||
var cursorStart = ImGui.GetCursorScreenPos();
|
||||
if (ImGui.Selectable($"##{quest.ObjectiveId}_Selectable_{marker.LevelId}", false, ImGuiSelectableFlags.None,
|
||||
new Vector2(ImGui.GetContentRegionAvail().X, ElementHeight * ImGuiHelpers.GlobalScale))) {
|
||||
System.IntegrationsController.OpenMap(marker.MapId);
|
||||
System.SystemConfig.FollowPlayer = false;
|
||||
|
||||
var mapOffsetVector = DrawHelpers.GetMapOffsetVector();
|
||||
System.MapRenderer.DrawOffset = -marker.Position.AsMapVector() * AgentMap.Instance()->SelectedMapSizeFactorFloat + mapOffsetVector;
|
||||
}
|
||||
|
||||
ImGui.SetCursorScreenPos(cursorStart);
|
||||
ImGui.Image(Service.TextureProvider.GetFromGameIcon(marker.IconId).GetWrapOrEmpty().Handle, ImGuiHelpers.ScaledVector2(ElementHeight, ElementHeight));
|
||||
|
||||
ImGui.SameLine();
|
||||
var text = $"Lv. {questData.ClassJobLevel.First()} {quest.Label}";
|
||||
|
||||
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + ElementHeight * ImGuiHelpers.GlobalScale / 2.0f - ImGui.CalcTextSize(text).Y / 2.0f);
|
||||
ImGui.Text(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const string text = "No quests available";
|
||||
var textSize = ImGui.CalcTextSize(text);
|
||||
ImGui.SetCursorPosX(ImGui.GetContentRegionAvail().X / 2.0f - textSize.X / 2.0f);
|
||||
ImGui.SetCursorPosY(ImGui.GetContentRegionAvail().Y / 2.0f - textSize.Y / 2.0f);
|
||||
ImGui.TextColored(KnownColor.Orange.Vector(), text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe class AcceptedQuestsTabItem : ITabItem
|
||||
{
|
||||
private const float ElementHeight = 48.0f;
|
||||
|
||||
public string Name => "Accepted Quests";
|
||||
|
||||
public bool Disabled => false;
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
if (AnyActiveQuests()) {
|
||||
foreach (var quest in Map.Instance()->QuestMarkers) {
|
||||
if (quest.ObjectiveId is 0) continue;
|
||||
|
||||
var questData = Service.DataManager.GetExcelSheet<Quest>().GetRow(quest.ObjectiveId + 65536u);
|
||||
|
||||
var index = 0;
|
||||
foreach (var marker in quest.MarkerData) {
|
||||
var cursorStart = ImGui.GetCursorScreenPos();
|
||||
if (ImGui.Selectable($"##{quest.ObjectiveId}_Selectable_{marker.LevelId}_{index++}", false, ImGuiSelectableFlags.None,
|
||||
new Vector2(ImGui.GetContentRegionAvail().X, ElementHeight * ImGuiHelpers.GlobalScale))) {
|
||||
System.IntegrationsController.OpenMap(marker.MapId);
|
||||
System.SystemConfig.FollowPlayer = false;
|
||||
System.MapRenderer.DrawOffset = -marker.Position.AsMapVector();
|
||||
}
|
||||
|
||||
var iconId = marker.IconId switch
|
||||
{
|
||||
>= 60483 and <= 60494 => DrawHelpers.QuestionMarkIcon,
|
||||
_ => marker.IconId,
|
||||
};
|
||||
|
||||
ImGui.SetCursorScreenPos(cursorStart);
|
||||
ImGui.Image(Service.TextureProvider.GetFromGameIcon(iconId).GetWrapOrEmpty().Handle, ImGuiHelpers.ScaledVector2(ElementHeight, ElementHeight));
|
||||
|
||||
ImGui.SameLine();
|
||||
var text = $"Lv. {questData.ClassJobLevel.First()} {quest.Label}";
|
||||
|
||||
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + ElementHeight * ImGuiHelpers.GlobalScale / 2.0f - ImGui.CalcTextSize(text).Y / 2.0f);
|
||||
ImGui.Text(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const string text = "No quests available";
|
||||
var textSize = ImGui.CalcTextSize(text);
|
||||
ImGui.SetCursorPosX(ImGui.GetContentRegionAvail().X / 2.0f - textSize.X / 2.0f);
|
||||
ImGui.SetCursorPosY(ImGui.GetContentRegionAvail().Y / 2.0f - textSize.Y / 2.0f);
|
||||
ImGui.TextColored(KnownColor.Orange.Vector(), text);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool AnyActiveQuests()
|
||||
{
|
||||
foreach (var questMarker in Map.Instance()->QuestMarkers) {
|
||||
if (questMarker.ObjectiveId is not 0) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user