implement pen and erase as strategy pattern introducing the CanvasMode classes

This commit is contained in:
2017-05-04 23:32:02 +01:00
parent 773ff61f92
commit 484bf6fab4
6 changed files with 162 additions and 68 deletions

View File

@@ -445,7 +445,7 @@ void App::initLayout()
}; };
layers->on_layer_change = [this](Node*, int old_idx, int new_idx) { layers->on_layer_change = [this](Node*, int old_idx, int new_idx) {
canvas->m_canvas->m_current_layer_idx = new_idx; canvas->m_canvas->m_current_layer_idx = canvas->m_canvas->m_order[new_idx];
}; };
layers->on_layer_order = [this](Node*, int old_idx, int new_idx) { layers->on_layer_order = [this](Node*, int old_idx, int new_idx) {
@@ -453,7 +453,7 @@ void App::initLayout()
}; };
layers->on_layer_opacity_changed = [this](Node*, int idx, float value) { layers->on_layer_opacity_changed = [this](Node*, int idx, float value) {
canvas->m_canvas->m_layers[idx].m_opacity = value; canvas->m_canvas->m_layers[canvas->m_canvas->m_order[idx]].m_opacity = value;
}; };
layers->on_layer_visibility_changed = [this](Node*, int idx, bool visible) { layers->on_layer_visibility_changed = [this](Node*, int idx, bool visible) {
@@ -472,10 +472,10 @@ void App::initLayout()
layout[main_id]->find<NodeButton>("btn-erase")->set_color(color_button_normal); layout[main_id]->find<NodeButton>("btn-erase")->set_color(color_button_normal);
layout[main_id]->find<NodeButton>("btn-line")->set_color(color_button_normal); layout[main_id]->find<NodeButton>("btn-line")->set_color(color_button_normal);
layout[main_id]->find<NodeButton>("btn-cam")->set_color(color_button_normal); layout[main_id]->find<NodeButton>("btn-cam")->set_color(color_button_normal);
Canvas::I->m_state = Canvas::kPenState::Draw; Canvas::set_mode(Canvas::kCanvasMode::Draw);
}; };
layout[main_id]->find<NodeButton>("btn-pen")->set_color(color_button_hlight); layout[main_id]->find<NodeButton>("btn-pen")->set_color(color_button_hlight);
Canvas::I->m_state = Canvas::kPenState::Draw; Canvas::set_mode(Canvas::kCanvasMode::Draw);
} }
if (auto* button = layout[main_id]->find<NodeButton>("btn-erase")) if (auto* button = layout[main_id]->find<NodeButton>("btn-erase"))
{ {
@@ -484,7 +484,7 @@ void App::initLayout()
layout[main_id]->find<NodeButton>("btn-erase")->set_color(color_button_hlight); layout[main_id]->find<NodeButton>("btn-erase")->set_color(color_button_hlight);
layout[main_id]->find<NodeButton>("btn-line")->set_color(color_button_normal); layout[main_id]->find<NodeButton>("btn-line")->set_color(color_button_normal);
layout[main_id]->find<NodeButton>("btn-cam")->set_color(color_button_normal); layout[main_id]->find<NodeButton>("btn-cam")->set_color(color_button_normal);
Canvas::I->m_state = Canvas::kPenState::Erase; Canvas::set_mode(Canvas::kCanvasMode::Erase);
}; };
} }
if (auto* button = layout[main_id]->find<NodeButton>("btn-line")) if (auto* button = layout[main_id]->find<NodeButton>("btn-line"))
@@ -494,7 +494,7 @@ void App::initLayout()
layout[main_id]->find<NodeButton>("btn-erase")->set_color(color_button_normal); layout[main_id]->find<NodeButton>("btn-erase")->set_color(color_button_normal);
layout[main_id]->find<NodeButton>("btn-line")->set_color(color_button_hlight); layout[main_id]->find<NodeButton>("btn-line")->set_color(color_button_hlight);
layout[main_id]->find<NodeButton>("btn-cam")->set_color(color_button_normal); layout[main_id]->find<NodeButton>("btn-cam")->set_color(color_button_normal);
Canvas::I->m_state = Canvas::kPenState::Line; Canvas::set_mode(Canvas::kCanvasMode::Line);
}; };
} }
if (auto* button = layout[main_id]->find<NodeButton>("btn-cam")) if (auto* button = layout[main_id]->find<NodeButton>("btn-cam"))
@@ -504,7 +504,7 @@ void App::initLayout()
layout[main_id]->find<NodeButton>("btn-erase")->set_color(color_button_normal); layout[main_id]->find<NodeButton>("btn-erase")->set_color(color_button_normal);
layout[main_id]->find<NodeButton>("btn-line")->set_color(color_button_normal); layout[main_id]->find<NodeButton>("btn-line")->set_color(color_button_normal);
layout[main_id]->find<NodeButton>("btn-cam")->set_color(color_button_hlight); layout[main_id]->find<NodeButton>("btn-cam")->set_color(color_button_hlight);
Canvas::I->m_state = Canvas::kPenState::Camera; Canvas::set_mode(Canvas::kCanvasMode::Camera);
}; };
} }
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-bucket")) if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-bucket"))

