#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(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(); }