Add line wrapping

This commit is contained in:
Lynix 2019-07-05 23:12:12 +02:00
parent b41637c990
commit 0ec1480024
7 changed files with 79 additions and 13 deletions

View File

@ -190,6 +190,7 @@ Nazara Engine:
- ⚠ SimpleTextDrawer no longer supports faux bold rendering - ⚠ SimpleTextDrawer no longer supports faux bold rendering
- Added PhysWorld2D::[RaycastQuery, RegionQuery] overloads taking a callback - Added PhysWorld2D::[RaycastQuery, RegionQuery] overloads taking a callback
- Added x and y mouse position to MouseWheelEvent - Added x and y mouse position to MouseWheelEvent
- Added SimpleTextDrawer::[Get|Set]MaxLineWidth (which does line wrap)
Nazara Development Kit: Nazara Development Kit:
- Added ImageWidget (#139) - Added ImageWidget (#139)
@ -275,6 +276,7 @@ Nazara Development Kit:
- BaseWidget now has a rendering rect property (allowing to tell a widget what part of it will be rendered) - BaseWidget now has a rendering rect property (allowing to tell a widget what part of it will be rendered)
- Added ScrollAreaWidget - Added ScrollAreaWidget
- Console has been remade with widgets (allowing to scroll back history, select text, etc.) - Console has been remade with widgets (allowing to scroll back history, select text, etc.)
- Added TextAreaWidget line wrap option
# 0.4: # 0.4:

View File

@ -32,7 +32,7 @@ namespace Ndk
//virtual TextAreaWidget* Clone() const = 0; //virtual TextAreaWidget* Clone() const = 0;
void EnableLineWrap(bool enable = true);
inline void EnableMultiline(bool enable = true); inline void EnableMultiline(bool enable = true);
inline void EnableTabWriting(bool enable = true); inline void EnableTabWriting(bool enable = true);
@ -57,6 +57,7 @@ namespace Ndk
inline bool HasSelection() const; inline bool HasSelection() const;
inline bool IsLineWrapEnabled() const;
inline bool IsMultilineEnabled() const; inline bool IsMultilineEnabled() const;
inline bool IsReadOnly() const; inline bool IsReadOnly() const;
inline bool IsTabWritingEnabled() const; inline bool IsTabWritingEnabled() const;
@ -122,6 +123,7 @@ namespace Ndk
Nz::Vector2ui m_cursorPositionEnd; Nz::Vector2ui m_cursorPositionEnd;
Nz::Vector2ui m_selectionCursor; Nz::Vector2ui m_selectionCursor;
std::vector<Nz::SpriteRef> m_cursorSprites; std::vector<Nz::SpriteRef> m_cursorSprites;
bool m_isLineWrapEnabled;
bool m_isMouseButtonDown; bool m_isMouseButtonDown;
bool m_multiLineEnabled; bool m_multiLineEnabled;
bool m_readOnly; bool m_readOnly;

View File

@ -123,6 +123,11 @@ namespace Ndk
return m_cursorPositionBegin != m_cursorPositionEnd; return m_cursorPositionBegin != m_cursorPositionEnd;
} }
inline bool TextAreaWidget::IsLineWrapEnabled() const
{
return m_isLineWrapEnabled;
}
inline bool TextAreaWidget::IsMultilineEnabled() const inline bool TextAreaWidget::IsMultilineEnabled() const
{ {
return m_multiLineEnabled; return m_multiLineEnabled;

View File

@ -45,6 +45,7 @@ namespace Ndk
// History // History
m_history = Add<TextAreaWidget>(); m_history = Add<TextAreaWidget>();
m_history->EnableBackground(true); m_history->EnableBackground(true);
m_history->EnableLineWrap(true);
m_history->SetReadOnly(true); m_history->SetReadOnly(true);
m_history->SetBackgroundColor(Nz::Color(80, 80, 160, 128)); m_history->SetBackgroundColor(Nz::Color(80, 80, 160, 128));

View File

@ -16,6 +16,7 @@ namespace Ndk
m_echoMode(EchoMode_Normal), m_echoMode(EchoMode_Normal),
m_cursorPositionBegin(0U, 0U), m_cursorPositionBegin(0U, 0U),
m_cursorPositionEnd(0U, 0U), m_cursorPositionEnd(0U, 0U),
m_isLineWrapEnabled(false),
m_isMouseButtonDown(false), m_isMouseButtonDown(false),
m_multiLineEnabled(false), m_multiLineEnabled(false),
m_readOnly(false), m_readOnly(false),
@ -74,12 +75,26 @@ namespace Ndk
} }
} }
m_textSprite->Update(m_drawer); UpdateTextSprite();
SetPreferredSize(Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths()));
OnTextChanged(this, m_text); OnTextChanged(this, m_text);
} }
void TextAreaWidget::EnableLineWrap(bool enable)
{
if (m_isLineWrapEnabled != enable)
{
m_isLineWrapEnabled = enable;
if (enable)
m_drawer.SetMaxLineWidth(GetWidth());
else
m_drawer.SetMaxLineWidth(std::numeric_limits<float>::infinity());
UpdateTextSprite();
}
}
void TextAreaWidget::Erase(std::size_t firstGlyph, std::size_t lastGlyph) void TextAreaWidget::Erase(std::size_t firstGlyph, std::size_t lastGlyph)
{ {
if (firstGlyph > lastGlyph) if (firstGlyph > lastGlyph)
@ -188,6 +203,12 @@ namespace Ndk
{ {
BaseWidget::Layout(); BaseWidget::Layout();
if (m_isLineWrapEnabled)
{
m_drawer.SetMaxLineWidth(GetWidth());
UpdateTextSprite();
}
RefreshCursor(); RefreshCursor();
} }
@ -607,9 +628,14 @@ namespace Ndk
break; break;
} }
m_textSprite->Update(m_drawer); UpdateTextSprite();
SetPreferredSize(Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths()));
SetCursorPosition(m_cursorPositionBegin); //< Refresh cursor position (prevent it from being outside of the text) SetCursorPosition(m_cursorPositionBegin); //< Refresh cursor position (prevent it from being outside of the text)
} }
void TextAreaWidget::UpdateTextSprite()
{
m_textSprite->Update(m_drawer);
SetPreferredSize(Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths()));
}
} }

