fix scroll node, improve animation panel
This commit is contained in:
@@ -15,21 +15,26 @@
|
||||
<text id="label" text="Layer"/>
|
||||
</node>
|
||||
</node>
|
||||
|
||||
<border id="container" dir="row" color=".6" margin="1" pad="2" grow="1">
|
||||
<!--frames list-->
|
||||
</border>
|
||||
|
||||
</border>
|
||||
</layout>
|
||||
|
||||
|
||||
<layout id="tpl-film">
|
||||
<border height="40" dir="row" color=".6" margin="1" pad="2" grow="1">
|
||||
<!--frames list-->
|
||||
</border>
|
||||
</layout>
|
||||
|
||||
<layout id="tpl-panel-animation">
|
||||
<node margin="0 0 10 0" rtl="ltr" grow="1" dir="col">
|
||||
<border color=".4" pad="0 5 0 5"><timeline id="timeline" margin="0 0 0 101" height="20"/></border>
|
||||
|
||||
<scroll id="container" pad="0 5 0 5" color=".4" dir="col-reverse" justify="flex-end" flood-events="1" grow="1" shrink="1">
|
||||
<!--layers list-->
|
||||
</scroll>
|
||||
<border pad="0 5 0 5" dir="row" color=".4" grow="1" shrink="1">
|
||||
<node color=".3" id="layers" width="100" dir="col-reverse" justify="flex-end" margin="20 5 0 0"></node>
|
||||
<scroll scroll-dir="h" color=".5" grow="1" shrink="1" dir="col" margin="0 0 5 0">
|
||||
<border color=".4"><timeline id="timeline" height="20"/></border>
|
||||
<node id="frames" dir="col-reverse" justify="flex-end" flood-events="1"></node>
|
||||
</scroll>
|
||||
</border>
|
||||
|
||||
<border height="40" color=".5" dir="row" align="center" flood-events="1">
|
||||
<button-custom id="btn-add" thickness="1" color="0 0" border-color=".0" shrink="1" margin="0 2 0 5">
|
||||
|
||||
@@ -538,13 +538,15 @@ bool App::update_ui_observer(Node *n)
|
||||
float pl = YGNodeLayoutGetPadding(p->y_node, YGEdgeLeft);
|
||||
glm::vec2 off_p(pl, pt);
|
||||
glm::vec2 off_s(pr, pb);
|
||||
glm::vec4 pclip = { xy(p->m_clip_uncut) + off_p, zw(p->m_clip_uncut) - off_s - off_p };
|
||||
glm::vec2 parent_offset = p->m_parent ? -p->m_parent->m_pos_offset_childred : glm::vec2(0.f);
|
||||
glm::vec4 pclip = { xy(p->m_clip_uncut) + off_p, zw(p->m_clip_uncut) - off_s - off_p + parent_offset };
|
||||
box = rect_intersection(box, pclip);
|
||||
p = p->m_parent;
|
||||
}
|
||||
//auto box = n->m_clip;
|
||||
//glm::ivec4 c = glm::vec4((int)box.x - 1, (int)(height / zoom - box.y - box.w) - 1, (int)box.z + 2, (int)box.w + 2) * zoom;
|
||||
if (box.z <= 0.f || box.w <= 0.f)
|
||||
glm::vec2 parent_offset = n->m_parent ? n->m_parent->m_pos_offset_childred : glm::vec2(0.f);
|
||||
if (box.z <= parent_offset.x || box.w <= parent_offset.y)
|
||||
{
|
||||
if (n->m_on_screen)
|
||||
{
|
||||
|
||||
@@ -566,7 +566,12 @@ glm::vec4 Node::get_children_rect() const
|
||||
for (auto& c : m_children)
|
||||
{
|
||||
if (c->m_display)
|
||||
{
|
||||
ret = rect_union(ret, c->m_clip_uncut);
|
||||
auto r = c->get_children_rect();
|
||||
if (r.w > 0 && r.z > 0)
|
||||
ret = rect_union(ret, r);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1088,9 +1093,9 @@ void Node::update_internal(const glm::vec2& origin, const glm::mat4& proj, float
|
||||
float pl = YGNodeLayoutGetPadding(m_parent->y_node, YGEdgeLeft);
|
||||
glm::vec2 off_p(pl, pt);
|
||||
glm::vec2 off_s(pr, pb);
|
||||
glm::vec4 pclip = { xy(m_parent->m_clip) + off_p, zw(m_parent->m_clip) - (off_s + off_p)};
|
||||
glm::vec4 pclip = { xy(m_parent->m_clip) + off_p, zw(m_parent->m_clip) - (off_s + off_p) };
|
||||
m_clip_uncut = glm::vec4(m_pos - glm::vec2(1), m_size + glm::vec2(2));
|
||||
m_clip = rect_intersection(m_clip_uncut, m_parent->m_clip);
|
||||
m_clip = rect_intersection(m_clip_uncut, m_parent->m_clip) + glm::vec4(0, 0, -parent_offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -49,6 +49,7 @@ enum class kAttribute : uint16_t
|
||||
AutoSize = const_hash("autosize"),
|
||||
MouseCapture = const_hash("mouse-capture"),
|
||||
ScrollColor = const_hash("scroll-color"),
|
||||
ScrollDir = const_hash("scroll-dir"),
|
||||
Multiline = const_hash("multiline"),
|
||||
TextAlign = const_hash("text-align"),
|
||||
TextVerticalAlign = const_hash("text-vertical-align"),
|
||||
@@ -116,6 +117,7 @@ public:
|
||||
|
||||
glm::mat4 m_proj;
|
||||
glm::mat4 m_mvp;
|
||||
glm::mat4 m_mvp_visible;
|
||||
bool m_mouse_focus = false;
|
||||
bool m_mouse_inside = false;
|
||||
bool m_flood_events = false;
|
||||
|
||||
@@ -26,7 +26,8 @@ void NodePanelAnimation::init()
|
||||
|
||||
void NodePanelAnimation::init_controls()
|
||||
{
|
||||
m_container = find<NodeScroll>("container");
|
||||
m_layers_container = find<NodeScroll>("layers");
|
||||
m_frames_container = find<NodeScroll>("frames");
|
||||
m_timeline = find<NodeAnimationTimeline>("timeline");
|
||||
btn_add = find<NodeButtonCustom>("btn-add");
|
||||
btn_remove = find<NodeButtonCustom>("btn-remove");
|
||||
@@ -62,23 +63,30 @@ void NodePanelAnimation::load_layers()
|
||||
{
|
||||
if (!added_to_root())
|
||||
return;
|
||||
m_container->remove_all_children();
|
||||
m_layers_container->remove_all_children();
|
||||
m_frames_container->remove_all_children();
|
||||
auto& layers = Canvas::I->m_layers;
|
||||
m_selected_frame = nullptr;
|
||||
float max_width = 0;
|
||||
for (int i = 0; i < layers.size(); i++)
|
||||
{
|
||||
auto l = m_container->add_child<NodeAnimationLayer>();
|
||||
auto l = m_layers_container->add_child<NodeAnimationLayer>();
|
||||
l->set_text(layers[i]->m_name);
|
||||
l->set_selected(Canvas::I->m_current_layer_idx == i);
|
||||
l->set_chekcbox(layers[i]->m_visible);
|
||||
auto film = m_frames_container->add_child_ref<NodeAnimationFilm>();
|
||||
film->SetWidth(layers[i]->total_duration() * 35.f);
|
||||
max_width = glm::max(max_width, layers[i]->total_duration() * 35.f);
|
||||
for (int fi = 0; fi < layers[i]->m_frames.size(); fi++)
|
||||
{
|
||||
auto b = l->add_frame(layers[i]->m_frames[fi].m_duration);
|
||||
auto b = film->add_frame(layers[i]->m_frames[fi].m_duration);
|
||||
|
||||
if (m_selected_frame_layer_id == layers[i]->id && m_selected_frame_index == fi)
|
||||
{
|
||||
b->set_active(true);
|
||||
m_selected_frame = b.get();
|
||||
}
|
||||
|
||||
b->on_click = [this, fi, lid=layers[i]->id, i] (Node* target) {
|
||||
auto frame = static_cast<NodeAnimationFrame*>(target);
|
||||
if (m_selected_frame)
|
||||
@@ -91,6 +99,7 @@ void NodePanelAnimation::load_layers()
|
||||
};
|
||||
}
|
||||
}
|
||||
m_timeline->SetWidth(max_width);
|
||||
}
|
||||
|
||||
void NodePanelAnimation::added(Node* parent)
|
||||
@@ -124,7 +133,6 @@ void NodeAnimationLayer::init_controls()
|
||||
{
|
||||
m_label = find<NodeText>("label");
|
||||
m_visibility = find<NodeCheckBox>("cb");
|
||||
m_container = find<NodeScroll>("container");
|
||||
}
|
||||
|
||||
void NodeAnimationLayer::draw()
|
||||
@@ -135,15 +143,9 @@ void NodeAnimationLayer::draw()
|
||||
parent::draw();
|
||||
}
|
||||
|
||||
std::shared_ptr<NodeAnimationFrame> NodeAnimationLayer::add_frame(int duration)
|
||||
{
|
||||
auto b = m_container->add_child_ref<NodeAnimationFrame>();
|
||||
b->SetWidth(30 * duration + 5 * (duration - 1));
|
||||
//b->SetFlexGrow(duration);
|
||||
b->SetHeightP(100);
|
||||
b->SetMargin(0, 5, 0, 0);
|
||||
return b;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -48,7 +48,8 @@ class NodePanelAnimation : public Node
|
||||
NodeButtonCustom* btn_up = nullptr;
|
||||
NodeButtonCustom* btn_down = nullptr;
|
||||
NodeButtonCustom* btn_duplicate = nullptr;
|
||||
NodeScroll* m_container = nullptr;
|
||||
Node* m_layers_container = nullptr;
|
||||
Node* m_frames_container = nullptr;
|
||||
NodeAnimationFrame* m_selected_frame = nullptr;
|
||||
NodeAnimationTimeline* m_timeline = nullptr;
|
||||
int m_selected_frame_index = -1;
|
||||
@@ -68,6 +69,32 @@ public:
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class NodeAnimationFilm : public NodeBorder
|
||||
{
|
||||
public:
|
||||
using this_class = NodeAnimationFilm;
|
||||
using parent = NodeBorder;
|
||||
|
||||
virtual Node* clone_instantiate() const override { return new this_class; }
|
||||
virtual void init() override
|
||||
{
|
||||
parent::init();
|
||||
init_template_file("data/dialogs/panel-animation.xml", "tpl-film");
|
||||
}
|
||||
|
||||
std::shared_ptr<NodeAnimationFrame> add_frame(int duration)
|
||||
{
|
||||
auto b = add_child_ref<NodeAnimationFrame>();
|
||||
b->SetWidth(30 * duration + 5 * (duration - 1));
|
||||
//b->SetFlexGrow(duration);
|
||||
b->SetHeightP(100);
|
||||
b->SetMargin(0, 5, 0, 0);
|
||||
return b;
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class NodeAnimationLayer : public NodeBorder
|
||||
{
|
||||
bool m_selected = false;
|
||||
@@ -76,7 +103,6 @@ class NodeAnimationLayer : public NodeBorder
|
||||
glm::vec4 m_color_hover = glm::vec4(.5, .5, .5, 1);
|
||||
NodeText* m_label = nullptr;
|
||||
NodeCheckBox* m_visibility = nullptr;
|
||||
NodeScroll* m_container = nullptr;
|
||||
public:
|
||||
std::function<void(NodeAnimationLayer* target)> on_selected;
|
||||
std::function<void(NodeAnimationLayer* target, bool visible)> on_visibility_changed;
|
||||
@@ -91,8 +117,7 @@ public:
|
||||
virtual void draw() override;
|
||||
|
||||
void init_controls();
|
||||
std::shared_ptr<NodeAnimationFrame> add_frame(int duration);
|
||||
void set_text(const std::string& text) { m_label->set_text(text.c_str()); }
|
||||
void set_selected(bool selected) { m_selected = selected; }
|
||||
void set_chekcbox(bool checked) { m_visibility->set_value(checked); }
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4,14 +4,6 @@
|
||||
#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;
|
||||
@@ -22,8 +14,15 @@ 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;
|
||||
if (rect.w > 0 && rect.z > 0)
|
||||
{
|
||||
m_offset = glm::clamp(m_offset, -zw(rect) + zw(m_clip_uncut) - padoff, { 0, 0 });
|
||||
m_pos_offset_childred = m_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pos_offset_childred = m_offset = { 0, 0 };
|
||||
}
|
||||
}
|
||||
|
||||
void NodeScroll::clone_copy(Node* dest) const
|
||||
@@ -31,6 +30,8 @@ void NodeScroll::clone_copy(Node* dest) const
|
||||
NodeBorder::clone_copy(dest);
|
||||
auto n = static_cast<NodeScroll*>(dest);
|
||||
n->m_scrollbar_color = m_scrollbar_color;
|
||||
n->m_mask = m_mask;
|
||||
n->m_direction = m_direction;
|
||||
}
|
||||
|
||||
void NodeScroll::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
|
||||
@@ -48,6 +49,18 @@ void NodeScroll::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* a
|
||||
m_scrollbar_color = col;
|
||||
break;
|
||||
}
|
||||
case kAttribute::ScrollDir:
|
||||
if (strcmpi(attr->Value(), "vertical") == 0 || strcmpi(attr->Value(), "v") == 0)
|
||||
{
|
||||
m_direction = kScrollDirection::Vertical;
|
||||
m_mask = { 0, 1 };
|
||||
}
|
||||
else if (strcmpi(attr->Value(), "horizontal") == 0 || strcmpi(attr->Value(), "h") == 0)
|
||||
{
|
||||
m_direction = kScrollDirection::Horizontal;
|
||||
m_mask = { 1, 0 };
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -57,13 +70,33 @@ 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)
|
||||
if (rect.w > 0 && rect.z > 0)
|
||||
{
|
||||
YGNodeStyleSetPadding(y_node, YGEdgeRight, new_pad);
|
||||
app_redraw();
|
||||
// fix scrollbar
|
||||
if (m_direction == kScrollDirection::Vertical)
|
||||
{
|
||||
float szv = m_size.y - (pad[0] + pad[2]);
|
||||
float new_padv = rect.w == 0 || rect.w <= szv + 2 ? 5 : 35;
|
||||
if (pad[1] != new_padv)
|
||||
{
|
||||
YGNodeStyleSetPadding(y_node, YGEdgeRight, new_padv);
|
||||
app_redraw();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float szh = m_size.x - (pad[3] + pad[1]);
|
||||
float new_padh = rect.z == 0 || rect.z <= szh + 2 ? 5 : 35;
|
||||
if (pad[2] != new_padh)
|
||||
{
|
||||
YGNodeStyleSetPadding(y_node, YGEdgeBottom, new_padh);
|
||||
app_redraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetPadding(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,21 +104,42 @@ 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();
|
||||
|
||||
if (rect.w > 0 && rect.z > 0)
|
||||
{
|
||||
glDisable(GL_BLEND);
|
||||
ShaderManager::use(kShader::Color);
|
||||
|
||||
if (m_direction == kScrollDirection::Vertical)
|
||||
{
|
||||
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;
|
||||
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))
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
float sz = m_size.x - (pad[3] + pad[1]);
|
||||
float h = glm::max(30.f, sz / rect.z * sz);
|
||||
float offset_percent = m_offset.x / (rect.z - sz);
|
||||
float pr = YGNodeLayoutGetPadding(y_node, YGEdgeBottom) - 5;
|
||||
ShaderManager::u_mat4(kShaderUniform::MVP, m_proj
|
||||
* glm::translate(glm::vec3(m_pos.x - offset_percent * (sz - h) + pad[3], m_pos.y + m_size.y - pr, 0))
|
||||
* glm::scale(glm::vec3(h, pr, 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)
|
||||
@@ -101,7 +155,10 @@ kEventResult NodeScroll::handle_event(Event* e)
|
||||
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;
|
||||
if (m_direction == kScrollDirection::Vertical)
|
||||
m_drag_dir = (me->m_pos.x - m_pos.x) > (m_size.x - YGNodeLayoutGetPadding(y_node, YGEdgeRight)) ? -1 : 1;
|
||||
else
|
||||
m_drag_dir = (me->m_pos.y - m_pos.y) > (m_size.y - YGNodeLayoutGetPadding(y_node, YGEdgeBottom)) ? -1 : 1;
|
||||
mouse_capture();
|
||||
break;
|
||||
case kEventType::MouseMove:
|
||||
@@ -109,9 +166,20 @@ kEventResult NodeScroll::handle_event(Event* e)
|
||||
{
|
||||
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();
|
||||
if (rect.w > 0 && rect.z > 0)
|
||||
{
|
||||
if (m_direction == kScrollDirection::Vertical)
|
||||
{
|
||||
float speed = m_drag_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_drag_dir * speed;
|
||||
}
|
||||
else
|
||||
{
|
||||
float speed = m_drag_dir < 0 ? rect.z / (m_size.x - (pad[3] + pad[1])) : 1;
|
||||
m_offset = m_offset_start + (me->m_pos - m_drag_start) * m_mask * m_drag_dir * speed;
|
||||
}
|
||||
fix_scroll();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case kEventType::MouseUpL:
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
class NodeScroll : public NodeBorder
|
||||
{
|
||||
bool m_dragging = false;
|
||||
float m_scroll_dir = 1.f;
|
||||
float m_drag_dir = 1.f;
|
||||
glm::vec2 m_drag_start = glm::vec2(0);
|
||||
glm::vec2 m_offset_start = glm::vec2(0);
|
||||
glm::vec2 m_offset = glm::vec2(0);
|
||||
glm::vec2 m_mask = glm::vec2(1, 0);
|
||||
glm::vec2 m_mask = glm::vec2(0, 1);
|
||||
glm::vec4 m_scrollbar_color = { .3, .3, .3, 1 };
|
||||
public:
|
||||
NodeScroll();
|
||||
enum class kScrollDirection : uint8_t { Vertical, Horizontal } m_direction;
|
||||
virtual Node* clone_instantiate() const override;
|
||||
virtual void clone_copy(Node* dest) const override;
|
||||
virtual kEventResult handle_event(Event* e) override;
|
||||
|
||||
Reference in New Issue
Block a user