added render target and bezier classes, added stroke settings panel
This commit is contained in:
411
engine/layout.h
411
engine/layout.h
@@ -4,6 +4,8 @@
|
||||
#include "shader.h"
|
||||
#include "font.h"
|
||||
#include "asset.h"
|
||||
#include "rtt.h"
|
||||
#include "bezier.h"
|
||||
#include <tinyxml2.h>
|
||||
#include <yoga/Yoga.h>
|
||||
|
||||
@@ -62,9 +64,12 @@ enum class kWidget : uint16_t
|
||||
Ref = const_hash("ref"),
|
||||
CheckBox = const_hash("checkbox"),
|
||||
Layer = const_hash("layer"),
|
||||
PanelLayers = const_hash("panel-layers"),
|
||||
PanelBrushes = const_hash("panel-brushes"),
|
||||
PanelLayer = const_hash("panel-layer"),
|
||||
PanelBrush = const_hash("panel-brush"),
|
||||
PanelColor = const_hash("panel-color"),
|
||||
PanelStroke = const_hash("panel-stroke"),
|
||||
ColorQuad = const_hash("color-quad"),
|
||||
Canvas2D = const_hash("canvas2D"),
|
||||
};
|
||||
|
||||
enum class kShapeType : uint16_t
|
||||
@@ -273,6 +278,7 @@ public:
|
||||
|
||||
virtual kEventResult on_event(Event* e);
|
||||
virtual kEventResult handle_event(Event* e) { return kEventResult::Available; }
|
||||
virtual void handle_resize(glm::vec2 old_size, glm::vec2 new_size) { };
|
||||
virtual void create() { }
|
||||
virtual void init() { }
|
||||
virtual void loaded() { }
|
||||
@@ -698,6 +704,7 @@ public:
|
||||
class NodePopupMenu : public Node
|
||||
{
|
||||
public:
|
||||
std::function<void(Node* target, int index)> on_select;
|
||||
virtual Node* clone_instantiate() const override { return new NodePopupMenu(); }
|
||||
virtual void init() override
|
||||
{
|
||||
@@ -706,19 +713,34 @@ public:
|
||||
SetWidth(100);
|
||||
SetHeight(400);
|
||||
SetPositioning(YGPositionTypeAbsolute);
|
||||
m_mouse_ignore = false;
|
||||
}
|
||||
virtual kEventResult handle_event(Event* e) override
|
||||
{
|
||||
switch (e->m_type)
|
||||
{
|
||||
case kEventType::MouseDownL:
|
||||
break;
|
||||
case kEventType::MouseUpL:
|
||||
if (!m_mouse_inside)
|
||||
{
|
||||
mouse_release();
|
||||
destroy();
|
||||
}
|
||||
break;
|
||||
case kEventType::MouseUpL:
|
||||
else
|
||||
{
|
||||
auto pos = ((MouseEvent*)e)->m_pos;
|
||||
for (int i = 0; i < m_children.size(); i++)
|
||||
{
|
||||
if (m_children[i]->m_mouse_inside)
|
||||
{
|
||||
if (on_select)
|
||||
on_select(this, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mouse_release();
|
||||
}
|
||||
destroy();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -833,7 +855,7 @@ public:
|
||||
static char name[256];
|
||||
int x, y, w, h;
|
||||
char* s = strtok(data, "\n");
|
||||
int i = strlen(s) + 1;
|
||||
auto i = strlen(s) + 1;
|
||||
while (i < size && sscanf(s, "%s %d %d %d %d", name, &w, &h, &x, &y) == 5)
|
||||
{
|
||||
m_icons[name] = glm::vec4(x, y, x + w, y + h);
|
||||
@@ -899,7 +921,7 @@ public:
|
||||
glClearColor(1, 0, 0, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
auto box = m_clip * root()->m_zoom;
|
||||
auto c = glm::vec4(box.x, (int)(vp[3] - box.y - box.w), box.z, box.w);
|
||||
glm::ivec4 c = (glm::ivec4)glm::vec4(box.x, (int)(vp[3] - box.y - box.w), box.z, box.w);
|
||||
glViewport(c.x, c.y, c.z, c.w);
|
||||
TextureManager::get(m_tex_id).bind();
|
||||
m_sampler->bind(0);
|
||||
@@ -963,6 +985,8 @@ class NodeSliderCursor : public NodeButtonCustom
|
||||
glm::vec2 old_pos;
|
||||
public:
|
||||
glm::vec2 m_mask{ 1, 0 };
|
||||
glm::vec2 m_value;
|
||||
std::function<void(Node* target, glm::vec2 value)> on_value_changed;
|
||||
virtual Node* clone_instantiate() const override { return new NodeSliderCursor(); }
|
||||
virtual void clone_copy(Node* dest) const override
|
||||
{
|
||||
@@ -992,6 +1016,9 @@ public:
|
||||
drag_diff = old_pos + (((MouseEvent*)e)->m_pos - drag_start) * m_mask;
|
||||
auto pos = glm::clamp(drag_diff, { 0, 0 }, sz);
|
||||
SetPosition(pos.x, pos.y);
|
||||
m_value = pos / glm::max({ 1,1 }, sz); // avoid div0
|
||||
if (on_value_changed)
|
||||
on_value_changed(this, m_value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -1005,15 +1032,29 @@ class NodeSliderH : public NodeBorder
|
||||
{
|
||||
public:
|
||||
NodeSliderCursor* m_cursor;
|
||||
std::function<void(Node* target, float value)> on_value_changed;
|
||||
virtual Node* clone_instantiate() const override { return new NodeSliderH(); }
|
||||
virtual void clone_finalize(Node* dest) const override
|
||||
{
|
||||
NodeSliderH* n = static_cast<NodeSliderH*>(dest);
|
||||
n->init_controls();
|
||||
}
|
||||
virtual void init() override
|
||||
{
|
||||
const auto& m_template = (NodeBorder*)init_template("tpl-slider-h");
|
||||
m_color = m_template->m_color;
|
||||
m_border_color = m_template->m_border_color;
|
||||
m_thinkness = m_thinkness;
|
||||
m_thinkness = m_template->m_thinkness;
|
||||
init_controls();
|
||||
}
|
||||
void init_controls()
|
||||
{
|
||||
m_cursor = find<NodeSliderCursor>("cursor");
|
||||
m_cursor->m_mask = { 1, 0 };
|
||||
m_cursor->on_value_changed = [this](Node*, glm::vec2 value) {
|
||||
if (on_value_changed)
|
||||
on_value_changed(this, value.x);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1021,15 +1062,29 @@ class NodeSliderV : public NodeBorder
|
||||
{
|
||||
public:
|
||||
NodeSliderCursor* m_cursor;
|
||||
std::function<void(Node* target, float value)> on_value_changed;
|
||||
virtual Node* clone_instantiate() const override { return new NodeSliderV(); }
|
||||
virtual void clone_finalize(Node* dest) const override
|
||||
{
|
||||
NodeSliderV* n = static_cast<NodeSliderV*>(dest);
|
||||
n->init_controls();
|
||||
}
|
||||
virtual void init() override
|
||||
{
|
||||
const auto& m_template = (NodeBorder*)init_template("tpl-slider-v");
|
||||
m_color = m_template->m_color;
|
||||
m_border_color = m_template->m_border_color;
|
||||
m_thinkness = m_thinkness;
|
||||
m_thinkness = m_template->m_thinkness;
|
||||
init_controls();
|
||||
}
|
||||
void init_controls()
|
||||
{
|
||||
m_cursor = find<NodeSliderCursor>("cursor");
|
||||
m_cursor->m_mask = { 0, 1 };
|
||||
m_cursor->on_value_changed = [this](Node*, glm::vec2 value) {
|
||||
if (on_value_changed)
|
||||
on_value_changed(this, value.y);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1037,25 +1092,34 @@ class NodeSliderHue : public NodeBorder
|
||||
{
|
||||
public:
|
||||
NodeSliderCursor* m_cursor;
|
||||
glm::vec4 m_color;
|
||||
std::function<void(Node* target, glm::vec4 color)> on_value_changed;
|
||||
virtual Node* clone_instantiate() const override { return new NodeSliderHue(); }
|
||||
virtual void clone_finalize(Node* dest) const override
|
||||
{
|
||||
NodeSliderHue* n = static_cast<NodeSliderHue*>(dest);
|
||||
n->m_cursor = n->find<NodeSliderCursor>("cursor");
|
||||
n->m_cursor->m_color = glm::vec4(0);
|
||||
n->m_cursor->m_border_color = glm::vec4(0, 0, 0, 1);
|
||||
n->init_controls();
|
||||
}
|
||||
virtual void init() override
|
||||
{
|
||||
const auto& m_template = (NodeBorder*)init_template("tpl-slider-hue");
|
||||
m_color = m_template->m_color;
|
||||
m_border_color = m_template->m_border_color;
|
||||
m_thinkness = m_thinkness;
|
||||
m_thinkness = m_template->m_thinkness;
|
||||
init_controls();
|
||||
}
|
||||
void init_controls()
|
||||
{
|
||||
m_cursor = find<NodeSliderCursor>("cursor");
|
||||
m_cursor->m_mask = { 0, 1 };
|
||||
m_cursor->m_thinkness = 1;
|
||||
m_cursor->m_color = glm::vec4(0);
|
||||
m_cursor->m_border_color = glm::vec4(0, 0, 0, 1);
|
||||
m_cursor->on_value_changed = [this](Node*, glm::vec2 value) {
|
||||
m_color = glm::vec4(convert_hsv2rgb({ value.y, 1, 1 }), 1);
|
||||
if (on_value_changed)
|
||||
on_value_changed(this, m_color);
|
||||
};
|
||||
}
|
||||
virtual void draw() override
|
||||
{
|
||||
@@ -1214,7 +1278,7 @@ public:
|
||||
virtual void draw() override
|
||||
{
|
||||
auto c = m_selected ? m_color_selected : m_color_normal;
|
||||
m_thinkness = m_selected ? 1 : 0;
|
||||
m_thinkness = m_selected ? 1.f : 0.f;
|
||||
m_color = m_mouse_inside ? m_color_hover : c;
|
||||
NodeBorder::draw();
|
||||
}
|
||||
@@ -1225,7 +1289,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class NodePanelLayers : public Node
|
||||
class NodePanelLayer : public Node
|
||||
{
|
||||
NodeButtonCustom* btn_add;
|
||||
NodeButtonCustom* btn_remove;
|
||||
@@ -1239,7 +1303,7 @@ public:
|
||||
NodeLayer* m_current_layer = nullptr;
|
||||
std::vector<NodeLayer*> m_layers;
|
||||
NodeBorder* m_layers_container;
|
||||
virtual Node* clone_instantiate() const override { return new NodePanelLayers(); }
|
||||
virtual Node* clone_instantiate() const override { return new NodePanelLayer(); }
|
||||
virtual void init() override
|
||||
{
|
||||
init_template("tpl-panel-layers");
|
||||
@@ -1283,7 +1347,7 @@ public:
|
||||
l->create();
|
||||
l->loaded();
|
||||
l->set_name(name);
|
||||
l->on_selected = std::bind(&NodePanelLayers::handle_layer_selected, this, std::placeholders::_1);
|
||||
l->on_selected = std::bind(&NodePanelLayer::handle_layer_selected, this, std::placeholders::_1);
|
||||
m_layers.push_back(l);
|
||||
if (on_layer_add)
|
||||
on_layer_add(this);
|
||||
@@ -1294,11 +1358,11 @@ public:
|
||||
auto i = m_layers_container->get_child_index(m_current_layer);
|
||||
m_layers_container->remove_child(m_current_layer);
|
||||
m_layers.erase(it);
|
||||
i = std::min<int>(i, m_layers.size() - 1);
|
||||
i = std::min<int>(i, (int)m_layers.size() - 1);
|
||||
m_current_layer = m_layers[i];
|
||||
m_current_layer->m_selected = true;
|
||||
if (on_layer_delete)
|
||||
on_layer_delete(this, std::distance(m_layers.begin(), it));
|
||||
on_layer_delete(this, (int)std::distance(m_layers.begin(), it));
|
||||
if (on_layer_change)
|
||||
on_layer_change(this, -1, i);
|
||||
}
|
||||
@@ -1342,14 +1406,14 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class NodePanelBrushes : public Node
|
||||
class NodePanelBrush : public Node
|
||||
{
|
||||
std::vector<NodeButtonBrush*> m_brushes;
|
||||
NodeButtonBrush* m_current = nullptr;
|
||||
Node* m_container;
|
||||
public:
|
||||
std::function<void(Node* target, int id)> on_brush_changed;
|
||||
virtual Node* clone_instantiate() const override { return new NodePanelLayers(); }
|
||||
virtual Node* clone_instantiate() const override { return new NodePanelLayer(); }
|
||||
virtual void init() override
|
||||
{
|
||||
init_template("tpl-panel-brushes");
|
||||
@@ -1369,7 +1433,7 @@ public:
|
||||
brush->set_icon(path.c_str());
|
||||
brush->m_brushID = count++;
|
||||
m_brushes.push_back(brush);
|
||||
brush->on_click = std::bind(&NodePanelBrushes::handle_click, this, std::placeholders::_1);
|
||||
brush->on_click = std::bind(&NodePanelBrush::handle_click, this, std::placeholders::_1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1402,32 +1466,307 @@ public:
|
||||
}
|
||||
return names;
|
||||
}
|
||||
uint16_t get_texture_id(int index) const
|
||||
{
|
||||
return m_brushes[index]->img->m_tex_id;
|
||||
}
|
||||
};
|
||||
|
||||
class NodeColorQuad : public NodeBorder
|
||||
{
|
||||
NodeBorder* m_picker;
|
||||
bool dragging = false;
|
||||
public:
|
||||
glm::vec2 m_value;
|
||||
std::function<void(Node* target, glm::vec2 value)> on_value_changed;
|
||||
virtual Node* clone_instantiate() const override { return new NodeColorQuad(); }
|
||||
virtual void clone_finalize(Node* dest) const override
|
||||
{
|
||||
auto n = (NodeColorQuad*)dest;
|
||||
n->m_picker = (NodeBorder*)n->m_children[0].get();
|
||||
}
|
||||
virtual void init() override
|
||||
{
|
||||
m_picker = new NodeBorder;
|
||||
m_picker->SetSize({ 20, 20 });
|
||||
m_picker->SetPositioning(YGPositionTypeAbsolute);
|
||||
m_picker->SetPosition(0, 0);
|
||||
m_picker->m_thinkness = 1;
|
||||
m_picker->m_color = glm::vec4(0);
|
||||
add_child(m_picker);
|
||||
}
|
||||
virtual kEventResult handle_event(Event* e) override
|
||||
{
|
||||
NodeBorder::handle_event(e);
|
||||
switch (e->m_type)
|
||||
{
|
||||
case kEventType::MouseDownL:
|
||||
{
|
||||
dragging = true;
|
||||
mouse_capture();
|
||||
auto sz = GetSize();
|
||||
auto pos = glm::clamp(((MouseEvent*)e)->m_pos - m_pos, { 0, 0 }, sz) - m_picker->GetSize() * .5f;
|
||||
m_picker->SetPosition(pos.x, pos.y);
|
||||
m_value = pos / glm::max({ 1,1 }, sz); // avoid div0
|
||||
if (on_value_changed)
|
||||
on_value_changed(this, m_value);
|
||||
}
|
||||
break;
|
||||
case kEventType::MouseUpL:
|
||||
mouse_release();
|
||||
dragging = false;
|
||||
break;
|
||||
case kEventType::MouseMove:
|
||||
if (dragging)
|
||||
{
|
||||
auto sz = GetSize();
|
||||
auto pos = glm::clamp(((MouseEvent*)e)->m_pos - m_pos, { 0, 0 }, sz) - m_picker->GetSize() * .5f;
|
||||
m_picker->SetPosition(pos.x, pos.y);
|
||||
m_value = pos / glm::max({ 1,1 }, sz); // avoid div0
|
||||
if (on_value_changed)
|
||||
on_value_changed(this, m_value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return kEventResult::Consumed;
|
||||
}
|
||||
virtual void draw() override
|
||||
{
|
||||
m_picker->m_border_color = m_value.y > .5f ? glm::vec4(1) : glm::vec4(0, 0, 0, 1);
|
||||
using namespace ui;
|
||||
ui::ShaderManager::use(kShader::ColorQuad);
|
||||
ui::ShaderManager::u_mat4(kShaderUniform::MVP, m_mvp);
|
||||
|
||||
// if (m_color.a != 1.f)
|
||||
// glEnable(GL_BLEND);
|
||||
|
||||
ui::ShaderManager::u_vec4(kShaderUniform::Col, m_color);
|
||||
m_plane.draw_fill();
|
||||
|
||||
// if (m_thinkness > 0)
|
||||
// {
|
||||
// glLineWidth(m_thinkness);
|
||||
// ui::ShaderManager::u_vec4(kShaderUniform::Col, m_border_color);
|
||||
// m_plane.draw_stroke();
|
||||
// }
|
||||
|
||||
// if (m_color.a != 1.f)
|
||||
// glDisable(GL_BLEND);
|
||||
}
|
||||
};
|
||||
|
||||
class NodePanelColor : public Node
|
||||
{
|
||||
public:
|
||||
NodeColorQuad* m_quad;
|
||||
NodeSliderHue* m_hue;
|
||||
glm::vec4 m_color;
|
||||
std::function<void(Node* target, glm::vec4 color)> on_color_changed;
|
||||
virtual Node* clone_instantiate() const override { return new NodePanelColor(); }
|
||||
virtual void clone_finalize(Node* dest) const override
|
||||
{
|
||||
NodePanelColor* n = static_cast<NodePanelColor*>(dest);
|
||||
n->init_controls();
|
||||
}
|
||||
virtual void init() override
|
||||
{
|
||||
const auto& m_template = (Node*)init_template("tpl-panel-color");
|
||||
init_controls();
|
||||
}
|
||||
void init_controls()
|
||||
{
|
||||
m_quad = find<NodeColorQuad>("quad");
|
||||
m_hue = find<NodeSliderHue>("hue");
|
||||
m_hue->on_value_changed = [this](Node*, glm::vec4 color) {
|
||||
m_color = m_quad->m_color = color;
|
||||
if (on_color_changed)
|
||||
on_color_changed(this, color);
|
||||
};
|
||||
m_quad->on_value_changed = [this](Node*, glm::vec2 pos)
|
||||
{
|
||||
auto x = glm::mix(m_color, glm::vec4(1, 1, 1, 1), pos.x);
|
||||
auto color = glm::mix(x, glm::vec4(0, 0, 0, 1), pos.y);
|
||||
if (on_color_changed)
|
||||
on_color_changed(this, color);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
class NodeCanvas2D : public NodeBorder
|
||||
{
|
||||
RTT m_rtt;
|
||||
Sampler m_sampler;
|
||||
static ui::Shader m_shader;
|
||||
public:
|
||||
uint16_t m_tex_id;
|
||||
glm::vec4 m_tip_color;
|
||||
float m_tip_size;
|
||||
float m_tip_spacing;
|
||||
float m_tip_flow;
|
||||
float m_tip_angle;
|
||||
float m_jitter_scale;
|
||||
float m_jitter_angle;
|
||||
float m_jitter_spread;
|
||||
float m_jitter_flow;
|
||||
static void static_init()
|
||||
{
|
||||
static const char* shader_v =
|
||||
SHADER_VERSION
|
||||
"uniform mat4 mvp;"
|
||||
"in vec4 pos;"
|
||||
"in vec2 uvs;"
|
||||
"out vec3 uv;"
|
||||
"void main(){"
|
||||
" uv = vec3(uvs, pos.w);"
|
||||
" gl_Position = mvp * vec4(pos.xyz, 1.f);"
|
||||
"}";
|
||||
static const char* shader_f =
|
||||
SHADER_VERSION
|
||||
"uniform sampler2D tex;"
|
||||
"uniform vec4 col;"
|
||||
"uniform float alpha;"
|
||||
"in vec3 uv;"
|
||||
"out vec4 frag;"
|
||||
"void main(){"
|
||||
" float a = (1 - texture(tex, uv.xy).r) * alpha;"
|
||||
" frag = vec4(col.rgb, a);"
|
||||
"}";
|
||||
m_shader.create(shader_v, shader_f);
|
||||
}
|
||||
virtual Node* clone_instantiate() const override { return new NodeCanvas2D(); }
|
||||
virtual void clone_copy(Node* dest) const override
|
||||
{
|
||||
NodeBorder::clone_copy(dest);
|
||||
}
|
||||
virtual void clone_children(Node* dest) const override
|
||||
{
|
||||
// stop children cloning
|
||||
}
|
||||
virtual void clone_finalize(Node* dest) const override
|
||||
{
|
||||
NodeCanvas2D* n = (NodeCanvas2D*)dest;
|
||||
n->init_controls();
|
||||
}
|
||||
void init_controls()
|
||||
{
|
||||
m_sampler.create();
|
||||
TextureManager::load("data/Icons/Round-Hard.png");
|
||||
m_tex_id = const_hash("data/Icons/Round-Hard.png");
|
||||
}
|
||||
void draw_stroke()
|
||||
{
|
||||
m_rtt.bindFramebuffer();
|
||||
{
|
||||
using namespace ui;
|
||||
GLint vp[4];
|
||||
GLfloat cc[4];
|
||||
glGetIntegerv(GL_VIEWPORT, vp);
|
||||
glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
|
||||
|
||||
double w = (double)m_rtt.getWidth();
|
||||
double h = (double)m_rtt.getHeight();
|
||||
std::vector<glm::vec2> kp = { {30, 30}, {30, h-30}, {w-30, 30}, { w-30, h-30 } };
|
||||
|
||||
glClearColor(1, 1, 1, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glViewport(0, 0, m_rtt.getWidth(), m_rtt.getHeight());
|
||||
glEnable(GL_BLEND);
|
||||
glm::mat4 proj = glm::ortho<float>(0, (float)m_rtt.getWidth(), 0, (float)m_rtt.getHeight(), -1, 1);
|
||||
auto& t = TextureManager::get(m_tex_id);
|
||||
float alpha = 0;
|
||||
|
||||
std::minstd_rand prng;
|
||||
m_shader.use();
|
||||
m_shader.u_vec4(kShaderUniform::Col, m_tip_color);
|
||||
m_shader.u_int(kShaderUniform::Tex, 0);
|
||||
t.bind();
|
||||
m_sampler.bind(0);
|
||||
while (alpha < 1.f)
|
||||
{
|
||||
auto rnd_nor = [&] { return float((double)prng() / (double)prng.max()); }; // normalized [0, +1]
|
||||
auto rnd_neg = [&] { return float((double)prng() / (double)prng.max() * 2.0 - 1.0); }; // normalized [-1, +1]
|
||||
auto rnd_rad = [&] { return float((double)prng() / (double)prng.max() * M_PI * 2.0); }; // normalized [0, 2pi]
|
||||
auto rnd_vec = [&] { float rad = rnd_rad(); return glm::vec2(cosf(rad), sinf(rad)); }; // normalized direction vector
|
||||
|
||||
float angle = (m_tip_angle + rnd_nor() * m_jitter_angle) * (float)(M_PI * 2.0);
|
||||
glm::vec2 pos = BezierCurve::Bezier2D(kp, alpha) + (rnd_vec() * m_jitter_spread * 100.f);
|
||||
float size = 100.f * m_tip_size * (1.f - rnd_nor() * m_jitter_scale);
|
||||
float flow = m_tip_flow * (1.f - rnd_nor() * m_jitter_flow);
|
||||
|
||||
alpha += glm::max(m_tip_spacing * .2f, .01f);
|
||||
auto mvp = proj *
|
||||
//glm::translate(glm::vec3(i * 40 * m_tip_spacing, m_rtt.getHeight() / 2, 0)) *
|
||||
glm::translate(glm::vec3(pos, 0)) *
|
||||
glm::scale(glm::vec3(size, size, 1)) *
|
||||
glm::eulerAngleZ(angle);
|
||||
m_shader.u_mat4(kShaderUniform::MVP, mvp);
|
||||
m_shader.u_float(kShaderUniform::Alpha, flow);
|
||||
m_plane.draw_fill();
|
||||
}
|
||||
m_sampler.unbind();
|
||||
t.unbind();
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glViewport(vp[0], vp[1], vp[2], vp[3]);
|
||||
glClearColor(cc[0], cc[1], cc[2], cc[3]);
|
||||
}
|
||||
m_rtt.unbindFramebuffer();
|
||||
}
|
||||
virtual void draw() override
|
||||
{
|
||||
using namespace ui;
|
||||
ui::ShaderManager::use(kShader::Texture);
|
||||
ui::ShaderManager::u_mat4(kShaderUniform::MVP, m_mvp);
|
||||
ui::ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||
m_rtt.bindTexture();
|
||||
m_sampler.bind(0);
|
||||
m_plane.draw_fill();
|
||||
m_sampler.unbind();
|
||||
m_rtt.unbindTexture();
|
||||
}
|
||||
virtual void handle_resize(glm::vec2 old_size, glm::vec2 new_size) override
|
||||
{
|
||||
m_rtt.destroy();
|
||||
m_rtt.create((int)new_size.x, (int)new_size.y);
|
||||
draw_stroke();
|
||||
}
|
||||
};
|
||||
|
||||
class NodePanelStroke : public Node
|
||||
{
|
||||
public:
|
||||
NodeCanvas2D* m_canvas;
|
||||
NodeSliderH* m_tip_size;
|
||||
NodeSliderH* m_tip_spacing;
|
||||
NodeSliderH* m_tip_flow;
|
||||
NodeSliderH* m_tip_angle;
|
||||
NodeSliderH* m_jitter_scale;
|
||||
NodeSliderH* m_jitter_angle;
|
||||
NodeSliderH* m_jitter_spread;
|
||||
NodeSliderH* m_jitter_flow;
|
||||
virtual Node* clone_instantiate() const override { return new NodePanelStroke(); }
|
||||
virtual void clone_finalize(Node* dest) const override
|
||||
{
|
||||
NodePanelColor* n = static_cast<NodePanelColor*>(dest);
|
||||
n->init_controls();
|
||||
}
|
||||
virtual void init() override
|
||||
{
|
||||
const auto& m_template = (Node*)init_template("tpl-panel-stroke");
|
||||
init_controls();
|
||||
}
|
||||
void init_controls()
|
||||
{
|
||||
m_canvas = find<NodeCanvas2D>("canvas");
|
||||
|
||||
init_slider(m_tip_size, "tip-size", &NodeCanvas2D::m_tip_size);
|
||||
init_slider(m_tip_spacing, "tip-spacing", &NodeCanvas2D::m_tip_spacing);
|
||||
init_slider(m_tip_flow, "tip-flow", &NodeCanvas2D::m_tip_flow);
|
||||
init_slider(m_tip_angle, "tip-angle", &NodeCanvas2D::m_tip_angle);
|
||||
init_slider(m_jitter_scale, "jitter-scale", &NodeCanvas2D::m_jitter_scale);
|
||||
init_slider(m_jitter_angle, "jitter-angle", &NodeCanvas2D::m_jitter_angle);
|
||||
init_slider(m_jitter_spread, "jitter-spread", &NodeCanvas2D::m_jitter_spread);
|
||||
init_slider(m_jitter_flow, "jitter-flow", &NodeCanvas2D::m_jitter_flow);
|
||||
}
|
||||
void init_slider(NodeSliderH*& slider, const char* id, float NodeCanvas2D::* prop)
|
||||
{
|
||||
slider = find<NodeSliderH>(id);
|
||||
slider->on_value_changed = std::bind(&NodePanelStroke::handle_slide,
|
||||
this, prop, std::placeholders::_1, std::placeholders::_2);
|
||||
}
|
||||
void handle_slide(float NodeCanvas2D::* prop, Node* target, float value)
|
||||
{
|
||||
m_canvas->*prop = value;
|
||||
m_canvas->draw_stroke();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user