mirror of
https://github.com/tonytins/CozyPixelStudio.git
synced 2025-06-25 22:44:42 -04:00
Custom brushes, crop image, split screen, about menu & asset re-organizing
- Added support for custom brushes. When you Ctrl-C a selection, it gets added to the list of custom brushes. Each mouse button can have a different brush, and the user can choose whether their color comes from the brush itself or the selected color in the tool options. They can also be resized based on the selected brush size. - Custom brushes are also being saved on .pxo files. - You can now crop images (per frame). All layers of that frame are taken into account and are affected. - Added split screen support. The user can toggle between single screen and split screen, where a second canvas is being shown. Note that you cannot draw on the second canvas. - Added an About Pixelorama selection on the new Help menu. - Project assets are re-organized.
This commit is contained in:
parent
62b9278537
commit
4e4a526332
27 changed files with 659 additions and 150 deletions
|
@ -34,6 +34,7 @@ func _ready() -> void:
|
|||
}
|
||||
var edit_menu_items := {
|
||||
"Scale Image" : 0,
|
||||
"Crop Image" : 0,
|
||||
"Clear Selection" : 0
|
||||
#"Undo" : KEY_MASK_CTRL + KEY_Z,
|
||||
#"Redo" : KEY_MASK_SHIFT + KEY_MASK_CTRL + KEY_Z,
|
||||
|
@ -41,12 +42,15 @@ func _ready() -> void:
|
|||
var view_menu_items := {
|
||||
"Tile Mode" : KEY_MASK_CTRL + KEY_T,
|
||||
"Show Grid" : KEY_MASK_CTRL + KEY_G
|
||||
#"Undo" : KEY_MASK_CTRL + KEY_Z,
|
||||
#"Redo" : KEY_MASK_SHIFT + KEY_MASK_CTRL + KEY_Z,
|
||||
}
|
||||
var help_menu_items := {
|
||||
"About Pixelorama" : 0
|
||||
}
|
||||
var file_menu : PopupMenu = Global.file_menu.get_popup()
|
||||
var edit_menu : PopupMenu = Global.edit_menu.get_popup()
|
||||
view_menu = Global.view_menu.get_popup()
|
||||
var help_menu : PopupMenu = Global.help_menu.get_popup()
|
||||
|
||||
var i = 0
|
||||
for item in file_menu_items.keys():
|
||||
file_menu.add_item(item, i, file_menu_items[item])
|
||||
|
@ -59,9 +63,15 @@ func _ready() -> void:
|
|||
for item in view_menu_items.keys():
|
||||
view_menu.add_check_item(item, i, view_menu_items[item])
|
||||
i += 1
|
||||
i = 0
|
||||
for item in help_menu_items.keys():
|
||||
help_menu.add_item(item, i, help_menu_items[item])
|
||||
i += 1
|
||||
|
||||
file_menu.connect("id_pressed", self, "file_menu_id_pressed")
|
||||
edit_menu.connect("id_pressed", self, "edit_menu_id_pressed")
|
||||
view_menu.connect("id_pressed", self, "view_menu_id_pressed")
|
||||
help_menu.connect("id_pressed", self, "help_menu_id_pressed")
|
||||
|
||||
var root = get_tree().get_root()
|
||||
pencil_tool = Global.find_node_by_name(root, "Pencil")
|
||||
|
@ -149,7 +159,37 @@ func edit_menu_id_pressed(id : int) -> void:
|
|||
0: #Scale Image
|
||||
$ScaleImage.popup_centered()
|
||||
Global.can_draw = false
|
||||
1: #Clear selection
|
||||
1: #Crop Image
|
||||
#Use first layer as a starting rectangle
|
||||
var used_rect : Rect2 = Global.canvas.layers[0][0].get_used_rect()
|
||||
#However, if first layer is empty, loop through all layers until we find one that isn't
|
||||
var i := 0
|
||||
while(i < Global.canvas.layers.size() - 1 && Global.canvas.layers[i][0].get_used_rect() == Rect2(0, 0, 0, 0)):
|
||||
i += 1
|
||||
used_rect = Global.canvas.layers[i][0].get_used_rect()
|
||||
|
||||
#Merge all layers with content
|
||||
for j in range(Global.canvas.layers.size() - 1, i, -1):
|
||||
if Global.canvas.layers[j][0].get_used_rect() != Rect2(0, 0, 0, 0):
|
||||
used_rect = used_rect.merge(Global.canvas.layers[j][0].get_used_rect())
|
||||
|
||||
#If no layer has any content, just return
|
||||
if used_rect == Rect2(0, 0, 0, 0):
|
||||
return
|
||||
|
||||
#Loop through all the layers to crop them
|
||||
for j in range(Global.canvas.layers.size() - 1, -1, -1):
|
||||
var sprite := Image.new()
|
||||
sprite = Global.canvas.layers[j][0].get_rect(used_rect)
|
||||
Global.canvas.layers[j][0] = sprite
|
||||
Global.canvas.layers[j][0].lock()
|
||||
Global.canvas.update_texture(j)
|
||||
|
||||
var width = Global.canvas.layers[0][0].get_width()
|
||||
var height = Global.canvas.layers[0][0].get_height()
|
||||
Global.canvas.size = Vector2(width, height).floor()
|
||||
Global.canvas.camera_zoom()
|
||||
2: #Clear selection
|
||||
Global.selection_rectangle.polygon[0] = Vector2.ZERO
|
||||
Global.selection_rectangle.polygon[1] = Vector2.ZERO
|
||||
Global.selection_rectangle.polygon[2] = Vector2.ZERO
|
||||
|
@ -165,12 +205,18 @@ func view_menu_id_pressed(id : int) -> void:
|
|||
Global.draw_grid = !Global.draw_grid
|
||||
view_menu.set_item_checked(1, Global.draw_grid)
|
||||
|
||||
func help_menu_id_pressed(id : int) -> void:
|
||||
match id:
|
||||
0: #About Pixelorama
|
||||
$AboutDialog.popup_centered()
|
||||
Global.can_draw = false
|
||||
|
||||
func _on_CreateNewImage_confirmed() -> void:
|
||||
var width := float($CreateNewImage/VBoxContainer/WidthCont/WidthValue.value)
|
||||
var height := float($CreateNewImage/VBoxContainer/HeightCont/HeightValue.value)
|
||||
var fill_color : Color = $CreateNewImage/VBoxContainer/FillColor/FillColor.color
|
||||
clear_canvases()
|
||||
Global.canvas = load("res://Canvas.tscn").instance()
|
||||
Global.canvas = load("res://Prefabs/Canvas.tscn").instance()
|
||||
Global.canvas.size = Vector2(width, height).floor()
|
||||
|
||||
Global.canvas_parent.add_child(Global.canvas)
|
||||
|
@ -187,12 +233,15 @@ func _on_OpenSprite_file_selected(path) -> void:
|
|||
var file := File.new()
|
||||
var err := file.open(path, File.READ)
|
||||
if err == 0:
|
||||
var current_version : String = ProjectSettings.get_setting("application/config/Version")
|
||||
var version := file.get_line()
|
||||
if current_version != version:
|
||||
OS.alert("File is from an older version of Pixelorama, as such it might not work properly")
|
||||
var frame := 0
|
||||
var frame_line := file.get_line()
|
||||
clear_canvases()
|
||||
while frame_line == "--":
|
||||
var canvas : Canvas = load("res://Canvas.tscn").instance()
|
||||
var canvas : Canvas = load("res://Prefabs/Canvas.tscn").instance()
|
||||
Global.canvas = canvas
|
||||
var width := file.get_16()
|
||||
var height := file.get_16()
|
||||
|
@ -233,6 +282,18 @@ func _on_OpenSprite_file_selected(path) -> void:
|
|||
for color in right_palette:
|
||||
Global.right_color_picker.get_picker().add_preset(color)
|
||||
|
||||
#Load custom brushes
|
||||
var brush_line := file.get_line()
|
||||
while brush_line == "/":
|
||||
var b_width := file.get_16()
|
||||
var b_height := file.get_16()
|
||||
var buffer := file.get_buffer(b_width * b_height * 4)
|
||||
var image := Image.new()
|
||||
image.create_from_data(b_width, b_height, false, Image.FORMAT_RGBA8, buffer)
|
||||
Global.custom_brushes.append(image)
|
||||
Global.create_brush_button(image)
|
||||
brush_line = file.get_line()
|
||||
|
||||
file.close()
|
||||
|
||||
func _on_SaveSprite_file_selected(path) -> void:
|
||||
|
@ -264,6 +325,13 @@ func _on_SaveSprite_file_selected(path) -> void:
|
|||
file.store_8(right_brush_size)
|
||||
file.store_var(left_palette)
|
||||
file.store_var(right_palette)
|
||||
#Save custom brushes
|
||||
for brush in Global.custom_brushes:
|
||||
file.store_line("/")
|
||||
file.store_16(brush.get_size().x)
|
||||
file.store_16(brush.get_size().y)
|
||||
file.store_buffer(brush.get_data())
|
||||
file.store_line("END_BRUSHES")
|
||||
file.close()
|
||||
|
||||
func _on_ImportSprites_files_selected(paths) -> void:
|
||||
|
@ -279,7 +347,7 @@ func _on_ImportSprites_files_selected(paths) -> void:
|
|||
var err = image.load(path)
|
||||
if err == OK:
|
||||
opensprite_file_selected = true
|
||||
var canvas : Canvas = load("res://Canvas.tscn").instance()
|
||||
var canvas : Canvas = load("res://Prefabs/Canvas.tscn").instance()
|
||||
canvas.size = image.get_size()
|
||||
image.convert(Image.FORMAT_RGBA8)
|
||||
image.lock()
|
||||
|
@ -488,7 +556,7 @@ func _on_RightBrushSizeEdit_value_changed(value) -> void:
|
|||
Global.right_brush_size = new_size
|
||||
|
||||
func _on_AddFrame_pressed() -> void:
|
||||
var canvas = load("res://Canvas.tscn").instance()
|
||||
var canvas = load("res://Prefabs/Canvas.tscn").instance()
|
||||
canvas.size = Global.canvas.size
|
||||
canvas.frame = Global.canvases.size()
|
||||
for canvas in Global.canvases:
|
||||
|
@ -524,7 +592,7 @@ func _on_RemoveFrame_pressed() -> void:
|
|||
|
||||
|
||||
func _on_CloneFrame_pressed() -> void:
|
||||
var canvas = load("res://Canvas.tscn").instance()
|
||||
var canvas = load("res://Prefabs/Canvas.tscn").instance()
|
||||
canvas.size = Global.canvas.size
|
||||
#canvas.layers = Global.canvas.layers.duplicate(true)
|
||||
for layer in Global.canvas.layers:
|
||||
|
@ -666,4 +734,14 @@ func _on_FutureOnionSkinning_value_changed(value) -> void:
|
|||
Global.onion_skinning_future_rate = int(value)
|
||||
|
||||
func _on_BlueRedMode_toggled(button_pressed) -> void:
|
||||
Global.onion_skinning_blue_red = button_pressed
|
||||
Global.onion_skinning_blue_red = button_pressed
|
||||
|
||||
func _on_SplitScreenButton_toggled(button_pressed) -> void:
|
||||
if button_pressed:
|
||||
Global.split_screen_button.text = ">"
|
||||
Global.viewport_separator.visible = true
|
||||
Global.second_viewport.visible = true
|
||||
else:
|
||||
Global.split_screen_button.text = "<"
|
||||
Global.viewport_separator.visible = false
|
||||
Global.second_viewport.visible = false
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue