Route canvas view execution through app core

This commit is contained in:
2026-06-05 05:47:42 +02:00
parent 9373e07d3e
commit e42afcc83f
15 changed files with 456 additions and 33 deletions

View File

@@ -1,9 +1,19 @@
#pragma once
#include "foundation/result.h"
#include <array>
#include <cmath>
namespace pp::app {
enum class CanvasViewCursorMode {
never = 0,
small_brush = 1,
not_painting = 2,
always = 3,
};
struct CanvasCameraState {
std::array<float, 16> rotation {};
std::array<float, 3> position {};
@@ -11,6 +21,24 @@ struct CanvasCameraState {
std::array<float, 2> pan {};
};
struct CanvasViewDensityPlan {
float density = 1.0F;
bool recreates_buffers = true;
};
struct CanvasViewCursorModePlan {
CanvasViewCursorMode mode = CanvasViewCursorMode::never;
};
class CanvasViewServices {
public:
virtual ~CanvasViewServices() = default;
virtual void reset_camera(const CanvasCameraState& state) = 0;
virtual void set_density(const CanvasViewDensityPlan& plan) = 0;
virtual void set_cursor_mode(const CanvasViewCursorModePlan& plan) = 0;
};
[[nodiscard]] constexpr CanvasCameraState plan_canvas_camera_reset() noexcept
{
CanvasCameraState state;
@@ -26,4 +54,62 @@ struct CanvasCameraState {
return state;
}
[[nodiscard]] inline pp::foundation::Result<CanvasViewDensityPlan> plan_canvas_view_density(float density)
{
if (!std::isfinite(density) || density <= 0.0F) {
return pp::foundation::Result<CanvasViewDensityPlan>::failure(
pp::foundation::Status::invalid_argument("canvas view density must be finite and positive"));
}
return pp::foundation::Result<CanvasViewDensityPlan>::success(CanvasViewDensityPlan {
.density = density,
.recreates_buffers = true,
});
}
[[nodiscard]] inline pp::foundation::Result<CanvasViewCursorModePlan> plan_canvas_view_cursor_mode(int mode)
{
if (mode < static_cast<int>(CanvasViewCursorMode::never)
|| mode > static_cast<int>(CanvasViewCursorMode::always)) {
return pp::foundation::Result<CanvasViewCursorModePlan>::failure(
pp::foundation::Status::out_of_range("canvas cursor mode is out of range"));
}
return pp::foundation::Result<CanvasViewCursorModePlan>::success(CanvasViewCursorModePlan {
.mode = static_cast<CanvasViewCursorMode>(mode),
});
}
[[nodiscard]] inline pp::foundation::Status execute_canvas_camera_reset(CanvasViewServices& services)
{
services.reset_camera(plan_canvas_camera_reset());
return pp::foundation::Status::success();
}
[[nodiscard]] inline pp::foundation::Status execute_canvas_view_density(
float density,
CanvasViewServices& services)
{
const auto plan = plan_canvas_view_density(density);
if (!plan) {
return plan.status();
}
services.set_density(plan.value());
return pp::foundation::Status::success();
}
[[nodiscard]] inline pp::foundation::Status execute_canvas_view_cursor_mode(
int mode,
CanvasViewServices& services)
{
const auto plan = plan_canvas_view_cursor_mode(mode);
if (!plan) {
return plan.status();
}
services.set_cursor_mode(plan.value());
return pp::foundation::Status::success();
}
} // namespace pp::app

View File

@@ -3,7 +3,7 @@
#include "legacy_app_preference_services.h"
#include "app.h"
#include "node_canvas.h"
#include "legacy_canvas_view_services.h"
#include "serializer.h"
#include "settings.h"
@@ -24,12 +24,9 @@ public:
void apply_viewport_scale(const pp::app::ScaleApplicationPlan& plan) override
{
if (!app_.canvas)
return;
app_.canvas->set_density(plan.scale);
Settings::set("vp-scale", Serializer::Float(plan.scale));
Settings::save();
const auto status = execute_legacy_canvas_view_density(app_, plan.scale);
if (!status.ok())
LOG("Viewport scale preference failed: %s", status.message);
}
void apply_interface_direction(const pp::app::InterfaceDirectionPlan& plan) override
@@ -68,12 +65,9 @@ public:
void apply_canvas_cursor_mode(const pp::app::StoredIntegerPreferencePlan& plan) override
{
if (!app_.canvas)
return;
app_.canvas->set_cursor_visibility(static_cast<NodeCanvas::kCursorVisibility>(plan.value));
Settings::set("show-cursor", Serializer::Integer(plan.value));
Settings::save();
const auto status = execute_legacy_canvas_cursor_mode(app_, plan.value);
if (!status.ok())
LOG("Canvas cursor mode preference failed: %s", status.message);
}
private:

View File

@@ -4,6 +4,7 @@
#include "app.h"
#include "app_core/document_import.h"
#include "legacy_canvas_view_services.h"
#include "legacy_document_canvas_services.h"
#include "legacy_history_services.h"
@@ -304,8 +305,9 @@ public:
void reset_camera() override
{
if (app_.canvas)
app_.canvas->reset_camera();
const auto status = execute_legacy_canvas_camera_reset(app_);
if (!status.ok())
LOG("Canvas camera reset failed: %s", status.message);
}
void show_shortcuts_dialog() override

View File

@@ -0,0 +1,90 @@
#include "pch.h"
#include "legacy_canvas_view_services.h"
#include "app.h"
#include "node_canvas.h"
#include "serializer.h"
#include "settings.h"
namespace pp::panopainter {
namespace {
class LegacyCanvasViewServices final : public pp::app::CanvasViewServices {
public:
explicit LegacyCanvasViewServices(App& app) noexcept
: app_(app)
{
}
void reset_camera(const pp::app::CanvasCameraState& state) override
{
if (!app_.canvas || !app_.canvas->m_canvas) {
return;
}
app_.canvas->m_canvas->m_cam_rot = glm::mat4(
state.rotation[0], state.rotation[1], state.rotation[2], state.rotation[3],
state.rotation[4], state.rotation[5], state.rotation[6], state.rotation[7],
state.rotation[8], state.rotation[9], state.rotation[10], state.rotation[11],
state.rotation[12], state.rotation[13], state.rotation[14], state.rotation[15]);
app_.canvas->m_canvas->m_cam_pos = {
state.position[0],
state.position[1],
state.position[2],
};
app_.canvas->m_canvas->m_cam_fov = state.field_of_view_degrees;
app_.canvas->m_canvas->m_pan = {
state.pan[0],
state.pan[1],
};
}
void set_density(const pp::app::CanvasViewDensityPlan& plan) override
{
if (!app_.canvas) {
return;
}
app_.canvas->set_density(plan.density);
Settings::set("vp-scale", Serializer::Float(plan.density));
Settings::save();
}
void set_cursor_mode(const pp::app::CanvasViewCursorModePlan& plan) override
{
if (!app_.canvas) {
return;
}
const auto mode = static_cast<int>(plan.mode);
app_.canvas->set_cursor_visibility(static_cast<NodeCanvas::kCursorVisibility>(mode));
Settings::set("show-cursor", Serializer::Integer(mode));
Settings::save();
}
private:
App& app_;
};
} // namespace
pp::foundation::Status execute_legacy_canvas_camera_reset(App& app)
{
LegacyCanvasViewServices services(app);
return pp::app::execute_canvas_camera_reset(services);
}
pp::foundation::Status execute_legacy_canvas_view_density(App& app, float density)
{
LegacyCanvasViewServices services(app);
return pp::app::execute_canvas_view_density(density, services);
}
pp::foundation::Status execute_legacy_canvas_cursor_mode(App& app, int mode)
{
LegacyCanvasViewServices services(app);
return pp::app::execute_canvas_view_cursor_mode(mode, services);
}
} // namespace pp::panopainter

View File

@@ -0,0 +1,13 @@
#pragma once
#include "app_core/canvas_view.h"
class App;
namespace pp::panopainter {
[[nodiscard]] pp::foundation::Status execute_legacy_canvas_camera_reset(App& app);
[[nodiscard]] pp::foundation::Status execute_legacy_canvas_view_density(App& app, float density);
[[nodiscard]] pp::foundation::Status execute_legacy_canvas_cursor_mode(App& app, int mode);
} // namespace pp::panopainter

View File

@@ -4,6 +4,7 @@
#include "app.h"
#include "canvas.h"
#include "legacy_canvas_view_services.h"
#include "node_dialog_cloud.h"
#include "node_progress_bar.h"
#include "util.h"
@@ -122,7 +123,9 @@ public:
m->m_message->set_text(progress);
});
app->canvas->reset_camera();
const auto reset_status = execute_legacy_canvas_camera_reset(*app);
if (!reset_status.ok())
LOG("Cloud download camera reset failed: %s", reset_status.message);
app->layers->clear();
app->canvas->m_canvas->project_open_thread(request.selected_path);

