Print messages using SkParagraph and new TextParagraph element
This commit is contained in:
parent
9ceb4e1b8a
commit
921e111255
9 changed files with 147 additions and 16 deletions
|
|
@ -94,6 +94,7 @@ set(sources "src/main.cpp"
|
|||
"src/GUIStuff/Elements/MovableTabList.cpp"
|
||||
"src/GUIStuff/Elements/PaintCircleMenu.cpp"
|
||||
"src/GUIStuff/Elements/RotateWheel.cpp"
|
||||
"src/GUIStuff/Elements/TextParagraph.cpp"
|
||||
"include/sago/platform_folders.cpp"
|
||||
"include/Helpers/Networking/NetLibrary.cpp"
|
||||
"include/Helpers/Networking/NetServer.cpp"
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ FontData::FontData()
|
|||
mgr = SkFontMgr_New_Custom_Empty();
|
||||
#endif
|
||||
map["Roboto"] = mgr->makeFromFile("data/fonts/Roboto-variable.ttf");
|
||||
collection = sk_make_sp<skia::textlayout::FontCollection>();
|
||||
collection->setDefaultFontManager(mgr);
|
||||
}
|
||||
|
||||
FontData::~FontData() {
|
||||
|
|
|
|||
|
|
@ -4,12 +4,14 @@
|
|||
#include <include/core/SkFont.h>
|
||||
#include <unordered_map>
|
||||
#include <Eigen/Dense>
|
||||
#include <modules/skparagraph/include/FontCollection.h>
|
||||
|
||||
using namespace Eigen;
|
||||
|
||||
struct FontData {
|
||||
FontData();
|
||||
sk_sp<SkFontMgr> mgr;
|
||||
sk_sp<skia::textlayout::FontCollection> collection;
|
||||
std::unordered_map<std::string, sk_sp<SkTypeface>> map;
|
||||
~FontData();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include <Eigen/Dense>
|
||||
#include <include/core/SkFont.h>
|
||||
#include <include/core/SkFontMgr.h>
|
||||
#include <modules/skparagraph/include/FontCollection.h>
|
||||
#include <modules/svg/include/SkSVGDOM.h>
|
||||
#include <Helpers/SCollision.hpp>
|
||||
#include <Helpers/Serializers.hpp>
|
||||
|
|
@ -95,6 +96,7 @@ struct UpdateInputData {
|
|||
bool copy = false;
|
||||
bool paste = false;
|
||||
bool cut = false;
|
||||
bool escape = false;
|
||||
} key;
|
||||
|
||||
struct {
|
||||
|
|
@ -107,6 +109,8 @@ struct UpdateInputData {
|
|||
uint16_t fontSize = 20;
|
||||
sk_sp<SkTypeface> textTypeface;
|
||||
|
||||
sk_sp<skia::textlayout::FontCollection> fontCollection;
|
||||
|
||||
std::string textInput;
|
||||
bool hoverObstructed = false;
|
||||
bool acceptingTextInput = false;
|
||||
|
|
|
|||
28
src/GUIStuff/Elements/TextParagraph.cpp
Normal file
28
src/GUIStuff/Elements/TextParagraph.cpp
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#include "TextParagraph.hpp"
|
||||
#include <include/core/SkPath.h>
|
||||
#include <iostream>
|
||||
|
||||
namespace GUIStuff {
|
||||
|
||||
void TextParagraph::update(UpdateInputData& io, std::unique_ptr<skia::textlayout::Paragraph> paragraph, float width, const std::function<void()>& elemUpdate) {
|
||||
data = std::move(paragraph);
|
||||
data->layout(width);
|
||||
CLAY({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_FIXED(width), .height = CLAY_SIZING_FIXED(data->getHeight())}
|
||||
},
|
||||
.custom = { .customData = this }
|
||||
}) {
|
||||
if(elemUpdate)
|
||||
elemUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void TextParagraph::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) {
|
||||
bb = get_bb(command);
|
||||
|
||||
if(data)
|
||||
data->paint(canvas, bb.min.x(), bb.min.y());
|
||||
}
|
||||
|
||||
}
|
||||
16
src/GUIStuff/Elements/TextParagraph.hpp
Normal file
16
src/GUIStuff/Elements/TextParagraph.hpp
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
#include "Element.hpp"
|
||||
#include <modules/skparagraph/include/Paragraph.h>
|
||||
|
||||
namespace GUIStuff {
|
||||
|
||||
class TextParagraph : public Element {
|
||||
public:
|
||||
void update(UpdateInputData& io, std::unique_ptr<skia::textlayout::Paragraph> paragraph, float width, const std::function<void()>& elemUpdate);
|
||||
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override;
|
||||
private:
|
||||
SCollision::AABB<float> bb = SCollision::AABB<float>({0.0f, 0.0f}, {0.0f, 0.0f});
|
||||
std::unique_ptr<skia::textlayout::Paragraph> data;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -7,13 +7,21 @@
|
|||
#include "Elements/SVGIcon.hpp"
|
||||
#include "Elements/SelectableButton.hpp"
|
||||
#include "Elements/RotateWheel.hpp"
|
||||
#include "Elements/TextParagraph.hpp"
|
||||
#include "Elements/MovableTabList.hpp"
|
||||
#include "Elements/Element.hpp"
|
||||
#include "Elements/TextParagraph.hpp"
|
||||
#include <Helpers/ConvertVec.hpp>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <modules/skparagraph/src/ParagraphBuilderImpl.h>
|
||||
#include <modules/skparagraph/include/ParagraphStyle.h>
|
||||
#include <modules/skparagraph/include/FontCollection.h>
|
||||
#include <modules/skparagraph/include/TextStyle.h>
|
||||
#include <modules/skunicode/include/SkUnicode_icu.h>
|
||||
|
||||
namespace GUIStuff {
|
||||
|
||||
|
|
@ -28,11 +36,20 @@ GUIManager::GUIManager()
|
|||
|
||||
Clay_Dimensions GUIManager::clay_skia_measure_text(Clay_StringSlice str, Clay_TextElementConfig* config, void* userData) {
|
||||
GUIManager* window = static_cast<GUIManager*>(userData);
|
||||
SkFont font = window->io->get_font(config->fontSize);
|
||||
SkFontMetrics metrics;
|
||||
font.getMetrics(&metrics);
|
||||
float nextText = font.measureText(str.chars, str.length, SkTextEncoding::kUTF8, nullptr);
|
||||
return Clay_Dimensions(nextText, - metrics.fAscent + metrics.fDescent);
|
||||
|
||||
skia::textlayout::ParagraphStyle pStyle;
|
||||
pStyle.setTextAlign(skia::textlayout::TextAlign::kLeft);
|
||||
skia::textlayout::TextStyle tStyle;
|
||||
tStyle.setFontSize(config->fontSize);
|
||||
tStyle.setFontFamilies({SkString{"Roboto"}});
|
||||
pStyle.setTextStyle(tStyle);
|
||||
|
||||
skia::textlayout::ParagraphBuilderImpl a(pStyle, window->io->fontCollection, SkUnicodes::ICU::Make());
|
||||
a.addText(str.chars, str.length);
|
||||
std::unique_ptr<skia::textlayout::Paragraph> p = a.Build();
|
||||
p->layout(std::numeric_limits<float>::max());
|
||||
|
||||
return Clay_Dimensions(p->getMaxIntrinsicWidth(), p->getHeight());
|
||||
}
|
||||
|
||||
void GUIManager::begin() {
|
||||
|
|
@ -92,12 +109,20 @@ void GUIManager::draw(SkCanvas* canvas) {
|
|||
}
|
||||
case CLAY_RENDER_COMMAND_TYPE_TEXT: {
|
||||
Clay_TextRenderData* config = &command->renderData.text;
|
||||
SkPaint paint;
|
||||
paint.setColor4f(convert_vec4<SkColor4f>(config->textColor));
|
||||
SkFont f = io->get_font(config->fontSize);
|
||||
SkFontMetrics metrics;
|
||||
f.getMetrics(&metrics);
|
||||
canvas->drawSimpleText(config->stringContents.chars, config->stringContents.length, SkTextEncoding::kUTF8, bb.x, (bb.y + bb.height - metrics.fDescent), io->get_font(config->fontSize), paint);
|
||||
|
||||
skia::textlayout::ParagraphStyle pStyle;
|
||||
pStyle.setTextAlign(skia::textlayout::TextAlign::kLeft);
|
||||
skia::textlayout::TextStyle tStyle;
|
||||
tStyle.setFontSize(config->fontSize);
|
||||
tStyle.setFontFamilies({SkString{"Roboto"}});
|
||||
pStyle.setTextStyle(tStyle);
|
||||
|
||||
skia::textlayout::ParagraphBuilderImpl a(pStyle, io->fontCollection, SkUnicodes::ICU::Make());
|
||||
a.addText(config->stringContents.chars, config->stringContents.length);
|
||||
std::unique_ptr<skia::textlayout::Paragraph> p = a.Build();
|
||||
p->layout(std::numeric_limits<float>::max());
|
||||
p->paint(canvas, bb.x, bb.y);
|
||||
|
||||
break;
|
||||
}
|
||||
case CLAY_RENDER_COMMAND_TYPE_BORDER: {
|
||||
|
|
@ -679,6 +704,13 @@ bool GUIManager::rotate_wheel(const std::string& id, double* angle, float size,
|
|||
return toRet;
|
||||
}
|
||||
|
||||
void GUIManager::text_paragraph(const std::string& id, std::unique_ptr<skia::textlayout::Paragraph> paragraph, float width, const std::function<void()>& elemUpdate) {
|
||||
push_id(id);
|
||||
TextParagraph* e = insert_element<TextParagraph>();
|
||||
e->update(*io, std::move(paragraph), width, elemUpdate);
|
||||
pop_id();
|
||||
}
|
||||
|
||||
void GUIManager::paint_circle_popup_menu(const std::string& id, const Vector2f& centerPos, const PaintCircleMenu::Data& val, const std::function<void()>& elemUpdate) {
|
||||
float size = 300.0f;
|
||||
push_id(id);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
#include <type_traits>
|
||||
#include <clay.h>
|
||||
|
||||
#include <modules/skparagraph/include/Paragraph.h>
|
||||
|
||||
using namespace Eigen;
|
||||
|
||||
namespace GUIStuff {
|
||||
|
|
@ -43,6 +45,7 @@ class GUIManager {
|
|||
|
||||
void input_text_field(const std::string& id, const std::string& name, std::string* val, const std::function<void(SelectionHelper&)>& elemUpdate = nullptr);
|
||||
|
||||
void text_paragraph(const std::string& id, std::unique_ptr<skia::textlayout::Paragraph> paragraph, float width, const std::function<void()>& elemUpdate = nullptr);
|
||||
void text_label_color(const std::string& val, const SkColor4f& color);
|
||||
void text_label_size(const std::string& val, float modifier);
|
||||
void text_label(const std::string& val);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,12 @@
|
|||
#include <Helpers/StringHelpers.hpp>
|
||||
#include <Helpers/VersionNumber.hpp>
|
||||
|
||||
#include <modules/skparagraph/src/ParagraphBuilderImpl.h>
|
||||
#include <modules/skparagraph/include/ParagraphStyle.h>
|
||||
#include <modules/skparagraph/include/FontCollection.h>
|
||||
#include <modules/skparagraph/include/TextStyle.h>
|
||||
#include <modules/skunicode/include/SkUnicode_icu.h>
|
||||
|
||||
#define UPDATE_DOWNLOAD_URL "https://infinipaint.com/download.html"
|
||||
#define UPDATE_NOTIFICATION_URL "https://infinipaint.com/updateNotificationVersion.txt"
|
||||
|
||||
|
|
@ -33,6 +39,7 @@ Toolbar::Toolbar(MainProgram& initMain):
|
|||
{
|
||||
io->textTypeface = main.fonts.map["Roboto"];
|
||||
io->textFontMgr = main.fonts.mgr;
|
||||
io->fontCollection = main.fonts.collection;
|
||||
io->fontSize = 20;
|
||||
|
||||
load_default_palette();
|
||||
|
|
@ -819,6 +826,7 @@ void Toolbar::bookmark_menu(bool justOpened) {
|
|||
}
|
||||
|
||||
void Toolbar::chat_box() {
|
||||
constexpr float CHATBOX_WIDTH = 700;
|
||||
if(main.world->network_being_used()) {
|
||||
CLAY({
|
||||
.layout = {
|
||||
|
|
@ -839,7 +847,7 @@ void Toolbar::chat_box() {
|
|||
}
|
||||
CLAY({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_FIXED(700), .height = CLAY_SIZING_FIT(0) },
|
||||
.sizing = {.width = CLAY_SIZING_FIXED(CHATBOX_WIDTH), .height = CLAY_SIZING_FIT(0) },
|
||||
.childGap = 0,
|
||||
.childAlignment = { .x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_BOTTOM},
|
||||
.layoutDirection = CLAY_TOP_TO_BOTTOM
|
||||
|
|
@ -849,6 +857,7 @@ void Toolbar::chat_box() {
|
|||
gui.obstructing_window();
|
||||
gui.push_id("chat box");
|
||||
if(chatBoxState == CHATBOXSTATE_JUSTOPEN || chatBoxState == CHATBOXSTATE_OPEN) {
|
||||
gui.push_id("messages");
|
||||
CLAY({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0) },
|
||||
|
|
@ -859,7 +868,9 @@ void Toolbar::chat_box() {
|
|||
},
|
||||
.backgroundColor = convert_vec4<Clay_Color>(io->theme->backColor1)
|
||||
}) {
|
||||
int id = 0;
|
||||
for(auto& chatMessage : main.world->chatMessages | std::views::reverse) {
|
||||
id++;
|
||||
SkColor4f c;
|
||||
switch(chatMessage.color) {
|
||||
case ChatMessage::COLOR_NORMAL:
|
||||
|
|
@ -869,9 +880,23 @@ void Toolbar::chat_box() {
|
|||
c = io->theme->fillColor4;
|
||||
break;
|
||||
}
|
||||
gui.text_label_color(chatMessage.text, c);
|
||||
gui.push_id(id);
|
||||
skia::textlayout::ParagraphStyle pStyle;
|
||||
pStyle.setTextAlign(skia::textlayout::TextAlign::kLeft);
|
||||
skia::textlayout::TextStyle tStyle;
|
||||
tStyle.setFontSize(io->fontSize);
|
||||
tStyle.setFontFamilies({SkString{"Roboto"}});
|
||||
tStyle.setForegroundColor(SkPaint{c});
|
||||
pStyle.setTextStyle(tStyle);
|
||||
|
||||
skia::textlayout::ParagraphBuilderImpl a(pStyle, io->fontCollection, SkUnicodes::ICU::Make());
|
||||
a.addText(chatMessage.text.c_str(), chatMessage.text.length());
|
||||
|
||||
gui.text_paragraph("text", a.Build(), CHATBOX_WIDTH);
|
||||
gui.pop_id();
|
||||
}
|
||||
}
|
||||
gui.pop_id();
|
||||
|
||||
gui.left_to_right_line_layout([&]() {
|
||||
gui.input_text("message input", &chatMessageInput);
|
||||
|
|
@ -888,9 +913,9 @@ void Toolbar::chat_box() {
|
|||
t.selection.selected = true;
|
||||
chatBoxState = CHATBOXSTATE_OPEN;
|
||||
}
|
||||
if(main.input.key(InputManager::KEY_GENERIC_ESCAPE).pressed)
|
||||
if(io->key.escape)
|
||||
t.selection.selected = false;
|
||||
if(main.input.key(InputManager::KEY_TEXT_ENTER).pressed) {
|
||||
if(io->key.enter) {
|
||||
main.world->send_chat_message(chatMessageInput);
|
||||
t.selection.selected = false;
|
||||
}
|
||||
|
|
@ -902,7 +927,10 @@ void Toolbar::chat_box() {
|
|||
else {
|
||||
constexpr float DISPLAY_TIME = 8.0f;
|
||||
constexpr float FADE_START_TIME = 7.0f;
|
||||
gui.push_id("messages popup");
|
||||
int id = 0;
|
||||
for(auto& chatMessage : main.world->chatMessages | std::views::reverse) {
|
||||
id++;
|
||||
chatMessage.time.update_time_since();
|
||||
if(chatMessage.time < DISPLAY_TIME) {
|
||||
float a = 1.0f - lerp_time<float>(chatMessage.time, DISPLAY_TIME, FADE_START_TIME);
|
||||
|
|
@ -925,11 +953,25 @@ void Toolbar::chat_box() {
|
|||
},
|
||||
.backgroundColor = convert_vec4<Clay_Color>(color_mul_alpha(io->theme->backColor1, a)),
|
||||
}) {
|
||||
gui.push_id(id);
|
||||
gui.obstructing_window();
|
||||
gui.text_label_color(chatMessage.text, color_mul_alpha(c, a));
|
||||
skia::textlayout::ParagraphStyle pStyle;
|
||||
pStyle.setTextAlign(skia::textlayout::TextAlign::kLeft);
|
||||
skia::textlayout::TextStyle tStyle;
|
||||
tStyle.setFontSize(io->fontSize);
|
||||
tStyle.setFontFamilies({SkString{"Roboto"}});
|
||||
tStyle.setForegroundColor(SkPaint{color_mul_alpha(c, a)});
|
||||
pStyle.setTextStyle(tStyle);
|
||||
|
||||
skia::textlayout::ParagraphBuilderImpl a(pStyle, io->fontCollection, SkUnicodes::ICU::Make());
|
||||
a.addText(chatMessage.text.c_str(), chatMessage.text.length());
|
||||
|
||||
gui.text_paragraph("text", a.Build(), CHATBOX_WIDTH);
|
||||
gui.pop_id();
|
||||
}
|
||||
}
|
||||
}
|
||||
gui.pop_id();
|
||||
}
|
||||
gui.pop_id();
|
||||
}
|
||||
|
|
@ -1910,6 +1952,7 @@ void Toolbar::initialize_io_before_update() {
|
|||
io->key.copy = main.input.key(InputManager::KEY_TEXT_COPY).repeat;
|
||||
io->key.paste = main.input.get_clipboard_paste_happened();
|
||||
io->key.cut = main.input.key(InputManager::KEY_TEXT_CUT).repeat;
|
||||
io->key.escape = main.input.key(InputManager::KEY_GENERIC_ESCAPE).repeat;
|
||||
|
||||
io->textInput = main.input.text.newInput;
|
||||
io->clipboard.textInFunc = [&]() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue