Popup presets panel, fix padding scissor, stacked mouse capture

This commit is contained in:
2019-01-26 00:55:57 +01:00
parent 79e4777f77
commit 14b26c8902
11 changed files with 184 additions and 66 deletions

View File

@@ -88,9 +88,6 @@
<!--brush-presets panel-->
<layout id="tpl-panel-brush-preset">
<node width="220" margin="0 0 10 0" rtl="ltr">
<border height="30" color=".5" align="center" justify="center">
<text text="Brush Presets" font-face="arial" font-size="11" color="1 1 1 1"/>
</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">
<icon width="30" icon="add"/>
@@ -106,17 +103,16 @@
<icon width="30" icon="bin_closed"/>
</button-custom>
</border>
<border id="layers-container" pad="5" color=".4" dir="col" flood-events="1">
</border>
<border id="brushes" color=".4" pad="5" dir="row" wrap="1" flood-events="1">
</border>
<scroll id="brushes" color=".4" pad="5 20 5 5" dir="row" wrap="1" flood-events="1" grow="1" height="1"/>
</node>
</layout>
<!--brush-presets-item icon-->
<layout id="tpl-brush-preset">
<button-custom width="100%" height="50" margin="1" pad="5" align="center" justify="center" dir="row">
<image id="thumb" width="50" height="50"/>
<stroke-preview id="canvas" width="1" grow="1" height="50"/>
<button-custom width="100%" height="70" margin="1" pad="5" align="center" justify="center" dir="row">
<border color="1" width="40" height="60" align="center" justify="center">
<image id="thumb" width="40" height="40"/>
</border>
<stroke-preview id="canvas" width="1" grow="1" height="60"/>
</button-custom>
</layout>
@@ -164,6 +160,7 @@
<node dir="row">
<node width="30%" dir="col">
<!--<node height="20" justify="center" margin="5 0 5 0"><text text="Shade" font-face="arial" font-size="11"/></node>-->
<node height="40" justify="center" margin="5 0 0 0"><text text="Preset" font-face="arial" font-size="11"/></node>
<node height="30" justify="center" margin="5 0 5 0"><text text="Blend" font-face="arial" font-size="11"/></node>
<node height="20" justify="center"><text text="Size" font-face="arial" font-size="11"/></node>
<node height="20" justify="center"><text text="Flow" font-face="arial" font-size="11"/></node>
@@ -180,6 +177,10 @@
</node>
<node dir="col" align="center" grow="1" width="1" flood-events="1">
<!--<node height="20" pad="1" width="100%" margin="5 0 5 0"><slider-h id="tip-shade" value="1"/></node>-->
<button-custom id="preset-button" width="100%" height="40" margin="5 0 0 0" dir="row" pad="4">
<image id="preset-thumb" path="data/thumbs/Round-Hard.png" width="32" height="100%"/>
<stroke-preview id="preset-preview" width="10" grow="1" height="100%"/>
</button-custom>
<node height="30" pad="1" width="100%" dir="row" margin="5 0 5 0">
<combobox id="blend-mode" text="Normal" width="100%" height="30" combo-list="Normal,-,Multiply,Screen,-,Color Dodge,Overlay" default="0"/>
</node>
@@ -484,7 +485,7 @@
<node grow="1"><text os="win,osx" id="path" text="Workind dir: path" text-wrap-width="470" font-face="arial" font-size="11" margin="10 5 10 10"/></node>
<button os="win,osx" id="btn-path" text="Set destination dir" width="140" height="30" margin="0 10 0 0"/>
</node>
<node id="footer" height="40" dir="row" align="flex-end" justify="flex-end" pad="10">
<node id="footer" height="50" dir="row" align="flex-end" justify="flex-end" pad="10">
<node grow="1"><button id="btn-delete" text="Delete Project" width="100" height="30" margin="0 10 0 0" color="1 0 0 1"/></node>
<button id="btn-ok" text="Open Project" width="100" height="30" margin="0 10 0 0"/>
<button id="btn-cancel" text="Cancel" width="60" height="30"/>

1
libs/curl-win Submodule

Submodule libs/curl-win added at 766a29301f

View File

@@ -484,6 +484,20 @@ void App::update(float dt)
if (n && n->m_display)
{
auto box = n->m_clip;
Node* p = n->parent;
while (p)
{
float pt = YGNodeLayoutGetPadding(p->y_node, YGEdgeTop);
float pr = YGNodeLayoutGetPadding(p->y_node, YGEdgeRight);
float pb = YGNodeLayoutGetPadding(p->y_node, YGEdgeBottom);
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) + off_p, zw(p->m_clip) - off_s - off_p };
box = rect_intersection(box, pclip);
p = p->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;
glm::ivec4 c = glm::vec4((int)box.x, (int)(height / zoom - box.y - box.w), (int)box.z, (int)box.w) * zoom;
glScissor(c.x, c.y, c.z, c.w);

View File

@@ -124,7 +124,7 @@ void App::init_sidebar()
color = find_or_create_panel<NodePanelColor>(panels);
stroke = find_or_create_panel<NodePanelStroke>(panels);
grid = find_or_create_panel<NodePanelGrid>(panels);
presets = find_or_create_panel<NodePanelBrushPreset>(panels);
//presets = find_or_create_panel<NodePanelBrushPreset>(panels);
// if (canvas)
// {
@@ -132,15 +132,15 @@ void App::init_sidebar()
// stroke->m_canvas->draw_stroke();
// }
presets->on_brush_changed = [this](Node* target, std::shared_ptr<Brush>& b) {
// don't change some params
b->m_tip_size = Canvas::I->m_current_brush->m_tip_size;
b->m_tip_color = Canvas::I->m_current_brush->m_tip_color;
*Canvas::I->m_current_brush = *b;
stroke->m_preview->draw_stroke();
stroke->m_brush_thumb->set_image(b->m_brush_thumb_path);
stroke->update_controls();
};
//presets->on_brush_changed = [this](Node* target, std::shared_ptr<Brush>& b) {
// // don't change some params
// b->m_tip_size = Canvas::I->m_current_brush->m_tip_size;
// b->m_tip_color = Canvas::I->m_current_brush->m_tip_color;
// *Canvas::I->m_current_brush = *b;
// stroke->m_preview->draw_stroke();
// stroke->m_brush_thumb->set_image(b->m_brush_thumb_path);
// stroke->update_controls();
//};
color->on_color_changed = [this](Node* target, glm::vec4 color) {
Canvas::I->m_current_brush->m_tip_color = color;
};
@@ -237,14 +237,14 @@ void App::init_sidebar()
// button->set_color(panels->get_child_index(brushes.get()) == -1 ? color_button_normal : color_button_hlight);
// };
//}
if (auto* button = layout[main_id]->find<NodeButton>("btn-brush-preset"))
{
button->on_click = [this, button](Node*) {
panels->get_child_index(presets.get()) == -1 ? panels->add_child(presets) : panels->remove_child(presets.get());
panels->fix_scroll();
button->set_color(panels->get_child_index(presets.get()) == -1 ? color_button_normal : color_button_hlight);
};
}
//if (auto* button = layout[main_id]->find<NodeButton>("btn-brush-preset"))
//{
// button->on_click = [this, button](Node*) {
// panels->get_child_index(presets.get()) == -1 ? panels->add_child(presets) : panels->remove_child(presets.get());
// panels->fix_scroll();
// button->set_color(panels->get_child_index(presets.get()) == -1 ? color_button_normal : color_button_hlight);
// };
//}
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-color"))
{
button->on_click = [this, button](Node*) {

View File

@@ -346,29 +346,71 @@ glm::vec4 Node::get_children_rect() const
return ret;
}
bool Node::is_child_recursive(Node* o) const
{
for (const auto& c : m_children)
{
if (c.get() == o || c->is_child_recursive(o))
return true;
}
return false;
}
void Node::mouse_capture()
{
auto& c = root()->current_mouse_capture;
auto& s = root()->m_capture_stack;
// already owner of capture
if (root()->current_mouse_capture == this)
if (c == this || std::find(s.begin(), s.end(), this) != s.end())
return;
// cancel previous owner
if (auto n = root()->current_mouse_capture)
if (c)
{
if (c->is_child_recursive(this))
{
// save on stack
s.push_back(c);
}
else
{
// cancel previous owner
MouseEvent e;
e.m_type = kEventType::MouseCancel;
n->handle_event(&e);
c->handle_event(&e);
// TODO: only delete nodes on a different tree,
// so preserve direct parents of this
// also clear the whole stack
s.clear();
}
}
// make current
root()->current_mouse_capture = this;
c = this;
m_mouse_captured = true;
}
void Node::mouse_release()
{
if (root()->current_mouse_capture == this)
root()->current_mouse_capture = nullptr;
auto& c = root()->current_mouse_capture;
auto& s = root()->m_capture_stack;
s.erase(std::remove(s.begin(), s.end(), this), s.end());
if (c == this)
{
if (s.empty())
{
c = nullptr;
}
else
{
c = s.back();
s.pop_back();
}
}
m_mouse_captured = false;
}
@@ -646,13 +688,14 @@ void Node::update_internal(const glm::vec2& origin, const glm::mat4& proj)
// correct the padding clip
// should not clip the padded area
// useful to draw decorations
float pt = 0;//YGNodeLayoutGetPadding(parent->y_node, YGEdgeTop);
float pr = 0;//YGNodeLayoutGetPadding(parent->y_node, YGEdgeRight);
float pb = 0;//YGNodeLayoutGetPadding(parent->y_node, YGEdgeBottom);
float pl = 0;//YGNodeLayoutGetPadding(parent->y_node, YGEdgeLeft);
float pt = YGNodeLayoutGetPadding(parent->y_node, YGEdgeTop);
float pr = YGNodeLayoutGetPadding(parent->y_node, YGEdgeRight);
float pb = YGNodeLayoutGetPadding(parent->y_node, YGEdgeBottom);
float pl = YGNodeLayoutGetPadding(parent->y_node, YGEdgeLeft);
glm::vec2 off_p(pl, pt);
glm::vec2 off_s(pr, pb);
m_clip_uncut = glm::vec4(m_pos - off_p - glm::vec2(1), m_size + off_p + off_s + glm::vec2(2));
glm::vec4 pclip = { xy(parent->m_clip) + off_p, zw(parent->m_clip) - off_s - off_p};
m_clip_uncut = glm::vec4(m_pos, m_size);
m_clip = rect_intersection(m_clip_uncut, parent->m_clip);
}
else

View File

@@ -111,6 +111,7 @@ public:
bool m_force_mouse_capture = false;
bool m_capture_children = true; // wether to capture children events when xx_capture() is used
bool m_destroyed = false;
std::vector<Node*> m_capture_stack;
bool m_mouse_ignore = true;
float m_zoom = 1.f;
@@ -217,7 +218,7 @@ public:
virtual void on_tick(float dt) { };
virtual kEventResult on_event(Event* e);
virtual kEventResult handle_event(Event* e);
virtual void handle_resize(glm::vec2 old_size, glm::vec2 new_size);;
virtual void handle_resize(glm::vec2 old_size, glm::vec2 new_size);
virtual void create();
virtual void init();
virtual void loaded();
@@ -240,6 +241,7 @@ public:
int get_child_index(Node* n);
Node* get_child_at(int index);
glm::vec4 get_children_rect() const;
bool is_child_recursive(Node* o) const;
void mouse_capture();
void mouse_release();
void key_capture();

View File

@@ -116,12 +116,6 @@ int NodePanelBrush::find_brush(const std::string & name) const
return -1;
}
uint16_t NodePanelBrush::get_texture_id(int index) const
{
TextureManager::load(m_brushes[index]->high_path.c_str(), true);
return m_brushes[index]->high_id;
}
std::string NodePanelBrush::get_texture_path(int index) const
{
return m_brushes[index]->high_path;
@@ -132,11 +126,6 @@ std::string NodePanelBrush::get_thumb_path(int index) const
return m_brushes[index]->thumb_path;
}
int NodePanelBrush::get_brush_id(int index) const
{
return m_brushes[index]->m_brushID;
}
// select the current brush based on the texture id
void NodePanelBrush::select_brush(int brush_id)
{
@@ -167,8 +156,8 @@ void NodeBrushPresetItem::init()
color_hover = glm::vec4(.7, .7, .7, 1);
color_normal = glm::vec4(.3, .3, .3, 1);
m_color = color_normal;
m_thumb = (NodeImage*)m_children[0].get();
m_preview = (NodeStrokePreview*)m_children[1].get();
m_thumb = find<NodeImage>("thumb");
m_preview = find<NodeStrokePreview>("canvas");
}
void NodeBrushPresetItem::draw()
@@ -193,7 +182,7 @@ Node* NodePanelBrushPreset::clone_instantiate() const
void NodePanelBrushPreset::init()
{
init_template("tpl-panel-brush-preset");
m_container = find<NodeBorder>("brushes");
m_container = find<Node>("brushes");
m_btn_add = find<NodeButtonCustom>("btn-add");
m_btn_add->on_click = [this] (Node*) {
NodeBrushPresetItem* brush = new NodeBrushPresetItem;
@@ -233,6 +222,24 @@ void NodePanelBrushPreset::init()
restore();
}
kEventResult NodePanelBrushPreset::handle_event(Event* e)
{
switch (e->m_type)
{
case kEventType::MouseUpL:
if (!m_mouse_inside)
{
mouse_release();
parent->remove_child(this);
}
break;
default:
return kEventResult::Available;
break;
}
return kEventResult::Consumed;
}
void NodePanelBrushPreset::handle_click(Node* target)
{
if (target == m_current)

View File

@@ -32,12 +32,9 @@ public:
virtual void init() override;
virtual kEventResult handle_event(Event* e) override;
void handle_click(Node* target);
std::vector<std::string> FindAllBrushes(const std::string& folder);
int find_brush(const std::string& name) const;
uint16_t get_texture_id(int index) const;
std::string get_texture_path(int index) const;
std::string get_thumb_path(int index) const;
int get_brush_id(int index) const;
void select_brush(int brush_id);
};
@@ -111,6 +108,7 @@ public:
std::function<void(Node* target, std::shared_ptr<Brush>& brush)> on_brush_changed;
virtual Node* clone_instantiate() const override;
virtual void init() override;
virtual kEventResult handle_event(Event* e) override;
void handle_click(Node* target);
std::shared_ptr<Brush> get_brush(int index) const;
bool save();

View File

@@ -60,6 +60,17 @@ void NodePanelStroke::init_controls()
m_brush_popup->m_flood_events = true;
m_brush_popup->m_capture_children = false;
m_presets_popup = std::make_shared<NodePanelBrushPreset>();
m_presets_popup->m_manager = m_manager;
m_presets_popup->init();
m_presets_popup->create();
m_presets_popup->loaded();
m_presets_popup->SetPositioning(YGPositionTypeAbsolute);
m_presets_popup->SetSize(200, 400);
m_presets_popup->m_mouse_ignore = false;
m_presets_popup->m_flood_events = true;
m_presets_popup->m_capture_children = false;
auto b = std::make_shared<Brush>();
int br_idx = m_brush_popup->find_brush("Round-Hard");
b->load_texture(m_brush_popup->get_texture_path(br_idx), m_brush_popup->get_thumb_path(br_idx));
@@ -70,6 +81,38 @@ void NodePanelStroke::init_controls()
b->m_tip_opacity = 1.f;
Canvas::I->m_current_brush = b;
m_preset_thumb = find<NodeImage>("preset-thumb");
m_preset_preview = find<NodeStrokePreview>("preset-preview");
m_preset_preview->m_brush = b;
m_preset_preview->draw_stroke();
m_preset_button = find<NodeButtonCustom>("preset-button");
m_preset_button->on_click = [this](Node*) {
auto screen = root()->m_size;
glm::vec2 pos = m_preset_button->m_pos + glm::vec2(m_preset_button->m_size.x, 0);
root()->add_child(m_presets_popup);
root()->update();
if ((pos.y + m_presets_popup->m_size.y) > screen.y) pos.y = screen.y - m_presets_popup->m_size.y;
if (pos.y < 0) pos.y = 0;
m_presets_popup->SetPosition(pos.x, pos.y);
m_presets_popup->mouse_capture();
root()->update();
m_presets_popup->on_brush_changed = [this](Node* target, std::shared_ptr<Brush>& b) {
// don't change some params
//b->m_tip_size = Canvas::I->m_current_brush->m_tip_size;
b->m_tip_color = Canvas::I->m_current_brush->m_tip_color;
*Canvas::I->m_current_brush = *b;
m_preview->draw_stroke();
m_preset_preview->draw_stroke();
m_brush_thumb->set_image(b->m_brush_thumb_path);
m_preset_thumb->set_image(b->m_brush_thumb_path);
update_controls();
//m_presets_popup->mouse_release();
//m_presets_popup->parent->remove_child(m_presets_popup.get());
};
};
m_brush_thumb = find<NodeImage>("tip-change-thumb");
m_brush_thumb->set_image(m_brush_popup->get_thumb_path(br_idx));

View File

@@ -41,7 +41,11 @@ public:
NodeCheckBox* m_tip_val_pressure;
NodeButtonCustom* m_brush_button;
NodeImage* m_brush_thumb;
NodeImage* m_preset_thumb;
NodeButtonCustom* m_preset_button;
NodeStrokePreview* m_preset_preview;
std::shared_ptr<NodePanelBrush> m_brush_popup;
std::shared_ptr<NodePanelBrushPreset> m_presets_popup;
std::function<void(Node* target)> on_stroke_change;
std::function<void(Node* target, const std::string& path)> on_stencil_changed;
std::function<void(Node* target, const std::string& path, const std::string& thumb)> on_brush_changed;

View File

@@ -5,6 +5,7 @@
#include "shader.h"
#include "bezier.h"
#include "canvas.h"
#include "app.h"
Node* NodeStrokePreview::clone_instantiate() const
{
@@ -68,7 +69,7 @@ void NodeStrokePreview::draw_stroke()
glm::mat4 proj = glm::ortho<float>(0, (float)m_rtt.getWidth(), 0, (float)m_rtt.getHeight(), -1, 1);
const auto& b = m_brush;
m_stroke.m_max_size = 0.1f;
m_stroke.m_max_size = m_size.y / 800.f * App::I.zoom;
m_stroke.m_camera.fov = Canvas::I->m_cam_fov;
m_stroke.m_camera.rot = Canvas::I->m_cam_rot;
m_stroke.reset();
@@ -141,10 +142,10 @@ void NodeStrokePreview::draw()
void NodeStrokePreview::handle_resize(glm::vec2 old_size, glm::vec2 new_size)
{
if (old_size == new_size)
if (m_rtt.getWidth() == new_size.x && m_rtt.getHeight() == new_size.y || !m_brush)
return;
float pad = 30.f;
float pad = m_size.x * .15f;
new_size *= root()->m_zoom;
float w = new_size.x;
float h = new_size.y;
@@ -152,7 +153,11 @@ void NodeStrokePreview::handle_resize(glm::vec2 old_size, glm::vec2 new_size)
m_stroke.reset();
m_stroke.start(m_brush);
for (int i = 0; i < 20; i++)
m_stroke.add_point(glm::vec3(BezierCurve::Bezier2D(kp, i / 20.f), 0), 1.f);
{
float t = (float)i / 20.f;
float p = 1.f - glm::abs(t * 2.f - 1.f);
m_stroke.add_point(glm::vec3(BezierCurve::Bezier2D(kp, t), 0), p);
}
m_rtt.destroy();
m_rtt.create((int)new_size.x, (int)new_size.y);