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.
BIN
Brushes/Icons/%icon_1.png
Normal file
After Width: | Height: | Size: 199 B |
BIN
Brushes/Icons/%icon_2.png
Normal file
After Width: | Height: | Size: 197 B |
BIN
Brushes/Icons/%icon_3.png
Normal file
After Width: | Height: | Size: 198 B |
BIN
Brushes/Icons/%icon_4.png
Normal file
After Width: | Height: | Size: 198 B |
BIN
Brushes/Lines/%random_line_1.png
Normal file
After Width: | Height: | Size: 110 B |
BIN
Brushes/Lines/%random_line_2.png
Normal file
After Width: | Height: | Size: 119 B |
BIN
Brushes/Lines/%random_line_3.png
Normal file
After Width: | Height: | Size: 158 B |
BIN
Brushes/Lines/%random_line_4.png
Normal file
After Width: | Height: | Size: 126 B |
BIN
Brushes/Lines/%random_line_5.png
Normal file
After Width: | Height: | Size: 141 B |
|
@ -2,6 +2,8 @@ extends BaseButton
|
||||||
|
|
||||||
export var brush_type = Global.BRUSH_TYPES.PIXEL
|
export var brush_type = Global.BRUSH_TYPES.PIXEL
|
||||||
export var custom_brush_index := -2
|
export var custom_brush_index := -2
|
||||||
|
# warning-ignore:unused_class_variable
|
||||||
|
var random_brushes := []
|
||||||
|
|
||||||
func _on_BrushButton_pressed() -> void:
|
func _on_BrushButton_pressed() -> void:
|
||||||
# Change left brush
|
# Change left brush
|
||||||
|
|
|
@ -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 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 := Vector2.ZERO
|
||||||
var previous_mouse_pos_for_lines := Vector2.ZERO
|
var previous_mouse_pos_for_lines := Vector2.ZERO
|
||||||
|
var can_undo := true
|
||||||
var cursor_inside_canvas := false
|
var cursor_inside_canvas := false
|
||||||
var previous_action := "None"
|
var previous_action := "None"
|
||||||
var mouse_inside_canvas := false #used for undo
|
var mouse_inside_canvas := false #used for undo
|
||||||
|
@ -80,8 +81,9 @@ func camera_zoom() -> void:
|
||||||
Global.camera_preview.offset = size / 2
|
Global.camera_preview.offset = size / 2
|
||||||
|
|
||||||
# warning-ignore:unused_argument
|
# warning-ignore:unused_argument
|
||||||
func _process(delta : float) -> void:
|
func _input(event) -> void:
|
||||||
sprite_changed_this_frame = false
|
sprite_changed_this_frame = false
|
||||||
|
if Global.current_frame == frame:
|
||||||
update()
|
update()
|
||||||
current_pixel = get_local_mouse_position() - location
|
current_pixel = get_local_mouse_position() - location
|
||||||
var mouse_pos := current_pixel
|
var mouse_pos := current_pixel
|
||||||
|
@ -90,8 +92,8 @@ func _process(delta : float) -> void:
|
||||||
var mouse_in_canvas := point_in_rectangle(mouse_pos, location, location + size)
|
var mouse_in_canvas := point_in_rectangle(mouse_pos, location, location + size)
|
||||||
var current_mouse_button := "None"
|
var current_mouse_button := "None"
|
||||||
var current_action := "None"
|
var current_action := "None"
|
||||||
var fill_area := 0 #For the bucket tool
|
var fill_area := 0 # For the bucket tool
|
||||||
#For the LightenDarken tool
|
# For the LightenDarken tool
|
||||||
var ld := 0
|
var ld := 0
|
||||||
var ld_amount := 0.1
|
var ld_amount := 0.1
|
||||||
if Input.is_mouse_button_pressed(BUTTON_LEFT):
|
if Input.is_mouse_button_pressed(BUTTON_LEFT):
|
||||||
|
@ -126,13 +128,13 @@ func _process(delta : float) -> void:
|
||||||
Global.right_cursor.visible = false
|
Global.right_cursor.visible = false
|
||||||
Input.set_custom_mouse_cursor(null)
|
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 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"))
|
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,...
|
# 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, ...
|
#. .. it means that the cursor was outside the canvas. Then, ...
|
||||||
#simulate "just pressed" logic the moment the cursor gets inside the canvas
|
# 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 Input.is_action_pressed("left_mouse") || Input.is_action_pressed("right_mouse"):
|
||||||
if mouse_in_canvas && Global.undos < Global.undo_redo.get_version():
|
if mouse_in_canvas && Global.undos < Global.undo_redo.get_version():
|
||||||
mouse_pressed = true
|
mouse_pressed = true
|
||||||
|
@ -151,7 +153,7 @@ func _process(delta : float) -> void:
|
||||||
if previous_action != "None" && previous_action != "RectSelect" && current_action != "ColorPicker":
|
if previous_action != "None" && previous_action != "RectSelect" && current_action != "ColorPicker":
|
||||||
handle_redo("Draw")
|
handle_redo("Draw")
|
||||||
|
|
||||||
match current_action: #Handle current tool
|
match current_action: # Handle current tool
|
||||||
"Pencil":
|
"Pencil":
|
||||||
var current_color : Color
|
var current_color : Color
|
||||||
if current_mouse_button == "left_mouse":
|
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")))
|
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:
|
func handle_undo(action : String) -> void:
|
||||||
|
if !can_undo:
|
||||||
|
return
|
||||||
var canvases := []
|
var canvases := []
|
||||||
var layer_index := -1
|
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]
|
canvases = [self]
|
||||||
layer_index = current_layer_index
|
layer_index = current_layer_index
|
||||||
else: #If we're animating, store all canvases
|
else: # If we're animating, store all canvases
|
||||||
canvases = Global.canvases
|
canvases = Global.canvases
|
||||||
Global.undos += 1
|
Global.undos += 1
|
||||||
Global.undo_redo.create_action(action)
|
Global.undo_redo.create_action(action)
|
||||||
for c in canvases:
|
for c in canvases:
|
||||||
#I'm not sure why I have to unlock it, but...
|
# I'm not sure why I have to unlock it, but...
|
||||||
#...if I don't, it doesn't work properly
|
# ...if I don't, it doesn't work properly
|
||||||
c.layers[c.current_layer_index][0].unlock()
|
c.layers[c.current_layer_index][0].unlock()
|
||||||
var data = c.layers[c.current_layer_index][0].data
|
var data = c.layers[c.current_layer_index][0].data
|
||||||
c.layers[c.current_layer_index][0].lock()
|
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_property(Global, "selected_pixels", selected_pixels)
|
||||||
Global.undo_redo.add_undo_method(Global, "undo", canvases, layer_index)
|
Global.undo_redo.add_undo_method(Global, "undo", canvases, layer_index)
|
||||||
|
|
||||||
|
can_undo = false
|
||||||
|
|
||||||
func handle_redo(action : String) -> void:
|
func handle_redo(action : String) -> void:
|
||||||
if Global.undos < Global.undo_redo.get_version():
|
if Global.undos < Global.undo_redo.get_version():
|
||||||
return
|
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.add_do_method(Global, "redo", canvases, layer_index)
|
||||||
Global.undo_redo.commit_action()
|
Global.undo_redo.commit_action()
|
||||||
|
|
||||||
|
can_undo = true
|
||||||
|
|
||||||
func update_texture(layer_index : int, update_frame_tex := true) -> void:
|
func update_texture(layer_index : int, update_frame_tex := true) -> void:
|
||||||
layers[layer_index][1].create_from_image(layers[layer_index][0], 0)
|
layers[layer_index][1].create_from_image(layers[layer_index][0], 0)
|
||||||
var layer_container := get_layer_container(layer_index)
|
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_size = Global.left_brush_size
|
||||||
brush_type = Global.current_left_brush_type
|
brush_type = Global.current_left_brush_type
|
||||||
brush_index = Global.custom_left_brush_index
|
brush_index = Global.custom_left_brush_index
|
||||||
|
if brush_type != Global.BRUSH_TYPES.RANDOM_FILE:
|
||||||
custom_brush_image = Global.custom_left_brush_image
|
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
|
horizontal_mirror = Global.left_horizontal_mirror
|
||||||
vertical_mirror = Global.left_vertical_mirror
|
vertical_mirror = Global.left_vertical_mirror
|
||||||
ld = Global.left_ld
|
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_size = Global.right_brush_size
|
||||||
brush_type = Global.current_right_brush_type
|
brush_type = Global.current_right_brush_type
|
||||||
brush_index = Global.custom_right_brush_index
|
brush_index = Global.custom_right_brush_index
|
||||||
|
if brush_type != Global.BRUSH_TYPES.RANDOM_FILE:
|
||||||
custom_brush_image = Global.custom_right_brush_image
|
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
|
horizontal_mirror = Global.right_horizontal_mirror
|
||||||
vertical_mirror = Global.right_vertical_mirror
|
vertical_mirror = Global.right_vertical_mirror
|
||||||
ld = Global.right_ld
|
ld = Global.right_ld
|
||||||
|
|
|
@ -83,7 +83,7 @@ var onion_skinning_future_rate := 0
|
||||||
var onion_skinning_blue_red := false
|
var onion_skinning_blue_red := false
|
||||||
|
|
||||||
# Brushes
|
# Brushes
|
||||||
enum BRUSH_TYPES {PIXEL, CIRCLE, FILE, CUSTOM}
|
enum BRUSH_TYPES {PIXEL, CIRCLE, FILE, RANDOM_FILE, CUSTOM}
|
||||||
# warning-ignore:unused_class_variable
|
# warning-ignore:unused_class_variable
|
||||||
var left_brush_size := 1
|
var left_brush_size := 1
|
||||||
# warning-ignore:unused_class_variable
|
# warning-ignore:unused_class_variable
|
||||||
|
@ -215,6 +215,7 @@ var palette_import_file_dialog : FileDialog
|
||||||
var error_dialog : AcceptDialog
|
var error_dialog : AcceptDialog
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
|
randomize()
|
||||||
# Load settings from the config file
|
# Load settings from the config file
|
||||||
config_cache.load("user://cache.ini")
|
config_cache.load("user://cache.ini")
|
||||||
|
|
||||||
|
@ -434,14 +435,14 @@ func frame_changed(value : int) -> void:
|
||||||
canvas = canvases[current_frame]
|
canvas = canvases[current_frame]
|
||||||
canvas.visible = true
|
canvas.visible = true
|
||||||
canvas.generate_layer_panels()
|
canvas.generate_layer_panels()
|
||||||
#Make all frame buttons unpressed
|
# Make all frame buttons unpressed
|
||||||
for c in canvases:
|
for c in canvases:
|
||||||
var text_color := Color.white
|
var text_color := Color.white
|
||||||
if theme_type == "Gold" || theme_type == "Light":
|
if theme_type == "Gold" || theme_type == "Light":
|
||||||
text_color = Color.black
|
text_color = Color.black
|
||||||
c.frame_button.get_node("FrameButton").pressed = false
|
c.frame_button.get_node("FrameButton").pressed = false
|
||||||
c.frame_button.get_node("FrameID").add_color_override("font_color", text_color)
|
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("FrameButton").pressed = true
|
||||||
canvas.frame_button.get_node("FrameID").add_color_override("font_color", Color("#3c5d75"))
|
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()
|
var brush_button = load("res://Prefabs/BrushButton.tscn").instance()
|
||||||
brush_button.brush_type = brush_type
|
brush_button.brush_type = brush_type
|
||||||
brush_button.custom_brush_index = custom_brushes.size() - 1
|
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
|
brush_container = file_brush_container
|
||||||
else:
|
else:
|
||||||
brush_container = project_brush_container
|
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_tex.create_from_image(brush_img, 0)
|
||||||
brush_button.get_child(0).texture = brush_tex
|
brush_button.get_child(0).texture = brush_tex
|
||||||
brush_button.hint_tooltip = hint_tooltip
|
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)
|
brush_container.add_child(brush_button)
|
||||||
|
|
||||||
func remove_brush_buttons() -> void:
|
func remove_brush_buttons() -> void:
|
||||||
|
|
|
@ -14,15 +14,25 @@ func import_brushes(path : String) -> void:
|
||||||
|
|
||||||
func find_brushes(brushes_dir : Directory, path : String) -> Array:
|
func find_brushes(brushes_dir : Directory, path : String) -> Array:
|
||||||
var subdirectories := []
|
var subdirectories := []
|
||||||
|
var found_random_brush := 0
|
||||||
brushes_dir.open(path)
|
brushes_dir.open(path)
|
||||||
brushes_dir.list_dir_begin(true)
|
brushes_dir.list_dir_begin(true)
|
||||||
var file := brushes_dir.get_next()
|
var file := brushes_dir.get_next()
|
||||||
while file != "":
|
while file != "":
|
||||||
print(file)
|
|
||||||
if file.get_extension().to_upper() == "PNG":
|
if file.get_extension().to_upper() == "PNG":
|
||||||
var image := Image.new()
|
var image := Image.new()
|
||||||
var err := image.load(path.plus_file(file))
|
var err := image.load(path.plus_file(file))
|
||||||
if err == OK:
|
if err == OK:
|
||||||
|
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)
|
image.convert(Image.FORMAT_RGBA8)
|
||||||
Global.custom_brushes.append(image)
|
Global.custom_brushes.append(image)
|
||||||
Global.create_brush_button(image, Global.BRUSH_TYPES.FILE, file.trim_suffix(".png"))
|
Global.create_brush_button(image, Global.BRUSH_TYPES.FILE, file.trim_suffix(".png"))
|
||||||
|
|