Fix Rich Text Box vertical alignment of the inlined images and whole contents

#3502 ae4ae7a638 7ee2e66881
This commit is contained in:
2026-01-29 10:55:10 +01:00
parent f773a0755d
commit c9d16e16cc
2 changed files with 53 additions and 34 deletions
@@ -143,6 +143,40 @@ namespace FlaxEngine.GUI
context.Caret.X = 0;
OnLineAdded(ref context, _text.Length - 1);
}
// Organize lines vertically
if (_textBlocks.Count != 0)
{
var lastBlock = _textBlocks[_textBlocks.Count - 1];
// Get style (global or leftover from style stack or the last lime)
var verticalAlignments = _textStyle.Alignment;
if (context.StyleStack.Count > 1)
verticalAlignments = context.StyleStack.Peek().Alignment;
else if ((lastBlock.Style.Alignment & TextBlockStyle.Alignments.VerticalMask) != TextBlockStyle.Alignments.Baseline)
verticalAlignments = lastBlock.Style.Alignment;
var totalSize = lastBlock.Bounds.BottomRight;
var sizeOffset = Size - totalSize;
var textBlocks = CollectionsMarshal.AsSpan(_textBlocks);
if ((verticalAlignments & TextBlockStyle.Alignments.Middle) == TextBlockStyle.Alignments.Middle)
{
sizeOffset.Y *= 0.5f;
for (int i = 0; i < _textBlocks.Count; i++)
{
ref TextBlock textBlock = ref textBlocks[i];
textBlock.Bounds.Location.Y += sizeOffset.Y;
}
}
else if ((verticalAlignments & TextBlockStyle.Alignments.Bottom) == TextBlockStyle.Alignments.Bottom)
{
for (int i = 0; i < _textBlocks.Count; i++)
{
ref TextBlock textBlock = ref textBlocks[i];
textBlock.Bounds.Location.Y += sizeOffset.Y;
}
}
}
}
/// <summary>
@@ -239,14 +273,15 @@ namespace FlaxEngine.GUI
}
// Organize text blocks within line
var horizontalAlignments = TextBlockStyle.Alignments.Baseline;
var verticalAlignments = TextBlockStyle.Alignments.Baseline;
var lineAlignments = TextBlockStyle.Alignments.Baseline;
for (int i = context.LineStartTextBlockIndex; i < _textBlocks.Count; i++)
{
ref TextBlock textBlock = ref textBlocks[i];
var vOffset = lineSize.Y - textBlock.Bounds.Height;
horizontalAlignments |= textBlock.Style.Alignment & TextBlockStyle.Alignments.HorizontalMask;
verticalAlignments |= textBlock.Style.Alignment & TextBlockStyle.Alignments.VerticalMask;
if (i == context.LineStartTextBlockIndex)
lineAlignments = textBlock.Style.Alignment;
else
lineAlignments &= textBlock.Style.Alignment;
switch (textBlock.Style.Alignment & TextBlockStyle.Alignments.VerticalMask)
{
case TextBlockStyle.Alignments.Baseline:
@@ -275,9 +310,9 @@ namespace FlaxEngine.GUI
}
}
// Organize blocks within whole container
// Organize whole line horizontally
var sizeOffset = Size - lineSize;
if ((horizontalAlignments & TextBlockStyle.Alignments.Center) == TextBlockStyle.Alignments.Center)
if ((lineAlignments & TextBlockStyle.Alignments.Center) == TextBlockStyle.Alignments.Center)
{
sizeOffset.X *= 0.5f;
for (int i = context.LineStartTextBlockIndex; i < _textBlocks.Count; i++)
@@ -286,7 +321,7 @@ namespace FlaxEngine.GUI
textBlock.Bounds.Location.X += sizeOffset.X;
}
}
else if ((horizontalAlignments & TextBlockStyle.Alignments.Right) == TextBlockStyle.Alignments.Right)
else if ((lineAlignments & TextBlockStyle.Alignments.Right) == TextBlockStyle.Alignments.Right)
{
for (int i = context.LineStartTextBlockIndex; i < _textBlocks.Count; i++)
{
@@ -294,23 +329,6 @@ namespace FlaxEngine.GUI
textBlock.Bounds.Location.X += sizeOffset.X;
}
}
if ((verticalAlignments & TextBlockStyle.Alignments.Middle) == TextBlockStyle.Alignments.Middle)
{
sizeOffset.Y *= 0.5f;
for (int i = context.LineStartTextBlockIndex; i < _textBlocks.Count; i++)
{
ref TextBlock textBlock = ref textBlocks[i];
textBlock.Bounds.Location.Y += sizeOffset.Y;
}
}
else if ((verticalAlignments & TextBlockStyle.Alignments.Bottom) == TextBlockStyle.Alignments.Bottom)
{
for (int i = context.LineStartTextBlockIndex; i < _textBlocks.Count; i++)
{
ref TextBlock textBlock = ref textBlocks[i];
textBlock.Bounds.Location.Y += sizeOffset.Y;
}
}
// Move to the next line
context.LineStartCharacterIndex = lineEnd + 1;
+11 -10
View File
@@ -175,7 +175,7 @@ namespace FlaxEngine.GUI
// Setup size
var font = imageBlock.Style.Font.GetFont();
if (font)
imageBlock.Bounds.Size = new Float2(font.Height);
imageBlock.Bounds.Size = new Float2(font.Ascender);
var imageSize = image.Size;
imageBlock.Bounds.Size.X *= imageSize.X / imageSize.Y; // Keep original aspect ratio
bool hasWidth = TryParseNumberTag(ref tag, "width", imageBlock.Bounds.Width, out var width);
@@ -215,16 +215,16 @@ namespace FlaxEngine.GUI
switch (valign)
{
case "top":
style.Alignment = TextBlockStyle.Alignments.Top;
style.Alignment |= TextBlockStyle.Alignments.Top;
break;
case "bottom":
style.Alignment = TextBlockStyle.Alignments.Bottom;
style.Alignment |= TextBlockStyle.Alignments.Bottom;
break;
case "middle":
style.Alignment = TextBlockStyle.Alignments.Middle;
style.Alignment |= TextBlockStyle.Alignments.Middle;
break;
case "baseline":
style.Alignment = TextBlockStyle.Alignments.Baseline;
style.Alignment |= TextBlockStyle.Alignments.Baseline;
break;
}
}
@@ -243,17 +243,17 @@ namespace FlaxEngine.GUI
var style = context.StyleStack.Peek();
if (tag.Attributes.TryGetValue(string.Empty, out var valign))
{
style.Alignment &= ~TextBlockStyle.Alignments.VerticalMask;
style.Alignment &= ~TextBlockStyle.Alignments.HorizontalMask;
switch (valign)
{
case "left":
style.Alignment = TextBlockStyle.Alignments.Left;
style.Alignment |= TextBlockStyle.Alignments.Left;
break;
case "right":
style.Alignment = TextBlockStyle.Alignments.Right;
style.Alignment |= TextBlockStyle.Alignments.Right;
break;
case "center":
style.Alignment = TextBlockStyle.Alignments.Center;
style.Alignment |= TextBlockStyle.Alignments.Center;
break;
}
}
@@ -270,7 +270,8 @@ namespace FlaxEngine.GUI
else
{
var style = context.StyleStack.Peek();
style.Alignment = TextBlockStyle.Alignments.Center;
style.Alignment &= ~TextBlockStyle.Alignments.HorizontalMask;
style.Alignment |= TextBlockStyle.Alignments.Center;
context.StyleStack.Push(style);
}
}