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

Layer Opacity - Change alpha of each layer

Added a slider under the layer add/remove/etc buttons that changes the currently selected layer's transparency. It gets saved in .png and .pxo files, while respecting non-opaque pixels in the image too. Which means, their alpha values aren't being overwritten.
This commit is contained in:
OverloadedOrama 2019-12-24 23:51:08 +02:00
parent aa860960e2
commit ed2e757c11
7 changed files with 77 additions and 35 deletions

View file

@ -158,12 +158,14 @@ anchor_bottom = 1.0
custom_constants/separation = 0
[node name="TopMenuContainer" type="Panel" parent="MenuAndUI"]
editor/display_folded = true
margin_right = 1152.0
margin_bottom = 28.0
rect_min_size = Vector2( 0, 28 )
custom_styles/panel = ExtResource( 3 )
[node name="MenuItems" type="HBoxContainer" parent="MenuAndUI/TopMenuContainer"]
editor/display_folded = true
margin_left = 2.0
margin_top = 4.0
margin_right = 1010.0
@ -233,7 +235,6 @@ text = "[64×64]"
align = 2
[node name="UI" type="HBoxContainer" parent="MenuAndUI"]
editor/display_folded = true
margin_top = 28.0
margin_right = 1152.0
margin_bottom = 648.0
@ -1326,7 +1327,6 @@ margin_right = 224.0
margin_bottom = 419.0
[node name="LayerVBoxContainer" type="VBoxContainer" parent="MenuAndUI/UI/LayerPanel/LayersAndMisc"]
editor/display_folded = true
margin_top = 423.0
margin_right = 224.0
margin_bottom = 604.0
@ -1417,9 +1417,16 @@ texture_normal = ExtResource( 55 )
texture_hover = ExtResource( 56 )
texture_disabled = ExtResource( 57 )
[node name="OpacitySlider" type="HSlider" parent="MenuAndUI/UI/LayerPanel/LayersAndMisc/LayerVBoxContainer"]
margin_top = 38.0
margin_right = 224.0
margin_bottom = 44.0
value = 100.0
ticks_on_borders = false
[node name="ScrollLayers" type="ScrollContainer" parent="MenuAndUI/UI/LayerPanel/LayersAndMisc/LayerVBoxContainer"]
editor/display_folded = true
margin_top = 38.0
margin_top = 50.0
margin_right = 224.0
margin_bottom = 181.0
size_flags_horizontal = 3
@ -1688,9 +1695,9 @@ anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = -92.0
margin_top = -36.0
margin_top = -27.0
margin_right = 92.0
margin_bottom = 5.0
margin_bottom = -4.0
custom_constants/vseparation = 4
custom_constants/hseparation = 4
columns = 2
@ -1871,6 +1878,7 @@ visible = false
[connection signal="pressed" from="MenuAndUI/UI/LayerPanel/LayersAndMisc/LayerVBoxContainer/CenterLayerButtons/LayerButtons/MovwDownLayer" to="." method="change_layer_order" binds= [ -1 ]]
[connection signal="pressed" from="MenuAndUI/UI/LayerPanel/LayersAndMisc/LayerVBoxContainer/CenterLayerButtons/LayerButtons/CloneLayer" to="." method="add_layer" binds= [ false ]]
[connection signal="pressed" from="MenuAndUI/UI/LayerPanel/LayersAndMisc/LayerVBoxContainer/CenterLayerButtons/LayerButtons/MergeDownLayer" to="." method="_on_MergeLayer_pressed"]
[connection signal="value_changed" from="MenuAndUI/UI/LayerPanel/LayersAndMisc/LayerVBoxContainer/OpacitySlider" to="." method="_on_OpacitySlider_value_changed"]
[connection signal="toggled" from="SplitScreenButton" to="." method="_on_SplitScreenButton_toggled"]
[connection signal="confirmed" from="CreateNewImage" to="." method="_on_CreateNewImage_confirmed"]
[connection signal="popup_hide" from="CreateNewImage" to="." method="_can_draw_true"]

View file

