diff --git a/LightlessSync/UI/StandaloneProfileUi.cs b/LightlessSync/UI/StandaloneProfileUi.cs index f1e782d..f2e805e 100644 --- a/LightlessSync/UI/StandaloneProfileUi.cs +++ b/LightlessSync/UI/StandaloneProfileUi.cs @@ -910,175 +910,176 @@ public class StandaloneProfileUi : WindowMediatorSubscriberBase bool useVanityColors = false; Vector4? vanityTextColor = null; Vector4? vanityGlowColor = null; - if (_groupData is not null && groupInfo is not null) + string primaryHeaderText = _groupData.AliasOrGID; + + List<(string Text, bool UseVanityColor, bool Disabled)> secondaryHeaderLines = + [ + (_groupData.GID, false, true) + ]; + + if (groupInfo is not null) + secondaryHeaderLines.Add(($"Owner: {groupInfo.Owner.AliasOrUID}", false, true)); + else + secondaryHeaderLines.Add(($"Unknown Owner", false, true)); + + var infoStartY = MathF.Max(contentStartY, bannerHeight + style.WindowPadding.Y); + var aliasColumnX = infoOffsetX + 18f * scale; + ImGui.SetCursorPos(new Vector2(aliasColumnX, infoStartY)); + + ImGui.BeginGroup(); + using (_uiSharedService.UidFont.Push()) { - string primaryHeaderText = _groupData.AliasOrGID; - - List<(string Text, bool UseVanityColor, bool Disabled)> secondaryHeaderLines = - [ - (_groupData.GID, false, true) - ]; - - if (groupInfo.Owner is not null) - secondaryHeaderLines.Add(($"Owner: {groupInfo.Owner.AliasOrUID}", false, true)); - - var infoStartY = MathF.Max(contentStartY, bannerHeight + style.WindowPadding.Y); - var aliasColumnX = infoOffsetX + 18f * scale; - ImGui.SetCursorPos(new Vector2(aliasColumnX, infoStartY)); - - ImGui.BeginGroup(); - using (_uiSharedService.UidFont.Push()) - { - ImGui.TextUnformatted(primaryHeaderText); - } - - foreach (var (text, useColor, disabled) in secondaryHeaderLines) - { - if (useColor && useVanityColors) - { - var seString = SeStringUtils.BuildFormattedPlayerName(text, vanityTextColor, vanityGlowColor); - SeStringUtils.RenderSeStringWithHitbox(seString, ImGui.GetCursorScreenPos(), ImGui.GetFont()); - } - else - { - if (disabled) - ImGui.TextDisabled(text); - else - ImGui.TextUnformatted(text); - } - } - ImGui.EndGroup(); - var namesEnd = ImGui.GetCursorPos(); - - var aliasGroupRectMin = ImGui.GetItemRectMin(); - var aliasGroupRectMax = ImGui.GetItemRectMax(); - var aliasGroupLocalMin = aliasGroupRectMin - windowPos; - var aliasGroupLocalMax = aliasGroupRectMax - windowPos; - - var tagsStartLocal = new Vector2(aliasGroupLocalMax.X + style.ItemSpacing.X + 25f * scale, aliasGroupLocalMin.Y + style.FramePadding.Y + 2f * scale); - ImGui.SetCursorPos(tagsStartLocal); - if (profileTags.Count > 0) - RenderProfileTags(profileTags, scale); - else - ImGui.TextDisabled("-- No tags set --"); - var tagsEndLocal = ImGui.GetCursorPos(); - var tagsBlockBottom = windowPos.Y + tagsEndLocal.Y; - var aliasBlockBottom = windowPos.Y + aliasGroupLocalMax.Y; - var aliasAndTagsBottomLocal = MathF.Max(aliasGroupLocalMax.Y, tagsEndLocal.Y); - var aliasAndTagsBlockBottom = MathF.Max(aliasBlockBottom, tagsBlockBottom); - - var descriptionSeparatorSpacing = style.ItemSpacing.Y * 0.35f; - var descriptionSeparatorThickness = MathF.Max(1f, scale); - var descriptionExtraOffset = groupInfo.Owner is not null ? style.ItemSpacing.Y * 0.6f : 0f; - var descriptionStartLocal = new Vector2(aliasColumnX, aliasAndTagsBottomLocal + descriptionSeparatorSpacing + descriptionExtraOffset); - var horizontalInset = style.ItemSpacing.X * 0.5f; - var descriptionSeparatorStart = windowPos + new Vector2(aliasColumnX - horizontalInset, descriptionStartLocal.Y); - var descriptionSeparatorEnd = new Vector2(windowPos.X + windowSize.X - style.WindowPadding.X + horizontalInset, descriptionSeparatorStart.Y); - drawList.AddLine(descriptionSeparatorStart, descriptionSeparatorEnd, ImGui.GetColorU32(portraitFrameBorder), descriptionSeparatorThickness); - - var descriptionContentStartLocal = new Vector2(aliasColumnX, descriptionStartLocal.Y + descriptionSeparatorThickness + descriptionSeparatorSpacing + style.FramePadding.Y * 0.75f); - ImGui.SetCursorPos(descriptionContentStartLocal); - ImGui.TextDisabled("Description"); - ImGui.SetCursorPosX(aliasColumnX); - var descriptionRegionWidth = ImGui.GetContentRegionAvail().X; - if (descriptionRegionWidth <= 0f) - descriptionRegionWidth = 1f; - var measurementWrapWidth = MathF.Max(1f, descriptionRegionWidth - style.WindowPadding.X * 2f); - var hasDescription = !string.IsNullOrWhiteSpace(profile.Description); - float descriptionContentHeight; - float lineHeightWithSpacing; - using (_uiSharedService.GameFont.Push()) - { - lineHeightWithSpacing = ImGui.GetTextLineHeightWithSpacing(); - var measurementText = hasDescription - ? NormalizeDescriptionForMeasurement(profile.Description!) - : GroupDescriptionPlaceholder; - if (string.IsNullOrWhiteSpace(measurementText)) - measurementText = GroupDescriptionPlaceholder; - - descriptionContentHeight = ImGui.CalcTextSize(measurementText, wrapWidth: measurementWrapWidth).Y; - if (descriptionContentHeight <= 0f) - descriptionContentHeight = lineHeightWithSpacing; - } - - var maxDescriptionHeight = lineHeightWithSpacing * DescriptionMaxVisibleLines; - var descriptionChildHeight = Math.Clamp(descriptionContentHeight, lineHeightWithSpacing, maxDescriptionHeight); - - RenderDescriptionChild( - "##StandaloneGroupDescription", - new Vector2(descriptionRegionWidth, descriptionChildHeight), - hasDescription ? profile.Description : null, - GroupDescriptionPlaceholder); - var descriptionEndLocal = ImGui.GetCursorPos(); - var descriptionBlockBottom = windowPos.Y + descriptionEndLocal.Y; - aliasAndTagsBottomLocal = MathF.Max(aliasAndTagsBottomLocal, descriptionEndLocal.Y); - aliasAndTagsBlockBottom = MathF.Max(aliasAndTagsBlockBottom, descriptionBlockBottom); - - var presenceLabelSpacing = style.ItemSpacing.Y * 0.35f; - var presenceAnchorY = MathF.Max(portraitFrameLocalMax.Y, aliasGroupLocalMax.Y); - var presenceStartLocal = new Vector2(portraitFrameLocalMin.X, presenceAnchorY + presenceLabelSpacing); - ImGui.SetCursorPos(presenceStartLocal); - ImGui.TextDisabled("Presence"); - ImGui.SetCursorPosX(portraitFrameLocalMin.X); - if (presenceTokens.Count > 0) - { - var presenceColumnWidth = MathF.Max(1f, aliasColumnX - portraitFrameLocalMin.X - style.ItemSpacing.X); - RenderPresenceTokens(presenceTokens, scale, presenceColumnWidth); - } - else - { - ImGui.TextDisabled("-- No status flags --"); - ImGui.Dummy(new Vector2(0f, style.ItemSpacing.Y * 0.25f)); - } - - var presenceContentEnd = ImGui.GetCursorPos(); - var separatorSpacing = style.ItemSpacing.Y * 0.2f; - var separatorThickness = MathF.Max(1f, scale); - var separatorStartLocal = new Vector2(portraitFrameLocalMin.X, presenceContentEnd.Y + separatorSpacing); - var separatorStart = windowPos + separatorStartLocal; - var separatorEnd = new Vector2(portraitFrameMax.X, separatorStart.Y); - drawList.AddLine(separatorStart, separatorEnd, ImGui.GetColorU32(portraitFrameBorder), separatorThickness); - var afterSeparatorLocal = separatorStartLocal + new Vector2(0f, separatorThickness + separatorSpacing * 0.75f); - - var columnStartLocalY = afterSeparatorLocal.Y; - var leftColumnX = portraitFrameLocalMin.X; - ImGui.SetCursorPos(new Vector2(leftColumnX, columnStartLocalY)); - float leftColumnEndY = columnStartLocalY; - - if (!string.IsNullOrEmpty(noteText)) - { - ImGui.TextDisabled("Notes"); - ImGui.SetCursorPosX(leftColumnX); - ImGui.PushTextWrapPos(ImGui.GetCursorPosX() + ImGui.GetContentRegionAvail().X); - ImGui.TextUnformatted(noteText); - ImGui.PopTextWrapPos(); - ImGui.SetCursorPos(new Vector2(leftColumnX, ImGui.GetCursorPosY() + style.ItemSpacing.Y * 0.5f)); - leftColumnEndY = ImGui.GetCursorPosY(); - } - - leftColumnEndY = MathF.Max(leftColumnEndY, ImGui.GetCursorPosY()); - - var columnsBottomLocal = leftColumnEndY; - var columnsBottom = windowPos.Y + columnsBottomLocal; - var topAreaBase = windowPos.Y + topAreaStart.Y; - var contentBlockBottom = MathF.Max(columnsBottom, aliasAndTagsBlockBottom); - var leftBlockBottom = MathF.Max(portraitBlockBottom, contentBlockBottom); - var topAreaHeight = leftBlockBottom - topAreaBase; - if (topAreaHeight < 0f) - topAreaHeight = 0f; - - ImGui.SetCursorPos(new Vector2(leftColumnX, topAreaStart.Y + topAreaHeight + style.ItemSpacing.Y)); - - var finalCursorY = ImGui.GetCursorPosY(); - var paddingY = ImGui.GetStyle().WindowPadding.Y; - var computedHeight = finalCursorY + paddingY; - var adjustedHeight = Math.Clamp(computedHeight, minHeight, maxAllowedHeight); - _lastComputedWindowHeight = adjustedHeight; - - var finalSize = new Vector2(baseWidth, adjustedHeight); - Size = finalSize; - ImGui.SetWindowSize(finalSize, ImGuiCond.Always); + ImGui.TextUnformatted(primaryHeaderText); } + + foreach (var (text, useColor, disabled) in secondaryHeaderLines) + { + if (useColor && useVanityColors) + { + var seString = SeStringUtils.BuildFormattedPlayerName(text, vanityTextColor, vanityGlowColor); + SeStringUtils.RenderSeStringWithHitbox(seString, ImGui.GetCursorScreenPos(), ImGui.GetFont()); + } + else + { + if (disabled) + ImGui.TextDisabled(text); + else + ImGui.TextUnformatted(text); + } + } + ImGui.EndGroup(); + var namesEnd = ImGui.GetCursorPos(); + + var aliasGroupRectMin = ImGui.GetItemRectMin(); + var aliasGroupRectMax = ImGui.GetItemRectMax(); + var aliasGroupLocalMin = aliasGroupRectMin - windowPos; + var aliasGroupLocalMax = aliasGroupRectMax - windowPos; + + var tagsStartLocal = new Vector2(aliasGroupLocalMax.X + style.ItemSpacing.X + 25f * scale, aliasGroupLocalMin.Y + style.FramePadding.Y + 2f * scale); + ImGui.SetCursorPos(tagsStartLocal); + if (profileTags.Count > 0) + RenderProfileTags(profileTags, scale); + else + ImGui.TextDisabled("-- No tags set --"); + var tagsEndLocal = ImGui.GetCursorPos(); + var tagsBlockBottom = windowPos.Y + tagsEndLocal.Y; + var aliasBlockBottom = windowPos.Y + aliasGroupLocalMax.Y; + var aliasAndTagsBottomLocal = MathF.Max(aliasGroupLocalMax.Y, tagsEndLocal.Y); + var aliasAndTagsBlockBottom = MathF.Max(aliasBlockBottom, tagsBlockBottom); + + var descriptionSeparatorSpacing = style.ItemSpacing.Y * 0.35f; + var descriptionSeparatorThickness = MathF.Max(1f, scale); + var descriptionExtraOffset = 0f; + if (groupInfo?.Owner is not null) + descriptionExtraOffset = style.ItemSpacing.Y * 0.6f; + var descriptionStartLocal = new Vector2(aliasColumnX, aliasAndTagsBottomLocal + descriptionSeparatorSpacing + descriptionExtraOffset); + var horizontalInset = style.ItemSpacing.X * 0.5f; + var descriptionSeparatorStart = windowPos + new Vector2(aliasColumnX - horizontalInset, descriptionStartLocal.Y); + var descriptionSeparatorEnd = new Vector2(windowPos.X + windowSize.X - style.WindowPadding.X + horizontalInset, descriptionSeparatorStart.Y); + drawList.AddLine(descriptionSeparatorStart, descriptionSeparatorEnd, ImGui.GetColorU32(portraitFrameBorder), descriptionSeparatorThickness); + + var descriptionContentStartLocal = new Vector2(aliasColumnX, descriptionStartLocal.Y + descriptionSeparatorThickness + descriptionSeparatorSpacing + style.FramePadding.Y * 0.75f); + ImGui.SetCursorPos(descriptionContentStartLocal); + ImGui.TextDisabled("Description"); + ImGui.SetCursorPosX(aliasColumnX); + var descriptionRegionWidth = ImGui.GetContentRegionAvail().X; + if (descriptionRegionWidth <= 0f) + descriptionRegionWidth = 1f; + var measurementWrapWidth = MathF.Max(1f, descriptionRegionWidth - style.WindowPadding.X * 2f); + var hasDescription = !string.IsNullOrWhiteSpace(profile.Description); + float descriptionContentHeight; + float lineHeightWithSpacing; + using (_uiSharedService.GameFont.Push()) + { + lineHeightWithSpacing = ImGui.GetTextLineHeightWithSpacing(); + var measurementText = hasDescription + ? NormalizeDescriptionForMeasurement(profile.Description!) + : GroupDescriptionPlaceholder; + if (string.IsNullOrWhiteSpace(measurementText)) + measurementText = GroupDescriptionPlaceholder; + + descriptionContentHeight = ImGui.CalcTextSize(measurementText, wrapWidth: measurementWrapWidth).Y; + if (descriptionContentHeight <= 0f) + descriptionContentHeight = lineHeightWithSpacing; + } + + var maxDescriptionHeight = lineHeightWithSpacing * DescriptionMaxVisibleLines; + var descriptionChildHeight = Math.Clamp(descriptionContentHeight, lineHeightWithSpacing, maxDescriptionHeight); + + RenderDescriptionChild( + "##StandaloneGroupDescription", + new Vector2(descriptionRegionWidth, descriptionChildHeight), + hasDescription ? profile.Description : null, + GroupDescriptionPlaceholder); + var descriptionEndLocal = ImGui.GetCursorPos(); + var descriptionBlockBottom = windowPos.Y + descriptionEndLocal.Y; + aliasAndTagsBottomLocal = MathF.Max(aliasAndTagsBottomLocal, descriptionEndLocal.Y); + aliasAndTagsBlockBottom = MathF.Max(aliasAndTagsBlockBottom, descriptionBlockBottom); + + var presenceLabelSpacing = style.ItemSpacing.Y * 0.35f; + var presenceAnchorY = MathF.Max(portraitFrameLocalMax.Y, aliasGroupLocalMax.Y); + var presenceStartLocal = new Vector2(portraitFrameLocalMin.X, presenceAnchorY + presenceLabelSpacing); + ImGui.SetCursorPos(presenceStartLocal); + ImGui.TextDisabled("Presence"); + ImGui.SetCursorPosX(portraitFrameLocalMin.X); + if (presenceTokens.Count > 0) + { + var presenceColumnWidth = MathF.Max(1f, aliasColumnX - portraitFrameLocalMin.X - style.ItemSpacing.X); + RenderPresenceTokens(presenceTokens, scale, presenceColumnWidth); + } + else + { + ImGui.TextDisabled("-- No status flags --"); + ImGui.Dummy(new Vector2(0f, style.ItemSpacing.Y * 0.25f)); + } + + var presenceContentEnd = ImGui.GetCursorPos(); + var separatorSpacing = style.ItemSpacing.Y * 0.2f; + var separatorThickness = MathF.Max(1f, scale); + var separatorStartLocal = new Vector2(portraitFrameLocalMin.X, presenceContentEnd.Y + separatorSpacing); + var separatorStart = windowPos + separatorStartLocal; + var separatorEnd = new Vector2(portraitFrameMax.X, separatorStart.Y); + drawList.AddLine(separatorStart, separatorEnd, ImGui.GetColorU32(portraitFrameBorder), separatorThickness); + var afterSeparatorLocal = separatorStartLocal + new Vector2(0f, separatorThickness + separatorSpacing * 0.75f); + + var columnStartLocalY = afterSeparatorLocal.Y; + var leftColumnX = portraitFrameLocalMin.X; + ImGui.SetCursorPos(new Vector2(leftColumnX, columnStartLocalY)); + float leftColumnEndY = columnStartLocalY; + + if (!string.IsNullOrEmpty(noteText)) + { + ImGui.TextDisabled("Notes"); + ImGui.SetCursorPosX(leftColumnX); + ImGui.PushTextWrapPos(ImGui.GetCursorPosX() + ImGui.GetContentRegionAvail().X); + ImGui.TextUnformatted(noteText); + ImGui.PopTextWrapPos(); + ImGui.SetCursorPos(new Vector2(leftColumnX, ImGui.GetCursorPosY() + style.ItemSpacing.Y * 0.5f)); + leftColumnEndY = ImGui.GetCursorPosY(); + } + + leftColumnEndY = MathF.Max(leftColumnEndY, ImGui.GetCursorPosY()); + + var columnsBottomLocal = leftColumnEndY; + var columnsBottom = windowPos.Y + columnsBottomLocal; + var topAreaBase = windowPos.Y + topAreaStart.Y; + var contentBlockBottom = MathF.Max(columnsBottom, aliasAndTagsBlockBottom); + var leftBlockBottom = MathF.Max(portraitBlockBottom, contentBlockBottom); + var topAreaHeight = leftBlockBottom - topAreaBase; + if (topAreaHeight < 0f) + topAreaHeight = 0f; + + ImGui.SetCursorPos(new Vector2(leftColumnX, topAreaStart.Y + topAreaHeight + style.ItemSpacing.Y)); + + var finalCursorY = ImGui.GetCursorPosY(); + var paddingY = ImGui.GetStyle().WindowPadding.Y; + var computedHeight = finalCursorY + paddingY; + var adjustedHeight = Math.Clamp(computedHeight, minHeight, maxAllowedHeight); + _lastComputedWindowHeight = adjustedHeight; + + var finalSize = new Vector2(baseWidth, adjustedHeight); + Size = finalSize; + ImGui.SetWindowSize(finalSize, ImGuiCond.Always); } private IDalamudTextureWrap? GetBannerTexture(byte[] bannerBytes)