Compare commits

...

8 Commits

Author SHA1 Message Date
defnotken
2f383c3ebe Version bump 2025-09-01 09:05:56 -05:00
defnotken
5dfd859542 Adding gitea workflow 2025-09-01 09:04:37 -05:00
Pim
beb737b267 Added functionality to rename groups (#12)
* Updated logos in Profile screen.

* Updated IPC calls for Petrenamer and bumped API version.

* IPC calls updated, APIVersion pushed for Moodles

* Updated version 1.11.4 in csproj

* Added Rename Tag UI for renaming of groups
2025-09-01 08:53:28 -05:00
azyges
68c0bf1334 random ui changes 2025-09-01 07:52:50 +09:00
azyges
05daa59e40 incorrect label.. 2025-08-31 10:02:02 +09:00
azyges
c3a6f2c88d fancy settings 2025-08-31 08:29:23 +09:00
defnotken
dc0265f614 1.11.4 Release Branch (#9)
* Updated logos in Profile screen. (#8)

* UI updates + bugfixes

* Updated version 1.11.4 in csproj

---------

Co-authored-by: Pim <48980200+CakeAndBanana@users.noreply.github.com>
2025-08-30 12:39:03 -05:00
defnotken
ba0e1cea08 Update lightless-tag-and-release.yml 2025-08-29 19:40:00 -05:00
16 changed files with 1009 additions and 518 deletions

View File

@@ -0,0 +1,182 @@
name: Tag and Release Lightless
on:
push:
branches: [ master ]
env:
PLUGIN_NAME: LightlessSync
DOTNET_VERSION: 9.x
jobs:
tag-and-release:
runs-on: ubuntu-22.04
permissions:
contents: write
steps:
- name: Checkout Lightless
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Setup .NET 9 SDK
uses: actions/setup-dotnet@v4
with:
dotnet-version: 9.x
- name: Download Dalamud
run: |
cd /
mkdir -p root/.xlcore/dalamud/Hooks/dev
curl -O https://goatcorp.github.io/dalamud-distrib/stg/latest.zip
unzip latest.zip -d /root/.xlcore/dalamud/Hooks/dev
- name: Lets Build Lightless!
run: |
dotnet restore
dotnet build --configuration Release --no-restore
dotnet publish --configuration Release --no-build
- name: Get version
id: package_version
uses: KageKirin/get-csproj-version@v0
with:
file: LightlessSync/LightlessSync.csproj
- name: Display version
run: |
echo "Version: ${{ steps.package_version.outputs.version }}"
- name: Prepare Lightless Client
run: |
PUBLISH_PATH="/workspace/Lightless-Sync/LightlessClient/LightlessSync/bin/x64/Release/publish/"
if [ -d "$PUBLISH_PATH" ]; then
rm -rf "$PUBLISH_PATH"
echo "Removed $PUBLISH_PATH"
else
echo "$PUBLISH_PATH does not exist, nothing to remove."
fi
mkdir -p output
(cd /workspace/Lightless-Sync/LightlessClient/LightlessSync/bin/x64/Release/ && zip -r $OLDPWD/output/LightlessClient.zip *)
- name: Create Git tag if not exists
run: |
tag="${{ steps.package_version.outputs.version }}"
git fetch --tags
if ! git tag -l "$tag" | grep -q "$tag"; then
echo "Tag $tag does not exist. Creating and pushing..."
git config user.name "GitHub Action"
git config user.email "action@github.com"
git tag "$tag"
git push origin "$tag"
else
echo "Tag $tag already exists. Skipping tag creation."
fi
- name: Create Release
id: create_release
run: |
echo "=== Searching for existing release ${{ steps.package_version.outputs.version }}==="
release_id=$(curl -s -H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \
"https://git.lightless-sync.org/api/v1/repos/${GITHUB_REPOSITORY}/releases/tags/${{ steps.package_version.outputs.version }}" | jq -r .id)
if [ "$release_id" != "null" ]; then
echo "=== Deleting existing release ${{ steps.package_version.outputs.version }}==="
curl -X DELETE -H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \
"https://git.lightless-sync.org/api/v1/repos/${GITHUB_REPOSITORY}/releases/$release_id"
fi
echo "=== Creating new release ${{ steps.package_version.outputs.version }}==="
response=$(
curl --fail-with-body -X POST \
-H "Content-Type: application/json" \
-H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \
-d '{
"tag_name": "${{ steps.package_version.outputs.version }}",
"name": "${{ steps.package_version.outputs.version }}",
"draft": false,
"prerelease": false
}' \
"https://git.lightless-sync.org/api/v1/repos/${GITHUB_REPOSITORY}/releases"
)
release_id=$(echo "$response" | jq -r .id)
echo "release_id=$release_id" >> "$GITHUB_OUTPUT"
- name: Upload Assets to release
run: |
curl --fail-with-body -s -X POST \
-H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \
-F "attachment=@output/LightlessClient.zip" \
"https://git.lightless-sync.org/api/v1/repos/${GITHUB_REPOSITORY}/releases/${{ steps.create_release.outputs.release_id }}/assets"
- name: Clone plugin hosting repo
run: |
mkdir LightlessSyncRepo
cd LightlessSyncRepo
git clone https://git.lightless-sync.org/${{ gitea.repository_owner }}/LightlessSync.git
env:
GIT_TERMINAL_PROMPT: 0
- name: Update plogonmaster.json with version
env:
VERSION: ${{ steps.package_version.outputs.version }}
run: |
set -e
pluginJsonPath="${PLUGIN_NAME}/bin/x64/Release/${PLUGIN_NAME}.json"
repoJsonPath="LightlessSyncRepo/LightlessSync/plogonmaster.json"
version="${VERSION}"
downloadUrl="https://git.lightless-sync.org/${{ gitea.repository_owner }}/LightlessClient/releases/download/$version/LightlessClient.zip"
# Read plugin JSON
pluginJson=$(cat "$pluginJsonPath")
internalName=$(jq -r '.InternalName' <<< "$pluginJson")
dalamudApiLevel=$(jq -r '.DalamudApiLevel' <<< "$pluginJson")
# Read repo JSON (force array if not already)
repoJsonRaw=$(cat "$repoJsonPath")
if echo "$repoJsonRaw" | jq 'type' | grep -q '"array"'; then
repoJson="$repoJsonRaw"
else
repoJson="[$repoJsonRaw]"
fi
# Update matching plugin entry
updatedRepoJson=$(jq \
--arg internalName "$internalName" \
--arg dalamudApiLevel "$dalamudApiLevel" \
--arg version "$version" \
--arg downloadUrl "$downloadUrl" \
'
map(
if .InternalName == $internalName
then
.DalamudApiLevel = $dalamudApiLevel
| .AssemblyVersion = $version
| .DownloadLinkInstall = $downloadUrl
| .DownloadLinkTesting = $downloadUrl
| .DownloadLinkUpdate = $downloadUrl
else
.
end
)
' <<< "$repoJson")
# Write back to file
echo "$updatedRepoJson" > "$repoJsonPath"
# Output the content of the file
cat "$repoJsonPath"
- name: Commit and push to LightlessSync
run: |
cd LightlessSyncRepo/LightlessSync
git config user.name "github-actions"
git config user.email "github-actions@github.com"
git add .
git diff-index --quiet HEAD || git commit -m "Update ${{ env.PLUGIN_NAME }} to ${{ steps.package_version.outputs.version }}"
git push https://x-access-token:${{ secrets.AUTOMATION_TOKEN }}@git.lightless-sync.org/${{ gitea.repository_owner }}/LightlessSync.git HEAD:main

View File

@@ -120,6 +120,16 @@ jobs:
$repoJson | ConvertTo-Json -Depth 100 | Set-Content $repoJsonPath
# Convert to JSON and force array brackets if necessary
$repoJsonString = $repoJson | ConvertTo-Json -Depth 100
# If the output is not an array, wrap it manually
if ($repoJsonString.Trim().StartsWith('{')) {
$repoJsonString = "[$repoJsonString]"
}
$repoJsonString | Set-Content $repoJsonPath
- name: Commit and push to LightlessSync
run: |
cd LightlessSyncRepo/LightlessSync

View File

@@ -27,9 +27,9 @@ public sealed class IpcCallerMoodles : IIpcCaller
_moodlesApiVersion = pi.GetIpcSubscriber<int>("Moodles.Version");
_moodlesOnChange = pi.GetIpcSubscriber<IPlayerCharacter, object>("Moodles.StatusManagerModified");
_moodlesGetStatus = pi.GetIpcSubscriber<nint, string>("Moodles.GetStatusManagerByPtr");
_moodlesSetStatus = pi.GetIpcSubscriber<nint, string, object>("Moodles.SetStatusManagerByPtr");
_moodlesRevertStatus = pi.GetIpcSubscriber<nint, object>("Moodles.ClearStatusManagerByPtr");
_moodlesGetStatus = pi.GetIpcSubscriber<nint, string>("Moodles.GetStatusManagerByPtrV2");
_moodlesSetStatus = pi.GetIpcSubscriber<nint, string, object>("Moodles.SetStatusManagerByPtrV2");
_moodlesRevertStatus = pi.GetIpcSubscriber<nint, object>("Moodles.ClearStatusManagerByPtrV2");
_moodlesOnChange.Subscribe(OnMoodlesChange);
@@ -47,7 +47,7 @@ public sealed class IpcCallerMoodles : IIpcCaller
{
try
{
APIAvailable = _moodlesApiVersion.InvokeFunc() == 1;
APIAvailable = _moodlesApiVersion.InvokeFunc() == 3;
}
catch
{

View File

@@ -30,12 +30,12 @@ public sealed class IpcCallerPetNames : IIpcCaller
_dalamudUtil = dalamudUtil;
_lightlessMediator = lightlessMediator;
_petnamesReady = pi.GetIpcSubscriber<object>("PetRenamer.Ready");
_petnamesDisposing = pi.GetIpcSubscriber<object>("PetRenamer.Disposing");
_petnamesReady = pi.GetIpcSubscriber<object>("PetRenamer.OnReady");
_petnamesDisposing = pi.GetIpcSubscriber<object>("PetRenamer.OnDisposing");
_apiVersion = pi.GetIpcSubscriber<(uint, uint)>("PetRenamer.ApiVersion");
_enabled = pi.GetIpcSubscriber<bool>("PetRenamer.Enabled");
_enabled = pi.GetIpcSubscriber<bool>("PetRenamer.IsEnabled");
_playerDataChanged = pi.GetIpcSubscriber<string, object>("PetRenamer.PlayerDataChanged");
_playerDataChanged = pi.GetIpcSubscriber<string, object>("PetRenamer.OnPlayerDataChanged");
_getPlayerData = pi.GetIpcSubscriber<string>("PetRenamer.GetPlayerData");
_setPlayerData = pi.GetIpcSubscriber<string, object>("PetRenamer.SetPlayerData");
_clearPlayerData = pi.GetIpcSubscriber<ushort, object>("PetRenamer.ClearPlayerData");
@@ -56,7 +56,7 @@ public sealed class IpcCallerPetNames : IIpcCaller
APIAvailable = _enabled?.InvokeFunc() ?? false;
if (APIAvailable)
{
APIAvailable = _apiVersion?.InvokeFunc() is { Item1: 3, Item2: >= 1 };
APIAvailable = _apiVersion?.InvokeFunc() is { Item1: 4, Item2: >= 0 };
}
}
catch

View File

@@ -3,7 +3,7 @@
<PropertyGroup>
<Authors></Authors>
<Company></Company>
<Version>1.11.3</Version>
<Version>1.11.5</Version>
<Description></Description>
<Copyright></Copyright>
<PackageProjectUrl>https://github.com/Light-Public-Syncshells/LightlessClient</PackageProjectUrl>

View File

@@ -72,8 +72,8 @@ public class Pair
Name = openProfileSeString,
OnClicked = (a) => _mediator.Publish(new ProfileOpenStandaloneMessage(this)),
UseDefaultPrefix = false,
PrefixChar = 'M',
PrefixColor = 526
PrefixChar = 'L',
PrefixColor = 708
});
args.AddMenuItem(new MenuItem()
@@ -81,8 +81,8 @@ public class Pair
Name = reapplyDataSeString,
OnClicked = (a) => ApplyLastReceivedData(forced: true),
UseDefaultPrefix = false,
PrefixChar = 'M',
PrefixColor = 526
PrefixChar = 'L',
PrefixColor = 708
});
args.AddMenuItem(new MenuItem()
@@ -90,8 +90,8 @@ public class Pair
Name = changePermissions,
OnClicked = (a) => _mediator.Publish(new OpenPermissionWindow(this)),
UseDefaultPrefix = false,
PrefixChar = 'M',
PrefixColor = 526
PrefixChar = 'L',
PrefixColor = 708
});
args.AddMenuItem(new MenuItem()
@@ -99,8 +99,8 @@ public class Pair
Name = cyclePauseState,
OnClicked = (a) => _mediator.Publish(new CyclePauseMessage(UserData)),
UseDefaultPrefix = false,
PrefixChar = 'M',
PrefixColor = 526
PrefixChar = 'L',
PrefixColor = 708
});
}

