Optimize rendering of large number of pairs

This commit is contained in:
Loporrit
2023-12-04 14:17:09 +00:00
parent 283d54aff6
commit 748d6184fc
6 changed files with 85 additions and 47 deletions

View File

@@ -71,7 +71,7 @@ public class CompactUi : WindowMediatorSubscriberBase
_groupPanel = new(this, uiShared, _pairManager, uidDisplayHandler, _serverManager); _groupPanel = new(this, uiShared, _pairManager, uidDisplayHandler, _serverManager);
_selectGroupForPairUi = new(tagHandler, uidDisplayHandler); _selectGroupForPairUi = new(tagHandler, uidDisplayHandler);
_selectPairsForGroupUi = new(tagHandler, uidDisplayHandler); _selectPairsForGroupUi = new(tagHandler, uidDisplayHandler);
_pairGroupsUi = new(configService, tagHandler, apiController, _selectPairsForGroupUi); _pairGroupsUi = new(configService, tagHandler, uidDisplayHandler, apiController, _selectPairsForGroupUi);
#if DEBUG #if DEBUG
string dev = "Dev Build"; string dev = "Dev Build";

View File

@@ -22,6 +22,7 @@ public abstract class DrawPairBase
_displayHandler = uIDDisplayHandler; _displayHandler = uIDDisplayHandler;
} }
public string ImGuiID => _id;
public string UID => _pair.UserData.UID; public string UID => _pair.UserData.UID;
public void DrawPairedClient() public void DrawPairedClient()
@@ -30,6 +31,20 @@ public abstract class DrawPairBase
var pauseIconSize = UiSharedService.GetIconButtonSize(FontAwesomeIcon.Play); var pauseIconSize = UiSharedService.GetIconButtonSize(FontAwesomeIcon.Play);
var textSize = ImGui.CalcTextSize(_pair.UserData.AliasOrUID); var textSize = ImGui.CalcTextSize(_pair.UserData.AliasOrUID);
var startPos = ImGui.GetCursorStartPos();
var framePadding = ImGui.GetStyle().FramePadding;
var lineHeight = textSize.Y + framePadding.Y * 2;
var off = startPos.Y;
var height = UiSharedService.GetWindowContentRegionHeight();
if ((originalY + off) < -lineHeight || (originalY + off) > height)
{
ImGui.Dummy(new System.Numerics.Vector2(0f, lineHeight));
return;
}
var textPosY = originalY + pauseIconSize.Y / 2 - textSize.Y / 2; var textPosY = originalY + pauseIconSize.Y / 2 - textSize.Y / 2;
DrawLeftSide(textPosY, originalY); DrawLeftSide(textPosY, originalY);
ImGui.SameLine(); ImGui.SameLine();

View File

