diff --git a/modules/paint/nodes/paint_canvas.cpp b/modules/paint/nodes/paint_canvas.cpp index ff55b132e..0b6c47975 100644 --- a/modules/paint/nodes/paint_canvas.cpp +++ b/modules/paint/nodes/paint_canvas.cpp @@ -176,70 +176,71 @@ void PaintCanvas::clear() { void PaintCanvas::clear_preview() { _preview_image->fill(Color(1.00, 1.00, 1.00, 0.00)); - _preview_image_texture->create_from_image(_preview_image, 0); } void PaintCanvas::update_textures() { - _image_texture->create_from_image(_image, 0); - _preview_image_texture->create_from_image(_preview_image, 0); + if (!_image->empty()) { + _image_texture->create_from_image(_image, 0); + } + + if (!_preview_image->empty()) { + _preview_image_texture->create_from_image(_preview_image, 0); + } update(); } -void PaintCanvas::resize(int width, int height) { - if (get_size().x == width && get_size().y == height) { +void PaintCanvas::resize_crop(int width, int height) { + Vector2i size = get_size(); + + if (size.x == width && size.y == height) { return; } - if (width < 0) { - width = 1; + if (width <= 0 || height <= 0) { + _image->clear(); + _preview_image->clear(); + + update_textures(); + + set_size(Vector2i(width, height)); + + return; } - if (height < 0) { - height = 1; - } - - set_size(Vector2i(width, height)); - - resize_image(_image); - resize_image(_preview_image); + _image->crop(width, height); + _preview_image->crop(width, height); update_textures(); + + set_size(Vector2i(width, height)); } -void PaintCanvas::resize_image(Ref image) { - ERR_FAIL_COND(!image.is_valid()); +void PaintCanvas::resize_interpolate(const int width, const int height, Image::Interpolation p_interpolation) { + Vector2i size = get_size(); - PoolColorArray pixel_colors; - int prev_width = image->get_size().x; - int prev_height = image->get_size().y; - - if (prev_width != 0 && prev_height != 0) { - image->lock(); - for (int y = 0; y < prev_height; ++y) { - for (int x = 0; x < prev_width; ++x) { - pixel_colors.append(image->get_pixel(x, y)); - } - } - image->unlock(); + if (size.x == width && size.y == height) { + return; } - image->create(get_size().x, get_size().y, false, Image::FORMAT_RGBA8); + if (width <= 0 || height <= 0) { + _image->clear(); + _preview_image->clear(); - image->lock(); + update_textures(); - for (int x = 0; x < prev_width; ++x) { - for (int y = 0; y < prev_height; ++y) { - if (x >= get_size().x || y >= get_size().y) { - continue; - } + set_size(Vector2i(width, height)); - image->set_pixel(x, y, pixel_colors[PaintUtilities::to_1D(x, y, prev_width)]); - } + return; } - image->unlock(); + _image->resize(width, height, p_interpolation); + _preview_image->resize(width, height, p_interpolation); + + update_textures(); + + set_size(Vector2i(width, height)); } PoolVector2iArray PaintCanvas::select_color(const int p_x, const int p_y) { @@ -871,13 +872,39 @@ PaintCanvas::PaintCanvas() { PaintCanvas::~PaintCanvas() { } +void PaintCanvas::_on_size_changed() { + Vector2i size = get_size(); + + if (size.x <= 0 || size.y <= 0) { + _image->clear(); + _preview_image->clear(); + + update_textures(); + + return; + } + + if (_image->empty()) { + _image->create(size.x, size.y, false, Image::FORMAT_RGBA8); + } else { + _image->crop(size.x, size.y); + } + + if (_preview_image->empty()) { + _preview_image->create(size.x, size.y, false, Image::FORMAT_RGBA8); + } else { + _preview_image->crop(size.x, size.y); + } + + update_textures(); +} + void PaintCanvas::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_POSTINITIALIZE: { + connect("size_changed", this, "_on_size_changed"); + } break; case NOTIFICATION_READY: { - //temp - resize(1, 1); - resize(128, 128); - if (!is_connected("current_tool_changed", this, "_on_tool_changed")) { connect("current_tool_changed", this, "_on_tool_changed"); } @@ -885,8 +912,13 @@ void PaintCanvas::_notification(int p_what) { _on_tool_changed(); } break; case NOTIFICATION_DRAW: { - draw_texture(_image_texture, Point2()); - draw_texture(_preview_image_texture, Point2()); + if (!_image->empty()) { + draw_texture(_image_texture, Point2()); + } + + if (!_preview_image->empty()) { + draw_texture(_preview_image_texture, Point2()); + } } break; } } @@ -943,8 +975,8 @@ void PaintCanvas::_bind_methods() { ClassDB::bind_method(D_METHOD("clear_preview"), &PaintCanvas::clear_preview); ClassDB::bind_method(D_METHOD("update_textures"), &PaintCanvas::update_textures); - ClassDB::bind_method(D_METHOD("resize", "width", "height"), &PaintCanvas::resize); - ClassDB::bind_method(D_METHOD("resize_image", "image"), &PaintCanvas::resize_image); + ClassDB::bind_method(D_METHOD("resize_crop", "width", "height"), &PaintCanvas::resize_crop); + ClassDB::bind_method(D_METHOD("resize_interpolate", "width", "height", "interpolation"), &PaintCanvas::resize_interpolate, Image::INTERPOLATE_BILINEAR); ClassDB::bind_method(D_METHOD("select_color", "x", "y"), &PaintCanvas::select_color); ClassDB::bind_method(D_METHOD("select_same_color", "x", "y"), &PaintCanvas::select_same_color); @@ -972,6 +1004,8 @@ void PaintCanvas::_bind_methods() { ClassDB::bind_method(D_METHOD("_on_tool_changed"), &PaintCanvas::_on_tool_changed); ClassDB::bind_method(D_METHOD("tool_process", "local_position", "event"), &PaintCanvas::tool_process); + ClassDB::bind_method(D_METHOD("_on_size_changed"), &PaintCanvas::_on_size_changed); + BIND_ENUM_CONSTANT(TOOL_PENCIL); BIND_ENUM_CONSTANT(TOOL_BRUSH); BIND_ENUM_CONSTANT(TOOL_BUCKET); diff --git a/modules/paint/nodes/paint_canvas.h b/modules/paint/nodes/paint_canvas.h index 508414cc0..488331196 100644 --- a/modules/paint/nodes/paint_canvas.h +++ b/modules/paint/nodes/paint_canvas.h @@ -69,8 +69,8 @@ public: void clear_preview(); void update_textures(); - void resize(const int width, const int height); - void resize_image(Ref image); + void resize_crop(const int width, const int height); + void resize_interpolate(const int width, const int height, Image::Interpolation p_interpolation = Image::INTERPOLATE_BILINEAR); PoolVector2iArray select_color(const int p_x, const int p_y); PoolVector2iArray select_same_color(const int p_x, const int p_y); @@ -108,6 +108,8 @@ public: ~PaintCanvas(); protected: + void _on_size_changed(); + void _notification(int p_what); static void _bind_methods(); diff --git a/modules/paint/nodes/paint_node.cpp b/modules/paint/nodes/paint_node.cpp index 294553b48..c7d71466f 100644 --- a/modules/paint/nodes/paint_node.cpp +++ b/modules/paint/nodes/paint_node.cpp @@ -7,12 +7,15 @@ Vector2i PaintNode::get_size() { return _size; } void PaintNode::set_size(const Vector2i &size) { + if (size == _size) { + return; + } + _size = size; - if (is_inside_tree()) { - _propagate_notification_resized(); - update(); - } + emit_signal("size_changed"); + _propagate_notification_resized(); + update(); } bool PaintNode::get_draw_outline() { @@ -21,9 +24,7 @@ bool PaintNode::get_draw_outline() { void PaintNode::set_draw_outline(const bool val) { _draw_outline = val; - if (is_inside_tree()) { - update(); - } + update(); } void PaintNode::save_image() { @@ -88,6 +89,26 @@ PaintProject *PaintNode::get_paint_project() { return NULL; } +PaintNode *PaintNode::get_parent_paint_node() { + return Object::cast_to(get_parent()); +} + +PaintNode *PaintNode::find_parent_paint_node() { + Node *p = get_parent(); + + while (p) { + PaintNode *pn = Object::cast_to(p); + + if (pn) { + return pn; + } + + p = Object::cast_to(p->get_parent()); + } + + return NULL; +} + String PaintNode::get_configuration_warning() const { const PaintNode *p = this; @@ -105,13 +126,14 @@ String PaintNode::get_configuration_warning() const { } void PaintNode::_propagate_notification_resized() { - notification(NOTIFICATION_PAINT_NODE_RESIZED); + //Only send it to children + //So if they don't resize themselves, the notification stops for (int i = 0; i < get_child_count(); ++i) { PaintNode *pn = Object::cast_to(get_child(i)); if (pn) { - pn->_propagate_notification_resized(); + pn->notification(NOTIFICATION_PARENT_PAINT_NODE_RESIZED); } } } @@ -148,6 +170,15 @@ PaintNode::~PaintNode() { void PaintNode::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_POST_ENTER_TREE: { + if (get_size() == Vector2i(0, 0)) { + PaintNode *pn = get_parent_paint_node(); + + if (pn) { + set_size(pn->get_size()); + } + } + } break; case NOTIFICATION_DRAW: { if (_draw_outline) { draw_line(Point2(0, 0), Point2(_size.x, 0), Color(0, 0, 0, 1)); @@ -162,6 +193,8 @@ void PaintNode::_notification(int p_what) { } void PaintNode::_bind_methods() { + ADD_SIGNAL(MethodInfo("size_changed")); + ClassDB::bind_method(D_METHOD("get_size"), &PaintNode::get_size); ClassDB::bind_method(D_METHOD("set_size", "size"), &PaintNode::set_size); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size"), "set_size", "get_size"); @@ -193,8 +226,10 @@ void PaintNode::_bind_methods() { ClassDB::bind_method(D_METHOD("_forward_canvas_gui_input", "event"), &PaintNode::_forward_canvas_gui_input); ClassDB::bind_method(D_METHOD("get_paint_project"), &PaintNode::get_paint_project); + ClassDB::bind_method(D_METHOD("get_parent_paint_node"), &PaintNode::get_parent_paint_node); + ClassDB::bind_method(D_METHOD("find_parent_paint_node"), &PaintNode::find_parent_paint_node); - BIND_CONSTANT(NOTIFICATION_PAINT_NODE_RESIZED); + BIND_CONSTANT(NOTIFICATION_PARENT_PAINT_NODE_RESIZED); BIND_CONSTANT(NOTIFICATION_PAINT_PROJECT_PRE_SAVE); BIND_CONSTANT(NOTIFICATION_PAINT_PROJECT_POST_SAVE); } diff --git a/modules/paint/nodes/paint_node.h b/modules/paint/nodes/paint_node.h index 19e1a317f..011e9ecf4 100644 --- a/modules/paint/nodes/paint_node.h +++ b/modules/paint/nodes/paint_node.h @@ -12,7 +12,7 @@ class PaintNode : public Node2D { public: enum { - NOTIFICATION_PAINT_NODE_RESIZED = 2500, + NOTIFICATION_PARENT_PAINT_NODE_RESIZED = 2500, NOTIFICATION_PAINT_PROJECT_PRE_SAVE = 2501, NOTIFICATION_PAINT_PROJECT_POST_SAVE = 2502, }; @@ -43,10 +43,12 @@ public: virtual bool _forward_canvas_gui_input(const Ref &p_event); PaintProject *get_paint_project(); + PaintNode *get_parent_paint_node(); + PaintNode *find_parent_paint_node(); String get_configuration_warning() const; - virtual void _propagate_notification_resized(); + void _propagate_notification_resized(); void _propagate_notification_project_pre_save(); void _propagate_notification_project_post_save(); diff --git a/modules/paint/nodes/paint_project.cpp b/modules/paint/nodes/paint_project.cpp index 1c30bcb4c..23b3b139f 100644 --- a/modules/paint/nodes/paint_project.cpp +++ b/modules/paint/nodes/paint_project.cpp @@ -92,9 +92,6 @@ void PaintProject::add_paint_visual_grid() { } } -void PaintProject::_propagate_notification_resized() { -} - PaintProject::PaintProject() { _current_color = Color(1, 1, 1, 1); } diff --git a/modules/paint/nodes/paint_project.h b/modules/paint/nodes/paint_project.h index 190265619..c13062857 100644 --- a/modules/paint/nodes/paint_project.h +++ b/modules/paint/nodes/paint_project.h @@ -31,8 +31,6 @@ public: void add_paint_canvas_backgorund(); void add_paint_visual_grid(); - void _propagate_notification_resized(); - PaintProject(); ~PaintProject(); diff --git a/modules/paint/ui/paint_canvas_background.cpp b/modules/paint/ui/paint_canvas_background.cpp index a865c6c81..e5de04050 100644 --- a/modules/paint/ui/paint_canvas_background.cpp +++ b/modules/paint/ui/paint_canvas_background.cpp @@ -82,7 +82,7 @@ PaintCanvasBackground::~PaintCanvasBackground() { void PaintCanvasBackground::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: - case PaintNode::NOTIFICATION_PAINT_NODE_RESIZED: { + case PaintNode::NOTIFICATION_PARENT_PAINT_NODE_RESIZED: { PaintNode *pn = get_paint_node(); if (pn) { diff --git a/modules/paint/ui/paint_visual_grid.cpp b/modules/paint/ui/paint_visual_grid.cpp index fb9d889b4..2128e70f1 100644 --- a/modules/paint/ui/paint_visual_grid.cpp +++ b/modules/paint/ui/paint_visual_grid.cpp @@ -61,7 +61,7 @@ PaintNode *PaintVisualGrid::get_paint_node() { void PaintVisualGrid::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: - case PaintNode::NOTIFICATION_PAINT_NODE_RESIZED: { + case PaintNode::NOTIFICATION_PARENT_PAINT_NODE_RESIZED: { PaintNode *pn = get_paint_node(); if (pn) {