Extract legacy canvas state helpers

This commit is contained in:
2026-06-16 10:02:49 +02:00
parent bde9f0c4f2
commit d68c97e609
3 changed files with 193 additions and 186 deletions

View File

@@ -22,6 +22,7 @@ set(PP_LEGACY_PAINT_DOCUMENT_SOURCES
src/canvas.cpp
src/canvas_actions.cpp
src/canvas_layer.cpp
src/legacy_canvas_state_services.cpp
src/event.cpp
)
@@ -92,6 +93,7 @@ set(PP_PANOPAINTER_APP_SOURCES
src/app_dialogs.cpp
src/app_events.cpp
src/app_layout.cpp
src/app_layout_tools_menu.cpp
src/app_shaders.cpp
src/app_vr.cpp
src/legacy_app_dialog_services.cpp

View File

@@ -305,74 +305,6 @@ glm::mat4 Canvas::m_plane_transform[6] = {
glm::lookAt(glm::vec3(), { 0,-1, 0}, {0, 0, 1}), // bottom
};
void Canvas::pick_start()
{
for (int i = 0; i < 6; i++)
m_pick_ready[i] = false;
}
void Canvas::pick_update(int plane)
{
// check if already updated
if (m_pick_ready[plane])
return;
App::I->render_task([this, plane]
{
std::array<bool, 6> faces{ false };
faces[plane] = true;
draw_merge(true, faces);
int i = plane;
if (!m_pick_data[plane])
m_pick_data[plane] = std::make_unique<glm::u8vec4[]>(m_width * m_height);
m_layers_merge.rtt(i).readPixelsRgba8(
0,
0,
m_width,
m_height,
m_pick_data[plane].get());
});
m_pick_ready[plane] = true;
}
glm::vec4 Canvas::pick_get(glm::vec2 canvas_loc)
{
glm::vec3 ray_origin;
glm::vec3 ray_dir;
glm::vec3 hit_pos;
glm::vec3 hit_normal;
glm::vec2 fb_pos;
int plane_id;
if (point_trace(canvas_loc, ray_origin, ray_dir, hit_pos, fb_pos, hit_normal, plane_id))
{
pick_update(plane_id);
int i = (int)fb_pos.x + (int)fb_pos.y * m_width;
return glm::vec4(m_pick_data[plane_id][i]) / 255.f;
}
return {0,0,0,1};
}
void Canvas::pick_end()
{
for (int i = 0; i < 6; i++)
m_pick_data[i].release();
}
void Canvas::clear(const glm::vec4& c/*={0,0,0,1}*/)
{
auto a = new ActionLayerClear;
a->m_layer = m_layers[m_current_layer_idx];
a->m_frame = layer().m_frame_index;
a->m_snap = std::make_shared<LayerFrame::Snapshot>(a->m_layer->snapshot());
a->m_color = c;
ActionManager::add(a);
m_layers[m_current_layer_idx]->clear(c);
m_unsaved = true;
}
void Canvas::clear_all()
{
for (auto& l : m_layers)
l->clear({0, 0, 0, 0});
}
void Canvas::stroke_end()
{
if (!m_current_stroke)
@@ -2340,53 +2272,6 @@ void Canvas::stroke_start(glm::vec3 point, float pressure)
m_mixer.unbindFramebuffer();
m_show_tmp = true;
}
void Canvas::layer_add(std::string name, std::shared_ptr<Layer> layer /*= nullptr*/, int index /*= 0*/)
{
LOG("canvas layer_add %s", name.c_str());
int idx = (int)m_layers.size();
if (layer)
{
m_layers.insert(m_layers.begin() + index, layer);
}
else
{
m_layers.insert(m_layers.begin() + index, std::make_unique<Layer>());
m_layers[index]->create(m_width, m_height, name);
}
m_current_layer_idx = index;
}
std::shared_ptr<Layer> Canvas::layer_with_id(uint32_t id)
{
auto layer = std::find_if(m_layers.begin(), m_layers.end(),
[id](const auto& l) { return l->id == id; });
if (layer != m_layers.end())
return *layer;
return nullptr;
}
void Canvas::layer_remove(int idx) // m_order index
{
LOG("canvas layer_remove %d", idx);
//m_layers[n]->destroy();
m_layers.erase(m_layers.begin() + idx);
m_current_layer_idx = std::min<int>((int)m_layers.size() - 1, idx);
}
void Canvas::layer_order(int idx, int pos) // m_order index
{
auto from = m_layers.begin() + idx;
auto to = m_layers.begin() + pos;
if (pos < idx)
std::rotate(to, from, from + 1);
if (pos > idx)
std::rotate(from, from + 1, to + 1);
if (m_current_layer_idx == idx)
m_current_layer_idx = pos;
else if (m_current_layer_idx == pos)
m_current_layer_idx = idx;
}
void Canvas::layer_merge(int source_idx, int dest_idx) // m_layer index
{
m_dirty = false;
@@ -2449,38 +2334,6 @@ void Canvas::layer_merge(int source_idx, int dest_idx) // m_layer index
});
}
int Canvas::anim_duration() const noexcept
{
int frames = 1;
for (auto& l : m_layers)
frames = glm::max(frames, l->total_duration());
return frames;
}
void Canvas::anim_update() noexcept
{
for (auto& l : m_layers)
l->goto_frame(m_anim_frame);
}
void Canvas::anim_goto_frame(int frame) noexcept
{
m_anim_frame = frame;
for (auto& l : m_layers)
l->goto_frame(frame);
}
void Canvas::anim_goto_next() noexcept
{
anim_goto_frame((m_anim_frame + 1) % anim_duration());
}
void Canvas::anim_goto_prev() noexcept
{
int k = anim_duration();
anim_goto_frame((m_anim_frame - 1 + k) % k);
}
void Canvas::flood_fill(int layer, int plane, std::vector<glm::ivec2> pos, FloodData& plane_data,
float threshold, glm::vec4 dest_color, std::unique_ptr<glm::vec4>& source_color)
{
@@ -2656,28 +2509,6 @@ void Canvas::FloodData::apply()
Canvas::I->m_unsaved = true;
}
void Canvas::resize(int width, int height)
{
m_width = width;
m_height = height;
m_size = { width, height };
for (int i = 0; i < 6; i++)
{
const auto stroke_format = current_canvas_stroke_internal_format();
m_tmp[i].create(width, height, -1, stroke_format);
m_tmp_dual[i].create(width, height, -1, stroke_format);
m_tex[i].create(width, height, rgba8_internal_format());
m_tex2[i].create(width, height, rgba8_internal_format());
}
for (auto& l : m_layers)
l->resize(width, height);
m_smask.create(width, height, "mask");
m_layers_merge.resize(width, height);
m_merge_rtt.create(width, height);
m_merge_tex.create(width, height);
m_unsaved = true;
}
void Canvas::destroy()
{
for (int i = 0; i < 6; i++)
@@ -2738,23 +2569,6 @@ bool Canvas::create(int width, int height)
return true;
}
void Canvas::snapshot_save()
{
LOG("SAVE SNAPSHOT");
m_layers_snapshot.clear();
m_layers_snapshot.resize(m_layers.size());
for (int i = 0; i < m_layers.size(); i++)
m_layers_snapshot[i] = m_layers[i]->snapshot();
}
void Canvas::snapshot_restore()
{
LOG("RESTORE SNAPSHOT");
for (int i = 0; i < m_layers.size(); i++)
m_layers[i]->restore(m_layers_snapshot[i]);
m_layers_snapshot.clear();
}
void Canvas::clear_context()
{
LOG("Canvas CLEAR CONTEXT");

View File

@@ -0,0 +1,191 @@
#include "pch.h"
#include "canvas.h"
#include "app.h"
void Canvas::pick_start()
{
for (int i = 0; i < 6; i++)
m_pick_ready[i] = false;
}
void Canvas::pick_update(int plane)
{
if (m_pick_ready[plane])
return;
App::I->render_task([this, plane]
{
std::array<bool, 6> faces{ false };
faces[plane] = true;
draw_merge(true, faces);
int i = plane;
if (!m_pick_data[plane])
m_pick_data[plane] = std::make_unique<glm::u8vec4[]>(m_width * m_height);
m_layers_merge.rtt(i).readPixelsRgba8(
0,
0,
m_width,
m_height,
m_pick_data[plane].get());
});
m_pick_ready[plane] = true;
}
glm::vec4 Canvas::pick_get(glm::vec2 canvas_loc)
{
glm::vec3 ray_origin;
glm::vec3 ray_dir;
glm::vec3 hit_pos;
glm::vec3 hit_normal;
glm::vec2 fb_pos;
int plane_id;
if (point_trace(canvas_loc, ray_origin, ray_dir, hit_pos, fb_pos, hit_normal, plane_id)) {
pick_update(plane_id);
int i = (int)fb_pos.x + (int)fb_pos.y * m_width;
return glm::vec4(m_pick_data[plane_id][i]) / 255.f;
}
return { 0, 0, 0, 1 };
}
void Canvas::pick_end()
{
for (int i = 0; i < 6; i++)
m_pick_data[i].release();
}
void Canvas::clear(const glm::vec4& c/*={0,0,0,1}*/)
{
auto a = new ActionLayerClear;
a->m_layer = m_layers[m_current_layer_idx];
a->m_frame = layer().m_frame_index;
a->m_snap = std::make_shared<LayerFrame::Snapshot>(a->m_layer->snapshot());
a->m_color = c;
ActionManager::add(a);
m_layers[m_current_layer_idx]->clear(c);
m_unsaved = true;
}
void Canvas::clear_all()
{
for (auto& l : m_layers)
l->clear({ 0, 0, 0, 0 });
}
void Canvas::layer_add(std::string name, std::shared_ptr<Layer> layer /*= nullptr*/, int index /*= 0*/)
{
LOG("canvas layer_add %s", name.c_str());
if (layer) {
m_layers.insert(m_layers.begin() + index, layer);
} else {
m_layers.insert(m_layers.begin() + index, std::make_unique<Layer>());
m_layers[index]->create(m_width, m_height, name);
}
m_current_layer_idx = index;
}
std::shared_ptr<Layer> Canvas::layer_with_id(uint32_t id)
{
auto layer = std::find_if(m_layers.begin(), m_layers.end(),
[id](const auto& l) { return l->id == id; });
if (layer != m_layers.end())
return *layer;
return nullptr;
}
void Canvas::layer_remove(int idx) // m_order index
{
LOG("canvas layer_remove %d", idx);
m_layers.erase(m_layers.begin() + idx);
m_current_layer_idx = std::min<int>((int)m_layers.size() - 1, idx);
}
void Canvas::layer_order(int idx, int pos) // m_order index
{
auto from = m_layers.begin() + idx;
auto to = m_layers.begin() + pos;
if (pos < idx)
std::rotate(to, from, from + 1);
if (pos > idx)
std::rotate(from, from + 1, to + 1);
if (m_current_layer_idx == idx)
m_current_layer_idx = pos;
else if (m_current_layer_idx == pos)
m_current_layer_idx = idx;
}
int Canvas::anim_duration() const noexcept
{
int frames = 1;
for (auto& l : m_layers)
frames = glm::max(frames, l->total_duration());
return frames;
}
void Canvas::anim_update() noexcept
{
for (auto& l : m_layers)
l->goto_frame(m_anim_frame);
}
void Canvas::anim_goto_frame(int frame) noexcept
{
m_anim_frame = frame;
for (auto& l : m_layers)
l->goto_frame(frame);
}
void Canvas::anim_goto_next() noexcept
{
anim_goto_frame((m_anim_frame + 1) % anim_duration());
}
void Canvas::anim_goto_prev() noexcept
{
int k = anim_duration();
anim_goto_frame((m_anim_frame - 1 + k) % k);
}
void Canvas::resize(int width, int height)
{
m_width = width;
m_height = height;
m_size = { width, height };
for (int i = 0; i < 6; i++) {
const auto stroke_format = current_canvas_stroke_internal_format();
m_tmp[i].create(width, height, -1, stroke_format);
m_tmp_dual[i].create(width, height, -1, stroke_format);
m_tex[i].create(width, height, rgba8_internal_format());
m_tex2[i].create(width, height, rgba8_internal_format());
}
for (auto& l : m_layers)
l->resize(width, height);
m_smask.create(width, height, "mask");
m_layers_merge.resize(width, height);
m_merge_rtt.create(width, height);
m_merge_tex.create(width, height);
m_unsaved = true;
}
void Canvas::snapshot_save()
{
LOG("SAVE SNAPSHOT");
m_layers_snapshot.clear();
m_layers_snapshot.resize(m_layers.size());
for (int i = 0; i < m_layers.size(); i++)
m_layers_snapshot[i] = m_layers[i]->snapshot();
}
void Canvas::snapshot_restore()
{
LOG("RESTORE SNAPSHOT");
for (int i = 0; i < m_layers.size(); i++)
m_layers[i]->restore(m_layers_snapshot[i]);
m_layers_snapshot.clear();
}