View File

@ -38,6 +38,7 @@ namespace Nz
std::size_t GetGlyphCount() const override; std::size_t GetGlyphCount() const override;
const Line& GetLine(std::size_t index) const override; const Line& GetLine(std::size_t index) const override;
std::size_t GetLineCount() const override; std::size_t GetLineCount() const override;
float GetMaxLineWidth() const;
const Color& GetOutlineColor() const; const Color& GetOutlineColor() const;
float GetOutlineThickness() const; float GetOutlineThickness() const;
TextStyleFlags GetStyle() const; TextStyleFlags GetStyle() const;
@ -46,6 +47,7 @@ namespace Nz
void SetCharacterSize(unsigned int characterSize); void SetCharacterSize(unsigned int characterSize);
void SetColor(const Color& color); void SetColor(const Color& color);
void SetFont(Font* font); void SetFont(Font* font);
void SetMaxLineWidth(float lineWidth);
void SetOutlineColor(const Color& color); void SetOutlineColor(const Color& color);
void SetOutlineThickness(float thickness); void SetOutlineThickness(float thickness);
void SetStyle(TextStyleFlags style); void SetStyle(TextStyleFlags style);
@ -88,6 +90,7 @@ namespace Nz
mutable Vector2ui m_drawPos; mutable Vector2ui m_drawPos;
mutable bool m_colorUpdated; mutable bool m_colorUpdated;
mutable bool m_glyphUpdated; mutable bool m_glyphUpdated;
float m_maxLineWidth;
float m_outlineThickness; float m_outlineThickness;
unsigned int m_characterSize; unsigned int m_characterSize;
}; };

View File

