246 lines
7.4 KiB
C++
246 lines
7.4 KiB
C++
#include "pch.h"
|
|
|
|
#include "canvas_modes.h"
|
|
|
|
#include "app.h"
|
|
#include "canvas.h"
|
|
#include "legacy_canvas_draw_merge_services.h"
|
|
#include "legacy_ui_overlay_services.h"
|
|
#include "node_tool_bucket.h"
|
|
#include "texture.h"
|
|
|
|
void CanvasModeFill::init()
|
|
{
|
|
m_shape.create();
|
|
}
|
|
|
|
void CanvasModeFill::leave(kCanvasMode next)
|
|
{
|
|
if (m_points.size() > 2)
|
|
{
|
|
auto drawer = [this](const glm::mat4& camera, const glm::mat4& proj) {
|
|
pp::panopainter::setup_legacy_vr_color_shader({
|
|
.color = { 1, 1, 1, 1 },
|
|
.mvp = proj * camera,
|
|
});
|
|
m_shape.draw_fill();
|
|
};
|
|
Canvas::I->draw_objects_direct(std::bind(drawer, std::placeholders::_1, std::placeholders::_2), Canvas::I->m_smask, 0);
|
|
m_points.clear();
|
|
Canvas::I->m_smask_active = true;
|
|
}
|
|
else
|
|
{
|
|
Canvas::I->m_smask_active = false;
|
|
}
|
|
}
|
|
|
|
void CanvasModeFill::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
|
|
{
|
|
if (Canvas::I->m_touch_lock && me->m_source == kEventSource::Touch)
|
|
return;
|
|
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::I->point_trace_plane(loc, ro, rd, hit_o, hit_d, hit_fb, 0))
|
|
{
|
|
m_dirty_planes[plane_id]++;
|
|
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::I->m_smask.clear({0, 0, 0, 0});
|
|
break;
|
|
}
|
|
case kEventType::MouseUpL:
|
|
pp::panopainter::release_legacy_mouse_capture(*node);
|
|
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::I->point_trace(loc, ro, rd, hit_o, fb_pos, hit_d, plane_id))
|
|
{
|
|
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)
|
|
{
|
|
m_points.pop_back();
|
|
m_shape.update_vertices(m_points.data(), (int)m_points.size());
|
|
}
|
|
m_dragging = false;
|
|
pp::panopainter::release_legacy_mouse_capture(*node);
|
|
if (m_points.size() < 4)
|
|
{
|
|
m_points.clear();
|
|
m_shape.update_vertices(m_points.data(), (int)m_points.size());
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CanvasModeFill::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const glm::mat4& camera)
|
|
{
|
|
if (!m_points.empty())
|
|
{
|
|
pp::panopainter::setup_legacy_vr_color_shader({
|
|
.color = { 0, 0, 0, .25 },
|
|
.mvp = proj * camera,
|
|
});
|
|
m_dragging ? m_shape.draw_fill() : m_shape.draw_stroke();
|
|
}
|
|
}
|
|
|
|
void CanvasModeFloodFill::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
|
|
{
|
|
m_draw_tip = App::I->draws_canvas_tip_for_input(me->m_source, me->m_type);
|
|
if (Canvas::I->m_touch_lock && me->m_source == kEventSource::Touch)
|
|
return;
|
|
|
|
struct ActionFloodFill : public Action
|
|
{
|
|
std::shared_ptr<Layer> m_layer;
|
|
std::shared_ptr<LayerFrame::Snapshot> m_snap;
|
|
std::array<bool, 6> m_dirty_face = SIXPLETTE(false);
|
|
std::array<glm::vec4, 6> m_dirty_box = SIXPLETTE(glm::vec4(0));
|
|
glm::ivec2 m_pos;
|
|
glm::vec4 m_color;
|
|
float m_threshold;
|
|
int m_layer_index;
|
|
int m_plane;
|
|
virtual void run() override { }
|
|
virtual size_t memory() override { return m_snap->memsize(); }
|
|
virtual Action* get_redo() override
|
|
{
|
|
auto a = new ActionFloodFill;
|
|
a->m_direction = reverse_direction();
|
|
a->m_layer = m_layer;
|
|
a->m_snap = m_snap;
|
|
a->m_pos = m_pos;
|
|
a->m_color = m_color;
|
|
a->m_layer_index = m_layer_index;
|
|
a->m_threshold = m_threshold;
|
|
a->m_plane = m_plane;
|
|
a->m_dirty_box = m_dirty_box;
|
|
a->m_dirty_face = m_dirty_face;
|
|
return a;
|
|
}
|
|
virtual void undo() override
|
|
{
|
|
if (m_direction == Direction::Undo)
|
|
{
|
|
m_layer->restore(*m_snap);
|
|
}
|
|
else
|
|
{
|
|
Canvas::FloodData plane_data;
|
|
std::unique_ptr<glm::vec4> color;
|
|
Canvas::I->flood_fill(m_layer_index, m_plane, { m_pos },
|
|
plane_data, m_threshold, m_color, color);
|
|
plane_data.apply();
|
|
}
|
|
}
|
|
};
|
|
|
|
switch (me->m_type)
|
|
{
|
|
case kEventType::MouseUpL:
|
|
glm::vec3 ro, rd, hit, n;
|
|
glm::vec2 pos;
|
|
int plane;
|
|
if (Canvas::I->point_trace(loc, ro, rd, hit, pos, n, plane))
|
|
{
|
|
Canvas::FloodData plane_data;
|
|
std::unique_ptr<glm::vec4> color;
|
|
Canvas::I->flood_fill(Canvas::I->m_current_layer_idx, plane, { (glm::ivec2)pos },
|
|
plane_data, m_tool->get_threshold(), Canvas::I->m_current_brush->m_tip_color, color);
|
|
|
|
auto a = new ActionFloodFill;
|
|
a->m_direction = Action::Direction::Undo;
|
|
a->m_layer = plane_data.layer;
|
|
a->m_snap = std::make_shared<LayerFrame::Snapshot>(plane_data.layer->snapshot());
|
|
a->m_pos = (glm::ivec2)pos;
|
|
a->m_color = Canvas::I->m_current_brush->m_tip_color;
|
|
a->m_layer_index = Canvas::I->m_current_layer_idx;
|
|
a->m_threshold = m_tool->get_threshold();
|
|
a->m_plane = plane;
|
|
a->m_dirty_box = plane_data.layer->frame().m_dirty_box;
|
|
a->m_dirty_face = plane_data.layer->frame().m_dirty_face;
|
|
ActionManager::add(a);
|
|
|
|
plane_data.apply();
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CanvasModeFloodFill::init()
|
|
{
|
|
TextureManager::load(m_cursor_path.c_str());
|
|
}
|
|
|
|
void CanvasModeFloodFill::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const glm::mat4& camera)
|
|
{
|
|
if (m_draw_tip)
|
|
{
|
|
pp::panopainter::setup_legacy_canvas_draw_merge_texture_shader({
|
|
.mvp = glm::scale(glm::vec3(1, -1, 1))
|
|
* ortho
|
|
* glm::translate(glm::vec3(Canvas::I->m_cur_pos, 0.f))
|
|
* glm::scale(glm::vec3(32, 32, 1))
|
|
* glm::translate(glm::vec3(0.5f, -0.5f, 0)),
|
|
.texture_slot = 0,
|
|
});
|
|
|
|
auto& t = TextureManager::get(m_cursor_id);
|
|
|
|
Canvas::I->m_sampler_linear.bind(0);
|
|
t.bind();
|
|
Canvas::I->m_plane.draw_fill();
|
|
t.unbind();
|
|
}
|
|
}
|
|
|
|
void CanvasModeFloodFill::enter(kCanvasMode prev)
|
|
{
|
|
auto tools = App::I->layout[App::I->main_id]->find("tools-container");
|
|
m_tool = tools->add_child<NodeToolBucket>();
|
|
}
|
|
|
|
void CanvasModeFloodFill::leave(kCanvasMode next)
|
|
{
|
|
pp::panopainter::destroy_legacy_node(*m_tool);
|
|
m_tool = nullptr;
|
|
}
|