add mcdo creation filters, upload all, apply data to all, more scaling bullshit

This commit is contained in:
Stanley Dimant
2025-02-23 14:08:25 +01:00
parent 286ef6d810
commit afda0416c0
5 changed files with 545 additions and 425 deletions

View File

@@ -608,6 +608,18 @@ public sealed partial class CharaDataManager : DisposableMediatorSubscriberBase
return _metaInfoCache.TryGetValue(key, out metaInfo); return _metaInfoCache.TryGetValue(key, out metaInfo);
} }
public void UploadAllCharaData()
{
UiBlockingComputation = Task.Run(async () =>
{
foreach (var updateDto in _updateDtos.Values.Where(u => u.HasChanges))
{
CharaUpdateTask = CharaUpdateAsync(updateDto);
await CharaUpdateTask.ConfigureAwait(false);
}
});
}
public void UploadCharaData(string id) public void UploadCharaData(string id)
{ {
var hasUpdateDto = _updateDtos.TryGetValue(id, out var updateDto); var hasUpdateDto = _updateDtos.TryGetValue(id, out var updateDto);
@@ -903,7 +915,6 @@ public sealed partial class CharaDataManager : DisposableMediatorSubscriberBase
var res = await _apiController.CharaDataUpdate(baseUpdateDto).ConfigureAwait(false); var res = await _apiController.CharaDataUpdate(baseUpdateDto).ConfigureAwait(false);
await AddOrUpdateDto(res).ConfigureAwait(false); await AddOrUpdateDto(res).ConfigureAwait(false);
CharaUpdateTask = null;
} }
private async Task DownloadAndAplyDataAsync(string charaName, CharaDataDownloadDto charaDataDownloadDto, CharaDataMetaInfoDto metaInfo, bool autoRevert = true) private async Task DownloadAndAplyDataAsync(string charaName, CharaDataDownloadDto charaDataDownloadDto, CharaDataMetaInfoDto metaInfo, bool autoRevert = true)

View File

