multiline labels
This commit is contained in:
@@ -20,7 +20,8 @@ namespace gui {
|
|||||||
using onnumberchange = std::function<void(GUI*, double)>;
|
using onnumberchange = std::function<void(GUI*, double)>;
|
||||||
|
|
||||||
enum class Align {
|
enum class Align {
|
||||||
left, center, right
|
left, center, right,
|
||||||
|
top=left, bottom=right,
|
||||||
};
|
};
|
||||||
|
|
||||||
class UINode {
|
class UINode {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include "controls.h"
|
#include "controls.h"
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
#include <sstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "../../window/Events.h"
|
#include "../../window/Events.h"
|
||||||
@@ -30,9 +32,16 @@ Label::Label(std::wstring text, std::string fontName)
|
|||||||
|
|
||||||
void Label::setText(std::wstring text) {
|
void Label::setText(std::wstring text) {
|
||||||
this->text = text;
|
this->text = text;
|
||||||
|
lines = 1;
|
||||||
|
for (size_t i = 0; i < text.length(); i++) {
|
||||||
|
if (text[i] == L'\n') {
|
||||||
|
lines++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lines = std::max(lines, 1U);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring Label::getText() const {
|
const std::wstring& Label::getText() const {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,18 +53,45 @@ const std::string& Label::getFontName() const {
|
|||||||
return fontName;
|
return fontName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Label::setVerticalAlign(Align align) {
|
||||||
|
this->valign = align;
|
||||||
|
}
|
||||||
|
|
||||||
|
Align Label::getVerticalAlign() const {
|
||||||
|
return valign;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Label::getLineInterval() const {
|
||||||
|
return lineInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Label::setLineInterval(float interval) {
|
||||||
|
lineInterval = interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Label::getTextYOffset() const {
|
||||||
|
return textYOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Label::getLineYOffset(uint line) const {
|
||||||
|
return line * totalLineHeight + textYOffset;
|
||||||
|
}
|
||||||
|
|
||||||
void Label::draw(const GfxContext* pctx, Assets* assets) {
|
void Label::draw(const GfxContext* pctx, Assets* assets) {
|
||||||
if (supplier) {
|
if (supplier) {
|
||||||
setText(supplier());
|
setText(supplier());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto batch = pctx->getBatch2D();
|
auto batch = pctx->getBatch2D();
|
||||||
|
auto font = assets->getFont(fontName);
|
||||||
|
|
||||||
batch->color = getColor();
|
batch->color = getColor();
|
||||||
Font* font = assets->getFont(fontName);
|
|
||||||
|
uint lineHeight = font->getLineHeight();
|
||||||
glm::vec2 size = getSize();
|
glm::vec2 size = getSize();
|
||||||
glm::vec2 newsize (
|
glm::vec2 newsize (
|
||||||
font->calcWidth(text),
|
font->calcWidth(text),
|
||||||
font->getLineHeight()+font->getYOffset()
|
(lines == 1 ? lineHeight : lineHeight*lineInterval)*lines + font->getYOffset()
|
||||||
);
|
);
|
||||||
|
|
||||||
glm::vec2 coord = calcCoord();
|
glm::vec2 coord = calcCoord();
|
||||||
@@ -69,14 +105,48 @@ void Label::draw(const GfxContext* pctx, Assets* assets) {
|
|||||||
coord.x += size.x-newsize.x;
|
coord.x += size.x-newsize.x;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
coord.y += (size.y-newsize.y)*0.5f;
|
switch (valign) {
|
||||||
font->draw(batch, text, coord.x, coord.y);
|
case Align::top:
|
||||||
|
break;
|
||||||
|
case Align::center:
|
||||||
|
coord.y += (size.y-newsize.y)*0.5f;
|
||||||
|
break;
|
||||||
|
case Align::bottom:
|
||||||
|
coord.y += size.y-newsize.y;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
textYOffset = coord.y;
|
||||||
|
totalLineHeight = lineHeight * lineInterval;
|
||||||
|
|
||||||
|
if (multiline) {
|
||||||
|
size_t offset = 0;
|
||||||
|
for (uint i = 0; i < lines; i++) {
|
||||||
|
std::wstring_view view(text.c_str()+offset, text.length()-offset);
|
||||||
|
size_t end = view.find(L'\n');
|
||||||
|
if (end != std::wstring::npos) {
|
||||||
|
view = std::wstring_view(text.c_str()+offset, end);
|
||||||
|
offset += end + 1;
|
||||||
|
}
|
||||||
|
font->draw(batch, view, coord.x, coord.y + i * totalLineHeight, FontStyle::none);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
font->draw(batch, text, coord.x, coord.y, FontStyle::none);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Label::textSupplier(wstringsupplier supplier) {
|
void Label::textSupplier(wstringsupplier supplier) {
|
||||||
this->supplier = supplier;
|
this->supplier = supplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Label::setMultiline(bool multiline) {
|
||||||
|
this->multiline = multiline;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Label::isMultiline() const {
|
||||||
|
return multiline;
|
||||||
|
}
|
||||||
|
|
||||||
// ================================= Image ====================================
|
// ================================= Image ====================================
|
||||||
Image::Image(std::string texture, glm::vec2 size) : UINode(glm::vec2(), size), texture(texture) {
|
Image::Image(std::string texture, glm::vec2 size) : UINode(glm::vec2(), size), texture(texture) {
|
||||||
setInteractive(false);
|
setInteractive(false);
|
||||||
@@ -264,7 +334,7 @@ void TextBox::draw(const GfxContext* pctx, Assets* assets) {
|
|||||||
if (!isFocused())
|
if (!isFocused())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const int yoffset = 2;
|
const int yoffset = 0;
|
||||||
const int lineHeight = font->getLineHeight();
|
const int lineHeight = font->getLineHeight();
|
||||||
glm::vec2 lcoord = label->calcCoord();
|
glm::vec2 lcoord = label->calcCoord();
|
||||||
auto batch = pctx->getBatch2D();
|
auto batch = pctx->getBatch2D();
|
||||||
@@ -390,6 +460,16 @@ bool TextBox::isValid() const {
|
|||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextBox::setMultiline(bool multiline) {
|
||||||
|
this->multiline = multiline;
|
||||||
|
label->setMultiline(multiline);
|
||||||
|
label->setVerticalAlign(multiline ? Align::top : Align::center);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TextBox::isMultiline() const {
|
||||||
|
return multiline;
|
||||||
|
}
|
||||||
|
|
||||||
void TextBox::setOnEditStart(runnable oneditstart) {
|
void TextBox::setOnEditStart(runnable oneditstart) {
|
||||||
onEditStart = oneditstart;
|
onEditStart = oneditstart;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,19 +24,40 @@ namespace gui {
|
|||||||
std::wstring text;
|
std::wstring text;
|
||||||
std::string fontName;
|
std::string fontName;
|
||||||
wstringsupplier supplier = nullptr;
|
wstringsupplier supplier = nullptr;
|
||||||
|
uint lines = 1;
|
||||||
|
float lineInterval = 1.5f;
|
||||||
|
Align valign = Align::center;
|
||||||
|
|
||||||
|
bool multiline = false;
|
||||||
|
|
||||||
|
// runtime values
|
||||||
|
int textYOffset = 0;
|
||||||
|
int totalLineHeight = 1;
|
||||||
public:
|
public:
|
||||||
Label(std::string text, std::string fontName="normal");
|
Label(std::string text, std::string fontName="normal");
|
||||||
Label(std::wstring text, std::string fontName="normal");
|
Label(std::wstring text, std::string fontName="normal");
|
||||||
|
|
||||||
virtual void setText(std::wstring text);
|
virtual void setText(std::wstring text);
|
||||||
std::wstring getText() const;
|
const std::wstring& getText() const;
|
||||||
|
|
||||||
virtual void setFontName(std::string name);
|
virtual void setFontName(std::string name);
|
||||||
const std::string& getFontName() const;
|
virtual const std::string& getFontName() const;
|
||||||
|
|
||||||
|
virtual void setVerticalAlign(Align align);
|
||||||
|
virtual Align getVerticalAlign() const;
|
||||||
|
|
||||||
|
virtual float getLineInterval() const;
|
||||||
|
virtual void setLineInterval(float interval);
|
||||||
|
|
||||||
|
virtual int getTextYOffset() const;
|
||||||
|
virtual int getLineYOffset(uint line) const;
|
||||||
|
|
||||||
virtual void draw(const GfxContext* pctx, Assets* assets) override;
|
virtual void draw(const GfxContext* pctx, Assets* assets) override;
|
||||||
|
|
||||||
virtual void textSupplier(wstringsupplier supplier);
|
virtual void textSupplier(wstringsupplier supplier);
|
||||||
|
|
||||||
|
virtual void setMultiline(bool multiline);
|
||||||
|
virtual bool isMultiline() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Image : public UINode {
|
class Image : public UINode {
|
||||||
@@ -121,6 +142,8 @@ namespace gui {
|
|||||||
size_t selectionEnd = 0;
|
size_t selectionEnd = 0;
|
||||||
size_t selectionOrigin = 0;
|
size_t selectionOrigin = 0;
|
||||||
|
|
||||||
|
bool multiline = false;
|
||||||
|
|
||||||
size_t normalizeIndex(int index);
|
size_t normalizeIndex(int index);
|
||||||
|
|
||||||
int calcIndexAt(int x) const;
|
int calcIndexAt(int x) const;
|
||||||
@@ -134,16 +157,9 @@ namespace gui {
|
|||||||
TextBox(std::wstring placeholder,
|
TextBox(std::wstring placeholder,
|
||||||
glm::vec4 padding=glm::vec4(4.0f));
|
glm::vec4 padding=glm::vec4(4.0f));
|
||||||
|
|
||||||
virtual std::shared_ptr<UINode> getAt(glm::vec2 pos, std::shared_ptr<UINode> self) override;
|
|
||||||
|
|
||||||
virtual void draw(const GfxContext* pctx, Assets* assets) override;
|
|
||||||
virtual void drawBackground(const GfxContext* pctx, Assets* assets) override;
|
|
||||||
virtual void typed(unsigned int codepoint) override;
|
|
||||||
virtual void keyPressed(keycode key) override;
|
|
||||||
virtual void setTextSupplier(wstringsupplier supplier);
|
virtual void setTextSupplier(wstringsupplier supplier);
|
||||||
virtual void setTextConsumer(wstringconsumer consumer);
|
virtual void setTextConsumer(wstringconsumer consumer);
|
||||||
virtual void setTextValidator(wstringchecker validator);
|
virtual void setTextValidator(wstringchecker validator);
|
||||||
virtual bool isFocuskeeper() const override {return true;}
|
|
||||||
virtual void setFocusedColor(glm::vec4 color);
|
virtual void setFocusedColor(glm::vec4 color);
|
||||||
virtual glm::vec4 getFocusedColor() const;
|
virtual glm::vec4 getFocusedColor() const;
|
||||||
virtual void setErrorColor(glm::vec4 color);
|
virtual void setErrorColor(glm::vec4 color);
|
||||||
@@ -161,11 +177,22 @@ namespace gui {
|
|||||||
virtual bool validate();
|
virtual bool validate();
|
||||||
virtual void setValid(bool valid);
|
virtual void setValid(bool valid);
|
||||||
virtual bool isValid() const;
|
virtual bool isValid() const;
|
||||||
|
|
||||||
|
// multiline mode is in development
|
||||||
|
virtual void setMultiline(bool multiline);
|
||||||
|
virtual bool isMultiline() const;
|
||||||
virtual void setOnEditStart(runnable oneditstart);
|
virtual void setOnEditStart(runnable oneditstart);
|
||||||
|
|
||||||
virtual void focus(GUI*) override;
|
virtual void focus(GUI*) override;
|
||||||
virtual void refresh() override;
|
virtual void refresh() override;
|
||||||
virtual void click(GUI*, int, int) override;
|
virtual void click(GUI*, int, int) override;
|
||||||
virtual void mouseMove(GUI*, int x, int y) override;
|
virtual void mouseMove(GUI*, int x, int y) override;
|
||||||
|
virtual bool isFocuskeeper() const override {return true;}
|
||||||
|
virtual void draw(const GfxContext* pctx, Assets* assets) override;
|
||||||
|
virtual void drawBackground(const GfxContext* pctx, Assets* assets) override;
|
||||||
|
virtual void typed(unsigned int codepoint) override;
|
||||||
|
virtual void keyPressed(keycode key) override;
|
||||||
|
virtual std::shared_ptr<UINode> getAt(glm::vec2 pos, std::shared_ptr<UINode> self) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class InputBindBox : public Panel {
|
class InputBindBox : public Panel {
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ static Align align_from_string(const std::string& str, Align def) {
|
|||||||
if (str == "left") return Align::left;
|
if (str == "left") return Align::left;
|
||||||
if (str == "center") return Align::center;
|
if (str == "center") return Align::center;
|
||||||
if (str == "right") return Align::right;
|
if (str == "right") return Align::right;
|
||||||
|
if (str == "top") return Align::top;
|
||||||
|
if (str == "bottom") return Align::bottom;
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,6 +140,11 @@ static std::shared_ptr<UINode> readLabel(UiXmlReader& reader, xml::xmlelement el
|
|||||||
std::wstring text = readAndProcessInnerText(element);
|
std::wstring text = readAndProcessInnerText(element);
|
||||||
auto label = std::make_shared<Label>(text);
|
auto label = std::make_shared<Label>(text);
|
||||||
_readUINode(reader, element, *label);
|
_readUINode(reader, element, *label);
|
||||||
|
if (element->has("valign")) {
|
||||||
|
label->setVerticalAlign(
|
||||||
|
align_from_string(element->attr("valign").getText(), label->getVerticalAlign())
|
||||||
|
);
|
||||||
|
}
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,7 +170,7 @@ static std::shared_ptr<UINode> readButton(UiXmlReader& reader, xml::xmlelement e
|
|||||||
auto callback = scripting::create_runnable(
|
auto callback = scripting::create_runnable(
|
||||||
reader.getEnvironment().getId(),
|
reader.getEnvironment().getId(),
|
||||||
element->attr("onclick").getText(),
|
element->attr("onclick").getText(),
|
||||||
reader.getFilename()+".lua"
|
reader.getFilename()
|
||||||
);
|
);
|
||||||
button->listenAction([callback](GUI*) {
|
button->listenAction([callback](GUI*) {
|
||||||
callback();
|
callback();
|
||||||
@@ -188,7 +195,7 @@ static std::shared_ptr<UINode> readCheckBox(UiXmlReader& reader, xml::xmlelement
|
|||||||
auto consumer = scripting::create_bool_consumer(
|
auto consumer = scripting::create_bool_consumer(
|
||||||
reader.getEnvironment().getId(),
|
reader.getEnvironment().getId(),
|
||||||
element->attr("consumer").getText(),
|
element->attr("consumer").getText(),
|
||||||
reader.getFilename()+".lua"
|
reader.getFilename()
|
||||||
);
|
);
|
||||||
checkbox->setConsumer(consumer);
|
checkbox->setConsumer(consumer);
|
||||||
}
|
}
|
||||||
@@ -197,7 +204,7 @@ static std::shared_ptr<UINode> readCheckBox(UiXmlReader& reader, xml::xmlelement
|
|||||||
auto supplier = scripting::create_bool_supplier(
|
auto supplier = scripting::create_bool_supplier(
|
||||||
reader.getEnvironment().getId(),
|
reader.getEnvironment().getId(),
|
||||||
element->attr("supplier").getText(),
|
element->attr("supplier").getText(),
|
||||||
reader.getFilename()+".lua"
|
reader.getFilename()
|
||||||
);
|
);
|
||||||
checkbox->setSupplier(supplier);
|
checkbox->setSupplier(supplier);
|
||||||
}
|
}
|
||||||
@@ -210,12 +217,16 @@ static std::shared_ptr<UINode> readTextBox(UiXmlReader& reader, xml::xmlelement
|
|||||||
auto textbox = std::make_shared<TextBox>(placeholder, glm::vec4(0.0f));
|
auto textbox = std::make_shared<TextBox>(placeholder, glm::vec4(0.0f));
|
||||||
_readPanel(reader, element, *textbox);
|
_readPanel(reader, element, *textbox);
|
||||||
textbox->setText(text);
|
textbox->setText(text);
|
||||||
|
|
||||||
|
if (element->has("multiline")) {
|
||||||
|
textbox->setMultiline(element->attr("multiline").asBool());
|
||||||
|
}
|
||||||
|
|
||||||
if (element->has("consumer")) {
|
if (element->has("consumer")) {
|
||||||
auto consumer = scripting::create_wstring_consumer(
|
auto consumer = scripting::create_wstring_consumer(
|
||||||
reader.getEnvironment().getId(),
|
reader.getEnvironment().getId(),
|
||||||
element->attr("consumer").getText(),
|
element->attr("consumer").getText(),
|
||||||
reader.getFilename()+".lua"
|
reader.getFilename()
|
||||||
);
|
);
|
||||||
textbox->setTextConsumer(consumer);
|
textbox->setTextConsumer(consumer);
|
||||||
}
|
}
|
||||||
@@ -224,7 +235,7 @@ static std::shared_ptr<UINode> readTextBox(UiXmlReader& reader, xml::xmlelement
|
|||||||
auto supplier = scripting::create_wstring_supplier(
|
auto supplier = scripting::create_wstring_supplier(
|
||||||
reader.getEnvironment().getId(),
|
reader.getEnvironment().getId(),
|
||||||
element->attr("consumer").getText(),
|
element->attr("consumer").getText(),
|
||||||
reader.getFilename()+".lua"
|
reader.getFilename()
|
||||||
);
|
);
|
||||||
textbox->setTextSupplier(supplier);
|
textbox->setTextSupplier(supplier);
|
||||||
}
|
}
|
||||||
@@ -238,7 +249,7 @@ static std::shared_ptr<UINode> readTextBox(UiXmlReader& reader, xml::xmlelement
|
|||||||
auto validator = scripting::create_wstring_validator(
|
auto validator = scripting::create_wstring_validator(
|
||||||
reader.getEnvironment().getId(),
|
reader.getEnvironment().getId(),
|
||||||
element->attr("validator").getText(),
|
element->attr("validator").getText(),
|
||||||
reader.getFilename()+".lua"
|
reader.getFilename()
|
||||||
);
|
);
|
||||||
textbox->setTextValidator(validator);
|
textbox->setTextValidator(validator);
|
||||||
}
|
}
|
||||||
@@ -265,7 +276,7 @@ static std::shared_ptr<UINode> readTrackBar(UiXmlReader& reader, xml::xmlelement
|
|||||||
auto consumer = scripting::create_number_consumer(
|
auto consumer = scripting::create_number_consumer(
|
||||||
reader.getEnvironment().getId(),
|
reader.getEnvironment().getId(),
|
||||||
element->attr("consumer").getText(),
|
element->attr("consumer").getText(),
|
||||||
reader.getFilename()+".lua"
|
reader.getFilename()
|
||||||
);
|
);
|
||||||
bar->setConsumer(consumer);
|
bar->setConsumer(consumer);
|
||||||
}
|
}
|
||||||
@@ -273,7 +284,7 @@ static std::shared_ptr<UINode> readTrackBar(UiXmlReader& reader, xml::xmlelement
|
|||||||
auto supplier = scripting::create_number_supplier(
|
auto supplier = scripting::create_number_supplier(
|
||||||
reader.getEnvironment().getId(),
|
reader.getEnvironment().getId(),
|
||||||
element->attr("supplier").getText(),
|
element->attr("supplier").getText(),
|
||||||
reader.getFilename()+".lua"
|
reader.getFilename()
|
||||||
);
|
);
|
||||||
bar->setSupplier(supplier);
|
bar->setSupplier(supplier);
|
||||||
}
|
}
|
||||||
|
|||||||
+65
-56
@@ -2,7 +2,9 @@
|
|||||||
#include "Texture.h"
|
#include "Texture.h"
|
||||||
#include "Batch2D.h"
|
#include "Batch2D.h"
|
||||||
|
|
||||||
using glm::vec4;
|
inline constexpr uint GLYPH_SIZE = 16;
|
||||||
|
inline constexpr uint MAX_CODEPAGES = 10000; // idk ho many codepages unicode has
|
||||||
|
inline constexpr glm::vec4 SHADOW_TINT(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
Font::Font(std::vector<std::unique_ptr<Texture>> pages, int lineHeight, int yoffset)
|
Font::Font(std::vector<std::unique_ptr<Texture>> pages, int lineHeight, int yoffset)
|
||||||
: lineHeight(lineHeight), yoffset(yoffset), pages(std::move(pages)) {
|
: lineHeight(lineHeight), yoffset(yoffset), pages(std::move(pages)) {
|
||||||
@@ -16,71 +18,78 @@ int Font::getYOffset() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Font::getLineHeight() const {
|
int Font::getLineHeight() const {
|
||||||
return lineHeight;
|
return lineHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Font::isPrintableChar(int c) {
|
bool Font::isPrintableChar(uint codepoint) const {
|
||||||
switch (c){
|
switch (codepoint){
|
||||||
case ' ':
|
case ' ':
|
||||||
case '\t':
|
case '\t':
|
||||||
case '\n':
|
case '\n':
|
||||||
case '\f':
|
case '\f':
|
||||||
case '\r':
|
case '\r':
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const int RES = 16;
|
|
||||||
|
|
||||||
int Font::calcWidth(std::wstring text, size_t length) {
|
int Font::calcWidth(std::wstring text, size_t length) {
|
||||||
return std::min(text.length(), length) * 8;
|
return std::min(text.length(), length) * 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::draw(Batch2D* batch, std::wstring text, int x, int y) {
|
void Font::draw(Batch2D* batch, std::wstring text, int x, int y) {
|
||||||
draw(batch, text, x, y, STYLE_NONE);
|
draw(batch, text, x, y, FontStyle::none);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::draw(Batch2D* batch, std::wstring text, int x, int y, int style) {
|
static inline void drawGlyph(Batch2D* batch, int x, int y, uint c, FontStyle style) {
|
||||||
int page = 0;
|
switch (style){
|
||||||
int next = 10000;
|
case FontStyle::shadow:
|
||||||
int init_x = x;
|
batch->sprite(x+1, y+1, GLYPH_SIZE, GLYPH_SIZE, 16, c, SHADOW_TINT);
|
||||||
do {
|
break;
|
||||||
for (unsigned c : text){
|
case FontStyle::outline:
|
||||||
if (isPrintableChar(c)){
|
for (int oy = -1; oy <= 1; oy++){
|
||||||
int charpage = c >> 8;
|
for (int ox = -1; ox <= 1; ox++){
|
||||||
if (charpage == page){
|
if (ox || oy) {
|
||||||
Texture* texture = pages[charpage].get();
|
batch->sprite(x+ox, y+oy, GLYPH_SIZE, GLYPH_SIZE, 16, c, SHADOW_TINT);
|
||||||
if (texture == nullptr){
|
}
|
||||||
texture = pages[0].get();
|
}
|
||||||
}
|
}
|
||||||
batch->texture(texture);
|
break;
|
||||||
|
}
|
||||||
|
batch->sprite(x, y, GLYPH_SIZE, GLYPH_SIZE, 16, c, batch->color);
|
||||||
|
}
|
||||||
|
|
||||||
switch (style){
|
void Font::draw(Batch2D* batch, std::wstring text, int x, int y, FontStyle style) {
|
||||||
case STYLE_SHADOW:
|
draw(batch, std::wstring_view(text.c_str(), text.length()), x, y, style);
|
||||||
batch->sprite(x+1, y+1, RES, RES, 16, c, vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
}
|
||||||
break;
|
|
||||||
case STYLE_OUTLINE:
|
|
||||||
for (int oy = -1; oy <= 1; oy++){
|
|
||||||
for (int ox = -1; ox <= 1; ox++){
|
|
||||||
if (ox || oy)
|
|
||||||
batch->sprite(x+ox, y+oy, RES, RES, 16, c, vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
batch->sprite(x, y, RES, RES, 16, c, batch->color);
|
void Font::draw(Batch2D* batch, std::wstring_view text, int x, int y, FontStyle style) {
|
||||||
}
|
uint page = 0;
|
||||||
else if (charpage > page && charpage < next){
|
uint next = MAX_CODEPAGES;
|
||||||
next = charpage;
|
int init_x = x;
|
||||||
}
|
do {
|
||||||
}
|
for (uint c : text){
|
||||||
x += 8;//getGlyphWidth(c);
|
if (!isPrintableChar(c)) {
|
||||||
}
|
x += 8;
|
||||||
page = next;
|
continue;
|
||||||
next = 10000;
|
}
|
||||||
x = init_x;
|
int charpage = c >> 8;
|
||||||
} while (page < 10000);
|
if (charpage == page){
|
||||||
|
Texture* texture = pages[charpage].get();
|
||||||
|
if (texture == nullptr){
|
||||||
|
texture = pages[0].get();
|
||||||
|
}
|
||||||
|
batch->texture(texture);
|
||||||
|
drawGlyph(batch, x, y, c, style);
|
||||||
|
}
|
||||||
|
else if (charpage > page && charpage < next){
|
||||||
|
next = charpage;
|
||||||
|
}
|
||||||
|
x += 8;//getGlyphWidth(c);
|
||||||
|
}
|
||||||
|
page = next;
|
||||||
|
next = MAX_CODEPAGES;
|
||||||
|
x = init_x;
|
||||||
|
} while (page < MAX_CODEPAGES);
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-13
@@ -9,25 +9,27 @@
|
|||||||
class Texture;
|
class Texture;
|
||||||
class Batch2D;
|
class Batch2D;
|
||||||
|
|
||||||
const uint STYLE_NONE = 0;
|
enum class FontStyle {
|
||||||
const uint STYLE_SHADOW = 1;
|
none,
|
||||||
const uint STYLE_OUTLINE = 2;
|
shadow,
|
||||||
|
outline
|
||||||
|
};
|
||||||
|
|
||||||
class Font {
|
class Font {
|
||||||
int lineHeight;
|
int lineHeight;
|
||||||
int yoffset;
|
int yoffset;
|
||||||
public:
|
public:
|
||||||
std::vector<std::unique_ptr<Texture>> pages;
|
std::vector<std::unique_ptr<Texture>> pages;
|
||||||
Font(std::vector<std::unique_ptr<Texture>> pages, int lineHeight, int yoffset);
|
Font(std::vector<std::unique_ptr<Texture>> pages, int lineHeight, int yoffset);
|
||||||
~Font();
|
~Font();
|
||||||
|
|
||||||
int getLineHeight() const;
|
int getLineHeight() const;
|
||||||
int getYOffset() const;
|
int getYOffset() const;
|
||||||
int calcWidth(std::wstring text, size_t length=-1);
|
int calcWidth(std::wstring text, size_t length=-1);
|
||||||
// int getGlyphWidth(char c);
|
bool isPrintableChar(uint codepoint) const;
|
||||||
bool isPrintableChar(int c);
|
void draw(Batch2D* batch, std::wstring text, int x, int y);
|
||||||
void draw(Batch2D* batch, std::wstring text, int x, int y);
|
void draw(Batch2D* batch, std::wstring text, int x, int y, FontStyle style);
|
||||||
void draw(Batch2D* batch, std::wstring text, int x, int y, int style);
|
void draw(Batch2D* batch, std::wstring_view text, int x, int y, FontStyle style);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* GRAPHICS_FONT_H_ */
|
#endif /* GRAPHICS_FONT_H_ */
|
||||||
|
|||||||
@@ -292,6 +292,10 @@ double util::parse_double(const std::string& str, size_t offset, size_t len) {
|
|||||||
return parse_double(str.substr(offset, len));
|
return parse_double(str.substr(offset, len));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Split string by delimiter
|
||||||
|
/// @param str source string
|
||||||
|
/// @param delimiter split delimiter size
|
||||||
|
/// @return vector of string parts, containing at least one string
|
||||||
std::vector<std::string> util::split(const std::string& str, char delimiter) {
|
std::vector<std::string> util::split(const std::string& str, char delimiter) {
|
||||||
std::vector<std::string> result;
|
std::vector<std::string> result;
|
||||||
std::stringstream ss(str);
|
std::stringstream ss(str);
|
||||||
@@ -299,9 +303,16 @@ std::vector<std::string> util::split(const std::string& str, char delimiter) {
|
|||||||
while (std::getline(ss, tmp, delimiter)) {
|
while (std::getline(ss, tmp, delimiter)) {
|
||||||
result.push_back(tmp);
|
result.push_back(tmp);
|
||||||
}
|
}
|
||||||
|
if (result.empty()) {
|
||||||
|
result.push_back("");
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Split wstring by delimiter
|
||||||
|
/// @param str source string
|
||||||
|
/// @param delimiter split delimiter size
|
||||||
|
/// @return vector of string parts, containing at least one string
|
||||||
std::vector<std::wstring> util::split(const std::wstring& str, char delimiter) {
|
std::vector<std::wstring> util::split(const std::wstring& str, char delimiter) {
|
||||||
std::vector<std::wstring> result;
|
std::vector<std::wstring> result;
|
||||||
std::wstringstream ss(str);
|
std::wstringstream ss(str);
|
||||||
@@ -309,5 +320,8 @@ std::vector<std::wstring> util::split(const std::wstring& str, char delimiter) {
|
|||||||
while (std::getline(ss, tmp, static_cast<wchar_t>(delimiter))) {
|
while (std::getline(ss, tmp, static_cast<wchar_t>(delimiter))) {
|
||||||
result.push_back(tmp);
|
result.push_back(tmp);
|
||||||
}
|
}
|
||||||
|
if (result.empty()) {
|
||||||
|
result.push_back(L"");
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user