mirror of
https://github.com/tonytins/CozyPixelStudio.git
synced 2025-06-25 12:04:43 -04:00
Merge branch 'master' into line-tool
This commit is contained in:
commit
f97818d134
18 changed files with 429 additions and 226 deletions
|
@ -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 cursor_inside_canvas := false
|
||||
var previous_action := "None"
|
||||
var mouse_inside_canvas := false #used for undo
|
||||
|
@ -250,7 +251,7 @@ func _process(delta : float) -> void:
|
|||
line_2d = Line2D.new()
|
||||
line_2d.width = 0.5
|
||||
line_2d.default_color = Color.darkgray
|
||||
line_2d.add_point(previous_mouse_pos)
|
||||
line_2d.add_point(previous_mouse_pos_for_lines)
|
||||
line_2d.add_point(mouse_pos)
|
||||
add_child(line_2d)
|
||||
is_making_line = true
|
||||
|
@ -258,10 +259,9 @@ func _process(delta : float) -> void:
|
|||
is_making_line = false
|
||||
if is_instance_valid(line_2d):
|
||||
line_2d.queue_free()
|
||||
|
||||
if is_making_line:
|
||||
line_2d.set_point_position(1, mouse_pos)
|
||||
|
||||
|
||||
|
||||
if is_making_selection != "None": #If we're making a selection
|
||||
if Input.is_action_just_released(is_making_selection): #Finish selection when button is released
|
||||
|
@ -289,6 +289,9 @@ func _process(delta : float) -> void:
|
|||
handle_redo("Rectangle Select")
|
||||
|
||||
previous_action = current_action
|
||||
previous_mouse_pos = current_pixel
|
||||
previous_mouse_pos.x = clamp(previous_mouse_pos.x, location.x, location.x + size.x)
|
||||
previous_mouse_pos.y = clamp(previous_mouse_pos.y, location.y, location.y + size.y)
|
||||
if sprite_changed_this_frame:
|
||||
update_texture(current_layer_index, (Input.is_action_just_released("left_mouse") || Input.is_action_just_released("right_mouse")))
|
||||
|
||||
|
@ -468,16 +471,16 @@ func generate_layer_panels() -> void:
|
|||
|
||||
func pencil_and_eraser(mouse_pos : Vector2, color : Color, current_mouse_button : String, current_action := "None") -> void:
|
||||
if is_making_line:
|
||||
fill_gaps(mouse_pos, color, current_mouse_button, current_action)
|
||||
fill_gaps(mouse_pos, previous_mouse_pos_for_lines, color, current_mouse_button, current_action)
|
||||
else:
|
||||
if point_in_rectangle(mouse_pos, location, location + size):
|
||||
mouse_inside_canvas = true
|
||||
#Draw
|
||||
draw_pixel(mouse_pos, color, current_mouse_button, current_action)
|
||||
fill_gaps(mouse_pos, color, current_mouse_button, current_action) #Fill the gaps
|
||||
fill_gaps(mouse_pos, previous_mouse_pos, color, current_mouse_button, current_action) #Fill the gaps
|
||||
#If mouse is not inside bounds but it used to be, fill the gaps
|
||||
elif point_in_rectangle(previous_mouse_pos, location, location + size):
|
||||
fill_gaps(mouse_pos, color, current_mouse_button, current_action)
|
||||
fill_gaps(mouse_pos, previous_mouse_pos, color, current_mouse_button, current_action)
|
||||
|
||||
func draw_pixel(pos : Vector2, color : Color, current_mouse_button : String, current_action := "None") -> void:
|
||||
if Global.can_draw && Global.has_focus && Global.current_frame == frame:
|
||||
|
@ -622,7 +625,7 @@ func draw_pixel(pos : Vector2, color : Color, current_mouse_button : String, cur
|
|||
mirror_x -= 1
|
||||
if int(pos_rect_clipped.size.y) % 2 != 0:
|
||||
mirror_y -= 1
|
||||
# Use custom blend function cause of godot's issue #31124
|
||||
# Use custom blend function cause of godot's issue #31124
|
||||
if color.a > 0: #If it's the pencil
|
||||
blend_rect(layers[current_layer_index][0], custom_brush_image, src_rect, dst)
|
||||
if horizontal_mirror:
|
||||
|
@ -649,17 +652,17 @@ func draw_pixel(pos : Vector2, color : Color, current_mouse_button : String, cur
|
|||
|
||||
layers[current_layer_index][0].lock()
|
||||
sprite_changed_this_frame = true
|
||||
|
||||
previous_mouse_pos = current_pixel
|
||||
previous_mouse_pos.x = clamp(previous_mouse_pos.x, location.x, location.x + size.x)
|
||||
previous_mouse_pos.y = clamp(previous_mouse_pos.y, location.y, location.y + size.y)
|
||||
|
||||
previous_mouse_pos_for_lines = current_pixel
|
||||
previous_mouse_pos_for_lines.x = clamp(previous_mouse_pos_for_lines.x, location.x, location.x + size.x)
|
||||
previous_mouse_pos_for_lines.y = clamp(previous_mouse_pos_for_lines.y, location.y, location.y + size.y)
|
||||
if is_making_line:
|
||||
line_2d.set_point_position(0, previous_mouse_pos)
|
||||
line_2d.set_point_position(0, previous_mouse_pos_for_lines)
|
||||
|
||||
#Bresenham's Algorithm
|
||||
#Thanks to https://godotengine.org/qa/35276/tile-based-line-drawing-algorithm-efficiency
|
||||
func fill_gaps(mouse_pos : Vector2, color : Color, current_mouse_button : String, current_action := "None") -> void:
|
||||
var previous_mouse_pos_floored = previous_mouse_pos.floor()
|
||||
func fill_gaps(mouse_pos : Vector2, prev_mouse_pos : Vector2, color : Color, current_mouse_button : String, current_action := "None") -> void:
|
||||
var previous_mouse_pos_floored = prev_mouse_pos.floor()
|
||||
var mouse_pos_floored = mouse_pos.floor()
|
||||
mouse_pos_floored.x = clamp(mouse_pos_floored.x, location.x - 1, location.x + size.x)
|
||||
mouse_pos_floored.y = clamp(mouse_pos_floored.y, location.y - 1, location.y + size.y)
|
||||
|
|
|
@ -103,6 +103,10 @@ var custom_left_brush_texture := ImageTexture.new()
|
|||
# warning-ignore:unused_class_variable
|
||||
var custom_right_brush_texture := ImageTexture.new()
|
||||
|
||||
#Palettes
|
||||
# warning-ignore:unused_class_variable
|
||||
var palettes := {}
|
||||
|
||||
#Nodes
|
||||
var control : Node
|
||||
var left_cursor : Sprite
|
||||
|
@ -176,6 +180,12 @@ var move_up_layer_button : BaseButton
|
|||
var move_down_layer_button : BaseButton
|
||||
var merge_down_layer_button : BaseButton
|
||||
|
||||
var add_palette_button : TextureButton
|
||||
var remove_palette_button : TextureButton
|
||||
var palette_option_button : OptionButton
|
||||
var edit_palette_button : BaseButton
|
||||
var palette_container : GridContainer
|
||||
|
||||
func _ready() -> void:
|
||||
undo_redo = UndoRedo.new()
|
||||
image_clipboard = Image.new()
|
||||
|
@ -258,6 +268,12 @@ func _ready() -> void:
|
|||
move_down_layer_button = find_node_by_name(root, "MoveDownLayer")
|
||||
merge_down_layer_button = find_node_by_name(root, "MergeDownLayer")
|
||||
|
||||
add_palette_button = find_node_by_name(root, "AddPalette")
|
||||
remove_palette_button = find_node_by_name(root, "RemovePalette")
|
||||
palette_option_button = find_node_by_name(root, "PaletteOptionButton")
|
||||
edit_palette_button = find_node_by_name(root, "EditPalette")
|
||||
palette_container = find_node_by_name(root, "PaletteContainer")
|
||||
|
||||
#Thanks to https://godotengine.org/qa/17524/how-to-find-an-instanced-scene-by-its-name
|
||||
func find_node_by_name(root, node_name) -> Node:
|
||||
if root.get_name() == node_name:
|
||||
|
|
|
@ -13,7 +13,7 @@ func _ready() -> void:
|
|||
changed_selection()
|
||||
|
||||
func _input(event : InputEvent):
|
||||
if event.is_action_released("ui_accept") && line_edit.visible:
|
||||
if event.is_action_released("ui_accept") && line_edit.visible && event.scancode != KEY_SPACE:
|
||||
label.visible = true
|
||||
line_edit.visible = false
|
||||
line_edit.editable = false
|
||||
|
|
|
@ -30,7 +30,7 @@ func _ready() -> void:
|
|||
loaded_locales = TranslationServer.get_loaded_locales()
|
||||
else:
|
||||
# Hardcoded list of locales
|
||||
loaded_locales = ["el", "en"]
|
||||
loaded_locales = ["de", "el", "en", "fr"]
|
||||
|
||||
# Make sure locales are always sorted, in the same order
|
||||
loaded_locales.sort()
|
||||
|
@ -1034,3 +1034,8 @@ func _exit_tree() -> void:
|
|||
config_cache.set_value("window", "position", OS.window_position)
|
||||
config_cache.set_value("window", "size", OS.window_size)
|
||||
config_cache.save("user://cache.ini")
|
||||
|
||||
func _on_PaletteOptionButton_item_selected(ID) -> void:
|
||||
var palette_name = Global.palette_option_button.get_item_metadata(ID)
|
||||
Global.palette_container.on_palette_select(palette_name)
|
||||
pass
|
||||
|
|
|
@ -2,6 +2,8 @@ extends GridContainer
|
|||
|
||||
var palette_button = preload("res://Prefabs/PaletteButton.tscn");
|
||||
|
||||
var current_palette = "Default"
|
||||
|
||||
var default_palette = [
|
||||
Color("#FF000000"),
|
||||
Color("#FF222034"),
|
||||
|
@ -39,18 +41,122 @@ var default_palette = [
|
|||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
#Global.palettes["Default"] = default_palette
|
||||
|
||||
_load_palettes()
|
||||
|
||||
on_palette_select(current_palette)
|
||||
pass # Replace with function body.
|
||||
|
||||
func _clear_swatches() -> void:
|
||||
for child in get_children():
|
||||
if child is BaseButton:
|
||||
child.disconnect("pressed", self, "on_color_select")
|
||||
child.queue_free()
|
||||
pass
|
||||
|
||||
func on_palette_select(palette_name : String) -> void:
|
||||
_clear_swatches()
|
||||
if Global.palettes.has(palette_name):
|
||||
_display_palette(Global.palettes[palette_name])
|
||||
else:
|
||||
_display_palette(Global.palettes["Default"])
|
||||
pass
|
||||
|
||||
func _display_palette(palette : Array) -> void:
|
||||
var index := 0
|
||||
for color in default_palette:
|
||||
for color_data in palette:
|
||||
var color = Color(color_data.data)
|
||||
var new_button = palette_button.instance()
|
||||
new_button.get_child(0).modulate = color
|
||||
new_button.connect("pressed", self, "_on_color_select", [index])
|
||||
new_button.hint_tooltip = color_data.data.to_upper() + " " + color_data.name
|
||||
new_button.connect("pressed", self, "on_color_select", [index])
|
||||
add_child(new_button)
|
||||
index += 1
|
||||
pass
|
||||
|
||||
func _on_color_select(index : int) -> void:
|
||||
func on_color_select(index : int) -> void:
|
||||
var color = Color(Global.palettes[current_palette][index].data)
|
||||
if Input.is_action_just_released("left_mouse"):
|
||||
Global.left_color_picker.color = default_palette[index]
|
||||
Global.left_color_picker.color = color
|
||||
Global.update_left_custom_brush()
|
||||
elif Input.is_action_just_released("right_mouse"):
|
||||
Global.right_color_picker.color = default_palette[index]
|
||||
Global.right_color_picker.color = color
|
||||
Global.update_right_custom_brush()
|
||||
pass
|
||||
|
||||
func _load_palettes() -> void:
|
||||
var files := []
|
||||
|
||||
var dir := Directory.new()
|
||||
|
||||
if not dir.dir_exists("user://palettes"):
|
||||
dir.make_dir("user://palettes");
|
||||
dir.copy("res://Assets/Graphics/Palette/default_palette.json","user://palettes/default_palette.json");
|
||||
dir.copy("res://Assets/Graphics/Palette/bubblegum16.json","user://palettes/bubblegum16.json");
|
||||
|
||||
dir.open("user://palettes")
|
||||
dir.list_dir_begin()
|
||||
|
||||
while true:
|
||||
var file_name = dir.get_next()
|
||||
if file_name == "":
|
||||
break
|
||||
elif not file_name.begins_with(".") && file_name.to_lower().ends_with("json"):
|
||||
files.append(file_name)
|
||||
|
||||
dir.list_dir_end()
|
||||
|
||||
for file_name in files:
|
||||
var result : String = load_palette("user://palettes/" + file_name)
|
||||
if result:
|
||||
Global.palette_option_button.add_item(result)
|
||||
var index := Global.palette_option_button.get_item_count() - 1
|
||||
Global.palette_option_button.set_item_metadata(index, result)
|
||||
if result == "Default":
|
||||
Global.palette_option_button.select(index)
|
||||
|
||||
for item in Global.palette_option_button.items:
|
||||
print(item)
|
||||
pass
|
||||
|
||||
func load_palette(path : String) -> String:
|
||||
var file := File.new()
|
||||
file.open(path, File.READ)
|
||||
|
||||
var text = file.get_as_text()
|
||||
var result_json = JSON.parse(text)
|
||||
var result = {}
|
||||
|
||||
var palette_name = null
|
||||
|
||||
if result_json.error != OK: # If parse has errors
|
||||
print("Error: ", result_json.error)
|
||||
print("Error Line: ", result_json.error_line)
|
||||
print("Error String: ", result_json.error_string)
|
||||
else: # If parse OK
|
||||
var data = result_json.result
|
||||
if data.has("name"):
|
||||
palette_name = data.name
|
||||
Global.palettes[data.name] = data.colors
|
||||
|
||||
file.close()
|
||||
|
||||
return palette_name
|
||||
|
||||
func _save_palette(palette : Array, name : String, path : String):
|
||||
var file := File.new()
|
||||
file.open(path, File.WRITE)
|
||||
|
||||
var data := {}
|
||||
data.name = name
|
||||
data.colors = palette
|
||||
|
||||
file.store_string(JSON.print(data))
|
||||
file.close()
|
||||
|
||||
pass
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
#func _process(delta):
|
||||
# pass
|
||||
|
|
|
@ -61,7 +61,7 @@ func _process(delta : float) -> void:
|
|||
Global.canvas.update_texture(Global.canvas.current_layer_index)
|
||||
tex.create_from_image(img, 0)
|
||||
update()
|
||||
|
||||
|
||||
# Makes line2d invisible
|
||||
if is_instance_valid(Global.canvas.line_2d): # Checks to see if line_2d object still exists
|
||||
Global.canvas.line_2d.default_color = Color(0, 0, 0, 0)
|
||||
|
@ -102,7 +102,7 @@ func _process(delta : float) -> void:
|
|||
Global.selected_pixels.append(Vector2(xx, yy))
|
||||
|
||||
Global.canvas.handle_redo("Rectangle Select") #Redo
|
||||
|
||||
|
||||
# Makes line2d visible
|
||||
if is_instance_valid(Global.canvas.line_2d): # Checks to see if line_2d object still exists
|
||||
Global.canvas.line_2d.default_color = Color.darkgray
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue