Files
panopainter/src/node_text.cpp

188 lines
5.4 KiB
C++

#include "pch.h"
#include "log.h"
#include "node_text.h"
#include "shader.h"
Node* NodeText::clone_instantiate() const
{
return new NodeText();
}
void NodeText::clone_copy(Node* dest) const
{
Node::clone_copy(dest);
NodeText* n = static_cast<NodeText*>(dest);
n->m_text_mesh.max_width = m_text_mesh.max_width;
n->m_text_mesh.create();
n->m_text_mesh.update(m_text, m_font_name, m_font_size, m_font_weight, m_font_italic);
n->m_text = m_text;
n->m_font_name = m_font_name;
n->m_font_size = m_font_size;
n->m_font_weight = m_font_weight;
n->m_font_italic = m_font_italic;
n->m_color = m_color;
n->m_multiline = m_multiline;
n->m_off = m_off;
n->m_text_align_v = m_text_align_v;
n->m_text_align_h = m_text_align_h;
}
void NodeText::create()
{
Node::create();
if (!m_font_name.empty())
{
m_text_mesh.create();
m_text_mesh.update(m_text, m_font_name, m_font_size, m_font_weight, m_font_italic);
update_layout();
}
}
void NodeText::set_font(const std::string& name, int size, const std::string& weight, bool italic)
{
m_font_name = name;
m_font_size = size;
m_font_weight = weight;
m_font_italic = italic;
m_text_mesh.create();
m_text_mesh.update(m_text, m_font_name, m_font_size, m_font_weight, m_font_italic);
update_layout();
}
void NodeText::set_font_size(int size)
{
m_font_size = size;
m_text_mesh.create();
m_text_mesh.update(m_text, m_font_name, m_font_size, m_font_weight, m_font_italic);
update_layout();
}
void NodeText::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
{
Node::parse_attributes(ka, attr);
std::string id = attr->Name();
switch (ka)
{
case kAttribute::Multiline:
m_multiline = attr->BoolValue();
break;
case kAttribute::TextAlign:
if (strcmp(attr->Value(), "left") == 0)
m_text_align_h = TextAlign::Begin;
else if (strcmp(attr->Value(), "center") == 0)
m_text_align_h = TextAlign::Center;
else if (strcmp(attr->Value(), "right") == 0)
m_text_align_h = TextAlign::End;
break;
case kAttribute::TextVerticalAlign:
if (strcmp(attr->Value(), "top") == 0)
m_text_align_v = TextAlign::Begin;
else if (strcmp(attr->Value(), "center") == 0)
m_text_align_v = TextAlign::Center;
else if (strcmp(attr->Value(), "bottom") == 0)
m_text_align_v = TextAlign::End;
break;
case kAttribute::TextWrapWidth:
m_text_mesh.max_width = attr->IntValue();
break;
case kAttribute::Text:
m_text = unescape(attr->Value());
break;
case kAttribute::FontFace:
m_font_name = attr->Value();
break;
case kAttribute::FontSize:
m_font_size = attr->IntValue();
break;
case kAttribute::Color:
{
glm::vec4 pad;
int n = sscanf(attr->Value(), "%f %f %f %f", &pad.x, &pad.y, &pad.z, &pad.w);
if (n == 1)
m_color = glm::vec4(pad.x);
else
m_color = pad;
break;
}
default:
break;
}
if (id == "size")
m_font_size = attr->IntValue();
else if (id == "weight")
m_font_weight = attr->Value();
else if (id == "italic")
m_font_italic = attr->BoolValue();
}
void NodeText::set_text(const std::string& s)
{
m_text = s;
m_text_mesh.update(m_text, m_font_name, m_font_size, m_font_weight, m_font_italic);
update_layout();
}
void NodeText::set_text_format(const char* fmt, ...)
{
static char buffer[4096];
va_list args;
va_start(args, fmt);
vsnprintf(buffer, sizeof(buffer), fmt, args);
va_end(args);
m_text = buffer;
m_text_mesh.update(m_text, m_font_name, m_font_size, m_font_weight, m_font_italic);
update_layout();
}
void NodeText::update_layout()
{
auto pad = GetPadding();
if (auto_width)
{
YGNodeStyleSetWidth(y_node, m_text_mesh.bb.x + (pad[1] + pad[3]));
m_size.x = m_text_mesh.bb.x + (pad[1] + pad[3]);
}
if (auto_height)
{
YGNodeStyleSetHeight(y_node, m_text_mesh.bb.y + (pad[0] + pad[2]));
m_size.y = m_text_mesh.bb.y + (pad[0] + pad[2]);
}
float w = m_size.x - (pad[1] + pad[3]);
float h = m_size.y - (pad[0] + pad[2]);
if (m_text_align_v == TextAlign::Begin)
m_off.y = pad[0];
else if (m_text_align_v == TextAlign::Center)
m_off.y = (h - m_text_mesh.bb.y) * 0.5f + pad[0];
else
m_off.y = (h - m_text_mesh.bb.y) + pad[0];
if (m_text_align_h == TextAlign::Begin)
m_off.x = pad[3];
else if (m_text_align_v == TextAlign::Center)
m_off.x = (w - m_text_mesh.bb.x) * 0.5f + pad[3];
else
m_off.x = (w - m_text_mesh.bb.x) + pad[3];
}
void NodeText::draw()
{
glm::mat4 pos = glm::translate(glm::vec3(glm::floor(m_pos + m_off), 0));
ShaderManager::use(kShader::Font);
ShaderManager::u_int(kShaderUniform::Tex, 0);
ShaderManager::u_mat4(kShaderUniform::MVP, m_proj * pos);
ShaderManager::u_vec4(kShaderUniform::Col, m_color);
glEnable(GL_BLEND);
m_text_mesh.draw();
glDisable(GL_BLEND);
}
void NodeText::handle_resize(glm::vec2 old_size, glm::vec2 new_size, float zoom)
{
auto pad = GetPadding();
m_text_mesh.max_width = m_multiline ? new_size.x - (pad[1] + pad[3]) : 0;
m_text_mesh.update(m_text, m_font_name, m_font_size, m_font_weight, m_font_italic);
update_layout();
}