View File

@@ -130,6 +130,7 @@ public sealed class Plugin : IDalamudPlugin
s.GetRequiredService<CharaDataManager>(),
s.GetRequiredService<LightlessMediator>()));
collection.AddSingleton<SelectPairForTagUi>();
collection.AddSingleton<RenameTagUi>();
collection.AddSingleton((s) => new EventAggregator(pluginInterface.ConfigDirectory.FullName,
s.GetRequiredService<ILogger<EventAggregator>>(), s.GetRequiredService<LightlessMediator>()));
collection.AddSingleton((s) => new DalamudUtilService(s.GetRequiredService<ILogger<DalamudUtilService>>(),

File diff suppressed because one or more lines are too long

View File

@@ -38,6 +38,7 @@ public class CompactUi : WindowMediatorSubscriberBase
private readonly PairManager _pairManager;
private readonly SelectTagForPairUi _selectGroupForPairUi;
private readonly SelectPairForTagUi _selectPairsForGroupUi;
private readonly RenameTagUi _renameTagUi;
private readonly IpcManager _ipcManager;
private readonly ServerConfigurationManager _serverManager;
private readonly TopTabMenu _tabMenu;
@@ -56,7 +57,7 @@ public class CompactUi : WindowMediatorSubscriberBase
public CompactUi(ILogger<CompactUi> logger, UiSharedService uiShared, LightlessConfigService configService, ApiController apiController, PairManager pairManager,
ServerConfigurationManager serverManager, LightlessMediator mediator, FileUploadManager fileTransferManager,
TagHandler tagHandler, DrawEntityFactory drawEntityFactory, SelectTagForPairUi selectTagForPairUi, SelectPairForTagUi selectPairForTagUi,
TagHandler tagHandler, DrawEntityFactory drawEntityFactory, SelectTagForPairUi selectTagForPairUi, SelectPairForTagUi selectPairForTagUi, RenameTagUi renameTagUi,
PerformanceCollectorService performanceCollectorService, IpcManager ipcManager)
: base(logger, mediator, "###LightlessSyncMainUI", performanceCollectorService)
{
@@ -70,6 +71,7 @@ public class CompactUi : WindowMediatorSubscriberBase
_drawEntityFactory = drawEntityFactory;
_selectGroupForPairUi = selectTagForPairUi;
_selectPairsForGroupUi = selectPairForTagUi;
_renameTagUi = renameTagUi;
_ipcManager = ipcManager;
_tabMenu = new TopTabMenu(Mediator, _apiController, _pairManager, _uiSharedService);
@@ -149,10 +151,10 @@ public class CompactUi : WindowMediatorSubscriberBase
var uidTextSize = ImGui.CalcTextSize(unsupported);
ImGui.SetCursorPosX((ImGui.GetWindowContentRegionMax().X + ImGui.GetWindowContentRegionMin().X) / 2 - uidTextSize.X / 2);
ImGui.AlignTextToFramePadding();
ImGui.TextColored(ImGuiColors.DalamudRed, unsupported);
ImGui.TextColored(UIColors.Get("DimRed"), unsupported);
}
UiSharedService.ColorTextWrapped($"Your Lightless Sync installation is out of date, the current version is {ver.Major}.{ver.Minor}.{ver.Build}. " +
$"It is highly recommended to keep Lightless Sync up to date. Open /xlplugins and update the plugin.", ImGuiColors.DalamudRed);
$"It is highly recommended to keep Lightless Sync up to date. Open /xlplugins and update the plugin.", UIColors.Get("DimRed"));
}
if (!_ipcManager.Initialized)
@@ -164,12 +166,12 @@ public class CompactUi : WindowMediatorSubscriberBase
var uidTextSize = ImGui.CalcTextSize(unsupported);
ImGui.SetCursorPosX((ImGui.GetWindowContentRegionMax().X + ImGui.GetWindowContentRegionMin().X) / 2 - uidTextSize.X / 2);
ImGui.AlignTextToFramePadding();
ImGui.TextColored(ImGuiColors.DalamudRed, unsupported);
ImGui.TextColored(UIColors.Get("DimRed"), unsupported);
}
var penumAvailable = _ipcManager.Penumbra.APIAvailable;
var glamAvailable = _ipcManager.Glamourer.APIAvailable;
UiSharedService.ColorTextWrapped($"One or more Plugins essential for Lightless operation are unavailable. Enable or update following plugins:", ImGuiColors.DalamudRed);
UiSharedService.ColorTextWrapped($"One or more Plugins essential for Lightless operation are unavailable. Enable or update following plugins:", UIColors.Get("DimRed"));
using var indent = ImRaii.PushIndent(10f);
if (!penumAvailable)
{
@@ -185,7 +187,7 @@ public class CompactUi : WindowMediatorSubscriberBase
}
using (ImRaii.PushId("header")) DrawUIDHeader();
ImGui.Separator();
_uiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 2f);
using (ImRaii.PushId("serverstatus")) DrawServerStatus();
ImGui.Separator();
@@ -198,6 +200,7 @@ public class CompactUi : WindowMediatorSubscriberBase
using (ImRaii.PushId("transfers")) DrawTransfers();
_transferPartHeight = ImGui.GetCursorPosY() - pairlistEnd - ImGui.GetTextLineHeight();
using (ImRaii.PushId("group-user-popup")) _selectPairsForGroupUi.Draw(_pairManager.DirectPairs);
using (ImRaii.PushId("group-user-edit")) _renameTagUi.Draw(_pairManager.DirectPairs);
using (ImRaii.PushId("grouping-popup")) _selectGroupForPairUi.Draw();
}
@@ -284,7 +287,7 @@ public class CompactUi : WindowMediatorSubscriberBase
else
{
ImGui.AlignTextToFramePadding();
ImGui.TextColored(ImGuiColors.DalamudRed, "Not connected to any server");
ImGui.TextColored(UIColors.Get("DimRed"), "Not connected to any server");
}
if (printShard)
@@ -587,21 +590,21 @@ public class CompactUi : WindowMediatorSubscriberBase
{
return _apiController.ServerState switch
{
ServerState.Connecting => ImGuiColors.DalamudYellow,
ServerState.Reconnecting => ImGuiColors.DalamudRed,
ServerState.Connecting => UIColors.Get("LightlessYellow"),
ServerState.Reconnecting => UIColors.Get("DimRed"),
ServerState.Connected => UIColors.Get("LightlessPurple"),
ServerState.Disconnected => ImGuiColors.DalamudYellow,
ServerState.Disconnecting => ImGuiColors.DalamudYellow,
ServerState.Unauthorized => ImGuiColors.DalamudRed,
ServerState.VersionMisMatch => ImGuiColors.DalamudRed,
ServerState.Offline => ImGuiColors.DalamudRed,
ServerState.RateLimited => ImGuiColors.DalamudYellow,
ServerState.NoSecretKey => ImGuiColors.DalamudYellow,
ServerState.MultiChara => ImGuiColors.DalamudYellow,
ServerState.OAuthMisconfigured => ImGuiColors.DalamudRed,
ServerState.OAuthLoginTokenStale => ImGuiColors.DalamudRed,
ServerState.NoAutoLogon => ImGuiColors.DalamudYellow,
_ => ImGuiColors.DalamudRed
ServerState.Disconnected => UIColors.Get("LightlessYellow"),
ServerState.Disconnecting => UIColors.Get("LightlessYellow"),
ServerState.Unauthorized => UIColors.Get("DimRed"),
ServerState.VersionMisMatch => UIColors.Get("DimRed"),
ServerState.Offline => UIColors.Get("DimRed"),
ServerState.RateLimited => UIColors.Get("LightlessYellow"),
ServerState.NoSecretKey => UIColors.Get("LightlessYellow"),
ServerState.MultiChara => UIColors.Get("LightlessYellow"),
ServerState.OAuthMisconfigured => UIColors.Get("DimRed"),
ServerState.OAuthLoginTokenStale => UIColors.Get("DimRed"),
ServerState.NoAutoLogon => UIColors.Get("LightlessYellow"),
_ => UIColors.Get("DimRed")
};
}