@@ -45,7 +45,7 @@ internal sealed partial class CharaDataHubUi
_charaDataGposeTogetherManager.CreateNewLobby(); _charaDataGposeTogetherManager.CreateNewLobby();
} }
ImGuiHelpers.ScaledDummy(5); ImGuiHelpers.ScaledDummy(5);
ImGui.SetNextItemWidth(250); UiSharedService.ScaledNextItemWidth(250);
ImGui.InputTextWithHint("##lobbyId", "GPose Lobby Id", ref _joinLobbyId, 30); ImGui.InputTextWithHint("##lobbyId", "GPose Lobby Id", ref _joinLobbyId, 30);
if (_uiSharedService.IconTextButton(FontAwesomeIcon.ArrowRight, "Join GPose Together Lobby")) if (_uiSharedService.IconTextButton(FontAwesomeIcon.ArrowRight, "Join GPose Together Lobby"))
{ {
@@ -187,7 +187,7 @@ internal sealed partial class CharaDataHubUi
using (ImRaii.Disabled(!_uiSharedService.IsInGpose)) using (ImRaii.Disabled(!_uiSharedService.IsInGpose))
{ {
ImGui.SetNextItemWidth(200); UiSharedService.ScaledNextItemWidth(200);
using (var combo = ImRaii.Combo("##character", string.IsNullOrEmpty(user.AssociatedCharaName) ? "No character assigned" : CharaName(user.AssociatedCharaName))) using (var combo = ImRaii.Combo("##character", string.IsNullOrEmpty(user.AssociatedCharaName) ? "No character assigned" : CharaName(user.AssociatedCharaName)))
{ {
if (combo) if (combo)

View File

@@ -11,6 +11,11 @@ namespace MareSynchronos.UI;
internal sealed partial class CharaDataHubUi internal sealed partial class CharaDataHubUi
{ {
private string _createDescFilter = string.Empty;
private string _createCodeFilter = string.Empty;
private bool _createOnlyShowFav = false;
private bool _createOnlyShowNotDownloadable = false;
private void DrawEditCharaData(CharaDataFullExtendedDto? dataDto) private void DrawEditCharaData(CharaDataFullExtendedDto? dataDto)
{ {
using var imguiid = ImRaii.PushId(dataDto?.Id ?? "NoData"); using var imguiid = ImRaii.PushId(dataDto?.Id ?? "NoData");
@@ -30,8 +35,17 @@ internal sealed partial class CharaDataHubUi
return; return;
} }
int otherUpdates = 0;
foreach (var item in _charaDataManager.OwnCharaData.Values.Where(v => !string.Equals(v.Id, dataDto.Id, StringComparison.Ordinal)))
{
if (_charaDataManager.GetUpdateDto(item.Id)?.HasChanges ?? false)
{
otherUpdates++;
}
}
bool canUpdate = updateDto.HasChanges; bool canUpdate = updateDto.HasChanges;
if (canUpdate || _charaDataManager.CharaUpdateTask != null) if (canUpdate || otherUpdates > 0 || (!_charaDataManager.CharaUpdateTask?.IsCompleted ?? false))
{ {
ImGuiHelpers.ScaledDummy(5); ImGuiHelpers.ScaledDummy(5);
} }
@@ -91,9 +105,27 @@ internal sealed partial class CharaDataHubUi
} }
}); });
} }
if (otherUpdates > 0)
{
ImGuiHelpers.ScaledDummy(5);
UiSharedService.DrawGrouped(() =>
{
ImGui.AlignTextToFramePadding();
UiSharedService.ColorTextWrapped($"You have {otherUpdates} other entries with unsaved changes.", ImGuiColors.DalamudYellow);
ImGui.SameLine();
using (ImRaii.Disabled(_charaDataManager.CharaUpdateTask != null && !_charaDataManager.CharaUpdateTask.IsCompleted))
{
if (_uiSharedService.IconTextButton(FontAwesomeIcon.ArrowAltCircleUp, "Save all to server"))
{
_charaDataManager.UploadAllCharaData();
}
}
});
}
indent.Dispose(); indent.Dispose();
if (canUpdate || _charaDataManager.CharaUpdateTask != null) if (canUpdate || otherUpdates > 0 || (!_charaDataManager.CharaUpdateTask?.IsCompleted ?? false))
{ {
ImGuiHelpers.ScaledDummy(5); ImGuiHelpers.ScaledDummy(5);
} }
@@ -550,7 +582,7 @@ internal sealed partial class CharaDataHubUi
} }
using (var table = ImRaii.Table("Own Character Data", 12, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.ScrollY, using (var table = ImRaii.Table("Own Character Data", 12, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.ScrollY,
new Vector2(ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X, 110 * ImGuiHelpers.GlobalScale))) new Vector2(ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X, 140 * ImGuiHelpers.GlobalScale)))
{ {
if (table) if (table)
{ {
@@ -566,9 +598,64 @@ internal sealed partial class CharaDataHubUi
ImGui.TableSetupColumn("Glamourer", ImGuiTableColumnFlags.WidthFixed, 18 * ImGuiHelpers.GlobalScale); ImGui.TableSetupColumn("Glamourer", ImGuiTableColumnFlags.WidthFixed, 18 * ImGuiHelpers.GlobalScale);
ImGui.TableSetupColumn("Customize+", ImGuiTableColumnFlags.WidthFixed, 18 * ImGuiHelpers.GlobalScale); ImGui.TableSetupColumn("Customize+", ImGuiTableColumnFlags.WidthFixed, 18 * ImGuiHelpers.GlobalScale);
ImGui.TableSetupColumn("Expires", ImGuiTableColumnFlags.WidthFixed, 18 * ImGuiHelpers.GlobalScale); ImGui.TableSetupColumn("Expires", ImGuiTableColumnFlags.WidthFixed, 18 * ImGuiHelpers.GlobalScale);
ImGui.TableSetupScrollFreeze(0, 1); ImGui.TableSetupScrollFreeze(0, 2);
ImGui.TableHeadersRow(); ImGui.TableHeadersRow();
foreach (var entry in _charaDataManager.OwnCharaData.Values.OrderBy(b => b.CreatedDate))
ImGui.TableNextColumn();
ImGui.Dummy(new(0, 0));
ImGui.TableNextColumn();
ImGui.Checkbox("###createOnlyShowfav", ref _createOnlyShowFav);
UiSharedService.AttachToolTip("Filter by favorites");
ImGui.TableNextColumn();
var x1 = ImGui.GetContentRegionAvail().X;
ImGui.SetNextItemWidth(x1);
ImGui.InputTextWithHint("###createFilterCode", "Filter by code", ref _createCodeFilter, 200);
ImGui.TableNextColumn();
var x2 = ImGui.GetContentRegionAvail().X;
ImGui.SetNextItemWidth(x2);
ImGui.InputTextWithHint("###createFilterDesc", "Filter by description", ref _createDescFilter, 200);
ImGui.TableNextColumn();
ImGui.Dummy(new(0, 0));
ImGui.TableNextColumn();
ImGui.Dummy(new(0, 0));
ImGui.TableNextColumn();
ImGui.Dummy(new(0, 0));
ImGui.TableNextColumn();
ImGui.Checkbox("###createShowNotDl", ref _createOnlyShowNotDownloadable);
UiSharedService.AttachToolTip("Filter by not downloadable");
ImGui.TableNextColumn();
ImGui.Dummy(new(0, 0));
ImGui.TableNextColumn();
ImGui.Dummy(new(0, 0));
ImGui.TableNextColumn();
ImGui.Dummy(new(0, 0));
ImGui.TableNextColumn();
ImGui.Dummy(new(0, 0));
foreach (var entry in _charaDataManager.OwnCharaData.Values
.Where(v =>
{
bool show = true;
if (!string.IsNullOrWhiteSpace(_createCodeFilter))
{
show &= v.FullId.Contains(_createCodeFilter, StringComparison.OrdinalIgnoreCase);
}
if (!string.IsNullOrWhiteSpace(_createDescFilter))
{
show &= v.Description.Contains(_createDescFilter, StringComparison.OrdinalIgnoreCase);
}
if (_createOnlyShowFav)
{
show &= _configService.Current.FavoriteCodes.ContainsKey(v.FullId);
}
if (_createOnlyShowNotDownloadable)
{
show &= !(!v.HasMissingFiles && !string.IsNullOrEmpty(v.GlamourerData));
}
return show;
}).OrderBy(b => b.CreatedDate))
{ {
var uDto = _charaDataManager.GetUpdateDto(entry.Id); var uDto = _charaDataManager.GetUpdateDto(entry.Id);
ImGui.TableNextColumn(); ImGui.TableNextColumn();
@@ -729,7 +816,7 @@ internal sealed partial class CharaDataHubUi
_uiSharedService.DrawHelpText("Users added to this list will be able to access this character data regardless of your pause or pair state with them." + UiSharedService.TooltipSeparator _uiSharedService.DrawHelpText("Users added to this list will be able to access this character data regardless of your pause or pair state with them." + UiSharedService.TooltipSeparator
+ "Note: Mistyped entries will be automatically removed on updating data to server."); + "Note: Mistyped entries will be automatically removed on updating data to server.");
using (var lb = ImRaii.ListBox("Allowed Individuals", new(200, 200))) using (var lb = ImRaii.ListBox("Allowed Individuals", new(200 * ImGuiHelpers.GlobalScale, 200 * ImGuiHelpers.GlobalScale)))
{ {
foreach (var user in updateDto.UserList) foreach (var user in updateDto.UserList)
{ {
@@ -749,6 +836,28 @@ internal sealed partial class CharaDataHubUi
_selectedSpecificUserIndividual = string.Empty; _selectedSpecificUserIndividual = string.Empty;
} }
} }
using (ImRaii.Disabled(!UiSharedService.CtrlPressed()))
{
if (_uiSharedService.IconTextButton(FontAwesomeIcon.ExclamationTriangle, "Apply current Allowed Individuals to all MCDO entries"))
{
foreach (var own in _charaDataManager.OwnCharaData.Values.Where(k => !string.Equals(k.Id, updateDto.Id, StringComparison.Ordinal)))
{
var otherUpdateDto = _charaDataManager.GetUpdateDto(own.Id);
if (otherUpdateDto == null) continue;
foreach (var user in otherUpdateDto.UserList.Select(k => k.UID).Concat(otherUpdateDto.AllowedUsers ?? []).Distinct(StringComparer.Ordinal).ToList())
{
otherUpdateDto.RemoveUserFromList(user);
}
foreach (var user in updateDto.UserList.Select(k => k.UID).Concat(updateDto.AllowedUsers ?? []).Distinct(StringComparer.Ordinal).ToList())
{
otherUpdateDto.AddUserToList(user);
}
}
}
}
UiSharedService.AttachToolTip("This will apply the current list of allowed specific individuals to ALL of your MCDO entries." + UiSharedService.TooltipSeparator
+ "Hold CTRL to enable.");
} }
} }
ImGui.SameLine(); ImGui.SameLine();
@@ -776,7 +885,7 @@ internal sealed partial class CharaDataHubUi
_uiSharedService.DrawHelpText("Users in Syncshells added to this list will be able to access this character data regardless of your pause or pair state with them." + UiSharedService.TooltipSeparator _uiSharedService.DrawHelpText("Users in Syncshells added to this list will be able to access this character data regardless of your pause or pair state with them." + UiSharedService.TooltipSeparator
+ "Note: Mistyped entries will be automatically removed on updating data to server."); + "Note: Mistyped entries will be automatically removed on updating data to server.");
using (var lb = ImRaii.ListBox("Allowed Syncshells", new(200, 200))) using (var lb = ImRaii.ListBox("Allowed Syncshells", new(200 * ImGuiHelpers.GlobalScale, 200 * ImGuiHelpers.GlobalScale)))
{ {
foreach (var group in updateDto.GroupList) foreach (var group in updateDto.GroupList)
{ {
@@ -796,6 +905,28 @@ internal sealed partial class CharaDataHubUi
_selectedSpecificGroupIndividual = string.Empty; _selectedSpecificGroupIndividual = string.Empty;
} }
} }
using (ImRaii.Disabled(!UiSharedService.CtrlPressed()))
{
if (_uiSharedService.IconTextButton(FontAwesomeIcon.ExclamationTriangle, "Apply current Allowed Syncshells to all MCDO entries"))
{
foreach (var own in _charaDataManager.OwnCharaData.Values.Where(k => !string.Equals(k.Id, updateDto.Id, StringComparison.Ordinal)))
{
var otherUpdateDto = _charaDataManager.GetUpdateDto(own.Id);
if (otherUpdateDto == null) continue;
foreach (var group in otherUpdateDto.GroupList.Select(k => k.GID).Concat(otherUpdateDto.AllowedGroups ?? []).Distinct(StringComparer.Ordinal).ToList())
{
otherUpdateDto.RemoveGroupFromList(group);
}
foreach (var group in updateDto.GroupList.Select(k => k.GID).Concat(updateDto.AllowedGroups ?? []).Distinct(StringComparer.Ordinal).ToList())
{
otherUpdateDto.AddGroupToList(group);
}
}
}
}
UiSharedService.AttachToolTip("This will apply the current list of allowed specific syncshells to ALL of your MCDO entries." + UiSharedService.TooltipSeparator
+ "Hold CTRL to enable.");
} }
} }