View File

@@ -4,6 +4,7 @@
#include "app.h"
#include "legacy_brush_package_import_services.h"
#include "legacy_canvas_view_services.h"
#include "legacy_history_services.h"
#include "log.h"
#include "node_panel_brush.h"
@@ -17,7 +18,9 @@ void open_legacy_project(App& app, const pp::app::DocumentOpenRoute& route)
app.doc_name = route.name;
app.doc_dir = route.directory;
app.doc_path = route.path;
app.canvas->reset_camera();
const auto reset_status = execute_legacy_canvas_camera_reset(app);
if (!reset_status.ok())
LOG("Project open camera reset failed: %s", reset_status.message);
app.layers->clear();
app.canvas->m_canvas->project_open(route.path, [&app](bool success) {
if (success)

View File

@@ -3,6 +3,7 @@
#include "legacy_document_session_services.h"
#include "app.h"
#include "legacy_canvas_view_services.h"
#include "legacy_history_services.h"
#include "node_dialog_open.h"
@@ -24,7 +25,9 @@ void create_legacy_new_document(
app.layers->clear();
app.canvas->m_canvas->m_layers.clear();
app.canvas->m_canvas->resize(plan.resolution, plan.resolution);
app.canvas->reset_camera();
const auto reset_status = execute_legacy_canvas_camera_reset(app);
if (!reset_status.ok())
LOG("New document camera reset failed: %s", reset_status.message);
pp::panopainter::clear_legacy_history();
app.layers->add_layer("Default", false, true);