View File

@@ -13,13 +13,15 @@ public class DrawFolderTag : DrawFolderBase
{
private readonly ApiController _apiController;
private readonly SelectPairForTagUi _selectPairForTagUi;
private readonly RenameTagUi _renameTagUi;
public DrawFolderTag(string id, IImmutableList<DrawUserPair> drawPairs, IImmutableList<Pair> allPairs,
TagHandler tagHandler, ApiController apiController, SelectPairForTagUi selectPairForTagUi, UiSharedService uiSharedService)
TagHandler tagHandler, ApiController apiController, SelectPairForTagUi selectPairForTagUi, RenameTagUi renameTagUi, UiSharedService uiSharedService)
: base(id, drawPairs, allPairs, tagHandler, uiSharedService)
{
_apiController = apiController;
_selectPairForTagUi = selectPairForTagUi;
_renameTagUi = renameTagUi;
}
protected override bool RenderIfEmpty => _id switch
@@ -100,12 +102,15 @@ public class DrawFolderTag : DrawFolderBase
protected override void DrawMenu(float menuWidth)
{
ImGui.TextUnformatted("Group Menu");
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Users, "Select Pairs", menuWidth, true))
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Users, "Select Pairs", menuWidth, isInPopup: true))
{
_selectPairForTagUi.Open(_id);
}
UiSharedService.AttachToolTip("Select Individual Pairs for this Pair Group");
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Delete Pair Group", menuWidth, true) && UiSharedService.CtrlPressed())
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Edit, "Rename Pair Group", menuWidth, isInPopup: true))
{
_renameTagUi.Open(_id);
}
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Delete Pair Group", menuWidth, isInPopup: true) && UiSharedService.CtrlPressed())
{
_tagHandler.RemoveTag(_id);
}