@ -3,6 +3,7 @@
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/SimpleTextDrawer.hpp> #include <Nazara/Utility/SimpleTextDrawer.hpp>
#include <limits>
#include <memory> #include <memory>
#include <Nazara/Utility/Debug.hpp> #include <Nazara/Utility/Debug.hpp>
@ -14,6 +15,7 @@ namespace Nz
m_style(TextStyle_Regular), m_style(TextStyle_Regular),
m_colorUpdated(true), m_colorUpdated(true),
m_glyphUpdated(true), m_glyphUpdated(true),
m_maxLineWidth(std::numeric_limits<float>::infinity()),
m_outlineThickness(0.f), m_outlineThickness(0.f),
m_characterSize(24) m_characterSize(24)
{ {
@ -27,6 +29,7 @@ namespace Nz
m_colorUpdated(false), m_colorUpdated(false),
m_glyphUpdated(false), m_glyphUpdated(false),
m_outlineColor(drawer.m_outlineColor), m_outlineColor(drawer.m_outlineColor),
m_maxLineWidth(drawer.m_maxLineWidth),
m_outlineThickness(drawer.m_outlineThickness), m_outlineThickness(drawer.m_outlineThickness),
m_characterSize(drawer.m_characterSize) m_characterSize(drawer.m_characterSize)
{ {
@ -124,6 +127,11 @@ namespace Nz
return m_lines.size(); return m_lines.size();
} }
float SimpleTextDrawer::GetMaxLineWidth() const
{
return m_maxLineWidth;
}
const Color& SimpleTextDrawer::GetOutlineColor() const const Color& SimpleTextDrawer::GetOutlineColor() const
{ {
return m_outlineColor; return m_outlineColor;
@ -173,6 +181,15 @@ namespace Nz
} }
} }
void SimpleTextDrawer::SetMaxLineWidth(float lineWidth)
{
NazaraAssert(m_maxLineWidth > 0.f, "Max line width must be positive");
m_maxLineWidth = lineWidth;
m_glyphUpdated = false;
}
void SimpleTextDrawer::SetOutlineColor(const Color& color) void SimpleTextDrawer::SetOutlineColor(const Color& color)
{ {
m_outlineColor = color; m_outlineColor = color;
@ -230,6 +247,7 @@ namespace Nz
m_glyphs = std::move(drawer.m_glyphs); m_glyphs = std::move(drawer.m_glyphs);
m_glyphUpdated = std::move(drawer.m_glyphUpdated); m_glyphUpdated = std::move(drawer.m_glyphUpdated);
m_font = std::move(drawer.m_font); m_font = std::move(drawer.m_font);
m_maxLineWidth = drawer.m_maxLineWidth;
m_outlineColor = std::move(drawer.m_outlineColor); m_outlineColor = std::move(drawer.m_outlineColor);
m_outlineThickness = std::move(drawer.m_outlineThickness); m_outlineThickness = std::move(drawer.m_outlineThickness);
m_style = std::move(drawer.m_style); m_style = std::move(drawer.m_style);
@ -365,7 +383,18 @@ namespace Nz
break; break;
} }
auto GenerateGlyph = [this](Glyph& glyph, char32_t character, float outlineThickness, Nz::Color color, int renderOrder, int* advance) auto AppendNewLine = [&]()
{
// Reset cursor
//advance = 0;
m_drawPos.x = 0;
m_drawPos.y += sizeInfo.lineHeight;
m_workingBounds.ExtendTo(m_lines.back().bounds);
m_lines.emplace_back(Line{ Rectf(0.f, float(sizeInfo.lineHeight * m_lines.size()), 0.f, float(sizeInfo.lineHeight)), m_glyphs.size() + 1 });
};
auto GenerateGlyph = [&](Glyph& glyph, char32_t character, float outlineThickness, Nz::Color color, int renderOrder, int* advance)
{ {
const Font::Glyph& fontGlyph = m_font->GetGlyph(m_characterSize, m_style, outlineThickness, character); const Font::Glyph& fontGlyph = m_font->GetGlyph(m_characterSize, m_style, outlineThickness, character);
if (fontGlyph.valid && fontGlyph.fauxOutlineThickness <= 0.f) if (fontGlyph.valid && fontGlyph.fauxOutlineThickness <= 0.f)
@ -377,6 +406,10 @@ namespace Nz
glyph.renderOrder = renderOrder; glyph.renderOrder = renderOrder;
glyph.bounds.Set(fontGlyph.aabb); glyph.bounds.Set(fontGlyph.aabb);
if (m_lines.back().glyphIndex <= m_glyphs.size() && m_lines.back().bounds.GetMaximum().x + glyph.bounds.width > m_maxLineWidth)
AppendNewLine();
glyph.bounds.x += m_drawPos.x; glyph.bounds.x += m_drawPos.x;
glyph.bounds.y += m_drawPos.y; glyph.bounds.y += m_drawPos.y;
@ -435,13 +468,7 @@ namespace Nz
{ {
case '\n': case '\n':
{ {
// Reset cursor AppendNewLine();
advance = 0;
m_drawPos.x = 0;
m_drawPos.y += sizeInfo.lineHeight;
m_workingBounds.ExtendTo(m_lines.back().bounds);
m_lines.emplace_back(Line{Rectf(0.f, float(sizeInfo.lineHeight * m_lines.size()), 0.f, float(sizeInfo.lineHeight)), m_glyphs.size() + 1});
break; break;
} }