@@ -395,63 +395,56 @@ internal sealed class GroupPanel
ImGui.Indent(20); ImGui.Indent(20);
if (_expandedGroupState[groupDto.GID]) if (_expandedGroupState[groupDto.GID])
{ {
var visibleUsers = pairsInGroup.Where(u => u.IsVisible) var sortedPairs = pairsInGroup
.OrderByDescending(u => string.Equals(u.UserData.UID, groupDto.OwnerUID, StringComparison.Ordinal)) .OrderByDescending(u => string.Equals(u.UserData.UID, groupDto.OwnerUID, StringComparison.Ordinal))
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsModerator()) .ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsModerator())
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsPinned()) .ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsPinned())
.ThenBy(u => u.GetNote() ?? u.UserData.AliasOrUID, StringComparer.OrdinalIgnoreCase) .ThenBy(u => u.GetNote() ?? u.UserData.AliasOrUID, StringComparer.OrdinalIgnoreCase);
.Select(c => new DrawGroupPair(groupDto.GID + c.UserData.UID, c, ApiController, _mainUi.Mediator, groupDto, c.GroupPair.Single(g => GroupDataComparer.Instance.Equals(g.Key.Group, groupDto.Group)).Value,
_uidDisplayHandler))
.ToList();
var onlineUsers = pairsInGroup.Where(u => u.IsOnline && !u.IsVisible)
.OrderByDescending(u => string.Equals(u.UserData.UID, groupDto.OwnerUID, StringComparison.Ordinal))
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsModerator())
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsPinned())
.ThenBy(u => u.GetNote() ?? u.UserData.AliasOrUID, StringComparer.OrdinalIgnoreCase)
.Select(c => new DrawGroupPair(groupDto.GID + c.UserData.UID, c, ApiController, _mainUi.Mediator, groupDto, c.GroupPair.Single(g => GroupDataComparer.Instance.Equals(g.Key.Group, groupDto.Group)).Value,
_uidDisplayHandler))
.ToList();
var offlineUsers = pairsInGroup.Where(u => !u.IsOnline && !u.IsVisible)
.OrderByDescending(u => string.Equals(u.UserData.UID, groupDto.OwnerUID, StringComparison.Ordinal))
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsModerator())
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsPinned())
.ThenBy(u => u.GetNote() ?? u.UserData.AliasOrUID, StringComparer.OrdinalIgnoreCase)
.Select(c => new DrawGroupPair(groupDto.GID + c.UserData.UID, c, ApiController, _mainUi.Mediator, groupDto, c.GroupPair.Single(g => GroupDataComparer.Instance.Equals(g.Key.Group, groupDto.Group)).Value,
_uidDisplayHandler))
.ToList();
if (visibleUsers.Any()) var visibleUsers = new List<DrawGroupPair>();
var onlineUsers = new List<DrawGroupPair>();
var offlineUsers = new List<DrawGroupPair>();
foreach (var pair in sortedPairs)
{ {
ImGui.Text("Visible"); var drawPair = new DrawGroupPair(
ImGui.Separator(); groupDto.GID + pair.UserData.UID, pair,
foreach (var entry in visibleUsers) ApiController, _mainUi.Mediator, groupDto,
{ pair.GroupPair.Single(
using (ImRaii.PushId(groupDto.GID + entry.UID)) entry.DrawPairedClient(); g => GroupDataComparer.Instance.Equals(g.Key.Group, groupDto.Group)
} ).Value,
_uidDisplayHandler);
if (pair.IsVisible)
visibleUsers.Add(drawPair);
else if (pair.IsOnline)
onlineUsers.Add(drawPair);
else
offlineUsers.Add(drawPair);
} }
if (onlineUsers.Any()) if (visibleUsers.Count > 0)
{ {
ImGui.Text("Online"); ImGui.TextUnformatted("Visible");
ImGui.Separator(); ImGui.Separator();
foreach (var entry in onlineUsers) _uidDisplayHandler.RenderPairList(visibleUsers);
{
using (ImRaii.PushId(groupDto.GID + entry.UID)) entry.DrawPairedClient();
}
} }
if (offlineUsers.Any()) if (onlineUsers.Count > 0)
{ {
ImGui.Text("Offline/Unknown"); ImGui.TextUnformatted("Online");
ImGui.Separator(); ImGui.Separator();
foreach (var entry in offlineUsers) _uidDisplayHandler.RenderPairList(onlineUsers);
{ }
using (ImRaii.PushId(groupDto.GID + entry.UID)) entry.DrawPairedClient();
} if (offlineUsers.Count > 0)
{
ImGui.TextUnformatted("Offline/Unknown");
ImGui.Separator();
_uidDisplayHandler.RenderPairList(offlineUsers);
} }
ImGui.Separator(); ImGui.Separator();
ImGui.Unindent(ImGui.GetStyle().ItemSpacing.X / 2);
} }
ImGui.Unindent(20); ImGui.Unindent(20);
} }

View File