View File

@@ -0,0 +1,93 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using LightlessSync.PlayerData.Pairs;
using LightlessSync.UI.Handlers;
using System.Numerics;
namespace LightlessSync.UI.Components;
public class RenameTagUi
{
private readonly TagHandler _tagHandler;
private readonly UiSharedService _uiSharedService;
private string _desiredName = string.Empty;
private bool _opened = false;
private HashSet<string> _peopleInGroup = new(StringComparer.Ordinal);
private bool _show = false;
private string _tag = string.Empty;
public RenameTagUi(TagHandler tagHandler, UiSharedService uiSharedService)
{
_tagHandler = tagHandler;
_uiSharedService = uiSharedService;
}
public void Draw(List<Pair> pairs)
{
var workHeight = ImGui.GetMainViewport().WorkSize.Y / ImGuiHelpers.GlobalScale;
var minSize = new Vector2(300, workHeight < 110 ? workHeight : 110) * ImGuiHelpers.GlobalScale;
var maxSize = new Vector2(300, 110) * ImGuiHelpers.GlobalScale;
var popupName = $"Renaming Group {_tag}";
if (!_show)
{
_opened = false;
}
if (_show && !_opened)
{
ImGui.SetNextWindowSize(minSize);
UiSharedService.CenterNextWindow(minSize.X, minSize.Y, ImGuiCond.Always);
ImGui.OpenPopup(popupName);
_opened = true;
}
ImGui.SetNextWindowSizeConstraints(minSize, maxSize);
if (ImGui.BeginPopupModal(popupName, ref _show, ImGuiWindowFlags.Popup | ImGuiWindowFlags.Modal))
{
ImGui.TextUnformatted($"Renaming {_tag}");
ImGui.InputTextWithHint("##desiredname", "Enter new group name", ref _desiredName, 255, ImGuiInputTextFlags.None);
using (ImRaii.Disabled(string.IsNullOrEmpty(_desiredName)))
{
if (_uiSharedService.IconTextButton(Dalamud.Interface.FontAwesomeIcon.Plus, "Rename Group"))
{
RenameTag(pairs, _tag, _desiredName);
_show = false;
}
}
ImGui.EndPopup();
}
else
{
_show = false;
}
}
public void Open(string tag)
{
_peopleInGroup = _tagHandler.GetOtherUidsForTag(tag);
_tag = tag;
_desiredName = "";
_show = true;
}
public void RenameTag(List<Pair> pairs, string oldTag, string newTag)
{
//Removal of old tag
_tagHandler.RemoveTag(oldTag);
//Creation of new tag and adding of old group pairs in new one.
_tagHandler.AddTag(newTag);
foreach (Pair pair in pairs)
{
var isInTag = _peopleInGroup.Contains(pair.UserData.UID);
if (isInTag)
{
_tagHandler.AddTagToPairedUid(pair.UserData.UID, newTag);
}
}
}
}

