Extract fill modes, preview runtime pockets, and brush item UI
This commit is contained in:
@@ -85,6 +85,7 @@ set(PP_LEGACY_UI_CORE_SOURCES
|
||||
|
||||
set(PP_LEGACY_APP_SOURCES
|
||||
src/canvas_modes.cpp
|
||||
src/legacy_canvas_mode_fill.cpp
|
||||
src/legacy_canvas_mode_pen_line.cpp
|
||||
src/legacy_canvas_mode_helpers.cpp
|
||||
src/legacy_canvas_mode_helpers.h
|
||||
@@ -151,6 +152,8 @@ set(PP_PANOPAINTER_APP_SOURCES
|
||||
src/legacy_brush_package_import_services.h
|
||||
src/legacy_brush_package_export_services.cpp
|
||||
src/legacy_brush_package_export_services.h
|
||||
src/legacy_brush_panel_item_ui.cpp
|
||||
src/legacy_brush_panel_item_ui.h
|
||||
src/legacy_brush_preset_services.cpp
|
||||
src/legacy_brush_preset_services.h
|
||||
src/legacy_cloud_services.cpp
|
||||
|
||||
@@ -81,11 +81,11 @@ Current hotspot files:
|
||||
|
||||
- `src/canvas.cpp`: 17 lines
|
||||
- `src/app_layout.cpp`: 125 lines
|
||||
- `src/canvas_modes.cpp`: 402 lines
|
||||
- `src/canvas_modes.cpp`: 176 lines
|
||||
- `src/node.cpp`: 260 lines
|
||||
- `src/main.cpp`: 130 lines
|
||||
- `src/node_panel_brush.cpp`: 231 lines
|
||||
- `src/node_stroke_preview.cpp`: 343 lines
|
||||
- `src/node_panel_brush.cpp`: 189 lines
|
||||
- `src/node_stroke_preview.cpp`: 280 lines
|
||||
- `src/node_canvas.cpp`: 219 lines
|
||||
- `src/app.cpp`: 113 lines
|
||||
- `src/app_dialogs.cpp`: 168 lines
|
||||
@@ -309,6 +309,10 @@ Current architecture mismatches that must be treated as real blockers:
|
||||
`CanvasModeLine` interaction families now also route through
|
||||
`src/legacy_canvas_mode_pen_line.cpp` instead of staying inline in
|
||||
`src/canvas_modes.cpp`,
|
||||
while the `CanvasModeFill` and `CanvasModeFloodFill` interaction families now
|
||||
also route through `src/legacy_canvas_mode_fill.cpp` instead of staying
|
||||
inline in `src/canvas_modes.cpp`, which materially thins another retained
|
||||
fill-mode execution pocket from the broader canvas/render hotspot family,
|
||||
while `NodePanelBrush` save/restore/scan/reload/find/get-path ownership now
|
||||
routes through `src/legacy_brush_panel_services.*` instead of staying inline
|
||||
in `src/node_panel_brush.cpp`, which trims another retained brush-workflow
|
||||
@@ -324,7 +328,13 @@ Current architecture mismatches that must be treated as real blockers:
|
||||
panel UI pocket, while the retained `LegacyBrushPresetListServices` block
|
||||
now also lives in `src/legacy_brush_preset_list_services.*` instead of
|
||||
staying inline in `src/node_panel_brush.cpp`, which trims another retained
|
||||
preset popup tail now also lives in `src/legacy_brush_preset_panel_ui.*`
|
||||
preset-list pocket, while `NodeButtonBrush` clone/init/icon/read/write/draw
|
||||
behavior and `NodeBrushPresetItem` clone/init/draw behavior now also live in
|
||||
`src/legacy_brush_panel_item_ui.*` instead of staying inline in
|
||||
`src/node_panel_brush.cpp`, which trims the remaining brush-item UI pocket
|
||||
from the live brush panel file, while `NodePanelBrushPreset` popup-close
|
||||
event handling now also lives in
|
||||
`src/legacy_brush_preset_panel_ui.*`
|
||||
instead of staying inline in `src/node_panel_brush.cpp`, which removes the
|
||||
last inline brush-panel popup close handler from the live node. The
|
||||
broader preset workflow pocket still remains, while `NodeCanvas::handle_event()`
|
||||
|
||||
@@ -132,6 +132,10 @@ Current slice:
|
||||
`src/legacy_canvas_mode_transform.cpp` instead of staying inline in
|
||||
`src/canvas_modes.cpp`, which materially thins another retained
|
||||
transform-mode pocket from the broader canvas/render hotspot family.
|
||||
- The `CanvasModeFill` and `CanvasModeFloodFill` interaction families now
|
||||
also live in `src/legacy_canvas_mode_fill.cpp` instead of staying inline in
|
||||
`src/canvas_modes.cpp`, which materially thins another retained fill-mode
|
||||
pocket from the live canvas-mode shell.
|
||||
- The live `Canvas::stroke_draw()` orchestration now also lives in
|
||||
`src/legacy_canvas_stroke_live_services.cpp` instead of staying inline in
|
||||
`src/canvas.cpp`, which materially thins another large retained live
|
||||
@@ -231,6 +235,9 @@ Current slice:
|
||||
which trims another coherent setup pocket from
|
||||
`src/node_stroke_preview.cpp` even though worker/readback ownership and
|
||||
broader preview flow still remain inline.
|
||||
- `src/node_stroke_preview.cpp` is now 280 lines after moving the preview
|
||||
background-capture and stroke-frame planning pocket into
|
||||
`legacy_node_stroke_preview_runtime_services.*`.
|
||||
- The remaining immediate preview pass shell in
|
||||
`NodeStrokePreview::draw_stroke_immediate()` now also routes through
|
||||
`execute_legacy_node_stroke_preview_draw_immediate_shell(...)`, which
|
||||
@@ -1133,6 +1140,11 @@ Current slice:
|
||||
`src/node_panel_brush.cpp`, which trims a coherent retained brush-workflow
|
||||
pocket from the live UI node even though cloud and package-worker ownership
|
||||
still remain separate follow-up work.
|
||||
- `NodeButtonBrush` clone/init/icon/read/write/draw behavior and
|
||||
`NodeBrushPresetItem` clone/init/draw behavior now also live in
|
||||
`src/legacy_brush_panel_item_ui.*` instead of staying inline in
|
||||
`src/node_panel_brush.cpp`, which trims the remaining brush-item UI pocket
|
||||
from the live brush panel file.
|
||||
- `NodePanelBrushPreset` save/restore plus PPBR/ABR import/export routing now
|
||||
also lives in `src/legacy_brush_preset_services.*` instead of staying inline
|
||||
in `src/node_panel_brush.cpp`, which trims another large preset-workflow
|
||||
|
||||
@@ -189,245 +189,3 @@ void ActionModeGrid::undo()
|
||||
m_mode->m_selected_index = m_selected_index;
|
||||
m_mode->m_lines = m_lines;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
90
src/legacy_brush_panel_item_ui.cpp
Normal file
90
src/legacy_brush_panel_item_ui.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "legacy_brush_panel_item_ui.h"
|
||||
|
||||
#include "app.h"
|
||||
#include "texture.h"
|
||||
|
||||
namespace pp::panopainter {
|
||||
|
||||
Node* clone_legacy_brush_button(const NodeButtonBrush&)
|
||||
{
|
||||
return new NodeButtonBrush();
|
||||
}
|
||||
|
||||
void init_legacy_brush_button(NodeButtonBrush& owner)
|
||||
{
|
||||
owner.init_template_file("data/dialogs/panel-brushes.xml", "tpl-brush-icon");
|
||||
owner.color_hover = glm::vec4(.7, .7, .7, 1);
|
||||
owner.color_normal = glm::vec4(.3, .3, .3, 1);
|
||||
owner.m_color = owner.color_normal;
|
||||
owner.img = (NodeImage*)owner.m_children[0].get();
|
||||
}
|
||||
|
||||
void set_legacy_brush_button_icon(NodeButtonBrush& owner, const char* path)
|
||||
{
|
||||
owner.img->m_path = path;
|
||||
owner.img->m_tex_id = const_hash(owner.img->m_path.c_str());
|
||||
owner.img->m_use_mipmaps = true;
|
||||
owner.img->create();
|
||||
}
|
||||
|
||||
void draw_legacy_brush_button(NodeButtonBrush& owner)
|
||||
{
|
||||
owner.m_color = owner.m_mouse_inside ? owner.color_hover : owner.color_normal;
|
||||
owner.m_color = owner.m_selected ? glm::vec4(.9, 0, 0, 1) : owner.m_color;
|
||||
owner.NodeButtonCustom::draw();
|
||||
}
|
||||
|
||||
bool read_legacy_brush_button(NodeButtonBrush& owner, BinaryStreamReader& r)
|
||||
{
|
||||
Serializer::Descriptor d;
|
||||
r >> d;
|
||||
d.value<Serializer::CString>("brush_name", owner.brush_name);
|
||||
d.value<Serializer::CString>("high_path", owner.high_path);
|
||||
d.value<Serializer::CString>("thumb_path", owner.thumb_path);
|
||||
d.value<Serializer::Boolean>("m_user_brush", owner.m_user_brush);
|
||||
owner.high_path = str_replace(owner.high_path, "{data_path}", App::I->data_path);
|
||||
owner.thumb_path = str_replace(owner.thumb_path, "{data_path}", App::I->data_path);
|
||||
return true;
|
||||
}
|
||||
|
||||
void write_legacy_brush_button(const NodeButtonBrush& owner, BinaryStreamWriter& w)
|
||||
{
|
||||
Serializer::Descriptor d;
|
||||
d.class_id = "brush";
|
||||
d.name = L"Brush class";
|
||||
d.props["brush_name"] = std::make_shared<Serializer::CString>(owner.brush_name);
|
||||
d.props["high_path"] = std::make_shared<Serializer::CString>(
|
||||
str_replace(owner.high_path, App::I->data_path, "{data_path}"));
|
||||
d.props["thumb_path"] = std::make_shared<Serializer::CString>(
|
||||
str_replace(owner.thumb_path, App::I->data_path, "{data_path}"));
|
||||
d.props["m_user_brush"] = std::make_shared<Serializer::Boolean>(owner.m_user_brush);
|
||||
w << d;
|
||||
}
|
||||
|
||||
Node* clone_legacy_brush_preset_item(const NodeBrushPresetItem&)
|
||||
{
|
||||
return new NodeBrushPresetItem();
|
||||
}
|
||||
|
||||
void init_legacy_brush_preset_item(NodeBrushPresetItem& owner)
|
||||
{
|
||||
owner.init_template_file("data/dialogs/panel-brushes.xml", "tpl-brush-preset");
|
||||
owner.color_hover = glm::vec4(.7, .7, .7, 1);
|
||||
owner.color_normal = glm::vec4(.3, .3, .3, 1);
|
||||
owner.m_color = owner.color_normal;
|
||||
owner.m_thumb = owner.find<NodeImage>("thumb");
|
||||
owner.m_caption_size = owner.find<NodeText>("caption-size");
|
||||
owner.m_preview = owner.find<NodeStrokePreview>("canvas");
|
||||
owner.m_preview->m_min_flow = 1.f;
|
||||
}
|
||||
|
||||
void draw_legacy_brush_preset_item(NodeBrushPresetItem& owner)
|
||||
{
|
||||
owner.m_color = owner.m_mouse_inside ? owner.color_hover : owner.color_normal;
|
||||
owner.m_color = owner.m_selected ? glm::vec4(.9, 0, 0, 1) : owner.m_color;
|
||||
owner.NodeButtonCustom::draw();
|
||||
}
|
||||
|
||||
} // namespace pp::panopainter
|
||||
18
src/legacy_brush_panel_item_ui.h
Normal file
18
src/legacy_brush_panel_item_ui.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "node_panel_brush.h"
|
||||
|
||||
namespace pp::panopainter {
|
||||
|
||||
Node* clone_legacy_brush_button(const NodeButtonBrush& owner);
|
||||
void init_legacy_brush_button(NodeButtonBrush& owner);
|
||||
void set_legacy_brush_button_icon(NodeButtonBrush& owner, const char* path);
|
||||
void draw_legacy_brush_button(NodeButtonBrush& owner);
|
||||
bool read_legacy_brush_button(NodeButtonBrush& owner, BinaryStreamReader& r);
|
||||
void write_legacy_brush_button(const NodeButtonBrush& owner, BinaryStreamWriter& w);
|
||||
|
||||
Node* clone_legacy_brush_preset_item(const NodeBrushPresetItem& owner);
|
||||
void init_legacy_brush_preset_item(NodeBrushPresetItem& owner);
|
||||
void draw_legacy_brush_preset_item(NodeBrushPresetItem& owner);
|
||||
|
||||
} // namespace pp::panopainter
|
||||
245
src/legacy_canvas_mode_fill.cpp
Normal file
245
src/legacy_canvas_mode_fill.cpp
Normal file
@@ -0,0 +1,245 @@
|
||||
#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;
|
||||
}
|
||||
@@ -24,6 +24,79 @@
|
||||
|
||||
namespace pp::panopainter {
|
||||
|
||||
void execute_legacy_node_stroke_preview_background_capture_pass(
|
||||
const LegacyNodeStrokePreviewBackgroundCaptureRequest& request)
|
||||
{
|
||||
if (!request.draw_checkerboard) {
|
||||
return;
|
||||
}
|
||||
|
||||
const float aspect = request.size.x / request.size.y;
|
||||
pp::panopainter::setup_legacy_canvas_draw_merge_checkerboard_shader(
|
||||
pp::panopainter::LegacyCanvasDrawMergeCheckerboardUniforms {
|
||||
.mvp = glm::ortho(-.5f, .5f, -.5f / aspect, .5f / aspect, -1.f, 1.f),
|
||||
.colorize = request.colorize,
|
||||
});
|
||||
request.draw_checkerboard();
|
||||
const auto copy_status = pp::paint_renderer::copy_stroke_preview_result_to_texture(
|
||||
[&] {
|
||||
request.background_texture.bind();
|
||||
},
|
||||
[](
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
int width,
|
||||
int height) {
|
||||
copy_framebuffer_to_texture_2d(src_x, src_y, dst_x, dst_y, width, height);
|
||||
},
|
||||
pp::paint_renderer::StrokePreviewCopySize {
|
||||
.width = static_cast<int>(request.size.x),
|
||||
.height = static_cast<int>(request.size.y),
|
||||
});
|
||||
assert(copy_status.ok());
|
||||
}
|
||||
|
||||
std::vector<LegacyNodeStrokePreviewFrame> plan_legacy_node_stroke_preview_stroke_frames(
|
||||
const LegacyNodeStrokePreviewStrokeComputeRequest& request)
|
||||
{
|
||||
auto samples = const_cast<Stroke&>(request.stroke).compute_samples();
|
||||
StrokeSample previous_sample = request.stroke.m_prev_sample;
|
||||
previous_sample.size *= request.zoom;
|
||||
for (auto& sample : samples) {
|
||||
sample.size *= request.zoom;
|
||||
}
|
||||
|
||||
return pp::panopainter::plan_legacy_canvas_stroke_frames(
|
||||
pp::panopainter::LegacyCanvasStrokeComputeRequest {
|
||||
.previous_sample = previous_sample,
|
||||
.samples = samples,
|
||||
.zoom = 1.0f,
|
||||
.mixer_size = request.mixer_size,
|
||||
},
|
||||
[](
|
||||
std::array<vertex_t, 4>& brush_quad,
|
||||
bool /*project_3d*/,
|
||||
glm::mat4 /*model_view*/) {
|
||||
return brush_quad;
|
||||
},
|
||||
[](
|
||||
glm::vec4 mixer_rect,
|
||||
glm::vec4 color,
|
||||
float flow,
|
||||
float opacity,
|
||||
std::array<vertex_t, 4>&& shapes) -> LegacyNodeStrokePreviewFrame {
|
||||
return LegacyNodeStrokePreviewFrame {
|
||||
.col = color,
|
||||
.flow = flow,
|
||||
.opacity = opacity,
|
||||
.shapes = std::move(shapes),
|
||||
.mixer_rect = mixer_rect,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
bool execute_legacy_node_stroke_preview_immediate_runtime(
|
||||
const LegacyNodeStrokePreviewImmediateRuntimeRequest& request)
|
||||
{
|
||||
|
||||
@@ -12,9 +12,29 @@
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace pp::panopainter {
|
||||
|
||||
struct LegacyNodeStrokePreviewBackgroundCaptureRequest {
|
||||
glm::vec2 size {};
|
||||
bool colorize = false;
|
||||
Texture2D& background_texture;
|
||||
std::function<void()> draw_checkerboard;
|
||||
};
|
||||
|
||||
void execute_legacy_node_stroke_preview_background_capture_pass(
|
||||
const LegacyNodeStrokePreviewBackgroundCaptureRequest& request);
|
||||
|
||||
struct LegacyNodeStrokePreviewStrokeComputeRequest {
|
||||
const Stroke& stroke;
|
||||
float zoom = 1.0f;
|
||||
glm::vec2 mixer_size {};
|
||||
};
|
||||
|
||||
[[nodiscard]] std::vector<LegacyNodeStrokePreviewFrame> plan_legacy_node_stroke_preview_stroke_frames(
|
||||
const LegacyNodeStrokePreviewStrokeComputeRequest& request);
|
||||
|
||||
struct LegacyNodeStrokePreviewImmediateRuntimeRequest {
|
||||
const std::shared_ptr<Brush>& brush;
|
||||
glm::vec2 preview_size {};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "pch.h"
|
||||
#include "log.h"
|
||||
#include "node_panel_brush.h"
|
||||
#include "legacy_brush_panel_item_ui.h"
|
||||
#include "legacy_brush_panel_ui.h"
|
||||
#include "legacy_brush_preset_panel_ui.h"
|
||||
#include "legacy_brush_preset_list_services.h"
|
||||
@@ -8,71 +9,35 @@
|
||||
#include "app_core/brush_ui.h"
|
||||
#include "legacy_brush_ui_services.h"
|
||||
#include "legacy_brush_preset_services.h"
|
||||
#include "legacy_ui_overlay_services.h"
|
||||
#include "texture.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <Foundation/Foundation.h>
|
||||
#endif
|
||||
|
||||
#include "canvas.h"
|
||||
#include "app.h"
|
||||
#include "abr.h"
|
||||
|
||||
Node* NodeButtonBrush::clone_instantiate() const
|
||||
{
|
||||
return new NodeButtonBrush();
|
||||
return pp::panopainter::clone_legacy_brush_button(*this);
|
||||
}
|
||||
|
||||
void NodeButtonBrush::init()
|
||||
{
|
||||
init_template_file("data/dialogs/panel-brushes.xml", "tpl-brush-icon");
|
||||
color_hover = glm::vec4(.7, .7, .7, 1);
|
||||
color_normal = glm::vec4(.3, .3, .3, 1);
|
||||
m_color = color_normal;
|
||||
img = (NodeImage*)m_children[0].get();
|
||||
pp::panopainter::init_legacy_brush_button(*this);
|
||||
}
|
||||
|
||||
void NodeButtonBrush::set_icon(const char* path)
|
||||
{
|
||||
img->m_path = path;
|
||||
img->m_tex_id = const_hash(img->m_path.c_str());
|
||||
img->m_use_mipmaps = true;
|
||||
img->create();
|
||||
pp::panopainter::set_legacy_brush_button_icon(*this, path);
|
||||
}
|
||||
|
||||
void NodeButtonBrush::draw()
|
||||
{
|
||||
m_color = m_mouse_inside ? color_hover : color_normal;
|
||||
m_color = m_selected ? glm::vec4(.9, 0, 0, 1) : m_color;
|
||||
NodeButtonCustom::draw();
|
||||
pp::panopainter::draw_legacy_brush_button(*this);
|
||||
}
|
||||
|
||||
bool NodeButtonBrush::read(BinaryStreamReader& r)
|
||||
{
|
||||
Serializer::Descriptor d;
|
||||
r >> d;
|
||||
d.value<Serializer::CString>("brush_name", brush_name);
|
||||
d.value<Serializer::CString>("high_path", high_path);
|
||||
d.value<Serializer::CString>("thumb_path", thumb_path);
|
||||
d.value<Serializer::Boolean>("m_user_brush", m_user_brush);
|
||||
high_path = str_replace(high_path, "{data_path}", App::I->data_path);
|
||||
thumb_path = str_replace(thumb_path, "{data_path}", App::I->data_path);
|
||||
return true;
|
||||
return pp::panopainter::read_legacy_brush_button(*this, r);
|
||||
}
|
||||
|
||||
void NodeButtonBrush::write(BinaryStreamWriter& w) const
|
||||
{
|
||||
Serializer::Descriptor d;
|
||||
d.class_id = "brush";
|
||||
d.name = L"Brush class";
|
||||
d.props["brush_name"] = std::make_shared<Serializer::CString>(brush_name);
|
||||
d.props["high_path"] = std::make_shared<Serializer::CString>(
|
||||
str_replace(high_path, App::I->data_path, "{data_path}"));
|
||||
d.props["thumb_path"] = std::make_shared<Serializer::CString>(
|
||||
str_replace(thumb_path, App::I->data_path, "{data_path}"));
|
||||
d.props["m_user_brush"] = std::make_shared<Serializer::Boolean>(m_user_brush);
|
||||
w << d;
|
||||
pp::panopainter::write_legacy_brush_button(*this, w);
|
||||
}
|
||||
|
||||
Node* NodePanelBrush::clone_instantiate() const
|
||||
@@ -155,26 +120,17 @@ std::vector<NodePanelBrushPreset*> NodePanelBrushPreset::s_panels;
|
||||
|
||||
Node* NodeBrushPresetItem::clone_instantiate() const
|
||||
{
|
||||
return new NodeBrushPresetItem();
|
||||
return pp::panopainter::clone_legacy_brush_preset_item(*this);
|
||||
}
|
||||
|
||||
void NodeBrushPresetItem::init()
|
||||
{
|
||||
init_template_file("data/dialogs/panel-brushes.xml", "tpl-brush-preset");
|
||||
color_hover = glm::vec4(.7, .7, .7, 1);
|
||||
color_normal = glm::vec4(.3, .3, .3, 1);
|
||||
m_color = color_normal;
|
||||
m_thumb = find<NodeImage>("thumb");
|
||||
m_caption_size = find<NodeText>("caption-size");
|
||||
m_preview = find<NodeStrokePreview>("canvas");
|
||||
m_preview->m_min_flow = 1.f;
|
||||
pp::panopainter::init_legacy_brush_preset_item(*this);
|
||||
}
|
||||
|
||||
void NodeBrushPresetItem::draw()
|
||||
{
|
||||
m_color = m_mouse_inside ? color_hover : color_normal;
|
||||
m_color = m_selected ? glm::vec4(.9, 0, 0, 1) : m_color;
|
||||
NodeButtonCustom::draw();
|
||||
pp::panopainter::draw_legacy_brush_preset_item(*this);
|
||||
}
|
||||
|
||||
NodePanelBrushPreset::NodePanelBrushPreset()
|
||||
|
||||
@@ -3,19 +3,13 @@
|
||||
#include "node_stroke_preview.h"
|
||||
#include "texture.h"
|
||||
#include "shader.h"
|
||||
#include "bezier.h"
|
||||
#include "canvas.h"
|
||||
#include "app.h"
|
||||
#include "legacy_canvas_draw_merge_services.h"
|
||||
#include "legacy_canvas_stroke_execution_services.h"
|
||||
#include "legacy_canvas_stroke_preview_services.h"
|
||||
#include "legacy_canvas_stroke_shader_services.h"
|
||||
#include "legacy_canvas_stroke_services.h"
|
||||
#include "legacy_node_stroke_preview_execution_services.h"
|
||||
#include "legacy_node_stroke_preview_runtime_services.h"
|
||||
#include "legacy_node_stroke_preview_sample_services.h"
|
||||
#include "legacy_ui_gl_dispatch.h"
|
||||
#include "paint_renderer/compositor.h"
|
||||
#include "renderer_gl/opengl_capabilities.h"
|
||||
#include "util.h"
|
||||
#include <array>
|
||||
@@ -119,39 +113,6 @@ void copy_stroke_preview_destination_texture_region(
|
||||
copy_framebuffer_to_texture_2d(src_x, src_y, dst_x, dst_y, width, height);
|
||||
}
|
||||
|
||||
void execute_stroke_preview_background_capture_pass(
|
||||
glm::vec2 size,
|
||||
bool colorize,
|
||||
Texture2D& background_texture,
|
||||
const std::function<void()>& draw_checkerboard)
|
||||
{
|
||||
const float aspect = size.x / size.y;
|
||||
pp::panopainter::setup_legacy_canvas_draw_merge_checkerboard_shader(
|
||||
pp::panopainter::LegacyCanvasDrawMergeCheckerboardUniforms {
|
||||
.mvp = glm::ortho(-.5f, .5f, -.5f / aspect, .5f / aspect, -1.f, 1.f),
|
||||
.colorize = colorize,
|
||||
});
|
||||
draw_checkerboard();
|
||||
const auto copy_status = pp::paint_renderer::copy_stroke_preview_result_to_texture(
|
||||
[&] {
|
||||
background_texture.bind();
|
||||
},
|
||||
[](
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
int width,
|
||||
int height) {
|
||||
copy_framebuffer_to_texture_2d(src_x, src_y, dst_x, dst_y, width, height);
|
||||
},
|
||||
pp::paint_renderer::StrokePreviewCopySize {
|
||||
.width = static_cast<int>(size.x),
|
||||
.height = static_cast<int>(size.y),
|
||||
});
|
||||
assert(copy_status.ok());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Node* NodeStrokePreview::clone_instantiate() const
|
||||
@@ -240,39 +201,11 @@ glm::vec4 NodeStrokePreview::stroke_draw_samples(
|
||||
|
||||
std::vector<NodeStrokePreview::StrokeFrame> NodeStrokePreview::stroke_draw_compute(const Stroke& stroke, float zoom) const
|
||||
{
|
||||
auto samples = const_cast<Stroke&>(stroke).compute_samples();
|
||||
StrokeSample previous_sample = stroke.m_prev_sample;
|
||||
previous_sample.size *= zoom;
|
||||
for (auto& sample : samples) {
|
||||
sample.size *= zoom;
|
||||
}
|
||||
|
||||
return pp::panopainter::plan_legacy_canvas_stroke_frames(
|
||||
pp::panopainter::LegacyCanvasStrokeComputeRequest {
|
||||
.previous_sample = previous_sample,
|
||||
.samples = samples,
|
||||
.zoom = 1.0f,
|
||||
return pp::panopainter::plan_legacy_node_stroke_preview_stroke_frames(
|
||||
pp::panopainter::LegacyNodeStrokePreviewStrokeComputeRequest {
|
||||
.stroke = stroke,
|
||||
.zoom = zoom,
|
||||
.mixer_size = glm::vec2(m_rtt.getWidth(), m_rtt.getHeight()),
|
||||
},
|
||||
[](
|
||||
std::array<vertex_t, 4>& brush_quad,
|
||||
bool /*project_3d*/,
|
||||
glm::mat4 /*model_view*/) {
|
||||
return brush_quad;
|
||||
},
|
||||
[](
|
||||
glm::vec4 mixer_rect,
|
||||
glm::vec4 color,
|
||||
float flow,
|
||||
float opacity,
|
||||
std::array<vertex_t, 4>&& shapes) -> StrokeFrame {
|
||||
return StrokeFrame {
|
||||
.col = color,
|
||||
.flow = flow,
|
||||
.opacity = opacity,
|
||||
.shapes = std::move(shapes),
|
||||
.mixer_rect = mixer_rect,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -339,12 +272,14 @@ void NodeStrokePreview::draw_stroke_immediate()
|
||||
bind_stroke_preview_dual_pass_textures(dual_brush);
|
||||
},
|
||||
.capture_background = [&](bool colorize) {
|
||||
execute_stroke_preview_background_capture_pass(
|
||||
size,
|
||||
colorize,
|
||||
m_tex_background,
|
||||
[&] {
|
||||
pp::panopainter::execute_legacy_node_stroke_preview_background_capture_pass(
|
||||
pp::panopainter::LegacyNodeStrokePreviewBackgroundCaptureRequest {
|
||||
.size = size,
|
||||
.colorize = colorize,
|
||||
.background_texture = m_tex_background,
|
||||
.draw_checkerboard = [&] {
|
||||
m_plane.draw_fill();
|
||||
},
|
||||
});
|
||||
},
|
||||
.compute_frames = [&](const Stroke& stroke, float frame_zoom) {
|
||||
|
||||
Reference in New Issue
Block a user