View File

@@ -58,7 +58,7 @@ internal partial class CharaDataHubUi
} }
_uiSharedService.DrawHelpText("When enabled, Mare will draw floating wisps where other's poses are in the world."); _uiSharedService.DrawHelpText("When enabled, Mare will draw floating wisps where other's poses are in the world.");
int poseDetectionDistance = _configService.Current.NearbyDistanceFilter; int poseDetectionDistance = _configService.Current.NearbyDistanceFilter;
ImGui.SetNextItemWidth(100); UiSharedService.ScaledNextItemWidth(100);
if (ImGui.SliderInt("Detection Distance", ref poseDetectionDistance, 5, 1000)) if (ImGui.SliderInt("Detection Distance", ref poseDetectionDistance, 5, 1000))
{ {
_configService.Current.NearbyDistanceFilter = poseDetectionDistance; _configService.Current.NearbyDistanceFilter = poseDetectionDistance;

View File

@@ -34,58 +34,45 @@ namespace MareSynchronos.UI;
public partial class UiSharedService : DisposableMediatorSubscriberBase public partial class UiSharedService : DisposableMediatorSubscriberBase
{ {
public const string TooltipSeparator = "--SEP--"; public const string TooltipSeparator = "--SEP--";
public static string DoubleNewLine => Environment.NewLine + Environment.NewLine;
public static readonly ImGuiWindowFlags PopupWindowFlags = ImGuiWindowFlags.NoResize | public static readonly ImGuiWindowFlags PopupWindowFlags = ImGuiWindowFlags.NoResize |
ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollbar |
ImGuiWindowFlags.NoScrollWithMouse; ImGuiWindowFlags.NoScrollWithMouse;
public readonly FileDialogManager FileDialogManager; public readonly FileDialogManager FileDialogManager;
private const string _notesEnd = "##MARE_SYNCHRONOS_USER_NOTES_END##"; private const string _notesEnd = "##MARE_SYNCHRONOS_USER_NOTES_END##";
private const string _notesStart = "##MARE_SYNCHRONOS_USER_NOTES_START##"; private const string _notesStart = "##MARE_SYNCHRONOS_USER_NOTES_START##";
private readonly ApiController _apiController; private readonly ApiController _apiController;
private readonly CacheMonitor _cacheMonitor; private readonly CacheMonitor _cacheMonitor;
private readonly MareConfigService _configService; private readonly MareConfigService _configService;
private readonly DalamudUtilService _dalamudUtil; private readonly DalamudUtilService _dalamudUtil;
private readonly IpcManager _ipcManager; private readonly IpcManager _ipcManager;
private readonly Dalamud.Localization _localization; private readonly Dalamud.Localization _localization;
private readonly IDalamudPluginInterface _pluginInterface; private readonly IDalamudPluginInterface _pluginInterface;
private readonly ITextureProvider _textureProvider;
private readonly Dictionary<string, object?> _selectedComboItems = new(StringComparer.Ordinal); private readonly Dictionary<string, object?> _selectedComboItems = new(StringComparer.Ordinal);
private readonly ServerConfigurationManager _serverConfigurationManager; private readonly ServerConfigurationManager _serverConfigurationManager;
private readonly ITextureProvider _textureProvider;
private readonly TokenProvider _tokenProvider; private readonly TokenProvider _tokenProvider;
private bool _brioExists = false;
private bool _cacheDirectoryHasOtherFilesThanCache = false; private bool _cacheDirectoryHasOtherFilesThanCache = false;
private bool _cacheDirectoryIsValidPath = true; private bool _cacheDirectoryIsValidPath = true;
private bool _customizePlusExists = false; private bool _customizePlusExists = false;
private string _customServerName = ""; private string _customServerName = "";
private string _customServerUri = ""; private string _customServerUri = "";
private Task<Uri?>? _discordOAuthCheck;
private Task<string?>? _discordOAuthGetCode;
private CancellationTokenSource _discordOAuthGetCts = new();
private Task<Dictionary<string, string>>? _discordOAuthUIDs;
private bool _glamourerExists = false; private bool _glamourerExists = false;
private bool _heelsExists = false; private bool _heelsExists = false;
private bool _honorificExists = false; private bool _honorificExists = false;
private bool _isDirectoryWritable = false; private bool _isDirectoryWritable = false;
private bool _isOneDrive = false; private bool _isOneDrive = false;
private bool _isPenumbraDirectory = false; private bool _isPenumbraDirectory = false;
private bool _moodlesExists = false; private bool _moodlesExists = false;
private Dictionary<string, DateTime> _oauthTokenExpiry = new();
private bool _penumbraExists = false; private bool _penumbraExists = false;
private bool _petNamesExists = false; private bool _petNamesExists = false;
private bool _brioExists = false;
private int _serverSelectionIndex = -1; private int _serverSelectionIndex = -1;
private Dictionary<string, DateTime> _oauthTokenExpiry = new();
public UiSharedService(ILogger<UiSharedService> logger, IpcManager ipcManager, ApiController apiController, public UiSharedService(ILogger<UiSharedService> logger, IpcManager ipcManager, ApiController apiController,
CacheMonitor cacheMonitor, FileDialogManager fileDialogManager, CacheMonitor cacheMonitor, FileDialogManager fileDialogManager,
MareConfigService configService, DalamudUtilService dalamudUtil, IDalamudPluginInterface pluginInterface, MareConfigService configService, DalamudUtilService dalamudUtil, IDalamudPluginInterface pluginInterface,
@@ -131,6 +118,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
IconFont = _pluginInterface.UiBuilder.IconFontFixedWidthHandle; IconFont = _pluginInterface.UiBuilder.IconFontFixedWidthHandle;
} }
public static string DoubleNewLine => Environment.NewLine + Environment.NewLine;
public ApiController ApiController => _apiController; public ApiController ApiController => _apiController;
public bool EditTrackerPosition { get; set; } public bool EditTrackerPosition { get; set; }
@@ -141,12 +129,11 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
public IFontHandle IconFont { get; init; } public IFontHandle IconFont { get; init; }
public bool IsInGpose => _dalamudUtil.IsInGpose; public bool IsInGpose => _dalamudUtil.IsInGpose;
public Dictionary<uint, string> JobData => _dalamudUtil.JobData.Value;
public string PlayerName => _dalamudUtil.GetPlayerName(); public string PlayerName => _dalamudUtil.GetPlayerName();
public IFontHandle UidFont { get; init; } public IFontHandle UidFont { get; init; }
public Dictionary<ushort, string> WorldData => _dalamudUtil.WorldData.Value; public Dictionary<ushort, string> WorldData => _dalamudUtil.WorldData.Value;
public Dictionary<uint, string> JobData => _dalamudUtil.JobData.Value;
public uint WorldId => _dalamudUtil.GetHomeWorldId(); public uint WorldId => _dalamudUtil.GetHomeWorldId();
public static void AttachToolTip(string text) public static void AttachToolTip(string text)
@@ -221,6 +208,38 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
public static bool CtrlPressed() => (GetKeyState(0xA2) & 0x8000) != 0 || (GetKeyState(0xA3) & 0x8000) != 0; public static bool CtrlPressed() => (GetKeyState(0xA2) & 0x8000) != 0 || (GetKeyState(0xA3) & 0x8000) != 0;
public static void DrawGrouped(Action imguiDrawAction, float rounding = 5f, float? expectedWidth = null)
{
var cursorPos = ImGui.GetCursorPos();
using (ImRaii.Group())
{
if (expectedWidth != null)
{
ImGui.Dummy(new(expectedWidth.Value, 0));
ImGui.SetCursorPos(cursorPos);
}
imguiDrawAction.Invoke();
}
ImGui.GetWindowDrawList().AddRect(
ImGui.GetItemRectMin() - ImGui.GetStyle().ItemInnerSpacing,
ImGui.GetItemRectMax() + ImGui.GetStyle().ItemInnerSpacing,
Color(ImGuiColors.DalamudGrey2), rounding);
}
public static void DrawGroupedCenteredColorText(string text, Vector4 color, float? maxWidth = null)
{
var availWidth = ImGui.GetContentRegionAvail().X;
var textWidth = ImGui.CalcTextSize(text, availWidth).X;
if (maxWidth != null && textWidth > maxWidth * ImGuiHelpers.GlobalScale) textWidth = maxWidth.Value * ImGuiHelpers.GlobalScale;
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + (availWidth / 2f) - (textWidth / 2f));
DrawGrouped(() =>
{
ColorTextWrapped(text, color, ImGui.GetCursorPosX() + textWidth);
}, expectedWidth: maxWidth == null ? null : maxWidth * ImGuiHelpers.GlobalScale);
}
public static void DrawOutlinedFont(string text, Vector4 fontColor, Vector4 outlineColor, int thickness) public static void DrawOutlinedFont(string text, Vector4 fontColor, Vector4 outlineColor, int thickness)
{ {
var original = ImGui.GetCursorPos(); var original = ImGui.GetCursorPos();
@@ -277,18 +296,16 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
drawList.AddText(textPos, fontColor, text); drawList.AddText(textPos, fontColor, text);
} }
public static Vector4 GetBoolColor(bool input) => input ? ImGuiColors.ParsedGreen : ImGuiColors.DalamudRed; public static void DrawTree(string leafName, Action drawOnOpened, ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags.None)
public float GetIconTextButtonSize(FontAwesomeIcon icon, string text)
{ {
Vector2 vector; using var tree = ImRaii.TreeNode(leafName, flags);
using (IconFont.Push()) if (tree)
vector = ImGui.CalcTextSize(icon.ToIconString()); {
drawOnOpened();
Vector2 vector2 = ImGui.CalcTextSize(text);
float num = 3f * ImGuiHelpers.GlobalScale;
return vector.X + vector2.X + ImGui.GetStyle().FramePadding.X * 2f + num;
} }
}
public static Vector4 GetBoolColor(bool input) => input ? ImGuiColors.ParsedGreen : ImGuiColors.DalamudRed;
public static string GetNotes(List<Pair> pairs) public static string GetNotes(List<Pair> pairs)
{ {
@@ -311,69 +328,6 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
return ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X; return ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X;
} }
public bool IconButton(FontAwesomeIcon icon, float? height = null)
{
string text = icon.ToIconString();
ImGui.PushID(text);
Vector2 vector;
using (IconFont.Push())
vector = ImGui.CalcTextSize(text);
ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList();
Vector2 cursorScreenPos = ImGui.GetCursorScreenPos();
float x = vector.X + ImGui.GetStyle().FramePadding.X * 2f;
float frameHeight = height ?? ImGui.GetFrameHeight();
bool result = ImGui.Button(string.Empty, new Vector2(x, frameHeight));
Vector2 pos = new Vector2(cursorScreenPos.X + ImGui.GetStyle().FramePadding.X,
cursorScreenPos.Y + (height ?? ImGui.GetFrameHeight()) / 2f - (vector.Y / 2f));
using (IconFont.Push())
windowDrawList.AddText(pos, ImGui.GetColorU32(ImGuiCol.Text), text);
ImGui.PopID();
return result;
}
private bool IconTextButtonInternal(FontAwesomeIcon icon, string text, Vector4? defaultColor = null, float? width = null)
{
int num = 0;
if (defaultColor.HasValue)
{
ImGui.PushStyleColor(ImGuiCol.Button, defaultColor.Value);
num++;
}
ImGui.PushID(text);
Vector2 vector;
using (IconFont.Push())
vector = ImGui.CalcTextSize(icon.ToIconString());
Vector2 vector2 = ImGui.CalcTextSize(text);
ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList();
Vector2 cursorScreenPos = ImGui.GetCursorScreenPos();
float num2 = 3f * ImGuiHelpers.GlobalScale;
float x = width ?? vector.X + vector2.X + ImGui.GetStyle().FramePadding.X * 2f + num2;
float frameHeight = ImGui.GetFrameHeight();
bool result = ImGui.Button(string.Empty, new Vector2(x, frameHeight));
Vector2 pos = new Vector2(cursorScreenPos.X + ImGui.GetStyle().FramePadding.X, cursorScreenPos.Y + ImGui.GetStyle().FramePadding.Y);
using (IconFont.Push())
windowDrawList.AddText(pos, ImGui.GetColorU32(ImGuiCol.Text), icon.ToIconString());
Vector2 pos2 = new Vector2(pos.X + vector.X + num2, cursorScreenPos.Y + ImGui.GetStyle().FramePadding.Y);
windowDrawList.AddText(pos2, ImGui.GetColorU32(ImGuiCol.Text), text);
ImGui.PopID();
if (num > 0)
{
ImGui.PopStyleColor(num);
}
return result;
}
public bool IconTextButton(FontAwesomeIcon icon, string text, float? width = null, bool isInPopup = false)
{
return IconTextButtonInternal(icon, text,
isInPopup ? ColorHelpers.RgbaUintToVector4(ImGui.GetColorU32(ImGuiCol.PopupBg)) : null,
width <= 0 ? null : width);
}
public static bool IsDirectoryWritable(string dirPath, bool throwIfFails = false) public static bool IsDirectoryWritable(string dirPath, bool throwIfFails = false)
{ {
try try
@@ -396,6 +350,16 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
} }
} }
public static void ScaledNextItemWidth(float width)
{
ImGui.SetNextItemWidth(width * ImGuiHelpers.GlobalScale);
}
public static void ScaledSameLine(float offset)
{
ImGui.SameLine(offset * ImGuiHelpers.GlobalScale);
}
public static void SetScaledWindowSize(float width, bool centerWindow = true) public static void SetScaledWindowSize(float width, bool centerWindow = true)
{ {
var newLineHeight = ImGui.GetCursorPosY(); var newLineHeight = ImGui.GetCursorPosY();
@@ -641,284 +605,6 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
AttachToolTip(helpText); AttachToolTip(helpText);
} }
public bool DrawOtherPluginState()
{
var check = FontAwesomeIcon.Check;
var cross = FontAwesomeIcon.SquareXmark;
ImGui.TextUnformatted("Mandatory Plugins:");
ImGui.SameLine(150);
ColorText("Penumbra", GetBoolColor(_penumbraExists));
AttachToolTip($"Penumbra is " + (_penumbraExists ? "available and up to date." : "unavailable or not up to date."));
ImGui.SameLine();
ColorText("Glamourer", GetBoolColor(_glamourerExists));
AttachToolTip($"Glamourer is " + (_glamourerExists ? "available and up to date." : "unavailable or not up to date."));
ImGui.TextUnformatted("Optional Plugins:");
ImGui.SameLine(150);
ColorText("SimpleHeels", GetBoolColor(_heelsExists));
AttachToolTip($"SimpleHeels is " + (_heelsExists ? "available and up to date." : "unavailable or not up to date."));
ImGui.SameLine();
ColorText("Customize+", GetBoolColor(_customizePlusExists));
AttachToolTip($"Customize+ is " + (_customizePlusExists ? "available and up to date." : "unavailable or not up to date."));
ImGui.SameLine();
ColorText("Honorific", GetBoolColor(_honorificExists));
AttachToolTip($"Honorific is " + (_honorificExists ? "available and up to date." : "unavailable or not up to date."));
ImGui.SameLine();
ColorText("Moodles", GetBoolColor(_moodlesExists));
AttachToolTip($"Moodles is " + (_moodlesExists ? "available and up to date." : "unavailable or not up to date."));
ImGui.SameLine();
ColorText("PetNicknames", GetBoolColor(_petNamesExists));
AttachToolTip($"PetNicknames is " + (_petNamesExists ? "available and up to date." : "unavailable or not up to date."));
ImGui.SameLine();
ColorText("Brio", GetBoolColor(_brioExists));
AttachToolTip($"Brio is " + (_brioExists ? "available and up to date." : "unavailable or not up to date."));
if (!_penumbraExists || !_glamourerExists)
{
ImGui.TextColored(ImGuiColors.DalamudRed, "You need to install both Penumbra and Glamourer and keep them up to date to use Mare Synchronos.");
return false;
}
return true;
}
public int DrawServiceSelection(bool selectOnChange = false, bool showConnect = true)
{
string[] comboEntries = _serverConfigurationManager.GetServerNames();
if (_serverSelectionIndex == -1)
{
_serverSelectionIndex = Array.IndexOf(_serverConfigurationManager.GetServerApiUrls(), _serverConfigurationManager.CurrentApiUrl);
}
if (_serverSelectionIndex == -1 || _serverSelectionIndex >= comboEntries.Length)
{
_serverSelectionIndex = 0;
}
for (int i = 0; i < comboEntries.Length; i++)
{
if (string.Equals(_serverConfigurationManager.CurrentServer?.ServerName, comboEntries[i], StringComparison.OrdinalIgnoreCase))
comboEntries[i] += " [Current]";
}
if (ImGui.BeginCombo("Select Service", comboEntries[_serverSelectionIndex]))
{
for (int i = 0; i < comboEntries.Length; i++)
{
bool isSelected = _serverSelectionIndex == i;
if (ImGui.Selectable(comboEntries[i], isSelected))
{
_serverSelectionIndex = i;
if (selectOnChange)
{
_serverConfigurationManager.SelectServer(i);
}
}
if (isSelected)
{
ImGui.SetItemDefaultFocus();
}
}
ImGui.EndCombo();
}
if (showConnect)
{
ImGui.SameLine();
var text = "Connect";
if (_serverSelectionIndex == _serverConfigurationManager.CurrentServerIndex) text = "Reconnect";
if (IconTextButton(FontAwesomeIcon.Link, text))
{
_serverConfigurationManager.SelectServer(_serverSelectionIndex);
_ = _apiController.CreateConnectionsAsync();
}
}
if (ImGui.TreeNode("Add Custom Service"))
{
ImGui.SetNextItemWidth(250);
ImGui.InputText("Custom Service URI", ref _customServerUri, 255);
ImGui.SetNextItemWidth(250);
ImGui.InputText("Custom Service Name", ref _customServerName, 255);
if (IconTextButton(FontAwesomeIcon.Plus, "Add Custom Service")
&& !string.IsNullOrEmpty(_customServerUri)
&& !string.IsNullOrEmpty(_customServerName))
{
_serverConfigurationManager.AddServer(new ServerStorage()
{
ServerName = _customServerName,
ServerUri = _customServerUri,
UseOAuth2 = true
});
_customServerName = string.Empty;
_customServerUri = string.Empty;
_configService.Save();
}
ImGui.TreePop();
}
return _serverSelectionIndex;
}
public Vector2 GetIconButtonSize(FontAwesomeIcon icon)
{
using var font = IconFont.Push();
return ImGuiHelpers.GetButtonSize(icon.ToIconString());
}
public Vector2 GetIconSize(FontAwesomeIcon icon)
{
using var font = IconFont.Push();
return ImGui.CalcTextSize(icon.ToIconString());
}
public void IconText(FontAwesomeIcon icon, uint color)
{
FontText(icon.ToIconString(), IconFont, color);
}
public void IconText(FontAwesomeIcon icon, Vector4? color = null)
{
IconText(icon, color == null ? ImGui.GetColorU32(ImGuiCol.Text) : ImGui.GetColorU32(color.Value));
}
public IDalamudTextureWrap LoadImage(byte[] imageData)
{
return _textureProvider.CreateFromImageAsync(imageData).Result;
}
public void LoadLocalization(string languageCode)
{
_localization.SetupWithLangCode(languageCode);
Strings.ToS = new Strings.ToSStrings();
}
[LibraryImport("user32")]
internal static partial short GetKeyState(int nVirtKey);
private static void CenterWindow(float width, float height, ImGuiCond cond = ImGuiCond.None)
{
var center = ImGui.GetMainViewport().GetCenter();
ImGui.SetWindowPos(new Vector2(center.X - width / 2, center.Y - height / 2), cond);
}
[GeneratedRegex(@"^(?:[a-zA-Z]:\\[\w\s\-\\]+?|\/(?:[\w\s\-\/])+?)$", RegexOptions.ECMAScript, 5000)]
private static partial Regex PathRegex();
private void FontText(string text, IFontHandle font, Vector4? color = null)
{
FontText(text, font, color == null ? ImGui.GetColorU32(ImGuiCol.Text) : ImGui.GetColorU32(color.Value));
}
private void FontText(string text, IFontHandle font, uint color)
{
using var pushedFont = font.Push();
using var pushedColor = ImRaii.PushColor(ImGuiCol.Text, color);
ImGui.TextUnformatted(text);
}
public sealed record IconScaleData(Vector2 IconSize, Vector2 NormalizedIconScale, float OffsetX, float IconScaling);
protected override void Dispose(bool disposing)
{
if (!disposing) return;
base.Dispose(disposing);
UidFont.Dispose();
GameFont.Dispose();
}
private Task<Uri?>? _discordOAuthCheck;
private CancellationTokenSource _discordOAuthGetCts = new();
private Task<string?>? _discordOAuthGetCode;
private Task<Dictionary<string, string>>? _discordOAuthUIDs;
public void DrawUpdateOAuthUIDsButton(ServerStorage selectedServer)
{
if (!selectedServer.UseOAuth2)
return;
using (ImRaii.Disabled(string.IsNullOrEmpty(selectedServer.OAuthToken)))
{
if ((_discordOAuthUIDs == null || _discordOAuthUIDs.IsCompleted)
&& IconTextButton(FontAwesomeIcon.ArrowsSpin, "Update UIDs from Service")
&& !string.IsNullOrEmpty(selectedServer.OAuthToken))
{
_discordOAuthUIDs = _serverConfigurationManager.GetUIDsWithDiscordToken(selectedServer.ServerUri, selectedServer.OAuthToken);
}
}
DateTime tokenExpiry = DateTime.MinValue;
if (!string.IsNullOrEmpty(selectedServer.OAuthToken) && !_oauthTokenExpiry.TryGetValue(selectedServer.OAuthToken, out tokenExpiry))
{
try
{
var handler = new JwtSecurityTokenHandler();
var jwt = handler.ReadJwtToken(selectedServer.OAuthToken);
tokenExpiry = _oauthTokenExpiry[selectedServer.OAuthToken] = jwt.ValidTo;
}
catch (Exception ex)
{
Logger.LogWarning(ex, "Could not parse OAuth token, deleting");
selectedServer.OAuthToken = null;
_serverConfigurationManager.Save();
tokenExpiry = DateTime.MinValue;
}
}
if (string.IsNullOrEmpty(selectedServer.OAuthToken) || tokenExpiry < DateTime.UtcNow)
{
ColorTextWrapped("You have no OAuth token or the OAuth token is expired. Please use the Service Settings to (re)link your OAuth account.", ImGuiColors.DalamudRed);
}
}
private record UIDAliasPair(string? UID, string? Alias);
public void DrawUIDComboForAuthentication(int indexOffset, Authentication item, string serverUri, ILogger? logger = null)
{
using (ImRaii.Disabled(_discordOAuthUIDs == null))
{
var aliasPairs = _discordOAuthUIDs?.Result?.Select(t => new UIDAliasPair(t.Key, t.Value)).ToList() ?? [new UIDAliasPair(item.UID ?? null, null)];
var uidComboName = "UID###" + item.CharacterName + item.WorldId + serverUri + indexOffset + aliasPairs.Count;
DrawCombo(uidComboName, aliasPairs,
(v) =>
{
if (v is null)
return "No UID set";
if (!string.IsNullOrEmpty(v.Alias))
{
return $"{v.UID} ({v.Alias})";
}
if (string.IsNullOrEmpty(v.UID))
return "No UID set";
return $"{v.UID}";
},
(v) =>
{
if (!string.Equals(v?.UID ?? null, item.UID, StringComparison.Ordinal))
{
item.UID = v?.UID ?? null;
_serverConfigurationManager.Save();
}
},
aliasPairs.Find(f => string.Equals(f.UID, item.UID, StringComparison.Ordinal)) ?? default);
}
if (_discordOAuthUIDs == null)
{
AttachToolTip("Use the button above to update your UIDs from the service before you can assign UIDs to characters.");
}
}
public void DrawOAuth(ServerStorage selectedServer) public void DrawOAuth(ServerStorage selectedServer)
{ {
var oauthToken = selectedServer.OAuthToken; var oauthToken = selectedServer.OAuthToken;
@@ -1069,6 +755,169 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
} }
} }
public bool DrawOtherPluginState()
{
ImGui.TextUnformatted("Mandatory Plugins:");
ImGui.SameLine(150);
ColorText("Penumbra", GetBoolColor(_penumbraExists));
AttachToolTip($"Penumbra is " + (_penumbraExists ? "available and up to date." : "unavailable or not up to date."));
ImGui.SameLine();
ColorText("Glamourer", GetBoolColor(_glamourerExists));
AttachToolTip($"Glamourer is " + (_glamourerExists ? "available and up to date." : "unavailable or not up to date."));
ImGui.TextUnformatted("Optional Plugins:");
ImGui.SameLine(150);
ColorText("SimpleHeels", GetBoolColor(_heelsExists));
AttachToolTip($"SimpleHeels is " + (_heelsExists ? "available and up to date." : "unavailable or not up to date."));
ImGui.SameLine();
ColorText("Customize+", GetBoolColor(_customizePlusExists));
AttachToolTip($"Customize+ is " + (_customizePlusExists ? "available and up to date." : "unavailable or not up to date."));
ImGui.SameLine();
ColorText("Honorific", GetBoolColor(_honorificExists));
AttachToolTip($"Honorific is " + (_honorificExists ? "available and up to date." : "unavailable or not up to date."));
ImGui.SameLine();
ColorText("Moodles", GetBoolColor(_moodlesExists));
AttachToolTip($"Moodles is " + (_moodlesExists ? "available and up to date." : "unavailable or not up to date."));
ImGui.SameLine();
ColorText("PetNicknames", GetBoolColor(_petNamesExists));
AttachToolTip($"PetNicknames is " + (_petNamesExists ? "available and up to date." : "unavailable or not up to date."));
ImGui.SameLine();
ColorText("Brio", GetBoolColor(_brioExists));
AttachToolTip($"Brio is " + (_brioExists ? "available and up to date." : "unavailable or not up to date."));
if (!_penumbraExists || !_glamourerExists)
{
ImGui.TextColored(ImGuiColors.DalamudRed, "You need to install both Penumbra and Glamourer and keep them up to date to use Mare Synchronos.");
return false;
}
return true;
}
public int DrawServiceSelection(bool selectOnChange = false, bool showConnect = true)
{
string[] comboEntries = _serverConfigurationManager.GetServerNames();
if (_serverSelectionIndex == -1)
{
_serverSelectionIndex = Array.IndexOf(_serverConfigurationManager.GetServerApiUrls(), _serverConfigurationManager.CurrentApiUrl);
}
if (_serverSelectionIndex == -1 || _serverSelectionIndex >= comboEntries.Length)
{
_serverSelectionIndex = 0;
}
for (int i = 0; i < comboEntries.Length; i++)
{
if (string.Equals(_serverConfigurationManager.CurrentServer?.ServerName, comboEntries[i], StringComparison.OrdinalIgnoreCase))
comboEntries[i] += " [Current]";
}
if (ImGui.BeginCombo("Select Service", comboEntries[_serverSelectionIndex]))
{
for (int i = 0; i < comboEntries.Length; i++)
{
bool isSelected = _serverSelectionIndex == i;
if (ImGui.Selectable(comboEntries[i], isSelected))
{
_serverSelectionIndex = i;
if (selectOnChange)
{
_serverConfigurationManager.SelectServer(i);
}
}
if (isSelected)
{
ImGui.SetItemDefaultFocus();
}
}
ImGui.EndCombo();
}
if (showConnect)
{
ImGui.SameLine();
var text = "Connect";
if (_serverSelectionIndex == _serverConfigurationManager.CurrentServerIndex) text = "Reconnect";
if (IconTextButton(FontAwesomeIcon.Link, text))
{
_serverConfigurationManager.SelectServer(_serverSelectionIndex);
_ = _apiController.CreateConnectionsAsync();
}
}
if (ImGui.TreeNode("Add Custom Service"))
{
ImGui.SetNextItemWidth(250);
ImGui.InputText("Custom Service URI", ref _customServerUri, 255);
ImGui.SetNextItemWidth(250);
ImGui.InputText("Custom Service Name", ref _customServerName, 255);
if (IconTextButton(FontAwesomeIcon.Plus, "Add Custom Service")
&& !string.IsNullOrEmpty(_customServerUri)
&& !string.IsNullOrEmpty(_customServerName))
{
_serverConfigurationManager.AddServer(new ServerStorage()
{
ServerName = _customServerName,
ServerUri = _customServerUri,
UseOAuth2 = true
});
_customServerName = string.Empty;
_customServerUri = string.Empty;
_configService.Save();
}
ImGui.TreePop();
}
return _serverSelectionIndex;
}
public void DrawUIDComboForAuthentication(int indexOffset, Authentication item, string serverUri, ILogger? logger = null)
{
using (ImRaii.Disabled(_discordOAuthUIDs == null))
{
var aliasPairs = _discordOAuthUIDs?.Result?.Select(t => new UIDAliasPair(t.Key, t.Value)).ToList() ?? [new UIDAliasPair(item.UID ?? null, null)];
var uidComboName = "UID###" + item.CharacterName + item.WorldId + serverUri + indexOffset + aliasPairs.Count;
DrawCombo(uidComboName, aliasPairs,
(v) =>
{
if (v is null)
return "No UID set";
if (!string.IsNullOrEmpty(v.Alias))
{
return $"{v.UID} ({v.Alias})";
}
if (string.IsNullOrEmpty(v.UID))
return "No UID set";
return $"{v.UID}";
},
(v) =>
{
if (!string.Equals(v?.UID ?? null, item.UID, StringComparison.Ordinal))
{
item.UID = v?.UID ?? null;
_serverConfigurationManager.Save();
}
},
aliasPairs.Find(f => string.Equals(f.UID, item.UID, StringComparison.Ordinal)) ?? default);
}
if (_discordOAuthUIDs == null)
{
AttachToolTip("Use the button above to update your UIDs from the service before you can assign UIDs to characters.");
}
}
public void DrawUnlinkOAuthButton(ServerStorage selectedServer) public void DrawUnlinkOAuthButton(ServerStorage selectedServer)
{ {
using (ImRaii.Disabled(!CtrlPressed())) using (ImRaii.Disabled(!CtrlPressed()))
@@ -1083,54 +932,114 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
DrawHelpText("Hold CTRL to unlink the current OAuth2 connection."); DrawHelpText("Hold CTRL to unlink the current OAuth2 connection.");
} }
internal void RestOAuthTasksState() public void DrawUpdateOAuthUIDsButton(ServerStorage selectedServer)
{ {
_discordOAuthCheck = null; if (!selectedServer.UseOAuth2)
_discordOAuthGetCts = _discordOAuthGetCts.CancelRecreate(); return;
_discordOAuthGetCode = null;
_discordOAuthUIDs = null; using (ImRaii.Disabled(string.IsNullOrEmpty(selectedServer.OAuthToken)))
{
if ((_discordOAuthUIDs == null || _discordOAuthUIDs.IsCompleted)
&& IconTextButton(FontAwesomeIcon.ArrowsSpin, "Update UIDs from Service")
&& !string.IsNullOrEmpty(selectedServer.OAuthToken))
{
_discordOAuthUIDs = _serverConfigurationManager.GetUIDsWithDiscordToken(selectedServer.ServerUri, selectedServer.OAuthToken);
}
}
DateTime tokenExpiry = DateTime.MinValue;
if (!string.IsNullOrEmpty(selectedServer.OAuthToken) && !_oauthTokenExpiry.TryGetValue(selectedServer.OAuthToken, out tokenExpiry))
{
try
{
var handler = new JwtSecurityTokenHandler();
var jwt = handler.ReadJwtToken(selectedServer.OAuthToken);
tokenExpiry = _oauthTokenExpiry[selectedServer.OAuthToken] = jwt.ValidTo;
}
catch (Exception ex)
{
Logger.LogWarning(ex, "Could not parse OAuth token, deleting");
selectedServer.OAuthToken = null;
_serverConfigurationManager.Save();
tokenExpiry = DateTime.MinValue;
}
}
if (string.IsNullOrEmpty(selectedServer.OAuthToken) || tokenExpiry < DateTime.UtcNow)
{
ColorTextWrapped("You have no OAuth token or the OAuth token is expired. Please use the Service Settings to (re)link your OAuth account.", ImGuiColors.DalamudRed);
}
} }
public static void DrawGrouped(Action imguiDrawAction, float rounding = 5f, float? expectedWidth = null) public Vector2 GetIconButtonSize(FontAwesomeIcon icon)
{ {
var cursorPos = ImGui.GetCursorPos(); using var font = IconFont.Push();
using (ImRaii.Group()) return ImGuiHelpers.GetButtonSize(icon.ToIconString());
{
if (expectedWidth != null)
{
ImGui.Dummy(new(expectedWidth.Value, 0));
ImGui.SetCursorPos(cursorPos);
} }
imguiDrawAction.Invoke(); public Vector2 GetIconSize(FontAwesomeIcon icon)
{
using var font = IconFont.Push();
return ImGui.CalcTextSize(icon.ToIconString());
} }
ImGui.GetWindowDrawList().AddRect( public float GetIconTextButtonSize(FontAwesomeIcon icon, string text)
ImGui.GetItemRectMin() - ImGui.GetStyle().ItemInnerSpacing, {
ImGui.GetItemRectMax() + ImGui.GetStyle().ItemInnerSpacing, Vector2 vector;
Color(ImGuiColors.DalamudGrey2), rounding); using (IconFont.Push())
vector = ImGui.CalcTextSize(icon.ToIconString());
Vector2 vector2 = ImGui.CalcTextSize(text);
float num = 3f * ImGuiHelpers.GlobalScale;
return vector.X + vector2.X + ImGui.GetStyle().FramePadding.X * 2f + num;
} }
public static void DrawGroupedCenteredColorText(string text, Vector4 color, float? maxWidth = null) public bool IconButton(FontAwesomeIcon icon, float? height = null)
{ {
var availWidth = ImGui.GetContentRegionAvail().X; string text = icon.ToIconString();
var textWidth = ImGui.CalcTextSize(text, availWidth).X;
if (maxWidth != null && textWidth > maxWidth * ImGuiHelpers.GlobalScale) textWidth = maxWidth.Value * ImGuiHelpers.GlobalScale; ImGui.PushID(text);
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + (availWidth / 2f) - (textWidth / 2f)); Vector2 vector;
DrawGrouped(() => using (IconFont.Push())
{ vector = ImGui.CalcTextSize(text);
ColorTextWrapped(text, color, ImGui.GetCursorPosX() + textWidth); ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList();
}, expectedWidth: maxWidth == null ? null : maxWidth * ImGuiHelpers.GlobalScale); Vector2 cursorScreenPos = ImGui.GetCursorScreenPos();
float x = vector.X + ImGui.GetStyle().FramePadding.X * 2f;
float frameHeight = height ?? ImGui.GetFrameHeight();
bool result = ImGui.Button(string.Empty, new Vector2(x, frameHeight));
Vector2 pos = new Vector2(cursorScreenPos.X + ImGui.GetStyle().FramePadding.X,
cursorScreenPos.Y + (height ?? ImGui.GetFrameHeight()) / 2f - (vector.Y / 2f));
using (IconFont.Push())
windowDrawList.AddText(pos, ImGui.GetColorU32(ImGuiCol.Text), text);
ImGui.PopID();
return result;
} }
public static void ScaledSameLine(float offset) public void IconText(FontAwesomeIcon icon, uint color)
{ {
ImGui.SameLine(offset * ImGuiHelpers.GlobalScale); FontText(icon.ToIconString(), IconFont, color);
} }
public static void ScaledNextItemWidth(float width) public void IconText(FontAwesomeIcon icon, Vector4? color = null)
{ {
ImGui.SetNextItemWidth(width * ImGuiHelpers.GlobalScale); IconText(icon, color == null ? ImGui.GetColorU32(ImGuiCol.Text) : ImGui.GetColorU32(color.Value));
}
public bool IconTextButton(FontAwesomeIcon icon, string text, float? width = null, bool isInPopup = false)
{
return IconTextButtonInternal(icon, text,
isInPopup ? ColorHelpers.RgbaUintToVector4(ImGui.GetColorU32(ImGuiCol.PopupBg)) : null,
width <= 0 ? null : width);
}
public IDalamudTextureWrap LoadImage(byte[] imageData)
{
return _textureProvider.CreateFromImageAsync(imageData).Result;
}
public void LoadLocalization(string languageCode)
{
_localization.SetupWithLangCode(languageCode);
Strings.ToS = new Strings.ToSStrings();
} }
internal static void DistanceSeparator() internal static void DistanceSeparator()
@@ -1140,12 +1049,81 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
ImGuiHelpers.ScaledDummy(5); ImGuiHelpers.ScaledDummy(5);
} }
public static void DrawTree(string leafName, Action drawOnOpened, ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags.None) [LibraryImport("user32")]
internal static partial short GetKeyState(int nVirtKey);
internal void RestOAuthTasksState()
{ {
using var tree = ImRaii.TreeNode(leafName, flags); _discordOAuthCheck = null;
if (tree) _discordOAuthGetCts = _discordOAuthGetCts.CancelRecreate();
_discordOAuthGetCode = null;
_discordOAuthUIDs = null;
}
protected override void Dispose(bool disposing)
{ {
drawOnOpened(); if (!disposing) return;
base.Dispose(disposing);
UidFont.Dispose();
GameFont.Dispose();
} }
private static void CenterWindow(float width, float height, ImGuiCond cond = ImGuiCond.None)
{
var center = ImGui.GetMainViewport().GetCenter();
ImGui.SetWindowPos(new Vector2(center.X - width / 2, center.Y - height / 2), cond);
} }
[GeneratedRegex(@"^(?:[a-zA-Z]:\\[\w\s\-\\]+?|\/(?:[\w\s\-\/])+?)$", RegexOptions.ECMAScript, 5000)]
private static partial Regex PathRegex();
private static void FontText(string text, IFontHandle font, Vector4? color = null)
{
FontText(text, font, color == null ? ImGui.GetColorU32(ImGuiCol.Text) : ImGui.GetColorU32(color.Value));
}
private static void FontText(string text, IFontHandle font, uint color)
{
using var pushedFont = font.Push();
using var pushedColor = ImRaii.PushColor(ImGuiCol.Text, color);
ImGui.TextUnformatted(text);
}
private bool IconTextButtonInternal(FontAwesomeIcon icon, string text, Vector4? defaultColor = null, float? width = null)
{
int num = 0;
if (defaultColor.HasValue)
{
ImGui.PushStyleColor(ImGuiCol.Button, defaultColor.Value);
num++;
}
ImGui.PushID(text);
Vector2 vector;
using (IconFont.Push())
vector = ImGui.CalcTextSize(icon.ToIconString());
Vector2 vector2 = ImGui.CalcTextSize(text);
ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList();
Vector2 cursorScreenPos = ImGui.GetCursorScreenPos();
float num2 = 3f * ImGuiHelpers.GlobalScale;
float x = width ?? vector.X + vector2.X + ImGui.GetStyle().FramePadding.X * 2f + num2;
float frameHeight = ImGui.GetFrameHeight();
bool result = ImGui.Button(string.Empty, new Vector2(x, frameHeight));
Vector2 pos = new Vector2(cursorScreenPos.X + ImGui.GetStyle().FramePadding.X, cursorScreenPos.Y + ImGui.GetStyle().FramePadding.Y);
using (IconFont.Push())
windowDrawList.AddText(pos, ImGui.GetColorU32(ImGuiCol.Text), icon.ToIconString());
Vector2 pos2 = new Vector2(pos.X + vector.X + num2, cursorScreenPos.Y + ImGui.GetStyle().FramePadding.Y);
windowDrawList.AddText(pos2, ImGui.GetColorU32(ImGuiCol.Text), text);
ImGui.PopID();
if (num > 0)
{
ImGui.PopStyleColor(num);
}
return result;
}
public sealed record IconScaleData(Vector2 IconSize, Vector2 NormalizedIconScale, float OffsetX, float IconScaling);
private record UIDAliasPair(string? UID, string? Alias);
} }