1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-06-16 04:25:23 +00:00

Added support for label and button text wrappping and alignment.

This commit is contained in:
Tim Sarbin 2018-11-28 23:03:32 -05:00
parent 403864fdd1
commit 04498ad9a5
6 changed files with 119 additions and 17 deletions

View File

@ -0,0 +1,9 @@
namespace OpenDiablo2.Common.Enums
{
public enum eTextAlign
{
Centered = 0,
Left,
Right
}
}

View File

@ -1,5 +1,6 @@
using System;
using System.Drawing;
using OpenDiablo2.Common.Enums;
namespace OpenDiablo2.Common.Interfaces
{
@ -9,5 +10,7 @@ namespace OpenDiablo2.Common.Interfaces
Point Location { get; set; }
Size TextArea { get; set; }
Color TextColor { get; set; }
int MaxWidth { get; set; }
eTextAlign Alignment { get; set; }
}
}

View File

@ -77,6 +77,7 @@
<Compile Include="Enums\eLevelSubType.cs" />
<Compile Include="Enums\eMPQFormatVersion.cs" />
<Compile Include="Enums\eRenderCellType.cs" />
<Compile Include="Enums\eTextAlign.cs" />
<Compile Include="Enums\eWildBorder.cs" />
<Compile Include="Interfaces\IButton.cs" />
<Compile Include="Interfaces\IEngineDataManager.cs" />

View File

@ -82,7 +82,6 @@ namespace OpenDiablo2.Core.UI
font = renderWindow.LoadFont(ResourcePaths.FontExocet10, Palettes.Units);
label = renderWindow.CreateLabel(font);
sprite = renderWindow.LoadSprite(buttonLayout.ResourceName, buttonLayout.PaletteName);
// TODO: Less stupid way of doing this would be nice
@ -94,6 +93,9 @@ namespace OpenDiablo2.Core.UI
buttonWidth += sprite.LocalFrameSize.Width;
buttonHeight = Math.Max(buttonHeight, sprite.LocalFrameSize.Height);
}
label.MaxWidth = buttonWidth - 8;
label.Alignment = Common.Enums.eTextAlign.Centered;
}
public bool Toggle()
@ -201,7 +203,8 @@ namespace OpenDiablo2.Core.UI
label.TextColor = Color.FromArgb(75, 75, 75);
var offsetX = (buttonWidth / 2) - (label.TextArea.Width / 2);
labelOffset = new Point(offsetX, -5);
var offsetY = (buttonHeight / 2) - (label.TextArea.Height / 2);
labelOffset = new Point(offsetX, offsetY - 5);
}
public void Dispose()

View File

@ -1,4 +1,5 @@
using OpenDiablo2.Common.Interfaces;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Interfaces;
using SDL2;
using System;
using System.Collections.Generic;
@ -43,25 +44,59 @@ namespace OpenDiablo2.SDL2_
}
}
public int MaxWidth { get; set; }
public eTextAlign Alignment { get; set; }
internal SDL2Label(IFont font, IntPtr renderer)
{
this.renderer = renderer;
this.font = font as SDL2Font;
this.texture = IntPtr.Zero;
this.MaxWidth = -1;
}
internal Size CalculateSize()
{
int w = 0;
int h = 0;
foreach (var ch in text)
if (MaxWidth == -1)
{
var metric = font.font.CharacterMetric[(byte)ch];
w += metric.Width;
h = Math.Max(Math.Max(h, metric.Height), font.sprite.FrameSize.Height);
int w = 0;
int h = 0;
foreach (var ch in text)
{
var metric = font.font.CharacterMetric[(byte)ch];
w += metric.Width;
h = Math.Max(Math.Max(h, metric.Height), font.sprite.FrameSize.Height);
}
return new Size(w, h);
}
return new Size(w, h);
if (MaxWidth < (font.sprite.FrameSize.Width))
throw new ApplicationException("Max label width cannot be smaller than a single character.");
var lastWordIndex = 0;
var width = 0;
var maxWidth = 0;
var height = font.sprite.FrameSize.Height;
for (int idx = 0; idx < text.Length; idx++)
{
width += font.font.CharacterMetric[(byte)text[idx]].Width;
if (width >= MaxWidth)
{
idx = lastWordIndex;
height += font.font.CharacterMetric[(byte)'|'].Height + 6;
width = 0;
continue;
}
maxWidth = Math.Max(width, maxWidth);
if (idx > 0 && (text[idx - 1] == ' ') && (text[idx] != ' '))
lastWordIndex = idx;
}
return new Size(maxWidth, height);
}
internal int Pow2(int input)
@ -90,14 +125,65 @@ namespace OpenDiablo2.SDL2_
SDL.SDL_RenderClear(renderer);
SDL.SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
int cx = 0;
int cy = 0;
foreach (var ch in text)
if (MaxWidth == -1)
{
WriteCharacter(cx, cy, (byte)ch);
cx += font.font.CharacterMetric[(byte)ch].Width;
}
int cx = 0;
int cy = 0;
foreach (var ch in text)
{
WriteCharacter(cx, cy, (byte)ch);
cx += font.font.CharacterMetric[(byte)ch].Width;
}
}
else
{
var linesToRender = new List<string>();
var lastWordIndex = 0;
var width = 0;
var lastStartX = 0;
for (int idx = 0; idx < text.Length; idx++)
{
width += font.font.CharacterMetric[(byte)text[idx]].Width;
if (width >= MaxWidth)
{
idx = lastWordIndex;
linesToRender.Add(text.Substring(lastStartX, lastWordIndex- lastStartX));
lastStartX = idx;
width = 0;
continue;
}
if (idx > 0 && text[idx - 1] == ' ' && text[idx] != ' ')
lastWordIndex = idx;
}
var lastLine = text.Substring(lastStartX)?.Trim();
if (!String.IsNullOrEmpty(lastLine))
linesToRender.Add(lastLine);
var y = 0;
foreach(var line in linesToRender)
{
var lineWidth = (line.Sum(c => font.font.CharacterMetric[(byte)c].Width));
var x = 0;
if (Alignment == eTextAlign.Centered)
x = (TextArea.Width / 2) - (lineWidth / 2);
else if (Alignment == eTextAlign.Right)
x = TextArea.Width - lineWidth;
foreach (var ch in line)
{
WriteCharacter(x, y, (byte)ch);
x += font.font.CharacterMetric[(byte)ch].Width;
}
y += font.font.CharacterMetric[(byte)'|'].Height + 6;
}
}
SDL.SDL_SetRenderTarget(renderer, IntPtr.Zero);
}

View File

@ -26,7 +26,7 @@ namespace OpenDiablo2.Scenes
backgroundSprite = renderWindow.LoadSprite(ResourcePaths.CharacterSelectionBackground, Palettes.Sky);
createNewCharacterButton = createButton(eButtonType.Tall);
// TODO: use strCreateNewCharacter -- need to get the text to split after 10 chars though.
createNewCharacterButton.Text = "Create New".ToUpper();
createNewCharacterButton.Text = textDictionary.Translate("strCreateNewCharacter");// "Create New".ToUpper();
createNewCharacterButton.Location = new Point(33, 467);
createNewCharacterButton.OnActivate = () => sceneManager.ChangeScene("Select Hero Class");