Extract canvas mask modes, preview draw pass, and node style shell
This commit is contained in:
@@ -2,26 +2,19 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "log.h"
|
||||
#include "canvas_modes.h"
|
||||
#include "layout.h"
|
||||
#include "canvas.h"
|
||||
#include "shader.h"
|
||||
#include "node_canvas.h"
|
||||
#include "legacy_canvas_draw_merge_services.h"
|
||||
#include "legacy_canvas_stroke_composite_services.h"
|
||||
#include "legacy_canvas_mode_helpers.h"
|
||||
#include "legacy_ui_overlay_services.h"
|
||||
#include "legacy_ui_gl_dispatch.h"
|
||||
#include "app.h"
|
||||
#include "util.h"
|
||||
#include "renderer_gl/opengl_capabilities.h"
|
||||
|
||||
NodeCanvas* CanvasMode::node;
|
||||
|
||||
using pp::legacy_canvas_mode::apply_canvas_mode_capability;
|
||||
using pp::legacy_canvas_mode::apply_canvas_mode_viewport;
|
||||
using pp::legacy_canvas_mode::query_canvas_mode_capability;
|
||||
using pp::legacy_canvas_mode::query_canvas_mode_read_framebuffer;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@@ -199,332 +192,6 @@ void ActionModeGrid::undo()
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CanvasModeMaskFree::init()
|
||||
{
|
||||
m_shape.create();
|
||||
}
|
||||
|
||||
void CanvasModeMaskFree::leave(kCanvasMode next)
|
||||
{
|
||||
// Canvas::I->draw_objects(std::bind(&CanvasModeFill::on_Draw, this, glm::mat4(1), std::placeholders::_1, std::placeholders::_2));
|
||||
if (next != kCanvasMode::Draw && next != kCanvasMode::Erase && next != kCanvasMode::Line)
|
||||
{
|
||||
m_points.clear();
|
||||
Canvas::I->m_smask_active = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasModeMaskFree::clear()
|
||||
{
|
||||
m_points.clear();
|
||||
m_points2d.clear();
|
||||
m_shape.clear();
|
||||
}
|
||||
|
||||
void CanvasModeMaskFree::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
|
||||
{
|
||||
static glm::vec2 oldpos;
|
||||
static glm::vec2 oldvec;
|
||||
static float acc = 0.f;
|
||||
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;
|
||||
m_points2d.clear();
|
||||
m_points.clear();
|
||||
oldpos = loc;
|
||||
oldvec = {1.f, 0.f};
|
||||
acc = 0;
|
||||
vertex_t vert;
|
||||
vert.pos = glm::vec4(loc, 0, 1);
|
||||
m_points2d.push_back(loc);
|
||||
m_points2d.push_back(loc);
|
||||
m_points.push_back(vert);
|
||||
m_points.push_back(vert);
|
||||
if (!(App::I->keys[(int)kKey::KeyShift] || App::I->keys[(int)kKey::KeyCtrl]))
|
||||
Canvas::I->m_smask.clear({0, 0, 0, 0});
|
||||
Canvas::I->m_smask_active = true;
|
||||
Canvas::I->m_smask_mode = 1;
|
||||
break;
|
||||
}
|
||||
case kEventType::MouseUpL:
|
||||
pp::panopainter::release_legacy_mouse_capture(*node);
|
||||
m_dragging = false;
|
||||
if (m_points2d.size() > 3)
|
||||
{
|
||||
if (!m_points.empty())
|
||||
{
|
||||
m_selection_cam = Canvas::I->get_camera();
|
||||
//m_points2d = poly_intersect(poly_remove_duplicate(m_points2d), Canvas::I->face_to_shape2D(0));
|
||||
auto drawer = [this](const glm::mat4& camera, const glm::mat4& proj) {
|
||||
// blending state intentionally left unchanged here.
|
||||
apply_canvas_mode_capability(pp::renderer::gl::depth_test_state(), false);
|
||||
pp::panopainter::setup_legacy_vr_color_shader({
|
||||
.color = App::I->keys[(int)kKey::KeyCtrl] ? glm::vec4(0, 0, 0, 1) : glm::vec4(1, 1, 1, 1),
|
||||
.mvp = proj * camera,
|
||||
});
|
||||
m_shape.draw_fill();
|
||||
};
|
||||
// use m_shape to render the mask polygon
|
||||
auto v = triangulate(poly_remove_duplicate(m_points2d));
|
||||
Canvas::I->project2Dpoints(v);
|
||||
m_shape.update_vertices(v.data(), (int)v.size());
|
||||
Canvas::I->draw_objects_direct(std::bind(drawer, std::placeholders::_1, std::placeholders::_2), Canvas::I->m_smask, 0);
|
||||
|
||||
// close the path and reset m_shape to contour rendering
|
||||
m_points.push_back(m_points.back());
|
||||
m_points.push_back(m_points.front());
|
||||
Canvas::I->project2Dpoints(m_points);
|
||||
m_shape.update_vertices(m_points.data(), (int)m_points.size());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Canvas::I->m_smask_active = false;
|
||||
}
|
||||
break;
|
||||
case kEventType::MouseMove:
|
||||
{
|
||||
if (m_dragging)
|
||||
{
|
||||
auto v = loc - oldpos;
|
||||
float len = glm::length(v);
|
||||
if (len > 5)
|
||||
{
|
||||
m_points.back().pos = glm::vec4(loc, 0, 1);
|
||||
m_points2d.back() = loc;
|
||||
|
||||
v = glm::normalize(v);
|
||||
float d = 1.f - glm::dot(v, oldvec);
|
||||
acc += d;
|
||||
oldpos = loc;
|
||||
oldvec = v;
|
||||
if (acc > 0.001) // angle change tolerance
|
||||
{
|
||||
//LOG("d=%f acc=%f", d, acc);
|
||||
acc = 0;
|
||||
|
||||
m_points2d.push_back(loc);
|
||||
vertex_t vert;
|
||||
vert.pos = glm::vec4(loc, 0, 1);
|
||||
m_points.push_back(vert);
|
||||
m_points.push_back(vert);
|
||||
}
|
||||
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 CanvasModeMaskFree::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const glm::mat4& camera)
|
||||
{
|
||||
const bool depth = query_canvas_mode_capability(pp::renderer::gl::depth_test_state());
|
||||
apply_canvas_mode_capability(pp::renderer::gl::depth_test_state(), false);
|
||||
if (m_points.size() > 3)
|
||||
{
|
||||
if (m_dragging)
|
||||
{
|
||||
pp::panopainter::setup_legacy_vr_color_shader({
|
||||
.color = { 0, 0, 0, 1 },
|
||||
.mvp = glm::scale(glm::vec3(1, -1, 1)) * ortho,
|
||||
});
|
||||
//m_dragging ? m_shape.draw_stroke() : m_shape.draw_fill();
|
||||
m_shape.draw_stroke();
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// ShaderManager::use(kShader::Color);
|
||||
// ShaderManager::u_mat4(kShaderUniform::MVP, proj * camera);
|
||||
// ShaderManager::u_vec4(kShaderUniform::Col, { 0, 0, 0, 1 });
|
||||
// m_shape.draw_stroke();
|
||||
//}
|
||||
}
|
||||
if (depth) apply_canvas_mode_capability(pp::renderer::gl::depth_test_state(), true);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CanvasModeMaskLine::init()
|
||||
{
|
||||
m_shape.create();
|
||||
}
|
||||
|
||||
void CanvasModeMaskLine::leave(kCanvasMode next)
|
||||
{
|
||||
if (next != kCanvasMode::Draw && next != kCanvasMode::Erase && next != kCanvasMode::Line)
|
||||
{
|
||||
m_points.clear();
|
||||
m_active_tool = false;
|
||||
Canvas::I->m_smask_active = false;
|
||||
}
|
||||
|
||||
if (!m_active_tool)
|
||||
return;
|
||||
|
||||
if (m_points2d.size() > 3)
|
||||
{
|
||||
std::vector<vertex_t> points;
|
||||
for (int i = 0; i < (int)m_points2d.size(); i++)
|
||||
points.emplace_back(m_points2d[i]);
|
||||
auto v = triangulate(poly_remove_duplicate(points));
|
||||
Canvas::I->project2Dpoints(v);
|
||||
LOG("%d points", (int)v.size());
|
||||
|
||||
m_shape.update_vertices(v.data(), (int)v.size());
|
||||
|
||||
if (!m_points.empty())
|
||||
{
|
||||
auto drawer = [this](const glm::mat4& camera, const glm::mat4& proj) {
|
||||
// blending state intentionally left unchanged here.
|
||||
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();
|
||||
// close the path
|
||||
m_points.push_back(m_points.back());
|
||||
m_points.push_back(m_points.back());
|
||||
m_points.push_back(m_points.front());
|
||||
Canvas::I->project2Dpoints(m_points);
|
||||
// reset m_shape to contour rendering
|
||||
m_shape.update_vertices(m_points.data(), (int)m_points.size());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Canvas::I->m_smask_active = false;
|
||||
}
|
||||
m_active_tool = false;
|
||||
}
|
||||
|
||||
void CanvasModeMaskLine::enter(kCanvasMode prev)
|
||||
{
|
||||
//m_points2d.clear();
|
||||
//m_points.clear();
|
||||
//Canvas::I->m_smask.clear({0, 0, 0, 0});
|
||||
//m_active_tool = true;
|
||||
}
|
||||
|
||||
void CanvasModeMaskLine::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:
|
||||
{
|
||||
if (m_active_tool == false)
|
||||
{
|
||||
m_active_tool = true;
|
||||
m_points2d.clear();
|
||||
m_points.clear();
|
||||
Canvas::I->m_smask.clear({ 0, 0, 0, 0 });
|
||||
Canvas::I->m_smask_active = true;
|
||||
Canvas::I->m_smask_mode = 2;
|
||||
}
|
||||
node->mouse_capture();
|
||||
m_dragging = true;
|
||||
m_points2d.push_back(loc);
|
||||
vertex_t vert;
|
||||
vert.pos = glm::vec4(loc, 0, 1);
|
||||
m_points.push_back(vert);
|
||||
m_shape.update_vertices(m_points.data(), (int)m_points.size());
|
||||
break;
|
||||
}
|
||||
case kEventType::MouseUpL:
|
||||
pp::panopainter::release_legacy_mouse_capture(*node);
|
||||
m_dragging = false;
|
||||
if (m_points.size() > 1)
|
||||
{
|
||||
m_selection_cam = Canvas::I->get_camera();
|
||||
m_points.push_back(m_points.back());
|
||||
m_shape.update_vertices(m_points.data(), (int)m_points.size());
|
||||
}
|
||||
break;
|
||||
case kEventType::MouseMove:
|
||||
{
|
||||
if (m_dragging)
|
||||
{
|
||||
if (glm::distance(m_points2d.front(), loc) < 10)
|
||||
loc = m_points2d.front();
|
||||
m_points.back().pos = glm::vec4(loc, 0, 1);
|
||||
m_points2d.back() = loc;
|
||||
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 CanvasModeMaskLine::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const glm::mat4& camera)
|
||||
{
|
||||
if (m_points.size() > 1)
|
||||
{
|
||||
if (m_active_tool)
|
||||
{
|
||||
pp::panopainter::setup_legacy_vr_color_shader({
|
||||
.color = { 0, 0, 0, 1 },
|
||||
.mvp = glm::scale(glm::vec3(1, -1, 1)) * ortho,
|
||||
});
|
||||
//m_dragging ? m_shape.draw_stroke() : m_shape.draw_fill();
|
||||
m_shape.draw_stroke();
|
||||
}
|
||||
else
|
||||
{
|
||||
pp::panopainter::setup_legacy_vr_color_shader({
|
||||
.color = { 0, 0, 0, 1 },
|
||||
.mvp = proj * camera,
|
||||
});
|
||||
m_shape.draw_stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CanvasModeFill::init()
|
||||
{
|
||||
m_shape.create();
|
||||
|
||||
327
src/legacy_canvas_mode_mask.cpp
Normal file
327
src/legacy_canvas_mode_mask.cpp
Normal file
@@ -0,0 +1,327 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "canvas_modes.h"
|
||||
|
||||
#include "app.h"
|
||||
#include "canvas.h"
|
||||
#include "legacy_canvas_mode_helpers.h"
|
||||
#include "legacy_ui_overlay_services.h"
|
||||
#include "log.h"
|
||||
#include "renderer_gl/opengl_capabilities.h"
|
||||
|
||||
using pp::legacy_canvas_mode::apply_canvas_mode_capability;
|
||||
using pp::legacy_canvas_mode::query_canvas_mode_capability;
|
||||
|
||||
void CanvasModeMaskFree::init()
|
||||
{
|
||||
m_shape.create();
|
||||
}
|
||||
|
||||
void CanvasModeMaskFree::leave(kCanvasMode next)
|
||||
{
|
||||
// Canvas::I->draw_objects(std::bind(&CanvasModeFill::on_Draw, this, glm::mat4(1), std::placeholders::_1, std::placeholders::_2));
|
||||
if (next != kCanvasMode::Draw && next != kCanvasMode::Erase && next != kCanvasMode::Line)
|
||||
{
|
||||
m_points.clear();
|
||||
Canvas::I->m_smask_active = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasModeMaskFree::clear()
|
||||
{
|
||||
m_points.clear();
|
||||
m_points2d.clear();
|
||||
m_shape.clear();
|
||||
}
|
||||
|
||||
void CanvasModeMaskFree::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
|
||||
{
|
||||
static glm::vec2 oldpos;
|
||||
static glm::vec2 oldvec;
|
||||
static float acc = 0.f;
|
||||
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;
|
||||
m_points2d.clear();
|
||||
m_points.clear();
|
||||
oldpos = loc;
|
||||
oldvec = {1.f, 0.f};
|
||||
acc = 0;
|
||||
vertex_t vert;
|
||||
vert.pos = glm::vec4(loc, 0, 1);
|
||||
m_points2d.push_back(loc);
|
||||
m_points2d.push_back(loc);
|
||||
m_points.push_back(vert);
|
||||
m_points.push_back(vert);
|
||||
if (!(App::I->keys[(int)kKey::KeyShift] || App::I->keys[(int)kKey::KeyCtrl]))
|
||||
Canvas::I->m_smask.clear({0, 0, 0, 0});
|
||||
Canvas::I->m_smask_active = true;
|
||||
Canvas::I->m_smask_mode = 1;
|
||||
break;
|
||||
}
|
||||
case kEventType::MouseUpL:
|
||||
pp::panopainter::release_legacy_mouse_capture(*node);
|
||||
m_dragging = false;
|
||||
if (m_points2d.size() > 3)
|
||||
{
|
||||
if (!m_points.empty())
|
||||
{
|
||||
m_selection_cam = Canvas::I->get_camera();
|
||||
//m_points2d = poly_intersect(poly_remove_duplicate(m_points2d), Canvas::I->face_to_shape2D(0));
|
||||
auto drawer = [this](const glm::mat4& camera, const glm::mat4& proj) {
|
||||
// blending state intentionally left unchanged here.
|
||||
apply_canvas_mode_capability(pp::renderer::gl::depth_test_state(), false);
|
||||
pp::panopainter::setup_legacy_vr_color_shader({
|
||||
.color = App::I->keys[(int)kKey::KeyCtrl] ? glm::vec4(0, 0, 0, 1) : glm::vec4(1, 1, 1, 1),
|
||||
.mvp = proj * camera,
|
||||
});
|
||||
m_shape.draw_fill();
|
||||
};
|
||||
// use m_shape to render the mask polygon
|
||||
auto v = triangulate(poly_remove_duplicate(m_points2d));
|
||||
Canvas::I->project2Dpoints(v);
|
||||
m_shape.update_vertices(v.data(), (int)v.size());
|
||||
Canvas::I->draw_objects_direct(std::bind(drawer, std::placeholders::_1, std::placeholders::_2), Canvas::I->m_smask, 0);
|
||||
|
||||
// close the path and reset m_shape to contour rendering
|
||||
m_points.push_back(m_points.back());
|
||||
m_points.push_back(m_points.front());
|
||||
Canvas::I->project2Dpoints(m_points);
|
||||
m_shape.update_vertices(m_points.data(), (int)m_points.size());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Canvas::I->m_smask_active = false;
|
||||
}
|
||||
break;
|
||||
case kEventType::MouseMove:
|
||||
{
|
||||
if (m_dragging)
|
||||
{
|
||||
auto v = loc - oldpos;
|
||||
float len = glm::length(v);
|
||||
if (len > 5)
|
||||
{
|
||||
m_points.back().pos = glm::vec4(loc, 0, 1);
|
||||
m_points2d.back() = loc;
|
||||
|
||||
v = glm::normalize(v);
|
||||
float d = 1.f - glm::dot(v, oldvec);
|
||||
acc += d;
|
||||
oldpos = loc;
|
||||
oldvec = v;
|
||||
if (acc > 0.001) // angle change tolerance
|
||||
{
|
||||
//LOG("d=%f acc=%f", d, acc);
|
||||
acc = 0;
|
||||
|
||||
m_points2d.push_back(loc);
|
||||
vertex_t vert;
|
||||
vert.pos = glm::vec4(loc, 0, 1);
|
||||
m_points.push_back(vert);
|
||||
m_points.push_back(vert);
|
||||
}
|
||||
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 CanvasModeMaskFree::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const glm::mat4& camera)
|
||||
{
|
||||
const bool depth = query_canvas_mode_capability(pp::renderer::gl::depth_test_state());
|
||||
apply_canvas_mode_capability(pp::renderer::gl::depth_test_state(), false);
|
||||
if (m_points.size() > 3)
|
||||
{
|
||||
if (m_dragging)
|
||||
{
|
||||
pp::panopainter::setup_legacy_vr_color_shader({
|
||||
.color = { 0, 0, 0, 1 },
|
||||
.mvp = glm::scale(glm::vec3(1, -1, 1)) * ortho,
|
||||
});
|
||||
//m_dragging ? m_shape.draw_stroke() : m_shape.draw_fill();
|
||||
m_shape.draw_stroke();
|
||||
}
|
||||
}
|
||||
if (depth) apply_canvas_mode_capability(pp::renderer::gl::depth_test_state(), true);
|
||||
}
|
||||
|
||||
void CanvasModeMaskLine::init()
|
||||
{
|
||||
m_shape.create();
|
||||
}
|
||||
|
||||
void CanvasModeMaskLine::leave(kCanvasMode next)
|
||||
{
|
||||
if (next != kCanvasMode::Draw && next != kCanvasMode::Erase && next != kCanvasMode::Line)
|
||||
{
|
||||
m_points.clear();
|
||||
m_active_tool = false;
|
||||
Canvas::I->m_smask_active = false;
|
||||
}
|
||||
|
||||
if (!m_active_tool)
|
||||
return;
|
||||
|
||||
if (m_points2d.size() > 3)
|
||||
{
|
||||
std::vector<vertex_t> points;
|
||||
for (int i = 0; i < (int)m_points2d.size(); i++)
|
||||
points.emplace_back(m_points2d[i]);
|
||||
auto v = triangulate(poly_remove_duplicate(points));
|
||||
Canvas::I->project2Dpoints(v);
|
||||
LOG("%d points", (int)v.size());
|
||||
|
||||
m_shape.update_vertices(v.data(), (int)v.size());
|
||||
|
||||
if (!m_points.empty())
|
||||
{
|
||||
auto drawer = [this](const glm::mat4& camera, const glm::mat4& proj) {
|
||||
// blending state intentionally left unchanged here.
|
||||
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();
|
||||
// close the path
|
||||
m_points.push_back(m_points.back());
|
||||
m_points.push_back(m_points.back());
|
||||
m_points.push_back(m_points.front());
|
||||
Canvas::I->project2Dpoints(m_points);
|
||||
// reset m_shape to contour rendering
|
||||
m_shape.update_vertices(m_points.data(), (int)m_points.size());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Canvas::I->m_smask_active = false;
|
||||
}
|
||||
m_active_tool = false;
|
||||
}
|
||||
|
||||
void CanvasModeMaskLine::enter(kCanvasMode prev)
|
||||
{
|
||||
//m_points2d.clear();
|
||||
//m_points.clear();
|
||||
//Canvas::I->m_smask.clear({0, 0, 0, 0});
|
||||
//m_active_tool = true;
|
||||
}
|
||||
|
||||
void CanvasModeMaskLine::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:
|
||||
{
|
||||
if (m_active_tool == false)
|
||||
{
|
||||
m_active_tool = true;
|
||||
m_points2d.clear();
|
||||
m_points.clear();
|
||||
Canvas::I->m_smask.clear({ 0, 0, 0, 0 });
|
||||
Canvas::I->m_smask_active = true;
|
||||
Canvas::I->m_smask_mode = 2;
|
||||
}
|
||||
node->mouse_capture();
|
||||
m_dragging = true;
|
||||
m_points2d.push_back(loc);
|
||||
vertex_t vert;
|
||||
vert.pos = glm::vec4(loc, 0, 1);
|
||||
m_points.push_back(vert);
|
||||
m_shape.update_vertices(m_points.data(), (int)m_points.size());
|
||||
break;
|
||||
}
|
||||
case kEventType::MouseUpL:
|
||||
pp::panopainter::release_legacy_mouse_capture(*node);
|
||||
m_dragging = false;
|
||||
if (m_points.size() > 1)
|
||||
{
|
||||
m_selection_cam = Canvas::I->get_camera();
|
||||
m_points.push_back(m_points.back());
|
||||
m_shape.update_vertices(m_points.data(), (int)m_points.size());
|
||||
}
|
||||
break;
|
||||
case kEventType::MouseMove:
|
||||
{
|
||||
if (m_dragging)
|
||||
{
|
||||
if (glm::distance(m_points2d.front(), loc) < 10)
|
||||
loc = m_points2d.front();
|
||||
m_points.back().pos = glm::vec4(loc, 0, 1);
|
||||
m_points2d.back() = loc;
|
||||
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 CanvasModeMaskLine::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const glm::mat4& camera)
|
||||
{
|
||||
if (m_points.size() > 1)
|
||||
{
|
||||
if (m_active_tool)
|
||||
{
|
||||
pp::panopainter::setup_legacy_vr_color_shader({
|
||||
.color = { 0, 0, 0, 1 },
|
||||
.mvp = glm::scale(glm::vec3(1, -1, 1)) * ortho,
|
||||
});
|
||||
//m_dragging ? m_shape.draw_stroke() : m_shape.draw_fill();
|
||||
m_shape.draw_stroke();
|
||||
}
|
||||
else
|
||||
{
|
||||
pp::panopainter::setup_legacy_vr_color_shader({
|
||||
.color = { 0, 0, 0, 1 },
|
||||
.mvp = proj * camera,
|
||||
});
|
||||
m_shape.draw_stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
123
src/legacy_node_stroke_preview_draw_services.cpp
Normal file
123
src/legacy_node_stroke_preview_draw_services.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "legacy_node_stroke_preview_draw_services.h"
|
||||
|
||||
namespace pp::panopainter {
|
||||
|
||||
namespace {
|
||||
|
||||
bool has_valid_live_render_callbacks(const LegacyNodeStrokePreviewLiveRenderRequest& request)
|
||||
{
|
||||
return request.bind_dual_pass_textures &&
|
||||
request.capture_background &&
|
||||
request.compute_frames &&
|
||||
request.draw_samples &&
|
||||
request.draw_mix &&
|
||||
request.unbind_mixer_texture &&
|
||||
request.bind_pattern_texture &&
|
||||
request.draw_composite;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool execute_legacy_node_stroke_preview_live_render_passes(
|
||||
const LegacyNodeStrokePreviewLiveRenderRequest& request)
|
||||
{
|
||||
if (!has_valid_live_render_callbacks(request)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return execute_legacy_node_stroke_preview_draw_immediate_shell<LegacyNodeStrokePreviewFrame>(
|
||||
request.brush,
|
||||
request.pass_orchestration,
|
||||
request.stroke_texture,
|
||||
request.mixer_rtt,
|
||||
request.render_target,
|
||||
request.background_texture,
|
||||
request.dual_texture,
|
||||
request.preview_texture,
|
||||
request.linear_sampler,
|
||||
request.repeat_sampler,
|
||||
request.copy_stroke_destination,
|
||||
request.size,
|
||||
kLegacyNodeStrokePreviewStrokeTextureSlot,
|
||||
[&] {
|
||||
if (!request.pass_orchestration.material.dual_pass.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
setup_legacy_stroke_dual_shader(request.pass_orchestration.material.dual_pass.uses_pattern);
|
||||
request.bind_dual_pass_textures(*request.prepared_strokes.dual_brush);
|
||||
execute_legacy_stroke_preview_live_pass(
|
||||
[&] {
|
||||
request.render_target.clear();
|
||||
},
|
||||
[&] {
|
||||
return request.compute_frames(
|
||||
const_cast<Stroke&>(request.prepared_strokes.dual_stroke),
|
||||
request.zoom);
|
||||
},
|
||||
[](auto& frame) {
|
||||
frame.col = { 0, 0, 0, 1 };
|
||||
},
|
||||
[&](auto& frame) {
|
||||
use_legacy_stroke_shader();
|
||||
apply_legacy_stroke_sample_uniforms(
|
||||
LegacyStrokeSampleUniforms {
|
||||
.color = frame.col,
|
||||
.alpha = frame.flow,
|
||||
.opacity = frame.opacity,
|
||||
});
|
||||
},
|
||||
[&](auto& frame) {
|
||||
request.draw_samples(frame.shapes, request.dual_texture, request.copy_stroke_destination);
|
||||
},
|
||||
[&] {
|
||||
copy_legacy_node_stroke_preview_framebuffer_to_texture(
|
||||
request.dual_texture,
|
||||
request.size,
|
||||
kLegacyNodeStrokePreviewStrokeTextureSlot);
|
||||
});
|
||||
},
|
||||
[&] {
|
||||
request.capture_background(request.pass_orchestration.background_colorize);
|
||||
},
|
||||
[&] {
|
||||
return request.compute_frames(
|
||||
const_cast<Stroke&>(request.prepared_strokes.stroke),
|
||||
request.zoom);
|
||||
},
|
||||
[&](auto& frame) {
|
||||
if (request.brush.m_tip_mix > 0.0f) {
|
||||
request.draw_mix(xy(frame.mixer_rect), zw(frame.mixer_rect));
|
||||
}
|
||||
|
||||
frame.col = request.brush.m_blend_mode != 0 || request.brush.m_tip_mix > 0.0f ?
|
||||
glm::vec4 { .7f, .4f, .1f, 1.0f } :
|
||||
glm::vec4 { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
frame.flow = glm::max(frame.flow, request.min_flow);
|
||||
},
|
||||
[&](auto& frame) {
|
||||
use_legacy_stroke_shader();
|
||||
apply_legacy_stroke_sample_uniforms(
|
||||
LegacyStrokeSampleUniforms {
|
||||
.color = frame.col,
|
||||
.alpha = frame.flow,
|
||||
.opacity = frame.opacity,
|
||||
});
|
||||
},
|
||||
[&](auto& frame) {
|
||||
request.draw_samples(frame.shapes, request.stroke_texture, request.copy_stroke_destination);
|
||||
},
|
||||
[&] {
|
||||
request.unbind_mixer_texture();
|
||||
},
|
||||
[&] {
|
||||
request.bind_pattern_texture();
|
||||
},
|
||||
[&] {
|
||||
request.draw_composite();
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace pp::panopainter
|
||||
51
src/legacy_node_stroke_preview_draw_services.h
Normal file
51
src/legacy_node_stroke_preview_draw_services.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include "brush.h"
|
||||
#include "legacy_node_stroke_preview_execution_services.h"
|
||||
#include "rtt.h"
|
||||
#include "texture.h"
|
||||
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
namespace pp::panopainter {
|
||||
|
||||
struct LegacyNodeStrokePreviewFrame {
|
||||
glm::vec4 col {};
|
||||
float flow = 0.0f;
|
||||
float opacity = 0.0f;
|
||||
std::array<vertex_t, 4> shapes {};
|
||||
glm::vec4 mixer_rect {};
|
||||
};
|
||||
|
||||
struct LegacyNodeStrokePreviewLiveRenderRequest {
|
||||
const Brush& brush;
|
||||
const LegacyNodeStrokePreviewPassOrchestrationPlan& pass_orchestration;
|
||||
const LegacyNodeStrokePreviewPreparedStrokes& prepared_strokes;
|
||||
Texture2D& stroke_texture;
|
||||
RTT& mixer_rtt;
|
||||
RTT& render_target;
|
||||
Texture2D& background_texture;
|
||||
Texture2D& dual_texture;
|
||||
Texture2D& preview_texture;
|
||||
Sampler& linear_sampler;
|
||||
Sampler& repeat_sampler;
|
||||
float zoom = 1.0f;
|
||||
float min_flow = 0.0f;
|
||||
bool copy_stroke_destination = false;
|
||||
glm::vec2 size {};
|
||||
std::function<void(const Brush&)> bind_dual_pass_textures;
|
||||
std::function<void(bool)> capture_background;
|
||||
std::function<std::vector<LegacyNodeStrokePreviewFrame>(const Stroke&, float)> compute_frames;
|
||||
std::function<glm::vec4(std::array<vertex_t, 4>&, Texture2D&, bool)> draw_samples;
|
||||
std::function<void(const glm::vec2&, const glm::vec2&)> draw_mix;
|
||||
std::function<void()> unbind_mixer_texture;
|
||||
std::function<void()> bind_pattern_texture;
|
||||
std::function<void()> draw_composite;
|
||||
};
|
||||
|
||||
[[nodiscard]] bool execute_legacy_node_stroke_preview_live_render_passes(
|
||||
const LegacyNodeStrokePreviewLiveRenderRequest& request);
|
||||
|
||||
} // namespace pp::panopainter
|
||||
250
src/legacy_ui_node_style.cpp
Normal file
250
src/legacy_ui_node_style.cpp
Normal file
@@ -0,0 +1,250 @@
|
||||
#include "pch.h"
|
||||
#include "legacy_ui_node_style.h"
|
||||
|
||||
#include "app.h"
|
||||
#include "node.h"
|
||||
|
||||
namespace pp::panopainter {
|
||||
|
||||
void legacy_ui_node_set_width(Node& node, float value)
|
||||
{
|
||||
YGNodeStyleSetWidth(node.y_node, value);
|
||||
node.m_size.x = value;
|
||||
node.auto_width = value == YGUndefined;
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_width_percent(Node& node, float value)
|
||||
{
|
||||
YGNodeStyleSetWidthPercent(node.y_node, value);
|
||||
node.auto_width = value == YGUndefined;
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_height(Node& node, float value)
|
||||
{
|
||||
YGNodeStyleSetHeight(node.y_node, value);
|
||||
node.m_size.y = value;
|
||||
node.auto_height = value == YGUndefined;
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_height_percent(Node& node, float value)
|
||||
{
|
||||
YGNodeStyleSetHeightPercent(node.y_node, value);
|
||||
node.auto_height = value == YGUndefined;
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_max_width(Node& node, float value)
|
||||
{
|
||||
YGNodeStyleSetMaxWidth(node.y_node, value);
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_max_width_percent(Node& node, float value)
|
||||
{
|
||||
YGNodeStyleSetMaxWidthPercent(node.y_node, value);
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_max_height(Node& node, float value)
|
||||
{
|
||||
YGNodeStyleSetMaxHeight(node.y_node, value);
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_max_height_percent(Node& node, float value)
|
||||
{
|
||||
YGNodeStyleSetMaxHeightPercent(node.y_node, value);
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_min_width(Node& node, float value)
|
||||
{
|
||||
YGNodeStyleSetMinWidth(node.y_node, value);
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_min_width_percent(Node& node, float value)
|
||||
{
|
||||
YGNodeStyleSetMinWidthPercent(node.y_node, value);
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_min_height(Node& node, float value)
|
||||
{
|
||||
YGNodeStyleSetMinHeight(node.y_node, value);
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_min_height_percent(Node& node, float value)
|
||||
{
|
||||
YGNodeStyleSetMinHeightPercent(node.y_node, value);
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_padding(Node& node, float t, float r, float b, float l)
|
||||
{
|
||||
YGNodeStyleSetPadding(node.y_node, YGEdgeTop, t);
|
||||
YGNodeStyleSetPadding(node.y_node, YGEdgeRight, r);
|
||||
YGNodeStyleSetPadding(node.y_node, YGEdgeBottom, b);
|
||||
YGNodeStyleSetPadding(node.y_node, YGEdgeLeft, l);
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
glm::vec4 legacy_ui_node_get_padding(const Node& node)
|
||||
{
|
||||
float t = YGNodeLayoutGetPadding(node.y_node, YGEdgeTop);
|
||||
float r = YGNodeLayoutGetPadding(node.y_node, YGEdgeRight);
|
||||
float b = YGNodeLayoutGetPadding(node.y_node, YGEdgeBottom);
|
||||
float l = YGNodeLayoutGetPadding(node.y_node, YGEdgeLeft);
|
||||
return { t, r, b, l };
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_margin(Node& node, float t, float r, float b, float l)
|
||||
{
|
||||
YGNodeStyleSetMargin(node.y_node, YGEdgeTop, t);
|
||||
YGNodeStyleSetMargin(node.y_node, YGEdgeRight, r);
|
||||
YGNodeStyleSetMargin(node.y_node, YGEdgeBottom, b);
|
||||
YGNodeStyleSetMargin(node.y_node, YGEdgeLeft, l);
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
glm::vec4 legacy_ui_node_get_margin(const Node& node)
|
||||
{
|
||||
float t = YGNodeLayoutGetMargin(node.y_node, YGEdgeTop);
|
||||
float r = YGNodeLayoutGetMargin(node.y_node, YGEdgeRight);
|
||||
float b = YGNodeLayoutGetMargin(node.y_node, YGEdgeBottom);
|
||||
float l = YGNodeLayoutGetMargin(node.y_node, YGEdgeLeft);
|
||||
return { t, r, b, l };
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_position(Node& node, float l, float t)
|
||||
{
|
||||
YGNodeStyleSetPosition(node.y_node, YGEdgeTop, t);
|
||||
YGNodeStyleSetPosition(node.y_node, YGEdgeLeft, l);
|
||||
node.m_pos = { l, t };
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_position(Node& node, float l, float t, float r, float b)
|
||||
{
|
||||
YGNodeStyleSetPosition(node.y_node, YGEdgeTop, t);
|
||||
YGNodeStyleSetPosition(node.y_node, YGEdgeRight, r);
|
||||
YGNodeStyleSetPosition(node.y_node, YGEdgeBottom, b);
|
||||
YGNodeStyleSetPosition(node.y_node, YGEdgeLeft, l);
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_flex_grow(Node& node, float value)
|
||||
{
|
||||
YGNodeStyleSetFlexGrow(node.y_node, value);
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_flex_shrink(Node& node, float value)
|
||||
{
|
||||
YGNodeStyleSetFlexShrink(node.y_node, value);
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_flex_dir(Node& node, YGFlexDirection value)
|
||||
{
|
||||
YGNodeStyleSetFlexDirection(node.y_node, value);
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_flex_wrap(Node& node, YGWrap value)
|
||||
{
|
||||
YGNodeStyleSetFlexWrap(node.y_node, value);
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_justify(Node& node, YGJustify value)
|
||||
{
|
||||
YGNodeStyleSetJustifyContent(node.y_node, value);
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_align(Node& node, YGAlign value)
|
||||
{
|
||||
YGNodeStyleSetAlignItems(node.y_node, value);
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_positioning(Node& node, YGPositionType value)
|
||||
{
|
||||
YGNodeStyleSetPositionType(node.y_node, value);
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_aspect_ratio(Node& node, float ar)
|
||||
{
|
||||
YGNodeStyleSetAspectRatio(node.y_node, ar);
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_rtl(Node& node, YGDirection dir)
|
||||
{
|
||||
YGNodeStyleSetDirection(node.y_node, dir);
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
bool legacy_ui_node_get_visibility(const Node& node)
|
||||
{
|
||||
return node.m_display;
|
||||
}
|
||||
|
||||
void legacy_ui_node_set_visibility(Node& node, bool visible)
|
||||
{
|
||||
App::I->ui_task([&node, visible]
|
||||
{
|
||||
if (node.m_display && !visible)
|
||||
{
|
||||
int idx = node.m_parent->get_child_index(&node);
|
||||
YGNodeRemoveChild(node.m_parent->y_node, node.y_node);
|
||||
node.y_placeholder = YGNodeNew();
|
||||
YGNodeInsertChild(node.m_parent->y_node, node.y_placeholder, idx);
|
||||
}
|
||||
else if (!node.m_display && visible)
|
||||
{
|
||||
int count = YGNodeGetChildCount(node.m_parent->y_node);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (YGNodeGetChild(node.m_parent->y_node, i) == node.y_placeholder)
|
||||
{
|
||||
YGNodeRemoveChild(node.m_parent->y_node, node.y_placeholder);
|
||||
YGNodeInsertChild(node.m_parent->y_node, node.y_node, i);
|
||||
YGNodeFree(node.y_placeholder);
|
||||
node.y_placeholder = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
node.m_display = visible;
|
||||
node.app_redraw();
|
||||
}
|
||||
|
||||
glm::vec2 legacy_ui_node_get_position(const Node& node)
|
||||
{
|
||||
return { YGNodeLayoutGetLeft(node.y_node), YGNodeLayoutGetTop(node.y_node) };
|
||||
}
|
||||
|
||||
float legacy_ui_node_get_width(const Node& node)
|
||||
{
|
||||
return YGNodeLayoutGetWidth(node.y_node);
|
||||
}
|
||||
|
||||
float legacy_ui_node_get_height(const Node& node)
|
||||
{
|
||||
return YGNodeLayoutGetHeight(node.y_node);
|
||||
}
|
||||
|
||||
YGDirection legacy_ui_node_get_rtl(const Node& node)
|
||||
{
|
||||
return YGNodeStyleGetDirection(node.y_node);
|
||||
}
|
||||
|
||||
} // namespace pp::panopainter
|
||||
45
src/legacy_ui_node_style.h
Normal file
45
src/legacy_ui_node_style.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <glm/vec2.hpp>
|
||||
#include <glm/vec4.hpp>
|
||||
#include <yoga/Yoga.h>
|
||||
|
||||
class Node;
|
||||
|
||||
namespace pp::panopainter {
|
||||
|
||||
void legacy_ui_node_set_width(Node& node, float value);
|
||||
void legacy_ui_node_set_width_percent(Node& node, float value);
|
||||
void legacy_ui_node_set_height(Node& node, float value);
|
||||
void legacy_ui_node_set_height_percent(Node& node, float value);
|
||||
void legacy_ui_node_set_max_width(Node& node, float value);
|
||||
void legacy_ui_node_set_max_width_percent(Node& node, float value);
|
||||
void legacy_ui_node_set_max_height(Node& node, float value);
|
||||
void legacy_ui_node_set_max_height_percent(Node& node, float value);
|
||||
void legacy_ui_node_set_min_width(Node& node, float value);
|
||||
void legacy_ui_node_set_min_width_percent(Node& node, float value);
|
||||
void legacy_ui_node_set_min_height(Node& node, float value);
|
||||
void legacy_ui_node_set_min_height_percent(Node& node, float value);
|
||||
void legacy_ui_node_set_padding(Node& node, float t, float r, float b, float l);
|
||||
glm::vec4 legacy_ui_node_get_padding(const Node& node);
|
||||
void legacy_ui_node_set_margin(Node& node, float t, float r, float b, float l);
|
||||
glm::vec4 legacy_ui_node_get_margin(const Node& node);
|
||||
void legacy_ui_node_set_position(Node& node, float l, float t);
|
||||
void legacy_ui_node_set_position(Node& node, float l, float t, float r, float b);
|
||||
void legacy_ui_node_set_flex_grow(Node& node, float value);
|
||||
void legacy_ui_node_set_flex_shrink(Node& node, float value);
|
||||
void legacy_ui_node_set_flex_dir(Node& node, YGFlexDirection value);
|
||||
void legacy_ui_node_set_flex_wrap(Node& node, YGWrap value);
|
||||
void legacy_ui_node_set_justify(Node& node, YGJustify value);
|
||||
void legacy_ui_node_set_align(Node& node, YGAlign value);
|
||||
void legacy_ui_node_set_positioning(Node& node, YGPositionType value);
|
||||
void legacy_ui_node_set_aspect_ratio(Node& node, float ar);
|
||||
void legacy_ui_node_set_rtl(Node& node, YGDirection dir);
|
||||
bool legacy_ui_node_get_visibility(const Node& node);
|
||||
void legacy_ui_node_set_visibility(Node& node, bool visible);
|
||||
glm::vec2 legacy_ui_node_get_position(const Node& node);
|
||||
float legacy_ui_node_get_width(const Node& node);
|
||||
float legacy_ui_node_get_height(const Node& node);
|
||||
YGDirection legacy_ui_node_get_rtl(const Node& node);
|
||||
|
||||
} // namespace pp::panopainter
|
||||
144
src/node.cpp
144
src/node.cpp
@@ -4,6 +4,7 @@
|
||||
#include "legacy_ui_node_attributes.h"
|
||||
#include "legacy_ui_node_event.h"
|
||||
#include "legacy_ui_node_loader.h"
|
||||
#include "legacy_ui_node_style.h"
|
||||
#include "node.h"
|
||||
#include "layout.h"
|
||||
#include "util.h"
|
||||
@@ -163,32 +164,22 @@ Node::~Node()
|
||||
|
||||
void Node::SetWidth(float value)
|
||||
{
|
||||
YGNodeStyleSetWidth(y_node, value);
|
||||
m_size.x = value;
|
||||
auto_width = value == YGUndefined;
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_width(*this, value);
|
||||
}
|
||||
|
||||
void Node::SetWidthP(float value)
|
||||
{
|
||||
YGNodeStyleSetWidthPercent(y_node, value);
|
||||
auto_width = value == YGUndefined;
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_width_percent(*this, value);
|
||||
}
|
||||
|
||||
void Node::SetHeight(float value)
|
||||
{
|
||||
YGNodeStyleSetHeight(y_node, value);
|
||||
m_size.y = value;
|
||||
auto_height = value == YGUndefined;
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_height(*this, value);
|
||||
}
|
||||
|
||||
void Node::SetHeightP(float value)
|
||||
{
|
||||
YGNodeStyleSetHeightPercent(y_node, value);
|
||||
auto_height = value == YGUndefined;
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_height_percent(*this, value);
|
||||
}
|
||||
|
||||
void Node::SetSize(float w, float h)
|
||||
@@ -231,86 +222,62 @@ void Node::SetMaxSize(glm::vec2 value)
|
||||
|
||||
void Node::SetMaxWidth(float value)
|
||||
{
|
||||
YGNodeStyleSetMaxWidth(y_node, value);
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_max_width(*this, value);
|
||||
}
|
||||
|
||||
void Node::SetMaxWidthP(float value)
|
||||
{
|
||||
YGNodeStyleSetMaxWidthPercent(y_node, value);
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_max_width_percent(*this, value);
|
||||
}
|
||||
|
||||
void Node::SetMaxHeight(float value)
|
||||
{
|
||||
YGNodeStyleSetMaxHeight(y_node, value);
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_max_height(*this, value);
|
||||
}
|
||||
|
||||
void Node::SetMaxHeightP(float value)
|
||||
{
|
||||
YGNodeStyleSetMaxHeightPercent(y_node, value);
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_max_height_percent(*this, value);
|
||||
}
|
||||
|
||||
void Node::SetMinWidth(float value)
|
||||
{
|
||||
YGNodeStyleSetMinWidth(y_node, value);
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_min_width(*this, value);
|
||||
}
|
||||
|
||||
void Node::SetMinWidthP(float value)
|
||||
{
|
||||
YGNodeStyleSetMinWidthPercent(y_node, value);
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_min_width_percent(*this, value);
|
||||
}
|
||||
|
||||
void Node::SetMinHeight(float value)
|
||||
{
|
||||
YGNodeStyleSetMinHeight(y_node, value);
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_min_height(*this, value);
|
||||
}
|
||||
|
||||
void Node::SetMinHeightP(float value)
|
||||
{
|
||||
YGNodeStyleSetMinHeightPercent(y_node, value);
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_min_height_percent(*this, value);
|
||||
}
|
||||
|
||||
void Node::SetPadding(float t, float r, float b, float l)
|
||||
{
|
||||
YGNodeStyleSetPadding(y_node, YGEdgeTop, t);
|
||||
YGNodeStyleSetPadding(y_node, YGEdgeRight, r);
|
||||
YGNodeStyleSetPadding(y_node, YGEdgeBottom, b);
|
||||
YGNodeStyleSetPadding(y_node, YGEdgeLeft, l);
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_padding(*this, t, r, b, l);
|
||||
}
|
||||
|
||||
glm::vec4 Node::GetPadding() const
|
||||
{
|
||||
float t = YGNodeLayoutGetPadding(y_node, YGEdgeTop);
|
||||
float r = YGNodeLayoutGetPadding(y_node, YGEdgeRight);
|
||||
float b = YGNodeLayoutGetPadding(y_node, YGEdgeBottom);
|
||||
float l = YGNodeLayoutGetPadding(y_node, YGEdgeLeft);
|
||||
return{ t, r, b, l };
|
||||
return pp::panopainter::legacy_ui_node_get_padding(*this);
|
||||
}
|
||||
|
||||
void Node::SetMargin(float t, float r, float b, float l)
|
||||
{
|
||||
YGNodeStyleSetMargin(y_node, YGEdgeTop, t);
|
||||
YGNodeStyleSetMargin(y_node, YGEdgeRight, r);
|
||||
YGNodeStyleSetMargin(y_node, YGEdgeBottom, b);
|
||||
YGNodeStyleSetMargin(y_node, YGEdgeLeft, l);
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_margin(*this, t, r, b, l);
|
||||
}
|
||||
|
||||
glm::vec4 Node::GetMargin() const
|
||||
{
|
||||
float t = YGNodeLayoutGetMargin(y_node, YGEdgeTop);
|
||||
float r = YGNodeLayoutGetMargin(y_node, YGEdgeRight);
|
||||
float b = YGNodeLayoutGetMargin(y_node, YGEdgeBottom);
|
||||
float l = YGNodeLayoutGetMargin(y_node, YGEdgeLeft);
|
||||
return{ t, r, b, l };
|
||||
return pp::panopainter::legacy_ui_node_get_margin(*this);
|
||||
}
|
||||
|
||||
void Node::SetPosition(const glm::vec2 pos)
|
||||
@@ -322,110 +289,67 @@ void Node::SetPosition(const glm::vec2 pos)
|
||||
|
||||
void Node::SetPosition(float l, float t)
|
||||
{
|
||||
YGNodeStyleSetPosition(y_node, YGEdgeTop, t);
|
||||
YGNodeStyleSetPosition(y_node, YGEdgeLeft, l);
|
||||
m_pos = {l, t};
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_position(*this, l, t);
|
||||
}
|
||||
|
||||
void Node::SetPosition(float l, float t, float r, float b)
|
||||
{
|
||||
YGNodeStyleSetPosition(y_node, YGEdgeTop, t);
|
||||
YGNodeStyleSetPosition(y_node, YGEdgeRight, r);
|
||||
YGNodeStyleSetPosition(y_node, YGEdgeBottom, b);
|
||||
YGNodeStyleSetPosition(y_node, YGEdgeLeft, l);
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_position(*this, l, t, r, b);
|
||||
}
|
||||
|
||||
void Node::SetFlexGrow(float value)
|
||||
{
|
||||
YGNodeStyleSetFlexGrow(y_node, value);
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_flex_grow(*this, value);
|
||||
}
|
||||
|
||||
void Node::SetFlexShrink(float value)
|
||||
{
|
||||
YGNodeStyleSetFlexShrink(y_node, value);
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_flex_shrink(*this, value);
|
||||
}
|
||||
|
||||
void Node::SetFlexDir(YGFlexDirection value)
|
||||
{
|
||||
YGNodeStyleSetFlexDirection(y_node, value);
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_flex_dir(*this, value);
|
||||
}
|
||||
|
||||
void Node::SetFlexWrap(YGWrap value)
|
||||
{
|
||||
YGNodeStyleSetFlexWrap(y_node, value);
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_flex_wrap(*this, value);
|
||||
}
|
||||
|
||||
void Node::SetJustify(YGJustify value)
|
||||
{
|
||||
YGNodeStyleSetJustifyContent(y_node, value);
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_justify(*this, value);
|
||||
}
|
||||
|
||||
void Node::SetAlign(YGAlign value)
|
||||
{
|
||||
YGNodeStyleSetAlignItems(y_node, value);
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_align(*this, value);
|
||||
}
|
||||
|
||||
void Node::SetPositioning(YGPositionType value)
|
||||
{
|
||||
YGNodeStyleSetPositionType(y_node, value);
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_positioning(*this, value);
|
||||
}
|
||||
|
||||
void Node::SetAspectRatio(float ar)
|
||||
{
|
||||
YGNodeStyleSetAspectRatio(y_node, ar);
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_aspect_ratio(*this, ar);
|
||||
}
|
||||
|
||||
void Node::SetRTL(YGDirection dir)
|
||||
{
|
||||
YGNodeStyleSetDirection(y_node, dir);
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_rtl(*this, dir);
|
||||
}
|
||||
|
||||
bool Node::GetVisibility()
|
||||
{
|
||||
return m_display;
|
||||
return pp::panopainter::legacy_ui_node_get_visibility(*this);
|
||||
}
|
||||
|
||||
void Node::SetVisibility(bool visible)
|
||||
{
|
||||
App::I->ui_task([&]
|
||||
{
|
||||
if (m_display && !visible)
|
||||
{
|
||||
// hide
|
||||
int idx = m_parent->get_child_index(this);
|
||||
YGNodeRemoveChild(m_parent->y_node, y_node);
|
||||
y_placeholder = YGNodeNew();
|
||||
YGNodeInsertChild(m_parent->y_node, y_placeholder, idx);
|
||||
}
|
||||
else if (!m_display && visible)
|
||||
{
|
||||
int count = YGNodeGetChildCount(m_parent->y_node);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (YGNodeGetChild(m_parent->y_node, i) == y_placeholder)
|
||||
{
|
||||
YGNodeRemoveChild(m_parent->y_node, y_placeholder);
|
||||
YGNodeInsertChild(m_parent->y_node, y_node, i);
|
||||
YGNodeFree(y_placeholder);
|
||||
y_placeholder = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
m_display = visible;
|
||||
app_redraw();
|
||||
pp::panopainter::legacy_ui_node_set_visibility(*this, visible);
|
||||
}
|
||||
|
||||
void Node::ToggleVisibility()
|
||||
@@ -435,17 +359,17 @@ void Node::ToggleVisibility()
|
||||
|
||||
glm::vec2 Node::GetPosition()
|
||||
{
|
||||
return { YGNodeLayoutGetLeft(y_node), YGNodeLayoutGetTop(y_node) };
|
||||
return pp::panopainter::legacy_ui_node_get_position(*this);
|
||||
}
|
||||
|
||||
float Node::GetWidth()
|
||||
{
|
||||
return YGNodeLayoutGetWidth(y_node);
|
||||
return pp::panopainter::legacy_ui_node_get_width(*this);
|
||||
}
|
||||
|
||||
float Node::GetHeight()
|
||||
{
|
||||
return YGNodeLayoutGetHeight(y_node);
|
||||
return pp::panopainter::legacy_ui_node_get_height(*this);
|
||||
}
|
||||
|
||||
glm::vec2 Node::GetSize()
|
||||
@@ -455,7 +379,7 @@ glm::vec2 Node::GetSize()
|
||||
|
||||
YGDirection Node::GetRTL()
|
||||
{
|
||||
return YGNodeStyleGetDirection(y_node);
|
||||
return pp::panopainter::legacy_ui_node_get_rtl(*this);
|
||||
}
|
||||
|
||||
void Node::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
|
||||
|
||||
@@ -448,9 +448,9 @@ glm::vec4 NodeStrokePreview::stroke_draw_samples(
|
||||
copy_stroke_destination);
|
||||
}
|
||||
|
||||
std::vector<NodeStrokePreview::StrokeFrame> NodeStrokePreview::stroke_draw_compute(Stroke& stroke, float zoom) const
|
||||
std::vector<NodeStrokePreview::StrokeFrame> NodeStrokePreview::stroke_draw_compute(const Stroke& stroke, float zoom) const
|
||||
{
|
||||
auto samples = stroke.compute_samples();
|
||||
auto samples = const_cast<Stroke&>(stroke).compute_samples();
|
||||
StrokeSample previous_sample = stroke.m_prev_sample;
|
||||
previous_sample.size *= zoom;
|
||||
for (auto& sample : samples) {
|
||||
@@ -475,13 +475,13 @@ std::vector<NodeStrokePreview::StrokeFrame> NodeStrokePreview::stroke_draw_compu
|
||||
glm::vec4 color,
|
||||
float flow,
|
||||
float opacity,
|
||||
std::array<vertex_t, 4>&& shapes) {
|
||||
std::array<vertex_t, 4>&& shapes) -> StrokeFrame {
|
||||
return StrokeFrame {
|
||||
.col = color,
|
||||
.flow = flow,
|
||||
.opacity = opacity,
|
||||
.shapes = std::move(shapes),
|
||||
.m_mixer_rect = mixer_rect,
|
||||
.mixer_rect = mixer_rect,
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -548,102 +548,55 @@ void NodeStrokePreview::draw_stroke_immediate()
|
||||
size,
|
||||
*b,
|
||||
ortho_proj));
|
||||
const bool copy_stroke_destination = pass_orchestration.copy_stroke_destination;
|
||||
pp::panopainter::setup_legacy_stroke_shader(pass_orchestration.stroke_shader);
|
||||
const bool sequence_ok = pp::panopainter::execute_legacy_node_stroke_preview_draw_immediate_shell<StrokeFrame>(
|
||||
*b,
|
||||
pass_orchestration,
|
||||
m_tex,
|
||||
m_rtt_mixer,
|
||||
m_rtt,
|
||||
m_tex_background,
|
||||
m_tex_dual,
|
||||
m_tex_preview,
|
||||
m_sampler_linear,
|
||||
m_sampler_linear_repeat,
|
||||
copy_stroke_destination,
|
||||
size,
|
||||
pp::panopainter::kLegacyNodeStrokePreviewStrokeTextureSlot,
|
||||
[&] {
|
||||
if (!pass_orchestration.material.dual_pass.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
pp::panopainter::setup_legacy_stroke_dual_shader(pass_orchestration.material.dual_pass.uses_pattern);
|
||||
bind_stroke_preview_dual_pass_textures(*prepared_strokes.dual_brush);
|
||||
pp::panopainter::execute_legacy_stroke_preview_live_pass(
|
||||
[&] {
|
||||
m_rtt.clear();
|
||||
},
|
||||
[&] {
|
||||
return stroke_draw_compute(prepared_strokes.dual_stroke, zoom);
|
||||
},
|
||||
[](auto& frame) {
|
||||
frame.col = { 0, 0, 0, 1 };
|
||||
},
|
||||
[&](auto& frame) {
|
||||
pp::panopainter::use_legacy_stroke_shader();
|
||||
pp::panopainter::apply_legacy_stroke_sample_uniforms(
|
||||
pp::panopainter::LegacyStrokeSampleUniforms {
|
||||
.color = frame.col,
|
||||
.alpha = frame.flow,
|
||||
.opacity = frame.opacity,
|
||||
});
|
||||
},
|
||||
[&](auto& frame) {
|
||||
/*auto rect =*/ stroke_draw_samples(frame.shapes, m_tex_dual, copy_stroke_destination);
|
||||
},
|
||||
[&] {
|
||||
pp::panopainter::copy_legacy_node_stroke_preview_framebuffer_to_texture(
|
||||
m_tex_dual,
|
||||
size,
|
||||
pp::panopainter::kLegacyNodeStrokePreviewStrokeTextureSlot);
|
||||
});
|
||||
},
|
||||
[&] {
|
||||
execute_stroke_preview_background_capture_pass(
|
||||
size,
|
||||
pass_orchestration.background_colorize,
|
||||
m_tex_background,
|
||||
[&] {
|
||||
m_plane.draw_fill();
|
||||
});
|
||||
},
|
||||
[&] {
|
||||
return stroke_draw_compute(prepared_strokes.stroke, zoom);
|
||||
},
|
||||
[&](auto& frame) {
|
||||
if (b->m_tip_mix > 0.f)
|
||||
{
|
||||
stroke_draw_mix(xy(frame.m_mixer_rect), zw(frame.m_mixer_rect));
|
||||
}
|
||||
|
||||
frame.col = b->m_blend_mode != 0 || b->m_tip_mix > 0.f ?
|
||||
glm::vec4 { .7, .4, .1, 1 } :
|
||||
glm::vec4 { 0, 0, 0, 1 };
|
||||
frame.flow = glm::max(frame.flow, m_min_flow);
|
||||
},
|
||||
[&](auto& frame) {
|
||||
pp::panopainter::use_legacy_stroke_shader();
|
||||
pp::panopainter::apply_legacy_stroke_sample_uniforms(
|
||||
pp::panopainter::LegacyStrokeSampleUniforms {
|
||||
.color = frame.col,
|
||||
.alpha = frame.flow,
|
||||
.opacity = frame.opacity,
|
||||
});
|
||||
},
|
||||
[&](auto& frame) {
|
||||
/*auto rect =*/ stroke_draw_samples(frame.shapes, m_tex, copy_stroke_destination);
|
||||
},
|
||||
[&] {
|
||||
set_active_texture_unit(3U);
|
||||
m_rtt_mixer.unbindTexture();
|
||||
},
|
||||
[&] {
|
||||
b->m_pattern_texture ? b->m_pattern_texture->bind() : unbind_texture_2d();
|
||||
},
|
||||
[&] {
|
||||
m_plane.draw_fill();
|
||||
const bool sequence_ok = pp::panopainter::execute_legacy_node_stroke_preview_live_render_passes(
|
||||
pp::panopainter::LegacyNodeStrokePreviewLiveRenderRequest {
|
||||
.brush = *b,
|
||||
.pass_orchestration = pass_orchestration,
|
||||
.prepared_strokes = prepared_strokes,
|
||||
.stroke_texture = m_tex,
|
||||
.mixer_rtt = m_rtt_mixer,
|
||||
.render_target = m_rtt,
|
||||
.background_texture = m_tex_background,
|
||||
.dual_texture = m_tex_dual,
|
||||
.preview_texture = m_tex_preview,
|
||||
.linear_sampler = m_sampler_linear,
|
||||
.repeat_sampler = m_sampler_linear_repeat,
|
||||
.zoom = zoom,
|
||||
.min_flow = m_min_flow,
|
||||
.copy_stroke_destination = pass_orchestration.copy_stroke_destination,
|
||||
.size = size,
|
||||
.bind_dual_pass_textures = [](const Brush& dual_brush) {
|
||||
bind_stroke_preview_dual_pass_textures(dual_brush);
|
||||
},
|
||||
.capture_background = [&](bool colorize) {
|
||||
execute_stroke_preview_background_capture_pass(
|
||||
size,
|
||||
colorize,
|
||||
m_tex_background,
|
||||
[&] {
|
||||
m_plane.draw_fill();
|
||||
});
|
||||
},
|
||||
.compute_frames = [&](const Stroke& stroke, float frame_zoom) {
|
||||
return stroke_draw_compute(stroke, frame_zoom);
|
||||
},
|
||||
.draw_samples = [&](std::array<vertex_t, 4>& shapes, Texture2D& texture, bool copy_stroke_destination) {
|
||||
return stroke_draw_samples(shapes, texture, copy_stroke_destination);
|
||||
},
|
||||
.draw_mix = [&](const glm::vec2& bb_min, const glm::vec2& bb_sz) {
|
||||
stroke_draw_mix(bb_min, bb_sz);
|
||||
},
|
||||
.unbind_mixer_texture = [&] {
|
||||
set_active_texture_unit(3U);
|
||||
m_rtt_mixer.unbindTexture();
|
||||
},
|
||||
.bind_pattern_texture = [&] {
|
||||
b->m_pattern_texture ? b->m_pattern_texture->bind() : unbind_texture_2d();
|
||||
},
|
||||
.draw_composite = [&] {
|
||||
m_plane.draw_fill();
|
||||
},
|
||||
});
|
||||
assert(sequence_ok);
|
||||
|
||||
|
||||
@@ -5,20 +5,12 @@
|
||||
#include "rtt.h"
|
||||
#include "brush.h"
|
||||
#include "texture.h"
|
||||
#include "legacy_node_stroke_preview_draw_services.h"
|
||||
#include "legacy_node_stroke_preview_execution_services.h"
|
||||
|
||||
class NodeStrokePreview : public NodeBorder
|
||||
{
|
||||
struct StrokeFrame
|
||||
{
|
||||
glm::vec4 col;
|
||||
float flow;
|
||||
float opacity;
|
||||
std::array<vertex_t, 4> shapes;
|
||||
glm::vec4 m_mixer_rect;
|
||||
};
|
||||
|
||||
using StrokeMainLivePassRequest = pp::panopainter::LegacyNodeStrokePreviewMainLivePassRequestT<StrokeFrame>;
|
||||
using StrokeFrame = pp::panopainter::LegacyNodeStrokePreviewFrame;
|
||||
|
||||
static RTT m_rtt;
|
||||
static RTT m_rtt_mixer;
|
||||
@@ -55,7 +47,7 @@ public:
|
||||
void stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2& bb_sz);
|
||||
// return rect {origin, size}
|
||||
glm::vec4 stroke_draw_samples(std::array<vertex_t, 4>& P, Texture2D& blend_tex, bool copy_stroke_destination);
|
||||
std::vector<StrokeFrame> stroke_draw_compute(Stroke& stroke, float zoom) const;
|
||||
std::vector<StrokeFrame> stroke_draw_compute(const Stroke& stroke, float zoom) const;
|
||||
void draw_stroke();
|
||||
void draw_stroke_immediate();
|
||||
Image render_to_image();
|
||||
|
||||
Reference in New Issue
Block a user