146 lines
4.1 KiB
C++
146 lines
4.1 KiB
C++
#include "pch.h"
|
|
#include "log.h"
|
|
#include "node_scroll.h"
|
|
#include "event.h"
|
|
#include "shader.h"
|
|
|
|
NodeScroll::NodeScroll()
|
|
{
|
|
m_drag_start = glm::vec2(0);
|
|
m_offset_start = glm::vec2(0);
|
|
m_offset = glm::vec2(0);
|
|
m_mask = glm::vec2(0, 1);
|
|
}
|
|
|
|
Node* NodeScroll::clone_instantiate() const
|
|
{
|
|
return new NodeScroll;
|
|
}
|
|
|
|
void NodeScroll::fix_scroll()
|
|
{
|
|
auto pad = GetPadding();
|
|
glm::vec2 padoff = { pad.y + pad.w, pad.x + pad.z };
|
|
auto rect = get_children_rect();
|
|
m_offset = glm::clamp(m_offset, - zw(rect) + zw(m_clip_uncut) - padoff, { 0, 0 });
|
|
m_pos_offset_childred = m_offset;
|
|
}
|
|
|
|
void NodeScroll::clone_copy(Node* dest) const
|
|
{
|
|
NodeBorder::clone_copy(dest);
|
|
auto n = static_cast<NodeScroll*>(dest);
|
|
n->m_scrollbar_color = m_scrollbar_color;
|
|
}
|
|
|
|
void NodeScroll::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
|
|
{
|
|
NodeBorder::parse_attributes(ka, attr);
|
|
switch (ka)
|
|
{
|
|
case kAttribute::ScrollColor:
|
|
{
|
|
glm::vec4 col;
|
|
int n = sscanf(attr->Value(), "%f %f %f %f", &col.x, &col.y, &col.z, &col.w);
|
|
if (n == 1)
|
|
m_scrollbar_color = glm::vec4(col.x, col.x, col.x, 1);
|
|
else
|
|
m_scrollbar_color = col;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void NodeScroll::on_tick(float dt)
|
|
{
|
|
auto pad = GetPadding();
|
|
auto rect = get_children_rect();
|
|
// fix scrollbar
|
|
float sz = m_size.y - (pad[0] + pad[2]);
|
|
float new_pad = rect.w == 0 || rect.w <= sz + 2 ? 5 : 35;
|
|
if (pad[1] != new_pad)
|
|
{
|
|
YGNodeStyleSetPadding(y_node, YGEdgeRight, new_pad);
|
|
app_redraw();
|
|
}
|
|
}
|
|
|
|
void NodeScroll::draw()
|
|
{
|
|
NodeBorder::draw();
|
|
fix_scroll();
|
|
glm::vec4 rect = get_children_rect();
|
|
glm::vec4 pad = GetPadding();
|
|
float sz = m_size.y - (pad[0] + pad[2]);
|
|
float h = glm::max(30.f, sz / rect.w * sz);
|
|
float offset_percent = m_offset.y / (rect.w - sz);
|
|
float pr = YGNodeLayoutGetPadding(y_node, YGEdgeRight) - 5;
|
|
glDisable(GL_BLEND);
|
|
ShaderManager::use(kShader::Color);
|
|
ShaderManager::u_mat4(kShaderUniform::MVP, m_proj
|
|
* glm::translate(glm::vec3(m_pos.x + m_size.x - pr, m_pos.y - offset_percent * (sz - h) + pad[0], 0))
|
|
* glm::scale(glm::vec3(pr, h, 1))
|
|
* glm::translate(glm::vec3(.5, .5, 0))
|
|
);
|
|
ShaderManager::u_vec4(kShaderUniform::Col, m_scrollbar_color);
|
|
m_plane.draw_fill();
|
|
}
|
|
|
|
kEventResult NodeScroll::handle_event(Event* e)
|
|
{
|
|
NodeBorder::handle_event(e);
|
|
auto me = static_cast<MouseEvent*>(e);
|
|
auto ge = static_cast<GestureEvent*>(e);
|
|
//auto loc = (me->m_pos - m_pos) * root()->m_zoom;
|
|
switch (e->m_type)
|
|
{
|
|
case kEventType::MouseDownL:
|
|
m_dragging = true;
|
|
m_drag_start = me->m_pos;
|
|
m_offset_start = m_offset;
|
|
// if click on the scroll area use scrolling direction, otherwise natural
|
|
m_scroll_dir = (me->m_pos.x - m_pos.x) > (m_size.x - YGNodeLayoutGetPadding(y_node, YGEdgeRight)) ? -1 : 1;
|
|
mouse_capture();
|
|
break;
|
|
case kEventType::MouseMove:
|
|
if (m_dragging)
|
|
{
|
|
glm::vec4 rect = get_children_rect();
|
|
glm::vec4 pad = GetPadding();
|
|
float speed = m_scroll_dir < 0 ? rect.w / (m_size.y - (pad[0] + pad[2])) : 1;
|
|
m_offset = m_offset_start + (me->m_pos - m_drag_start) * m_mask * m_scroll_dir * speed;
|
|
fix_scroll();
|
|
}
|
|
break;
|
|
case kEventType::MouseUpL:
|
|
mouse_release();
|
|
m_dragging = false;
|
|
break;
|
|
case kEventType::MouseScroll:
|
|
m_offset += me->m_scroll_delta * 50 * m_mask;
|
|
fix_scroll();
|
|
break;
|
|
case kEventType::GestureStart:
|
|
m_offset_start = m_offset;
|
|
mouse_capture();
|
|
break;
|
|
case kEventType::GestureMove:
|
|
m_offset = m_offset_start + ge->m_pos_delta * m_mask;
|
|
fix_scroll();
|
|
break;
|
|
case kEventType::GestureEnd:
|
|
mouse_release();
|
|
break;
|
|
case kEventType::MouseCancel:
|
|
mouse_release();
|
|
m_dragging = false;
|
|
break;
|
|
default:
|
|
return kEventResult::Available;
|
|
break;
|
|
}
|
|
return kEventResult::Consumed;
|
|
}
|