mirror of
https://github.com/Relintai/pandemonium_paint_experimental.git
synced 2024-11-07 16:52:10 +01:00
528 lines
14 KiB
GDScript
528 lines
14 KiB
GDScript
tool
|
|
extends PaintCanvas
|
|
|
|
var _mouse_down : bool = false
|
|
var _mouse_button_down : int = -1
|
|
|
|
var _actions_history : Array
|
|
var _redo_history : Array
|
|
var _current_action : PaintAction
|
|
|
|
var _picked_color : bool = false
|
|
|
|
var _selection_cells : PoolVector2iArray
|
|
var _selection_colors : PoolColorArray
|
|
|
|
var _cut_pos : Vector2i
|
|
var _cut_size : Vector2i
|
|
|
|
var _mouse_position : Vector2
|
|
var _canvas_mouse_position : Vector2
|
|
var _cell_mouse_position : Vector2
|
|
|
|
var _last_mouse_position : Vector2
|
|
var _last_canvas_mouse_position : Vector2
|
|
var _last_cell_mouse_position : Vector2
|
|
|
|
func handle_draw(local_position : Vector2, event: InputEvent) -> void:
|
|
var proj : PaintProject = get_paint_project()
|
|
|
|
if !proj:
|
|
print("!proj!")
|
|
|
|
set_pixel(local_position.x, local_position.y, proj.current_color)
|
|
|
|
func get_current_color() -> Color:
|
|
var proj : PaintProject = get_paint_project()
|
|
|
|
if !proj:
|
|
print("!proj!")
|
|
return Color(1, 1, 1, 1)
|
|
|
|
return proj.current_color
|
|
|
|
func update_mouse_position(local_position : Vector2, event: InputEvent) -> void:
|
|
if event.device == -1:
|
|
_mouse_position = get_global_mouse_position()
|
|
_cell_mouse_position = local_position
|
|
|
|
_last_mouse_position = _mouse_position
|
|
_last_cell_mouse_position = local_position
|
|
|
|
func handle_left_mouse_button_down(local_position : Vector2, event: InputEvent) -> void:
|
|
update_mouse_position(local_position, event)
|
|
|
|
if current_tool == TOOL_CUT:
|
|
if !event.is_pressed():
|
|
commit_action()
|
|
elif current_tool == TOOL_BUCKET:
|
|
if !_current_action:
|
|
_current_action = get_action()
|
|
|
|
var arr : Array = Array()
|
|
arr.push_back(_cell_mouse_position)
|
|
arr.push_back(_last_cell_mouse_position)
|
|
arr.push_back(get_current_color())
|
|
|
|
do_action(arr)
|
|
commit_action()
|
|
elif current_tool == TOOL_COLORPICKER:
|
|
var c : Color = get_pixel(_cell_mouse_position.x, _cell_mouse_position.y);
|
|
|
|
if (c.a < 0.00001):
|
|
return;
|
|
|
|
_picked_color = true;
|
|
|
|
var project : PaintProject = get_paint_project()
|
|
|
|
if (project):
|
|
project.current_color = c
|
|
|
|
tool_process(local_position, event)
|
|
|
|
func handle_left_mouse_button_up(local_position : Vector2, event: InputEvent) -> void:
|
|
if event.device == -1:
|
|
_mouse_position = get_global_mouse_position()
|
|
_cell_mouse_position = local_position
|
|
|
|
_last_mouse_position = _mouse_position
|
|
_last_cell_mouse_position = local_position
|
|
|
|
if current_tool == TOOL_COLORPICKER:
|
|
if (_picked_color):
|
|
current_tool = get_previous_tool()
|
|
_picked_color = false
|
|
|
|
tool_process(local_position, event)
|
|
|
|
func handle_right_mouse_button_down(local_position : Vector2, event: InputEvent) -> void:
|
|
update_mouse_position(local_position, event)
|
|
|
|
if current_tool == TOOL_CUT:
|
|
if !event.is_pressed():
|
|
commit_action()
|
|
elif current_tool == TOOL_COLORPICKER:
|
|
current_tool = get_previous_tool()
|
|
elif current_tool == TOOL_PASTECUT:
|
|
commit_action()
|
|
current_tool = TOOL_PENCIL
|
|
elif current_tool == TOOL_BUCKET:
|
|
current_tool = get_previous_tool()
|
|
|
|
tool_process(local_position, event)
|
|
|
|
func draw_brush_preview() -> void:
|
|
clear_preview()
|
|
|
|
if current_tool == TOOL_PASTECUT:
|
|
# for (int idx = 0; idx < _selection_cells.size(); ++idx) {
|
|
# Vector2i pixel = _selection_cells[idx];
|
|
# //if pixel.x < 0 || pixel.y < 0:
|
|
# // print(pixel);
|
|
# Color color = _selection_colors[idx];
|
|
# pixel -= _cut_pos + _cut_size / 2;
|
|
# pixel += cell_mouse_position;
|
|
# paint_canvas->_set_pixel_v(paint_canvas->tool_layer, pixel, color);
|
|
# }
|
|
for idx in range(_selection_cells.size()):
|
|
var pixel : Vector2i = _selection_cells[idx];
|
|
var color : Color = _selection_colors[idx];
|
|
pixel -= _cut_pos + _cut_size / 2;
|
|
pixel.x += _cell_mouse_position.x;
|
|
pixel.y += _cell_mouse_position.y;
|
|
set_preview_pixel_v(pixel, color)
|
|
|
|
update_textures()
|
|
elif current_tool == TOOL_BRUSH:
|
|
# PoolVector2iArray pixels = BrushPrefabs::get_brush(selected_brush_prefab, brush_size_slider->get_value());
|
|
#
|
|
# PoolVector2iArray::Read r = pixels.read();
|
|
#
|
|
# for (int i = 0; i < pixels.size(); ++i) {
|
|
# Vector2i pixel = r[i];
|
|
# paint_canvas->_set_pixel(paint_canvas->tool_layer, cell_mouse_position.x + pixel.x, cell_mouse_position.y + pixel.y, _selected_color);
|
|
# //print_error("ad " + String::num(cell_mouse_position.x + pixel.x) + " " + String::num(cell_mouse_position.y + pixel.y));
|
|
# }
|
|
#
|
|
# r.release();
|
|
|
|
update_textures()
|
|
elif current_tool == TOOL_RAINBOW:
|
|
set_preview_pixel(_cell_mouse_position.x, _cell_mouse_position.y, Color(0.46875, 0.446777, 0.446777, 0.3));
|
|
update_textures()
|
|
elif current_tool == TOOL_COLORPICKER:
|
|
set_preview_pixel(_cell_mouse_position.x, _cell_mouse_position.y, Color(0.866667, 0.847059, 0.847059, 0.3));
|
|
update_textures()
|
|
else:
|
|
set_preview_pixel(_cell_mouse_position.x, _cell_mouse_position.y, get_current_color());
|
|
update_textures()
|
|
|
|
|
|
#void PaintWindow::_draw_tool_brush() {
|
|
# paint_canvas->tool_layer->clear();
|
|
#
|
|
# switch (brush_mode) {
|
|
# case Tools::PASTECUT: {
|
|
# for (int idx = 0; idx < _selection_cells.size(); ++idx) {
|
|
# Vector2i pixel = _selection_cells[idx];
|
|
# //if pixel.x < 0 || pixel.y < 0:
|
|
# // print(pixel);
|
|
# Color color = _selection_colors[idx];
|
|
# pixel -= _cut_pos + _cut_size / 2;
|
|
# pixel += cell_mouse_position;
|
|
# paint_canvas->_set_pixel_v(paint_canvas->tool_layer, pixel, color);
|
|
# }
|
|
# } break;
|
|
# case Tools::BRUSH: {
|
|
# PoolVector2iArray pixels = BrushPrefabs::get_brush(selected_brush_prefab, brush_size_slider->get_value());
|
|
#
|
|
# PoolVector2iArray::Read r = pixels.read();
|
|
#
|
|
# for (int i = 0; i < pixels.size(); ++i) {
|
|
# Vector2i pixel = r[i];
|
|
# paint_canvas->_set_pixel(paint_canvas->tool_layer, cell_mouse_position.x + pixel.x, cell_mouse_position.y + pixel.y, _selected_color);
|
|
# //print_error("ad " + String::num(cell_mouse_position.x + pixel.x) + " " + String::num(cell_mouse_position.y + pixel.y));
|
|
# }
|
|
#
|
|
# r.release();
|
|
# } break;
|
|
# case Tools::RAINBOW: {
|
|
# paint_canvas->_set_pixel(paint_canvas->tool_layer, cell_mouse_position.x, cell_mouse_position.y, Color(0.46875, 0.446777, 0.446777, 0.196078));
|
|
# } break;
|
|
# case Tools::COLORPICKER: {
|
|
# paint_canvas->_set_pixel(paint_canvas->tool_layer, cell_mouse_position.x, cell_mouse_position.y, Color(0.866667, 0.847059, 0.847059, 0.196078));
|
|
# } break;
|
|
# default: {
|
|
# paint_canvas->_set_pixel(paint_canvas->tool_layer, cell_mouse_position.x, cell_mouse_position.y, _selected_color);
|
|
# } break;
|
|
# }
|
|
#
|
|
# paint_canvas->update();
|
|
#}
|
|
|
|
func do_action(arr : Array) -> void:
|
|
if !_current_action:
|
|
return
|
|
|
|
_current_action.do_action(arr)
|
|
update_textures()
|
|
|
|
func commit_action() -> void:
|
|
if !_current_action:
|
|
return
|
|
|
|
_current_action.commit_action()
|
|
|
|
_actions_history.push_back(_current_action)
|
|
_redo_history.clear()
|
|
update_textures()
|
|
|
|
if current_tool == TOOL_CUT:
|
|
var ca : CutAction = _current_action;
|
|
|
|
_cut_pos = ca.mouse_start_pos;
|
|
_cut_size = ca.mouse_end_pos - ca.mouse_start_pos;
|
|
|
|
_selection_cells.clear();
|
|
_selection_colors.clear();
|
|
|
|
_selection_cells.append_array(ca.redo_cells);
|
|
_selection_colors.append_array(ca.redo_colors);
|
|
|
|
current_tool = TOOL_PASTECUT
|
|
|
|
_current_action = null
|
|
|
|
func redo_action() -> void:
|
|
if (_redo_history.empty()):
|
|
print("PaintCanvas: nothing to redo");
|
|
return;
|
|
|
|
var action : PaintAction = _redo_history[_redo_history.size() - 1];
|
|
_redo_history.remove(_redo_history.size() - 1);
|
|
|
|
if (!action):
|
|
return;
|
|
|
|
_actions_history.push_back(action);
|
|
action.redo_action();
|
|
update_textures()
|
|
|
|
print("PaintCanvas: redo action");
|
|
|
|
func undo_action() -> void:
|
|
if (_actions_history.empty()):
|
|
print("PaintCanvas: nothing to undo");
|
|
return;
|
|
|
|
var action : PaintAction = _actions_history[_actions_history.size() - 1];
|
|
_actions_history.remove(_actions_history.size() - 1);
|
|
|
|
if (!action):
|
|
return;
|
|
|
|
_redo_history.push_back(action);
|
|
action.undo_action();
|
|
update_textures()
|
|
|
|
print("PaintCanvas: undo action")
|
|
|
|
#void PaintWindow::redo_action_old() {
|
|
# if (_redo_history.empty()) {
|
|
# //print("nothing to redo");
|
|
# return;
|
|
# }
|
|
#
|
|
# Ref<PaintAction> action = _redo_history[_redo_history.size() - 1];
|
|
# _redo_history.remove(_redo_history.size() - 1);
|
|
#
|
|
# if (!action.is_valid()) {
|
|
# return;
|
|
# }
|
|
#
|
|
# _actions_history.push_back(action);
|
|
# action->redo_action_old(paint_canvas);
|
|
# paint_canvas->update();
|
|
#
|
|
# //print("redo action");
|
|
#}
|
|
|
|
#void PaintWindow::undo_action_old() {
|
|
# if (_actions_history.empty()) {
|
|
# return;
|
|
# }
|
|
#
|
|
# Ref<PaintAction> action = _actions_history[_actions_history.size() - 1];
|
|
# _actions_history.remove(_actions_history.size() - 1);
|
|
#
|
|
# if (!action.is_valid()) {
|
|
# return;
|
|
# }
|
|
#
|
|
# _redo_history.push_back(action);
|
|
# action->undo_action_old(paint_canvas);
|
|
# update();
|
|
# paint_canvas->update();
|
|
#
|
|
# //print("undo action")
|
|
#}
|
|
|
|
func has_point(var pos : Vector2) -> bool:
|
|
if pos.x < 0 || pos.y < 0 || pos.x > size.x || pos.y > size.y:
|
|
return false
|
|
|
|
return true
|
|
|
|
func get_action() -> PaintAction:
|
|
var action : PaintAction = null
|
|
|
|
if current_tool == TOOL_PENCIL:
|
|
action = PencilAction.new()
|
|
elif current_tool == TOOL_BRUSH:
|
|
action = BrushAction.new()
|
|
elif current_tool == TOOL_LINE:
|
|
action = LineAction.new()
|
|
elif current_tool == TOOL_RAINBOW:
|
|
action = RainbowAction.new()
|
|
elif current_tool == TOOL_BUCKET:
|
|
action = BucketAction.new()
|
|
elif current_tool == TOOL_RECT:
|
|
action = RectAction.new()
|
|
elif current_tool == TOOL_DARKEN:
|
|
action = DarkenAction.new()
|
|
elif current_tool == TOOL_BRIGHTEN:
|
|
action = BrightenAction.new()
|
|
elif current_tool == TOOL_CUT:
|
|
action = CutAction.new()
|
|
elif current_tool == TOOL_PASTECUT:
|
|
action = PasteCutAction.new()
|
|
|
|
if action:
|
|
action.paint_canvas = self
|
|
|
|
return action
|
|
|
|
func _on_tool_changed() -> void:
|
|
if current_tool == TOOL_COLORPICKER:
|
|
if _current_action:
|
|
_current_action = null
|
|
return
|
|
|
|
if get_previous_tool() == TOOL_CUT:
|
|
clear_preview()
|
|
|
|
_current_action = get_action()
|
|
|
|
func tool_process(local_position : Vector2, event: InputEvent) -> void:
|
|
if current_tool == TOOL_COLORPICKER:
|
|
return
|
|
|
|
if !_current_action:
|
|
_current_action = get_action()
|
|
|
|
if current_tool == TOOL_PENCIL || current_tool == TOOL_LINE || current_tool == TOOL_RECT:
|
|
var arr : Array = Array()
|
|
|
|
arr.push_back(_cell_mouse_position)
|
|
arr.push_back(_last_cell_mouse_position)
|
|
|
|
if _mouse_button_down == BUTTON_LEFT:
|
|
arr.push_back(get_current_color())
|
|
elif _mouse_button_down == BUTTON_RIGHT:
|
|
arr.push_back(Color(1, 1, 1, 0))
|
|
|
|
do_action(arr)
|
|
elif current_tool == TOOL_DARKEN || current_tool == TOOL_BRIGHTEN || current_tool == TOOL_CUT:
|
|
var arr : Array = Array()
|
|
|
|
arr.push_back(_cell_mouse_position)
|
|
arr.push_back(_last_cell_mouse_position)
|
|
arr.push_back(get_current_color())
|
|
|
|
do_action(arr)
|
|
elif current_tool == TOOL_BRUSH:
|
|
var arr : Array = Array()
|
|
|
|
arr.push_back(_cell_mouse_position)
|
|
arr.push_back(_last_cell_mouse_position)
|
|
|
|
if _mouse_button_down == BUTTON_LEFT:
|
|
arr.push_back(get_current_color())
|
|
elif _mouse_button_down == BUTTON_RIGHT:
|
|
arr.push_back(Color(1, 1, 1, 0))
|
|
|
|
arr.push_back(brush_prefab)
|
|
arr.push_back(brush_size)
|
|
|
|
do_action(arr)
|
|
elif current_tool == TOOL_COLORPICKER:
|
|
# Nothing to do here
|
|
pass
|
|
elif current_tool == TOOL_PASTECUT:
|
|
var arr : Array = Array()
|
|
|
|
arr.append(_cell_mouse_position);
|
|
arr.append(_last_cell_mouse_position);
|
|
arr.append(_selection_cells);
|
|
arr.append(_selection_colors);
|
|
arr.append(_cut_pos);
|
|
arr.append(_cut_size);
|
|
|
|
do_action(arr);
|
|
elif current_tool == TOOL_RAINBOW:
|
|
var arr : Array = Array()
|
|
|
|
arr.push_back(_cell_mouse_position)
|
|
arr.push_back(_last_cell_mouse_position)
|
|
|
|
do_action(arr)
|
|
|
|
func _forward_canvas_gui_input(event: InputEvent) -> bool:
|
|
if !is_visible_in_tree():
|
|
return false
|
|
|
|
if event is InputEventMouseButton:
|
|
if _mouse_down && _mouse_button_down != event.button_index:
|
|
# Ignore it, but consume the event from the editor
|
|
return true
|
|
|
|
if event.button_index != BUTTON_LEFT && event.button_index != BUTTON_RIGHT:
|
|
return false
|
|
|
|
# This seems to be the easiest way to get local mouse position,
|
|
# even though the event is available
|
|
var local_position : Vector2 = get_local_mouse_position()
|
|
|
|
if _mouse_down:
|
|
if !event.pressed:
|
|
_mouse_down = false
|
|
_mouse_button_down = -1
|
|
|
|
if _mouse_button_down == BUTTON_LEFT:
|
|
handle_left_mouse_button_up(local_position, event)
|
|
|
|
commit_action()
|
|
else:
|
|
if has_point(local_position):
|
|
_mouse_down = true
|
|
_mouse_button_down = event.button_index
|
|
|
|
clear_preview()
|
|
|
|
if _mouse_button_down == BUTTON_LEFT:
|
|
handle_left_mouse_button_down(local_position, event)
|
|
elif _mouse_button_down == BUTTON_RIGHT:
|
|
handle_right_mouse_button_down(local_position, event)
|
|
|
|
return true
|
|
|
|
if event is InputEventMouseMotion:
|
|
var local_position : Vector2 = get_local_mouse_position()
|
|
|
|
_mouse_position = get_global_mouse_position()
|
|
_cell_mouse_position = local_position
|
|
|
|
if _mouse_down:
|
|
if has_point(local_position):
|
|
#handle_draw(local_position, event)
|
|
_cell_mouse_position = local_position
|
|
|
|
tool_process(local_position, event)
|
|
update_textures()
|
|
update()
|
|
|
|
_last_mouse_position = _mouse_position
|
|
_last_cell_mouse_position = local_position
|
|
|
|
return true
|
|
else:
|
|
draw_brush_preview()
|
|
|
|
_last_mouse_position = _mouse_position
|
|
_last_cell_mouse_position = local_position
|
|
|
|
if event is InputEventKey:
|
|
if event.echo || !event.pressed:
|
|
return false
|
|
|
|
var scancode : int = event.get_physical_scancode_with_modifiers()
|
|
|
|
var undo : bool = false
|
|
if (scancode == (KEY_Z | KEY_MASK_CTRL)):
|
|
undo = true
|
|
|
|
var redo : bool = false
|
|
if (scancode == (KEY_Z | KEY_MASK_CTRL | KEY_MASK_SHIFT)):
|
|
redo = true
|
|
|
|
if !undo && !redo:
|
|
return false
|
|
|
|
var local_position : Vector2 = get_local_mouse_position()
|
|
|
|
if has_point(local_position):
|
|
if redo:
|
|
redo_action()
|
|
return true
|
|
|
|
if undo:
|
|
undo_action()
|
|
return true
|
|
|
|
return false
|
|
|
|
func _ready() -> void:
|
|
#temp
|
|
#resize(1, 1)
|
|
#resize(128, 128)
|
|
|
|
if !is_connected("current_tool_changed", self, "_on_tool_changed"):
|
|
connect("current_tool_changed", self, "_on_tool_changed")
|
|
|
|
_on_tool_changed()
|
|
|
|
func _draw() -> void:
|
|
draw_texture(get_image_texture(), Vector2())
|
|
draw_texture(get_preview_image_texture(), Vector2())
|