Lightless Lightfinder redesign + stuff #127
@@ -58,6 +58,7 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
private List<GroupFullInfoDto> _currentSyncshells = [];
|
||||
private GroupJoinDto? _joinDto;
|
||||
private GroupJoinInfoDto? _joinInfo;
|
||||
private bool _joinModalOpen = true;
|
||||
private readonly List<GroupJoinDto> _nearbySyncshells = [];
|
||||
private DefaultPermissionsDto _ownPermissions = null!;
|
||||
private readonly HashSet<string> _recentlyJoined = new(StringComparer.Ordinal);
|
||||
@@ -66,6 +67,11 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
private LightfinderTab _selectedTab = LightfinderTab.NearbySyncshells;
|
||||
private string _userUid = string.Empty;
|
||||
|
||||
private const float AnimationSpeed = 6f;
|
||||
private readonly Dictionary<string, float> _itemAlpha = new(StringComparer.Ordinal);
|
||||
private readonly HashSet<string> _currentVisibleItems = new(StringComparer.Ordinal);
|
||||
private readonly HashSet<string> _previousVisibleItems = new(StringComparer.Ordinal);
|
||||
|
||||
private enum LightfinderTab { NearbySyncshells, NearbyPlayers, BroadcastSettings, Help }
|
||||
|
||||
#if DEBUG
|
||||
@@ -106,14 +112,14 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
_lightlessProfileManager = lightlessProfileManager;
|
||||
_actorObjectService = actorObjectService;
|
||||
|
||||
_animatedHeader.Height = 100f;
|
||||
_animatedHeader.Height = 85f;
|
||||
_animatedHeader.EnableBottomGradient = true;
|
||||
_animatedHeader.GradientHeight = 120f;
|
||||
_animatedHeader.GradientHeight = 90f;
|
||||
_animatedHeader.EnableParticles = _configService.Current.EnableParticleEffects;
|
||||
|
||||
IsOpen = false;
|
||||
WindowBuilder.For(this)
|
||||
.SetSizeConstraints(new Vector2(620, 85), new Vector2(700, 600))
|
||||
.SetSizeConstraints(new Vector2(620, 85), new Vector2(700, 2000))
|
||||
.Apply();
|
||||
|
||||
Mediator.Subscribe<SyncshellBroadcastsUpdatedMessage>(this, async _ => await RefreshNearbySyncshellsAsync().ConfigureAwait(false));
|
||||
@@ -367,6 +373,52 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
|
||||
#endregion
|
||||
|
||||
#region Animation Helpers
|
||||
|
||||
private void UpdateItemAnimations(IEnumerable<string> visibleItemIds)
|
||||
{
|
||||
var deltaTime = ImGui.GetIO().DeltaTime;
|
||||
|
||||
_previousVisibleItems.Clear();
|
||||
foreach (var id in _currentVisibleItems)
|
||||
_previousVisibleItems.Add(id);
|
||||
|
||||
_currentVisibleItems.Clear();
|
||||
foreach (var id in visibleItemIds)
|
||||
_currentVisibleItems.Add(id);
|
||||
|
||||
// Fade in new items
|
||||
foreach (var id in _currentVisibleItems)
|
||||
{
|
||||
if (!_itemAlpha.ContainsKey(id))
|
||||
_itemAlpha[id] = 0f;
|
||||
|
||||
_itemAlpha[id] = Math.Min(1f, _itemAlpha[id] + deltaTime * AnimationSpeed);
|
||||
}
|
||||
|
||||
// Fade out removed items
|
||||
var toRemove = new List<string>();
|
||||
foreach (var (id, alpha) in _itemAlpha)
|
||||
{
|
||||
if (!_currentVisibleItems.Contains(id))
|
||||
{
|
||||
_itemAlpha[id] = Math.Max(0f, alpha - deltaTime * AnimationSpeed);
|
||||
if (_itemAlpha[id] <= 0.01f)
|
||||
toRemove.Add(id);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var id in toRemove)
|
||||
_itemAlpha.Remove(id);
|
||||
}
|
||||
|
||||
private float GetItemAlpha(string itemId)
|
||||
{
|
||||
return _itemAlpha.TryGetValue(itemId, out var alpha) ? alpha : 1f;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Nearby Syncshells Tab
|
||||
|
||||
private void DrawNearbySyncshellsTab()
|
||||
@@ -400,10 +452,14 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
var cardData = BuildSyncshellCardData();
|
||||
if (cardData.Count == 0)
|
||||
{
|
||||
UpdateItemAnimations([]);
|
||||
ImGui.TextColored(ImGuiColors.DalamudGrey, "No nearby syncshells found.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Update animations for syncshell items
|
||||
UpdateItemAnimations(cardData.Select(c => $"shell_{c.Shell.Group.GID}"));
|
||||
|
||||
if (_compactView)
|
||||
DrawSyncshellGrid(cardData);
|
||||
else
|
||||
@@ -499,7 +555,13 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
|
||||
private void DrawSyncshellListItem(GroupJoinDto shell, string broadcasterName, bool isOwnBroadcast)
|
||||
{
|
||||
var itemId = $"shell_{shell.Group.GID}";
|
||||
var alpha = GetItemAlpha(itemId);
|
||||
if (alpha <= 0.01f)
|
||||
return;
|
||||
|
||||
ImGui.PushID(shell.Group.GID);
|
||||
using var alphaStyle = ImRaii.PushStyle(ImGuiStyleVar.Alpha, alpha);
|
||||
float rowHeight = 74f * ImGuiHelpers.GlobalScale;
|
||||
|
||||
ImGui.BeginChild($"ShellRow##{shell.Group.GID}", new Vector2(-1, rowHeight), border: true);
|
||||
@@ -572,7 +634,13 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
|
||||
private void DrawSyncshellCompactItem(GroupJoinDto shell, bool isOwnBroadcast)
|
||||
{
|
||||
var itemId = $"shell_{shell.Group.GID}";
|
||||
var alpha = GetItemAlpha(itemId);
|
||||
if (alpha <= 0.01f)
|
||||
return;
|
||||
|
||||
ImGui.PushID(shell.Group.GID);
|
||||
using var alphaStyle = ImRaii.PushStyle(ImGuiStyleVar.Alpha, alpha);
|
||||
float rowHeight = 36f * ImGuiHelpers.GlobalScale;
|
||||
|
||||
ImGui.BeginChild($"ShellCompact##{shell.Group.GID}", new Vector2(-1, rowHeight), border: true);
|
||||
@@ -655,6 +723,7 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
{
|
||||
_joinDto = new GroupJoinDto(shell.Group, shell.Password, shell.GroupUserPreferredPermissions);
|
||||
_joinInfo = info;
|
||||
_joinModalOpen = true;
|
||||
_ownPermissions = _apiController.DefaultPermissions.DeepClone()!;
|
||||
}
|
||||
}
|
||||
@@ -685,65 +754,188 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
{
|
||||
if (_joinDto == null || _joinInfo == null) return;
|
||||
|
||||
ImGui.Separator();
|
||||
ImGui.TextUnformatted($"Join Syncshell: {_joinDto.Group.AliasOrGID} by {_joinInfo.OwnerAliasOrUID}");
|
||||
ImGuiHelpers.ScaledDummy(2f);
|
||||
ImGui.TextUnformatted("Suggested Permissions:");
|
||||
var scale = ImGuiHelpers.GlobalScale;
|
||||
|
||||
// if not already open
|
||||
if (!ImGui.IsPopupOpen("JoinSyncshellModal"))
|
||||
ImGui.OpenPopup("JoinSyncshellModal");
|
||||
|
||||
DrawPermissionRow("Sounds", _joinInfo.GroupPermissions.IsPreferDisableSounds(), _ownPermissions.DisableGroupSounds, v => _ownPermissions.DisableGroupSounds = v);
|
||||
DrawPermissionRow("Animations", _joinInfo.GroupPermissions.IsPreferDisableAnimations(), _ownPermissions.DisableGroupAnimations, v => _ownPermissions.DisableGroupAnimations = v);
|
||||
DrawPermissionRow("VFX", _joinInfo.GroupPermissions.IsPreferDisableVFX(), _ownPermissions.DisableGroupVFX, v => _ownPermissions.DisableGroupVFX = v);
|
||||
|
||||
ImGui.NewLine();
|
||||
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Plus, $"Finalize and join {_joinDto.Group.AliasOrGID}"))
|
||||
Vector2 windowPos = ImGui.GetWindowPos();
|
||||
Vector2 windowSize = ImGui.GetWindowSize();
|
||||
float modalWidth = Math.Min(420f * scale, windowSize.X - 40f * scale);
|
||||
float modalHeight = 295f * scale;
|
||||
ImGui.SetNextWindowPos(new Vector2(
|
||||
windowPos.X + (windowSize.X - modalWidth) * 0.5f,
|
||||
windowPos.Y + (windowSize.Y - modalHeight) * 0.5f
|
||||
), ImGuiCond.Always);
|
||||
ImGui.SetNextWindowSize(new Vector2(modalWidth, modalHeight));
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.WindowRounding, 6f * ImGuiHelpers.GlobalScale);
|
||||
ImGui.PushStyleColor(ImGuiCol.Border, Vector4.Zero);
|
||||
|
||||
using ImRaii.Color modalBorder = ImRaii.PushColor(ImGuiCol.Border, UIColors.Get("LightlessPurple").WithAlpha(0.5f));
|
||||
using ImRaii.Style rounding = ImRaii.PushStyle(ImGuiStyleVar.WindowRounding, 8f * scale);
|
||||
using ImRaii.Style borderSize = ImRaii.PushStyle(ImGuiStyleVar.WindowBorderSize, 2f * scale);
|
||||
using ImRaii.Style padding = ImRaii.PushStyle(ImGuiStyleVar.WindowPadding, new Vector2(16f * scale, 16f * scale));
|
||||
|
||||
ImGuiWindowFlags flags = ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoScrollbar;
|
||||
if (ImGui.BeginPopupModal("JoinSyncshellModal", ref _joinModalOpen, flags))
|
||||
{
|
||||
var finalPermissions = GroupUserPreferredPermissions.NoneSet;
|
||||
finalPermissions.SetDisableSounds(_ownPermissions.DisableGroupSounds);
|
||||
finalPermissions.SetDisableAnimations(_ownPermissions.DisableGroupAnimations);
|
||||
finalPermissions.SetDisableVFX(_ownPermissions.DisableGroupVFX);
|
||||
float contentWidth = ImGui.GetContentRegionAvail().X;
|
||||
|
||||
_ = _apiController.GroupJoinFinalize(new GroupJoinDto(_joinDto.Group, _joinDto.Password, finalPermissions));
|
||||
_recentlyJoined.Add(_joinDto.Group.GID);
|
||||
// Header
|
||||
_uiSharedService.MediumText("Join Syncshell", UIColors.Get("LightlessPurple"));
|
||||
ImGuiHelpers.ScaledDummy(2f);
|
||||
ImGui.TextColored(ImGuiColors.DalamudGrey, $"{_joinDto.Group.AliasOrGID} by {_joinInfo.OwnerAliasOrUID}");
|
||||
|
||||
_joinDto = null;
|
||||
_joinInfo = null;
|
||||
}
|
||||
ImGuiHelpers.ScaledDummy(8f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurpleDefault").WithAlpha(0.4f));
|
||||
ImGuiHelpers.ScaledDummy(8f);
|
||||
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button("Cancel"))
|
||||
{
|
||||
_joinDto = null;
|
||||
_joinInfo = null;
|
||||
// Permissions section
|
||||
ImGui.TextColored(ImGuiColors.DalamudWhite, "Permissions");
|
||||
ImGuiHelpers.ScaledDummy(6f);
|
||||
|
||||
DrawPermissionToggleRow("Sounds", FontAwesomeIcon.VolumeUp,
|
||||
_joinInfo.GroupPermissions.IsPreferDisableSounds(),
|
||||
_ownPermissions.DisableGroupSounds,
|
||||
v => _ownPermissions.DisableGroupSounds = v,
|
||||
contentWidth);
|
||||
|
||||
DrawPermissionToggleRow("Animations", FontAwesomeIcon.Running,
|
||||
_joinInfo.GroupPermissions.IsPreferDisableAnimations(),
|
||||
_ownPermissions.DisableGroupAnimations,
|
||||
v => _ownPermissions.DisableGroupAnimations = v,
|
||||
contentWidth);
|
||||
|
||||
DrawPermissionToggleRow("VFX", FontAwesomeIcon.Magic,
|
||||
_joinInfo.GroupPermissions.IsPreferDisableVFX(),
|
||||
_ownPermissions.DisableGroupVFX,
|
||||
v => _ownPermissions.DisableGroupVFX = v,
|
||||
contentWidth);
|
||||
|
||||
ImGuiHelpers.ScaledDummy(12f);
|
||||
|
||||
// Buttons
|
||||
float buttonHeight = 32f * scale;
|
||||
float buttonSpacing = 8f * scale;
|
||||
float joinButtonWidth = (contentWidth - buttonSpacing) * 0.65f;
|
||||
float cancelButtonWidth = (contentWidth - buttonSpacing) * 0.35f;
|
||||
|
||||
using (ImRaii.PushStyle(ImGuiStyleVar.FrameRounding, 6f * scale))
|
||||
{
|
||||
// Join button
|
||||
using (ImRaii.PushColor(ImGuiCol.Button, UIColors.Get("LightlessGreen")))
|
||||
using (ImRaii.PushColor(ImGuiCol.ButtonHovered, UIColors.Get("LightlessGreen").WithAlpha(0.85f)))
|
||||
using (ImRaii.PushColor(ImGuiCol.ButtonActive, UIColors.Get("LightlessGreen").WithAlpha(0.75f)))
|
||||
{
|
||||
if (ImGui.Button($"Join Syncshell##{_joinDto.Group.GID}", new Vector2(joinButtonWidth, buttonHeight)))
|
||||
{
|
||||
var finalPermissions = GroupUserPreferredPermissions.NoneSet;
|
||||
finalPermissions.SetDisableSounds(_ownPermissions.DisableGroupSounds);
|
||||
finalPermissions.SetDisableAnimations(_ownPermissions.DisableGroupAnimations);
|
||||
finalPermissions.SetDisableVFX(_ownPermissions.DisableGroupVFX);
|
||||
|
||||
_ = _apiController.GroupJoinFinalize(new GroupJoinDto(_joinDto.Group, _joinDto.Password, finalPermissions));
|
||||
_recentlyJoined.Add(_joinDto.Group.GID);
|
||||
|
||||
_joinDto = null;
|
||||
_joinInfo = null;
|
||||
ImGui.CloseCurrentPopup();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.SameLine(0f, buttonSpacing);
|
||||
|
||||
// Cancel button
|
||||
using (ImRaii.PushColor(ImGuiCol.Button, new Vector4(0.3f, 0.3f, 0.3f, 1f)))
|
||||
using (ImRaii.PushColor(ImGuiCol.ButtonHovered, new Vector4(0.4f, 0.4f, 0.4f, 1f)))
|
||||
using (ImRaii.PushColor(ImGuiCol.ButtonActive, new Vector4(0.25f, 0.25f, 0.25f, 1f)))
|
||||
{
|
||||
if (ImGui.Button("Cancel", new Vector2(cancelButtonWidth, buttonHeight)))
|
||||
{
|
||||
_joinDto = null;
|
||||
_joinInfo = null;
|
||||
ImGui.CloseCurrentPopup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle modal close via the bool ref
|
||||
if (!_joinModalOpen)
|
||||
{
|
||||
_joinDto = null;
|
||||
_joinInfo = null;
|
||||
}
|
||||
|
||||
ImGui.EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawPermissionRow(string label, bool suggested, bool current, Action<bool> apply)
|
||||
private void DrawPermissionToggleRow(string label, FontAwesomeIcon icon, bool suggested, bool current, Action<bool> apply, float contentWidth)
|
||||
{
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted($"- {label}");
|
||||
|
||||
ImGui.SameLine(120 * ImGuiHelpers.GlobalScale);
|
||||
ImGui.Text("Current:");
|
||||
ImGui.SameLine();
|
||||
_uiSharedService.BooleanToColoredIcon(!current);
|
||||
|
||||
ImGui.SameLine(240 * ImGuiHelpers.GlobalScale);
|
||||
ImGui.Text("Suggested:");
|
||||
ImGui.SameLine();
|
||||
_uiSharedService.BooleanToColoredIcon(!suggested);
|
||||
|
||||
ImGui.SameLine(380 * ImGuiHelpers.GlobalScale);
|
||||
using var id = ImRaii.PushId(label);
|
||||
if (current != suggested)
|
||||
var scale = ImGuiHelpers.GlobalScale;
|
||||
float rowHeight = 28f * scale;
|
||||
bool isDifferent = current != suggested;
|
||||
|
||||
using (ImRaii.PushStyle(ImGuiStyleVar.FrameRounding, 4f * scale))
|
||||
using (ImRaii.PushStyle(ImGuiStyleVar.ChildRounding, 4f * scale))
|
||||
using (ImRaii.PushColor(ImGuiCol.ChildBg, new Vector4(0.18f, 0.15f, 0.22f, 0.6f)))
|
||||
{
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.ArrowRight, "Apply"))
|
||||
apply(suggested);
|
||||
}
|
||||
ImGui.BeginChild($"PermRow_{label}", new Vector2(contentWidth, rowHeight), false, ImGuiWindowFlags.NoScrollbar);
|
||||
|
||||
float innerPadding = 8f * scale;
|
||||
ImGui.SetCursorPos(new Vector2(innerPadding, (rowHeight - ImGui.GetTextLineHeight()) * 0.5f));
|
||||
|
||||
ImGui.NewLine();
|
||||
// Icon and label
|
||||
var enabledColor = UIColors.Get("LightlessGreen");
|
||||
var disabledColor = UIColors.Get("DimRed");
|
||||
var currentColor = !current ? enabledColor : disabledColor;
|
||||
|
||||
_uiSharedService.IconText(icon, currentColor);
|
||||
ImGui.SameLine(0f, 6f * scale);
|
||||
ImGui.TextUnformatted(label);
|
||||
|
||||
// Current status
|
||||
ImGui.SameLine();
|
||||
float statusX = contentWidth * 0.38f;
|
||||
ImGui.SetCursorPosX(statusX);
|
||||
ImGui.TextColored(ImGuiColors.DalamudGrey, "Current:");
|
||||
ImGui.SameLine(0f, 4f * scale);
|
||||
_uiSharedService.BooleanToColoredIcon(!current, false);
|
||||
|
||||
// Suggested status
|
||||
ImGui.SameLine();
|
||||
float suggestedX = contentWidth * 0.60f;
|
||||
ImGui.SetCursorPosX(suggestedX);
|
||||
ImGui.TextColored(ImGuiColors.DalamudGrey, "Suggested:");
|
||||
ImGui.SameLine(0f, 4f * scale);
|
||||
_uiSharedService.BooleanToColoredIcon(!suggested, false);
|
||||
|
||||
// Apply checkmark button if different
|
||||
if (isDifferent)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
float applyX = contentWidth - 26f * scale;
|
||||
ImGui.SetCursorPosX(applyX);
|
||||
ImGui.SetCursorPosY((rowHeight - ImGui.GetFrameHeight()) * 0.5f);
|
||||
|
||||
using (ImRaii.PushColor(ImGuiCol.Button, UIColors.Get("LightlessGreen").WithAlpha(0.6f)))
|
||||
using (ImRaii.PushColor(ImGuiCol.ButtonHovered, UIColors.Get("LightlessGreen")))
|
||||
using (ImRaii.PushColor(ImGuiCol.ButtonActive, UIColors.Get("LightlessGreenDefault")))
|
||||
{
|
||||
if (_uiSharedService.IconButton(FontAwesomeIcon.Check))
|
||||
apply(suggested);
|
||||
}
|
||||
if (ImGui.IsItemHovered())
|
||||
ImGui.SetTooltip("Apply suggested");
|
||||
}
|
||||
|
||||
ImGui.EndChild();
|
||||
}
|
||||
ImGui.Dummy(new Vector2(0, 2f * scale));
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Nearby Players Tab
|
||||
@@ -785,10 +977,14 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
var playerData = BuildNearbyPlayerData(activeBroadcasts);
|
||||
if (playerData.Count == 0)
|
||||
{
|
||||
UpdateItemAnimations([]);
|
||||
ImGui.TextColored(ImGuiColors.DalamudGrey, "No nearby Lightfinder players found.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Update animations for player items
|
||||
UpdateItemAnimations(playerData.Select(p => $"player_{p.HashedCid}"));
|
||||
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.FrameRounding, 8f);
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.FrameBorderSize, 1f);
|
||||
|
||||
@@ -848,7 +1044,13 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
|
||||
private void DrawNearbyPlayerRow(NearbyPlayerData data)
|
||||
{
|
||||
var itemId = $"player_{data.HashedCid}";
|
||||
var alpha = GetItemAlpha(itemId);
|
||||
if (alpha <= 0.01f)
|
||||
return;
|
||||
|
||||
ImGui.PushID(data.HashedCid);
|
||||
using var alphaStyle = ImRaii.PushStyle(ImGuiStyleVar.Alpha, alpha);
|
||||
float rowHeight = 74f * ImGuiHelpers.GlobalScale;
|
||||
|
||||
ImGui.BeginChild($"PlayerRow##{data.HashedCid}", new Vector2(-1, rowHeight), border: true);
|
||||
@@ -903,7 +1105,7 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
ImGui.SetCursorPosX(startX);
|
||||
_uiSharedService.IconText(FontAwesomeIcon.Wifi, UIColors.Get("LightlessBlue"));
|
||||
ImGui.SameLine(0f, 4f * ImGuiHelpers.GlobalScale);
|
||||
ImGui.TextColored(ImGuiColors.DalamudGrey, "Lightfinder User");
|
||||
ImGui.TextColored(ImGuiColors.DalamudGrey, "Lightfinder sir ma'am or whatever");
|
||||
}
|
||||
|
||||
ImGui.Dummy(new Vector2(0, 4 * ImGuiHelpers.GlobalScale));
|
||||
@@ -916,7 +1118,13 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
|
||||
private void DrawNearbyPlayerCompactRow(NearbyPlayerData data)
|
||||
{
|
||||
var itemId = $"player_{data.HashedCid}";
|
||||
var alpha = GetItemAlpha(itemId);
|
||||
if (alpha <= 0.01f)
|
||||
return;
|
||||
|
||||
ImGui.PushID(data.HashedCid);
|
||||
using var alphaStyle = ImRaii.PushStyle(ImGuiStyleVar.Alpha, alpha);
|
||||
float rowHeight = 36f * ImGuiHelpers.GlobalScale;
|
||||
|
||||
ImGui.BeginChild($"PlayerCompact##{data.HashedCid}", new Vector2(-1, rowHeight), border: true);
|
||||
|
||||
Reference in New Issue
Block a user