From a159361a2f5cfd4b9cc81f3627398ac703e0811a Mon Sep 17 00:00:00 2001 From: TwistedTwigleg Date: Fri, 3 Nov 2017 14:23:07 -0400 Subject: [PATCH 1/4] Added a simple drawing example to help show how to use the drawing functions in CanvasItem to make a simple MS paint like program. --- 2d/gd_paint/PaintBrushData.gd | 26 ++ 2d/gd_paint/PaintControl.gd | 261 +++++++++++++++ 2d/gd_paint/PaintTools.png | Bin 0 -> 393 bytes 2d/gd_paint/Paint_root.tscn | 586 ++++++++++++++++++++++++++++++++++ 2d/gd_paint/ToolsPanel.gd | 107 +++++++ 2d/gd_paint/default_env.tres | 101 ++++++ 2d/gd_paint/icon.png | Bin 0 -> 884 bytes 2d/gd_paint/project.godot | 30 ++ 8 files changed, 1111 insertions(+) create mode 100644 2d/gd_paint/PaintBrushData.gd create mode 100644 2d/gd_paint/PaintControl.gd create mode 100644 2d/gd_paint/PaintTools.png create mode 100644 2d/gd_paint/Paint_root.tscn create mode 100644 2d/gd_paint/ToolsPanel.gd create mode 100644 2d/gd_paint/default_env.tres create mode 100644 2d/gd_paint/icon.png create mode 100644 2d/gd_paint/project.godot diff --git a/2d/gd_paint/PaintBrushData.gd b/2d/gd_paint/PaintBrushData.gd new file mode 100644 index 0000000000..2fa680f728 --- /dev/null +++ b/2d/gd_paint/PaintBrushData.gd @@ -0,0 +1,26 @@ +extends Reference + +# The type of brush this brush object is. There are only four types: +# 'pencil', 'eraser', 'rectangle shape' and 'circle shape' +var brush_type = "pencil" + +# The position of the brush, generally the center of the brush (see Paint_control.gd) +var brush_pos = Vector2() + +# the shape of the brush (only applies to the pencil and eraser) +# It can be either 'box' or 'circle' +var brush_shape = "box" + +# the size (in pixels) of the brush +var brush_size = 32 + +# the color of the brush +var brush_color = Color(1, 1, 1, 1) + +# The bottom right corner of the rectangle shape (if the brush type is 'rectangle shape') +# NOTE: The top left corner is assumed to be assigned to brush_pos +var brush_shape_rect_pos_BR = Vector2() + +# The radius of the circle shape (if the brush type is 'circle shape') +# NOTE: It's assumed that brush_pos is the center of the the circle +var brush_shape_circle_radius = 0 diff --git a/2d/gd_paint/PaintControl.gd b/2d/gd_paint/PaintControl.gd new file mode 100644 index 0000000000..1f90fe741b --- /dev/null +++ b/2d/gd_paint/PaintControl.gd @@ -0,0 +1,261 @@ +extends Control + +# The TL position of the canvas +var TL_node + +# A list to hold all of the brushes (called elements here to help distinguish it from the other variables) +var draw_elements_list = [] + +# A boolean to hold whether or not the mouse is inside the drawing area, the mouse position last _process call +# and the position of the mouse when the left mouse button was pressed +var is_mouse_in_drawing_area = false +var last_mouse_pos = Vector2() +var mouse_click_start_pos = null + +# A boolean to tell whether we've set undo_elements_list_num, which holds the size of draw_elements_list +# before a new stroke is added (unless the current brush mode is 'rectangle shape' or 'circle shape', in +# which case we do things a litte differently. See the undo_stroke function for more details) +var undo_set = false +var undo_element_list_num = -1 + +# A constant for whether or not we're needing to undo a shape +const UNDO_MODE_SHAPE = -2 +# A constant for whether or not we can undo +const UNDO_NONE = -1 + +# The brush_data object. This class just holds all of the data we need for any brush +var brush_data = preload("res://PaintBrushData.gd") + +# The current brush settings: The mode, size, color, and shape we have currently selected +var brush_mode = "pencil" +var brush_size = 32 +var brush_color = Color(1, 1, 1, 1) +var brush_shape = "circle" + +# The color of the background. We need this for the eraser (see the how we handle the eraser +# in the _draw function for more details) +var bg_color = Color(1, 1, 1, 1) + +# How large is the image (it's actually the size of DrawingAreaBG, because that's our background canvas) +const IMAGE_SIZE = Vector2(930, 720) + + +func _ready(): + # Get the top left position node. We need this to find out whether or not the mouse is inside the canvas + TL_node = get_node("TLPos") + set_process(true) + + +func _process(delta): + + var mouse_pos = get_viewport().get_mouse_position() + + # Check if the mouse is currently inside the canvas/drawing-area + is_mouse_in_drawing_area = false + if mouse_pos.x > TL_node.global_position.x: + if mouse_pos.y > TL_node.global_position.y: + is_mouse_in_drawing_area = true + + + if Input.is_mouse_button_pressed(BUTTON_LEFT): + + # If we do not have a position for when the mouse was first clicked, then this most + # be the first time is_mouse_button_pressed has been called since the mouse button was + # released, so we need to store the position + if mouse_click_start_pos == null: + mouse_click_start_pos = mouse_pos + + # If the mouse is inside the canvas and the mouse is 1px away from the position of the mouse last _process call + if check_if_mouse_is_inside_canvas(): + if mouse_pos.distance_to(last_mouse_pos) >= 1: + # If we are in pencil or eraser mode, then we need to draw + if brush_mode == "pencil" or brush_mode == "eraser": + # If undo has not been set, meaning we've started a new stroke, then store the size of the + # draw_elements_list so we can undo from this point in time + if undo_set == false: + undo_set = true + undo_element_list_num = draw_elements_list.size() + + # Add the brush object to draw_elements_array + add_brush(mouse_pos, brush_mode) + + else: + # We've finished our stroke, so we can set a new undo (if a new storke is made) + undo_set = false + + # If the mouse is inside the canvas + if check_if_mouse_is_inside_canvas(): + # If we're using either the circle shape mode, or the rectangle shape mode, then + # add the brush object to draw_elements_array + if brush_mode == "circle shape" or brush_mode == "rectangle shape": + add_brush(mouse_pos, brush_mode) + # We handle undo's differently than either pencil or eraser mode, so we need to set undo + # element_list_num to -2 so we can tell if we need to undo a shape. See undo_stroke for details + undo_element_list_num = UNDO_MODE_SHAPE + + # Since we've released the left mouse, we need to get a new mouse_click_start_pos next time + #is_mouse_button_pressed is true. + mouse_click_start_pos = null + + # Store mouse_pos as last_mouse_pos now that we're done with _process + last_mouse_pos = mouse_pos + + +func check_if_mouse_is_inside_canvas(): + # Make sure we have a mouse click starting position + if mouse_click_start_pos != null: + # Make sure the mouse click starting position is inside the canvas. + # This is so if we start out click outside the canvas (say chosing a color from the color picker) + # and then move our mouse back into the canvas, it won't start painting + if mouse_click_start_pos.x > TL_node.global_position.x and mouse_click_start_pos.y > TL_node.global_position.y: + # Make sure the current mouse position is inside the canvas + if is_mouse_in_drawing_area == true: + return true + return false + + +func undo_stroke(): + # Only undo a stroke if we have one + if undo_element_list_num == UNDO_NONE: + return + + # If we are undoing a shape, then we can just remove the latest brush + if undo_element_list_num == UNDO_MODE_SHAPE: + if draw_elements_list.size() > 0: + draw_elements_list.remove(draw_elements_list.size() - 1) + + # Now that we've undone a shape, we cannot undo again until another stoke is added + undo_element_list_num = UNDO_NONE + # NOTE: if we only had shape brushes, then we could remove the above line and could let the user + # undo until we have a empty element list + + # Otherwise we're removing a either a pencil stroke or a eraser stroke. + else: + # Figure out how many elements/brushes we've added in the last stroke + var elements_to_remove = draw_elements_list.size() - undo_element_list_num + # Remove all of the elements we've added this in the last stroke + for elment_num in range(0, elements_to_remove): + draw_elements_list.pop_back() + + # Now that we've undone a stoke, we cannot undo again until another stoke is added + undo_element_list_num = UNDO_NONE + + # Redraw the brushes + update() + + +func add_brush(mouse_pos, type): + + # Make new brush object + var brush = brush_data.new() + + # Assign all of the values based on our global brush settings variables + brush.brush_type = type + brush.brush_pos = mouse_pos + brush.brush_shape = brush_shape + brush.brush_size = brush_size + brush.brush_color = brush_color + + # If the bursh is a rectangle shape, we need to calculate the top left corner of the rectangle and the + # bottom right corner of the rectangle + if type == "rectangle shape": + var TL_pos = Vector2() + var BR_pos = Vector2() + + # Figure out the left and right positions of the corners and assign them to the proper variable + if mouse_pos.x < mouse_click_start_pos.x: + TL_pos.x = mouse_pos.x + BR_pos.x = mouse_click_start_pos.x + else: + TL_pos.x = mouse_click_start_pos.x + BR_pos.x = mouse_pos.x + + # Figure out the top and bottom positions of the corners and assign them to the proper variable + if mouse_pos.y < mouse_click_start_pos.y: + TL_pos.y = mouse_pos.y + BR_pos.y = mouse_click_start_pos.y + else: + TL_pos.y = mouse_click_start_pos.y + BR_pos.y = mouse_pos.y + + # Assign the positions to the brush + brush.brush_pos = TL_pos + brush.brush_shape_rect_pos_BR = BR_pos + + # If the brush isa circle shape, then we need to calculate the radius of the circle + if type == "circle shape": + # Get the center point inbetween the mouse position and the position of the mouse when we clicked + var center_pos = Vector2((mouse_pos.x + mouse_click_start_pos.x) / 2, (mouse_pos.y + mouse_click_start_pos.y) / 2) + # Assign the brush position to the center point, and calculate the radius of the circle using the distance from + # the center to the top/bottom positon of the mouse + brush.brush_pos = center_pos + brush.brush_shape_circle_radius = center_pos.distance_to(Vector2(center_pos.x, mouse_pos.y)) + + # Add the brush and update/draw all of the brushes + draw_elements_list.append(brush) + update() + + + +func _draw(): + # Go through all of the brushes in draw_elements_list + for brush in draw_elements_list: + + # If the brush is a pencil + if brush.brush_type == "pencil": + # If the brush shape is a box, then we need to make a Rect2 so we can use draw_rect. + # Draw_rect draws a rectagle at the top left corner, using the scale for the size. + # So we offset the position by half of the brush size so the rectangle's center is at mouse position + if brush.brush_shape == "box": + var rect = Rect2(brush.brush_pos - Vector2(brush.brush_size / 2, brush.brush_size / 2), Vector2(brush.brush_size, brush.brush_size)) + draw_rect(rect, brush.brush_color) + # If the brush shape is a circle, then we draw a circle at the mouse position, + # making the radius half of brush size (so the circle is brush size pixels in diameter) + elif brush.brush_shape == "circle": + draw_circle(brush.brush_pos, brush.brush_size / 2, brush.brush_color) + + # If the brush is a eraser + elif brush.brush_type == "eraser": + # NOTE: this is a really cheap way of erasing that isn't really erasing! + # But I couldn't think of a easy(ish) way to make an actual eraser + + # Erasing works exactly the same was as pencil does for both the box shape and the circle shape, + # but instead of using brush.brush_color, we instead use bg_color instead. + if brush.brush_shape == "box": + var rect = Rect2(brush.brush_pos - Vector2(brush.brush_size / 2, brush.brush_size / 2), Vector2(brush.brush_size, brush.brush_size)) + draw_rect(rect, bg_color) + elif brush.brush_shape == "circle": + draw_circle(brush.brush_pos, brush.brush_size / 2, bg_color) + + # If the brush is a rectangle shape + elif brush.brush_type == "rectangle shape": + # We make a Rect2 with the postion at the top left. To get the size we take the bottom right position + # and subtract the top left corner's position + var rect = Rect2(brush.brush_pos, brush.brush_shape_rect_pos_BR - brush.brush_pos) + draw_rect(rect, brush.brush_color) + + # If the brush is a circle shape + elif brush.brush_type == "circle shape": + # We simply draw a circle using stored in brush + draw_circle(brush.brush_pos, brush.brush_shape_circle_radius, brush.brush_color) + + + +func save_picture(path): + + # Wait a couple frames so the save dialog isn't in the way + yield (get_tree(), "idle_frame") + yield (get_tree(), "idle_frame") + + # Get the viewport image + var img = get_viewport().get_texture().get_data() + # Crop the image so we only have canvas area. + var cropped_image = img.get_rect(Rect2(TL_node.global_position, IMAGE_SIZE)) + # Flip the image on the Y-axis (it's flipped upside down by default) + cropped_image.flip_y() + + # Save the image with the passed in path we got from the save dialog + cropped_image.save_png(path) + + return + diff --git a/2d/gd_paint/PaintTools.png b/2d/gd_paint/PaintTools.png new file mode 100644 index 0000000000000000000000000000000000000000..7b2ba580d5650ce629bba48f3d39962ec091351d GIT binary patch literal 393 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzwj^(N7a$D;Kb?2i11Zh|kH}&M z25w;xW@MN(M}mQYQPb1KF(l&f+i80Rn+?5t)+9rf7g83`ktSG;l?`V%O)$9FbfFY zUd46l$)Ud;EI-0F*Tq&B`zPtfs2tdSt8|w3#3pstnjaBLTiKpH*!KDolj0BiV>7N6 zTsD!o%UWEpXUowCj*Yqxg&WsCWNx&5aM-nCpMKMBod#>hv}Y4qB;-0+-mwVmEw2-b z{1Es($b#X($BCl-~sXLPEtn^6r=tgBrv$!uD>PqK)d5p}%R=7=_mU1sEKzoSXU3R6EkJZkUgmBb_e jhyRIBqLkVps*WfXWRji9hg7on&wh0?L0a~qe`aCbK*5bNbkC4*ULip68o|{Rm|` zaJuhkK-8a5);VI{526OtvY3~cXvPV=SBg3F?cMOl(rsE@?Ct2b66vPFgl+W`pizfn zz;_&P$eGXHoc%oNtpP|M?uj)uwY*V8Jpf=>HjG#tN^20Q8aF_I!1qziFQe$W0Dypb zB%7T+JNIcMuK*yKY93TXJ){)uR2o(y32m4)KRf^sDQLrll}N%)r9nzT5%nZf&4U0y z?I*7sG2{3^fVNX@G0ot_ex*r|@lr~^mHVC9Gtp<$1 z^m_>e9gBzhi;rDBQ`PfbPv8D^PsidYcrF6d?^OU=R>?#~C9}3D0yVCb1w{tH>Z}B6 zREW4j?fXZ!udS`e%l0~_rncM}mHHs^4v+|h>ZrT)W#b25@2p4Q;N1;d!L*2!Jp| zV7Dya^{ibSAOHkF2s)tFGA|Ag00Llp9k5%O|DU-R2M7QGP+bSq`dKdy5CGdf2K!#F zuZPdqwB^MC0zd$4-T`CJ?{BRSs_cX?WL_K~00hA19Z>$aS!Vv{P6%V}#Q_39095x| zptKXp`=IOMt+J=vYs&!)Ufi_k>P)M%GI&veF$1hzCW?yIW@XG!+ldPg8f^2XY1xP+ zl92$AcXB9rE|$F9Lq$M_nf-$2M#2SwUqr!k!OXrQmC*~66F(aE9cqo4#&N&kL7Op< zQgu80^5O!(49Cq6eSiPru?B#6D*f7S+;a-xwxZ{PIRKFY5!L)QlSKK~mO$sfzErya%s0000< KMNUMnLSTZIyNag( literal 0 HcmV?d00001 diff --git a/2d/gd_paint/project.godot b/2d/gd_paint/project.godot new file mode 100644 index 0000000000..797248f084 --- /dev/null +++ b/2d/gd_paint/project.godot @@ -0,0 +1,30 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=3 + +[application] + +config/name="GD Paint" +run/main_scene="res://Paint_root.tscn" +config/icon="res://icon.png" + +[display] + +window/size/width=1280 +window/size/height=720 +window/stretch/mode="2d" +window/stretch/aspect="keep" + +[gdnative] + +singletons=[ ] + +[rendering] + +environment/default_environment="res://default_env.tres" From 7ad43829ef12eebe6b236b7c9b080b44fea98e19 Mon Sep 17 00:00:00 2001 From: TwistedTwigleg Date: Sun, 9 Jun 2019 18:44:01 -0400 Subject: [PATCH 2/4] Updated project to work with the latest version of Godot. Reworked the code so it is cleaner and easier to understand. Updated comments within code according to changes --- 2d/gd_paint/PaintBrushData.gd | 26 --- 2d/gd_paint/PaintControl.gd | 157 +++++++------- 2d/gd_paint/Paint_root.tscn | 373 +--------------------------------- 2d/gd_paint/ToolsPanel.gd | 42 ++-- 2d/gd_paint/default_env.tres | 87 -------- 2d/gd_paint/project.godot | 7 +- 6 files changed, 115 insertions(+), 577 deletions(-) delete mode 100644 2d/gd_paint/PaintBrushData.gd diff --git a/2d/gd_paint/PaintBrushData.gd b/2d/gd_paint/PaintBrushData.gd deleted file mode 100644 index 2fa680f728..0000000000 --- a/2d/gd_paint/PaintBrushData.gd +++ /dev/null @@ -1,26 +0,0 @@ -extends Reference - -# The type of brush this brush object is. There are only four types: -# 'pencil', 'eraser', 'rectangle shape' and 'circle shape' -var brush_type = "pencil" - -# The position of the brush, generally the center of the brush (see Paint_control.gd) -var brush_pos = Vector2() - -# the shape of the brush (only applies to the pencil and eraser) -# It can be either 'box' or 'circle' -var brush_shape = "box" - -# the size (in pixels) of the brush -var brush_size = 32 - -# the color of the brush -var brush_color = Color(1, 1, 1, 1) - -# The bottom right corner of the rectangle shape (if the brush type is 'rectangle shape') -# NOTE: The top left corner is assumed to be assigned to brush_pos -var brush_shape_rect_pos_BR = Vector2() - -# The radius of the circle shape (if the brush type is 'circle shape') -# NOTE: It's assumed that brush_pos is the center of the the circle -var brush_shape_circle_radius = 0 diff --git a/2d/gd_paint/PaintControl.gd b/2d/gd_paint/PaintControl.gd index 1f90fe741b..085c6c1d0a 100644 --- a/2d/gd_paint/PaintControl.gd +++ b/2d/gd_paint/PaintControl.gd @@ -3,8 +3,8 @@ extends Control # The TL position of the canvas var TL_node -# A list to hold all of the brushes (called elements here to help distinguish it from the other variables) -var draw_elements_list = [] +# A list to hold all of the dictionaries that make up each brush. +var brush_data_list = [] # A boolean to hold whether or not the mouse is inside the drawing area, the mouse position last _process call # and the position of the mouse when the left mouse button was pressed @@ -23,14 +23,19 @@ const UNDO_MODE_SHAPE = -2 # A constant for whether or not we can undo const UNDO_NONE = -1 -# The brush_data object. This class just holds all of the data we need for any brush -var brush_data = preload("res://PaintBrushData.gd") +# Enums for the various modes and brush shapes that can be applied +enum BRUSH_MODES { + pencil, eraser, circle_shape, rectangle_shape +} +enum BRUSH_SHAPES { + rectangle, circle +} # The current brush settings: The mode, size, color, and shape we have currently selected -var brush_mode = "pencil" +var brush_mode = BRUSH_MODES.pencil var brush_size = 32 var brush_color = Color(1, 1, 1, 1) -var brush_shape = "circle" +var brush_shape = BRUSH_SHAPES.circle; # The color of the background. We need this for the eraser (see the how we handle the eraser # in the _draw function for more details) @@ -47,56 +52,51 @@ func _ready(): func _process(delta): - var mouse_pos = get_viewport().get_mouse_position() - + # Check if the mouse is currently inside the canvas/drawing-area is_mouse_in_drawing_area = false if mouse_pos.x > TL_node.global_position.x: if mouse_pos.y > TL_node.global_position.y: is_mouse_in_drawing_area = true - - + if Input.is_mouse_button_pressed(BUTTON_LEFT): - # If we do not have a position for when the mouse was first clicked, then this most # be the first time is_mouse_button_pressed has been called since the mouse button was # released, so we need to store the position if mouse_click_start_pos == null: mouse_click_start_pos = mouse_pos - + # If the mouse is inside the canvas and the mouse is 1px away from the position of the mouse last _process call if check_if_mouse_is_inside_canvas(): if mouse_pos.distance_to(last_mouse_pos) >= 1: # If we are in pencil or eraser mode, then we need to draw - if brush_mode == "pencil" or brush_mode == "eraser": + if brush_mode == BRUSH_MODES.pencil or brush_mode == BRUSH_MODES.eraser: # If undo has not been set, meaning we've started a new stroke, then store the size of the # draw_elements_list so we can undo from this point in time if undo_set == false: undo_set = true - undo_element_list_num = draw_elements_list.size() - + undo_element_list_num = brush_data_list.size() # Add the brush object to draw_elements_array add_brush(mouse_pos, brush_mode) - + else: # We've finished our stroke, so we can set a new undo (if a new storke is made) undo_set = false - + # If the mouse is inside the canvas if check_if_mouse_is_inside_canvas(): # If we're using either the circle shape mode, or the rectangle shape mode, then # add the brush object to draw_elements_array - if brush_mode == "circle shape" or brush_mode == "rectangle shape": + if brush_mode == BRUSH_MODES.circle_shape or brush_mode == BRUSH_MODES.rectangle_shape: add_brush(mouse_pos, brush_mode) # We handle undo's differently than either pencil or eraser mode, so we need to set undo # element_list_num to -2 so we can tell if we need to undo a shape. See undo_stroke for details undo_element_list_num = UNDO_MODE_SHAPE - # Since we've released the left mouse, we need to get a new mouse_click_start_pos next time #is_mouse_button_pressed is true. mouse_click_start_pos = null - + # Store mouse_pos as last_mouse_pos now that we're done with _process last_mouse_pos = mouse_pos @@ -107,10 +107,11 @@ func check_if_mouse_is_inside_canvas(): # Make sure the mouse click starting position is inside the canvas. # This is so if we start out click outside the canvas (say chosing a color from the color picker) # and then move our mouse back into the canvas, it won't start painting - if mouse_click_start_pos.x > TL_node.global_position.x and mouse_click_start_pos.y > TL_node.global_position.y: - # Make sure the current mouse position is inside the canvas - if is_mouse_in_drawing_area == true: - return true + if mouse_click_start_pos.x > TL_node.global_position.x: + if mouse_click_start_pos.y > TL_node.global_position.y: + # Make sure the current mouse position is inside the canvas + if is_mouse_in_drawing_area == true: + return true return false @@ -118,25 +119,25 @@ func undo_stroke(): # Only undo a stroke if we have one if undo_element_list_num == UNDO_NONE: return - + # If we are undoing a shape, then we can just remove the latest brush if undo_element_list_num == UNDO_MODE_SHAPE: - if draw_elements_list.size() > 0: - draw_elements_list.remove(draw_elements_list.size() - 1) - + if brush_data_list.size() > 0: + brush_data_list.remove(brush_data_list.size() - 1) + # Now that we've undone a shape, we cannot undo again until another stoke is added undo_element_list_num = UNDO_NONE # NOTE: if we only had shape brushes, then we could remove the above line and could let the user # undo until we have a empty element list - + # Otherwise we're removing a either a pencil stroke or a eraser stroke. else: # Figure out how many elements/brushes we've added in the last stroke - var elements_to_remove = draw_elements_list.size() - undo_element_list_num + var elements_to_remove = brush_data_list.size() - undo_element_list_num # Remove all of the elements we've added this in the last stroke for elment_num in range(0, elements_to_remove): - draw_elements_list.pop_back() - + brush_data_list.pop_back() + # Now that we've undone a stoke, we cannot undo again until another stoke is added undo_element_list_num = UNDO_NONE @@ -145,23 +146,23 @@ func undo_stroke(): func add_brush(mouse_pos, type): - - # Make new brush object - var brush = brush_data.new() - - # Assign all of the values based on our global brush settings variables - brush.brush_type = type - brush.brush_pos = mouse_pos - brush.brush_shape = brush_shape - brush.brush_size = brush_size - brush.brush_color = brush_color - - # If the bursh is a rectangle shape, we need to calculate the top left corner of the rectangle and the + # Make new brush dictionary that will hold all of the data we need for the brush. + var new_brush = {} + + # Populate the dictionary with values based on the global brush variables. + # We will override these as needed if the brush is a rectange or circle. + new_brush.brush_type = type + new_brush.brush_pos = mouse_pos + new_brush.brush_shape = brush_shape + new_brush.brush_size = brush_size + new_brush.brush_color = brush_color + + # If the new bursh is a rectangle shape, we need to calculate the top left corner of the rectangle and the # bottom right corner of the rectangle - if type == "rectangle shape": + if type == BRUSH_MODES.rectangle_shape: var TL_pos = Vector2() var BR_pos = Vector2() - + # Figure out the left and right positions of the corners and assign them to the proper variable if mouse_pos.x < mouse_click_start_pos.x: TL_pos.x = mouse_pos.x @@ -169,7 +170,7 @@ func add_brush(mouse_pos, type): else: TL_pos.x = mouse_click_start_pos.x BR_pos.x = mouse_pos.x - + # Figure out the top and bottom positions of the corners and assign them to the proper variable if mouse_pos.y < mouse_click_start_pos.y: TL_pos.y = mouse_pos.y @@ -177,85 +178,83 @@ func add_brush(mouse_pos, type): else: TL_pos.y = mouse_click_start_pos.y BR_pos.y = mouse_pos.y - + # Assign the positions to the brush - brush.brush_pos = TL_pos - brush.brush_shape_rect_pos_BR = BR_pos - + new_brush.brush_pos = TL_pos + new_brush.brush_shape_rect_pos_BR = BR_pos + # If the brush isa circle shape, then we need to calculate the radius of the circle - if type == "circle shape": + if type == BRUSH_MODES.circle_shape: # Get the center point inbetween the mouse position and the position of the mouse when we clicked var center_pos = Vector2((mouse_pos.x + mouse_click_start_pos.x) / 2, (mouse_pos.y + mouse_click_start_pos.y) / 2) # Assign the brush position to the center point, and calculate the radius of the circle using the distance from # the center to the top/bottom positon of the mouse - brush.brush_pos = center_pos - brush.brush_shape_circle_radius = center_pos.distance_to(Vector2(center_pos.x, mouse_pos.y)) - + new_brush.brush_pos = center_pos + new_brush.brush_shape_circle_radius = center_pos.distance_to(Vector2(center_pos.x, mouse_pos.y)) + # Add the brush and update/draw all of the brushes - draw_elements_list.append(brush) + brush_data_list.append(new_brush) update() - func _draw(): - # Go through all of the brushes in draw_elements_list - for brush in draw_elements_list: - + # Go through all of the brushes in brush_data_list + for brush in brush_data_list: + # If the brush is a pencil - if brush.brush_type == "pencil": - # If the brush shape is a box, then we need to make a Rect2 so we can use draw_rect. + if brush.brush_type == BRUSH_MODES.pencil: + # If the brush shape is a rectangle, then we need to make a Rect2 so we can use draw_rect. # Draw_rect draws a rectagle at the top left corner, using the scale for the size. # So we offset the position by half of the brush size so the rectangle's center is at mouse position - if brush.brush_shape == "box": + if brush.brush_shape == BRUSH_SHAPES.rectangle: var rect = Rect2(brush.brush_pos - Vector2(brush.brush_size / 2, brush.brush_size / 2), Vector2(brush.brush_size, brush.brush_size)) draw_rect(rect, brush.brush_color) # If the brush shape is a circle, then we draw a circle at the mouse position, # making the radius half of brush size (so the circle is brush size pixels in diameter) - elif brush.brush_shape == "circle": + elif brush.brush_shape == BRUSH_SHAPES.circle: draw_circle(brush.brush_pos, brush.brush_size / 2, brush.brush_color) - + # If the brush is a eraser - elif brush.brush_type == "eraser": + elif brush.brush_type == BRUSH_MODES.eraser: # NOTE: this is a really cheap way of erasing that isn't really erasing! - # But I couldn't think of a easy(ish) way to make an actual eraser - - # Erasing works exactly the same was as pencil does for both the box shape and the circle shape, + # However, this gives similar results in a fairy simple way! + + # Erasing works exactly the same was as pencil does for both the rectangle shape and the circle shape, # but instead of using brush.brush_color, we instead use bg_color instead. - if brush.brush_shape == "box": + if brush.brush_shape == BRUSH_SHAPES.rectangle: var rect = Rect2(brush.brush_pos - Vector2(brush.brush_size / 2, brush.brush_size / 2), Vector2(brush.brush_size, brush.brush_size)) draw_rect(rect, bg_color) - elif brush.brush_shape == "circle": + elif brush.brush_shape == BRUSH_SHAPES.circle: draw_circle(brush.brush_pos, brush.brush_size / 2, bg_color) - + # If the brush is a rectangle shape - elif brush.brush_type == "rectangle shape": + elif brush.brush_type == BRUSH_MODES.rectangle_shape: # We make a Rect2 with the postion at the top left. To get the size we take the bottom right position # and subtract the top left corner's position var rect = Rect2(brush.brush_pos, brush.brush_shape_rect_pos_BR - brush.brush_pos) draw_rect(rect, brush.brush_color) - + # If the brush is a circle shape - elif brush.brush_type == "circle shape": + elif brush.brush_type == BRUSH_MODES.circle_shape: # We simply draw a circle using stored in brush draw_circle(brush.brush_pos, brush.brush_shape_circle_radius, brush.brush_color) func save_picture(path): - # Wait a couple frames so the save dialog isn't in the way yield (get_tree(), "idle_frame") yield (get_tree(), "idle_frame") - + # Get the viewport image var img = get_viewport().get_texture().get_data() # Crop the image so we only have canvas area. var cropped_image = img.get_rect(Rect2(TL_node.global_position, IMAGE_SIZE)) # Flip the image on the Y-axis (it's flipped upside down by default) cropped_image.flip_y() - + # Save the image with the passed in path we got from the save dialog cropped_image.save_png(path) - + return diff --git a/2d/gd_paint/Paint_root.tscn b/2d/gd_paint/Paint_root.tscn index 462ecdf3ed..0dda1959a9 100644 --- a/2d/gd_paint/Paint_root.tscn +++ b/2d/gd_paint/Paint_root.tscn @@ -5,582 +5,217 @@ [ext_resource path="res://PaintTools.png" type="Texture" id=3] [sub_resource type="StyleBoxFlat" id=1] - -content_margin_left = -1.0 -content_margin_right = -1.0 -content_margin_top = -1.0 -content_margin_bottom = -1.0 bg_color = Color( 1, 1, 1, 1 ) -draw_center = true -border_width_left = 0 -border_width_top = 0 -border_width_right = 0 -border_width_bottom = 0 -border_color = Color( 0.8, 0.8, 0.8, 1 ) -border_blend = false -corner_radius_top_left = 0 -corner_radius_top_right = 0 -corner_radius_bottom_right = 0 -corner_radius_bottom_left = 0 -corner_detail = 8 -expand_margin_left = 0.0 -expand_margin_right = 0.0 -expand_margin_top = 0.0 -expand_margin_bottom = 0.0 -shadow_color = Color( 0, 0, 0, 0.6 ) -shadow_size = 0 -anti_aliasing = true -anti_aliasing_size = 1 - -[node name="Paint_root" type="Control"] - -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 + +[node name="PaintRoot" type="Control"] margin_right = 40.0 margin_bottom = 40.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 [node name="DrawingAreaBG" type="Panel" parent="."] - -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 margin_left = 350.0 margin_right = 1280.0 margin_bottom = 720.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 custom_styles/panelf = SubResource( 1 ) custom_styles/panel = SubResource( 1 ) custom_styles/panelnc = SubResource( 1 ) -_sections_unfolded = [ "Rect", "Visibility", "custom_styles" ] [node name="PaintControl" type="Control" parent="."] - editor/display_folded = true -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 margin_right = 40.0 margin_bottom = 40.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 script = ExtResource( 1 ) -_sections_unfolded = [ "Rect" ] [node name="TLPos" type="Position2D" parent="PaintControl"] - position = Vector2( 350, 0 ) -_sections_unfolded = [ "Transform" ] [node name="ToolsPanel" type="Panel" parent="."] - editor/display_folded = true -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 margin_right = 350.0 margin_bottom = 720.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 script = ExtResource( 2 ) [node name="LabelTools" type="Label" parent="ToolsPanel"] - -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 margin_left = 20.0 margin_top = 10.0 margin_right = 330.0 margin_bottom = 24.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 2 -size_flags_horizontal = 1 -size_flags_vertical = 4 text = "Selected tool: pencil" align = 1 -percent_visible = 1.0 -lines_skipped = 0 -max_lines_visible = -1 [node name="ButtonToolPencil" type="Button" parent="ToolsPanel"] - editor/display_folded = true -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 margin_left = 40.0 margin_top = 40.0 margin_right = 100.0 margin_bottom = 100.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 -toggle_mode = false -enabled_focus_mode = 2 -shortcut = null -group = null -flat = false -_sections_unfolded = [ "Rect" ] [node name="Sprite" type="Sprite" parent="ToolsPanel/ButtonToolPencil"] - position = Vector2( 30, 30 ) scale = Vector2( 2.5, 2.5 ) texture = ExtResource( 3 ) region_enabled = true region_rect = Rect2( 0, 0, 16, 16 ) -_sections_unfolded = [ "Region" ] [node name="ButtonToolEraser" type="Button" parent="ToolsPanel"] - editor/display_folded = true -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 margin_left = 110.0 margin_top = 40.0 margin_right = 170.0 margin_bottom = 100.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 -toggle_mode = false -enabled_focus_mode = 2 -shortcut = null -group = null -flat = false -_sections_unfolded = [ "Rect" ] [node name="Sprite" type="Sprite" parent="ToolsPanel/ButtonToolEraser"] - position = Vector2( 30, 30 ) scale = Vector2( 2.5, 2.5 ) texture = ExtResource( 3 ) region_enabled = true region_rect = Rect2( 16, 0, 16, 16 ) -_sections_unfolded = [ "Region" ] [node name="ButtonToolRectangle" type="Button" parent="ToolsPanel"] - editor/display_folded = true -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 margin_left = 180.0 margin_top = 40.0 margin_right = 240.0 margin_bottom = 100.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 -toggle_mode = false -enabled_focus_mode = 2 -shortcut = null -group = null -flat = false -_sections_unfolded = [ "Rect" ] [node name="Sprite" type="Sprite" parent="ToolsPanel/ButtonToolRectangle"] - position = Vector2( 30, 30 ) scale = Vector2( 2.5, 2.5 ) texture = ExtResource( 3 ) region_enabled = true region_rect = Rect2( 0, 16, 16, 16 ) -_sections_unfolded = [ "Region" ] [node name="ButtonToolCircle" type="Button" parent="ToolsPanel"] - editor/display_folded = true -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 margin_left = 250.0 margin_top = 40.0 margin_right = 310.0 margin_bottom = 100.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 -toggle_mode = false -enabled_focus_mode = 2 -shortcut = null -group = null -flat = false -_sections_unfolded = [ "Rect" ] [node name="Sprite" type="Sprite" parent="ToolsPanel/ButtonToolCircle"] - position = Vector2( 30, 30 ) scale = Vector2( 2.5, 2.5 ) texture = ExtResource( 3 ) region_enabled = true region_rect = Rect2( 16, 16, 16, 16 ) -_sections_unfolded = [ "Region" ] [node name="LabelBrushColor" type="Label" parent="ToolsPanel"] - -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 margin_left = 20.0 margin_top = 120.0 margin_right = 330.0 margin_bottom = 134.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 2 -size_flags_horizontal = 1 -size_flags_vertical = 4 text = "Current color" align = 1 -percent_visible = 1.0 -lines_skipped = 0 -max_lines_visible = -1 [node name="ColorPickerBrush" type="ColorPickerButton" parent="ToolsPanel"] - -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 margin_left = 20.0 margin_top = 140.0 margin_right = 330.0 margin_bottom = 190.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 -toggle_mode = false -enabled_focus_mode = 2 -shortcut = null -group = null -flat = false color = Color( 1, 1, 1, 1 ) -edit_alpha = true [node name="LabelBrushSize" type="Label" parent="ToolsPanel"] - -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 margin_left = 20.0 margin_top = 210.0 margin_right = 330.0 margin_bottom = 224.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 2 -size_flags_horizontal = 1 -size_flags_vertical = 4 text = "Brush size: 32px" align = 1 -percent_visible = 1.0 -lines_skipped = 0 -max_lines_visible = -1 [node name="HScrollBarBrushSize" type="HScrollBar" parent="ToolsPanel"] - -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 margin_left = 20.0 margin_top = 230.0 margin_right = 330.0 margin_bottom = 260.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 0 -size_flags_horizontal = 1 -size_flags_vertical = 0 min_value = 1.0 -max_value = 100.0 -step = 0.0 -page = 0.0 value = 32.0 -exp_edit = false -rounded = false -custom_step = -1.0 [node name="LabelBrushShape" type="Label" parent="ToolsPanel"] - -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 margin_left = 20.0 margin_top = 280.0 margin_right = 330.0 margin_bottom = 294.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 2 -size_flags_horizontal = 1 -size_flags_vertical = 4 text = "Brush shape: circle" align = 1 -percent_visible = 1.0 -lines_skipped = 0 -max_lines_visible = -1 [node name="ButtonShapeBox" type="Button" parent="ToolsPanel"] - editor/display_folded = true -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 margin_left = 100.0 margin_top = 300.0 margin_right = 160.0 margin_bottom = 360.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 -toggle_mode = false -enabled_focus_mode = 2 -shortcut = null -group = null -flat = false -_sections_unfolded = [ "Rect" ] [node name="Sprite" type="Sprite" parent="ToolsPanel/ButtonShapeBox"] - position = Vector2( 30, 30 ) scale = Vector2( 2.5, 2.5 ) texture = ExtResource( 3 ) region_enabled = true region_rect = Rect2( 0, 16, 16, 16 ) -_sections_unfolded = [ "Region" ] [node name="ButtonShapeCircle" type="Button" parent="ToolsPanel"] - editor/display_folded = true -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 margin_left = 190.0 margin_top = 300.0 margin_right = 250.0 margin_bottom = 360.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 -toggle_mode = false -enabled_focus_mode = 2 -shortcut = null -group = null -flat = false -_sections_unfolded = [ "Rect" ] [node name="Sprite" type="Sprite" parent="ToolsPanel/ButtonShapeCircle"] - position = Vector2( 30, 30 ) scale = Vector2( 2.5, 2.5 ) texture = ExtResource( 3 ) region_enabled = true region_rect = Rect2( 16, 16, 16, 16 ) -_sections_unfolded = [ "Region" ] [node name="LabelBackgroundColor" type="Label" parent="ToolsPanel"] - -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 margin_left = 20.0 margin_top = 400.0 margin_right = 330.0 margin_bottom = 414.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 2 -size_flags_horizontal = 1 -size_flags_vertical = 4 text = "Background color" align = 1 -percent_visible = 1.0 -lines_skipped = 0 -max_lines_visible = -1 [node name="ColorPickerBackground" type="ColorPickerButton" parent="ToolsPanel"] - -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 margin_left = 20.0 margin_top = 420.0 margin_right = 330.0 margin_bottom = 470.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 -toggle_mode = false -enabled_focus_mode = 2 -shortcut = null -group = null -flat = false color = Color( 1, 1, 1, 1 ) edit_alpha = false [node name="LabelStats" type="Label" parent="ToolsPanel"] - modulate = Color( 0.414062, 0.414062, 0.414062, 1 ) -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 margin_left = 20.0 margin_top = 590.0 margin_right = 330.0 margin_bottom = 604.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 2 -size_flags_horizontal = 1 -size_flags_vertical = 4 text = "Brush objects: 00000" align = 1 -percent_visible = 1.0 -lines_skipped = 0 -max_lines_visible = -1 -_sections_unfolded = [ "Visibility" ] [node name="ButtonUndo" type="Button" parent="ToolsPanel"] - -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 margin_left = 10.0 margin_top = 520.0 margin_right = 340.0 margin_bottom = 560.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 -toggle_mode = false -enabled_focus_mode = 2 -shortcut = null -group = null text = "Undo last stroke" -flat = false [node name="ButtonSave" type="Button" parent="ToolsPanel"] - -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 margin_left = 10.0 margin_top = 620.0 margin_right = 340.0 margin_bottom = 660.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 -toggle_mode = false -enabled_focus_mode = 2 -shortcut = null -group = null text = "Save picture" -flat = false [node name="ButtonClear" type="Button" parent="ToolsPanel"] - -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 margin_left = 10.0 margin_top = 670.0 margin_right = 340.0 margin_bottom = 710.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 -toggle_mode = false -enabled_focus_mode = 2 -shortcut = null -group = null text = "Clear picture" -flat = false [node name="SaveFileDialog" type="FileDialog" parent="."] - -visible = false -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 margin_right = 600.0 margin_bottom = 400.0 -rect_min_size = Vector2( 200, 70 ) -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 -popup_exclusive = false -window_title = "Save a File" resizable = true -dialog_hide_on_ok = false -mode = 4 access = 2 filters = PoolStringArray( "*.png" ) -show_hidden_files = false - - +current_dir = "/home/ubuntu_noah/Documents/New_2019_GitHub_Repositories/godot-demo-projects/2d/gd_paint" +current_path = "/home/ubuntu_noah/Documents/New_2019_GitHub_Repositories/godot-demo-projects/2d/gd_paint/" diff --git a/2d/gd_paint/ToolsPanel.gd b/2d/gd_paint/ToolsPanel.gd index d62c31c07e..86e228aa1f 100644 --- a/2d/gd_paint/ToolsPanel.gd +++ b/2d/gd_paint/ToolsPanel.gd @@ -12,7 +12,6 @@ var save_dialog func _ready(): - # Get PaintControl and SaveFileDialog paint_control = get_parent().get_node("PaintControl") save_dialog = get_parent().get_node("SaveFileDialog") @@ -27,7 +26,7 @@ func _ready(): get_node("ButtonToolEraser").connect("pressed", self, "button_pressed", ["mode_eraser"]) get_node("ButtonToolRectangle").connect("pressed", self, "button_pressed", ["mode_rectangle"]) get_node("ButtonToolCircle").connect("pressed", self, "button_pressed", ["mode_circle"]) - get_node("ButtonShapeBox").connect("pressed", self, "button_pressed", ["shape_box"]) + get_node("ButtonShapeBox").connect("pressed", self, "button_pressed", ["shape_rectangle"]) get_node("ButtonShapeCircle").connect("pressed", self, "button_pressed", ["shape_circle"]) # Assign all of the needed signals for the other brush settings (and ColorPickerBackground) @@ -50,45 +49,56 @@ func _ready(): func _physics_process(delta): # Update the status label with the newest brush element count - label_stats.text = "Brush objects: " + String(paint_control.draw_elements_list.size()) + label_stats.text = "Brush objects: " + String(paint_control.brush_data_list.size()) func button_pressed(button_name): - # If a brush mode button is pressed + var tool_name = null + var shape_name = null + if button_name == "mode_pencil": - paint_control.brush_mode = "pencil" + paint_control.brush_mode = paint_control.BRUSH_MODES.pencil + tool_name = "pencil" elif button_name == "mode_eraser": - paint_control.brush_mode = "eraser" + paint_control.brush_mode = paint_control.BRUSH_MODES.eraser + tool_name = "eraser" elif button_name == "mode_rectangle": - paint_control.brush_mode = "rectangle shape" + paint_control.brush_mode = paint_control.BRUSH_MODES.rectangle_shape + tool_name = "rectangle shape" elif button_name == "mode_circle": - paint_control.brush_mode = "circle shape" + paint_control.brush_mode = paint_control.BRUSH_MODES.circle_shape + tool_name = "circle shape" # If a brush shape button is pressed - elif button_name == "shape_box": - paint_control.brush_shape = "box" + elif button_name == "shape_rectangle": + paint_control.brush_shape = paint_control.BRUSH_SHAPES.rectangle + shape_name = "rectangle" elif button_name == "shape_circle": - paint_control.brush_shape = "circle" + paint_control.brush_shape = paint_control.BRUSH_SHAPES.circle + shape_name = "circle"; # If a opperation button is pressed elif button_name == "clear_picture": - paint_control.draw_elements_list = [] + paint_control.brush_data_list = [] paint_control.update() elif button_name == "save_picture": save_dialog.popup_centered() elif button_name == "undo_stroke": paint_control.undo_stroke() - + # Update the labels (in case the brush mode or brush shape has changed) - label_tools.text = "Selected tool: " + paint_control.brush_mode - label_brush_shape.text = "Brush shape: " + paint_control.brush_shape + if tool_name != null: + label_tools.text = "Selected tool: " + tool_name + if shape_name != null: + label_brush_shape.text = "Brush shape: " + shape_name func brush_color_changed(color): # Change the brush color to whatever color the color picker is paint_control.brush_color = color + func background_color_changed(color): # Change the background color to whatever colorthe background color picker is get_parent().get_node("DrawingAreaBG").modulate = color @@ -96,11 +106,13 @@ func background_color_changed(color): # Because of how the eraser works we also need to redraw the paint control paint_control.update() + func brush_size_changed(value): # Change the size of the brush, and update the label to reflect the new value paint_control.brush_size = ceil(value) label_brush_size.text = "Brush size: " + String(ceil(value)) + "px" + func save_file_selected(path): # Call save_picture in paint_control, passing in the path we recieved from SaveFileDialog paint_control.save_picture(path) diff --git a/2d/gd_paint/default_env.tres b/2d/gd_paint/default_env.tres index ad86b722a9..dfe62abb7b 100644 --- a/2d/gd_paint/default_env.tres +++ b/2d/gd_paint/default_env.tres @@ -1,101 +1,14 @@ [gd_resource type="Environment" load_steps=2 format=2] [sub_resource type="ProceduralSky" id=1] - -radiance_size = 4 sky_top_color = Color( 0.0470588, 0.454902, 0.976471, 1 ) sky_horizon_color = Color( 0.556863, 0.823529, 0.909804, 1 ) sky_curve = 0.25 -sky_energy = 1.0 ground_bottom_color = Color( 0.101961, 0.145098, 0.188235, 1 ) ground_horizon_color = Color( 0.482353, 0.788235, 0.952941, 1 ) ground_curve = 0.01 -ground_energy = 1.0 -sun_color = Color( 1, 1, 1, 1 ) -sun_latitude = 35.0 -sun_longitude = 0.0 -sun_angle_min = 1.0 -sun_angle_max = 100.0 -sun_curve = 0.05 sun_energy = 16.0 -texture_size = 2 [resource] - background_mode = 2 background_sky = SubResource( 1 ) -background_sky_custom_fov = 0.0 -background_color = Color( 0, 0, 0, 1 ) -background_energy = 1.0 -background_canvas_max_layer = 0 -ambient_light_color = Color( 0, 0, 0, 1 ) -ambient_light_energy = 1.0 -ambient_light_sky_contribution = 1.0 -fog_enabled = false -fog_color = Color( 0.5, 0.6, 0.7, 1 ) -fog_sun_color = Color( 1, 0.9, 0.7, 1 ) -fog_sun_amount = 0.0 -fog_depth_enabled = true -fog_depth_begin = 10.0 -fog_depth_curve = 1.0 -fog_transmit_enabled = false -fog_transmit_curve = 1.0 -fog_height_enabled = false -fog_height_min = 0.0 -fog_height_max = 100.0 -fog_height_curve = 1.0 -tonemap_mode = 0 -tonemap_exposure = 1.0 -tonemap_white = 1.0 -auto_exposure_enabled = false -auto_exposure_scale = 0.4 -auto_exposure_min_luma = 0.05 -auto_exposure_max_luma = 8.0 -auto_exposure_speed = 0.5 -ss_reflections_enabled = false -ss_reflections_max_steps = 64 -ss_reflections_fade_in = 0.15 -ss_reflections_fade_out = 2.0 -ss_reflections_depth_tolerance = 0.2 -ss_reflections_roughness = true -ssao_enabled = false -ssao_radius = 1.0 -ssao_intensity = 1.0 -ssao_radius2 = 0.0 -ssao_intensity2 = 1.0 -ssao_bias = 0.01 -ssao_light_affect = 0.0 -ssao_color = Color( 0, 0, 0, 1 ) -ssao_quality = 0 -ssao_blur = 3 -ssao_edge_sharpness = 4.0 -dof_blur_far_enabled = false -dof_blur_far_distance = 10.0 -dof_blur_far_transition = 5.0 -dof_blur_far_amount = 0.1 -dof_blur_far_quality = 1 -dof_blur_near_enabled = false -dof_blur_near_distance = 2.0 -dof_blur_near_transition = 1.0 -dof_blur_near_amount = 0.1 -dof_blur_near_quality = 1 -glow_enabled = false -glow_levels/1 = false -glow_levels/2 = false -glow_levels/3 = true -glow_levels/4 = false -glow_levels/5 = true -glow_levels/6 = false -glow_levels/7 = false -glow_intensity = 0.8 -glow_strength = 1.0 -glow_bloom = 0.0 -glow_blend_mode = 2 -glow_hdr_threshold = 1.0 -glow_hdr_scale = 2.0 -glow_bicubic_upscale = false -adjustment_enabled = false -adjustment_brightness = 1.0 -adjustment_contrast = 1.0 -adjustment_saturation = 1.0 - diff --git a/2d/gd_paint/project.godot b/2d/gd_paint/project.godot index 797248f084..17547124e6 100644 --- a/2d/gd_paint/project.godot +++ b/2d/gd_paint/project.godot @@ -6,7 +6,12 @@ ; [section] ; section goes between [] ; param=value ; assign values to parameters -config_version=3 +config_version=4 + +_global_script_classes=[ ] +_global_script_class_icons={ + +} [application] From 2c5b4a48d0c8b8514bf7acf4ea56a844610b4dfd Mon Sep 17 00:00:00 2001 From: TwistedTwigleg Date: Sat, 15 Jun 2019 11:52:41 -0400 Subject: [PATCH 3/4] Made changes to gd_paint demo based on feedback by aaronfranke --- 2d/gd_paint/PaintControl.gd | 3 ++- 2d/gd_paint/ToolsPanel.gd | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/2d/gd_paint/PaintControl.gd b/2d/gd_paint/PaintControl.gd index 085c6c1d0a..7838a60d18 100644 --- a/2d/gd_paint/PaintControl.gd +++ b/2d/gd_paint/PaintControl.gd @@ -51,7 +51,7 @@ func _ready(): set_process(true) -func _process(delta): +func _process(_delta): var mouse_pos = get_viewport().get_mouse_position() # Check if the mouse is currently inside the canvas/drawing-area @@ -135,6 +135,7 @@ func undo_stroke(): # Figure out how many elements/brushes we've added in the last stroke var elements_to_remove = brush_data_list.size() - undo_element_list_num # Remove all of the elements we've added this in the last stroke + #warning-ignore:unused_variable for elment_num in range(0, elements_to_remove): brush_data_list.pop_back() diff --git a/2d/gd_paint/ToolsPanel.gd b/2d/gd_paint/ToolsPanel.gd index 86e228aa1f..e1026a3719 100644 --- a/2d/gd_paint/ToolsPanel.gd +++ b/2d/gd_paint/ToolsPanel.gd @@ -16,6 +16,7 @@ func _ready(): paint_control = get_parent().get_node("PaintControl") save_dialog = get_parent().get_node("SaveFileDialog") + # warning-ignore-all:return_value_discarded # Assign all of the needed signals for the oppersation buttons get_node("ButtonUndo").connect("pressed", self, "button_pressed", ["undo_stroke"]) get_node("ButtonSave").connect("pressed", self, "button_pressed", ["save_picture"]) @@ -47,7 +48,7 @@ func _ready(): set_physics_process(true) -func _physics_process(delta): +func _physics_process(_delta): # Update the status label with the newest brush element count label_stats.text = "Brush objects: " + String(paint_control.brush_data_list.size()) From 0d40b69c191ecc0998de1bfdb05e8059bf7c5a8d Mon Sep 17 00:00:00 2001 From: TwistedTwigleg Date: Thu, 29 Aug 2019 13:17:15 -0400 Subject: [PATCH 4/4] Minor changes to GD_Paint demo --- 2d/gd_paint/PaintControl.gd | 2 -- 2d/gd_paint/PaintTools.png | Bin 393 -> 440 bytes 2 files changed, 2 deletions(-) diff --git a/2d/gd_paint/PaintControl.gd b/2d/gd_paint/PaintControl.gd index 7838a60d18..bd08f5485f 100644 --- a/2d/gd_paint/PaintControl.gd +++ b/2d/gd_paint/PaintControl.gd @@ -256,6 +256,4 @@ func save_picture(path): # Save the image with the passed in path we got from the save dialog cropped_image.save_png(path) - - return diff --git a/2d/gd_paint/PaintTools.png b/2d/gd_paint/PaintTools.png index 7b2ba580d5650ce629bba48f3d39962ec091351d..37c67c9048a1a5333b512f8325a533663add8f77 100644 GIT binary patch delta 408 zcmV;J0cZY+1Goc_Du4d~{{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2jd120W=(y2*X(b00BiwL_t(o!|j#3aRea@K&724<9a}aY-D$_HMpgVyfrxUj3~g# zCeGY~9IRmg!y!0)>);eJi1&o}0300HGFjGDeBwN}<-Wh|xqqKu003aO4QN?#(k{Tv zV$bKSOe;JLm4IAkF&{6xc_48sTqPiv*;m>sQG-_nLU<}sI|J9?cH8O#Ik*cVx*1N( zg2h{K4UW(2FnCtrp737+_l8FTN5JDl`1INZ_t63O0wN+g2{k+u8n_og4CeeuG{KYV zwQvA{ldl#LM1KS@vgxZ@3x9;ahRiHI$)zWmnE?ROHIazQe|>9|q?uWA>$&ki70|4c z=1rq|$;@Jmsm?RTL@l2N!Mk%t?SQKKa2MPmosPbS4}nnvXsy-%8T(uuCQy9g6gk6M zKt!rtu+~OT_-SN6i3r^zlU_?Fm;N9B<1;!kz5((Gf)SJdK>OJM0000y%B>j3`Qki#$X3~5UOMgX2?pZ!VKwhCl8Q@CS6ug3KE|I8_VE>hOY(rJsJN1 zuyZiyWo}z`g>{`*`+W4Z?+*X~*scT9G^nHl5E0v|3d-cd{eOrA_*S!iU3+s+Vl7-G zz_;3Unk$ilCk1@?SR%Cs=HRyL(gGp)KgO8VaMLsx-34=SytKvOL4hsd6M?Pa1A#r@ z!$o+$FM_))fI9(Z=8%LK9*6|)1Q5M6zJ8CO