diff --git a/PanoPainter/GameViewController.m b/PanoPainter/GameViewController.m
index f43ba23..0278b5c 100644
--- a/PanoPainter/GameViewController.m
+++ b/PanoPainter/GameViewController.m
@@ -35,7 +35,7 @@ NSThread* lock_thread;
lock_count++;
[EAGLContext setCurrentContext:self.context];
GLKView* view = (GLKView*)self.view;
- //[view bindDrawable];
+ [view bindDrawable];
}
- (void)async_unlock
{
@@ -45,7 +45,7 @@ NSThread* lock_thread;
}
- (void)async_swap
{
- [[EAGLContext currentContext] presentRenderbuffer:GL_RENDERBUFFER];
+ [self.context presentRenderbuffer:GL_RENDERBUFFER];
}
- (void)insertText:(NSString *)text
@@ -317,6 +317,7 @@ NSThread* lock_thread;
[gl_lock lock];
if (!(App::I.redraw || App::I.animate))
{
+ [self.context presentRenderbuffer:GL_FRAMEBUFFER];
[gl_lock unlock];
return;
}
@@ -324,7 +325,7 @@ NSThread* lock_thread;
[view bindDrawable];
App::I.clear();
App::I.update(0);
- //[self.context presentRenderbuffer:GL_FRAMEBUFFER];
+ [self.context presentRenderbuffer:GL_FRAMEBUFFER];
[gl_lock unlock];
}
diff --git a/data/layout.xml b/data/layout.xml
index a4ba7f5..3eba331 100644
--- a/data/layout.xml
+++ b/data/layout.xml
@@ -541,7 +541,9 @@
-
+
+
+
diff --git a/engine/app.cpp b/engine/app.cpp
index d58c7f0..65f372c 100644
--- a/engine/app.cpp
+++ b/engine/app.cpp
@@ -147,6 +147,7 @@ void App::async_update()
#if __OSX__
[osx_view async_swap];
#elif __IOS__
+ [ios_view->glview bindDrawable];
[ios_view async_swap];
#elif __ANDROID__
android_async_swap(and_engine);
diff --git a/engine/app_layout.cpp b/engine/app_layout.cpp
index 9d44618..023dd3d 100644
--- a/engine/app_layout.cpp
+++ b/engine/app_layout.cpp
@@ -241,15 +241,21 @@ void App::init_sidebar()
void App::init_toolbar_draw()
{
+ static auto select_button = [] (Node* main, NodeButton* button) {
+ main->find("btn-pen")->set_color(color_button_normal);
+ main->find("btn-erase")->set_color(color_button_normal);
+ main->find("btn-line")->set_color(color_button_normal);
+ main->find("btn-cam")->set_color(color_button_normal);
+ main->find("btn-grid")->set_color(color_button_normal);
+ //main->find("btn-fill")->set_color(color_button_normal);
+ main->find("btn-mask-free")->set_color(color_button_normal);
+ main->find("btn-mask-line")->set_color(color_button_normal);
+ button->set_color(color_button_hlight);
+ };
if (auto* button = layout[main_id]->find("btn-pen"))
{
- button->on_click = [this](Node*) {
- layout[main_id]->find("btn-pen")->set_color(color_button_hlight);
- layout[main_id]->find("btn-erase")->set_color(color_button_normal);
- layout[main_id]->find("btn-line")->set_color(color_button_normal);
- layout[main_id]->find("btn-cam")->set_color(color_button_normal);
- layout[main_id]->find("btn-grid")->set_color(color_button_normal);
- layout[main_id]->find("btn-fill")->set_color(color_button_normal);
+ button->on_click = [this, button](Node*) {
+ select_button(layout[main_id], button);
Canvas::set_mode(Canvas::kCanvasMode::Draw);
};
layout[main_id]->find("btn-pen")->set_color(color_button_hlight);
@@ -273,61 +279,50 @@ void App::init_toolbar_draw()
}
if (auto* button = layout[main_id]->find("btn-erase"))
{
- button->on_click = [this](Node*) {
- layout[main_id]->find("btn-pen")->set_color(color_button_normal);
- layout[main_id]->find("btn-erase")->set_color(color_button_hlight);
- layout[main_id]->find("btn-line")->set_color(color_button_normal);
- layout[main_id]->find("btn-cam")->set_color(color_button_normal);
- layout[main_id]->find("btn-grid")->set_color(color_button_normal);
- layout[main_id]->find("btn-fill")->set_color(color_button_normal);
+ button->on_click = [this, button](Node*) {
+ select_button(layout[main_id], button);
Canvas::set_mode(Canvas::kCanvasMode::Erase);
};
}
if (auto* button = layout[main_id]->find("btn-line"))
{
- button->on_click = [this](Node*) {
- layout[main_id]->find("btn-pen")->set_color(color_button_normal);
- layout[main_id]->find("btn-erase")->set_color(color_button_normal);
- layout[main_id]->find("btn-line")->set_color(color_button_hlight);
- layout[main_id]->find("btn-cam")->set_color(color_button_normal);
- layout[main_id]->find("btn-grid")->set_color(color_button_normal);
- layout[main_id]->find("btn-fill")->set_color(color_button_normal);
+ button->on_click = [this, button](Node*) {
+ select_button(layout[main_id], button);
Canvas::set_mode(Canvas::kCanvasMode::Line);
};
}
if (auto* button = layout[main_id]->find("btn-cam"))
{
- button->on_click = [this](Node*) {
- layout[main_id]->find("btn-pen")->set_color(color_button_normal);
- layout[main_id]->find("btn-erase")->set_color(color_button_normal);
- layout[main_id]->find("btn-line")->set_color(color_button_normal);
- layout[main_id]->find("btn-cam")->set_color(color_button_hlight);
- layout[main_id]->find("btn-grid")->set_color(color_button_normal);
- layout[main_id]->find("btn-fill")->set_color(color_button_normal);
+ button->on_click = [this, button](Node*) {
+ select_button(layout[main_id], button);
Canvas::set_mode(Canvas::kCanvasMode::Camera);
};
}
if (auto* button = layout[main_id]->find("btn-grid"))
{
- button->on_click = [this](Node*) {
- layout[main_id]->find("btn-pen")->set_color(color_button_normal);
- layout[main_id]->find("btn-erase")->set_color(color_button_normal);
- layout[main_id]->find("btn-line")->set_color(color_button_normal);
- layout[main_id]->find("btn-cam")->set_color(color_button_normal);
- layout[main_id]->find("btn-grid")->set_color(color_button_hlight);
- layout[main_id]->find("btn-fill")->set_color(color_button_normal);
+ button->on_click = [this, button](Node*) {
+ select_button(layout[main_id], button);
Canvas::set_mode(Canvas::kCanvasMode::Grid);
};
}
if (auto* button = layout[main_id]->find("btn-fill"))
{
- button->on_click = [this](Node*) {
- layout[main_id]->find("btn-pen")->set_color(color_button_normal);
- layout[main_id]->find("btn-erase")->set_color(color_button_normal);
- layout[main_id]->find("btn-line")->set_color(color_button_normal);
- layout[main_id]->find("btn-cam")->set_color(color_button_normal);
- layout[main_id]->find("btn-grid")->set_color(color_button_normal);
- layout[main_id]->find("btn-fill")->set_color(color_button_hlight);
+ button->on_click = [this, button](Node*) {
+ select_button(layout[main_id], button);
+ Canvas::set_mode(Canvas::kCanvasMode::Fill);
+ };
+ }
+ if (auto* button = layout[main_id]->find("btn-mask-free"))
+ {
+ button->on_click = [this, button](Node*) {
+ select_button(layout[main_id], button);
+ Canvas::set_mode(Canvas::kCanvasMode::MaskFree);
+ };
+ }
+ if (auto* button = layout[main_id]->find("btn-mask-line"))
+ {
+ button->on_click = [this, button](Node*) {
+ select_button(layout[main_id], button);
Canvas::set_mode(Canvas::kCanvasMode::Fill);
};
}
diff --git a/engine/canvas.cpp b/engine/canvas.cpp
index e3c6e1c..883b2d1 100644
--- a/engine/canvas.cpp
+++ b/engine/canvas.cpp
@@ -19,6 +19,8 @@ std::vector ui::Canvas::modes[] = {
{ new CanvasModeCamera, new CanvasModeBasicCamera },
{ new CanvasModeGrid, new CanvasModeBasicCamera },
{ new CanvasModeFill, new CanvasModeBasicCamera },
+ { new CanvasModeMaskFree, new CanvasModeBasicCamera },
+ { new CanvasModeMaskFree, new CanvasModeBasicCamera },
};
glm::vec3 ui::Canvas::m_plane_origin[6] = {
{ 0, 0,-1}, // front
diff --git a/engine/canvas.h b/engine/canvas.h
index f7aa6e1..859013c 100644
--- a/engine/canvas.h
+++ b/engine/canvas.h
@@ -86,7 +86,7 @@ public:
glm::vec3 m_cam_pos;
float m_cam_fov = 85;
- enum class kCanvasMode { Draw, Erase, Line, Camera, Grid, Fill, COUNT };
+ enum class kCanvasMode { Draw, Erase, Line, Camera, Grid, Fill, MaskFree, MaskLine, COUNT };
kCanvasMode m_state{ kCanvasMode::Draw };
static std::vector modes[];
std::vector* m_mode = nullptr;
diff --git a/engine/canvas_modes.cpp b/engine/canvas_modes.cpp
index 1e97b08..1802bc0 100644
--- a/engine/canvas_modes.cpp
+++ b/engine/canvas_modes.cpp
@@ -367,45 +367,19 @@ void CanvasModeGrid::clear()
////////////////////////////////////////////////////////////////////
-void CanvasModeFill::init()
+void CanvasModeMaskFree::init()
{
m_shape.create();
}
-void CanvasModeFill::leave()
+void CanvasModeMaskFree::leave()
{
// canvas->draw_objects(std::bind(&CanvasModeFill::on_Draw, this, glm::mat4(), std::placeholders::_1, std::placeholders::_2));
// m_points.clear();
}
-// Returns 1 if the lines intersect, otherwise 0. In addition, if the lines
-// intersect the intersection point may be stored in the floats i_x and i_y.
-char get_line_intersection(float p0_x, float p0_y, float p1_x, float p1_y,
- float p2_x, float p2_y, float p3_x, float p3_y, float *i_x, float *i_y)
-{
- float s1_x, s1_y, s2_x, s2_y;
- s1_x = p1_x - p0_x; s1_y = p1_y - p0_y;
- s2_x = p3_x - p2_x; s2_y = p3_y - p2_y;
-
- float s, t;
- s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y);
- t = (s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y);
-
- if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
- {
- // Collision detected
- if (i_x != NULL)
- *i_x = p0_x + (t * s1_x);
- if (i_y != NULL)
- *i_y = p0_y + (t * s1_y);
- return 1;
- }
-
- return 0; // No collision
-}
-
int SegmentCount = 0;
-std::vector CanvasModeFill::triangulate(const std::vector>& points)
+std::vector CanvasModeMaskFree::triangulate(const std::vector>& points)
{
struct Segment
{
@@ -543,39 +517,13 @@ std::vector CanvasModeFill::triangulate(const std::vectorm_type)
{
- case kEventType::MouseDownR:
- {
- /*
- if (!m_points.empty())
- {
- auto drawer = [this](const glm::mat4& camera, const glm::mat4& proj) {
- ui::ShaderManager::use(ui::kShader::Color);
- ui::ShaderManager::u_mat4(ui::kShaderUniform::MVP, proj * camera);
- ui::ShaderManager::u_vec4(ui::kShaderUniform::Col, { node->m_brush.m_tip_color.rgb(), node->m_brush.m_tip_opacity });
- m_shape.draw_fill();
- };
- std::vector planes;
- for (auto p : m_dirty_planes)
- {
- planes.push_back(p.first);
- canvas->m_dirty_face[p.first] = true;
- canvas->m_dirty_box[p.first] = { 0, 0, canvas->m_width, canvas->m_height };
- }
- canvas->snap_history(planes);
- canvas->draw_objects(std::bind(drawer, std::placeholders::_1, std::placeholders::_2));
- m_points.clear();
- m_dirty_planes.clear();
- }
- */
- break;
- }
case kEventType::MouseDownL:
{
node->mouse_capture();
@@ -618,17 +566,8 @@ void CanvasModeFill::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
ui::ShaderManager::u_vec4(ui::kShaderUniform::Col, {1, 1, 1, 1});
m_shape.draw_fill();
};
- std::vector planes;
- for (auto p : m_dirty_planes)
- {
- planes.push_back(p.first);
- canvas->m_dirty_face[p.first] = true;
- canvas->m_dirty_box[p.first] = { 0, 0, canvas->m_width, canvas->m_height };
- }
- canvas->snap_history(planes);
canvas->draw_objects(std::bind(drawer, std::placeholders::_1, std::placeholders::_2), canvas->m_smask);
m_points.clear();
- m_dirty_planes.clear();
}
}
else
@@ -667,35 +606,116 @@ void CanvasModeFill::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
}
}
break;
-/*
-glm::vec3 ro, rd, hit_o, hit_d;
-glm::vec2 hit_fb;
-int plane_id;
-if (canvas->point_trace_plane(loc, ro, rd, hit_o, hit_d, hit_fb, 0))
+ }
+ case kEventType::MouseCancel:
+ if (m_dragging)
+ {
+ m_points.pop_back();
+ m_shape.update_vertices(m_points.data(), (int)m_points.size());
+ }
+ m_dragging = false;
+ node->mouse_release();
+ if (m_points.size() < 4)
+ {
+ m_points.clear();
+ m_shape.update_vertices(m_points.data(), (int)m_points.size());
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void CanvasModeMaskFree::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const glm::mat4& camera)
{
- m_dirty_planes[plane_id]++;
- ui::Shape::vertex_t v;
- v.pos = glm::vec4(hit_o, 1);
- v.uvs = glm::vec2(0);
- if (m_points.size() < 3)
+ if (!m_points.empty())
{
- m_points.push_back(v);
+ ui::ShaderManager::use(ui::kShader::Color);
+ ui::ShaderManager::u_mat4(ui::kShaderUniform::MVP, glm::scale(glm::vec3(1,-1,1)) * ortho);
+ ui::ShaderManager::u_vec4(ui::kShaderUniform::Col, { 0, 0, 0, 1 });
+ m_dragging ? m_shape.draw_stroke() : m_shape.draw_fill();
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////
+
+void CanvasModeFill::init()
+{
+ m_shape.create();
+}
+
+void CanvasModeFill::leave()
+{
+ if (m_points.size() > 2)
+ {
+ auto drawer = [this](const glm::mat4& camera, const glm::mat4& proj) {
+ ui::ShaderManager::use(ui::kShader::Color);
+ ui::ShaderManager::u_mat4(ui::kShaderUniform::MVP, proj * camera);
+ ui::ShaderManager::u_vec4(ui::kShaderUniform::Col, {1, 1, 1, 1});
+ m_shape.draw_fill();
+ };
+ canvas->draw_objects(std::bind(drawer, std::placeholders::_1, std::placeholders::_2), canvas->m_smask);
+ m_points.clear();
+ canvas->m_smask_active = true;
}
else
{
- auto last = m_points.back();
- m_points.push_back(m_points[0]);
- m_points.push_back(last);
- m_points.push_back(v);
- float isx, isy;
- if (get_line_intersection(m_points[0].pos.x, m_points[0].pos.y, v.pos.x, v.pos.y, 1, -1, 1, 1, &isx, &isy))
- {
- LOG("intersection in %f %f", isx, isy);
- }
+ canvas->m_smask_active = false;
}
- m_shape.update_vertices(m_points.data(), m_points.size());
}
-*/
+
+void CanvasModeFill::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
+{
+ switch (me->m_type)
+ {
+ case kEventType::MouseDownL:
+ {
+ node->mouse_capture();
+ m_dragging = true;
+ glm::vec3 ro, rd, hit_o, hit_d;
+ glm::vec2 hit_fb;
+ int plane_id;
+ if (canvas->point_trace_plane(loc, ro, rd, hit_o, hit_d, hit_fb, 0))
+ {
+ m_dirty_planes[plane_id]++;
+ ui::Shape::vertex_t v;
+ v.pos = glm::vec4(hit_o, 1);
+ v.uvs = glm::vec2(0);
+ if (m_points.size() < 3)
+ {
+ m_points.push_back(v);
+ }
+ else
+ {
+ auto last = m_points.back();
+ m_points.push_back(m_points[0]);
+ m_points.push_back(last);
+ m_points.push_back(v);
+ }
+ m_shape.update_vertices(m_points.data(), (int)m_points.size());
+ }
+ canvas->m_smask.clear({0, 0, 0, 0});
+ break;
+ }
+ case kEventType::MouseUpL:
+ node->mouse_release();
+ m_dragging = false;
+ break;
+ case kEventType::MouseMove:
+ {
+ glm::vec3 ro, rd, hit_o, hit_d;
+ glm::vec2 fb_pos;
+ int plane_id;
+ if (m_dragging && canvas->point_trace(loc, ro, rd, hit_o, fb_pos, hit_d, plane_id))
+ {
+ ui::Shape::vertex_t v;
+ v.pos = glm::vec4(hit_o, 1);
+ v.uvs = glm::vec2(0);
+ m_points.back() = v;
+ m_shape.update_vertices(m_points.data(), (int)m_points.size());
+ }
+ break;
}
case kEventType::MouseCancel:
if (m_dragging)
@@ -721,8 +741,8 @@ void CanvasModeFill::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, cons
if (!m_points.empty())
{
ui::ShaderManager::use(ui::kShader::Color);
- ui::ShaderManager::u_mat4(ui::kShaderUniform::MVP, glm::scale(glm::vec3(1,-1,1)) * ortho);
- ui::ShaderManager::u_vec4(ui::kShaderUniform::Col, { 0, 0, 0, 1 });
- m_dragging ? m_shape.draw_stroke() : m_shape.draw_fill();
+ ui::ShaderManager::u_mat4(ui::kShaderUniform::MVP, proj * camera);
+ ui::ShaderManager::u_vec4(ui::kShaderUniform::Col, { 0, 0, 0, .25 });
+ m_shape.draw_fill();
}
}
diff --git a/engine/canvas_modes.h b/engine/canvas_modes.h
index 6f830d5..a9107e0 100644
--- a/engine/canvas_modes.h
+++ b/engine/canvas_modes.h
@@ -92,6 +92,19 @@ public:
};
class CanvasModeFill : public CanvasMode
+{
+ ui::DynamicShape m_shape;
+ bool m_dragging = false;
+ std::vector m_points;
+ std::map m_dirty_planes;
+public:
+ virtual void on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const glm::mat4& camera) override;
+ virtual void on_MouseEvent(MouseEvent* me, glm::vec2& loc) override;
+ virtual void init() override;
+ virtual void leave() override;
+};
+
+class CanvasModeMaskFree : public CanvasMode
{
ui::DynamicShape m_shape;
bool m_dragging = false;
diff --git a/engine/node_canvas.cpp b/engine/node_canvas.cpp
index 3cb9f1e..4046002 100644
--- a/engine/node_canvas.cpp
+++ b/engine/node_canvas.cpp
@@ -120,6 +120,7 @@ void NodeCanvas::draw()
if (m_canvas->m_state == ui::Canvas::kCanvasMode::Erase && m_canvas->m_show_tmp && m_canvas->m_current_layer_idx == layer_index)
{
+ m_sampler.bind(0);
ui::ShaderManager::use(kShader::CompErase);
ui::ShaderManager::u_int(kShaderUniform::Tex, 0);
ui::ShaderManager::u_int(kShaderUniform::TexStroke, 1);
@@ -143,6 +144,7 @@ void NodeCanvas::draw()
}
else if(m_canvas->m_show_tmp && m_canvas->m_current_layer_idx == layer_index)
{
+ m_sampler.bind(0);
auto& paper = TextureManager::get(const_hash("data/paper.jpg"));
ui::ShaderManager::use(kShader::CompDraw);
ui::ShaderManager::u_int(kShaderUniform::Tex, 0);
@@ -172,6 +174,7 @@ void NodeCanvas::draw()
}
else
{
+ m_sampler_stencil.bind(0);
ui::ShaderManager::use(kShader::TextureAlpha);
ui::ShaderManager::u_int(kShaderUniform::Tex, 0);
ui::ShaderManager::u_float(kShaderUniform::Alpha, m_canvas->m_layers[layer_index].m_opacity);
@@ -199,6 +202,29 @@ void NodeCanvas::draw()
}
}
+ if (m_canvas->m_smask_active && !m_canvas->m_show_tmp)
+ {
+ glDisable(GL_DEPTH_TEST);
+ glClear(GL_DEPTH_BUFFER_BIT);
+ for (int plane_index = 0; plane_index < 6; plane_index++)
+ {
+ auto plane_mvp = proj * camera *
+// glm::scale(glm::vec3(m_canvas->m_order.size() + 500)) *
+ m_canvas->m_plane_transform[plane_index] *
+ glm::translate(glm::vec3(0, 0, -1));
+
+ ui::ShaderManager::use(kShader::TextureAlpha);
+ ui::ShaderManager::u_int(kShaderUniform::Tex, 0);
+ ui::ShaderManager::u_float(kShaderUniform::Alpha, 0.5f);
+ ui::ShaderManager::u_int(kShaderUniform::Highlight, 0);
+ ui::ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp);
+ glActiveTexture(GL_TEXTURE0);
+ m_canvas->m_smask.m_rtt[plane_index].bindTexture();
+ m_face_plane.draw_fill();
+ m_canvas->m_smask.m_rtt[plane_index].unbindTexture();
+ }
+ }
+
for (auto& mode : *m_canvas->m_mode)
mode->on_Draw(ortho_proj, proj, camera);