254 lines
6.8 KiB
C++
254 lines
6.8 KiB
C++
#include "pch.h"
|
|
#include "app.h"
|
|
#include "log.h"
|
|
#include "node_text_input.h"
|
|
#include "node_border.h"
|
|
|
|
Node* NodeTextInput::clone_instantiate() const
|
|
{
|
|
return new NodeTextInput();
|
|
}
|
|
|
|
void NodeTextInput::on_tick(float dt)
|
|
{
|
|
timer += dt;
|
|
|
|
bool focus = root()->current_key_capture.get() == this;
|
|
if (!focus)
|
|
m_cursor_visible = false;
|
|
m_thinkness = focus;
|
|
|
|
if (timer > 1.0)
|
|
{
|
|
timer = 0;
|
|
if (focus)
|
|
{
|
|
m_cursor_visible = !m_cursor_visible;
|
|
app_redraw();
|
|
}
|
|
}
|
|
}
|
|
|
|
void NodeTextInput::clone_copy(Node* dest) const
|
|
{
|
|
NodeBorder::clone_copy(dest);
|
|
NodeTextInput* n = static_cast<NodeTextInput*>(dest);
|
|
n->m_text_mesh.max_width = m_text_mesh.max_width;
|
|
n->m_text_mesh.create();
|
|
n->m_text_mesh.update(font_id, m_text);
|
|
n->m_text = m_text;
|
|
n->m_font = m_font;
|
|
n->m_color = m_color;
|
|
n->m_font_size = m_font_size;
|
|
n->font_id = font_id;
|
|
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;
|
|
}
|
|
|
|
kEventResult NodeTextInput::handle_event(Event* e)
|
|
{
|
|
KeyEvent* ke = (KeyEvent*)e;
|
|
switch (e->m_type)
|
|
{
|
|
case kEventType::MouseDownL:
|
|
App::I->showKeyboard();
|
|
break;
|
|
case kEventType::MouseUpL:
|
|
key_capture();
|
|
timer = 0;
|
|
m_cursor_visible = true;
|
|
break;
|
|
case kEventType::KeyDown:
|
|
if (!has_focus())
|
|
return kEventResult::Available;
|
|
//switch (ke->m_key)
|
|
//{
|
|
//case VK_BACK:
|
|
// m_string.erase(m_string.end() - 1);
|
|
// m_text->set_text(m_string);
|
|
// break;
|
|
//default:
|
|
// break;
|
|
//}
|
|
break;
|
|
case kEventType::KeyUp:
|
|
if (!has_focus())
|
|
return kEventResult::Available;
|
|
if (ke->m_key == kKey::KeyEnter && on_return)
|
|
on_return(this);
|
|
if (ke->m_key == kKey::KeyBackspace)
|
|
{
|
|
if (!m_text.empty())
|
|
{
|
|
m_text.erase(m_text.end() - 1);
|
|
set_text(m_text);
|
|
}
|
|
}
|
|
break;
|
|
case kEventType::KeyChar:
|
|
if (!has_focus())
|
|
return kEventResult::Available;
|
|
timer = 0;
|
|
m_cursor_visible = true;
|
|
if (ke->m_char == '\b' // backspace
|
|
|| ke->m_char == 0x7f // DEL
|
|
)
|
|
{
|
|
if (!m_text.empty())
|
|
{
|
|
m_text.erase(m_text.end() - 1);
|
|
set_text(m_text);
|
|
}
|
|
}
|
|
else if (ke->m_char == '\n' || ke->m_char == '\r') // enter/return
|
|
{
|
|
if (m_multiline)
|
|
{
|
|
m_text += '\n';
|
|
set_text(m_text);
|
|
}
|
|
else if (on_return)
|
|
{
|
|
on_return(this);
|
|
}
|
|
}
|
|
else if ((uint8_t)ke->m_char >= 32 && (uint8_t)ke->m_char < 256) // visible ascii character
|
|
{
|
|
m_text += (char)ke->m_char;
|
|
set_text(m_text);
|
|
}
|
|
break;
|
|
default:
|
|
return kEventResult::Available;
|
|
break;
|
|
}
|
|
return kEventResult::Consumed;
|
|
}
|
|
|
|
void NodeTextInput::set_text(const std::string& s)
|
|
{
|
|
m_text = s;
|
|
m_text_mesh.update(font_id, s);
|
|
update_layout();
|
|
}
|
|
|
|
void NodeTextInput::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(font_id, buffer);
|
|
update_layout();
|
|
}
|
|
|
|
void NodeTextInput::update_layout()
|
|
{
|
|
auto pad = GetPadding();
|
|
float h = GetHeight() - (pad[1] + pad[3]);
|
|
float w = GetWidth() - (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];
|
|
}
|
|
|
|
bool NodeTextInput::has_focus() noexcept
|
|
{
|
|
return root()->current_key_capture.get() == this;
|
|
}
|
|
|
|
void NodeTextInput::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;
|
|
update_layout();
|
|
}
|
|
|
|
void NodeTextInput::create()
|
|
{
|
|
NodeBorder::create();
|
|
if (!m_font.empty())
|
|
{
|
|
font_id = fmt::format("{}-{}", m_font, m_font_size);
|
|
m_text_mesh.create();
|
|
m_text_mesh.update(font_id, m_text);
|
|
update_layout();
|
|
}
|
|
}
|
|
|
|
void NodeTextInput::draw()
|
|
{
|
|
NodeBorder::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);
|
|
|
|
if (m_cursor_visible)
|
|
{
|
|
glDisable(GL_BLEND);
|
|
glm::mat4 cur_pos = glm::translate(glm::vec3(m_pos + m_off + xy(m_text_mesh.cur_box), 0));
|
|
glm::mat4 cur_scale = glm::scale(glm::vec3(zw(m_text_mesh.cur_box), 1));
|
|
glm::mat4 cur_pivot = glm::translate(glm::vec3(0.5, 0.5, 0));
|
|
ShaderManager::use(kShader::Color);
|
|
ShaderManager::u_mat4(kShaderUniform::MVP, m_proj * cur_pos * cur_scale * cur_pivot);
|
|
ShaderManager::u_vec4(kShaderUniform::Col, { 0, 0, 0, 1 });
|
|
m_plane.draw_fill();
|
|
}
|
|
}
|
|
|
|
void NodeTextInput::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
|
|
{
|
|
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;
|
|
default:
|
|
NodeBorder::parse_attributes(ka, attr);
|
|
}
|
|
}
|
|
|
|
void NodeTextInput::destroy()
|
|
{
|
|
if (root()->current_key_capture.get() == this)
|
|
App::I->hideKeyboard();
|
|
NodeBorder::destroy();
|
|
}
|