@@ -15,11 +15,13 @@ public class PairGroupsUi
private readonly MareConfigService _mareConfig; private readonly MareConfigService _mareConfig;
private readonly SelectPairForGroupUi _selectGroupForPairUi; private readonly SelectPairForGroupUi _selectGroupForPairUi;
private readonly TagHandler _tagHandler; private readonly TagHandler _tagHandler;
private readonly UidDisplayHandler _uidDisplayHandler;
public PairGroupsUi(MareConfigService mareConfig, TagHandler tagHandler, ApiController apiController, SelectPairForGroupUi selectGroupForPairUi) public PairGroupsUi(MareConfigService mareConfig, TagHandler tagHandler, UidDisplayHandler uidDisplayHandler, ApiController apiController, SelectPairForGroupUi selectGroupForPairUi)
{ {
_mareConfig = mareConfig; _mareConfig = mareConfig;
_tagHandler = tagHandler; _tagHandler = tagHandler;
_uidDisplayHandler = uidDisplayHandler;
_apiController = apiController; _apiController = apiController;
_selectGroupForPairUi = selectGroupForPairUi; _selectGroupForPairUi = selectGroupForPairUi;
} }
@@ -182,10 +184,7 @@ public class PairGroupsUi
private void DrawPairs(string tag, IEnumerable<DrawPairBase> availablePairsInThisCategory) private void DrawPairs(string tag, IEnumerable<DrawPairBase> availablePairsInThisCategory)
{ {
// These are all the OtherUIDs that are tagged with this tag // These are all the OtherUIDs that are tagged with this tag
foreach (var pair in availablePairsInThisCategory) _uidDisplayHandler.RenderPairList(availablePairsInThisCategory);
{
using (ImRaii.PushId($"tag-{tag}-pair-${pair.UID}")) pair.DrawPairedClient();
}
ImGui.Separator(); ImGui.Separator();
} }

View File

@@ -6,6 +6,7 @@ using MareSynchronos.Services.ServerConfiguration;
using MareSynchronos.MareConfiguration; using MareSynchronos.MareConfiguration;
using ImGuiScene; using ImGuiScene;
using MareSynchronos.Services.Mediator; using MareSynchronos.Services.Mediator;
using MareSynchronos.UI.Components;
namespace MareSynchronos.UI.Handlers; namespace MareSynchronos.UI.Handlers;
@@ -32,6 +33,31 @@ public class UidDisplayHandler
_mareConfigService = mareConfigService; _mareConfigService = mareConfigService;
} }
public void RenderPairList(IEnumerable<DrawPairBase> pairs)
{
var textHeight = ImGui.GetFontSize();
var style = ImGui.GetStyle();
var framePadding = style.FramePadding;
var spacing = style.ItemSpacing;
var lineHeight = textHeight + framePadding.Y * 2 + spacing.Y;
var startY = ImGui.GetCursorStartPos().Y;
var cursorY = ImGui.GetCursorPosY();
var contentHeight = UiSharedService.GetWindowContentRegionHeight();
foreach (var entry in pairs)
{
if ((startY + cursorY) < -lineHeight || (startY + cursorY) > contentHeight)
{
cursorY += lineHeight;
ImGui.SetCursorPosY(cursorY);
continue;
}
using (ImRaii.PushId(entry.ImGuiID)) entry.DrawPairedClient();
cursorY += lineHeight;
}
}
public void DrawPairText(string id, Pair pair, float textPosX, float originalY, Func<float> editBoxWidth) public void DrawPairText(string id, Pair pair, float textPosX, float originalY, Func<float> editBoxWidth)
{ {
ImGui.SameLine(textPosX); ImGui.SameLine(textPosX);

View File

@@ -326,6 +326,11 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
return ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X; return ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X;
} }
public static float GetWindowContentRegionHeight()
{
return ImGui.GetWindowContentRegionMax().Y - ImGui.GetWindowContentRegionMin().Y;
}
public static Vector2 GetNormalizedIconTextButtonSize(FontAwesomeIcon icon, string text, float? width = null, bool isInPopup = false) public static Vector2 GetNormalizedIconTextButtonSize(FontAwesomeIcon icon, string text, float? width = null, bool isInPopup = false)
{ {
var iconData = GetIconData(icon); var iconData = GetIconData(icon);