View File

@@ -23,11 +23,12 @@ public class DrawEntityFactory
private readonly PlayerPerformanceConfigService _playerPerformanceConfigService;
private readonly CharaDataManager _charaDataManager;
private readonly SelectTagForPairUi _selectTagForPairUi;
private readonly RenameTagUi _renameTagUi;
private readonly TagHandler _tagHandler;
private readonly IdDisplayHandler _uidDisplayHandler;
public DrawEntityFactory(ILogger<DrawEntityFactory> logger, ApiController apiController, IdDisplayHandler uidDisplayHandler,
SelectTagForPairUi selectTagForPairUi, LightlessMediator mediator,
SelectTagForPairUi selectTagForPairUi, RenameTagUi renameTagUi, LightlessMediator mediator,
TagHandler tagHandler, SelectPairForTagUi selectPairForTagUi,
ServerConfigurationManager serverConfigurationManager, UiSharedService uiSharedService,
PlayerPerformanceConfigService playerPerformanceConfigService, CharaDataManager charaDataManager)
@@ -36,6 +37,7 @@ public class DrawEntityFactory
_apiController = apiController;
_uidDisplayHandler = uidDisplayHandler;
_selectTagForPairUi = selectTagForPairUi;
_renameTagUi = renameTagUi;
_mediator = mediator;
_tagHandler = tagHandler;
_selectPairForTagUi = selectPairForTagUi;
@@ -58,8 +60,8 @@ public class DrawEntityFactory
Dictionary<Pair, List<GroupFullInfoDto>> filteredPairs,
IImmutableList<Pair> allPairs)
{
return new(tag, filteredPairs.Select(u => CreateDrawPair(tag, u.Key, u.Value, null)).ToImmutableList(),
allPairs, _tagHandler, _apiController, _selectPairForTagUi, _uiSharedService);
return new(tag, filteredPairs.Select(u => CreateDrawPair(tag, u.Key, u.Value, currentGroup: null)).ToImmutableList(),
allPairs, _tagHandler, _apiController, _selectPairForTagUi, _renameTagUi, _uiSharedService);
}
public DrawUserPair CreateDrawPair(string id, Pair user, List<GroupFullInfoDto> groups, GroupFullInfoDto? currentGroup)

View File

