diff --git a/data/layout.xml b/data/layout.xml
index 752776f..da3c70e 100644
--- a/data/layout.xml
+++ b/data/layout.xml
@@ -106,7 +106,7 @@
-
+
@@ -394,7 +394,7 @@
-
+
diff --git a/engine.vcxproj b/engine.vcxproj
index 89993c9..be2ed74 100644
--- a/engine.vcxproj
+++ b/engine.vcxproj
@@ -153,6 +153,7 @@
+
@@ -191,6 +192,7 @@
+
@@ -203,6 +205,7 @@
+
diff --git a/engine.vcxproj.filters b/engine.vcxproj.filters
index 20f7b40..8464ef6 100644
--- a/engine.vcxproj.filters
+++ b/engine.vcxproj.filters
@@ -63,6 +63,9 @@
Source Files
+
+ Source Files
+
@@ -101,8 +104,12 @@
Header Files
+
+ Header Files
+
+
\ No newline at end of file
diff --git a/engine/canvas.cpp b/engine/canvas.cpp
new file mode 100644
index 0000000..8f50fbd
--- /dev/null
+++ b/engine/canvas.cpp
@@ -0,0 +1,5 @@
+#include "pch.h"
+#include "canvas.h"
+
+
+
diff --git a/engine/canvas.h b/engine/canvas.h
new file mode 100644
index 0000000..89d3f8a
--- /dev/null
+++ b/engine/canvas.h
@@ -0,0 +1,147 @@
+#pragma once
+#include "rtt.h"
+#include "texture.h"
+#include "shader.h"
+#include "shape.h"
+
+NS_START
+
+class Brush
+{
+public:
+ std::string m_name;
+ int id;
+ uint16_t m_texture_id;
+};
+
+class Stroke
+{
+public:
+ struct Keypoint
+ {
+ glm::vec2 pos;
+ float pressure;
+ };
+ int m_layer;
+ float m_dist;
+ std::shared_ptr m_brush;
+ std::vector m_keypoints;
+ void add_point(glm::vec2 pos, float pressure)
+ {
+ m_keypoints.emplace_back();
+ m_keypoints.back().pos = pos;
+ m_keypoints.back().pressure = pressure;
+ }
+};
+
+class Layer
+{
+public:
+ RTT m_rtt;
+ bool m_visible = true;
+ bool m_locked = false;
+ float m_alpha = 1.f;
+ std::string m_name;
+ bool create(int width, int height, std::string name)
+ {
+ m_rtt.create(width, height);
+ return true;
+ }
+};
+
+class Canvas
+{
+public:
+ int m_width;
+ int m_height;
+ std::vector m_layers;
+ std::vector m_strokes;
+ std::unique_ptr m_tmp;
+ Stroke* m_current_stroke = nullptr;
+ int m_current_layer_idx = 0;
+ RTT m_fb;
+ Sampler m_sampler;
+ Plane m_plane;
+ bool create(int width, int height)
+ {
+ m_width = width;
+ m_height = height;
+ m_tmp = std::make_unique();
+ m_tmp->create(width, height, "tmp");
+ m_fb.create(width, height);
+ m_sampler.create();
+ m_plane.create<1>(1, 1);
+ return true;
+ }
+ void layer_add(std::string name)
+ {
+ m_layers.emplace_back();
+ m_layers.back().create(m_width, m_height, name);
+ }
+ void stroke_start(glm::vec2 point, float pressure, std::shared_ptr brush)
+ {
+ m_strokes.emplace_back();
+ m_strokes.back().m_brush = brush;
+ m_strokes.back().add_point(point, pressure);
+ m_current_stroke = &m_strokes.back();
+ }
+ void stroke_update(glm::vec2 point, float pressure)
+ {
+ m_current_stroke->add_point(point, pressure);
+
+ m_fb.bindFramebuffer();
+
+ GLint vp[4];
+ GLfloat cc[4];
+ glGetIntegerv(GL_VIEWPORT, vp);
+ glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
+
+ glViewport(0, 0, m_width, m_height);
+
+ auto mvp = glm::ortho(0.f, (float)m_width, (float)m_height, 0.f, -1.f, 1.f) *
+ glm::translate(glm::vec3(point, 0)) *
+ glm::scale(glm::vec3(30, 30, 1));
+
+ auto& tex = TextureManager::get(m_current_stroke->m_brush->m_texture_id);
+ tex.bind();
+ m_sampler.bind(0);
+ ui::ShaderManager::use(kShader::Texture);
+ ui::ShaderManager::u_int(kShaderUniform::Tex, 0);
+ ui::ShaderManager::u_mat4(kShaderUniform::MVP, mvp);
+ m_plane.draw_fill();
+ m_sampler.unbind();
+ tex.unbind();
+
+
+ glViewport(vp[0], vp[1], vp[2], vp[3]);
+ glClearColor(cc[0], cc[1], cc[2], cc[3]);
+
+ m_fb.unbindFramebuffer();
+ }
+ void stroke_end()
+ {
+ m_current_stroke = nullptr;
+ }
+ void clear()
+ {
+ m_fb.bindFramebuffer();
+
+ GLint vp[4];
+ GLfloat cc[4];
+ glGetIntegerv(GL_VIEWPORT, vp);
+ glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
+
+ glClearColor(1, 1, 1, 1);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glViewport(0, 0, m_width, m_height);
+
+ //
+
+ glViewport(vp[0], vp[1], vp[2], vp[3]);
+ glClearColor(cc[0], cc[1], cc[2], cc[3]);
+
+ m_fb.unbindFramebuffer();
+ }
+};
+
+NS_END
diff --git a/engine/layout.cpp b/engine/layout.cpp
index 5ba5236..5b80eff 100644
--- a/engine/layout.cpp
+++ b/engine/layout.cpp
@@ -463,7 +463,8 @@ void Node::load_internal(const tinyxml2::XMLElement* x_node)
CASE(kWidget::PanelColor, NodePanelColor);
CASE(kWidget::PanelStroke, NodePanelStroke);
CASE(kWidget::ColorQuad, NodeColorQuad);
- CASE(kWidget::Canvas2D, NodeStrokePreview);
+ CASE(kWidget::StrokePreview, NodeStrokePreview);
+ CASE(kWidget::Canvas, NodeCanvas);
#undef CASE
case kWidget::Ref:
{
diff --git a/engine/layout.h b/engine/layout.h
index 435c587..f362263 100644
--- a/engine/layout.h
+++ b/engine/layout.h
@@ -6,6 +6,7 @@
#include "asset.h"
#include "rtt.h"
#include "bezier.h"
+#include "canvas.h"
#include
#include
@@ -72,7 +73,8 @@ enum class kWidget : uint16_t
PanelColor = const_hash("panel-color"),
PanelStroke = const_hash("panel-stroke"),
ColorQuad = const_hash("color-quad"),
- Canvas2D = const_hash("canvas2D"),
+ StrokePreview = const_hash("stroke-preview"),
+ Canvas = const_hash("canvas"),
};
enum class kShapeType : uint16_t
@@ -733,15 +735,15 @@ public:
key_capture();
break;
case kEventType::KeyDown:
- switch (ke->m_key)
- {
+// switch (ke->m_key)
+// {
// case VK_BACK:
// m_string.erase(m_string.end() - 1);
// m_text->set_text(m_string.c_str());
// break;
- default:
- break;
- }
+// default:
+// break;
+// }
break;
case kEventType::KeyChar:
if (ke->m_key >= 32 && ke->m_key < 32+96)
@@ -1852,4 +1854,83 @@ public:
}
};
+class NodeCanvas : public Node
+{
+ bool m_dragging = false;
+public:
+ std::unique_ptr m_canvas;
+ virtual Node* clone_instantiate() const override { return new NodeCanvas(); }
+ virtual void init() override
+ {
+ m_mouse_ignore = false;
+ m_canvas = std::make_unique();
+ m_canvas->create(512, 512);
+ m_canvas->clear();
+ }
+ virtual void draw() override
+ {
+ using namespace ui;
+ //glm::mat4 cam = glm::lookAt(glm::vec3(sinf(angle) * 10, 0, -10), glm::vec3(0, 0, 0), glm::vec3(0, -1, 0));
+ //glm::mat4 proj = glm::perspective(glm::radians(45.f), m_clip.z / m_clip.w, .1f, 100);
+ GLint vp[4];
+ GLfloat cc[4];
+ glGetIntegerv(GL_VIEWPORT, vp);
+ glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
+
+ glClearColor(1, 0, 0, 1);
+ glClear(GL_COLOR_BUFFER_BIT);
+ auto box = m_clip * root()->m_zoom;
+ 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);
+
+ glm::vec2 sz = { m_canvas->m_width, m_canvas->m_height };
+ auto mvp = glm::ortho(0.f, box.z, box.w, 0.f, -1.f, 1.f) *
+ glm::translate(glm::vec3((m_size - sz) * 0.5f, 0)) *
+ glm::scale(glm::vec3(sz, 1)) *
+ glm::translate(glm::vec3(.5f, .5f, 0.f)); // pivot
+
+ m_canvas->m_fb.bindTexture();
+ m_canvas->m_sampler.bind(0);
+ ui::ShaderManager::use(kShader::Texture);
+ ui::ShaderManager::u_int(kShaderUniform::Tex, 0);
+ ui::ShaderManager::u_mat4(kShaderUniform::MVP, mvp);
+ NodeBorder::m_plane.draw_fill();
+ m_canvas->m_sampler.unbind();
+ m_canvas->m_fb.unbindTexture();
+
+
+ glViewport(vp[0], vp[1], vp[2], vp[3]);
+ glClearColor(cc[0], cc[1], cc[2], cc[3]);
+ }
+ virtual void handle_resize(glm::vec2 old_size, glm::vec2 new_size) override
+ {
+ }
+ virtual kEventResult handle_event(Event* e) override
+ {
+ MouseEvent* me = static_cast(e);
+ Node::handle_event(e);
+ switch (e->m_type)
+ {
+ case kEventType::MouseDownL:
+ {
+ auto b = std::make_shared();
+ b->m_texture_id = const_hash("data/Icons/Round-Brush.png");
+ m_canvas->stroke_start(me->m_pos, 1.f, b);
+ m_dragging = true;
+ break;
+ }
+ case kEventType::MouseUpL:
+ m_canvas->stroke_end();
+ m_dragging = false;
+ break;
+ case kEventType::MouseMove:
+ if (m_dragging)
+ m_canvas->stroke_update(me->m_pos, 1.f);
+ break;
+ default:
+ break;
+ }
+ return kEventResult::Consumed;
+ }
+};
diff --git a/engine/pch.h b/engine/pch.h
index 5aa7235..34ff803 100644
--- a/engine/pch.h
+++ b/engine/pch.h
@@ -33,6 +33,9 @@
#define SHADER_VERSION "#version 150\n"
#endif
+#define NS_START namespace ui {
+#define NS_END }
+
#ifdef __cplusplus
#include