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

Created a new Cel class, to handle cel information

Like the Layer class, it is used in place of Canvas.layers nested array mess. It hasn't been tested thoroughly yet, so there may be crashes.
This commit is contained in:
OverloadedOrama 2020-06-01 18:50:31 +03:00
parent f246ed1a7a
commit df0032c515
15 changed files with 108 additions and 110 deletions

View file

@ -14,6 +14,11 @@ _global_script_classes=[ {
"language": "GDScript",
"path": "res://src/Canvas.gd"
}, {
"base": "Reference",
"class": "Cel",
"language": "GDScript",
"path": "res://src/Cel.gd"
}, {
"base": "Line2D",
"class": "Guide",
"language": "GDScript",
@ -41,6 +46,7 @@ _global_script_classes=[ {
} ]
_global_script_class_icons={
"Canvas": "",
"Cel": "",
"Guide": "",
"Layer": "",
"LayerButton": "",

View file

@ -499,7 +499,7 @@ func canvases_changed(value : Array) -> void:
var cel_button = load("res://src/UI/Timeline/CelButton.tscn").instance()
cel_button.frame = j
cel_button.layer = i
cel_button.get_child(0).texture = Global.canvases[j].layers[i][1]
cel_button.get_child(0).texture = Global.canvases[j].layers[i].image_texture
layers[i].frame_container.add_child(cel_button)
@ -566,7 +566,7 @@ func layers_changed(value : Array) -> void:
var cel_button = load("res://src/UI/Timeline/CelButton.tscn").instance()
cel_button.frame = j
cel_button.layer = i
cel_button.get_child(0).texture = Global.canvases[j].layers[i][1]
cel_button.get_child(0).texture = Global.canvases[j].layers[i].image_texture
layers[i].frame_container.add_child(cel_button)
@ -621,8 +621,8 @@ func frame_changed(value : int) -> void:
func layer_changed(value : int) -> void:
current_layer = value
layer_opacity_slider.value = canvas.layers[current_layer][2] * 100
layer_opacity_spinbox.value = canvas.layers[current_layer][2] * 100
layer_opacity_slider.value = canvas.layers[current_layer].opacity * 100
layer_opacity_spinbox.value = canvas.layers[current_layer].opacity * 100
for container in layers_container.get_children():
container.pressed = false

View file

@ -87,9 +87,7 @@ func open_pxo_file(path : String, untitled_backup : bool = false) -> void:
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_transparency])
canvas.layers.append(Cel.new(image, layer_transparency))
if file_major_version >= 0 and file_minor_version >= 7:
if frame in linked_cels[layer_i]:
Global.layers[layer_i].linked_cels.append(canvas)
@ -201,8 +199,8 @@ func save_pxo_file(path : String, autosave : bool) -> void:
file.store_16(canvas.size.y)
for layer in canvas.layers: # Store canvas layers
file.store_line("-")
file.store_buffer(layer[0].get_data())
file.store_float(layer[2]) # Layer transparency
file.store_buffer(layer.image.get_data())
file.store_float(layer.opacity)
file.store_line("END_LAYERS")
# Store guides

View file

@ -47,17 +47,13 @@ func _ready() -> void:
sprite.fill(fill_color)
sprite.lock()
var tex := ImageTexture.new()
tex.create_from_image(sprite, 0)
# Store [Image, ImageTexture, Opacity]
layers.append([sprite, tex, 1])
layers.append(Cel.new(sprite, 1.0))
if self in l.linked_cels:
# If the linked button is pressed, set as the Image & ImageTexture
# to be the same as the first linked cel
layers[layer_i][0] = l.linked_cels[0].layers[layer_i][0]
layers[layer_i][1] = l.linked_cels[0].layers[layer_i][1]
layers[layer_i].image = l.linked_cels[0].layers[layer_i].image
layers[layer_i].image_texture = l.linked_cels[0].layers[layer_i].image_texture
layer_i += 1
@ -79,19 +75,19 @@ func _draw() -> void:
# Draw current frame layers
for i in range(layers.size()):
var modulate_color := Color(1, 1, 1, layers[i][2])
var modulate_color := Color(1, 1, 1, layers[i].opacity)
if Global.layers[i].visible: # if it's visible
draw_texture(layers[i][1], location, modulate_color)
draw_texture(layers[i].image_texture, location, modulate_color)
if Global.tile_mode:
draw_texture(layers[i][1], Vector2(location.x, location.y + size.y), modulate_color) # Down
draw_texture(layers[i][1], Vector2(location.x - size.x, location.y + size.y), modulate_color) # Down Left
draw_texture(layers[i][1], Vector2(location.x - size.x, location.y), modulate_color) # Left
draw_texture(layers[i][1], location - size, modulate_color) # Up left
draw_texture(layers[i][1], Vector2(location.x, location.y - size.y), modulate_color) # Up
draw_texture(layers[i][1], Vector2(location.x + size.x, location.y - size.y), modulate_color) # Up right
draw_texture(layers[i][1], Vector2(location.x + size.x, location.y), modulate_color) # Right
draw_texture(layers[i][1], location + size, modulate_color) # Down right
draw_texture(layers[i].image_texture, Vector2(location.x, location.y + size.y), modulate_color) # Down
draw_texture(layers[i].image_texture, Vector2(location.x - size.x, location.y + size.y), modulate_color) # Down Left
draw_texture(layers[i].image_texture, Vector2(location.x - size.x, location.y), modulate_color) # Left
draw_texture(layers[i].image_texture, location - size, modulate_color) # Up left
draw_texture(layers[i].image_texture, Vector2(location.x, location.y - size.y), modulate_color) # Up
draw_texture(layers[i].image_texture, Vector2(location.x + size.x, location.y - size.y), modulate_color) # Up right
draw_texture(layers[i].image_texture, Vector2(location.x + size.x, location.y), modulate_color) # Right
draw_texture(layers[i].image_texture, location + size, modulate_color) # Down right
if Global.draw_grid:
draw_grid(Global.grid_type)
@ -295,7 +291,7 @@ func camera_zoom() -> void:
func handle_tools(current_mouse_button : int, current_action : int, mouse_pos : Vector2, can_handle : bool) -> void:
var sprite : Image = layers[Global.current_layer][0]
var sprite : Image = layers[Global.current_layer].image
var mouse_pos_floored := mouse_pos.floor()
var mouse_pos_ceiled := mouse_pos.ceil()
@ -444,10 +440,10 @@ func handle_undo(action : String) -> void:
for c in canvases:
# I'm not sure why I have to unlock it, but...
# ...if I don't, it doesn't work properly
c.layers[Global.current_layer][0].unlock()
var data = c.layers[Global.current_layer][0].data
c.layers[Global.current_layer][0].lock()
Global.undo_redo.add_undo_property(c.layers[Global.current_layer][0], "data", data)
c.layers[Global.current_layer].image.unlock()
var data = c.layers[Global.current_layer].image.data
c.layers[Global.current_layer].image.lock()
Global.undo_redo.add_undo_property(c.layers[Global.current_layer].image, "data", data)
if action == "Rectangle Select":
var selected_pixels = Global.selected_pixels.duplicate()
Global.undo_redo.add_undo_property(Global.selection_rectangle, "polygon", Global.selection_rectangle.polygon)
@ -470,7 +466,7 @@ func handle_redo(action : String) -> void:
else:
canvases = Global.canvases
for c in canvases:
Global.undo_redo.add_do_property(c.layers[Global.current_layer][0], "data", c.layers[Global.current_layer][0].data)
Global.undo_redo.add_do_property(c.layers[Global.current_layer].image, "data", c.layers[Global.current_layer].image.data)
if action == "Rectangle Select":
Global.undo_redo.add_do_property(Global.selection_rectangle, "polygon", Global.selection_rectangle.polygon)
Global.undo_redo.add_do_property(Global, "selected_pixels", Global.selected_pixels)
@ -479,11 +475,11 @@ func handle_redo(action : String) -> void:
func update_texture(layer_index : int) -> void:
layers[layer_index][1].create_from_image(layers[layer_index][0], 0)
layers[layer_index].image_texture.create_from_image(layers[layer_index].image, 0)
var frame_texture_rect : TextureRect
frame_texture_rect = Global.find_node_by_name(Global.layers[layer_index].frame_container.get_child(frame), "CelTexture")
frame_texture_rect.texture = layers[layer_index][1]
frame_texture_rect.texture = layers[layer_index].image_texture
func onion_skinning() -> void:
@ -500,7 +496,7 @@ func onion_skinning() -> void:
for layer in Global.canvases[Global.current_frame - i].layers:
if Global.layers[layer_i].visible:
color.a = 0.6 / i
draw_texture(layer[1], location, color)
draw_texture(layer.image_texture, location, color)
layer_i += 1
# Future
@ -516,7 +512,7 @@ func onion_skinning() -> void:
for layer in Global.canvases[Global.current_frame + i].layers:
if Global.layers[layer_i].visible:
color.a = 0.6 / i
draw_texture(layer[1], location, color)
draw_texture(layer.image_texture, location, color)
layer_i += 1

19
src/Cel.gd Normal file
View file

@ -0,0 +1,19 @@
class_name Cel
extends Reference
# A class for cel properties
var image : Image setget image_changed
var image_texture : ImageTexture
var opacity : float
func _init(_image := Image.new(), _opacity := 1.0) -> void:
self.image = _image
opacity = _opacity
func image_changed(value : Image) -> void:
image = value
image_texture = ImageTexture.new()
image_texture.create_from_image(image, 0)

View file

@ -1,5 +1,6 @@
class_name Layer
extends Reference
# A class for layer properties
var name := ""
@ -7,12 +8,13 @@ var visible := true
var locked := false
var frame_container : HBoxContainer
var new_cels_linked := false
var linked_cels := []
var linked_cels := [] # Array of Canvases
func _init(_name := tr("Layer") + " 0", _visible := true, _locked := false, _frame_container := HBoxContainer.new(), _new_cels_linked := false, _linked_cels := []) -> void:
self.name = _name
self.visible = _visible
self.locked = _locked
self.frame_container = _frame_container
self.new_cels_linked = _new_cels_linked
self.linked_cels = _linked_cels
name = _name
visible = _visible
locked = _locked
frame_container = _frame_container
new_cels_linked = _new_cels_linked
linked_cels = _linked_cels

View file

@ -400,7 +400,7 @@ func show_scale_image_popup() -> void:
func crop_image() -> void:
# Use first cel as a starting rectangle
var used_rect : Rect2 = Global.canvases[0].layers[0][0].get_used_rect()
var used_rect : Rect2 = Global.canvases[0].layers[0].image.get_used_rect()
for c in Global.canvases:
# However, if first cel is empty, loop through all cels until we find one that isn't
@ -409,12 +409,12 @@ func crop_image() -> void:
break
else:
if layer[0].get_used_rect() != Rect2(0, 0, 0, 0):
used_rect = layer[0].get_used_rect()
used_rect = layer.image.get_used_rect()
# Merge all layers with content
for layer in c.layers:
if layer[0].get_used_rect() != Rect2(0, 0, 0, 0):
used_rect = used_rect.merge(layer[0].get_used_rect())
if layer.image.get_used_rect() != Rect2(0, 0, 0, 0):
used_rect = used_rect.merge(layer.image.get_used_rect())
# If no layer has any content, just return
if used_rect == Rect2(0, 0, 0, 0):
@ -428,9 +428,9 @@ func crop_image() -> void:
Global.undo_redo.add_do_property(c, "size", Vector2(width, height).floor())
# Loop through all the layers to crop them
for j in range(Global.canvas.layers.size() - 1, -1, -1):
var sprite : Image = c.layers[j][0].get_rect(used_rect)
Global.undo_redo.add_do_property(c.layers[j][0], "data", sprite.data)
Global.undo_redo.add_undo_property(c.layers[j][0], "data", c.layers[j][0].data)
var sprite : Image = c.layers[j].image.get_rect(used_rect)
Global.undo_redo.add_do_property(c.layers[j].image, "data", sprite.data)
Global.undo_redo.add_undo_property(c.layers[j].image, "data", c.layers[j].image.data)
Global.undo_redo.add_undo_property(c, "size", c.size)
Global.undo_redo.add_undo_method(Global, "undo", Global.canvases)
@ -441,30 +441,30 @@ func crop_image() -> void:
func flip_image_horizontal() -> void:
var canvas : Canvas = Global.canvas
canvas.handle_undo("Draw")
canvas.layers[Global.current_layer][0].unlock()
canvas.layers[Global.current_layer][0].flip_x()
canvas.layers[Global.current_layer][0].lock()
canvas.layers[Global.current_layer].image.unlock()
canvas.layers[Global.current_layer].image.flip_x()
canvas.layers[Global.current_layer].image.lock()
canvas.handle_redo("Draw")
func flip_image_vertical() -> void:
var canvas : Canvas = Global.canvas
canvas.handle_undo("Draw")
canvas.layers[Global.current_layer][0].unlock()
canvas.layers[Global.current_layer][0].flip_y()
canvas.layers[Global.current_layer][0].lock()
canvas.layers[Global.current_layer].image.unlock()
canvas.layers[Global.current_layer].image.flip_y()
canvas.layers[Global.current_layer].image.lock()
canvas.handle_redo("Draw")
func show_rotate_image_popup() -> void:
var image : Image = Global.canvas.layers[Global.current_layer][0]
var image : Image = Global.canvas.layers[Global.current_layer].image
$RotateImage.set_sprite(image)
$RotateImage.popup_centered()
Global.dialog_open(true)
func invert_image_colors() -> void:
var image : Image = Global.canvas.layers[Global.current_layer][0]
var image : Image = Global.canvas.layers[Global.current_layer].image
Global.canvas.handle_undo("Draw")
for xx in image.get_size().x:
for yy in image.get_size().y:
@ -476,7 +476,7 @@ func invert_image_colors() -> void:
func desaturate_image() -> void:
var image : Image = Global.canvas.layers[Global.current_layer][0]
var image : Image = Global.canvas.layers[Global.current_layer].image
Global.canvas.handle_undo("Draw")
for xx in image.get_size().x:
for yy in image.get_size().y:

View file

@ -27,7 +27,7 @@ func _process(_delta : float) -> void:
var start_pos := polygon[0]
var end_pos := polygon[2]
var current_layer_index : int = Global.current_layer
var layer : Image = Global.canvas.layers[current_layer_index][0]
var layer : Image = Global.canvas.layers[current_layer_index].image
if end_pos == start_pos:
visible = false

View file

@ -87,8 +87,8 @@ func _on_CreateNewImage_confirmed() -> void:
Global.layers = Global.layers # To trigger Global.layers_changed()
Global.project_has_changed = false
if fill_color.a > 0:
Global.canvas.layers[0][0].fill(fill_color)
Global.canvas.layers[0][0].lock()
Global.canvas.layers[0].image.fill(fill_color)
Global.canvas.layers[0].image.lock()
Global.canvas.update_texture(0)

View file

@ -367,13 +367,13 @@ func blend_layers(image: Image, canvas: Canvas, origin: Vector2 = Vector2(0, 0))
for layer in canvas.layers:
if Global.layers[layer_i].visible:
var layer_image := Image.new()
layer_image.copy_from(layer[0])
layer_image.copy_from(layer.image)
layer_image.lock()
if layer[2] < 1: # If we have layer transparency
if layer.opacity < 1: # If we have layer transparency
for xx in layer_image.get_size().x:
for yy in layer_image.get_size().y:
var pixel_color := layer_image.get_pixel(xx, yy)
var alpha : float = pixel_color.a * layer[2]
var alpha : float = pixel_color.a * layer.opacity
layer_image.set_pixel(xx, yy, Color(pixel_color.r, pixel_color.g, pixel_color.b, alpha))
DrawingAlgos.blend_rect(image, layer_image, Rect2(canvas.position, canvas.size), origin)
layer_i += 1

View file

@ -23,7 +23,7 @@ func _ready() -> void:
func _on_HSVDialog_about_to_show() -> void:
current_layer = Global.canvas.layers[Global.current_layer][0]
current_layer = Global.canvas.layers[Global.current_layer].image
preview_image.copy_from(current_layer)
update_preview()

View file

@ -64,22 +64,14 @@ func _on_ImportSprites_files_selected(paths : PoolStringArray) -> void:
canvas.size = image.get_size()
image.convert(Image.FORMAT_RGBA8)
image.lock()
var tex := ImageTexture.new()
tex.create_from_image(image, 0)
# Store [Image, ImageTexture, Opacity]
canvas.layers.append([image, tex, 1])
canvas.layers.append(Cel.new(image, 1))
for _i in range(1, Global.layers.size()):
var empty_sprite := Image.new()
empty_sprite.create(canvas.size.x, canvas.size.y, false, Image.FORMAT_RGBA8)
empty_sprite.fill(Color(0, 0, 0, 0))
empty_sprite.lock()
var empty_tex := ImageTexture.new()
empty_tex.create_from_image(empty_sprite, 0)
# Store [Image, ImageTexture, Opacity]
canvas.layers.append([empty_sprite, empty_tex, 1])
canvas.layers.append(Cel.new(empty_sprite, 1))
canvas.frame = i
Global.canvases.append(canvas)
@ -119,21 +111,14 @@ func _on_ImportSprites_files_selected(paths : PoolStringArray) -> void:
canvas.size = cropped_image.get_size()
cropped_image.convert(Image.FORMAT_RGBA8)
cropped_image.lock()
var tex := ImageTexture.new()
tex.create_from_image(cropped_image, 0)
# Store [Image, ImageTexture, Opacity]
canvas.layers.append([cropped_image, tex, 1])
canvas.layers.append(Cel.new(cropped_image, 1))
for _i in range(1, Global.layers.size()):
var empty_sprite := Image.new()
empty_sprite.create(canvas.size.x, canvas.size.y, false, Image.FORMAT_RGBA8)
empty_sprite.fill(Color(0, 0, 0, 0))
empty_sprite.lock()
var empty_tex := ImageTexture.new()
empty_tex.create_from_image(empty_sprite, 0)
# Store [Image, ImageTexture, Opacity]
canvas.layers.append([empty_sprite, empty_tex, 1])
canvas.layers.append(Cel.new(empty_sprite, 1))
canvas.frame = i
Global.canvases.append(canvas)

View file

@ -10,7 +10,7 @@ func _on_OutlineDialog_confirmed() -> void:
var diagonal : bool = $OptionsContainer/DiagonalCheckBox.pressed
var inside_image : bool = $OptionsContainer/InsideImageCheckBox.pressed
var image : Image = Global.canvas.layers[Global.current_layer][0]
var image : Image = Global.canvas.layers[Global.current_layer].image
if image.is_invisible():
return
var new_image := Image.new()

View file

@ -12,10 +12,10 @@ func _on_ScaleImage_confirmed() -> void:
Global.undo_redo.add_do_property(c, "size", Vector2(width, height).floor())
for i in range(c.layers.size() - 1, -1, -1):
var sprite := Image.new()
sprite.copy_from(c.layers[i][0])
sprite.copy_from(c.layers[i].image)
sprite.resize(width, height, interpolation)
Global.undo_redo.add_do_property(c.layers[i][0], "data", sprite.data)
Global.undo_redo.add_undo_property(c.layers[i][0], "data", c.layers[i][0].data)
Global.undo_redo.add_do_property(c.layers[i].image, "data", sprite.data)
Global.undo_redo.add_undo_property(c.layers[i].image, "data", c.layers[i].image.data)
Global.undo_redo.add_undo_property(c, "size", c.size)
Global.undo_redo.add_undo_method(Global, "undo", Global.canvases)

View file

@ -130,11 +130,9 @@ func _on_CopyFrame_pressed(frame := -1) -> void:
for layer in canvas.layers: # Copy every layer
var sprite := Image.new()
sprite.copy_from(layer[0])
sprite.copy_from(layer.image)
sprite.lock()
var tex := ImageTexture.new()
tex.create_from_image(sprite, 0)
new_canvas.layers.append([sprite, tex, layer[2]])
new_canvas.layers.append(Cel.new(sprite, layer.opacity))
var new_animation_tags := Global.animation_tags.duplicate(true)
# Loop through the tags to see if the frame is in one
@ -350,15 +348,12 @@ func add_layer(is_new := true) -> void:
if is_new:
new_layer.create(c.size.x, c.size.y, false, Image.FORMAT_RGBA8)
else: # Clone layer
new_layer.copy_from(c.layers[Global.current_layer][0])
new_layer.copy_from(c.layers[Global.current_layer].image)
new_layer.lock()
var new_layer_tex := ImageTexture.new()
new_layer_tex.create_from_image(new_layer, 0)
var new_canvas_layers : Array = c.layers.duplicate()
# Store [Image, ImageTexture, Opacity]
new_canvas_layers.append([new_layer, new_layer_tex, 1])
new_canvas_layers.append(Cel.new(new_layer, 1))
Global.undo_redo.add_do_property(c, "layers", new_canvas_layers)
Global.undo_redo.add_undo_property(c, "layers", c.layers)
@ -430,30 +425,27 @@ func _on_MergeDownLayer_pressed() -> void:
for c in Global.canvases:
var new_layers_canvas : Array = c.layers.duplicate(true)
var selected_layer := Image.new()
selected_layer.copy_from(new_layers_canvas[Global.current_layer][0])
selected_layer.copy_from(new_layers_canvas[Global.current_layer].image)
selected_layer.lock()
if c.layers[Global.current_layer][2] < 1: # If we have layer transparency
if c.layers[Global.current_layer].opacity < 1: # If we have layer transparency
for xx in selected_layer.get_size().x:
for yy in selected_layer.get_size().y:
var pixel_color : Color = selected_layer.get_pixel(xx, yy)
var alpha : float = pixel_color.a * c.layers[Global.current_layer][2]
var alpha : float = pixel_color.a * c.layers[Global.current_layer].opacity
selected_layer.set_pixel(xx, yy, Color(pixel_color.r, pixel_color.g, pixel_color.b, alpha))
var new_layer := Image.new()
new_layer.copy_from(c.layers[Global.current_layer - 1][0])
new_layer.copy_from(c.layers[Global.current_layer - 1].image)
new_layer.lock()
DrawingAlgos.blend_rect(new_layer, selected_layer, Rect2(c.position, c.size), Vector2.ZERO)
new_layers_canvas.remove(Global.current_layer)
if !selected_layer.is_invisible() and Global.layers[Global.current_layer - 1].linked_cels.size() > 1 and (c in Global.layers[Global.current_layer - 1].linked_cels):
new_layers[Global.current_layer - 1].linked_cels.erase(c)
var tex := ImageTexture.new()
tex.create_from_image(new_layer, 0)
new_layers_canvas[Global.current_layer - 1][0] = new_layer
new_layers_canvas[Global.current_layer - 1][1] = tex
new_layers_canvas[Global.current_layer - 1].image = new_layer
else:
Global.undo_redo.add_do_property(c.layers[Global.current_layer - 1][0], "data", new_layer.data)
Global.undo_redo.add_undo_property(c.layers[Global.current_layer - 1][0], "data", c.layers[Global.current_layer - 1][0].data)
Global.undo_redo.add_do_property(c.layers[Global.current_layer - 1].image, "data", new_layer.data)
Global.undo_redo.add_undo_property(c.layers[Global.current_layer - 1].image, "data", c.layers[Global.current_layer - 1].image.data)
Global.undo_redo.add_do_property(c, "layers", new_layers_canvas)
Global.undo_redo.add_undo_property(c, "layers", c.layers)
@ -470,7 +462,7 @@ func _on_MergeDownLayer_pressed() -> void:
func _on_OpacitySlider_value_changed(value) -> void:
Global.canvas.layers[Global.current_layer][2] = value / 100
Global.canvas.layers[Global.current_layer].opacity = value / 100
Global.layer_opacity_slider.value = value
Global.layer_opacity_slider.value = value
Global.layer_opacity_spinbox.value = value