@@ -102,7 +102,7 @@ public class PermissionWindowUI : WindowMediatorSubscriberBase
{
_ownPermissions.SetDisableAnimations(disableAnimations);
}
_uiSharedService.DrawHelpText("Disabling sounds will remove all animations synced with this user on both sides." + UiSharedService.TooltipSeparator
_uiSharedService.DrawHelpText("Disabling animations will remove all animations synced with this user on both sides." + UiSharedService.TooltipSeparator
+ "Note: this is bidirectional, either user disabling animation sync will stop animation sync on both sides.");
using (ImRaii.PushIndent(indentSize, false))
{
@@ -116,7 +116,7 @@ public class PermissionWindowUI : WindowMediatorSubscriberBase
{
_ownPermissions.SetDisableVFX(disableVfx);
}
_uiSharedService.DrawHelpText("Disabling sounds will remove all VFX synced with this user on both sides." + UiSharedService.TooltipSeparator
_uiSharedService.DrawHelpText("Disabling VFX will remove all VFX synced with this user on both sides." + UiSharedService.TooltipSeparator
+ "Note: this is bidirectional, either user disabling VFX sync will stop VFX sync on both sides.");
using (ImRaii.PushIndent(indentSize, false))
{

View File

@@ -214,7 +214,8 @@ public class SettingsUi : WindowMediatorSubscriberBase
private void DrawCurrentTransfers()
{
_lastTab = "Transfers";
_uiShared.BigText("Transfer Settings");
_uiShared.UnderlinedBigText("Transfer Settings", UIColors.Get("LightlessBlue"));
ImGuiHelpers.ScaledDummy(5);
int maxParallelDownloads = _configService.Current.ParallelDownloads;
bool useAlternativeUpload = _configService.Current.UseAlternativeFileUpload;
@@ -263,7 +264,8 @@ public class SettingsUi : WindowMediatorSubscriberBase
_uiShared.DrawHelpText("This will attempt to upload files in one go instead of a stream. Typically not necessary to enable. Use if you have upload issues.");
ImGui.Separator();
_uiShared.BigText("Transfer UI");
_uiShared.UnderlinedBigText("Transfer UI", UIColors.Get("LightlessBlue"));
ImGuiHelpers.ScaledDummy(5);
bool showTransferWindow = _configService.Current.ShowTransferWindow;
if (ImGui.Checkbox("Show separate transfer window", ref showTransferWindow))
@@ -400,7 +402,8 @@ public class SettingsUi : WindowMediatorSubscriberBase
}
ImGui.Separator();
_uiShared.BigText("Current Transfers");
_uiShared.UnderlinedBigText("Current Transfers", UIColors.Get("LightlessBlue"));
ImGuiHelpers.ScaledDummy(5);
if (ImGui.BeginTabBar("TransfersTabBar"))
{
@@ -561,7 +564,8 @@ public class SettingsUi : WindowMediatorSubscriberBase
{
_lastTab = "Debug";
_uiShared.BigText("Debug");
_uiShared.UnderlinedBigText("Debug", UIColors.Get("LightlessYellow"));
ImGuiHelpers.ScaledDummy(10);
#if DEBUG
if (LastCreatedCharacterData != null && ImGui.TreeNode("Last created character data"))
{
@@ -621,13 +625,15 @@ public class SettingsUi : WindowMediatorSubscriberBase
}
_uiShared.DrawHelpText("Having modified game files will still mark your logs with UNSUPPORTED and you will not receive support, message shown or not." + UiSharedService.TooltipSeparator
+ "Keeping LOD enabled can lead to more crashes. Use at your own risk.");
_uiShared.ColoredSeparator(UIColors.Get("LightlessYellow"), 2f);
}
private void DrawFileStorageSettings()
{
_lastTab = "FileCache";
_uiShared.BigText("Export MCDF");
_uiShared.UnderlinedBigText("Export MCDF", UIColors.Get("LightlessBlue"));
ImGuiHelpers.ScaledDummy(10);
@@ -646,7 +652,8 @@ public class SettingsUi : WindowMediatorSubscriberBase
ImGuiHelpers.ScaledDummy(5);
ImGui.Separator();
_uiShared.BigText("Storage");
_uiShared.UnderlinedBigText("Storage", UIColors.Get("LightlessBlue"));
ImGuiHelpers.ScaledDummy(5);
UiSharedService.TextWrapped("Lightless stores downloaded files from paired people permanently. This is to improve loading performance and requiring less downloads. " +
"The storage governs itself by clearing data beyond the set storage size. Please set the storage size accordingly. It is not necessary to manually clear the storage.");
@@ -759,6 +766,9 @@ public class SettingsUi : WindowMediatorSubscriberBase
ImGuiHelpers.ScaledDummy(new Vector2(10, 10));
ImGui.Separator();
if (_uiShared.MediumTreeNode("Storage Validation", UIColors.Get("LightlessYellow")))
{
UiSharedService.TextWrapped("File Storage validation can make sure that all files in your local Lightless Storage are valid. " +
"Run the validation before you clear the Storage for no reason. " + Environment.NewLine +
"This operation, depending on how many files you have in your storage, can take a while and will be CPU and drive intensive.");
@@ -798,9 +808,15 @@ public class SettingsUi : WindowMediatorSubscriberBase
}
}
}
_uiShared.ColoredSeparator(UIColors.Get("LightlessYellow"), 1.5f);
ImGui.TreePop();
}
ImGui.Separator();
ImGuiHelpers.ScaledDummy(new Vector2(10, 10));
if (_uiShared.MediumTreeNode("Storage Clearing", UIColors.Get("DimRed")))
{
ImGui.TextUnformatted("To clear the local storage accept the following disclaimer");
ImGui.Indent();
ImGui.Checkbox("##readClearCache", ref _readClearCache);
@@ -827,6 +843,10 @@ public class SettingsUi : WindowMediatorSubscriberBase
if (!_readClearCache)
ImGui.EndDisabled();
ImGui.Unindent();
_uiShared.ColoredSeparator(UIColors.Get("DimRed"), 1.5f);
ImGui.TreePop();
}
}
private void DrawGeneral()
@@ -840,7 +860,12 @@ public class SettingsUi : WindowMediatorSubscriberBase
//UiSharedService.FontText("Experimental", _uiShared.UidFont);
//ImGui.Separator();
_uiShared.UnderlinedBigText("General Settings", UIColors.Get("LightlessBlue"));
ImGui.Dummy(new Vector2(10));
_uiShared.BigText("Notes");
if (_uiShared.MediumTreeNode("Import & Export", UIColors.Get("LightlessPurple")))
{
if (_uiShared.IconTextButton(FontAwesomeIcon.StickyNote, "Export all your user notes to clipboard"))
{
ImGui.SetClipboardText(UiSharedService.GetNotes(_pairManager.DirectPairs.UnionBy(_pairManager.GroupPairs.SelectMany(p => p.Value), p => p.UserData, UserDataComparer.Instance).ToList()));
@@ -864,8 +889,15 @@ public class SettingsUi : WindowMediatorSubscriberBase
UiSharedService.ColorTextWrapped("Attempt to import notes from clipboard failed. Check formatting and try again", ImGuiColors.DalamudRed);
}
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
ImGui.TreePop();
}
ImGui.Separator();
var openPopupOnAddition = _configService.Current.OpenPopupOnAdd;
if (_uiShared.MediumTreeNode("Popup & Auto Fill", UIColors.Get("LightlessPurple")))
{
if (ImGui.Checkbox("Open Notes Popup on user addition", ref openPopupOnAddition))
{
_configService.Current.OpenPopupOnAdd = openPopupOnAddition;
@@ -881,8 +913,14 @@ public class SettingsUi : WindowMediatorSubscriberBase
}
_uiShared.DrawHelpText("This will automatically populate user notes using the first encountered player name if the note was not set prior");
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
ImGui.TreePop();
}
ImGui.Separator();
ImGui.Dummy(new Vector2(10));
_uiShared.BigText("UI");
var showNameInsteadOfNotes = _configService.Current.ShowCharacterNameInsteadOfNotesForVisible;
var showVisibleSeparate = _configService.Current.ShowVisibleUsersSeparately;
var showOfflineSeparate = _configService.Current.ShowOfflineUsersSeparately;
@@ -904,6 +942,9 @@ public class SettingsUi : WindowMediatorSubscriberBase
var groupInVisible = _configService.Current.ShowSyncshellUsersInVisible;
var syncshellOfflineSeparate = _configService.Current.ShowSyncshellOfflineUsersSeparately;
if (_uiShared.MediumTreeNode("Behavior", UIColors.Get("LightlessPurple")))
{
if (ImGui.Checkbox("Enable Game Right Click Menu Entries", ref enableRightClickMenu))
{
_configService.Current.EnableRightClickMenus = enableRightClickMenu;
@@ -999,6 +1040,14 @@ public class SettingsUi : WindowMediatorSubscriberBase
}
}
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
ImGui.TreePop();
}
ImGui.Separator();
if (_uiShared.MediumTreeNode("Pair List", UIColors.Get("LightlessPurple")))
{
if (ImGui.Checkbox("Show separate Visible group", ref showVisibleSeparate))
{
_configService.Current.ShowVisibleUsersSeparately = showVisibleSeparate;
@@ -1071,6 +1120,13 @@ public class SettingsUi : WindowMediatorSubscriberBase
_configService.Save();
}
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
ImGui.TreePop();
}
ImGui.Separator();
if (_uiShared.MediumTreeNode("Profiles", UIColors.Get("LightlessPurple")))
{
if (ImGui.Checkbox("Show Lightless Profiles on Hover", ref showProfiles))
{
Mediator.Publish(new ClearProfileDataMessage());
@@ -1103,14 +1159,21 @@ public class SettingsUi : WindowMediatorSubscriberBase
}
_uiShared.DrawHelpText("Will show profiles that have the NSFW tag enabled");
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
ImGui.TreePop();
}
ImGui.Separator();
ImGui.Dummy(new Vector2(10));
_uiShared.BigText("Notifications");
var disableOptionalPluginWarnings = _configService.Current.DisableOptionalPluginWarnings;
var onlineNotifs = _configService.Current.ShowOnlineNotifications;
var onlineNotifsPairsOnly = _configService.Current.ShowOnlineNotificationsOnlyForIndividualPairs;
var onlineNotifsNamedOnly = _configService.Current.ShowOnlineNotificationsOnlyForNamedPairs;
_uiShared.BigText("Notifications");
if (_uiShared.MediumTreeNode("Display", UIColors.Get("LightlessPurple")))
{
_uiShared.DrawCombo("Info Notification Display##settingsUi", (NotificationLocation[])Enum.GetValues(typeof(NotificationLocation)), (i) => i.ToString(),
(i) =>
{
@@ -1147,6 +1210,14 @@ public class SettingsUi : WindowMediatorSubscriberBase
+ Environment.NewLine + "'Toast' will show Error toast notifications in the bottom right corner"
+ Environment.NewLine + "'Both' will show chat as well as the toast notification");
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
ImGui.TreePop();
}
ImGui.Separator();
if (_uiShared.MediumTreeNode("Toggles", UIColors.Get("LightlessPurple")))
{
if (ImGui.Checkbox("Disable optional plugin warnings", ref disableOptionalPluginWarnings))
{
_configService.Current.DisableOptionalPluginWarnings = disableOptionalPluginWarnings;
@@ -1173,16 +1244,22 @@ public class SettingsUi : WindowMediatorSubscriberBase
_configService.Save();
}
_uiShared.DrawHelpText("Enabling this will only show online notifications (type: Info) for pairs where you have set an individual note.");
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
ImGui.TreePop();
}
}
private void DrawPerformance()
{
_uiShared.BigText("Performance Settings");
_uiShared.UnderlinedBigText("Performance Settings", UIColors.Get("LightlessBlue"));
ImGui.Dummy(new Vector2(10));
UiSharedService.TextWrapped("The configuration options here are to give you more informed warnings and automation when it comes to other performance-intensive synced players.");
ImGui.Dummy(new Vector2(10));
ImGui.Separator();
ImGui.Dummy(new Vector2(10));
bool showPerformanceIndicator = _playerPerformanceConfigService.Current.ShowPerformanceIndicator;
if (_uiShared.MediumTreeNode("Warnings", UIColors.Get("LightlessPurple")))
{
if (ImGui.Checkbox("Show performance indicator", ref showPerformanceIndicator))
{
_playerPerformanceConfigService.Current.ShowPerformanceIndicator = showPerformanceIndicator;
@@ -1232,9 +1309,18 @@ public class SettingsUi : WindowMediatorSubscriberBase
_uiShared.DrawHelpText("Limit in approximate used triangles from mods to trigger warning or performance indicator on UI." + UiSharedService.TooltipSeparator
+ "Default: 165 thousand");
}
ImGui.Dummy(new Vector2(10));
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
ImGui.TreePop();
}
ImGui.Separator();
bool autoPause = _playerPerformanceConfigService.Current.AutoPausePlayersExceedingThresholds;
bool autoPauseEveryone = _playerPerformanceConfigService.Current.AutoPausePlayersWithPreferredPermissionsExceedingThresholds;
if (_uiShared.MediumTreeNode("Auto Pause", UIColors.Get("LightlessPurple")))
{
if (ImGui.Checkbox("Automatically pause players exceeding thresholds", ref autoPause))
{
_playerPerformanceConfigService.Current.AutoPausePlayersExceedingThresholds = autoPause;
@@ -1276,8 +1362,17 @@ public class SettingsUi : WindowMediatorSubscriberBase
_uiShared.DrawHelpText("When a loading in player and their triangle count exceeds this amount, automatically pauses the synced player." + UiSharedService.TooltipSeparator
+ "Default: 250 thousand");
}
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
ImGui.TreePop();
}
ImGui.Separator();
ImGui.Dummy(new Vector2(10));
_uiShared.BigText("Whitelisted UIDs");
_uiShared.UnderlinedBigText("Whitelisted UIDs", UIColors.Get("LightlessBlue"));
ImGuiHelpers.ScaledDummy(5);
UiSharedService.TextWrapped("The entries in the list below will be ignored for all warnings and auto pause operations.");
ImGui.Dummy(new Vector2(10));
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
@@ -1328,7 +1423,11 @@ public class SettingsUi : WindowMediatorSubscriberBase
_lastTab = "Service Settings";
if (ApiController.ServerAlive)
{
_uiShared.BigText("Service Actions");
_uiShared.UnderlinedBigText("Service Actions", UIColors.Get("LightlessBlue"));
ImGui.Dummy(new Vector2(10));
if (_uiShared.MediumTreeNode("Deletion", UIColors.Get("DimRed")))
{
ImGuiHelpers.ScaledDummy(new Vector2(5, 5));
if (ImGui.Button("Delete all my files"))
{
@@ -1403,12 +1502,20 @@ public class SettingsUi : WindowMediatorSubscriberBase
UiSharedService.SetScaledWindowSize(325);
ImGui.EndPopup();
}
_uiShared.ColoredSeparator(UIColors.Get("DimRed"), 1.5f);
ImGui.TreePop();
}
ImGui.Separator();
}
_uiShared.BigText("Service & Character Settings");
ImGuiHelpers.ScaledDummy(new Vector2(5, 5));
ImGui.Dummy(new Vector2(10));
_uiShared.MediumText("Service & Character Settings", UIColors.Get("LightlessPurple"));
ImGui.Dummy(new Vector2(5));
var sendCensus = _serverConfigurationManager.SendCensusData;
if (ImGui.Checkbox("Send Statistical Census Data", ref sendCensus))
{
_serverConfigurationManager.SendCensusData = sendCensus;
@@ -1881,6 +1988,8 @@ public class SettingsUi : WindowMediatorSubscriberBase
}
ImGui.EndTabBar();
}
ImGui.Dummy(new Vector2(10));
}
private int _lastSelectedServerIndex = -1;

