From 3a20b3e073339c49ab2e7cfcdcfe7541cb2bf755 Mon Sep 17 00:00:00 2001 From: OverloadedOrama <35376950+OverloadedOrama@users.noreply.github.com> Date: Thu, 26 Dec 2019 21:36:56 +0200 Subject: [PATCH] Added a new brush type - Random Brushes They're like File brushes, but each time you draw, expect to see something different! To make a random brush, just put the images you want in the same folder (under the main Brushes folder of course), and make sure their filename starts with "%". I also changed _process() to _input() in Canvas.gd, so there may be some unexpected behavior. --- Brushes/Icons/%icon_1.png | Bin 0 -> 199 bytes Brushes/Icons/%icon_2.png | Bin 0 -> 197 bytes Brushes/Icons/%icon_3.png | Bin 0 -> 198 bytes Brushes/Icons/%icon_4.png | Bin 0 -> 198 bytes Brushes/Lines/%random_line_1.png | Bin 0 -> 110 bytes Brushes/Lines/%random_line_2.png | Bin 0 -> 119 bytes Brushes/Lines/%random_line_3.png | Bin 0 -> 158 bytes Brushes/Lines/%random_line_4.png | Bin 0 -> 126 bytes Brushes/Lines/%random_line_5.png | Bin 0 -> 141 bytes Scripts/BrushButton.gd | 2 ++ Scripts/Canvas.gd | 58 +++++++++++++++++++++++-------- Scripts/Global.gd | 11 +++--- Scripts/Import.gd | 18 +++++++--- 13 files changed, 66 insertions(+), 23 deletions(-) create mode 100644 Brushes/Icons/%icon_1.png create mode 100644 Brushes/Icons/%icon_2.png create mode 100644 Brushes/Icons/%icon_3.png create mode 100644 Brushes/Icons/%icon_4.png create mode 100644 Brushes/Lines/%random_line_1.png create mode 100644 Brushes/Lines/%random_line_2.png create mode 100644 Brushes/Lines/%random_line_3.png create mode 100644 Brushes/Lines/%random_line_4.png create mode 100644 Brushes/Lines/%random_line_5.png diff --git a/Brushes/Icons/%icon_1.png b/Brushes/Icons/%icon_1.png new file mode 100644 index 0000000000000000000000000000000000000000..453a50e9efee04843ee6eba56f8a1bc57223fc5f GIT binary patch literal 199 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`eV#6kAr`$$gB|%A40xC}|F4(i zUsn3|madzh6(gt8MyI1UdCJV07&6zZ#~!-rpr*pu(JfH+W{y{b4RBM0CX8hPfHvL6m5zu7}p00i_>zopr0BHwCegFUf literal 0 HcmV?d00001 diff --git a/Brushes/Icons/%icon_2.png b/Brushes/Icons/%icon_2.png new file mode 100644 index 0000000000000000000000000000000000000000..e4d5abbea1bf6e52e2c6e5fb7730d8eded68ac37 GIT binary patch literal 197 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`J)SO(Ar`$$CkOH!P~dQme*Aa+ z8M|eC0vA$hRxa#!)806pC4JY7TowkGEZdzbR~RClgw9Ba)a0(;XI+zU$(mt{=en29 zF&WEmCjKnF$YYx&Uidv}w^Y}qLvM<_5BN@H_?nWoc6Ix5&L_7HYWipC29fXumes|eC?^SaCTES`G{TwcRbd75Cu<6_*_i(bqob9vk8eCtTQ2nl>a)D~+ xa-AnU3hIHIG|cOqr>tIGSG(-e%Vz%LtZ%X`d5vKOeT96Zx}==!y<=hNyN?r<`2pERxQ z;C|a8dt&Y)%kMXX-W}}EI4*Y2(u+BIlGmb32e^zUYad+e#k{*aM_-TK=}&Lq3;Uz$ xA7`=7XKYdNn{0B*uJ!kZ_7AT9w2e(*CGOc(fJKfk65XaIw!tDnm{ Hr-UW|U0Wif literal 0 HcmV?d00001 diff --git a/Brushes/Lines/%random_line_2.png b/Brushes/Lines/%random_line_2.png new file mode 100644 index 0000000000000000000000000000000000000000..cf61b87a7a9fa556d0fb2cb897f01a246f24e9e9 GIT binary patch literal 119 zcmeAS@N?(olHy`uVBq!ia0vp^f*{Pn1|+R>-G2coJ5LwK5R2aAlm$G0(i4C{C6rl8 z!PP#D*@MaX1cRDa?xHU36=@8idz$k&j^0zaEwJi1-_5v%tGwCl>KPaoEATRY_~Um1 PXcB{`tDnm{r-UW|wLc;# literal 0 HcmV?d00001 diff --git a/Brushes/Lines/%random_line_3.png b/Brushes/Lines/%random_line_3.png new file mode 100644 index 0000000000000000000000000000000000000000..118c27cf0f35ca3d046d555c64a6da6edf7db78b GIT binary patch literal 158 zcmeAS@N?(olHy`uVBq!ia0vp^fFVdQ I&MBb@0Q@^TGXMYp literal 0 HcmV?d00001 diff --git a/Brushes/Lines/%random_line_4.png b/Brushes/Lines/%random_line_4.png new file mode 100644 index 0000000000000000000000000000000000000000..ace4cc968a78e51a5181bca808fffee564a2b7c7 GIT binary patch literal 126 zcmeAS@N?(olHy`uVBq!ia0vp^+(0bK!3HEJ6o{M!Qm&pZjv*QolM@mWew=quNocy{ zlC2PF=))Z6+ryIMFkL-E+LK{jBj&d)%@4u+XuJhl#<_ WoLfM#ReCPaKn71&KbLh*2~7a=n o2|Ci@DmU9L=hcTS1#Sk0Uz-%3hb-_u3N)X=)78&qol`;+0K1GR-v9sr literal 0 HcmV?d00001 diff --git a/Scripts/BrushButton.gd b/Scripts/BrushButton.gd index a5b06529e..bbc169dcc 100644 --- a/Scripts/BrushButton.gd +++ b/Scripts/BrushButton.gd @@ -2,6 +2,8 @@ extends BaseButton export var brush_type = Global.BRUSH_TYPES.PIXEL export var custom_brush_index := -2 +# warning-ignore:unused_class_variable +var random_brushes := [] func _on_BrushButton_pressed() -> void: # Change left brush diff --git a/Scripts/Canvas.gd b/Scripts/Canvas.gd index ef02b42fd..e786fbde6 100644 --- a/Scripts/Canvas.gd +++ b/Scripts/Canvas.gd @@ -12,6 +12,7 @@ var frame_texture_rect : TextureRect var current_pixel := Vector2.ZERO #pretty much same as mouse_pos, but can be accessed externally var previous_mouse_pos := Vector2.ZERO var previous_mouse_pos_for_lines := Vector2.ZERO +var can_undo := true var cursor_inside_canvas := false var previous_action := "None" var mouse_inside_canvas := false #used for undo @@ -80,9 +81,10 @@ func camera_zoom() -> void: Global.camera_preview.offset = size / 2 # warning-ignore:unused_argument -func _process(delta : float) -> void: +func _input(event) -> void: sprite_changed_this_frame = false - update() + if Global.current_frame == frame: + update() current_pixel = get_local_mouse_position() - location var mouse_pos := current_pixel var mouse_pos_floored := mouse_pos.floor() @@ -90,8 +92,8 @@ func _process(delta : float) -> void: var mouse_in_canvas := point_in_rectangle(mouse_pos, location, location + size) var current_mouse_button := "None" var current_action := "None" - var fill_area := 0 #For the bucket tool - #For the LightenDarken tool + var fill_area := 0 # For the bucket tool + # For the LightenDarken tool var ld := 0 var ld_amount := 0.1 if Input.is_mouse_button_pressed(BUTTON_LEFT): @@ -126,13 +128,13 @@ func _process(delta : float) -> void: Global.right_cursor.visible = false Input.set_custom_mouse_cursor(null) - #Handle Undo/Redo + # Handle Undo/Redo var can_handle : bool = mouse_in_canvas && Global.can_draw && Global.has_focus && !made_line var mouse_pressed : bool = (Input.is_action_just_pressed("left_mouse") && !Input.is_action_pressed("right_mouse")) || (Input.is_action_just_pressed("right_mouse") && !Input.is_action_pressed("left_mouse")) - #If we're already pressing a mouse button and we haven't handled undo yet,... - #... it means that the cursor was outside the canvas. Then, ... - #simulate "just pressed" logic the moment the cursor gets inside the canvas + # If we're already pressing a mouse button and we haven't handled undo yet,... + #. .. it means that the cursor was outside the canvas. Then, ... + # simulate "just pressed" logic the moment the cursor gets inside the canvas if Input.is_action_pressed("left_mouse") || Input.is_action_pressed("right_mouse"): if mouse_in_canvas && Global.undos < Global.undo_redo.get_version(): mouse_pressed = true @@ -151,7 +153,7 @@ func _process(delta : float) -> void: if previous_action != "None" && previous_action != "RectSelect" && current_action != "ColorPicker": handle_redo("Draw") - match current_action: #Handle current tool + match current_action: # Handle current tool "Pencil": var current_color : Color if current_mouse_button == "left_mouse": @@ -316,18 +318,20 @@ func _process(delta : float) -> void: update_texture(current_layer_index, (Input.is_action_just_released("left_mouse") || Input.is_action_just_released("right_mouse"))) func handle_undo(action : String) -> void: + if !can_undo: + return var canvases := [] var layer_index := -1 - if Global.animation_timer.is_stopped(): #if we're not animating, store only the current canvas + if Global.animation_timer.is_stopped(): # if we're not animating, store only the current canvas canvases = [self] layer_index = current_layer_index - else: #If we're animating, store all canvases + else: # If we're animating, store all canvases canvases = Global.canvases Global.undos += 1 Global.undo_redo.create_action(action) for c in canvases: - #I'm not sure why I have to unlock it, but... - #...if I don't, it doesn't work properly + # I'm not sure why I have to unlock it, but... + # ...if I don't, it doesn't work properly c.layers[c.current_layer_index][0].unlock() var data = c.layers[c.current_layer_index][0].data c.layers[c.current_layer_index][0].lock() @@ -338,6 +342,8 @@ func handle_undo(action : String) -> void: Global.undo_redo.add_undo_property(Global, "selected_pixels", selected_pixels) Global.undo_redo.add_undo_method(Global, "undo", canvases, layer_index) + can_undo = false + func handle_redo(action : String) -> void: if Global.undos < Global.undo_redo.get_version(): return @@ -356,6 +362,8 @@ func handle_redo(action : String) -> void: Global.undo_redo.add_do_method(Global, "redo", canvases, layer_index) Global.undo_redo.commit_action() + can_undo = true + func update_texture(layer_index : int, update_frame_tex := true) -> void: layers[layer_index][1].create_from_image(layers[layer_index][0], 0) var layer_container := get_layer_container(layer_index) @@ -533,7 +541,17 @@ func draw_pixel(pos : Vector2, color : Color, current_mouse_button : String, cur brush_size = Global.left_brush_size brush_type = Global.current_left_brush_type brush_index = Global.custom_left_brush_index - custom_brush_image = Global.custom_left_brush_image + if brush_type != Global.BRUSH_TYPES.RANDOM_FILE: + custom_brush_image = Global.custom_left_brush_image + else: # Handle random brush + var brush_button = Global.file_brush_container.get_child(brush_index + 2) + var random_index = randi() % brush_button.random_brushes.size() + custom_brush_image = brush_button.random_brushes[random_index] + var custom_brush_size = custom_brush_image.get_size() + custom_brush_image.resize(custom_brush_size.x * brush_size, custom_brush_size.y * brush_size, Image.INTERPOLATE_NEAREST) + custom_brush_image = Global.blend_image_with_color(custom_brush_image, color, Global.left_interpolate_spinbox.value / 100) + custom_brush_image.lock() + horizontal_mirror = Global.left_horizontal_mirror vertical_mirror = Global.left_vertical_mirror ld = Global.left_ld @@ -542,7 +560,17 @@ func draw_pixel(pos : Vector2, color : Color, current_mouse_button : String, cur brush_size = Global.right_brush_size brush_type = Global.current_right_brush_type brush_index = Global.custom_right_brush_index - custom_brush_image = Global.custom_right_brush_image + if brush_type != Global.BRUSH_TYPES.RANDOM_FILE: + custom_brush_image = Global.custom_right_brush_image + else: # Handle random brush + var brush_button = Global.file_brush_container.get_child(brush_index + 2) + var random_index = randi() % brush_button.random_brushes.size() + custom_brush_image = brush_button.random_brushes[random_index] + var custom_brush_size = custom_brush_image.get_size() + custom_brush_image.resize(custom_brush_size.x * brush_size, custom_brush_size.y * brush_size, Image.INTERPOLATE_NEAREST) + custom_brush_image = Global.blend_image_with_color(custom_brush_image, color, Global.right_interpolate_spinbox.value / 100) + custom_brush_image.lock() + horizontal_mirror = Global.right_horizontal_mirror vertical_mirror = Global.right_vertical_mirror ld = Global.right_ld diff --git a/Scripts/Global.gd b/Scripts/Global.gd index 5defd2cd6..182b430a7 100644 --- a/Scripts/Global.gd +++ b/Scripts/Global.gd @@ -83,7 +83,7 @@ var onion_skinning_future_rate := 0 var onion_skinning_blue_red := false # Brushes -enum BRUSH_TYPES {PIXEL, CIRCLE, FILE, CUSTOM} +enum BRUSH_TYPES {PIXEL, CIRCLE, FILE, RANDOM_FILE, CUSTOM} # warning-ignore:unused_class_variable var left_brush_size := 1 # warning-ignore:unused_class_variable @@ -215,6 +215,7 @@ var palette_import_file_dialog : FileDialog var error_dialog : AcceptDialog func _ready() -> void: + randomize() # Load settings from the config file config_cache.load("user://cache.ini") @@ -434,14 +435,14 @@ func frame_changed(value : int) -> void: canvas = canvases[current_frame] canvas.visible = true canvas.generate_layer_panels() - #Make all frame buttons unpressed + # Make all frame buttons unpressed for c in canvases: var text_color := Color.white if theme_type == "Gold" || theme_type == "Light": text_color = Color.black c.frame_button.get_node("FrameButton").pressed = false c.frame_button.get_node("FrameID").add_color_override("font_color", text_color) - #Make only the current frame button pressed + # Make only the current frame button pressed canvas.frame_button.get_node("FrameButton").pressed = true canvas.frame_button.get_node("FrameID").add_color_override("font_color", Color("#3c5d75")) @@ -451,7 +452,7 @@ func create_brush_button(brush_img : Image, brush_type := BRUSH_TYPES.CUSTOM, hi var brush_button = load("res://Prefabs/BrushButton.tscn").instance() brush_button.brush_type = brush_type brush_button.custom_brush_index = custom_brushes.size() - 1 - if brush_type == BRUSH_TYPES.FILE: + if brush_type == BRUSH_TYPES.FILE || brush_type == BRUSH_TYPES.RANDOM_FILE: brush_container = file_brush_container else: brush_container = project_brush_container @@ -459,6 +460,8 @@ func create_brush_button(brush_img : Image, brush_type := BRUSH_TYPES.CUSTOM, hi brush_tex.create_from_image(brush_img, 0) brush_button.get_child(0).texture = brush_tex brush_button.hint_tooltip = hint_tooltip + if brush_type == BRUSH_TYPES.RANDOM_FILE: + brush_button.random_brushes.append(brush_img) brush_container.add_child(brush_button) func remove_brush_buttons() -> void: diff --git a/Scripts/Import.gd b/Scripts/Import.gd index c12798c66..b9dda5dbd 100644 --- a/Scripts/Import.gd +++ b/Scripts/Import.gd @@ -14,18 +14,28 @@ func import_brushes(path : String) -> void: func find_brushes(brushes_dir : Directory, path : String) -> Array: var subdirectories := [] + var found_random_brush := 0 brushes_dir.open(path) brushes_dir.list_dir_begin(true) var file := brushes_dir.get_next() while file != "": - print(file) if file.get_extension().to_upper() == "PNG": var image := Image.new() var err := image.load(path.plus_file(file)) if err == OK: - image.convert(Image.FORMAT_RGBA8) - Global.custom_brushes.append(image) - Global.create_brush_button(image, Global.BRUSH_TYPES.FILE, file.trim_suffix(".png")) + if "%" in file: + if found_random_brush == 0: + found_random_brush = Global.file_brush_container.get_child_count() + image.convert(Image.FORMAT_RGBA8) + Global.custom_brushes.append(image) + Global.create_brush_button(image, Global.BRUSH_TYPES.RANDOM_FILE, file.trim_suffix(".png")) + else: + var brush_button = Global.file_brush_container.get_child(found_random_brush) + brush_button.random_brushes.append(image) + else: + image.convert(Image.FORMAT_RGBA8) + Global.custom_brushes.append(image) + Global.create_brush_button(image, Global.BRUSH_TYPES.FILE, file.trim_suffix(".png")) elif file.get_extension() == "": # Probably a directory var subdir := "./%s" % [file] if brushes_dir.dir_exists(subdir): # If it's an actual directory