View File

@@ -3,6 +3,10 @@
#include "canvas.h" #include "canvas.h"
ui::Canvas* ui::Canvas::I; ui::Canvas* ui::Canvas::I;
CanvasMode* ui::Canvas::modes[] = {
new CanvasModePen,
new CanvasModePen,
};
glm::vec3 ui::Canvas::m_plane_origin[6] = { glm::vec3 ui::Canvas::m_plane_origin[6] = {
{ 0, 0,-1}, // front { 0, 0,-1}, // front
{ 1, 0, 0}, // right { 1, 0, 0}, // right
@@ -88,7 +92,7 @@ void ui::Canvas::stroke_draw()
else else
{ {
glDisable(GL_BLEND); glDisable(GL_BLEND);
if (m_state == kPenState::Erase) if (m_state == kCanvasMode::Erase)
{ {
ShaderManager::use(ui::kShader::StrokeErase); ShaderManager::use(ui::kShader::StrokeErase);
//ShaderManager::u_vec4(kShaderUniform::Col, m_brush.m_tip_color); //ShaderManager::u_vec4(kShaderUniform::Col, m_brush.m_tip_color);
@@ -275,7 +279,7 @@ void ui::Canvas::stroke_commit()
m_tex2[i].bind(); m_tex2[i].bind();
m_sampler.bind(0); m_sampler.bind(0);
m_sampler_bg.bind(1); m_sampler_bg.bind(1);
if (m_state == kPenState::Erase) if (m_state == kCanvasMode::Erase)
{ {
ShaderManager::use(ui::kShader::Texture); ShaderManager::use(ui::kShader::Texture);
} }
@@ -324,7 +328,7 @@ void ui::Canvas::stroke_start(glm::vec2 point, float pressure, const ui::Brush&
m_dirty_box[i] = glm::vec4(m_width, m_height, 0, 0); // reset bounding box m_dirty_box[i] = glm::vec4(m_width, m_height, 0, 0); // reset bounding box
m_dirty_face[i] = false; m_dirty_face[i] = false;
if (m_state == kPenState::Erase) if (m_state == kCanvasMode::Erase)
{ {
m_layers[m_current_layer_idx].m_rtt[i].bindFramebuffer(); m_layers[m_current_layer_idx].m_rtt[i].bindFramebuffer();
m_tmp[i].bindTexture(); m_tmp[i].bindTexture();

View File

@@ -5,6 +5,7 @@
#include "shape.h" #include "shape.h"
#include "brush.h" #include "brush.h"
#include "action.h" #include "action.h"
#include "canvas_modes.h"
NS_START NS_START
@@ -66,8 +67,17 @@ public:
Sampler m_sampler_mask; Sampler m_sampler_mask;
glm::vec2 m_cam_rot; glm::vec2 m_cam_rot;
float m_cam_fov = 85; float m_cam_fov = 85;
enum class kPenState { Draw, Erase, Line, Camera };
kPenState m_state{ kPenState::Draw }; enum class kCanvasMode { Draw, Erase, Line, Camera };
kCanvasMode m_state{ kCanvasMode::Draw };
static CanvasMode* modes[];
CanvasMode* m_mode;
static void set_mode(kCanvasMode mode)
{
I->m_mode = modes[(int)mode];
I->m_state = mode;
I->m_mode->canvas = I;
}
GLuint cube_id; GLuint cube_id;
RTT m_latlong; RTT m_latlong;
@@ -96,7 +106,6 @@ public:
void preview_generate(); void preview_generate();
}; };
class ActionStroke : public Action class ActionStroke : public Action
{ {
public: public:

64
engine/canvas_modes.cpp Normal file
View File

@@ -0,0 +1,64 @@
#include "pch.h"
#include "log.h"
#include "canvas_modes.h"
#include "layout.h"
#include "canvas.h"
NodeCanvas* CanvasMode::node;
ui::Canvas* CanvasMode::canvas;
void CanvasModePen::on_MouseDownL(MouseEvent* me, glm::vec2& loc)
{
canvas->stroke_start(loc, 1.f, node->m_brush);
m_dragging = true;
node->mouse_capture();
}
void CanvasModePen::on_MouseUpL(MouseEvent* me, glm::vec2& loc)
{
canvas->stroke_end();
m_dragging = false;
node->mouse_release();
}
void CanvasModePen::on_MouseDownR(MouseEvent* me, glm::vec2& loc)
{
m_draggingR = true;
m_dragR_start = me->m_pos;
m_pan_start = m_pan;
node->mouse_capture();
}
void CanvasModePen::on_MouseUpR(MouseEvent* me, glm::vec2& loc)
{
m_draggingR = false;
node->mouse_release();
}
void CanvasModePen::on_MouseMove(MouseEvent* me, glm::vec2& loc)
{
if (m_dragging)
canvas->stroke_update(loc, 1.f);
if (m_draggingR)
m_pan = m_pan_start + (me->m_pos - m_dragR_start) * glm::vec2(-1, -1);
m_cur = loc;
canvas->m_cam_rot = m_pan * 0.003f;
}
void CanvasModePen::on_MouseScroll(MouseEvent* me, glm::vec2& loc)
{
m_zoom_canvas += me->m_scroll_delta * 0.1f;
canvas->m_cam_fov -= me->m_scroll_delta * 20.1f;
}
void CanvasModePen::on_MouseCancel(MouseEvent* me, glm::vec2& loc)
{
m_dragging = false;
node->mouse_release();
}
void CanvasModePen::on_GestureStart(GestureEvent* ge)
{
m_pan_start = m_pan;
m_zoom_start = m_zoom_canvas;
m_camera_fov = canvas->m_cam_fov;
}
void CanvasModePen::on_GestureMove(GestureEvent* ge)
{
m_pan = m_pan_start + ge->m_pos_delta * glm::vec2(-1, -1) * 0.3f;
canvas->m_cam_fov = m_camera_fov - ge->m_distance_delta * .05f;
canvas->m_cam_rot = m_pan * 0.003f;
}

47
engine/canvas_modes.h Normal file
View File

@@ -0,0 +1,47 @@
#pragma once
#include "event.h"
NS_START
class Canvas;
NS_END
class CanvasMode
{
public:
static class NodeCanvas* node;
static ui::Canvas* canvas;
virtual void on_MouseDownL(MouseEvent* me, glm::vec2& loc) {}
virtual void on_MouseUpL(MouseEvent* me, glm::vec2& loc) {}
virtual void on_MouseDownR(MouseEvent* me, glm::vec2& loc) {}
virtual void on_MouseUpR(MouseEvent* me, glm::vec2& loc) {}
virtual void on_MouseMove(MouseEvent* me, glm::vec2& loc) {}
virtual void on_MouseScroll(MouseEvent* me, glm::vec2& loc) {}
virtual void on_MouseCancel(MouseEvent* me, glm::vec2& loc) {}
virtual void on_KeyDown(KeyEvent* ke) {}
virtual void on_KeyUp(KeyEvent* ke) {}
virtual void on_GestureStart(GestureEvent* ge) {}
virtual void on_GestureMove(GestureEvent* ge) {}
};
class CanvasModePen : public CanvasMode
{
bool m_dragging = false;
bool m_draggingR = false;
glm::vec2 m_dragR_start;
glm::vec2 m_pan_start;
glm::vec2 m_pan;
glm::vec2 m_cur;
float m_camera_fov;
float m_zoom_canvas = 1.f;
float m_zoom_start;
public:
virtual void on_MouseDownL(MouseEvent* me, glm::vec2& loc) override;
virtual void on_MouseUpL(MouseEvent* me, glm::vec2& loc) override;
virtual void on_MouseDownR(MouseEvent* me, glm::vec2& loc) override;
virtual void on_MouseUpR(MouseEvent* me, glm::vec2& loc) override;
virtual void on_MouseMove(MouseEvent* me, glm::vec2& loc) override;
virtual void on_MouseScroll(MouseEvent* me, glm::vec2& loc) override;
virtual void on_MouseCancel(MouseEvent* me, glm::vec2& loc) override;
virtual void on_GestureStart(GestureEvent* ge) override;
virtual void on_GestureMove(GestureEvent* ge) override;
};

View File

@@ -1967,15 +1967,6 @@ public:
class NodeCanvas : public Node class NodeCanvas : public Node
{ {
bool m_dragging = false;
bool m_draggingR = false;
glm::vec2 m_dragR_start;
glm::vec2 m_pan_start;
glm::vec2 m_pan;
glm::vec2 m_cur;
float m_camera_fov;
float m_zoom_canvas = 1.f;
float m_zoom_start;
public: public:
std::string data_path; std::string data_path;
std::unique_ptr<ui::Canvas> m_canvas; std::unique_ptr<ui::Canvas> m_canvas;
@@ -1987,9 +1978,9 @@ public:
{ {
m_mouse_ignore = false; m_mouse_ignore = false;
m_canvas = std::make_unique<ui::Canvas>(); m_canvas = std::make_unique<ui::Canvas>();
CanvasMode::node = this;
CanvasMode::canvas = m_canvas.get();
m_canvas->create(1024, 1024); m_canvas->create(1024, 1024);
//m_canvas->layer_add("asd");
//m_canvas->clear();
m_sampler.create(); m_sampler.create();
m_face_plane.create<1>(2, 2); m_face_plane.create<1>(2, 2);
} }
@@ -1998,7 +1989,6 @@ public:
Node::restore_context(); Node::restore_context();
m_canvas->create(1024, 1024); m_canvas->create(1024, 1024);
m_sampler.create(); m_sampler.create();
//m_canvas->clear();
m_face_plane.create<1>(2, 2); m_face_plane.create<1>(2, 2);
m_canvas->snapshot_restore(); m_canvas->snapshot_restore();
} }
@@ -2023,7 +2013,7 @@ public:
glm::ivec4 c = (glm::ivec4)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); glViewport(c.x, c.y, c.z, c.w);
m_canvas->m_cam_rot = m_pan * 0.003f; //m_canvas->m_cam_rot = m_pan * 0.003f;
//glm::mat4 proj = glm::ortho(0.f, box.z, 0.f, box.w, -1000.f, 1000.f); //glm::mat4 proj = glm::ortho(0.f, box.z, 0.f, box.w, -1000.f, 1000.f);
glm::mat4 proj = glm::perspective(glm::radians(m_canvas->m_cam_fov), box.z / box.w, 0.1f, 1000.f); glm::mat4 proj = glm::perspective(glm::radians(m_canvas->m_cam_fov), box.z / box.w, 0.1f, 1000.f);
@@ -2054,7 +2044,7 @@ public:
ui::ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp); ui::ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp);
for (auto layer_index : m_canvas->m_order) for (auto layer_index : m_canvas->m_order)
{ {
if (!(m_canvas->m_state == ui::Canvas::kPenState::Erase && if (!(m_canvas->m_state == ui::Canvas::kCanvasMode::Erase &&
m_canvas->m_show_tmp && m_canvas->m_current_layer_idx == layer_index)) m_canvas->m_show_tmp && m_canvas->m_current_layer_idx == layer_index))
{ {
ui::ShaderManager::u_float(kShaderUniform::Alpha, m_canvas->m_layers[layer_index].m_opacity); ui::ShaderManager::u_float(kShaderUniform::Alpha, m_canvas->m_layers[layer_index].m_opacity);
@@ -2104,67 +2094,47 @@ public:
switch (e->m_type) switch (e->m_type)
{ {
case kEventType::MouseDownL: case kEventType::MouseDownL:
{ m_canvas->m_mode->on_MouseDownL(me, loc);
m_canvas->stroke_start(loc, 1.f, m_brush);
m_dragging = true;
mouse_capture();
break; break;
}
case kEventType::MouseUpL: case kEventType::MouseUpL:
m_canvas->stroke_end(); m_canvas->m_mode->on_MouseUpL(me, loc);
m_dragging = false;
mouse_release();
break; break;
case kEventType::MouseDownR: case kEventType::MouseDownR:
m_draggingR = true; m_canvas->m_mode->on_MouseDownR(me, loc);
m_dragR_start = me->m_pos;
m_pan_start = m_pan;
mouse_capture();
break; break;
case kEventType::MouseUpR: case kEventType::MouseUpR:
m_draggingR = false; m_canvas->m_mode->on_MouseUpR(me, loc);
mouse_release();
break; break;
case kEventType::MouseMove: case kEventType::MouseMove:
if (m_dragging) m_canvas->m_mode->on_MouseMove(me, loc);
m_canvas->stroke_update(loc, 1.f);
if (m_draggingR)
m_pan = m_pan_start + (me->m_pos - m_dragR_start) * glm::vec2(-1, -1);
m_cur = loc;
break; break;
case kEventType::MouseScroll: case kEventType::MouseScroll:
m_zoom_canvas += me->m_scroll_delta * 0.1f; m_canvas->m_mode->on_MouseScroll(me, loc);
m_canvas->m_cam_fov -= me->m_scroll_delta * 20.1f;
break; break;
case kEventType::MouseCancel: case kEventType::MouseCancel:
m_dragging = false; m_canvas->m_mode->on_MouseCancel(me, loc);
mouse_release();
break; break;
case kEventType::KeyDown: case kEventType::KeyDown:
if (ke->m_key == kKey::KeyE) // if (ke->m_key == kKey::KeyE)
m_canvas->m_state = ui::Canvas::kPenState::Erase; // m_canvas->m_state = ui::Canvas::kPenState::Erase;
if (ke->m_key == kKey::KeySpacebar) // if (ke->m_key == kKey::KeySpacebar)
m_canvas->m_alpha_lock = true; // m_canvas->m_alpha_lock = true;
if (ke->m_key == kKey::AndroidVolumeUp) // if (ke->m_key == kKey::AndroidVolumeUp)
m_zoom_canvas *= 0.9f; // m_zoom_canvas *= 0.9f;
if (ke->m_key == kKey::AndroidVolumeDown) // if (ke->m_key == kKey::AndroidVolumeDown)
m_zoom_canvas *= 1.1f; // m_zoom_canvas *= 1.1f;
break; break;
case kEventType::KeyUp: case kEventType::KeyUp:
if (ke->m_key == kKey::KeyE) // if (ke->m_key == kKey::KeyE)
m_canvas->m_state = ui::Canvas::kPenState::Draw; // m_canvas->m_state = ui::Canvas::kPenState::Draw;
if (ke->m_key == kKey::KeySpacebar) // if (ke->m_key == kKey::KeySpacebar)
m_canvas->m_alpha_lock = false; // m_canvas->m_alpha_lock = false;
break; break;
case kEventType::GestureStart: case kEventType::GestureStart:
m_pan_start = m_pan; m_canvas->m_mode->on_GestureStart(ge);
m_zoom_start = m_zoom_canvas;
m_camera_fov = m_canvas->m_cam_fov;
break; break;
case kEventType::GestureMove: case kEventType::GestureMove:
m_pan = m_pan_start + ge->m_pos_delta * glm::vec2(-1, -1) * 0.3f; m_canvas->m_mode->on_GestureMove(ge);
m_canvas->m_cam_fov = m_camera_fov - ge->m_distance_delta * .05f;
//m_zoom_canvas = m_zoom_start + ge->m_distance_delta * .001f;
break; break;
default: default:
return kEventResult::Available; return kEventResult::Available;