Centralize legacy brush UI bridge
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
#include "app_core/main_toolbar.h"
|
||||
#include "app_core/tools_menu.h"
|
||||
#include "legacy_app_shell_services.h"
|
||||
#include "legacy_brush_ui_services.h"
|
||||
#include "legacy_canvas_tool_services.h"
|
||||
#include "legacy_document_layer_services.h"
|
||||
#include "legacy_history_services.h"
|
||||
@@ -31,115 +32,19 @@
|
||||
|
||||
namespace {
|
||||
|
||||
class LegacyBrushUiServices final : public pp::app::BrushUiServices {
|
||||
public:
|
||||
LegacyBrushUiServices(
|
||||
App& app,
|
||||
bool update_quick = false,
|
||||
bool update_color_panel = false,
|
||||
const std::shared_ptr<Brush>& preset_brush = nullptr) noexcept
|
||||
: app_(app)
|
||||
, update_quick_(update_quick)
|
||||
, update_color_panel_(update_color_panel)
|
||||
, preset_brush_(preset_brush)
|
||||
{
|
||||
}
|
||||
|
||||
void set_tip_color(float r, float g, float b, float a) override
|
||||
{
|
||||
if (!Canvas::I || !Canvas::I->m_current_brush)
|
||||
return;
|
||||
|
||||
Canvas::I->m_current_brush->m_tip_color = glm::vec4(r, g, b, a);
|
||||
if (update_quick_ && app_.quick)
|
||||
app_.quick->set_color(Canvas::I->m_current_brush->m_tip_color);
|
||||
if (update_color_panel_ && app_.color)
|
||||
app_.color->set_color(Canvas::I->m_current_brush->m_tip_color);
|
||||
}
|
||||
|
||||
void set_texture(
|
||||
pp::app::BrushUiTextureSlot slot,
|
||||
std::string_view path,
|
||||
std::string_view thumbnail_path) override
|
||||
{
|
||||
if (!Canvas::I || !Canvas::I->m_current_brush)
|
||||
return;
|
||||
|
||||
const std::string texture_path(path);
|
||||
const std::string thumbnail(thumbnail_path);
|
||||
switch (slot)
|
||||
{
|
||||
case pp::app::BrushUiTextureSlot::tip:
|
||||
Canvas::I->m_current_brush->load_tip(texture_path, thumbnail);
|
||||
break;
|
||||
case pp::app::BrushUiTextureSlot::pattern:
|
||||
Canvas::I->m_current_brush->load_pattern(texture_path, thumbnail);
|
||||
break;
|
||||
case pp::app::BrushUiTextureSlot::dual:
|
||||
Canvas::I->m_current_brush->load_dual(texture_path, thumbnail);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void replace_brush_from_preset(bool preserve_existing_color, bool load_resources) override
|
||||
{
|
||||
if (!Canvas::I || !Canvas::I->m_current_brush || !preset_brush_)
|
||||
return;
|
||||
|
||||
const auto color = Canvas::I->m_current_brush->m_tip_color;
|
||||
*Canvas::I->m_current_brush = *preset_brush_;
|
||||
if (preserve_existing_color)
|
||||
Canvas::I->m_current_brush->m_tip_color = color;
|
||||
if (load_resources)
|
||||
Canvas::I->m_current_brush->load();
|
||||
}
|
||||
|
||||
void refresh_brush_ui(bool update_color_ui, bool update_brush_ui) override
|
||||
{
|
||||
app_.brush_update(update_color_ui, update_brush_ui);
|
||||
}
|
||||
|
||||
private:
|
||||
App& app_;
|
||||
bool update_quick_ = false;
|
||||
bool update_color_panel_ = false;
|
||||
std::shared_ptr<Brush> preset_brush_;
|
||||
};
|
||||
|
||||
bool apply_brush_color_plan(App& app, glm::vec4 color, bool update_quick, bool update_color_panel)
|
||||
{
|
||||
const auto plan = pp::app::plan_brush_ui_color(color.r, color.g, color.b, color.a);
|
||||
if (!plan)
|
||||
return false;
|
||||
LegacyBrushUiServices services(app, update_quick, update_color_panel);
|
||||
const auto status = pp::app::execute_brush_ui_plan(plan.value(), services);
|
||||
if (!status.ok())
|
||||
LOG("Brush color action failed: %s", status.message);
|
||||
return status.ok();
|
||||
return pp::panopainter::apply_legacy_brush_color_plan(app, color, update_quick, update_color_panel);
|
||||
}
|
||||
|
||||
bool apply_brush_texture_plan(pp::app::BrushUiTextureSlot slot, const std::string& path, const std::string& thumb)
|
||||
bool apply_brush_texture_plan(App& app, pp::app::BrushUiTextureSlot slot, const std::string& path, const std::string& thumb)
|
||||
{
|
||||
const auto plan = pp::app::plan_brush_ui_texture(slot, path, thumb);
|
||||
if (!plan)
|
||||
return false;
|
||||
LegacyBrushUiServices services(*App::I);
|
||||
const auto status = pp::app::execute_brush_ui_plan(plan.value(), services);
|
||||
if (!status.ok())
|
||||
LOG("Brush texture action failed: %s", status.message);
|
||||
return status.ok();
|
||||
return pp::panopainter::apply_legacy_brush_texture_plan(app, slot, path, thumb);
|
||||
}
|
||||
|
||||
bool apply_brush_preset_plan(App& app, const std::shared_ptr<Brush>& brush)
|
||||
{
|
||||
const auto plan = pp::app::plan_brush_ui_preset_replace(static_cast<bool>(brush));
|
||||
if (!plan)
|
||||
return false;
|
||||
LegacyBrushUiServices services(app, false, false, brush);
|
||||
const auto status = pp::app::execute_brush_ui_plan(plan.value(), services);
|
||||
if (!status.ok())
|
||||
LOG("Brush preset action failed: %s", status.message);
|
||||
return status.ok();
|
||||
return pp::panopainter::apply_legacy_brush_preset_plan(app, brush);
|
||||
}
|
||||
|
||||
bool apply_document_export_menu_plan(App& app, pp::app::DocumentExportMenuKind kind)
|
||||
@@ -410,18 +315,16 @@ void App::init_sidebar()
|
||||
};
|
||||
|
||||
stroke->on_brush_changed = [this](Node* target, const std::string& path, const std::string& thumb) {
|
||||
apply_brush_texture_plan(pp::app::BrushUiTextureSlot::tip, path, thumb);
|
||||
apply_brush_texture_plan(*this, pp::app::BrushUiTextureSlot::tip, path, thumb);
|
||||
};
|
||||
stroke->on_pattern_changed = [this](Node*target, const std::string& path, const std::string& thumb) {
|
||||
apply_brush_texture_plan(pp::app::BrushUiTextureSlot::pattern, path, thumb);
|
||||
apply_brush_texture_plan(*this, pp::app::BrushUiTextureSlot::pattern, path, thumb);
|
||||
};
|
||||
stroke->on_dual_changed = [this](Node*target, const std::string& path, const std::string& thumb) {
|
||||
apply_brush_texture_plan(pp::app::BrushUiTextureSlot::dual, path, thumb);
|
||||
apply_brush_texture_plan(*this, pp::app::BrushUiTextureSlot::dual, path, thumb);
|
||||
};
|
||||
stroke->on_stroke_change = [this](Node*) {
|
||||
const auto plan = pp::app::plan_brush_ui_stroke_settings_changed();
|
||||
LegacyBrushUiServices services(*this);
|
||||
const auto status = pp::app::execute_brush_ui_plan(plan, services);
|
||||
const auto status = pp::panopainter::execute_legacy_brush_stroke_changed_plan(*this);
|
||||
if (!status.ok())
|
||||
LOG("Brush stroke settings action failed: %s", status.message);
|
||||
};
|
||||
|
||||
388
src/legacy_brush_ui_services.cpp
Normal file
388
src/legacy_brush_ui_services.cpp
Normal file
@@ -0,0 +1,388 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "legacy_brush_ui_services.h"
|
||||
|
||||
#include "app.h"
|
||||
#include "asset.h"
|
||||
#include "canvas.h"
|
||||
#include "image.h"
|
||||
#include "log.h"
|
||||
#include "node_panel_brush.h"
|
||||
#include "node_panel_stroke.h"
|
||||
|
||||
namespace pp::panopainter {
|
||||
namespace {
|
||||
|
||||
class LegacyBrushUiServices final : public pp::app::BrushUiServices {
|
||||
public:
|
||||
LegacyBrushUiServices(
|
||||
App& app,
|
||||
bool update_quick = false,
|
||||
bool update_color_panel = false,
|
||||
const std::shared_ptr<Brush>& preset_brush = nullptr) noexcept
|
||||
: app_(app)
|
||||
, update_quick_(update_quick)
|
||||
, update_color_panel_(update_color_panel)
|
||||
, preset_brush_(preset_brush)
|
||||
{
|
||||
}
|
||||
|
||||
void set_tip_color(float r, float g, float b, float a) override
|
||||
{
|
||||
if (!Canvas::I || !Canvas::I->m_current_brush)
|
||||
return;
|
||||
|
||||
Canvas::I->m_current_brush->m_tip_color = glm::vec4(r, g, b, a);
|
||||
if (update_quick_ && app_.quick)
|
||||
app_.quick->set_color(Canvas::I->m_current_brush->m_tip_color);
|
||||
if (update_color_panel_ && app_.color)
|
||||
app_.color->set_color(Canvas::I->m_current_brush->m_tip_color);
|
||||
}
|
||||
|
||||
void set_texture(
|
||||
pp::app::BrushUiTextureSlot slot,
|
||||
std::string_view path,
|
||||
std::string_view thumbnail_path) override
|
||||
{
|
||||
if (!Canvas::I || !Canvas::I->m_current_brush)
|
||||
return;
|
||||
|
||||
const std::string texture_path(path);
|
||||
const std::string thumbnail(thumbnail_path);
|
||||
switch (slot)
|
||||
{
|
||||
case pp::app::BrushUiTextureSlot::tip:
|
||||
Canvas::I->m_current_brush->load_tip(texture_path, thumbnail);
|
||||
break;
|
||||
case pp::app::BrushUiTextureSlot::pattern:
|
||||
Canvas::I->m_current_brush->load_pattern(texture_path, thumbnail);
|
||||
break;
|
||||
case pp::app::BrushUiTextureSlot::dual:
|
||||
Canvas::I->m_current_brush->load_dual(texture_path, thumbnail);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void replace_brush_from_preset(bool preserve_existing_color, bool load_resources) override
|
||||
{
|
||||
if (!Canvas::I || !Canvas::I->m_current_brush || !preset_brush_)
|
||||
return;
|
||||
|
||||
const auto color = Canvas::I->m_current_brush->m_tip_color;
|
||||
*Canvas::I->m_current_brush = *preset_brush_;
|
||||
if (preserve_existing_color)
|
||||
Canvas::I->m_current_brush->m_tip_color = color;
|
||||
if (load_resources)
|
||||
Canvas::I->m_current_brush->load();
|
||||
}
|
||||
|
||||
void refresh_brush_ui(bool update_color_ui, bool update_brush_ui) override
|
||||
{
|
||||
app_.brush_update(update_color_ui, update_brush_ui);
|
||||
}
|
||||
|
||||
private:
|
||||
App& app_;
|
||||
bool update_quick_ = false;
|
||||
bool update_color_panel_ = false;
|
||||
std::shared_ptr<Brush> preset_brush_;
|
||||
};
|
||||
|
||||
class LegacyBrushStrokeControlServices final : public pp::app::BrushStrokeControlServices {
|
||||
public:
|
||||
explicit LegacyBrushStrokeControlServices(NodePanelStroke& panel) : panel_(panel) {}
|
||||
|
||||
void set_float_setting(pp::app::BrushStrokeFloatSetting setting, float value) override
|
||||
{
|
||||
auto& brush = *Canvas::I->m_current_brush;
|
||||
switch (setting) {
|
||||
case pp::app::BrushStrokeFloatSetting::tip_size: brush.m_tip_size = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_spacing: brush.m_tip_spacing = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_flow: brush.m_tip_flow = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_opacity: brush.m_tip_opacity = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_angle: brush.m_tip_angle = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_angle_smooth: brush.m_tip_angle_smooth = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_mix: brush.m_tip_mix = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_wet: brush.m_tip_wet = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_noise: brush.m_tip_noise = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_hue: brush.m_tip_hue = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_saturation: brush.m_tip_sat = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_value: brush.m_tip_val = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::jitter_scale: brush.m_jitter_scale = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::jitter_angle: brush.m_jitter_angle = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::jitter_scatter: brush.m_jitter_scatter = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::jitter_flow: brush.m_jitter_flow = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::jitter_opacity: brush.m_jitter_opacity = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::jitter_hue: brush.m_jitter_hue = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::jitter_saturation: brush.m_jitter_sat = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::jitter_value: brush.m_jitter_val = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::jitter_aspect: brush.m_jitter_aspect = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::dual_size: brush.m_dual_size = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::dual_spacing: brush.m_dual_spacing = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::dual_scatter: brush.m_dual_scatter = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_aspect: brush.m_tip_aspect = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::dual_opacity: brush.m_dual_opacity = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::dual_flow: brush.m_dual_flow = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::dual_rotate: brush.m_dual_rotate = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::pattern_scale: brush.m_pattern_scale = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::pattern_brightness: brush.m_pattern_brightness = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::pattern_contrast: brush.m_pattern_contrast = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::pattern_depth: brush.m_pattern_depth = value; break;
|
||||
}
|
||||
}
|
||||
|
||||
void set_bool_setting(pp::app::BrushStrokeBoolSetting setting, bool value) override
|
||||
{
|
||||
auto& brush = *Canvas::I->m_current_brush;
|
||||
switch (setting) {
|
||||
case pp::app::BrushStrokeBoolSetting::tip_angle_init: brush.m_tip_angle_init = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::tip_angle_follow: brush.m_tip_angle_follow = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::tip_flow_pressure: brush.m_tip_flow_pressure = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::tip_opacity_pressure: brush.m_tip_opacity_pressure = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::tip_size_pressure: brush.m_tip_size_pressure = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::jitter_scatter_both_axis: brush.m_jitter_scatter_bothaxis = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::jitter_aspect_both_axis: brush.m_jitter_aspect_bothaxis = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::jitter_hsv_each_sample: brush.m_jitter_hsv_eachsample = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::tip_invert: brush.m_tip_invert = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::tip_flip_x: brush.m_tip_flipx = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::tip_flip_y: brush.m_tip_flipy = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::pattern_enabled: brush.m_pattern_enabled = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::dual_enabled: brush.m_dual_enabled = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::dual_scatter_both_axis: brush.m_dual_scatter_bothaxis = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::dual_invert: brush.m_dual_invert = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::dual_flip_x: brush.m_dual_flipx = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::dual_flip_y: brush.m_dual_flipy = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::dual_random_flip: brush.m_dual_randflip = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::tip_random_flip_x: brush.m_tip_randflipx = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::tip_random_flip_y: brush.m_tip_randflipy = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::pattern_each_sample: brush.m_pattern_eachsample = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::pattern_invert: brush.m_pattern_invert = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::pattern_flip_x: brush.m_pattern_flipx = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::pattern_flip_y: brush.m_pattern_flipy = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::pattern_random_offset: brush.m_pattern_rand_offset = value; break;
|
||||
}
|
||||
}
|
||||
|
||||
void set_blend_mode(pp::app::BrushStrokeBlendSetting setting, int blend_mode) override
|
||||
{
|
||||
auto& brush = *Canvas::I->m_current_brush;
|
||||
switch (setting) {
|
||||
case pp::app::BrushStrokeBlendSetting::tip: brush.m_blend_mode = blend_mode; break;
|
||||
case pp::app::BrushStrokeBlendSetting::dual: brush.m_dual_blend_mode = blend_mode; break;
|
||||
case pp::app::BrushStrokeBlendSetting::pattern: brush.m_pattern_blend_mode = blend_mode; break;
|
||||
}
|
||||
}
|
||||
|
||||
void reset_tip_aspect(float value) override
|
||||
{
|
||||
panel_.m_tip_aspect->set_value(value);
|
||||
Canvas::I->m_current_brush->m_tip_aspect = value;
|
||||
}
|
||||
|
||||
void reset_default_brush() override
|
||||
{
|
||||
auto brush = std::make_shared<Brush>();
|
||||
brush->load_tip(
|
||||
panel_.m_brush_popup->get_texture_path(panel_.m_default_brush_index),
|
||||
panel_.m_brush_popup->get_thumb_path(panel_.m_default_brush_index));
|
||||
brush->m_tip_size = 30;
|
||||
brush->m_tip_flow = .9f;
|
||||
brush->m_tip_spacing = .1f;
|
||||
brush->m_tip_opacity = 1.f;
|
||||
Canvas::I->m_current_brush = brush;
|
||||
}
|
||||
|
||||
void update_stroke_controls() override
|
||||
{
|
||||
panel_.update_controls();
|
||||
}
|
||||
|
||||
void refresh_stroke_preview() override
|
||||
{
|
||||
if (panel_.m_preview) {
|
||||
panel_.m_preview->m_brush = Canvas::I->m_current_brush;
|
||||
}
|
||||
}
|
||||
|
||||
void notify_stroke_changed() override
|
||||
{
|
||||
if (panel_.on_stroke_change) {
|
||||
panel_.on_stroke_change(&panel_);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
NodePanelStroke& panel_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
class LegacyBrushTextureListServices final : public pp::app::BrushTextureListServices {
|
||||
public:
|
||||
explicit LegacyBrushTextureListServices(NodePanelBrush& panel) noexcept
|
||||
: panel_(panel)
|
||||
{
|
||||
}
|
||||
|
||||
pp::foundation::Status add_texture_from_source(
|
||||
std::string_view source_path,
|
||||
std::string_view high_path,
|
||||
std::string_view thumbnail_path,
|
||||
std::string_view brush_name,
|
||||
bool converts_brush_alpha) override
|
||||
{
|
||||
Image img;
|
||||
if (!img.load_file(std::string(source_path))) {
|
||||
return pp::foundation::Status::invalid_argument("brush texture source could not be loaded");
|
||||
}
|
||||
|
||||
if (converts_brush_alpha) {
|
||||
img.gayscale_alpha();
|
||||
}
|
||||
|
||||
auto thumbnail_image = img.resize(64, 64).resize_squared(glm::u8vec4(255));
|
||||
thumbnail_image.save_png(std::string(thumbnail_path));
|
||||
img.save_png(std::string(high_path));
|
||||
|
||||
NodeButtonBrush* brush = new NodeButtonBrush;
|
||||
panel_.m_container->add_child(brush);
|
||||
brush->init();
|
||||
brush->create();
|
||||
brush->loaded();
|
||||
const auto thumbnail_path_string = std::string(thumbnail_path);
|
||||
brush->set_icon(thumbnail_path_string.c_str());
|
||||
brush->thumb_path = std::string(thumbnail_path);
|
||||
brush->high_path = std::string(high_path);
|
||||
brush->brush_name = std::string(brush_name);
|
||||
brush->m_user_brush = true;
|
||||
brush->on_click = std::bind(&NodePanelBrush::handle_click, &panel_, std::placeholders::_1);
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
void remove_texture(int index, bool delete_texture_files) override
|
||||
{
|
||||
auto* brush = brush_at(index);
|
||||
if (!brush) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (delete_texture_files) {
|
||||
Asset::delete_file(brush->thumb_path);
|
||||
Asset::delete_file(brush->high_path);
|
||||
}
|
||||
|
||||
if (panel_.m_current == brush) {
|
||||
panel_.m_current = nullptr;
|
||||
}
|
||||
panel_.m_container->remove_child(brush);
|
||||
}
|
||||
|
||||
void move_texture(int from_index, int to_index) override
|
||||
{
|
||||
if (auto* brush = brush_at(from_index)) {
|
||||
panel_.m_container->move_child(brush, to_index);
|
||||
}
|
||||
}
|
||||
|
||||
void select_texture(int index) override
|
||||
{
|
||||
if (panel_.m_current) {
|
||||
panel_.m_current->m_selected = false;
|
||||
}
|
||||
|
||||
panel_.m_current = brush_at(index);
|
||||
if (!panel_.m_current) {
|
||||
return;
|
||||
}
|
||||
|
||||
panel_.m_current->m_selected = true;
|
||||
if (panel_.on_brush_changed) {
|
||||
panel_.on_brush_changed(&panel_, index);
|
||||
}
|
||||
}
|
||||
|
||||
void save_texture_list() override
|
||||
{
|
||||
panel_.save();
|
||||
}
|
||||
|
||||
private:
|
||||
NodeButtonBrush* brush_at(int index) const
|
||||
{
|
||||
if (index < 0 || index >= static_cast<int>(panel_.m_container->m_children.size())) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<NodeButtonBrush*>(panel_.m_container->m_children[index].get());
|
||||
}
|
||||
|
||||
NodePanelBrush& panel_;
|
||||
};
|
||||
|
||||
bool apply_legacy_brush_color_plan(
|
||||
App& app,
|
||||
glm::vec4 color,
|
||||
bool update_quick,
|
||||
bool update_color_panel)
|
||||
{
|
||||
const auto plan = pp::app::plan_brush_ui_color(color.r, color.g, color.b, color.a);
|
||||
if (!plan)
|
||||
return false;
|
||||
LegacyBrushUiServices services(app, update_quick, update_color_panel);
|
||||
const auto status = pp::app::execute_brush_ui_plan(plan.value(), services);
|
||||
if (!status.ok())
|
||||
LOG("Brush color action failed: %s", status.message);
|
||||
return status.ok();
|
||||
}
|
||||
|
||||
bool apply_legacy_brush_texture_plan(
|
||||
App& app,
|
||||
pp::app::BrushUiTextureSlot slot,
|
||||
const std::string& path,
|
||||
const std::string& thumb)
|
||||
{
|
||||
const auto plan = pp::app::plan_brush_ui_texture(slot, path, thumb);
|
||||
if (!plan)
|
||||
return false;
|
||||
LegacyBrushUiServices services(app);
|
||||
const auto status = pp::app::execute_brush_ui_plan(plan.value(), services);
|
||||
if (!status.ok())
|
||||
LOG("Brush texture action failed: %s", status.message);
|
||||
return status.ok();
|
||||
}
|
||||
|
||||
bool apply_legacy_brush_preset_plan(App& app, const std::shared_ptr<Brush>& brush)
|
||||
{
|
||||
const auto plan = pp::app::plan_brush_ui_preset_replace(static_cast<bool>(brush));
|
||||
if (!plan)
|
||||
return false;
|
||||
LegacyBrushUiServices services(app, false, false, brush);
|
||||
const auto status = pp::app::execute_brush_ui_plan(plan.value(), services);
|
||||
if (!status.ok())
|
||||
LOG("Brush preset action failed: %s", status.message);
|
||||
return status.ok();
|
||||
}
|
||||
|
||||
pp::foundation::Status execute_legacy_brush_stroke_changed_plan(App& app)
|
||||
{
|
||||
const auto plan = pp::app::plan_brush_ui_stroke_settings_changed();
|
||||
LegacyBrushUiServices services(app);
|
||||
return pp::app::execute_brush_ui_plan(plan, services);
|
||||
}
|
||||
|
||||
pp::foundation::Status execute_legacy_brush_texture_list_plan(
|
||||
NodePanelBrush& panel,
|
||||
const pp::app::BrushTextureListPlan& plan)
|
||||
{
|
||||
LegacyBrushTextureListServices services(panel);
|
||||
return pp::app::execute_brush_texture_list_plan(plan, services);
|
||||
}
|
||||
|
||||
pp::foundation::Status execute_legacy_brush_stroke_control_plan(
|
||||
NodePanelStroke& panel,
|
||||
const pp::app::BrushStrokeControlPlan& plan)
|
||||
{
|
||||
LegacyBrushStrokeControlServices services(panel);
|
||||
return pp::app::execute_brush_stroke_control_plan(plan, services);
|
||||
}
|
||||
|
||||
} // namespace pp::panopainter
|
||||
38
src/legacy_brush_ui_services.h
Normal file
38
src/legacy_brush_ui_services.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include "app_core/brush_ui.h"
|
||||
#include "foundation/result.h"
|
||||
#include "glm/glm.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
class App;
|
||||
class Brush;
|
||||
class NodePanelBrush;
|
||||
class NodePanelStroke;
|
||||
|
||||
namespace pp::panopainter {
|
||||
|
||||
[[nodiscard]] bool apply_legacy_brush_color_plan(
|
||||
App& app,
|
||||
glm::vec4 color,
|
||||
bool update_quick,
|
||||
bool update_color_panel);
|
||||
[[nodiscard]] bool apply_legacy_brush_texture_plan(
|
||||
App& app,
|
||||
pp::app::BrushUiTextureSlot slot,
|
||||
const std::string& path,
|
||||
const std::string& thumb);
|
||||
[[nodiscard]] bool apply_legacy_brush_preset_plan(
|
||||
App& app,
|
||||
const std::shared_ptr<Brush>& brush);
|
||||
[[nodiscard]] pp::foundation::Status execute_legacy_brush_stroke_changed_plan(App& app);
|
||||
[[nodiscard]] pp::foundation::Status execute_legacy_brush_texture_list_plan(
|
||||
NodePanelBrush& panel,
|
||||
const pp::app::BrushTextureListPlan& plan);
|
||||
[[nodiscard]] pp::foundation::Status execute_legacy_brush_stroke_control_plan(
|
||||
NodePanelStroke& panel,
|
||||
const pp::app::BrushStrokeControlPlan& plan);
|
||||
|
||||
} // namespace pp::panopainter
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "log.h"
|
||||
#include "node_panel_brush.h"
|
||||
#include "app_core/brush_ui.h"
|
||||
#include "legacy_brush_ui_services.h"
|
||||
#include "asset.h"
|
||||
#include "texture.h"
|
||||
|
||||
@@ -78,109 +79,7 @@ Node* NodePanelBrush::clone_instantiate() const
|
||||
|
||||
void NodePanelBrush::execute_texture_list_plan(const pp::app::BrushTextureListPlan& plan)
|
||||
{
|
||||
class LegacyBrushTextureListServices final : public pp::app::BrushTextureListServices {
|
||||
public:
|
||||
explicit LegacyBrushTextureListServices(NodePanelBrush& panel) noexcept
|
||||
: panel_(panel)
|
||||
{
|
||||
}
|
||||
|
||||
pp::foundation::Status add_texture_from_source(
|
||||
std::string_view source_path,
|
||||
std::string_view high_path,
|
||||
std::string_view thumbnail_path,
|
||||
std::string_view brush_name,
|
||||
bool converts_brush_alpha) override
|
||||
{
|
||||
Image img;
|
||||
if (!img.load_file(std::string(source_path))) {
|
||||
return pp::foundation::Status::invalid_argument("brush texture source could not be loaded");
|
||||
}
|
||||
|
||||
if (converts_brush_alpha) {
|
||||
img.gayscale_alpha();
|
||||
}
|
||||
|
||||
auto thumbnail_image = img.resize(64, 64).resize_squared(glm::u8vec4(255));
|
||||
thumbnail_image.save_png(std::string(thumbnail_path));
|
||||
img.save_png(std::string(high_path));
|
||||
|
||||
NodeButtonBrush* brush = new NodeButtonBrush;
|
||||
panel_.m_container->add_child(brush);
|
||||
brush->init();
|
||||
brush->create();
|
||||
brush->loaded();
|
||||
const auto thumbnail_path_string = std::string(thumbnail_path);
|
||||
brush->set_icon(thumbnail_path_string.c_str());
|
||||
brush->thumb_path = std::string(thumbnail_path);
|
||||
brush->high_path = std::string(high_path);
|
||||
brush->brush_name = std::string(brush_name);
|
||||
brush->m_user_brush = true;
|
||||
brush->on_click = std::bind(&NodePanelBrush::handle_click, &panel_, std::placeholders::_1);
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
void remove_texture(int index, bool delete_texture_files) override
|
||||
{
|
||||
auto* brush = brush_at(index);
|
||||
if (!brush) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (delete_texture_files) {
|
||||
Asset::delete_file(brush->thumb_path);
|
||||
Asset::delete_file(brush->high_path);
|
||||
}
|
||||
|
||||
if (panel_.m_current == brush) {
|
||||
panel_.m_current = nullptr;
|
||||
}
|
||||
panel_.m_container->remove_child(brush);
|
||||
}
|
||||
|
||||
void move_texture(int from_index, int to_index) override
|
||||
{
|
||||
if (auto* brush = brush_at(from_index)) {
|
||||
panel_.m_container->move_child(brush, to_index);
|
||||
}
|
||||
}
|
||||
|
||||
void select_texture(int index) override
|
||||
{
|
||||
if (panel_.m_current) {
|
||||
panel_.m_current->m_selected = false;
|
||||
}
|
||||
|
||||
panel_.m_current = brush_at(index);
|
||||
if (!panel_.m_current) {
|
||||
return;
|
||||
}
|
||||
|
||||
panel_.m_current->m_selected = true;
|
||||
if (panel_.on_brush_changed) {
|
||||
panel_.on_brush_changed(&panel_, index);
|
||||
}
|
||||
}
|
||||
|
||||
void save_texture_list() override
|
||||
{
|
||||
panel_.save();
|
||||
}
|
||||
|
||||
private:
|
||||
NodeButtonBrush* brush_at(int index) const
|
||||
{
|
||||
if (index < 0 || index >= static_cast<int>(panel_.m_container->m_children.size())) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<NodeButtonBrush*>(panel_.m_container->m_children[index].get());
|
||||
}
|
||||
|
||||
NodePanelBrush& panel_;
|
||||
};
|
||||
|
||||
LegacyBrushTextureListServices services(*this);
|
||||
const auto status = pp::app::execute_brush_texture_list_plan(plan, services);
|
||||
const auto status = pp::panopainter::execute_legacy_brush_texture_list_plan(*this, plan);
|
||||
if (!status.ok()) {
|
||||
LOG("Brush texture list action failed: %s", status.message);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
namespace pp::app {
|
||||
struct BrushTextureListPlan;
|
||||
}
|
||||
namespace pp::panopainter {
|
||||
class LegacyBrushTextureListServices;
|
||||
}
|
||||
|
||||
class NodeButtonBrush : public NodeButtonCustom, public Serializer::Type
|
||||
{
|
||||
@@ -34,6 +37,8 @@ public:
|
||||
|
||||
class NodePanelBrush : public Node
|
||||
{
|
||||
friend class pp::panopainter::LegacyBrushTextureListServices;
|
||||
|
||||
// brushes that are marked as deleted but file still exists
|
||||
std::vector<std::string> m_deleted;
|
||||
NodeButtonBrush* m_current = nullptr;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "pch.h"
|
||||
#include "app_core/brush_ui.h"
|
||||
#include "legacy_brush_ui_services.h"
|
||||
#include "log.h"
|
||||
#include "node_panel_stroke.h"
|
||||
#include "canvas.h"
|
||||
@@ -7,137 +8,6 @@
|
||||
#include "app.h"
|
||||
#include "abr.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class LegacyBrushStrokeControlServices final : public pp::app::BrushStrokeControlServices {
|
||||
public:
|
||||
explicit LegacyBrushStrokeControlServices(NodePanelStroke& panel) : panel_(panel) {}
|
||||
|
||||
void set_float_setting(pp::app::BrushStrokeFloatSetting setting, float value) override
|
||||
{
|
||||
auto& brush = *Canvas::I->m_current_brush;
|
||||
switch (setting) {
|
||||
case pp::app::BrushStrokeFloatSetting::tip_size: brush.m_tip_size = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_spacing: brush.m_tip_spacing = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_flow: brush.m_tip_flow = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_opacity: brush.m_tip_opacity = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_angle: brush.m_tip_angle = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_angle_smooth: brush.m_tip_angle_smooth = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_mix: brush.m_tip_mix = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_wet: brush.m_tip_wet = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_noise: brush.m_tip_noise = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_hue: brush.m_tip_hue = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_saturation: brush.m_tip_sat = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_value: brush.m_tip_val = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::jitter_scale: brush.m_jitter_scale = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::jitter_angle: brush.m_jitter_angle = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::jitter_scatter: brush.m_jitter_scatter = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::jitter_flow: brush.m_jitter_flow = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::jitter_opacity: brush.m_jitter_opacity = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::jitter_hue: brush.m_jitter_hue = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::jitter_saturation: brush.m_jitter_sat = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::jitter_value: brush.m_jitter_val = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::jitter_aspect: brush.m_jitter_aspect = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::dual_size: brush.m_dual_size = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::dual_spacing: brush.m_dual_spacing = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::dual_scatter: brush.m_dual_scatter = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::tip_aspect: brush.m_tip_aspect = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::dual_opacity: brush.m_dual_opacity = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::dual_flow: brush.m_dual_flow = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::dual_rotate: brush.m_dual_rotate = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::pattern_scale: brush.m_pattern_scale = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::pattern_brightness: brush.m_pattern_brightness = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::pattern_contrast: brush.m_pattern_contrast = value; break;
|
||||
case pp::app::BrushStrokeFloatSetting::pattern_depth: brush.m_pattern_depth = value; break;
|
||||
}
|
||||
}
|
||||
|
||||
void set_bool_setting(pp::app::BrushStrokeBoolSetting setting, bool value) override
|
||||
{
|
||||
auto& brush = *Canvas::I->m_current_brush;
|
||||
switch (setting) {
|
||||
case pp::app::BrushStrokeBoolSetting::tip_angle_init: brush.m_tip_angle_init = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::tip_angle_follow: brush.m_tip_angle_follow = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::tip_flow_pressure: brush.m_tip_flow_pressure = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::tip_opacity_pressure: brush.m_tip_opacity_pressure = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::tip_size_pressure: brush.m_tip_size_pressure = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::jitter_scatter_both_axis: brush.m_jitter_scatter_bothaxis = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::jitter_aspect_both_axis: brush.m_jitter_aspect_bothaxis = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::jitter_hsv_each_sample: brush.m_jitter_hsv_eachsample = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::tip_invert: brush.m_tip_invert = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::tip_flip_x: brush.m_tip_flipx = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::tip_flip_y: brush.m_tip_flipy = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::pattern_enabled: brush.m_pattern_enabled = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::dual_enabled: brush.m_dual_enabled = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::dual_scatter_both_axis: brush.m_dual_scatter_bothaxis = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::dual_invert: brush.m_dual_invert = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::dual_flip_x: brush.m_dual_flipx = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::dual_flip_y: brush.m_dual_flipy = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::dual_random_flip: brush.m_dual_randflip = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::tip_random_flip_x: brush.m_tip_randflipx = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::tip_random_flip_y: brush.m_tip_randflipy = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::pattern_each_sample: brush.m_pattern_eachsample = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::pattern_invert: brush.m_pattern_invert = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::pattern_flip_x: brush.m_pattern_flipx = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::pattern_flip_y: brush.m_pattern_flipy = value; break;
|
||||
case pp::app::BrushStrokeBoolSetting::pattern_random_offset: brush.m_pattern_rand_offset = value; break;
|
||||
}
|
||||
}
|
||||
|
||||
void set_blend_mode(pp::app::BrushStrokeBlendSetting setting, int blend_mode) override
|
||||
{
|
||||
auto& brush = *Canvas::I->m_current_brush;
|
||||
switch (setting) {
|
||||
case pp::app::BrushStrokeBlendSetting::tip: brush.m_blend_mode = blend_mode; break;
|
||||
case pp::app::BrushStrokeBlendSetting::dual: brush.m_dual_blend_mode = blend_mode; break;
|
||||
case pp::app::BrushStrokeBlendSetting::pattern: brush.m_pattern_blend_mode = blend_mode; break;
|
||||
}
|
||||
}
|
||||
|
||||
void reset_tip_aspect(float value) override
|
||||
{
|
||||
panel_.m_tip_aspect->set_value(value);
|
||||
Canvas::I->m_current_brush->m_tip_aspect = value;
|
||||
}
|
||||
|
||||
void reset_default_brush() override
|
||||
{
|
||||
auto brush = std::make_shared<Brush>();
|
||||
brush->load_tip(
|
||||
panel_.m_brush_popup->get_texture_path(panel_.m_default_brush_index),
|
||||
panel_.m_brush_popup->get_thumb_path(panel_.m_default_brush_index));
|
||||
brush->m_tip_size = 30;
|
||||
brush->m_tip_flow = .9f;
|
||||
brush->m_tip_spacing = .1f;
|
||||
brush->m_tip_opacity = 1.f;
|
||||
Canvas::I->m_current_brush = brush;
|
||||
}
|
||||
|
||||
void update_stroke_controls() override
|
||||
{
|
||||
panel_.update_controls();
|
||||
}
|
||||
|
||||
void refresh_stroke_preview() override
|
||||
{
|
||||
if (panel_.m_preview) {
|
||||
panel_.m_preview->m_brush = Canvas::I->m_current_brush;
|
||||
}
|
||||
}
|
||||
|
||||
void notify_stroke_changed() override
|
||||
{
|
||||
if (panel_.on_stroke_change) {
|
||||
panel_.on_stroke_change(&panel_);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
NodePanelStroke& panel_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
Node* NodePanelStroke::clone_instantiate() const
|
||||
{
|
||||
return new NodePanelStroke();
|
||||
@@ -704,8 +574,7 @@ void NodePanelStroke::handle_checkbox(
|
||||
|
||||
void NodePanelStroke::execute_stroke_control_plan(const pp::app::BrushStrokeControlPlan& plan)
|
||||
{
|
||||
LegacyBrushStrokeControlServices services(*this);
|
||||
const auto status = pp::app::execute_brush_stroke_control_plan(plan, services);
|
||||
const auto status = pp::panopainter::execute_legacy_brush_stroke_control_plan(*this, plan);
|
||||
if (!status.ok()) {
|
||||
LOG("Brush stroke control action failed: %s", status.message);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user