diff --git a/modules/paint/actions/paint_action.cpp b/modules/paint/actions/paint_action.cpp index d30a110a4..d6904ab95 100644 --- a/modules/paint/actions/paint_action.cpp +++ b/modules/paint/actions/paint_action.cpp @@ -179,11 +179,10 @@ PoolVector2iArray PaintAction::get_xy_sym_points(const int canvas_width, const i return points; } PoolVector2iArray PaintAction::get_points(const Vector2i &pixel) { - PoolVector2iArray points; -/* TODO enable - if (_paint_canvas->symmetry_x && _paint_canvas->symmetry_y) { - PoolVector2iArray sym_points = get_xy_sym_points(_paint_canvas->get_canvas_width(), _paint_canvas->get_canvas_height(), pixel); + + if (_paint_canvas->get_symmetry_x() && _paint_canvas->get_symmetry_y()) { + PoolVector2iArray sym_points = get_xy_sym_points(_paint_canvas->get_size().x, _paint_canvas->get_size().y, pixel); for (int i = 0; i < sym_points.size(); ++i) { Vector2i point = sym_points[i]; @@ -192,14 +191,14 @@ PoolVector2iArray PaintAction::get_points(const Vector2i &pixel) { continue; } - if (_paint_canvas->is_alpha_locked() && _paint_canvas->get_pixel_v(pixel) == Color(0, 0, 0, 0)) { + if (_paint_canvas->get_alpha_locked() && _paint_canvas->get_pixel_v(pixel).a < 0.00001) { continue; } points.append(point); } - } else if (_paint_canvas->symmetry_y) { - PoolVector2iArray sym_points = get_y_sym_points(_paint_canvas->get_canvas_height(), pixel); + } else if (_paint_canvas->get_symmetry_y()) { + PoolVector2iArray sym_points = get_y_sym_points(_paint_canvas->get_size().y, pixel); for (int i = 0; i < sym_points.size(); ++i) { Vector2i point = sym_points[i]; @@ -208,14 +207,14 @@ PoolVector2iArray PaintAction::get_points(const Vector2i &pixel) { continue; } - if (_paint_canvas->is_alpha_locked() && _paint_canvas->get_pixel_v(pixel) == Color(0, 0, 0, 0)) { + if (_paint_canvas->get_alpha_locked() && _paint_canvas->get_pixel_v(pixel).a < 0.00001) { continue; } points.append(point); } - } else if (_paint_canvas->symmetry_x) { - PoolVector2iArray sym_points = get_x_sym_points(_paint_canvas->get_canvas_width(), pixel); + } else if (_paint_canvas->get_symmetry_x()) { + PoolVector2iArray sym_points = get_x_sym_points(_paint_canvas->get_size().x, pixel); for (int i = 0; i < sym_points.size(); ++i) { Vector2i point = sym_points[i]; @@ -224,7 +223,7 @@ PoolVector2iArray PaintAction::get_points(const Vector2i &pixel) { continue; } - if (_paint_canvas->is_alpha_locked() && _paint_canvas->get_pixel_v(pixel) == Color(0, 0, 0, 0)) { + if (_paint_canvas->get_alpha_locked() && _paint_canvas->get_pixel_v(pixel).a < 0.00001) { continue; } @@ -236,14 +235,14 @@ PoolVector2iArray PaintAction::get_points(const Vector2i &pixel) { return points; } - if (_paint_canvas->is_alpha_locked() && _paint_canvas->get_pixel_v(pixel) == Color(0, 0, 0, 0)) { + if (_paint_canvas->get_alpha_locked() && _paint_canvas->get_pixel_v(pixel).a < 0.00001) { //empty return points; } points.append(pixel); } -*/ + return points; } @@ -316,13 +315,12 @@ PoolVector2iArray PaintAction::get_points_old(PaintCanvasOld *canvas, const Vect } void PaintAction::draw_points(const PoolVector2iArray &point_arr, const PoolColorArray &color_arr) { - /* TODO enable for (int i = 0; i < point_arr.size(); ++i) { Vector2i pixel = point_arr[i]; Color col = color_arr[i]; - if (_paint_canvas->is_alpha_locked() && col.a < 0.00001) { + if (_paint_canvas->get_alpha_locked() && col.a < 0.00001) { continue; } @@ -334,7 +332,6 @@ void PaintAction::draw_points(const PoolVector2iArray &point_arr, const PoolColo redo_cells.append(pixel); redo_colors.append(col); } - */ } void PaintAction::draw_points_old(PaintCanvasOld *canvas, const PoolVector2iArray &point_arr, const PoolColorArray &color_arr) { diff --git a/modules/paint/nodes/paint_canvas.cpp b/modules/paint/nodes/paint_canvas.cpp index 4d41a9013..620bebc9d 100644 --- a/modules/paint/nodes/paint_canvas.cpp +++ b/modules/paint/nodes/paint_canvas.cpp @@ -1,10 +1,180 @@ #include "paint_canvas.h" +#include "core/io/image.h" +#include "scene/resources/texture.h" + +bool PaintCanvas::get_symmetry_x() const { + return _symmetry_x; +} +void PaintCanvas::set_symmetry_x(const bool val) { + _symmetry_x = val; +} + +bool PaintCanvas::get_symmetry_y() const { + return _symmetry_y; +} +void PaintCanvas::set_symmetry_y(const bool val) { + _symmetry_y = val; +} + +bool PaintCanvas::get_alpha_locked() const { + return _alpha_locked; +} +void PaintCanvas::set_alpha_locked(const bool val) { + _alpha_locked = val; +} + +bool PaintCanvas::validate_pixel_v(const Vector2i &pos) const { + if (pos.x < 0 || pos.y < 0 || pos.x >= _image->get_width() || pos.y >= _image->get_height()) { + return false; + } + + return true; +} + +bool PaintCanvas::is_inside_canvas(const int x, const int y) { + if (x < 0 || y < 0) { + return false; + } + if (x >= get_size().x || y >= get_size().y) { + return false; + } + + return true; +} + +void PaintCanvas::set_pixel_arr(const PoolVector2iArray &pixels, const Color &color) { + PoolVector2iArray::Read r = pixels.read(); + + for (int i = 0; i < pixels.size(); ++i) { + const Vector2i &pixel = r[i]; + + set_pixel(pixel.x, pixel.y, color); + } +} +void PaintCanvas::set_pixel_v(const Vector2i &pos, const Color &color) { + set_pixel(pos.x, pos.y, color); +} +void PaintCanvas::set_pixel(const int x, const int y, const Color &color) { + if (x < 0 || y < 0 || x >= _image->get_width() || y >= _image->get_height()) { + return; + } + + _image->lock(); + _image->set_pixel(x, y, color); + _image->unlock(); +} + +Color PaintCanvas::get_pixel_v(const Vector2i &pos) { + return get_pixel(pos.x, pos.y); +} +Color PaintCanvas::get_pixel(const int x, const int y) { + if (x < 0 || y < 0 || x >= _image->get_width() || y >= _image->get_height()) { + return Color(); + } + + _image->lock(); + Color pixel = _image->get_pixel(x, y); + _image->unlock(); + + return pixel; +} +void PaintCanvas::set_preview_pixel_v(const Vector2i &pos, const Color &color) { + set_preview_pixel(pos.x, pos.y, color); +} + +void PaintCanvas::set_preview_pixel(const int x, const int y, const Color &color) { + if (x < 0 || y < 0 || x >= _preview_image->get_width() || y >= _preview_image->get_height()) { + return; + } + + _preview_image->lock(); + _preview_image->set_pixel(x, y, color); + _preview_image->unlock(); +} +Color PaintCanvas::get_preview_pixel_v(const Vector2i &pos) { + return get_preview_pixel(pos.x, pos.y); +} + +Color PaintCanvas::get_preview_pixel(const int x, const int y) { + if (x < 0 || y < 0 || x >= _preview_image->get_width() || y >= _preview_image->get_height()) { + return Color(); + } + + _preview_image->lock(); + Color pixel = _preview_image->get_pixel(x, y); + _preview_image->unlock(); + + return pixel; +} + +void PaintCanvas::clear() { + _image->fill(Color(1.00, 1.00, 1.00, 0.00)); + + update_textures(); +} + +void PaintCanvas::update_textures() { + _image_texture->create_from_image(_image, 0); + _preview_image_texture->create_from_image(_preview_image, 0); + + update(); +} + PaintCanvas::PaintCanvas() { + _symmetry_x = false; + _symmetry_y = false; + _alpha_locked = false; + + _image.instance(); + _preview_image.instance(); + + _image_texture.instance(); + _preview_image_texture.instance(); } PaintCanvas::~PaintCanvas() { } -void PaintCanvas::_bind_methods() { +void PaintCanvas::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_DRAW: { + draw_texture(_image_texture, Point2()); + draw_texture(_preview_image_texture, Point2()); + } break; + } +} + +void PaintCanvas::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_symmetry_x"), &PaintCanvas::get_symmetry_x); + ClassDB::bind_method(D_METHOD("set_symmetry_x", "val"), &PaintCanvas::set_symmetry_x); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "symmetry_x"), "set_symmetry_x", "get_symmetry_x"); + + ClassDB::bind_method(D_METHOD("get_symmetry_y"), &PaintCanvas::get_symmetry_y); + ClassDB::bind_method(D_METHOD("set_symmetry_y", "val"), &PaintCanvas::set_symmetry_y); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "symmetry_y"), "set_symmetry_y", "get_symmetry_y"); + + ClassDB::bind_method(D_METHOD("get_alpha_locked"), &PaintCanvas::get_alpha_locked); + ClassDB::bind_method(D_METHOD("set_alpha_locked", "val"), &PaintCanvas::set_alpha_locked); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "alpha_locked"), "set_alpha_locked", "get_alpha_locked"); + + ClassDB::bind_method(D_METHOD("is_inside_canvas", "x", "y"), &PaintCanvas::is_inside_canvas); + ClassDB::bind_method(D_METHOD("set_pixel_arr", "pixels", "color"), &PaintCanvas::set_pixel_arr); + + ClassDB::bind_method(D_METHOD("set_pixel_v", "pos", "color"), &PaintCanvas::set_pixel_v); + ClassDB::bind_method(D_METHOD("set_pixel", "x", "y", "color"), &PaintCanvas::set_pixel); + + ClassDB::bind_method(D_METHOD("get_pixel_v", "pos"), &PaintCanvas::get_pixel_v); + ClassDB::bind_method(D_METHOD("get_pixel", "x", "y"), &PaintCanvas::get_pixel); + + ClassDB::bind_method(D_METHOD("set_preview_pixel_v", "pos", "color"), &PaintCanvas::set_preview_pixel_v); + ClassDB::bind_method(D_METHOD("set_preview_pixel", "x", "y", "color"), &PaintCanvas::set_preview_pixel); + + ClassDB::bind_method(D_METHOD("get_preview_pixel_v", "pos"), &PaintCanvas::get_preview_pixel_v); + ClassDB::bind_method(D_METHOD("get_preview_pixel", "x", "y"), &PaintCanvas::get_preview_pixel); + + ClassDB::bind_method(D_METHOD("validate_pixel_v", "pos"), &PaintCanvas::validate_pixel_v); + + ClassDB::bind_method(D_METHOD("clear"), &PaintCanvas::clear); + ClassDB::bind_method(D_METHOD("update_textures"), &PaintCanvas::update_textures); } diff --git a/modules/paint/nodes/paint_canvas.h b/modules/paint/nodes/paint_canvas.h index 1478526c1..6ebc8c0ab 100644 --- a/modules/paint/nodes/paint_canvas.h +++ b/modules/paint/nodes/paint_canvas.h @@ -1,17 +1,64 @@ #ifndef PAINT_CANVAS_H #define PAINT_CANVAS_H +#include "core/object/reference.h" + #include "paint_node.h" +class Image; +class ImageTexture; + class PaintCanvas : public PaintNode { GDCLASS(PaintCanvas, PaintNode); public: + bool get_symmetry_x() const; + void set_symmetry_x(const bool val); + + bool get_symmetry_y() const; + void set_symmetry_y(const bool val); + + bool get_alpha_locked() const; + void set_alpha_locked(const bool val); + + bool is_inside_canvas(const int x, const int y); + + void set_pixel_arr(const PoolVector2iArray &pixels, const Color &color); + + void set_pixel_v(const Vector2i &pos, const Color &color); + void set_pixel(const int x, const int y, const Color &color); + + Color get_pixel_v(const Vector2i &pos); + Color get_pixel(const int x, const int y); + + void set_preview_pixel_v(const Vector2i &pos, const Color &color); + void set_preview_pixel(const int x, const int y, const Color &color); + + Color get_preview_pixel_v(const Vector2i &pos); + Color get_preview_pixel(const int x, const int y); + + bool validate_pixel_v(const Vector2i &pos) const; + + void clear(); + void update_textures(); + PaintCanvas(); ~PaintCanvas(); protected: + void _notification(int p_what); + static void _bind_methods(); + + bool _symmetry_x; + bool _symmetry_y; + bool _alpha_locked; + + Ref _image; + Ref _preview_image; + + Ref _image_texture; + Ref _preview_image_texture; }; #endif