1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-01-18 09:09:47 +00:00

v0.4 - Undo/Redo, mirrored drawing, lighten/darken tool and more!

In this commit:
- Added notification labels that appear when the user does an action (for undoing, redoing and saving)
- Fixed symmetry with custom brushes.
- In Main.gd, current_save_path and current_export_path get cleared when the user creates a new drawing or opens one.

v0.4 of Pixelorama is out! Check https://functionoverload590613498.wordpress.com/2019/11/13/pixelorama-v0-4-is-out/ for the full changelog.
This commit is contained in:
OverloadedOrama 2019-11-13 15:45:55 +02:00
parent 17d117a0b1
commit d66c501b5c
9 changed files with 79 additions and 18 deletions

View file

@ -23,6 +23,7 @@ size_flags_horizontal = 3
custom_constants/separation = 0
[node name="ToolPanel" type="Panel" parent="UI"]
editor/display_folded = true
margin_right = 230.0
margin_bottom = 600.0
rect_min_size = Vector2( 230, 0 )
@ -36,6 +37,7 @@ size_flags_horizontal = 3
size_flags_vertical = 3
[node name="MenusAndTools" type="VBoxContainer" parent="UI/ToolPanel/Tools"]
editor/display_folded = true
margin_right = 230.0
margin_bottom = 224.0
size_flags_vertical = 3
@ -167,6 +169,7 @@ margin_right = 230.0
margin_bottom = 232.0
[node name="ToolOptions" type="HBoxContainer" parent="UI/ToolPanel/Tools"]
editor/display_folded = true
margin_top = 236.0
margin_right = 230.0
margin_bottom = 460.0
@ -174,7 +177,6 @@ size_flags_vertical = 3
custom_constants/separation = 0
[node name="LeftToolOptions" type="VBoxContainer" parent="UI/ToolPanel/Tools/ToolOptions"]
editor/display_folded = true
margin_right = 113.0
margin_bottom = 224.0
size_flags_horizontal = 3
@ -260,12 +262,14 @@ text = "C"
margin_top = 166.0
margin_right = 113.0
margin_bottom = 190.0
hint_tooltip = "Enable horizontal mirrored drawing for the left tool"
text = "Horiz. Mirror"
[node name="LeftVerticalMirroring" type="CheckBox" parent="UI/ToolPanel/Tools/ToolOptions/LeftToolOptions"]
margin_top = 194.0
margin_right = 113.0
margin_bottom = 218.0
hint_tooltip = "Enable vertical mirrored drawing for the left tool"
text = "Vert. Mirror"
[node name="VSeparator" type="VSeparator" parent="UI/ToolPanel/Tools/ToolOptions"]
@ -274,7 +278,6 @@ margin_right = 117.0
margin_bottom = 224.0
[node name="RightToolOptions" type="VBoxContainer" parent="UI/ToolPanel/Tools/ToolOptions"]
editor/display_folded = true
margin_left = 117.0
margin_right = 230.0
margin_bottom = 224.0
@ -360,12 +363,14 @@ text = "C"
margin_top = 166.0
margin_right = 113.0
margin_bottom = 190.0
hint_tooltip = "Enable horizontal mirrored drawing for the right tool"
text = "Horiz. Mirror"
[node name="RightVerticalMirroring" type="CheckBox" parent="UI/ToolPanel/Tools/ToolOptions/RightToolOptions"]
margin_top = 194.0
margin_right = 113.0
margin_bottom = 218.0
hint_tooltip = "Enable vertical mirrored drawing for the right tool"
text = "Vert. Mirror"
[node name="HSeparator2" type="HSeparator" parent="UI/ToolPanel/Tools"]

View file