@ -36,8 +36,8 @@ func _ready() -> void:
var tex := ImageTexture.new()
tex.create_from_image(sprite, 0)
#Store [Image, ImageTexture, Layer Name, Visibity boolean]
layers.append([sprite, tex, "Layer 0", true])
#Store [Image, ImageTexture, Layer Name, Visibity boolean, Opacity]
layers.append([sprite, tex, "Layer 0", true, 1])
generate_layer_panels()
@ -407,18 +407,19 @@ func _draw() -> void:
#Draw current frame layers
for texture in layers:
var modulate_color := Color(1, 1, 1, texture[4])
if texture[3]: #if it's visible
draw_texture(texture[1], location)
draw_texture(texture[1], location, modulate_color)
if Global.tile_mode:
draw_texture(texture[1], Vector2(location.x, location.y + size.y)) #Down
draw_texture(texture[1], Vector2(location.x - size.x, location.y + size.y)) #Down Left
draw_texture(texture[1], Vector2(location.x - size.x, location.y)) #Left
draw_texture(texture[1], location - size) #Up left
draw_texture(texture[1], Vector2(location.x, location.y - size.y)) #Up
draw_texture(texture[1], Vector2(location.x + size.x, location.y - size.y)) #Up right
draw_texture(texture[1], Vector2(location.x + size.x, location.y)) #Right
draw_texture(texture[1], location + size) #Down right
draw_texture(texture[1], Vector2(location.x, location.y + size.y), modulate_color) #Down
draw_texture(texture[1], Vector2(location.x - size.x, location.y + size.y), modulate_color) #Down Left
draw_texture(texture[1], Vector2(location.x - size.x, location.y), modulate_color) #Left
draw_texture(texture[1], location - size, modulate_color) #Up left
draw_texture(texture[1], Vector2(location.x, location.y - size.y), modulate_color) #Up
draw_texture(texture[1], Vector2(location.x + size.x, location.y - size.y), modulate_color) #Up right
draw_texture(texture[1], Vector2(location.x + size.x, location.y), modulate_color) #Right
draw_texture(texture[1], location + size, modulate_color) #Down right
#Idea taken from flurick (on GitHub)
if Global.draw_grid:
@ -476,7 +477,7 @@ func generate_layer_panels() -> void:
layer_container.get_child(1).get_child(0).texture = layers[i][1]
layer_container.get_child(1).get_child(1).text = layers[i][2]
layer_container.get_child(1).get_child(2).text = layers[i][2]
layers[i][3] = true #set visible
layers[i][3] = true # Set visible
Global.vbox_layer_container.add_child(layer_container)
func pencil_and_eraser(mouse_pos : Vector2, color : Color, current_mouse_button : String, current_action := "None") -> void:

View file

@ -46,7 +46,7 @@ func _on_PopupMenu_id_pressed(ID : int) -> void:
sprite.lock()
var tex := ImageTexture.new()
tex.create_from_image(sprite, 0)
new_canvas.layers.append([sprite, tex, layer[2], layer[3]])
new_canvas.layers.append([sprite, tex, layer[2], layer[3], layer[4]])
Global.undos += 1
Global.undo_redo.create_action("Add Frame")

View file

@ -189,6 +189,7 @@ var remove_layer_button : BaseButton
var move_up_layer_button : BaseButton
var move_down_layer_button : BaseButton
var merge_down_layer_button : BaseButton
var layer_opacity_slider : HSlider
var add_palette_button : TextureButton
var remove_palette_button : TextureButton
@ -285,12 +286,15 @@ func _ready() -> void:
play_backwards = find_node_by_name(root, "PlayBackwards")
frame_container = find_node_by_name(root, "FrameContainer")
var layer_buttons = find_node_by_name(root, "LayerButtons")
var layer_stuff_container = find_node_by_name(root, "LayerVBoxContainer")
var layer_buttons = find_node_by_name(layer_stuff_container, "LayerButtons")
remove_layer_button = find_node_by_name(layer_buttons, "RemoveLayer")
move_up_layer_button = find_node_by_name(layer_buttons, "MoveUpLayer")
move_down_layer_button = find_node_by_name(layer_buttons, "MovwDownLayer")
merge_down_layer_button = find_node_by_name(layer_buttons, "MergeDownLayer")
vbox_layer_container = find_node_by_name(root, "VBoxLayerContainer")
layer_opacity_slider = find_node_by_name(layer_stuff_container, "OpacitySlider")
vbox_layer_container = find_node_by_name(layer_stuff_container, "VBoxLayerContainer")
add_palette_button = find_node_by_name(root, "AddPalette")
remove_palette_button = find_node_by_name(root, "RemovePalette")

View file

@ -43,9 +43,10 @@ func changed_selection() -> void:
child.label.visible = true
child.line_edit.visible = false
child.line_edit.editable = false
if Global.canvas.current_layer_index == child.i:
if Global.canvas.current_layer_index == child.i: # The selected layer
child.currently_selected = true
child.pressed = true
Global.layer_opacity_slider.value = Global.canvas.layers[child.i][4] * 100
if Global.canvas.current_layer_index < Global.canvas.layers.size() - 1:
Global.move_up_layer_button.disabled = false

View file

@ -387,8 +387,10 @@ func _on_OpenSprite_file_selected(path : String) -> void:
return
var current_version : String = ProjectSettings.get_setting("application/config/Version")
var current_version_number = float(current_version.substr(1, 3)) # Example, "0.6"
var version := file.get_line()
if current_version != version:
var version_number = float(version.substr(1, 3)) # Example, "0.6"
if current_version_number < 0.5:
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()
@ -403,12 +405,15 @@ func _on_OpenSprite_file_selected(path : String) -> void:
while layer_line == "-": #Load layers
var buffer := file.get_buffer(width * height * 4)
var layer_name := file.get_line()
var layer_transparency := 1.0
if version_number > 0.5:
layer_transparency = file.get_float()
var image := Image.new()
image.create_from_data(width, height, false, Image.FORMAT_RGBA8, buffer)
image.lock()
var tex := ImageTexture.new()
tex.create_from_image(image, 0)
canvas.layers.append([image, tex, layer_name, true])
canvas.layers.append([image, tex, layer_name, true, layer_transparency])
layer_line = file.get_line()
var guide_line := file.get_line() #"guideline" no pun intended
@ -475,14 +480,15 @@ func _on_SaveSprite_file_selected(path) -> void:
var err := file.open(path, File.WRITE)
if err == 0:
file.store_line(ProjectSettings.get_setting("application/config/Version"))
for canvas in Global.canvases: #Store frames
for canvas in Global.canvases: # Store frames
file.store_line("--")
file.store_16(canvas.size.x)
file.store_16(canvas.size.y)
for layer in canvas.layers: #Store layers
for layer in canvas.layers: # Store layers
file.store_line("-")
file.store_buffer(layer[0].get_data())
file.store_line(layer[2])
file.store_line(layer[2]) # Layer name
file.store_float(layer[4]) # Layer transparency
file.store_line("END_LAYERS")
for child in canvas.get_children(): #Store guides
@ -544,8 +550,8 @@ func _on_ImportSprites_files_selected(paths) -> void:
image.lock()
var tex := ImageTexture.new()
tex.create_from_image(image, 0)
#Store [Image, ImageTexture, Layer Name, Visibity boolean]
canvas.layers.append([image, tex, "Layer 0", true])
#Store [Image, ImageTexture, Layer Name, Visibity boolean, Opacity]
canvas.layers.append([image, tex, "Layer 0", true, 1])
canvas.frame = i
Global.canvases.append(canvas)
Global.canvas_parent.add_child(canvas)
@ -606,7 +612,16 @@ func save_sprite(canvas : Canvas, path : String) -> void:
whole_image.create(canvas.size.x, canvas.size.y, false, Image.FORMAT_RGBA8)
whole_image.lock()
for layer in canvas.layers:
canvas.blend_rect(whole_image, layer[0], Rect2(canvas.position, canvas.size), Vector2.ZERO)
var img : Image = layer[0]
img.lock()
if layer[4] < 1: # If we have layer transparency
for xx in img.get_size().x:
for yy in img.get_size().y:
var pixel_color := img.get_pixel(xx, yy)
var alpha : float = pixel_color.a * layer[4]
img.set_pixel(xx, yy, Color(pixel_color.r, pixel_color.g, pixel_color.b, alpha))
canvas.blend_rect(whole_image, img, Rect2(canvas.position, canvas.size), Vector2.ZERO)
layer[0].lock()
var err = whole_image.save_png(path)
if err != OK:
@ -635,8 +650,18 @@ func save_spritesheet() -> void:
var dst := Vector2.ZERO
for canvas in Global.canvases:
for layer in canvas.layers:
canvas.blend_rect(whole_image, layer[0], Rect2(canvas.position, canvas.size), dst)
var img : Image = layer[0]
img.lock()
if layer[4] < 1: # If we have layer transparency
for xx in img.get_size().x:
for yy in img.get_size().y:
var pixel_color := img.get_pixel(xx, yy)
var alpha : float = pixel_color.a * layer[4]
img.set_pixel(xx, yy, Color(pixel_color.r, pixel_color.g, pixel_color.b, alpha))
canvas.blend_rect(whole_image, img, Rect2(canvas.position, canvas.size), dst)
layer[0].lock()
if export_vertical_spritesheet.pressed:
dst += Vector2(0, canvas.size.y)
else:
@ -691,7 +716,7 @@ func _on_OutlineDialog_confirmed() -> void:
new_image.set_pixelv(new_pos, outline_color)
new_pos = pos + Vector2.RIGHT * i
if new_pos.x < Global.canvas.size.x - 1:
if new_pos.x < Global.canvas.size.x:
var new_pixel = image.get_pixelv(new_pos)
if new_pixel.a == 0:
new_image.set_pixelv(new_pos, outline_color)
@ -703,7 +728,7 @@ func _on_OutlineDialog_confirmed() -> void:
new_image.set_pixelv(new_pos, outline_color)
new_pos = pos + Vector2.DOWN * i
if new_pos.y < Global.canvas.size.y - 1:
if new_pos.y < Global.canvas.size.y:
var new_pixel = image.get_pixelv(new_pos)
if new_pixel.a == 0:
new_image.set_pixelv(new_pos, outline_color)
@ -828,7 +853,7 @@ func add_layer(is_new := true) -> void:
new_layer_tex.create_from_image(new_layer, 0)
var new_layers := Global.canvas.layers.duplicate()
new_layers.append([new_layer, new_layer_tex, null, true])
new_layers.append([new_layer, new_layer_tex, null, true, 1])
Global.undos += 1
Global.undo_redo.create_action("Add Layer")
Global.undo_redo.add_do_property(Global.canvas, "layers", new_layers)
@ -1103,6 +1128,9 @@ func _on_RightHorizontalMirroring_toggled(button_pressed) -> void:
func _on_RightVerticalMirroring_toggled(button_pressed) -> void:
Global.right_vertical_mirror = button_pressed
func _on_OpacitySlider_value_changed(value) -> void:
Global.canvas.layers[Global.canvas.current_layer_index][4] = value / 100
func _on_QuitDialog_confirmed() -> void:
# Darken the UI to denote that the application is currently exiting
# (it won't respond to user input in this state).
@ -1110,7 +1138,7 @@ func _on_QuitDialog_confirmed() -> void:
get_tree().quit()
func _on_AddPalette_pressed():
func _on_AddPalette_pressed() -> void:
Global.add_palette_button.get_child(0).popup(Rect2(Global.add_palette_button.rect_global_position, Vector2.ONE))
func _on_RemovePalette_pressed() -> void:

View file

@ -51,7 +51,7 @@ boot_splash/image="res://splash.png"
boot_splash/bg_color=Color( 0.145098, 0.145098, 0.164706, 1 )
config/icon="res://icon.png"
config/description="A free & open-source 2D sprite editor"
config/Version="v0.5"
config/Version="v0.6"
[autoload]