View File

@@ -8,9 +8,10 @@ namespace LightlessSync.UI
private static readonly Dictionary<string, string> HexColors = new(StringComparer.OrdinalIgnoreCase)
{
{ "LightlessPurple", "#ad8af5" },
{ "LightlessBlue", "#64c7e8" },
{ "PairBlue", "#4e98b1" },
{ "DimRed", "#bd0000" },
{ "LightlessBlue", "#a6c2ff" },
{ "LightlessYellow", "#ffe97a" },
{ "PairBlue", "#88a2db" },
{ "DimRed", "#d44444" },
};
public static Vector4 Get(string name)

View File

@@ -114,6 +114,15 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
SizePx = 35
}));
});
MediumFont = _pluginInterface.UiBuilder.FontAtlas.NewDelegateFontHandle(e =>
{
e.OnPreBuild(tk => tk.AddDalamudAssetFont(Dalamud.DalamudAsset.NotoSansJpMedium, new()
{
SizePx = 22,
}));
});
GameFont = _pluginInterface.UiBuilder.FontAtlas.NewGameFontHandle(new(GameFontFamilyAndSize.Axis12));
IconFont = _pluginInterface.UiBuilder.IconFontFixedWidthHandle;
}
@@ -133,6 +142,8 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
public string PlayerName => _dalamudUtil.GetPlayerName();
public IFontHandle UidFont { get; init; }
public IFontHandle MediumFont { get; init; }
public Dictionary<ushort, string> WorldData => _dalamudUtil.WorldData.Value;
public uint WorldId => _dalamudUtil.GetHomeWorldId();
@@ -434,6 +445,79 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
FontText(text, UidFont, color);
}
public void UnderlinedBigText(
string text,
Vector4? textColor = null,
Vector4? underlineColor = null,
float underlineThickness = 2f)
{
using var font = UidFont.Push();
var drawList = ImGui.GetWindowDrawList();
var textSize = ImGui.CalcTextSize(text);
var pos = ImGui.GetCursorScreenPos();
var text_color = textColor ?? ImGuiColors.DalamudWhite;
var line_color = underlineColor ?? text_color;
ImGui.PushStyleColor(ImGuiCol.Text, text_color);
ImGui.TextUnformatted(text);
ImGui.PopStyleColor();
var lineY = pos.Y + textSize.Y + 2f;
drawList.AddLine(
new Vector2(pos.X, lineY),
new Vector2(pos.X + textSize.X, lineY),
ImGui.GetColorU32(line_color),
underlineThickness * ImGuiHelpers.GlobalScale
);
}
public void ColoredSeparator(Vector4? color = null, float thickness = 1f, float indent = 0f)
{
var drawList = ImGui.GetWindowDrawList();
var min = ImGui.GetCursorScreenPos();
var max = new Vector2(min.X + ImGui.GetContentRegionAvail().X, min.Y);
min.X += indent;
max.X -= indent;
drawList.AddLine(
min,
new Vector2(max.X, min.Y),
ImGui.GetColorU32(color ?? ImGuiColors.DalamudGrey),
thickness * ImGuiHelpers.GlobalScale
);
ImGui.Dummy(new Vector2(0, thickness * ImGuiHelpers.GlobalScale));
}
public void MediumText(string text, Vector4? color = null)
{
FontText(text, MediumFont, color);
}
public bool MediumTreeNode(string label, Vector4? textColor = null, float lineWidth = 2f, ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags.SpanAvailWidth)
{
using var font = MediumFont.Push();
var lineColor = textColor ?? ImGuiColors.DalamudWhite;
var textSize = ImGui.CalcTextSize(label);
var cursorScreen = ImGui.GetCursorScreenPos();
var cursorLocal = ImGui.GetCursorPos();
ImGui.GetWindowDrawList().AddLine(
new Vector2(cursorScreen.X, cursorScreen.Y),
new Vector2(cursorScreen.X, cursorScreen.Y + textSize.Y),
ImGui.GetColorU32(lineColor),
lineWidth * ImGuiHelpers.GlobalScale
);
ImGui.SetCursorPosX(cursorLocal.X + 6f);
using var color = ImRaii.PushColor(ImGuiCol.Text, lineColor);
return ImGui.TreeNodeEx(label, flags);
}
public void BooleanToColoredIcon(bool value, bool inline = true)
{
using var colorgreen = ImRaii.PushColor(ImGuiCol.Text, UIColors.Get("LightlessBlue"), value);
@@ -1085,6 +1169,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
UidFont.Dispose();
GameFont.Dispose();
MediumFont.Dispose();
}
private static void CenterWindow(float width, float height, ImGuiCond cond = ImGuiCond.None)