Route layer panel view through app core

This commit is contained in:
2026-06-05 00:50:37 +02:00
parent bd6cdc20c5
commit 75fd7faeb0
8 changed files with 368 additions and 7 deletions

View File

@@ -8,6 +8,7 @@
#include <string>
#include <string_view>
#include <utility>
#include <vector>
namespace pp::app {
@@ -84,6 +85,33 @@ struct DocumentLayerMergePlan {
bool create_history = true;
};
struct DocumentLayerPanelInput {
int layer_index = 0;
std::string name;
float opacity = 1.0F;
bool visible = true;
bool alpha_locked = false;
int blend_mode = 0;
};
struct DocumentLayerPanelLayerView {
int layer_index = 0;
std::string name;
float opacity = 1.0F;
bool visible = true;
bool alpha_locked = false;
int blend_mode = 0;
bool current = false;
};
struct DocumentLayerPanelView {
int current_index = 0;
float current_opacity = 1.0F;
bool current_alpha_locked = false;
int current_blend_mode = 0;
std::vector<DocumentLayerPanelLayerView> layers;
};
class DocumentLayerMenuServices {
public:
virtual ~DocumentLayerMenuServices() = default;
@@ -158,6 +186,60 @@ public:
return pp::foundation::Status::success();
}
[[nodiscard]] inline pp::foundation::Result<DocumentLayerPanelView> plan_document_layer_panel_view(
const std::vector<DocumentLayerPanelInput>& layers,
int current_index)
{
if (layers.empty()) {
return pp::foundation::Result<DocumentLayerPanelView>::failure(
pp::foundation::Status::invalid_argument("layer panel requires at least one layer"));
}
const auto current_status = validate_layer_index(static_cast<int>(layers.size()), current_index);
if (!current_status.ok()) {
return pp::foundation::Result<DocumentLayerPanelView>::failure(current_status);
}
DocumentLayerPanelView view;
view.current_index = current_index;
view.layers.reserve(layers.size());
for (const auto& input : layers) {
const auto index_status = validate_layer_index(static_cast<int>(layers.size()), input.layer_index);
if (!index_status.ok()) {
return pp::foundation::Result<DocumentLayerPanelView>::failure(index_status);
}
if (!std::isfinite(input.opacity) || input.opacity < 0.0F || input.opacity > 1.0F) {
return pp::foundation::Result<DocumentLayerPanelView>::failure(
pp::foundation::Status::out_of_range("layer opacity must be finite and within 0..1"));
}
if (input.blend_mode < 0 || input.blend_mode >= document_layer_legacy_blend_mode_count) {
return pp::foundation::Result<DocumentLayerPanelView>::failure(
pp::foundation::Status::out_of_range("layer blend mode is outside the supported range"));
}
const bool current = input.layer_index == current_index;
DocumentLayerPanelLayerView layer;
layer.layer_index = input.layer_index;
layer.name = input.name;
layer.opacity = input.opacity;
layer.visible = input.visible;
layer.alpha_locked = input.alpha_locked;
layer.blend_mode = input.blend_mode;
layer.current = current;
if (current) {
view.current_opacity = input.opacity;
view.current_alpha_locked = input.alpha_locked;
view.current_blend_mode = input.blend_mode;
}
view.layers.push_back(std::move(layer));
}
return pp::foundation::Result<DocumentLayerPanelView>::success(std::move(view));
}
[[nodiscard]] inline pp::foundation::Result<DocumentLayerRenamePlan> plan_document_layer_rename(
std::string_view old_name,
std::string_view requested_name)

View File

@@ -1,4 +1,5 @@
#include "pch.h"
#include "app_core/document_layer.h"
#include "log.h"
#include "node_panel_layer.h"
#include "canvas.h"
@@ -367,13 +368,38 @@ void NodePanelLayer::clear()
void NodePanelLayer::update_attributes()
{
auto& l = Canvas::I->m_layers[Canvas::I->m_current_layer_idx];
m_opacity->set_value(l->m_opacity);
m_alpha_lock->set_value(l->m_alpha_locked);
m_blend_mode->set_index(l->m_blend_mode);
for (int i = 0; i < Canvas::I->m_layers.size(); i++)
if (!Canvas::I)
return;
std::vector<pp::app::DocumentLayerPanelInput> layer_inputs;
layer_inputs.reserve(Canvas::I->m_layers.size());
for (int i = 0; i < static_cast<int>(Canvas::I->m_layers.size()); i++)
{
m_layers[i]->m_visibility->set_value(Canvas::I->m_layers[i]->m_visible);
const auto& layer = Canvas::I->m_layers[i];
layer_inputs.push_back(pp::app::DocumentLayerPanelInput {
.layer_index = i,
.name = layer->m_name,
.opacity = layer->m_opacity,
.visible = layer->m_visible,
.alpha_locked = layer->m_alpha_locked,
.blend_mode = layer->m_blend_mode,
});
}
const auto view = pp::app::plan_document_layer_panel_view(layer_inputs, Canvas::I->m_current_layer_idx);
if (!view)
{
LOG("Layer panel view failed: %s", view.status().message);
return;
}
m_opacity->set_value(view.value().current_opacity);
m_alpha_lock->set_value(view.value().current_alpha_locked);
m_blend_mode->set_index(view.value().current_blend_mode);
for (const auto& layer : view.value().layers)
{
if (layer.layer_index >= 0 && layer.layer_index < static_cast<int>(m_layers.size()))
m_layers[layer.layer_index]->m_visibility->set_value(layer.visible);
}
}