@ -0,0 +1,17 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://Scripts/NotificationLabel.gd" type="Script" id=1]
[node name="NotificationLabel" type="Label"]
margin_right = 116.0
margin_bottom = 14.0
custom_colors/font_color_shadow = Color( 0, 0, 0, 1 )
text = "Undo: Notification"
script = ExtResource( 1 )
[node name="Tween" type="Tween" parent="."]
[node name="Timer" type="Timer" parent="."]
one_shot = true
autostart = true
[connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"]

View file

@ -1,28 +1,30 @@
# Pixelorama - your free and open-source sprite editor!
A free & open-source 2D sprite editor, made with Godot Engine, using GDScript!
Your free & open-source 2D sprite editor, made in the Godot Engine, using GDScript!
[![Pixelorama's horrible UI](https://functionoverload590613498.files.wordpress.com/2019/10/screenshot_265.png)](https://www.youtube.com/watch?v=L8o8QKB8lPs)
[![Pixelorama's horrible UI](https://functionoverload590613498.files.wordpress.com/2019/11/screenshot_268.png)](https://www.youtube.com/watch?v=h3OJROgAR-A)
Current features as of version v0.3:
Current features as of version v0.4:
- Choosing between 4 tools pencil, eraser, fill bucket and rectangle select and mapping them to both of your left and right mouse buttons. Thats, pretty wild, huh?
- Choosing between 6 tools pencil, eraser, fill bucket, paint same color, lighten/darken and rectangle select and mapping them to both of your left and right mouse buttons.
- Different colors and brush sizes for each of the mouse buttons.
- Custom brush support.
- Support of two types of custom brushes: "From files" and "per project" brushes. Custom brushes from files get loaded from the "Brushes" folder that comes with Pixelorama, and per project brushes get saved with the rectangle select tool.
- Creating a new canvas with a size of your choosing.
- Are you an animator? Then you've come to the right place! Pixelorama has its own Animation Timeline just for you!
- Importing PNG and JPEG images, and edit them inside Pixelorama. If you import multiple files, they will be added as individual animation frames.
- Import images and edit them inside Pixelorama. If you import multiple files, they will be added as individual animation frames.
- Export your gorgeous art as PNG files.
- Save snd open your projects as Pixelorama's custom file format, .pxo
- Undo/Redo support!
- Horizontal & vertical mirrored drawing!
- Tile Mode for pattern creation!
- Split screen mode to see your masterpiece twice!
- Create straight lines for pencil and eraser by holding down Shift while you draw.
- The middle mouse wheel isnt forgotten, you can use it to pan around the canvas and by scrolling up and down, you can zoom in and out!
- Keyboard shortcuts! Im pretty sure this is a lifesaver for most of you.
- Just like onions, Pixelorama has a multiple layer system! You can add, remove, move up and down, clone and merge as many layers as you like!
- Scale and crop your images!
- Just like onions, Pixelorama has a multiple layer system! You can add, remove, move up and down, clone and merge as many layers as you like! You can also rename them!
- Scale, crop and flip your images!
Make sure to read my blog post on Function(Overload) for more information! https://functionoverload590613498.wordpress.com/2019/08/18/i-made-my-own-sprite-editor-in-godot/
Download it as a stand-alone on itch.io: https://orama-interactive.itch.io/pixelorama
And if you like, consider helping me by sponsoring this project!
If you like, consider helping me by sponsoring this project! It would enable me to focus more on Pixelorama, and make more projects in the future!

View file

@ -542,8 +542,12 @@ func draw_pixel(pos : Vector2, color : Color, current_mouse_button : String, cur
src_rect.size.y = min(src_rect.size.y, selection_rect.size.y)
#Handle mirroring
var mirror_x := east_limit + west_limit - pos.x - (pos.x - dst.x) - 1
var mirror_y := south_limit + north_limit - pos.y - (pos.y - dst.y) - 1
var mirror_x := east_limit + west_limit - pos.x - (pos.x - dst.x)
var mirror_y := south_limit + north_limit - pos.y - (pos.y - dst.y)
if int(pos_rect_clipped.size.x) % 2 != 0:
mirror_x -= 1
if int(pos_rect_clipped.size.y) % 2 != 0:
mirror_y -= 1
if color.a > 0: #If it's the pencil
layers[current_layer_index][0].blend_rect(custom_brush_image, src_rect, dst)

View file

@ -20,6 +20,7 @@ var draw_grid := false
var canvases := []
# warning-ignore:unused_class_variable
var hidden_canvases := []
var control : Node
var canvas : Canvas
var canvas_parent : Node
var second_viewport : ViewportContainer
@ -109,6 +110,7 @@ var custom_right_brush_texture := ImageTexture.new()
func _ready() -> void:
undo_redo = UndoRedo.new()
var root = get_tree().get_root()
control = find_node_by_name(root, "Control")
canvas = find_node_by_name(root, "Canvas")
canvases.append(canvas)
canvas_parent = canvas.get_parent()
@ -165,6 +167,12 @@ func find_node_by_name(root, node_name) -> Node:
return found
return null
func notification_label(text : String) -> void:
var notification : Label = load("res://Prefabs/NotificationLabel.tscn").instance()
notification.text = text
notification.rect_position = Vector2(240, OS.window_size.y - 150)
get_tree().get_root().add_child(notification)
func undo(_canvases : Array, layer_index : int = -1) -> void:
undos -= 1
var action_name := undo_redo.get_current_action_name()
@ -202,7 +210,8 @@ func undo(_canvases : Array, layer_index : int = -1) -> void:
frame_container.move_child(_canvases[0].frame_button, current_frame)
canvas_parent.move_child(_canvases[0], current_frame)
print("Undo: ", action_name)
notification_label("Undo: %s" % action_name)
func redo(_canvases : Array, layer_index : int = -1) -> void:
if undos < undo_redo.get_version(): #If we did undo and then redo
@ -241,7 +250,8 @@ func redo(_canvases : Array, layer_index : int = -1) -> void:
frame_container.move_child(_canvases[0].frame_button, current_frame)
canvas_parent.move_child(_canvases[0], current_frame)
print("Redo: ", action_name)
if control.redone:
notification_label("Redo: %s" % action_name)
func frame_changed(value : int) -> void:
current_frame = value
@ -302,7 +312,7 @@ func undo_custom_brush(_brush_button : Button = null) -> void:
hbox_container.add_child(_brush_button)
hbox_container.move_child(_brush_button, _brush_button.custom_brush_index - brushes_from_files)
_brush_button.get_node("DeleteButton").visible = false
print("Undo: ", action_name)
notification_label("Undo: %s" % action_name)
func redo_custom_brush(_brush_button : Button = null) -> void:
if undos < undo_redo.get_version(): #If we did undo and then redo
@ -311,7 +321,8 @@ func redo_custom_brush(_brush_button : Button = null) -> void:
var hbox_container := find_node_by_name(get_tree().get_root(), "CustomBrushHBoxContainer")
if action_name == "Delete Custom Brush":
hbox_container.remove_child(_brush_button)
print("Redo: ", action_name)
if control.redone:
notification_label("Redo: %s" % action_name)
func update_left_custom_brush() -> void:
if custom_left_brush_index > -1:

View file

@ -9,6 +9,7 @@ var import_as_new_frame : CheckBox
var export_all_frames : CheckBox
var export_as_single_file : CheckBox
var export_vertical_spritesheet : CheckBox
var redone := false
var fps := 1.0
var animation_loop := 0 #0 is no loop, 1 is cycle loop, 2 is ping-pong loop
var animation_forward := true
@ -168,7 +169,9 @@ func edit_menu_id_pressed(id : int) -> void:
0: #Undo
Global.undo_redo.undo()
1: #Redo
redone = true
Global.undo_redo.redo()
redone = false
2: #Scale Image
$ScaleImage.popup_centered()
Global.can_draw = false
@ -382,6 +385,7 @@ func _on_SaveSprite_file_selected(path) -> void:
file.store_buffer(brush.get_data())
file.store_line("END_BRUSHES")
file.close()
Global.notification_label("File saved")
func _on_ImportSprites_files_selected(paths) -> void:
if !import_as_new_frame.pressed: #If we're not adding a new frame, delete the previous
@ -442,6 +446,8 @@ func clear_canvases() -> void:
if child is Canvas:
child.queue_free()
Global.canvases.clear()
current_save_path = ""
current_export_path = ""
func _on_ExportSprites_file_selected(path : String) -> void:
current_export_path = path
@ -461,6 +467,7 @@ func export_project() -> void:
save_spritesheet()
else:
save_sprite(Global.canvas, current_export_path)
Global.notification_label("File exported")
func save_sprite(canvas : Canvas, path : String) -> void:
var whole_image := Image.new()

View file

@ -0,0 +1,15 @@
extends Label
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
var tween := $Tween
tween.interpolate_property(self, "rect_position", rect_position, Vector2(rect_position.x, rect_position.y - 100), 1, Tween.TRANS_LINEAR, Tween.EASE_OUT)
tween.interpolate_property(self, "modulate", modulate, Color(modulate.r, modulate.g, modulate.b, 0), 1, Tween.TRANS_LINEAR, Tween.EASE_OUT)
tween.start()
func _on_Timer_timeout() -> void:
queue_free()

BIN
icon.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View file

@ -29,7 +29,7 @@ _global_script_class_icons={
config/name="Pixelorama"
run/main_scene="res://Main.tscn"
config/icon="res://icon.png"
config/Version="v0.3"
config/Version="v0.4"
[autoload]