mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2024-11-23 17:38:20 +01:00
588 lines
13 KiB
C++
588 lines
13 KiB
C++
/*
|
|
Copyright (c) 2019 Flairieve
|
|
Copyright (c) 2020-2022 cobrapitz
|
|
Copyright (c) 2022 Péter Magyar
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
SOFTWARE.
|
|
*/
|
|
|
|
#include "paint_canvas.h"
|
|
|
|
#include "paint_canvas_outline.h"
|
|
#include "paint_visual_grid.h"
|
|
#include "scene/gui/control.h"
|
|
#include "scene/gui/texture_rect.h"
|
|
|
|
#include "paint_canvas_layer.h"
|
|
|
|
void PaintCanvas::_enter_tree() {
|
|
/*
|
|
#-------------------------------
|
|
# Set nodes
|
|
#-------------------------------
|
|
canvas = find_node("Canvas")
|
|
grid = find_node("Grid")
|
|
big_grid = find_node("BigGrid")
|
|
canvas_layers = find_node("CanvasLayers")
|
|
|
|
#-------------------------------
|
|
# setup layers and canvas
|
|
#-------------------------------
|
|
connect("mouse_entered", self, "_on_mouse_entered")
|
|
connect("mouse_exited", self, "_on_mouse_exited")
|
|
|
|
#-------------------------------
|
|
# setup layers and canvas
|
|
#-------------------------------
|
|
#canvas_size = Vector2(int(rect_size.x / grid_size), int(rect_size.y / grid_size))
|
|
#pixel_size = canvas_size
|
|
|
|
active_layer = add_new_layer("Layer1")
|
|
preview_layer = add_new_layer("Preview")
|
|
tool_layer = add_new_layer("Tool")
|
|
|
|
set_process(true)
|
|
*/
|
|
}
|
|
void PaintCanvas::_process(float delta) {
|
|
/*
|
|
if not is_visible_in_tree():
|
|
return
|
|
var mouse_position = get_local_mouse_position()
|
|
var rect = Rect2(Vector2(0, 0), rect_size)
|
|
mouse_in_region = rect.has_point(mouse_position)
|
|
*/
|
|
}
|
|
void PaintCanvas::_draw() {
|
|
/*
|
|
for layer in layers:
|
|
layer.update_texture()
|
|
|
|
preview_layer.update_texture()
|
|
tool_layer.update_texture()
|
|
*/
|
|
}
|
|
|
|
int PaintCanvas::get_pixel_size() const {
|
|
return _pixel_size;
|
|
}
|
|
|
|
void PaintCanvas::set_pixel_size(const int size) {
|
|
/*
|
|
pixel_size = size
|
|
set_grid_size(grid_size)
|
|
set_big_grid_size(big_grid_size)
|
|
set_canvas_width(canvas_width)
|
|
set_canvas_height(canvas_height)
|
|
*/
|
|
}
|
|
|
|
int PaintCanvas::get_grid_size() const {
|
|
return _grid_size;
|
|
}
|
|
void PaintCanvas::set_grid_size(const int size) {
|
|
/*
|
|
grid_size = size
|
|
if not find_node("Grid"):
|
|
return
|
|
find_node("Grid").size = size * pixel_size
|
|
*/
|
|
}
|
|
|
|
int PaintCanvas::get_big_grid_size() const {
|
|
return _big_grid_size;
|
|
}
|
|
void PaintCanvas::set_big_grid_size(const int size) {
|
|
/*
|
|
big_grid_size = size
|
|
if not find_node("BigGrid"):
|
|
return
|
|
find_node("BigGrid").size = size * pixel_size
|
|
*/
|
|
}
|
|
|
|
int PaintCanvas::get_canvas_width() const {
|
|
return _canvas_width;
|
|
}
|
|
void PaintCanvas::set_canvas_width(const int val) {
|
|
/*
|
|
canvas_width = val
|
|
rect_size.x = canvas_width * pixel_size
|
|
*/
|
|
}
|
|
|
|
int PaintCanvas::get_canvas_height() const {
|
|
return _canvas_height;
|
|
}
|
|
void PaintCanvas::set_canvas_height(const int val) {
|
|
/*
|
|
canvas_height = val
|
|
rect_size.y = canvas_height * pixel_size
|
|
*/
|
|
}
|
|
void PaintCanvas::toggle_alpha_locked(const String &layer_name) {
|
|
/*
|
|
var layer = find_layer_by_name(layer_name)
|
|
layer.toggle_alpha_locked()
|
|
*/
|
|
}
|
|
bool PaintCanvas::is_alpha_locked() {
|
|
/*
|
|
return active_layer.alpha_locked
|
|
*/
|
|
return false;
|
|
}
|
|
Rect2 PaintCanvas::get_content_margin() {
|
|
/*
|
|
var rect = Rect2(999999, 999999, -999999, -999999)
|
|
|
|
preview_layer.image.get_used_rect()
|
|
for layer in layers:
|
|
|
|
var r = layer.image.get_used_rect()
|
|
|
|
if r.position.x < rect.position.x:
|
|
rect.position.x = r.position.x
|
|
if r.position.y < rect.position.y:
|
|
rect.position.y = r.position.y
|
|
if r.size.x > rect.size.x:
|
|
rect.size.x = r.size.x
|
|
if r.size.y > rect.size.y:
|
|
rect.size.y = r.size.y
|
|
|
|
return rect
|
|
*/
|
|
|
|
return Rect2();
|
|
}
|
|
void PaintCanvas::crop_to_content() {
|
|
/*
|
|
var rect = get_content_margin()
|
|
|
|
#print(rect)
|
|
|
|
for layer in layers:
|
|
layer.image
|
|
|
|
# set_canvas_width(rect.size.x)
|
|
# set_canvas_height(rect.size.x)
|
|
|
|
# preview_layer.resize(width, height)
|
|
# tool_layer.resize(width, height)
|
|
# for layer in layers:
|
|
# layer.resize(width, height)
|
|
*/
|
|
}
|
|
Node *PaintCanvas::get_active_layer() {
|
|
/*
|
|
return active_layer
|
|
*/
|
|
|
|
return nullptr;
|
|
}
|
|
Node *PaintCanvas::get_preview_layer() {
|
|
/*
|
|
return preview_layer
|
|
*/
|
|
return nullptr;
|
|
}
|
|
void PaintCanvas::clear_active_layer() {
|
|
/*
|
|
active_layer.clear()
|
|
*/
|
|
}
|
|
void PaintCanvas::clear_preview_layer() {
|
|
/*
|
|
preview_layer.clear()
|
|
*/
|
|
}
|
|
|
|
void PaintCanvas::clear_layer(const String &layer_name) {
|
|
/*
|
|
for layer in layers:
|
|
if layer.name == layer_name:
|
|
layer.clear()
|
|
break
|
|
*/
|
|
}
|
|
Node *PaintCanvas::remove_layer(const String &layer_name) {
|
|
/*
|
|
# change current layer if the active layer is removed
|
|
var del_layer = find_layer_by_name(layer_name)
|
|
del_layer.clear()
|
|
if del_layer == active_layer:
|
|
for layer in layers:
|
|
if layer == preview_layer or layer == active_layer or layer == tool_layer:
|
|
continue
|
|
active_layer = layer
|
|
break
|
|
layers.erase(del_layer)
|
|
return active_layer
|
|
*/
|
|
return nullptr;
|
|
}
|
|
Node *PaintCanvas::add_new_layer(const String &layer_name) {
|
|
/*
|
|
for layer in layers:
|
|
if layer.name == layer_name:
|
|
return
|
|
var layer = GELayer.new()
|
|
layer.name = layer_name
|
|
|
|
if layer_name == "Preview":
|
|
layer.create($PreviewLayer, canvas_width, canvas_height)
|
|
elif layer_name == "Tool":
|
|
layer.create($ToolPreviewLayer, canvas_width, canvas_height)
|
|
else:
|
|
var texture_rect = TextureRect.new()
|
|
texture_rect.name = layer_name
|
|
canvas_layers.add_child(texture_rect, true)
|
|
texture_rect.expand = true
|
|
texture_rect.anchor_right = 1
|
|
texture_rect.anchor_bottom = 1
|
|
texture_rect.margin_right = 0
|
|
texture_rect.margin_bottom = 0
|
|
texture_rect.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
layer.create(texture_rect, canvas_width, canvas_height)
|
|
layers.append(layer)
|
|
|
|
return layer
|
|
*/
|
|
return nullptr;
|
|
}
|
|
Node *PaintCanvas::duplicate_layer(const String &layer_name, const String &new_layer_name) {
|
|
/*
|
|
for layer in layers:
|
|
if layer.name == new_layer_name:
|
|
return
|
|
|
|
var dup_layer :GELayer = find_layer_by_name(layer_name)
|
|
var layer :GELayer = add_new_layer(new_layer_name)
|
|
layer.image.copy_from(dup_layer.image)
|
|
return layer
|
|
*/
|
|
return nullptr;
|
|
}
|
|
void PaintCanvas::toggle_layer_visibility(const String &layer_name) {
|
|
/*
|
|
for layer in layers:
|
|
if layer.name == layer_name:
|
|
layer.visible = not layer.visible
|
|
*/
|
|
}
|
|
Node *PaintCanvas::find_layer_by_name(const String &layer_name) {
|
|
/*
|
|
for layer in layers:
|
|
if layer.name == layer_name:
|
|
return layer
|
|
return null
|
|
*/
|
|
return nullptr;
|
|
}
|
|
void PaintCanvas::toggle_lock_layer(const String &layer_name) {
|
|
/*
|
|
find_layer_by_name(layer_name).toggle_lock()
|
|
*/
|
|
}
|
|
bool PaintCanvas::is_active_layer_locked() {
|
|
/*
|
|
return active_layer.locked
|
|
*/
|
|
|
|
return false;
|
|
}
|
|
void PaintCanvas::move_layer_forward(const String &layer_name) {
|
|
/*
|
|
var layer = find_layer_by_name(layer_name).texture_rect_ref
|
|
var new_idx = max(layer.get_index() - 1, 0)
|
|
canvas_layers.move_child(layer, new_idx)
|
|
*/
|
|
}
|
|
void PaintCanvas::move_layer_back(const String &layer_name) {
|
|
/*
|
|
var layer = find_layer_by_name(layer_name).texture_rect_ref
|
|
canvas_layers.move_child(layer, layer.get_index() + 1)
|
|
*/
|
|
}
|
|
|
|
void PaintCanvas::select_layer(const String &layer_name) {
|
|
/*
|
|
active_layer = find_layer_by_name(layer_name)
|
|
*/
|
|
}
|
|
void PaintCanvas::_on_mouse_entered() {
|
|
/*
|
|
mouse_on_top = true
|
|
*/
|
|
}
|
|
void PaintCanvas::_on_mouse_exited() {
|
|
/*
|
|
mouse_on_top = false
|
|
*/
|
|
}
|
|
bool PaintCanvas::is_inside_canvas(const int x, const int y) {
|
|
/*
|
|
if x < 0 or y < 0:
|
|
return false
|
|
if x >= canvas_width or y >= canvas_height:
|
|
return false
|
|
return true
|
|
*/
|
|
return false;
|
|
}
|
|
|
|
//Note: Arrays are always passed by reference. To get a copy of an array which
|
|
// can be modified independently of the original array, use duplicate.
|
|
// (https://docs.godotengine.org/en/stable/classes/class_array.html)
|
|
void PaintCanvas::set_pixel_arr(const Array &pixels, const Color &color) {
|
|
/*
|
|
for pixel in pixels:
|
|
_set_pixel(active_layer, pixel.x, pixel.y, color)
|
|
*/
|
|
}
|
|
void PaintCanvas::set_pixel_v(const Vector2 &pos, const Color &color) {
|
|
/*
|
|
set_pixel(pos.x, pos.y, color)
|
|
*/
|
|
}
|
|
void PaintCanvas::set_pixel(const int x, const int y, const Color &color) {
|
|
/*
|
|
_set_pixel(active_layer, x, y, color)
|
|
*/
|
|
}
|
|
void PaintCanvas::_set_pixel_v(PaintCanvasLayer *layer, const Vector2 &v, const Color &color) {
|
|
/*
|
|
_set_pixel(layer, v.x, v.y, color)
|
|
*/
|
|
}
|
|
void PaintCanvas::_set_pixel(PaintCanvasLayer *layer, const int x, const int y, const Color &color) {
|
|
/*
|
|
if not is_inside_canvas(x, y):
|
|
return
|
|
layer.set_pixel(x, y, color)
|
|
*/
|
|
}
|
|
Color PaintCanvas::get_pixel_v(const Vector2 &pos) {
|
|
/*
|
|
return get_pixel(pos.x, pos.y)
|
|
*/
|
|
return Color();
|
|
}
|
|
Color PaintCanvas::get_pixel(const int x, const int y) {
|
|
/*
|
|
if active_layer:
|
|
return active_layer.get_pixel(x, y)
|
|
return null
|
|
*/
|
|
return Color();
|
|
}
|
|
void PaintCanvas::set_preview_pixel_v(const Vector2 &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 not is_inside_canvas(x, y):
|
|
return
|
|
preview_layer.set_pixel(x, y, color)
|
|
*/
|
|
}
|
|
Color PaintCanvas::get_preview_pixel_v(const Vector2 &pos) {
|
|
/*
|
|
return get_preview_pixel(pos.x, pos.y)
|
|
*/
|
|
return Color();
|
|
}
|
|
|
|
Color PaintCanvas::get_preview_pixel(const int x, const int y) {
|
|
/*
|
|
if not preview_layer:
|
|
return null
|
|
return preview_layer.get_pixel(x, y)
|
|
*/
|
|
return Color();
|
|
}
|
|
void PaintCanvas::toggle_grid() {
|
|
/*
|
|
$Grid.visible = not $Grid.visible
|
|
*/
|
|
}
|
|
void PaintCanvas::show_grid() {
|
|
/*
|
|
$Grid.show()
|
|
*/
|
|
}
|
|
void PaintCanvas::hide_grid() {
|
|
/*
|
|
$Grid.hide()
|
|
*/
|
|
}
|
|
|
|
Array PaintCanvas::select_color(const int x, const int y) {
|
|
/*
|
|
print("???")
|
|
var same_color_pixels = []
|
|
var color = get_pixel(x, y)
|
|
for x in range(active_layer.layer_width):
|
|
for y in range(active_layer.layer_height):
|
|
var pixel_color = active_layer.get_pixel(x, y)
|
|
if pixel_color == color:
|
|
same_color_pixels.append(color)
|
|
return same_color_pixels
|
|
*/
|
|
return Array();
|
|
}
|
|
Array PaintCanvas::select_same_color(const int x, const int y) {
|
|
/*
|
|
return get_neighbouring_pixels(x, y)
|
|
*/
|
|
|
|
return Array();
|
|
}
|
|
|
|
// returns array of Vector2
|
|
// yoinked from
|
|
// https://www.geeksforgeeks.org/flood-fill-algorithm-implement-fill-paint/
|
|
Array PaintCanvas::get_neighbouring_pixels(const int pos_x, const int pos_y) {
|
|
/*
|
|
var pixels = []
|
|
|
|
var to_check_queue = []
|
|
var checked_queue = []
|
|
|
|
to_check_queue.append(GEUtils.to_1D(pos_x, pos_y, canvas_width))
|
|
|
|
var color = get_pixel(pos_x, pos_y)
|
|
|
|
while not to_check_queue.empty():
|
|
var idx = to_check_queue.pop_front()
|
|
var p = GEUtils.to_2D(idx, canvas_width)
|
|
|
|
if idx in checked_queue:
|
|
continue
|
|
|
|
checked_queue.append(idx)
|
|
|
|
if get_pixel(p.x, p.y) != color:
|
|
continue
|
|
|
|
# add to result
|
|
pixels.append(p)
|
|
|
|
# check neighbours
|
|
var x = p.x - 1
|
|
var y = p.y
|
|
if is_inside_canvas(x, y):
|
|
idx = GEUtils.to_1D(x, y, canvas_width)
|
|
to_check_queue.append(idx)
|
|
|
|
x = p.x + 1
|
|
if is_inside_canvas(x, y):
|
|
idx = GEUtils.to_1D(x, y, canvas_width)
|
|
to_check_queue.append(idx)
|
|
|
|
x = p.x
|
|
y = p.y - 1
|
|
if is_inside_canvas(x, y):
|
|
idx = GEUtils.to_1D(x, y, canvas_width)
|
|
to_check_queue.append(idx)
|
|
|
|
y = p.y + 1
|
|
if is_inside_canvas(x, y):
|
|
idx = GEUtils.to_1D(x, y, canvas_width)
|
|
to_check_queue.append(idx)
|
|
|
|
return pixels
|
|
*/
|
|
return Array();
|
|
}
|
|
|
|
void PaintCanvas::resize(const int width, const int height) {
|
|
/*
|
|
if width < 0:
|
|
width = 1
|
|
if height < 0:
|
|
height = 1
|
|
|
|
set_canvas_width(width)
|
|
set_canvas_height(height)
|
|
|
|
preview_layer.resize(width, height)
|
|
tool_layer.resize(width, height)
|
|
for layer in layers:
|
|
layer.resize(width, height)
|
|
*/
|
|
}
|
|
|
|
PaintCanvas::PaintCanvas() {
|
|
big_grid = nullptr;
|
|
|
|
_pixel_size = 16;
|
|
_canvas_width = 48;
|
|
_canvas_height = 28;
|
|
_grid_size = 16;
|
|
_big_grid_size = 10;
|
|
_can_draw = true;
|
|
|
|
symmetry_x = false;
|
|
symmetry_y = false;
|
|
|
|
mouse_in_region = false;
|
|
mouse_on_top = false;
|
|
|
|
canvas_background_rect = memnew(TextureRect);
|
|
//canvas_background_rect->set_texture();//res://addons/Godoxel/assets/grid.png
|
|
canvas_background_rect->set_expand(true);
|
|
canvas_background_rect->set_stretch_mode(TextureRect::STRETCH_TILE);
|
|
add_child(canvas_background_rect);
|
|
|
|
canvas_layers = memnew(Control);
|
|
canvas_layers->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
|
|
add_child(canvas_layers);
|
|
|
|
preview_layer_rect = memnew(TextureRect);
|
|
preview_layer_rect->set_expand(true);
|
|
preview_layer_rect->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
|
|
add_child(preview_layer_rect);
|
|
|
|
tool_preview_layer_rect = memnew(TextureRect);
|
|
tool_preview_layer_rect->set_expand(true);
|
|
tool_preview_layer_rect->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
|
|
add_child(tool_preview_layer_rect);
|
|
|
|
grid = memnew(PaintVisualGrid);
|
|
grid->color = Color(1, 1, 1, 1);
|
|
grid->size = 4;
|
|
grid->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
|
|
add_child(grid);
|
|
|
|
canvas_outline = memnew(PaintCanvasOutline);
|
|
canvas_outline->color = Color(0, 1, 0, 1);
|
|
canvas_outline->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
|
|
add_child(canvas_outline);
|
|
}
|
|
|
|
PaintCanvas::~PaintCanvas() {
|
|
}
|
|
|
|
void PaintCanvas::_bind_methods() {
|
|
}
|