From 7d0c25f505418b8eb43b3be270f202833eb87a63 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 18 Aug 2021 18:00:35 -0400 Subject: [PATCH 001/154] Fixed issues with Shading tool Saturation and Value not always being right in Hue Shading mode --- src/Tools/Shading.gd | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/Tools/Shading.gd b/src/Tools/Shading.gd index 8d91aa2f1649..d50225fb1cd4 100644 --- a/src/Tools/Shading.gd +++ b/src/Tools/Shading.gd @@ -56,20 +56,16 @@ class LightenDarkenOp extends Drawer.ColorOp: if lighten_or_darken == LightenDarken.LIGHTEN: hue_shift = hue_limit_lighten(dst.h, hue_shift) dst.h += hue_shift - dst.s -= sat_shift + if dst.s > sat_lighten_limit: + dst.s = max(dst.s - min(sat_shift, dst.s), sat_lighten_limit) dst.v += value_shift - if dst.s < sat_lighten_limit: - dst.v = prev_value - dst.s = prev_sat - dst.h = prev_hue else: hue_shift = hue_limit_darken(dst.h, hue_shift) dst.h -= hue_shift dst.s += sat_shift - dst.v -= value_shift - if dst.v < value_darken_limit: - dst.v = prev_value + if dst.v > value_darken_limit: + dst.v = max(dst.v - min(value_shift, dst.v), value_darken_limit) return dst From f82a6fc67074e6c5505c4343e21cae401f3ac943 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sun, 22 Aug 2021 20:55:48 -0400 Subject: [PATCH 002/154] Shading tool hue shifting fixes and tweaks --- src/Tools/Shading.gd | 52 ++++++++++++++++++++++++------------------ src/Tools/Shading.tscn | 4 ++-- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/Tools/Shading.gd b/src/Tools/Shading.gd index 838ed0ad812e..b77117716d63 100644 --- a/src/Tools/Shading.gd +++ b/src/Tools/Shading.gd @@ -23,8 +23,8 @@ class LightenDarkenOp extends Drawer.ColorOp: var sat_amount := 10.0 var value_amount := 10.0 - var hue_lighten_limit := 60.0 / 359.0 # A yellow color - var hue_darken_limit := 270.0 / 359.0 # A purple color + var hue_lighten_limit := 60.0 / 360.0 # A yellow color + var hue_darken_limit := 240.0 / 360.0 # A blue color var sat_lighten_limit := 10.0 / 100.0 var value_darken_limit := 10.0 / 100.0 @@ -40,25 +40,25 @@ class LightenDarkenOp extends Drawer.ColorOp: elif strength < 0: dst = dst.darkened(-strength) else: - var hue_shift := hue_amount / 359.0 + var hue_shift := hue_amount / 360.0 var sat_shift := sat_amount / 100.0 var value_shift := value_amount / 100.0 - # If the colors are roughly between yellow and purple, + # If the colors are roughly between yellow-green-blue, # reverse hue direction - if !hue_range(dst.h): + if hue_range(dst.h): hue_shift = -hue_shift if lighten_or_darken == LightenDarken.LIGHTEN: hue_shift = hue_limit_lighten(dst.h, hue_shift) - dst.h += hue_shift + dst.h = fposmod(dst.h + hue_shift, 1) if dst.s > sat_lighten_limit: dst.s = max(dst.s - min(sat_shift, dst.s), sat_lighten_limit) dst.v += value_shift else: hue_shift = hue_limit_darken(dst.h, hue_shift) - dst.h -= hue_shift + dst.h = fposmod(dst.h - hue_shift, 1) dst.s += sat_shift if dst.v > value_darken_limit: dst.v = max(dst.v - min(value_shift, dst.v), value_darken_limit) @@ -66,37 +66,45 @@ class LightenDarkenOp extends Drawer.ColorOp: return dst - # Returns true if the colors are roughly between red and yellow, and purple and red - # False when the colors are roughly between yellow and purple (includes green & blue) + # Returns true if the colors are roughly between yellow, green and blue + # False when the colors are roughly between red-orange-yellow, or blue-purple-red func hue_range(hue : float) -> bool: - return hue < hue_lighten_limit or hue > hue_darken_limit + return hue > hue_lighten_limit and hue < hue_darken_limit func hue_limit_lighten(hue : float, hue_shift : float) -> float: - # Colors between red-yellow and purple-red + # Colors between red-orange-yellow and blue-purple-red if hue_shift > 0: - # Just colors between red-yellow + # Just colors between red-orange-yellow if hue < hue_darken_limit: if hue + hue_shift >= hue_lighten_limit: - hue_shift = 0 + hue_shift = hue_lighten_limit - hue + # Just blue-purple-red + else: + if hue + hue_shift >= hue_lighten_limit + 1: # +1 looping around the color wheel + hue_shift = hue_lighten_limit - hue - # Colors between yellow-purple + # Colors between yellow-green-blue elif hue_shift < 0 and hue + hue_shift <= hue_lighten_limit: - hue_shift = clamp(hue_shift, -(hue - hue_lighten_limit), 0) + hue_shift = hue_lighten_limit - hue return hue_shift func hue_limit_darken(hue : float, hue_shift : float) -> float: - # Colors between red-yellow and purple-red + # Colors between red-orange-yellow and blue-purple-red if hue_shift > 0: - # Just colors between purple-red - if hue > hue_darken_limit: - if hue + hue_shift <= hue_darken_limit: - hue_shift = 0 + # Just colors between red-orange-yellow + if hue < hue_darken_limit: + if hue - hue_shift <= hue_darken_limit - 1: # -1 looping backwards around the color wheel + hue_shift = hue - hue_darken_limit + # Just blue-purple-red + else: + if hue - hue_shift <= hue_darken_limit: + hue_shift = hue - hue_darken_limit - # Colors between yellow-purple + # Colors between yellow-green-blue elif hue_shift < 0 and hue - hue_shift >= hue_darken_limit: - hue_shift = clamp(hue_shift, -(hue_darken_limit - hue), 0) + hue_shift = hue - hue_darken_limit return hue_shift diff --git a/src/Tools/Shading.tscn b/src/Tools/Shading.tscn index 3610af186940..b30c7027741c 100644 --- a/src/Tools/Shading.tscn +++ b/src/Tools/Shading.tscn @@ -113,7 +113,7 @@ margin_bottom = 42.0 hint_tooltip = "Lighten/Darken amount" mouse_default_cursor_shape = 2 size_flags_horizontal = 4 -max_value = 359.0 +max_value = 180.0 value = 10.0 align = 1 @@ -128,7 +128,7 @@ focus_mode = 0 mouse_default_cursor_shape = 2 size_flags_horizontal = 4 size_flags_vertical = 1 -max_value = 359.0 +max_value = 180.0 value = 10.0 ticks_on_borders = true From 51e1b6b608e72ecda15274530cc4426011982939 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 5 May 2022 23:07:05 -0400 Subject: [PATCH 003/154] Bringing over changes from layer groups brach, without any changes to layer blending --- Translations/Translations.pot | 6 + assets/graphics/layers/group_collapsed.png | Bin 0 -> 180 bytes .../layers/group_collapsed.png.import | 35 ++++ assets/graphics/layers/group_expanded.png | Bin 0 -> 202 bytes .../graphics/layers/group_expanded.png.import | 35 ++++ assets/graphics/layers/group_new.png | Bin 0 -> 184 bytes assets/graphics/layers/group_new.png.import | 35 ++++ src/Autoload/Global.gd | 3 +- src/Autoload/OpenSave.gd | 51 +++--- src/Autoload/Palettes.gd | 2 +- src/Classes/BaseCel.gd | 10 ++ src/Classes/BaseLayer.gd | 53 ++++++ src/Classes/GroupCel.gd | 15 ++ src/Classes/GroupLayer.gd | 29 +++ src/Classes/ImageEffect.gd | 4 +- src/Classes/Layer.gd | 23 --- src/Classes/{Cel.gd => PixelCel.gd} | 11 +- src/Classes/PixelLayer.gd | 34 ++++ src/Classes/Project.gd | 131 +++++++------- src/Main.gd | 2 +- src/Tools/BaseTool.gd | 2 +- src/Tools/Draw.gd | 2 +- src/Tools/Move.gd | 2 +- src/UI/Canvas/OnionSkinning.gd | 4 +- src/UI/Canvas/Selection.gd | 2 +- src/UI/Dialogs/CreateNewImage.gd | 2 +- src/UI/Timeline/AnimationTimeline.gd | 56 +++++- src/UI/Timeline/AnimationTimeline.tscn | 55 ++++-- .../{LayerButton.gd => BaseLayerButton.gd} | 47 +++-- src/UI/Timeline/GroupCelButton.gd | 35 ++++ src/UI/Timeline/GroupCelButton.tscn | 65 +++++++ src/UI/Timeline/GroupLayerButton.gd | 15 ++ src/UI/Timeline/GroupLayerButton.tscn | 170 ++++++++++++++++++ .../{CelButton.gd => PixelCelButton.gd} | 10 +- .../{CelButton.tscn => PixelCelButton.tscn} | 8 +- src/UI/Timeline/PixelLayerButton.gd | 25 +++ ...LayerButton.tscn => PixelLayerButton.tscn} | 33 ++-- 37 files changed, 823 insertions(+), 189 deletions(-) create mode 100644 assets/graphics/layers/group_collapsed.png create mode 100644 assets/graphics/layers/group_collapsed.png.import create mode 100644 assets/graphics/layers/group_expanded.png create mode 100644 assets/graphics/layers/group_expanded.png.import create mode 100644 assets/graphics/layers/group_new.png create mode 100644 assets/graphics/layers/group_new.png.import create mode 100644 src/Classes/BaseCel.gd create mode 100644 src/Classes/BaseLayer.gd create mode 100644 src/Classes/GroupCel.gd create mode 100644 src/Classes/GroupLayer.gd delete mode 100644 src/Classes/Layer.gd rename src/Classes/{Cel.gd => PixelCel.gd} (81%) create mode 100644 src/Classes/PixelLayer.gd rename src/UI/Timeline/{LayerButton.gd => BaseLayerButton.gd} (78%) create mode 100644 src/UI/Timeline/GroupCelButton.gd create mode 100644 src/UI/Timeline/GroupCelButton.tscn create mode 100644 src/UI/Timeline/GroupLayerButton.gd create mode 100644 src/UI/Timeline/GroupLayerButton.tscn rename src/UI/Timeline/{CelButton.gd => PixelCelButton.gd} (97%) rename src/UI/Timeline/{CelButton.tscn => PixelCelButton.tscn} (96%) create mode 100644 src/UI/Timeline/PixelLayerButton.gd rename src/UI/Timeline/{LayerButton.tscn => PixelLayerButton.tscn} (83%) diff --git a/Translations/Translations.pot b/Translations/Translations.pot index e196388a64bb..ad0e39f07bfa 100644 --- a/Translations/Translations.pot +++ b/Translations/Translations.pot @@ -1419,6 +1419,9 @@ msgstr "" msgid "Create a new layer" msgstr "" +msgid "Create a new group layer" +msgstr "" + msgid "Remove current layer" msgstr "" @@ -1453,6 +1456,9 @@ msgid "Enable/disable cel linking\n\n" "Linked cels are being shared across multiple frames" msgstr "" +msgid "Expand/collapse group" +msgstr "" + msgid "Palette" msgstr "" diff --git a/assets/graphics/layers/group_collapsed.png b/assets/graphics/layers/group_collapsed.png new file mode 100644 index 0000000000000000000000000000000000000000..d513e9ef3c74d59fb3b57cd50ead4a19054b5bd7 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4fjKx9jP7LeL$-D$|@;qG}Lo9mV zPVwYAV8Fxt^wR(On|oEn%P+UEajoq;=+iPm_it9$uL(0NEhIM1-g+?og5VFQ7y)1A z#Tt5!s>_bcga?aR%sSyNwqy6qOI%#;lEOc%tM1IT+PdW+OIEXH$fU6Jj1=X!n=84S cxW6do9FVdQ&MBb@088LMN&o-= literal 0 HcmV?d00001 diff --git a/assets/graphics/layers/group_collapsed.png.import b/assets/graphics/layers/group_collapsed.png.import new file mode 100644 index 000000000000..83ac242ef698 --- /dev/null +++ b/assets/graphics/layers/group_collapsed.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/group_collapsed.png-9d08fac1c2f635c754860111d024aa0f.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/graphics/layers/group_collapsed.png" +dest_files=[ "res://.import/group_collapsed.png-9d08fac1c2f635c754860111d024aa0f.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=false +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=false +svg/scale=1.0 diff --git a/assets/graphics/layers/group_expanded.png b/assets/graphics/layers/group_expanded.png new file mode 100644 index 0000000000000000000000000000000000000000..7f013ae335dd862d8f80608ddf237ac247009d65 GIT binary patch literal 202 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4fjKx9jP7LeL$-D$|T0C7GLo9mV zPC3YTK!L;g<);7tQ_Cbd4I4x!zui!1)aAbIJZCKAOu>P<(`0VP0 zRidg2nU~EhtTSG9iOwiwcu@IKtK0CKwss%Gn&rV8zTRohne#I7uV~?;ROw?}tCzn& z82r&DmdKI;Vst0DyH* AX8-^I literal 0 HcmV?d00001 diff --git a/assets/graphics/layers/group_expanded.png.import b/assets/graphics/layers/group_expanded.png.import new file mode 100644 index 000000000000..9c8eff2dd93d --- /dev/null +++ b/assets/graphics/layers/group_expanded.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/group_expanded.png-f3cd620185a4989737d6d9a36f4b57f3.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/graphics/layers/group_expanded.png" +dest_files=[ "res://.import/group_expanded.png-f3cd620185a4989737d6d9a36f4b57f3.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=false +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=false +svg/scale=1.0 diff --git a/assets/graphics/layers/group_new.png b/assets/graphics/layers/group_new.png new file mode 100644 index 0000000000000000000000000000000000000000..6f3d95ffc4ce2c4e275aba7b15d293efe839dad7 GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4fjKx9jP7LeL$-D$|iacE$Lo9mV zhD386P~h2|{C$7XH{*kuzZM9mY^uqWzBMbs`)8r^D@FzlN0$g2mbELUZ!TD}JTml0 z&jcMy6aG7g=2g~SZhSAf;_2^-z4<9})m74;x6HRPWVp~a&2i%Wn??K5?=jzOJ-kG! h<(ydk*0}G-ShYLDAI^$gbpU8PgQu&X%Q~loCIE~BNXGyG literal 0 HcmV?d00001 diff --git a/assets/graphics/layers/group_new.png.import b/assets/graphics/layers/group_new.png.import new file mode 100644 index 000000000000..904b6b0bd6fd --- /dev/null +++ b/assets/graphics/layers/group_new.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/group_new.png-4ebdc7dd84d8c8a7b7979f50f4471543.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/graphics/layers/group_new.png" +dest_files=[ "res://.import/group_new.png-4ebdc7dd84d8c8a7b7979f50f4471543.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=false +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=false +svg/scale=1.0 diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index 32cf05c261ba..d606198ba5d2 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -243,7 +243,8 @@ func undo_or_redo( if action_name == "Scale": for i in project.frames.size(): for j in project.layers.size(): - var current_cel: Cel = project.frames[i].cels[j] + # TODO: ensure this is the correct cel type: + var current_cel: BaseCel = project.frames[i].cels[j] current_cel.image_texture.create_from_image(current_cel.image, 0) canvas.camera_zoom() canvas.grid.update() diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index 41eea3a2258a..14f16aa80914 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -188,13 +188,16 @@ func open_old_pxo_file(file: File, new_project: Project, first_line: String) -> if file_major_version >= 0 and file_minor_version > 6: var global_layer_line := file.get_line() while global_layer_line == ".": - var layer_name := file.get_line() - var layer_visibility := file.get_8() - var layer_lock := file.get_8() - var layer_new_cels_linked := file.get_8() + var layer_dict:= { + "name": file.get_line(), + "visible": file.get_8(), + "locked": file.get_8(), + "new_cels_linked": file.get_8(), + "linked_cels": [] + } linked_cels.append(file.get_var()) - - var l := Layer.new(layer_name, layer_visibility, layer_lock, layer_new_cels_linked, []) + var l := PixelLayer.new() + l.deserialize(layer_dict) new_project.layers.append(l) global_layer_line = file.get_line() @@ -211,17 +214,17 @@ func open_old_pxo_file(file: File, new_project: Project, first_line: String) -> if file_major_version == 0 and file_minor_version < 7: var layer_name_old_version = file.get_line() if frame == 0: - var l := Layer.new(layer_name_old_version) + var l := PixelLayer.new(layer_name_old_version) new_project.layers.append(l) var cel_opacity := 1.0 if file_major_version >= 0 and file_minor_version > 5: cel_opacity = file.get_float() var image := Image.new() image.create_from_data(width, height, false, Image.FORMAT_RGBA8, buffer) - frame_class.cels.append(Cel.new(image, cel_opacity)) + frame_class.cels.append(PixelCel.new(image, cel_opacity)) if file_major_version >= 0 and file_minor_version >= 7: if frame in linked_cels[layer_i]: - var linked_cel: Cel = new_project.layers[layer_i].linked_cels[0].cels[layer_i] + var linked_cel: PixelCel = new_project.layers[layer_i].linked_cels[0].cels[layer_i] new_project.layers[layer_i].linked_cels.append(frame_class) frame_class.cels[layer_i].image = linked_cel.image frame_class.cels[layer_i].image_texture = linked_cel.image_texture @@ -346,7 +349,7 @@ func save_pxo_file( file.store_line(to_save) for frame in project.frames: for cel in frame.cels: - file.store_buffer(cel.image.get_data()) + file.store_buffer(cel.get_image().get_data()) for brush in project.brushes: file.store_buffer(brush.get_data()) @@ -386,12 +389,12 @@ func save_pxo_file( func open_image_as_new_tab(path: String, image: Image) -> void: var project = Project.new([], path.get_file(), image.get_size()) - project.layers.append(Layer.new()) + project.layers.append(PixelLayer.new()) Global.projects.append(project) var frame := Frame.new() image.convert(Image.FORMAT_RGBA8) - frame.cels.append(Cel.new(image, 1)) + frame.cels.append(PixelCel.new(image, 1)) project.frames.append(frame) set_new_imported_tab(project, path) @@ -399,7 +402,7 @@ func open_image_as_new_tab(path: String, image: Image) -> void: func open_image_as_spritesheet_tab(path: String, image: Image, horiz: int, vert: int) -> void: var project = Project.new([], path.get_file()) - project.layers.append(Layer.new()) + project.layers.append(PixelLayer.new()) Global.projects.append(project) horiz = min(horiz, image.get_size().x) vert = min(vert, image.get_size().y) @@ -414,13 +417,13 @@ func open_image_as_spritesheet_tab(path: String, image: Image, horiz: int, vert: ) project.size = cropped_image.get_size() cropped_image.convert(Image.FORMAT_RGBA8) - frame.cels.append(Cel.new(cropped_image, 1)) + frame.cels.append(PixelCel.new(cropped_image, 1)) for _i in range(1, project.layers.size()): var empty_sprite := Image.new() empty_sprite.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8) empty_sprite.fill(Color(0, 0, 0, 0)) - frame.cels.append(Cel.new(empty_sprite, 1)) + frame.cels.append(PixelCel.new(empty_sprite, 1)) project.frames.append(frame) @@ -457,12 +460,12 @@ func open_image_as_spritesheet_layer( var frame: Frame = project.new_empty_frame() new_frames.insert(project.current_frame + 1, frame) #Create new layer for spritesheet - var layer := Layer.new(file_name) + var layer := PixelLayer.new(file_name) new_layers.append(layer) for f in new_frames: var new_layer := Image.new() new_layer.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8) - f.cels.append(Cel.new(new_layer, 1)) + f.cels.append(PixelCel.new(new_layer, 1)) # slice spritesheet var image_no: int = 0 @@ -479,7 +482,7 @@ func open_image_as_spritesheet_layer( for i in new_frames.size(): if i == frame_index: cropped_image.convert(Image.FORMAT_RGBA8) - new_frames[i].cels[layer_index] = (Cel.new(cropped_image, 1)) + new_frames[i].cels[layer_index] = (PixelCel.new(cropped_image, 1)) image_no += 1 project.undo_redo.add_do_property(project, "current_frame", new_frames.size() - 1) @@ -512,7 +515,7 @@ func open_image_at_frame(image: Image, layer_index := 0, frame_index := 0) -> vo for i in project.frames.size(): if i == frame_index: image.convert(Image.FORMAT_RGBA8) - frames[i].cels[layer_index] = (Cel.new(image, 1)) + frames[i].cels[layer_index] = (PixelCel.new(image, 1)) project.undo_redo.add_do_property(project.frames[i], "cels", frames[i].cels) project.undo_redo.add_undo_property(project.frames[i], "cels", project.frames[i].cels) @@ -536,11 +539,11 @@ func open_image_as_new_frame(image: Image, layer_index := 0) -> void: for i in project.layers.size(): if i == layer_index: image.convert(Image.FORMAT_RGBA8) - frame.cels.append(Cel.new(image, 1)) + frame.cels.append(PixelCel.new(image, 1)) else: var empty_image := Image.new() empty_image.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8) - frame.cels.append(Cel.new(empty_image, 1)) + frame.cels.append(PixelCel.new(empty_image, 1)) new_frames.append(frame) @@ -563,7 +566,7 @@ func open_image_as_new_layer(image: Image, file_name: String, frame_index := 0) var project = Global.current_project image.crop(project.size.x, project.size.y) var new_layers: Array = Global.current_project.layers.duplicate() - var layer := Layer.new(file_name) + var layer := PixelLayer.new(file_name) Global.current_project.undos += 1 Global.current_project.undo_redo.create_action("Add Layer") @@ -571,11 +574,11 @@ func open_image_as_new_layer(image: Image, file_name: String, frame_index := 0) var new_cels: Array = project.frames[i].cels.duplicate(true) if i == frame_index: image.convert(Image.FORMAT_RGBA8) - new_cels.append(Cel.new(image, 1)) + new_cels.append(PixelCel.new(image, 1)) else: var empty_image := Image.new() empty_image.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8) - new_cels.append(Cel.new(empty_image, 1)) + new_cels.append(PixelCel.new(empty_image, 1)) project.undo_redo.add_do_property(project.frames[i], "cels", new_cels) project.undo_redo.add_undo_property(project.frames[i], "cels", project.frames[i].cels) diff --git a/src/Autoload/Palettes.gd b/src/Autoload/Palettes.gd index d11755274607..e2fbd75659bb 100644 --- a/src/Autoload/Palettes.gd +++ b/src/Autoload/Palettes.gd @@ -174,7 +174,7 @@ func _fill_new_palette_with_colors( match get_colors_from: GetColorsFrom.CURRENT_CEL: for cel_index in current_project.selected_cels: - var cel: Cel = current_project.frames[cel_index[0]].cels[cel_index[1]] + var cel: PixelCel = current_project.frames[cel_index[0]].cels[cel_index[1]] cels.append(cel) GetColorsFrom.CURRENT_FRAME: for cel in current_project.frames[current_project.current_frame].cels: diff --git a/src/Classes/BaseCel.gd b/src/Classes/BaseCel.gd new file mode 100644 index 000000000000..ab4da102a239 --- /dev/null +++ b/src/Classes/BaseCel.gd @@ -0,0 +1,10 @@ +class_name BaseCel +extends Reference +# Base class for cel properties. +# The term "cel" comes from "celluloid" (https://en.wikipedia.org/wiki/Cel). + +var opacity: float + +# Each Cel type should have a get_image function, which will either return +# its image data for PixelCels, or return a render of that cel. It's meant +# for read-only usage of image data from any type of cel diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd new file mode 100644 index 000000000000..0a1e5ce05165 --- /dev/null +++ b/src/Classes/BaseLayer.gd @@ -0,0 +1,53 @@ +class_name BaseLayer +extends Reference +# Base class for layer properties. Different layer types extend from this class. + +var name := "" +var visible := true +var locked := false +var blend_mode := 0 +var parent: BaseLayer +var project +var index: int + +func serialize() -> Dictionary: + assert(index == project.layers.find(self)) # TODO: remove once sure index is synced properly + return { + "name": name, + "visible": visible, + "locked": locked, + "blend_mode": blend_mode, + "parent": parent.index if is_instance_valid(parent) else -1 + } + + +func deserialize(dict: Dictionary) -> void: + name = dict.name + visible = dict.visible + locked = dict.locked + blend_mode = dict.get("blend_mode", 0) + if dict.get("parent", -1) != -1: + parent = project.layers[dict.parent] + + +func can_layer_get_drawn() -> bool: + return false + + +# TODO: Search for layer visbility/locked checks that should be changed to the hierarchy ones: +func is_visible_in_hierarchy() -> bool: + if is_instance_valid(parent) and visible: + return parent.is_visible_in_hierarchy() + return visible + + +func is_locked_in_hierarchy() -> bool: + if is_instance_valid(parent) and not locked: + return parent.is_locked_in_hierarchy() + return locked + + +func get_hierarchy_depth() -> int: + if is_instance_valid(parent): + return parent.get_hierarchy_depth() + 1 + return 0 diff --git a/src/Classes/GroupCel.gd b/src/Classes/GroupCel.gd new file mode 100644 index 000000000000..38cef8bcfefe --- /dev/null +++ b/src/Classes/GroupCel.gd @@ -0,0 +1,15 @@ +class_name GroupCel +extends BaseCel +# A class for the properties of cels in GroupLayers. +# The term "cel" comes from "celluloid" (https://en.wikipedia.org/wiki/Cel). + +var material := ShaderMaterial.new() + +func _init(_opacity := 1.0) -> void: + print("group cel added") + opacity = _opacity + + +func get_image() -> Image: + # TODO: render the material as an image and return it + return Image.new() diff --git a/src/Classes/GroupLayer.gd b/src/Classes/GroupLayer.gd new file mode 100644 index 000000000000..8b11b117c08e --- /dev/null +++ b/src/Classes/GroupLayer.gd @@ -0,0 +1,29 @@ +class_name GroupLayer +extends BaseLayer +# A class for group layer properties + +#var children := [] +var expanded := true +var blend_shader: Shader + + +func _init(_name := "") -> void: + name = _name + + +func serialize() -> Dictionary: + var data = .serialize() + data["type"] = "group" + data["expanded"] = expanded + return data + + +func deserialize(dict: Dictionary) -> void: + .deserialize(dict) + expanded = dict.expanded + + +func is_expanded_in_hierarchy() -> bool: + if is_instance_valid(parent) and expanded: + return parent.is_expanded_in_hierarchy() + return expanded diff --git a/src/Classes/ImageEffect.gd b/src/Classes/ImageEffect.gd index 4635faf4980c..d84c9256a3fc 100644 --- a/src/Classes/ImageEffect.gd +++ b/src/Classes/ImageEffect.gd @@ -47,7 +47,7 @@ func _confirmed() -> void: for cel_index in project.selected_cels: if !project.layers[cel_index[1]].can_layer_get_drawn(): continue - var cel: Cel = project.frames[cel_index[0]].cels[cel_index[1]] + var cel: PixelCel = project.frames[cel_index[0]].cels[cel_index[1]] var cel_image: Image = cel.image commit_action(cel_image) _commit_undo("Draw", undo_data, project) @@ -118,7 +118,7 @@ func _get_selected_draw_images(project: Project) -> Array: # Array of Images var images := [] if affect == CEL: for cel_index in project.selected_cels: - var cel: Cel = project.frames[cel_index[0]].cels[cel_index[1]] + var cel: PixelCel = project.frames[cel_index[0]].cels[cel_index[1]] images.append(cel.image) else: for frame in project.frames: diff --git a/src/Classes/Layer.gd b/src/Classes/Layer.gd deleted file mode 100644 index 7ff4dec1875a..000000000000 --- a/src/Classes/Layer.gd +++ /dev/null @@ -1,23 +0,0 @@ -class_name Layer -extends Reference -# A class for layer properties. - -var name := "" -var visible := true -var locked := false -var new_cels_linked := false -var linked_cels := [] # Array of Frames - - -func _init( - _name := "", _visible := true, _locked := false, _new_cels_linked := false, _linked_cels := [] -) -> void: - name = _name - visible = _visible - locked = _locked - new_cels_linked = _new_cels_linked - linked_cels = _linked_cels - - -func can_layer_get_drawn() -> bool: - return visible && !locked diff --git a/src/Classes/Cel.gd b/src/Classes/PixelCel.gd similarity index 81% rename from src/Classes/Cel.gd rename to src/Classes/PixelCel.gd index c8c9a5d12fbd..d0d5c56c5c74 100644 --- a/src/Classes/Cel.gd +++ b/src/Classes/PixelCel.gd @@ -1,12 +1,11 @@ -class_name Cel -extends Reference -# A class for cel properties. +class_name PixelCel +extends BaseCel +# A class for the properties of cels in PixelLayers. # The term "cel" comes from "celluloid" (https://en.wikipedia.org/wiki/Cel). # The "image" variable is where the image data of each cel are. var image: Image setget image_changed var image_texture: ImageTexture -var opacity: float func _init(_image := Image.new(), _opacity := 1.0, _image_texture: ImageTexture = null) -> void: @@ -22,3 +21,7 @@ func image_changed(value: Image) -> void: image = value if !image.is_empty(): image_texture.create_from_image(image, 0) + + +func get_image() -> Image: + return image diff --git a/src/Classes/PixelLayer.gd b/src/Classes/PixelLayer.gd new file mode 100644 index 000000000000..41d5a6766de4 --- /dev/null +++ b/src/Classes/PixelLayer.gd @@ -0,0 +1,34 @@ +class_name PixelLayer +extends BaseLayer +# A class for standard pixel layer properties. + +var new_cels_linked := false +var linked_cels := [] # Array of Frames + +func _init(_name := "") -> void: + name = _name + + +func serialize() -> Dictionary: + var dict = .serialize() + dict["type"] = "pixel" + dict["new_cels_linked"] = new_cels_linked + dict["linked_cels"] = [] + for cel in linked_cels: + dict.linked_cels.append(project.frames.find(cel)) + return dict + + +func deserialize(dict: Dictionary) -> void: + .deserialize(dict) + new_cels_linked = dict.new_cels_linked + + for linked_cel_number in dict.linked_cels: + linked_cels.append(project.frames[linked_cel_number]) + var linked_cel: PixelCel = project.frames[linked_cel_number].cels[index] + linked_cel.image = linked_cels[0].cels[index].image + linked_cel.image_texture = linked_cels[0].cels[index].image_texture + + +func can_layer_get_drawn() -> bool: + return is_visible_in_hierarchy() && !is_locked_in_hierarchy() diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 0e6309a9d2c4..71fa4d04e7f7 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -46,8 +46,10 @@ var was_exported := false var export_overwrite := false var frame_button_node = preload("res://src/UI/Timeline/FrameButton.tscn") -var layer_button_node = preload("res://src/UI/Timeline/LayerButton.tscn") -var cel_button_node = preload("res://src/UI/Timeline/CelButton.tscn") +var pixel_layer_button_node = preload("res://src/UI/Timeline/PixelLayerButton.tscn") +var group_layer_button_node = preload("res://src/UI/Timeline/GroupLayerButton.tscn") +var pixel_cel_button_node = preload("res://src/UI/Timeline/PixelCelButton.tscn") +var group_cel_button_node = preload("res://src/UI/Timeline/GroupCelButton.tscn") var animation_tag_node = preload("res://src/UI/Timeline/AnimationTagUI.tscn") @@ -113,7 +115,7 @@ func new_empty_frame() -> Frame: image.create(size.x, size.y, false, Image.FORMAT_RGBA8) if bottom_layer: image.fill(fill_color) - frame.cels.append(Cel.new(image, 1)) + frame.cels.append(PixelCel.new(image, 1)) bottom_layer = false return frame @@ -150,7 +152,11 @@ func change_project() -> void: # Create new ones for i in range(layers.size() - 1, -1, -1): # Create layer buttons - var layer_container = layer_button_node.instance() + var layer_container: BaseLayerButton + if layers[i] is PixelLayer: + layer_container = pixel_layer_button_node.instance() + elif layers[i] is GroupLayer: + layer_container = group_layer_button_node.instance() layer_container.layer = i if layers[i].name == "": layers[i].name = tr("Layer") + " %s" % i @@ -162,7 +168,7 @@ func change_project() -> void: var layer_cel_container := HBoxContainer.new() Global.frames_container.add_child(layer_cel_container) for j in range(frames.size()): # Create Cel buttons - var cel_button = cel_button_node.instance() + var cel_button = pixel_cel_button_node.instance() cel_button.frame = j cel_button.layer = i cel_button.get_child(0).texture = frames[j].cels[i].image_texture @@ -296,19 +302,7 @@ func change_project() -> void: func serialize() -> Dictionary: var layer_data := [] for layer in layers: - var linked_cels := [] - for cel in layer.linked_cels: - linked_cels.append(frames.find(cel)) - - layer_data.append( - { - "name": layer.name, - "visible": layer.visible, - "locked": layer.locked, - "new_cels_linked": layer.new_cels_linked, - "linked_cels": linked_cels, - } - ) + layer_data.append(layer.serialize()) var tag_data := [] for tag in animation_tags: @@ -374,6 +368,7 @@ func deserialize(dict: Dictionary) -> void: if dict.has("size_x") and dict.has("size_y"): size.x = dict.size_x size.y = dict.size_y + _update_tile_mode_rects() selection_bitmap = resize_bitmap(selection_bitmap, size) if dict.has("save_path"): @@ -383,7 +378,7 @@ func deserialize(dict: Dictionary) -> void: for frame in dict.frames: var cels := [] for cel in frame.cels: - cels.append(Cel.new(Image.new(), cel.opacity)) + cels.append(PixelCel.new(Image.new(), cel.opacity)) var duration := 1.0 if frame.has("duration"): duration = frame.duration @@ -394,23 +389,18 @@ func deserialize(dict: Dictionary) -> void: frame_i += 1 if dict.has("layers"): - var layer_i := 0 for saved_layer in dict.layers: - var linked_cels := [] - for linked_cel_number in saved_layer.linked_cels: - linked_cels.append(frames[linked_cel_number]) - var linked_cel: Cel = frames[linked_cel_number].cels[layer_i] - linked_cel.image = linked_cels[0].cels[layer_i].image - linked_cel.image_texture = linked_cels[0].cels[layer_i].image_texture - var layer := Layer.new( - saved_layer.name, - saved_layer.visible, - saved_layer.locked, - saved_layer.new_cels_linked, - linked_cels - ) - layers.append(layer) - layer_i += 1 + match saved_layer.get("type", "pixel"): + "pixel": + layers.append(PixelLayer.new()) + "group": + layers.append(GroupLayer.new()) + # Parent references to other layers are created when deserializing + # a layer, so loop again after creating them. + for layer_i in range(dict.layers.size()): + layers[layer_i].project = self + layers[layer_i].index = layer_i + layers[layer_i].deserialize(dict.layers[layer_i]) if dict.has("tags"): for tag in dict.tags: animation_tags.append(AnimationTag.new(tag.name, Color(tag.color), tag.from, tag.to)) @@ -470,11 +460,15 @@ func _frames_changed(value: Array) -> void: layer_cel_container.name = "FRAMESS " + str(i) Global.frames_container.add_child(layer_cel_container) for j in range(frames.size()): - var cel_button = cel_button_node.instance() - cel_button.frame = j - cel_button.layer = i - cel_button.get_child(0).texture = frames[j].cels[i].image_texture - layer_cel_container.add_child(cel_button) + if layers[j] is PixelLayer: + var cel_button = pixel_cel_button_node.instance() + cel_button.frame = j + cel_button.layer = i + cel_button.get_child(0).texture = frames[j].cels[i].image_texture + layer_cel_container.add_child(cel_button) + elif layers[j] is GroupLayer: + # TODO: Make GroupLayers work here + pass for j in range(frames.size()): var button: Button = frame_button_node.instance() @@ -500,8 +494,14 @@ func _layers_changed(value: Array) -> void: _remove_cel_buttons() for i in range(layers.size() - 1, -1, -1): - var layer_button: LayerButton = layer_button_node.instance() + var layer_button: BaseLayerButton + if layers[i] is PixelLayer: + layer_button = pixel_layer_button_node.instance() + elif layers[i] is GroupLayer: + layer_button = group_layer_button_node.instance() layer_button.layer = i + layers[i].index = i + layers[i].project = self if layers[i].name == "": layers[i].name = tr("Layer") + " %s" % i @@ -512,12 +512,17 @@ func _layers_changed(value: Array) -> void: var layer_cel_container := HBoxContainer.new() layer_cel_container.name = "LAYERSSS " + str(i) Global.frames_container.add_child(layer_cel_container) + # TODO: FIGURE OUT FRAMES WITH GROUP LAYERS! for j in range(frames.size()): - var cel_button = cel_button_node.instance() - cel_button.frame = j - cel_button.layer = i - cel_button.get_child(0).texture = frames[j].cels[i].image_texture - layer_cel_container.add_child(cel_button) + if layers[i] is PixelLayer: + var cel_button = pixel_cel_button_node.instance() + cel_button.frame = j + cel_button.layer = i + cel_button.get_child(0).texture = frames[j].cels[i].image_texture + layer_cel_container.add_child(cel_button) + elif layers[i] is GroupLayer: + var cel_button = group_cel_button_node.instance() + layer_cel_container.add_child(cel_button) var layer_button = Global.layers_container.get_child( Global.layers_container.get_child_count() - 1 - current_layer @@ -570,10 +575,13 @@ func _frame_changed(value: int) -> void: Global.move_right_frame_button, frames.size() == 1 or current_frame == frames.size() - 1 ) + if current_frame < frames.size(): - var cel_opacity: float = frames[current_frame].cels[current_layer].opacity - Global.layer_opacity_slider.value = cel_opacity * 100 - Global.layer_opacity_spinbox.value = cel_opacity * 100 + # TODO: Make this work with groups: + if not layers[current_layer] is GroupLayer: + var cel_opacity: float = frames[current_frame].cels[current_layer].opacity + Global.layer_opacity_slider.value = cel_opacity * 100 + Global.layer_opacity_spinbox.value = cel_opacity * 100 Global.canvas.update() Global.transparent_checker.update_rect() @@ -602,7 +610,7 @@ func _layer_changed(value: int) -> void: func _toggle_layer_buttons_layers() -> void: if !layers: return - if layers[current_layer].locked: + if layers[current_layer].is_locked_in_hierarchy(): Global.disable_button(Global.remove_layer_button, true) if layers.size() == 1: @@ -610,7 +618,7 @@ func _toggle_layer_buttons_layers() -> void: Global.disable_button(Global.move_up_layer_button, true) Global.disable_button(Global.move_down_layer_button, true) Global.disable_button(Global.merge_down_layer_button, true) - elif !layers[current_layer].locked: + elif !layers[current_layer].is_locked_in_hierarchy(): Global.disable_button(Global.remove_layer_button, false) @@ -628,7 +636,7 @@ func _toggle_layer_buttons_current_layer() -> void: Global.disable_button(Global.merge_down_layer_button, true) if current_layer < layers.size(): - if layers[current_layer].locked: + if layers[current_layer].is_locked_in_hierarchy(): Global.disable_button(Global.remove_layer_button, true) else: if layers.size() > 1: @@ -700,6 +708,7 @@ func is_empty() -> bool: return ( frames.size() == 1 and layers.size() == 1 + and layers[0] is PixelLayer and frames[0].cels[0].image.is_invisible() and animation_tags.size() == 0 ) @@ -710,14 +719,16 @@ func duplicate_layers() -> Array: # Loop through the array to create new classes for each element, so that they # won't be the same as the original array's classes. Needed for undo/redo to work properly. for i in new_layers.size(): - var new_linked_cels = new_layers[i].linked_cels.duplicate() - new_layers[i] = Layer.new( - new_layers[i].name, - new_layers[i].visible, - new_layers[i].locked, - new_layers[i].new_cels_linked, - new_linked_cels - ) + var layer_dict: Dictionary = new_layers[i].serialize() + #layer_dict.linked_cels = new_layers[i].linked_cels.duplicate() + match layer_dict.type: + "pixel": + new_layers[i] = PixelLayer.new() + "group": + new_layers[i] = GroupLayer.new() + new_layers[i].index = i + new_layers[i].project = self + new_layers[i].deserialize(layer_dict) return new_layers diff --git a/src/Main.gd b/src/Main.gd index f55ffa55166f..87d825015f6f 100644 --- a/src/Main.gd +++ b/src/Main.gd @@ -22,7 +22,7 @@ func _ready() -> void: Global.window_title = tr("untitled") + " - Pixelorama " + Global.current_version - Global.current_project.layers.append(Layer.new()) + Global.current_project.layers.append(PixelLayer.new()) var frame: Frame = Global.current_project.new_empty_frame() Global.current_project.frames.append(frame) Global.current_project.layers = Global.current_project.layers diff --git a/src/Tools/BaseTool.gd b/src/Tools/BaseTool.gd index cd0aaf04cbed..f98272e13cdd 100644 --- a/src/Tools/BaseTool.gd +++ b/src/Tools/BaseTool.gd @@ -88,7 +88,7 @@ func _get_selected_draw_images() -> Array: # Array of Images var images := [] var project: Project = Global.current_project for cel_index in project.selected_cels: - var cel: Cel = project.frames[cel_index[0]].cels[cel_index[1]] + var cel: PixelCel = project.frames[cel_index[0]].cels[cel_index[1]] if project.layers[cel_index[1]].can_layer_get_drawn(): images.append(cel.image) return images diff --git a/src/Tools/Draw.gd b/src/Tools/Draw.gd index c332c146556d..a1aacb11842a 100644 --- a/src/Tools/Draw.gd +++ b/src/Tools/Draw.gd @@ -539,7 +539,7 @@ func _get_undo_data() -> Dictionary: cels.append(project.frames[cel_index[0]].cels[cel_index[1]]) else: for frame in project.frames: - var cel: Cel = frame.cels[project.current_layer] + var cel: PixelCel = frame.cels[project.current_layer] cels.append(cel) for cel in cels: var image: Image = cel.image diff --git a/src/Tools/Move.gd b/src/Tools/Move.gd index 03221424f531..2a819fc887e1 100644 --- a/src/Tools/Move.gd +++ b/src/Tools/Move.gd @@ -137,7 +137,7 @@ func _get_undo_data() -> Dictionary: cels.append(project.frames[cel_index[0]].cels[cel_index[1]]) else: for frame in project.frames: - var cel: Cel = frame.cels[project.current_layer] + var cel: PixelCel = frame.cels[project.current_layer] cels.append(cel) for cel in cels: var image: Image = cel.image diff --git a/src/UI/Canvas/OnionSkinning.gd b/src/UI/Canvas/OnionSkinning.gd index 6121cd42b12c..fa8841a98fef 100644 --- a/src/UI/Canvas/OnionSkinning.gd +++ b/src/UI/Canvas/OnionSkinning.gd @@ -27,8 +27,8 @@ func _draw() -> void: if change == clamp(change, 0, Global.current_project.frames.size() - 1): var layer_i := 0 for cel in Global.current_project.frames[change].cels: - var layer: Layer = Global.current_project.layers[layer_i] - if layer.visible: + var layer: PixelLayer = Global.current_project.layers[layer_i] + if layer.is_visible_in_hierarchy(): # Ignore layer if it has the "_io" suffix in its name (case in-sensitive) if not (layer.name.to_lower().ends_with("_io")): color.a = 0.6 / i diff --git a/src/UI/Canvas/Selection.gd b/src/UI/Canvas/Selection.gd index 9788bd726649..ff556168fe77 100644 --- a/src/UI/Canvas/Selection.gd +++ b/src/UI/Canvas/Selection.gd @@ -643,7 +643,7 @@ func _get_selected_draw_images() -> Array: # Array of Images var images := [] var project: Project = Global.current_project for cel_index in project.selected_cels: - var cel: Cel = project.frames[cel_index[0]].cels[cel_index[1]] + var cel: PixelCel = project.frames[cel_index[0]].cels[cel_index[1]] images.append(cel.image) return images diff --git a/src/UI/Dialogs/CreateNewImage.gd b/src/UI/Dialogs/CreateNewImage.gd index 99ce4d7557bb..beaa55c0504a 100644 --- a/src/UI/Dialogs/CreateNewImage.gd +++ b/src/UI/Dialogs/CreateNewImage.gd @@ -108,7 +108,7 @@ func _on_CreateNewImage_confirmed() -> void: proj_name = tr("untitled") var new_project := Project.new([], proj_name, Vector2(width, height).floor()) - new_project.layers.append(Layer.new()) + new_project.layers.append(PixelLayer.new()) new_project.fill_color = fill_color var frame: Frame = new_project.new_empty_frame() new_project.frames.append(frame) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index a4ba26d5caaf..a9ed5c21ad01 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -309,7 +309,7 @@ func copy_frames(frames := []) -> void: sprite.copy_from(cel.image) var sprite_texture := ImageTexture.new() sprite_texture.create_from_image(sprite, 0) - new_frame.cels.append(Cel.new(sprite, cel.opacity, sprite_texture)) + new_frame.cels.append(PixelCel.new(sprite, cel.opacity, sprite_texture)) new_frame.duration = prev_frame.duration for l_i in range(new_layers.size()): @@ -598,7 +598,7 @@ func _on_FuturePlacement_item_selected(index: int) -> void: func add_layer(is_new := true) -> void: Global.canvas.selection.transform_content_confirm() var new_layers: Array = Global.current_project.layers.duplicate() - var l := Layer.new() + var l := PixelLayer.new() if !is_new: # Clone layer l.name = ( Global.current_project.layers[Global.current_project.current_layer].name @@ -624,7 +624,53 @@ func add_layer(is_new := true) -> void: new_layer.copy_from(f.cels[Global.current_project.current_layer].image) var new_cels: Array = f.cels.duplicate() - new_cels.append(Cel.new(new_layer, 1)) + new_cels.append(PixelCel.new(new_layer, 1)) + Global.current_project.undo_redo.add_do_property(f, "cels", new_cels) + Global.current_project.undo_redo.add_undo_property(f, "cels", f.cels) + + Global.current_project.undo_redo.add_do_property( + Global.current_project, "current_layer", Global.current_project.layers.size() + ) + Global.current_project.undo_redo.add_do_property(Global.current_project, "layers", new_layers) + Global.current_project.undo_redo.add_undo_property( + Global.current_project, "current_layer", Global.current_project.current_layer + ) + Global.current_project.undo_redo.add_undo_property( + Global.current_project, "layers", Global.current_project.layers + ) + + Global.current_project.undo_redo.add_undo_method(Global, "undo_or_redo", true) + Global.current_project.undo_redo.add_do_method(Global, "undo_or_redo", false) + Global.current_project.undo_redo.commit_action() + + +func add_group_layer(is_new := true) -> void: + Global.canvas.selection.transform_content_confirm() + var new_layers: Array = Global.current_project.layers.duplicate() + var l := GroupLayer.new() +# if !is_new: # Clone layer +# l.name = ( +# Global.current_project.layers[Global.current_project.current_layer].name +# + " (" +# + tr("copy") +# + ")" +# ) + new_layers.append(l) + # Add current layer to this group +# Global.current_project.layers[Global.current_project.current_layer].parent = l + # Add all layers to this group: + for layer in Global.current_project.layers: + if not layer.parent: + layer.parent = l + # Add last layer to this group: +# Global.current_project.layers[-1].parent = l + + Global.current_project.undos += 1 + Global.current_project.undo_redo.create_action("Add Layer") + + for f in Global.current_project.frames: + var new_cels: Array = f.cels.duplicate() + new_cels.append(GroupCel.new()) Global.current_project.undo_redo.add_do_property(f, "cels", new_cels) Global.current_project.undo_redo.add_undo_property(f, "cels", f.cels) @@ -718,7 +764,7 @@ func _on_MergeDownLayer_pressed() -> void: for f in Global.current_project.frames: var new_cels: Array = f.cels.duplicate() for i in new_cels.size(): - new_cels[i] = Cel.new(new_cels[i].image, new_cels[i].opacity) + new_cels[i] = PixelCel.new(new_cels[i].image, new_cels[i].opacity) var selected_layer := Image.new() selected_layer.copy_from(new_cels[Global.current_project.current_layer].image) @@ -790,7 +836,7 @@ func _on_MergeDownLayer_pressed() -> void: func _on_OpacitySlider_value_changed(value) -> void: var current_frame: Frame = Global.current_project.frames[Global.current_project.current_frame] - var cel: Cel = current_frame.cels[Global.current_project.current_layer] + var cel: BaseCel = current_frame.cels[Global.current_project.current_layer] cel.opacity = value / 100 Global.layer_opacity_slider.value = value Global.layer_opacity_spinbox.value = value diff --git a/src/UI/Timeline/AnimationTimeline.tscn b/src/UI/Timeline/AnimationTimeline.tscn index 64f456e2972c..5c0f3528b85c 100644 --- a/src/UI/Timeline/AnimationTimeline.tscn +++ b/src/UI/Timeline/AnimationTimeline.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=43 format=2] +[gd_scene load_steps=44 format=2] [ext_resource path="res://src/UI/Timeline/AnimationTimeline.gd" type="Script" id=1] [ext_resource path="res://assets/graphics/layers/new.png" type="Texture" id=2] @@ -9,6 +9,7 @@ [ext_resource path="res://assets/graphics/layers/clone.png" type="Texture" id=7] [ext_resource path="res://assets/graphics/timeline/move_arrow.png" type="Texture" id=8] [ext_resource path="res://src/UI/Timeline/FrameButton.tscn" type="PackedScene" id=9] +[ext_resource path="res://assets/graphics/layers/group_new.png" type="Texture" id=10] [ext_resource path="res://assets/graphics/timeline/new_frame.png" type="Texture" id=19] [ext_resource path="res://assets/graphics/timeline/remove_frame.png" type="Texture" id=20] [ext_resource path="res://assets/graphics/timeline/go_to_first_frame.png" type="Texture" id=21] @@ -107,6 +108,9 @@ margin_bottom = 160.0 rect_min_size = Vector2( 36, 160 ) rect_clip_content = true script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} [node name="ScrollContainer" type="ScrollContainer" parent="."] anchor_right = 1.0 @@ -127,14 +131,14 @@ margin_bottom = 38.0 size_flags_horizontal = 3 [node name="LayerButtonPanelContainer" type="PanelContainer" parent="ScrollContainer/TimelineContainer/TimelineButtons"] -margin_right = 186.0 +margin_right = 217.0 margin_bottom = 38.0 custom_styles/panel = SubResource( 2 ) [node name="LayerButtons" type="HBoxContainer" parent="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer"] margin_left = 4.5 margin_top = 3.0 -margin_right = 181.5 +margin_right = 212.5 margin_bottom = 25.0 size_flags_vertical = 0 custom_constants/separation = 9 @@ -163,11 +167,35 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="RemoveLayer" type="Button" parent="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]] +[node name="AddGroup" type="Button" parent="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]] margin_left = 31.0 margin_right = 53.0 margin_bottom = 22.0 rect_min_size = Vector2( 22, 22 ) +hint_tooltip = "Create a new group layer" +mouse_default_cursor_shape = 2 + +[node name="TextureRect" type="TextureRect" parent="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/AddGroup"] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -11.0 +margin_top = -11.0 +margin_right = 11.0 +margin_bottom = 11.0 +size_flags_horizontal = 0 +size_flags_vertical = 0 +texture = ExtResource( 10 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="RemoveLayer" type="Button" parent="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]] +margin_left = 62.0 +margin_right = 84.0 +margin_bottom = 22.0 +rect_min_size = Vector2( 22, 22 ) hint_tooltip = "Remove current layer" focus_mode = 0 mouse_default_cursor_shape = 8 @@ -190,8 +218,8 @@ __meta__ = { } [node name="MoveUpLayer" type="Button" parent="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]] -margin_left = 62.0 -margin_right = 84.0 +margin_left = 93.0 +margin_right = 115.0 margin_bottom = 22.0 rect_min_size = Vector2( 22, 22 ) hint_tooltip = "Move up the current layer" @@ -216,8 +244,8 @@ __meta__ = { } [node name="MoveDownLayer" type="Button" parent="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]] -margin_left = 93.0 -margin_right = 115.0 +margin_left = 124.0 +margin_right = 146.0 margin_bottom = 22.0 rect_min_size = Vector2( 22, 22 ) hint_tooltip = "Move down the current layer" @@ -242,8 +270,8 @@ __meta__ = { } [node name="CloneLayer" type="Button" parent="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]] -margin_left = 124.0 -margin_right = 146.0 +margin_left = 155.0 +margin_right = 177.0 margin_bottom = 22.0 rect_min_size = Vector2( 22, 22 ) hint_tooltip = "Clone current layer" @@ -267,8 +295,8 @@ __meta__ = { } [node name="MergeDownLayer" type="Button" parent="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]] -margin_left = 155.0 -margin_right = 177.0 +margin_left = 186.0 +margin_right = 208.0 margin_bottom = 22.0 rect_min_size = Vector2( 22, 22 ) hint_tooltip = "Merge current layer with the one below" @@ -293,7 +321,7 @@ __meta__ = { } [node name="Control" type="Control" parent="ScrollContainer/TimelineContainer/TimelineButtons"] -margin_left = 190.0 +margin_left = 221.0 margin_right = 386.0 margin_bottom = 38.0 size_flags_horizontal = 3 @@ -1007,6 +1035,7 @@ autowrap = true [connection signal="item_rect_changed" from="." to="." method="_on_AnimationTimeline_item_rect_changed"] [connection signal="item_rect_changed" from="ScrollContainer/TimelineContainer" to="." method="_on_TimelineContainer_item_rect_changed"] [connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/AddLayer" to="." method="add_layer" binds= [ true ]] +[connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/AddGroup" to="." method="add_group_layer" binds= [ true ]] [connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/RemoveLayer" to="." method="_on_RemoveLayer_pressed"] [connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/MoveUpLayer" to="." method="change_layer_order" binds= [ 1 ]] [connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/MoveDownLayer" to="." method="change_layer_order" binds= [ -1 ]] diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/BaseLayerButton.gd similarity index 78% rename from src/UI/Timeline/LayerButton.gd rename to src/UI/Timeline/BaseLayerButton.gd index 450657b7baf7..ca087d1d4e7e 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/BaseLayerButton.gd @@ -1,13 +1,13 @@ -class_name LayerButton +class_name BaseLayerButton extends Button var layer := 0 onready var visibility_button: BaseButton = find_node("VisibilityButton") onready var lock_button: BaseButton = find_node("LockButton") -onready var linked_button: BaseButton = find_node("LinkButton") onready var label: Label = find_node("Label") onready var line_edit: LineEdit = find_node("LineEdit") +onready var hierarchy_spacer: Control = find_node("HierarchySpacer") func _ready() -> void: @@ -16,11 +16,11 @@ func _ready() -> void: var layer_buttons = find_node("LayerButtons") for child in layer_buttons.get_children(): var texture = child.get_child(0) - var last_backslash = texture.texture.resource_path.get_base_dir().find_last("/") - var button_category = texture.texture.resource_path.get_base_dir().right(last_backslash + 1) - var normal_file_name = texture.texture.resource_path.get_file() +# var last_backslash = texture.texture.resource_path.get_base_dir().find_last("/") +# var button_category = texture.texture.resource_path.get_base_dir().right(last_backslash + 1) +# var normal_file_name = texture.texture.resource_path.get_file() - texture.texture = load("res://assets/graphics/%s/%s" % [button_category, normal_file_name]) +# texture.texture = load("res://assets/graphics/%s/%s" % [button_category, normal_file_name]) texture.modulate = Global.modulate_icon_color if Global.current_project.layers[layer].visible: @@ -33,10 +33,21 @@ func _ready() -> void: else: Global.change_button_texturerect(lock_button.get_child(0), "unlock.png") - if Global.current_project.layers[layer].new_cels_linked: # If new layers will be linked - Global.change_button_texturerect(linked_button.get_child(0), "linked_layer.png") - else: - Global.change_button_texturerect(linked_button.get_child(0), "unlinked_layer.png") + # Visualize how deep into the hierarchy the layer is + var hierarchy_depth: int = Global.current_project.layers[layer].get_hierarchy_depth() + hierarchy_spacer.rect_min_size.x = hierarchy_depth * 8 + if Global.control.theme.get_color("font_color", "Button").v > 0.5: # Light text is dark theme + self_modulate.v += hierarchy_depth * 0.2 + else: # Dark text should be light theme + self_modulate.v -= hierarchy_depth * 0.075 + + if is_instance_valid(Global.current_project.layers[layer].parent): + if not Global.current_project.layers[layer].parent.is_expanded_in_hierarchy(): + visible = false + if not Global.current_project.layers[layer].parent.is_visible_in_hierarchy(): + visibility_button.modulate.a = 0.33 + if Global.current_project.layers[layer].parent.is_locked_in_hierarchy(): + lock_button.modulate.a = 0.33 func _input(event: InputEvent) -> void: @@ -106,22 +117,6 @@ func _on_LockButton_pressed() -> void: _select_current_layer() -func _on_LinkButton_pressed() -> void: - Global.canvas.selection.transform_content_confirm() - var layer_class: Layer = Global.current_project.layers[layer] - layer_class.new_cels_linked = !layer_class.new_cels_linked - if layer_class.new_cels_linked && !layer_class.linked_cels: - # If button is pressed and there are no linked cels in the layer - layer_class.linked_cels.append( - Global.current_project.frames[Global.current_project.current_frame] - ) - var container = Global.frames_container.get_child(Global.current_project.current_layer) - container.get_child(Global.current_project.current_frame).button_setup() - - _select_current_layer() - Global.current_project.layers = Global.current_project.layers # Call the setter - - func _select_current_layer() -> void: Global.current_project.selected_cels.clear() var frame_layer := [Global.current_project.current_frame, layer] diff --git a/src/UI/Timeline/GroupCelButton.gd b/src/UI/Timeline/GroupCelButton.gd new file mode 100644 index 000000000000..080bd324f5f7 --- /dev/null +++ b/src/UI/Timeline/GroupCelButton.gd @@ -0,0 +1,35 @@ +extends Button + +var frame := 0 +var layer := 0 +var cel: GroupCel +var mat: Material + +onready var popup_menu: PopupMenu = $PopupMenu + + +func _ready() -> void: + button_setup() + + +func button_setup() -> void: + rect_min_size.x = Global.animation_timeline.cel_size + rect_min_size.y = Global.animation_timeline.cel_size + + hint_tooltip = tr("Frame: %s, Layer: %s") % [frame + 1, layer] + + # Reset the checkers size because it assumes you want the same size as the canvas + var checker = $CelShader/TransparentChecker + checker.rect_size = checker.get_parent().rect_size +# cel = Global.current_project.frames[frame].cels[layer] + #image = cel.image + + +func _on_GroupCelButton_resized() -> void: + get_node("CelShader").rect_min_size.x = rect_min_size.x - 4 + get_node("CelShader").rect_min_size.y = rect_min_size.y - 4 + + +func _pressed(): + # TODO: PixelCelButton could just use the func instead of signal too + pass diff --git a/src/UI/Timeline/GroupCelButton.tscn b/src/UI/Timeline/GroupCelButton.tscn new file mode 100644 index 000000000000..054aa82f7c18 --- /dev/null +++ b/src/UI/Timeline/GroupCelButton.tscn @@ -0,0 +1,65 @@ +[gd_scene load_steps=5 format=2] + +[ext_resource path="res://src/UI/Timeline/GroupCelButton.gd" type="Script" id=1] +[ext_resource path="res://src/UI/TransparentChecker.tscn" type="PackedScene" id=2] +[ext_resource path="res://src/Shaders/TransparentChecker.shader" type="Shader" id=3] + +[sub_resource type="ShaderMaterial" id=1] +shader = ExtResource( 3 ) +shader_param/size = 10.0 +shader_param/alpha = 1.0 +shader_param/color1 = Color( 0.7, 0.7, 0.7, 1 ) +shader_param/color2 = Color( 1, 1, 1, 1 ) +shader_param/offset = Vector2( 0, 0 ) +shader_param/scale = Vector2( 0, 0 ) +shader_param/rect_size = Vector2( 0, 0 ) +shader_param/follow_movement = false +shader_param/follow_scale = false + +[node name="GroupCelButton" type="Button"] +margin_top = 18.0 +margin_right = 36.0 +margin_bottom = 54.0 +rect_min_size = Vector2( 36, 36 ) +mouse_default_cursor_shape = 2 +size_flags_horizontal = 0 +size_flags_vertical = 0 +toggle_mode = true +button_mask = 7 +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="CelShader" type="TextureRect" parent="."] +margin_left = 2.0 +margin_top = 1.78536 +margin_right = 34.0 +margin_bottom = 33.7854 +rect_min_size = Vector2( 32, 32 ) +size_flags_horizontal = 0 +size_flags_vertical = 0 +expand = true +stretch_mode = 6 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="TransparentChecker" parent="CelShader" instance=ExtResource( 2 )] +show_behind_parent = true +material = SubResource( 1 ) +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_right = 0.0 +margin_bottom = 0.0 + +[node name="PopupMenu" type="PopupMenu" parent="."] +margin_right = 20.0 +margin_bottom = 20.0 +mouse_default_cursor_shape = 2 +__meta__ = { +"_edit_use_anchors_": false +} + +[connection signal="pressed" from="." to="." method="_on_CelButton_pressed"] +[connection signal="resized" from="." to="." method="_on_GroupCelButton_resized"] diff --git a/src/UI/Timeline/GroupLayerButton.gd b/src/UI/Timeline/GroupLayerButton.gd new file mode 100644 index 000000000000..51a6ca7c058b --- /dev/null +++ b/src/UI/Timeline/GroupLayerButton.gd @@ -0,0 +1,15 @@ +class_name GroupLayerButton +extends BaseLayerButton + +onready var expand_button: BaseButton = find_node("ExpandButton") + +func _ready() -> void: + if Global.current_project.layers[layer].expanded: # If the group is expanded + Global.change_button_texturerect(expand_button.get_child(0), "group_expanded.png") + else: + Global.change_button_texturerect(expand_button.get_child(0), "group_collapsed.png") + + + +func _on_ExpandButton_pressed(): + Global.current_project.layers[layer].expanded = !Global.current_project.layers[layer].expanded diff --git a/src/UI/Timeline/GroupLayerButton.tscn b/src/UI/Timeline/GroupLayerButton.tscn new file mode 100644 index 000000000000..653f52d9aa0a --- /dev/null +++ b/src/UI/Timeline/GroupLayerButton.tscn @@ -0,0 +1,170 @@ +[gd_scene load_steps=5 format=2] + +[ext_resource path="res://src/UI/Timeline/GroupLayerButton.gd" type="Script" id=1] +[ext_resource path="res://assets/graphics/layers/layer_visible.png" type="Texture" id=2] +[ext_resource path="res://assets/graphics/layers/unlock.png" type="Texture" id=3] +[ext_resource path="res://assets/graphics/layers/group_expanded.png" type="Texture" id=4] + +[node name="GroupLayerContainer" type="Button"] +margin_right = 236.0 +margin_bottom = 36.0 +rect_min_size = Vector2( 236, 36 ) +mouse_default_cursor_shape = 2 +size_flags_horizontal = 0 +toggle_mode = true +action_mode = 0 +script = ExtResource( 1 ) +__meta__ = { +"_edit_horizontal_guides_": [ ], +"_edit_use_anchors_": false +} + +[node name="HBoxContainer" type="HBoxContainer" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +size_flags_horizontal = 0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="EmptySpacer" type="Control" parent="HBoxContainer"] +margin_bottom = 36.0 + +[node name="LayerButtons" type="HBoxContainer" parent="HBoxContainer"] +margin_left = 4.0 +margin_right = 90.0 +margin_bottom = 36.0 +custom_constants/separation = 10 + +[node name="ExpandButton" type="ToolButton" parent="HBoxContainer/LayerButtons" groups=["UIButtons"]] +margin_top = 7.0 +margin_right = 22.0 +margin_bottom = 29.0 +rect_min_size = Vector2( 22, 22 ) +hint_tooltip = "Expand/collapse group" +mouse_default_cursor_shape = 2 +size_flags_horizontal = 0 +size_flags_vertical = 4 + +[node name="TextureRect" type="TextureRect" parent="HBoxContainer/LayerButtons/ExpandButton"] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -11.0 +margin_top = -11.0 +margin_right = 11.0 +margin_bottom = 11.0 +size_flags_horizontal = 0 +size_flags_vertical = 0 +texture = ExtResource( 4 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="VisibilityButton" type="ToolButton" parent="HBoxContainer/LayerButtons" groups=["UIButtons"]] +margin_left = 32.0 +margin_top = 7.0 +margin_right = 54.0 +margin_bottom = 29.0 +rect_min_size = Vector2( 22, 22 ) +hint_tooltip = "Toggle layer's visibility" +focus_mode = 0 +mouse_default_cursor_shape = 2 +size_flags_horizontal = 0 +size_flags_vertical = 4 + +[node name="TextureRect" type="TextureRect" parent="HBoxContainer/LayerButtons/VisibilityButton"] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -11.0 +margin_top = -11.0 +margin_right = 11.0 +margin_bottom = 11.0 +size_flags_horizontal = 0 +size_flags_vertical = 0 +texture = ExtResource( 2 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="LockButton" type="ToolButton" parent="HBoxContainer/LayerButtons" groups=["UIButtons"]] +margin_left = 64.0 +margin_top = 7.0 +margin_right = 86.0 +margin_bottom = 29.0 +rect_min_size = Vector2( 22, 22 ) +hint_tooltip = "Lock/unlock layer" +focus_mode = 0 +mouse_default_cursor_shape = 2 +size_flags_horizontal = 0 +size_flags_vertical = 4 + +[node name="TextureRect" type="TextureRect" parent="HBoxContainer/LayerButtons/LockButton"] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -11.0 +margin_top = -11.0 +margin_right = 11.0 +margin_bottom = 11.0 +size_flags_horizontal = 0 +size_flags_vertical = 0 +texture = ExtResource( 3 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Spacer" type="Control" parent="HBoxContainer"] +margin_left = 94.0 +margin_right = 122.0 +margin_bottom = 36.0 +rect_min_size = Vector2( 28, 0 ) +mouse_filter = 2 + +[node name="LayerName" type="HBoxContainer" parent="HBoxContainer"] +margin_left = 126.0 +margin_right = 230.0 +margin_bottom = 36.0 +rect_min_size = Vector2( 104, 0 ) +mouse_default_cursor_shape = 2 +size_flags_horizontal = 0 +alignment = 1 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="HierarchySpacer" type="Control" parent="HBoxContainer/LayerName"] +margin_bottom = 36.0 +mouse_filter = 2 + +[node name="Label" type="Label" parent="HBoxContainer/LayerName"] +margin_left = 4.0 +margin_top = 11.0 +margin_right = 104.0 +margin_bottom = 25.0 +size_flags_horizontal = 3 +text = "Layer 0" +clip_text = true + +[node name="LineEdit" type="LineEdit" parent="HBoxContainer/LayerName"] +visible = false +margin_left = 86.0 +margin_top = 5.0 +margin_right = 166.0 +margin_bottom = 37.0 +rect_min_size = Vector2( 80, 32 ) +size_flags_vertical = 4 +text = "Layer 0" +editable = false +caret_blink = true +caret_blink_speed = 0.5 + +[connection signal="gui_input" from="." to="." method="_on_LayerContainer_gui_input"] +[connection signal="pressed" from="HBoxContainer/LayerButtons/ExpandButton" to="." method="_on_ExpandButton_pressed"] +[connection signal="pressed" from="HBoxContainer/LayerButtons/VisibilityButton" to="." method="_on_VisibilityButton_pressed"] +[connection signal="pressed" from="HBoxContainer/LayerButtons/LockButton" to="." method="_on_LockButton_pressed"] +[connection signal="focus_exited" from="HBoxContainer/LayerName/LineEdit" to="." method="_on_LineEdit_focus_exited"] diff --git a/src/UI/Timeline/CelButton.gd b/src/UI/Timeline/PixelCelButton.gd similarity index 97% rename from src/UI/Timeline/CelButton.gd rename to src/UI/Timeline/PixelCelButton.gd index 206f5a339082..8c5832566798 100644 --- a/src/UI/Timeline/CelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -4,7 +4,7 @@ enum MenuOptions { DELETE, LINK, PROPERTIES } var frame := 0 var layer := 0 -var cel: Cel +var cel: PixelCel var image: Image onready var popup_menu: PopupMenu = $PopupMenu @@ -108,7 +108,7 @@ func _on_PopupMenu_id_pressed(id: int) -> void: var new_layers: Array = Global.current_project.duplicate_layers() var new_cels: Array = f.cels.duplicate() for i in new_cels.size(): - new_cels[i] = Cel.new( + new_cels[i] = PixelCel.new( new_cels[i].image, new_cels[i].opacity, new_cels[i].image_texture ) @@ -160,7 +160,7 @@ func _on_PopupMenu_id_pressed(id: int) -> void: func _delete_cel_content() -> void: if image.is_invisible(): return - var curr_layer: Layer = Global.current_project.layers[layer] + var curr_layer: PixelLayer = Global.current_project.layers[layer] if !curr_layer.can_layer_get_drawn(): return var project = Global.current_project @@ -188,11 +188,11 @@ func get_drag_data(_position) -> Array: button.add_child(texture_rect) set_drag_preview(button) - return ["Cel", frame, layer] + return ["PixelCel", frame, layer] func can_drop_data(_pos, data) -> bool: - if typeof(data) == TYPE_ARRAY and data[0] == "Cel": + if typeof(data) == TYPE_ARRAY and data[0] == "PixelCel": var new_frame = data[1] var new_layer = data[2] if ( diff --git a/src/UI/Timeline/CelButton.tscn b/src/UI/Timeline/PixelCelButton.tscn similarity index 96% rename from src/UI/Timeline/CelButton.tscn rename to src/UI/Timeline/PixelCelButton.tscn index 649c72da8c7c..0856f2c252e1 100644 --- a/src/UI/Timeline/CelButton.tscn +++ b/src/UI/Timeline/PixelCelButton.tscn @@ -1,11 +1,11 @@ [gd_scene load_steps=5 format=2] -[ext_resource path="res://src/UI/Timeline/CelButton.gd" type="Script" id=1] +[ext_resource path="res://src/Shaders/TransparentChecker.shader" type="Shader" id=1] [ext_resource path="res://src/UI/TransparentChecker.tscn" type="PackedScene" id=2] -[ext_resource path="res://src/Shaders/TransparentChecker.shader" type="Shader" id=3] +[ext_resource path="res://src/UI/Timeline/CelButton.gd" type="Script" id=3] [sub_resource type="ShaderMaterial" id=1] -shader = ExtResource( 3 ) +shader = ExtResource( 1 ) shader_param/size = 10.0 shader_param/alpha = 1.0 shader_param/color1 = Color( 0.7, 0.7, 0.7, 1 ) @@ -26,7 +26,7 @@ size_flags_horizontal = 0 size_flags_vertical = 0 toggle_mode = true button_mask = 7 -script = ExtResource( 1 ) +script = ExtResource( 3 ) __meta__ = { "_edit_use_anchors_": false } diff --git a/src/UI/Timeline/PixelLayerButton.gd b/src/UI/Timeline/PixelLayerButton.gd new file mode 100644 index 000000000000..f6b9cf73d40c --- /dev/null +++ b/src/UI/Timeline/PixelLayerButton.gd @@ -0,0 +1,25 @@ +class_name PixelLayerButton +extends BaseLayerButton + +onready var linked_button: BaseButton = find_node("LinkButton") + +func _ready() -> void: + if Global.current_project.layers[layer].new_cels_linked: # If new layers will be linked + Global.change_button_texturerect(linked_button.get_child(0), "linked_layer.png") + else: + Global.change_button_texturerect(linked_button.get_child(0), "unlinked_layer.png") + + +func _on_LinkButton_pressed() -> void: + Global.canvas.selection.transform_content_confirm() + var layer_class: PixelLayer = Global.current_project.layers[layer] + layer_class.new_cels_linked = !layer_class.new_cels_linked + if layer_class.new_cels_linked && !layer_class.linked_cels: + # If button is pressed and there are no linked cels in the layer + layer_class.linked_cels.append( + Global.current_project.frames[Global.current_project.current_frame] + ) + var container = Global.frames_container.get_child(Global.current_project.current_layer) + container.get_child(Global.current_project.current_frame).button_setup() + + Global.current_project.layers = Global.current_project.layers # Call the setter diff --git a/src/UI/Timeline/LayerButton.tscn b/src/UI/Timeline/PixelLayerButton.tscn similarity index 83% rename from src/UI/Timeline/LayerButton.tscn rename to src/UI/Timeline/PixelLayerButton.tscn index c17453134afa..ad9cc4af966b 100644 --- a/src/UI/Timeline/LayerButton.tscn +++ b/src/UI/Timeline/PixelLayerButton.tscn @@ -1,14 +1,14 @@ [gd_scene load_steps=5 format=2] -[ext_resource path="res://src/UI/Timeline/LayerButton.gd" type="Script" id=1] +[ext_resource path="res://src/UI/Timeline/PixelLayerButton.gd" type="Script" id=1] [ext_resource path="res://assets/graphics/layers/layer_visible.png" type="Texture" id=2] [ext_resource path="res://assets/graphics/layers/unlock.png" type="Texture" id=3] [ext_resource path="res://assets/graphics/layers/unlinked_layer.png" type="Texture" id=4] -[node name="LayerContainer" type="Button"] -margin_right = 210.0 +[node name="PixelLayerContainer" type="Button"] +margin_right = 236.0 margin_bottom = 36.0 -rect_min_size = Vector2( 212, 36 ) +rect_min_size = Vector2( 236, 36 ) mouse_default_cursor_shape = 2 size_flags_horizontal = 0 toggle_mode = true @@ -27,16 +27,19 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="EmptySpacer" type="Control" parent="HBoxContainer"] +[node name="Spacer" type="Control" parent="HBoxContainer"] +margin_right = 32.0 margin_bottom = 36.0 +rect_min_size = Vector2( 32, 0 ) +mouse_filter = 2 [node name="LayerButtons" type="HBoxContainer" parent="HBoxContainer"] -margin_left = 4.0 -margin_right = 90.0 +margin_left = 36.0 +margin_right = 122.0 margin_bottom = 36.0 custom_constants/separation = 10 -[node name="VisibilityButton" type="Button" parent="HBoxContainer/LayerButtons" groups=["UIButtons"]] +[node name="VisibilityButton" type="ToolButton" parent="HBoxContainer/LayerButtons" groups=["UIButtons"]] margin_top = 7.0 margin_right = 22.0 margin_bottom = 29.0 @@ -63,7 +66,7 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="LockButton" type="Button" parent="HBoxContainer/LayerButtons" groups=["UIButtons"]] +[node name="LockButton" type="ToolButton" parent="HBoxContainer/LayerButtons" groups=["UIButtons"]] margin_left = 32.0 margin_top = 7.0 margin_right = 54.0 @@ -91,7 +94,7 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="LinkButton" type="Button" parent="HBoxContainer/LayerButtons" groups=["UIButtons"]] +[node name="LinkButton" type="ToolButton" parent="HBoxContainer/LayerButtons" groups=["UIButtons"]] margin_left = 64.0 margin_top = 7.0 margin_right = 86.0 @@ -122,8 +125,8 @@ __meta__ = { } [node name="LayerName" type="HBoxContainer" parent="HBoxContainer"] -margin_left = 94.0 -margin_right = 198.0 +margin_left = 126.0 +margin_right = 230.0 margin_bottom = 36.0 rect_min_size = Vector2( 104, 0 ) mouse_default_cursor_shape = 2 @@ -133,13 +136,17 @@ __meta__ = { "_edit_use_anchors_": false } +[node name="HierarchySpacer" type="Control" parent="HBoxContainer/LayerName"] +margin_bottom = 36.0 +mouse_filter = 2 + [node name="Label" type="Label" parent="HBoxContainer/LayerName"] +margin_left = 4.0 margin_top = 11.0 margin_right = 104.0 margin_bottom = 25.0 size_flags_horizontal = 3 text = "Layer 0" -align = 1 clip_text = true [node name="LineEdit" type="LineEdit" parent="HBoxContainer/LayerName"] From 031813b61b84c372c27a08e64edd118de5558462 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 6 May 2022 10:41:10 -0400 Subject: [PATCH 004/154] Some quick fixes to make it work again --- src/Classes/BaseCel.gd | 1 + src/Classes/GroupCel.gd | 3 --- src/Classes/GroupLayer.gd | 2 -- src/UI/Canvas/Canvas.gd | 10 +++++++--- src/UI/Canvas/CanvasPreview.gd | 4 +++- src/UI/Canvas/CurrentFrameDrawer.gd | 4 +++- src/UI/Timeline/PixelCelButton.tscn | 2 +- 7 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/Classes/BaseCel.gd b/src/Classes/BaseCel.gd index ab4da102a239..82c6f46dec44 100644 --- a/src/Classes/BaseCel.gd +++ b/src/Classes/BaseCel.gd @@ -5,6 +5,7 @@ extends Reference var opacity: float +# TODO: Should this be the case? # Each Cel type should have a get_image function, which will either return # its image data for PixelCels, or return a render of that cel. It's meant # for read-only usage of image data from any type of cel diff --git a/src/Classes/GroupCel.gd b/src/Classes/GroupCel.gd index 38cef8bcfefe..fdac4931de59 100644 --- a/src/Classes/GroupCel.gd +++ b/src/Classes/GroupCel.gd @@ -3,10 +3,7 @@ extends BaseCel # A class for the properties of cels in GroupLayers. # The term "cel" comes from "celluloid" (https://en.wikipedia.org/wiki/Cel). -var material := ShaderMaterial.new() - func _init(_opacity := 1.0) -> void: - print("group cel added") opacity = _opacity diff --git a/src/Classes/GroupLayer.gd b/src/Classes/GroupLayer.gd index 8b11b117c08e..f781eda2fbce 100644 --- a/src/Classes/GroupLayer.gd +++ b/src/Classes/GroupLayer.gd @@ -4,8 +4,6 @@ extends BaseLayer #var children := [] var expanded := true -var blend_shader: Shader - func _init(_name := "") -> void: name = _name diff --git a/src/UI/Canvas/Canvas.gd b/src/UI/Canvas/Canvas.gd index 902b684f38e4..80597e8c6fa3 100644 --- a/src/UI/Canvas/Canvas.gd +++ b/src/UI/Canvas/Canvas.gd @@ -38,8 +38,10 @@ func _draw() -> void: draw_set_transform(position_tmp, rotation, scale_tmp) # Draw current frame layers for i in range(Global.current_project.layers.size()): + if current_cels[i] is GroupCel: + continue var modulate_color := Color(1, 1, 1, current_cels[i].opacity) - if Global.current_project.layers[i].visible: # if it's visible + if Global.current_project.layers[i].is_visible_in_hierarchy(): if i == current_layer: draw_texture(current_cels[i].image_texture, move_preview_location, modulate_color) else: @@ -108,7 +110,8 @@ func update_texture(layer_i: int, frame_i := -1, project: Project = Global.curre frame_i = project.current_frame if frame_i < project.frames.size() and layer_i < project.layers.size(): - var current_cel: Cel = project.frames[frame_i].cels[layer_i] + # TODO: make sure this is right: + var current_cel: PixelCel = project.frames[frame_i].cels[layer_i] current_cel.image_texture.set_data(current_cel.image) if project == Global.current_project: @@ -125,7 +128,8 @@ func update_selected_cels_textures(project: Project = Global.current_project) -> var frame_index: int = cel_index[0] var layer_index: int = cel_index[1] if frame_index < project.frames.size() and layer_index < project.layers.size(): - var current_cel: Cel = project.frames[frame_index].cels[layer_index] + # TODO: make sure this is right: + var current_cel: PixelCel = project.frames[frame_index].cels[layer_index] current_cel.image_texture.set_data(current_cel.image) if project == Global.current_project: diff --git a/src/UI/Canvas/CanvasPreview.gd b/src/UI/Canvas/CanvasPreview.gd index 5a459ca400a7..ab61f7ae247b 100644 --- a/src/UI/Canvas/CanvasPreview.gd +++ b/src/UI/Canvas/CanvasPreview.gd @@ -20,8 +20,10 @@ func _draw() -> void: # Draw current frame layers for i in range(current_cels.size()): + if current_cels[i] is GroupCel: + continue var modulate_color := Color(1, 1, 1, current_cels[i].opacity) - if i < current_project.layers.size() and current_project.layers[i].visible: + if i < current_project.layers.size() and current_project.layers[i].is_visible_in_hierarchy(): draw_texture(current_cels[i].image_texture, Vector2.ZERO, modulate_color) diff --git a/src/UI/Canvas/CurrentFrameDrawer.gd b/src/UI/Canvas/CurrentFrameDrawer.gd index e102a58adb78..4285f2dd80e6 100644 --- a/src/UI/Canvas/CurrentFrameDrawer.gd +++ b/src/UI/Canvas/CurrentFrameDrawer.gd @@ -4,6 +4,8 @@ extends Node2D func _draw() -> void: var current_cels: Array = Global.current_project.frames[Global.current_project.current_frame].cels for i in range(Global.current_project.layers.size()): - if Global.current_project.layers[i].visible and current_cels[i].opacity > 0: + if current_cels[i] is GroupCel: + continue + if Global.current_project.layers[i].is_visible_in_hierarchy() and current_cels[i].opacity > 0: var modulate_color := Color(1, 1, 1, current_cels[i].opacity) draw_texture(current_cels[i].image_texture, Vector2.ZERO, modulate_color) diff --git a/src/UI/Timeline/PixelCelButton.tscn b/src/UI/Timeline/PixelCelButton.tscn index 0856f2c252e1..34ead37a6abb 100644 --- a/src/UI/Timeline/PixelCelButton.tscn +++ b/src/UI/Timeline/PixelCelButton.tscn @@ -2,7 +2,7 @@ [ext_resource path="res://src/Shaders/TransparentChecker.shader" type="Shader" id=1] [ext_resource path="res://src/UI/TransparentChecker.tscn" type="PackedScene" id=2] -[ext_resource path="res://src/UI/Timeline/CelButton.gd" type="Script" id=3] +[ext_resource path="res://src/UI/Timeline/PixelCelButton.gd" type="Script" id=3] [sub_resource type="ShaderMaterial" id=1] shader = ExtResource( 1 ) From ed33874070497d8818cb936d96614569c76690a4 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 6 May 2022 18:29:26 -0400 Subject: [PATCH 005/154] Fixed some of the places where GroupLayers cause errors. Cel Buttons are now hidden when groups are collapsed --- src/Autoload/Export.gd | 3 ++- src/Autoload/Global.gd | 14 ++++++++------ src/Classes/Project.gd | 16 ++++++++-------- src/Tools/BaseTool.gd | 3 ++- src/Tools/Draw.gd | 2 ++ src/UI/Timeline/GroupCelButton.gd | 5 +++++ src/UI/Timeline/PixelCelButton.gd | 5 +++++ 7 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/Autoload/Export.gd b/src/Autoload/Export.gd index 3d80013e2345..78c00b49c32c 100644 --- a/src/Autoload/Export.gd +++ b/src/Autoload/Export.gd @@ -380,7 +380,8 @@ func blend_layers(image: Image, frame: Frame, origin: Vector2 = Vector2(0, 0)) - image.lock() var layer_i := 0 for cel in frame.cels: - if Global.current_project.layers[layer_i].visible: + # TODO: Check + if Global.current_project.layers[layer_i].visible and not cel is GroupCel: var cel_image := Image.new() cel_image.copy_from(cel.image) cel_image.lock() diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index d606198ba5d2..ce165d2b3dd9 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -232,12 +232,14 @@ func undo_or_redo( "Unlink Cel" ] ): - if layer_index > -1 and frame_index > -1: - canvas.update_texture(layer_index, frame_index, project) - else: - for i in project.frames.size(): - for j in project.layers.size(): - canvas.update_texture(j, i, project) + # TODO: Check this: + if not current_project.layers[layer_index] is GroupLayer: + if layer_index > -1 and frame_index > -1: + canvas.update_texture(layer_index, frame_index, project) + else: + for i in project.frames.size(): + for j in project.layers.size(): + canvas.update_texture(j, i, project) canvas.selection.update() if action_name == "Scale": diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 71fa4d04e7f7..12e4210982e2 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -460,13 +460,13 @@ func _frames_changed(value: Array) -> void: layer_cel_container.name = "FRAMESS " + str(i) Global.frames_container.add_child(layer_cel_container) for j in range(frames.size()): - if layers[j] is PixelLayer: + if layers[i] is PixelLayer: var cel_button = pixel_cel_button_node.instance() cel_button.frame = j cel_button.layer = i cel_button.get_child(0).texture = frames[j].cels[i].image_texture layer_cel_container.add_child(cel_button) - elif layers[j] is GroupLayer: + elif layers[i] is GroupLayer: # TODO: Make GroupLayers work here pass @@ -514,15 +514,15 @@ func _layers_changed(value: Array) -> void: Global.frames_container.add_child(layer_cel_container) # TODO: FIGURE OUT FRAMES WITH GROUP LAYERS! for j in range(frames.size()): + var cel_button # TODO: Figure out static typing (will there be a BaseCelButton?) if layers[i] is PixelLayer: - var cel_button = pixel_cel_button_node.instance() - cel_button.frame = j - cel_button.layer = i + cel_button = pixel_cel_button_node.instance() cel_button.get_child(0).texture = frames[j].cels[i].image_texture - layer_cel_container.add_child(cel_button) elif layers[i] is GroupLayer: - var cel_button = group_cel_button_node.instance() - layer_cel_container.add_child(cel_button) + cel_button = group_cel_button_node.instance() + cel_button.frame = j + cel_button.layer = i + layer_cel_container.add_child(cel_button) var layer_button = Global.layers_container.get_child( Global.layers_container.get_child_count() - 1 - current_layer diff --git a/src/Tools/BaseTool.gd b/src/Tools/BaseTool.gd index f98272e13cdd..a439f6f29221 100644 --- a/src/Tools/BaseTool.gd +++ b/src/Tools/BaseTool.gd @@ -88,7 +88,8 @@ func _get_selected_draw_images() -> Array: # Array of Images var images := [] var project: Project = Global.current_project for cel_index in project.selected_cels: - var cel: PixelCel = project.frames[cel_index[0]].cels[cel_index[1]] + # TODO: Check this: (BaseCel is fine because it asks can_layer_get_drawn) + var cel: BaseCel = project.frames[cel_index[0]].cels[cel_index[1]] if project.layers[cel_index[1]].can_layer_get_drawn(): images.append(cel.image) return images diff --git a/src/Tools/Draw.gd b/src/Tools/Draw.gd index a1aacb11842a..1cafd9dbe93b 100644 --- a/src/Tools/Draw.gd +++ b/src/Tools/Draw.gd @@ -542,6 +542,8 @@ func _get_undo_data() -> Dictionary: var cel: PixelCel = frame.cels[project.current_layer] cels.append(cel) for cel in cels: + if cel is GroupCel: + continue var image: Image = cel.image image.unlock() data[image] = image.data diff --git a/src/UI/Timeline/GroupCelButton.gd b/src/UI/Timeline/GroupCelButton.gd index 080bd324f5f7..6b84095ebdfc 100644 --- a/src/UI/Timeline/GroupCelButton.gd +++ b/src/UI/Timeline/GroupCelButton.gd @@ -24,6 +24,11 @@ func button_setup() -> void: # cel = Global.current_project.frames[frame].cels[layer] #image = cel.image + # TODO: Check formatting: + if (is_instance_valid(Global.current_project.layers[layer].parent) + and not Global.current_project.layers[layer].parent.is_expanded_in_hierarchy()): + visible = false + func _on_GroupCelButton_resized() -> void: get_node("CelShader").rect_min_size.x = rect_min_size.x - 4 diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index 8c5832566798..49806eb2271a 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -34,6 +34,11 @@ func button_setup() -> void: cel = Global.current_project.frames[frame].cels[layer] image = cel.image + # TODO: Check formatting: + if (is_instance_valid(Global.current_project.layers[layer].parent) + and not Global.current_project.layers[layer].parent.is_expanded_in_hierarchy()): + visible = false + func _on_CelButton_resized() -> void: get_node("CelTexture").rect_min_size.x = rect_min_size.x - 4 From 2bbc3039ac8d97c3487fa4e6420238c46247c912 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sun, 8 May 2022 15:12:30 -0400 Subject: [PATCH 006/154] Layer drag highlighting (need to actually drop them correctly, also need to do cels) --- src/Classes/BaseLayer.gd | 4 +++ src/Classes/GroupLayer.gd | 5 ++- src/UI/Timeline/AnimationTimeline.gd | 18 +++++++++-- src/UI/Timeline/AnimationTimeline.tscn | 38 ++++++++++++++-------- src/UI/Timeline/BaseLayerButton.gd | 45 +++++++++++++++++++++++--- 5 files changed, 88 insertions(+), 22 deletions(-) diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index 0a1e5ce05165..4773c1d1aa6b 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -34,6 +34,10 @@ func can_layer_get_drawn() -> bool: return false +func accepts_child(layer: BaseLayer) -> bool: + return false + + # TODO: Search for layer visbility/locked checks that should be changed to the hierarchy ones: func is_visible_in_hierarchy() -> bool: if is_instance_valid(parent) and visible: diff --git a/src/Classes/GroupLayer.gd b/src/Classes/GroupLayer.gd index f781eda2fbce..ecf2abcee14f 100644 --- a/src/Classes/GroupLayer.gd +++ b/src/Classes/GroupLayer.gd @@ -2,7 +2,6 @@ class_name GroupLayer extends BaseLayer # A class for group layer properties -#var children := [] var expanded := true func _init(_name := "") -> void: @@ -21,6 +20,10 @@ func deserialize(dict: Dictionary) -> void: expanded = dict.expanded +func accepts_child(layer: BaseLayer) -> bool: + return true + + func is_expanded_in_hierarchy() -> bool: if is_instance_valid(parent) and expanded: return parent.is_expanded_in_hierarchy() diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index a9ed5c21ad01..ec298a69428c 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -23,6 +23,7 @@ onready var tag_scroll_container: ScrollContainer = find_node("TagScroll") onready var fps_spinbox: SpinBox = find_node("FPSValue") onready var onion_skinning_button: BaseButton = find_node("OnionSkinning") onready var loop_animation_button: BaseButton = find_node("LoopAnim") +onready var drag_highlight: ColorRect = find_node("DragHighlight") func _ready() -> void: @@ -36,6 +37,16 @@ func _ready() -> void: timeline_scroll.size_flags_horizontal = SIZE_FILL +func _notification(what: int) -> void: + if what == NOTIFICATION_DRAG_END: + drag_highlight.hide() + +func can_drop_data(_position, _data) -> bool: + drag_highlight.hide() + print ("can drag?") + return false + + func _input(event: InputEvent) -> void: var mouse_pos := get_global_mouse_position() var timeline_rect := Rect2(rect_global_position, rect_size) @@ -656,12 +667,13 @@ func add_group_layer(is_new := true) -> void: # + ")" # ) new_layers.append(l) + # Add current layer to this group # Global.current_project.layers[Global.current_project.current_layer].parent = l # Add all layers to this group: - for layer in Global.current_project.layers: - if not layer.parent: - layer.parent = l +# for layer in Global.current_project.layers: +# if not layer.parent: +# layer.parent = l # Add last layer to this group: # Global.current_project.layers[-1].parent = l diff --git a/src/UI/Timeline/AnimationTimeline.tscn b/src/UI/Timeline/AnimationTimeline.tscn index 5c0f3528b85c..665795502bb2 100644 --- a/src/UI/Timeline/AnimationTimeline.tscn +++ b/src/UI/Timeline/AnimationTimeline.tscn @@ -131,14 +131,15 @@ margin_bottom = 38.0 size_flags_horizontal = 3 [node name="LayerButtonPanelContainer" type="PanelContainer" parent="ScrollContainer/TimelineContainer/TimelineButtons"] -margin_right = 217.0 +margin_right = 190.0 margin_bottom = 38.0 +rect_min_size = Vector2( 190, 0 ) custom_styles/panel = SubResource( 2 ) [node name="LayerButtons" type="HBoxContainer" parent="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer"] margin_left = 4.5 margin_top = 3.0 -margin_right = 212.5 +margin_right = 185.5 margin_bottom = 25.0 size_flags_vertical = 0 custom_constants/separation = 9 @@ -218,6 +219,7 @@ __meta__ = { } [node name="MoveUpLayer" type="Button" parent="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]] +visible = false margin_left = 93.0 margin_right = 115.0 margin_bottom = 22.0 @@ -244,8 +246,9 @@ __meta__ = { } [node name="MoveDownLayer" type="Button" parent="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]] -margin_left = 124.0 -margin_right = 146.0 +visible = false +margin_left = 93.0 +margin_right = 115.0 margin_bottom = 22.0 rect_min_size = Vector2( 22, 22 ) hint_tooltip = "Move down the current layer" @@ -270,8 +273,8 @@ __meta__ = { } [node name="CloneLayer" type="Button" parent="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]] -margin_left = 155.0 -margin_right = 177.0 +margin_left = 93.0 +margin_right = 115.0 margin_bottom = 22.0 rect_min_size = Vector2( 22, 22 ) hint_tooltip = "Clone current layer" @@ -295,8 +298,8 @@ __meta__ = { } [node name="MergeDownLayer" type="Button" parent="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]] -margin_left = 186.0 -margin_right = 208.0 +margin_left = 124.0 +margin_right = 146.0 margin_bottom = 22.0 rect_min_size = Vector2( 22, 22 ) hint_tooltip = "Merge current layer with the one below" @@ -321,7 +324,7 @@ __meta__ = { } [node name="Control" type="Control" parent="ScrollContainer/TimelineContainer/TimelineButtons"] -margin_left = 221.0 +margin_left = 194.0 margin_right = 386.0 margin_bottom = 38.0 size_flags_horizontal = 3 @@ -821,12 +824,12 @@ align = 1 [node name="SpacerControl2" type="Control" parent="ScrollContainer/TimelineContainer/OpacityAndTagContainer"] margin_left = 188.0 -margin_right = 217.0 +margin_right = 240.0 margin_bottom = 32.0 -rect_min_size = Vector2( 29, 0 ) +rect_min_size = Vector2( 52, 32 ) [node name="TagScroll" type="ScrollContainer" parent="ScrollContainer/TimelineContainer/OpacityAndTagContainer"] -margin_left = 219.0 +margin_left = 242.0 margin_right = 902.0 margin_bottom = 32.0 rect_min_size = Vector2( 0, 32 ) @@ -836,7 +839,7 @@ theme = SubResource( 20 ) scroll_vertical_enabled = false [node name="HBoxContainer" type="HBoxContainer" parent="ScrollContainer/TimelineContainer/OpacityAndTagContainer/TagScroll"] -margin_right = 683.0 +margin_right = 660.0 margin_bottom = 32.0 size_flags_horizontal = 3 size_flags_vertical = 3 @@ -846,7 +849,7 @@ custom_constants/separation = 0 margin_bottom = 32.0 [node name="TagContainer" type="Control" parent="ScrollContainer/TimelineContainer/OpacityAndTagContainer/TagScroll/HBoxContainer"] -margin_right = 683.0 +margin_right = 660.0 margin_bottom = 32.0 size_flags_horizontal = 3 @@ -1032,6 +1035,13 @@ autowrap = true [node name="FrameTagDialog" parent="." instance=ExtResource( 42 )] +[node name="DragHighlight" type="ColorRect" parent="."] +visible = false +margin_right = 40.0 +margin_bottom = 40.0 +mouse_filter = 2 +color = Color( 0, 0.741176, 1, 0.501961 ) + [connection signal="item_rect_changed" from="." to="." method="_on_AnimationTimeline_item_rect_changed"] [connection signal="item_rect_changed" from="ScrollContainer/TimelineContainer" to="." method="_on_TimelineContainer_item_rect_changed"] [connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/AddLayer" to="." method="add_layer" binds= [ true ]] diff --git a/src/UI/Timeline/BaseLayerButton.gd b/src/UI/Timeline/BaseLayerButton.gd index ca087d1d4e7e..72c506a864a1 100644 --- a/src/UI/Timeline/BaseLayerButton.gd +++ b/src/UI/Timeline/BaseLayerButton.gd @@ -1,6 +1,8 @@ class_name BaseLayerButton extends Button +const HIERARCHY_DEPTH_PIXEL_SHIFT = 8 + var layer := 0 onready var visibility_button: BaseButton = find_node("VisibilityButton") @@ -35,7 +37,7 @@ func _ready() -> void: # Visualize how deep into the hierarchy the layer is var hierarchy_depth: int = Global.current_project.layers[layer].get_hierarchy_depth() - hierarchy_spacer.rect_min_size.x = hierarchy_depth * 8 + hierarchy_spacer.rect_min_size.x = hierarchy_depth * HIERARCHY_DEPTH_PIXEL_SHIFT if Global.control.theme.get_color("font_color", "Button").v > 0.5: # Light text is dark theme self_modulate.v += hierarchy_depth * 0.2 else: # Dark text should be light theme @@ -138,9 +140,37 @@ func get_drag_data(_position) -> Array: func can_drop_data(_pos, data) -> bool: if typeof(data) == TYPE_ARRAY: - return data[0] == "Layer" - else: - return false + if data[0] == "Layer": + var region: Rect2 + var depth: int = Global.current_project.layers[layer].get_hierarchy_depth() + if Input.is_key_pressed(KEY_CONTROL): # Swap layers + region = get_global_rect() + else: # Shift layers + if Global.current_project.layers[layer].accepts_child(data[1]): + # Top, center, or bottom region? + if _get_region_rect(0, 0.25).has_point(get_global_mouse_position()): + # Drawn regions are shifted up/down a bit from actual for visual clearity + region = _get_region_rect(-0.1, 0.25) + elif _get_region_rect(0.25, 0.5).has_point(get_global_mouse_position()): + region = _get_region_rect(0.15, 0.7) + depth += 1 + else: + region = _get_region_rect(0.85, 0.25) + else: + # Top or bottom region? + if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): + region = _get_region_rect(-0.1, 0.25) + else: + region = _get_region_rect(0.85, 0.25) + # Shift drawn region to the right a bit for hierarchy depth visualization: + region.position.x += depth * HIERARCHY_DEPTH_PIXEL_SHIFT + region.size.x -= depth * HIERARCHY_DEPTH_PIXEL_SHIFT + Global.animation_timeline.drag_highlight.rect_global_position = region.position + Global.animation_timeline.drag_highlight.rect_size = region.size + Global.animation_timeline.drag_highlight.show() + return true + Global.animation_timeline.drag_highlight.hide() + return false func drop_data(_pos, data) -> void: @@ -177,3 +207,10 @@ func drop_data(_pos, data) -> void: Global.current_project.undo_redo.add_undo_method(Global, "undo_or_redo", true) Global.current_project.undo_redo.add_do_method(Global, "undo_or_redo", false) Global.current_project.undo_redo.commit_action() + + +func _get_region_rect(y_offset: float, y_size: float) -> Rect2: + var rect := get_global_rect() + rect.position.y += rect.size.y * y_offset + rect.size.y *= y_size + return rect From 0e96c9fbef2be5f0ceec6fa396fa2b7d6117ef84 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sun, 8 May 2022 16:43:58 -0400 Subject: [PATCH 007/154] Added more layer hierarchy related functions, organized the function order in the Layer classes a bit --- src/Classes/BaseLayer.gd | 40 ++++++++++++++++++---------------- src/Classes/GroupLayer.gd | 46 ++++++++++++++++++++++++++++++++++----- src/Classes/PixelLayer.gd | 2 ++ 3 files changed, 63 insertions(+), 25 deletions(-) diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index 4773c1d1aa6b..94f1a6ea6069 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -10,6 +10,27 @@ var parent: BaseLayer var project var index: int +# TODO: Search for layer visbility/locked checks that should be changed to the hierarchy ones: +func is_visible_in_hierarchy() -> bool: + if is_instance_valid(parent) and visible: + return parent.is_visible_in_hierarchy() + return visible + + +func is_locked_in_hierarchy() -> bool: + if is_instance_valid(parent) and not locked: + return parent.is_locked_in_hierarchy() + return locked + + +func get_hierarchy_depth() -> int: + if is_instance_valid(parent): + return parent.get_hierarchy_depth() + 1 + return 0 + + +# Functions to Override: + func serialize() -> Dictionary: assert(index == project.layers.find(self)) # TODO: remove once sure index is synced properly return { @@ -36,22 +57,3 @@ func can_layer_get_drawn() -> bool: func accepts_child(layer: BaseLayer) -> bool: return false - - -# TODO: Search for layer visbility/locked checks that should be changed to the hierarchy ones: -func is_visible_in_hierarchy() -> bool: - if is_instance_valid(parent) and visible: - return parent.is_visible_in_hierarchy() - return visible - - -func is_locked_in_hierarchy() -> bool: - if is_instance_valid(parent) and not locked: - return parent.is_locked_in_hierarchy() - return locked - - -func get_hierarchy_depth() -> int: - if is_instance_valid(parent): - return parent.get_hierarchy_depth() + 1 - return 0 diff --git a/src/Classes/GroupLayer.gd b/src/Classes/GroupLayer.gd index ecf2abcee14f..664c363659db 100644 --- a/src/Classes/GroupLayer.gd +++ b/src/Classes/GroupLayer.gd @@ -8,6 +8,46 @@ func _init(_name := "") -> void: name = _name +func is_expanded_in_hierarchy() -> bool: + if is_instance_valid(parent) and expanded: + return parent.is_expanded_in_hierarchy() + return expanded + + +func is_an_ancestor_of(layer: BaseLayer) -> bool: + if layer.parent == self: + return true + elif is_instance_valid(layer.parent): + return is_an_ancestor_of(layer.parent) + return false + +# Only gets direct children +func get_children() -> Array: + var children := [] + # TODO: Consider going backwards, to allow breaking + for i in range(index): + if project.layers[i].parent == self: + children.append(project.layers[i]) + return children + +# Gets both direct AND indirect children +func get_successors() -> Array: + var successors := [] + # TODO: Consider going backwards, to allow breaking + for i in range(index): + if is_an_ancestor_of(project.layers[i]): + successors.append(project.layers[i]) + return successors + + +func has_children() -> bool: + if index == 0: + return false + return project.layers[index - 1].parent == self + + +# Overridden Functions: + func serialize() -> Dictionary: var data = .serialize() data["type"] = "group" @@ -22,9 +62,3 @@ func deserialize(dict: Dictionary) -> void: func accepts_child(layer: BaseLayer) -> bool: return true - - -func is_expanded_in_hierarchy() -> bool: - if is_instance_valid(parent) and expanded: - return parent.is_expanded_in_hierarchy() - return expanded diff --git a/src/Classes/PixelLayer.gd b/src/Classes/PixelLayer.gd index 41d5a6766de4..83ed2e5e089e 100644 --- a/src/Classes/PixelLayer.gd +++ b/src/Classes/PixelLayer.gd @@ -30,5 +30,7 @@ func deserialize(dict: Dictionary) -> void: linked_cel.image_texture = linked_cels[0].cels[index].image_texture +# Overridden Functions: + func can_layer_get_drawn() -> bool: return is_visible_in_hierarchy() && !is_locked_in_hierarchy() From 3b33d8010293c6541d73335ada8b90bd8ee5696a Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sun, 8 May 2022 17:13:53 -0400 Subject: [PATCH 008/154] Switched the layer type changing from string to int --- src/Classes/BaseLayer.gd | 2 ++ src/Classes/GroupLayer.gd | 2 +- src/Classes/PixelLayer.gd | 2 +- src/Classes/Project.gd | 10 +++++----- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index 94f1a6ea6069..92c9c403db9d 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -2,6 +2,8 @@ class_name BaseLayer extends Reference # Base class for layer properties. Different layer types extend from this class. +enum { PIXEL_LAYER = 0, GROUP_LAYER = 1 } + var name := "" var visible := true var locked := false diff --git a/src/Classes/GroupLayer.gd b/src/Classes/GroupLayer.gd index 664c363659db..36cd26b4dfcf 100644 --- a/src/Classes/GroupLayer.gd +++ b/src/Classes/GroupLayer.gd @@ -50,7 +50,7 @@ func has_children() -> bool: func serialize() -> Dictionary: var data = .serialize() - data["type"] = "group" + data["type"] = GROUP_LAYER data["expanded"] = expanded return data diff --git a/src/Classes/PixelLayer.gd b/src/Classes/PixelLayer.gd index 83ed2e5e089e..d25a6a8f2b99 100644 --- a/src/Classes/PixelLayer.gd +++ b/src/Classes/PixelLayer.gd @@ -11,7 +11,7 @@ func _init(_name := "") -> void: func serialize() -> Dictionary: var dict = .serialize() - dict["type"] = "pixel" + dict["type"] = PIXEL_LAYER dict["new_cels_linked"] = new_cels_linked dict["linked_cels"] = [] for cel in linked_cels: diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 12e4210982e2..90aaf9d5cb4d 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -390,10 +390,10 @@ func deserialize(dict: Dictionary) -> void: if dict.has("layers"): for saved_layer in dict.layers: - match saved_layer.get("type", "pixel"): - "pixel": + match int(saved_layer.get("type", BaseLayer.PIXEL_LAYER)): + BaseLayer.PIXEL_LAYER: layers.append(PixelLayer.new()) - "group": + BaseLayer.GROUP_LAYER: layers.append(GroupLayer.new()) # Parent references to other layers are created when deserializing # a layer, so loop again after creating them. @@ -722,9 +722,9 @@ func duplicate_layers() -> Array: var layer_dict: Dictionary = new_layers[i].serialize() #layer_dict.linked_cels = new_layers[i].linked_cels.duplicate() match layer_dict.type: - "pixel": + BaseLayer.PIXEL_LAYER: new_layers[i] = PixelLayer.new() - "group": + BaseLayer.GROUP_LAYER: new_layers[i] = GroupLayer.new() new_layers[i].index = i new_layers[i].project = self From 831818c789e285d5a2bc6d6dcebc733fa48b254c Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sun, 8 May 2022 17:21:30 -0400 Subject: [PATCH 009/154] Moved layer type enum to Global --- src/Autoload/Global.gd | 1 + src/Classes/BaseLayer.gd | 2 -- src/Classes/GroupLayer.gd | 2 +- src/Classes/PixelLayer.gd | 2 +- src/Classes/Project.gd | 10 +++++----- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index ce165d2b3dd9..143a5982dd3b 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -2,6 +2,7 @@ extends Node signal project_changed +enum LayerTypes { PIXEL, GROUP } enum GridTypes { CARTESIAN, ISOMETRIC, ALL } enum PressureSensitivity { NONE, ALPHA, SIZE, ALPHA_AND_SIZE } enum TileMode { NONE, BOTH, X_AXIS, Y_AXIS } diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index 92c9c403db9d..94f1a6ea6069 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -2,8 +2,6 @@ class_name BaseLayer extends Reference # Base class for layer properties. Different layer types extend from this class. -enum { PIXEL_LAYER = 0, GROUP_LAYER = 1 } - var name := "" var visible := true var locked := false diff --git a/src/Classes/GroupLayer.gd b/src/Classes/GroupLayer.gd index 36cd26b4dfcf..91db76de13b9 100644 --- a/src/Classes/GroupLayer.gd +++ b/src/Classes/GroupLayer.gd @@ -50,7 +50,7 @@ func has_children() -> bool: func serialize() -> Dictionary: var data = .serialize() - data["type"] = GROUP_LAYER + data["type"] = Global.LayerTypes.GROUP data["expanded"] = expanded return data diff --git a/src/Classes/PixelLayer.gd b/src/Classes/PixelLayer.gd index d25a6a8f2b99..446e12952879 100644 --- a/src/Classes/PixelLayer.gd +++ b/src/Classes/PixelLayer.gd @@ -11,7 +11,7 @@ func _init(_name := "") -> void: func serialize() -> Dictionary: var dict = .serialize() - dict["type"] = PIXEL_LAYER + dict["type"] = Global.LayerTypes.PIXEL dict["new_cels_linked"] = new_cels_linked dict["linked_cels"] = [] for cel in linked_cels: diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 90aaf9d5cb4d..a413733bb5e0 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -390,10 +390,10 @@ func deserialize(dict: Dictionary) -> void: if dict.has("layers"): for saved_layer in dict.layers: - match int(saved_layer.get("type", BaseLayer.PIXEL_LAYER)): - BaseLayer.PIXEL_LAYER: + match int(saved_layer.get("type", Global.LayerTypes.PIXEL)): + Global.LayerTypes.PIXEL: layers.append(PixelLayer.new()) - BaseLayer.GROUP_LAYER: + Global.LayerTypes.GROUP: layers.append(GroupLayer.new()) # Parent references to other layers are created when deserializing # a layer, so loop again after creating them. @@ -722,9 +722,9 @@ func duplicate_layers() -> Array: var layer_dict: Dictionary = new_layers[i].serialize() #layer_dict.linked_cels = new_layers[i].linked_cels.duplicate() match layer_dict.type: - BaseLayer.PIXEL_LAYER: + Global.LayerTypes.PIXEL: new_layers[i] = PixelLayer.new() - BaseLayer.GROUP_LAYER: + Global.LayerTypes.GROUP: new_layers[i] = GroupLayer.new() new_layers[i].index = i new_layers[i].project = self From 1e6a74f8c77dc361d41c35134b5f9ba83adef86c Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sun, 8 May 2022 17:34:10 -0400 Subject: [PATCH 010/154] Added get_layer_type_name(), currently used for the default layer name --- Translations/Translations.pot | 3 +++ src/Classes/BaseLayer.gd | 4 ++++ src/Classes/GroupLayer.gd | 4 ++++ src/Classes/PixelLayer.gd | 4 ++++ src/Classes/Project.gd | 4 ++-- 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Translations/Translations.pot b/Translations/Translations.pot index ad0e39f07bfa..94c7bfcf5fae 100644 --- a/Translations/Translations.pot +++ b/Translations/Translations.pot @@ -1413,6 +1413,9 @@ msgstr "" msgid "Layer" msgstr "" +msgid "Group" +msgstr "" + msgid "Layers" msgstr "" diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index 94f1a6ea6069..624b1d7b588c 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -51,6 +51,10 @@ func deserialize(dict: Dictionary) -> void: parent = project.layers[dict.parent] +func get_layer_type_name() -> String: + return "Base" + + func can_layer_get_drawn() -> bool: return false diff --git a/src/Classes/GroupLayer.gd b/src/Classes/GroupLayer.gd index 91db76de13b9..fe14968082e3 100644 --- a/src/Classes/GroupLayer.gd +++ b/src/Classes/GroupLayer.gd @@ -60,5 +60,9 @@ func deserialize(dict: Dictionary) -> void: expanded = dict.expanded +func get_layer_type_name() -> String: + return "Group" + + func accepts_child(layer: BaseLayer) -> bool: return true diff --git a/src/Classes/PixelLayer.gd b/src/Classes/PixelLayer.gd index 446e12952879..89f7b184010e 100644 --- a/src/Classes/PixelLayer.gd +++ b/src/Classes/PixelLayer.gd @@ -32,5 +32,9 @@ func deserialize(dict: Dictionary) -> void: # Overridden Functions: +func get_layer_type_name() -> String: + return "Layer" # In the interface, its just referred to as a regular "Layer" + + func can_layer_get_drawn() -> bool: return is_visible_in_hierarchy() && !is_locked_in_hierarchy() diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index a413733bb5e0..46defcee0b9b 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -159,7 +159,7 @@ func change_project() -> void: layer_container = group_layer_button_node.instance() layer_container.layer = i if layers[i].name == "": - layers[i].name = tr("Layer") + " %s" % i + layers[i].name = tr(layers[i].get_layer_type_name()) + " %s" % i Global.layers_container.add_child(layer_container) layer_container.label.text = layers[i].name @@ -503,7 +503,7 @@ func _layers_changed(value: Array) -> void: layers[i].index = i layers[i].project = self if layers[i].name == "": - layers[i].name = tr("Layer") + " %s" % i + layers[i].name = tr(layers[i].get_layer_type_name()) + " %s" % i Global.layers_container.add_child(layer_button) layer_button.label.text = layers[i].name From 3be9a74393fda2f128b8c19ae087efbb190ce340 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Mon, 9 May 2022 12:07:52 -0400 Subject: [PATCH 011/154] Renamed the layer get_children/is_a_parent_of functions --- src/Classes/GroupLayer.gd | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/Classes/GroupLayer.gd b/src/Classes/GroupLayer.gd index fe14968082e3..33297b08546d 100644 --- a/src/Classes/GroupLayer.gd +++ b/src/Classes/GroupLayer.gd @@ -13,31 +13,29 @@ func is_expanded_in_hierarchy() -> bool: return parent.is_expanded_in_hierarchy() return expanded - -func is_an_ancestor_of(layer: BaseLayer) -> bool: +# Returns true if this is a direct or indirect parent of layer +func is_a_parent_of(layer: BaseLayer) -> bool: if layer.parent == self: return true elif is_instance_valid(layer.parent): - return is_an_ancestor_of(layer.parent) + return is_a_parent_of(layer.parent) return false -# Only gets direct children -func get_children() -> Array: +# TODO: Consider going backwards in get_children functions, to allow breaking +func get_children_direct() -> Array: var children := [] - # TODO: Consider going backwards, to allow breaking for i in range(index): if project.layers[i].parent == self: children.append(project.layers[i]) return children -# Gets both direct AND indirect children -func get_successors() -> Array: - var successors := [] - # TODO: Consider going backwards, to allow breaking + +func get_children_recursive() -> Array: + var children := [] for i in range(index): - if is_an_ancestor_of(project.layers[i]): - successors.append(project.layers[i]) - return successors + if is_a_parent_of(project.layers[i]): + children.append(project.layers[i]) + return children func has_children() -> bool: From 17dcb68c95416285e0eefeb04efef173bc89d29b Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Mon, 9 May 2022 12:18:47 -0400 Subject: [PATCH 012/154] changed get_layer_type_name() to get_default_name(number) --- src/Classes/BaseLayer.gd | 4 ++-- src/Classes/GroupLayer.gd | 4 ++-- src/Classes/PixelLayer.gd | 4 ---- src/Classes/Project.gd | 4 ++-- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index 624b1d7b588c..86e1181f0ff0 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -51,8 +51,8 @@ func deserialize(dict: Dictionary) -> void: parent = project.layers[dict.parent] -func get_layer_type_name() -> String: - return "Base" +func get_default_name(number: int) -> String: + return tr("Layer") + " %s" % number func can_layer_get_drawn() -> bool: diff --git a/src/Classes/GroupLayer.gd b/src/Classes/GroupLayer.gd index 33297b08546d..2e9bce7be7d7 100644 --- a/src/Classes/GroupLayer.gd +++ b/src/Classes/GroupLayer.gd @@ -58,8 +58,8 @@ func deserialize(dict: Dictionary) -> void: expanded = dict.expanded -func get_layer_type_name() -> String: - return "Group" +func get_default_name(number: int) -> String: + return tr("Group") + " %s" % number func accepts_child(layer: BaseLayer) -> bool: diff --git a/src/Classes/PixelLayer.gd b/src/Classes/PixelLayer.gd index 89f7b184010e..446e12952879 100644 --- a/src/Classes/PixelLayer.gd +++ b/src/Classes/PixelLayer.gd @@ -32,9 +32,5 @@ func deserialize(dict: Dictionary) -> void: # Overridden Functions: -func get_layer_type_name() -> String: - return "Layer" # In the interface, its just referred to as a regular "Layer" - - func can_layer_get_drawn() -> bool: return is_visible_in_hierarchy() && !is_locked_in_hierarchy() diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 46defcee0b9b..7d890e56e305 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -159,7 +159,7 @@ func change_project() -> void: layer_container = group_layer_button_node.instance() layer_container.layer = i if layers[i].name == "": - layers[i].name = tr(layers[i].get_layer_type_name()) + " %s" % i + layers[i].name = layers[i].get_default_name(i) Global.layers_container.add_child(layer_container) layer_container.label.text = layers[i].name @@ -503,7 +503,7 @@ func _layers_changed(value: Array) -> void: layers[i].index = i layers[i].project = self if layers[i].name == "": - layers[i].name = tr(layers[i].get_layer_type_name()) + " %s" % i + layers[i].name = layers[i].get_default_name(i) Global.layers_container.add_child(layer_button) layer_button.label.text = layers[i].name From cc2b0eb7ff762839e7067d830ea25486ec9b8de0 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 11 May 2022 14:43:42 -0400 Subject: [PATCH 013/154] New layer drag and dropping behavior --- src/UI/Timeline/BaseLayerButton.gd | 119 ++++++++++++++++++++++------- 1 file changed, 90 insertions(+), 29 deletions(-) diff --git a/src/UI/Timeline/BaseLayerButton.gd b/src/UI/Timeline/BaseLayerButton.gd index 72c506a864a1..cb84c4d359cb 100644 --- a/src/UI/Timeline/BaseLayerButton.gd +++ b/src/UI/Timeline/BaseLayerButton.gd @@ -18,6 +18,7 @@ func _ready() -> void: var layer_buttons = find_node("LayerButtons") for child in layer_buttons.get_children(): var texture = child.get_child(0) + # TODO: Check if this can be safely removed: # var last_backslash = texture.texture.resource_path.get_base_dir().find_last("/") # var button_category = texture.texture.resource_path.get_base_dir().right(last_backslash + 1) # var normal_file_name = texture.texture.resource_path.get_file() @@ -39,7 +40,7 @@ func _ready() -> void: var hierarchy_depth: int = Global.current_project.layers[layer].get_hierarchy_depth() hierarchy_spacer.rect_min_size.x = hierarchy_depth * HIERARCHY_DEPTH_PIXEL_SHIFT if Global.control.theme.get_color("font_color", "Button").v > 0.5: # Light text is dark theme - self_modulate.v += hierarchy_depth * 0.2 + self_modulate.v += hierarchy_depth * 0.4 else: # Dark text should be light theme self_modulate.v -= hierarchy_depth * 0.075 @@ -145,23 +146,21 @@ func can_drop_data(_pos, data) -> bool: var depth: int = Global.current_project.layers[layer].get_hierarchy_depth() if Input.is_key_pressed(KEY_CONTROL): # Swap layers region = get_global_rect() + # TODO: Check if depth is correct else: # Shift layers - if Global.current_project.layers[layer].accepts_child(data[1]): - # Top, center, or bottom region? - if _get_region_rect(0, 0.25).has_point(get_global_mouse_position()): - # Drawn regions are shifted up/down a bit from actual for visual clearity - region = _get_region_rect(-0.1, 0.25) - elif _get_region_rect(0.25, 0.5).has_point(get_global_mouse_position()): - region = _get_region_rect(0.15, 0.7) + # If accepted as a child, is it in the center region? + if (Global.current_project.layers[layer].accepts_child(data[1]) + and _get_region_rect(0.25, 0.75).has_point(get_global_mouse_position()) + ): + # Drawn regions are adusted a bit from actual to clearify drop position + region = _get_region_rect(0.15, 0.85) depth += 1 - else: - region = _get_region_rect(0.85, 0.25) else: # Top or bottom region? if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): - region = _get_region_rect(-0.1, 0.25) + region = _get_region_rect(-0.1, 0.15) else: - region = _get_region_rect(0.85, 0.25) + region = _get_region_rect(0.85, 1.1) # Shift drawn region to the right a bit for hierarchy depth visualization: region.position.x += depth * HIERARCHY_DEPTH_PIXEL_SHIFT region.size.x -= depth * HIERARCHY_DEPTH_PIXEL_SHIFT @@ -174,27 +173,89 @@ func can_drop_data(_pos, data) -> bool: func drop_data(_pos, data) -> void: - var new_layer = data[1] - if layer == new_layer: + var dropped_layer: int = data[1] + # TODO: Invalid cases can be prevented in can_drop_data only + if layer == dropped_layer: return + Global.current_project.undo_redo.create_action("Change Layer Order") var new_layers: Array = Global.current_project.layers.duplicate() - var temp = new_layers[layer] - new_layers[layer] = new_layers[new_layer] - new_layers[new_layer] = temp + var temp: BaseLayer = new_layers[layer] + if Input.is_key_pressed(KEY_CONTROL): # Swap layers # TODO Need to check when swapping is allowed + new_layers[layer] = new_layers[dropped_layer] + new_layers[dropped_layer] = temp + + # TODO: Make sure to swap parents too + + for f in Global.current_project.frames: + var new_cels: Array = f.cels.duplicate() + var temp_canvas = new_cels[layer] + new_cels[layer] = new_cels[dropped_layer] + new_cels[dropped_layer] = temp_canvas + Global.current_project.undo_redo.add_do_property(f, "cels", new_cels) + Global.current_project.undo_redo.add_undo_property(f, "cels", f.cels) + # TODO: Having "SourceLayers/OldLayers (that you don't change) and new_layers would make this less confusing + else: + # layers_to_shift should be in order of the layer indices, starting from the lowest + var layers_to_shift: Array = new_layers[dropped_layer].get_children_recursive() + layers_to_shift.append(new_layers[dropped_layer]) + + var to_index: int # the index where the LOWEST shifted layer should end up + var to_parent: BaseLayer + + # If accepted as a child, is it in the center region? + if (new_layers[layer].accepts_child(data[1]) + and _get_region_rect(0.25, 0.75).has_point(get_global_mouse_position()) + ): + to_index = layer + to_parent = new_layers[layer] + else: + # Top or bottom region? + if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): + to_index = layer + 1 # TODO Is this right? + to_parent = new_layers[layer].parent + else: + # Place under the layer, if it has children, place after its lowest child + if new_layers[layer].has_children(): + to_index = new_layers[layer].get_children_recursive()[0].index + else: + to_index = layer # TODO Is this right? + to_parent = new_layers[layer].parent - Global.current_project.undo_redo.create_action("Change Layer Order") - for f in Global.current_project.frames: - var new_cels: Array = f.cels.duplicate() - var temp_canvas = new_cels[layer] - new_cels[layer] = new_cels[new_layer] - new_cels[new_layer] = temp_canvas - Global.current_project.undo_redo.add_do_property(f, "cels", new_cels) - Global.current_project.undo_redo.add_undo_property(f, "cels", f.cels) + # Make sure to set parent BEFORE adjusting new_layers + Global.current_project.undo_redo.add_do_property( + new_layers[dropped_layer], "parent", to_parent + ) + Global.current_project.undo_redo.add_undo_property( + new_layers[dropped_layer], "parent", new_layers[dropped_layer].parent + ) + + if dropped_layer < layer: + to_index -= layers_to_shift.size() + print("to_index = ", to_index) + + var x := layers_to_shift.size() - 1 + while x >= 0: + new_layers.remove(layers_to_shift[x].index) + x -= 1 + for i in range(layers_to_shift.size()): + new_layers.insert(to_index + i, layers_to_shift[i]) + + for f in Global.current_project.frames: + var new_cels: Array = f.cels.duplicate() + x = layers_to_shift.size() - 1 + while x >= 0: + new_cels.remove(layers_to_shift[x].index) + x -= 1 + for i in range(layers_to_shift.size()): + new_cels.insert(to_index + i, f.cels[layers_to_shift[i].index]) + + Global.current_project.undo_redo.add_do_property(f, "cels", new_cels) + Global.current_project.undo_redo.add_undo_property(f, "cels", f.cels) if Global.current_project.current_layer == layer: Global.current_project.undo_redo.add_do_property( - Global.current_project, "current_layer", new_layer + Global.current_project, "current_layer", dropped_layer ) Global.current_project.undo_redo.add_undo_property( Global.current_project, "current_layer", Global.current_project.current_layer @@ -209,8 +270,8 @@ func drop_data(_pos, data) -> void: Global.current_project.undo_redo.commit_action() -func _get_region_rect(y_offset: float, y_size: float) -> Rect2: +func _get_region_rect(y_begin: float, y_end: float) -> Rect2: var rect := get_global_rect() - rect.position.y += rect.size.y * y_offset - rect.size.y *= y_size + rect.position.y += rect.size.y * y_begin + rect.size.y *= y_end - y_begin return rect From dbf23fd67f9a6655cda4cd49b461be573e4090db Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 11 May 2022 14:46:19 -0400 Subject: [PATCH 014/154] Added read/write_image_data_from/to_pxo functions to Cel classes to handle saving/loading the binary image data for each cel type --- src/Autoload/OpenSave.gd | 8 ++------ src/Classes/BaseCel.gd | 10 ++++++++++ src/Classes/BaseLayer.gd | 31 +++++++++++++++++++++++++++++++ src/Classes/GroupLayer.gd | 30 ------------------------------ src/Classes/PixelCel.gd | 10 ++++++++++ src/Classes/PixelLayer.gd | 4 ++-- src/Classes/Project.gd | 1 + 7 files changed, 56 insertions(+), 38 deletions(-) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index 14f16aa80914..37008e56485f 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -109,11 +109,7 @@ func open_pxo_file(path: String, untitled_backup: bool = false, replace_empty: b new_project.deserialize(dict.result) for frame in new_project.frames: for cel in frame.cels: - var buffer := file.get_buffer(new_project.size.x * new_project.size.y * 4) - cel.image.create_from_data( - new_project.size.x, new_project.size.y, false, Image.FORMAT_RGBA8, buffer - ) - cel.image = cel.image # Just to call image_changed + cel.load_image_data_from_pxo(file, new_project.size) if dict.result.has("brushes"): for brush in dict.result.brushes: @@ -349,7 +345,7 @@ func save_pxo_file( file.store_line(to_save) for frame in project.frames: for cel in frame.cels: - file.store_buffer(cel.get_image().get_data()) + cel.save_image_data_to_pxo(file) for brush in project.brushes: file.store_buffer(brush.get_data()) diff --git a/src/Classes/BaseCel.gd b/src/Classes/BaseCel.gd index 82c6f46dec44..df61a91b7fc1 100644 --- a/src/Classes/BaseCel.gd +++ b/src/Classes/BaseCel.gd @@ -5,7 +5,17 @@ extends Reference var opacity: float + +# Functions to override: + # TODO: Should this be the case? # Each Cel type should have a get_image function, which will either return # its image data for PixelCels, or return a render of that cel. It's meant # for read-only usage of image data from any type of cel + +func save_image_data_to_pxo(_file: File) -> void: + return + + +func load_image_data_from_pxo(_file: File, _project_size: Vector2) -> void: + return diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index 86e1181f0ff0..c8805cc1fdd6 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -11,6 +11,37 @@ var project var index: int # TODO: Search for layer visbility/locked checks that should be changed to the hierarchy ones: +# Returns true if this is a direct or indirect parent of layer +func is_a_parent_of(layer: BaseLayer) -> bool: + if layer.parent == self: + return true + elif is_instance_valid(layer.parent): + return is_a_parent_of(layer.parent) + return false + +# TODO: Consider going backwards in get_children functions, to allow breaking +func get_children_direct() -> Array: + var children := [] + for i in range(index): + if project.layers[i].parent == self: + children.append(project.layers[i]) + return children + + +func get_children_recursive() -> Array: + var children := [] + for i in range(index): + if is_a_parent_of(project.layers[i]): + children.append(project.layers[i]) + return children + + +func has_children() -> bool: + if index == 0: + return false + return project.layers[index - 1].parent == self + + func is_visible_in_hierarchy() -> bool: if is_instance_valid(parent) and visible: return parent.is_visible_in_hierarchy() diff --git a/src/Classes/GroupLayer.gd b/src/Classes/GroupLayer.gd index 2e9bce7be7d7..bddc1f6bc767 100644 --- a/src/Classes/GroupLayer.gd +++ b/src/Classes/GroupLayer.gd @@ -13,36 +13,6 @@ func is_expanded_in_hierarchy() -> bool: return parent.is_expanded_in_hierarchy() return expanded -# Returns true if this is a direct or indirect parent of layer -func is_a_parent_of(layer: BaseLayer) -> bool: - if layer.parent == self: - return true - elif is_instance_valid(layer.parent): - return is_a_parent_of(layer.parent) - return false - -# TODO: Consider going backwards in get_children functions, to allow breaking -func get_children_direct() -> Array: - var children := [] - for i in range(index): - if project.layers[i].parent == self: - children.append(project.layers[i]) - return children - - -func get_children_recursive() -> Array: - var children := [] - for i in range(index): - if is_a_parent_of(project.layers[i]): - children.append(project.layers[i]) - return children - - -func has_children() -> bool: - if index == 0: - return false - return project.layers[index - 1].parent == self - # Overridden Functions: diff --git a/src/Classes/PixelCel.gd b/src/Classes/PixelCel.gd index d0d5c56c5c74..7aa462635744 100644 --- a/src/Classes/PixelCel.gd +++ b/src/Classes/PixelCel.gd @@ -25,3 +25,13 @@ func image_changed(value: Image) -> void: func get_image() -> Image: return image + + +func save_image_data_to_pxo(file: File) -> void: + file.store_buffer(image.get_data()) + + +func load_image_data_from_pxo(file: File, project_size: Vector2) -> void: + var buffer := file.get_buffer(project_size.x * project_size.y * 4) + image.create_from_data(project_size.x, project_size.y, false, Image.FORMAT_RGBA8, buffer) + image_changed(image) diff --git a/src/Classes/PixelLayer.gd b/src/Classes/PixelLayer.gd index 446e12952879..e72627d5af9d 100644 --- a/src/Classes/PixelLayer.gd +++ b/src/Classes/PixelLayer.gd @@ -9,6 +9,8 @@ func _init(_name := "") -> void: name = _name +# Overridden Functions: + func serialize() -> Dictionary: var dict = .serialize() dict["type"] = Global.LayerTypes.PIXEL @@ -30,7 +32,5 @@ func deserialize(dict: Dictionary) -> void: linked_cel.image_texture = linked_cels[0].cels[index].image_texture -# Overridden Functions: - func can_layer_get_drawn() -> bool: return is_visible_in_hierarchy() && !is_locked_in_hierarchy() diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 7d890e56e305..c4052fabe9aa 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -378,6 +378,7 @@ func deserialize(dict: Dictionary) -> void: for frame in dict.frames: var cels := [] for cel in frame.cels: + # TODO: Give the correct cel type cels.append(PixelCel.new(Image.new(), cel.opacity)) var duration := 1.0 if frame.has("duration"): From a81e231e589535e82f4dabd1e12a11f034a6a44b Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 11 May 2022 16:48:58 -0400 Subject: [PATCH 015/154] Fixed warning --- src/Classes/BaseLayer.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index c8805cc1fdd6..d6019b6aff6a 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -90,5 +90,5 @@ func can_layer_get_drawn() -> bool: return false -func accepts_child(layer: BaseLayer) -> bool: +func accepts_child(_layer: BaseLayer) -> bool: return false From 37c6c0a429afc5526201a0183754db15c5d41100 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 11 May 2022 16:50:26 -0400 Subject: [PATCH 016/154] Added a line to child layers wich makes it easier to see where they are in the hierarchy --- src/UI/Timeline/BaseLayerButton.gd | 9 +++++++++ src/UI/Timeline/PixelLayerButton.tscn | 1 + 2 files changed, 10 insertions(+) diff --git a/src/UI/Timeline/BaseLayerButton.gd b/src/UI/Timeline/BaseLayerButton.gd index cb84c4d359cb..2db5503eee43 100644 --- a/src/UI/Timeline/BaseLayerButton.gd +++ b/src/UI/Timeline/BaseLayerButton.gd @@ -39,6 +39,7 @@ func _ready() -> void: # Visualize how deep into the hierarchy the layer is var hierarchy_depth: int = Global.current_project.layers[layer].get_hierarchy_depth() hierarchy_spacer.rect_min_size.x = hierarchy_depth * HIERARCHY_DEPTH_PIXEL_SHIFT + if Global.control.theme.get_color("font_color", "Button").v > 0.5: # Light text is dark theme self_modulate.v += hierarchy_depth * 0.4 else: # Dark text should be light theme @@ -53,6 +54,14 @@ func _ready() -> void: lock_button.modulate.a = 0.33 +func _draw(): + if hierarchy_spacer.rect_size.x > 0.1: + var color := Color(1, 1, 1, 0.33) + color.v = round(Global.control.theme.get_color("font_color", "Button").v) + var x = hierarchy_spacer.rect_global_position.x - rect_global_position.x + hierarchy_spacer.rect_size.x + draw_line(Vector2(x, 0), Vector2(x, rect_size.y), color) + + func _input(event: InputEvent) -> void: if ( (event.is_action_released("ui_accept") or event.is_action_released("ui_cancel")) diff --git a/src/UI/Timeline/PixelLayerButton.tscn b/src/UI/Timeline/PixelLayerButton.tscn index ad9cc4af966b..f9d77557370d 100644 --- a/src/UI/Timeline/PixelLayerButton.tscn +++ b/src/UI/Timeline/PixelLayerButton.tscn @@ -129,6 +129,7 @@ margin_left = 126.0 margin_right = 230.0 margin_bottom = 36.0 rect_min_size = Vector2( 104, 0 ) +rect_pivot_offset = Vector2( -187, -9 ) mouse_default_cursor_shape = 2 size_flags_horizontal = 0 alignment = 1 From c2bf5e9f32e66f13290c3466625e3640515214bc Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 11 May 2022 17:41:20 -0400 Subject: [PATCH 017/154] Fixed debugger warning --- src/Classes/GroupLayer.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Classes/GroupLayer.gd b/src/Classes/GroupLayer.gd index bddc1f6bc767..da9db17cf4e1 100644 --- a/src/Classes/GroupLayer.gd +++ b/src/Classes/GroupLayer.gd @@ -32,5 +32,5 @@ func get_default_name(number: int) -> String: return tr("Group") + " %s" % number -func accepts_child(layer: BaseLayer) -> bool: +func accepts_child(_layer: BaseLayer) -> bool: return true From e1e38678b4ee877eb729d62d97c9bb5d41688156 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 11 May 2022 19:21:10 -0400 Subject: [PATCH 018/154] Fixed all cel types loading as PixelCels --- src/Classes/Project.gd | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index c4052fabe9aa..c18ee52c1b64 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -171,6 +171,7 @@ func change_project() -> void: var cel_button = pixel_cel_button_node.instance() cel_button.frame = j cel_button.layer = i + # TODO: Mak sure this works properly with groups cel_button.get_child(0).texture = frames[j].cels[i].image_texture if j == current_frame and i == current_layer: cel_button.pressed = true @@ -373,13 +374,18 @@ func deserialize(dict: Dictionary) -> void: selection_bitmap = resize_bitmap(selection_bitmap, size) if dict.has("save_path"): OpenSave.current_save_paths[Global.projects.find(self)] = dict.save_path - if dict.has("frames"): + if dict.has("frames") and dict.has("layers"): var frame_i := 0 for frame in dict.frames: var cels := [] + var cel_i := 0 for cel in frame.cels: - # TODO: Give the correct cel type - cels.append(PixelCel.new(Image.new(), cel.opacity)) + match int(dict.layers[cel_i].get("type", Global.LayerTypes.PIXEL)): + Global.LayerTypes.PIXEL: + cels.append(PixelCel.new(Image.new(), cel.opacity)) + Global.LayerTypes.GROUP: + cels.append(GroupCel.new(cel.opacity)) + cel_i += 1 var duration := 1.0 if frame.has("duration"): duration = frame.duration @@ -389,19 +395,18 @@ func deserialize(dict: Dictionary) -> void: frames.append(Frame.new(cels, duration)) frame_i += 1 - if dict.has("layers"): - for saved_layer in dict.layers: - match int(saved_layer.get("type", Global.LayerTypes.PIXEL)): - Global.LayerTypes.PIXEL: - layers.append(PixelLayer.new()) - Global.LayerTypes.GROUP: - layers.append(GroupLayer.new()) - # Parent references to other layers are created when deserializing - # a layer, so loop again after creating them. - for layer_i in range(dict.layers.size()): - layers[layer_i].project = self - layers[layer_i].index = layer_i - layers[layer_i].deserialize(dict.layers[layer_i]) + for saved_layer in dict.layers: + match int(saved_layer.get("type", Global.LayerTypes.PIXEL)): + Global.LayerTypes.PIXEL: + layers.append(PixelLayer.new()) + Global.LayerTypes.GROUP: + layers.append(GroupLayer.new()) + # Parent references to other layers are created when deserializing + # a layer, so loop again after creating them: + for layer_i in range(dict.layers.size()): + layers[layer_i].project = self + layers[layer_i].index = layer_i + layers[layer_i].deserialize(dict.layers[layer_i]) if dict.has("tags"): for tag in dict.tags: animation_tags.append(AnimationTag.new(tag.name, Color(tag.color), tag.from, tag.to)) From e8d2bfef48877445a1b820afd42099107cdf5ffe Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 12 May 2022 12:39:13 -0400 Subject: [PATCH 019/154] Fixed spacing issue with cels when collapsing groups --- src/Classes/Project.gd | 10 ++++++++++ src/UI/Timeline/GroupCelButton.gd | 5 ----- src/UI/Timeline/PixelCelButton.gd | 5 ----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index c18ee52c1b64..0ab09d860a8d 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -178,6 +178,10 @@ func change_project() -> void: layer_cel_container.add_child(cel_button) + if (is_instance_valid(layers[i].parent) + and not layers[i].parent.is_expanded_in_hierarchy()): + layer_cel_container.visible = false + for j in range(frames.size()): # Create frame ID labels var button: Button = frame_button_node.instance() button.frame = j @@ -475,6 +479,9 @@ func _frames_changed(value: Array) -> void: elif layers[i] is GroupLayer: # TODO: Make GroupLayers work here pass + if (is_instance_valid(layers[i].parent) + and not layers[i].parent.is_expanded_in_hierarchy()): + layer_cel_container.visible = false for j in range(frames.size()): var button: Button = frame_button_node.instance() @@ -529,6 +536,9 @@ func _layers_changed(value: Array) -> void: cel_button.frame = j cel_button.layer = i layer_cel_container.add_child(cel_button) + if (is_instance_valid(layers[i].parent) + and not layers[i].parent.is_expanded_in_hierarchy()): + layer_cel_container.visible = false var layer_button = Global.layers_container.get_child( Global.layers_container.get_child_count() - 1 - current_layer diff --git a/src/UI/Timeline/GroupCelButton.gd b/src/UI/Timeline/GroupCelButton.gd index 6b84095ebdfc..080bd324f5f7 100644 --- a/src/UI/Timeline/GroupCelButton.gd +++ b/src/UI/Timeline/GroupCelButton.gd @@ -24,11 +24,6 @@ func button_setup() -> void: # cel = Global.current_project.frames[frame].cels[layer] #image = cel.image - # TODO: Check formatting: - if (is_instance_valid(Global.current_project.layers[layer].parent) - and not Global.current_project.layers[layer].parent.is_expanded_in_hierarchy()): - visible = false - func _on_GroupCelButton_resized() -> void: get_node("CelShader").rect_min_size.x = rect_min_size.x - 4 diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index 49806eb2271a..8c5832566798 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -34,11 +34,6 @@ func button_setup() -> void: cel = Global.current_project.frames[frame].cels[layer] image = cel.image - # TODO: Check formatting: - if (is_instance_valid(Global.current_project.layers[layer].parent) - and not Global.current_project.layers[layer].parent.is_expanded_in_hierarchy()): - visible = false - func _on_CelButton_resized() -> void: get_node("CelTexture").rect_min_size.x = rect_min_size.x - 4 From 683ac3c07302268f187d0dba22f09ee7a4971a35 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 13 May 2022 09:30:27 -0400 Subject: [PATCH 020/154] Fixed bug when dropping a child layer to the bottom region of its parent group, where it would end up to far down (maybe disappearing) --- src/UI/Timeline/BaseLayerButton.gd | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/UI/Timeline/BaseLayerButton.gd b/src/UI/Timeline/BaseLayerButton.gd index 2db5503eee43..d7297bcfdbbc 100644 --- a/src/UI/Timeline/BaseLayerButton.gd +++ b/src/UI/Timeline/BaseLayerButton.gd @@ -227,6 +227,9 @@ func drop_data(_pos, data) -> void: # Place under the layer, if it has children, place after its lowest child if new_layers[layer].has_children(): to_index = new_layers[layer].get_children_recursive()[0].index + + if new_layers[layer].is_a_parent_of(new_layers[dropped_layer]): + to_index += layers_to_shift.size() else: to_index = layer # TODO Is this right? to_parent = new_layers[layer].parent From 0cfd25c2f002d03b4a490a07495f4a420d8233cd Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 13 May 2022 13:14:50 -0400 Subject: [PATCH 021/154] updated temporary todo comments --- src/Autoload/Global.gd | 2 +- src/Classes/BaseLayer.gd | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index 143a5982dd3b..bab6574b0e18 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -233,7 +233,7 @@ func undo_or_redo( "Unlink Cel" ] ): - # TODO: Check this: + # TODO: Check this: THIS IS PROBABLY WRONG (can't check if GROUP LAYER if INDEX is -1) if not current_project.layers[layer_index] is GroupLayer: if layer_index > -1 and frame_index > -1: canvas.update_texture(layer_index, frame_index, project) diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index d6019b6aff6a..db8679d52341 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -10,7 +10,6 @@ var parent: BaseLayer var project var index: int -# TODO: Search for layer visbility/locked checks that should be changed to the hierarchy ones: # Returns true if this is a direct or indirect parent of layer func is_a_parent_of(layer: BaseLayer) -> bool: if layer.parent == self: @@ -41,7 +40,7 @@ func has_children() -> bool: return false return project.layers[index - 1].parent == self - +# TODO: Search for layer visbility/locked checks that should be changed to the hierarchy ones: func is_visible_in_hierarchy() -> bool: if is_instance_valid(parent) and visible: return parent.is_visible_in_hierarchy() From 132d5e20d883f220b671fbef32b423b9fcce6439 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 13 May 2022 17:21:02 -0400 Subject: [PATCH 022/154] Created a base scene for layer buttons and merged layer button script into one --- src/UI/Timeline/BaseLayerButton.tscn | 169 +++++++++++++++++ src/UI/Timeline/GroupLayerButton.gd | 15 -- src/UI/Timeline/GroupLayerButton.tscn | 170 +----------------- .../{BaseLayerButton.gd => LayerButton.gd} | 45 ++++- src/UI/Timeline/PixelCelButton.gd | 3 +- src/UI/Timeline/PixelLayerButton.gd | 25 --- src/UI/Timeline/PixelLayerButton.tscn | 146 +-------------- 7 files changed, 222 insertions(+), 351 deletions(-) create mode 100644 src/UI/Timeline/BaseLayerButton.tscn delete mode 100644 src/UI/Timeline/GroupLayerButton.gd rename src/UI/Timeline/{BaseLayerButton.gd => LayerButton.gd} (86%) delete mode 100644 src/UI/Timeline/PixelLayerButton.gd diff --git a/src/UI/Timeline/BaseLayerButton.tscn b/src/UI/Timeline/BaseLayerButton.tscn new file mode 100644 index 000000000000..11dc8bd40249 --- /dev/null +++ b/src/UI/Timeline/BaseLayerButton.tscn @@ -0,0 +1,169 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://src/UI/Timeline/LayerButton.gd" type="Script" id=1] +[ext_resource path="res://assets/graphics/layers/layer_visible.png" type="Texture" id=2] +[ext_resource path="res://assets/graphics/layers/unlock.png" type="Texture" id=3] + +[node name="BaseLayerButton" type="Button"] +margin_right = 236.0 +margin_bottom = 36.0 +rect_min_size = Vector2( 236, 36 ) +mouse_default_cursor_shape = 2 +size_flags_horizontal = 0 +toggle_mode = true +action_mode = 0 +script = ExtResource( 1 ) +__meta__ = { +"_edit_horizontal_guides_": [ ], +"_edit_use_anchors_": false +} + +[node name="HBoxContainer" type="HBoxContainer" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +size_flags_horizontal = 0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="EmptySpacer" type="Control" parent="HBoxContainer"] +margin_bottom = 36.0 +mouse_filter = 2 + +[node name="LayerButtons" type="HBoxContainer" parent="HBoxContainer"] +margin_left = 4.0 +margin_right = 90.0 +margin_bottom = 36.0 +custom_constants/separation = 10 + +[node name="ExpandButton" type="ToolButton" parent="HBoxContainer/LayerButtons" groups=["UIButtons"]] +margin_top = 7.0 +margin_right = 22.0 +margin_bottom = 29.0 +rect_min_size = Vector2( 22, 22 ) +hint_tooltip = "Expand/collapse group" +mouse_default_cursor_shape = 2 +size_flags_horizontal = 0 +size_flags_vertical = 4 + +[node name="TextureRect" type="TextureRect" parent="HBoxContainer/LayerButtons/ExpandButton"] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -11.0 +margin_top = -11.0 +margin_right = 11.0 +margin_bottom = 11.0 +size_flags_horizontal = 0 +size_flags_vertical = 0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="VisibilityButton" type="ToolButton" parent="HBoxContainer/LayerButtons" groups=["UIButtons"]] +margin_left = 32.0 +margin_top = 7.0 +margin_right = 54.0 +margin_bottom = 29.0 +rect_min_size = Vector2( 22, 22 ) +hint_tooltip = "Toggle layer's visibility" +focus_mode = 0 +mouse_default_cursor_shape = 2 +size_flags_horizontal = 0 +size_flags_vertical = 4 + +[node name="TextureRect" type="TextureRect" parent="HBoxContainer/LayerButtons/VisibilityButton"] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -11.0 +margin_top = -11.0 +margin_right = 11.0 +margin_bottom = 11.0 +size_flags_horizontal = 0 +size_flags_vertical = 0 +texture = ExtResource( 2 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="LockButton" type="ToolButton" parent="HBoxContainer/LayerButtons" groups=["UIButtons"]] +margin_left = 64.0 +margin_top = 7.0 +margin_right = 86.0 +margin_bottom = 29.0 +rect_min_size = Vector2( 22, 22 ) +hint_tooltip = "Lock/unlock layer" +focus_mode = 0 +mouse_default_cursor_shape = 2 +size_flags_horizontal = 0 +size_flags_vertical = 4 + +[node name="TextureRect" type="TextureRect" parent="HBoxContainer/LayerButtons/LockButton"] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -11.0 +margin_top = -11.0 +margin_right = 11.0 +margin_bottom = 11.0 +size_flags_horizontal = 0 +size_flags_vertical = 0 +texture = ExtResource( 3 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="LayerName" type="HBoxContainer" parent="HBoxContainer"] +margin_left = 126.0 +margin_right = 236.0 +margin_bottom = 36.0 +rect_min_size = Vector2( 110, 0 ) +rect_pivot_offset = Vector2( -187, -9 ) +mouse_default_cursor_shape = 2 +size_flags_horizontal = 10 +alignment = 1 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="HierarchySpacer" type="Control" parent="HBoxContainer/LayerName"] +margin_bottom = 36.0 +mouse_filter = 2 + +[node name="Label" type="Label" parent="HBoxContainer/LayerName"] +margin_left = 4.0 +margin_top = 11.0 +margin_right = 106.0 +margin_bottom = 25.0 +size_flags_horizontal = 3 +text = "Layer 0" +clip_text = true + +[node name="LineEdit" type="LineEdit" parent="HBoxContainer/LayerName"] +visible = false +margin_left = 30.0 +margin_top = 2.0 +margin_right = 110.0 +margin_bottom = 34.0 +size_flags_horizontal = 3 +size_flags_vertical = 4 +text = "Layer 0" +editable = false +caret_blink = true +caret_blink_speed = 0.5 + +[node name="EmptySpacer" type="Control" parent="HBoxContainer/LayerName"] +margin_left = 110.0 +margin_right = 110.0 +margin_bottom = 36.0 +mouse_filter = 2 + +[connection signal="gui_input" from="." to="." method="_on_LayerContainer_gui_input"] +[connection signal="pressed" from="HBoxContainer/LayerButtons/ExpandButton" to="." method="_on_ExpandButton_pressed"] +[connection signal="pressed" from="HBoxContainer/LayerButtons/VisibilityButton" to="." method="_on_VisibilityButton_pressed"] +[connection signal="pressed" from="HBoxContainer/LayerButtons/LockButton" to="." method="_on_LockButton_pressed"] +[connection signal="focus_exited" from="HBoxContainer/LayerName/LineEdit" to="." method="_on_LineEdit_focus_exited"] diff --git a/src/UI/Timeline/GroupLayerButton.gd b/src/UI/Timeline/GroupLayerButton.gd deleted file mode 100644 index 51a6ca7c058b..000000000000 --- a/src/UI/Timeline/GroupLayerButton.gd +++ /dev/null @@ -1,15 +0,0 @@ -class_name GroupLayerButton -extends BaseLayerButton - -onready var expand_button: BaseButton = find_node("ExpandButton") - -func _ready() -> void: - if Global.current_project.layers[layer].expanded: # If the group is expanded - Global.change_button_texturerect(expand_button.get_child(0), "group_expanded.png") - else: - Global.change_button_texturerect(expand_button.get_child(0), "group_collapsed.png") - - - -func _on_ExpandButton_pressed(): - Global.current_project.layers[layer].expanded = !Global.current_project.layers[layer].expanded diff --git a/src/UI/Timeline/GroupLayerButton.tscn b/src/UI/Timeline/GroupLayerButton.tscn index 653f52d9aa0a..c1464f47007b 100644 --- a/src/UI/Timeline/GroupLayerButton.tscn +++ b/src/UI/Timeline/GroupLayerButton.tscn @@ -1,170 +1,10 @@ -[gd_scene load_steps=5 format=2] +[gd_scene load_steps=3 format=2] -[ext_resource path="res://src/UI/Timeline/GroupLayerButton.gd" type="Script" id=1] -[ext_resource path="res://assets/graphics/layers/layer_visible.png" type="Texture" id=2] -[ext_resource path="res://assets/graphics/layers/unlock.png" type="Texture" id=3] +[ext_resource path="res://src/UI/Timeline/BaseLayerButton.tscn" type="PackedScene" id=1] [ext_resource path="res://assets/graphics/layers/group_expanded.png" type="Texture" id=4] -[node name="GroupLayerContainer" type="Button"] -margin_right = 236.0 -margin_bottom = 36.0 -rect_min_size = Vector2( 236, 36 ) -mouse_default_cursor_shape = 2 -size_flags_horizontal = 0 -toggle_mode = true -action_mode = 0 -script = ExtResource( 1 ) -__meta__ = { -"_edit_horizontal_guides_": [ ], -"_edit_use_anchors_": false -} +[node name="GroupLayerButton" instance=ExtResource( 1 )] +hide_expand_button = false -[node name="HBoxContainer" type="HBoxContainer" parent="."] -anchor_right = 1.0 -anchor_bottom = 1.0 -size_flags_horizontal = 0 -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="EmptySpacer" type="Control" parent="HBoxContainer"] -margin_bottom = 36.0 - -[node name="LayerButtons" type="HBoxContainer" parent="HBoxContainer"] -margin_left = 4.0 -margin_right = 90.0 -margin_bottom = 36.0 -custom_constants/separation = 10 - -[node name="ExpandButton" type="ToolButton" parent="HBoxContainer/LayerButtons" groups=["UIButtons"]] -margin_top = 7.0 -margin_right = 22.0 -margin_bottom = 29.0 -rect_min_size = Vector2( 22, 22 ) -hint_tooltip = "Expand/collapse group" -mouse_default_cursor_shape = 2 -size_flags_horizontal = 0 -size_flags_vertical = 4 - -[node name="TextureRect" type="TextureRect" parent="HBoxContainer/LayerButtons/ExpandButton"] -anchor_left = 0.5 -anchor_top = 0.5 -anchor_right = 0.5 -anchor_bottom = 0.5 -margin_left = -11.0 -margin_top = -11.0 -margin_right = 11.0 -margin_bottom = 11.0 -size_flags_horizontal = 0 -size_flags_vertical = 0 +[node name="TextureRect" parent="HBoxContainer/LayerButtons/ExpandButton" index="0"] texture = ExtResource( 4 ) -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="VisibilityButton" type="ToolButton" parent="HBoxContainer/LayerButtons" groups=["UIButtons"]] -margin_left = 32.0 -margin_top = 7.0 -margin_right = 54.0 -margin_bottom = 29.0 -rect_min_size = Vector2( 22, 22 ) -hint_tooltip = "Toggle layer's visibility" -focus_mode = 0 -mouse_default_cursor_shape = 2 -size_flags_horizontal = 0 -size_flags_vertical = 4 - -[node name="TextureRect" type="TextureRect" parent="HBoxContainer/LayerButtons/VisibilityButton"] -anchor_left = 0.5 -anchor_top = 0.5 -anchor_right = 0.5 -anchor_bottom = 0.5 -margin_left = -11.0 -margin_top = -11.0 -margin_right = 11.0 -margin_bottom = 11.0 -size_flags_horizontal = 0 -size_flags_vertical = 0 -texture = ExtResource( 2 ) -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="LockButton" type="ToolButton" parent="HBoxContainer/LayerButtons" groups=["UIButtons"]] -margin_left = 64.0 -margin_top = 7.0 -margin_right = 86.0 -margin_bottom = 29.0 -rect_min_size = Vector2( 22, 22 ) -hint_tooltip = "Lock/unlock layer" -focus_mode = 0 -mouse_default_cursor_shape = 2 -size_flags_horizontal = 0 -size_flags_vertical = 4 - -[node name="TextureRect" type="TextureRect" parent="HBoxContainer/LayerButtons/LockButton"] -anchor_left = 0.5 -anchor_top = 0.5 -anchor_right = 0.5 -anchor_bottom = 0.5 -margin_left = -11.0 -margin_top = -11.0 -margin_right = 11.0 -margin_bottom = 11.0 -size_flags_horizontal = 0 -size_flags_vertical = 0 -texture = ExtResource( 3 ) -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="Spacer" type="Control" parent="HBoxContainer"] -margin_left = 94.0 -margin_right = 122.0 -margin_bottom = 36.0 -rect_min_size = Vector2( 28, 0 ) -mouse_filter = 2 - -[node name="LayerName" type="HBoxContainer" parent="HBoxContainer"] -margin_left = 126.0 -margin_right = 230.0 -margin_bottom = 36.0 -rect_min_size = Vector2( 104, 0 ) -mouse_default_cursor_shape = 2 -size_flags_horizontal = 0 -alignment = 1 -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="HierarchySpacer" type="Control" parent="HBoxContainer/LayerName"] -margin_bottom = 36.0 -mouse_filter = 2 - -[node name="Label" type="Label" parent="HBoxContainer/LayerName"] -margin_left = 4.0 -margin_top = 11.0 -margin_right = 104.0 -margin_bottom = 25.0 -size_flags_horizontal = 3 -text = "Layer 0" -clip_text = true - -[node name="LineEdit" type="LineEdit" parent="HBoxContainer/LayerName"] -visible = false -margin_left = 86.0 -margin_top = 5.0 -margin_right = 166.0 -margin_bottom = 37.0 -rect_min_size = Vector2( 80, 32 ) -size_flags_vertical = 4 -text = "Layer 0" -editable = false -caret_blink = true -caret_blink_speed = 0.5 - -[connection signal="gui_input" from="." to="." method="_on_LayerContainer_gui_input"] -[connection signal="pressed" from="HBoxContainer/LayerButtons/ExpandButton" to="." method="_on_ExpandButton_pressed"] -[connection signal="pressed" from="HBoxContainer/LayerButtons/VisibilityButton" to="." method="_on_VisibilityButton_pressed"] -[connection signal="pressed" from="HBoxContainer/LayerButtons/LockButton" to="." method="_on_LockButton_pressed"] -[connection signal="focus_exited" from="HBoxContainer/LayerName/LineEdit" to="." method="_on_LineEdit_focus_exited"] diff --git a/src/UI/Timeline/BaseLayerButton.gd b/src/UI/Timeline/LayerButton.gd similarity index 86% rename from src/UI/Timeline/BaseLayerButton.gd rename to src/UI/Timeline/LayerButton.gd index d7297bcfdbbc..c269e3766a3b 100644 --- a/src/UI/Timeline/BaseLayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -1,16 +1,19 @@ -class_name BaseLayerButton +class_name LayerButton extends Button const HIERARCHY_DEPTH_PIXEL_SHIFT = 8 var layer := 0 +onready var expand_button: BaseButton = find_node("ExpandButton") onready var visibility_button: BaseButton = find_node("VisibilityButton") onready var lock_button: BaseButton = find_node("LockButton") onready var label: Label = find_node("Label") onready var line_edit: LineEdit = find_node("LineEdit") onready var hierarchy_spacer: Control = find_node("HierarchySpacer") +onready var linked_button: BaseButton = find_node("LinkButton") +export var hide_expand_button := true func _ready() -> void: rect_min_size.y = Global.animation_timeline.cel_size @@ -18,14 +21,17 @@ func _ready() -> void: var layer_buttons = find_node("LayerButtons") for child in layer_buttons.get_children(): var texture = child.get_child(0) - # TODO: Check if this can be safely removed: -# var last_backslash = texture.texture.resource_path.get_base_dir().find_last("/") -# var button_category = texture.texture.resource_path.get_base_dir().right(last_backslash + 1) -# var normal_file_name = texture.texture.resource_path.get_file() - -# texture.texture = load("res://assets/graphics/%s/%s" % [button_category, normal_file_name]) texture.modulate = Global.modulate_icon_color + if hide_expand_button: + expand_button.mouse_filter = Control.MOUSE_FILTER_IGNORE + expand_button.get_child(0).visible = false # Hide the TextureRect + else: + if Global.current_project.layers[layer].expanded: + Global.change_button_texturerect(expand_button.get_child(0), "group_expanded.png") + else: + Global.change_button_texturerect(expand_button.get_child(0), "group_collapsed.png") + if Global.current_project.layers[layer].visible: Global.change_button_texturerect(visibility_button.get_child(0), "layer_visible.png") else: @@ -36,6 +42,12 @@ func _ready() -> void: else: Global.change_button_texturerect(lock_button.get_child(0), "unlock.png") + if linked_button: + if Global.current_project.layers[layer].new_cels_linked: # If new layers will be linked + Global.change_button_texturerect(linked_button.get_child(0), "linked_layer.png") + else: + Global.change_button_texturerect(linked_button.get_child(0), "unlinked_layer.png") + # Visualize how deep into the hierarchy the layer is var hierarchy_depth: int = Global.current_project.layers[layer].get_hierarchy_depth() hierarchy_spacer.rect_min_size.x = hierarchy_depth * HIERARCHY_DEPTH_PIXEL_SHIFT @@ -116,6 +128,10 @@ func _save_layer_name(new_name: String) -> void: Global.current_project.layers[layer].name = new_name +func _on_ExpandButton_pressed(): + Global.current_project.layers[layer].expanded = !Global.current_project.layers[layer].expanded + + func _on_VisibilityButton_pressed() -> void: Global.canvas.selection.transform_content_confirm() Global.current_project.layers[layer].visible = !Global.current_project.layers[layer].visible @@ -129,6 +145,21 @@ func _on_LockButton_pressed() -> void: _select_current_layer() +func _on_LinkButton_pressed() -> void: + Global.canvas.selection.transform_content_confirm() + var layer_class: PixelLayer = Global.current_project.layers[layer] + layer_class.new_cels_linked = !layer_class.new_cels_linked + if layer_class.new_cels_linked && !layer_class.linked_cels: + # If button is pressed and there are no linked cels in the layer + layer_class.linked_cels.append( + Global.current_project.frames[Global.current_project.current_frame] + ) + var container = Global.frames_container.get_child(Global.current_project.current_layer) + container.get_child(Global.current_project.current_frame).button_setup() + + Global.current_project.layers = Global.current_project.layers # Call the setter + + func _select_current_layer() -> void: Global.current_project.selected_cels.clear() var frame_layer := [Global.current_project.current_frame, layer] diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index 8c5832566798..a3795a12d7f0 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -108,10 +108,11 @@ func _on_PopupMenu_id_pressed(id: int) -> void: var new_layers: Array = Global.current_project.duplicate_layers() var new_cels: Array = f.cels.duplicate() for i in new_cels.size(): + # TODO: This doesn't work new_cels[i] = PixelCel.new( new_cels[i].image, new_cels[i].opacity, new_cels[i].image_texture ) - +# TODO: Make sure all this stuff still works after refactor: if popup_menu.get_item_metadata(MenuOptions.LINK) == "Unlink Cel": new_layers[layer].linked_cels.remove(cel_index) var sprite := Image.new() diff --git a/src/UI/Timeline/PixelLayerButton.gd b/src/UI/Timeline/PixelLayerButton.gd deleted file mode 100644 index f6b9cf73d40c..000000000000 --- a/src/UI/Timeline/PixelLayerButton.gd +++ /dev/null @@ -1,25 +0,0 @@ -class_name PixelLayerButton -extends BaseLayerButton - -onready var linked_button: BaseButton = find_node("LinkButton") - -func _ready() -> void: - if Global.current_project.layers[layer].new_cels_linked: # If new layers will be linked - Global.change_button_texturerect(linked_button.get_child(0), "linked_layer.png") - else: - Global.change_button_texturerect(linked_button.get_child(0), "unlinked_layer.png") - - -func _on_LinkButton_pressed() -> void: - Global.canvas.selection.transform_content_confirm() - var layer_class: PixelLayer = Global.current_project.layers[layer] - layer_class.new_cels_linked = !layer_class.new_cels_linked - if layer_class.new_cels_linked && !layer_class.linked_cels: - # If button is pressed and there are no linked cels in the layer - layer_class.linked_cels.append( - Global.current_project.frames[Global.current_project.current_frame] - ) - var container = Global.frames_container.get_child(Global.current_project.current_layer) - container.get_child(Global.current_project.current_frame).button_setup() - - Global.current_project.layers = Global.current_project.layers # Call the setter diff --git a/src/UI/Timeline/PixelLayerButton.tscn b/src/UI/Timeline/PixelLayerButton.tscn index f9d77557370d..6f66558f2e1e 100644 --- a/src/UI/Timeline/PixelLayerButton.tscn +++ b/src/UI/Timeline/PixelLayerButton.tscn @@ -1,114 +1,27 @@ -[gd_scene load_steps=5 format=2] +[gd_scene load_steps=3 format=2] -[ext_resource path="res://src/UI/Timeline/PixelLayerButton.gd" type="Script" id=1] -[ext_resource path="res://assets/graphics/layers/layer_visible.png" type="Texture" id=2] -[ext_resource path="res://assets/graphics/layers/unlock.png" type="Texture" id=3] +[ext_resource path="res://src/UI/Timeline/BaseLayerButton.tscn" type="PackedScene" id=1] [ext_resource path="res://assets/graphics/layers/unlinked_layer.png" type="Texture" id=4] -[node name="PixelLayerContainer" type="Button"] -margin_right = 236.0 -margin_bottom = 36.0 -rect_min_size = Vector2( 236, 36 ) -mouse_default_cursor_shape = 2 -size_flags_horizontal = 0 -toggle_mode = true -action_mode = 0 -script = ExtResource( 1 ) -__meta__ = { -"_edit_horizontal_guides_": [ ], -"_edit_use_anchors_": false -} - -[node name="HBoxContainer" type="HBoxContainer" parent="."] -anchor_right = 1.0 -anchor_bottom = 1.0 -size_flags_horizontal = 0 -__meta__ = { -"_edit_use_anchors_": false -} +[node name="PixelLayerButton" instance=ExtResource( 1 )] -[node name="Spacer" type="Control" parent="HBoxContainer"] -margin_right = 32.0 -margin_bottom = 36.0 -rect_min_size = Vector2( 32, 0 ) -mouse_filter = 2 - -[node name="LayerButtons" type="HBoxContainer" parent="HBoxContainer"] -margin_left = 36.0 +[node name="LayerButtons" parent="HBoxContainer" index="1"] margin_right = 122.0 -margin_bottom = 36.0 -custom_constants/separation = 10 - -[node name="VisibilityButton" type="ToolButton" parent="HBoxContainer/LayerButtons" groups=["UIButtons"]] -margin_top = 7.0 -margin_right = 22.0 -margin_bottom = 29.0 -rect_min_size = Vector2( 22, 22 ) -hint_tooltip = "Toggle layer's visibility" -focus_mode = 0 -mouse_default_cursor_shape = 2 -size_flags_horizontal = 0 -size_flags_vertical = 4 - -[node name="TextureRect" type="TextureRect" parent="HBoxContainer/LayerButtons/VisibilityButton"] -anchor_left = 0.5 -anchor_top = 0.5 -anchor_right = 0.5 -anchor_bottom = 0.5 -margin_left = -11.0 -margin_top = -11.0 -margin_right = 11.0 -margin_bottom = 11.0 -size_flags_horizontal = 0 -size_flags_vertical = 0 -texture = ExtResource( 2 ) -__meta__ = { -"_edit_use_anchors_": false -} -[node name="LockButton" type="ToolButton" parent="HBoxContainer/LayerButtons" groups=["UIButtons"]] -margin_left = 32.0 +[node name="LinkButton" type="ToolButton" parent="HBoxContainer/LayerButtons" index="3" groups=["UIButtons"]] +margin_left = 96.0 margin_top = 7.0 -margin_right = 54.0 -margin_bottom = 29.0 -rect_min_size = Vector2( 22, 22 ) -hint_tooltip = "Lock/unlock layer" -focus_mode = 0 -mouse_default_cursor_shape = 2 -size_flags_horizontal = 0 -size_flags_vertical = 4 - -[node name="TextureRect" type="TextureRect" parent="HBoxContainer/LayerButtons/LockButton"] -anchor_left = 0.5 -anchor_top = 0.5 -anchor_right = 0.5 -anchor_bottom = 0.5 -margin_left = -11.0 -margin_top = -11.0 -margin_right = 11.0 -margin_bottom = 11.0 -size_flags_horizontal = 0 -size_flags_vertical = 0 -texture = ExtResource( 3 ) -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="LinkButton" type="ToolButton" parent="HBoxContainer/LayerButtons" groups=["UIButtons"]] -margin_left = 64.0 -margin_top = 7.0 -margin_right = 86.0 +margin_right = 118.0 margin_bottom = 29.0 rect_min_size = Vector2( 22, 22 ) hint_tooltip = "Enable/disable cel linking Linked cels are being shared across multiple frames" -focus_mode = 0 mouse_default_cursor_shape = 2 size_flags_horizontal = 0 size_flags_vertical = 4 -[node name="TextureRect" type="TextureRect" parent="HBoxContainer/LayerButtons/LinkButton"] +[node name="TextureRect" type="TextureRect" parent="HBoxContainer/LayerButtons/LinkButton" index="0"] anchor_left = 0.5 anchor_top = 0.5 anchor_right = 0.5 @@ -124,47 +37,4 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="LayerName" type="HBoxContainer" parent="HBoxContainer"] -margin_left = 126.0 -margin_right = 230.0 -margin_bottom = 36.0 -rect_min_size = Vector2( 104, 0 ) -rect_pivot_offset = Vector2( -187, -9 ) -mouse_default_cursor_shape = 2 -size_flags_horizontal = 0 -alignment = 1 -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="HierarchySpacer" type="Control" parent="HBoxContainer/LayerName"] -margin_bottom = 36.0 -mouse_filter = 2 - -[node name="Label" type="Label" parent="HBoxContainer/LayerName"] -margin_left = 4.0 -margin_top = 11.0 -margin_right = 104.0 -margin_bottom = 25.0 -size_flags_horizontal = 3 -text = "Layer 0" -clip_text = true - -[node name="LineEdit" type="LineEdit" parent="HBoxContainer/LayerName"] -visible = false -margin_left = 86.0 -margin_top = 5.0 -margin_right = 166.0 -margin_bottom = 37.0 -rect_min_size = Vector2( 80, 32 ) -size_flags_vertical = 4 -text = "Layer 0" -editable = false -caret_blink = true -caret_blink_speed = 0.5 - -[connection signal="gui_input" from="." to="." method="_on_LayerContainer_gui_input"] -[connection signal="pressed" from="HBoxContainer/LayerButtons/VisibilityButton" to="." method="_on_VisibilityButton_pressed"] -[connection signal="pressed" from="HBoxContainer/LayerButtons/LockButton" to="." method="_on_LockButton_pressed"] [connection signal="pressed" from="HBoxContainer/LayerButtons/LinkButton" to="." method="_on_LinkButton_pressed"] -[connection signal="focus_exited" from="HBoxContainer/LayerName/LineEdit" to="." method="_on_LineEdit_focus_exited"] From 54d4c0829f367f026bde2844696973409dc16d04 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 13 May 2022 18:30:49 -0400 Subject: [PATCH 023/154] Prevent the case of parenting to itself in layer drag and drop, fixed static reference to LayerButton still being BaseLayerButton --- src/Classes/Project.gd | 4 ++-- src/UI/Timeline/LayerButton.gd | 23 +++++++++++++++++------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 0ab09d860a8d..0e18680da708 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -152,7 +152,7 @@ func change_project() -> void: # Create new ones for i in range(layers.size() - 1, -1, -1): # Create layer buttons - var layer_container: BaseLayerButton + var layer_container: LayerButton if layers[i] is PixelLayer: layer_container = pixel_layer_button_node.instance() elif layers[i] is GroupLayer: @@ -507,7 +507,7 @@ func _layers_changed(value: Array) -> void: _remove_cel_buttons() for i in range(layers.size() - 1, -1, -1): - var layer_button: BaseLayerButton + var layer_button: LayerButton if layers[i] is PixelLayer: layer_button = pixel_layer_button_node.instance() elif layers[i] is GroupLayer: diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index c269e3766a3b..76ff6cc8d46c 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -182,12 +182,26 @@ func get_drag_data(_position) -> Array: func can_drop_data(_pos, data) -> bool: if typeof(data) == TYPE_ARRAY: if data[0] == "Layer": + var curr_layer: BaseLayer = Global.current_project.layers[layer] + var drag_layer: BaseLayer = Global.current_project.layers[data[1]] + + if curr_layer == drag_layer: + Global.animation_timeline.drag_highlight.visible = false + return false + var region: Rect2 var depth: int = Global.current_project.layers[layer].get_hierarchy_depth() + if Input.is_key_pressed(KEY_CONTROL): # Swap layers + if drag_layer.is_a_parent_of(curr_layer) or curr_layer.is_a_parent_of(drag_layer): + Global.animation_timeline.drag_highlight.visible = false + return false region = get_global_rect() - # TODO: Check if depth is correct + else: # Shift layers + if drag_layer.is_a_parent_of(curr_layer): + Global.animation_timeline.drag_highlight.visible = false + return false # If accepted as a child, is it in the center region? if (Global.current_project.layers[layer].accepts_child(data[1]) and _get_region_rect(0.25, 0.75).has_point(get_global_mouse_position()) @@ -206,17 +220,14 @@ func can_drop_data(_pos, data) -> bool: region.size.x -= depth * HIERARCHY_DEPTH_PIXEL_SHIFT Global.animation_timeline.drag_highlight.rect_global_position = region.position Global.animation_timeline.drag_highlight.rect_size = region.size - Global.animation_timeline.drag_highlight.show() + Global.animation_timeline.drag_highlight.visible = true return true - Global.animation_timeline.drag_highlight.hide() + Global.animation_timeline.drag_highlight.visible = false return false func drop_data(_pos, data) -> void: var dropped_layer: int = data[1] - # TODO: Invalid cases can be prevented in can_drop_data only - if layer == dropped_layer: - return Global.current_project.undo_redo.create_action("Change Layer Order") var new_layers: Array = Global.current_project.layers.duplicate() From c1eaa6f05cd3f41672797e88703f4d92d2abbf7b Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 14 May 2022 10:36:51 -0400 Subject: [PATCH 024/154] Use a base scene for CelButtons --- src/UI/Timeline/BaseCelButton.tscn | 55 +++++++++++++++++++++++ src/UI/Timeline/GroupCelButton.gd | 8 ++-- src/UI/Timeline/GroupCelButton.tscn | 68 +++-------------------------- src/UI/Timeline/PixelCelButton.tscn | 64 ++++----------------------- 4 files changed, 73 insertions(+), 122 deletions(-) create mode 100644 src/UI/Timeline/BaseCelButton.tscn diff --git a/src/UI/Timeline/BaseCelButton.tscn b/src/UI/Timeline/BaseCelButton.tscn new file mode 100644 index 000000000000..232b9b8cbc7b --- /dev/null +++ b/src/UI/Timeline/BaseCelButton.tscn @@ -0,0 +1,55 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://src/Shaders/TransparentChecker.shader" type="Shader" id=1] +[ext_resource path="res://src/UI/TransparentChecker.tscn" type="PackedScene" id=2] + +[sub_resource type="ShaderMaterial" id=1] +shader = ExtResource( 1 ) +shader_param/size = 10.0 +shader_param/alpha = 1.0 +shader_param/color1 = Color( 0.7, 0.7, 0.7, 1 ) +shader_param/color2 = Color( 1, 1, 1, 1 ) +shader_param/offset = Vector2( 0, 0 ) +shader_param/scale = Vector2( 0, 0 ) +shader_param/rect_size = Vector2( 0, 0 ) +shader_param/follow_movement = false +shader_param/follow_scale = false + +[node name="BaseCelButton" type="Button"] +margin_top = 18.0 +margin_right = 36.0 +margin_bottom = 54.0 +rect_min_size = Vector2( 36, 36 ) +mouse_default_cursor_shape = 2 +size_flags_horizontal = 0 +size_flags_vertical = 0 +toggle_mode = true +button_mask = 7 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="CelTexture" type="TextureRect" parent="."] +margin_left = 2.0 +margin_top = 1.78536 +margin_right = 34.0 +margin_bottom = 33.7854 +rect_min_size = Vector2( 32, 32 ) +size_flags_horizontal = 0 +size_flags_vertical = 0 +expand = true +stretch_mode = 6 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="TransparentChecker" parent="CelTexture" instance=ExtResource( 2 )] +show_behind_parent = true +material = SubResource( 1 ) +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_right = 0.0 +margin_bottom = 0.0 + +[connection signal="pressed" from="." to="." method="_on_CelButton_pressed"] +[connection signal="resized" from="." to="." method="_on_CelButton_resized"] diff --git a/src/UI/Timeline/GroupCelButton.gd b/src/UI/Timeline/GroupCelButton.gd index 080bd324f5f7..6b91d392918f 100644 --- a/src/UI/Timeline/GroupCelButton.gd +++ b/src/UI/Timeline/GroupCelButton.gd @@ -19,17 +19,19 @@ func button_setup() -> void: hint_tooltip = tr("Frame: %s, Layer: %s") % [frame + 1, layer] # Reset the checkers size because it assumes you want the same size as the canvas - var checker = $CelShader/TransparentChecker + var checker = $CelTexture/TransparentChecker checker.rect_size = checker.get_parent().rect_size # cel = Global.current_project.frames[frame].cels[layer] #image = cel.image func _on_GroupCelButton_resized() -> void: - get_node("CelShader").rect_min_size.x = rect_min_size.x - 4 - get_node("CelShader").rect_min_size.y = rect_min_size.y - 4 + get_node("CelTexture").rect_min_size.x = rect_min_size.x - 4 + get_node("CelTexture").rect_min_size.y = rect_min_size.y - 4 func _pressed(): # TODO: PixelCelButton could just use the func instead of signal too + + # TODO: Some of the funtionality from PixelCelButton needs to be moved over pass diff --git a/src/UI/Timeline/GroupCelButton.tscn b/src/UI/Timeline/GroupCelButton.tscn index 054aa82f7c18..75035ca7c51c 100644 --- a/src/UI/Timeline/GroupCelButton.tscn +++ b/src/UI/Timeline/GroupCelButton.tscn @@ -1,65 +1,7 @@ -[gd_scene load_steps=5 format=2] +[gd_scene load_steps=3 format=2] -[ext_resource path="res://src/UI/Timeline/GroupCelButton.gd" type="Script" id=1] -[ext_resource path="res://src/UI/TransparentChecker.tscn" type="PackedScene" id=2] -[ext_resource path="res://src/Shaders/TransparentChecker.shader" type="Shader" id=3] +[ext_resource path="res://src/UI/Timeline/BaseCelButton.tscn" type="PackedScene" id=1] +[ext_resource path="res://src/UI/Timeline/GroupCelButton.gd" type="Script" id=2] -[sub_resource type="ShaderMaterial" id=1] -shader = ExtResource( 3 ) -shader_param/size = 10.0 -shader_param/alpha = 1.0 -shader_param/color1 = Color( 0.7, 0.7, 0.7, 1 ) -shader_param/color2 = Color( 1, 1, 1, 1 ) -shader_param/offset = Vector2( 0, 0 ) -shader_param/scale = Vector2( 0, 0 ) -shader_param/rect_size = Vector2( 0, 0 ) -shader_param/follow_movement = false -shader_param/follow_scale = false - -[node name="GroupCelButton" type="Button"] -margin_top = 18.0 -margin_right = 36.0 -margin_bottom = 54.0 -rect_min_size = Vector2( 36, 36 ) -mouse_default_cursor_shape = 2 -size_flags_horizontal = 0 -size_flags_vertical = 0 -toggle_mode = true -button_mask = 7 -script = ExtResource( 1 ) -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="CelShader" type="TextureRect" parent="."] -margin_left = 2.0 -margin_top = 1.78536 -margin_right = 34.0 -margin_bottom = 33.7854 -rect_min_size = Vector2( 32, 32 ) -size_flags_horizontal = 0 -size_flags_vertical = 0 -expand = true -stretch_mode = 6 -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="TransparentChecker" parent="CelShader" instance=ExtResource( 2 )] -show_behind_parent = true -material = SubResource( 1 ) -anchor_right = 1.0 -anchor_bottom = 1.0 -margin_right = 0.0 -margin_bottom = 0.0 - -[node name="PopupMenu" type="PopupMenu" parent="."] -margin_right = 20.0 -margin_bottom = 20.0 -mouse_default_cursor_shape = 2 -__meta__ = { -"_edit_use_anchors_": false -} - -[connection signal="pressed" from="." to="." method="_on_CelButton_pressed"] -[connection signal="resized" from="." to="." method="_on_GroupCelButton_resized"] +[node name="GroupCelButton" instance=ExtResource( 1 )] +script = ExtResource( 2 ) diff --git a/src/UI/Timeline/PixelCelButton.tscn b/src/UI/Timeline/PixelCelButton.tscn index 34ead37a6abb..0a729386a722 100644 --- a/src/UI/Timeline/PixelCelButton.tscn +++ b/src/UI/Timeline/PixelCelButton.tscn @@ -1,59 +1,13 @@ -[gd_scene load_steps=5 format=2] +[gd_scene load_steps=3 format=2] -[ext_resource path="res://src/Shaders/TransparentChecker.shader" type="Shader" id=1] -[ext_resource path="res://src/UI/TransparentChecker.tscn" type="PackedScene" id=2] -[ext_resource path="res://src/UI/Timeline/PixelCelButton.gd" type="Script" id=3] +[ext_resource path="res://src/UI/Timeline/BaseCelButton.tscn" type="PackedScene" id=1] +[ext_resource path="res://src/UI/Timeline/PixelCelButton.gd" type="Script" id=2] -[sub_resource type="ShaderMaterial" id=1] -shader = ExtResource( 1 ) -shader_param/size = 10.0 -shader_param/alpha = 1.0 -shader_param/color1 = Color( 0.7, 0.7, 0.7, 1 ) -shader_param/color2 = Color( 1, 1, 1, 1 ) -shader_param/offset = Vector2( 0, 0 ) -shader_param/scale = Vector2( 0, 0 ) -shader_param/rect_size = Vector2( 0, 0 ) -shader_param/follow_movement = false -shader_param/follow_scale = false +[node name="PixelCelButton" instance=ExtResource( 1 )] +rect_pivot_offset = Vector2( -18, 6 ) +script = ExtResource( 2 ) -[node name="CelButton" type="Button"] -margin_top = 18.0 -margin_right = 36.0 -margin_bottom = 54.0 -rect_min_size = Vector2( 36, 36 ) -mouse_default_cursor_shape = 2 -size_flags_horizontal = 0 -size_flags_vertical = 0 -toggle_mode = true -button_mask = 7 -script = ExtResource( 3 ) -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="CelTexture" type="TextureRect" parent="."] -margin_left = 2.0 -margin_top = 1.78536 -margin_right = 34.0 -margin_bottom = 33.7854 -rect_min_size = Vector2( 32, 32 ) -size_flags_horizontal = 0 -size_flags_vertical = 0 -expand = true -stretch_mode = 6 -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="TransparentChecker" parent="CelTexture" instance=ExtResource( 2 )] -show_behind_parent = true -material = SubResource( 1 ) -anchor_right = 1.0 -anchor_bottom = 1.0 -margin_right = 0.0 -margin_bottom = 0.0 - -[node name="PopupMenu" type="PopupMenu" parent="."] +[node name="PopupMenu" type="PopupMenu" parent="." index="1"] margin_right = 20.0 margin_bottom = 20.0 mouse_default_cursor_shape = 2 @@ -62,12 +16,10 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="LinkedIndicator" type="Polygon2D" parent="."] +[node name="LinkedIndicator" type="Polygon2D" parent="." index="2"] color = Color( 0.0627451, 0.741176, 0.215686, 1 ) invert_enable = true invert_border = 1.0 polygon = PoolVector2Array( 0, 0, 36, 0, 36, 36, 0, 36 ) -[connection signal="pressed" from="." to="." method="_on_CelButton_pressed"] -[connection signal="resized" from="." to="." method="_on_CelButton_resized"] [connection signal="id_pressed" from="PopupMenu" to="." method="_on_PopupMenu_id_pressed"] From 9a7b77ae6a8924df09b967e442eb6aa5255138bf Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sun, 15 May 2022 23:15:13 -0400 Subject: [PATCH 025/154] First bit of the refactoring work --- src/Classes/Project.gd | 111 +++++++++++ src/UI/Timeline/AnimationTimeline.gd | 264 ++++++--------------------- src/UI/Timeline/LayerButton.gd | 91 ++++----- 3 files changed, 208 insertions(+), 258 deletions(-) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 0e18680da708..95e3efb01b22 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -911,3 +911,114 @@ func resize_bitmap_values(bitmap: BitMap, new_size: Vector2, flip_x: bool, flip_ new_bitmap.create_from_image_alpha(image) return new_bitmap + + +func add_frame(frame: Frame, index: int) -> void: + # TODO: May need to call _frames_changed setter here (at least for some of it) + frames.insert(index, frame) + current_frame = index # TODO Probably need to call setter + # TODO: Test link/unlink cels and animation tag pushing thoroughly, I'm not sure if they're + # easily reversable (probably possible though, tags may need an "undo" bool, links + # may work with a passed array, or maybe its better if they're just not handled here + + # Link cels: + for l_i in range(layers.size()): + if layers[l_i].new_cels_linked: # If the link button is pressed + layers[l_i].linked_cels.append(frame) + frame.cels[l_i].image = layers[l_i].linked_cels[0].cels[l_i].image + frame.cels[l_i].image_texture = layers[l_i].linked_cels[0].cels[l_i].image_texture + + # PUSH AHEAD animation tags starting after the frame + for tag in animation_tags: + if index >= tag.from && index <= tag.to: + tag.to += 1 + elif (index) < tag.from: + tag.from += 1 + tag.to += 1 + + # TODO: Check if these (especially remove/move) mess up selection? + _frames_changed(frames)# TODO: Add Frame and Cel Buttons + + +func remove_frame(index: int) -> void: + # TODO: If this messes up selection, would doing multiple here help? + frames.remove(index) + # TODO: Figure out what to set current_frame to + current_frame -= 1 + + # Unlink cels: + for layer in layers: + for linked in layer.linked_cels: + if linked == frames[index]: + layer.linked_cels.erase(linked) + + # PUSH BACK animation tags starting after the frame + for tag in animation_tags: + if index >= tag.from && index <= tag.to: + tag.to -= 1 + elif (index) < tag.from: + tag.from -= 1 + tag.to -= 1 + + _frames_changed(frames)# TODO: Remove Frame/CelButtons + + +func move_frame(from_index: int, to_index: int) -> void: + var frame = frames[from_index] + frames.remove(from_index) + # TODO: Ensure the final position is always right + frames.insert(to_index, frame) + # TODO: Set current frame + _frames_changed(frames)# TODO: Remove and then add Frame/CelButtons + + +func add_layer(layer: BaseLayer, index: int, cels: Array) -> void: + # TODO: Global.canvas.selection.transform_content_confirm() + layers.insert(index, layer) + current_layer = index # TODO: Setter (which is the preferred way to call it?) + for f in range(frames.size()): + frames[f].cels.insert(index, cels[f]) + # TODO: Update layer index + _layers_changed(layers)# TODO: Add layer and cel buttons + + +func remove_layer(index: int) -> void: + # TODO: Global.canvas.selection.transform_content_confirm() + layers.remove(index) + current_layer = index - 1 # TODO: Setter + for frame in frames: + frame.cels.remove(index) + # TODO: Update layer index + _layers_changed(layers)# TODO: Remove layer and cel buttons + + +# from_indices and to_indicies should start from the lowest index, and go up +func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> void: + # TODO: it may be good to do a test run with using loops of add/remove_layer instead of using move_layers + # to_parents could just be a single for now, but then how should move_layers be named? + # TODO: Global.canvas.selection.transform_content_confirm() + var old_layers := layers.duplicate() + var removed_cels := [] # Array of array of cels (an array for each layer removed) + + for i in range(from_indices.size()): + # With each removed index, future indices need to be lowered, so subtract by i + layers.remove(from_indices[i] - i) + removed_cels.append([]) + for frame in frames: + removed_cels[i].append(frame.cels[from_indices[i] - i]) + frame.cels.remove(from_indices[i] - i) + # TODO: remove layer and cel buttons + for i in range(to_indices.size()): + layers.insert(to_indices[i], old_layers[from_indices[i]]) + layers[to_indices[i]].parent = to_parents[i] + # TODO: Frames... + for f in range(frames.size()): + frames[f].cels.insert(to_indices[i], removed_cels[i][f]) + # TODO: Add layer and cel buttons + # TODO: Update layer index + _layers_changed(layers) # TODO Remove (needs buttons and index update) + + +func move_cel() -> void: + # not sure about this one + pass diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index ec298a69428c..9c621cfede83 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -134,53 +134,15 @@ func add_frame() -> void: var project: Project = Global.current_project var frame_add_index := project.current_frame + 1 var frame: Frame = project.new_empty_frame() - var new_frames: Array = project.frames.duplicate() - var new_layers: Array = project.duplicate_layers() - new_frames.insert(frame_add_index, frame) - - for l_i in range(new_layers.size()): - if new_layers[l_i].new_cels_linked: # If the link button is pressed - new_layers[l_i].linked_cels.append(frame) - frame.cels[l_i].image = new_layers[l_i].linked_cels[0].cels[l_i].image - frame.cels[l_i].image_texture = new_layers[l_i].linked_cels[0].cels[l_i].image_texture - - # Code to PUSH AHEAD tags starting after the frame - var new_animation_tags := Global.current_project.animation_tags.duplicate() - # Loop through the tags to create new classes for them, so that they won't be the same - # as Global.current_project.animation_tags's classes. Needed for undo/redo to work properly. - for i in new_animation_tags.size(): - new_animation_tags[i] = AnimationTag.new( - new_animation_tags[i].name, - new_animation_tags[i].color, - new_animation_tags[i].from, - new_animation_tags[i].to - ) - # Loop through the tags to see if the frame is in one - for tag in new_animation_tags: - if frame_add_index >= tag.from && frame_add_index <= tag.to: - tag.to += 1 - elif (frame_add_index) < tag.from: - tag.from += 1 - tag.to += 1 project.undos += 1 project.undo_redo.create_action("Add Frame") project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) - project.undo_redo.add_do_property(project, "frames", new_frames) - project.undo_redo.add_do_property(project, "current_frame", project.current_frame + 1) - Global.current_project.undo_redo.add_do_property( - Global.current_project, "animation_tags", new_animation_tags - ) - project.undo_redo.add_do_property(project, "layers", new_layers) + project.undo_redo.add_do_method(project, "add_frame", frame, frame_add_index) + project.undo_redo.add_undo_method(project, "remove_frame", frame_add_index) - project.undo_redo.add_undo_property(project, "frames", project.frames) - project.undo_redo.add_undo_property(project, "current_frame", project.current_frame) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "animation_tags", Global.current_project.animation_tags - ) - project.undo_redo.add_undo_property(project, "layers", project.layers) project.undo_redo.commit_action() @@ -195,85 +157,25 @@ func _on_DeleteFrame_pressed(frame := -1) -> void: func delete_frames(frames := []) -> void: - if Global.current_project.frames.size() == 1: + var project: Project = Global.current_project + if project.frames.size() == 1: return if frames.size() == 0: - frames.append(Global.current_project.current_frame) - - var new_frames: Array = Global.current_project.frames.duplicate() - var current_frame := Global.current_project.current_frame - var new_layers: Array = Global.current_project.duplicate_layers() - var frame_correction := 0 # Only needed for tag adjustment + frames.append(project.current_frame) - var new_animation_tags := Global.current_project.animation_tags.duplicate() - # Loop through the tags to create new classes for them, so that they won't be the same - # as Global.current_project.animation_tags's classes. Needed for undo/redo to work properly. - for i in new_animation_tags.size(): - new_animation_tags[i] = AnimationTag.new( - new_animation_tags[i].name, - new_animation_tags[i].color, - new_animation_tags[i].from, - new_animation_tags[i].to + project.undos += 1 + project.undo_redo.create_action("Remove Frame") + + var x := frames.size() - 1 + while x >= 0: + project.undo_redo.add_do_method(project, "remove_frame", frames[x]) + x -= 1 + for i in range(frames.size()): + project.undo_redo.add_undo_method( + project, "add_frame", project.frames[frames[i]], frames[i] ) - for frame in frames: - if new_frames.size() == 1: # If only 1 frame - break - var frame_to_delete: Frame = Global.current_project.frames[frame] - new_frames.erase(frame_to_delete) - if current_frame > 0 && current_frame == new_frames.size(): # If it's the last frame - current_frame -= 1 - - # Check if one of the cels of the frame is linked - # if they are, unlink them too - # this prevents removed cels being kept in linked memory - for layer in new_layers: - for linked in layer.linked_cels: - if linked == Global.current_project.frames[frame]: - layer.linked_cels.erase(linked) - - # Loop through the tags to see if the frame is in one - frame -= frame_correction # Erasing made frames indexes 1 step ahead their intended tags - var tag_correction := 0 # needed when tag is erased - for tag_ind in new_animation_tags.size(): - var tag = new_animation_tags[tag_ind - tag_correction] - if frame + 1 >= tag.from && frame + 1 <= tag.to: - if tag.from == tag.to: # If we're deleting the only frame in the tag - new_animation_tags.erase(tag) - tag_correction += 1 - else: - tag.to -= 1 - elif frame + 1 < tag.from: - tag.from -= 1 - tag.to -= 1 - frame_correction += 1 # Compensation for the next batch - - Global.current_project.undos += 1 - Global.current_project.undo_redo.create_action("Remove Frame") - - Global.current_project.undo_redo.add_do_property(Global.current_project, "frames", new_frames) - Global.current_project.undo_redo.add_do_property( - Global.current_project, "current_frame", current_frame - ) - Global.current_project.undo_redo.add_do_property( - Global.current_project, "animation_tags", new_animation_tags - ) - Global.current_project.undo_redo.add_do_property(Global.current_project, "layers", new_layers) - - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "frames", Global.current_project.frames - ) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "current_frame", Global.current_project.current_frame - ) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "animation_tags", Global.current_project.animation_tags - ) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "layers", Global.current_project.layers - ) - Global.current_project.undo_redo.add_do_method(Global, "undo_or_redo", false) Global.current_project.undo_redo.add_undo_method(Global, "undo_or_redo", true) Global.current_project.undo_redo.commit_action() @@ -290,6 +192,7 @@ func _on_CopyFrame_pressed(frame := -1) -> void: func copy_frames(frames := []) -> void: + # TODO: Work on this one (probably need a copy_to function on Cel classes) Global.canvas.selection.transform_content_confirm() if frames.size() == 0: @@ -371,6 +274,7 @@ func _on_FrameTagButton_pressed() -> void: func _on_MoveLeft_pressed() -> void: + # TODO: Do these var frame: int = Global.current_project.current_frame if frame == 0: return @@ -607,133 +511,85 @@ func _on_FuturePlacement_item_selected(index: int) -> void: func add_layer(is_new := true) -> void: + # TODO: Duplicate functionality should probably be split out to allow for different layer types Global.canvas.selection.transform_content_confirm() - var new_layers: Array = Global.current_project.layers.duplicate() var l := PixelLayer.new() + var project: Project = Global.current_project if !is_new: # Clone layer l.name = ( - Global.current_project.layers[Global.current_project.current_layer].name + project.layers[project.current_layer].name + " (" + tr("copy") + ")" ) - new_layers.append(l) - Global.current_project.undos += 1 - Global.current_project.undo_redo.create_action("Add Layer") + project.undos += 1 + project.undo_redo.create_action("Add Layer") - for f in Global.current_project.frames: + var cels := [] + + for f in project.frames: var new_layer := Image.new() if is_new: new_layer.create( - Global.current_project.size.x, - Global.current_project.size.y, + project.size.x, + project.size.y, false, Image.FORMAT_RGBA8 ) else: # Clone layer - new_layer.copy_from(f.cels[Global.current_project.current_layer].image) + new_layer.copy_from(f.cels[project.current_layer].image) - var new_cels: Array = f.cels.duplicate() - new_cels.append(PixelCel.new(new_layer, 1)) - Global.current_project.undo_redo.add_do_property(f, "cels", new_cels) - Global.current_project.undo_redo.add_undo_property(f, "cels", f.cels) + cels.append(PixelCel.new(new_layer, 1)) - Global.current_project.undo_redo.add_do_property( - Global.current_project, "current_layer", Global.current_project.layers.size() - ) - Global.current_project.undo_redo.add_do_property(Global.current_project, "layers", new_layers) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "current_layer", Global.current_project.current_layer - ) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "layers", Global.current_project.layers - ) + project.undo_redo.add_do_method(project, "add_layer", l, project.layers.size(), cels) + project.undo_redo.add_undo_method(project, "remove_layer", project.layers.size()) - Global.current_project.undo_redo.add_undo_method(Global, "undo_or_redo", true) - Global.current_project.undo_redo.add_do_method(Global, "undo_or_redo", false) - Global.current_project.undo_redo.commit_action() + project.undo_redo.add_undo_method(Global, "undo_or_redo", true) + project.undo_redo.add_do_method(Global, "undo_or_redo", false) + project.undo_redo.commit_action() func add_group_layer(is_new := true) -> void: Global.canvas.selection.transform_content_confirm() - var new_layers: Array = Global.current_project.layers.duplicate() var l := GroupLayer.new() -# if !is_new: # Clone layer -# l.name = ( -# Global.current_project.layers[Global.current_project.current_layer].name -# + " (" -# + tr("copy") -# + ")" -# ) - new_layers.append(l) - - # Add current layer to this group -# Global.current_project.layers[Global.current_project.current_layer].parent = l - # Add all layers to this group: -# for layer in Global.current_project.layers: -# if not layer.parent: -# layer.parent = l - # Add last layer to this group: -# Global.current_project.layers[-1].parent = l - Global.current_project.undos += 1 - Global.current_project.undo_redo.create_action("Add Layer") + var project: Project = Global.current_project + project.undos += 1 + project.undo_redo.create_action("Add Layer") - for f in Global.current_project.frames: - var new_cels: Array = f.cels.duplicate() - new_cels.append(GroupCel.new()) - Global.current_project.undo_redo.add_do_property(f, "cels", new_cels) - Global.current_project.undo_redo.add_undo_property(f, "cels", f.cels) + var cels := [] + for f in project.frames: + cels.append(GroupCel.new()) - Global.current_project.undo_redo.add_do_property( - Global.current_project, "current_layer", Global.current_project.layers.size() - ) - Global.current_project.undo_redo.add_do_property(Global.current_project, "layers", new_layers) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "current_layer", Global.current_project.current_layer - ) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "layers", Global.current_project.layers - ) + project.undo_redo.add_do_method(project, "add_layer", l, project.layers.size(), cels) + project.undo_redo.add_undo_method(project, "remove_layer", project.layers.size()) - Global.current_project.undo_redo.add_undo_method(Global, "undo_or_redo", true) - Global.current_project.undo_redo.add_do_method(Global, "undo_or_redo", false) - Global.current_project.undo_redo.commit_action() + project.undo_redo.add_undo_method(Global, "undo_or_redo", true) + project.undo_redo.add_do_method(Global, "undo_or_redo", false) + project.undo_redo.commit_action() func _on_RemoveLayer_pressed() -> void: - if Global.current_project.layers.size() == 1: + var project: Project = Global.current_project + if project.layers.size() == 1: return - var new_layers: Array = Global.current_project.layers.duplicate() - new_layers.remove(Global.current_project.current_layer) - Global.current_project.undos += 1 - Global.current_project.undo_redo.create_action("Remove Layer") - if Global.current_project.current_layer > 0: - Global.current_project.undo_redo.add_do_property( - Global.current_project, "current_layer", Global.current_project.current_layer - 1 - ) - else: - Global.current_project.undo_redo.add_do_property( - Global.current_project, "current_layer", Global.current_project.current_layer - ) - for f in Global.current_project.frames: - var new_cels: Array = f.cels.duplicate() - new_cels.remove(Global.current_project.current_layer) - Global.current_project.undo_redo.add_do_property(f, "cels", new_cels) - Global.current_project.undo_redo.add_undo_property(f, "cels", f.cels) + project.undos += 1 + project.undo_redo.create_action("Remove Layer") - Global.current_project.undo_redo.add_do_property(Global.current_project, "layers", new_layers) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "current_layer", Global.current_project.current_layer - ) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "layers", Global.current_project.layers + var cels := [] + for f in project.frames: + cels.append(f.cels[project.current_layer]) + + project.undo_redo.add_do_method(project, "remove_layer", project.current_layer) + project.undo_redo.add_undo_method( + project, "add_layer", project.layers[project.current_layer], project.current_layer, cels ) - Global.current_project.undo_redo.add_do_method(Global, "undo_or_redo", false) - Global.current_project.undo_redo.add_undo_method(Global, "undo_or_redo", true) - Global.current_project.undo_redo.commit_action() + + project.undo_redo.add_do_method(Global, "undo_or_redo", false) + project.undo_redo.add_undo_method(Global, "undo_or_redo", true) + project.undo_redo.commit_action() func change_layer_order(rate: int) -> void: diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index 76ff6cc8d46c..6c5804375f0d 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -192,7 +192,7 @@ func can_drop_data(_pos, data) -> bool: var region: Rect2 var depth: int = Global.current_project.layers[layer].get_hierarchy_depth() - if Input.is_key_pressed(KEY_CONTROL): # Swap layers + if Input.is_action_pressed("ctrl"): # Swap layers if drag_layer.is_a_parent_of(curr_layer) or curr_layer.is_a_parent_of(drag_layer): Global.animation_timeline.drag_highlight.visible = false return false @@ -232,24 +232,30 @@ func drop_data(_pos, data) -> void: Global.current_project.undo_redo.create_action("Change Layer Order") var new_layers: Array = Global.current_project.layers.duplicate() var temp: BaseLayer = new_layers[layer] - if Input.is_key_pressed(KEY_CONTROL): # Swap layers # TODO Need to check when swapping is allowed - new_layers[layer] = new_layers[dropped_layer] - new_layers[dropped_layer] = temp - - # TODO: Make sure to swap parents too - - for f in Global.current_project.frames: - var new_cels: Array = f.cels.duplicate() - var temp_canvas = new_cels[layer] - new_cels[layer] = new_cels[dropped_layer] - new_cels[dropped_layer] = temp_canvas - Global.current_project.undo_redo.add_do_property(f, "cels", new_cels) - Global.current_project.undo_redo.add_undo_property(f, "cels", f.cels) + if Input.is_action_pressed("ctrl"): # Swap layers # TODO Need to check when swapping is allowed + pass # TODO: Figure out swapping +# new_layers[layer] = new_layers[dropped_layer] +# new_layers[dropped_layer] = temp +# +# # TODO: Make sure to swap parents too +# +# for f in Global.current_project.frames: +# var new_cels: Array = f.cels.duplicate() +# var temp_canvas = new_cels[layer] +# new_cels[layer] = new_cels[dropped_layer] +# new_cels[dropped_layer] = temp_canvas +# Global.current_project.undo_redo.add_do_property(f, "cels", new_cels) +# Global.current_project.undo_redo.add_undo_property(f, "cels", f.cels) # TODO: Having "SourceLayers/OldLayers (that you don't change) and new_layers would make this less confusing else: # layers_to_shift should be in order of the layer indices, starting from the lowest - var layers_to_shift: Array = new_layers[dropped_layer].get_children_recursive() - layers_to_shift.append(new_layers[dropped_layer]) +# var layers_to_shift: Array = new_layers[dropped_layer].get_children_recursive() +# layers_to_shift.append(new_layers[dropped_layer]) + + var from_indices := [] + for c in new_layers[dropped_layer].get_children_recursive(): + from_indices.append(c.index) + from_indices.append(dropped_layer) var to_index: int # the index where the LOWEST shifted layer should end up var to_parent: BaseLayer @@ -271,54 +277,31 @@ func drop_data(_pos, data) -> void: to_index = new_layers[layer].get_children_recursive()[0].index if new_layers[layer].is_a_parent_of(new_layers[dropped_layer]): - to_index += layers_to_shift.size() + to_index += from_indices.size() else: to_index = layer # TODO Is this right? to_parent = new_layers[layer].parent - # Make sure to set parent BEFORE adjusting new_layers - Global.current_project.undo_redo.add_do_property( - new_layers[dropped_layer], "parent", to_parent - ) - Global.current_project.undo_redo.add_undo_property( - new_layers[dropped_layer], "parent", new_layers[dropped_layer].parent - ) - if dropped_layer < layer: - to_index -= layers_to_shift.size() + to_index -= from_indices.size() print("to_index = ", to_index) - var x := layers_to_shift.size() - 1 - while x >= 0: - new_layers.remove(layers_to_shift[x].index) - x -= 1 - for i in range(layers_to_shift.size()): - new_layers.insert(to_index + i, layers_to_shift[i]) - - for f in Global.current_project.frames: - var new_cels: Array = f.cels.duplicate() - x = layers_to_shift.size() - 1 - while x >= 0: - new_cels.remove(layers_to_shift[x].index) - x -= 1 - for i in range(layers_to_shift.size()): - new_cels.insert(to_index + i, f.cels[layers_to_shift[i].index]) - - Global.current_project.undo_redo.add_do_property(f, "cels", new_cels) - Global.current_project.undo_redo.add_undo_property(f, "cels", f.cels) - - if Global.current_project.current_layer == layer: - Global.current_project.undo_redo.add_do_property( - Global.current_project, "current_layer", dropped_layer + var to_indices := [] + var from_parents := [] + for i in range(from_indices.size()): + to_indices.append(to_index + i) + from_parents.append(new_layers[from_indices[i]].parent) + var to_parents := from_parents.duplicate() + to_parents[-1] = to_parent + + Global.current_project.undo_redo.add_do_method( + Global.current_project, "move_layers", from_indices, to_indices, to_parents ) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "current_layer", Global.current_project.current_layer + Global.current_project.undo_redo.add_undo_method( + Global.current_project, "move_layers", to_indices, from_indices, from_parents ) - Global.current_project.undo_redo.add_do_property(Global.current_project, "layers", new_layers) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "layers", Global.current_project.layers - ) + # TODO: undo_or_redo is at end here, but earlier in others, does it matter which order? Global.current_project.undo_redo.add_undo_method(Global, "undo_or_redo", true) Global.current_project.undo_redo.add_do_method(Global, "undo_or_redo", false) Global.current_project.undo_redo.commit_action() From 2751193802da3756d5ca3d73bb17c54d2f4a586a Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Mon, 20 Jun 2022 15:39:35 -0400 Subject: [PATCH 026/154] Several bits of refactoring --- src/Autoload/Global.gd | 1 + src/Classes/BaseCel.gd | 8 + src/Classes/GroupCel.gd | 4 + src/Classes/PixelCel.gd | 6 + src/Classes/Project.gd | 437 +++++++++++++++---------- src/UI/Canvas/Canvas.gd | 13 +- src/UI/Timeline/AnimationTimeline.gd | 222 ++++++++++++- src/UI/Timeline/AnimationTimeline.tscn | 19 +- src/UI/Timeline/FrameButton.gd | 103 ++++-- src/UI/Timeline/LayerButton.gd | 53 +-- src/UI/Timeline/PixelCelButton.gd | 161 +++++---- 11 files changed, 706 insertions(+), 321 deletions(-) diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index bab6574b0e18..3c593d47a435 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -255,6 +255,7 @@ func undo_or_redo( cursor_position_label.text = "[%s×%s]" % [project.size.x, project.size.y] elif "Frame" in action_name: + # TODO: Does what this comment says after the refacotr remain true? # This actually means that frames.size is one, but it hasn't been updated yet if (undo and project.frames.size() == 2) or project.frames.size() == 1: # Stop animating play_forward.pressed = false diff --git a/src/Classes/BaseCel.gd b/src/Classes/BaseCel.gd index df61a91b7fc1..744863b08907 100644 --- a/src/Classes/BaseCel.gd +++ b/src/Classes/BaseCel.gd @@ -13,9 +13,17 @@ var opacity: float # its image data for PixelCels, or return a render of that cel. It's meant # for read-only usage of image data from any type of cel +func get_image() -> Image: + return null + + func save_image_data_to_pxo(_file: File) -> void: return func load_image_data_from_pxo(_file: File, _project_size: Vector2) -> void: return + + +func create_cel_button() -> Button: + return null diff --git a/src/Classes/GroupCel.gd b/src/Classes/GroupCel.gd index fdac4931de59..e03d6f971f7b 100644 --- a/src/Classes/GroupCel.gd +++ b/src/Classes/GroupCel.gd @@ -10,3 +10,7 @@ func _init(_opacity := 1.0) -> void: func get_image() -> Image: # TODO: render the material as an image and return it return Image.new() + + +func create_cel_button() -> Button: + return load("res://src/UI/Timeline/GroupCelButton.tscn").instance() as Button diff --git a/src/Classes/PixelCel.gd b/src/Classes/PixelCel.gd index 7aa462635744..24b70d073361 100644 --- a/src/Classes/PixelCel.gd +++ b/src/Classes/PixelCel.gd @@ -35,3 +35,9 @@ func load_image_data_from_pxo(file: File, project_size: Vector2) -> void: var buffer := file.get_buffer(project_size.x * project_size.y * 4) image.create_from_data(project_size.x, project_size.y, false, Image.FORMAT_RGBA8, buffer) image_changed(image) + + +func create_cel_button() -> Button: + var cel_button = load("res://src/UI/Timeline/PixelCelButton.tscn").instance() + cel_button.get_child(0).texture = image_texture + return cel_button diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 95e3efb01b22..b74b16767bcc 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -45,11 +45,13 @@ var file_format: int = Export.FileFormat.PNG var was_exported := false var export_overwrite := false +# TODO: These should be able to be removed.... var frame_button_node = preload("res://src/UI/Timeline/FrameButton.tscn") var pixel_layer_button_node = preload("res://src/UI/Timeline/PixelLayerButton.tscn") var group_layer_button_node = preload("res://src/UI/Timeline/GroupLayerButton.tscn") var pixel_cel_button_node = preload("res://src/UI/Timeline/PixelCelButton.tscn") var group_cel_button_node = preload("res://src/UI/Timeline/GroupCelButton.tscn") +# ... up to this: var animation_tag_node = preload("res://src/UI/Timeline/AnimationTagUI.tscn") @@ -140,63 +142,65 @@ func _selection_offset_changed(value: Vector2) -> void: func change_project() -> void: # Remove old nodes - for container in Global.layers_container.get_children(): - container.queue_free() - - _remove_cel_buttons() - - for frame_id in Global.frame_ids.get_children(): - Global.frame_ids.remove_child(frame_id) - frame_id.queue_free() - - # Create new ones - for i in range(layers.size() - 1, -1, -1): - # Create layer buttons - var layer_container: LayerButton - if layers[i] is PixelLayer: - layer_container = pixel_layer_button_node.instance() - elif layers[i] is GroupLayer: - layer_container = group_layer_button_node.instance() - layer_container.layer = i - if layers[i].name == "": - layers[i].name = layers[i].get_default_name(i) - - Global.layers_container.add_child(layer_container) - layer_container.label.text = layers[i].name - layer_container.line_edit.text = layers[i].name - - var layer_cel_container := HBoxContainer.new() - Global.frames_container.add_child(layer_cel_container) - for j in range(frames.size()): # Create Cel buttons - var cel_button = pixel_cel_button_node.instance() - cel_button.frame = j - cel_button.layer = i - # TODO: Mak sure this works properly with groups - cel_button.get_child(0).texture = frames[j].cels[i].image_texture - if j == current_frame and i == current_layer: - cel_button.pressed = true - - layer_cel_container.add_child(cel_button) - - if (is_instance_valid(layers[i].parent) - and not layers[i].parent.is_expanded_in_hierarchy()): - layer_cel_container.visible = false - - for j in range(frames.size()): # Create frame ID labels - var button: Button = frame_button_node.instance() - button.frame = j - button.rect_min_size.x = Global.animation_timeline.cel_size - button.text = str(j + 1) - if j == current_frame: - button.add_color_override( - "font_color", Global.control.theme.get_color("Selected Color", "Label") - ) - Global.frame_ids.add_child(button) - - var layer_button = Global.layers_container.get_child( - Global.layers_container.get_child_count() - 1 - current_layer - ) - layer_button.pressed = true +# for container in Global.layers_container.get_children(): +# container.queue_free() +# +# _remove_cel_buttons() +# +# for frame_id in Global.frame_ids.get_children(): +# Global.frame_ids.remove_child(frame_id) +# frame_id.queue_free() +# +# # Create new ones +# for i in range(layers.size() - 1, -1, -1): +# # Create layer buttons +# var layer_container: LayerButton +# if layers[i] is PixelLayer: +# layer_container = pixel_layer_button_node.instance() +# elif layers[i] is GroupLayer: +# layer_container = group_layer_button_node.instance() +# layer_container.layer = i +# if layers[i].name == "": +# layers[i].name = layers[i].get_default_name(i) +# +# Global.layers_container.add_child(layer_container) +# layer_container.label.text = layers[i].name +# layer_container.line_edit.text = layers[i].name +# +# var layer_cel_container := HBoxContainer.new() +# Global.frames_container.add_child(layer_cel_container) +# for j in range(frames.size()): # Create Cel buttons +# var cel_button = pixel_cel_button_node.instance() +# cel_button.frame = j +# cel_button.layer = i +# # TODO: Mak sure this works properly with groups +# cel_button.get_child(0).texture = frames[j].cels[i].image_texture +# if j == current_frame and i == current_layer: +# cel_button.pressed = true +# +# layer_cel_container.add_child(cel_button) +# +# if (is_instance_valid(layers[i].parent) +# and not layers[i].parent.is_expanded_in_hierarchy()): +# layer_cel_container.visible = false +# +# for j in range(frames.size()): # Create frame ID labels +# var button: Button = frame_button_node.instance() +# button.frame = j +# button.rect_min_size.x = Global.animation_timeline.cel_size +# button.text = str(j + 1) +# if j == current_frame: +# button.add_color_override( +# "font_color", Global.control.theme.get_color("Selected Color", "Label") +# ) +# Global.frame_ids.add_child(button) +# +# var layer_button = Global.layers_container.get_child( +# Global.layers_container.get_child_count() - 1 - current_layer +# ) +# layer_button.pressed = true + + Global.animation_timeline.project_changed() Global.current_frame_mark_label.text = "%s/%s" % [str(current_frame + 1), frames.size()] @@ -459,36 +463,36 @@ func _frames_changed(value: Array) -> void: Global.canvas.selection.transform_content_confirm() frames = value selected_cels.clear() - _remove_cel_buttons() - - for frame_id in Global.frame_ids.get_children(): - Global.frame_ids.remove_child(frame_id) - frame_id.queue_free() - - for i in range(layers.size() - 1, -1, -1): - var layer_cel_container := HBoxContainer.new() - layer_cel_container.name = "FRAMESS " + str(i) - Global.frames_container.add_child(layer_cel_container) - for j in range(frames.size()): - if layers[i] is PixelLayer: - var cel_button = pixel_cel_button_node.instance() - cel_button.frame = j - cel_button.layer = i - cel_button.get_child(0).texture = frames[j].cels[i].image_texture - layer_cel_container.add_child(cel_button) - elif layers[i] is GroupLayer: - # TODO: Make GroupLayers work here - pass - if (is_instance_valid(layers[i].parent) - and not layers[i].parent.is_expanded_in_hierarchy()): - layer_cel_container.visible = false - - for j in range(frames.size()): - var button: Button = frame_button_node.instance() - button.frame = j - button.rect_min_size.x = Global.animation_timeline.cel_size - button.text = str(j + 1) - Global.frame_ids.add_child(button) +# _remove_cel_buttons() +# +# for frame_id in Global.frame_ids.get_children(): +# Global.frame_ids.remove_child(frame_id) +# frame_id.queue_free() +# +# for i in range(layers.size() - 1, -1, -1): +# var layer_cel_container := HBoxContainer.new() +# layer_cel_container.name = "FRAMESS " + str(i) +# Global.frames_container.add_child(layer_cel_container) +# for j in range(frames.size()): +# if layers[i] is PixelLayer: +# var cel_button = pixel_cel_button_node.instance() +# cel_button.frame = j +# cel_button.layer = i +# cel_button.get_child(0).texture = frames[j].cels[i].image_texture +# layer_cel_container.add_child(cel_button) +# elif layers[i] is GroupLayer: +# # TODO: Make GroupLayers work here +# pass +# if (is_instance_valid(layers[i].parent) +# and not layers[i].parent.is_expanded_in_hierarchy()): +# layer_cel_container.visible = false +# +# for j in range(frames.size()): +# var button: Button = frame_button_node.instance() +# button.frame = j +# button.rect_min_size.x = Global.animation_timeline.cel_size +# button.text = str(j + 1) +# Global.frame_ids.add_child(button) _set_timeline_first_and_last_frames() @@ -501,50 +505,50 @@ func _layers_changed(value: Array) -> void: selected_cels.clear() - for container in Global.layers_container.get_children(): - container.queue_free() - - _remove_cel_buttons() - - for i in range(layers.size() - 1, -1, -1): - var layer_button: LayerButton - if layers[i] is PixelLayer: - layer_button = pixel_layer_button_node.instance() - elif layers[i] is GroupLayer: - layer_button = group_layer_button_node.instance() - layer_button.layer = i - layers[i].index = i - layers[i].project = self - if layers[i].name == "": - layers[i].name = layers[i].get_default_name(i) - - Global.layers_container.add_child(layer_button) - layer_button.label.text = layers[i].name - layer_button.line_edit.text = layers[i].name - - var layer_cel_container := HBoxContainer.new() - layer_cel_container.name = "LAYERSSS " + str(i) - Global.frames_container.add_child(layer_cel_container) - # TODO: FIGURE OUT FRAMES WITH GROUP LAYERS! - for j in range(frames.size()): - var cel_button # TODO: Figure out static typing (will there be a BaseCelButton?) - if layers[i] is PixelLayer: - cel_button = pixel_cel_button_node.instance() - cel_button.get_child(0).texture = frames[j].cels[i].image_texture - elif layers[i] is GroupLayer: - cel_button = group_cel_button_node.instance() - cel_button.frame = j - cel_button.layer = i - layer_cel_container.add_child(cel_button) - if (is_instance_valid(layers[i].parent) - and not layers[i].parent.is_expanded_in_hierarchy()): - layer_cel_container.visible = false - - var layer_button = Global.layers_container.get_child( - Global.layers_container.get_child_count() - 1 - current_layer - ) - layer_button.pressed = true - self.current_frame = current_frame # Call frame_changed to update UI +# for container in Global.layers_container.get_children(): +# container.queue_free() +# +# _remove_cel_buttons() +# +# for i in range(layers.size() - 1, -1, -1): +# var layer_button: LayerButton +# if layers[i] is PixelLayer: +# layer_button = pixel_layer_button_node.instance() +# elif layers[i] is GroupLayer: +# layer_button = group_layer_button_node.instance() +# layer_button.layer = i +# layers[i].index = i +# layers[i].project = self +# if layers[i].name == "": +# layers[i].name = layers[i].get_default_name(i) +# +# Global.layers_container.add_child(layer_button) +# layer_button.label.text = layers[i].name +# layer_button.line_edit.text = layers[i].name +# +# var layer_cel_container := HBoxContainer.new() +# layer_cel_container.name = "LAYERSSS " + str(i) +# Global.frames_container.add_child(layer_cel_container) +# # TODO: FIGURE OUT FRAMES WITH GROUP LAYERS! +# for j in range(frames.size()): +# var cel_button # TODO: Figure out static typing (will there be a BaseCelButton?) +# if layers[i] is PixelLayer: +# cel_button = pixel_cel_button_node.instance() +# cel_button.get_child(0).texture = frames[j].cels[i].image_texture +# elif layers[i] is GroupLayer: +# cel_button = group_cel_button_node.instance() +# cel_button.frame = j +# cel_button.layer = i +# layer_cel_container.add_child(cel_button) +# if (is_instance_valid(layers[i].parent) +# and not layers[i].parent.is_expanded_in_hierarchy()): +# layer_cel_container.visible = false +# +# var layer_button = Global.layers_container.get_child( +# Global.layers_container.get_child_count() - 1 - current_layer +# ) +# layer_button.pressed = true +# self.current_frame = current_frame # Call frame_changed to update UI _toggle_layer_buttons_layers() @@ -916,80 +920,127 @@ func resize_bitmap_values(bitmap: BitMap, new_size: Vector2, flip_x: bool, flip_ func add_frame(frame: Frame, index: int) -> void: # TODO: May need to call _frames_changed setter here (at least for some of it) frames.insert(index, frame) - current_frame = index # TODO Probably need to call setter - # TODO: Test link/unlink cels and animation tag pushing thoroughly, I'm not sure if they're + # TODO: Test link/unlink cels thoroughly, I'm not sure if they're # easily reversable (probably possible though, tags may need an "undo" bool, links # may work with a passed array, or maybe its better if they're just not handled here - # Link cels: - for l_i in range(layers.size()): - if layers[l_i].new_cels_linked: # If the link button is pressed - layers[l_i].linked_cels.append(frame) - frame.cels[l_i].image = layers[l_i].linked_cels[0].cels[l_i].image - frame.cels[l_i].image_texture = layers[l_i].linked_cels[0].cels[l_i].image_texture - - # PUSH AHEAD animation tags starting after the frame - for tag in animation_tags: - if index >= tag.from && index <= tag.to: - tag.to += 1 - elif (index) < tag.from: - tag.from += 1 - tag.to += 1 +# # Link cels: +# for l_i in range(layers.size()): +# if layers[l_i].new_cels_linked: # If the link button is pressed +# layers[l_i].linked_cels.append(frame) +# frame.cels[l_i].image = layers[l_i].linked_cels[0].cels[l_i].image +# frame.cels[l_i].image_texture = layers[l_i].linked_cels[0].cels[l_i].image_texture +# # TODO: Check if these (especially remove/move) mess up selection? - _frames_changed(frames)# TODO: Add Frame and Cel Buttons + _frames_changed(frames)# TODO: Remove + # TODO: These may need an if self == Global.current_project depending on use + Global.animation_timeline.project_frame_added(index) + # Update the frames and frame buttons: + for f in range(frames.size()): + Global.frame_ids.get_child(f).frame = f + Global.frame_ids.get_child(f).text = str(f + 1) + # Update the cel buttons: + for l in range(layers.size()): + var layer_cel_container = Global.frames_container.get_child(layers.size() - 1 - l) + for f in range(frames.size()): + layer_cel_container.get_child(f).frame = f + layer_cel_container.get_child(f).button_setup() func remove_frame(index: int) -> void: # TODO: If this messes up selection, would doing multiple here help? frames.remove(index) - # TODO: Figure out what to set current_frame to - current_frame -= 1 - # Unlink cels: - for layer in layers: - for linked in layer.linked_cels: - if linked == frames[index]: - layer.linked_cels.erase(linked) +# # Unlink cels: +# for layer in layers: +# for linked in layer.linked_cels: +# if linked == frames[index]: +# layer.linked_cels.erase(linked) - # PUSH BACK animation tags starting after the frame - for tag in animation_tags: - if index >= tag.from && index <= tag.to: - tag.to -= 1 - elif (index) < tag.from: - tag.from -= 1 - tag.to -= 1 - - _frames_changed(frames)# TODO: Remove Frame/CelButtons + _frames_changed(frames)# TODO: Remove + Global.animation_timeline.project_frame_removed(index) + # Update the frames and frame buttons: + for f in range(frames.size()): + Global.frame_ids.get_child(f).frame = f + Global.frame_ids.get_child(f).text = str(f + 1) + # Update the cel buttons: + for l in range(layers.size()): + var layer_cel_container = Global.frames_container.get_child(layers.size() - 1 - l) + for f in range(frames.size()): + layer_cel_container.get_child(f).frame = f + layer_cel_container.get_child(f).button_setup() func move_frame(from_index: int, to_index: int) -> void: var frame = frames[from_index] frames.remove(from_index) + Global.animation_timeline.project_frame_removed(from_index) # TODO: Ensure the final position is always right frames.insert(to_index, frame) # TODO: Set current frame - _frames_changed(frames)# TODO: Remove and then add Frame/CelButtons + Global.animation_timeline.project_frame_added(to_index) + _frames_changed(frames)# TODO: Remove + # Update the frames and frame buttons: + for f in range(frames.size()): + Global.frame_ids.get_child(f).frame = f + Global.frame_ids.get_child(f).text = str(f + 1) + # Update the cel buttons: + for l in range(layers.size()): + var layer_cel_container = Global.frames_container.get_child(layers.size() - 1 - l) + for f in range(frames.size()): + layer_cel_container.get_child(f).frame = f + layer_cel_container.get_child(f).button_setup() + + +func swap_frame(a_index: int, b_index: int) -> void: + # TODO: current frame + var temp: Frame = frames[a_index] + frames[a_index] = frames[b_index] + frames[b_index] = temp + Global.animation_timeline.project_frame_removed(a_index) + Global.animation_timeline.project_frame_added(a_index) + Global.animation_timeline.project_frame_removed(b_index) + Global.animation_timeline.project_frame_added(b_index) func add_layer(layer: BaseLayer, index: int, cels: Array) -> void: # TODO: Global.canvas.selection.transform_content_confirm() layers.insert(index, layer) - current_layer = index # TODO: Setter (which is the preferred way to call it?) for f in range(frames.size()): frames[f].cels.insert(index, cels[f]) - # TODO: Update layer index - _layers_changed(layers)# TODO: Add layer and cel buttons + layer.project = self + # TODO: Update layer index (and others, more efficient if add layer supports multiple) + # TODO: Update layer button indices + _layers_changed(layers)# TODO: Remove + Global.animation_timeline.project_layer_added(index) + # Update the layer indices and layer/cel buttons: + for l in range(layers.size()): + layers[l].index = l + Global.layers_container.get_child(layers.size() - 1 - l).layer = l + var layer_cel_container = Global.frames_container.get_child(layers.size() - 1 - l) + for f in range(frames.size()): + layer_cel_container.get_child(f).layer = l + layer_cel_container.get_child(f).button_setup() func remove_layer(index: int) -> void: # TODO: Global.canvas.selection.transform_content_confirm() layers.remove(index) - current_layer = index - 1 # TODO: Setter for frame in frames: frame.cels.remove(index) - # TODO: Update layer index - _layers_changed(layers)# TODO: Remove layer and cel buttons + # TODO: Update layer index (and others, more efficient if remove layer supports multiple) + # TODO: Update layer button indices + _layers_changed(layers)# TODO: Remove + Global.animation_timeline.project_layer_removed(index) + # Update the layer indices and layer/cel buttons: + for l in range(layers.size()): + layers[l].index = l + Global.layers_container.get_child(layers.size() - 1 - l).layer = l + var layer_cel_container = Global.frames_container.get_child(layers.size() - 1 - l) + for f in range(frames.size()): + layer_cel_container.get_child(f).layer = l + layer_cel_container.get_child(f).button_setup() # from_indices and to_indicies should start from the lowest index, and go up @@ -1007,6 +1058,7 @@ func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> v for frame in frames: removed_cels[i].append(frame.cels[from_indices[i] - i]) frame.cels.remove(from_indices[i] - i) + Global.animation_timeline.project_layer_removed(from_indices[i] - i) # TODO: remove layer and cel buttons for i in range(to_indices.size()): layers.insert(to_indices[i], old_layers[from_indices[i]]) @@ -1014,11 +1066,46 @@ func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> v # TODO: Frames... for f in range(frames.size()): frames[f].cels.insert(to_indices[i], removed_cels[i][f]) + Global.animation_timeline.project_layer_added(to_indices[i]) # TODO: Add layer and cel buttons - # TODO: Update layer index + # Update the layer indices and layer/cel buttons: + for l in range(layers.size()): + layers[l].index = l + Global.layers_container.get_child(layers.size() - 1 - l).layer = l + var layer_cel_container = Global.frames_container.get_child(layers.size() - 1 - l) + for f in range(frames.size()): + layer_cel_container.get_child(f).layer = l + layer_cel_container.get_child(f).button_setup() _layers_changed(layers) # TODO Remove (needs buttons and index update) -func move_cel() -> void: - # not sure about this one - pass +func move_cel(from_frame: int, to_frame: int, layer: int) -> void: + # TODO: Current frame + # TODO: Current layer + var cel: BaseCel = frames[from_frame].cels[layer] + if from_frame < to_frame: + for f in range(from_frame + 1, to_frame + 1): + frames[f - 1].cels[layer] = frames[f].cels[layer] + else: + for f in range(to_frame, from_frame): + frames[f + 1].cels[layer] = frames[f].cels[layer] + frames[to_frame].cels[layer] = cel + Global.animation_timeline.project_cel_removed(from_frame, layer) + Global.animation_timeline.project_cel_added(to_frame, layer) + # Update the cel buttons for this layer: + var layer_cel_container = Global.frames_container.get_child(layers.size() - 1 - layer) + for f in range(frames.size()): + layer_cel_container.get_child(f).frame = f + layer_cel_container.get_child(f).button_setup() + + +func swap_cel(a_frame: int, a_layer: int, b_frame: int, b_layer: int) -> void: + # TODO: Current frame + # TODO: Current layer + var temp: BaseCel = frames[a_frame].cels[a_layer] + frames[a_frame].cels[a_layer] = frames[b_frame].cels[b_layer] + frames[b_frame].cels[b_layer] = temp + Global.animation_timeline.project_cel_removed(a_frame, a_layer) + Global.animation_timeline.project_cel_added(a_frame, a_layer) + Global.animation_timeline.project_cel_removed(b_frame, b_layer) + Global.animation_timeline.project_cel_added(b_frame, b_layer) diff --git a/src/UI/Canvas/Canvas.gd b/src/UI/Canvas/Canvas.gd index 80597e8c6fa3..792e592e2b51 100644 --- a/src/UI/Canvas/Canvas.gd +++ b/src/UI/Canvas/Canvas.gd @@ -132,12 +132,13 @@ func update_selected_cels_textures(project: Project = Global.current_project) -> var current_cel: PixelCel = project.frames[frame_index].cels[layer_index] current_cel.image_texture.set_data(current_cel.image) - if project == Global.current_project: - var container_index = Global.frames_container.get_child_count() - 1 - layer_index - var layer_cel_container = Global.frames_container.get_child(container_index) - var cel_button = layer_cel_container.get_child(frame_index) - var cel_texture_rect: TextureRect = cel_button.find_node("CelTexture") - cel_texture_rect.texture = current_cel.image_texture + # TODO: This wasn't working anymore, but is it even needed? (Same as above) +# if project == Global.current_project: +# var container_index = Global.frames_container.get_child_count() - 1 - layer_index +# var layer_cel_container = Global.frames_container.get_child(container_index) +# var cel_button = layer_cel_container.get_child(frame_index) +# var cel_texture_rect: TextureRect = cel_button.find_node("CelTexture") +# cel_texture_rect.texture = current_cel.image_texture func refresh_onion() -> void: diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 9c621cfede83..7440cb8d6682 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -12,6 +12,12 @@ var max_cel_size := 144 var past_above_canvas := true var future_above_canvas := true +var frame_button_node = preload("res://src/UI/Timeline/FrameButton.tscn") +var pixel_layer_button_node = preload("res://src/UI/Timeline/PixelLayerButton.tscn") +var group_layer_button_node = preload("res://src/UI/Timeline/GroupLayerButton.tscn") +var pixel_cel_button_node = preload("res://src/UI/Timeline/PixelCelButton.tscn") +var group_cel_button_node = preload("res://src/UI/Timeline/GroupCelButton.tscn") + onready var old_scroll: int = 0 # The previous scroll state of $ScrollContainer onready var tag_spacer = find_node("TagSpacer") onready var start_spacer = find_node("StartSpacer") @@ -134,15 +140,45 @@ func add_frame() -> void: var project: Project = Global.current_project var frame_add_index := project.current_frame + 1 var frame: Frame = project.new_empty_frame() + var new_layers: Array = project.duplicate_layers() + + for l_i in range(new_layers.size()): + if new_layers[l_i].new_cels_linked: # If the link button is pressed + new_layers[l_i].linked_cels.append(frame) + frame.cels[l_i].image = new_layers[l_i].linked_cels[0].cels[l_i].image + frame.cels[l_i].image_texture = new_layers[l_i].linked_cels[0].cels[l_i].image_texture + + # Code to PUSH AHEAD tags starting after the frame + var new_animation_tags := project.animation_tags.duplicate() + # Loop through the tags to create new classes for them, so that they won't be the same + # as Global.current_project.animation_tags's classes. Needed for undo/redo to work properly. + for i in new_animation_tags.size(): + new_animation_tags[i] = AnimationTag.new( + new_animation_tags[i].name, + new_animation_tags[i].color, + new_animation_tags[i].from, + new_animation_tags[i].to + ) + # Loop through the tags to see if the frame is in one + for tag in new_animation_tags: + if frame_add_index >= tag.from && frame_add_index <= tag.to: + tag.to += 1 + elif (frame_add_index) < tag.from: + tag.from += 1 + tag.to += 1 project.undos += 1 project.undo_redo.create_action("Add Frame") project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) - project.undo_redo.add_do_method(project, "add_frame", frame, frame_add_index) project.undo_redo.add_undo_method(project, "remove_frame", frame_add_index) - + project.undo_redo.add_do_property(project, "layers", new_layers) + project.undo_redo.add_undo_property(project, "layers", project.layers) + project.undo_redo.add_do_property(project, "animation_tags", new_animation_tags) + project.undo_redo.add_undo_property(project, "animation_tags", project.animation_tags) + project.undo_redo.add_do_property(project, "current_frame", project.current_frame + 1) + project.undo_redo.add_undo_property(project, "current_frame", project.current_frame) project.undo_redo.commit_action() @@ -164,6 +200,54 @@ func delete_frames(frames := []) -> void: if frames.size() == 0: frames.append(project.current_frame) + var new_frames: Array = project.frames.duplicate() + var current_frame := project.current_frame + var new_layers: Array = project.duplicate_layers() + var frame_correction := 0 # Only needed for tag adjustment + + var new_animation_tags := project.animation_tags.duplicate() + # Loop through the tags to create new classes for them, so that they won't be the same + # as Global.current_project.animation_tags's classes. Needed for undo/redo to work properly. + for i in new_animation_tags.size(): + new_animation_tags[i] = AnimationTag.new( + new_animation_tags[i].name, + new_animation_tags[i].color, + new_animation_tags[i].from, + new_animation_tags[i].to + ) + + for frame in frames: + if new_frames.size() == 1: # If only 1 frame + break + var frame_to_delete: Frame = project.frames[frame] + new_frames.erase(frame_to_delete) + if current_frame > 0 && current_frame == new_frames.size(): # If it's the last frame + current_frame -= 1 + + # Check if one of the cels of the frame is linked + # if they are, unlink them too + # this prevents removed cels being kept in linked memory + for layer in new_layers: + for linked in layer.linked_cels: + if linked == project.frames[frame]: + layer.linked_cels.erase(linked) + + # Loop through the tags to see if the frame is in one + frame -= frame_correction # Erasing made frames indexes 1 step ahead their intended tags + var tag_correction := 0 # needed when tag is erased + for tag_ind in new_animation_tags.size(): + var tag = new_animation_tags[tag_ind - tag_correction] + if frame + 1 >= tag.from && frame + 1 <= tag.to: + if tag.from == tag.to: # If we're deleting the only frame in the tag + new_animation_tags.erase(tag) + tag_correction += 1 + else: + tag.to -= 1 + elif frame + 1 < tag.from: + tag.from -= 1 + tag.to -= 1 + frame_correction += 1 # Compensation for the next batch + project.undos += 1 project.undo_redo.create_action("Remove Frame") @@ -176,9 +260,15 @@ func delete_frames(frames := []) -> void: project, "add_frame", project.frames[frames[i]], frames[i] ) - Global.current_project.undo_redo.add_do_method(Global, "undo_or_redo", false) - Global.current_project.undo_redo.add_undo_method(Global, "undo_or_redo", true) - Global.current_project.undo_redo.commit_action() + project.undo_redo.add_do_property(project, "layers", new_layers) + project.undo_redo.add_undo_property(project, "layers", Global.current_project.layers) + project.undo_redo.add_do_property(project, "animation_tags", new_animation_tags) + project.undo_redo.add_undo_property(project, "animation_tags", project.animation_tags) + project.undo_redo.add_do_property(project, "current_frame", current_frame) + project.undo_redo.add_undo_property(project, "current_frame", project.current_frame) + project.undo_redo.add_do_method(Global, "undo_or_redo", false) + project.undo_redo.add_undo_method(Global, "undo_or_redo", true) + project.undo_redo.commit_action() func _on_CopyFrame_pressed(frame := -1) -> void: @@ -190,7 +280,7 @@ func _on_CopyFrame_pressed(frame := -1) -> void: frames.sort() copy_frames(frames) - +# TODO: Refactor copy_frames as well: func copy_frames(frames := []) -> void: # TODO: Work on this one (probably need a copy_to function on Cel classes) Global.canvas.selection.transform_content_confirm() @@ -544,7 +634,8 @@ func add_layer(is_new := true) -> void: project.undo_redo.add_do_method(project, "add_layer", l, project.layers.size(), cels) project.undo_redo.add_undo_method(project, "remove_layer", project.layers.size()) - + project.undo_redo.add_do_property(project, "current_layer", project.layers.size()) + project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.commit_action() @@ -564,7 +655,8 @@ func add_group_layer(is_new := true) -> void: project.undo_redo.add_do_method(project, "add_layer", l, project.layers.size(), cels) project.undo_redo.add_undo_method(project, "remove_layer", project.layers.size()) - + project.undo_redo.add_do_property(project, "current_layer", project.layers.size()) + project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.commit_action() @@ -586,12 +678,13 @@ func _on_RemoveLayer_pressed() -> void: project.undo_redo.add_undo_method( project, "add_layer", project.layers[project.current_layer], project.current_layer, cels ) - + project.undo_redo.add_do_property(project, "current_layer", max(project.current_layer - 1, 0)) + project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.commit_action() - +# TODO: Refactor this (probably completely remove) func change_layer_order(rate: int) -> void: var change = Global.current_project.current_layer + rate @@ -713,3 +806,112 @@ func _on_OpacitySlider_value_changed(value) -> void: func _on_OnionSkinningSettings_popup_hide() -> void: Global.can_draw = true + + +func project_changed() -> void: + var project: Project = Global.current_project # TODO: maybe pass in instead? + # TODO: Remove all buttons + for child in Global.layers_container.get_children(): + child.queue_free() + for child in Global.frame_ids.get_children(): + child.queue_free() + for container in Global.frames_container.get_children(): + container.queue_free() + + for i in range(project.layers.size()): + project_layer_added(i) + for f in range(project.frames.size()): + var button: Button = frame_button_node.instance() + button.frame = f + button.rect_min_size.x = Global.animation_timeline.cel_size + button.text = str(f + 1) + Global.frame_ids.add_child(button) + Global.frame_ids.move_child(button, f) + + # TODO: May not be needed, depending on other changes to selection + var current_layer_button = Global.layers_container.get_child( + Global.layers_container.get_child_count() - 1 - project.current_layer + ) + current_layer_button.pressed = true + + +func project_frame_added(frame: int) -> void: + var project: Project = Global.current_project # TODO: maybe pass in instead? + var button: Button = frame_button_node.instance() + button.frame = frame + button.rect_min_size.x = Global.animation_timeline.cel_size + button.text = str(frame + 1) + Global.frame_ids.add_child(button) + Global.frame_ids.move_child(button, frame) + + var layer := 0 # TODO: This probably needs to be reveresed... + for container in Global.frames_container.get_children(): + var cel_button = project.frames[frame].cels[layer].create_cel_button() + cel_button.frame = frame + cel_button.layer = layer + container.add_child(cel_button) + container.move_child(cel_button, frame) + layer += 1 + + +func project_frame_removed(frame: int) -> void: + Global.frame_ids.get_child(frame).free() + for container in Global.frames_container.get_children(): + container.get_child(frame).free() + + +func project_layer_added(layer: int) -> void: + var project: Project = Global.current_project # TODO: maybe pass in instead? + # TODO: should probably have a "layer" variable... (to many project.layers[layer])... + # ...or refactor things so less of this code is needed here. + + var layer_button: LayerButton + if project.layers[layer] is PixelLayer: + layer_button = pixel_layer_button_node.instance() + elif project.layers[layer] is GroupLayer: + layer_button = group_layer_button_node.instance() + layer_button.layer = layer# - 1 # TODO: See if needed + if project.layers[layer].name == "": # TODO: This probably could be somewhere else... + project.layers[layer].name = project.layers[layer].get_default_name(layer) + + Global.layers_container.add_child(layer_button) + var count := Global.layers_container.get_child_count() + Global.layers_container.move_child(layer_button, count - 1 - layer) + + var layer_cel_container := HBoxContainer.new() + # TODO: Is there any need for a name (and why is it LAYERSSS in one place, and FRAMESS in another?) + layer_cel_container.name = "LAYERSSS " + str(layer) + Global.frames_container.add_child(layer_cel_container) + Global.frames_container.move_child(layer_cel_container, count - 1 - layer) + for f in range(project.frames.size()): + var cel_button = project.frames[f].cels[layer].create_cel_button() + cel_button.frame = f + cel_button.layer = layer# - 1 # TODO: See if needed + layer_cel_container.add_child(cel_button) + +# TODO: are names like "project_layer_removed" or "remove_layer_ui" better? +# maybe "layer_removed_in_project"? or something else? +func project_layer_removed(layer: int) -> void: + var count := Global.layers_container.get_child_count() + Global.layers_container.get_child(count - layer).free() + Global.frames_container.get_child(count - layer).free() + + +func project_cel_added(frame: int, layer: int) -> void: + var container := Global.frames_container.get_child( + Global.frames_container.get_child_count() - 1 - layer + ) + var cel_button = Global.current_project.frames[frame].cels[layer].create_cel_button() + cel_button.frame = frame + cel_button.layer = layer + # TODO: Do we need stuff like this for selection? +# cel_button.pressed = Global.current_project.selected_cels.has([frame, layer]) + container.add_child(cel_button) + container.move_child(cel_button, frame) + +# TODO: Not yet sure if this is really needed: +func project_cel_removed(frame: int, layer: int) -> void: + var container := Global.frames_container.get_child( + Global.frames_container.get_child_count() - 1 - layer + ) + container.get_child(frame).free() diff --git a/src/UI/Timeline/AnimationTimeline.tscn b/src/UI/Timeline/AnimationTimeline.tscn index 665795502bb2..64c9491865ef 100644 --- a/src/UI/Timeline/AnimationTimeline.tscn +++ b/src/UI/Timeline/AnimationTimeline.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=44 format=2] +[gd_scene load_steps=43 format=2] [ext_resource path="res://src/UI/Timeline/AnimationTimeline.gd" type="Script" id=1] [ext_resource path="res://assets/graphics/layers/new.png" type="Texture" id=2] @@ -8,7 +8,6 @@ [ext_resource path="res://assets/graphics/layers/delete.png" type="Texture" id=6] [ext_resource path="res://assets/graphics/layers/clone.png" type="Texture" id=7] [ext_resource path="res://assets/graphics/timeline/move_arrow.png" type="Texture" id=8] -[ext_resource path="res://src/UI/Timeline/FrameButton.tscn" type="PackedScene" id=9] [ext_resource path="res://assets/graphics/layers/group_new.png" type="Texture" id=10] [ext_resource path="res://assets/graphics/timeline/new_frame.png" type="Texture" id=19] [ext_resource path="res://assets/graphics/timeline/remove_frame.png" type="Texture" id=20] @@ -876,7 +875,7 @@ margin_bottom = 68.0 size_flags_horizontal = 3 [node name="LayersAndFrames" type="HBoxContainer" parent="ScrollContainer/TimelineContainer/PanelContainer/HBoxContainer/TimelineScroll"] -margin_right = 81.0 +margin_right = 45.0 margin_bottom = 68.0 size_flags_vertical = 3 @@ -899,22 +898,16 @@ margin_bottom = 20.0 [node name="FrameButtonsAndIds" type="VBoxContainer" parent="ScrollContainer/TimelineContainer/PanelContainer/HBoxContainer/TimelineScroll/LayersAndFrames"] margin_left = 45.0 -margin_right = 81.0 +margin_right = 45.0 margin_bottom = 68.0 [node name="FrameIDs" type="HBoxContainer" parent="ScrollContainer/TimelineContainer/PanelContainer/HBoxContainer/TimelineScroll/LayersAndFrames/FrameButtonsAndIds"] -margin_right = 36.0 -margin_bottom = 20.0 +margin_bottom = 16.0 rect_min_size = Vector2( 0, 16 ) -[node name="FrameButton" parent="ScrollContainer/TimelineContainer/PanelContainer/HBoxContainer/TimelineScroll/LayersAndFrames/FrameButtonsAndIds/FrameIDs" instance=ExtResource( 9 )] -margin_right = 36.0 -rect_min_size = Vector2( 36, 0 ) - [node name="FramesContainer" type="VBoxContainer" parent="ScrollContainer/TimelineContainer/PanelContainer/HBoxContainer/TimelineScroll/LayersAndFrames/FrameButtonsAndIds"] -margin_top = 24.0 -margin_right = 36.0 -margin_bottom = 24.0 +margin_top = 20.0 +margin_bottom = 20.0 [node name="EndSpacer" type="Control" parent="ScrollContainer/TimelineContainer/PanelContainer/HBoxContainer"] margin_left = 888.0 diff --git a/src/UI/Timeline/FrameButton.gd b/src/UI/Timeline/FrameButton.gd index bd86ce0d7454..179d96d78c83 100644 --- a/src/UI/Timeline/FrameButton.gd +++ b/src/UI/Timeline/FrameButton.gd @@ -126,40 +126,79 @@ func get_drag_data(_position) -> Array: func can_drop_data(_pos, data) -> bool: if typeof(data) == TYPE_ARRAY: - return data[0] == "Frame" - else: - return false + if data[0] == "Frame": + if data[1] != frame: # Can't move to same frame + var region: Rect2 + if Input.is_action_pressed("ctrl"): # Swap frames + region = get_global_rect() + else: # Move frames + if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): + region = _get_region_rect(-0.125, 0.125) + region.position.x -= 2 # Container spacing + else: + region = _get_region_rect(0.875, 1.125) + region.position.x += 2 # Container spacing + Global.animation_timeline.drag_highlight.rect_global_position = region.position + Global.animation_timeline.drag_highlight.rect_size = region.size + Global.animation_timeline.drag_highlight.visible = true + return true + Global.animation_timeline.drag_highlight.visible = false + return false func drop_data(_pos, data) -> void: - var new_frame = data[1] - if frame == new_frame: - return - - var new_frames: Array = Global.current_project.frames.duplicate() - var temp = new_frames[frame] - new_frames[frame] = new_frames[new_frame] - new_frames[new_frame] = temp - - Global.current_project.undo_redo.create_action("Change Frame Order") - Global.current_project.undo_redo.add_do_property(Global.current_project, "frames", new_frames) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "frames", Global.current_project.frames - ) + var drop_frame = data[1] + var project = Global.current_project + +# var drop_frames: Array = Global.current_project.frames.duplicate() +# var temp = drop_frames[frame] +# drop_frames[frame] = drop_frames[drop_frame] +# drop_frames[drop_frame] = temp + + project.undo_redo.create_action("Change Frame Order") +# Global.current_project.undo_redo.add_do_property(Global.current_project, "frames", drop_frames) +# Global.current_project.undo_redo.add_undo_property( +# Global.current_project, "frames", Global.current_project.frames +# ) +# +# if Global.current_project.current_frame == drop_frame: +# Global.current_project.undo_redo.add_do_property( +# Global.current_project, "current_frame", frame +# ) +# else: +# Global.current_project.undo_redo.add_do_property( +# Global.current_project, "current_frame", Global.current_project.current_frame +# ) +# +# Global.current_project.undo_redo.add_undo_property( +# Global.current_project, "current_frame", Global.current_project.current_frame +# ) + + if Input.is_action_pressed("ctrl"): # Swap frames + project.undo_redo.add_do_method(project, "swap_frame", frame, drop_frame) + project.undo_redo.add_undo_method(project, "swap_frame", frame, drop_frame) + else: # Move frames + var to_frame: int + # TODO: Test that this is correct: (after cel button ui changes) + if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): + to_frame = frame + else: + to_frame = frame + 1 + project.undo_redo.add_do_method(project, "move_frame", drop_frame, to_frame) + project.undo_redo.add_undo_method(project, "move_frame", to_frame, drop_frame) - if Global.current_project.current_frame == new_frame: - Global.current_project.undo_redo.add_do_property( - Global.current_project, "current_frame", frame - ) + if project.current_frame == drop_frame: + project.undo_redo.add_do_property(project, "current_frame", frame) else: - Global.current_project.undo_redo.add_do_property( - Global.current_project, "current_frame", Global.current_project.current_frame - ) - - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "current_frame", Global.current_project.current_frame - ) - - Global.current_project.undo_redo.add_undo_method(Global, "undo_or_redo", true) - Global.current_project.undo_redo.add_do_method(Global, "undo_or_redo", false) - Global.current_project.undo_redo.commit_action() + project.undo_redo.add_do_property(project, "current_frame", project.current_frame) + project.undo_redo.add_undo_property(project, "current_frame", project.current_frame) + project.undo_redo.add_undo_method(Global, "undo_or_redo", true) + project.undo_redo.add_do_method(Global, "undo_or_redo", false) + project.undo_redo.commit_action() + + +func _get_region_rect(x_begin: float, x_end: float) -> Rect2: + var rect := get_global_rect() + rect.position.x += rect.size.x * x_begin + rect.size.x *= x_end - x_begin + return rect diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index 6c5804375f0d..6238224f32f4 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -18,6 +18,9 @@ export var hide_expand_button := true func _ready() -> void: rect_min_size.y = Global.animation_timeline.cel_size + label.text = Global.current_project.layers[layer].name + line_edit.text = Global.current_project.layers[layer].name + var layer_buttons = find_node("LayerButtons") for child in layer_buttons.get_children(): var texture = child.get_child(0) @@ -227,35 +230,33 @@ func can_drop_data(_pos, data) -> bool: func drop_data(_pos, data) -> void: - var dropped_layer: int = data[1] + var drop_layer: int = data[1] + var project = Global.current_project # TODO: perhaps having a project variable for the enitre class would be nice (also for cel/frame buttons) - Global.current_project.undo_redo.create_action("Change Layer Order") - var new_layers: Array = Global.current_project.layers.duplicate() + project.undo_redo.create_action("Change Layer Order") + var new_layers: Array = project.layers.duplicate() var temp: BaseLayer = new_layers[layer] if Input.is_action_pressed("ctrl"): # Swap layers # TODO Need to check when swapping is allowed pass # TODO: Figure out swapping -# new_layers[layer] = new_layers[dropped_layer] -# new_layers[dropped_layer] = temp +# new_layers[layer] = new_layers[drop_layer] +# new_layers[drop_layer] = temp # # # TODO: Make sure to swap parents too # # for f in Global.current_project.frames: # var new_cels: Array = f.cels.duplicate() # var temp_canvas = new_cels[layer] -# new_cels[layer] = new_cels[dropped_layer] -# new_cels[dropped_layer] = temp_canvas -# Global.current_project.undo_redo.add_do_property(f, "cels", new_cels) -# Global.current_project.undo_redo.add_undo_property(f, "cels", f.cels) +# new_cels[layer] = new_cels[drop_layer] +# new_cels[drop_layer] = temp_canvas +# project.undo_redo.add_do_property(f, "cels", new_cels) +# project.undo_redo.add_undo_property(f, "cels", f.cels) # TODO: Having "SourceLayers/OldLayers (that you don't change) and new_layers would make this less confusing else: - # layers_to_shift should be in order of the layer indices, starting from the lowest -# var layers_to_shift: Array = new_layers[dropped_layer].get_children_recursive() -# layers_to_shift.append(new_layers[dropped_layer]) - + # from_indices should be in order of the layer indices, starting from the lowest var from_indices := [] - for c in new_layers[dropped_layer].get_children_recursive(): + for c in new_layers[drop_layer].get_children_recursive(): from_indices.append(c.index) - from_indices.append(dropped_layer) + from_indices.append(drop_layer) var to_index: int # the index where the LOWEST shifted layer should end up var to_parent: BaseLayer @@ -276,13 +277,13 @@ func drop_data(_pos, data) -> void: if new_layers[layer].has_children(): to_index = new_layers[layer].get_children_recursive()[0].index - if new_layers[layer].is_a_parent_of(new_layers[dropped_layer]): + if new_layers[layer].is_a_parent_of(new_layers[drop_layer]): to_index += from_indices.size() else: to_index = layer # TODO Is this right? to_parent = new_layers[layer].parent - if dropped_layer < layer: + if drop_layer < layer: to_index -= from_indices.size() print("to_index = ", to_index) @@ -294,17 +295,19 @@ func drop_data(_pos, data) -> void: var to_parents := from_parents.duplicate() to_parents[-1] = to_parent - Global.current_project.undo_redo.add_do_method( - Global.current_project, "move_layers", from_indices, to_indices, to_parents + project.undo_redo.add_do_method( + project, "move_layers", from_indices, to_indices, to_parents ) - Global.current_project.undo_redo.add_undo_method( - Global.current_project, "move_layers", to_indices, from_indices, from_parents + project.undo_redo.add_undo_method( + project, "move_layers", to_indices, from_indices, from_parents ) - + if project.current_layer == layer: + project.undo_redo.add_do_property(project, "current_layer", drop_layer) + project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) # TODO: undo_or_redo is at end here, but earlier in others, does it matter which order? - Global.current_project.undo_redo.add_undo_method(Global, "undo_or_redo", true) - Global.current_project.undo_redo.add_do_method(Global, "undo_or_redo", false) - Global.current_project.undo_redo.commit_action() + project.undo_redo.add_undo_method(Global, "undo_or_redo", true) + project.undo_redo.add_do_method(Global, "undo_or_redo", false) + project.undo_redo.commit_action() func _get_region_rect(y_begin: float, y_end: float) -> Rect2: diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index a3795a12d7f0..6edd1c6d4fe5 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -103,6 +103,7 @@ func _on_PopupMenu_id_pressed(id: int) -> void: _delete_cel_content() MenuOptions.LINK: + # TODO: See if there is any refactoring to do here: var f: Frame = Global.current_project.frames[frame] var cel_index: int = Global.current_project.layers[layer].linked_cels.find(f) var new_layers: Array = Global.current_project.duplicate_layers() @@ -194,71 +195,111 @@ func get_drag_data(_position) -> Array: func can_drop_data(_pos, data) -> bool: if typeof(data) == TYPE_ARRAY and data[0] == "PixelCel": - var new_frame = data[1] - var new_layer = data[2] - if ( + var drag_frame = data[1] + var drag_layer = data[2] + # TODO: Is this part really right? Should't it only matter if they're linked, and we're changing layers? + # It would need to add linked cel logic to project move/swap_cel though + # If the cel we're dragging or the cel we are targeting are linked, don't allow dragging + if not ( Global.current_project.frames[frame] in Global.current_project.layers[layer].linked_cels or ( - Global.current_project.frames[new_frame] - in Global.current_project.layers[new_layer].linked_cels + Global.current_project.frames[drag_frame] + in Global.current_project.layers[drag_layer].linked_cels ) ): - # If the cel we're dragging or the cel we are targeting are linked, don't allow dragging - return false - else: - return true - else: - return false + # TODO: This may be able to be combined with the previous condition depending on the the last TODO + if not (drag_frame == frame and drag_layer == layer): + var region: Rect2 + if Input.is_action_pressed("ctrl") or layer != drag_layer: # Swap cels + region = get_global_rect() + else: # Move cels + if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): + region = _get_region_rect(-0.125, 0.125) + region.position.x -= 2 # Container spacing + else: + region = _get_region_rect(0.875, 1.125) + region.position.x += 2 # Container spacing + Global.animation_timeline.drag_highlight.rect_global_position = region.position + Global.animation_timeline.drag_highlight.rect_size = region.size + Global.animation_timeline.drag_highlight.visible = true + return true + + Global.animation_timeline.drag_highlight.visible = false + return false func drop_data(_pos, data) -> void: - var new_frame = data[1] - var new_layer = data[2] - if new_frame == frame and new_layer == layer: - return + var drop_frame = data[1] + var drop_layer = data[2] + var project = Global.current_project - var this_frame_new_cels = Global.current_project.frames[frame].cels.duplicate() - var new_frame_new_cels - var temp = this_frame_new_cels[layer] - this_frame_new_cels[layer] = Global.current_project.frames[new_frame].cels[new_layer] - if frame == new_frame: - this_frame_new_cels[new_layer] = temp - else: - new_frame_new_cels = Global.current_project.frames[new_frame].cels.duplicate() - new_frame_new_cels[new_layer] = temp - - Global.current_project.undo_redo.create_action("Move Cels") - Global.current_project.undo_redo.add_do_property( - Global.current_project.frames[frame], "cels", this_frame_new_cels - ) - - Global.current_project.undo_redo.add_do_property(Global.current_project, "current_layer", layer) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "current_layer", Global.current_project.current_layer - ) - - if frame != new_frame: # If the cel moved to a different frame - Global.current_project.undo_redo.add_do_property( - Global.current_project.frames[new_frame], "cels", new_frame_new_cels - ) - - Global.current_project.undo_redo.add_do_property( - Global.current_project, "current_frame", frame - ) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "current_frame", Global.current_project.current_frame - ) - - Global.current_project.undo_redo.add_undo_property( - Global.current_project.frames[new_frame], - "cels", - Global.current_project.frames[new_frame].cels - ) - - Global.current_project.undo_redo.add_undo_property( - Global.current_project.frames[frame], "cels", Global.current_project.frames[frame].cels - ) - - Global.current_project.undo_redo.add_undo_method(Global, "undo_or_redo", true) - Global.current_project.undo_redo.add_do_method(Global, "undo_or_redo", false) - Global.current_project.undo_redo.commit_action() +# var this_frame_new_cels = project.frames[frame].cels.duplicate() +# var drop_frame_new_cels +# var temp = this_frame_new_cels[layer] +# this_frame_new_cels[layer] = project.frames[drop_frame].cels[drop_layer] +# if frame == drop_frame: +# this_frame_new_cels[drop_layer] = temp +# else: +# drop_frame_new_cels = project.frames[drop_frame].cels.duplicate() +# drop_frame_new_cels[drop_layer] = temp + + project.undo_redo.create_action("Move Cels") +# project.undo_redo.add_do_property( +# project.frames[frame], "cels", this_frame_new_cels +# ) +# +# project.undo_redo.add_do_property(project, "current_layer", layer) +# project.undo_redo.add_undo_property( +# project, "current_layer", project.current_layer +# ) +# +# if frame != drop_frame: # If the cel moved to a different frame +# project.undo_redo.add_do_property( +# project.frames[drop_frame], "cels", drop_frame_new_cels +# ) +# +# project.undo_redo.add_do_property( +# project, "current_frame", frame +# ) +# project.undo_redo.add_undo_property( +# project, "current_frame", project.current_frame +# ) +# +# project.undo_redo.add_undo_property( +# project.frames[drop_frame], +# "cels", +# project.frames[drop_frame].cels +# ) +# +# project.undo_redo.add_undo_property( +# project.frames[frame], "cels", project.frames[frame].cels +# ) + + if Input.is_action_pressed("ctrl") or layer != drop_layer: # Swap cels + project.undo_redo.add_do_method(project, "swap_cel", frame, layer, drop_frame, drop_layer) + project.undo_redo.add_undo_method(project, "swap_cel", frame, layer, drop_frame, drop_layer) + else: # Move cels + var to_frame: int + # TODO: Test that this is correct: (after cel button ui changes) + if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): + to_frame = frame + else: + to_frame = frame + 1 + project.undo_redo.add_do_method(project, "move_cel", drop_frame, to_frame, layer) + project.undo_redo.add_undo_method(project, "move_cel", to_frame, drop_frame, layer) + + project.undo_redo.add_do_property(project, "current_layer", layer) + project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) + if frame != drop_frame: # If the cel moved to a different frame + project.undo_redo.add_do_property(project, "current_frame", frame) + project.undo_redo.add_undo_property(project, "current_frame", project.current_frame) + project.undo_redo.add_undo_method(Global, "undo_or_redo", true) + project.undo_redo.add_do_method(Global, "undo_or_redo", false) + project.undo_redo.commit_action() + + +func _get_region_rect(x_begin: float, x_end: float) -> Rect2: + var rect := get_global_rect() + rect.position.x += rect.size.x * x_begin + rect.size.x *= x_end - x_begin + return rect From 57b51f83d82a634e1ef8e18755c26203e11a746f Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 22 Jun 2022 16:58:42 -0400 Subject: [PATCH 027/154] Fixed moving cels --- src/Classes/Project.gd | 31 ++++++++++++++++++++++++++----- src/Main.gd | 5 +++-- src/UI/Timeline/FrameButton.gd | 6 ++++-- src/UI/Timeline/PixelCelButton.gd | 12 ++++++++---- 4 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index b74b16767bcc..99ace6b13f50 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -1082,20 +1082,41 @@ func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> v func move_cel(from_frame: int, to_frame: int, layer: int) -> void: # TODO: Current frame # TODO: Current layer + + # TODO: Remove this debugging chunk: + var OG_CELS = [] + for F in frames: + OG_CELS.append(F.cels[layer]) + var cel: BaseCel = frames[from_frame].cels[layer] - if from_frame < to_frame: - for f in range(from_frame + 1, to_frame + 1): - frames[f - 1].cels[layer] = frames[f].cels[layer] + if to_frame < from_frame: + # TODO: These cels were not always correct... verify they are: + # TODO: After testing for correctness, can you reduce the amoutn of +/- 1s? + for f in range(from_frame - 1, to_frame - 1, -1): # Backward range + frames[f + 1].cels[layer] = frames[f].cels[layer] # Move right else: - for f in range(to_frame, from_frame): - frames[f + 1].cels[layer] = frames[f].cels[layer] + for f in range(from_frame + 1, to_frame + 1): # Forward range + frames[f - 1].cels[layer] = frames[f].cels[layer] # Move left frames[to_frame].cels[layer] = cel Global.animation_timeline.project_cel_removed(from_frame, layer) Global.animation_timeline.project_cel_added(to_frame, layer) + + # TODO: Remove this debugging chunk: + var TEMP_CEL_INDICES = [] + for F in frames: + TEMP_CEL_INDICES.append(OG_CELS.find(F.cels[layer])) + assert(TEMP_CEL_INDICES.count(TEMP_CEL_INDICES[-1]) == 1) + print("From: ", from_frame, " To: ", to_frame) + print("CELS: ", TEMP_CEL_INDICES) + # Update the cel buttons for this layer: var layer_cel_container = Global.frames_container.get_child(layers.size() - 1 - layer) for f in range(frames.size()): layer_cel_container.get_child(f).frame = f + + # TODO: Remove this after the fix is verified (and remove all spacing): + layer_cel_container.get_child(f).cel = frames[f].cels[layer] + layer_cel_container.get_child(f).button_setup() diff --git a/src/Main.gd b/src/Main.gd index 87d825015f6f..2d545c4bbd75 100644 --- a/src/Main.gd +++ b/src/Main.gd @@ -22,9 +22,10 @@ func _ready() -> void: Global.window_title = tr("untitled") + " - Pixelorama " + Global.current_version - Global.current_project.layers.append(PixelLayer.new()) + Global.current_project.add_layer(PixelLayer.new(), 0, []) var frame: Frame = Global.current_project.new_empty_frame() - Global.current_project.frames.append(frame) + Global.current_project.add_frame(frame, 0) + # TODO: I Think this line should be safe to remove: (calling setter) Global.current_project.layers = Global.current_project.layers Import.import_brushes(Global.directory_module.get_brushes_search_path_in_order()) diff --git a/src/UI/Timeline/FrameButton.gd b/src/UI/Timeline/FrameButton.gd index 179d96d78c83..39c081e278e4 100644 --- a/src/UI/Timeline/FrameButton.gd +++ b/src/UI/Timeline/FrameButton.gd @@ -180,10 +180,12 @@ func drop_data(_pos, data) -> void: else: # Move frames var to_frame: int # TODO: Test that this is correct: (after cel button ui changes) - if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): + if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): # Left to_frame = frame - else: + else: # Right to_frame = frame + 1 + if drop_frame < frame: + to_frame -= 1 project.undo_redo.add_do_method(project, "move_frame", drop_frame, to_frame) project.undo_redo.add_undo_method(project, "move_frame", to_frame, drop_frame) diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index 6edd1c6d4fe5..178c45c70e0f 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -213,10 +213,10 @@ func can_drop_data(_pos, data) -> bool: if Input.is_action_pressed("ctrl") or layer != drag_layer: # Swap cels region = get_global_rect() else: # Move cels - if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): + if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): # Left region = _get_region_rect(-0.125, 0.125) region.position.x -= 2 # Container spacing - else: + else: # Right region = _get_region_rect(0.875, 1.125) region.position.x += 2 # Container spacing Global.animation_timeline.drag_highlight.rect_global_position = region.position @@ -281,10 +281,14 @@ func drop_data(_pos, data) -> void: else: # Move cels var to_frame: int # TODO: Test that this is correct: (after cel button ui changes) - if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): + # TODO: This breaks sometimes (after several tests usually), I'm not sure what the condition it breaks in is, maybe need to draw it out? + # (This is probably an error in the project.move_cel function) + if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): # Left to_frame = frame - else: + else: # Right to_frame = frame + 1 + if drop_frame < frame: + to_frame -= 1 project.undo_redo.add_do_method(project, "move_cel", drop_frame, to_frame, layer) project.undo_redo.add_undo_method(project, "move_cel", to_frame, drop_frame, layer) From bb9e6976cc31c9f47bbaed6da5d77e3165bec969 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 22 Jun 2022 17:10:46 -0400 Subject: [PATCH 028/154] Cleaned up Project.move_cel function --- src/Classes/Project.gd | 26 +++++--------------------- src/UI/Timeline/PixelCelButton.gd | 3 --- 2 files changed, 5 insertions(+), 24 deletions(-) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 99ace6b13f50..503a80db7426 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -1082,33 +1082,17 @@ func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> v func move_cel(from_frame: int, to_frame: int, layer: int) -> void: # TODO: Current frame # TODO: Current layer - - # TODO: Remove this debugging chunk: - var OG_CELS = [] - for F in frames: - OG_CELS.append(F.cels[layer]) - var cel: BaseCel = frames[from_frame].cels[layer] - if to_frame < from_frame: - # TODO: These cels were not always correct... verify they are: - # TODO: After testing for correctness, can you reduce the amoutn of +/- 1s? - for f in range(from_frame - 1, to_frame - 1, -1): # Backward range - frames[f + 1].cels[layer] = frames[f].cels[layer] # Move right + if from_frame < to_frame: + for f in range(from_frame, to_frame): # Forward range + frames[f].cels[layer] = frames[f + 1].cels[layer] # Move left else: - for f in range(from_frame + 1, to_frame + 1): # Forward range - frames[f - 1].cels[layer] = frames[f].cels[layer] # Move left + for f in range(from_frame, to_frame, -1): # Backward range + frames[f].cels[layer] = frames[f - 1].cels[layer] # Move right frames[to_frame].cels[layer] = cel Global.animation_timeline.project_cel_removed(from_frame, layer) Global.animation_timeline.project_cel_added(to_frame, layer) - # TODO: Remove this debugging chunk: - var TEMP_CEL_INDICES = [] - for F in frames: - TEMP_CEL_INDICES.append(OG_CELS.find(F.cels[layer])) - assert(TEMP_CEL_INDICES.count(TEMP_CEL_INDICES[-1]) == 1) - print("From: ", from_frame, " To: ", to_frame) - print("CELS: ", TEMP_CEL_INDICES) - # Update the cel buttons for this layer: var layer_cel_container = Global.frames_container.get_child(layers.size() - 1 - layer) for f in range(frames.size()): diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index 178c45c70e0f..05e768af5c4e 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -280,9 +280,6 @@ func drop_data(_pos, data) -> void: project.undo_redo.add_undo_method(project, "swap_cel", frame, layer, drop_frame, drop_layer) else: # Move cels var to_frame: int - # TODO: Test that this is correct: (after cel button ui changes) - # TODO: This breaks sometimes (after several tests usually), I'm not sure what the condition it breaks in is, maybe need to draw it out? - # (This is probably an error in the project.move_cel function) if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): # Left to_frame = frame else: # Right From 380e709b3623d34f02c175e1b01a1229468c05b8 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 23 Jun 2022 22:14:00 -0400 Subject: [PATCH 029/154] Fixed project_layer_removed --- src/UI/Timeline/AnimationTimeline.gd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 7440cb8d6682..548a9692ece4 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -893,8 +893,8 @@ func project_layer_added(layer: int) -> void: # maybe "layer_removed_in_project"? or something else? func project_layer_removed(layer: int) -> void: var count := Global.layers_container.get_child_count() - Global.layers_container.get_child(count - layer).free() - Global.frames_container.get_child(count - layer).free() + Global.layers_container.get_child(count - 1 - layer).free() + Global.frames_container.get_child(count - 1 - layer).free() func project_cel_added(frame: int, layer: int) -> void: From bb40950d4cae87fc98b916c859bf3ea8bbca28f2 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 24 Jun 2022 12:26:25 -0400 Subject: [PATCH 030/154] Updated change_frame_order on FrameButton. Some (not all) work on getting the layer UI updated when pressing buttons such as collapse/visible/lock --- src/UI/Timeline/AnimationTimeline.gd | 8 ++++- src/UI/Timeline/FrameButton.gd | 48 +++++++++++++--------------- src/UI/Timeline/LayerButton.gd | 11 ++++--- 3 files changed, 37 insertions(+), 30 deletions(-) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 548a9692ece4..75286b061a48 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -855,7 +855,8 @@ func project_frame_added(frame: int) -> void: func project_frame_removed(frame: int) -> void: - Global.frame_ids.get_child(frame).free() + Global.frame_ids.get_child(frame).queue_free() + Global.frame_ids.remove_child(Global.frame_ids.get_child(frame)) for container in Global.frames_container.get_children(): container.get_child(frame).free() @@ -915,3 +916,8 @@ func project_cel_removed(frame: int, layer: int) -> void: Global.frames_container.get_child_count() - 1 - layer ) container.get_child(frame).free() + +# TODO: Consider if this is better kept here, inline in LayerButton, or as a method in LayerButton +func update_layer_buttons() -> void: + for c in Global.layers_container.get_children(): + c._ready() # TODO: Should there be a specific place for this? diff --git a/src/UI/Timeline/FrameButton.gd b/src/UI/Timeline/FrameButton.gd index 39c081e278e4..394c8f96d009 100644 --- a/src/UI/Timeline/FrameButton.gd +++ b/src/UI/Timeline/FrameButton.gd @@ -82,36 +82,34 @@ func _on_PopupMenu_id_pressed(id: int) -> void: frame_properties.set_frame_label(frame) frame_properties.set_frame_dur(Global.current_project.frames[frame].duration) - +# TODO: Remove this later... (or simplify?) func change_frame_order(rate: int) -> void: var change = frame + rate - var new_frames: Array = Global.current_project.frames.duplicate() - var temp = new_frames[frame] - new_frames[frame] = new_frames[change] - new_frames[change] = temp - - Global.current_project.undo_redo.create_action("Change Frame Order") - Global.current_project.undo_redo.add_do_property(Global.current_project, "frames", new_frames) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "frames", Global.current_project.frames - ) - - if Global.current_project.current_frame == frame: - Global.current_project.undo_redo.add_do_property( - Global.current_project, "current_frame", change - ) + var project = Global.current_project +# var new_frames: Array = Global.current_project.frames.duplicate() +# var temp = new_frames[frame] +# new_frames[frame] = new_frames[change] +# new_frames[change] = temp + + project.undo_redo.create_action("Change Frame Order") +# project.undo_redo.add_do_property(project, "frames", new_frames) +# project.undo_redo.add_undo_property( +# project, "frames", project.frames +# ) + + project.undo_redo.add_do_method(project, "move_frame", frame, change) + project.undo_redo.add_undo_method(project, "move_frame", change, frame) + + if project.current_frame == frame: + project.undo_redo.add_do_property(project, "current_frame", change) else: - Global.current_project.undo_redo.add_do_property( - Global.current_project, "current_frame", Global.current_project.current_frame - ) + project.undo_redo.add_do_property(project, "current_frame", project.current_frame) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "current_frame", Global.current_project.current_frame - ) + project.undo_redo.add_undo_property(project, "current_frame", project.current_frame) - Global.current_project.undo_redo.add_undo_method(Global, "undo_or_redo", true) - Global.current_project.undo_redo.add_do_method(Global, "undo_or_redo", false) - Global.current_project.undo_redo.commit_action() + project.undo_redo.add_undo_method(Global, "undo_or_redo", true) + project.undo_redo.add_do_method(Global, "undo_or_redo", false) + project.undo_redo.commit_action() func get_drag_data(_position) -> Array: diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index 6238224f32f4..91316ed238b0 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -56,13 +56,12 @@ func _ready() -> void: hierarchy_spacer.rect_min_size.x = hierarchy_depth * HIERARCHY_DEPTH_PIXEL_SHIFT if Global.control.theme.get_color("font_color", "Button").v > 0.5: # Light text is dark theme - self_modulate.v += hierarchy_depth * 0.4 + self_modulate.v = 1 + hierarchy_depth * 0.4 else: # Dark text should be light theme - self_modulate.v -= hierarchy_depth * 0.075 + self_modulate.v = 1 - hierarchy_depth * 0.075 if is_instance_valid(Global.current_project.layers[layer].parent): - if not Global.current_project.layers[layer].parent.is_expanded_in_hierarchy(): - visible = false + visible = Global.current_project.layers[layer].parent.is_expanded_in_hierarchy() if not Global.current_project.layers[layer].parent.is_visible_in_hierarchy(): visibility_button.modulate.a = 0.33 if Global.current_project.layers[layer].parent.is_locked_in_hierarchy(): @@ -133,6 +132,7 @@ func _save_layer_name(new_name: String) -> void: func _on_ExpandButton_pressed(): Global.current_project.layers[layer].expanded = !Global.current_project.layers[layer].expanded + Global.animation_timeline.update_layer_buttons() func _on_VisibilityButton_pressed() -> void: @@ -140,12 +140,14 @@ func _on_VisibilityButton_pressed() -> void: Global.current_project.layers[layer].visible = !Global.current_project.layers[layer].visible Global.canvas.update() _select_current_layer() + Global.animation_timeline.update_layer_buttons() func _on_LockButton_pressed() -> void: Global.canvas.selection.transform_content_confirm() Global.current_project.layers[layer].locked = !Global.current_project.layers[layer].locked _select_current_layer() + Global.animation_timeline.update_layer_buttons() func _on_LinkButton_pressed() -> void: @@ -161,6 +163,7 @@ func _on_LinkButton_pressed() -> void: container.get_child(Global.current_project.current_frame).button_setup() Global.current_project.layers = Global.current_project.layers # Call the setter + Global.animation_timeline.update_layer_buttons() # TODO: this one doesn't need to update all (and others only a specific range) func _select_current_layer() -> void: From 1b9c8468ebd6c97808f64dcf5cadffd02eb20d4e Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Tue, 28 Jun 2022 14:29:27 -0400 Subject: [PATCH 031/154] Bug fixes. Updating layer button's buttons --- src/Autoload/OpenSave.gd | 10 +-- src/Classes/BaseLayer.gd | 6 ++ src/Classes/GroupLayer.gd | 7 -- src/Classes/Project.gd | 102 +++++++++++++++++---------- src/UI/Timeline/AnimationTimeline.gd | 24 ++++--- src/UI/Timeline/LayerButton.gd | 47 ++++++++---- src/UI/Timeline/PixelCelButton.gd | 2 +- 7 files changed, 123 insertions(+), 75 deletions(-) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index 37008e56485f..b611d356e884 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -122,14 +122,16 @@ func open_pxo_file(path: String, untitled_backup: bool = false, replace_empty: b Brushes.add_project_brush(image) file.close() - if !empty_project: - Global.projects.append(new_project) - Global.tabs.current_tab = Global.tabs.get_tab_count() - 1 - else: + if empty_project: if dict.error == OK and dict.result.has("fps"): Global.animation_timeline.fps_spinbox.value = dict.result.fps + Global.animation_timeline.project_changed() + # TODO: Do these need to be here? new_project.frames = new_project.frames # Just to call frames_changed new_project.layers = new_project.layers # Just to call layers_changed + else: + Global.projects.append(new_project) + Global.tabs.current_tab = Global.tabs.get_tab_count() - 1 Global.canvas.camera_zoom() if not untitled_backup: diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index db8679d52341..74d48c6e7a8f 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -40,6 +40,12 @@ func has_children() -> bool: return false return project.layers[index - 1].parent == self + +func is_expanded_in_hierarchy() -> bool: + if is_instance_valid(parent): + return parent.expanded and parent.is_expanded_in_hierarchy() + return true + # TODO: Search for layer visbility/locked checks that should be changed to the hierarchy ones: func is_visible_in_hierarchy() -> bool: if is_instance_valid(parent) and visible: diff --git a/src/Classes/GroupLayer.gd b/src/Classes/GroupLayer.gd index da9db17cf4e1..6a1ef2f23dee 100644 --- a/src/Classes/GroupLayer.gd +++ b/src/Classes/GroupLayer.gd @@ -7,13 +7,6 @@ var expanded := true func _init(_name := "") -> void: name = _name - -func is_expanded_in_hierarchy() -> bool: - if is_instance_valid(parent) and expanded: - return parent.is_expanded_in_hierarchy() - return expanded - - # Overridden Functions: func serialize() -> Dictionary: diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 503a80db7426..94274c4688cf 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -462,7 +462,7 @@ func _size_changed(value: Vector2) -> void: func _frames_changed(value: Array) -> void: Global.canvas.selection.transform_content_confirm() frames = value - selected_cels.clear() +# selected_cels.clear() # TODO: This is commented out to prevent selected_cels being blank at begginning (Will it still be needed? Will removing the setter calls in the new functions fix it?) # _remove_cel_buttons() # # for frame_id in Global.frame_ids.get_children(): @@ -503,7 +503,7 @@ func _layers_changed(value: Array) -> void: Global.layers_changed_skip = false return - selected_cels.clear() +# selected_cels.clear() # TODO: This is commented out to prevent selected_cels being blank at begginning (Will it still be needed? Will removing the setter calls in the new functions fix it?) # for container in Global.layers_container.get_children(): # container.queue_free() @@ -690,7 +690,7 @@ func _animation_tags_changed(value: Array) -> void: _set_timeline_first_and_last_frames() - +# TODO: Is this really required in _frames_changed (or the add/remove frame funcs, seems to work fine without when playing anim) func _set_timeline_first_and_last_frames() -> void: # This is useful in case tags get modified DURING the animation is playing # otherwise, this code is useless in this context, since these values are being set @@ -918,22 +918,12 @@ func resize_bitmap_values(bitmap: BitMap, new_size: Vector2, flip_x: bool, flip_ func add_frame(frame: Frame, index: int) -> void: + Global.canvas.selection.transform_content_confirm() + selected_cels.clear() # TODO: May need to call _frames_changed setter here (at least for some of it) frames.insert(index, frame) - # TODO: Test link/unlink cels thoroughly, I'm not sure if they're - # easily reversable (probably possible though, tags may need an "undo" bool, links - # may work with a passed array, or maybe its better if they're just not handled here - -# # Link cels: -# for l_i in range(layers.size()): -# if layers[l_i].new_cels_linked: # If the link button is pressed -# layers[l_i].linked_cels.append(frame) -# frame.cels[l_i].image = layers[l_i].linked_cels[0].cels[l_i].image -# frame.cels[l_i].image_texture = layers[l_i].linked_cels[0].cels[l_i].image_texture -# - # TODO: Check if these (especially remove/move) mess up selection? - _frames_changed(frames)# TODO: Remove +# _frames_changed(frames)# TODO: Remove # TODO: These may need an if self == Global.current_project depending on use Global.animation_timeline.project_frame_added(index) # Update the frames and frame buttons: @@ -946,19 +936,19 @@ func add_frame(frame: Frame, index: int) -> void: for f in range(frames.size()): layer_cel_container.get_child(f).frame = f layer_cel_container.get_child(f).button_setup() +# _update_animation_timeline_selection() +# # TODO: Remove after testing: +# print(selected_cels) +# print(current_frame) func remove_frame(index: int) -> void: + Global.canvas.selection.transform_content_confirm() + selected_cels.clear() # TODO: If this messes up selection, would doing multiple here help? + # TODO: Could one half of cel linking and animation tags be included in the add or remove_frame functions? (ie: removing works, but adding doesn't?) frames.remove(index) - -# # Unlink cels: -# for layer in layers: -# for linked in layer.linked_cels: -# if linked == frames[index]: -# layer.linked_cels.erase(linked) - - _frames_changed(frames)# TODO: Remove +# _frames_changed(frames)# TODO: Remove Global.animation_timeline.project_frame_removed(index) # Update the frames and frame buttons: for f in range(frames.size()): @@ -973,14 +963,16 @@ func remove_frame(index: int) -> void: func move_frame(from_index: int, to_index: int) -> void: + # TODO: move_cel transform_content_confirm bug likely applies here too... + Global.canvas.selection.transform_content_confirm() + selected_cels.clear() var frame = frames[from_index] frames.remove(from_index) Global.animation_timeline.project_frame_removed(from_index) # TODO: Ensure the final position is always right frames.insert(to_index, frame) - # TODO: Set current frame Global.animation_timeline.project_frame_added(to_index) - _frames_changed(frames)# TODO: Remove +# _frames_changed(frames)# TODO: Remove # Update the frames and frame buttons: for f in range(frames.size()): Global.frame_ids.get_child(f).frame = f @@ -994,7 +986,7 @@ func move_frame(from_index: int, to_index: int) -> void: func swap_frame(a_index: int, b_index: int) -> void: - # TODO: current frame + Global.canvas.selection.transform_content_confirm() var temp: Frame = frames[a_index] frames[a_index] = frames[b_index] frames[b_index] = temp @@ -1012,7 +1004,7 @@ func add_layer(layer: BaseLayer, index: int, cels: Array) -> void: layer.project = self # TODO: Update layer index (and others, more efficient if add layer supports multiple) # TODO: Update layer button indices - _layers_changed(layers)# TODO: Remove +# _layers_changed(layers)# TODO: Remove Global.animation_timeline.project_layer_added(index) # Update the layer indices and layer/cel buttons: for l in range(layers.size()): @@ -1022,6 +1014,8 @@ func add_layer(layer: BaseLayer, index: int, cels: Array) -> void: for f in range(frames.size()): layer_cel_container.get_child(f).layer = l layer_cel_container.get_child(f).button_setup() + _toggle_layer_buttons_layers() +# _update_animation_timeline_selection() func remove_layer(index: int) -> void: @@ -1030,8 +1024,8 @@ func remove_layer(index: int) -> void: for frame in frames: frame.cels.remove(index) # TODO: Update layer index (and others, more efficient if remove layer supports multiple) - # TODO: Update layer button indices - _layers_changed(layers)# TODO: Remove +# # TODO: Update layer button indices +# _layers_changed(layers)# TODO: Remove Global.animation_timeline.project_layer_removed(index) # Update the layer indices and layer/cel buttons: for l in range(layers.size()): @@ -1041,6 +1035,8 @@ func remove_layer(index: int) -> void: for f in range(frames.size()): layer_cel_container.get_child(f).layer = l layer_cel_container.get_child(f).button_setup() + # TODO: This causes a bug where the current layer index is incorrect (should be fixed) + _toggle_layer_buttons_layers() # from_indices and to_indicies should start from the lowest index, and go up @@ -1063,11 +1059,10 @@ func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> v for i in range(to_indices.size()): layers.insert(to_indices[i], old_layers[from_indices[i]]) layers[to_indices[i]].parent = to_parents[i] - # TODO: Frames... for f in range(frames.size()): frames[f].cels.insert(to_indices[i], removed_cels[i][f]) + for i in range(to_indices.size()): # Loop again (All parents must be set before adding the UI) Global.animation_timeline.project_layer_added(to_indices[i]) - # TODO: Add layer and cel buttons # Update the layer indices and layer/cel buttons: for l in range(layers.size()): layers[l].index = l @@ -1076,12 +1071,20 @@ func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> v for f in range(frames.size()): layer_cel_container.get_child(f).layer = l layer_cel_container.get_child(f).button_setup() - _layers_changed(layers) # TODO Remove (needs buttons and index update) + #_layers_changed(layers) # TODO Remove (needs buttons and index update) + _toggle_layer_buttons_layers() + + +func swap_layers() -> void: + # TODO: Implement swap_layers + pass + _toggle_layer_buttons_layers() func move_cel(from_frame: int, to_frame: int, layer: int) -> void: - # TODO: Current frame - # TODO: Current layer + # TODO: In move_cel there seems to be an issue with transform_content_confirm losing image data + # sometimes, may not happen in swap_cel from quick test + Global.canvas.selection.transform_content_confirm() var cel: BaseCel = frames[from_frame].cels[layer] if from_frame < to_frame: for f in range(from_frame, to_frame): # Forward range @@ -1099,14 +1102,14 @@ func move_cel(from_frame: int, to_frame: int, layer: int) -> void: layer_cel_container.get_child(f).frame = f # TODO: Remove this after the fix is verified (and remove all spacing): - layer_cel_container.get_child(f).cel = frames[f].cels[layer] +# layer_cel_container.get_child(f).cel = frames[f].cels[layer] layer_cel_container.get_child(f).button_setup() +# Global.canvas.update() # TODO This shouldn't be needed, is it? (Global.undo_redo should do it) func swap_cel(a_frame: int, a_layer: int, b_frame: int, b_layer: int) -> void: - # TODO: Current frame - # TODO: Current layer + Global.canvas.selection.transform_content_confirm() var temp: BaseCel = frames[a_frame].cels[a_layer] frames[a_frame].cels[a_layer] = frames[b_frame].cels[b_layer] frames[b_frame].cels[b_layer] = temp @@ -1114,3 +1117,26 @@ func swap_cel(a_frame: int, a_layer: int, b_frame: int, b_layer: int) -> void: Global.animation_timeline.project_cel_added(a_frame, a_layer) Global.animation_timeline.project_cel_removed(b_frame, b_layer) Global.animation_timeline.project_cel_added(b_frame, b_layer) + + +func _update_animation_timeline_selection() -> void: + for cel in selected_cels: + var current_frame_tmp: int = cel[0] + var current_layer_tmp: int = cel[1] + if current_frame_tmp < Global.frame_ids.get_child_count(): + var frame_button: BaseButton = Global.frame_ids.get_child(current_frame_tmp) + frame_button.pressed = true + + var container_child_count: int = Global.frames_container.get_child_count() + if current_layer_tmp < container_child_count: + var container = Global.frames_container.get_child( + container_child_count - 1 - current_layer_tmp + ) + if current_frame_tmp < container.get_child_count(): + var cel_button = container.get_child(current_frame_tmp) + cel_button.pressed = true + + var layer_button = Global.layers_container.get_child( + container_child_count - 1 - current_layer_tmp + ) + layer_button.pressed = true diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 75286b061a48..91be3dba4f50 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -180,6 +180,9 @@ func add_frame() -> void: project.undo_redo.add_do_property(project, "current_frame", project.current_frame + 1) project.undo_redo.add_undo_property(project, "current_frame", project.current_frame) project.undo_redo.commit_action() + # TODO: Remove after testing: + print(project.selected_cels) + print(project.current_frame) func _on_DeleteFrame_pressed(frame := -1) -> void: @@ -602,6 +605,7 @@ func _on_FuturePlacement_item_selected(index: int) -> void: func add_layer(is_new := true) -> void: # TODO: Duplicate functionality should probably be split out to allow for different layer types + # TODO: Bug where adding a layer isn't selecting the new layer? Global.canvas.selection.transform_content_confirm() var l := PixelLayer.new() var project: Project = Global.current_project @@ -632,10 +636,10 @@ func add_layer(is_new := true) -> void: cels.append(PixelCel.new(new_layer, 1)) - project.undo_redo.add_do_method(project, "add_layer", l, project.layers.size(), cels) - project.undo_redo.add_undo_method(project, "remove_layer", project.layers.size()) project.undo_redo.add_do_property(project, "current_layer", project.layers.size()) project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) + project.undo_redo.add_do_method(project, "add_layer", l, project.layers.size(), cels) + project.undo_redo.add_undo_method(project, "remove_layer", project.layers.size()) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.commit_action() @@ -653,10 +657,10 @@ func add_group_layer(is_new := true) -> void: for f in project.frames: cels.append(GroupCel.new()) - project.undo_redo.add_do_method(project, "add_layer", l, project.layers.size(), cels) - project.undo_redo.add_undo_method(project, "remove_layer", project.layers.size()) project.undo_redo.add_do_property(project, "current_layer", project.layers.size()) project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) + project.undo_redo.add_do_method(project, "add_layer", l, project.layers.size(), cels) + project.undo_redo.add_undo_method(project, "remove_layer", project.layers.size()) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.commit_action() @@ -674,12 +678,12 @@ func _on_RemoveLayer_pressed() -> void: for f in project.frames: cels.append(f.cels[project.current_layer]) + project.undo_redo.add_do_property(project, "current_layer", max(project.current_layer - 1, 0)) + project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) project.undo_redo.add_do_method(project, "remove_layer", project.current_layer) project.undo_redo.add_undo_method( project, "add_layer", project.layers[project.current_layer], project.current_layer, cels ) - project.undo_redo.add_do_property(project, "current_layer", max(project.current_layer - 1, 0)) - project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.commit_action() @@ -890,6 +894,9 @@ func project_layer_added(layer: int) -> void: cel_button.layer = layer# - 1 # TODO: See if needed layer_cel_container.add_child(cel_button) + layer_button.visible = Global.current_project.layers[layer].is_expanded_in_hierarchy() + layer_cel_container.visible = layer_button.visible + # TODO: are names like "project_layer_removed" or "remove_layer_ui" better? # maybe "layer_removed_in_project"? or something else? func project_layer_removed(layer: int) -> void: @@ -916,8 +923,3 @@ func project_cel_removed(frame: int, layer: int) -> void: Global.frames_container.get_child_count() - 1 - layer ) container.get_child(frame).free() - -# TODO: Consider if this is better kept here, inline in LayerButton, or as a method in LayerButton -func update_layer_buttons() -> void: - for c in Global.layers_container.get_children(): - c._ready() # TODO: Should there be a specific place for this? diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index 91316ed238b0..88127e161a09 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -26,6 +26,19 @@ func _ready() -> void: var texture = child.get_child(0) texture.modulate = Global.modulate_icon_color + # Visualize how deep into the hierarchy the layer is + var hierarchy_depth: int = Global.current_project.layers[layer].get_hierarchy_depth() + hierarchy_spacer.rect_min_size.x = hierarchy_depth * HIERARCHY_DEPTH_PIXEL_SHIFT + + if Global.control.theme.get_color("font_color", "Button").v > 0.5: # Light text is dark theme + self_modulate.v = 1 + hierarchy_depth * 0.4 + else: # Dark text should be light theme + self_modulate.v = 1 - hierarchy_depth * 0.075 + + _update_buttons() + + +func _update_buttons(): if hide_expand_button: expand_button.mouse_filter = Control.MOUSE_FILTER_IGNORE expand_button.get_child(0).visible = false # Hide the TextureRect @@ -51,23 +64,26 @@ func _ready() -> void: else: Global.change_button_texturerect(linked_button.get_child(0), "unlinked_layer.png") - # Visualize how deep into the hierarchy the layer is - var hierarchy_depth: int = Global.current_project.layers[layer].get_hierarchy_depth() - hierarchy_spacer.rect_min_size.x = hierarchy_depth * HIERARCHY_DEPTH_PIXEL_SHIFT - - if Global.control.theme.get_color("font_color", "Button").v > 0.5: # Light text is dark theme - self_modulate.v = 1 + hierarchy_depth * 0.4 - else: # Dark text should be light theme - self_modulate.v = 1 - hierarchy_depth * 0.075 - + visibility_button.modulate.a = 1 + lock_button.modulate.a = 1 if is_instance_valid(Global.current_project.layers[layer].parent): - visible = Global.current_project.layers[layer].parent.is_expanded_in_hierarchy() if not Global.current_project.layers[layer].parent.is_visible_in_hierarchy(): visibility_button.modulate.a = 0.33 if Global.current_project.layers[layer].parent.is_locked_in_hierarchy(): lock_button.modulate.a = 0.33 +func _update_buttons_all_layers() -> void: + # TODO: would it be better to have specified range? (if so rename all_layers to for_layers) + # TODO: IDK if this the right place to put it, but sometimes when moving a layer into a group + # their heirachy visualization isn't at the right level (perhaps not removed and readded?) + for layer_button in Global.layers_container.get_children(): + layer_button._update_buttons() + var expanded = Global.current_project.layers[layer_button.layer].is_expanded_in_hierarchy() + layer_button.visible = expanded + Global.frames_container.get_child(layer_button.get_index()).visible = expanded + + func _draw(): if hierarchy_spacer.rect_size.x > 0.1: var color := Color(1, 1, 1, 0.33) @@ -131,8 +147,10 @@ func _save_layer_name(new_name: String) -> void: func _on_ExpandButton_pressed(): + # TODO: What should happen when the current_layer or selected_cels are children of a layer you collapse? + # Should the current_layer/selection move to ones aren't collapsed? Maybe add to github list of possible later changes Global.current_project.layers[layer].expanded = !Global.current_project.layers[layer].expanded - Global.animation_timeline.update_layer_buttons() + _update_buttons_all_layers() func _on_VisibilityButton_pressed() -> void: @@ -140,14 +158,14 @@ func _on_VisibilityButton_pressed() -> void: Global.current_project.layers[layer].visible = !Global.current_project.layers[layer].visible Global.canvas.update() _select_current_layer() - Global.animation_timeline.update_layer_buttons() + _update_buttons_all_layers() func _on_LockButton_pressed() -> void: Global.canvas.selection.transform_content_confirm() Global.current_project.layers[layer].locked = !Global.current_project.layers[layer].locked _select_current_layer() - Global.animation_timeline.update_layer_buttons() + _update_buttons_all_layers() func _on_LinkButton_pressed() -> void: @@ -163,7 +181,7 @@ func _on_LinkButton_pressed() -> void: container.get_child(Global.current_project.current_frame).button_setup() Global.current_project.layers = Global.current_project.layers # Call the setter - Global.animation_timeline.update_layer_buttons() # TODO: this one doesn't need to update all (and others only a specific range) + _update_buttons() func _select_current_layer() -> void: @@ -256,6 +274,7 @@ func drop_data(_pos, data) -> void: # TODO: Having "SourceLayers/OldLayers (that you don't change) and new_layers would make this less confusing else: # from_indices should be in order of the layer indices, starting from the lowest + # TODO: can this code be made easier to read? var from_indices := [] for c in new_layers[drop_layer].get_children_recursive(): from_indices.append(c.index) diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index 05e768af5c4e..be25c89fbf89 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -109,7 +109,7 @@ func _on_PopupMenu_id_pressed(id: int) -> void: var new_layers: Array = Global.current_project.duplicate_layers() var new_cels: Array = f.cels.duplicate() for i in new_cels.size(): - # TODO: This doesn't work + # TODO: This doesn't work (currently replaces ALL cels on the frame) new_cels[i] = PixelCel.new( new_cels[i].image, new_cels[i].opacity, new_cels[i].image_texture ) From 7303bb7b2d95e2e90c668090c36de8aac0a90658 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Tue, 28 Jun 2022 15:36:01 -0400 Subject: [PATCH 032/154] Fixed timeline selection issues when creating a new project. Some code cleanup --- src/Autoload/Global.gd | 1 + src/Classes/PixelLayer.gd | 2 +- src/Main.gd | 10 ++++++---- src/UI/Dialogs/CreateNewImage.gd | 4 ++-- src/UI/Timeline/AnimationTimeline.gd | 17 +++++++++-------- src/UI/Timeline/FrameButton.gd | 2 ++ 6 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index 3c593d47a435..8de597652556 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -263,6 +263,7 @@ func undo_or_redo( animation_timer.stop() elif "Move Cels" == action_name: + # TODO: is this still required? project.frames = project.frames # to call frames_changed canvas.update() diff --git a/src/Classes/PixelLayer.gd b/src/Classes/PixelLayer.gd index e72627d5af9d..0e245019eb76 100644 --- a/src/Classes/PixelLayer.gd +++ b/src/Classes/PixelLayer.gd @@ -4,7 +4,7 @@ extends BaseLayer var new_cels_linked := false var linked_cels := [] # Array of Frames - +# TODO: Should _init include project as a parameter? (for all Layer types) func _init(_name := "") -> void: name = _name diff --git a/src/Main.gd b/src/Main.gd index 2d545c4bbd75..e3f0d93119a7 100644 --- a/src/Main.gd +++ b/src/Main.gd @@ -22,11 +22,13 @@ func _ready() -> void: Global.window_title = tr("untitled") + " - Pixelorama " + Global.current_version - Global.current_project.add_layer(PixelLayer.new(), 0, []) - var frame: Frame = Global.current_project.new_empty_frame() - Global.current_project.add_frame(frame, 0) + Global.current_project.layers.append(PixelLayer.new()) + Global.current_project.layers[0].project = Global.current_project + Global.current_project.frames.append(Global.current_project.new_empty_frame()) + Global.animation_timeline.project_changed() + # TODO: I Think this line should be safe to remove: (calling setter) - Global.current_project.layers = Global.current_project.layers +# Global.current_project.layers = Global.current_project.layers Import.import_brushes(Global.directory_module.get_brushes_search_path_in_order()) Import.import_patterns(Global.directory_module.get_patterns_search_path_in_order()) diff --git a/src/UI/Dialogs/CreateNewImage.gd b/src/UI/Dialogs/CreateNewImage.gd index beaa55c0504a..49a65d98141f 100644 --- a/src/UI/Dialogs/CreateNewImage.gd +++ b/src/UI/Dialogs/CreateNewImage.gd @@ -109,9 +109,9 @@ func _on_CreateNewImage_confirmed() -> void: var new_project := Project.new([], proj_name, Vector2(width, height).floor()) new_project.layers.append(PixelLayer.new()) + new_project.layers[0].project = new_project new_project.fill_color = fill_color - var frame: Frame = new_project.new_empty_frame() - new_project.frames.append(frame) + new_project.frames.append(new_project.new_empty_frame()) Global.projects.append(new_project) Global.tabs.current_tab = Global.tabs.get_tab_count() - 1 Global.canvas.camera_zoom() diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 91be3dba4f50..3c94b557181e 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -13,6 +13,7 @@ var past_above_canvas := true var future_above_canvas := true var frame_button_node = preload("res://src/UI/Timeline/FrameButton.tscn") +# TODO: May remove some of these: var pixel_layer_button_node = preload("res://src/UI/Timeline/PixelLayerButton.tscn") var group_layer_button_node = preload("res://src/UI/Timeline/GroupLayerButton.tscn") var pixel_cel_button_node = preload("res://src/UI/Timeline/PixelCelButton.tscn") @@ -827,24 +828,23 @@ func project_changed() -> void: for f in range(project.frames.size()): var button: Button = frame_button_node.instance() button.frame = f - button.rect_min_size.x = Global.animation_timeline.cel_size - button.text = str(f + 1) Global.frame_ids.add_child(button) Global.frame_ids.move_child(button, f) # TODO: May not be needed, depending on other changes to selection - var current_layer_button = Global.layers_container.get_child( - Global.layers_container.get_child_count() - 1 - project.current_layer - ) - current_layer_button.pressed = true +# var current_layer_button = Global.layers_container.get_child( +# Global.layers_container.get_child_count() - 1 - project.current_layer +# ) +# current_layer_button.pressed = true + + # TODO: Remove an inline what's needed here if this isn't used anywhere else: + Global.current_project._update_animation_timeline_selection() func project_frame_added(frame: int) -> void: var project: Project = Global.current_project # TODO: maybe pass in instead? var button: Button = frame_button_node.instance() button.frame = frame - button.rect_min_size.x = Global.animation_timeline.cel_size - button.text = str(frame + 1) Global.frame_ids.add_child(button) Global.frame_ids.move_child(button, frame) @@ -856,6 +856,7 @@ func project_frame_added(frame: int) -> void: container.add_child(cel_button) container.move_child(cel_button, frame) layer += 1 + # TODO: Adding a frame with multiple layers results in the cels being put backwards! func project_frame_removed(frame: int) -> void: diff --git a/src/UI/Timeline/FrameButton.gd b/src/UI/Timeline/FrameButton.gd index 394c8f96d009..0fa39249dacc 100644 --- a/src/UI/Timeline/FrameButton.gd +++ b/src/UI/Timeline/FrameButton.gd @@ -7,6 +7,8 @@ onready var frame_properties: ConfirmationDialog = Global.control.find_node("Fra func _ready() -> void: + rect_min_size.x = Global.animation_timeline.cel_size + text = str(frame + 1) connect("pressed", self, "_button_pressed") connect("mouse_entered", self, "_update_tooltip") From 43be23d9e962d3ab3e6f99efa67ae9ed54195e58 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Tue, 28 Jun 2022 16:12:52 -0400 Subject: [PATCH 033/154] tweaks --- src/Classes/Project.gd | 42 ++++++++++++++-------------- src/UI/Timeline/AnimationTimeline.gd | 6 ---- src/UI/Timeline/LayerButton.gd | 6 ++-- 3 files changed, 23 insertions(+), 31 deletions(-) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 94274c4688cf..06d59a3f1fb7 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -574,20 +574,20 @@ func _frame_changed(value: int) -> void: selected_cels.append([current_frame, current_layer]) # Select the new frame for cel in selected_cels: - var current_frame_tmp: int = cel[0] - var current_layer_tmp: int = cel[1] - if current_frame_tmp < Global.frame_ids.get_child_count(): - var frame_button: BaseButton = Global.frame_ids.get_child(current_frame_tmp) + var frame: int = cel[0] + var layer: int = cel[1] + if frame < Global.frame_ids.get_child_count(): + var frame_button: BaseButton = Global.frame_ids.get_child(frame) frame_button.pressed = true var container_child_count: int = Global.frames_container.get_child_count() - if current_layer_tmp < container_child_count: + if layer < container_child_count: var container = Global.frames_container.get_child( - container_child_count - 1 - current_layer_tmp + container_child_count - 1 - layer ) - if current_frame_tmp < container.get_child_count(): - var fbutton = container.get_child(current_frame_tmp) - fbutton.pressed = true + if frame < container.get_child_count(): + var cel_button = container.get_child(frame) + cel_button.pressed = true Global.disable_button(Global.remove_frame_button, frames.size() == 1) Global.disable_button(Global.move_left_frame_button, frames.size() == 1 or current_frame == 0) @@ -619,10 +619,10 @@ func _layer_changed(value: int) -> void: layer_button.pressed = false for cel in selected_cels: - var current_layer_tmp: int = cel[1] - if current_layer_tmp < Global.layers_container.get_child_count(): + var layer: int = cel[1] + if layer < Global.layers_container.get_child_count(): var layer_button = Global.layers_container.get_child( - Global.layers_container.get_child_count() - 1 - current_layer_tmp + Global.layers_container.get_child_count() - 1 - layer ) layer_button.pressed = true @@ -1121,22 +1121,22 @@ func swap_cel(a_frame: int, a_layer: int, b_frame: int, b_layer: int) -> void: func _update_animation_timeline_selection() -> void: for cel in selected_cels: - var current_frame_tmp: int = cel[0] - var current_layer_tmp: int = cel[1] - if current_frame_tmp < Global.frame_ids.get_child_count(): - var frame_button: BaseButton = Global.frame_ids.get_child(current_frame_tmp) + var frame: int = cel[0] + var layer: int = cel[1] + if frame < Global.frame_ids.get_child_count(): + var frame_button: BaseButton = Global.frame_ids.get_child(frame) frame_button.pressed = true var container_child_count: int = Global.frames_container.get_child_count() - if current_layer_tmp < container_child_count: + if layer < container_child_count: var container = Global.frames_container.get_child( - container_child_count - 1 - current_layer_tmp + container_child_count - 1 - layer ) - if current_frame_tmp < container.get_child_count(): - var cel_button = container.get_child(current_frame_tmp) + if frame < container.get_child_count(): + var cel_button = container.get_child(frame) cel_button.pressed = true var layer_button = Global.layers_container.get_child( - container_child_count - 1 - current_layer_tmp + container_child_count - 1 - layer ) layer_button.pressed = true diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 3c94b557181e..e20601873eb7 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -831,12 +831,6 @@ func project_changed() -> void: Global.frame_ids.add_child(button) Global.frame_ids.move_child(button, f) - # TODO: May not be needed, depending on other changes to selection -# var current_layer_button = Global.layers_container.get_child( -# Global.layers_container.get_child_count() - 1 - project.current_layer -# ) -# current_layer_button.pressed = true - # TODO: Remove an inline what's needed here if this isn't used anywhere else: Global.current_project._update_animation_timeline_selection() diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index 88127e161a09..82da23003601 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -38,7 +38,7 @@ func _ready() -> void: _update_buttons() -func _update_buttons(): +func _update_buttons() -> void: if hide_expand_button: expand_button.mouse_filter = Control.MOUSE_FILTER_IGNORE expand_button.get_child(0).visible = false # Hide the TextureRect @@ -75,8 +75,6 @@ func _update_buttons(): func _update_buttons_all_layers() -> void: # TODO: would it be better to have specified range? (if so rename all_layers to for_layers) - # TODO: IDK if this the right place to put it, but sometimes when moving a layer into a group - # their heirachy visualization isn't at the right level (perhaps not removed and readded?) for layer_button in Global.layers_container.get_children(): layer_button._update_buttons() var expanded = Global.current_project.layers[layer_button.layer].is_expanded_in_hierarchy() @@ -84,7 +82,7 @@ func _update_buttons_all_layers() -> void: Global.frames_container.get_child(layer_button.get_index()).visible = expanded -func _draw(): +func _draw() -> void: if hierarchy_spacer.rect_size.x > 0.1: var color := Color(1, 1, 1, 0.33) color.v = round(Global.control.theme.get_color("font_color", "Button").v) From a45cd332cbffb6fedc667051db966f9937af1963 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Tue, 28 Jun 2022 16:20:02 -0400 Subject: [PATCH 034/154] Removed a bunch of commented out code --- src/Classes/Project.gd | 128 --------------------------- src/UI/Timeline/AnimationTimeline.gd | 7 +- src/UI/Timeline/FrameButton.gd | 35 -------- 3 files changed, 2 insertions(+), 168 deletions(-) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 06d59a3f1fb7..973b77017950 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -141,65 +141,6 @@ func _selection_offset_changed(value: Vector2) -> void: func change_project() -> void: - # Remove old nodes -# for container in Global.layers_container.get_children(): -# container.queue_free() -# -# _remove_cel_buttons() -# -# for frame_id in Global.frame_ids.get_children(): -# Global.frame_ids.remove_child(frame_id) -# frame_id.queue_free() -# -# # Create new ones -# for i in range(layers.size() - 1, -1, -1): -# # Create layer buttons -# var layer_container: LayerButton -# if layers[i] is PixelLayer: -# layer_container = pixel_layer_button_node.instance() -# elif layers[i] is GroupLayer: -# layer_container = group_layer_button_node.instance() -# layer_container.layer = i -# if layers[i].name == "": -# layers[i].name = layers[i].get_default_name(i) -# -# Global.layers_container.add_child(layer_container) -# layer_container.label.text = layers[i].name -# layer_container.line_edit.text = layers[i].name -# -# var layer_cel_container := HBoxContainer.new() -# Global.frames_container.add_child(layer_cel_container) -# for j in range(frames.size()): # Create Cel buttons -# var cel_button = pixel_cel_button_node.instance() -# cel_button.frame = j -# cel_button.layer = i -# # TODO: Mak sure this works properly with groups -# cel_button.get_child(0).texture = frames[j].cels[i].image_texture -# if j == current_frame and i == current_layer: -# cel_button.pressed = true -# -# layer_cel_container.add_child(cel_button) -# -# if (is_instance_valid(layers[i].parent) -# and not layers[i].parent.is_expanded_in_hierarchy()): -# layer_cel_container.visible = false -# -# for j in range(frames.size()): # Create frame ID labels -# var button: Button = frame_button_node.instance() -# button.frame = j -# button.rect_min_size.x = Global.animation_timeline.cel_size -# button.text = str(j + 1) -# if j == current_frame: -# button.add_color_override( -# "font_color", Global.control.theme.get_color("Selected Color", "Label") -# ) -# Global.frame_ids.add_child(button) -# -# var layer_button = Global.layers_container.get_child( -# Global.layers_container.get_child_count() - 1 - current_layer -# ) -# layer_button.pressed = true - Global.animation_timeline.project_changed() Global.current_frame_mark_label.text = "%s/%s" % [str(current_frame + 1), frames.size()] @@ -463,36 +404,6 @@ func _frames_changed(value: Array) -> void: Global.canvas.selection.transform_content_confirm() frames = value # selected_cels.clear() # TODO: This is commented out to prevent selected_cels being blank at begginning (Will it still be needed? Will removing the setter calls in the new functions fix it?) -# _remove_cel_buttons() -# -# for frame_id in Global.frame_ids.get_children(): -# Global.frame_ids.remove_child(frame_id) -# frame_id.queue_free() -# -# for i in range(layers.size() - 1, -1, -1): -# var layer_cel_container := HBoxContainer.new() -# layer_cel_container.name = "FRAMESS " + str(i) -# Global.frames_container.add_child(layer_cel_container) -# for j in range(frames.size()): -# if layers[i] is PixelLayer: -# var cel_button = pixel_cel_button_node.instance() -# cel_button.frame = j -# cel_button.layer = i -# cel_button.get_child(0).texture = frames[j].cels[i].image_texture -# layer_cel_container.add_child(cel_button) -# elif layers[i] is GroupLayer: -# # TODO: Make GroupLayers work here -# pass -# if (is_instance_valid(layers[i].parent) -# and not layers[i].parent.is_expanded_in_hierarchy()): -# layer_cel_container.visible = false -# -# for j in range(frames.size()): -# var button: Button = frame_button_node.instance() -# button.frame = j -# button.rect_min_size.x = Global.animation_timeline.cel_size -# button.text = str(j + 1) -# Global.frame_ids.add_child(button) _set_timeline_first_and_last_frames() @@ -505,45 +416,6 @@ func _layers_changed(value: Array) -> void: # selected_cels.clear() # TODO: This is commented out to prevent selected_cels being blank at begginning (Will it still be needed? Will removing the setter calls in the new functions fix it?) -# for container in Global.layers_container.get_children(): -# container.queue_free() -# -# _remove_cel_buttons() -# -# for i in range(layers.size() - 1, -1, -1): -# var layer_button: LayerButton -# if layers[i] is PixelLayer: -# layer_button = pixel_layer_button_node.instance() -# elif layers[i] is GroupLayer: -# layer_button = group_layer_button_node.instance() -# layer_button.layer = i -# layers[i].index = i -# layers[i].project = self -# if layers[i].name == "": -# layers[i].name = layers[i].get_default_name(i) -# -# Global.layers_container.add_child(layer_button) -# layer_button.label.text = layers[i].name -# layer_button.line_edit.text = layers[i].name -# -# var layer_cel_container := HBoxContainer.new() -# layer_cel_container.name = "LAYERSSS " + str(i) -# Global.frames_container.add_child(layer_cel_container) -# # TODO: FIGURE OUT FRAMES WITH GROUP LAYERS! -# for j in range(frames.size()): -# var cel_button # TODO: Figure out static typing (will there be a BaseCelButton?) -# if layers[i] is PixelLayer: -# cel_button = pixel_cel_button_node.instance() -# cel_button.get_child(0).texture = frames[j].cels[i].image_texture -# elif layers[i] is GroupLayer: -# cel_button = group_cel_button_node.instance() -# cel_button.frame = j -# cel_button.layer = i -# layer_cel_container.add_child(cel_button) -# if (is_instance_valid(layers[i].parent) -# and not layers[i].parent.is_expanded_in_hierarchy()): -# layer_cel_container.visible = false -# # var layer_button = Global.layers_container.get_child( # Global.layers_container.get_child_count() - 1 - current_layer # ) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index e20601873eb7..4313fabc20d9 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -181,9 +181,6 @@ func add_frame() -> void: project.undo_redo.add_do_property(project, "current_frame", project.current_frame + 1) project.undo_redo.add_undo_property(project, "current_frame", project.current_frame) project.undo_redo.commit_action() - # TODO: Remove after testing: - print(project.selected_cels) - print(project.current_frame) func _on_DeleteFrame_pressed(frame := -1) -> void: @@ -689,7 +686,7 @@ func _on_RemoveLayer_pressed() -> void: project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.commit_action() -# TODO: Refactor this (probably completely remove) +# TODO: Refactor this (maybe completely remove) func change_layer_order(rate: int) -> void: var change = Global.current_project.current_layer + rate @@ -721,7 +718,7 @@ func change_layer_order(rate: int) -> void: Global.current_project.undo_redo.add_do_method(Global, "undo_or_redo", false) Global.current_project.undo_redo.commit_action() - +# TODO: Does this need to be part of the refactor? func _on_MergeDownLayer_pressed() -> void: var new_layers: Array = Global.current_project.duplicate_layers() diff --git a/src/UI/Timeline/FrameButton.gd b/src/UI/Timeline/FrameButton.gd index 0fa39249dacc..43b1d2543684 100644 --- a/src/UI/Timeline/FrameButton.gd +++ b/src/UI/Timeline/FrameButton.gd @@ -88,17 +88,8 @@ func _on_PopupMenu_id_pressed(id: int) -> void: func change_frame_order(rate: int) -> void: var change = frame + rate var project = Global.current_project -# var new_frames: Array = Global.current_project.frames.duplicate() -# var temp = new_frames[frame] -# new_frames[frame] = new_frames[change] -# new_frames[change] = temp project.undo_redo.create_action("Change Frame Order") -# project.undo_redo.add_do_property(project, "frames", new_frames) -# project.undo_redo.add_undo_property( -# project, "frames", project.frames -# ) - project.undo_redo.add_do_method(project, "move_frame", frame, change) project.undo_redo.add_undo_method(project, "move_frame", change, frame) @@ -108,7 +99,6 @@ func change_frame_order(rate: int) -> void: project.undo_redo.add_do_property(project, "current_frame", project.current_frame) project.undo_redo.add_undo_property(project, "current_frame", project.current_frame) - project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.commit_action() @@ -149,37 +139,12 @@ func can_drop_data(_pos, data) -> bool: func drop_data(_pos, data) -> void: var drop_frame = data[1] var project = Global.current_project - -# var drop_frames: Array = Global.current_project.frames.duplicate() -# var temp = drop_frames[frame] -# drop_frames[frame] = drop_frames[drop_frame] -# drop_frames[drop_frame] = temp - project.undo_redo.create_action("Change Frame Order") -# Global.current_project.undo_redo.add_do_property(Global.current_project, "frames", drop_frames) -# Global.current_project.undo_redo.add_undo_property( -# Global.current_project, "frames", Global.current_project.frames -# ) -# -# if Global.current_project.current_frame == drop_frame: -# Global.current_project.undo_redo.add_do_property( -# Global.current_project, "current_frame", frame -# ) -# else: -# Global.current_project.undo_redo.add_do_property( -# Global.current_project, "current_frame", Global.current_project.current_frame -# ) -# -# Global.current_project.undo_redo.add_undo_property( -# Global.current_project, "current_frame", Global.current_project.current_frame -# ) - if Input.is_action_pressed("ctrl"): # Swap frames project.undo_redo.add_do_method(project, "swap_frame", frame, drop_frame) project.undo_redo.add_undo_method(project, "swap_frame", frame, drop_frame) else: # Move frames var to_frame: int - # TODO: Test that this is correct: (after cel button ui changes) if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): # Left to_frame = frame else: # Right From 3d29f853121bed6a38741af3e50c775e4e0ebbb2 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Tue, 28 Jun 2022 16:23:01 -0400 Subject: [PATCH 035/154] Removing more commented out code --- src/UI/Timeline/PixelCelButton.gd | 41 ------------------------------- 1 file changed, 41 deletions(-) diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index be25c89fbf89..0dce3d218bb0 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -233,48 +233,7 @@ func drop_data(_pos, data) -> void: var drop_layer = data[2] var project = Global.current_project -# var this_frame_new_cels = project.frames[frame].cels.duplicate() -# var drop_frame_new_cels -# var temp = this_frame_new_cels[layer] -# this_frame_new_cels[layer] = project.frames[drop_frame].cels[drop_layer] -# if frame == drop_frame: -# this_frame_new_cels[drop_layer] = temp -# else: -# drop_frame_new_cels = project.frames[drop_frame].cels.duplicate() -# drop_frame_new_cels[drop_layer] = temp - project.undo_redo.create_action("Move Cels") -# project.undo_redo.add_do_property( -# project.frames[frame], "cels", this_frame_new_cels -# ) -# -# project.undo_redo.add_do_property(project, "current_layer", layer) -# project.undo_redo.add_undo_property( -# project, "current_layer", project.current_layer -# ) -# -# if frame != drop_frame: # If the cel moved to a different frame -# project.undo_redo.add_do_property( -# project.frames[drop_frame], "cels", drop_frame_new_cels -# ) -# -# project.undo_redo.add_do_property( -# project, "current_frame", frame -# ) -# project.undo_redo.add_undo_property( -# project, "current_frame", project.current_frame -# ) -# -# project.undo_redo.add_undo_property( -# project.frames[drop_frame], -# "cels", -# project.frames[drop_frame].cels -# ) -# -# project.undo_redo.add_undo_property( -# project.frames[frame], "cels", project.frames[frame].cels -# ) - if Input.is_action_pressed("ctrl") or layer != drop_layer: # Swap cels project.undo_redo.add_do_method(project, "swap_cel", frame, layer, drop_frame, drop_layer) project.undo_redo.add_undo_method(project, "swap_cel", frame, layer, drop_frame, drop_layer) From 262fb8586f0a8385c4ce696a87bedc48825027a7 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 29 Jun 2022 17:07:56 -0400 Subject: [PATCH 036/154] Fixed bugs with timeline selectio. Fixed cels being placed in the reverse layer order when adding a frame --- src/Classes/Project.gd | 51 ++++++++-------------------- src/UI/Timeline/AnimationTimeline.gd | 20 +++++------ src/UI/Timeline/LayerButton.gd | 8 +++-- 3 files changed, 28 insertions(+), 51 deletions(-) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 973b77017950..e2bc810ebf77 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -403,8 +403,7 @@ func _size_changed(value: Vector2) -> void: func _frames_changed(value: Array) -> void: Global.canvas.selection.transform_content_confirm() frames = value -# selected_cels.clear() # TODO: This is commented out to prevent selected_cels being blank at begginning (Will it still be needed? Will removing the setter calls in the new functions fix it?) - +# selected_cels.clear() # TODO: Determine if this needs to be kept (If it is, selected cels needs to be intialized after creating project (ie: in Main), rather than here _set_timeline_first_and_last_frames() @@ -414,8 +413,8 @@ func _layers_changed(value: Array) -> void: Global.layers_changed_skip = false return -# selected_cels.clear() # TODO: This is commented out to prevent selected_cels being blank at begginning (Will it still be needed? Will removing the setter calls in the new functions fix it?) - +# selected_cels.clear() # TODO: Determine if this needs to be kept (If it is, selected cels needs to be intialized after creating project (ie: in Main), rather than here + # TODO: investigate wether these are still required: # var layer_button = Global.layers_container.get_child( # Global.layers_container.get_child_count() - 1 - current_layer # ) @@ -467,7 +466,6 @@ func _frame_changed(value: int) -> void: Global.move_right_frame_button, frames.size() == 1 or current_frame == frames.size() - 1 ) - if current_frame < frames.size(): # TODO: Make this work with groups: if not layers[current_layer] is GroupLayer: @@ -790,12 +788,10 @@ func resize_bitmap_values(bitmap: BitMap, new_size: Vector2, flip_x: bool, flip_ func add_frame(frame: Frame, index: int) -> void: + assert(self == Global.current_project) # TODO: Remove (Things like calling project_frame/layer_added may need to do a check if its the current project if this fails) Global.canvas.selection.transform_content_confirm() selected_cels.clear() - # TODO: May need to call _frames_changed setter here (at least for some of it) frames.insert(index, frame) - # TODO: Check if these (especially remove/move) mess up selection? -# _frames_changed(frames)# TODO: Remove # TODO: These may need an if self == Global.current_project depending on use Global.animation_timeline.project_frame_added(index) # Update the frames and frame buttons: @@ -808,10 +804,6 @@ func add_frame(frame: Frame, index: int) -> void: for f in range(frames.size()): layer_cel_container.get_child(f).frame = f layer_cel_container.get_child(f).button_setup() -# _update_animation_timeline_selection() -# # TODO: Remove after testing: -# print(selected_cels) -# print(current_frame) func remove_frame(index: int) -> void: @@ -820,7 +812,6 @@ func remove_frame(index: int) -> void: # TODO: If this messes up selection, would doing multiple here help? # TODO: Could one half of cel linking and animation tags be included in the add or remove_frame functions? (ie: removing works, but adding doesn't?) frames.remove(index) -# _frames_changed(frames)# TODO: Remove Global.animation_timeline.project_frame_removed(index) # Update the frames and frame buttons: for f in range(frames.size()): @@ -835,16 +826,13 @@ func remove_frame(index: int) -> void: func move_frame(from_index: int, to_index: int) -> void: - # TODO: move_cel transform_content_confirm bug likely applies here too... Global.canvas.selection.transform_content_confirm() selected_cels.clear() var frame = frames[from_index] frames.remove(from_index) Global.animation_timeline.project_frame_removed(from_index) - # TODO: Ensure the final position is always right frames.insert(to_index, frame) Global.animation_timeline.project_frame_added(to_index) -# _frames_changed(frames)# TODO: Remove # Update the frames and frame buttons: for f in range(frames.size()): Global.frame_ids.get_child(f).frame = f @@ -859,6 +847,7 @@ func move_frame(from_index: int, to_index: int) -> void: func swap_frame(a_index: int, b_index: int) -> void: Global.canvas.selection.transform_content_confirm() + selected_cels.clear() var temp: Frame = frames[a_index] frames[a_index] = frames[b_index] frames[b_index] = temp @@ -869,14 +858,14 @@ func swap_frame(a_index: int, b_index: int) -> void: func add_layer(layer: BaseLayer, index: int, cels: Array) -> void: - # TODO: Global.canvas.selection.transform_content_confirm() + assert(self == Global.current_project) # TODO: Remove (Things like calling project_frame/layer_added may need to do a check if its the current project if this fails) + # TODO: is Global.canvas.selection.transform_content_confirm() needed for layer changes (it wasn't used before I think) + selected_cels.clear() layers.insert(index, layer) for f in range(frames.size()): frames[f].cels.insert(index, cels[f]) layer.project = self # TODO: Update layer index (and others, more efficient if add layer supports multiple) - # TODO: Update layer button indices -# _layers_changed(layers)# TODO: Remove Global.animation_timeline.project_layer_added(index) # Update the layer indices and layer/cel buttons: for l in range(layers.size()): @@ -887,17 +876,14 @@ func add_layer(layer: BaseLayer, index: int, cels: Array) -> void: layer_cel_container.get_child(f).layer = l layer_cel_container.get_child(f).button_setup() _toggle_layer_buttons_layers() -# _update_animation_timeline_selection() func remove_layer(index: int) -> void: - # TODO: Global.canvas.selection.transform_content_confirm() + selected_cels.clear() layers.remove(index) for frame in frames: frame.cels.remove(index) # TODO: Update layer index (and others, more efficient if remove layer supports multiple) -# # TODO: Update layer button indices -# _layers_changed(layers)# TODO: Remove Global.animation_timeline.project_layer_removed(index) # Update the layer indices and layer/cel buttons: for l in range(layers.size()): @@ -907,15 +893,14 @@ func remove_layer(index: int) -> void: for f in range(frames.size()): layer_cel_container.get_child(f).layer = l layer_cel_container.get_child(f).button_setup() - # TODO: This causes a bug where the current layer index is incorrect (should be fixed) _toggle_layer_buttons_layers() # from_indices and to_indicies should start from the lowest index, and go up func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> void: # TODO: it may be good to do a test run with using loops of add/remove_layer instead of using move_layers - # to_parents could just be a single for now, but then how should move_layers be named? - # TODO: Global.canvas.selection.transform_content_confirm() + # TODO: to_parents could just be a single for now, but then how should move_layers be named? + selected_cels.clear() var old_layers := layers.duplicate() var removed_cels := [] # Array of array of cels (an array for each layer removed) @@ -927,10 +912,9 @@ func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> v removed_cels[i].append(frame.cels[from_indices[i] - i]) frame.cels.remove(from_indices[i] - i) Global.animation_timeline.project_layer_removed(from_indices[i] - i) - # TODO: remove layer and cel buttons for i in range(to_indices.size()): layers.insert(to_indices[i], old_layers[from_indices[i]]) - layers[to_indices[i]].parent = to_parents[i] + layers[to_indices[i]].parent = to_parents[i] # TODO: it could be possible to do the to_parents when removing (previous loop), allowing this loop to be recombined with the next for f in range(frames.size()): frames[f].cels.insert(to_indices[i], removed_cels[i][f]) for i in range(to_indices.size()): # Loop again (All parents must be set before adding the UI) @@ -943,20 +927,19 @@ func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> v for f in range(frames.size()): layer_cel_container.get_child(f).layer = l layer_cel_container.get_child(f).button_setup() - #_layers_changed(layers) # TODO Remove (needs buttons and index update) _toggle_layer_buttons_layers() func swap_layers() -> void: + selected_cels.clear() # TODO: Implement swap_layers pass _toggle_layer_buttons_layers() func move_cel(from_frame: int, to_frame: int, layer: int) -> void: - # TODO: In move_cel there seems to be an issue with transform_content_confirm losing image data - # sometimes, may not happen in swap_cel from quick test Global.canvas.selection.transform_content_confirm() + selected_cels.clear() var cel: BaseCel = frames[from_frame].cels[layer] if from_frame < to_frame: for f in range(from_frame, to_frame): # Forward range @@ -972,16 +955,12 @@ func move_cel(from_frame: int, to_frame: int, layer: int) -> void: var layer_cel_container = Global.frames_container.get_child(layers.size() - 1 - layer) for f in range(frames.size()): layer_cel_container.get_child(f).frame = f - - # TODO: Remove this after the fix is verified (and remove all spacing): -# layer_cel_container.get_child(f).cel = frames[f].cels[layer] - layer_cel_container.get_child(f).button_setup() -# Global.canvas.update() # TODO This shouldn't be needed, is it? (Global.undo_redo should do it) func swap_cel(a_frame: int, a_layer: int, b_frame: int, b_layer: int) -> void: Global.canvas.selection.transform_content_confirm() + selected_cels.clear() var temp: BaseCel = frames[a_frame].cels[a_layer] frames[a_frame].cels[a_layer] = frames[b_frame].cels[b_layer] frames[b_frame].cels[b_layer] = temp diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 4313fabc20d9..752436642282 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -43,7 +43,7 @@ func _ready() -> void: find_node("EndSpacer").size_flags_horizontal = SIZE_EXPAND_FILL timeline_scroll.size_flags_horizontal = SIZE_FILL - +# TODO: See if these two should be kept or done another way: func _notification(what: int) -> void: if what == NOTIFICATION_DRAG_END: drag_highlight.hide() @@ -251,7 +251,6 @@ func delete_frames(frames := []) -> void: project.undos += 1 project.undo_redo.create_action("Remove Frame") - var x := frames.size() - 1 while x >= 0: project.undo_redo.add_do_method(project, "remove_frame", frames[x]) @@ -260,7 +259,6 @@ func delete_frames(frames := []) -> void: project.undo_redo.add_undo_method( project, "add_frame", project.frames[frames[i]], frames[i] ) - project.undo_redo.add_do_property(project, "layers", new_layers) project.undo_redo.add_undo_property(project, "layers", Global.current_project.layers) project.undo_redo.add_do_property(project, "animation_tags", new_animation_tags) @@ -812,7 +810,7 @@ func _on_OnionSkinningSettings_popup_hide() -> void: func project_changed() -> void: var project: Project = Global.current_project # TODO: maybe pass in instead? - # TODO: Remove all buttons + # TODO: Could using queue_free rather than free (or remove and queue_free) actually cause bugs? for child in Global.layers_container.get_children(): child.queue_free() for child in Global.frame_ids.get_children(): @@ -839,15 +837,14 @@ func project_frame_added(frame: int) -> void: Global.frame_ids.add_child(button) Global.frame_ids.move_child(button, frame) - var layer := 0 # TODO: This probably needs to be reveresed... + var layer := Global.frames_container.get_child_count() - 1 for container in Global.frames_container.get_children(): var cel_button = project.frames[frame].cels[layer].create_cel_button() cel_button.frame = frame cel_button.layer = layer container.add_child(cel_button) container.move_child(cel_button, frame) - layer += 1 - # TODO: Adding a frame with multiple layers results in the cels being put backwards! + layer -= 1 func project_frame_removed(frame: int) -> void: @@ -861,13 +858,13 @@ func project_layer_added(layer: int) -> void: var project: Project = Global.current_project # TODO: maybe pass in instead? # TODO: should probably have a "layer" variable... (to many project.layers[layer])... # ...or refactor things so less of this code is needed here. - + # TODO: Could this function be organized in a better way? var layer_button: LayerButton if project.layers[layer] is PixelLayer: layer_button = pixel_layer_button_node.instance() elif project.layers[layer] is GroupLayer: layer_button = group_layer_button_node.instance() - layer_button.layer = layer# - 1 # TODO: See if needed + layer_button.layer = layer # TODO: See if needed if project.layers[layer].name == "": # TODO: This probably could be somewhere else... project.layers[layer].name = project.layers[layer].get_default_name(layer) @@ -889,8 +886,7 @@ func project_layer_added(layer: int) -> void: layer_button.visible = Global.current_project.layers[layer].is_expanded_in_hierarchy() layer_cel_container.visible = layer_button.visible -# TODO: are names like "project_layer_removed" or "remove_layer_ui" better? -# maybe "layer_removed_in_project"? or something else? + func project_layer_removed(layer: int) -> void: var count := Global.layers_container.get_child_count() Global.layers_container.get_child(count - 1 - layer).free() @@ -909,7 +905,7 @@ func project_cel_added(frame: int, layer: int) -> void: container.add_child(cel_button) container.move_child(cel_button, frame) -# TODO: Not yet sure if this is really needed: + func project_cel_removed(frame: int, layer: int) -> void: var container := Global.frames_container.get_child( Global.frames_container.get_child_count() - 1 - layer diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index 82da23003601..7e09ec0217de 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -321,9 +321,11 @@ func drop_data(_pos, data) -> void: project.undo_redo.add_undo_method( project, "move_layers", to_indices, from_indices, from_parents ) - if project.current_layer == layer: - project.undo_redo.add_do_property(project, "current_layer", drop_layer) - project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) + if project.current_layer == drop_layer: # TODO: This doesn't work... + project.undo_redo.add_do_property(project, "current_layer", layer) + else: + project.undo_redo.add_do_property(project, "current_layer", project.current_layer) + project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) # TODO: undo_or_redo is at end here, but earlier in others, does it matter which order? project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.add_do_method(Global, "undo_or_redo", false) From 252ca6a22bc92b9b43d75dde8855612b1a6dbecb Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 30 Jun 2022 13:39:50 -0400 Subject: [PATCH 037/154] Changed add/remove_frame to add/remove_frames (multiple support) --- src/Classes/Project.gd | 18 ++++++++++-------- src/UI/Timeline/AnimationTimeline.gd | 18 ++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index e2bc810ebf77..7e19784194ce 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -787,13 +787,13 @@ func resize_bitmap_values(bitmap: BitMap, new_size: Vector2, flip_x: bool, flip_ return new_bitmap -func add_frame(frame: Frame, index: int) -> void: +func add_frames(new_frames: Array, indices: Array) -> void: # indices should be in ascending order assert(self == Global.current_project) # TODO: Remove (Things like calling project_frame/layer_added may need to do a check if its the current project if this fails) Global.canvas.selection.transform_content_confirm() selected_cels.clear() - frames.insert(index, frame) - # TODO: These may need an if self == Global.current_project depending on use - Global.animation_timeline.project_frame_added(index) + for i in range(new_frames.size()): + frames.insert(indices[i], new_frames[i]) + Global.animation_timeline.project_frame_added(indices[i]) # Update the frames and frame buttons: for f in range(frames.size()): Global.frame_ids.get_child(f).frame = f @@ -806,13 +806,15 @@ func add_frame(frame: Frame, index: int) -> void: layer_cel_container.get_child(f).button_setup() -func remove_frame(index: int) -> void: +func remove_frames(indices: Array) -> void: # indices should be in ascending order Global.canvas.selection.transform_content_confirm() selected_cels.clear() # TODO: If this messes up selection, would doing multiple here help? # TODO: Could one half of cel linking and animation tags be included in the add or remove_frame functions? (ie: removing works, but adding doesn't?) - frames.remove(index) - Global.animation_timeline.project_frame_removed(index) + for i in range(indices.size()): + # With each removed index, future indices need to be lowered, so subtract by i + frames.remove(indices[i] - i) + Global.animation_timeline.project_frame_removed(indices[i] - i) # Update the frames and frame buttons: for f in range(frames.size()): Global.frame_ids.get_child(f).frame = f @@ -896,7 +898,7 @@ func remove_layer(index: int) -> void: _toggle_layer_buttons_layers() -# from_indices and to_indicies should start from the lowest index, and go up +# from_indices and to_indicies should be in ascending order func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> void: # TODO: it may be good to do a test run with using loops of add/remove_layer instead of using move_layers # TODO: to_parents could just be a single for now, but then how should move_layers be named? diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 752436642282..e73e104b79ec 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -172,8 +172,8 @@ func add_frame() -> void: project.undo_redo.create_action("Add Frame") project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) - project.undo_redo.add_do_method(project, "add_frame", frame, frame_add_index) - project.undo_redo.add_undo_method(project, "remove_frame", frame_add_index) + project.undo_redo.add_do_method(project, "add_frames", [frame], [frame_add_index]) + project.undo_redo.add_undo_method(project, "remove_frames", [frame_add_index]) project.undo_redo.add_do_property(project, "layers", new_layers) project.undo_redo.add_undo_property(project, "layers", project.layers) project.undo_redo.add_do_property(project, "animation_tags", new_animation_tags) @@ -249,16 +249,14 @@ func delete_frames(frames := []) -> void: tag.to -= 1 frame_correction += 1 # Compensation for the next batch + var frame_refs := [] + for f in frames: + frame_refs.append(project.frames[f]) + project.undos += 1 project.undo_redo.create_action("Remove Frame") - var x := frames.size() - 1 - while x >= 0: - project.undo_redo.add_do_method(project, "remove_frame", frames[x]) - x -= 1 - for i in range(frames.size()): - project.undo_redo.add_undo_method( - project, "add_frame", project.frames[frames[i]], frames[i] - ) + project.undo_redo.add_do_method(project, "remove_frames", frames) + project.undo_redo.add_undo_method(project, "add_frames", frame_refs, frames) project.undo_redo.add_do_property(project, "layers", new_layers) project.undo_redo.add_undo_property(project, "layers", Global.current_project.layers) project.undo_redo.add_do_property(project, "animation_tags", new_animation_tags) From 2bca533e66bc4737a369b90e5bb2d00f9f01e1ee Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 1 Jul 2022 11:36:23 -0400 Subject: [PATCH 038/154] Refactored copy_frames in animation timeline --- src/UI/Timeline/AnimationTimeline.gd | 66 ++++++++++++---------------- 1 file changed, 29 insertions(+), 37 deletions(-) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index e73e104b79ec..02256d598497 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -267,7 +267,7 @@ func delete_frames(frames := []) -> void: project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.commit_action() - +# TODO: Is there any point in frame here being a func parameter? Same with _on_DeleteFrame_presssed above (and maybe more) func _on_CopyFrame_pressed(frame := -1) -> void: var frames := [] for cel in Global.current_project.selected_cels: @@ -277,20 +277,21 @@ func _on_CopyFrame_pressed(frame := -1) -> void: frames.sort() copy_frames(frames) -# TODO: Refactor copy_frames as well: + func copy_frames(frames := []) -> void: - # TODO: Work on this one (probably need a copy_to function on Cel classes) Global.canvas.selection.transform_content_confirm() + var project: Project = Global.current_project if frames.size() == 0: - frames.append(Global.current_project.current_frame) + frames.append(project.current_frame) - var new_frames := Global.current_project.frames.duplicate() - var new_layers: Array = Global.current_project.duplicate_layers() + var new_layers: Array = project.duplicate_layers() + var copied_frames := [] + var copied_indices := [] - var new_animation_tags := Global.current_project.animation_tags.duplicate() + var new_animation_tags := project.animation_tags.duplicate() # Loop through the tags to create new classes for them, so that they won't be the same - # as Global.current_project.animation_tags's classes. Needed for undo/redo to work properly. + # as project.animation_tags's classes. Needed for undo/redo to work properly. for i in new_animation_tags.size(): new_animation_tags[i] = AnimationTag.new( new_animation_tags[i].name, @@ -299,13 +300,16 @@ func copy_frames(frames := []) -> void: new_animation_tags[i].to ) - for frm in frames.size(): - var frame = frames[(frames.size() - 1) - frm] + for i in frames.size(): + var frame = frames[i] var new_frame := Frame.new() - new_frames.insert(frames[-1] + 1, new_frame) + copied_frames.append(new_frame) + # Indices should start after the last frame to copy, and go up for each iteration: + copied_indices.append(frames[-1] + 1 + i) - var prev_frame: Frame = Global.current_project.frames[frame] + var prev_frame: Frame = project.frames[frame] for cel in prev_frame.cels: # Copy every cel + # TODO: if Cel classes had a copy func, that would be quite useful here (and when copying layers) var sprite := Image.new() sprite.copy_from(cel.image) var sprite_texture := ImageTexture.new() @@ -327,33 +331,21 @@ func copy_frames(frames := []) -> void: tag.from += 1 tag.to += 1 - Global.current_project.undos += 1 - Global.current_project.undo_redo.create_action("Add Frame") - Global.current_project.undo_redo.add_do_method(Global, "undo_or_redo", false) - Global.current_project.undo_redo.add_undo_method(Global, "undo_or_redo", true) + project.undos += 1 + project.undo_redo.create_action("Add Frame") + project.undo_redo.add_do_method(Global, "undo_or_redo", false) + project.undo_redo.add_undo_method(Global, "undo_or_redo", true) + project.undo_redo.add_do_method(project, "add_frames", copied_frames, copied_indices) + project.undo_redo.add_undo_method(project, "remove_frames", copied_indices) - Global.current_project.undo_redo.add_do_property(Global.current_project, "frames", new_frames) - Global.current_project.undo_redo.add_do_property( - Global.current_project, "current_frame", frames[-1] + 1 - ) - Global.current_project.undo_redo.add_do_property(Global.current_project, "layers", new_layers) - Global.current_project.undo_redo.add_do_property( - Global.current_project, "animation_tags", new_animation_tags - ) + project.undo_redo.add_do_property(project, "current_frame", frames[-1] + 1) + project.undo_redo.add_do_property(project, "layers", new_layers) + project.undo_redo.add_do_property(project, "animation_tags", new_animation_tags) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "frames", Global.current_project.frames - ) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "current_frame", frames[-1] - ) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "layers", Global.current_project.layers - ) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "animation_tags", Global.current_project.animation_tags - ) - Global.current_project.undo_redo.commit_action() + project.undo_redo.add_undo_property(project, "current_frame", frames[-1]) + project.undo_redo.add_undo_property(project, "layers", project.layers) + project.undo_redo.add_undo_property(project, "animation_tags", project.animation_tags) + project.undo_redo.commit_action() func _on_FrameTagButton_pressed() -> void: From cda37f21b7e0722b994a3ebb3be8c71d7226043c Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 1 Jul 2022 12:09:26 -0400 Subject: [PATCH 039/154] added copy function to cel classes --- src/Classes/BaseCel.gd | 4 ++++ src/Classes/GroupCel.gd | 5 +++++ src/Classes/PixelCel.gd | 9 +++++++++ src/UI/Timeline/AnimationTimeline.gd | 13 ++++--------- 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/Classes/BaseCel.gd b/src/Classes/BaseCel.gd index 744863b08907..d4d0bc97ebce 100644 --- a/src/Classes/BaseCel.gd +++ b/src/Classes/BaseCel.gd @@ -25,5 +25,9 @@ func load_image_data_from_pxo(_file: File, _project_size: Vector2) -> void: return +func copy() -> BaseCel: + return null + + func create_cel_button() -> Button: return null diff --git a/src/Classes/GroupCel.gd b/src/Classes/GroupCel.gd index e03d6f971f7b..ae8b91f8f6bd 100644 --- a/src/Classes/GroupCel.gd +++ b/src/Classes/GroupCel.gd @@ -12,5 +12,10 @@ func get_image() -> Image: return Image.new() +func copy() -> BaseCel: + # Using get_script over the class name prevents a cyclic reference: + return get_script().new(opacity) + + func create_cel_button() -> Button: return load("res://src/UI/Timeline/GroupCelButton.tscn").instance() as Button diff --git a/src/Classes/PixelCel.gd b/src/Classes/PixelCel.gd index 24b70d073361..b4a6738f36b2 100644 --- a/src/Classes/PixelCel.gd +++ b/src/Classes/PixelCel.gd @@ -37,6 +37,15 @@ func load_image_data_from_pxo(file: File, project_size: Vector2) -> void: image_changed(image) +func copy() -> BaseCel: + var copy_image := Image.new() + copy_image.copy_from(image) + var copy_texture := ImageTexture.new() + copy_texture.create_from_image(copy_image, 0) + # Using get_script over the class name prevents a cyclic reference: + return get_script().new(copy_image, opacity, copy_texture) + + func create_cel_button() -> Button: var cel_button = load("res://src/UI/Timeline/PixelCelButton.tscn").instance() cel_button.get_child(0).texture = image_texture diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 02256d598497..c7fed6b67fd3 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -308,17 +308,12 @@ func copy_frames(frames := []) -> void: copied_indices.append(frames[-1] + 1 + i) var prev_frame: Frame = project.frames[frame] - for cel in prev_frame.cels: # Copy every cel - # TODO: if Cel classes had a copy func, that would be quite useful here (and when copying layers) - var sprite := Image.new() - sprite.copy_from(cel.image) - var sprite_texture := ImageTexture.new() - sprite_texture.create_from_image(sprite, 0) - new_frame.cels.append(PixelCel.new(sprite, cel.opacity, sprite_texture)) + for cel in prev_frame.cels: + new_frame.cels.append(cel.copy()) new_frame.duration = prev_frame.duration for l_i in range(new_layers.size()): - if new_layers[l_i].new_cels_linked: # If the link button is pressed + if new_layers[l_i].get("new_cels_linked"): # If the link button is pressed new_layers[l_i].linked_cels.append(new_frame) new_frame.cels[l_i].image = new_layers[l_i].linked_cels[0].cels[l_i].image new_frame.cels[l_i].image_texture = new_layers[l_i].linked_cels[0].cels[l_i].image_texture @@ -592,7 +587,7 @@ func _on_FuturePlacement_item_selected(index: int) -> void: func add_layer(is_new := true) -> void: # TODO: Duplicate functionality should probably be split out to allow for different layer types # TODO: Bug where adding a layer isn't selecting the new layer? - Global.canvas.selection.transform_content_confirm() + Global.canvas.selection.transform_content_confirm() # TODO: Figure out once and for all, do these belong here, or in the project reversable functions (where these will be called on undo as well) var l := PixelLayer.new() var project: Project = Global.current_project if !is_new: # Clone layer From 44a2bd8d538901ad339194a388dcbdb708898ce3 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 1 Jul 2022 14:21:39 -0400 Subject: [PATCH 040/154] added layer copy function --- src/Classes/BaseLayer.gd | 8 +++++ src/Classes/Project.gd | 12 ++----- src/UI/Timeline/AnimationTimeline.gd | 49 +++++++++++++--------------- src/UI/Timeline/PixelCelButton.gd | 2 +- 4 files changed, 33 insertions(+), 38 deletions(-) diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index 74d48c6e7a8f..dd911857002b 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -87,6 +87,14 @@ func deserialize(dict: Dictionary) -> void: parent = project.layers[dict.parent] +func copy() -> BaseLayer: + var copy = get_script().new() + copy.project = project + copy.index = index + copy.deserialize(serialize()) + return copy + + func get_default_name(number: int) -> String: return tr("Layer") + " %s" % number diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 7e19784194ce..f035db2bca85 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -605,20 +605,12 @@ func is_empty() -> bool: func duplicate_layers() -> Array: + # TODO: May want to test this a bit after refactor var new_layers: Array = layers.duplicate() # Loop through the array to create new classes for each element, so that they # won't be the same as the original array's classes. Needed for undo/redo to work properly. for i in new_layers.size(): - var layer_dict: Dictionary = new_layers[i].serialize() - #layer_dict.linked_cels = new_layers[i].linked_cels.duplicate() - match layer_dict.type: - Global.LayerTypes.PIXEL: - new_layers[i] = PixelLayer.new() - Global.LayerTypes.GROUP: - new_layers[i] = GroupLayer.new() - new_layers[i].index = i - new_layers[i].project = self - new_layers[i].deserialize(layer_dict) + new_layers[i] = new_layers[i].copy() return new_layers diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index c7fed6b67fd3..79dc9e1cd791 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -588,38 +588,34 @@ func add_layer(is_new := true) -> void: # TODO: Duplicate functionality should probably be split out to allow for different layer types # TODO: Bug where adding a layer isn't selecting the new layer? Global.canvas.selection.transform_content_confirm() # TODO: Figure out once and for all, do these belong here, or in the project reversable functions (where these will be called on undo as well) - var l := PixelLayer.new() var project: Project = Global.current_project - if !is_new: # Clone layer - l.name = ( - project.layers[project.current_layer].name - + " (" - + tr("copy") - + ")" - ) - - project.undos += 1 - project.undo_redo.create_action("Add Layer") + var l : BaseLayer + if is_new: + l = PixelLayer.new() + else: # Clone layer + l = project.layers[project.current_layer].copy() + l.name = str(project.layers[project.current_layer].name, " (", tr("copy"), ")") var cels := [] - for f in project.frames: - var new_layer := Image.new() if is_new: - new_layer.create( - project.size.x, - project.size.y, - false, - Image.FORMAT_RGBA8 - ) + var new_cel_image := Image.new() + new_cel_image.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8) + cels.append(PixelCel.new(new_cel_image, 1)) else: # Clone layer - new_layer.copy_from(f.cels[project.current_layer].image) + cels.append(f.cels[project.current_layer].copy()) - cels.append(PixelCel.new(new_layer, 1)) + # TODO: Copies don't have linked cels properly set up... - project.undo_redo.add_do_property(project, "current_layer", project.layers.size()) + project.undos += 1 + project.undo_redo.create_action("Add Layer") + if is_new: + project.undo_redo.add_do_property(project, "current_layer", project.layers.size()) + project.undo_redo.add_do_method(project, "add_layer", l, project.layers.size(), cels) + else: + project.undo_redo.add_do_property(project, "current_layer", project.current_layer + 1) + project.undo_redo.add_do_method(project, "add_layer", l, project.current_layer + 1, cels) project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) - project.undo_redo.add_do_method(project, "add_layer", l, project.layers.size(), cels) project.undo_redo.add_undo_method(project, "remove_layer", project.layers.size()) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.add_do_method(Global, "undo_or_redo", false) @@ -628,16 +624,15 @@ func add_layer(is_new := true) -> void: func add_group_layer(is_new := true) -> void: Global.canvas.selection.transform_content_confirm() - var l := GroupLayer.new() var project: Project = Global.current_project - project.undos += 1 - project.undo_redo.create_action("Add Layer") - + var l := GroupLayer.new() var cels := [] for f in project.frames: cels.append(GroupCel.new()) + project.undos += 1 + project.undo_redo.create_action("Add Layer") project.undo_redo.add_do_property(project, "current_layer", project.layers.size()) project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) project.undo_redo.add_do_method(project, "add_layer", l, project.layers.size(), cels) diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index 0dce3d218bb0..16a2a2d7a9f2 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -9,7 +9,7 @@ var image: Image onready var popup_menu: PopupMenu = $PopupMenu - +# TODO: The linked indicator seems to not get updated properly (adding a new linked cel won't show the indicator until another timeline change, same with linking an existing cel) func _ready() -> void: button_setup() From 3ed3dd2648329a7d72c6855a2eb09af8cb6f1657 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 1 Jul 2022 14:49:54 -0400 Subject: [PATCH 041/154] simplifed copy_frames a tiny bit --- src/UI/Timeline/AnimationTimeline.gd | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 79dc9e1cd791..190bc6f75fe7 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -287,7 +287,7 @@ func copy_frames(frames := []) -> void: var new_layers: Array = project.duplicate_layers() var copied_frames := [] - var copied_indices := [] + var copied_indices := range(frames[-1] + 1, frames[-1] + 1 + frames.size()) var new_animation_tags := project.animation_tags.duplicate() # Loop through the tags to create new classes for them, so that they won't be the same @@ -300,12 +300,9 @@ func copy_frames(frames := []) -> void: new_animation_tags[i].to ) - for i in frames.size(): - var frame = frames[i] + for frame in frames: var new_frame := Frame.new() copied_frames.append(new_frame) - # Indices should start after the last frame to copy, and go up for each iteration: - copied_indices.append(frames[-1] + 1 + i) var prev_frame: Frame = project.frames[frame] for cel in prev_frame.cels: From a196185bd90e4724f33f8c151bc868bad48dc935 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 1 Jul 2022 15:18:25 -0400 Subject: [PATCH 042/154] Updated TODO comments to categorize them and remove any that were already done --- src/Autoload/Export.gd | 2 +- src/Autoload/Global.gd | 8 +++--- src/Autoload/OpenSave.gd | 2 +- src/Classes/BaseCel.gd | 2 +- src/Classes/BaseLayer.gd | 6 ++-- src/Classes/GroupCel.gd | 2 +- src/Classes/PixelLayer.gd | 2 +- src/Classes/Project.gd | 34 ++++++++++------------ src/Main.gd | 4 +-- src/Tools/BaseTool.gd | 2 +- src/UI/Canvas/Canvas.gd | 6 ++-- src/UI/Timeline/AnimationTimeline.gd | 42 +++++++++++++--------------- src/UI/Timeline/FrameButton.gd | 2 +- src/UI/Timeline/GroupCelButton.gd | 4 +-- src/UI/Timeline/LayerButton.gd | 24 ++++++++-------- src/UI/Timeline/PixelCelButton.gd | 12 ++++---- 16 files changed, 74 insertions(+), 80 deletions(-) diff --git a/src/Autoload/Export.gd b/src/Autoload/Export.gd index 78c00b49c32c..5dccf0441ba1 100644 --- a/src/Autoload/Export.gd +++ b/src/Autoload/Export.gd @@ -380,7 +380,7 @@ func blend_layers(image: Image, frame: Frame, origin: Vector2 = Vector2(0, 0)) - image.lock() var layer_i := 0 for cel in frame.cels: - # TODO: Check + # TODO H: Check if Global.current_project.layers[layer_i].visible and not cel is GroupCel: var cel_image := Image.new() cel_image.copy_from(cel.image) diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index 8de597652556..281c6b5cbd3a 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -233,7 +233,7 @@ func undo_or_redo( "Unlink Cel" ] ): - # TODO: Check this: THIS IS PROBABLY WRONG (can't check if GROUP LAYER if INDEX is -1) + # TODO H: Check this: THIS IS PROBABLY WRONG (can't check if GROUP LAYER if INDEX is -1) if not current_project.layers[layer_index] is GroupLayer: if layer_index > -1 and frame_index > -1: canvas.update_texture(layer_index, frame_index, project) @@ -246,7 +246,7 @@ func undo_or_redo( if action_name == "Scale": for i in project.frames.size(): for j in project.layers.size(): - # TODO: ensure this is the correct cel type: + # TODO H: ensure this is the correct cel type: var current_cel: BaseCel = project.frames[i].cels[j] current_cel.image_texture.create_from_image(current_cel.image, 0) canvas.camera_zoom() @@ -255,7 +255,7 @@ func undo_or_redo( cursor_position_label.text = "[%s×%s]" % [project.size.x, project.size.y] elif "Frame" in action_name: - # TODO: Does what this comment says after the refacotr remain true? + # TODO R: Does what this comment says after the refacotr remain true? # This actually means that frames.size is one, but it hasn't been updated yet if (undo and project.frames.size() == 2) or project.frames.size() == 1: # Stop animating play_forward.pressed = false @@ -263,7 +263,7 @@ func undo_or_redo( animation_timer.stop() elif "Move Cels" == action_name: - # TODO: is this still required? + # TODO R: is this still required? project.frames = project.frames # to call frames_changed canvas.update() diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index b611d356e884..5069a8638167 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -126,7 +126,7 @@ func open_pxo_file(path: String, untitled_backup: bool = false, replace_empty: b if dict.error == OK and dict.result.has("fps"): Global.animation_timeline.fps_spinbox.value = dict.result.fps Global.animation_timeline.project_changed() - # TODO: Do these need to be here? + # TODO R: Do these need to be here? new_project.frames = new_project.frames # Just to call frames_changed new_project.layers = new_project.layers # Just to call layers_changed else: diff --git a/src/Classes/BaseCel.gd b/src/Classes/BaseCel.gd index d4d0bc97ebce..6ffc2c9d6d80 100644 --- a/src/Classes/BaseCel.gd +++ b/src/Classes/BaseCel.gd @@ -8,7 +8,7 @@ var opacity: float # Functions to override: -# TODO: Should this be the case? +# TODO H: Should this be the case? # Each Cel type should have a get_image function, which will either return # its image data for PixelCels, or return a render of that cel. It's meant # for read-only usage of image data from any type of cel diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index dd911857002b..5eb6c84a7279 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -18,7 +18,7 @@ func is_a_parent_of(layer: BaseLayer) -> bool: return is_a_parent_of(layer.parent) return false -# TODO: Consider going backwards in get_children functions, to allow breaking +# TODO L: Consider going backwards in get_children functions, to allow breaking func get_children_direct() -> Array: var children := [] for i in range(index): @@ -46,7 +46,7 @@ func is_expanded_in_hierarchy() -> bool: return parent.expanded and parent.is_expanded_in_hierarchy() return true -# TODO: Search for layer visbility/locked checks that should be changed to the hierarchy ones: +# TODO H: Search for layer visbility/locked checks that should be changed to the hierarchy ones: func is_visible_in_hierarchy() -> bool: if is_instance_valid(parent) and visible: return parent.is_visible_in_hierarchy() @@ -68,7 +68,7 @@ func get_hierarchy_depth() -> int: # Functions to Override: func serialize() -> Dictionary: - assert(index == project.layers.find(self)) # TODO: remove once sure index is synced properly + assert(index == project.layers.find(self)) # TODO H: remove once sure index is synced properly return { "name": name, "visible": visible, diff --git a/src/Classes/GroupCel.gd b/src/Classes/GroupCel.gd index ae8b91f8f6bd..0a54bc68908a 100644 --- a/src/Classes/GroupCel.gd +++ b/src/Classes/GroupCel.gd @@ -8,7 +8,7 @@ func _init(_opacity := 1.0) -> void: func get_image() -> Image: - # TODO: render the material as an image and return it + # TODO H: render the material as an image and return it return Image.new() diff --git a/src/Classes/PixelLayer.gd b/src/Classes/PixelLayer.gd index 0e245019eb76..60c3584a74cc 100644 --- a/src/Classes/PixelLayer.gd +++ b/src/Classes/PixelLayer.gd @@ -4,7 +4,7 @@ extends BaseLayer var new_cels_linked := false var linked_cels := [] # Array of Frames -# TODO: Should _init include project as a parameter? (for all Layer types) +# TODO H: Should _init include project as a parameter? (for all Layer types) func _init(_name := "") -> void: name = _name diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index f035db2bca85..b05f416df603 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -45,7 +45,7 @@ var file_format: int = Export.FileFormat.PNG var was_exported := false var export_overwrite := false -# TODO: These should be able to be removed.... +# TODO R: These should be able to be removed.... var frame_button_node = preload("res://src/UI/Timeline/FrameButton.tscn") var pixel_layer_button_node = preload("res://src/UI/Timeline/PixelLayerButton.tscn") var group_layer_button_node = preload("res://src/UI/Timeline/GroupLayerButton.tscn") @@ -403,7 +403,7 @@ func _size_changed(value: Vector2) -> void: func _frames_changed(value: Array) -> void: Global.canvas.selection.transform_content_confirm() frames = value -# selected_cels.clear() # TODO: Determine if this needs to be kept (If it is, selected cels needs to be intialized after creating project (ie: in Main), rather than here +# selected_cels.clear() # TODO R: Determine if this needs to be kept (If it is, selected cels needs to be intialized after creating project (ie: in Main), rather than here _set_timeline_first_and_last_frames() @@ -413,8 +413,8 @@ func _layers_changed(value: Array) -> void: Global.layers_changed_skip = false return -# selected_cels.clear() # TODO: Determine if this needs to be kept (If it is, selected cels needs to be intialized after creating project (ie: in Main), rather than here - # TODO: investigate wether these are still required: +# selected_cels.clear() # TODO R: Determine if this needs to be kept (If it is, selected cels needs to be intialized after creating project (ie: in Main), rather than here + # TODO R: investigate wether these are still required: # var layer_button = Global.layers_container.get_child( # Global.layers_container.get_child_count() - 1 - current_layer # ) @@ -467,7 +467,7 @@ func _frame_changed(value: int) -> void: ) if current_frame < frames.size(): - # TODO: Make this work with groups: + # TODO H: Make this work with groups: if not layers[current_layer] is GroupLayer: var cel_opacity: float = frames[current_frame].cels[current_layer].opacity Global.layer_opacity_slider.value = cel_opacity * 100 @@ -560,7 +560,7 @@ func _animation_tags_changed(value: Array) -> void: _set_timeline_first_and_last_frames() -# TODO: Is this really required in _frames_changed (or the add/remove frame funcs, seems to work fine without when playing anim) +# TODO R: Is this really required in _frames_changed (or the add/remove frame funcs, seems to work fine without when playing anim) func _set_timeline_first_and_last_frames() -> void: # This is useful in case tags get modified DURING the animation is playing # otherwise, this code is useless in this context, since these values are being set @@ -605,13 +605,12 @@ func is_empty() -> bool: func duplicate_layers() -> Array: - # TODO: May want to test this a bit after refactor + # TODO R: May want to test this a bit after refactor var new_layers: Array = layers.duplicate() # Loop through the array to create new classes for each element, so that they # won't be the same as the original array's classes. Needed for undo/redo to work properly. for i in new_layers.size(): new_layers[i] = new_layers[i].copy() - return new_layers @@ -780,7 +779,7 @@ func resize_bitmap_values(bitmap: BitMap, new_size: Vector2, flip_x: bool, flip_ func add_frames(new_frames: Array, indices: Array) -> void: # indices should be in ascending order - assert(self == Global.current_project) # TODO: Remove (Things like calling project_frame/layer_added may need to do a check if its the current project if this fails) + assert(self == Global.current_project) # TODO R: Remove (Things like calling project_frame/layer_added may need to do a check if its the current project if this fails) Global.canvas.selection.transform_content_confirm() selected_cels.clear() for i in range(new_frames.size()): @@ -801,8 +800,7 @@ func add_frames(new_frames: Array, indices: Array) -> void: # indices should be func remove_frames(indices: Array) -> void: # indices should be in ascending order Global.canvas.selection.transform_content_confirm() selected_cels.clear() - # TODO: If this messes up selection, would doing multiple here help? - # TODO: Could one half of cel linking and animation tags be included in the add or remove_frame functions? (ie: removing works, but adding doesn't?) + # TODO R: Could one half of cel linking and animation tags be included in the add or remove_frame functions? (ie: removing works, but adding doesn't?) for i in range(indices.size()): # With each removed index, future indices need to be lowered, so subtract by i frames.remove(indices[i] - i) @@ -852,14 +850,13 @@ func swap_frame(a_index: int, b_index: int) -> void: func add_layer(layer: BaseLayer, index: int, cels: Array) -> void: - assert(self == Global.current_project) # TODO: Remove (Things like calling project_frame/layer_added may need to do a check if its the current project if this fails) - # TODO: is Global.canvas.selection.transform_content_confirm() needed for layer changes (it wasn't used before I think) + assert(self == Global.current_project) # TODO R: Remove (Things like calling project_frame/layer_added may need to do a check if its the current project if this fails) selected_cels.clear() layers.insert(index, layer) for f in range(frames.size()): frames[f].cels.insert(index, cels[f]) layer.project = self - # TODO: Update layer index (and others, more efficient if add layer supports multiple) + # TODO R: Update layer index (and others, more efficient if add layer supports multiple) Global.animation_timeline.project_layer_added(index) # Update the layer indices and layer/cel buttons: for l in range(layers.size()): @@ -877,7 +874,7 @@ func remove_layer(index: int) -> void: layers.remove(index) for frame in frames: frame.cels.remove(index) - # TODO: Update layer index (and others, more efficient if remove layer supports multiple) + # TODO R: Update layer index (and others, more efficient if remove layer supports multiple) Global.animation_timeline.project_layer_removed(index) # Update the layer indices and layer/cel buttons: for l in range(layers.size()): @@ -892,8 +889,7 @@ func remove_layer(index: int) -> void: # from_indices and to_indicies should be in ascending order func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> void: - # TODO: it may be good to do a test run with using loops of add/remove_layer instead of using move_layers - # TODO: to_parents could just be a single for now, but then how should move_layers be named? + # TODO R: it may be good to do a test run with using add/remove_layers instead of using move_layers selected_cels.clear() var old_layers := layers.duplicate() var removed_cels := [] # Array of array of cels (an array for each layer removed) @@ -908,7 +904,7 @@ func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> v Global.animation_timeline.project_layer_removed(from_indices[i] - i) for i in range(to_indices.size()): layers.insert(to_indices[i], old_layers[from_indices[i]]) - layers[to_indices[i]].parent = to_parents[i] # TODO: it could be possible to do the to_parents when removing (previous loop), allowing this loop to be recombined with the next + layers[to_indices[i]].parent = to_parents[i] # TODO R: it could be possible to do the to_parents when removing (previous loop), allowing this loop to be recombined with the next for f in range(frames.size()): frames[f].cels.insert(to_indices[i], removed_cels[i][f]) for i in range(to_indices.size()): # Loop again (All parents must be set before adding the UI) @@ -926,7 +922,7 @@ func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> v func swap_layers() -> void: selected_cels.clear() - # TODO: Implement swap_layers + # TODO R: Implement swap_layers pass _toggle_layer_buttons_layers() diff --git a/src/Main.gd b/src/Main.gd index e3f0d93119a7..c45d221dc735 100644 --- a/src/Main.gd +++ b/src/Main.gd @@ -25,9 +25,9 @@ func _ready() -> void: Global.current_project.layers.append(PixelLayer.new()) Global.current_project.layers[0].project = Global.current_project Global.current_project.frames.append(Global.current_project.new_empty_frame()) - Global.animation_timeline.project_changed() + Global.animation_timeline.project_changed() # TODO R: would it be a good idea to remove this, and the intial buttons back into the timeiline scene? - # TODO: I Think this line should be safe to remove: (calling setter) + # TODO R: I Think this line should be safe to remove: (calling setter) # Global.current_project.layers = Global.current_project.layers Import.import_brushes(Global.directory_module.get_brushes_search_path_in_order()) diff --git a/src/Tools/BaseTool.gd b/src/Tools/BaseTool.gd index a439f6f29221..84aa3b722e1a 100644 --- a/src/Tools/BaseTool.gd +++ b/src/Tools/BaseTool.gd @@ -88,7 +88,7 @@ func _get_selected_draw_images() -> Array: # Array of Images var images := [] var project: Project = Global.current_project for cel_index in project.selected_cels: - # TODO: Check this: (BaseCel is fine because it asks can_layer_get_drawn) + # TODO H: Check this: (BaseCel is fine because it asks can_layer_get_drawn) var cel: BaseCel = project.frames[cel_index[0]].cels[cel_index[1]] if project.layers[cel_index[1]].can_layer_get_drawn(): images.append(cel.image) diff --git a/src/UI/Canvas/Canvas.gd b/src/UI/Canvas/Canvas.gd index 792e592e2b51..56645aeb4934 100644 --- a/src/UI/Canvas/Canvas.gd +++ b/src/UI/Canvas/Canvas.gd @@ -110,7 +110,7 @@ func update_texture(layer_i: int, frame_i := -1, project: Project = Global.curre frame_i = project.current_frame if frame_i < project.frames.size() and layer_i < project.layers.size(): - # TODO: make sure this is right: + # TODO H: make sure this is right: var current_cel: PixelCel = project.frames[frame_i].cels[layer_i] current_cel.image_texture.set_data(current_cel.image) @@ -128,11 +128,11 @@ func update_selected_cels_textures(project: Project = Global.current_project) -> var frame_index: int = cel_index[0] var layer_index: int = cel_index[1] if frame_index < project.frames.size() and layer_index < project.layers.size(): - # TODO: make sure this is right: + # TODO H: make sure this is right: var current_cel: PixelCel = project.frames[frame_index].cels[layer_index] current_cel.image_texture.set_data(current_cel.image) - # TODO: This wasn't working anymore, but is it even needed? (Same as above) + # TODO H: This wasn't working anymore, but is it even needed? (Same as above) # if project == Global.current_project: # var container_index = Global.frames_container.get_child_count() - 1 - layer_index # var layer_cel_container = Global.frames_container.get_child(container_index) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 190bc6f75fe7..e1f544168c0a 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -13,7 +13,7 @@ var past_above_canvas := true var future_above_canvas := true var frame_button_node = preload("res://src/UI/Timeline/FrameButton.tscn") -# TODO: May remove some of these: +# TODO R: May remove some of these: var pixel_layer_button_node = preload("res://src/UI/Timeline/PixelLayerButton.tscn") var group_layer_button_node = preload("res://src/UI/Timeline/GroupLayerButton.tscn") var pixel_cel_button_node = preload("res://src/UI/Timeline/PixelCelButton.tscn") @@ -43,7 +43,7 @@ func _ready() -> void: find_node("EndSpacer").size_flags_horizontal = SIZE_EXPAND_FILL timeline_scroll.size_flags_horizontal = SIZE_FILL -# TODO: See if these two should be kept or done another way: +# TODO L: See if these two should be kept or done another way: func _notification(what: int) -> void: if what == NOTIFICATION_DRAG_END: drag_highlight.hide() @@ -267,7 +267,7 @@ func delete_frames(frames := []) -> void: project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.commit_action() -# TODO: Is there any point in frame here being a func parameter? Same with _on_DeleteFrame_presssed above (and maybe more) +# TODO L: Is there any point in frame here being a func parameter? Same with _on_DeleteFrame_presssed above (and maybe more) func _on_CopyFrame_pressed(frame := -1) -> void: var frames := [] for cel in Global.current_project.selected_cels: @@ -345,7 +345,6 @@ func _on_FrameTagButton_pressed() -> void: func _on_MoveLeft_pressed() -> void: - # TODO: Do these var frame: int = Global.current_project.current_frame if frame == 0: return @@ -582,9 +581,8 @@ func _on_FuturePlacement_item_selected(index: int) -> void: func add_layer(is_new := true) -> void: - # TODO: Duplicate functionality should probably be split out to allow for different layer types - # TODO: Bug where adding a layer isn't selecting the new layer? - Global.canvas.selection.transform_content_confirm() # TODO: Figure out once and for all, do these belong here, or in the project reversable functions (where these will be called on undo as well) + # TODO R: Duplicate functionality should probably be split out to allow for different layer types + Global.canvas.selection.transform_content_confirm() # TODO R: Figure out once and for all, do these belong here, or in the project reversable functions (where these will be called on undo as well) var project: Project = Global.current_project var l : BaseLayer if is_new: @@ -602,7 +600,7 @@ func add_layer(is_new := true) -> void: else: # Clone layer cels.append(f.cels[project.current_layer].copy()) - # TODO: Copies don't have linked cels properly set up... + # TODO R: Copies don't have linked cels properly set up... project.undos += 1 project.undo_redo.create_action("Add Layer") @@ -661,7 +659,7 @@ func _on_RemoveLayer_pressed() -> void: project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.commit_action() -# TODO: Refactor this (maybe completely remove) +# TODO L: Refactor this (maybe completely remove) func change_layer_order(rate: int) -> void: var change = Global.current_project.current_layer + rate @@ -693,7 +691,7 @@ func change_layer_order(rate: int) -> void: Global.current_project.undo_redo.add_do_method(Global, "undo_or_redo", false) Global.current_project.undo_redo.commit_action() -# TODO: Does this need to be part of the refactor? +# TODO R: Does this need to be part of the refactor? func _on_MergeDownLayer_pressed() -> void: var new_layers: Array = Global.current_project.duplicate_layers() @@ -786,8 +784,8 @@ func _on_OnionSkinningSettings_popup_hide() -> void: func project_changed() -> void: - var project: Project = Global.current_project # TODO: maybe pass in instead? - # TODO: Could using queue_free rather than free (or remove and queue_free) actually cause bugs? + var project: Project = Global.current_project # TODO R: maybe pass in instead? + # TODO R: Could using queue_free rather than free (or remove and queue_free) actually cause bugs? for child in Global.layers_container.get_children(): child.queue_free() for child in Global.frame_ids.get_children(): @@ -803,12 +801,12 @@ func project_changed() -> void: Global.frame_ids.add_child(button) Global.frame_ids.move_child(button, f) - # TODO: Remove an inline what's needed here if this isn't used anywhere else: + # TODO R: Remove and inline what's needed here if this isn't used anywhere else: Global.current_project._update_animation_timeline_selection() func project_frame_added(frame: int) -> void: - var project: Project = Global.current_project # TODO: maybe pass in instead? + var project: Project = Global.current_project # TODO R: maybe pass in instead? var button: Button = frame_button_node.instance() button.frame = frame Global.frame_ids.add_child(button) @@ -832,17 +830,17 @@ func project_frame_removed(frame: int) -> void: func project_layer_added(layer: int) -> void: - var project: Project = Global.current_project # TODO: maybe pass in instead? - # TODO: should probably have a "layer" variable... (to many project.layers[layer])... + var project: Project = Global.current_project + # TODO R: should probably have a "layer" variable... (to many project.layers[layer])... # ...or refactor things so less of this code is needed here. - # TODO: Could this function be organized in a better way? + # TODO R: Could this function be organized in a better way? var layer_button: LayerButton if project.layers[layer] is PixelLayer: layer_button = pixel_layer_button_node.instance() elif project.layers[layer] is GroupLayer: layer_button = group_layer_button_node.instance() - layer_button.layer = layer # TODO: See if needed - if project.layers[layer].name == "": # TODO: This probably could be somewhere else... + layer_button.layer = layer # TODO R: See if needed + if project.layers[layer].name == "": # TODO R: This probably could be somewhere else... add_layer(s) in project? project.layers[layer].name = project.layers[layer].get_default_name(layer) Global.layers_container.add_child(layer_button) @@ -850,14 +848,14 @@ func project_layer_added(layer: int) -> void: Global.layers_container.move_child(layer_button, count - 1 - layer) var layer_cel_container := HBoxContainer.new() - # TODO: Is there any need for a name (and why is it LAYERSSS in one place, and FRAMESS in another?) + # TODO R: Is there any need for a name (and why is it LAYERSSS in one place, and FRAMESS in another?) layer_cel_container.name = "LAYERSSS " + str(layer) Global.frames_container.add_child(layer_cel_container) Global.frames_container.move_child(layer_cel_container, count - 1 - layer) for f in range(project.frames.size()): var cel_button = project.frames[f].cels[layer].create_cel_button() cel_button.frame = f - cel_button.layer = layer# - 1 # TODO: See if needed + cel_button.layer = layer# - 1 # TODO R: See if needed layer_cel_container.add_child(cel_button) layer_button.visible = Global.current_project.layers[layer].is_expanded_in_hierarchy() @@ -877,7 +875,7 @@ func project_cel_added(frame: int, layer: int) -> void: var cel_button = Global.current_project.frames[frame].cels[layer].create_cel_button() cel_button.frame = frame cel_button.layer = layer - # TODO: Do we need stuff like this for selection? + # TODO R: Do we need stuff like this for selection? # cel_button.pressed = Global.current_project.selected_cels.has([frame, layer]) container.add_child(cel_button) container.move_child(cel_button, frame) diff --git a/src/UI/Timeline/FrameButton.gd b/src/UI/Timeline/FrameButton.gd index 43b1d2543684..45ef298f15e7 100644 --- a/src/UI/Timeline/FrameButton.gd +++ b/src/UI/Timeline/FrameButton.gd @@ -84,7 +84,7 @@ func _on_PopupMenu_id_pressed(id: int) -> void: frame_properties.set_frame_label(frame) frame_properties.set_frame_dur(Global.current_project.frames[frame].duration) -# TODO: Remove this later... (or simplify?) + func change_frame_order(rate: int) -> void: var change = frame + rate var project = Global.current_project diff --git a/src/UI/Timeline/GroupCelButton.gd b/src/UI/Timeline/GroupCelButton.gd index 6b91d392918f..2b811b94f221 100644 --- a/src/UI/Timeline/GroupCelButton.gd +++ b/src/UI/Timeline/GroupCelButton.gd @@ -31,7 +31,7 @@ func _on_GroupCelButton_resized() -> void: func _pressed(): - # TODO: PixelCelButton could just use the func instead of signal too + # TODO L: PixelCelButton could just use the func instead of signal too - # TODO: Some of the funtionality from PixelCelButton needs to be moved over + # TODO H: Some of the funtionality from PixelCelButton needs to be moved over pass diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index 7e09ec0217de..9987e9997c10 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -74,7 +74,8 @@ func _update_buttons() -> void: func _update_buttons_all_layers() -> void: - # TODO: would it be better to have specified range? (if so rename all_layers to for_layers) + # TODO R: would it be better to have specified range? (if so rename all_layers to for_layers) + # Maybe update_buttons_recursive (including children) is all we need? for layer_button in Global.layers_container.get_children(): layer_button._update_buttons() var expanded = Global.current_project.layers[layer_button.layer].is_expanded_in_hierarchy() @@ -145,7 +146,7 @@ func _save_layer_name(new_name: String) -> void: func _on_ExpandButton_pressed(): - # TODO: What should happen when the current_layer or selected_cels are children of a layer you collapse? + # TODO L: What should happen when the current_layer or selected_cels are children of a layer you collapse? # Should the current_layer/selection move to ones aren't collapsed? Maybe add to github list of possible later changes Global.current_project.layers[layer].expanded = !Global.current_project.layers[layer].expanded _update_buttons_all_layers() @@ -250,17 +251,17 @@ func can_drop_data(_pos, data) -> bool: func drop_data(_pos, data) -> void: var drop_layer: int = data[1] - var project = Global.current_project # TODO: perhaps having a project variable for the enitre class would be nice (also for cel/frame buttons) + var project = Global.current_project # TODO L: perhaps having a project variable for the enitre class would be nice (also for cel/frame buttons) project.undo_redo.create_action("Change Layer Order") var new_layers: Array = project.layers.duplicate() var temp: BaseLayer = new_layers[layer] - if Input.is_action_pressed("ctrl"): # Swap layers # TODO Need to check when swapping is allowed - pass # TODO: Figure out swapping + if Input.is_action_pressed("ctrl"): # Swap layers + pass # TODO R: Figure out swapping # new_layers[layer] = new_layers[drop_layer] # new_layers[drop_layer] = temp # -# # TODO: Make sure to swap parents too +# # TODO R: Make sure to swap parents too # # for f in Global.current_project.frames: # var new_cels: Array = f.cels.duplicate() @@ -269,10 +270,10 @@ func drop_data(_pos, data) -> void: # new_cels[drop_layer] = temp_canvas # project.undo_redo.add_do_property(f, "cels", new_cels) # project.undo_redo.add_undo_property(f, "cels", f.cels) - # TODO: Having "SourceLayers/OldLayers (that you don't change) and new_layers would make this less confusing + # TODO R: Having "SourceLayers/OldLayers (that you don't change) and new_layers would make this less confusing else: # from_indices should be in order of the layer indices, starting from the lowest - # TODO: can this code be made easier to read? + # TODO R: can this code be made easier to read? var from_indices := [] for c in new_layers[drop_layer].get_children_recursive(): from_indices.append(c.index) @@ -290,7 +291,7 @@ func drop_data(_pos, data) -> void: else: # Top or bottom region? if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): - to_index = layer + 1 # TODO Is this right? + to_index = layer + 1 to_parent = new_layers[layer].parent else: # Place under the layer, if it has children, place after its lowest child @@ -300,7 +301,7 @@ func drop_data(_pos, data) -> void: if new_layers[layer].is_a_parent_of(new_layers[drop_layer]): to_index += from_indices.size() else: - to_index = layer # TODO Is this right? + to_index = layer to_parent = new_layers[layer].parent if drop_layer < layer: @@ -321,12 +322,11 @@ func drop_data(_pos, data) -> void: project.undo_redo.add_undo_method( project, "move_layers", to_indices, from_indices, from_parents ) - if project.current_layer == drop_layer: # TODO: This doesn't work... + if project.current_layer == drop_layer: # TODO R: This doesn't work... (Actually I think this was fixed?, should match FrameButton) project.undo_redo.add_do_property(project, "current_layer", layer) else: project.undo_redo.add_do_property(project, "current_layer", project.current_layer) project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) - # TODO: undo_or_redo is at end here, but earlier in others, does it matter which order? project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.commit_action() diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index 16a2a2d7a9f2..2d441e6801ff 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -9,7 +9,7 @@ var image: Image onready var popup_menu: PopupMenu = $PopupMenu -# TODO: The linked indicator seems to not get updated properly (adding a new linked cel won't show the indicator until another timeline change, same with linking an existing cel) +# TODO R: The linked indicator seems to not get updated properly (adding a new linked cel won't show the indicator until another timeline change, same with linking an existing cel) func _ready() -> void: button_setup() @@ -103,17 +103,17 @@ func _on_PopupMenu_id_pressed(id: int) -> void: _delete_cel_content() MenuOptions.LINK: - # TODO: See if there is any refactoring to do here: + # TODO R: See if there is any refactoring to do here: var f: Frame = Global.current_project.frames[frame] var cel_index: int = Global.current_project.layers[layer].linked_cels.find(f) var new_layers: Array = Global.current_project.duplicate_layers() var new_cels: Array = f.cels.duplicate() for i in new_cels.size(): - # TODO: This doesn't work (currently replaces ALL cels on the frame) + # TODO H: This doesn't work (currently replaces ALL cels on the frame) new_cels[i] = PixelCel.new( new_cels[i].image, new_cels[i].opacity, new_cels[i].image_texture ) -# TODO: Make sure all this stuff still works after refactor: +# TODO R: Make sure all this stuff still works after refactor: if popup_menu.get_item_metadata(MenuOptions.LINK) == "Unlink Cel": new_layers[layer].linked_cels.remove(cel_index) var sprite := Image.new() @@ -197,7 +197,7 @@ func can_drop_data(_pos, data) -> bool: if typeof(data) == TYPE_ARRAY and data[0] == "PixelCel": var drag_frame = data[1] var drag_layer = data[2] - # TODO: Is this part really right? Should't it only matter if they're linked, and we're changing layers? + # TODO L: Is this part really right? Should't it only matter if they're linked, and we're changing layers? # It would need to add linked cel logic to project move/swap_cel though # If the cel we're dragging or the cel we are targeting are linked, don't allow dragging if not ( @@ -207,7 +207,7 @@ func can_drop_data(_pos, data) -> bool: in Global.current_project.layers[drag_layer].linked_cels ) ): - # TODO: This may be able to be combined with the previous condition depending on the the last TODO + # TODO L: This may be able to be combined with the previous condition depending on the the last TODO if not (drag_frame == frame and drag_layer == layer): var region: Rect2 if Input.is_action_pressed("ctrl") or layer != drag_layer: # Swap cels From 1e018ba339556bc288586edc5543fa358a20aba2 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 1 Jul 2022 16:24:36 -0400 Subject: [PATCH 043/154] Turned Project.add/remove_layer into Project.add/remove_layers (multiple support), not yet tested --- src/Classes/Project.gd | 27 ++++++++++++++------------- src/UI/Timeline/AnimationTimeline.gd | 14 +++++++------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index b05f416df603..840388c737b5 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -849,15 +849,15 @@ func swap_frame(a_index: int, b_index: int) -> void: Global.animation_timeline.project_frame_added(b_index) -func add_layer(layer: BaseLayer, index: int, cels: Array) -> void: +func add_layers(new_layers: Array, indices: Array, cels: Array) -> void: # cels is 2d Array of cels assert(self == Global.current_project) # TODO R: Remove (Things like calling project_frame/layer_added may need to do a check if its the current project if this fails) selected_cels.clear() - layers.insert(index, layer) - for f in range(frames.size()): - frames[f].cels.insert(index, cels[f]) - layer.project = self - # TODO R: Update layer index (and others, more efficient if add layer supports multiple) - Global.animation_timeline.project_layer_added(index) + for i in range(indices.size()): + layers.insert(indices[i], new_layers[i]) + for f in range(frames.size()): + frames[f].cels.insert(indices[i], cels[i][f]) + new_layers[i].project = self + Global.animation_timeline.project_layer_added(indices[i]) # Update the layer indices and layer/cel buttons: for l in range(layers.size()): layers[l].index = l @@ -869,13 +869,14 @@ func add_layer(layer: BaseLayer, index: int, cels: Array) -> void: _toggle_layer_buttons_layers() -func remove_layer(index: int) -> void: +func remove_layers(indices: Array) -> void: selected_cels.clear() - layers.remove(index) - for frame in frames: - frame.cels.remove(index) - # TODO R: Update layer index (and others, more efficient if remove layer supports multiple) - Global.animation_timeline.project_layer_removed(index) + for i in range(indices.size()): + # With each removed index, future indices need to be lowered, so subtract by i + layers.remove(indices[i] - i) + for frame in frames: + frame.cels.remove(indices[i] - i) + Global.animation_timeline.project_layer_removed(indices[i] - i) # Update the layer indices and layer/cel buttons: for l in range(layers.size()): layers[l].index = l diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index e1f544168c0a..aee508d86c2f 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -606,12 +606,12 @@ func add_layer(is_new := true) -> void: project.undo_redo.create_action("Add Layer") if is_new: project.undo_redo.add_do_property(project, "current_layer", project.layers.size()) - project.undo_redo.add_do_method(project, "add_layer", l, project.layers.size(), cels) + project.undo_redo.add_do_method(project, "add_layers", [l], [project.layers.size()], [cels]) else: project.undo_redo.add_do_property(project, "current_layer", project.current_layer + 1) - project.undo_redo.add_do_method(project, "add_layer", l, project.current_layer + 1, cels) + project.undo_redo.add_do_method(project, "add_layers", [l], [project.current_layer + 1], [cels]) project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) - project.undo_redo.add_undo_method(project, "remove_layer", project.layers.size()) + project.undo_redo.add_undo_method(project, "remove_layers", [project.layers.size()]) # TODO R: this is the wrong index for a duplicated layer project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.commit_action() @@ -630,8 +630,8 @@ func add_group_layer(is_new := true) -> void: project.undo_redo.create_action("Add Layer") project.undo_redo.add_do_property(project, "current_layer", project.layers.size()) project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) - project.undo_redo.add_do_method(project, "add_layer", l, project.layers.size(), cels) - project.undo_redo.add_undo_method(project, "remove_layer", project.layers.size()) + project.undo_redo.add_do_method(project, "add_layers", [l], [project.layers.size()], [cels]) + project.undo_redo.add_undo_method(project, "remove_layers", [project.layers.size()]) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.commit_action() @@ -651,9 +651,9 @@ func _on_RemoveLayer_pressed() -> void: project.undo_redo.add_do_property(project, "current_layer", max(project.current_layer - 1, 0)) project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) - project.undo_redo.add_do_method(project, "remove_layer", project.current_layer) + project.undo_redo.add_do_method(project, "remove_layers", [project.current_layer]) project.undo_redo.add_undo_method( - project, "add_layer", project.layers[project.current_layer], project.current_layer, cels + project, "add_layers", [project.layers[project.current_layer]], [project.current_layer], [cels] ) project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) From 53128f74b19aa0ec7d189c03673281def25f12e0 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 1 Jul 2022 17:38:45 -0400 Subject: [PATCH 044/154] Seperated the layer cloning functionality in timeline's add_layer to its own function, since they're only used by one button, renamed to _on_Button_pressed naming scheme, added children support to the delete layer button --- src/Classes/Project.gd | 1 + src/UI/Timeline/AnimationTimeline.gd | 84 +++++++++++++++----------- src/UI/Timeline/AnimationTimeline.tscn | 7 ++- 3 files changed, 55 insertions(+), 37 deletions(-) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 840388c737b5..55a5313bf28c 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -606,6 +606,7 @@ func is_empty() -> bool: func duplicate_layers() -> Array: # TODO R: May want to test this a bit after refactor + # TODO H: When duplicating the layers, parent references would be using the old layers now, this will probably cause bugs var new_layers: Array = layers.duplicate() # Loop through the array to create new classes for each element, so that they # won't be the same as the original array's classes. Needed for undo/redo to work properly. diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index aee508d86c2f..692117c535d1 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -580,47 +580,33 @@ func _on_FuturePlacement_item_selected(index: int) -> void: # Layer buttons -func add_layer(is_new := true) -> void: +func _on_AddLayer_pressed() -> void: # TODO R: Duplicate functionality should probably be split out to allow for different layer types Global.canvas.selection.transform_content_confirm() # TODO R: Figure out once and for all, do these belong here, or in the project reversable functions (where these will be called on undo as well) var project: Project = Global.current_project - var l : BaseLayer - if is_new: - l = PixelLayer.new() - else: # Clone layer - l = project.layers[project.current_layer].copy() - l.name = str(project.layers[project.current_layer].name, " (", tr("copy"), ")") + var l := PixelLayer.new() var cels := [] for f in project.frames: - if is_new: - var new_cel_image := Image.new() - new_cel_image.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8) - cels.append(PixelCel.new(new_cel_image, 1)) - else: # Clone layer - cels.append(f.cels[project.current_layer].copy()) - - # TODO R: Copies don't have linked cels properly set up... + var new_cel_image := Image.new() + new_cel_image.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8) + cels.append(PixelCel.new(new_cel_image, 1)) project.undos += 1 project.undo_redo.create_action("Add Layer") - if is_new: - project.undo_redo.add_do_property(project, "current_layer", project.layers.size()) - project.undo_redo.add_do_method(project, "add_layers", [l], [project.layers.size()], [cels]) - else: - project.undo_redo.add_do_property(project, "current_layer", project.current_layer + 1) - project.undo_redo.add_do_method(project, "add_layers", [l], [project.current_layer + 1], [cels]) + project.undo_redo.add_do_property(project, "current_layer", project.layers.size()) project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) - project.undo_redo.add_undo_method(project, "remove_layers", [project.layers.size()]) # TODO R: this is the wrong index for a duplicated layer - project.undo_redo.add_undo_method(Global, "undo_or_redo", true) + project.undo_redo.add_do_method(project, "add_layers", [l], [project.layers.size()], [cels]) + project.undo_redo.add_undo_method(project, "remove_layers", [project.layers.size()]) project.undo_redo.add_do_method(Global, "undo_or_redo", false) + project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.commit_action() -func add_group_layer(is_new := true) -> void: +func _on_AddGroup_pressed() -> void: Global.canvas.selection.transform_content_confirm() - var project: Project = Global.current_project + var l := GroupLayer.new() var cels := [] for f in project.frames: @@ -632,8 +618,32 @@ func add_group_layer(is_new := true) -> void: project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) project.undo_redo.add_do_method(project, "add_layers", [l], [project.layers.size()], [cels]) project.undo_redo.add_undo_method(project, "remove_layers", [project.layers.size()]) + project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) + project.undo_redo.commit_action() + + +func _on_CloneLayer_pressed() -> void: + # TODO L: Multiple layer support here would be nice + Global.canvas.selection.transform_content_confirm() + + var project: Project = Global.current_project + var l: BaseLayer = project.layers[project.current_layer].copy() + l.name = str(project.layers[project.current_layer].name, " (", tr("copy"), ")") + var cels := [] + for f in project.frames: + cels.append(f.cels[project.current_layer].copy()) + + # TODO R: Copies don't have linked cels properly set up... + + project.undos += 1 + project.undo_redo.create_action("Add Layer") + project.undo_redo.add_do_property(project, "current_layer", project.current_layer + 1) + project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) + project.undo_redo.add_do_method(project, "add_layers", [l], [project.current_layer + 1], [cels]) + project.undo_redo.add_undo_method(project, "remove_layers", [project.current_layer + 1]) project.undo_redo.add_do_method(Global, "undo_or_redo", false) + project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.commit_action() @@ -642,19 +652,25 @@ func _on_RemoveLayer_pressed() -> void: if project.layers.size() == 1: return - project.undos += 1 - project.undo_redo.create_action("Remove Layer") + var layers : Array = project.layers[project.current_layer].get_children_recursive() + layers.append(project.layers[project.current_layer]) + var indices := [] + for l in layers: + indices.append(l.index) var cels := [] - for f in project.frames: - cels.append(f.cels[project.current_layer]) + for l in layers: + cels.append([]) + for f in project.frames: + cels[-1].append(f.cels[l.index]) - project.undo_redo.add_do_property(project, "current_layer", max(project.current_layer - 1, 0)) + project.undos += 1 + project.undo_redo.create_action("Remove Layer") + # TODO R: what should be the new current layer? + project.undo_redo.add_do_property(project, "current_layer", max(indices[0] - 1, 0)) project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) - project.undo_redo.add_do_method(project, "remove_layers", [project.current_layer]) - project.undo_redo.add_undo_method( - project, "add_layers", [project.layers[project.current_layer]], [project.current_layer], [cels] - ) + project.undo_redo.add_do_method(project, "remove_layers", indices) + project.undo_redo.add_undo_method(project, "add_layers", layers, indices, cels) project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.commit_action() diff --git a/src/UI/Timeline/AnimationTimeline.tscn b/src/UI/Timeline/AnimationTimeline.tscn index 64c9491865ef..f6f9e253d78d 100644 --- a/src/UI/Timeline/AnimationTimeline.tscn +++ b/src/UI/Timeline/AnimationTimeline.tscn @@ -173,6 +173,7 @@ margin_right = 53.0 margin_bottom = 22.0 rect_min_size = Vector2( 22, 22 ) hint_tooltip = "Create a new group layer" +focus_mode = 0 mouse_default_cursor_shape = 2 [node name="TextureRect" type="TextureRect" parent="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/AddGroup"] @@ -1037,12 +1038,12 @@ color = Color( 0, 0.741176, 1, 0.501961 ) [connection signal="item_rect_changed" from="." to="." method="_on_AnimationTimeline_item_rect_changed"] [connection signal="item_rect_changed" from="ScrollContainer/TimelineContainer" to="." method="_on_TimelineContainer_item_rect_changed"] -[connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/AddLayer" to="." method="add_layer" binds= [ true ]] -[connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/AddGroup" to="." method="add_group_layer" binds= [ true ]] +[connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/AddLayer" to="." method="_on_AddLayer_pressed"] +[connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/AddGroup" to="." method="_on_AddGroup_pressed"] [connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/RemoveLayer" to="." method="_on_RemoveLayer_pressed"] [connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/MoveUpLayer" to="." method="change_layer_order" binds= [ 1 ]] [connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/MoveDownLayer" to="." method="change_layer_order" binds= [ -1 ]] -[connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/CloneLayer" to="." method="add_layer" binds= [ false ]] +[connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/CloneLayer" to="." method="_on_CloneLayer_pressed"] [connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/MergeDownLayer" to="." method="_on_MergeDownLayer_pressed"] [connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/AddFrame" to="." method="add_frame"] [connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/DeleteFrame" to="." method="_on_DeleteFrame_pressed"] From 4604c4c039e68e562547da9f58cbac2215473318 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 2 Jul 2022 16:47:46 -0400 Subject: [PATCH 045/154] some TODOs --- src/Autoload/Global.gd | 2 +- src/Classes/Project.gd | 56 ++++++++++++++++++++++------ src/UI/Timeline/AnimationTimeline.gd | 7 +--- src/UI/Timeline/LayerButton.gd | 2 +- 4 files changed, 48 insertions(+), 19 deletions(-) diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index 281c6b5cbd3a..5654e19295ac 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -255,7 +255,7 @@ func undo_or_redo( cursor_position_label.text = "[%s×%s]" % [project.size.x, project.size.y] elif "Frame" in action_name: - # TODO R: Does what this comment says after the refacotr remain true? + # TODO R: Does what this comment says after the refacotr remain true? (Perhaps this should be moved to move_frame?) # This actually means that frames.size is one, but it hasn't been updated yet if (undo and project.frames.size() == 2) or project.frames.size() == 1: # Stop animating play_forward.pressed = false diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 55a5313bf28c..59282d521f6f 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -45,13 +45,7 @@ var file_format: int = Export.FileFormat.PNG var was_exported := false var export_overwrite := false -# TODO R: These should be able to be removed.... -var frame_button_node = preload("res://src/UI/Timeline/FrameButton.tscn") -var pixel_layer_button_node = preload("res://src/UI/Timeline/PixelLayerButton.tscn") -var group_layer_button_node = preload("res://src/UI/Timeline/GroupLayerButton.tscn") -var pixel_cel_button_node = preload("res://src/UI/Timeline/PixelCelButton.tscn") -var group_cel_button_node = preload("res://src/UI/Timeline/GroupCelButton.tscn") -# ... up to this: +# TODO L: Perhaps animation_tags could get a similar refactoring (In a later PR) var animation_tag_node = preload("res://src/UI/Timeline/AnimationTagUI.tscn") @@ -460,6 +454,7 @@ func _frame_changed(value: int) -> void: var cel_button = container.get_child(frame) cel_button.pressed = true + # TODO R: When starting up, with only one frame, these aren't getting called: Global.disable_button(Global.remove_frame_button, frames.size() == 1) Global.disable_button(Global.move_left_frame_button, frames.size() == 1 or current_frame == 0) Global.disable_button( @@ -822,7 +817,7 @@ func move_frame(from_index: int, to_index: int) -> void: Global.canvas.selection.transform_content_confirm() selected_cels.clear() var frame = frames[from_index] - frames.remove(from_index) + frames.remove(from_index) # TODO: Maybe the insert(pop_at) trick will work here? Global.animation_timeline.project_frame_removed(from_index) frames.insert(to_index, frame) Global.animation_timeline.project_frame_added(to_index) @@ -893,7 +888,7 @@ func remove_layers(indices: Array) -> void: func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> void: # TODO R: it may be good to do a test run with using add/remove_layers instead of using move_layers selected_cels.clear() - var old_layers := layers.duplicate() + var old_layers := layers.duplicate() # TODO R: Could maybe change to just empty layers array, using append(pop_at) trick like in swap_layers var removed_cels := [] # Array of array of cels (an array for each layer removed) for i in range(from_indices.size()): @@ -922,10 +917,47 @@ func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> v _toggle_layer_buttons_layers() -func swap_layers() -> void: +func swap_layers(a_indices: Array, a_parents: Array, b_indices: Array, b_parents: Array) -> void: selected_cels.clear() - # TODO R: Implement swap_layers - pass + + var a_layers := [] + var b_layers := [] + + # TODO R: With these inputs, this probably isn't reversable if multiple layer suppport is added with a split. + + # THIS IS PROBABLY NOT NEEDED (Combined below with append + pop_at to move them to these arrays) +# for l in a_indices: +# a_layers.append(layers[l]) +# for l in b_indices: +# b_layers.append(layers[l]) + + # remove a_indices from layers, while adding to a_layers + # remove b_indices (+ a_indicies.size() if b_indices > a_indices) Ifrom layers, while adding to b_layers + + # TODO R: Got to consider which of a_indices or b_indices is higher here, probably + a_indicies.size() if b_indices > a_indices) + for i in range(a_indices.size()): +# layers.remove(a_indices[i] + i) + a_layers.append(layers.pop_at(a_indices[i] + i)) + Global.animation_timeline.project_layer_removed(a_indices[i] + i) + for i in range(b_indices.size()): +# layers.remove(b_indices[i] + i) + b_layers.append(layers.pop_at(b_indices[i] + i)) + Global.animation_timeline.project_layer_removed(b_indices[i] + i) + + # TODO R: What about if one is higher thant he other? + # add b_layers to a_indices + # add a_layers to b_indices + + # TODO R: Do something about the parents... + + # Update the layer indices and layer/cel buttons: + for l in range(layers.size()): + layers[l].index = l + Global.layers_container.get_child(layers.size() - 1 - l).layer = l + var layer_cel_container = Global.frames_container.get_child(layers.size() - 1 - l) + for f in range(frames.size()): + layer_cel_container.get_child(f).layer = l + layer_cel_container.get_child(f).button_setup() _toggle_layer_buttons_layers() diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 692117c535d1..3ca037e2cb3e 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -16,8 +16,6 @@ var frame_button_node = preload("res://src/UI/Timeline/FrameButton.tscn") # TODO R: May remove some of these: var pixel_layer_button_node = preload("res://src/UI/Timeline/PixelLayerButton.tscn") var group_layer_button_node = preload("res://src/UI/Timeline/GroupLayerButton.tscn") -var pixel_cel_button_node = preload("res://src/UI/Timeline/PixelCelButton.tscn") -var group_cel_button_node = preload("res://src/UI/Timeline/GroupCelButton.tscn") onready var old_scroll: int = 0 # The previous scroll state of $ScrollContainer onready var tag_spacer = find_node("TagSpacer") @@ -194,6 +192,7 @@ func _on_DeleteFrame_pressed(frame := -1) -> void: func delete_frames(frames := []) -> void: + # TODO R: If there is mulitple frames, it is currently possible to select and delete them all var project: Project = Global.current_project if project.frames.size() == 1: return @@ -581,7 +580,6 @@ func _on_FuturePlacement_item_selected(index: int) -> void: func _on_AddLayer_pressed() -> void: - # TODO R: Duplicate functionality should probably be split out to allow for different layer types Global.canvas.selection.transform_content_confirm() # TODO R: Figure out once and for all, do these belong here, or in the project reversable functions (where these will be called on undo as well) var project: Project = Global.current_project @@ -648,6 +646,7 @@ func _on_CloneLayer_pressed() -> void: func _on_RemoveLayer_pressed() -> void: + # TODO R: It is currently possible to delete all layers (by having all layers in a group and deleting the group) var project: Project = Global.current_project if project.layers.size() == 1: return @@ -891,8 +890,6 @@ func project_cel_added(frame: int, layer: int) -> void: var cel_button = Global.current_project.frames[frame].cels[layer].create_cel_button() cel_button.frame = frame cel_button.layer = layer - # TODO R: Do we need stuff like this for selection? -# cel_button.pressed = Global.current_project.selected_cels.has([frame, layer]) container.add_child(cel_button) container.move_child(cel_button, frame) diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index 9987e9997c10..2ca6290d6407 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -322,7 +322,7 @@ func drop_data(_pos, data) -> void: project.undo_redo.add_undo_method( project, "move_layers", to_indices, from_indices, from_parents ) - if project.current_layer == drop_layer: # TODO R: This doesn't work... (Actually I think this was fixed?, should match FrameButton) + if project.current_layer == drop_layer: project.undo_redo.add_do_property(project, "current_layer", layer) else: project.undo_redo.add_do_property(project, "current_layer", project.current_layer) From 2e6f71f71f8470def84e258583afa03fcca6f2bc Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 7 Jul 2022 13:03:48 -0400 Subject: [PATCH 046/154] Added layer swapping --- src/Classes/BaseLayer.gd | 3 + src/Classes/Project.gd | 65 ++++++++--------- src/UI/Timeline/AnimationTimeline.gd | 1 + src/UI/Timeline/GroupCelButton.gd | 2 - src/UI/Timeline/LayerButton.gd | 100 ++++++++++++++++----------- 5 files changed, 99 insertions(+), 72 deletions(-) diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index 5eb6c84a7279..668524889b5c 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -7,6 +7,9 @@ var visible := true var locked := false var blend_mode := 0 var parent: BaseLayer +# TODO H: Memory seems to not be freed when closing a project. I suspect this new project ref to +# be the reason (in Project.remove simply removing the project from the Global.projects array +# can't auto free it because there's still refences to it, in the layers): var project var index: int diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 59282d521f6f..85f4b5ea6dc7 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -889,15 +889,14 @@ func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> v # TODO R: it may be good to do a test run with using add/remove_layers instead of using move_layers selected_cels.clear() var old_layers := layers.duplicate() # TODO R: Could maybe change to just empty layers array, using append(pop_at) trick like in swap_layers - var removed_cels := [] # Array of array of cels (an array for each layer removed) + var removed_cels := [] # 2D array of cels (an array for each layer removed) for i in range(from_indices.size()): # With each removed index, future indices need to be lowered, so subtract by i layers.remove(from_indices[i] - i) removed_cels.append([]) for frame in frames: - removed_cels[i].append(frame.cels[from_indices[i] - i]) - frame.cels.remove(from_indices[i] - i) + removed_cels[i].append(frame.cels.pop_at(from_indices[i] - i)) Global.animation_timeline.project_layer_removed(from_indices[i] - i) for i in range(to_indices.size()): layers.insert(to_indices[i], old_layers[from_indices[i]]) @@ -917,38 +916,42 @@ func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> v _toggle_layer_buttons_layers() -func swap_layers(a_indices: Array, a_parents: Array, b_indices: Array, b_parents: Array) -> void: +# "a" and "b" should both contain "from", "to", and "to_parents" arrays. +# (Using dictionaries because there seems to be a limit of 5 arguments for do/undo method calls) +func swap_layers(a: Dictionary, b: Dictionary) -> void: selected_cels.clear() - + print("a: ", a, " b: ", b) # TODO R: Remove var a_layers := [] var b_layers := [] + var a_cels := [] # 2D array of cels (an array for each layer removed) + var b_cels := [] # 2D array of cels (an array for each layer removed) + for i in a.from.size(): + a_layers.append(layers.pop_at(a.from[i] - i)) + Global.animation_timeline.project_layer_removed(a.from[i] - i) + a_layers[i].parent = a.to_parents[i] # All parents must be set early, before creating buttons + a_cels.append([]) + for frame in frames: + a_cels[i].append(frame.cels.pop_at(a.from[i] - i)) + for i in b.from.size(): + var index = (b.from[i] - i) if a.from[0] > b.from[0] else (b.from[i] - i - a.from.size()) + b_layers.append(layers.pop_at(index)) + Global.animation_timeline.project_layer_removed(index) + b_layers[i].parent = b.to_parents[i] # All parents must be set early, before creating buttons + b_cels.append([]) + for frame in frames: + b_cels[i].append(frame.cels.pop_at(index)) - # TODO R: With these inputs, this probably isn't reversable if multiple layer suppport is added with a split. - - # THIS IS PROBABLY NOT NEEDED (Combined below with append + pop_at to move them to these arrays) -# for l in a_indices: -# a_layers.append(layers[l]) -# for l in b_indices: -# b_layers.append(layers[l]) - - # remove a_indices from layers, while adding to a_layers - # remove b_indices (+ a_indicies.size() if b_indices > a_indices) Ifrom layers, while adding to b_layers - - # TODO R: Got to consider which of a_indices or b_indices is higher here, probably + a_indicies.size() if b_indices > a_indices) - for i in range(a_indices.size()): -# layers.remove(a_indices[i] + i) - a_layers.append(layers.pop_at(a_indices[i] + i)) - Global.animation_timeline.project_layer_removed(a_indices[i] + i) - for i in range(b_indices.size()): -# layers.remove(b_indices[i] + i) - b_layers.append(layers.pop_at(b_indices[i] + i)) - Global.animation_timeline.project_layer_removed(b_indices[i] + i) - - # TODO R: What about if one is higher thant he other? - # add b_layers to a_indices - # add a_layers to b_indices - - # TODO R: Do something about the parents... + for i in a_layers.size(): + var index = a.to[i] if a.to[0] < b.to[0] else (a.to[i] - b.to.size()) + layers.insert(index, a_layers[i]) + for f in range(frames.size()): + frames[f].cels.insert(index, a_cels[i][f]) + Global.animation_timeline.project_layer_added(index) + for i in b_layers.size(): + layers.insert(b.to[i], b_layers[i]) + for f in range(frames.size()): + frames[f].cels.insert(b.to[i], b_cels[i][f]) + Global.animation_timeline.project_layer_added(b.to[i]) # Update the layer indices and layer/cel buttons: for l in range(layers.size()): diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 3ca037e2cb3e..f4645ae550cb 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -799,6 +799,7 @@ func _on_OnionSkinningSettings_popup_hide() -> void: func project_changed() -> void: + # TODO H: Changing project takes twice as long as previously, why? (Not sure if this func is the problem) var project: Project = Global.current_project # TODO R: maybe pass in instead? # TODO R: Could using queue_free rather than free (or remove and queue_free) actually cause bugs? for child in Global.layers_container.get_children(): diff --git a/src/UI/Timeline/GroupCelButton.gd b/src/UI/Timeline/GroupCelButton.gd index 2b811b94f221..eece7f346cb6 100644 --- a/src/UI/Timeline/GroupCelButton.gd +++ b/src/UI/Timeline/GroupCelButton.gd @@ -5,8 +5,6 @@ var layer := 0 var cel: GroupCel var mat: Material -onready var popup_menu: PopupMenu = $PopupMenu - func _ready() -> void: button_setup() diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index 2ca6290d6407..e38ff8f9da76 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -193,11 +193,17 @@ func _select_current_layer() -> void: func get_drag_data(_position) -> Array: - var button := Button.new() - button.rect_size = rect_size - button.theme = Global.control.theme - button.text = label.text - set_drag_preview(button) + var layers := range(layer - Global.current_project.layers[layer].get_children_recursive().size(), layer + 1) + + var box := VBoxContainer.new() + + for i in range(layers.size()): + var button := Button.new() + button.rect_min_size = rect_size + button.theme = Global.control.theme + button.text = Global.current_project.layers[layers[-1 - i]].name + box.add_child(button) + set_drag_preview(box) return ["Layer", layer] @@ -255,30 +261,50 @@ func drop_data(_pos, data) -> void: project.undo_redo.create_action("Change Layer Order") var new_layers: Array = project.layers.duplicate() - var temp: BaseLayer = new_layers[layer] + + # TODO R: Check for other loops that could be replaced with a range... + # TODO R: new_layers is a little confusing, does it acutally need to be duplicated anymore? It shouldn't be modified... + # TODO R: can this code be made easier to read? + + var drop_from_indices := range(drop_layer - new_layers[drop_layer].get_children_recursive().size(), drop_layer + 1 ) + + var drop_from_parents := [] + for i in range(drop_from_indices.size()): + drop_from_parents.append(new_layers[drop_from_indices[i]].parent) + if Input.is_action_pressed("ctrl"): # Swap layers - pass # TODO R: Figure out swapping -# new_layers[layer] = new_layers[drop_layer] -# new_layers[drop_layer] = temp -# -# # TODO R: Make sure to swap parents too -# -# for f in Global.current_project.frames: -# var new_cels: Array = f.cels.duplicate() -# var temp_canvas = new_cels[layer] -# new_cels[layer] = new_cels[drop_layer] -# new_cels[drop_layer] = temp_canvas -# project.undo_redo.add_do_property(f, "cels", new_cels) -# project.undo_redo.add_undo_property(f, "cels", f.cels) - # TODO R: Having "SourceLayers/OldLayers (that you don't change) and new_layers would make this less confusing - else: - # from_indices should be in order of the layer indices, starting from the lowest - # TODO R: can this code be made easier to read? - var from_indices := [] - for c in new_layers[drop_layer].get_children_recursive(): - from_indices.append(c.index) - from_indices.append(drop_layer) + # a and b both need "from", "to", and "to_parents" + # a is this layer (and children), b is the dropped layers + var a := { "from": range(layer - new_layers[layer].get_children_recursive().size(), layer + 1) } + var b := { "from": drop_from_indices} + + if a.from[0] < b.from[0]: + a["to"] = range(b.from[-1] + 1 - a.from.size(), b.from[-1] + 1) # Size of a, starting from end of b + b["to"] = range(a.from[0], a.from[0] + b.from.size()) # Size of b, starting from beginning of a + else: + a["to"] = range(b.from[0], b.from[0] + a.from.size()) # Size of a, starting from beginning of b + b["to"] = range(a.from[-1] + 1 - b.from.size(), a.from[-1] + 1) # Size of b, starting from end of a + + var a_from_parents := [] + for l in a.from: + a_from_parents.append(new_layers[l].parent) + + a["to_parents"] = a_from_parents.duplicate() + b["to_parents"] = drop_from_parents.duplicate() + for i in a.to_parents.size(): # TODO R: comment to explain this + if a.to_parents[i] == a_from_parents[-1]: + a.to_parents[i] = drop_from_parents[-1] + for i in b.to_parents.size(): + if b.to_parents[i] == drop_from_parents[-1]: + b.to_parents[i] = a_from_parents[-1] + + project.undo_redo.add_do_method(project, "swap_layers", a, b) + project.undo_redo.add_undo_method(project, "swap_layers", + { "from": a.to, "to": a.from, "to_parents": a_from_parents }, + { "from": b.to, "to": drop_from_indices, "to_parents": drop_from_parents } + ) + else: # Move layers var to_index: int # the index where the LOWEST shifted layer should end up var to_parent: BaseLayer @@ -299,28 +325,24 @@ func drop_data(_pos, data) -> void: to_index = new_layers[layer].get_children_recursive()[0].index if new_layers[layer].is_a_parent_of(new_layers[drop_layer]): - to_index += from_indices.size() + to_index += drop_from_indices.size() else: to_index = layer to_parent = new_layers[layer].parent if drop_layer < layer: - to_index -= from_indices.size() - print("to_index = ", to_index) - - var to_indices := [] - var from_parents := [] - for i in range(from_indices.size()): - to_indices.append(to_index + i) - from_parents.append(new_layers[from_indices[i]].parent) - var to_parents := from_parents.duplicate() + to_index -= drop_from_indices.size() + + var drop_to_indices := range(to_index, to_index + drop_from_indices.size()) + + var to_parents := drop_from_parents.duplicate() to_parents[-1] = to_parent project.undo_redo.add_do_method( - project, "move_layers", from_indices, to_indices, to_parents + project, "move_layers", drop_from_indices, drop_to_indices, to_parents ) project.undo_redo.add_undo_method( - project, "move_layers", to_indices, from_indices, from_parents + project, "move_layers", drop_to_indices, drop_from_indices, drop_from_parents ) if project.current_layer == drop_layer: project.undo_redo.add_do_property(project, "current_layer", layer) From 78f74dc95bd7917c494c105e48bf0310ba0c69da Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 9 Jul 2022 15:50:43 -0400 Subject: [PATCH 047/154] Added priorities to refactor TODOs --- src/Autoload/Global.gd | 4 ++-- src/Autoload/OpenSave.gd | 2 +- src/Classes/BaseLayer.gd | 2 +- src/Classes/Project.gd | 25 ++++++++++---------- src/Main.gd | 4 ++-- src/UI/Timeline/AnimationTimeline.gd | 34 ++++++++++++++-------------- src/UI/Timeline/LayerButton.gd | 10 ++++---- src/UI/Timeline/PixelCelButton.gd | 6 ++--- 8 files changed, 43 insertions(+), 44 deletions(-) diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index 5654e19295ac..90aceb3d3f0d 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -255,7 +255,7 @@ func undo_or_redo( cursor_position_label.text = "[%s×%s]" % [project.size.x, project.size.y] elif "Frame" in action_name: - # TODO R: Does what this comment says after the refacotr remain true? (Perhaps this should be moved to move_frame?) + # TODO R2: Does what this comment says after the refacotr remain true? (Perhaps this should be moved to move_frame?) # This actually means that frames.size is one, but it hasn't been updated yet if (undo and project.frames.size() == 2) or project.frames.size() == 1: # Stop animating play_forward.pressed = false @@ -263,7 +263,7 @@ func undo_or_redo( animation_timer.stop() elif "Move Cels" == action_name: - # TODO R: is this still required? + # TODO R2: is this still required? project.frames = project.frames # to call frames_changed canvas.update() diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index 5069a8638167..9fa2246830bc 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -126,7 +126,7 @@ func open_pxo_file(path: String, untitled_backup: bool = false, replace_empty: b if dict.error == OK and dict.result.has("fps"): Global.animation_timeline.fps_spinbox.value = dict.result.fps Global.animation_timeline.project_changed() - # TODO R: Do these need to be here? + # TODO R3: Do these need to be here? (Consider the bug where new project doesn't set the hidden frame buttons in frames_changed) new_project.frames = new_project.frames # Just to call frames_changed new_project.layers = new_project.layers # Just to call layers_changed else: diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index 668524889b5c..73da7326291e 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -97,7 +97,7 @@ func copy() -> BaseLayer: copy.deserialize(serialize()) return copy - +# TODO L: Should this be turned into set_as_default_name? func get_default_name(number: int) -> String: return tr("Layer") + " %s" % number diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 85f4b5ea6dc7..613720446327 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -397,7 +397,7 @@ func _size_changed(value: Vector2) -> void: func _frames_changed(value: Array) -> void: Global.canvas.selection.transform_content_confirm() frames = value -# selected_cels.clear() # TODO R: Determine if this needs to be kept (If it is, selected cels needs to be intialized after creating project (ie: in Main), rather than here +# selected_cels.clear() # TODO R2: Determine if this needs to be kept (If it is, selected cels needs to be intialized after creating project (ie: in Main), rather than here _set_timeline_first_and_last_frames() @@ -407,8 +407,8 @@ func _layers_changed(value: Array) -> void: Global.layers_changed_skip = false return -# selected_cels.clear() # TODO R: Determine if this needs to be kept (If it is, selected cels needs to be intialized after creating project (ie: in Main), rather than here - # TODO R: investigate wether these are still required: +# selected_cels.clear() # TODO R2: Determine if this needs to be kept (If it is, selected cels needs to be intialized after creating project (ie: in Main), rather than here + # TODO R2: investigate wether these are still required: # var layer_button = Global.layers_container.get_child( # Global.layers_container.get_child_count() - 1 - current_layer # ) @@ -454,7 +454,7 @@ func _frame_changed(value: int) -> void: var cel_button = container.get_child(frame) cel_button.pressed = true - # TODO R: When starting up, with only one frame, these aren't getting called: + # TODO R0: When starting up, with only one frame, these aren't getting called: Global.disable_button(Global.remove_frame_button, frames.size() == 1) Global.disable_button(Global.move_left_frame_button, frames.size() == 1 or current_frame == 0) Global.disable_button( @@ -555,7 +555,7 @@ func _animation_tags_changed(value: Array) -> void: _set_timeline_first_and_last_frames() -# TODO R: Is this really required in _frames_changed (or the add/remove frame funcs, seems to work fine without when playing anim) +# TODO R1: Is this really required in _frames_changed (or the add/remove frame funcs, seems to work fine without when playing anim) func _set_timeline_first_and_last_frames() -> void: # This is useful in case tags get modified DURING the animation is playing # otherwise, this code is useless in this context, since these values are being set @@ -600,7 +600,7 @@ func is_empty() -> bool: func duplicate_layers() -> Array: - # TODO R: May want to test this a bit after refactor + # TODO R1: May want to test this a bit after refactor # TODO H: When duplicating the layers, parent references would be using the old layers now, this will probably cause bugs var new_layers: Array = layers.duplicate() # Loop through the array to create new classes for each element, so that they @@ -775,7 +775,7 @@ func resize_bitmap_values(bitmap: BitMap, new_size: Vector2, flip_x: bool, flip_ func add_frames(new_frames: Array, indices: Array) -> void: # indices should be in ascending order - assert(self == Global.current_project) # TODO R: Remove (Things like calling project_frame/layer_added may need to do a check if its the current project if this fails) + assert(self == Global.current_project) # TODO R3: Remove (Things like calling project_frame/layer_added may need to do a check if its the current project if this fails) Global.canvas.selection.transform_content_confirm() selected_cels.clear() for i in range(new_frames.size()): @@ -796,7 +796,7 @@ func add_frames(new_frames: Array, indices: Array) -> void: # indices should be func remove_frames(indices: Array) -> void: # indices should be in ascending order Global.canvas.selection.transform_content_confirm() selected_cels.clear() - # TODO R: Could one half of cel linking and animation tags be included in the add or remove_frame functions? (ie: removing works, but adding doesn't?) + # TODO R1: Could one half of cel linking and animation tags be included in the add or remove_frame functions? (ie: removing works, but adding doesn't?) for i in range(indices.size()): # With each removed index, future indices need to be lowered, so subtract by i frames.remove(indices[i] - i) @@ -846,7 +846,7 @@ func swap_frame(a_index: int, b_index: int) -> void: func add_layers(new_layers: Array, indices: Array, cels: Array) -> void: # cels is 2d Array of cels - assert(self == Global.current_project) # TODO R: Remove (Things like calling project_frame/layer_added may need to do a check if its the current project if this fails) + assert(self == Global.current_project) # TODO R3: Remove (Things like calling project_frame/layer_added may need to do a check if its the current project if this fails) selected_cels.clear() for i in range(indices.size()): layers.insert(indices[i], new_layers[i]) @@ -886,9 +886,8 @@ func remove_layers(indices: Array) -> void: # from_indices and to_indicies should be in ascending order func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> void: - # TODO R: it may be good to do a test run with using add/remove_layers instead of using move_layers selected_cels.clear() - var old_layers := layers.duplicate() # TODO R: Could maybe change to just empty layers array, using append(pop_at) trick like in swap_layers + var old_layers := layers.duplicate() # TODO R1: Could maybe change to just empty layers array, using append(pop_at) trick like in swap_layers var removed_cels := [] # 2D array of cels (an array for each layer removed) for i in range(from_indices.size()): @@ -900,7 +899,7 @@ func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> v Global.animation_timeline.project_layer_removed(from_indices[i] - i) for i in range(to_indices.size()): layers.insert(to_indices[i], old_layers[from_indices[i]]) - layers[to_indices[i]].parent = to_parents[i] # TODO R: it could be possible to do the to_parents when removing (previous loop), allowing this loop to be recombined with the next + layers[to_indices[i]].parent = to_parents[i] # TODO R1: it could be possible to do the to_parents when removing (previous loop), allowing this loop to be recombined with the next for f in range(frames.size()): frames[f].cels.insert(to_indices[i], removed_cels[i][f]) for i in range(to_indices.size()): # Loop again (All parents must be set before adding the UI) @@ -920,7 +919,7 @@ func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> v # (Using dictionaries because there seems to be a limit of 5 arguments for do/undo method calls) func swap_layers(a: Dictionary, b: Dictionary) -> void: selected_cels.clear() - print("a: ", a, " b: ", b) # TODO R: Remove + print("a: ", a, " b: ", b) # TODO R3: Remove var a_layers := [] var b_layers := [] var a_cels := [] # 2D array of cels (an array for each layer removed) diff --git a/src/Main.gd b/src/Main.gd index c45d221dc735..d5e371563a8c 100644 --- a/src/Main.gd +++ b/src/Main.gd @@ -25,9 +25,9 @@ func _ready() -> void: Global.current_project.layers.append(PixelLayer.new()) Global.current_project.layers[0].project = Global.current_project Global.current_project.frames.append(Global.current_project.new_empty_frame()) - Global.animation_timeline.project_changed() # TODO R: would it be a good idea to remove this, and the intial buttons back into the timeiline scene? + Global.animation_timeline.project_changed() # TODO R2: would it be a good idea to remove this, and the intial buttons back into the timeiline scene? - # TODO R: I Think this line should be safe to remove: (calling setter) + # TODO R3: I Think this line should be safe to remove: (calling setter) # Global.current_project.layers = Global.current_project.layers Import.import_brushes(Global.directory_module.get_brushes_search_path_in_order()) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index f4645ae550cb..6014aa3c8918 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -13,7 +13,7 @@ var past_above_canvas := true var future_above_canvas := true var frame_button_node = preload("res://src/UI/Timeline/FrameButton.tscn") -# TODO R: May remove some of these: +# TODO R1: May remove some of these: var pixel_layer_button_node = preload("res://src/UI/Timeline/PixelLayerButton.tscn") var group_layer_button_node = preload("res://src/UI/Timeline/GroupLayerButton.tscn") @@ -192,7 +192,7 @@ func _on_DeleteFrame_pressed(frame := -1) -> void: func delete_frames(frames := []) -> void: - # TODO R: If there is mulitple frames, it is currently possible to select and delete them all + # TODO R0: If there is mulitple frames, it is currently possible to select and delete them all var project: Project = Global.current_project if project.frames.size() == 1: return @@ -580,7 +580,7 @@ func _on_FuturePlacement_item_selected(index: int) -> void: func _on_AddLayer_pressed() -> void: - Global.canvas.selection.transform_content_confirm() # TODO R: Figure out once and for all, do these belong here, or in the project reversable functions (where these will be called on undo as well) + Global.canvas.selection.transform_content_confirm() # TODO R2: Figure out once and for all, do these belong here, or in the project reversable functions (where these will be called on undo as well) var project: Project = Global.current_project var l := PixelLayer.new() @@ -632,7 +632,7 @@ func _on_CloneLayer_pressed() -> void: for f in project.frames: cels.append(f.cels[project.current_layer].copy()) - # TODO R: Copies don't have linked cels properly set up... + # TODO R0: Copies don't have linked cels properly set up... project.undos += 1 project.undo_redo.create_action("Add Layer") @@ -646,7 +646,7 @@ func _on_CloneLayer_pressed() -> void: func _on_RemoveLayer_pressed() -> void: - # TODO R: It is currently possible to delete all layers (by having all layers in a group and deleting the group) + # TODO R0: It is currently possible to delete all layers (by having all layers in a group and deleting the group) var project: Project = Global.current_project if project.layers.size() == 1: return @@ -665,7 +665,7 @@ func _on_RemoveLayer_pressed() -> void: project.undos += 1 project.undo_redo.create_action("Remove Layer") - # TODO R: what should be the new current layer? + # TODO R3: what should be the new current layer? project.undo_redo.add_do_property(project, "current_layer", max(indices[0] - 1, 0)) project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) project.undo_redo.add_do_method(project, "remove_layers", indices) @@ -706,7 +706,7 @@ func change_layer_order(rate: int) -> void: Global.current_project.undo_redo.add_do_method(Global, "undo_or_redo", false) Global.current_project.undo_redo.commit_action() -# TODO R: Does this need to be part of the refactor? +# TODO R0: Does this need to be part of the refactor? func _on_MergeDownLayer_pressed() -> void: var new_layers: Array = Global.current_project.duplicate_layers() @@ -800,8 +800,8 @@ func _on_OnionSkinningSettings_popup_hide() -> void: func project_changed() -> void: # TODO H: Changing project takes twice as long as previously, why? (Not sure if this func is the problem) - var project: Project = Global.current_project # TODO R: maybe pass in instead? - # TODO R: Could using queue_free rather than free (or remove and queue_free) actually cause bugs? + var project: Project = Global.current_project # TODO R3: maybe pass in instead? + # TODO R2: Could using queue_free rather than free (or remove and queue_free) actually cause bugs? for child in Global.layers_container.get_children(): child.queue_free() for child in Global.frame_ids.get_children(): @@ -817,12 +817,12 @@ func project_changed() -> void: Global.frame_ids.add_child(button) Global.frame_ids.move_child(button, f) - # TODO R: Remove and inline what's needed here if this isn't used anywhere else: + # TODO R3: Remove and inline what's needed here if this isn't used anywhere else: Global.current_project._update_animation_timeline_selection() func project_frame_added(frame: int) -> void: - var project: Project = Global.current_project # TODO R: maybe pass in instead? + var project: Project = Global.current_project # TODO R3: maybe pass in instead? var button: Button = frame_button_node.instance() button.frame = frame Global.frame_ids.add_child(button) @@ -847,16 +847,16 @@ func project_frame_removed(frame: int) -> void: func project_layer_added(layer: int) -> void: var project: Project = Global.current_project - # TODO R: should probably have a "layer" variable... (to many project.layers[layer])... + # TODO R3: should probably have a "layer" variable... (to many project.layers[layer])... # ...or refactor things so less of this code is needed here. - # TODO R: Could this function be organized in a better way? + # TODO R1: Could this function be organized in a better way? var layer_button: LayerButton if project.layers[layer] is PixelLayer: layer_button = pixel_layer_button_node.instance() elif project.layers[layer] is GroupLayer: layer_button = group_layer_button_node.instance() - layer_button.layer = layer # TODO R: See if needed - if project.layers[layer].name == "": # TODO R: This probably could be somewhere else... add_layer(s) in project? + layer_button.layer = layer # TODO R1: See if needed + if project.layers[layer].name == "": # TODO R1: This probably could be somewhere else... add_layer(s) in project? project.layers[layer].name = project.layers[layer].get_default_name(layer) Global.layers_container.add_child(layer_button) @@ -864,14 +864,14 @@ func project_layer_added(layer: int) -> void: Global.layers_container.move_child(layer_button, count - 1 - layer) var layer_cel_container := HBoxContainer.new() - # TODO R: Is there any need for a name (and why is it LAYERSSS in one place, and FRAMESS in another?) + # TODO R3: Is there any need for a name (and why is it LAYERSSS in one place, and FRAMESS in another?) layer_cel_container.name = "LAYERSSS " + str(layer) Global.frames_container.add_child(layer_cel_container) Global.frames_container.move_child(layer_cel_container, count - 1 - layer) for f in range(project.frames.size()): var cel_button = project.frames[f].cels[layer].create_cel_button() cel_button.frame = f - cel_button.layer = layer# - 1 # TODO R: See if needed + cel_button.layer = layer# - 1 # TODO R1: See if needed layer_cel_container.add_child(cel_button) layer_button.visible = Global.current_project.layers[layer].is_expanded_in_hierarchy() diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index e38ff8f9da76..78be9f883628 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -74,7 +74,7 @@ func _update_buttons() -> void: func _update_buttons_all_layers() -> void: - # TODO R: would it be better to have specified range? (if so rename all_layers to for_layers) + # TODO R2: would it be better to have specified range? (if so rename all_layers to for_layers) # Maybe update_buttons_recursive (including children) is all we need? for layer_button in Global.layers_container.get_children(): layer_button._update_buttons() @@ -262,9 +262,9 @@ func drop_data(_pos, data) -> void: project.undo_redo.create_action("Change Layer Order") var new_layers: Array = project.layers.duplicate() - # TODO R: Check for other loops that could be replaced with a range... - # TODO R: new_layers is a little confusing, does it acutally need to be duplicated anymore? It shouldn't be modified... - # TODO R: can this code be made easier to read? + # TODO R1: Check for other loops that could be replaced with a range... + # TODO R1: new_layers is a little confusing, does it acutally need to be duplicated anymore? It shouldn't be modified... + # TODO R1: can this code be made easier to read? var drop_from_indices := range(drop_layer - new_layers[drop_layer].get_children_recursive().size(), drop_layer + 1 ) @@ -291,7 +291,7 @@ func drop_data(_pos, data) -> void: a["to_parents"] = a_from_parents.duplicate() b["to_parents"] = drop_from_parents.duplicate() - for i in a.to_parents.size(): # TODO R: comment to explain this + for i in a.to_parents.size(): # TODO R0: comment to explain this if a.to_parents[i] == a_from_parents[-1]: a.to_parents[i] = drop_from_parents[-1] for i in b.to_parents.size(): diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index 2d441e6801ff..f81ebe46412e 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -9,7 +9,7 @@ var image: Image onready var popup_menu: PopupMenu = $PopupMenu -# TODO R: The linked indicator seems to not get updated properly (adding a new linked cel won't show the indicator until another timeline change, same with linking an existing cel) +# TODO R0: The linked indicator seems to not get updated properly (adding a new linked cel won't show the indicator until another timeline change, same with linking an existing cel) func _ready() -> void: button_setup() @@ -103,7 +103,7 @@ func _on_PopupMenu_id_pressed(id: int) -> void: _delete_cel_content() MenuOptions.LINK: - # TODO R: See if there is any refactoring to do here: + # TODO R0: See if there is any refactoring to do here: var f: Frame = Global.current_project.frames[frame] var cel_index: int = Global.current_project.layers[layer].linked_cels.find(f) var new_layers: Array = Global.current_project.duplicate_layers() @@ -113,7 +113,7 @@ func _on_PopupMenu_id_pressed(id: int) -> void: new_cels[i] = PixelCel.new( new_cels[i].image, new_cels[i].opacity, new_cels[i].image_texture ) -# TODO R: Make sure all this stuff still works after refactor: +# TODO R3: Make sure all this stuff still works after refactor: if popup_menu.get_item_metadata(MenuOptions.LINK) == "Unlink Cel": new_layers[layer].linked_cels.remove(cel_index) var sprite := Image.new() From 4ffec4cfbf47993501547673d0058974b1ce9126 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sun, 10 Jul 2022 20:42:50 -0400 Subject: [PATCH 048/154] Simplified layer swapping code a little --- src/UI/Timeline/LayerButton.gd | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index 78be9f883628..33d93de4ded8 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -193,17 +193,18 @@ func _select_current_layer() -> void: func get_drag_data(_position) -> Array: + # TODO H: If keeping this new multi layer drag design, layers here can be reutrned in the array + # instead of layer... var layers := range(layer - Global.current_project.layers[layer].get_children_recursive().size(), layer + 1) var box := VBoxContainer.new() - - for i in range(layers.size()): + for i in layers.size(): var button := Button.new() button.rect_min_size = rect_size button.theme = Global.control.theme button.text = Global.current_project.layers[layers[-1 - i]].name box.add_child(button) - set_drag_preview(box) + set_drag_preview(box) return ["Layer", layer] @@ -289,14 +290,13 @@ func drop_data(_pos, data) -> void: for l in a.from: a_from_parents.append(new_layers[l].parent) + # to_parents starts as a dulpicate of from_parents, set the root layer's (with one layer or + # group with its children, this will always be the last layer [-1]) parent to the other + # root layer's parent a["to_parents"] = a_from_parents.duplicate() b["to_parents"] = drop_from_parents.duplicate() - for i in a.to_parents.size(): # TODO R0: comment to explain this - if a.to_parents[i] == a_from_parents[-1]: - a.to_parents[i] = drop_from_parents[-1] - for i in b.to_parents.size(): - if b.to_parents[i] == drop_from_parents[-1]: - b.to_parents[i] = a_from_parents[-1] + a.to_parents[-1] = drop_from_parents[-1] + b.to_parents[-1] = a_from_parents[-1] project.undo_redo.add_do_method(project, "swap_layers", a, b) project.undo_redo.add_undo_method(project, "swap_layers", From 23abd6022c4efcbac7b4936ca8d64753e8e0436a Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sun, 10 Jul 2022 20:44:23 -0400 Subject: [PATCH 049/154] Fixed performance regression on changing project, updated TODOs --- src/Autoload/Global.gd | 4 ++ src/Classes/BaseCel.gd | 2 +- src/Classes/BaseLayer.gd | 4 ++ src/Classes/GroupCel.gd | 4 +- src/Classes/GroupLayer.gd | 4 ++ src/Classes/PixelCel.gd | 5 +-- src/Classes/PixelLayer.gd | 4 ++ src/Classes/Project.gd | 8 ++-- src/Main.gd | 2 +- src/UI/Timeline/AnimationTimeline.gd | 31 ++++++++-------- src/UI/Timeline/PixelCelButton.gd | 55 +++++++++++++--------------- 11 files changed, 67 insertions(+), 56 deletions(-) diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index 90aceb3d3f0d..8d8052ff6bab 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -103,6 +103,10 @@ var palettes := {} # Nodes var notification_label_node: PackedScene = preload("res://src/UI/NotificationLabel.tscn") +var pixel_layer_button_node: PackedScene = preload("res://src/UI/Timeline/PixelLayerButton.tscn") +var group_layer_button_node: PackedScene = preload("res://src/UI/Timeline/GroupLayerButton.tscn") +var pixel_cel_button_node: PackedScene = preload("res://src/UI/Timeline/PixelCelButton.tscn") +var group_cel_button_node: PackedScene = preload("res://src/UI/Timeline/GroupCelButton.tscn") onready var control: Node = get_tree().get_root().get_node("Control") diff --git a/src/Classes/BaseCel.gd b/src/Classes/BaseCel.gd index 6ffc2c9d6d80..87e25e8b4150 100644 --- a/src/Classes/BaseCel.gd +++ b/src/Classes/BaseCel.gd @@ -29,5 +29,5 @@ func copy() -> BaseCel: return null -func create_cel_button() -> Button: +func create_cel_button() -> Node: return null diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index 73da7326291e..1d90d9da1e61 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -108,3 +108,7 @@ func can_layer_get_drawn() -> bool: func accepts_child(_layer: BaseLayer) -> bool: return false + + +func create_layer_button() -> Node: + return null diff --git a/src/Classes/GroupCel.gd b/src/Classes/GroupCel.gd index 0a54bc68908a..5f1d47037346 100644 --- a/src/Classes/GroupCel.gd +++ b/src/Classes/GroupCel.gd @@ -17,5 +17,5 @@ func copy() -> BaseCel: return get_script().new(opacity) -func create_cel_button() -> Button: - return load("res://src/UI/Timeline/GroupCelButton.tscn").instance() as Button +func create_cel_button() -> Node: + return Global.group_cel_button_node.instance() diff --git a/src/Classes/GroupLayer.gd b/src/Classes/GroupLayer.gd index 6a1ef2f23dee..f42ff4e96ceb 100644 --- a/src/Classes/GroupLayer.gd +++ b/src/Classes/GroupLayer.gd @@ -27,3 +27,7 @@ func get_default_name(number: int) -> String: func accepts_child(_layer: BaseLayer) -> bool: return true + + +func create_layer_button() -> Node: + return Global.group_layer_button_node.instance() diff --git a/src/Classes/PixelCel.gd b/src/Classes/PixelCel.gd index b4a6738f36b2..6295bfb3f368 100644 --- a/src/Classes/PixelCel.gd +++ b/src/Classes/PixelCel.gd @@ -7,7 +7,6 @@ extends BaseCel var image: Image setget image_changed var image_texture: ImageTexture - func _init(_image := Image.new(), _opacity := 1.0, _image_texture: ImageTexture = null) -> void: if _image_texture: image_texture = _image_texture @@ -46,7 +45,7 @@ func copy() -> BaseCel: return get_script().new(copy_image, opacity, copy_texture) -func create_cel_button() -> Button: - var cel_button = load("res://src/UI/Timeline/PixelCelButton.tscn").instance() +func create_cel_button() -> Node: + var cel_button = Global.pixel_cel_button_node.instance() cel_button.get_child(0).texture = image_texture return cel_button diff --git a/src/Classes/PixelLayer.gd b/src/Classes/PixelLayer.gd index 60c3584a74cc..1396d394c9ba 100644 --- a/src/Classes/PixelLayer.gd +++ b/src/Classes/PixelLayer.gd @@ -34,3 +34,7 @@ func deserialize(dict: Dictionary) -> void: func can_layer_get_drawn() -> bool: return is_visible_in_hierarchy() && !is_locked_in_hierarchy() + + +func create_layer_button() -> Node: + return Global.pixel_layer_button_node.instance() diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 613720446327..47bc535941a3 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -462,11 +462,9 @@ func _frame_changed(value: int) -> void: ) if current_frame < frames.size(): - # TODO H: Make this work with groups: - if not layers[current_layer] is GroupLayer: - var cel_opacity: float = frames[current_frame].cels[current_layer].opacity - Global.layer_opacity_slider.value = cel_opacity * 100 - Global.layer_opacity_spinbox.value = cel_opacity * 100 + var cel_opacity: float = frames[current_frame].cels[current_layer].opacity + Global.layer_opacity_slider.value = cel_opacity * 100 + Global.layer_opacity_spinbox.value = cel_opacity * 100 Global.canvas.update() Global.transparent_checker.update_rect() diff --git a/src/Main.gd b/src/Main.gd index d5e371563a8c..7a69685df3e4 100644 --- a/src/Main.gd +++ b/src/Main.gd @@ -27,7 +27,7 @@ func _ready() -> void: Global.current_project.frames.append(Global.current_project.new_empty_frame()) Global.animation_timeline.project_changed() # TODO R2: would it be a good idea to remove this, and the intial buttons back into the timeiline scene? - # TODO R3: I Think this line should be safe to remove: (calling setter) + # TODO R3: I Think this line should be safe to remove: (calling setter, already called when appending the layer) # Global.current_project.layers = Global.current_project.layers Import.import_brushes(Global.directory_module.get_brushes_search_path_in_order()) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 6014aa3c8918..22914e04bee1 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -13,9 +13,6 @@ var past_above_canvas := true var future_above_canvas := true var frame_button_node = preload("res://src/UI/Timeline/FrameButton.tscn") -# TODO R1: May remove some of these: -var pixel_layer_button_node = preload("res://src/UI/Timeline/PixelLayerButton.tscn") -var group_layer_button_node = preload("res://src/UI/Timeline/GroupLayerButton.tscn") onready var old_scroll: int = 0 # The previous scroll state of $ScrollContainer onready var tag_spacer = find_node("TagSpacer") @@ -799,23 +796,31 @@ func _on_OnionSkinningSettings_popup_hide() -> void: func project_changed() -> void: - # TODO H: Changing project takes twice as long as previously, why? (Not sure if this func is the problem) + # TODO R0: When changing project the selcted frames will be 1 less (1 further to the left) + # then they should be + # TODO R0: If you draw in the automatically created project, then load/create a new project, + # then going back to the automatically created project tab, you can't add/remove + # layers/frames (and probaly other issues). + # THIS HASN't BEEN REPEATED var project: Project = Global.current_project # TODO R3: maybe pass in instead? - # TODO R2: Could using queue_free rather than free (or remove and queue_free) actually cause bugs? + # TODO R0: Could using queue_free rather than free (or remove and queue_free) actually cause bugs? + # This caused the bug where changing the project would have the wrong frame button + # selected, but only when move_children was not called for child in Global.layers_container.get_children(): child.queue_free() for child in Global.frame_ids.get_children(): - child.queue_free() +# child.queue_free() + child.free() for container in Global.frames_container.get_children(): container.queue_free() - for i in range(project.layers.size()): + for i in range(project.layers.size()): # TODO R2: Could this be faster if it did it in reverse order? project_layer_added(i) for f in range(project.frames.size()): var button: Button = frame_button_node.instance() button.frame = f Global.frame_ids.add_child(button) - Global.frame_ids.move_child(button, f) +# Global.frame_ids.move_child(button, f) # TODO R0: Is this needed? Shouldn't they be in order already? (Perhaps commenting it out caused one of the above issues?) # TODO R3: Remove and inline what's needed here if this isn't used anywhere else: Global.current_project._update_animation_timeline_selection() @@ -847,14 +852,9 @@ func project_frame_removed(frame: int) -> void: func project_layer_added(layer: int) -> void: var project: Project = Global.current_project - # TODO R3: should probably have a "layer" variable... (to many project.layers[layer])... - # ...or refactor things so less of this code is needed here. + # TODO R1: Could this function be organized in a better way? - var layer_button: LayerButton - if project.layers[layer] is PixelLayer: - layer_button = pixel_layer_button_node.instance() - elif project.layers[layer] is GroupLayer: - layer_button = group_layer_button_node.instance() + var layer_button: LayerButton = project.layers[layer].create_layer_button() layer_button.layer = layer # TODO R1: See if needed if project.layers[layer].name == "": # TODO R1: This probably could be somewhere else... add_layer(s) in project? project.layers[layer].name = project.layers[layer].get_default_name(layer) @@ -865,6 +865,7 @@ func project_layer_added(layer: int) -> void: var layer_cel_container := HBoxContainer.new() # TODO R3: Is there any need for a name (and why is it LAYERSSS in one place, and FRAMESS in another?) + # TODO R0: Could the order here affect performance? layer_cel_container.name = "LAYERSSS " + str(layer) Global.frames_container.add_child(layer_cel_container) Global.frames_container.move_child(layer_cel_container, count - 1 - layer) diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index f81ebe46412e..3a5b39555265 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -9,7 +9,10 @@ var image: Image onready var popup_menu: PopupMenu = $PopupMenu -# TODO R0: The linked indicator seems to not get updated properly (adding a new linked cel won't show the indicator until another timeline change, same with linking an existing cel) +# TODO R3: The linked indicator seems to not get updated properly (adding a new linked cel won't show +# the indicator until another timeline change, same with linking an existing cel) +# (this is most likely due to the order of do/undo methods/properties being added in +# AnimationTimeline. Will leave until I decide what to do about setting linked in the first place) func _ready() -> void: button_setup() @@ -103,10 +106,12 @@ func _on_PopupMenu_id_pressed(id: int) -> void: _delete_cel_content() MenuOptions.LINK: - # TODO R0: See if there is any refactoring to do here: - var f: Frame = Global.current_project.frames[frame] - var cel_index: int = Global.current_project.layers[layer].linked_cels.find(f) - var new_layers: Array = Global.current_project.duplicate_layers() + # TODO R3: If you do part of linked cels in add/remove frames, consider changes here: + # TODO R3: Make add_do/undo_property/method order consistent + var project: Project = Global.current_project + var f: Frame = project.frames[frame] + var cel_index: int = project.layers[layer].linked_cels.find(f) + var new_layers: Array = project.duplicate_layers() var new_cels: Array = f.cels.duplicate() for i in new_cels.size(): # TODO H: This doesn't work (currently replaces ALL cels on the frame) @@ -123,40 +128,32 @@ func _on_PopupMenu_id_pressed(id: int) -> void: new_cels[layer].image = sprite new_cels[layer].image_texture = sprite_texture - Global.current_project.undo_redo.create_action("Unlink Cel") - Global.current_project.undo_redo.add_do_property( - Global.current_project, "layers", new_layers - ) - Global.current_project.undo_redo.add_do_property(f, "cels", new_cels) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "layers", Global.current_project.layers - ) - Global.current_project.undo_redo.add_undo_property(f, "cels", f.cels) + project.undo_redo.create_action("Unlink Cel") + project.undo_redo.add_do_property(project, "layers", new_layers) + project.undo_redo.add_do_property(f, "cels", new_cels) + project.undo_redo.add_undo_property(project, "layers", project.layers) + project.undo_redo.add_undo_property(f, "cels", f.cels) - Global.current_project.undo_redo.add_undo_method(Global, "undo_or_redo", true) - Global.current_project.undo_redo.add_do_method(Global, "undo_or_redo", false) - Global.current_project.undo_redo.commit_action() + project.undo_redo.add_undo_method(Global, "undo_or_redo", true) + project.undo_redo.add_do_method(Global, "undo_or_redo", false) + project.undo_redo.commit_action() elif popup_menu.get_item_metadata(MenuOptions.LINK) == "Link Cel": new_layers[layer].linked_cels.append(f) - Global.current_project.undo_redo.create_action("Link Cel") - Global.current_project.undo_redo.add_do_property( - Global.current_project, "layers", new_layers - ) + project.undo_redo.create_action("Link Cel") + project.undo_redo.add_do_property(project, "layers", new_layers) if new_layers[layer].linked_cels.size() > 1: # If there are already linked cels, set the current cel's image # to the first linked cel's image new_cels[layer].image = new_layers[layer].linked_cels[0].cels[layer].image new_cels[layer].image_texture = new_layers[layer].linked_cels[0].cels[layer].image_texture - Global.current_project.undo_redo.add_do_property(f, "cels", new_cels) - Global.current_project.undo_redo.add_undo_property(f, "cels", f.cels) + project.undo_redo.add_do_property(f, "cels", new_cels) + project.undo_redo.add_undo_property(f, "cels", f.cels) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "layers", Global.current_project.layers - ) - Global.current_project.undo_redo.add_undo_method(Global, "undo_or_redo", true) - Global.current_project.undo_redo.add_do_method(Global, "undo_or_redo", false) - Global.current_project.undo_redo.commit_action() + project.undo_redo.add_undo_property(project, "layers", project.layers) + project.undo_redo.add_undo_method(Global, "undo_or_redo", true) + project.undo_redo.add_do_method(Global, "undo_or_redo", false) + project.undo_redo.commit_action() func _delete_cel_content() -> void: From c2193e062fcfe026b2fb56e92ec350ca59845e00 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 14 Jul 2022 14:03:45 -0400 Subject: [PATCH 050/154] Included _on_MergeDownLayer_pressed in timeline refactor --- src/Classes/PixelCel.gd | 5 +- src/UI/Timeline/AnimationTimeline.gd | 180 ++++++++++++++++++--------- src/UI/Timeline/PixelCelButton.gd | 3 + 3 files changed, 126 insertions(+), 62 deletions(-) diff --git a/src/Classes/PixelCel.gd b/src/Classes/PixelCel.gd index 6295bfb3f368..ac703e1279ae 100644 --- a/src/Classes/PixelCel.gd +++ b/src/Classes/PixelCel.gd @@ -35,7 +35,10 @@ func load_image_data_from_pxo(file: File, project_size: Vector2) -> void: image.create_from_data(project_size.x, project_size.y, false, Image.FORMAT_RGBA8, buffer) image_changed(image) - +# TODO R3: A copy_image bool parameter could be useful for places such as the merging layers function +# where the copied cels don't need the image to be copied (at least not yet in that case) +# Alternatively, keep it as is, and maybe put a comment on the copy function mentioning that it +# copies the image data too... func copy() -> BaseCel: var copy_image := Image.new() copy_image.copy_from(image) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 22914e04bee1..ffb2d2a024f2 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -703,83 +703,141 @@ func change_layer_order(rate: int) -> void: Global.current_project.undo_redo.add_do_method(Global, "undo_or_redo", false) Global.current_project.undo_redo.commit_action() -# TODO R0: Does this need to be part of the refactor? + +#func _on_MergeDownLayer_pressed() -> void: +# var project: Project = Global.current_project +# var new_layers: Array = project.duplicate_layers() +# +# project.undos += 1 +# project.undo_redo.create_action("Merge Layer") +# for f in project.frames: +# var new_cels: Array = f.cels.duplicate() +# for i in new_cels.size(): +# new_cels[i] = PixelCel.new(new_cels[i].image, new_cels[i].opacity) +# # TODO Later: top_image here doesn't really need to be a copy if there isn't layer transparency +# # though this probably will be rewriten with blend modes anyway... +# var top_image := Image.new() +# top_image.copy_from(new_cels[project.current_layer].image) +# +# top_image.lock() +# if f.cels[project.current_layer].opacity < 1: # If we have layer transparency +# for xx in top_image.get_size().x: +# for yy in top_image.get_size().y: +# var pixel_color: Color = top_image.get_pixel(xx, yy) +# var alpha: float = pixel_color.a * f.cels[project.current_layer].opacity +# top_image.set_pixel( +# xx, yy, Color(pixel_color.r, pixel_color.g, pixel_color.b, alpha) +# ) +# top_image.unlock() +# +# var bottom_image := Image.new() +# bottom_image.copy_from(f.cels[project.current_layer - 1].image) +# bottom_image.blend_rect(top_image, Rect2(Vector2.ZERO, project.size), Vector2.ZERO) +# new_cels.remove(project.current_layer) # TODO NOTE: Removign the cel here +# if ( +# !top_image.is_invisible() +# and project.layers[project.current_layer - 1].linked_cels.size() > 1 +# and f in project.layers[project.current_layer - 1].linked_cels +# ): +# new_layers[project.current_layer - 1].linked_cels.erase(f) +# new_cels[project.current_layer - 1].image = bottom_image +# else: +# project.undo_redo.add_do_property( +# f.cels[project.current_layer - 1].image, "data", bottom_image.data +# ) +# project.undo_redo.add_undo_property( +# f.cels[project.current_layer - 1].image, +# "data", +# f.cels[project.current_layer - 1].image.data +# ) +# +# project.undo_redo.add_do_property(f, "cels", new_cels) +# project.undo_redo.add_undo_property(f, "cels", f.cels) +# +# new_layers.remove(project.current_layer) +# project.undo_redo.add_do_property(project, "current_layer", project.current_layer - 1) +# project.undo_redo.add_do_property(project, "layers", new_layers) +# project.undo_redo.add_undo_property(project, "layers", project.layers) +# project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) +# +# project.undo_redo.add_undo_method(Global, "undo_or_redo", true) +# project.undo_redo.add_do_method(Global, "undo_or_redo", false) +# project.undo_redo.commit_action() + + func _on_MergeDownLayer_pressed() -> void: - var new_layers: Array = Global.current_project.duplicate_layers() + var project: Project = Global.current_project + var new_bottom_linked_cels: Array = project.layers[project.current_layer - 1].linked_cels.duplicate() - Global.current_project.undos += 1 - Global.current_project.undo_redo.create_action("Merge Layer") - for f in Global.current_project.frames: - var new_cels: Array = f.cels.duplicate() - for i in new_cels.size(): - new_cels[i] = PixelCel.new(new_cels[i].image, new_cels[i].opacity) - var selected_layer := Image.new() - selected_layer.copy_from(new_cels[Global.current_project.current_layer].image) - - selected_layer.lock() - if f.cels[Global.current_project.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 - * f.cels[Global.current_project.current_layer].opacity - ) - selected_layer.set_pixel( + project.undos += 1 + project.undo_redo.create_action("Merge Layer") + + for f in project.frames: + # TODO Later: top_image here doesn't really need to be a copy if there isn't layer transparency + # though this probably will be rewriten with blend modes anyway... + var top_image := Image.new() + top_image.copy_from(f.cels[project.current_layer].image) + + top_image.lock() + if f.cels[project.current_layer].opacity < 1: # If we have layer transparency + for xx in top_image.get_size().x: + for yy in top_image.get_size().y: + var pixel_color: Color = top_image.get_pixel(xx, yy) + var alpha: float = pixel_color.a * f.cels[project.current_layer].opacity + top_image.set_pixel( xx, yy, Color(pixel_color.r, pixel_color.g, pixel_color.b, alpha) ) - selected_layer.unlock() + top_image.unlock() - var new_layer := Image.new() - new_layer.copy_from(f.cels[Global.current_project.current_layer - 1].image) - new_layer.blend_rect( - selected_layer, Rect2(Vector2.ZERO, Global.current_project.size), Vector2.ZERO - ) - new_cels.remove(Global.current_project.current_layer) + var bottom_image := Image.new() + bottom_image.copy_from(f.cels[project.current_layer - 1].image) + bottom_image.blend_rect(top_image, Rect2(Vector2.ZERO, project.size), Vector2.ZERO) if ( - !selected_layer.is_invisible() - and ( - Global.current_project.layers[Global.current_project.current_layer - 1].linked_cels.size() - > 1 - ) - and ( - f - in Global.current_project.layers[( - Global.current_project.current_layer - - 1 - )].linked_cels - ) + !top_image.is_invisible() + and project.layers[project.current_layer - 1].linked_cels.size() > 1 + and f in project.layers[project.current_layer - 1].linked_cels ): - new_layers[Global.current_project.current_layer - 1].linked_cels.erase(f) - new_cels[Global.current_project.current_layer - 1].image = new_layer + new_bottom_linked_cels.erase(f) + + project.undo_redo.add_do_property(f.cels[project.current_layer - 1], "image_texture", ImageTexture.new()) + project.undo_redo.add_undo_property(f.cels[project.current_layer - 1], "image_texture", f.cels[project.current_layer - 1].image_texture) + + project.undo_redo.add_do_property(f.cels[project.current_layer - 1], "image", bottom_image) + project.undo_redo.add_undo_property( + f.cels[project.current_layer - 1], "image", f.cels[project.current_layer - 1].image + ) else: - Global.current_project.undo_redo.add_do_property( - f.cels[Global.current_project.current_layer - 1].image, "data", new_layer.data + project.undo_redo.add_do_property( + f.cels[project.current_layer - 1].image, "data", bottom_image.data ) - Global.current_project.undo_redo.add_undo_property( - f.cels[Global.current_project.current_layer - 1].image, + project.undo_redo.add_undo_property( + f.cels[project.current_layer - 1].image, "data", - f.cels[Global.current_project.current_layer - 1].image.data + f.cels[project.current_layer - 1].image.data ) - Global.current_project.undo_redo.add_do_property(f, "cels", new_cels) - Global.current_project.undo_redo.add_undo_property(f, "cels", f.cels) + var top_cels := [] + for f in project.frames: + top_cels.append(f.cels[project.current_layer]) - new_layers.remove(Global.current_project.current_layer) - Global.current_project.undo_redo.add_do_property( - Global.current_project, "current_layer", Global.current_project.current_layer - 1 + project.undo_redo.add_do_property(project, "current_layer", project.current_layer - 1) + project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) + project.undo_redo.add_do_property( + project.layers[project.current_layer - 1], "linked_cels", new_bottom_linked_cels ) - Global.current_project.undo_redo.add_do_property(Global.current_project, "layers", new_layers) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "layers", Global.current_project.layers + project.undo_redo.add_undo_property( + project.layers[project.current_layer - 1], + "linked_cels", + project.layers[project.current_layer - 1].linked_cels ) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "current_layer", Global.current_project.current_layer + project.undo_redo.add_do_method(project, "remove_layers", [project.current_layer]) + project.undo_redo.add_undo_method( + project, "add_layers", + [project.layers[project.current_layer]], [project.current_layer], [top_cels] ) - - Global.current_project.undo_redo.add_undo_method(Global, "undo_or_redo", true) - Global.current_project.undo_redo.add_do_method(Global, "undo_or_redo", false) - Global.current_project.undo_redo.commit_action() + project.undo_redo.add_undo_method(Global, "undo_or_redo", true) + project.undo_redo.add_do_method(Global, "undo_or_redo", false) + project.undo_redo.commit_action() func _on_OpacitySlider_value_changed(value) -> void: diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index 3a5b39555265..2f633bc8e24a 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -123,6 +123,9 @@ func _on_PopupMenu_id_pressed(id: int) -> void: new_layers[layer].linked_cels.remove(cel_index) var sprite := Image.new() sprite.copy_from(f.cels[layer].image) + # TODO L: In PixelCel's image setter, setting the iamge already calls create_from_image on the texture, + # so I think its getting called twice, setting the new image texture first and then setting + # the image should work without having to call create_from_image here: var sprite_texture := ImageTexture.new() sprite_texture.create_from_image(sprite, 0) new_cels[layer].image = sprite From 593c9283fda9d32c1f3eb532c4171390fe992ed7 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 14 Jul 2022 14:20:58 -0400 Subject: [PATCH 051/154] Cleaned up _on_MergeDownLayer_pressed refactor --- src/UI/Timeline/AnimationTimeline.gd | 122 ++++++--------------------- 1 file changed, 26 insertions(+), 96 deletions(-) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index ffb2d2a024f2..dc836a3ef04f 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -704,70 +704,11 @@ func change_layer_order(rate: int) -> void: Global.current_project.undo_redo.commit_action() -#func _on_MergeDownLayer_pressed() -> void: -# var project: Project = Global.current_project -# var new_layers: Array = project.duplicate_layers() -# -# project.undos += 1 -# project.undo_redo.create_action("Merge Layer") -# for f in project.frames: -# var new_cels: Array = f.cels.duplicate() -# for i in new_cels.size(): -# new_cels[i] = PixelCel.new(new_cels[i].image, new_cels[i].opacity) -# # TODO Later: top_image here doesn't really need to be a copy if there isn't layer transparency -# # though this probably will be rewriten with blend modes anyway... -# var top_image := Image.new() -# top_image.copy_from(new_cels[project.current_layer].image) -# -# top_image.lock() -# if f.cels[project.current_layer].opacity < 1: # If we have layer transparency -# for xx in top_image.get_size().x: -# for yy in top_image.get_size().y: -# var pixel_color: Color = top_image.get_pixel(xx, yy) -# var alpha: float = pixel_color.a * f.cels[project.current_layer].opacity -# top_image.set_pixel( -# xx, yy, Color(pixel_color.r, pixel_color.g, pixel_color.b, alpha) -# ) -# top_image.unlock() -# -# var bottom_image := Image.new() -# bottom_image.copy_from(f.cels[project.current_layer - 1].image) -# bottom_image.blend_rect(top_image, Rect2(Vector2.ZERO, project.size), Vector2.ZERO) -# new_cels.remove(project.current_layer) # TODO NOTE: Removign the cel here -# if ( -# !top_image.is_invisible() -# and project.layers[project.current_layer - 1].linked_cels.size() > 1 -# and f in project.layers[project.current_layer - 1].linked_cels -# ): -# new_layers[project.current_layer - 1].linked_cels.erase(f) -# new_cels[project.current_layer - 1].image = bottom_image -# else: -# project.undo_redo.add_do_property( -# f.cels[project.current_layer - 1].image, "data", bottom_image.data -# ) -# project.undo_redo.add_undo_property( -# f.cels[project.current_layer - 1].image, -# "data", -# f.cels[project.current_layer - 1].image.data -# ) -# -# project.undo_redo.add_do_property(f, "cels", new_cels) -# project.undo_redo.add_undo_property(f, "cels", f.cels) -# -# new_layers.remove(project.current_layer) -# project.undo_redo.add_do_property(project, "current_layer", project.current_layer - 1) -# project.undo_redo.add_do_property(project, "layers", new_layers) -# project.undo_redo.add_undo_property(project, "layers", project.layers) -# project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) -# -# project.undo_redo.add_undo_method(Global, "undo_or_redo", true) -# project.undo_redo.add_do_method(Global, "undo_or_redo", false) -# project.undo_redo.commit_action() - - func _on_MergeDownLayer_pressed() -> void: var project: Project = Global.current_project - var new_bottom_linked_cels: Array = project.layers[project.current_layer - 1].linked_cels.duplicate() + var top_layer: PixelLayer = project.layers[project.current_layer] + var bottom_layer : PixelLayer = project.layers[project.current_layer - 1] + var new_linked_cels: Array = bottom_layer.linked_cels.duplicate() project.undos += 1 project.undo_redo.create_action("Merge Layer") @@ -776,65 +717,54 @@ func _on_MergeDownLayer_pressed() -> void: # TODO Later: top_image here doesn't really need to be a copy if there isn't layer transparency # though this probably will be rewriten with blend modes anyway... var top_image := Image.new() - top_image.copy_from(f.cels[project.current_layer].image) + top_image.copy_from(f.cels[top_layer.index].image) top_image.lock() - if f.cels[project.current_layer].opacity < 1: # If we have layer transparency + if f.cels[top_layer.index].opacity < 1: # If we have layer transparency for xx in top_image.get_size().x: for yy in top_image.get_size().y: var pixel_color: Color = top_image.get_pixel(xx, yy) - var alpha: float = pixel_color.a * f.cels[project.current_layer].opacity + var alpha: float = pixel_color.a * f.cels[top_layer.index].opacity top_image.set_pixel( xx, yy, Color(pixel_color.r, pixel_color.g, pixel_color.b, alpha) ) top_image.unlock() var bottom_image := Image.new() - bottom_image.copy_from(f.cels[project.current_layer - 1].image) + bottom_image.copy_from(f.cels[bottom_layer.index].image) bottom_image.blend_rect(top_image, Rect2(Vector2.ZERO, project.size), Vector2.ZERO) if ( !top_image.is_invisible() - and project.layers[project.current_layer - 1].linked_cels.size() > 1 - and f in project.layers[project.current_layer - 1].linked_cels + and bottom_layer.linked_cels.size() > 1 + and f in bottom_layer.linked_cels ): - new_bottom_linked_cels.erase(f) - - project.undo_redo.add_do_property(f.cels[project.current_layer - 1], "image_texture", ImageTexture.new()) - project.undo_redo.add_undo_property(f.cels[project.current_layer - 1], "image_texture", f.cels[project.current_layer - 1].image_texture) - - project.undo_redo.add_do_property(f.cels[project.current_layer - 1], "image", bottom_image) + new_linked_cels.erase(f) + project.undo_redo.add_do_property(f.cels[bottom_layer.index], "image_texture", ImageTexture.new()) + project.undo_redo.add_undo_property( + f.cels[bottom_layer.index], "image_texture", f.cels[bottom_layer.index].image_texture + ) + project.undo_redo.add_do_property(f.cels[bottom_layer.index], "image", bottom_image) project.undo_redo.add_undo_property( - f.cels[project.current_layer - 1], "image", f.cels[project.current_layer - 1].image + f.cels[bottom_layer.index], "image", f.cels[bottom_layer.index].image ) else: project.undo_redo.add_do_property( - f.cels[project.current_layer - 1].image, "data", bottom_image.data + f.cels[bottom_layer.index].image, "data", bottom_image.data ) project.undo_redo.add_undo_property( - f.cels[project.current_layer - 1].image, - "data", - f.cels[project.current_layer - 1].image.data + f.cels[bottom_layer.index].image, "data", f.cels[bottom_layer.index].image.data ) var top_cels := [] for f in project.frames: - top_cels.append(f.cels[project.current_layer]) - - project.undo_redo.add_do_property(project, "current_layer", project.current_layer - 1) - project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) - project.undo_redo.add_do_property( - project.layers[project.current_layer - 1], "linked_cels", new_bottom_linked_cels - ) - project.undo_redo.add_undo_property( - project.layers[project.current_layer - 1], - "linked_cels", - project.layers[project.current_layer - 1].linked_cels - ) - project.undo_redo.add_do_method(project, "remove_layers", [project.current_layer]) - project.undo_redo.add_undo_method( - project, "add_layers", - [project.layers[project.current_layer]], [project.current_layer], [top_cels] - ) + top_cels.append(f.cels[top_layer.index]) + + project.undo_redo.add_do_property(project, "current_layer", bottom_layer.index) + project.undo_redo.add_undo_property(project, "current_layer", top_layer.index) + project.undo_redo.add_do_property(bottom_layer, "linked_cels", new_linked_cels) + project.undo_redo.add_undo_property(bottom_layer, "linked_cels", bottom_layer.linked_cels) + project.undo_redo.add_do_method(project, "remove_layers", [top_layer.index]) + project.undo_redo.add_undo_method(project, "add_layers", [top_layer], [top_layer.index], [top_cels]) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.commit_action() From 5729f68de46f83d3bfd4af4cf5f9a9edc289ceb7 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 14 Jul 2022 19:26:02 -0400 Subject: [PATCH 052/154] If all frames are selected, prevent being able to remove all of them --- src/UI/Timeline/AnimationTimeline.gd | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index dc836a3ef04f..b8d99bfe841b 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -189,12 +189,13 @@ func _on_DeleteFrame_pressed(frame := -1) -> void: func delete_frames(frames := []) -> void: - # TODO R0: If there is mulitple frames, it is currently possible to select and delete them all var project: Project = Global.current_project if project.frames.size() == 1: return - if frames.size() == 0: + if frames.size() == project.frames.size(): + frames.remove(frames.size() - 1) # Ensure the project has at least 1 frame + elif frames.size() == 0: frames.append(project.current_frame) var new_frames: Array = project.frames.duplicate() @@ -214,8 +215,6 @@ func delete_frames(frames := []) -> void: ) for frame in frames: - if new_frames.size() == 1: # If only 1 frame - break var frame_to_delete: Frame = project.frames[frame] new_frames.erase(frame_to_delete) if current_frame > 0 && current_frame == new_frames.size(): # If it's the last frame @@ -643,7 +642,6 @@ func _on_CloneLayer_pressed() -> void: func _on_RemoveLayer_pressed() -> void: - # TODO R0: It is currently possible to delete all layers (by having all layers in a group and deleting the group) var project: Project = Global.current_project if project.layers.size() == 1: return @@ -784,23 +782,14 @@ func _on_OnionSkinningSettings_popup_hide() -> void: func project_changed() -> void: - # TODO R0: When changing project the selcted frames will be 1 less (1 further to the left) - # then they should be - # TODO R0: If you draw in the automatically created project, then load/create a new project, - # then going back to the automatically created project tab, you can't add/remove - # layers/frames (and probaly other issues). - # THIS HASN't BEEN REPEATED var project: Project = Global.current_project # TODO R3: maybe pass in instead? - # TODO R0: Could using queue_free rather than free (or remove and queue_free) actually cause bugs? - # This caused the bug where changing the project would have the wrong frame button - # selected, but only when move_children was not called + # These must be removed from tree immediately to not mess up the indices of the new buttons: for child in Global.layers_container.get_children(): - child.queue_free() + child.free() for child in Global.frame_ids.get_children(): -# child.queue_free() child.free() for container in Global.frames_container.get_children(): - container.queue_free() + container.free() for i in range(project.layers.size()): # TODO R2: Could this be faster if it did it in reverse order? project_layer_added(i) @@ -808,7 +797,6 @@ func project_changed() -> void: var button: Button = frame_button_node.instance() button.frame = f Global.frame_ids.add_child(button) -# Global.frame_ids.move_child(button, f) # TODO R0: Is this needed? Shouldn't they be in order already? (Perhaps commenting it out caused one of the above issues?) # TODO R3: Remove and inline what's needed here if this isn't used anywhere else: Global.current_project._update_animation_timeline_selection() @@ -853,7 +841,6 @@ func project_layer_added(layer: int) -> void: var layer_cel_container := HBoxContainer.new() # TODO R3: Is there any need for a name (and why is it LAYERSSS in one place, and FRAMESS in another?) - # TODO R0: Could the order here affect performance? layer_cel_container.name = "LAYERSSS " + str(layer) Global.frames_container.add_child(layer_cel_container) Global.frames_container.move_child(layer_cel_container, count - 1 - layer) From 1d77155a07ef9b0bceb248d0c85a0f47e7495358 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 14 Jul 2022 21:38:12 -0400 Subject: [PATCH 053/154] Fixed cel linking when cloning layers/frames. Moved the copy function from cel classes to layer classes, splitting into copy_cel and copy_all_cels --- src/Classes/BaseCel.gd | 4 --- src/Classes/BaseLayer.gd | 10 ++++++++ src/Classes/GroupCel.gd | 5 ---- src/Classes/GroupLayer.gd | 13 ++++++++++ src/Classes/PixelCel.gd | 14 +--------- src/Classes/PixelLayer.gd | 38 ++++++++++++++++++++++++++++ src/Classes/Project.gd | 4 +++ src/UI/Timeline/AnimationTimeline.gd | 16 ++++++------ 8 files changed, 74 insertions(+), 30 deletions(-) diff --git a/src/Classes/BaseCel.gd b/src/Classes/BaseCel.gd index 87e25e8b4150..7aedf5f3eccd 100644 --- a/src/Classes/BaseCel.gd +++ b/src/Classes/BaseCel.gd @@ -25,9 +25,5 @@ func load_image_data_from_pxo(_file: File, _project_size: Vector2) -> void: return -func copy() -> BaseCel: - return null - - func create_cel_button() -> Node: return null diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index 1d90d9da1e61..208e9303bca5 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -97,6 +97,16 @@ func copy() -> BaseLayer: copy.deserialize(serialize()) return copy + +func copy_cel(_frame: int, _new_content: bool) -> BaseCel: + return null + +# TODO R3: Currently new content is never needed to be false, should it be removed? +# Used to copy all cels with cel linking properly set up between copies: +func copy_all_cels(_new_content: bool) -> Array: + return [] + + # TODO L: Should this be turned into set_as_default_name? func get_default_name(number: int) -> String: return tr("Layer") + " %s" % number diff --git a/src/Classes/GroupCel.gd b/src/Classes/GroupCel.gd index 5f1d47037346..f1f5868e7432 100644 --- a/src/Classes/GroupCel.gd +++ b/src/Classes/GroupCel.gd @@ -12,10 +12,5 @@ func get_image() -> Image: return Image.new() -func copy() -> BaseCel: - # Using get_script over the class name prevents a cyclic reference: - return get_script().new(opacity) - - func create_cel_button() -> Node: return Global.group_cel_button_node.instance() diff --git a/src/Classes/GroupLayer.gd b/src/Classes/GroupLayer.gd index f42ff4e96ceb..77271bc160b5 100644 --- a/src/Classes/GroupLayer.gd +++ b/src/Classes/GroupLayer.gd @@ -21,6 +21,19 @@ func deserialize(dict: Dictionary) -> void: expanded = dict.expanded +func copy_cel(frame_index: int, _new_content: bool) -> BaseCel: + var cel: GroupCel = project.frames[frame_index].cels[index] + return GroupCel.new(cel.opacity) + + +func copy_all_cels(_new_content: bool) -> Array: + var cels := [] + for frame in project.frames: + var cel: GroupCel = frame.cels[index] + cels.append(GroupCel.new(cel.opacity)) + return cels + + func get_default_name(number: int) -> String: return tr("Group") + " %s" % number diff --git a/src/Classes/PixelCel.gd b/src/Classes/PixelCel.gd index ac703e1279ae..ac6187e6b7c0 100644 --- a/src/Classes/PixelCel.gd +++ b/src/Classes/PixelCel.gd @@ -12,7 +12,7 @@ func _init(_image := Image.new(), _opacity := 1.0, _image_texture: ImageTexture image_texture = _image_texture else: image_texture = ImageTexture.new() - self.image = _image + self.image = _image # Set image and call setter opacity = _opacity @@ -35,18 +35,6 @@ func load_image_data_from_pxo(file: File, project_size: Vector2) -> void: image.create_from_data(project_size.x, project_size.y, false, Image.FORMAT_RGBA8, buffer) image_changed(image) -# TODO R3: A copy_image bool parameter could be useful for places such as the merging layers function -# where the copied cels don't need the image to be copied (at least not yet in that case) -# Alternatively, keep it as is, and maybe put a comment on the copy function mentioning that it -# copies the image data too... -func copy() -> BaseCel: - var copy_image := Image.new() - copy_image.copy_from(image) - var copy_texture := ImageTexture.new() - copy_texture.create_from_image(copy_image, 0) - # Using get_script over the class name prevents a cyclic reference: - return get_script().new(copy_image, opacity, copy_texture) - func create_cel_button() -> Node: var cel_button = Global.pixel_cel_button_node.instance() diff --git a/src/Classes/PixelLayer.gd b/src/Classes/PixelLayer.gd index 1396d394c9ba..83b6c83b8457 100644 --- a/src/Classes/PixelLayer.gd +++ b/src/Classes/PixelLayer.gd @@ -32,6 +32,44 @@ func deserialize(dict: Dictionary) -> void: linked_cel.image_texture = linked_cels[0].cels[index].image_texture +func copy_cel(frame_index: int, new_content: bool) -> BaseCel: + var cel: PixelCel = project.frames[frame_index].cels[index] + if new_content: + var copy_image := Image.new() + copy_image.copy_from(cel.image) + return PixelCel.new(copy_image, cel.opacity) + else: + return PixelCel.new(cel.image, cel.opacity, cel.image_texture) + + +func copy_all_cels(new_content: bool) -> Array: + var cels := [] + + var linked_image: Image + var linked_texture: ImageTexture + if not linked_cels.empty(): + var cel: PixelCel = linked_cels[0].cels[index] + if new_content: + linked_image = Image.new() + linked_image.copy_from(cel.image) + linked_texture = ImageTexture.new() + else: + linked_image = cel.image + linked_texture = cel.image_texture + + for frame in project.frames: + var cel: PixelCel = frame.cels[index] + if linked_cels.has(frame): + cels.append(PixelCel.new(linked_image, cel.opacity, linked_texture)) + elif new_content: + var copy_image := Image.new() + copy_image.copy_from(cel.image) + cels.append(PixelCel.new(copy_image, cel.opacity)) + else: + cels.append(PixelCel.new(cel.image, cel.opacity, cel.image_texture)) + return cels + + func can_layer_get_drawn() -> bool: return is_visible_in_hierarchy() && !is_locked_in_hierarchy() diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 47bc535941a3..c45256242d01 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -496,6 +496,10 @@ func _toggle_layer_buttons_layers() -> void: if layers[current_layer].is_locked_in_hierarchy(): Global.disable_button(Global.remove_layer_button, true) + # TODO R0: Figure out how to disable the remove layer button when a group that has all layers as chidlren + # is selected: + var current_layer_size = layers[current_layer].get_children_recursive().size() + 1 + if layers.size() == 1: Global.disable_button(Global.remove_layer_button, true) Global.disable_button(Global.move_up_layer_button, true) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index b8d99bfe841b..5a21226fdb5c 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -300,12 +300,16 @@ func copy_frames(frames := []) -> void: copied_frames.append(new_frame) var prev_frame: Frame = project.frames[frame] - for cel in prev_frame.cels: - new_frame.cels.append(cel.copy()) new_frame.duration = prev_frame.duration for l_i in range(new_layers.size()): - if new_layers[l_i].get("new_cels_linked"): # If the link button is pressed + # If the layer has new_cels_linked variable, and its true + var new_cels_linked: bool = new_layers[l_i].get("new_cels_linked") + + # Copy the cel, create new cel content if new cels aren't linked + new_frame.cels.append(new_layers[l_i].copy_cel(frame, !new_cels_linked)) + + if new_cels_linked: # If the link button is pressed new_layers[l_i].linked_cels.append(new_frame) new_frame.cels[l_i].image = new_layers[l_i].linked_cels[0].cels[l_i].image new_frame.cels[l_i].image_texture = new_layers[l_i].linked_cels[0].cels[l_i].image_texture @@ -624,11 +628,7 @@ func _on_CloneLayer_pressed() -> void: var project: Project = Global.current_project var l: BaseLayer = project.layers[project.current_layer].copy() l.name = str(project.layers[project.current_layer].name, " (", tr("copy"), ")") - var cels := [] - for f in project.frames: - cels.append(f.cels[project.current_layer].copy()) - - # TODO R0: Copies don't have linked cels properly set up... + var cels: Array = project.layers[project.current_layer].copy_all_cels(true) project.undos += 1 project.undo_redo.create_action("Add Layer") From f282cda1c457959d97f40b2c02ef3d55f7b44ec0 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sun, 17 Jul 2022 21:02:12 -0400 Subject: [PATCH 054/154] Combined and rewrote the 2 project _toggle_layer_buttons_.. functions into 1 simpler _toggle_layer_buttons function --- src/Classes/Project.gd | 66 ++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 44 deletions(-) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index c45256242d01..266cbcdee3d8 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -144,8 +144,7 @@ func change_project() -> void: Global.disable_button( Global.move_right_frame_button, frames.size() == 1 or current_frame == frames.size() - 1 ) - _toggle_layer_buttons_layers() - _toggle_layer_buttons_current_layer() + _toggle_layer_buttons() self.animation_tags = animation_tags @@ -414,7 +413,7 @@ func _layers_changed(value: Array) -> void: # ) # layer_button.pressed = true # self.current_frame = current_frame # Call frame_changed to update UI - _toggle_layer_buttons_layers() + _toggle_layer_buttons() func _remove_cel_buttons() -> void: @@ -474,7 +473,7 @@ func _layer_changed(value: int) -> void: Global.canvas.selection.transform_content_confirm() current_layer = value - _toggle_layer_buttons_current_layer() + _toggle_layer_buttons() yield(Global.get_tree().create_timer(0.01), "timeout") self.current_frame = current_frame # Call frame_changed to update UI @@ -490,44 +489,23 @@ func _layer_changed(value: int) -> void: layer_button.pressed = true -func _toggle_layer_buttons_layers() -> void: - if !layers: +func _toggle_layer_buttons() -> void: + if layers.empty() or current_layer >= layers.size(): return - if layers[current_layer].is_locked_in_hierarchy(): - Global.disable_button(Global.remove_layer_button, true) + # The size of the current layer (1) plus its children: + var current_layer_size: int = 1 + layers[current_layer].get_children_recursive().size() - # TODO R0: Figure out how to disable the remove layer button when a group that has all layers as chidlren - # is selected: - var current_layer_size = layers[current_layer].get_children_recursive().size() + 1 - - if layers.size() == 1: - Global.disable_button(Global.remove_layer_button, true) - Global.disable_button(Global.move_up_layer_button, true) - Global.disable_button(Global.move_down_layer_button, true) - Global.disable_button(Global.merge_down_layer_button, true) - elif !layers[current_layer].is_locked_in_hierarchy(): - Global.disable_button(Global.remove_layer_button, false) - - -func _toggle_layer_buttons_current_layer() -> void: - if current_layer < layers.size() - 1: - Global.disable_button(Global.move_up_layer_button, false) - else: - Global.disable_button(Global.move_up_layer_button, true) - - if current_layer > 0: - Global.disable_button(Global.move_down_layer_button, false) - Global.disable_button(Global.merge_down_layer_button, false) - else: - Global.disable_button(Global.move_down_layer_button, true) - Global.disable_button(Global.merge_down_layer_button, true) - - if current_layer < layers.size(): - if layers[current_layer].is_locked_in_hierarchy(): - Global.disable_button(Global.remove_layer_button, true) - else: - if layers.size() > 1: - Global.disable_button(Global.remove_layer_button, false) + Global.disable_button(Global.remove_layer_button, + layers[current_layer].is_locked_in_hierarchy() + or layers.size() == current_layer_size + ) + Global.disable_button(Global.move_up_layer_button, current_layer == layers.size() - 1) + Global.disable_button(Global.move_down_layer_button, current_layer == current_layer_size - 1) + Global.disable_button(Global.merge_down_layer_button, + current_layer == current_layer_size - 1 + or layers[current_layer] is GroupLayer + or layers[current_layer - 1] is GroupLayer + ) func _animation_tags_changed(value: Array) -> void: @@ -864,7 +842,7 @@ func add_layers(new_layers: Array, indices: Array, cels: Array) -> void: # cels for f in range(frames.size()): layer_cel_container.get_child(f).layer = l layer_cel_container.get_child(f).button_setup() - _toggle_layer_buttons_layers() + _toggle_layer_buttons() func remove_layers(indices: Array) -> void: @@ -883,7 +861,7 @@ func remove_layers(indices: Array) -> void: for f in range(frames.size()): layer_cel_container.get_child(f).layer = l layer_cel_container.get_child(f).button_setup() - _toggle_layer_buttons_layers() + _toggle_layer_buttons() # from_indices and to_indicies should be in ascending order @@ -914,7 +892,7 @@ func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> v for f in range(frames.size()): layer_cel_container.get_child(f).layer = l layer_cel_container.get_child(f).button_setup() - _toggle_layer_buttons_layers() + _toggle_layer_buttons() # "a" and "b" should both contain "from", "to", and "to_parents" arrays. @@ -962,7 +940,7 @@ func swap_layers(a: Dictionary, b: Dictionary) -> void: for f in range(frames.size()): layer_cel_container.get_child(f).layer = l layer_cel_container.get_child(f).button_setup() - _toggle_layer_buttons_layers() + _toggle_layer_buttons() func move_cel(from_frame: int, to_frame: int, layer: int) -> void: From bf3a61dd6f277f7be76c5ea675546db1beab4815 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sun, 17 Jul 2022 22:27:45 -0400 Subject: [PATCH 055/154] Simplified _toggle_layer_buttons some more --- src/Classes/Project.gd | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 266cbcdee3d8..23d2ff8d98f6 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -492,17 +492,16 @@ func _layer_changed(value: int) -> void: func _toggle_layer_buttons() -> void: if layers.empty() or current_layer >= layers.size(): return - # The size of the current layer (1) plus its children: - var current_layer_size: int = 1 + layers[current_layer].get_children_recursive().size() + var child_count: int = layers[current_layer].get_children_recursive().size() Global.disable_button(Global.remove_layer_button, layers[current_layer].is_locked_in_hierarchy() - or layers.size() == current_layer_size + or layers.size() == child_count + 1 ) Global.disable_button(Global.move_up_layer_button, current_layer == layers.size() - 1) - Global.disable_button(Global.move_down_layer_button, current_layer == current_layer_size - 1) + Global.disable_button(Global.move_down_layer_button, current_layer == child_count) Global.disable_button(Global.merge_down_layer_button, - current_layer == current_layer_size - 1 + current_layer == child_count or layers[current_layer] is GroupLayer or layers[current_layer - 1] is GroupLayer ) From 22bf2c9b8e966841511e2680a54f27259a4021e5 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Mon, 18 Jul 2022 20:01:43 -0400 Subject: [PATCH 056/154] Added hierarchy support for move up/down layer buttons --- src/Classes/Project.gd | 5 +- src/UI/Timeline/AnimationTimeline.gd | 82 ++++++++++++++++---------- src/UI/Timeline/AnimationTimeline.tscn | 18 +++--- 3 files changed, 64 insertions(+), 41 deletions(-) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 23d2ff8d98f6..8807513b0994 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -499,7 +499,10 @@ func _toggle_layer_buttons() -> void: or layers.size() == child_count + 1 ) Global.disable_button(Global.move_up_layer_button, current_layer == layers.size() - 1) - Global.disable_button(Global.move_down_layer_button, current_layer == child_count) + Global.disable_button(Global.move_down_layer_button, + current_layer == child_count + and not is_instance_valid(layers[current_layer].parent) + ) Global.disable_button(Global.merge_down_layer_button, current_layer == child_count or layers[current_layer] is GroupLayer diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 5a21226fdb5c..7f0596088cfb 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -669,37 +669,56 @@ func _on_RemoveLayer_pressed() -> void: project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.commit_action() -# TODO L: Refactor this (maybe completely remove) -func change_layer_order(rate: int) -> void: - var change = Global.current_project.current_layer + rate - - var new_layers: Array = Global.current_project.layers.duplicate() - var temp = new_layers[Global.current_project.current_layer] - new_layers[Global.current_project.current_layer] = new_layers[change] - new_layers[change] = temp - Global.current_project.undo_redo.create_action("Change Layer Order") - for f in Global.current_project.frames: - var new_cels: Array = f.cels.duplicate() - var temp_canvas = new_cels[Global.current_project.current_layer] - new_cels[Global.current_project.current_layer] = new_cels[change] - new_cels[change] = temp_canvas - Global.current_project.undo_redo.add_do_property(f, "cels", new_cels) - Global.current_project.undo_redo.add_undo_property(f, "cels", f.cels) - - Global.current_project.undo_redo.add_do_property( - Global.current_project, "current_layer", change - ) - Global.current_project.undo_redo.add_do_property(Global.current_project, "layers", new_layers) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "layers", Global.current_project.layers - ) - Global.current_project.undo_redo.add_undo_property( - Global.current_project, "current_layer", Global.current_project.current_layer - ) - Global.current_project.undo_redo.add_undo_method(Global, "undo_or_redo", true) - Global.current_project.undo_redo.add_do_method(Global, "undo_or_redo", false) - Global.current_project.undo_redo.commit_action() +func change_layer_order(up: bool) -> void: + var project: Project = Global.current_project + var layer: BaseLayer = project.layers[project.current_layer] + var to_index = layer.index + var child_count = layer.get_children_recursive().size() + var from_indices := range(layer.index - child_count, layer.index + 1) + var from_parents := [] + for l in from_indices: + from_parents.append(project.layers[l].parent) + var to_parents := from_parents.duplicate() + + if up: + var above_layer: BaseLayer = project.layers[project.current_layer + 1] + if layer.parent == above_layer: # Above is the parent, leave the parent + to_parents[-1] = above_layer.parent + to_index = layer.index + 1 + elif layer.parent != above_layer.parent: # Above layer must be deeper in the hierarchy + to_parents[-1] = above_layer.parent # (this may be more than 1 level deeper) + while to_parents[-1].parent != layer.parent: + to_parents[-1]= to_parents[-1].parent # Incase we went multiple levels, drop extra + elif above_layer.accepts_child(layer): + to_parents[-1] = above_layer + else: + to_index = layer.index + 1 + else: # Down + if layer.index == child_count: # If at the very bottom of the layer stack + if not is_instance_valid(layer.parent): + return + to_parents[-1] = layer.parent.parent # Drop a level in the hierarchy + else: + var below_layer: BaseLayer = project.layers[project.current_layer - 1 - child_count] + if layer.parent != below_layer.parent: # If there is a hierarchy change + to_parents[-1] = below_layer.parent + elif below_layer.accepts_child(layer): + to_parents[-1] = below_layer + to_index = layer.index - 1 + else: + to_index = layer.index - 1 + + var to_indices := range(to_index - child_count, to_index + 1) + + project.undo_redo.create_action("Change Layer Order") + project.undo_redo.add_do_property(project, "current_layer", to_index) + project.undo_redo.add_do_method(project, "move_layers", from_indices, to_indices, to_parents) + project.undo_redo.add_undo_method(project, "move_layers", to_indices, from_indices, from_parents) + project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) + project.undo_redo.add_undo_method(Global, "undo_or_redo", true) + project.undo_redo.add_do_method(Global, "undo_or_redo", false) + project.undo_redo.commit_action() func _on_MergeDownLayer_pressed() -> void: @@ -711,6 +730,9 @@ func _on_MergeDownLayer_pressed() -> void: project.undos += 1 project.undo_redo.create_action("Merge Layer") + # TODO R0: When there is a group layer/cel present in the tree, merging down Pixel Layers + # doesn't get the texture updated. (Image is updated though, doing something else will update texture) + for f in project.frames: # TODO Later: top_image here doesn't really need to be a copy if there isn't layer transparency # though this probably will be rewriten with blend modes anyway... diff --git a/src/UI/Timeline/AnimationTimeline.tscn b/src/UI/Timeline/AnimationTimeline.tscn index f6f9e253d78d..ad6e1804644c 100644 --- a/src/UI/Timeline/AnimationTimeline.tscn +++ b/src/UI/Timeline/AnimationTimeline.tscn @@ -219,7 +219,6 @@ __meta__ = { } [node name="MoveUpLayer" type="Button" parent="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]] -visible = false margin_left = 93.0 margin_right = 115.0 margin_bottom = 22.0 @@ -246,9 +245,8 @@ __meta__ = { } [node name="MoveDownLayer" type="Button" parent="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]] -visible = false -margin_left = 93.0 -margin_right = 115.0 +margin_left = 124.0 +margin_right = 146.0 margin_bottom = 22.0 rect_min_size = Vector2( 22, 22 ) hint_tooltip = "Move down the current layer" @@ -273,8 +271,8 @@ __meta__ = { } [node name="CloneLayer" type="Button" parent="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]] -margin_left = 93.0 -margin_right = 115.0 +margin_left = 155.0 +margin_right = 177.0 margin_bottom = 22.0 rect_min_size = Vector2( 22, 22 ) hint_tooltip = "Clone current layer" @@ -298,8 +296,8 @@ __meta__ = { } [node name="MergeDownLayer" type="Button" parent="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]] -margin_left = 124.0 -margin_right = 146.0 +margin_left = 186.0 +margin_right = 208.0 margin_bottom = 22.0 rect_min_size = Vector2( 22, 22 ) hint_tooltip = "Merge current layer with the one below" @@ -1041,8 +1039,8 @@ color = Color( 0, 0.741176, 1, 0.501961 ) [connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/AddLayer" to="." method="_on_AddLayer_pressed"] [connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/AddGroup" to="." method="_on_AddGroup_pressed"] [connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/RemoveLayer" to="." method="_on_RemoveLayer_pressed"] -[connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/MoveUpLayer" to="." method="change_layer_order" binds= [ 1 ]] -[connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/MoveDownLayer" to="." method="change_layer_order" binds= [ -1 ]] +[connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/MoveUpLayer" to="." method="change_layer_order" binds= [ true ]] +[connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/MoveDownLayer" to="." method="change_layer_order" binds= [ false ]] [connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/CloneLayer" to="." method="_on_CloneLayer_pressed"] [connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/MergeDownLayer" to="." method="_on_MergeDownLayer_pressed"] [connection signal="pressed" from="ScrollContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/AddFrame" to="." method="add_frame"] From 1dfa0ed357a1c3d852844c427b858408b1c3a93f Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Mon, 18 Jul 2022 20:14:58 -0400 Subject: [PATCH 057/154] Added toggle_frame_buttons method to project (extracted from _frame_changed). Called from main when setting up startup project. Removed _ from start of _toggle_layer_buttons name --- src/Classes/Project.gd | 32 +++++++++++++++++--------------- src/Main.gd | 2 +- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 8807513b0994..855b169f8513 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -144,7 +144,7 @@ func change_project() -> void: Global.disable_button( Global.move_right_frame_button, frames.size() == 1 or current_frame == frames.size() - 1 ) - _toggle_layer_buttons() + toggle_layer_buttons() self.animation_tags = animation_tags @@ -413,7 +413,7 @@ func _layers_changed(value: Array) -> void: # ) # layer_button.pressed = true # self.current_frame = current_frame # Call frame_changed to update UI - _toggle_layer_buttons() + toggle_layer_buttons() func _remove_cel_buttons() -> void: @@ -453,18 +453,12 @@ func _frame_changed(value: int) -> void: var cel_button = container.get_child(frame) cel_button.pressed = true - # TODO R0: When starting up, with only one frame, these aren't getting called: - Global.disable_button(Global.remove_frame_button, frames.size() == 1) - Global.disable_button(Global.move_left_frame_button, frames.size() == 1 or current_frame == 0) - Global.disable_button( - Global.move_right_frame_button, frames.size() == 1 or current_frame == frames.size() - 1 - ) - if current_frame < frames.size(): var cel_opacity: float = frames[current_frame].cels[current_layer].opacity Global.layer_opacity_slider.value = cel_opacity * 100 Global.layer_opacity_spinbox.value = cel_opacity * 100 + toggle_frame_buttons() Global.canvas.update() Global.transparent_checker.update_rect() @@ -473,7 +467,7 @@ func _layer_changed(value: int) -> void: Global.canvas.selection.transform_content_confirm() current_layer = value - _toggle_layer_buttons() + toggle_layer_buttons() yield(Global.get_tree().create_timer(0.01), "timeout") self.current_frame = current_frame # Call frame_changed to update UI @@ -489,7 +483,15 @@ func _layer_changed(value: int) -> void: layer_button.pressed = true -func _toggle_layer_buttons() -> void: +func toggle_frame_buttons() -> void: + Global.disable_button(Global.remove_frame_button, frames.size() == 1) + Global.disable_button(Global.move_left_frame_button, frames.size() == 1 or current_frame == 0) + Global.disable_button( + Global.move_right_frame_button, frames.size() == 1 or current_frame == frames.size() - 1 + ) + + +func toggle_layer_buttons() -> void: if layers.empty() or current_layer >= layers.size(): return var child_count: int = layers[current_layer].get_children_recursive().size() @@ -844,7 +846,7 @@ func add_layers(new_layers: Array, indices: Array, cels: Array) -> void: # cels for f in range(frames.size()): layer_cel_container.get_child(f).layer = l layer_cel_container.get_child(f).button_setup() - _toggle_layer_buttons() + toggle_layer_buttons() func remove_layers(indices: Array) -> void: @@ -863,7 +865,7 @@ func remove_layers(indices: Array) -> void: for f in range(frames.size()): layer_cel_container.get_child(f).layer = l layer_cel_container.get_child(f).button_setup() - _toggle_layer_buttons() + toggle_layer_buttons() # from_indices and to_indicies should be in ascending order @@ -894,7 +896,7 @@ func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> v for f in range(frames.size()): layer_cel_container.get_child(f).layer = l layer_cel_container.get_child(f).button_setup() - _toggle_layer_buttons() + toggle_layer_buttons() # "a" and "b" should both contain "from", "to", and "to_parents" arrays. @@ -942,7 +944,7 @@ func swap_layers(a: Dictionary, b: Dictionary) -> void: for f in range(frames.size()): layer_cel_container.get_child(f).layer = l layer_cel_container.get_child(f).button_setup() - _toggle_layer_buttons() + toggle_layer_buttons() func move_cel(from_frame: int, to_frame: int, layer: int) -> void: diff --git a/src/Main.gd b/src/Main.gd index 7a69685df3e4..4bd549915f70 100644 --- a/src/Main.gd +++ b/src/Main.gd @@ -26,7 +26,7 @@ func _ready() -> void: Global.current_project.layers[0].project = Global.current_project Global.current_project.frames.append(Global.current_project.new_empty_frame()) Global.animation_timeline.project_changed() # TODO R2: would it be a good idea to remove this, and the intial buttons back into the timeiline scene? - + Global.current_project.toggle_frame_buttons() # TODO R3: I Think this line should be safe to remove: (calling setter, already called when appending the layer) # Global.current_project.layers = Global.current_project.layers From 4714b96ab459ab0187335f8880b62b7c2f498691 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Tue, 19 Jul 2022 17:33:50 -0400 Subject: [PATCH 058/154] Fixed duplicate_layers parent references being to the original layers --- src/Classes/Project.gd | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 855b169f8513..9265ae14971f 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -584,13 +584,14 @@ func is_empty() -> bool: func duplicate_layers() -> Array: - # TODO R1: May want to test this a bit after refactor - # TODO H: When duplicating the layers, parent references would be using the old layers now, this will probably cause bugs var new_layers: Array = layers.duplicate() # Loop through the array to create new classes for each element, so that they # won't be the same as the original array's classes. Needed for undo/redo to work properly. for i in new_layers.size(): new_layers[i] = new_layers[i].copy() + for l in new_layers: + if is_instance_valid(l.parent): + l.parent = new_layers[l.parent.index] # Update the parent to the new copy of the parent return new_layers From e90878d1ec26096d72be54899f3250ec6849f992 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Tue, 19 Jul 2022 19:17:48 -0400 Subject: [PATCH 059/154] cleaned up project.move_layers method a bit --- src/Classes/Project.gd | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 9265ae14971f..b1027372e4b3 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -872,22 +872,21 @@ func remove_layers(indices: Array) -> void: # from_indices and to_indicies should be in ascending order func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> void: selected_cels.clear() - var old_layers := layers.duplicate() # TODO R1: Could maybe change to just empty layers array, using append(pop_at) trick like in swap_layers + var removed_layers := [] var removed_cels := [] # 2D array of cels (an array for each layer removed) - for i in range(from_indices.size()): + for i in from_indices.size(): # With each removed index, future indices need to be lowered, so subtract by i - layers.remove(from_indices[i] - i) + removed_layers.append(layers.pop_at(from_indices[i] - i)) + removed_layers[i].parent = to_parents[i] # parents must be set before UI created in next loop removed_cels.append([]) for frame in frames: removed_cels[i].append(frame.cels.pop_at(from_indices[i] - i)) Global.animation_timeline.project_layer_removed(from_indices[i] - i) - for i in range(to_indices.size()): - layers.insert(to_indices[i], old_layers[from_indices[i]]) - layers[to_indices[i]].parent = to_parents[i] # TODO R1: it could be possible to do the to_parents when removing (previous loop), allowing this loop to be recombined with the next + for i in to_indices.size(): + layers.insert(to_indices[i], removed_layers[i]) for f in range(frames.size()): frames[f].cels.insert(to_indices[i], removed_cels[i][f]) - for i in range(to_indices.size()): # Loop again (All parents must be set before adding the UI) Global.animation_timeline.project_layer_added(to_indices[i]) # Update the layer indices and layer/cel buttons: for l in range(layers.size()): From 0f58b0fe6707847a0b1c59ab25428f14f8a7a273 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 20 Jul 2022 11:37:26 -0400 Subject: [PATCH 060/154] TODOs --- src/Autoload/Global.gd | 4 ++-- src/Classes/BaseLayer.gd | 2 +- src/Classes/Project.gd | 25 ++++++++++++++++++++++--- src/Main.gd | 2 +- src/UI/Timeline/AnimationTimeline.gd | 4 ++-- src/UI/Timeline/LayerButton.gd | 3 +-- 6 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index 8d8052ff6bab..440aa2af8e51 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -259,7 +259,7 @@ func undo_or_redo( cursor_position_label.text = "[%s×%s]" % [project.size.x, project.size.y] elif "Frame" in action_name: - # TODO R2: Does what this comment says after the refacotr remain true? (Perhaps this should be moved to move_frame?) + # TODO R2: Does what this comment says after the refacotr remain true? # This actually means that frames.size is one, but it hasn't been updated yet if (undo and project.frames.size() == 2) or project.frames.size() == 1: # Stop animating play_forward.pressed = false @@ -267,7 +267,7 @@ func undo_or_redo( animation_timer.stop() elif "Move Cels" == action_name: - # TODO R2: is this still required? + # TODO R3: is this still required? (Looks safe to remove, unless something is added back to frames_changed) project.frames = project.frames # to call frames_changed canvas.update() diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index 208e9303bca5..e278b44f0ff0 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -97,7 +97,7 @@ func copy() -> BaseLayer: copy.deserialize(serialize()) return copy - +# TODO R3: Would linked be be better than new_content? (Have to reverse the branches of course) func copy_cel(_frame: int, _new_content: bool) -> BaseCel: return null diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index b1027372e4b3..fe33ded885db 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -396,7 +396,17 @@ func _size_changed(value: Vector2) -> void: func _frames_changed(value: Array) -> void: Global.canvas.selection.transform_content_confirm() frames = value -# selected_cels.clear() # TODO R2: Determine if this needs to be kept (If it is, selected cels needs to be intialized after creating project (ie: in Main), rather than here +# selected_cels.clear() # TODO R4: Determine if this needs to be kept (If it is, selected cels needs to be intialized after creating project (ie: in Main), rather than here + # TODO NOTE: perhaps if you don't clear the selected cels, some invalid ones may be included? (ie: removed cels?) + # selected cels is already cleared when using the new frame/layer/cel functions + # THESE SHOULD PROBABLY BE SAFE TO REMOVE FOR NORMAL USAGE, IS THERE A PLACE WHERE THEY'RE NOT? + # OTHER THAN ON STARTUP, IS THERE ANY DISADVANGTAGE TO KEEPING? (may be better to keep just to be sure) + print(selected_cels) + for c in selected_cels: + if c[0] >= frames.size(): + print("invalid frame in selected cel") + # REMOVE ALL THAT DEBUG CODE ^^^^^^^^^^^^^^^^ + _set_timeline_first_and_last_frames() @@ -406,8 +416,17 @@ func _layers_changed(value: Array) -> void: Global.layers_changed_skip = false return -# selected_cels.clear() # TODO R2: Determine if this needs to be kept (If it is, selected cels needs to be intialized after creating project (ie: in Main), rather than here - # TODO R2: investigate wether these are still required: +# selected_cels.clear() # TODO R4: Determine if this needs to be kept (If it is, selected cels needs to be intialized after creating project (ie: in Main), rather than here + # TODO NOTE: perhaps if you don't clear the selected cels, some invalid ones may be included? (ie: removed cels?) + # selected cels is already cleared when using the new frame/layer/cel functions + # THESE SHOULD PROBABLY BE SAFE TO REMOVE FOR NORMAL USAGE, IS THERE A PLACE WHERE THEY'RE NOT? + # OTHER THAN ON STARTUP, IS THERE ANY DISADVANGTAGE TO KEEPING? (may be better to keep just to be sure) + for c in selected_cels: + if c[1] >= layers.size(): + print("invalid layer in selected cel") + # REMOVE ALL THAT DEBUG CODE ^^^^^^^^^^^^^^^^ + + # TODO R4: investigate wether these are still required (Should be safe to remove): # var layer_button = Global.layers_container.get_child( # Global.layers_container.get_child_count() - 1 - current_layer # ) diff --git a/src/Main.gd b/src/Main.gd index 4bd549915f70..4ce5a7bf68f0 100644 --- a/src/Main.gd +++ b/src/Main.gd @@ -25,7 +25,7 @@ func _ready() -> void: Global.current_project.layers.append(PixelLayer.new()) Global.current_project.layers[0].project = Global.current_project Global.current_project.frames.append(Global.current_project.new_empty_frame()) - Global.animation_timeline.project_changed() # TODO R2: would it be a good idea to remove this, and the intial buttons back into the timeiline scene? + Global.animation_timeline.project_changed() Global.current_project.toggle_frame_buttons() # TODO R3: I Think this line should be safe to remove: (calling setter, already called when appending the layer) # Global.current_project.layers = Global.current_project.layers diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 7f0596088cfb..c334d25a5ce0 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -139,6 +139,7 @@ func add_frame() -> void: var new_layers: Array = project.duplicate_layers() for l_i in range(new_layers.size()): + # TODO H: Make sure this works with groups (Check out copy frames): if new_layers[l_i].new_cels_linked: # If the link button is pressed new_layers[l_i].linked_cels.append(frame) frame.cels[l_i].image = new_layers[l_i].linked_cels[0].cels[l_i].image @@ -622,7 +623,6 @@ func _on_AddGroup_pressed() -> void: func _on_CloneLayer_pressed() -> void: - # TODO L: Multiple layer support here would be nice Global.canvas.selection.transform_content_confirm() var project: Project = Global.current_project @@ -730,7 +730,7 @@ func _on_MergeDownLayer_pressed() -> void: project.undos += 1 project.undo_redo.create_action("Merge Layer") - # TODO R0: When there is a group layer/cel present in the tree, merging down Pixel Layers + # TODO H: When there is a group layer/cel present in the tree, merging down Pixel Layers # doesn't get the texture updated. (Image is updated though, doing something else will update texture) for f in project.frames: diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index 33d93de4ded8..52e613c3d80f 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -74,7 +74,7 @@ func _update_buttons() -> void: func _update_buttons_all_layers() -> void: - # TODO R2: would it be better to have specified range? (if so rename all_layers to for_layers) + # TODO R3: would it be better to have specified range? (if so rename all_layers to for_layers) # Maybe update_buttons_recursive (including children) is all we need? for layer_button in Global.layers_container.get_children(): layer_button._update_buttons() @@ -263,7 +263,6 @@ func drop_data(_pos, data) -> void: project.undo_redo.create_action("Change Layer Order") var new_layers: Array = project.layers.duplicate() - # TODO R1: Check for other loops that could be replaced with a range... # TODO R1: new_layers is a little confusing, does it acutally need to be duplicated anymore? It shouldn't be modified... # TODO R1: can this code be made easier to read? From 423da6fab28706b36bcead979299552d84eb0c1f Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 20 Jul 2022 11:46:29 -0400 Subject: [PATCH 061/154] moved the transform_content_confirm calls for the layer buttons in AnimationTimeline (Add/remove/clone) to the project layer modification functions --- src/Classes/Project.gd | 4 ++++ src/UI/Timeline/AnimationTimeline.gd | 9 ++------- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index fe33ded885db..293f6d1666ce 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -851,6 +851,7 @@ func swap_frame(a_index: int, b_index: int) -> void: func add_layers(new_layers: Array, indices: Array, cels: Array) -> void: # cels is 2d Array of cels assert(self == Global.current_project) # TODO R3: Remove (Things like calling project_frame/layer_added may need to do a check if its the current project if this fails) + Global.canvas.selection.transform_content_confirm() selected_cels.clear() for i in range(indices.size()): layers.insert(indices[i], new_layers[i]) @@ -870,6 +871,7 @@ func add_layers(new_layers: Array, indices: Array, cels: Array) -> void: # cels func remove_layers(indices: Array) -> void: + Global.canvas.selection.transform_content_confirm() selected_cels.clear() for i in range(indices.size()): # With each removed index, future indices need to be lowered, so subtract by i @@ -890,6 +892,7 @@ func remove_layers(indices: Array) -> void: # from_indices and to_indicies should be in ascending order func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> void: + Global.canvas.selection.transform_content_confirm() selected_cels.clear() var removed_layers := [] var removed_cels := [] # 2D array of cels (an array for each layer removed) @@ -921,6 +924,7 @@ func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> v # "a" and "b" should both contain "from", "to", and "to_parents" arrays. # (Using dictionaries because there seems to be a limit of 5 arguments for do/undo method calls) func swap_layers(a: Dictionary, b: Dictionary) -> void: + Global.canvas.selection.transform_content_confirm() selected_cels.clear() print("a: ", a, " b: ", b) # TODO R3: Remove var a_layers := [] diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index c334d25a5ce0..a6989c775da2 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -275,7 +275,6 @@ func _on_CopyFrame_pressed(frame := -1) -> void: func copy_frames(frames := []) -> void: - Global.canvas.selection.transform_content_confirm() var project: Project = Global.current_project if frames.size() == 0: @@ -522,8 +521,8 @@ func play_animation(play: bool, forward_dir: bool) -> void: func _on_NextFrame_pressed() -> void: - Global.canvas.selection.transform_content_confirm() - Global.current_project.selected_cels.clear() + Global.canvas.selection.transform_content_confirm() # TODO R4: These may be safe to remove, (frame_changed in project calls it) + Global.current_project.selected_cels.clear() # TODO NOTE: ^^ Though clearing the selected cels may mess that up. if Global.current_project.current_frame < Global.current_project.frames.size() - 1: Global.current_project.current_frame += 1 @@ -581,7 +580,6 @@ func _on_FuturePlacement_item_selected(index: int) -> void: func _on_AddLayer_pressed() -> void: - Global.canvas.selection.transform_content_confirm() # TODO R2: Figure out once and for all, do these belong here, or in the project reversable functions (where these will be called on undo as well) var project: Project = Global.current_project var l := PixelLayer.new() @@ -603,7 +601,6 @@ func _on_AddLayer_pressed() -> void: func _on_AddGroup_pressed() -> void: - Global.canvas.selection.transform_content_confirm() var project: Project = Global.current_project var l := GroupLayer.new() @@ -623,8 +620,6 @@ func _on_AddGroup_pressed() -> void: func _on_CloneLayer_pressed() -> void: - Global.canvas.selection.transform_content_confirm() - var project: Project = Global.current_project var l: BaseLayer = project.layers[project.current_layer].copy() l.name = str(project.layers[project.current_layer].name, " (", tr("copy"), ")") From 7f3d5c1f0bdad2178b8de65e948a145b52407b35 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 20 Jul 2022 12:30:19 -0400 Subject: [PATCH 062/154] animation first/last_frame tweaks and un-press play buttons when the first/last_frame are the same in _on_AnimationTimer_timeout in AnimationTimeline --- src/Autoload/Global.gd | 12 +++++++----- src/Classes/Project.gd | 5 +++++ src/UI/Timeline/AnimationTimeline.gd | 2 ++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index 440aa2af8e51..ac957c57581e 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -259,12 +259,14 @@ func undo_or_redo( cursor_position_label.text = "[%s×%s]" % [project.size.x, project.size.y] elif "Frame" in action_name: - # TODO R2: Does what this comment says after the refacotr remain true? + # TODO R4: This should be safe to remove after adding play_forwards/backwards.pressed = false to _on_AnimationTimer_timeout + # If not, does what this comment says after the refacotr remain true? # This actually means that frames.size is one, but it hasn't been updated yet - if (undo and project.frames.size() == 2) or project.frames.size() == 1: # Stop animating - play_forward.pressed = false - play_backwards.pressed = false - animation_timer.stop() +# if (undo and project.frames.size() == 2) or project.frames.size() == 1: # Stop animating +# play_forward.pressed = false +# play_backwards.pressed = false +# animation_timer.stop() + pass elif "Move Cels" == action_name: # TODO R3: is this still required? (Looks safe to remove, unless something is added back to frames_changed) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 293f6d1666ce..2a1ad58f58c8 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -565,6 +565,7 @@ func _set_timeline_first_and_last_frames() -> void: # when the play buttons get pressed anyway Global.animation_timeline.first_frame = 0 Global.animation_timeline.last_frame = frames.size() - 1 + # TODO NOTE: Perhaps its needed fo the play_only_tags bit? if Global.play_only_tags: for tag in animation_tags: if current_frame + 1 >= tag.from && current_frame + 1 <= tag.to: @@ -795,6 +796,7 @@ func add_frames(new_frames: Array, indices: Array) -> void: # indices should be for f in range(frames.size()): layer_cel_container.get_child(f).frame = f layer_cel_container.get_child(f).button_setup() + _set_timeline_first_and_last_frames() func remove_frames(indices: Array) -> void: # indices should be in ascending order @@ -815,6 +817,7 @@ func remove_frames(indices: Array) -> void: # indices should be in ascending or for f in range(frames.size()): layer_cel_container.get_child(f).frame = f layer_cel_container.get_child(f).button_setup() + _set_timeline_first_and_last_frames() func move_frame(from_index: int, to_index: int) -> void: @@ -835,6 +838,7 @@ func move_frame(from_index: int, to_index: int) -> void: for f in range(frames.size()): layer_cel_container.get_child(f).frame = f layer_cel_container.get_child(f).button_setup() + _set_timeline_first_and_last_frames() func swap_frame(a_index: int, b_index: int) -> void: @@ -847,6 +851,7 @@ func swap_frame(a_index: int, b_index: int) -> void: Global.animation_timeline.project_frame_added(a_index) Global.animation_timeline.project_frame_removed(b_index) Global.animation_timeline.project_frame_added(b_index) + _set_timeline_first_and_last_frames() func add_layers(new_layers: Array, indices: Array, cels: Array) -> void: # cels is 2d Array of cels diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index a6989c775da2..2e9fda0bf5ab 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -415,6 +415,8 @@ func _on_PlayBackwards_toggled(button_pressed: bool) -> void: func _on_AnimationTimer_timeout() -> void: if first_frame == last_frame: + Global.play_forward.pressed = false + Global.play_backwards.pressed = false $AnimationTimer.stop() return From 2c9382d6925188c43251d2f48b041a77ed6c429b Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 20 Jul 2022 12:36:06 -0400 Subject: [PATCH 063/154] Cleaned up project_changed in ANimationTimeline a bit --- src/UI/Timeline/AnimationTimeline.gd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 2e9fda0bf5ab..853deac58b7e 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -810,9 +810,9 @@ func project_changed() -> void: for container in Global.frames_container.get_children(): container.free() - for i in range(project.layers.size()): # TODO R2: Could this be faster if it did it in reverse order? + for i in project.layers.size(): project_layer_added(i) - for f in range(project.frames.size()): + for f in project.frames.size(): var button: Button = frame_button_node.instance() button.frame = f Global.frame_ids.add_child(button) From a1dfc7c114debbf11e599f77b7a6da5575e20e3d Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 20 Jul 2022 14:17:39 -0400 Subject: [PATCH 064/154] Cleaned up project_layer_added in AnimationTimeline --- src/UI/Timeline/AnimationTimeline.gd | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 853deac58b7e..9e376ef08fe6 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -848,30 +848,29 @@ func project_frame_removed(frame: int) -> void: func project_layer_added(layer: int) -> void: var project: Project = Global.current_project - # TODO R1: Could this function be organized in a better way? var layer_button: LayerButton = project.layers[layer].create_layer_button() - layer_button.layer = layer # TODO R1: See if needed + layer_button.layer = layer if project.layers[layer].name == "": # TODO R1: This probably could be somewhere else... add_layer(s) in project? project.layers[layer].name = project.layers[layer].get_default_name(layer) - Global.layers_container.add_child(layer_button) - var count := Global.layers_container.get_child_count() - Global.layers_container.move_child(layer_button, count - 1 - layer) - var layer_cel_container := HBoxContainer.new() # TODO R3: Is there any need for a name (and why is it LAYERSSS in one place, and FRAMESS in another?) layer_cel_container.name = "LAYERSSS " + str(layer) - Global.frames_container.add_child(layer_cel_container) - Global.frames_container.move_child(layer_cel_container, count - 1 - layer) for f in range(project.frames.size()): var cel_button = project.frames[f].cels[layer].create_cel_button() cel_button.frame = f - cel_button.layer = layer# - 1 # TODO R1: See if needed + cel_button.layer = layer layer_cel_container.add_child(cel_button) layer_button.visible = Global.current_project.layers[layer].is_expanded_in_hierarchy() layer_cel_container.visible = layer_button.visible + Global.layers_container.add_child(layer_button) + var count := Global.layers_container.get_child_count() + Global.layers_container.move_child(layer_button, count - 1 - layer) + Global.frames_container.add_child(layer_cel_container) + Global.frames_container.move_child(layer_cel_container, count - 1 - layer) + func project_layer_removed(layer: int) -> void: var count := Global.layers_container.get_child_count() From a65b4e6a9ffda224997fadb41ad2c4f369f46fe2 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 20 Jul 2022 14:21:14 -0400 Subject: [PATCH 065/154] Changed Layer classes get_default_name to set_name_to_default --- src/Classes/BaseLayer.gd | 5 ++--- src/Classes/GroupLayer.gd | 4 ++-- src/Classes/Project.gd | 3 +-- src/UI/Timeline/AnimationTimeline.gd | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index e278b44f0ff0..9a1b88b7bc79 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -107,9 +107,8 @@ func copy_all_cels(_new_content: bool) -> Array: return [] -# TODO L: Should this be turned into set_as_default_name? -func get_default_name(number: int) -> String: - return tr("Layer") + " %s" % number +func set_name_to_default(number: int) -> void: + name = tr("Layer") + " %s" % number func can_layer_get_drawn() -> bool: diff --git a/src/Classes/GroupLayer.gd b/src/Classes/GroupLayer.gd index 77271bc160b5..4c3a3dcb09dd 100644 --- a/src/Classes/GroupLayer.gd +++ b/src/Classes/GroupLayer.gd @@ -34,8 +34,8 @@ func copy_all_cels(_new_content: bool) -> Array: return cels -func get_default_name(number: int) -> String: - return tr("Group") + " %s" % number +func set_name_to_default(number: int) -> void: + name = tr("Group") + " %s" % number func accepts_child(_layer: BaseLayer) -> bool: diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 2a1ad58f58c8..71820a6a4c67 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -558,14 +558,13 @@ func _animation_tags_changed(value: Array) -> void: _set_timeline_first_and_last_frames() -# TODO R1: Is this really required in _frames_changed (or the add/remove frame funcs, seems to work fine without when playing anim) + func _set_timeline_first_and_last_frames() -> void: # This is useful in case tags get modified DURING the animation is playing # otherwise, this code is useless in this context, since these values are being set # when the play buttons get pressed anyway Global.animation_timeline.first_frame = 0 Global.animation_timeline.last_frame = frames.size() - 1 - # TODO NOTE: Perhaps its needed fo the play_only_tags bit? if Global.play_only_tags: for tag in animation_tags: if current_frame + 1 >= tag.from && current_frame + 1 <= tag.to: diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 9e376ef08fe6..db69986cdfe9 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -851,7 +851,7 @@ func project_layer_added(layer: int) -> void: var layer_button: LayerButton = project.layers[layer].create_layer_button() layer_button.layer = layer if project.layers[layer].name == "": # TODO R1: This probably could be somewhere else... add_layer(s) in project? - project.layers[layer].name = project.layers[layer].get_default_name(layer) + project.layers[layer].set_name_to_default(layer) var layer_cel_container := HBoxContainer.new() # TODO R3: Is there any need for a name (and why is it LAYERSSS in one place, and FRAMESS in another?) From df3cabd1b8761eb380c90d564760cd2ff39469e7 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 20 Jul 2022 14:32:09 -0400 Subject: [PATCH 066/154] Cleaned up LayerButton.drop_data slightly --- src/UI/Timeline/AnimationTimeline.gd | 2 +- src/UI/Timeline/LayerButton.gd | 27 ++++++++++++++------------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index db69986cdfe9..22ece247f508 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -850,7 +850,7 @@ func project_layer_added(layer: int) -> void: var layer_button: LayerButton = project.layers[layer].create_layer_button() layer_button.layer = layer - if project.layers[layer].name == "": # TODO R1: This probably could be somewhere else... add_layer(s) in project? + if project.layers[layer].name == "": project.layers[layer].set_name_to_default(layer) var layer_cel_container := HBoxContainer.new() diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index 52e613c3d80f..fe12d51acd02 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -261,21 +261,20 @@ func drop_data(_pos, data) -> void: var project = Global.current_project # TODO L: perhaps having a project variable for the enitre class would be nice (also for cel/frame buttons) project.undo_redo.create_action("Change Layer Order") - var new_layers: Array = project.layers.duplicate() + var layers: Array = project.layers # This shouldn't be modified directly - # TODO R1: new_layers is a little confusing, does it acutally need to be duplicated anymore? It shouldn't be modified... # TODO R1: can this code be made easier to read? - var drop_from_indices := range(drop_layer - new_layers[drop_layer].get_children_recursive().size(), drop_layer + 1 ) + var drop_from_indices := range(drop_layer - layers[drop_layer].get_children_recursive().size(), drop_layer + 1 ) var drop_from_parents := [] for i in range(drop_from_indices.size()): - drop_from_parents.append(new_layers[drop_from_indices[i]].parent) + drop_from_parents.append(layers[drop_from_indices[i]].parent) if Input.is_action_pressed("ctrl"): # Swap layers # a and b both need "from", "to", and "to_parents" # a is this layer (and children), b is the dropped layers - var a := { "from": range(layer - new_layers[layer].get_children_recursive().size(), layer + 1) } + var a := { "from": range(layer - layers[layer].get_children_recursive().size(), layer + 1) } var b := { "from": drop_from_indices} if a.from[0] < b.from[0]: @@ -287,7 +286,7 @@ func drop_data(_pos, data) -> void: var a_from_parents := [] for l in a.from: - a_from_parents.append(new_layers[l].parent) + a_from_parents.append(layers[l].parent) # to_parents starts as a dulpicate of from_parents, set the root layer's (with one layer or # group with its children, this will always be the last layer [-1]) parent to the other @@ -304,30 +303,32 @@ func drop_data(_pos, data) -> void: ) else: # Move layers + # TODO R1: would it make it more consistent (and easier to read) if to_index was changed + # to use the highest layer? var to_index: int # the index where the LOWEST shifted layer should end up var to_parent: BaseLayer # If accepted as a child, is it in the center region? - if (new_layers[layer].accepts_child(data[1]) + if (layers[layer].accepts_child(data[1]) and _get_region_rect(0.25, 0.75).has_point(get_global_mouse_position()) ): to_index = layer - to_parent = new_layers[layer] + to_parent = layers[layer] else: # Top or bottom region? if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): to_index = layer + 1 - to_parent = new_layers[layer].parent + to_parent = layers[layer].parent else: # Place under the layer, if it has children, place after its lowest child - if new_layers[layer].has_children(): - to_index = new_layers[layer].get_children_recursive()[0].index + if layers[layer].has_children(): + to_index = layers[layer].get_children_recursive()[0].index - if new_layers[layer].is_a_parent_of(new_layers[drop_layer]): + if layers[layer].is_a_parent_of(layers[drop_layer]): to_index += drop_from_indices.size() else: to_index = layer - to_parent = new_layers[layer].parent + to_parent = layers[layer].parent if drop_layer < layer: to_index -= drop_from_indices.size() From 4f75f300ae16353a3cbe70339499de46f237af51 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 20 Jul 2022 14:45:36 -0400 Subject: [PATCH 067/154] Looked at some of my TODOs --- src/Autoload/Global.gd | 2 +- src/Autoload/OpenSave.gd | 2 +- src/Classes/Project.gd | 3 --- src/Main.gd | 2 +- src/UI/Timeline/AnimationTimeline.gd | 7 +++---- src/UI/Timeline/LayerButton.gd | 2 +- src/UI/Timeline/PixelCelButton.gd | 2 +- 7 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index ac957c57581e..320d94e7c443 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -269,7 +269,7 @@ func undo_or_redo( pass elif "Move Cels" == action_name: - # TODO R3: is this still required? (Looks safe to remove, unless something is added back to frames_changed) + # TODO R4: is this still required? (Looks safe to remove, unless something is added back to frames_changed) project.frames = project.frames # to call frames_changed canvas.update() diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index 9fa2246830bc..a0f5ea8b323c 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -126,7 +126,7 @@ func open_pxo_file(path: String, untitled_backup: bool = false, replace_empty: b if dict.error == OK and dict.result.has("fps"): Global.animation_timeline.fps_spinbox.value = dict.result.fps Global.animation_timeline.project_changed() - # TODO R3: Do these need to be here? (Consider the bug where new project doesn't set the hidden frame buttons in frames_changed) + # TODO R4: Do these need to be here? (Consider the bug where new project doesn't set the hidden frame buttons in frames_changed) new_project.frames = new_project.frames # Just to call frames_changed new_project.layers = new_project.layers # Just to call layers_changed else: diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 71820a6a4c67..2a6182426914 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -779,7 +779,6 @@ func resize_bitmap_values(bitmap: BitMap, new_size: Vector2, flip_x: bool, flip_ func add_frames(new_frames: Array, indices: Array) -> void: # indices should be in ascending order - assert(self == Global.current_project) # TODO R3: Remove (Things like calling project_frame/layer_added may need to do a check if its the current project if this fails) Global.canvas.selection.transform_content_confirm() selected_cels.clear() for i in range(new_frames.size()): @@ -854,7 +853,6 @@ func swap_frame(a_index: int, b_index: int) -> void: func add_layers(new_layers: Array, indices: Array, cels: Array) -> void: # cels is 2d Array of cels - assert(self == Global.current_project) # TODO R3: Remove (Things like calling project_frame/layer_added may need to do a check if its the current project if this fails) Global.canvas.selection.transform_content_confirm() selected_cels.clear() for i in range(indices.size()): @@ -930,7 +928,6 @@ func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> v func swap_layers(a: Dictionary, b: Dictionary) -> void: Global.canvas.selection.transform_content_confirm() selected_cels.clear() - print("a: ", a, " b: ", b) # TODO R3: Remove var a_layers := [] var b_layers := [] var a_cels := [] # 2D array of cels (an array for each layer removed) diff --git a/src/Main.gd b/src/Main.gd index 4ce5a7bf68f0..3fe42122214c 100644 --- a/src/Main.gd +++ b/src/Main.gd @@ -27,7 +27,7 @@ func _ready() -> void: Global.current_project.frames.append(Global.current_project.new_empty_frame()) Global.animation_timeline.project_changed() Global.current_project.toggle_frame_buttons() - # TODO R3: I Think this line should be safe to remove: (calling setter, already called when appending the layer) + # TODO R4: I Think this line should be safe to remove: (calling setter, already called when appending the layer) # Global.current_project.layers = Global.current_project.layers Import.import_brushes(Global.directory_module.get_brushes_search_path_in_order()) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 22ece247f508..ac9b74bfca6d 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -657,7 +657,6 @@ func _on_RemoveLayer_pressed() -> void: project.undos += 1 project.undo_redo.create_action("Remove Layer") - # TODO R3: what should be the new current layer? project.undo_redo.add_do_property(project, "current_layer", max(indices[0] - 1, 0)) project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) project.undo_redo.add_do_method(project, "remove_layers", indices) @@ -801,7 +800,7 @@ func _on_OnionSkinningSettings_popup_hide() -> void: func project_changed() -> void: - var project: Project = Global.current_project # TODO R3: maybe pass in instead? + var project: Project = Global.current_project # These must be removed from tree immediately to not mess up the indices of the new buttons: for child in Global.layers_container.get_children(): child.free() @@ -817,12 +816,12 @@ func project_changed() -> void: button.frame = f Global.frame_ids.add_child(button) - # TODO R3: Remove and inline what's needed here if this isn't used anywhere else: + # TODO R4: Remove and inline what's needed here if this isn't used anywhere else: Global.current_project._update_animation_timeline_selection() func project_frame_added(frame: int) -> void: - var project: Project = Global.current_project # TODO R3: maybe pass in instead? + var project: Project = Global.current_project var button: Button = frame_button_node.instance() button.frame = frame Global.frame_ids.add_child(button) diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index fe12d51acd02..5d8b210dead8 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -74,7 +74,7 @@ func _update_buttons() -> void: func _update_buttons_all_layers() -> void: - # TODO R3: would it be better to have specified range? (if so rename all_layers to for_layers) + # TODO R4: would it be better to have specified range? (if so rename all_layers to for_layers) # Maybe update_buttons_recursive (including children) is all we need? for layer_button in Global.layers_container.get_children(): layer_button._update_buttons() diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index 2f633bc8e24a..e186444f0b9c 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -107,7 +107,7 @@ func _on_PopupMenu_id_pressed(id: int) -> void: MenuOptions.LINK: # TODO R3: If you do part of linked cels in add/remove frames, consider changes here: - # TODO R3: Make add_do/undo_property/method order consistent + # TODO R4: Make add_do/undo_property/method order consistent (and make sure it doesn't cause issues) var project: Project = Global.current_project var f: Frame = project.frames[frame] var cel_index: int = project.layers[layer].linked_cels.find(f) From 586a820f7ac648f2034d21af7d5d3235ab985cf7 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 20 Jul 2022 14:56:50 -0400 Subject: [PATCH 068/154] cleaned up copying cels --- src/Classes/BaseLayer.gd | 7 +++---- src/Classes/GroupLayer.gd | 4 ++-- src/Classes/PixelLayer.gd | 24 +++++++++--------------- src/UI/Timeline/AnimationTimeline.gd | 2 +- 4 files changed, 15 insertions(+), 22 deletions(-) diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index 9a1b88b7bc79..0a67d96db817 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -97,13 +97,12 @@ func copy() -> BaseLayer: copy.deserialize(serialize()) return copy -# TODO R3: Would linked be be better than new_content? (Have to reverse the branches of course) -func copy_cel(_frame: int, _new_content: bool) -> BaseCel: + +func copy_cel(_frame: int, _linked: bool) -> BaseCel: return null -# TODO R3: Currently new content is never needed to be false, should it be removed? # Used to copy all cels with cel linking properly set up between copies: -func copy_all_cels(_new_content: bool) -> Array: +func copy_all_cels() -> Array: return [] diff --git a/src/Classes/GroupLayer.gd b/src/Classes/GroupLayer.gd index 4c3a3dcb09dd..7fb0aa6d71f0 100644 --- a/src/Classes/GroupLayer.gd +++ b/src/Classes/GroupLayer.gd @@ -21,12 +21,12 @@ func deserialize(dict: Dictionary) -> void: expanded = dict.expanded -func copy_cel(frame_index: int, _new_content: bool) -> BaseCel: +func copy_cel(frame_index: int, _linked: bool) -> BaseCel: var cel: GroupCel = project.frames[frame_index].cels[index] return GroupCel.new(cel.opacity) -func copy_all_cels(_new_content: bool) -> Array: +func copy_all_cels() -> Array: var cels := [] for frame in project.frames: var cel: GroupCel = frame.cels[index] diff --git a/src/Classes/PixelLayer.gd b/src/Classes/PixelLayer.gd index 83b6c83b8457..e6e4dafdf78b 100644 --- a/src/Classes/PixelLayer.gd +++ b/src/Classes/PixelLayer.gd @@ -32,41 +32,35 @@ func deserialize(dict: Dictionary) -> void: linked_cel.image_texture = linked_cels[0].cels[index].image_texture -func copy_cel(frame_index: int, new_content: bool) -> BaseCel: +func copy_cel(frame_index: int, linked: bool) -> BaseCel: var cel: PixelCel = project.frames[frame_index].cels[index] - if new_content: + if linked: + return PixelCel.new(cel.image, cel.opacity, cel.image_texture) + else: var copy_image := Image.new() copy_image.copy_from(cel.image) return PixelCel.new(copy_image, cel.opacity) - else: - return PixelCel.new(cel.image, cel.opacity, cel.image_texture) -func copy_all_cels(new_content: bool) -> Array: +func copy_all_cels() -> Array: var cels := [] var linked_image: Image var linked_texture: ImageTexture if not linked_cels.empty(): var cel: PixelCel = linked_cels[0].cels[index] - if new_content: - linked_image = Image.new() - linked_image.copy_from(cel.image) - linked_texture = ImageTexture.new() - else: - linked_image = cel.image - linked_texture = cel.image_texture + linked_image = Image.new() + linked_image.copy_from(cel.image) + linked_texture = ImageTexture.new() for frame in project.frames: var cel: PixelCel = frame.cels[index] if linked_cels.has(frame): cels.append(PixelCel.new(linked_image, cel.opacity, linked_texture)) - elif new_content: + else: var copy_image := Image.new() copy_image.copy_from(cel.image) cels.append(PixelCel.new(copy_image, cel.opacity)) - else: - cels.append(PixelCel.new(cel.image, cel.opacity, cel.image_texture)) return cels diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index ac9b74bfca6d..6ba5f7e2609f 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -625,7 +625,7 @@ func _on_CloneLayer_pressed() -> void: var project: Project = Global.current_project var l: BaseLayer = project.layers[project.current_layer].copy() l.name = str(project.layers[project.current_layer].name, " (", tr("copy"), ")") - var cels: Array = project.layers[project.current_layer].copy_all_cels(true) + var cels: Array = project.layers[project.current_layer].copy_all_cels() project.undos += 1 project.undo_redo.create_action("Add Layer") From a52f055daf8acf8fdc96ee4b4bfedbba7927631b Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 20 Jul 2022 15:22:10 -0400 Subject: [PATCH 069/154] Fixed CelButton linked_indicator not showing up right away when becoming linked --- src/UI/Timeline/AnimationTimeline.gd | 19 +++++++++---------- src/UI/Timeline/PixelCelButton.gd | 13 +++++++------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 6ba5f7e2609f..0e1d13c8a963 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -168,10 +168,10 @@ func add_frame() -> void: project.undo_redo.create_action("Add Frame") project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) - project.undo_redo.add_do_method(project, "add_frames", [frame], [frame_add_index]) - project.undo_redo.add_undo_method(project, "remove_frames", [frame_add_index]) project.undo_redo.add_do_property(project, "layers", new_layers) project.undo_redo.add_undo_property(project, "layers", project.layers) + project.undo_redo.add_do_method(project, "add_frames", [frame], [frame_add_index]) + project.undo_redo.add_undo_method(project, "remove_frames", [frame_add_index]) project.undo_redo.add_do_property(project, "animation_tags", new_animation_tags) project.undo_redo.add_undo_property(project, "animation_tags", project.animation_tags) project.undo_redo.add_do_property(project, "current_frame", project.current_frame + 1) @@ -251,10 +251,10 @@ func delete_frames(frames := []) -> void: project.undos += 1 project.undo_redo.create_action("Remove Frame") - project.undo_redo.add_do_method(project, "remove_frames", frames) - project.undo_redo.add_undo_method(project, "add_frames", frame_refs, frames) project.undo_redo.add_do_property(project, "layers", new_layers) project.undo_redo.add_undo_property(project, "layers", Global.current_project.layers) + project.undo_redo.add_do_method(project, "remove_frames", frames) + project.undo_redo.add_undo_method(project, "add_frames", frame_refs, frames) project.undo_redo.add_do_property(project, "animation_tags", new_animation_tags) project.undo_redo.add_undo_property(project, "animation_tags", project.animation_tags) project.undo_redo.add_do_property(project, "current_frame", current_frame) @@ -306,8 +306,9 @@ func copy_frames(frames := []) -> void: # If the layer has new_cels_linked variable, and its true var new_cels_linked: bool = new_layers[l_i].get("new_cels_linked") + # TODO R3: Make sure this is working: # Copy the cel, create new cel content if new cels aren't linked - new_frame.cels.append(new_layers[l_i].copy_cel(frame, !new_cels_linked)) + new_frame.cels.append(new_layers[l_i].copy_cel(frame, new_cels_linked)) if new_cels_linked: # If the link button is pressed new_layers[l_i].linked_cels.append(new_frame) @@ -326,15 +327,13 @@ func copy_frames(frames := []) -> void: project.undo_redo.create_action("Add Frame") project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) + project.undo_redo.add_do_property(project, "layers", new_layers) + project.undo_redo.add_undo_property(project, "layers", project.layers) project.undo_redo.add_do_method(project, "add_frames", copied_frames, copied_indices) project.undo_redo.add_undo_method(project, "remove_frames", copied_indices) - project.undo_redo.add_do_property(project, "current_frame", frames[-1] + 1) - project.undo_redo.add_do_property(project, "layers", new_layers) - project.undo_redo.add_do_property(project, "animation_tags", new_animation_tags) - project.undo_redo.add_undo_property(project, "current_frame", frames[-1]) - project.undo_redo.add_undo_property(project, "layers", project.layers) + project.undo_redo.add_do_property(project, "animation_tags", new_animation_tags) project.undo_redo.add_undo_property(project, "animation_tags", project.animation_tags) project.undo_redo.commit_action() diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index e186444f0b9c..f18269f849f4 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -8,11 +8,8 @@ var cel: PixelCel var image: Image onready var popup_menu: PopupMenu = $PopupMenu +onready var linked_indicator: Polygon2D = $LinkedIndicator -# TODO R3: The linked indicator seems to not get updated properly (adding a new linked cel won't show -# the indicator until another timeline change, same with linking an existing cel) -# (this is most likely due to the order of do/undo methods/properties being added in -# AnimationTimeline. Will leave until I decide what to do about setting linked in the first place) func _ready() -> void: button_setup() @@ -23,11 +20,11 @@ func button_setup() -> void: hint_tooltip = tr("Frame: %s, Layer: %s") % [frame + 1, layer] if Global.current_project.frames[frame] in Global.current_project.layers[layer].linked_cels: - get_node("LinkedIndicator").visible = true + linked_indicator.visible = true popup_menu.set_item_text(MenuOptions.LINK, "Unlink Cel") popup_menu.set_item_metadata(MenuOptions.LINK, "Unlink Cel") else: - get_node("LinkedIndicator").visible = false + linked_indicator.visible = false popup_menu.set_item_text(MenuOptions.LINK, "Link Cel") popup_menu.set_item_metadata(MenuOptions.LINK, "Link Cel") @@ -133,8 +130,10 @@ func _on_PopupMenu_id_pressed(id: int) -> void: project.undo_redo.create_action("Unlink Cel") project.undo_redo.add_do_property(project, "layers", new_layers) + project.undo_redo.add_do_method(self, "button_setup") project.undo_redo.add_do_property(f, "cels", new_cels) project.undo_redo.add_undo_property(project, "layers", project.layers) + project.undo_redo.add_undo_method(self, "button_setup") project.undo_redo.add_undo_property(f, "cels", f.cels) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) @@ -145,6 +144,7 @@ func _on_PopupMenu_id_pressed(id: int) -> void: new_layers[layer].linked_cels.append(f) project.undo_redo.create_action("Link Cel") project.undo_redo.add_do_property(project, "layers", new_layers) + project.undo_redo.add_do_method(self, "button_setup") if new_layers[layer].linked_cels.size() > 1: # If there are already linked cels, set the current cel's image # to the first linked cel's image @@ -154,6 +154,7 @@ func _on_PopupMenu_id_pressed(id: int) -> void: project.undo_redo.add_undo_property(f, "cels", f.cels) project.undo_redo.add_undo_property(project, "layers", project.layers) + project.undo_redo.add_undo_method(self, "button_setup") project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.commit_action() From 5d4c0443275800b810cdcbc902f91b473d801621 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 20 Jul 2022 15:59:20 -0400 Subject: [PATCH 070/154] Cleand up link/unlink cel menu option a little. Fixed situatoin where trying to call button_setup on cel_button that doesn't exist anymore due to undo/redo --- src/UI/Timeline/AnimationTimeline.gd | 3 ++- src/UI/Timeline/PixelCelButton.gd | 27 +++++++++++---------------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 0e1d13c8a963..1755637d6221 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -891,4 +891,5 @@ func project_cel_removed(frame: int, layer: int) -> void: var container := Global.frames_container.get_child( Global.frames_container.get_child_count() - 1 - layer ) - container.get_child(frame).free() + container.get_child(frame).queue_free() + container.remove_child(container.get_child(frame)) diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index f18269f849f4..a27252d1c005 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -127,24 +127,13 @@ func _on_PopupMenu_id_pressed(id: int) -> void: sprite_texture.create_from_image(sprite, 0) new_cels[layer].image = sprite new_cels[layer].image_texture = sprite_texture - project.undo_redo.create_action("Unlink Cel") - project.undo_redo.add_do_property(project, "layers", new_layers) - project.undo_redo.add_do_method(self, "button_setup") project.undo_redo.add_do_property(f, "cels", new_cels) - project.undo_redo.add_undo_property(project, "layers", project.layers) - project.undo_redo.add_undo_method(self, "button_setup") project.undo_redo.add_undo_property(f, "cels", f.cels) - project.undo_redo.add_undo_method(Global, "undo_or_redo", true) - project.undo_redo.add_do_method(Global, "undo_or_redo", false) - project.undo_redo.commit_action() - elif popup_menu.get_item_metadata(MenuOptions.LINK) == "Link Cel": new_layers[layer].linked_cels.append(f) project.undo_redo.create_action("Link Cel") - project.undo_redo.add_do_property(project, "layers", new_layers) - project.undo_redo.add_do_method(self, "button_setup") if new_layers[layer].linked_cels.size() > 1: # If there are already linked cels, set the current cel's image # to the first linked cel's image @@ -153,11 +142,17 @@ func _on_PopupMenu_id_pressed(id: int) -> void: project.undo_redo.add_do_property(f, "cels", new_cels) project.undo_redo.add_undo_property(f, "cels", f.cels) - project.undo_redo.add_undo_property(project, "layers", project.layers) - project.undo_redo.add_undo_method(self, "button_setup") - project.undo_redo.add_undo_method(Global, "undo_or_redo", true) - project.undo_redo.add_do_method(Global, "undo_or_redo", false) - project.undo_redo.commit_action() + project.undo_redo.add_do_property(project, "layers", new_layers) + project.undo_redo.add_undo_property(project, "layers", project.layers) + # Remove and add a new cel button to update appearance + project.undo_redo.add_do_method(Global.animation_timeline, "project_cel_removed", frame, layer) + project.undo_redo.add_undo_method(Global.animation_timeline, "project_cel_removed", frame, layer) + project.undo_redo.add_do_method(Global.animation_timeline, "project_cel_added", frame, layer) + project.undo_redo.add_undo_method(Global.animation_timeline, "project_cel_added", frame, layer) + + project.undo_redo.add_undo_method(Global, "undo_or_redo", true) + project.undo_redo.add_do_method(Global, "undo_or_redo", false) + project.undo_redo.commit_action() func _delete_cel_content() -> void: From d7810e863522fdc2561698529c4f80efe1951e47 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 20 Jul 2022 16:15:13 -0400 Subject: [PATCH 071/154] Fixed regression with copy_cel (linked) in when cloning a frame --- src/Classes/PixelLayer.gd | 5 +++-- src/UI/Timeline/AnimationTimeline.gd | 1 - src/UI/Timeline/PixelCelButton.gd | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Classes/PixelLayer.gd b/src/Classes/PixelLayer.gd index e6e4dafdf78b..7e8a7dfa142b 100644 --- a/src/Classes/PixelLayer.gd +++ b/src/Classes/PixelLayer.gd @@ -33,10 +33,11 @@ func deserialize(dict: Dictionary) -> void: func copy_cel(frame_index: int, linked: bool) -> BaseCel: - var cel: PixelCel = project.frames[frame_index].cels[index] - if linked: + if linked and not linked_cels.empty(): + var cel: PixelCel = linked_cels[0].cels[index] return PixelCel.new(cel.image, cel.opacity, cel.image_texture) else: + var cel: PixelCel = project.frames[frame_index].cels[index] var copy_image := Image.new() copy_image.copy_from(cel.image) return PixelCel.new(copy_image, cel.opacity) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 1755637d6221..ffcacbb7b994 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -306,7 +306,6 @@ func copy_frames(frames := []) -> void: # If the layer has new_cels_linked variable, and its true var new_cels_linked: bool = new_layers[l_i].get("new_cels_linked") - # TODO R3: Make sure this is working: # Copy the cel, create new cel content if new cels aren't linked new_frame.cels.append(new_layers[l_i].copy_cel(frame, new_cels_linked)) diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index a27252d1c005..dd20906b9d5f 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -104,7 +104,6 @@ func _on_PopupMenu_id_pressed(id: int) -> void: MenuOptions.LINK: # TODO R3: If you do part of linked cels in add/remove frames, consider changes here: - # TODO R4: Make add_do/undo_property/method order consistent (and make sure it doesn't cause issues) var project: Project = Global.current_project var f: Frame = project.frames[frame] var cel_index: int = project.layers[layer].linked_cels.find(f) @@ -150,8 +149,8 @@ func _on_PopupMenu_id_pressed(id: int) -> void: project.undo_redo.add_do_method(Global.animation_timeline, "project_cel_added", frame, layer) project.undo_redo.add_undo_method(Global.animation_timeline, "project_cel_added", frame, layer) - project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.add_do_method(Global, "undo_or_redo", false) + project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.commit_action() From 33ae0931608a8b89985b2039622d990036e5e213 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 21 Jul 2022 11:12:14 -0400 Subject: [PATCH 072/154] Minor cleanup, more detailed comments, updated TODOs --- src/Classes/BaseLayer.gd | 3 ++- src/UI/Timeline/AnimationTimeline.gd | 8 +++++--- src/UI/Timeline/PixelCelButton.gd | 3 ++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index 0a67d96db817..5616f641e91d 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -21,7 +21,8 @@ func is_a_parent_of(layer: BaseLayer) -> bool: return is_a_parent_of(layer.parent) return false -# TODO L: Consider going backwards in get_children functions, to allow breaking +# TODO L: Consider going backwards in get_children functions, to allow breaking (test performance) +# TODO L: Consider combining these into one func with bool, and adding a get_child_count func func get_children_direct() -> Array: var children := [] for i in range(index): diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index ffcacbb7b994..6bcf137265a6 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -410,12 +410,12 @@ func _on_PlayBackwards_toggled(button_pressed: bool) -> void: play_animation(button_pressed, false) - +# Called on each frame of the animation func _on_AnimationTimer_timeout() -> void: if first_frame == last_frame: Global.play_forward.pressed = false Global.play_backwards.pressed = false - $AnimationTimer.stop() + Global.animation_timer.stop() return Global.canvas.selection.transform_content_confirm() @@ -620,6 +620,7 @@ func _on_AddGroup_pressed() -> void: func _on_CloneLayer_pressed() -> void: + # TODO H: clone children along with layer var project: Project = Global.current_project var l: BaseLayer = project.layers[project.current_layer].copy() l.name = str(project.layers[project.current_layer].name, " (", tr("copy"), ")") @@ -799,7 +800,8 @@ func _on_OnionSkinningSettings_popup_hide() -> void: func project_changed() -> void: var project: Project = Global.current_project - # These must be removed from tree immediately to not mess up the indices of the new buttons: + # These must be removed from tree immediately to not mess up the indices of + # the new buttons, so use either free or queue_free + parent.remove_child for child in Global.layers_container.get_children(): child.free() for child in Global.frame_ids.get_children(): diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index dd20906b9d5f..60ea70a13987 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -143,7 +143,8 @@ func _on_PopupMenu_id_pressed(id: int) -> void: project.undo_redo.add_do_property(project, "layers", new_layers) project.undo_redo.add_undo_property(project, "layers", project.layers) - # Remove and add a new cel button to update appearance + # Remove and add a new cel button to update appearance (can't use self.button_setup + # because there is no guarantee that it will be the exact same cel button instance) project.undo_redo.add_do_method(Global.animation_timeline, "project_cel_removed", frame, layer) project.undo_redo.add_undo_method(Global.animation_timeline, "project_cel_removed", frame, layer) project.undo_redo.add_do_method(Global.animation_timeline, "project_cel_added", frame, layer) From e33a55379ecc0061cb47ec572972664622cf8524 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 21 Jul 2022 11:21:00 -0400 Subject: [PATCH 073/154] more improved comments --- src/UI/Timeline/AnimationTimeline.gd | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 6bcf137265a6..a6e253b8369a 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -664,7 +664,8 @@ func _on_RemoveLayer_pressed() -> void: project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.commit_action() - +# Move the layer up or down in layer order and/or reparent to be deeper/shallower in the +# layer hierarchy depending on its current index and parent func change_layer_order(up: bool) -> void: var project: Project = Global.current_project var layer: BaseLayer = project.layers[project.current_layer] @@ -678,13 +679,15 @@ func change_layer_order(up: bool) -> void: if up: var above_layer: BaseLayer = project.layers[project.current_layer + 1] - if layer.parent == above_layer: # Above is the parent, leave the parent + if layer.parent == above_layer: # Above is the parent, leave the parent and go up to_parents[-1] = above_layer.parent to_index = layer.index + 1 elif layer.parent != above_layer.parent: # Above layer must be deeper in the hierarchy - to_parents[-1] = above_layer.parent # (this may be more than 1 level deeper) + # Move layer 1 level deeper in hierarchy. Done by setting its parent to the parent of + # above_layer, and if that is multiple levels, drop levels until its just 1 + to_parents[-1] = above_layer.parent while to_parents[-1].parent != layer.parent: - to_parents[-1]= to_parents[-1].parent # Incase we went multiple levels, drop extra + to_parents[-1] = to_parents[-1].parent elif above_layer.accepts_child(layer): to_parents[-1] = above_layer else: From 77e6b66552ea4da8defc69372172b2f2590c1384 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 21 Jul 2022 11:32:08 -0400 Subject: [PATCH 074/154] Made focus_mode on Cel/Layer/FrameButton NONE to fix bug where it looks like one is selected after pressing it and adding a new Layer/Frame (but its just in the focus state, not the pressed state --- src/UI/Timeline/BaseCelButton.tscn | 2 ++ src/UI/Timeline/BaseLayerButton.tscn | 2 ++ src/UI/Timeline/FrameButton.tscn | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/UI/Timeline/BaseCelButton.tscn b/src/UI/Timeline/BaseCelButton.tscn index 232b9b8cbc7b..ca2f6231d234 100644 --- a/src/UI/Timeline/BaseCelButton.tscn +++ b/src/UI/Timeline/BaseCelButton.tscn @@ -20,11 +20,13 @@ margin_top = 18.0 margin_right = 36.0 margin_bottom = 54.0 rect_min_size = Vector2( 36, 36 ) +focus_mode = 0 mouse_default_cursor_shape = 2 size_flags_horizontal = 0 size_flags_vertical = 0 toggle_mode = true button_mask = 7 +enabled_focus_mode = 0 __meta__ = { "_edit_use_anchors_": false } diff --git a/src/UI/Timeline/BaseLayerButton.tscn b/src/UI/Timeline/BaseLayerButton.tscn index 11dc8bd40249..92b85666bf8b 100644 --- a/src/UI/Timeline/BaseLayerButton.tscn +++ b/src/UI/Timeline/BaseLayerButton.tscn @@ -8,10 +8,12 @@ margin_right = 236.0 margin_bottom = 36.0 rect_min_size = Vector2( 236, 36 ) +focus_mode = 0 mouse_default_cursor_shape = 2 size_flags_horizontal = 0 toggle_mode = true action_mode = 0 +enabled_focus_mode = 0 script = ExtResource( 1 ) __meta__ = { "_edit_horizontal_guides_": [ ], diff --git a/src/UI/Timeline/FrameButton.tscn b/src/UI/Timeline/FrameButton.tscn index 0d5fb7895a79..37ae95090a5b 100644 --- a/src/UI/Timeline/FrameButton.tscn +++ b/src/UI/Timeline/FrameButton.tscn @@ -5,9 +5,11 @@ [node name="FrameButton" type="Button"] margin_right = 12.0 margin_bottom = 20.0 +focus_mode = 0 mouse_default_cursor_shape = 2 toggle_mode = true button_mask = 7 +enabled_focus_mode = 0 text = "1" script = ExtResource( 1 ) __meta__ = { From 48788e0b7866948ed938bdac0c70398500746f32 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 21 Jul 2022 13:48:05 -0400 Subject: [PATCH 075/154] Made AnimationTimeline.change_layer_order work a little more consistantly with LayerButton.drop_data, and fixed a minor bug in it --- src/UI/Timeline/AnimationTimeline.gd | 20 ++++++++++---------- src/UI/Timeline/LayerButton.gd | 4 +--- src/UI/Timeline/PixelCelButton.gd | 2 +- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index a6e253b8369a..148a37f4cba0 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -669,19 +669,19 @@ func _on_RemoveLayer_pressed() -> void: func change_layer_order(up: bool) -> void: var project: Project = Global.current_project var layer: BaseLayer = project.layers[project.current_layer] - var to_index = layer.index var child_count = layer.get_children_recursive().size() var from_indices := range(layer.index - child_count, layer.index + 1) var from_parents := [] for l in from_indices: from_parents.append(project.layers[l].parent) var to_parents := from_parents.duplicate() + var to_index = layer.index - child_count # the index where the LOWEST shifted layer should end up if up: var above_layer: BaseLayer = project.layers[project.current_layer + 1] if layer.parent == above_layer: # Above is the parent, leave the parent and go up to_parents[-1] = above_layer.parent - to_index = layer.index + 1 + to_index = to_index + 1 elif layer.parent != above_layer.parent: # Above layer must be deeper in the hierarchy # Move layer 1 level deeper in hierarchy. Done by setting its parent to the parent of # above_layer, and if that is multiple levels, drop levels until its just 1 @@ -691,7 +691,7 @@ func change_layer_order(up: bool) -> void: elif above_layer.accepts_child(layer): to_parents[-1] = above_layer else: - to_index = layer.index + 1 + to_index = to_index + 1 else: # Down if layer.index == child_count: # If at the very bottom of the layer stack if not is_instance_valid(layer.parent): @@ -700,22 +700,22 @@ func change_layer_order(up: bool) -> void: else: var below_layer: BaseLayer = project.layers[project.current_layer - 1 - child_count] if layer.parent != below_layer.parent: # If there is a hierarchy change - to_parents[-1] = below_layer.parent + to_parents[-1] = layer.parent.parent # Drop a level in the hierarchy elif below_layer.accepts_child(layer): to_parents[-1] = below_layer - to_index = layer.index - 1 + to_index = to_index - 1 else: - to_index = layer.index - 1 + to_index = to_index - 1 - var to_indices := range(to_index - child_count, to_index + 1) + var to_indices := range(to_index, to_index + child_count + 1) project.undo_redo.create_action("Change Layer Order") - project.undo_redo.add_do_property(project, "current_layer", to_index) + project.undo_redo.add_do_property(project, "current_layer", to_index + child_count) + project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) project.undo_redo.add_do_method(project, "move_layers", from_indices, to_indices, to_parents) project.undo_redo.add_undo_method(project, "move_layers", to_indices, from_indices, from_parents) - project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) - project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.add_do_method(Global, "undo_or_redo", false) + project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.commit_action() diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index 5d8b210dead8..8d5d20300667 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -303,9 +303,7 @@ func drop_data(_pos, data) -> void: ) else: # Move layers - # TODO R1: would it make it more consistent (and easier to read) if to_index was changed - # to use the highest layer? - var to_index: int # the index where the LOWEST shifted layer should end up + var to_index: int # the index where the LOWEST moved layer should end up var to_parent: BaseLayer # If accepted as a child, is it in the center region? diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index 60ea70a13987..51db3c9b90e5 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -114,7 +114,7 @@ func _on_PopupMenu_id_pressed(id: int) -> void: new_cels[i] = PixelCel.new( new_cels[i].image, new_cels[i].opacity, new_cels[i].image_texture ) -# TODO R3: Make sure all this stuff still works after refactor: + # TODO H: Make sure all this works with group layers: if popup_menu.get_item_metadata(MenuOptions.LINK) == "Unlink Cel": new_layers[layer].linked_cels.remove(cel_index) var sprite := Image.new() From 3316ee147aeb0c588257f6430d0adfa5864efc0d Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 21 Jul 2022 14:52:42 -0400 Subject: [PATCH 076/154] Updated comments and TODOs --- src/Classes/Project.gd | 1 - src/UI/Timeline/AnimationTimeline.gd | 9 ++++++--- src/UI/Timeline/LayerButton.gd | 4 +--- src/UI/Timeline/PixelCelButton.gd | 1 - 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 2a6182426914..8976fedc477e 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -800,7 +800,6 @@ func add_frames(new_frames: Array, indices: Array) -> void: # indices should be func remove_frames(indices: Array) -> void: # indices should be in ascending order Global.canvas.selection.transform_content_confirm() selected_cels.clear() - # TODO R1: Could one half of cel linking and animation tags be included in the add or remove_frame functions? (ie: removing works, but adding doesn't?) for i in range(indices.size()): # With each removed index, future indices need to be lowered, so subtract by i frames.remove(indices[i] - i) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 148a37f4cba0..8ec06b0f9463 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -521,7 +521,7 @@ func play_animation(play: bool, forward_dir: bool) -> void: func _on_NextFrame_pressed() -> void: - Global.canvas.selection.transform_content_confirm() # TODO R4: These may be safe to remove, (frame_changed in project calls it) + Global.canvas.selection.transform_content_confirm() # TODO R3: These may be safe to remove, (frame_changed in project calls it) Global.current_project.selected_cels.clear() # TODO NOTE: ^^ Though clearing the selected cels may mess that up. if Global.current_project.current_frame < Global.current_project.frames.size() - 1: Global.current_project.current_frame += 1 @@ -801,6 +801,9 @@ func _on_OnionSkinningSettings_popup_hide() -> void: Global.can_draw = true +# Methods to update the UI in response to changes in the current project + + func project_changed() -> void: var project: Project = Global.current_project # These must be removed from tree immediately to not mess up the indices of @@ -819,7 +822,7 @@ func project_changed() -> void: button.frame = f Global.frame_ids.add_child(button) - # TODO R4: Remove and inline what's needed here if this isn't used anywhere else: + # TODO R3: Remove and inline what's needed here if this isn't used anywhere else: Global.current_project._update_animation_timeline_selection() @@ -856,7 +859,7 @@ func project_layer_added(layer: int) -> void: project.layers[layer].set_name_to_default(layer) var layer_cel_container := HBoxContainer.new() - # TODO R3: Is there any need for a name (and why is it LAYERSSS in one place, and FRAMESS in another?) + # TODO R4: Is there any need for a name (and why is it LAYERSSS in one place, and FRAMESS in another?) layer_cel_container.name = "LAYERSSS " + str(layer) for f in range(project.frames.size()): var cel_button = project.frames[f].cels[layer].create_cel_button() diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index 8d5d20300667..c263fe9e2c0d 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -74,7 +74,7 @@ func _update_buttons() -> void: func _update_buttons_all_layers() -> void: - # TODO R4: would it be better to have specified range? (if so rename all_layers to for_layers) + # TODO R3: would it be better to have specified range? (if so rename all_layers to for_layers) # Maybe update_buttons_recursive (including children) is all we need? for layer_button in Global.layers_container.get_children(): layer_button._update_buttons() @@ -263,8 +263,6 @@ func drop_data(_pos, data) -> void: project.undo_redo.create_action("Change Layer Order") var layers: Array = project.layers # This shouldn't be modified directly - # TODO R1: can this code be made easier to read? - var drop_from_indices := range(drop_layer - layers[drop_layer].get_children_recursive().size(), drop_layer + 1 ) var drop_from_parents := [] diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index 51db3c9b90e5..913c6eb55303 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -103,7 +103,6 @@ func _on_PopupMenu_id_pressed(id: int) -> void: _delete_cel_content() MenuOptions.LINK: - # TODO R3: If you do part of linked cels in add/remove frames, consider changes here: var project: Project = Global.current_project var f: Frame = project.frames[frame] var cel_index: int = project.layers[layer].linked_cels.find(f) From 8e33b74c7d2ff67250e4b918722bb4f04fb7e68a Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 21 Jul 2022 15:22:57 -0400 Subject: [PATCH 077/154] cleanup --- src/Classes/Project.gd | 28 ++++------------------------ src/UI/Timeline/AnimationTimeline.gd | 27 +++++++++++++++++++++++---- src/UI/Timeline/LayerButton.gd | 4 +--- 3 files changed, 28 insertions(+), 31 deletions(-) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 8976fedc477e..bdf6909262df 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -434,7 +434,7 @@ func _layers_changed(value: Array) -> void: # self.current_frame = current_frame # Call frame_changed to update UI toggle_layer_buttons() - +# TODO R4: should be safe to remove func _remove_cel_buttons() -> void: for container in Global.frames_container.get_children(): Global.frames_container.remove_child(container) @@ -778,6 +778,9 @@ func resize_bitmap_values(bitmap: BitMap, new_size: Vector2, flip_x: bool, flip_ return new_bitmap +# Timeline modifications + + func add_frames(new_frames: Array, indices: Array) -> void: # indices should be in ascending order Global.canvas.selection.transform_content_confirm() selected_cels.clear() @@ -1001,26 +1004,3 @@ func swap_cel(a_frame: int, a_layer: int, b_frame: int, b_layer: int) -> void: Global.animation_timeline.project_cel_added(a_frame, a_layer) Global.animation_timeline.project_cel_removed(b_frame, b_layer) Global.animation_timeline.project_cel_added(b_frame, b_layer) - - -func _update_animation_timeline_selection() -> void: - for cel in selected_cels: - var frame: int = cel[0] - var layer: int = cel[1] - if frame < Global.frame_ids.get_child_count(): - var frame_button: BaseButton = Global.frame_ids.get_child(frame) - frame_button.pressed = true - - var container_child_count: int = Global.frames_container.get_child_count() - if layer < container_child_count: - var container = Global.frames_container.get_child( - container_child_count - 1 - layer - ) - if frame < container.get_child_count(): - var cel_button = container.get_child(frame) - cel_button.pressed = true - - var layer_button = Global.layers_container.get_child( - container_child_count - 1 - layer - ) - layer_button.pressed = true diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 8ec06b0f9463..c11e04a8fbed 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -521,8 +521,8 @@ func play_animation(play: bool, forward_dir: bool) -> void: func _on_NextFrame_pressed() -> void: - Global.canvas.selection.transform_content_confirm() # TODO R3: These may be safe to remove, (frame_changed in project calls it) - Global.current_project.selected_cels.clear() # TODO NOTE: ^^ Though clearing the selected cels may mess that up. + Global.canvas.selection.transform_content_confirm() + Global.current_project.selected_cels.clear() if Global.current_project.current_frame < Global.current_project.frames.size() - 1: Global.current_project.current_frame += 1 @@ -822,8 +822,27 @@ func project_changed() -> void: button.frame = f Global.frame_ids.add_child(button) - # TODO R3: Remove and inline what's needed here if this isn't used anywhere else: - Global.current_project._update_animation_timeline_selection() + # Press selected cel/frame/layer buttons + for cel in project.selected_cels: + var frame: int = cel[0] + var layer: int = cel[1] + if frame < Global.frame_ids.get_child_count(): + var frame_button: BaseButton = Global.frame_ids.get_child(frame) + frame_button.pressed = true + + var container_child_count: int = Global.frames_container.get_child_count() + if layer < container_child_count: + var container = Global.frames_container.get_child( + container_child_count - 1 - layer + ) + if frame < container.get_child_count(): + var cel_button = container.get_child(frame) + cel_button.pressed = true + + var layer_button = Global.layers_container.get_child( + container_child_count - 1 - layer + ) + layer_button.pressed = true func project_frame_added(frame: int) -> void: diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index c263fe9e2c0d..86bffa2c36aa 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -72,10 +72,8 @@ func _update_buttons() -> void: if Global.current_project.layers[layer].parent.is_locked_in_hierarchy(): lock_button.modulate.a = 0.33 - +# Used when pressing a button on this changes the appearnce of other layers (ie: expand or visible) func _update_buttons_all_layers() -> void: - # TODO R3: would it be better to have specified range? (if so rename all_layers to for_layers) - # Maybe update_buttons_recursive (including children) is all we need? for layer_button in Global.layers_container.get_children(): layer_button._update_buttons() var expanded = Global.current_project.layers[layer_button.layer].is_expanded_in_hierarchy() From e3c548a938f724fdf519000f2b4d1b7fff5c902b Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 21 Jul 2022 15:46:32 -0400 Subject: [PATCH 078/154] removed some code that should no longer be needed --- src/Autoload/Global.gd | 14 -------------- src/Classes/Project.gd | 6 ------ src/UI/Timeline/AnimationTimeline.gd | 2 -- 3 files changed, 22 deletions(-) diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index 320d94e7c443..f4516b38f224 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -258,20 +258,6 @@ func undo_or_redo( canvas.pixel_grid.update() cursor_position_label.text = "[%s×%s]" % [project.size.x, project.size.y] - elif "Frame" in action_name: - # TODO R4: This should be safe to remove after adding play_forwards/backwards.pressed = false to _on_AnimationTimer_timeout - # If not, does what this comment says after the refacotr remain true? - # This actually means that frames.size is one, but it hasn't been updated yet -# if (undo and project.frames.size() == 2) or project.frames.size() == 1: # Stop animating -# play_forward.pressed = false -# play_backwards.pressed = false -# animation_timer.stop() - pass - - elif "Move Cels" == action_name: - # TODO R4: is this still required? (Looks safe to remove, unless something is added back to frames_changed) - project.frames = project.frames # to call frames_changed - canvas.update() if !project.has_changed: project.has_changed = true diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index bdf6909262df..e29d46941764 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -434,12 +434,6 @@ func _layers_changed(value: Array) -> void: # self.current_frame = current_frame # Call frame_changed to update UI toggle_layer_buttons() -# TODO R4: should be safe to remove -func _remove_cel_buttons() -> void: - for container in Global.frames_container.get_children(): - Global.frames_container.remove_child(container) - container.queue_free() - func _frame_changed(value: int) -> void: Global.canvas.selection.transform_content_confirm() diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index c11e04a8fbed..6077ea7383bb 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -878,8 +878,6 @@ func project_layer_added(layer: int) -> void: project.layers[layer].set_name_to_default(layer) var layer_cel_container := HBoxContainer.new() - # TODO R4: Is there any need for a name (and why is it LAYERSSS in one place, and FRAMESS in another?) - layer_cel_container.name = "LAYERSSS " + str(layer) for f in range(project.frames.size()): var cel_button = project.frames[f].cels[layer].create_cel_button() cel_button.frame = f From b16f3d692b3c5926969c785565a92335e5a6660e Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 21 Jul 2022 16:34:36 -0400 Subject: [PATCH 079/154] updated comment --- src/Classes/BaseLayer.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index 5616f641e91d..1e151ee24894 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -102,7 +102,7 @@ func copy() -> BaseLayer: func copy_cel(_frame: int, _linked: bool) -> BaseCel: return null -# Used to copy all cels with cel linking properly set up between copies: +# Used to copy all cels with cel linking properly set up between this set of copies: func copy_all_cels() -> Array: return [] From f15549bc076bb71e9f2ca266d17e849087c35b02 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 21 Jul 2022 17:46:36 -0400 Subject: [PATCH 080/154] removed Project's frames and layers setters _frames_changed and _layers_changed --- src/Autoload/Global.gd | 1 - src/Autoload/OpenSave.gd | 3 --- src/Classes/Project.gd | 46 ++-------------------------------- src/Main.gd | 2 -- src/UI/Timeline/LayerButton.gd | 2 -- 5 files changed, 2 insertions(+), 52 deletions(-) diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index f4516b38f224..9e1132c403e8 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -22,7 +22,6 @@ var current_project_index := 0 setget _project_changed var ui_tooltips := {} # Canvas related stuff -var layers_changed_skip := false var can_draw := false var move_guides_on_canvas := false var has_focus := false diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index a0f5ea8b323c..65960622d0f6 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -126,9 +126,6 @@ func open_pxo_file(path: String, untitled_backup: bool = false, replace_empty: b if dict.error == OK and dict.result.has("fps"): Global.animation_timeline.fps_spinbox.value = dict.result.fps Global.animation_timeline.project_changed() - # TODO R4: Do these need to be here? (Consider the bug where new project doesn't set the hidden frame buttons in frames_changed) - new_project.frames = new_project.frames # Just to call frames_changed - new_project.layers = new_project.layers # Just to call layers_changed else: Global.projects.append(new_project) Global.tabs.current_tab = Global.tabs.get_tab_count() - 1 diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index e29d46941764..07a83db65aaa 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -10,8 +10,8 @@ var tile_mode_rects := [] # Cached to avoid recalculation var undos := 0 # The number of times we added undo properties var fill_color := Color(0) var has_changed := false setget _has_changed_changed -var frames := [] setget _frames_changed # Array of Frames (that contain Cels) -var layers := [] setget _layers_changed # Array of Layers +var frames := [] # Array of Frames (that contain Cels) +var layers := [] # Array of Layers var current_frame := 0 setget _frame_changed var current_layer := 0 setget _layer_changed var selected_cels := [[0, 0]] # Array of Arrays of 2 integers (frame & layer) @@ -393,48 +393,6 @@ func _size_changed(value: Vector2) -> void: _update_tile_mode_rects() -func _frames_changed(value: Array) -> void: - Global.canvas.selection.transform_content_confirm() - frames = value -# selected_cels.clear() # TODO R4: Determine if this needs to be kept (If it is, selected cels needs to be intialized after creating project (ie: in Main), rather than here - # TODO NOTE: perhaps if you don't clear the selected cels, some invalid ones may be included? (ie: removed cels?) - # selected cels is already cleared when using the new frame/layer/cel functions - # THESE SHOULD PROBABLY BE SAFE TO REMOVE FOR NORMAL USAGE, IS THERE A PLACE WHERE THEY'RE NOT? - # OTHER THAN ON STARTUP, IS THERE ANY DISADVANGTAGE TO KEEPING? (may be better to keep just to be sure) - print(selected_cels) - for c in selected_cels: - if c[0] >= frames.size(): - print("invalid frame in selected cel") - # REMOVE ALL THAT DEBUG CODE ^^^^^^^^^^^^^^^^ - - _set_timeline_first_and_last_frames() - - -func _layers_changed(value: Array) -> void: - layers = value - if Global.layers_changed_skip: - Global.layers_changed_skip = false - return - -# selected_cels.clear() # TODO R4: Determine if this needs to be kept (If it is, selected cels needs to be intialized after creating project (ie: in Main), rather than here - # TODO NOTE: perhaps if you don't clear the selected cels, some invalid ones may be included? (ie: removed cels?) - # selected cels is already cleared when using the new frame/layer/cel functions - # THESE SHOULD PROBABLY BE SAFE TO REMOVE FOR NORMAL USAGE, IS THERE A PLACE WHERE THEY'RE NOT? - # OTHER THAN ON STARTUP, IS THERE ANY DISADVANGTAGE TO KEEPING? (may be better to keep just to be sure) - for c in selected_cels: - if c[1] >= layers.size(): - print("invalid layer in selected cel") - # REMOVE ALL THAT DEBUG CODE ^^^^^^^^^^^^^^^^ - - # TODO R4: investigate wether these are still required (Should be safe to remove): -# var layer_button = Global.layers_container.get_child( -# Global.layers_container.get_child_count() - 1 - current_layer -# ) -# layer_button.pressed = true -# self.current_frame = current_frame # Call frame_changed to update UI - toggle_layer_buttons() - - func _frame_changed(value: int) -> void: Global.canvas.selection.transform_content_confirm() current_frame = value diff --git a/src/Main.gd b/src/Main.gd index 3fe42122214c..f17764828d9d 100644 --- a/src/Main.gd +++ b/src/Main.gd @@ -27,8 +27,6 @@ func _ready() -> void: Global.current_project.frames.append(Global.current_project.new_empty_frame()) Global.animation_timeline.project_changed() Global.current_project.toggle_frame_buttons() - # TODO R4: I Think this line should be safe to remove: (calling setter, already called when appending the layer) -# Global.current_project.layers = Global.current_project.layers Import.import_brushes(Global.directory_module.get_brushes_search_path_in_order()) Import.import_patterns(Global.directory_module.get_patterns_search_path_in_order()) diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index 86bffa2c36aa..c5e03be247e5 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -139,7 +139,6 @@ func _save_layer_name(new_name: String) -> void: line_edit.visible = false line_edit.editable = false label.text = new_name - Global.layers_changed_skip = true Global.current_project.layers[layer].name = new_name @@ -177,7 +176,6 @@ func _on_LinkButton_pressed() -> void: var container = Global.frames_container.get_child(Global.current_project.current_layer) container.get_child(Global.current_project.current_frame).button_setup() - Global.current_project.layers = Global.current_project.layers # Call the setter _update_buttons() From 7e5514dc466610fcef1e6bb75930d746af17a81f Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 22 Jul 2022 12:41:47 -0400 Subject: [PATCH 081/154] Made some 'for x in range(array.size())' just 'for x in array.size()' --- src/Classes/Project.gd | 52 ++++++++++++++-------------- src/UI/Timeline/AnimationTimeline.gd | 2 +- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 07a83db65aaa..e0c7a9bfaa79 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -736,17 +736,17 @@ func resize_bitmap_values(bitmap: BitMap, new_size: Vector2, flip_x: bool, flip_ func add_frames(new_frames: Array, indices: Array) -> void: # indices should be in ascending order Global.canvas.selection.transform_content_confirm() selected_cels.clear() - for i in range(new_frames.size()): + for i in new_frames.size(): frames.insert(indices[i], new_frames[i]) Global.animation_timeline.project_frame_added(indices[i]) # Update the frames and frame buttons: - for f in range(frames.size()): + for f in frames.size(): Global.frame_ids.get_child(f).frame = f Global.frame_ids.get_child(f).text = str(f + 1) # Update the cel buttons: - for l in range(layers.size()): + for l in layers.size(): var layer_cel_container = Global.frames_container.get_child(layers.size() - 1 - l) - for f in range(frames.size()): + for f in frames.size(): layer_cel_container.get_child(f).frame = f layer_cel_container.get_child(f).button_setup() _set_timeline_first_and_last_frames() @@ -755,18 +755,18 @@ func add_frames(new_frames: Array, indices: Array) -> void: # indices should be func remove_frames(indices: Array) -> void: # indices should be in ascending order Global.canvas.selection.transform_content_confirm() selected_cels.clear() - for i in range(indices.size()): + for i in indices.size(): # With each removed index, future indices need to be lowered, so subtract by i frames.remove(indices[i] - i) Global.animation_timeline.project_frame_removed(indices[i] - i) # Update the frames and frame buttons: - for f in range(frames.size()): + for f in frames.size(): Global.frame_ids.get_child(f).frame = f Global.frame_ids.get_child(f).text = str(f + 1) # Update the cel buttons: - for l in range(layers.size()): + for l in layers.size(): var layer_cel_container = Global.frames_container.get_child(layers.size() - 1 - l) - for f in range(frames.size()): + for f in frames.size(): layer_cel_container.get_child(f).frame = f layer_cel_container.get_child(f).button_setup() _set_timeline_first_and_last_frames() @@ -781,13 +781,13 @@ func move_frame(from_index: int, to_index: int) -> void: frames.insert(to_index, frame) Global.animation_timeline.project_frame_added(to_index) # Update the frames and frame buttons: - for f in range(frames.size()): + for f in frames.size(): Global.frame_ids.get_child(f).frame = f Global.frame_ids.get_child(f).text = str(f + 1) # Update the cel buttons: - for l in range(layers.size()): + for l in layers.size(): var layer_cel_container = Global.frames_container.get_child(layers.size() - 1 - l) - for f in range(frames.size()): + for f in frames.size(): layer_cel_container.get_child(f).frame = f layer_cel_container.get_child(f).button_setup() _set_timeline_first_and_last_frames() @@ -809,18 +809,18 @@ func swap_frame(a_index: int, b_index: int) -> void: func add_layers(new_layers: Array, indices: Array, cels: Array) -> void: # cels is 2d Array of cels Global.canvas.selection.transform_content_confirm() selected_cels.clear() - for i in range(indices.size()): + for i in indices.size(): layers.insert(indices[i], new_layers[i]) - for f in range(frames.size()): + for f in frames.size(): frames[f].cels.insert(indices[i], cels[i][f]) new_layers[i].project = self Global.animation_timeline.project_layer_added(indices[i]) # Update the layer indices and layer/cel buttons: - for l in range(layers.size()): + for l in layers.size(): layers[l].index = l Global.layers_container.get_child(layers.size() - 1 - l).layer = l var layer_cel_container = Global.frames_container.get_child(layers.size() - 1 - l) - for f in range(frames.size()): + for f in frames.size(): layer_cel_container.get_child(f).layer = l layer_cel_container.get_child(f).button_setup() toggle_layer_buttons() @@ -829,18 +829,18 @@ func add_layers(new_layers: Array, indices: Array, cels: Array) -> void: # cels func remove_layers(indices: Array) -> void: Global.canvas.selection.transform_content_confirm() selected_cels.clear() - for i in range(indices.size()): + for i in indices.size(): # With each removed index, future indices need to be lowered, so subtract by i layers.remove(indices[i] - i) for frame in frames: frame.cels.remove(indices[i] - i) Global.animation_timeline.project_layer_removed(indices[i] - i) # Update the layer indices and layer/cel buttons: - for l in range(layers.size()): + for l in layers.size(): layers[l].index = l Global.layers_container.get_child(layers.size() - 1 - l).layer = l var layer_cel_container = Global.frames_container.get_child(layers.size() - 1 - l) - for f in range(frames.size()): + for f in frames.size(): layer_cel_container.get_child(f).layer = l layer_cel_container.get_child(f).button_setup() toggle_layer_buttons() @@ -863,15 +863,15 @@ func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> v Global.animation_timeline.project_layer_removed(from_indices[i] - i) for i in to_indices.size(): layers.insert(to_indices[i], removed_layers[i]) - for f in range(frames.size()): + for f in frames.size(): frames[f].cels.insert(to_indices[i], removed_cels[i][f]) Global.animation_timeline.project_layer_added(to_indices[i]) # Update the layer indices and layer/cel buttons: - for l in range(layers.size()): + for l in layers.size(): layers[l].index = l Global.layers_container.get_child(layers.size() - 1 - l).layer = l var layer_cel_container = Global.frames_container.get_child(layers.size() - 1 - l) - for f in range(frames.size()): + for f in frames.size(): layer_cel_container.get_child(f).layer = l layer_cel_container.get_child(f).button_setup() toggle_layer_buttons() @@ -905,21 +905,21 @@ func swap_layers(a: Dictionary, b: Dictionary) -> void: for i in a_layers.size(): var index = a.to[i] if a.to[0] < b.to[0] else (a.to[i] - b.to.size()) layers.insert(index, a_layers[i]) - for f in range(frames.size()): + for f in frames.size(): frames[f].cels.insert(index, a_cels[i][f]) Global.animation_timeline.project_layer_added(index) for i in b_layers.size(): layers.insert(b.to[i], b_layers[i]) - for f in range(frames.size()): + for f in frames.size(): frames[f].cels.insert(b.to[i], b_cels[i][f]) Global.animation_timeline.project_layer_added(b.to[i]) # Update the layer indices and layer/cel buttons: - for l in range(layers.size()): + for l in layers.size(): layers[l].index = l Global.layers_container.get_child(layers.size() - 1 - l).layer = l var layer_cel_container = Global.frames_container.get_child(layers.size() - 1 - l) - for f in range(frames.size()): + for f in frames.size(): layer_cel_container.get_child(f).layer = l layer_cel_container.get_child(f).button_setup() toggle_layer_buttons() @@ -941,7 +941,7 @@ func move_cel(from_frame: int, to_frame: int, layer: int) -> void: # Update the cel buttons for this layer: var layer_cel_container = Global.frames_container.get_child(layers.size() - 1 - layer) - for f in range(frames.size()): + for f in frames.size(): layer_cel_container.get_child(f).frame = f layer_cel_container.get_child(f).button_setup() diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 6077ea7383bb..4df85b1a628f 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -878,7 +878,7 @@ func project_layer_added(layer: int) -> void: project.layers[layer].set_name_to_default(layer) var layer_cel_container := HBoxContainer.new() - for f in range(project.frames.size()): + for f in project.frames.size(): var cel_button = project.frames[f].cels[layer].create_cel_button() cel_button.frame = f cel_button.layer = layer From c233ae878b13638794fb9829ac125f99eea183af Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 23 Jul 2022 15:50:38 -0400 Subject: [PATCH 082/154] updated comments/TODOs --- src/Classes/BaseCel.gd | 20 +++++++++++++++++++- src/Classes/BaseLayer.gd | 2 +- src/Classes/GroupLayer.gd | 2 +- src/Classes/PixelLayer.gd | 2 +- src/Classes/Project.gd | 2 +- 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/Classes/BaseCel.gd b/src/Classes/BaseCel.gd index 7aedf5f3eccd..7b553d99c1a5 100644 --- a/src/Classes/BaseCel.gd +++ b/src/Classes/BaseCel.gd @@ -5,14 +5,32 @@ extends Reference var opacity: float +# Methods to override: + +# TODO H: Perhaps get_content, set_content, and delete_content/clear_content methods will be good to have here: +# - get_content will return certain content of the cel (should metadata be included?) +# - set_content will set the content (same structure as get_content returns) +# - delete/clear_content will erase it, +# - using get_content and set_content could become useful for linking/unlinking cels, and will be reversible for undo +# - this can be used to replace copy_cel and copy_all_cels in layer classes +# - using all 3 will allow you to delete content, and undo it in cel button +# = making this generic and should solve issues with combing cel_button scripts into 1 +# - copy_content may also be a useful method to have + -# Functions to override: # TODO H: Should this be the case? # Each Cel type should have a get_image function, which will either return # its image data for PixelCels, or return a render of that cel. It's meant # for read-only usage of image data from any type of cel +# TODO NOTE ^: I'm thinking this shouldn't be the case right now. I'm thinking each cel should have +# a texture var. using texture.get_data it can be possible to copy selections or color pick. +# There will be an update_texture method, which will either immedietly update it, or set it +# to be queued for update (only frames that aren't currently being viewed). When the user +# isn't drawing, Pixelorama can update these textures. (maybe an update_texture and a queue_texture_update +# method may be better, we'll see + func get_image() -> Image: return null diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index 1e151ee24894..e8f30b91cc82 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -69,7 +69,7 @@ func get_hierarchy_depth() -> int: return 0 -# Functions to Override: +# Methods to override: func serialize() -> Dictionary: assert(index == project.layers.find(self)) # TODO H: remove once sure index is synced properly diff --git a/src/Classes/GroupLayer.gd b/src/Classes/GroupLayer.gd index 7fb0aa6d71f0..f373dd4b9f3c 100644 --- a/src/Classes/GroupLayer.gd +++ b/src/Classes/GroupLayer.gd @@ -7,7 +7,7 @@ var expanded := true func _init(_name := "") -> void: name = _name -# Overridden Functions: +# Overridden Methods: func serialize() -> Dictionary: var data = .serialize() diff --git a/src/Classes/PixelLayer.gd b/src/Classes/PixelLayer.gd index 7e8a7dfa142b..2391fcad19ee 100644 --- a/src/Classes/PixelLayer.gd +++ b/src/Classes/PixelLayer.gd @@ -9,7 +9,7 @@ func _init(_name := "") -> void: name = _name -# Overridden Functions: +# Overridden Methods: func serialize() -> Dictionary: var dict = .serialize() diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 9ae83ff4e69d..ac1f0193dde2 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -399,7 +399,7 @@ func deserialize(dict: Dictionary) -> void: fps = dict.fps _deserialize_metadata(self, dict) - +# TODO H: Consider how these are used: func _serialize_metadata(object: Object) -> Dictionary: var metadata := {} for meta in object.get_meta_list(): From c600c2ee223b0a62dcce2f7defa4542116e71f72 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 13 Aug 2022 18:51:20 -0400 Subject: [PATCH 083/154] Cel content changes intial --- src/Classes/BaseCel.gd | 22 ++++++++- src/Classes/BaseLayer.gd | 2 +- src/Classes/PixelCel.gd | 25 ++++++++++ src/UI/Timeline/PixelCelButton.gd | 80 +++++++++++++++++++++---------- 4 files changed, 101 insertions(+), 28 deletions(-) diff --git a/src/Classes/BaseCel.gd b/src/Classes/BaseCel.gd index 7b553d99c1a5..3988399e7906 100644 --- a/src/Classes/BaseCel.gd +++ b/src/Classes/BaseCel.gd @@ -5,7 +5,7 @@ extends Reference var opacity: float -# Methods to override: +# Methods to Override: # TODO H: Perhaps get_content, set_content, and delete_content/clear_content methods will be good to have here: # - get_content will return certain content of the cel (should metadata be included?) @@ -17,6 +17,26 @@ var opacity: float # = making this generic and should solve issues with combing cel_button scripts into 1 # - copy_content may also be a useful method to have +# TODO H1: These content methods need good doc comments: + +func set_content(content: Array) -> void: + return + +# TODO H0: Consider if the return content methods should have a bool option for including a texture, +# of if the texture should be completely not included (textures aren't always needed. But how can we +# ensure that different texture types are properly set up if textures are completely not included here? +# Will seperate methods for the textures be able to work well? +# Maybe for now, don't worry about possible different texture types, and don't do copying layers/frames +func get_content() -> Array: + return [] + + +func create_empty_content() -> Array: + return [] + + +func copy_content() -> Array: + return [] # TODO H: Should this be the case? diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index e8f30b91cc82..4aff71a81f23 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -69,7 +69,7 @@ func get_hierarchy_depth() -> int: return 0 -# Methods to override: +# Methods to Override: func serialize() -> Dictionary: assert(index == project.layers.find(self)) # TODO H: remove once sure index is synced properly diff --git a/src/Classes/PixelCel.gd b/src/Classes/PixelCel.gd index ac6187e6b7c0..852a3a184c9c 100644 --- a/src/Classes/PixelCel.gd +++ b/src/Classes/PixelCel.gd @@ -22,6 +22,31 @@ func image_changed(value: Image) -> void: image_texture.create_from_image(image, 0) +func set_content(content: Array) -> void: + image = content[0] + image_texture = content[1] + + +func get_content() -> Array: + return [image, image_texture] + + +func create_empty_content() -> Array: + var empty_image := Image.new() + empty_image.create(image.get_size().x, image.get_size().y, false, Image.FORMAT_RGBA8) + var empty_texture := ImageTexture.new() + empty_texture.create_from_image(empty_image, 0) + return [empty_image, empty_texture] + + +func copy_content() -> Array: + var copy_image := Image.new() + copy_image.create_from_data(image.get_width(), image.get_height(), false, Image.FORMAT_RGBA8, image.get_data()) + var copy_texture := ImageTexture.new() + copy_texture.create_from_image(copy_image, 0) + return [copy_image, copy_texture] + + func get_image() -> Image: return image diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index 913c6eb55303..47741a2b8d7c 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -106,6 +106,8 @@ func _on_PopupMenu_id_pressed(id: int) -> void: var project: Project = Global.current_project var f: Frame = project.frames[frame] var cel_index: int = project.layers[layer].linked_cels.find(f) + # TODO H0: If my content methods idea is used, I think new_cels won't need to exist + # Will new_layers be needed either? var new_layers: Array = project.duplicate_layers() var new_cels: Array = f.cels.duplicate() for i in new_cels.size(): @@ -116,18 +118,21 @@ func _on_PopupMenu_id_pressed(id: int) -> void: # TODO H: Make sure all this works with group layers: if popup_menu.get_item_metadata(MenuOptions.LINK) == "Unlink Cel": new_layers[layer].linked_cels.remove(cel_index) - var sprite := Image.new() - sprite.copy_from(f.cels[layer].image) - # TODO L: In PixelCel's image setter, setting the iamge already calls create_from_image on the texture, - # so I think its getting called twice, setting the new image texture first and then setting - # the image should work without having to call create_from_image here: - var sprite_texture := ImageTexture.new() - sprite_texture.create_from_image(sprite, 0) - new_cels[layer].image = sprite - new_cels[layer].image_texture = sprite_texture +# var sprite := Image.new() +# sprite.copy_from(f.cels[layer].image) +# # TODO L: In PixelCel's image setter, setting the iamge already calls create_from_image on the texture, +# # so I think its getting called twice, setting the new image texture first and then setting +# # the image should work without having to call create_from_image here: +# var sprite_texture := ImageTexture.new() +# sprite_texture.create_from_image(sprite, 0) +# new_cels[layer].image = sprite +# new_cels[layer].image_texture = sprite_texture project.undo_redo.create_action("Unlink Cel") - project.undo_redo.add_do_property(f, "cels", new_cels) - project.undo_redo.add_undo_property(f, "cels", f.cels) +# project.undo_redo.add_do_property(f, "cels", new_cels) +# project.undo_redo.add_undo_property(f, "cels", f.cels) + var cel: BaseCel = project.frames[frame].cels[layer] + project.undo_redo.add_do_method(cel, "set_content", cel.copy_content()) + project.undo_redo.add_undo_method(cel, "set_content", cel.get_content()) elif popup_menu.get_item_metadata(MenuOptions.LINK) == "Link Cel": new_layers[layer].linked_cels.append(f) @@ -135,10 +140,14 @@ func _on_PopupMenu_id_pressed(id: int) -> void: if new_layers[layer].linked_cels.size() > 1: # If there are already linked cels, set the current cel's image # to the first linked cel's image - new_cels[layer].image = new_layers[layer].linked_cels[0].cels[layer].image - new_cels[layer].image_texture = new_layers[layer].linked_cels[0].cels[layer].image_texture - project.undo_redo.add_do_property(f, "cels", new_cels) - project.undo_redo.add_undo_property(f, "cels", f.cels) +# new_cels[layer].image = new_layers[layer].linked_cels[0].cels[layer].image +# new_cels[layer].image_texture = new_layers[layer].linked_cels[0].cels[layer].image_texture +# project.undo_redo.add_do_property(f, "cels", new_cels) +# project.undo_redo.add_undo_property(f, "cels", f.cels) + var cel: BaseCel = project.frames[frame].cels[layer] + var linked_cel: BaseCel = project.layers[layer].linked_cels[0].cels[layer] + project.undo_redo.add_do_method(cel, "set_content", linked_cel.get_content()) + project.undo_redo.add_undo_method(cel, "set_content", cel.get_content()) project.undo_redo.add_do_property(project, "layers", new_layers) project.undo_redo.add_undo_property(project, "layers", project.layers) @@ -155,21 +164,40 @@ func _on_PopupMenu_id_pressed(id: int) -> void: func _delete_cel_content() -> void: - if image.is_invisible(): - return - var curr_layer: PixelLayer = Global.current_project.layers[layer] - if !curr_layer.can_layer_get_drawn(): - return +# if image.is_invisible(): +# return +# var curr_layer: PixelLayer = Global.current_project.layers[layer] +# if !curr_layer.can_layer_get_drawn(): +# return +# var project = Global.current_project +# image.unlock() +# var data := image.data +# project.undos += 1 +# project.undo_redo.create_action("Draw") +# project.undo_redo.add_undo_property(image, "data", data) +# project.undo_redo.add_undo_method(Global, "undo_or_redo", true, frame, layer, project) +# image.fill(0) +# project.undo_redo.add_do_property(image, "data", image.data) +# project.undo_redo.add_do_method(Global, "undo_or_redo", false, frame, layer, project) +# project.undo_redo.commit_action()' var project = Global.current_project - image.unlock() - var data := image.data + var cel: BaseCel = project.frames[frame].cels[layer] + var empty_content = cel.create_empty_content() + var old_content = cel.get_content() project.undos += 1 project.undo_redo.create_action("Draw") - project.undo_redo.add_undo_property(image, "data", data) - project.undo_redo.add_undo_method(Global, "undo_or_redo", true, frame, layer, project) - image.fill(0) - project.undo_redo.add_do_property(image, "data", image.data) + if project.frames[frame] in project.layers[layer].linked_cels: + for frame in project.layers[layer].linked_cels: + project.undo_redo.add_do_method(frame.cels[layer], "set_content", empty_content) + project.undo_redo.add_undo_method(frame.cels[layer], "set_content", old_content) + # TODO H0: Creating an empty texture here is wasting memory, also the updating + # TODO would be fixed automatically by using the same texture + # TODO H0: The other cel buttons need their texture updated... + else: + project.undo_redo.add_do_method(cel, "set_content", empty_content) + project.undo_redo.add_undo_method(cel, "set_content", old_content) project.undo_redo.add_do_method(Global, "undo_or_redo", false, frame, layer, project) + project.undo_redo.add_undo_method(Global, "undo_or_redo", true, frame, layer, project) project.undo_redo.commit_action() From d24938b18940114314d6e6751f27a413cbe1c66d Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 8 Sep 2022 14:45:29 -0400 Subject: [PATCH 084/154] Added 'content' methods to Cel classes --- src/Classes/BaseCel.gd | 9 ++++---- src/Classes/PixelCel.gd | 24 ++++++++----------- src/UI/Timeline/PixelCelButton.gd | 38 ++++--------------------------- 3 files changed, 19 insertions(+), 52 deletions(-) diff --git a/src/Classes/BaseCel.gd b/src/Classes/BaseCel.gd index 3988399e7906..e6c3c48a2abd 100644 --- a/src/Classes/BaseCel.gd +++ b/src/Classes/BaseCel.gd @@ -4,6 +4,7 @@ extends Reference # The term "cel" comes from "celluloid" (https://en.wikipedia.org/wiki/Cel). var opacity: float +var image_texture: ImageTexture # Methods to Override: @@ -19,7 +20,7 @@ var opacity: float # TODO H1: These content methods need good doc comments: -func set_content(content: Array) -> void: +func set_content(content) -> void: return # TODO H0: Consider if the return content methods should have a bool option for including a texture, @@ -27,15 +28,15 @@ func set_content(content: Array) -> void: # ensure that different texture types are properly set up if textures are completely not included here? # Will seperate methods for the textures be able to work well? # Maybe for now, don't worry about possible different texture types, and don't do copying layers/frames -func get_content() -> Array: +func get_content(): return [] -func create_empty_content() -> Array: +func create_empty_content(): return [] -func copy_content() -> Array: +func copy_content(): return [] diff --git a/src/Classes/PixelCel.gd b/src/Classes/PixelCel.gd index 852a3a184c9c..808c8b204616 100644 --- a/src/Classes/PixelCel.gd +++ b/src/Classes/PixelCel.gd @@ -5,7 +5,7 @@ extends BaseCel # The "image" variable is where the image data of each cel are. var image: Image setget image_changed -var image_texture: ImageTexture +#var image_texture: ImageTexture # TODO H1: ERASE if having in base class works nicely func _init(_image := Image.new(), _opacity := 1.0, _image_texture: ImageTexture = null) -> void: if _image_texture: @@ -22,29 +22,25 @@ func image_changed(value: Image) -> void: image_texture.create_from_image(image, 0) -func set_content(content: Array) -> void: - image = content[0] - image_texture = content[1] +func set_content(content) -> void: + image = content + image_texture.create_from_image(image, 0) -func get_content() -> Array: - return [image, image_texture] +func get_content(): + return image -func create_empty_content() -> Array: +func create_empty_content(): var empty_image := Image.new() empty_image.create(image.get_size().x, image.get_size().y, false, Image.FORMAT_RGBA8) - var empty_texture := ImageTexture.new() - empty_texture.create_from_image(empty_image, 0) - return [empty_image, empty_texture] + return empty_image -func copy_content() -> Array: +func copy_content(): var copy_image := Image.new() copy_image.create_from_data(image.get_width(), image.get_height(), false, Image.FORMAT_RGBA8, image.get_data()) - var copy_texture := ImageTexture.new() - copy_texture.create_from_image(copy_image, 0) - return [copy_image, copy_texture] + return copy_image func get_image() -> Image: diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index 47741a2b8d7c..69144af87ac2 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -118,19 +118,10 @@ func _on_PopupMenu_id_pressed(id: int) -> void: # TODO H: Make sure all this works with group layers: if popup_menu.get_item_metadata(MenuOptions.LINK) == "Unlink Cel": new_layers[layer].linked_cels.remove(cel_index) -# var sprite := Image.new() -# sprite.copy_from(f.cels[layer].image) -# # TODO L: In PixelCel's image setter, setting the iamge already calls create_from_image on the texture, -# # so I think its getting called twice, setting the new image texture first and then setting -# # the image should work without having to call create_from_image here: -# var sprite_texture := ImageTexture.new() -# sprite_texture.create_from_image(sprite, 0) -# new_cels[layer].image = sprite -# new_cels[layer].image_texture = sprite_texture project.undo_redo.create_action("Unlink Cel") -# project.undo_redo.add_do_property(f, "cels", new_cels) -# project.undo_redo.add_undo_property(f, "cels", f.cels) var cel: BaseCel = project.frames[frame].cels[layer] + project.undo_redo.add_do_property(cel, "image_texture", ImageTexture.new()) + project.undo_redo.add_undo_property(cel, "image_texture", cel.image_texture) project.undo_redo.add_do_method(cel, "set_content", cel.copy_content()) project.undo_redo.add_undo_method(cel, "set_content", cel.get_content()) @@ -140,12 +131,10 @@ func _on_PopupMenu_id_pressed(id: int) -> void: if new_layers[layer].linked_cels.size() > 1: # If there are already linked cels, set the current cel's image # to the first linked cel's image -# new_cels[layer].image = new_layers[layer].linked_cels[0].cels[layer].image -# new_cels[layer].image_texture = new_layers[layer].linked_cels[0].cels[layer].image_texture -# project.undo_redo.add_do_property(f, "cels", new_cels) -# project.undo_redo.add_undo_property(f, "cels", f.cels) var cel: BaseCel = project.frames[frame].cels[layer] var linked_cel: BaseCel = project.layers[layer].linked_cels[0].cels[layer] + project.undo_redo.add_do_property(cel, "image_texture", linked_cel.image_texture) + project.undo_redo.add_undo_property(cel, "image_texture", cel.image_texture) project.undo_redo.add_do_method(cel, "set_content", linked_cel.get_content()) project.undo_redo.add_undo_method(cel, "set_content", cel.get_content()) @@ -164,22 +153,6 @@ func _on_PopupMenu_id_pressed(id: int) -> void: func _delete_cel_content() -> void: -# if image.is_invisible(): -# return -# var curr_layer: PixelLayer = Global.current_project.layers[layer] -# if !curr_layer.can_layer_get_drawn(): -# return -# var project = Global.current_project -# image.unlock() -# var data := image.data -# project.undos += 1 -# project.undo_redo.create_action("Draw") -# project.undo_redo.add_undo_property(image, "data", data) -# project.undo_redo.add_undo_method(Global, "undo_or_redo", true, frame, layer, project) -# image.fill(0) -# project.undo_redo.add_do_property(image, "data", image.data) -# project.undo_redo.add_do_method(Global, "undo_or_redo", false, frame, layer, project) -# project.undo_redo.commit_action()' var project = Global.current_project var cel: BaseCel = project.frames[frame].cels[layer] var empty_content = cel.create_empty_content() @@ -190,9 +163,6 @@ func _delete_cel_content() -> void: for frame in project.layers[layer].linked_cels: project.undo_redo.add_do_method(frame.cels[layer], "set_content", empty_content) project.undo_redo.add_undo_method(frame.cels[layer], "set_content", old_content) - # TODO H0: Creating an empty texture here is wasting memory, also the updating - # TODO would be fixed automatically by using the same texture - # TODO H0: The other cel buttons need their texture updated... else: project.undo_redo.add_do_method(cel, "set_content", empty_content) project.undo_redo.add_undo_method(cel, "set_content", old_content) From 3bdc03c50988d98412806be786545522b5e2067f Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 8 Sep 2022 14:55:40 -0400 Subject: [PATCH 085/154] Removed image var from PixelCelButton --- src/UI/Timeline/PixelCelButton.gd | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index 69144af87ac2..1b85cb86f649 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -5,7 +5,6 @@ enum MenuOptions { DELETE, LINK, PROPERTIES } var frame := 0 var layer := 0 var cel: PixelCel -var image: Image onready var popup_menu: PopupMenu = $PopupMenu onready var linked_indicator: Polygon2D = $LinkedIndicator @@ -32,7 +31,6 @@ func button_setup() -> void: var checker = $CelTexture/TransparentChecker checker.rect_size = checker.get_parent().rect_size cel = Global.current_project.frames[frame].cels[layer] - image = cel.image func _on_CelButton_resized() -> void: @@ -110,6 +108,7 @@ func _on_PopupMenu_id_pressed(id: int) -> void: # Will new_layers be needed either? var new_layers: Array = project.duplicate_layers() var new_cels: Array = f.cels.duplicate() + # TODO H: Make sure all this works with group layers: for i in new_cels.size(): # TODO H: This doesn't work (currently replaces ALL cels on the frame) new_cels[i] = PixelCel.new( From 172a47624a3afa9f5677671319427b8ebb8e7534 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 8 Sep 2022 15:04:23 -0400 Subject: [PATCH 086/154] Reusing PixelCelButton.gd on GroupCelButton scene --- src/UI/Timeline/GroupCelButton.tscn | 2 +- src/UI/Timeline/PixelCelButton.gd | 23 ++++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/UI/Timeline/GroupCelButton.tscn b/src/UI/Timeline/GroupCelButton.tscn index 75035ca7c51c..6ee65d05337c 100644 --- a/src/UI/Timeline/GroupCelButton.tscn +++ b/src/UI/Timeline/GroupCelButton.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=3 format=2] [ext_resource path="res://src/UI/Timeline/BaseCelButton.tscn" type="PackedScene" id=1] -[ext_resource path="res://src/UI/Timeline/GroupCelButton.gd" type="Script" id=2] +[ext_resource path="res://src/UI/Timeline/PixelCelButton.gd" type="Script" id=2] [node name="GroupCelButton" instance=ExtResource( 1 )] script = ExtResource( 2 ) diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/PixelCelButton.gd index 1b85cb86f649..eae69dfc1153 100644 --- a/src/UI/Timeline/PixelCelButton.gd +++ b/src/UI/Timeline/PixelCelButton.gd @@ -4,10 +4,10 @@ enum MenuOptions { DELETE, LINK, PROPERTIES } var frame := 0 var layer := 0 -var cel: PixelCel +var cel: BaseCel -onready var popup_menu: PopupMenu = $PopupMenu -onready var linked_indicator: Polygon2D = $LinkedIndicator +onready var popup_menu: PopupMenu = get_node_or_null("PopupMenu") +onready var linked_indicator: Polygon2D = get_node_or_null("LinkedIndicator") func _ready() -> void: button_setup() @@ -18,14 +18,15 @@ func button_setup() -> void: rect_min_size.y = Global.animation_timeline.cel_size hint_tooltip = tr("Frame: %s, Layer: %s") % [frame + 1, layer] - if Global.current_project.frames[frame] in Global.current_project.layers[layer].linked_cels: - linked_indicator.visible = true - popup_menu.set_item_text(MenuOptions.LINK, "Unlink Cel") - popup_menu.set_item_metadata(MenuOptions.LINK, "Unlink Cel") - else: - linked_indicator.visible = false - popup_menu.set_item_text(MenuOptions.LINK, "Link Cel") - popup_menu.set_item_metadata(MenuOptions.LINK, "Link Cel") + if is_instance_valid(linked_indicator): + if Global.current_project.frames[frame] in Global.current_project.layers[layer].linked_cels: + linked_indicator.visible = true + popup_menu.set_item_text(MenuOptions.LINK, "Unlink Cel") + popup_menu.set_item_metadata(MenuOptions.LINK, "Unlink Cel") + else: + linked_indicator.visible = false + popup_menu.set_item_text(MenuOptions.LINK, "Link Cel") + popup_menu.set_item_metadata(MenuOptions.LINK, "Link Cel") # Reset the checkers size because it assumes you want the same size as the canvas var checker = $CelTexture/TransparentChecker From c5b50b0af765285f82058ae30cb2018590cf1587 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 8 Sep 2022 15:08:36 -0400 Subject: [PATCH 087/154] Renamed PixelCelButton.gd to CelButton.gd (as it will be used for all Cel Buttons) and deleted GroupCelButton.gd --- .../{PixelCelButton.gd => CelButton.gd} | 0 src/UI/Timeline/GroupCelButton.gd | 35 ------------------- src/UI/Timeline/GroupCelButton.tscn | 2 +- src/UI/Timeline/PixelCelButton.tscn | 2 +- 4 files changed, 2 insertions(+), 37 deletions(-) rename src/UI/Timeline/{PixelCelButton.gd => CelButton.gd} (100%) delete mode 100644 src/UI/Timeline/GroupCelButton.gd diff --git a/src/UI/Timeline/PixelCelButton.gd b/src/UI/Timeline/CelButton.gd similarity index 100% rename from src/UI/Timeline/PixelCelButton.gd rename to src/UI/Timeline/CelButton.gd diff --git a/src/UI/Timeline/GroupCelButton.gd b/src/UI/Timeline/GroupCelButton.gd deleted file mode 100644 index eece7f346cb6..000000000000 --- a/src/UI/Timeline/GroupCelButton.gd +++ /dev/null @@ -1,35 +0,0 @@ -extends Button - -var frame := 0 -var layer := 0 -var cel: GroupCel -var mat: Material - - -func _ready() -> void: - button_setup() - - -func button_setup() -> void: - rect_min_size.x = Global.animation_timeline.cel_size - rect_min_size.y = Global.animation_timeline.cel_size - - hint_tooltip = tr("Frame: %s, Layer: %s") % [frame + 1, layer] - - # Reset the checkers size because it assumes you want the same size as the canvas - var checker = $CelTexture/TransparentChecker - checker.rect_size = checker.get_parent().rect_size -# cel = Global.current_project.frames[frame].cels[layer] - #image = cel.image - - -func _on_GroupCelButton_resized() -> void: - get_node("CelTexture").rect_min_size.x = rect_min_size.x - 4 - get_node("CelTexture").rect_min_size.y = rect_min_size.y - 4 - - -func _pressed(): - # TODO L: PixelCelButton could just use the func instead of signal too - - # TODO H: Some of the funtionality from PixelCelButton needs to be moved over - pass diff --git a/src/UI/Timeline/GroupCelButton.tscn b/src/UI/Timeline/GroupCelButton.tscn index 6ee65d05337c..2846f7adbfef 100644 --- a/src/UI/Timeline/GroupCelButton.tscn +++ b/src/UI/Timeline/GroupCelButton.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=3 format=2] [ext_resource path="res://src/UI/Timeline/BaseCelButton.tscn" type="PackedScene" id=1] -[ext_resource path="res://src/UI/Timeline/PixelCelButton.gd" type="Script" id=2] +[ext_resource path="res://src/UI/Timeline/CelButton.gd" type="Script" id=2] [node name="GroupCelButton" instance=ExtResource( 1 )] script = ExtResource( 2 ) diff --git a/src/UI/Timeline/PixelCelButton.tscn b/src/UI/Timeline/PixelCelButton.tscn index 0a729386a722..dd057087c7bd 100644 --- a/src/UI/Timeline/PixelCelButton.tscn +++ b/src/UI/Timeline/PixelCelButton.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=3 format=2] [ext_resource path="res://src/UI/Timeline/BaseCelButton.tscn" type="PackedScene" id=1] -[ext_resource path="res://src/UI/Timeline/PixelCelButton.gd" type="Script" id=2] +[ext_resource path="res://src/UI/Timeline/CelButton.gd" type="Script" id=2] [node name="PixelCelButton" instance=ExtResource( 1 )] rect_pivot_offset = Vector2( -18, 6 ) From 5c36673bd88ecd24254a5cd08e7df0ce12960334 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 8 Sep 2022 15:12:00 -0400 Subject: [PATCH 088/154] Hide the TransparentChecker on GroupCelButton.tscn until a preview texture is added for GroupCels --- src/UI/Timeline/GroupCelButton.tscn | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/UI/Timeline/GroupCelButton.tscn b/src/UI/Timeline/GroupCelButton.tscn index 2846f7adbfef..07476c0099e4 100644 --- a/src/UI/Timeline/GroupCelButton.tscn +++ b/src/UI/Timeline/GroupCelButton.tscn @@ -5,3 +5,6 @@ [node name="GroupCelButton" instance=ExtResource( 1 )] script = ExtResource( 2 ) + +[node name="TransparentChecker" parent="CelTexture" index="0"] +visible = false From f377848e504c81a08f884e0aba28165553b49a31 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 9 Sep 2022 13:33:11 -0400 Subject: [PATCH 089/154] TODOs, prevent memory leak when closing projects --- src/Autoload/OpenSave.gd | 3 ++- src/Classes/BaseLayer.gd | 3 --- src/Classes/GroupCel.gd | 2 +- src/Classes/PixelCel.gd | 1 - src/Classes/Project.gd | 2 ++ 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index 2dc279683734..32e0d2aed910 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -442,6 +442,7 @@ func open_image_as_spritesheet_tab(path: String, image: Image, horiz: int, vert: func open_image_as_spritesheet_layer( _path: String, image: Image, file_name: String, horizontal: int, vertical: int, start_frame: int ) -> void: + # TODO H0: Will need to rewrite this method using new ways to add layers/frames. (no ducplicate arrays). Check other open methods too! # Data needed to slice images horizontal = min(horizontal, image.get_size().x) vertical = min(vertical, image.get_size().y) @@ -475,7 +476,7 @@ func open_image_as_spritesheet_layer( for l_i in range(new_layers.size()): # Create as many cels as there are layers var new_img := Image.new() new_img.create(project_width, project_height, false, Image.FORMAT_RGBA8) - # TODO H1: Make sure this PixelCel is right: + # TODO H1: Make sure this PixelCel is right: (I this can be for any layer type) new_frame.cels.append(PixelCel.new(new_img, 1)) if new_layers[l_i].new_cels_linked: new_layers[l_i].linked_cels.append(new_frame) diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index 4aff71a81f23..d1e167fd8040 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -7,9 +7,6 @@ var visible := true var locked := false var blend_mode := 0 var parent: BaseLayer -# TODO H: Memory seems to not be freed when closing a project. I suspect this new project ref to -# be the reason (in Project.remove simply removing the project from the Global.projects array -# can't auto free it because there's still refences to it, in the layers): var project var index: int diff --git a/src/Classes/GroupCel.gd b/src/Classes/GroupCel.gd index f1f5868e7432..ff44f1b8632e 100644 --- a/src/Classes/GroupCel.gd +++ b/src/Classes/GroupCel.gd @@ -8,7 +8,7 @@ func _init(_opacity := 1.0) -> void: func get_image() -> Image: - # TODO H: render the material as an image and return it + # TODO H: This can be used for copying selections or picking colors... Can maybe make from texture data? return Image.new() diff --git a/src/Classes/PixelCel.gd b/src/Classes/PixelCel.gd index 808c8b204616..cf1270d1d92b 100644 --- a/src/Classes/PixelCel.gd +++ b/src/Classes/PixelCel.gd @@ -5,7 +5,6 @@ extends BaseCel # The "image" variable is where the image data of each cel are. var image: Image setget image_changed -#var image_texture: ImageTexture # TODO H1: ERASE if having in base class works nicely func _init(_image := Image.new(), _opacity := 1.0, _image_texture: ImageTexture = null) -> void: if _image_texture: diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 8f9db511fd7c..ddf0ff165048 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -86,6 +86,8 @@ func remove() -> void: undo_redo.free() for guide in guides: guide.queue_free() + # Prevents memory leak (due to the layers' project reference stopping ref counting from freeing) + layers.clear() Global.projects.erase(self) From 8dfe30a1b166d590c0b125739b588932fa05aa3b Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 9 Sep 2022 13:59:51 -0400 Subject: [PATCH 090/154] Link/unlink cel cleanup : --- src/UI/Timeline/CelButton.gd | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/UI/Timeline/CelButton.gd b/src/UI/Timeline/CelButton.gd index eae69dfc1153..123534baa324 100644 --- a/src/UI/Timeline/CelButton.gd +++ b/src/UI/Timeline/CelButton.gd @@ -87,8 +87,9 @@ func _on_CelButton_pressed() -> void: release_focus() elif Input.is_action_just_released("right_mouse"): - popup_menu.popup(Rect2(get_global_mouse_position(), Vector2.ONE)) - pressed = !pressed + if is_instance_valid(popup_menu): + popup_menu.popup(Rect2(get_global_mouse_position(), Vector2.ONE)) + pressed = !pressed elif Input.is_action_just_released("middle_mouse"): pressed = !pressed _delete_cel_content() @@ -105,19 +106,9 @@ func _on_PopupMenu_id_pressed(id: int) -> void: var project: Project = Global.current_project var f: Frame = project.frames[frame] var cel_index: int = project.layers[layer].linked_cels.find(f) - # TODO H0: If my content methods idea is used, I think new_cels won't need to exist - # Will new_layers be needed either? - var new_layers: Array = project.duplicate_layers() - var new_cels: Array = f.cels.duplicate() - # TODO H: Make sure all this works with group layers: - for i in new_cels.size(): - # TODO H: This doesn't work (currently replaces ALL cels on the frame) - new_cels[i] = PixelCel.new( - new_cels[i].image, new_cels[i].opacity, new_cels[i].image_texture - ) - # TODO H: Make sure all this works with group layers: + var new_linked_cels: Array = project.layers[layer].linked_cels.duplicate() if popup_menu.get_item_metadata(MenuOptions.LINK) == "Unlink Cel": - new_layers[layer].linked_cels.remove(cel_index) + new_linked_cels.remove(cel_index) project.undo_redo.create_action("Unlink Cel") var cel: BaseCel = project.frames[frame].cels[layer] project.undo_redo.add_do_property(cel, "image_texture", ImageTexture.new()) @@ -126,9 +117,9 @@ func _on_PopupMenu_id_pressed(id: int) -> void: project.undo_redo.add_undo_method(cel, "set_content", cel.get_content()) elif popup_menu.get_item_metadata(MenuOptions.LINK) == "Link Cel": - new_layers[layer].linked_cels.append(f) + new_linked_cels.append(f) project.undo_redo.create_action("Link Cel") - if new_layers[layer].linked_cels.size() > 1: + if new_linked_cels.size() > 1: # If there are already linked cels, set the current cel's image # to the first linked cel's image var cel: BaseCel = project.frames[frame].cels[layer] @@ -138,8 +129,10 @@ func _on_PopupMenu_id_pressed(id: int) -> void: project.undo_redo.add_do_method(cel, "set_content", linked_cel.get_content()) project.undo_redo.add_undo_method(cel, "set_content", cel.get_content()) - project.undo_redo.add_do_property(project, "layers", new_layers) - project.undo_redo.add_undo_property(project, "layers", project.layers) + project.undo_redo.add_do_property(project.layers[layer], "linked_cels", new_linked_cels) + project.undo_redo.add_undo_property( + project.layers[layer], "linked_cels", project.layers[layer].linked_cels + ) # Remove and add a new cel button to update appearance (can't use self.button_setup # because there is no guarantee that it will be the exact same cel button instance) project.undo_redo.add_do_method(Global.animation_timeline, "project_cel_removed", frame, layer) From 8d211251f8ec8402e1d61959fdfe3be885d4ac6d Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 9 Sep 2022 14:23:43 -0400 Subject: [PATCH 091/154] Added _project param to _init methods of Layer classes --- src/Autoload/OpenSave.gd | 12 ++++++------ src/Classes/BaseLayer.gd | 2 +- src/Classes/GroupLayer.gd | 3 ++- src/Classes/PixelLayer.gd | 5 +++-- src/Classes/Project.gd | 5 ++--- src/Main.gd | 3 +-- src/UI/Dialogs/CreateNewImage.gd | 3 +-- src/UI/Timeline/AnimationTimeline.gd | 4 ++-- 8 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index 32e0d2aed910..d9aa6c96cf4e 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -202,7 +202,7 @@ func open_old_pxo_file(file: File, new_project: Project, first_line: String) -> "linked_cels": [] } linked_cels.append(file.get_var()) - var l := PixelLayer.new() + var l := PixelLayer.new(new_project) l.deserialize(layer_dict) new_project.layers.append(l) global_layer_line = file.get_line() @@ -220,7 +220,7 @@ func open_old_pxo_file(file: File, new_project: Project, first_line: String) -> if file_major_version == 0 and file_minor_version < 7: var layer_name_old_version = file.get_line() if frame == 0: - var l := PixelLayer.new(layer_name_old_version) + var l := PixelLayer.new(new_project, layer_name_old_version) new_project.layers.append(l) var cel_opacity := 1.0 if file_major_version >= 0 and file_minor_version > 5: @@ -398,7 +398,7 @@ func save_pxo_file( func open_image_as_new_tab(path: String, image: Image) -> void: var project = Project.new([], path.get_file(), image.get_size()) - project.layers.append(PixelLayer.new()) + project.layers.append(PixelLayer.new(project)) Global.projects.append(project) var frame := Frame.new() @@ -411,7 +411,7 @@ func open_image_as_new_tab(path: String, image: Image) -> void: func open_image_as_spritesheet_tab(path: String, image: Image, horiz: int, vert: int) -> void: var project = Project.new([], path.get_file()) - project.layers.append(PixelLayer.new()) + project.layers.append(PixelLayer.new(project)) Global.projects.append(project) horiz = min(horiz, image.get_size().x) vert = min(vert, image.get_size().y) @@ -485,7 +485,7 @@ func open_image_as_spritesheet_layer( new_frames.insert(project.current_frame + 1, new_frame) # Create new layer for spritesheet - var layer := PixelLayer.new(file_name) + var layer := PixelLayer.new(project, file_name) new_layers.append(layer) for f in new_frames: var new_layer := Image.new() @@ -589,7 +589,7 @@ func open_image_as_new_layer(image: Image, file_name: String, frame_index := 0) var project = Global.current_project image.crop(project.size.x, project.size.y) var new_layers: Array = Global.current_project.layers.duplicate() - var layer := PixelLayer.new(file_name) + var layer := PixelLayer.new(project, file_name) Global.current_project.undos += 1 Global.current_project.undo_redo.create_action("Add Layer") diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index d1e167fd8040..15722b6672b1 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -89,7 +89,7 @@ func deserialize(dict: Dictionary) -> void: func copy() -> BaseLayer: - var copy = get_script().new() + var copy = get_script().new(project) copy.project = project copy.index = index copy.deserialize(serialize()) diff --git a/src/Classes/GroupLayer.gd b/src/Classes/GroupLayer.gd index f373dd4b9f3c..63ecc6739798 100644 --- a/src/Classes/GroupLayer.gd +++ b/src/Classes/GroupLayer.gd @@ -4,7 +4,8 @@ extends BaseLayer var expanded := true -func _init(_name := "") -> void: +func _init(_project, _name := "") -> void: + project = _project name = _name # Overridden Methods: diff --git a/src/Classes/PixelLayer.gd b/src/Classes/PixelLayer.gd index 2391fcad19ee..ba2ee87bff2a 100644 --- a/src/Classes/PixelLayer.gd +++ b/src/Classes/PixelLayer.gd @@ -4,8 +4,9 @@ extends BaseLayer var new_cels_linked := false var linked_cels := [] # Array of Frames -# TODO H: Should _init include project as a parameter? (for all Layer types) -func _init(_name := "") -> void: + +func _init(_project, _name := "") -> void: + project = _project name = _name diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index ddf0ff165048..47fac634c98b 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -363,13 +363,12 @@ func deserialize(dict: Dictionary) -> void: for saved_layer in dict.layers: match int(saved_layer.get("type", Global.LayerTypes.PIXEL)): Global.LayerTypes.PIXEL: - layers.append(PixelLayer.new()) + layers.append(PixelLayer.new(self)) Global.LayerTypes.GROUP: - layers.append(GroupLayer.new()) + layers.append(GroupLayer.new(self)) # Parent references to other layers are created when deserializing # a layer, so loop again after creating them: for layer_i in dict.layers.size(): - layers[layer_i].project = self layers[layer_i].index = layer_i layers[layer_i].deserialize(dict.layers[layer_i]) _deserialize_metadata(layers[layer_i], dict.layers[layer_i]) diff --git a/src/Main.gd b/src/Main.gd index 2dd12a898a64..7e380698dbc6 100644 --- a/src/Main.gd +++ b/src/Main.gd @@ -25,8 +25,7 @@ func _ready() -> void: Global.window_title = tr("untitled") + " - Pixelorama " + Global.current_version - Global.current_project.layers.append(PixelLayer.new()) - Global.current_project.layers[0].project = Global.current_project + Global.current_project.layers.append(PixelLayer.new(Global.current_project)) Global.current_project.frames.append(Global.current_project.new_empty_frame()) Global.animation_timeline.project_changed() Global.current_project.toggle_frame_buttons() diff --git a/src/UI/Dialogs/CreateNewImage.gd b/src/UI/Dialogs/CreateNewImage.gd index 49a65d98141f..a20bb0967cc6 100644 --- a/src/UI/Dialogs/CreateNewImage.gd +++ b/src/UI/Dialogs/CreateNewImage.gd @@ -108,8 +108,7 @@ func _on_CreateNewImage_confirmed() -> void: proj_name = tr("untitled") var new_project := Project.new([], proj_name, Vector2(width, height).floor()) - new_project.layers.append(PixelLayer.new()) - new_project.layers[0].project = new_project + new_project.layers.append(PixelLayer.new(new_project)) new_project.fill_color = fill_color new_project.frames.append(new_project.new_empty_frame()) Global.projects.append(new_project) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 6d2abbe65a57..79456fef800e 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -584,7 +584,7 @@ func _on_FuturePlacement_item_selected(index: int) -> void: func _on_AddLayer_pressed() -> void: var project: Project = Global.current_project - var l := PixelLayer.new() + var l := PixelLayer.new(project) var cels := [] for f in project.frames: var new_cel_image := Image.new() @@ -605,7 +605,7 @@ func _on_AddLayer_pressed() -> void: func _on_AddGroup_pressed() -> void: var project: Project = Global.current_project - var l := GroupLayer.new() + var l := GroupLayer.new(project) var cels := [] for f in project.frames: cels.append(GroupCel.new()) From c568e4f0c26cf6afeda75ab0b5dba52e90d4b24d Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Mon, 12 Sep 2022 11:11:05 -0400 Subject: [PATCH 092/154] Added update_texture method to Cel classes (moving part from the update_texture and update_selected_cels_textures methods from Canvas.gd --- src/Autoload/Global.gd | 1 + src/Classes/BaseCel.gd | 4 ++++ src/Classes/PixelCel.gd | 4 ++++ src/UI/Canvas/Canvas.gd | 25 ++++++++++++------------- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index d493de7cad12..c5c823be17a5 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -439,6 +439,7 @@ func undo_or_redo( ] ): # TODO H: Check this: THIS IS PROBABLY WRONG (can't check if GROUP LAYER if INDEX is -1) + # I THINK IF I ADD AN UPDATE_TEXTURE METHOD TO EACH CEL TYPE, IT WON'T NEED THIS CHECK! if not current_project.layers[layer_index] is GroupLayer: if layer_index > -1 and frame_index > -1: canvas.update_texture(layer_index, frame_index, project) diff --git a/src/Classes/BaseCel.gd b/src/Classes/BaseCel.gd index e6c3c48a2abd..8434158dbbb2 100644 --- a/src/Classes/BaseCel.gd +++ b/src/Classes/BaseCel.gd @@ -56,6 +56,10 @@ func get_image() -> Image: return null +func update_texture() -> void: + return + + func save_image_data_to_pxo(_file: File) -> void: return diff --git a/src/Classes/PixelCel.gd b/src/Classes/PixelCel.gd index cf1270d1d92b..b3760df1bcc3 100644 --- a/src/Classes/PixelCel.gd +++ b/src/Classes/PixelCel.gd @@ -46,6 +46,10 @@ func get_image() -> Image: return image +func update_texture() -> void: + image_texture.set_data(image) + + func save_image_data_to_pxo(file: File) -> void: file.store_buffer(image.get_data()) diff --git a/src/UI/Canvas/Canvas.gd b/src/UI/Canvas/Canvas.gd index 22033ec01949..8cc929591b4f 100644 --- a/src/UI/Canvas/Canvas.gd +++ b/src/UI/Canvas/Canvas.gd @@ -123,17 +123,17 @@ func update_texture(layer_i: int, frame_i := -1, project: Project = Global.curre frame_i = project.current_frame if frame_i < project.frames.size() and layer_i < project.layers.size(): - # TODO H: make sure this is right: - var current_cel: PixelCel = project.frames[frame_i].cels[layer_i] - current_cel.image_texture.set_data(current_cel.image) + var current_cel: BaseCel = project.frames[frame_i].cels[layer_i] + current_cel.update_texture() - if project == Global.current_project: - var container_index = Global.frames_container.get_child_count() - 1 - layer_i - var layer_cel_container = Global.frames_container.get_child(container_index) - var cel_button = layer_cel_container.get_child(frame_i) - var cel_texture_rect: TextureRect - cel_texture_rect = cel_button.find_node("CelTexture") - cel_texture_rect.texture = current_cel.image_texture + # TODO H: is this even needed? (Same as below) +# if project == Global.current_project: +# var container_index = Global.frames_container.get_child_count() - 1 - layer_i +# var layer_cel_container = Global.frames_container.get_child(container_index) +# var cel_button = layer_cel_container.get_child(frame_i) +# var cel_texture_rect: TextureRect +# cel_texture_rect = cel_button.find_node("CelTexture") +# cel_texture_rect.texture = current_cel.image_texture func update_selected_cels_textures(project: Project = Global.current_project) -> void: @@ -141,9 +141,8 @@ func update_selected_cels_textures(project: Project = Global.current_project) -> var frame_index: int = cel_index[0] var layer_index: int = cel_index[1] if frame_index < project.frames.size() and layer_index < project.layers.size(): - # TODO H: make sure this is right: - var current_cel: PixelCel = project.frames[frame_index].cels[layer_index] - current_cel.image_texture.set_data(current_cel.image) + var current_cel: BaseCel = project.frames[frame_index].cels[layer_index] + current_cel.update_texture() # TODO H: This wasn't working anymore, but is it even needed? (Same as above) # if project == Global.current_project: From caa202e323c6dc91dac41c4784e2371f7eeeb81c Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Mon, 12 Sep 2022 12:42:50 -0400 Subject: [PATCH 093/154] Removed a temporary check (which also fixed another bug) --- src/Autoload/Global.gd | 15 ++++++--------- src/UI/Timeline/AnimationTimeline.gd | 3 --- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index c5c823be17a5..620ef1c66943 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -438,15 +438,12 @@ func undo_or_redo( "Unlink Cel" ] ): - # TODO H: Check this: THIS IS PROBABLY WRONG (can't check if GROUP LAYER if INDEX is -1) - # I THINK IF I ADD AN UPDATE_TEXTURE METHOD TO EACH CEL TYPE, IT WON'T NEED THIS CHECK! - if not current_project.layers[layer_index] is GroupLayer: - if layer_index > -1 and frame_index > -1: - canvas.update_texture(layer_index, frame_index, project) - else: - for i in project.frames.size(): - for j in project.layers.size(): - canvas.update_texture(j, i, project) + if layer_index > -1 and frame_index > -1: + canvas.update_texture(layer_index, frame_index, project) + else: + for i in project.frames.size(): + for j in project.layers.size(): + canvas.update_texture(j, i, project) canvas.selection.update() if action_name == "Scale": diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 79456fef800e..fefa77328665 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -730,9 +730,6 @@ func _on_MergeDownLayer_pressed() -> void: project.undos += 1 project.undo_redo.create_action("Merge Layer") - # TODO H: When there is a group layer/cel present in the tree, merging down Pixel Layers - # doesn't get the texture updated. (Image is updated though, doing something else will update texture) - for f in project.frames: # TODO Later: top_image here doesn't really need to be a copy if there isn't layer transparency # though this probably will be rewriten with blend modes anyway... From 016e14a04c740ecd929df67fd7383b7e88f423fe Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Mon, 12 Sep 2022 13:12:46 -0400 Subject: [PATCH 094/154] Clone child layers when cloning a layer --- src/UI/Timeline/AnimationTimeline.gd | 31 +++++++++++++++++++++------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index fefa77328665..bf5f3c598820 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -622,18 +622,33 @@ func _on_AddGroup_pressed() -> void: func _on_CloneLayer_pressed() -> void: - # TODO H: clone children along with layer var project: Project = Global.current_project - var l: BaseLayer = project.layers[project.current_layer].copy() - l.name = str(project.layers[project.current_layer].name, " (", tr("copy"), ")") - var cels: Array = project.layers[project.current_layer].copy_all_cels() + var source_layers: Array = project.layers[project.current_layer].get_children_recursive() + source_layers.append(project.layers[project.current_layer]) + + var clones := [] # Array of Layers + var cels := [] # 2D Array of Cels + for sl in source_layers: + var cl: BaseLayer = sl.copy() + if sl.index == project.current_layer: + cl.name = str(sl.name, " (", tr("copy"), ")") + clones.append(cl) + cels.append(sl.copy_all_cels()) + + # Swap parents with clones if the parent is one of the source layers + for cl in clones: + var p = source_layers.find(cl.parent) + if p > -1: + cl.parent = clones[p] + + var indices := range(project.current_layer + 1, project.current_layer + clones.size() + 1) project.undos += 1 project.undo_redo.create_action("Add Layer") - project.undo_redo.add_do_property(project, "current_layer", project.current_layer + 1) + project.undo_redo.add_do_property(project, "current_layer", project.current_layer + clones.size()) project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) - project.undo_redo.add_do_method(project, "add_layers", [l], [project.current_layer + 1], [cels]) - project.undo_redo.add_undo_method(project, "remove_layers", [project.current_layer + 1]) + project.undo_redo.add_do_method(project, "add_layers", clones, indices, cels) + project.undo_redo.add_undo_method(project, "remove_layers", indices) project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.commit_action() @@ -644,7 +659,7 @@ func _on_RemoveLayer_pressed() -> void: if project.layers.size() == 1: return - var layers : Array = project.layers[project.current_layer].get_children_recursive() + var layers: Array = project.layers[project.current_layer].get_children_recursive() layers.append(project.layers[project.current_layer]) var indices := [] for l in layers: From 4359d9d447193e132c375d4d4c2cb48913bc8e39 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Mon, 12 Sep 2022 13:24:50 -0400 Subject: [PATCH 095/154] Added temp dummy get_image method to GroupCel, and use get_image when copying or picking colors --- src/Classes/GroupCel.gd | 4 +++- src/Tools/BaseTool.gd | 3 +-- src/UI/Canvas/Selection.gd | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Classes/GroupCel.gd b/src/Classes/GroupCel.gd index ff44f1b8632e..310030a465bc 100644 --- a/src/Classes/GroupCel.gd +++ b/src/Classes/GroupCel.gd @@ -9,7 +9,9 @@ func _init(_opacity := 1.0) -> void: func get_image() -> Image: # TODO H: This can be used for copying selections or picking colors... Can maybe make from texture data? - return Image.new() + var image = Image.new() + image.create(Global.current_project.size.x, Global.current_project.size.y, false, Image.FORMAT_RGBA8) + return image func create_cel_button() -> Node: diff --git a/src/Tools/BaseTool.gd b/src/Tools/BaseTool.gd index 71f4cbd6c278..e81cc8138706 100644 --- a/src/Tools/BaseTool.gd +++ b/src/Tools/BaseTool.gd @@ -82,14 +82,13 @@ func _get_draw_rect() -> Rect2: func _get_draw_image() -> Image: var project: Project = Global.current_project - return project.frames[project.current_frame].cels[project.current_layer].image + return project.frames[project.current_frame].cels[project.current_layer].get_image() func _get_selected_draw_images() -> Array: # Array of Images var images := [] var project: Project = Global.current_project for cel_index in project.selected_cels: - # TODO H: Check this: (BaseCel is fine because it asks can_layer_get_drawn) var cel: BaseCel = project.frames[cel_index[0]].cels[cel_index[1]] if project.layers[cel_index[1]].can_layer_get_drawn(): images.append(cel.image) diff --git a/src/UI/Canvas/Selection.gd b/src/UI/Canvas/Selection.gd index 30d1fa2e1e92..a2eae1009121 100644 --- a/src/UI/Canvas/Selection.gd +++ b/src/UI/Canvas/Selection.gd @@ -644,6 +644,7 @@ func _get_selected_draw_images() -> Array: # Array of Images var images := [] var project: Project = Global.current_project for cel_index in project.selected_cels: + # TODO: Figure this out (Issue when pasting selection to group cel) var cel: PixelCel = project.frames[cel_index[0]].cels[cel_index[1]] if project.layers[cel_index[1]].can_layer_get_drawn(): images.append(cel.image) @@ -665,7 +666,7 @@ func copy() -> void: var cl_big_bounding_rectangle := Rect2() var cl_selection_offset := Vector2.ZERO - var image: Image = project.frames[project.current_frame].cels[project.current_layer].image + var image: Image = project.frames[project.current_frame].cels[project.current_layer].get_image() var to_copy := Image.new() if !project.has_selection: to_copy.copy_from(image) From 0a19ec5ea5169db295f719b1590aeb8955477788 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Mon, 12 Sep 2022 13:41:37 -0400 Subject: [PATCH 096/154] TODOs --- src/Autoload/DrawingAlgos.gd | 1 + src/Autoload/Global.gd | 6 ++++-- src/UI/Canvas/Selection.gd | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Autoload/DrawingAlgos.gd b/src/Autoload/DrawingAlgos.gd index 4dc1070e4f10..c4a20d78c7bc 100644 --- a/src/Autoload/DrawingAlgos.gd +++ b/src/Autoload/DrawingAlgos.gd @@ -393,6 +393,7 @@ func scale_image(width: int, height: int, interpolation: int) -> void: for f in Global.current_project.frames: for i in range(f.cels.size() - 1, -1, -1): + # TODO H: Make work with Groups var sprite := Image.new() sprite.copy_from(f.cels[i].image) # Different method for scale_3x diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index 620ef1c66943..58a8acc368b5 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -449,9 +449,11 @@ func undo_or_redo( if action_name == "Scale": for i in project.frames.size(): for j in project.layers.size(): - # TODO H: ensure this is the correct cel type: var current_cel: BaseCel = project.frames[i].cels[j] - current_cel.image_texture.create_from_image(current_cel.image, 0) + # TODO H: Would using current_cel.update_texture with a new recreate param for + # using create_from_image instead (which actually resizes too, but is slower) be better? + # Or maybe a create texture method? + current_cel.image_texture.create_from_image(current_cel.get_image(), 0) canvas.camera_zoom() canvas.grid.update() canvas.pixel_grid.update() diff --git a/src/UI/Canvas/Selection.gd b/src/UI/Canvas/Selection.gd index a2eae1009121..63288a6cc79b 100644 --- a/src/UI/Canvas/Selection.gd +++ b/src/UI/Canvas/Selection.gd @@ -71,7 +71,7 @@ func _ready() -> void: # gizmos.append(Gizmo.new(Gizmo.Type.ROTATE)) # Rotation gizmo (temp) - +# TODO H/L: Can't move/resize a selection on a group cel (It just draws a new selection), maybe has to do with can_layer_get_drawn? func _input(event: InputEvent) -> void: if is_moving_content: if Input.is_action_just_pressed("transformation_confirm"): From eb5803312021efe808496c28e66488cbc35bb8b5 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Tue, 13 Sep 2022 14:17:05 -0400 Subject: [PATCH 097/154] Made open_image_as_spritesheet_layer work after the timeline refactor (still doesn't work with groups yet though). TODO comment updates --- src/Autoload/OpenSave.gd | 47 +++++++++++++++------------- src/UI/Timeline/AnimationTimeline.gd | 8 ++--- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index d9aa6c96cf4e..d379e3fc3c52 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -442,7 +442,7 @@ func open_image_as_spritesheet_tab(path: String, image: Image, horiz: int, vert: func open_image_as_spritesheet_layer( _path: String, image: Image, file_name: String, horizontal: int, vertical: int, start_frame: int ) -> void: - # TODO H0: Will need to rewrite this method using new ways to add layers/frames. (no ducplicate arrays). Check other open methods too! + # TODO H0: Check other open methods too! # Data needed to slice images horizontal = min(horizontal, image.get_size().x) vertical = min(vertical, image.get_size().y) @@ -459,42 +459,43 @@ func open_image_as_spritesheet_layer( # Initialize undo mechanism project.undos += 1 project.undo_redo.create_action("Add Spritesheet Layer") - var new_layers: Array = project.layers.duplicate() - var new_frames: Array = [] - # Create a duplicate of "project.frames" - for i in project.frames.size(): - var frame := Frame.new() - frame.cels = project.frames[i].cels.duplicate(true) - new_frames.append(frame) + var new_layers: Array = project.layers.duplicate() # Used for updating linked_cels lists # Create new frames (if needed) - var new_frames_size = start_frame + (vertical * horizontal) + var new_frames_size = max(project.frames.size(), (start_frame + (vertical * horizontal))) + var frames := [] + var frame_indices: Array + if new_frames_size > project.frames.size(): var required_frames = new_frames_size - project.frames.size() + # TODO H: Is adding the new frames starting after the current frame right? (Maybe its better to start after the last frame) + frame_indices= range(project.current_frame + 1, project.current_frame + required_frames + 1) for i in required_frames: var new_frame := Frame.new() - for l_i in range(new_layers.size()): # Create as many cels as there are layers + for l_i in range(project.layers.size()): # Create as many cels as there are layers + # TODO H1: This should work for any layer type: (Probably add a create_empty_cel for each layer type? var new_img := Image.new() new_img.create(project_width, project_height, false, Image.FORMAT_RGBA8) - # TODO H1: Make sure this PixelCel is right: (I this can be for any layer type) new_frame.cels.append(PixelCel.new(new_img, 1)) + # TODO H: Make sure setting of linked cels like this works everywhere (ie: image should be replaced with content) + # CONSIDER NEW LINKED CELS IDEA, DOES IT AFFECT THIS? if new_layers[l_i].new_cels_linked: new_layers[l_i].linked_cels.append(new_frame) new_frame.cels[l_i].image = new_layers[l_i].linked_cels[0].cels[l_i].image new_frame.cels[l_i].image_texture = new_layers[l_i].linked_cels[0].cels[l_i].image_texture - new_frames.insert(project.current_frame + 1, new_frame) + frames.append(new_frame) # Create new layer for spritesheet var layer := PixelLayer.new(project, file_name) - new_layers.append(layer) - for f in new_frames: + var cels := [] + for f in new_frames_size: + # TODO H: use that create_empty_cel method if made var new_layer := Image.new() new_layer.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8) - f.cels.append(PixelCel.new(new_layer, 1)) + cels.append(PixelCel.new(new_layer, 1)) # Slice spritesheet var image_no: int = 0 - var layer_index = new_layers.size() - 1 for yy in range(vertical): for xx in range(horizontal): var cropped_image := Image.new() @@ -503,20 +504,22 @@ func open_image_as_spritesheet_layer( ) cropped_image.crop(project.size.x, project.size.y) var frame_index = start_frame + image_no - cropped_image.convert(Image.FORMAT_RGBA8) - new_frames[frame_index].cels[layer_index] = (PixelCel.new(cropped_image, 1)) + cels[frame_index].image = cropped_image image_no += 1 - project.undo_redo.add_do_property(project, "current_frame", new_frames.size() - 1) + project.undo_redo.add_do_property(project, "current_frame", new_frames_size - 1) project.undo_redo.add_do_property(project, "current_layer", project.layers.size()) - project.undo_redo.add_do_property(project, "frames", new_frames) + project.undo_redo.add_do_method(project, "add_frames", frames, frame_indices) project.undo_redo.add_do_property(project, "layers", new_layers) + project.undo_redo.add_do_method(project, "add_layers", [layer], [project.layers.size()], [cels]) + project.undo_redo.add_do_method(Global, "undo_or_redo", false) + project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) project.undo_redo.add_undo_property(project, "current_frame", project.current_frame) + project.undo_redo.add_undo_method(project, "remove_layers", [project.layers.size()]) project.undo_redo.add_undo_property(project, "layers", project.layers) - project.undo_redo.add_undo_property(project, "frames", project.frames) - project.undo_redo.add_do_method(Global, "undo_or_redo", false) + project.undo_redo.add_undo_method(project, "remove_frames", frame_indices) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.commit_action() diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index bf5f3c598820..91354ff2802a 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -138,7 +138,7 @@ func add_frame() -> void: var project: Project = Global.current_project var frame_add_index := project.current_frame + 1 var frame: Frame = project.new_empty_frame() - var new_layers: Array = project.duplicate_layers() + var new_layers: Array = project.duplicate_layers() # TODO H: Perhaps new_layers here should be replaced with new_linked_cels (ALSO CONSIDER NEW LINKED CELS IDEA WHICH SHOULD FIX AUTOMATICALLY)? for l_i in range(new_layers.size()): # TODO H: Make sure this works with groups (Check out copy frames): @@ -201,9 +201,9 @@ func delete_frames(frames := []) -> void: elif frames.size() == 0: frames.append(project.current_frame) - var new_frames: Array = project.frames.duplicate() + var new_frames: Array = project.frames.duplicate() # TODO H: Is new_frames here still REALLY being used? var current_frame := project.current_frame - var new_layers: Array = project.duplicate_layers() + var new_layers: Array = project.duplicate_layers() # TODO H: Perhaps new_layers here should be replaced with new_linked_cels (ALSO CONSIDER NEW LINKED CELS IDEA WHICH SHOULD FIX AUTOMATICALLY)? var frame_correction := 0 # Only needed for tag adjustment var new_animation_tags := project.animation_tags.duplicate() @@ -282,7 +282,7 @@ func copy_frames(frames := []) -> void: if frames.size() == 0: frames.append(project.current_frame) - var new_layers: Array = project.duplicate_layers() + var new_layers: Array = project.duplicate_layers() # TODO H: Perhaps new_layers here should be replaced with new_linked_cels (ALSO CONSIDER NEW LINKED CELS IDEA WHICH SHOULD FIX AUTOMATICALLY)? var copied_frames := [] var copied_indices := range(frames[-1] + 1, frames[-1] + 1 + frames.size()) From b92f653e6df1fed3f7c427efc68a3e11a9dc0ff4 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 14 Sep 2022 12:58:03 -0400 Subject: [PATCH 098/154] Added create_new_cel methods to Layer classes --- src/Autoload/OpenSave.gd | 30 +++++++++++++--------------- src/Classes/BaseLayer.gd | 4 ++++ src/Classes/GroupLayer.gd | 4 ++++ src/Classes/PixelLayer.gd | 6 ++++++ src/Classes/Project.gd | 10 ++++------ src/UI/Timeline/AnimationTimeline.gd | 6 ++---- 6 files changed, 34 insertions(+), 26 deletions(-) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index d379e3fc3c52..4eb10615d0f5 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -428,6 +428,7 @@ func open_image_as_spritesheet_tab(path: String, image: Image, horiz: int, vert: cropped_image.convert(Image.FORMAT_RGBA8) frame.cels.append(PixelCel.new(cropped_image, 1)) + # TODO L: This for loop doesn't need to exist (its adding cels to layers that never exist): for _i in range(1, project.layers.size()): var empty_sprite := Image.new() empty_sprite.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8) @@ -465,18 +466,14 @@ func open_image_as_spritesheet_layer( var new_frames_size = max(project.frames.size(), (start_frame + (vertical * horizontal))) var frames := [] var frame_indices: Array - if new_frames_size > project.frames.size(): var required_frames = new_frames_size - project.frames.size() - # TODO H: Is adding the new frames starting after the current frame right? (Maybe its better to start after the last frame) + # TODO L: Is adding the new frames starting after the current frame right? (Maybe its better to start after the last frame) frame_indices= range(project.current_frame + 1, project.current_frame + required_frames + 1) for i in required_frames: var new_frame := Frame.new() for l_i in range(project.layers.size()): # Create as many cels as there are layers - # TODO H1: This should work for any layer type: (Probably add a create_empty_cel for each layer type? - var new_img := Image.new() - new_img.create(project_width, project_height, false, Image.FORMAT_RGBA8) - new_frame.cels.append(PixelCel.new(new_img, 1)) + new_frame.cels.append(project.layers[l_i].create_empty_cel()) # TODO H: Make sure setting of linked cels like this works everywhere (ie: image should be replaced with content) # CONSIDER NEW LINKED CELS IDEA, DOES IT AFFECT THIS? if new_layers[l_i].new_cels_linked: @@ -489,10 +486,11 @@ func open_image_as_spritesheet_layer( var layer := PixelLayer.new(project, file_name) var cels := [] for f in new_frames_size: - # TODO H: use that create_empty_cel method if made - var new_layer := Image.new() - new_layer.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8) - cels.append(PixelCel.new(new_layer, 1)) + # TODO H: Consider optimizing this so extra images aren't made for frames that are in the range + # of the spritesheet's frames (To do this, need to resize cel array at first, and set them by index for + # cels not in that range, and then in the # Splice spritesheet section, create the PixelCel there. + # (Maybe instead calculate the yy and xx values, removing the yy/xx loops, and combining with this loop?) + cels.append(layer.create_empty_cel()) # Slice spritesheet var image_no: int = 0 @@ -525,6 +523,7 @@ func open_image_as_spritesheet_layer( func open_image_at_frame(image: Image, layer_index := 0, frame_index := 0) -> void: + # TODO H: What should happen if the layer_index isn't a PixelLayer? var project = Global.current_project image.crop(project.size.x, project.size.y) @@ -557,6 +556,8 @@ func open_image_at_frame(image: Image, layer_index := 0, frame_index := 0) -> vo func open_image_as_new_frame(image: Image, layer_index := 0) -> void: + # TODO H: Make work after the timeline refactor + # TODO H: What should happen if the layer_index isn't a PixelLayer? var project = Global.current_project image.crop(project.size.x, project.size.y) var new_frames: Array = project.frames.duplicate() @@ -567,9 +568,7 @@ func open_image_as_new_frame(image: Image, layer_index := 0) -> void: image.convert(Image.FORMAT_RGBA8) frame.cels.append(PixelCel.new(image, 1)) else: - var empty_image := Image.new() - empty_image.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8) - frame.cels.append(PixelCel.new(empty_image, 1)) + frame.cels.append(project.layers[i].create_empty_cel()) new_frames.append(frame) @@ -589,6 +588,7 @@ func open_image_as_new_frame(image: Image, layer_index := 0) -> void: func open_image_as_new_layer(image: Image, file_name: String, frame_index := 0) -> void: + # TODO H: Make work after the timeline refactor var project = Global.current_project image.crop(project.size.x, project.size.y) var new_layers: Array = Global.current_project.layers.duplicate() @@ -602,9 +602,7 @@ func open_image_as_new_layer(image: Image, file_name: String, frame_index := 0) image.convert(Image.FORMAT_RGBA8) new_cels.append(PixelCel.new(image, 1)) else: - var empty_image := Image.new() - empty_image.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8) - new_cels.append(PixelCel.new(empty_image, 1)) + new_cels.append(layer.create_empty_cel()) project.undo_redo.add_do_property(project.frames[i], "cels", new_cels) project.undo_redo.add_undo_property(project.frames[i], "cels", project.frames[i].cels) diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index 15722b6672b1..cbc04fdcbfde 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -96,6 +96,10 @@ func copy() -> BaseLayer: return copy +func create_empty_cel() -> BaseCel: + return null + + func copy_cel(_frame: int, _linked: bool) -> BaseCel: return null diff --git a/src/Classes/GroupLayer.gd b/src/Classes/GroupLayer.gd index 63ecc6739798..9acd050a4575 100644 --- a/src/Classes/GroupLayer.gd +++ b/src/Classes/GroupLayer.gd @@ -22,6 +22,10 @@ func deserialize(dict: Dictionary) -> void: expanded = dict.expanded +func create_empty_cel() -> BaseCel: + return GroupCel.new() + + func copy_cel(frame_index: int, _linked: bool) -> BaseCel: var cel: GroupCel = project.frames[frame_index].cels[index] return GroupCel.new(cel.opacity) diff --git a/src/Classes/PixelLayer.gd b/src/Classes/PixelLayer.gd index ba2ee87bff2a..c67087dd692d 100644 --- a/src/Classes/PixelLayer.gd +++ b/src/Classes/PixelLayer.gd @@ -33,6 +33,12 @@ func deserialize(dict: Dictionary) -> void: linked_cel.image_texture = linked_cels[0].cels[index].image_texture +func create_empty_cel() -> BaseCel: + var image := Image.new() + image.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8) + return PixelCel.new(image) + + func copy_cel(frame_index: int, linked: bool) -> BaseCel: if linked and not linked_cels.empty(): var cel: PixelCel = linked_cels[0].cels[index] diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 47fac634c98b..3ac3217d9d0e 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -108,13 +108,11 @@ func new_empty_frame() -> Frame: var frame := Frame.new() var bottom_layer := true for l in layers: # Create as many cels as there are layers - var image := Image.new() - image.create(size.x, size.y, false, Image.FORMAT_RGBA8) - if bottom_layer and fill_color.a > 0: - image.fill(fill_color) - frame.cels.append(PixelCel.new(image, 1)) + var cel: BaseCel = l.create_empty_cel() + if cel is PixelCel and bottom_layer and fill_color.a > 0: + cel.image.fill(fill_color) + frame.cels.append(cel) bottom_layer = false - return frame diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 91354ff2802a..0258cb463e7f 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -587,9 +587,7 @@ func _on_AddLayer_pressed() -> void: var l := PixelLayer.new(project) var cels := [] for f in project.frames: - var new_cel_image := Image.new() - new_cel_image.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8) - cels.append(PixelCel.new(new_cel_image, 1)) + cels.append(l.create_empty_cel()) project.undos += 1 project.undo_redo.create_action("Add Layer") @@ -608,7 +606,7 @@ func _on_AddGroup_pressed() -> void: var l := GroupLayer.new(project) var cels := [] for f in project.frames: - cels.append(GroupCel.new()) + cels.append(l.create_empty_cel()) project.undos += 1 project.undo_redo.create_action("Add Layer") From a8c7183fac926aceb0d23a88cfee26a5453c08cc Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 14 Sep 2022 13:18:29 -0400 Subject: [PATCH 099/154] Updated TODOs and comments --- src/Autoload/Global.gd | 3 --- src/Autoload/OpenSave.gd | 2 +- src/Classes/BaseCel.gd | 27 +++++++-------------------- src/UI/Timeline/AnimationTimeline.gd | 6 +++--- 4 files changed, 11 insertions(+), 27 deletions(-) diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index 58a8acc368b5..83ba49a281ee 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -450,9 +450,6 @@ func undo_or_redo( for i in project.frames.size(): for j in project.layers.size(): var current_cel: BaseCel = project.frames[i].cels[j] - # TODO H: Would using current_cel.update_texture with a new recreate param for - # using create_from_image instead (which actually resizes too, but is slower) be better? - # Or maybe a create texture method? current_cel.image_texture.create_from_image(current_cel.get_image(), 0) canvas.camera_zoom() canvas.grid.update() diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index 4eb10615d0f5..c6ef862c3d1c 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -443,7 +443,7 @@ func open_image_as_spritesheet_tab(path: String, image: Image, horiz: int, vert: func open_image_as_spritesheet_layer( _path: String, image: Image, file_name: String, horizontal: int, vertical: int, start_frame: int ) -> void: - # TODO H0: Check other open methods too! + # Data needed to slice images horizontal = min(horizontal, image.get_size().x) vertical = min(vertical, image.get_size().y) diff --git a/src/Classes/BaseCel.gd b/src/Classes/BaseCel.gd index 8434158dbbb2..71a9c55076d3 100644 --- a/src/Classes/BaseCel.gd +++ b/src/Classes/BaseCel.gd @@ -8,7 +8,10 @@ var image_texture: ImageTexture # Methods to Override: -# TODO H: Perhaps get_content, set_content, and delete_content/clear_content methods will be good to have here: +# TODO H: Check if copying cels can use the content methods + +# TODO H1: These content methods need good doc comments: +# COMMENT FROM THE IDEA TODO COMMENT (MAY BE USEFUL FOR WRITING COMMENTS) # - get_content will return certain content of the cel (should metadata be included?) # - set_content will set the content (same structure as get_content returns) # - delete/clear_content will erase it, @@ -18,16 +21,10 @@ var image_texture: ImageTexture # = making this generic and should solve issues with combing cel_button scripts into 1 # - copy_content may also be a useful method to have -# TODO H1: These content methods need good doc comments: - func set_content(content) -> void: return -# TODO H0: Consider if the return content methods should have a bool option for including a texture, -# of if the texture should be completely not included (textures aren't always needed. But how can we -# ensure that different texture types are properly set up if textures are completely not included here? -# Will seperate methods for the textures be able to work well? -# Maybe for now, don't worry about possible different texture types, and don't do copying layers/frames + func get_content(): return [] @@ -40,18 +37,8 @@ func copy_content(): return [] -# TODO H: Should this be the case? -# Each Cel type should have a get_image function, which will either return -# its image data for PixelCels, or return a render of that cel. It's meant -# for read-only usage of image data from any type of cel - -# TODO NOTE ^: I'm thinking this shouldn't be the case right now. I'm thinking each cel should have -# a texture var. using texture.get_data it can be possible to copy selections or color pick. -# There will be an update_texture method, which will either immedietly update it, or set it -# to be queued for update (only frames that aren't currently being viewed). When the user -# isn't drawing, Pixelorama can update these textures. (maybe an update_texture and a queue_texture_update -# method may be better, we'll see - +# Returns the image var for image based cel types, or a render for procedural types. +# It's meant for read-only usage of image data, such as copying selections or color picking. func get_image() -> Image: return null diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 0258cb463e7f..b30c439de355 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -138,7 +138,7 @@ func add_frame() -> void: var project: Project = Global.current_project var frame_add_index := project.current_frame + 1 var frame: Frame = project.new_empty_frame() - var new_layers: Array = project.duplicate_layers() # TODO H: Perhaps new_layers here should be replaced with new_linked_cels (ALSO CONSIDER NEW LINKED CELS IDEA WHICH SHOULD FIX AUTOMATICALLY)? + var new_layers: Array = project.duplicate_layers() for l_i in range(new_layers.size()): # TODO H: Make sure this works with groups (Check out copy frames): @@ -203,7 +203,7 @@ func delete_frames(frames := []) -> void: var new_frames: Array = project.frames.duplicate() # TODO H: Is new_frames here still REALLY being used? var current_frame := project.current_frame - var new_layers: Array = project.duplicate_layers() # TODO H: Perhaps new_layers here should be replaced with new_linked_cels (ALSO CONSIDER NEW LINKED CELS IDEA WHICH SHOULD FIX AUTOMATICALLY)? + var new_layers: Array = project.duplicate_layers() var frame_correction := 0 # Only needed for tag adjustment var new_animation_tags := project.animation_tags.duplicate() @@ -282,7 +282,7 @@ func copy_frames(frames := []) -> void: if frames.size() == 0: frames.append(project.current_frame) - var new_layers: Array = project.duplicate_layers() # TODO H: Perhaps new_layers here should be replaced with new_linked_cels (ALSO CONSIDER NEW LINKED CELS IDEA WHICH SHOULD FIX AUTOMATICALLY)? + var new_layers: Array = project.duplicate_layers() var copied_frames := [] var copied_indices := range(frames[-1] + 1, frames[-1] + 1 + frames.size()) From 87802468af2519520fe52de0c6d417ce0b864f9d Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 14 Sep 2022 13:34:03 -0400 Subject: [PATCH 100/154] Renamed Layer class's create_empty_cel to new_empty_cel to match Project's new_emtpy_frame --- src/Autoload/OpenSave.gd | 8 ++++---- src/Classes/BaseLayer.gd | 2 +- src/Classes/GroupLayer.gd | 2 +- src/Classes/PixelLayer.gd | 2 +- src/Classes/Project.gd | 2 +- src/UI/Timeline/AnimationTimeline.gd | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index c6ef862c3d1c..0a7025522448 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -473,7 +473,7 @@ func open_image_as_spritesheet_layer( for i in required_frames: var new_frame := Frame.new() for l_i in range(project.layers.size()): # Create as many cels as there are layers - new_frame.cels.append(project.layers[l_i].create_empty_cel()) + new_frame.cels.append(project.layers[l_i].new_empty_cel()) # TODO H: Make sure setting of linked cels like this works everywhere (ie: image should be replaced with content) # CONSIDER NEW LINKED CELS IDEA, DOES IT AFFECT THIS? if new_layers[l_i].new_cels_linked: @@ -490,7 +490,7 @@ func open_image_as_spritesheet_layer( # of the spritesheet's frames (To do this, need to resize cel array at first, and set them by index for # cels not in that range, and then in the # Splice spritesheet section, create the PixelCel there. # (Maybe instead calculate the yy and xx values, removing the yy/xx loops, and combining with this loop?) - cels.append(layer.create_empty_cel()) + cels.append(layer.new_empty_cel()) # Slice spritesheet var image_no: int = 0 @@ -568,7 +568,7 @@ func open_image_as_new_frame(image: Image, layer_index := 0) -> void: image.convert(Image.FORMAT_RGBA8) frame.cels.append(PixelCel.new(image, 1)) else: - frame.cels.append(project.layers[i].create_empty_cel()) + frame.cels.append(project.layers[i].new_empty_cel()) new_frames.append(frame) @@ -602,7 +602,7 @@ func open_image_as_new_layer(image: Image, file_name: String, frame_index := 0) image.convert(Image.FORMAT_RGBA8) new_cels.append(PixelCel.new(image, 1)) else: - new_cels.append(layer.create_empty_cel()) + new_cels.append(layer.new_empty_cel()) project.undo_redo.add_do_property(project.frames[i], "cels", new_cels) project.undo_redo.add_undo_property(project.frames[i], "cels", project.frames[i].cels) diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index cbc04fdcbfde..b597369ef4b5 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -96,7 +96,7 @@ func copy() -> BaseLayer: return copy -func create_empty_cel() -> BaseCel: +func new_empty_cel() -> BaseCel: return null diff --git a/src/Classes/GroupLayer.gd b/src/Classes/GroupLayer.gd index 9acd050a4575..d418d9ebb7a7 100644 --- a/src/Classes/GroupLayer.gd +++ b/src/Classes/GroupLayer.gd @@ -22,7 +22,7 @@ func deserialize(dict: Dictionary) -> void: expanded = dict.expanded -func create_empty_cel() -> BaseCel: +func new_empty_cel() -> BaseCel: return GroupCel.new() diff --git a/src/Classes/PixelLayer.gd b/src/Classes/PixelLayer.gd index c67087dd692d..ae6fbef23236 100644 --- a/src/Classes/PixelLayer.gd +++ b/src/Classes/PixelLayer.gd @@ -33,7 +33,7 @@ func deserialize(dict: Dictionary) -> void: linked_cel.image_texture = linked_cels[0].cels[index].image_texture -func create_empty_cel() -> BaseCel: +func new_empty_cel() -> BaseCel: var image := Image.new() image.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8) return PixelCel.new(image) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 3ac3217d9d0e..04152e14aa38 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -108,7 +108,7 @@ func new_empty_frame() -> Frame: var frame := Frame.new() var bottom_layer := true for l in layers: # Create as many cels as there are layers - var cel: BaseCel = l.create_empty_cel() + var cel: BaseCel = l.new_empty_cel() if cel is PixelCel and bottom_layer and fill_color.a > 0: cel.image.fill(fill_color) frame.cels.append(cel) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index b30c439de355..39f9adf818e5 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -587,7 +587,7 @@ func _on_AddLayer_pressed() -> void: var l := PixelLayer.new(project) var cels := [] for f in project.frames: - cels.append(l.create_empty_cel()) + cels.append(l.new_empty_cel()) project.undos += 1 project.undo_redo.create_action("Add Layer") @@ -606,7 +606,7 @@ func _on_AddGroup_pressed() -> void: var l := GroupLayer.new(project) var cels := [] for f in project.frames: - cels.append(l.create_empty_cel()) + cels.append(l.new_empty_cel()) project.undos += 1 project.undo_redo.create_action("Add Layer") From 5c06190229316cfefd34a423ee1e5cf8e989df51 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 14 Sep 2022 13:37:12 -0400 Subject: [PATCH 101/154] Renamed create_layer/cel_button to instantiate_layer/cel_button --- src/Classes/BaseCel.gd | 2 +- src/Classes/BaseLayer.gd | 2 +- src/Classes/GroupCel.gd | 2 +- src/Classes/GroupLayer.gd | 2 +- src/Classes/PixelCel.gd | 2 +- src/Classes/PixelLayer.gd | 2 +- src/UI/Timeline/AnimationTimeline.gd | 8 ++++---- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Classes/BaseCel.gd b/src/Classes/BaseCel.gd index 71a9c55076d3..1e5f2d1af857 100644 --- a/src/Classes/BaseCel.gd +++ b/src/Classes/BaseCel.gd @@ -55,5 +55,5 @@ func load_image_data_from_pxo(_file: File, _project_size: Vector2) -> void: return -func create_cel_button() -> Node: +func instantiate_cel_button() -> Node: return null diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index b597369ef4b5..a8d5ec56b726 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -120,5 +120,5 @@ func accepts_child(_layer: BaseLayer) -> bool: return false -func create_layer_button() -> Node: +func instantiate_layer_button() -> Node: return null diff --git a/src/Classes/GroupCel.gd b/src/Classes/GroupCel.gd index 310030a465bc..94b5017cbb16 100644 --- a/src/Classes/GroupCel.gd +++ b/src/Classes/GroupCel.gd @@ -14,5 +14,5 @@ func get_image() -> Image: return image -func create_cel_button() -> Node: +func instantiate_cel_button() -> Node: return Global.group_cel_button_node.instance() diff --git a/src/Classes/GroupLayer.gd b/src/Classes/GroupLayer.gd index d418d9ebb7a7..44fdfa059e24 100644 --- a/src/Classes/GroupLayer.gd +++ b/src/Classes/GroupLayer.gd @@ -47,5 +47,5 @@ func accepts_child(_layer: BaseLayer) -> bool: return true -func create_layer_button() -> Node: +func instantiate_layer_button() -> Node: return Global.group_layer_button_node.instance() diff --git a/src/Classes/PixelCel.gd b/src/Classes/PixelCel.gd index b3760df1bcc3..074e0fc82a97 100644 --- a/src/Classes/PixelCel.gd +++ b/src/Classes/PixelCel.gd @@ -60,7 +60,7 @@ func load_image_data_from_pxo(file: File, project_size: Vector2) -> void: image_changed(image) -func create_cel_button() -> Node: +func instantiate_cel_button() -> Node: var cel_button = Global.pixel_cel_button_node.instance() cel_button.get_child(0).texture = image_texture return cel_button diff --git a/src/Classes/PixelLayer.gd b/src/Classes/PixelLayer.gd index ae6fbef23236..1f7cd2d72b84 100644 --- a/src/Classes/PixelLayer.gd +++ b/src/Classes/PixelLayer.gd @@ -76,5 +76,5 @@ func can_layer_get_drawn() -> bool: return is_visible_in_hierarchy() && !is_locked_in_hierarchy() -func create_layer_button() -> Node: +func instantiate_layer_button() -> Node: return Global.pixel_layer_button_node.instance() diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 39f9adf818e5..5b9ad937e6fb 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -866,7 +866,7 @@ func project_frame_added(frame: int) -> void: var layer := Global.frames_container.get_child_count() - 1 for container in Global.frames_container.get_children(): - var cel_button = project.frames[frame].cels[layer].create_cel_button() + var cel_button = project.frames[frame].cels[layer].instantiate_cel_button() cel_button.frame = frame cel_button.layer = layer container.add_child(cel_button) @@ -884,14 +884,14 @@ func project_frame_removed(frame: int) -> void: func project_layer_added(layer: int) -> void: var project: Project = Global.current_project - var layer_button: LayerButton = project.layers[layer].create_layer_button() + var layer_button: LayerButton = project.layers[layer].instantiate_layer_button() layer_button.layer = layer if project.layers[layer].name == "": project.layers[layer].set_name_to_default(layer) var layer_cel_container := HBoxContainer.new() for f in project.frames.size(): - var cel_button = project.frames[f].cels[layer].create_cel_button() + var cel_button = project.frames[f].cels[layer].instantiate_cel_button() cel_button.frame = f cel_button.layer = layer layer_cel_container.add_child(cel_button) @@ -916,7 +916,7 @@ func project_cel_added(frame: int, layer: int) -> void: var container := Global.frames_container.get_child( Global.frames_container.get_child_count() - 1 - layer ) - var cel_button = Global.current_project.frames[frame].cels[layer].create_cel_button() + var cel_button = Global.current_project.frames[frame].cels[layer].instantiate_cel_button() cel_button.frame = frame cel_button.layer = layer container.add_child(cel_button) From 2fc90309807110926c8824026b9ebde3bdcc5b67 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 14 Sep 2022 13:54:53 -0400 Subject: [PATCH 102/154] updated TODOs --- src/Autoload/OpenSave.gd | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index 0a7025522448..ec4e748df430 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -524,6 +524,8 @@ func open_image_as_spritesheet_layer( func open_image_at_frame(image: Image, layer_index := 0, frame_index := 0) -> void: # TODO H: What should happen if the layer_index isn't a PixelLayer? + # Option 1: Disable OK button and show red message saying to choose a Pixel Layer + # Option 2: Replace spinbox with an option list that contains all Pixel Layers (maybe better UX too) var project = Global.current_project image.crop(project.size.x, project.size.y) @@ -558,6 +560,8 @@ func open_image_at_frame(image: Image, layer_index := 0, frame_index := 0) -> vo func open_image_as_new_frame(image: Image, layer_index := 0) -> void: # TODO H: Make work after the timeline refactor # TODO H: What should happen if the layer_index isn't a PixelLayer? + # Option 1: Disable OK button and show red message saying to choose a Pixel Layer + # Option 2: Replace spinbox with an option list that contains all Pixel Layers (maybe better UX too) var project = Global.current_project image.crop(project.size.x, project.size.y) var new_frames: Array = project.frames.duplicate() From 8af1bb904e8690dd3f41523fec1dca89558e2002 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 14 Sep 2022 14:04:30 -0400 Subject: [PATCH 103/154] prioritized TODOs --- src/Autoload/DrawingAlgos.gd | 2 +- src/Autoload/Export.gd | 2 +- src/Autoload/OpenSave.gd | 13 +++++++------ src/Classes/BaseCel.gd | 2 +- src/Classes/BaseLayer.gd | 4 ++-- src/Classes/GroupCel.gd | 2 +- src/Classes/Project.gd | 2 +- src/UI/Canvas/Canvas.gd | 4 ++-- src/UI/Canvas/Selection.gd | 2 +- src/UI/Timeline/AnimationTimeline.gd | 2 +- src/UI/Timeline/LayerButton.gd | 2 +- 11 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/Autoload/DrawingAlgos.gd b/src/Autoload/DrawingAlgos.gd index c4a20d78c7bc..99fee4e2271a 100644 --- a/src/Autoload/DrawingAlgos.gd +++ b/src/Autoload/DrawingAlgos.gd @@ -393,7 +393,7 @@ func scale_image(width: int, height: int, interpolation: int) -> void: for f in Global.current_project.frames: for i in range(f.cels.size() - 1, -1, -1): - # TODO H: Make work with Groups + # TODO H0: Make work with Groups var sprite := Image.new() sprite.copy_from(f.cels[i].image) # Different method for scale_3x diff --git a/src/Autoload/Export.gd b/src/Autoload/Export.gd index 8bb4544d380a..3d9958c0fbb7 100644 --- a/src/Autoload/Export.gd +++ b/src/Autoload/Export.gd @@ -380,7 +380,7 @@ func blend_layers(image: Image, frame: Frame, origin: Vector2 = Vector2(0, 0)) - image.lock() var layer_i := 0 for cel in frame.cels: - # TODO H: Check + # TODO H0: Check if Global.current_project.layers[layer_i].visible and not cel is GroupCel: var cel_image := Image.new() cel_image.copy_from(cel.image) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index ec4e748df430..bdc17939ac00 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -474,7 +474,7 @@ func open_image_as_spritesheet_layer( var new_frame := Frame.new() for l_i in range(project.layers.size()): # Create as many cels as there are layers new_frame.cels.append(project.layers[l_i].new_empty_cel()) - # TODO H: Make sure setting of linked cels like this works everywhere (ie: image should be replaced with content) + # TODO H0: Make sure setting of linked cels like this works everywhere (ie: image should be replaced with content) # CONSIDER NEW LINKED CELS IDEA, DOES IT AFFECT THIS? if new_layers[l_i].new_cels_linked: new_layers[l_i].linked_cels.append(new_frame) @@ -486,7 +486,7 @@ func open_image_as_spritesheet_layer( var layer := PixelLayer.new(project, file_name) var cels := [] for f in new_frames_size: - # TODO H: Consider optimizing this so extra images aren't made for frames that are in the range + # TODO H0: Consider optimizing this so extra images aren't made for frames that are in the range # of the spritesheet's frames (To do this, need to resize cel array at first, and set them by index for # cels not in that range, and then in the # Splice spritesheet section, create the PixelCel there. # (Maybe instead calculate the yy and xx values, removing the yy/xx loops, and combining with this loop?) @@ -506,6 +506,7 @@ func open_image_as_spritesheet_layer( cels[frame_index].image = cropped_image image_no += 1 + # TODO L: Maybe this is the better undo/redo order (As sometimes the do and undo steps can't be in the same order like here), should everything be made consistent with this? project.undo_redo.add_do_property(project, "current_frame", new_frames_size - 1) project.undo_redo.add_do_property(project, "current_layer", project.layers.size()) project.undo_redo.add_do_method(project, "add_frames", frames, frame_indices) @@ -523,7 +524,7 @@ func open_image_as_spritesheet_layer( func open_image_at_frame(image: Image, layer_index := 0, frame_index := 0) -> void: - # TODO H: What should happen if the layer_index isn't a PixelLayer? + # TODO H1: What should happen if the layer_index isn't a PixelLayer? # Option 1: Disable OK button and show red message saying to choose a Pixel Layer # Option 2: Replace spinbox with an option list that contains all Pixel Layers (maybe better UX too) var project = Global.current_project @@ -558,8 +559,8 @@ func open_image_at_frame(image: Image, layer_index := 0, frame_index := 0) -> vo func open_image_as_new_frame(image: Image, layer_index := 0) -> void: - # TODO H: Make work after the timeline refactor - # TODO H: What should happen if the layer_index isn't a PixelLayer? + # TODO H0: Make work after the timeline refactor + # TODO H1: What should happen if the layer_index isn't a PixelLayer? # Option 1: Disable OK button and show red message saying to choose a Pixel Layer # Option 2: Replace spinbox with an option list that contains all Pixel Layers (maybe better UX too) var project = Global.current_project @@ -592,7 +593,7 @@ func open_image_as_new_frame(image: Image, layer_index := 0) -> void: func open_image_as_new_layer(image: Image, file_name: String, frame_index := 0) -> void: - # TODO H: Make work after the timeline refactor + # TODO H0: Make work after the timeline refactor var project = Global.current_project image.crop(project.size.x, project.size.y) var new_layers: Array = Global.current_project.layers.duplicate() diff --git a/src/Classes/BaseCel.gd b/src/Classes/BaseCel.gd index 1e5f2d1af857..4b8592d34544 100644 --- a/src/Classes/BaseCel.gd +++ b/src/Classes/BaseCel.gd @@ -8,7 +8,7 @@ var image_texture: ImageTexture # Methods to Override: -# TODO H: Check if copying cels can use the content methods +# TODO H0: Check if copying cels can use the content methods # TODO H1: These content methods need good doc comments: # COMMENT FROM THE IDEA TODO COMMENT (MAY BE USEFUL FOR WRITING COMMENTS) diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index a8d5ec56b726..c7268c58d12c 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -47,7 +47,7 @@ func is_expanded_in_hierarchy() -> bool: return parent.expanded and parent.is_expanded_in_hierarchy() return true -# TODO H: Search for layer visbility/locked checks that should be changed to the hierarchy ones: +# TODO H2: Search for layer visbility/locked checks that should be changed to the hierarchy ones: func is_visible_in_hierarchy() -> bool: if is_instance_valid(parent) and visible: return parent.is_visible_in_hierarchy() @@ -69,7 +69,7 @@ func get_hierarchy_depth() -> int: # Methods to Override: func serialize() -> Dictionary: - assert(index == project.layers.find(self)) # TODO H: remove once sure index is synced properly + assert(index == project.layers.find(self)) # TODO H2: remove once sure index is synced properly return { "name": name, "visible": visible, diff --git a/src/Classes/GroupCel.gd b/src/Classes/GroupCel.gd index 94b5017cbb16..825492f938cf 100644 --- a/src/Classes/GroupCel.gd +++ b/src/Classes/GroupCel.gd @@ -8,7 +8,7 @@ func _init(_opacity := 1.0) -> void: func get_image() -> Image: - # TODO H: This can be used for copying selections or picking colors... Can maybe make from texture data? + # TODO H1: This can be used for copying selections or picking colors... Can maybe make from texture data? var image = Image.new() image.create(Global.current_project.size.x, Global.current_project.size.y, false, Image.FORMAT_RGBA8) return image diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 04152e14aa38..d010f2f886ec 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -404,7 +404,7 @@ func deserialize(dict: Dictionary) -> void: fps = dict.fps _deserialize_metadata(self, dict) -# TODO H: Consider how these are used: +# TODO H1: Consider how these are used: func _serialize_metadata(object: Object) -> Dictionary: var metadata := {} for meta in object.get_meta_list(): diff --git a/src/UI/Canvas/Canvas.gd b/src/UI/Canvas/Canvas.gd index 8cc929591b4f..0a47a466df26 100644 --- a/src/UI/Canvas/Canvas.gd +++ b/src/UI/Canvas/Canvas.gd @@ -126,7 +126,7 @@ func update_texture(layer_i: int, frame_i := -1, project: Project = Global.curre var current_cel: BaseCel = project.frames[frame_i].cels[layer_i] current_cel.update_texture() - # TODO H: is this even needed? (Same as below) + # TODO H2: is this even needed? (Same as below) # if project == Global.current_project: # var container_index = Global.frames_container.get_child_count() - 1 - layer_i # var layer_cel_container = Global.frames_container.get_child(container_index) @@ -144,7 +144,7 @@ func update_selected_cels_textures(project: Project = Global.current_project) -> var current_cel: BaseCel = project.frames[frame_index].cels[layer_index] current_cel.update_texture() - # TODO H: This wasn't working anymore, but is it even needed? (Same as above) + # TODO H2: This wasn't working anymore, but is it even needed? (Same as above) # if project == Global.current_project: # var container_index = Global.frames_container.get_child_count() - 1 - layer_index # var layer_cel_container = Global.frames_container.get_child(container_index) diff --git a/src/UI/Canvas/Selection.gd b/src/UI/Canvas/Selection.gd index 63288a6cc79b..35c95a49a9e0 100644 --- a/src/UI/Canvas/Selection.gd +++ b/src/UI/Canvas/Selection.gd @@ -97,7 +97,7 @@ func _input(event: InputEvent) -> void: if Global.cross_cursor: cursor = Control.CURSOR_CROSS var project: Project = Global.current_project - # TODO H1: Make sure this BaseLayer is supposed to be BaseLayer + # TODO H0: Make sure this BaseLayer is supposed to be BaseLayer var layer: BaseLayer = project.layers[project.current_layer] if not layer.can_layer_get_drawn(): cursor = Control.CURSOR_FORBIDDEN diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 5b9ad937e6fb..4215d1146eb0 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -141,7 +141,7 @@ func add_frame() -> void: var new_layers: Array = project.duplicate_layers() for l_i in range(new_layers.size()): - # TODO H: Make sure this works with groups (Check out copy frames): + # TODO H0: Make sure this works with groups (Check out copy frames): if new_layers[l_i].new_cels_linked: # If the link button is pressed new_layers[l_i].linked_cels.append(frame) frame.cels[l_i].image = new_layers[l_i].linked_cels[0].cels[l_i].image diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index c5e03be247e5..44822dd0bafb 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -189,7 +189,7 @@ func _select_current_layer() -> void: func get_drag_data(_position) -> Array: - # TODO H: If keeping this new multi layer drag design, layers here can be reutrned in the array + # TODO H1: If keeping this new multi layer drag design, layers here can be reutrned in the array # instead of layer... var layers := range(layer - Global.current_project.layers[layer].get_children_recursive().size(), layer + 1) From 34fe893613f84e81a58d84e6642d537725bf7c56 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 14 Sep 2022 14:14:46 -0400 Subject: [PATCH 104/154] Fixed some warnings --- src/Classes/BaseCel.gd | 2 +- src/UI/Timeline/CelButton.gd | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Classes/BaseCel.gd b/src/Classes/BaseCel.gd index 4b8592d34544..00a69304c4b9 100644 --- a/src/Classes/BaseCel.gd +++ b/src/Classes/BaseCel.gd @@ -21,7 +21,7 @@ var image_texture: ImageTexture # = making this generic and should solve issues with combing cel_button scripts into 1 # - copy_content may also be a useful method to have -func set_content(content) -> void: +func set_content(_content) -> void: return diff --git a/src/UI/Timeline/CelButton.gd b/src/UI/Timeline/CelButton.gd index 123534baa324..5864ce6db838 100644 --- a/src/UI/Timeline/CelButton.gd +++ b/src/UI/Timeline/CelButton.gd @@ -110,7 +110,7 @@ func _on_PopupMenu_id_pressed(id: int) -> void: if popup_menu.get_item_metadata(MenuOptions.LINK) == "Unlink Cel": new_linked_cels.remove(cel_index) project.undo_redo.create_action("Unlink Cel") - var cel: BaseCel = project.frames[frame].cels[layer] +# var cel: BaseCel = project.frames[frame].cels[layer] project.undo_redo.add_do_property(cel, "image_texture", ImageTexture.new()) project.undo_redo.add_undo_property(cel, "image_texture", cel.image_texture) project.undo_redo.add_do_method(cel, "set_content", cel.copy_content()) @@ -122,7 +122,7 @@ func _on_PopupMenu_id_pressed(id: int) -> void: if new_linked_cels.size() > 1: # If there are already linked cels, set the current cel's image # to the first linked cel's image - var cel: BaseCel = project.frames[frame].cels[layer] +# var cel: BaseCel = project.frames[frame].cels[layer] var linked_cel: BaseCel = project.layers[layer].linked_cels[0].cels[layer] project.undo_redo.add_do_property(cel, "image_texture", linked_cel.image_texture) project.undo_redo.add_undo_property(cel, "image_texture", cel.image_texture) @@ -147,15 +147,15 @@ func _on_PopupMenu_id_pressed(id: int) -> void: func _delete_cel_content() -> void: var project = Global.current_project - var cel: BaseCel = project.frames[frame].cels[layer] +# var cel: BaseCel = project.frames[frame].cels[layer] var empty_content = cel.create_empty_content() var old_content = cel.get_content() project.undos += 1 project.undo_redo.create_action("Draw") if project.frames[frame] in project.layers[layer].linked_cels: - for frame in project.layers[layer].linked_cels: - project.undo_redo.add_do_method(frame.cels[layer], "set_content", empty_content) - project.undo_redo.add_undo_method(frame.cels[layer], "set_content", old_content) + for f in project.layers[layer].linked_cels: + project.undo_redo.add_do_method(f.cels[layer], "set_content", empty_content) + project.undo_redo.add_undo_method(f.cels[layer], "set_content", old_content) else: project.undo_redo.add_do_method(cel, "set_content", empty_content) project.undo_redo.add_undo_method(cel, "set_content", old_content) From 1126958a2b308a5d6ddcf1f5d724e84ad98d5172 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Wed, 14 Sep 2022 14:15:42 -0400 Subject: [PATCH 105/154] removed commented out code from previous commit --- src/UI/Timeline/CelButton.gd | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/UI/Timeline/CelButton.gd b/src/UI/Timeline/CelButton.gd index 5864ce6db838..d29eee47166b 100644 --- a/src/UI/Timeline/CelButton.gd +++ b/src/UI/Timeline/CelButton.gd @@ -110,7 +110,6 @@ func _on_PopupMenu_id_pressed(id: int) -> void: if popup_menu.get_item_metadata(MenuOptions.LINK) == "Unlink Cel": new_linked_cels.remove(cel_index) project.undo_redo.create_action("Unlink Cel") -# var cel: BaseCel = project.frames[frame].cels[layer] project.undo_redo.add_do_property(cel, "image_texture", ImageTexture.new()) project.undo_redo.add_undo_property(cel, "image_texture", cel.image_texture) project.undo_redo.add_do_method(cel, "set_content", cel.copy_content()) @@ -122,7 +121,6 @@ func _on_PopupMenu_id_pressed(id: int) -> void: if new_linked_cels.size() > 1: # If there are already linked cels, set the current cel's image # to the first linked cel's image -# var cel: BaseCel = project.frames[frame].cels[layer] var linked_cel: BaseCel = project.layers[layer].linked_cels[0].cels[layer] project.undo_redo.add_do_property(cel, "image_texture", linked_cel.image_texture) project.undo_redo.add_undo_property(cel, "image_texture", cel.image_texture) @@ -147,7 +145,6 @@ func _on_PopupMenu_id_pressed(id: int) -> void: func _delete_cel_content() -> void: var project = Global.current_project -# var cel: BaseCel = project.frames[frame].cels[layer] var empty_content = cel.create_empty_content() var old_content = cel.get_content() project.undos += 1 From 5439a544c1dc85c1e03f895c8e26d8dd59ea41d8 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 15 Sep 2022 11:53:13 -0400 Subject: [PATCH 106/154] Fixed export --- src/Autoload/Export.gd | 3 +-- src/Classes/ImageEffect.gd | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Autoload/Export.gd b/src/Autoload/Export.gd index 3d9958c0fbb7..ce2f71a80ee2 100644 --- a/src/Autoload/Export.gd +++ b/src/Autoload/Export.gd @@ -380,8 +380,7 @@ func blend_layers(image: Image, frame: Frame, origin: Vector2 = Vector2(0, 0)) - image.lock() var layer_i := 0 for cel in frame.cels: - # TODO H0: Check - if Global.current_project.layers[layer_i].visible and not cel is GroupCel: + if Global.current_project.layers[layer_i].is_visible_in_hierarchy() and cel is PixelCel: var cel_image := Image.new() cel_image.copy_from(cel.image) cel_image.lock() diff --git a/src/Classes/ImageEffect.gd b/src/Classes/ImageEffect.gd index c0930951c53a..d4f9a12bc9cf 100644 --- a/src/Classes/ImageEffect.gd +++ b/src/Classes/ImageEffect.gd @@ -123,6 +123,7 @@ func _get_undo_data(project: Project) -> Dictionary: func _get_selected_draw_images(project: Project) -> Array: # Array of Images + # TODO H0: Make GroupCel work on ImageEffect (this method is part of it) var images := [] if affect == SELECTED_CELS: for cel_index in project.selected_cels: From 042048914cb1de282c75a41b7f5f589dccbcc292 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 15 Sep 2022 12:04:37 -0400 Subject: [PATCH 107/154] Made open_image_as_new_frame work after timeline refactor --- src/Autoload/OpenSave.gd | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index bdc17939ac00..45bed447c0cd 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -559,13 +559,11 @@ func open_image_at_frame(image: Image, layer_index := 0, frame_index := 0) -> vo func open_image_as_new_frame(image: Image, layer_index := 0) -> void: - # TODO H0: Make work after the timeline refactor # TODO H1: What should happen if the layer_index isn't a PixelLayer? # Option 1: Disable OK button and show red message saying to choose a Pixel Layer # Option 2: Replace spinbox with an option list that contains all Pixel Layers (maybe better UX too) var project = Global.current_project image.crop(project.size.x, project.size.y) - var new_frames: Array = project.frames.duplicate() var frame := Frame.new() for i in project.layers.size(): @@ -575,20 +573,18 @@ func open_image_as_new_frame(image: Image, layer_index := 0) -> void: else: frame.cels.append(project.layers[i].new_empty_cel()) - new_frames.append(frame) - project.undos += 1 project.undo_redo.create_action("Add Frame") project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) - project.undo_redo.add_do_property(project, "frames", new_frames) - project.undo_redo.add_do_property(project, "current_frame", new_frames.size() - 1) + project.undo_redo.add_do_method(project, "add_frames", [frame], [project.frames.size()]) project.undo_redo.add_do_property(project, "current_layer", layer_index) + project.undo_redo.add_do_property(project, "current_frame", project.frames.size()) - project.undo_redo.add_undo_property(project, "frames", project.frames) - project.undo_redo.add_undo_property(project, "current_frame", project.current_frame) + project.undo_redo.add_undo_method(project, "remove_frames", [project.frames.size()]) project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) + project.undo_redo.add_undo_property(project, "current_frame", project.current_frame) project.undo_redo.commit_action() From 68e5ad67a6fb8250b38f61f0b119e12e9beccc9f Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 15 Sep 2022 12:29:38 -0400 Subject: [PATCH 108/154] Fixed open_image_as_new_layer after timeline refactor --- src/Autoload/OpenSave.gd | 19 ++++++------------- src/Classes/Project.gd | 2 ++ 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index 45bed447c0cd..052d7cd1b1a2 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -589,33 +589,26 @@ func open_image_as_new_frame(image: Image, layer_index := 0) -> void: func open_image_as_new_layer(image: Image, file_name: String, frame_index := 0) -> void: - # TODO H0: Make work after the timeline refactor var project = Global.current_project image.crop(project.size.x, project.size.y) - var new_layers: Array = Global.current_project.layers.duplicate() var layer := PixelLayer.new(project, file_name) + var cels := [] Global.current_project.undos += 1 Global.current_project.undo_redo.create_action("Add Layer") for i in project.frames.size(): - var new_cels: Array = project.frames[i].cels.duplicate(true) if i == frame_index: image.convert(Image.FORMAT_RGBA8) - new_cels.append(PixelCel.new(image, 1)) + cels.append(PixelCel.new(image, 1)) else: - new_cels.append(layer.new_empty_cel()) - - project.undo_redo.add_do_property(project.frames[i], "cels", new_cels) - project.undo_redo.add_undo_property(project.frames[i], "cels", project.frames[i].cels) + cels.append(layer.new_empty_cel()) - new_layers.append(layer) - - project.undo_redo.add_do_property(project, "current_layer", new_layers.size() - 1) - project.undo_redo.add_do_property(project, "layers", new_layers) + project.undo_redo.add_do_property(project, "current_layer", project.layers.size()) + project.undo_redo.add_do_method(project, "add_layers", [layer], [project.layers.size()], [cels]) project.undo_redo.add_do_property(project, "current_frame", frame_index) project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) - project.undo_redo.add_undo_property(project, "layers", project.layers) + project.undo_redo.add_undo_method(project, "remove_layers", [project.layers.size()]) project.undo_redo.add_undo_property(project, "current_frame", project.current_frame) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index d010f2f886ec..f31bfc0c250f 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -11,6 +11,7 @@ var fill_color := Color(0) var has_changed := false setget _has_changed_changed var frames := [] # Array of Frames (that contain Cels) var layers := [] # Array of Layers +# TODO H1: Comment how these are intended to be modified (or document somehow else?) var current_frame := 0 setget _frame_changed var current_layer := 0 setget _layer_changed var selected_cels := [[0, 0]] # Array of Arrays of 2 integers (frame & layer) @@ -622,6 +623,7 @@ func can_pixel_get_drawn( # Timeline modifications +# TODO H1: Comment how these are meant to be used func add_frames(new_frames: Array, indices: Array) -> void: # indices should be in ascending order Global.canvas.selection.transform_content_confirm() From 3ff4e7010bb25e2ff5fdadb21a4ccc37e30c325f Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 15 Sep 2022 13:03:29 -0400 Subject: [PATCH 109/154] Some linked cel fixes --- src/Autoload/OpenSave.gd | 2 +- src/UI/Timeline/AnimationTimeline.gd | 11 ++++++----- src/UI/Timeline/CelButton.gd | 9 +++++---- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index 052d7cd1b1a2..e27ee616c842 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -476,7 +476,7 @@ func open_image_as_spritesheet_layer( new_frame.cels.append(project.layers[l_i].new_empty_cel()) # TODO H0: Make sure setting of linked cels like this works everywhere (ie: image should be replaced with content) # CONSIDER NEW LINKED CELS IDEA, DOES IT AFFECT THIS? - if new_layers[l_i].new_cels_linked: + if new_layers[l_i].get("new_cels_linked"): new_layers[l_i].linked_cels.append(new_frame) new_frame.cels[l_i].image = new_layers[l_i].linked_cels[0].cels[l_i].image new_frame.cels[l_i].image_texture = new_layers[l_i].linked_cels[0].cels[l_i].image_texture diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 4215d1146eb0..e562526ff097 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -141,10 +141,9 @@ func add_frame() -> void: var new_layers: Array = project.duplicate_layers() for l_i in range(new_layers.size()): - # TODO H0: Make sure this works with groups (Check out copy frames): - if new_layers[l_i].new_cels_linked: # If the link button is pressed + if new_layers[l_i].get("new_cels_linked"): # If the link button is pressed new_layers[l_i].linked_cels.append(frame) - frame.cels[l_i].image = new_layers[l_i].linked_cels[0].cels[l_i].image + frame.cels[l_i].set_content(new_layers[l_i].linked_cels[0].cels[l_i].get_content()) frame.cels[l_i].image_texture = new_layers[l_i].linked_cels[0].cels[l_i].image_texture # Code to PUSH AHEAD tags starting after the frame @@ -306,14 +305,16 @@ func copy_frames(frames := []) -> void: new_frame.duration = prev_frame.duration for l_i in range(new_layers.size()): # If the layer has new_cels_linked variable, and its true - var new_cels_linked: bool = new_layers[l_i].get("new_cels_linked") + var new_cels_linked = new_layers[l_i].get("new_cels_linked") + if new_cels_linked == null: + new_cels_linked = false # Copy the cel, create new cel content if new cels aren't linked new_frame.cels.append(new_layers[l_i].copy_cel(frame, new_cels_linked)) if new_cels_linked: # If the link button is pressed new_layers[l_i].linked_cels.append(new_frame) - new_frame.cels[l_i].image = new_layers[l_i].linked_cels[0].cels[l_i].image + new_frame.cels[l_i].set_content(new_layers[l_i].linked_cels[0].cels[l_i].get_content()) new_frame.cels[l_i].image_texture = new_layers[l_i].linked_cels[0].cels[l_i].image_texture # Loop through the tags to see if the frame is in one diff --git a/src/UI/Timeline/CelButton.gd b/src/UI/Timeline/CelButton.gd index d29eee47166b..a61cf7c877df 100644 --- a/src/UI/Timeline/CelButton.gd +++ b/src/UI/Timeline/CelButton.gd @@ -38,10 +38,11 @@ func _on_CelButton_resized() -> void: get_node("CelTexture").rect_min_size.x = rect_min_size.x - 4 get_node("CelTexture").rect_min_size.y = rect_min_size.y - 4 - get_node("LinkedIndicator").polygon[1].x = rect_min_size.x - get_node("LinkedIndicator").polygon[2].x = rect_min_size.x - get_node("LinkedIndicator").polygon[2].y = rect_min_size.y - get_node("LinkedIndicator").polygon[3].y = rect_min_size.y + if is_instance_valid(linked_indicator): + linked_indicator.polygon[1].x = rect_min_size.x + linked_indicator.polygon[2].x = rect_min_size.x + linked_indicator.polygon[2].y = rect_min_size.y + linked_indicator.polygon[3].y = rect_min_size.y func _on_CelButton_pressed() -> void: From 83f6c82dca6c6063cbe21e049937956dfdd3dc4b Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 15 Sep 2022 13:20:05 -0400 Subject: [PATCH 110/154] More linked cels fixes --- src/Autoload/OpenSave.gd | 4 +--- src/UI/Timeline/AnimationTimeline.gd | 6 +++--- src/UI/Timeline/LayerButton.gd | 4 +++- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index e27ee616c842..b38cc483e520 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -474,11 +474,9 @@ func open_image_as_spritesheet_layer( var new_frame := Frame.new() for l_i in range(project.layers.size()): # Create as many cels as there are layers new_frame.cels.append(project.layers[l_i].new_empty_cel()) - # TODO H0: Make sure setting of linked cels like this works everywhere (ie: image should be replaced with content) - # CONSIDER NEW LINKED CELS IDEA, DOES IT AFFECT THIS? if new_layers[l_i].get("new_cels_linked"): new_layers[l_i].linked_cels.append(new_frame) - new_frame.cels[l_i].image = new_layers[l_i].linked_cels[0].cels[l_i].image + new_frame.cels[l_i].set_content(new_layers[l_i].linked_cels[0].cels[l_i].get_content()) new_frame.cels[l_i].image_texture = new_layers[l_i].linked_cels[0].cels[l_i].image_texture frames.append(new_frame) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index e562526ff097..c40d69f19237 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -305,9 +305,9 @@ func copy_frames(frames := []) -> void: new_frame.duration = prev_frame.duration for l_i in range(new_layers.size()): # If the layer has new_cels_linked variable, and its true - var new_cels_linked = new_layers[l_i].get("new_cels_linked") - if new_cels_linked == null: - new_cels_linked = false + var new_cels_linked: bool + if new_layers[l_i].get("new_cels_linked"): + new_cels_linked = true # Copy the cel, create new cel content if new cels aren't linked new_frame.cels.append(new_layers[l_i].copy_cel(frame, new_cels_linked)) diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index 44822dd0bafb..fe3f7d13aab4 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -173,7 +173,9 @@ func _on_LinkButton_pressed() -> void: layer_class.linked_cels.append( Global.current_project.frames[Global.current_project.current_frame] ) - var container = Global.frames_container.get_child(Global.current_project.current_layer) + var container = Global.frames_container.get_child( + Global.frames_container.get_child_count() - 1 - Global.current_project.current_layer + ) container.get_child(Global.current_project.current_frame).button_setup() _update_buttons() From fb2b6fd32fd92188385f87ea76b7d77516ca4cfd Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 15 Sep 2022 13:23:31 -0400 Subject: [PATCH 111/154] cleanup --- src/UI/Timeline/AnimationTimeline.gd | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index c40d69f19237..4c56cfb5238c 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -305,9 +305,7 @@ func copy_frames(frames := []) -> void: new_frame.duration = prev_frame.duration for l_i in range(new_layers.size()): # If the layer has new_cels_linked variable, and its true - var new_cels_linked: bool - if new_layers[l_i].get("new_cels_linked"): - new_cels_linked = true + var new_cels_linked := true if new_layers[l_i].get("new_cels_linked") else false # Copy the cel, create new cel content if new cels aren't linked new_frame.cels.append(new_layers[l_i].copy_cel(frame, new_cels_linked)) From 4a9b7c85cd6053c202be6d6c9fc39f541a2f421e Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 15 Sep 2022 13:41:50 -0400 Subject: [PATCH 112/154] Optimized importing spreadsheet as new layer --- src/Autoload/OpenSave.gd | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index b38cc483e520..a1b49c9032d0 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -484,25 +484,19 @@ func open_image_as_spritesheet_layer( var layer := PixelLayer.new(project, file_name) var cels := [] for f in new_frames_size: - # TODO H0: Consider optimizing this so extra images aren't made for frames that are in the range - # of the spritesheet's frames (To do this, need to resize cel array at first, and set them by index for - # cels not in that range, and then in the # Splice spritesheet section, create the PixelCel there. - # (Maybe instead calculate the yy and xx values, removing the yy/xx loops, and combining with this loop?) - cels.append(layer.new_empty_cel()) - - # Slice spritesheet - var image_no: int = 0 - for yy in range(vertical): - for xx in range(horizontal): + if f >= start_frame and f < (start_frame + (vertical * horizontal)): + # Slice spritesheet + var xx: int = (f - start_frame) % horizontal + var yy: int = (f - start_frame) / horizontal var cropped_image := Image.new() cropped_image = image.get_rect( Rect2(frame_width * xx, frame_height * yy, frame_width, frame_height) ) cropped_image.crop(project.size.x, project.size.y) - var frame_index = start_frame + image_no cropped_image.convert(Image.FORMAT_RGBA8) - cels[frame_index].image = cropped_image - image_no += 1 + cels.append(PixelCel.new(cropped_image)) + else: + cels.append(layer.new_empty_cel()) # TODO L: Maybe this is the better undo/redo order (As sometimes the do and undo steps can't be in the same order like here), should everything be made consistent with this? project.undo_redo.add_do_property(project, "current_frame", new_frames_size - 1) From 4877af36df4f8789169c1e0ebcf5e4a810cba450 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 15 Sep 2022 14:15:33 -0400 Subject: [PATCH 113/154] Fixed Scale Image crash with Groups --- src/Autoload/DrawingAlgos.gd | 3 ++- src/Classes/GroupCel.gd | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Autoload/DrawingAlgos.gd b/src/Autoload/DrawingAlgos.gd index c2ed511ce658..dfa91d77c9ba 100644 --- a/src/Autoload/DrawingAlgos.gd +++ b/src/Autoload/DrawingAlgos.gd @@ -423,7 +423,8 @@ func scale_image(width: int, height: int, interpolation: int) -> void: for f in Global.current_project.frames: for i in range(f.cels.size() - 1, -1, -1): - # TODO H0: Make work with Groups + if f.cels[i] is GroupCel: + continue var sprite := Image.new() sprite.copy_from(f.cels[i].image) # Different method for scale_3x diff --git a/src/Classes/GroupCel.gd b/src/Classes/GroupCel.gd index 825492f938cf..51472bdd7c1e 100644 --- a/src/Classes/GroupCel.gd +++ b/src/Classes/GroupCel.gd @@ -5,6 +5,7 @@ extends BaseCel func _init(_opacity := 1.0) -> void: opacity = _opacity + image_texture = ImageTexture.new() func get_image() -> Image: From 13e265e3ef2f2a2dbc6ada75a3562252b1dda215 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Thu, 15 Sep 2022 14:24:14 -0400 Subject: [PATCH 114/154] Fixed onion skin with groups --- src/UI/Canvas/OnionSkinning.gd | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/UI/Canvas/OnionSkinning.gd b/src/UI/Canvas/OnionSkinning.gd index 68e39cb4e6b2..e856f6ee0991 100644 --- a/src/UI/Canvas/OnionSkinning.gd +++ b/src/UI/Canvas/OnionSkinning.gd @@ -28,8 +28,7 @@ func _draw() -> void: if change == clamp(change, 0, Global.current_project.frames.size() - 1): var layer_i := 0 for cel in Global.current_project.frames[change].cels: - # TODO H0: Is this PixelLayer usage correct? - var layer: PixelLayer = Global.current_project.layers[layer_i] + var layer: BaseLayer = Global.current_project.layers[layer_i] if layer.is_visible_in_hierarchy(): # Ignore layer if it has the "_io" suffix in its name (case in-sensitive) if not (layer.name.to_lower().ends_with("_io")): From 3a826530d6f8ba6831f3671c623ba14fd2b8abc3 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 16 Sep 2022 09:25:08 -0400 Subject: [PATCH 115/154] Removed blend_mode from BaseLayer for now --- src/Classes/BaseLayer.gd | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index c7268c58d12c..b27aa2d8beac 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -5,7 +5,6 @@ extends Reference var name := "" var visible := true var locked := false -var blend_mode := 0 var parent: BaseLayer var project var index: int @@ -74,7 +73,6 @@ func serialize() -> Dictionary: "name": name, "visible": visible, "locked": locked, - "blend_mode": blend_mode, "parent": parent.index if is_instance_valid(parent) else -1 } @@ -83,7 +81,6 @@ func deserialize(dict: Dictionary) -> void: name = dict.name visible = dict.visible locked = dict.locked - blend_mode = dict.get("blend_mode", 0) if dict.get("parent", -1) != -1: parent = project.layers[dict.parent] From 3c8dc77ade9fad8aac1a4576ad526ef741f3da5a Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 16 Sep 2022 09:45:41 -0400 Subject: [PATCH 116/154] Mostly fixed image effects --- src/Autoload/Export.gd | 4 +++- src/Classes/ImageEffect.gd | 9 +++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Autoload/Export.gd b/src/Autoload/Export.gd index ce2f71a80ee2..604d97bcb4de 100644 --- a/src/Autoload/Export.gd +++ b/src/Autoload/Export.gd @@ -406,9 +406,11 @@ func blend_selected_cels(image: Image, frame: Frame, origin: Vector2 = Vector2(0 var test_array = [Global.current_project.current_frame, cel_ind] if not test_array in Global.current_project.selected_cels: continue + if not frame.cels[cel_ind] is PixelCel: + continue - # TODO H1: Make sure this PixelCel usage is right var cel: PixelCel = frame.cels[cel_ind] + if Global.current_project.layers[layer_i].visible: var cel_image := Image.new() cel_image.copy_from(cel.image) diff --git a/src/Classes/ImageEffect.gd b/src/Classes/ImageEffect.gd index d4f9a12bc9cf..e5749c696682 100644 --- a/src/Classes/ImageEffect.gd +++ b/src/Classes/ImageEffect.gd @@ -123,16 +123,17 @@ func _get_undo_data(project: Project) -> Dictionary: func _get_selected_draw_images(project: Project) -> Array: # Array of Images - # TODO H0: Make GroupCel work on ImageEffect (this method is part of it) var images := [] if affect == SELECTED_CELS: for cel_index in project.selected_cels: - var cel: PixelCel = project.frames[cel_index[0]].cels[cel_index[1]] - images.append(cel.image) + var cel: BaseCel = project.frames[cel_index[0]].cels[cel_index[1]] + if cel is PixelCel: + images.append(cel.image) else: for frame in project.frames: for cel in frame.cels: - images.append(cel.image) + if cel is PixelCel: + images.append(cel.image) return images From c2ab5fac77a268ee375c6d382023bb5bf1e809e1 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 16 Sep 2022 10:39:28 -0400 Subject: [PATCH 117/154] Fixed resize canvas --- src/Autoload/DrawingAlgos.gd | 2 ++ src/UI/Dialogs/ImageEffects/ResizeCanvas.gd | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Autoload/DrawingAlgos.gd b/src/Autoload/DrawingAlgos.gd index dfa91d77c9ba..1c01154614e1 100644 --- a/src/Autoload/DrawingAlgos.gd +++ b/src/Autoload/DrawingAlgos.gd @@ -506,6 +506,8 @@ func resize_canvas(width: int, height: int, offset_x: int, offset_y: int) -> voi general_do_scale(width, height) for f in Global.current_project.frames: for c in f.cels: + if not c is PixelCel: + continue var sprite := Image.new() sprite.create(width, height, false, Image.FORMAT_RGBA8) sprite.blend_rect( diff --git a/src/UI/Dialogs/ImageEffects/ResizeCanvas.gd b/src/UI/Dialogs/ImageEffects/ResizeCanvas.gd index 00f7d152e259..d87d8dac9f93 100644 --- a/src/UI/Dialogs/ImageEffects/ResizeCanvas.gd +++ b/src/UI/Dialogs/ImageEffects/ResizeCanvas.gd @@ -22,7 +22,7 @@ func _on_ResizeCanvas_about_to_show() -> void: var layer_i := 0 for cel in Global.current_project.frames[Global.current_project.current_frame].cels: - if Global.current_project.layers[layer_i].visible: + if cel is PixelCel and Global.current_project.layers[layer_i].is_visible_in_hierarchy(): var cel_image := Image.new() cel_image.copy_from(cel.image) cel_image.lock() From eab05762d44840001ac9cfdfe43958c237c56bab Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 16 Sep 2022 10:59:45 -0400 Subject: [PATCH 118/154] Fixed drag and drop not working with Cel Buttons on Group Layers --- src/UI/Timeline/CelButton.gd | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/UI/Timeline/CelButton.gd b/src/UI/Timeline/CelButton.gd index a61cf7c877df..da1127f08853 100644 --- a/src/UI/Timeline/CelButton.gd +++ b/src/UI/Timeline/CelButton.gd @@ -174,17 +174,18 @@ func get_drag_data(_position) -> Array: button.add_child(texture_rect) set_drag_preview(button) - return ["PixelCel", frame, layer] + return ["Cel", frame, layer] func can_drop_data(_pos, data) -> bool: - if typeof(data) == TYPE_ARRAY and data[0] == "PixelCel": + if typeof(data) == TYPE_ARRAY and data[0] == "Cel": var drag_frame = data[1] var drag_layer = data[2] # TODO L: Is this part really right? Should't it only matter if they're linked, and we're changing layers? # It would need to add linked cel logic to project move/swap_cel though + # I THINK I WILL CHANGE THIS WITH FUTURE LINKED CEL UPDATE (might not need move/swap_cel logic) # If the cel we're dragging or the cel we are targeting are linked, don't allow dragging - if not ( + if Global.current_project.layers[layer] is GroupLayer or not ( Global.current_project.frames[frame] in Global.current_project.layers[layer].linked_cels or ( Global.current_project.frames[drag_frame] From a1dda9521a71a9a446e79180954387cce169dfc4 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 16 Sep 2022 11:53:02 -0400 Subject: [PATCH 119/154] updated TODOs --- src/Classes/BaseCel.gd | 2 +- src/UI/Canvas/Selection.gd | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Classes/BaseCel.gd b/src/Classes/BaseCel.gd index 00a69304c4b9..c107d4f29835 100644 --- a/src/Classes/BaseCel.gd +++ b/src/Classes/BaseCel.gd @@ -8,7 +8,7 @@ var image_texture: ImageTexture # Methods to Override: -# TODO H0: Check if copying cels can use the content methods +# TODO L: Check if copying cels can use the content methods (Do during/after Linked Cel refactor) # TODO H1: These content methods need good doc comments: # COMMENT FROM THE IDEA TODO COMMENT (MAY BE USEFUL FOR WRITING COMMENTS) diff --git a/src/UI/Canvas/Selection.gd b/src/UI/Canvas/Selection.gd index 35c95a49a9e0..17aa0eae3042 100644 --- a/src/UI/Canvas/Selection.gd +++ b/src/UI/Canvas/Selection.gd @@ -71,7 +71,8 @@ func _ready() -> void: # gizmos.append(Gizmo.new(Gizmo.Type.ROTATE)) # Rotation gizmo (temp) -# TODO H/L: Can't move/resize a selection on a group cel (It just draws a new selection), maybe has to do with can_layer_get_drawn? +# TODO L: Can't move/resize a selection on a group cel (It just draws a new selection), maybe has to do with can_layer_get_drawn? +# This is a bug with the selection input in general, also happens with locked Pixel Layers. Ask Overloaded about it func _input(event: InputEvent) -> void: if is_moving_content: if Input.is_action_just_pressed("transformation_confirm"): @@ -97,7 +98,6 @@ func _input(event: InputEvent) -> void: if Global.cross_cursor: cursor = Control.CURSOR_CROSS var project: Project = Global.current_project - # TODO H0: Make sure this BaseLayer is supposed to be BaseLayer var layer: BaseLayer = project.layers[project.current_layer] if not layer.can_layer_get_drawn(): cursor = Control.CURSOR_FORBIDDEN From 875d2ab12505b1a67b8e9d4070e53c1ccbb5a54a Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 16 Sep 2022 12:28:00 -0400 Subject: [PATCH 120/154] Renamed Replace Frame (in open image) to Replace Cel --- Translations/Translations.pot | 2 +- src/Autoload/OpenSave.gd | 3 ++- src/UI/Dialogs/PreviewDialog.gd | 30 +++++++++++++++--------------- src/UI/Dialogs/PreviewDialog.tscn | 10 +++++----- 4 files changed, 23 insertions(+), 22 deletions(-) diff --git a/Translations/Translations.pot b/Translations/Translations.pot index 92cc187107da..5b86e113c21c 100644 --- a/Translations/Translations.pot +++ b/Translations/Translations.pot @@ -313,7 +313,7 @@ msgstr "" msgid "New frame" msgstr "" -msgid "Replace frame" +msgid "Replace cel" msgstr "" msgid "New layer" diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index a1b49c9032d0..cd98a689eaf4 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -515,10 +515,11 @@ func open_image_as_spritesheet_layer( project.undo_redo.commit_action() -func open_image_at_frame(image: Image, layer_index := 0, frame_index := 0) -> void: +func open_image_at_cel(image: Image, layer_index := 0, frame_index := 0) -> void: # TODO H1: What should happen if the layer_index isn't a PixelLayer? # Option 1: Disable OK button and show red message saying to choose a Pixel Layer # Option 2: Replace spinbox with an option list that contains all Pixel Layers (maybe better UX too) + # TODO H0: Make work after refactor (Its directly setting frames, and the cel button doesn't' get updated) var project = Global.current_project image.crop(project.size.x, project.size.y) diff --git a/src/UI/Dialogs/PreviewDialog.gd b/src/UI/Dialogs/PreviewDialog.gd index 14ac0e10cc43..0bb68c99ac8d 100644 --- a/src/UI/Dialogs/PreviewDialog.gd +++ b/src/UI/Dialogs/PreviewDialog.gd @@ -5,7 +5,7 @@ enum ImageImportOptions { SPRITESHEET_TAB, SPRITESHEET_LAYER, NEW_FRAME, - REPLACE_FRAME, + REPLACE_CEL, NEW_LAYER, PALETTE, BRUSH, @@ -29,7 +29,7 @@ onready var frame_size_label: Label = $VBoxContainer/SizeContainer/FrameSizeLabe onready var spritesheet_tab_options = $VBoxContainer/HBoxContainer/SpritesheetTabOptions onready var spritesheet_lay_opt = $VBoxContainer/HBoxContainer/SpritesheetLayerOptions onready var new_frame_options = $VBoxContainer/HBoxContainer/NewFrameOptions -onready var replace_frame_options = $VBoxContainer/HBoxContainer/ReplaceFrameOptions +onready var replace_cel_options = $VBoxContainer/HBoxContainer/ReplaceCelOptions onready var new_layer_options = $VBoxContainer/HBoxContainer/NewLayerOptions onready var new_brush_options = $VBoxContainer/HBoxContainer/NewBrushOptions onready var new_brush_name = $VBoxContainer/HBoxContainer/NewBrushOptions/BrushName @@ -47,7 +47,7 @@ func _on_PreviewDialog_about_to_show() -> void: import_options.add_item("Spritesheet (new project)") import_options.add_item("Spritesheet (new layer)") import_options.add_item("New frame") - import_options.add_item("Replace frame") + import_options.add_item("Replace cel") import_options.add_item("New layer") import_options.add_item("New palette") import_options.add_item("New brush") @@ -128,10 +128,10 @@ func _on_PreviewDialog_confirmed() -> void: var layer_index: int = new_frame_options.get_node("AtLayerSpinbox").value OpenSave.open_image_as_new_frame(image, layer_index) - elif current_import_option == ImageImportOptions.REPLACE_FRAME: - var layer_index: int = replace_frame_options.get_node("AtLayerSpinbox").value - var frame_index: int = replace_frame_options.get_node("AtFrameSpinbox").value - 1 - OpenSave.open_image_at_frame(image, layer_index, frame_index) + elif current_import_option == ImageImportOptions.REPLACE_CEL: + var layer_index: int = replace_cel_options.get_node("AtLayerSpinbox").value + var frame_index: int = replace_cel_options.get_node("AtFrameSpinbox").value - 1 + OpenSave.open_image_at_cel(image, layer_index, frame_index) elif current_import_option == ImageImportOptions.NEW_LAYER: var frame_index: int = new_layer_options.get_node("AtFrameSpinbox").value - 1 @@ -204,11 +204,11 @@ func synchronize() -> void: "AtLayerSpinbox" ).value) - elif id == ImageImportOptions.REPLACE_FRAME: - dialog.replace_frame_options.get_node("AtLayerSpinbox").value = (replace_frame_options.get_node( + elif id == ImageImportOptions.REPLACE_CEL: + dialog.replace_cel_options.get_node("AtLayerSpinbox").value = (replace_cel_options.get_node( "AtLayerSpinbox" ).value) - dialog.replace_frame_options.get_node("AtFrameSpinbox").value = (replace_frame_options.get_node( + dialog.replace_cel_options.get_node("AtFrameSpinbox").value = (replace_cel_options.get_node( "AtFrameSpinbox" ).value) @@ -231,7 +231,7 @@ func _on_ImportOption_item_selected(id: int) -> void: spritesheet_tab_options.visible = false spritesheet_lay_opt.visible = false new_frame_options.visible = false - replace_frame_options.visible = false + replace_cel_options.visible = false new_layer_options.visible = false new_brush_options.visible = false texture_rect.get_child(0).visible = false @@ -260,13 +260,13 @@ func _on_ImportOption_item_selected(id: int) -> void: - 1 ) - elif id == ImageImportOptions.REPLACE_FRAME: - replace_frame_options.visible = true - replace_frame_options.get_node("AtLayerSpinbox").max_value = ( + elif id == ImageImportOptions.REPLACE_CEL: + replace_cel_options.visible = true + replace_cel_options.get_node("AtLayerSpinbox").max_value = ( Global.current_project.layers.size() - 1 ) - var at_frame_spinbox: SpinBox = replace_frame_options.get_node("AtFrameSpinbox") + var at_frame_spinbox: SpinBox = replace_cel_options.get_node("AtFrameSpinbox") at_frame_spinbox.max_value = Global.current_project.frames.size() elif id == ImageImportOptions.NEW_LAYER: diff --git a/src/UI/Dialogs/PreviewDialog.tscn b/src/UI/Dialogs/PreviewDialog.tscn index e4fe9d54dbba..bea1ea7af2eb 100644 --- a/src/UI/Dialogs/PreviewDialog.tscn +++ b/src/UI/Dialogs/PreviewDialog.tscn @@ -168,33 +168,33 @@ margin_bottom = 24.0 mouse_default_cursor_shape = 2 max_value = 0.0 -[node name="ReplaceFrameOptions" type="HBoxContainer" parent="VBoxContainer/HBoxContainer"] +[node name="ReplaceCelOptions" type="HBoxContainer" parent="VBoxContainer/HBoxContainer"] visible = false margin_left = 155.0 margin_right = 427.0 margin_bottom = 24.0 -[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/ReplaceFrameOptions"] +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/ReplaceCelOptions"] margin_top = 5.0 margin_right = 53.0 margin_bottom = 19.0 text = "At layer:" -[node name="AtLayerSpinbox" type="SpinBox" parent="VBoxContainer/HBoxContainer/ReplaceFrameOptions"] +[node name="AtLayerSpinbox" type="SpinBox" parent="VBoxContainer/HBoxContainer/ReplaceCelOptions"] margin_left = 57.0 margin_right = 131.0 margin_bottom = 24.0 mouse_default_cursor_shape = 2 max_value = 0.0 -[node name="Label2" type="Label" parent="VBoxContainer/HBoxContainer/ReplaceFrameOptions"] +[node name="Label2" type="Label" parent="VBoxContainer/HBoxContainer/ReplaceCelOptions"] margin_left = 135.0 margin_top = 5.0 margin_right = 194.0 margin_bottom = 19.0 text = "At frame:" -[node name="AtFrameSpinbox" type="SpinBox" parent="VBoxContainer/HBoxContainer/ReplaceFrameOptions"] +[node name="AtFrameSpinbox" type="SpinBox" parent="VBoxContainer/HBoxContainer/ReplaceCelOptions"] margin_left = 198.0 margin_right = 272.0 margin_bottom = 24.0 From cc5215a9add9f398e3b51f4bdecc6c1f614c9fb4 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 16 Sep 2022 12:29:56 -0400 Subject: [PATCH 121/154] Continued renaming Replace Frame to Replace Cel --- src/Autoload/OpenSave.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index cd98a689eaf4..0e664c06ff7e 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -524,7 +524,7 @@ func open_image_at_cel(image: Image, layer_index := 0, frame_index := 0) -> void image.crop(project.size.x, project.size.y) project.undos += 1 - project.undo_redo.create_action("Replaced Frame") + project.undo_redo.create_action("Replaced Cel") var frames: Array = [] # create a duplicate of "project.frames" From 64cade74e71ff039d51e866dcff6b1f281282ca1 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 16 Sep 2022 13:06:30 -0400 Subject: [PATCH 122/154] Made open_image_at_cels work after timeline refactor --- src/Autoload/OpenSave.gd | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index 0e664c06ff7e..e385e3dcf231 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -519,34 +519,26 @@ func open_image_at_cel(image: Image, layer_index := 0, frame_index := 0) -> void # TODO H1: What should happen if the layer_index isn't a PixelLayer? # Option 1: Disable OK button and show red message saying to choose a Pixel Layer # Option 2: Replace spinbox with an option list that contains all Pixel Layers (maybe better UX too) - # TODO H0: Make work after refactor (Its directly setting frames, and the cel button doesn't' get updated) var project = Global.current_project - image.crop(project.size.x, project.size.y) - project.undos += 1 project.undo_redo.create_action("Replaced Cel") - var frames: Array = [] - # create a duplicate of "project.frames" - for i in project.frames.size(): - var frame := Frame.new() - frame.cels = project.frames[i].cels.duplicate(true) - frames.append(frame) - for i in project.frames.size(): if i == frame_index: + image.crop(project.size.x, project.size.y) image.convert(Image.FORMAT_RGBA8) - frames[i].cels[layer_index] = (PixelCel.new(image, 1)) - project.undo_redo.add_do_property(project.frames[i], "cels", frames[i].cels) - project.undo_redo.add_undo_property(project.frames[i], "cels", project.frames[i].cels) + var cel: PixelCel = project.frames[i].cels[layer_index] + project.undo_redo.add_do_property(cel, "image", image) + project.undo_redo.add_undo_property(cel, "image", cel.image) - project.undo_redo.add_do_property(project, "frames", frames) + project.undo_redo.add_do_property(project, "selected_cels", []) + project.undo_redo.add_do_property(project, "current_layer", layer_index) project.undo_redo.add_do_property(project, "current_frame", frame_index) + project.undo_redo.add_do_method(Global, "undo_or_redo", false) - project.undo_redo.add_undo_property(project, "frames", project.frames) + project.undo_redo.add_undo_property(project, "selected_cels", []) + project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) project.undo_redo.add_undo_property(project, "current_frame", project.current_frame) - - project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.commit_action() @@ -569,12 +561,11 @@ func open_image_as_new_frame(image: Image, layer_index := 0) -> void: project.undos += 1 project.undo_redo.create_action("Add Frame") project.undo_redo.add_do_method(Global, "undo_or_redo", false) - project.undo_redo.add_undo_method(Global, "undo_or_redo", true) - project.undo_redo.add_do_method(project, "add_frames", [frame], [project.frames.size()]) project.undo_redo.add_do_property(project, "current_layer", layer_index) project.undo_redo.add_do_property(project, "current_frame", project.frames.size()) + project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.add_undo_method(project, "remove_frames", [project.frames.size()]) project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) project.undo_redo.add_undo_property(project, "current_frame", project.current_frame) From b6d7ef32cf953ee51a4dfad333b2a68bdea5bcc9 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 16 Sep 2022 14:09:20 -0400 Subject: [PATCH 123/154] Added get_layer_path method to BaseLayer --- src/Classes/BaseLayer.gd | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index b27aa2d8beac..33bc5b256171 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -65,6 +65,11 @@ func get_hierarchy_depth() -> int: return 0 +func get_layer_path() -> String: + if is_instance_valid(parent): + return str(parent.get_layer_path(), "/", name) + return name + # Methods to Override: func serialize() -> Dictionary: From 17f31b7e366fe97865188fa2fbed6a369efc0416 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 16 Sep 2022 14:10:11 -0400 Subject: [PATCH 124/154] Replaced AtLayerSpinbox with AtLayerOption for Open Image as New Frame or Replace Cel --- src/UI/Dialogs/PreviewDialog.gd | 49 ++++++++++++++++++++----------- src/UI/Dialogs/PreviewDialog.tscn | 18 +++++++----- 2 files changed, 42 insertions(+), 25 deletions(-) diff --git a/src/UI/Dialogs/PreviewDialog.gd b/src/UI/Dialogs/PreviewDialog.gd index 0bb68c99ac8d..87ecf3042872 100644 --- a/src/UI/Dialogs/PreviewDialog.gd +++ b/src/UI/Dialogs/PreviewDialog.gd @@ -125,11 +125,11 @@ func _on_PreviewDialog_confirmed() -> void: ) elif current_import_option == ImageImportOptions.NEW_FRAME: - var layer_index: int = new_frame_options.get_node("AtLayerSpinbox").value + var layer_index: int = new_frame_options.get_node("AtLayerOption").get_selected_id() OpenSave.open_image_as_new_frame(image, layer_index) elif current_import_option == ImageImportOptions.REPLACE_CEL: - var layer_index: int = replace_cel_options.get_node("AtLayerSpinbox").value + var layer_index: int = replace_cel_options.get_node("AtLayerOption").get_selected_id() var frame_index: int = replace_cel_options.get_node("AtFrameSpinbox").value - 1 OpenSave.open_image_at_cel(image, layer_index, frame_index) @@ -200,14 +200,14 @@ func synchronize() -> void: ).value) elif id == ImageImportOptions.NEW_FRAME: - dialog.new_frame_options.get_node("AtLayerSpinbox").value = (new_frame_options.get_node( - "AtLayerSpinbox" - ).value) + dialog.new_frame_options.get_node("AtLayerOption").selected = (new_frame_options.get_node( + "AtLayerOption" + ).selected) elif id == ImageImportOptions.REPLACE_CEL: - dialog.replace_cel_options.get_node("AtLayerSpinbox").value = (replace_cel_options.get_node( - "AtLayerSpinbox" - ).value) + dialog.replace_cel_options.get_node("AtLayerOption").selected = (replace_cel_options.get_node( + "AtLayerOption" + ).selected) dialog.replace_cel_options.get_node("AtFrameSpinbox").value = (replace_cel_options.get_node( "AtFrameSpinbox" ).value) @@ -255,17 +255,32 @@ func _on_ImportOption_item_selected(id: int) -> void: elif id == ImageImportOptions.NEW_FRAME: new_frame_options.visible = true - new_frame_options.get_node("AtLayerSpinbox").max_value = ( - Global.current_project.layers.size() - - 1 - ) - + # Fill the at layer option button: + var at_layer_option: OptionButton = new_frame_options.get_node("AtLayerOption") + var layers := Global.current_project.layers.duplicate() + layers.invert() + var i := 0 + for l in layers: + if not l is PixelLayer: + continue + at_layer_option.add_item(l.name, l.index) + at_layer_option.set_item_tooltip(i, l.get_layer_path()) + i += 1 + at_layer_option.selected = at_layer_option.get_item_count() - 1 elif id == ImageImportOptions.REPLACE_CEL: replace_cel_options.visible = true - replace_cel_options.get_node("AtLayerSpinbox").max_value = ( - Global.current_project.layers.size() - - 1 - ) + # Fill the at layer option button: + var at_layer_option: OptionButton = replace_cel_options.get_node("AtLayerOption") + var layers := Global.current_project.layers.duplicate() + layers.invert() + var i := 0 + for l in layers: + if not l is PixelLayer: + continue + at_layer_option.add_item(l.name, l.index) + at_layer_option.set_item_tooltip(i, l.get_layer_path()) + i += 1 + at_layer_option.selected = at_layer_option.get_item_count() - 1 var at_frame_spinbox: SpinBox = replace_cel_options.get_node("AtFrameSpinbox") at_frame_spinbox.max_value = Global.current_project.frames.size() diff --git a/src/UI/Dialogs/PreviewDialog.tscn b/src/UI/Dialogs/PreviewDialog.tscn index bea1ea7af2eb..bddf8ca55804 100644 --- a/src/UI/Dialogs/PreviewDialog.tscn +++ b/src/UI/Dialogs/PreviewDialog.tscn @@ -154,6 +154,7 @@ visible = false margin_left = 155.0 margin_right = 286.0 margin_bottom = 24.0 +size_flags_horizontal = 3 [node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/NewFrameOptions"] margin_top = 5.0 @@ -161,18 +162,19 @@ margin_right = 53.0 margin_bottom = 19.0 text = "At layer:" -[node name="AtLayerSpinbox" type="SpinBox" parent="VBoxContainer/HBoxContainer/NewFrameOptions"] +[node name="AtLayerOption" type="OptionButton" parent="VBoxContainer/HBoxContainer/NewFrameOptions"] margin_left = 57.0 -margin_right = 131.0 -margin_bottom = 24.0 +margin_right = 86.0 +margin_bottom = 20.0 mouse_default_cursor_shape = 2 -max_value = 0.0 +align = 2 [node name="ReplaceCelOptions" type="HBoxContainer" parent="VBoxContainer/HBoxContainer"] visible = false margin_left = 155.0 margin_right = 427.0 margin_bottom = 24.0 +size_flags_horizontal = 3 [node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/ReplaceCelOptions"] margin_top = 5.0 @@ -180,12 +182,12 @@ margin_right = 53.0 margin_bottom = 19.0 text = "At layer:" -[node name="AtLayerSpinbox" type="SpinBox" parent="VBoxContainer/HBoxContainer/ReplaceCelOptions"] +[node name="AtLayerOption" type="OptionButton" parent="VBoxContainer/HBoxContainer/ReplaceCelOptions"] margin_left = 57.0 -margin_right = 131.0 -margin_bottom = 24.0 +margin_right = 86.0 +margin_bottom = 20.0 mouse_default_cursor_shape = 2 -max_value = 0.0 +align = 2 [node name="Label2" type="Label" parent="VBoxContainer/HBoxContainer/ReplaceCelOptions"] margin_left = 135.0 From d90541626ba1eecdab3be05c460dcdffba8476bc Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 16 Sep 2022 14:13:22 -0400 Subject: [PATCH 125/154] Updated TODOs --- src/Autoload/OpenSave.gd | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index e385e3dcf231..5f54edddefeb 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -516,9 +516,6 @@ func open_image_as_spritesheet_layer( func open_image_at_cel(image: Image, layer_index := 0, frame_index := 0) -> void: - # TODO H1: What should happen if the layer_index isn't a PixelLayer? - # Option 1: Disable OK button and show red message saying to choose a Pixel Layer - # Option 2: Replace spinbox with an option list that contains all Pixel Layers (maybe better UX too) var project = Global.current_project project.undos += 1 project.undo_redo.create_action("Replaced Cel") @@ -544,9 +541,6 @@ func open_image_at_cel(image: Image, layer_index := 0, frame_index := 0) -> void func open_image_as_new_frame(image: Image, layer_index := 0) -> void: - # TODO H1: What should happen if the layer_index isn't a PixelLayer? - # Option 1: Disable OK button and show red message saying to choose a Pixel Layer - # Option 2: Replace spinbox with an option list that contains all Pixel Layers (maybe better UX too) var project = Global.current_project image.crop(project.size.x, project.size.y) From 699a93ab2c9d7ee282eaec3ec254964e87aa0f08 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 16 Sep 2022 14:26:55 -0400 Subject: [PATCH 126/154] updated TODOs --- src/Classes/GroupCel.gd | 1 - src/Classes/Project.gd | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Classes/GroupCel.gd b/src/Classes/GroupCel.gd index 51472bdd7c1e..f5e1dde0308b 100644 --- a/src/Classes/GroupCel.gd +++ b/src/Classes/GroupCel.gd @@ -9,7 +9,6 @@ func _init(_opacity := 1.0) -> void: func get_image() -> Image: - # TODO H1: This can be used for copying selections or picking colors... Can maybe make from texture data? var image = Image.new() image.create(Global.current_project.size.x, Global.current_project.size.y, false, Image.FORMAT_RGBA8) return image diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index f31bfc0c250f..9003760dab35 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -9,9 +9,9 @@ var tiles: Tiles var undos := 0 # The number of times we added undo properties var fill_color := Color(0) var has_changed := false setget _has_changed_changed +# TODO H1: Comment how these are intended to be modified (or document somehow else?) var frames := [] # Array of Frames (that contain Cels) var layers := [] # Array of Layers -# TODO H1: Comment how these are intended to be modified (or document somehow else?) var current_frame := 0 setget _frame_changed var current_layer := 0 setget _layer_changed var selected_cels := [[0, 0]] # Array of Arrays of 2 integers (frame & layer) From 988cc6444b95dc5feffed1b738b3a7ee42abb129 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 16 Sep 2022 14:43:09 -0400 Subject: [PATCH 127/154] Comments for cel content methods --- src/Classes/BaseCel.gd | 24 +++++++++--------------- src/Classes/PixelCel.gd | 8 ++++---- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/Classes/BaseCel.gd b/src/Classes/BaseCel.gd index c107d4f29835..fb3703660056 100644 --- a/src/Classes/BaseCel.gd +++ b/src/Classes/BaseCel.gd @@ -10,29 +10,23 @@ var image_texture: ImageTexture # TODO L: Check if copying cels can use the content methods (Do during/after Linked Cel refactor) -# TODO H1: These content methods need good doc comments: -# COMMENT FROM THE IDEA TODO COMMENT (MAY BE USEFUL FOR WRITING COMMENTS) -# - get_content will return certain content of the cel (should metadata be included?) -# - set_content will set the content (same structure as get_content returns) -# - delete/clear_content will erase it, -# - using get_content and set_content could become useful for linking/unlinking cels, and will be reversible for undo -# - this can be used to replace copy_cel and copy_all_cels in layer classes -# - using all 3 will allow you to delete content, and undo it in cel button -# = making this generic and should solve issues with combing cel_button scripts into 1 -# - copy_content may also be a useful method to have +# The content methods deal with the unique content of each cel type. For example, an Image for +# PixelLayers, or a Dictionary of settings for a procedural layer type, and null for Groups. +# Can be used fo linking/unlinking cels, copying, and deleting content +func get_content(): + return null + func set_content(_content) -> void: return -func get_content(): - return [] - - +# Can be used to delete the content of the cel with set_content +# (using the old content from get_content as undo data) func create_empty_content(): return [] - +# Can be used for creating copy content for copying cels or unlinking cels func copy_content(): return [] diff --git a/src/Classes/PixelCel.gd b/src/Classes/PixelCel.gd index 074e0fc82a97..eeb6a74f22a8 100644 --- a/src/Classes/PixelCel.gd +++ b/src/Classes/PixelCel.gd @@ -21,15 +21,15 @@ func image_changed(value: Image) -> void: image_texture.create_from_image(image, 0) +func get_content(): + return image + + func set_content(content) -> void: image = content image_texture.create_from_image(image, 0) -func get_content(): - return image - - func create_empty_content(): var empty_image := Image.new() empty_image.create(image.get_size().x, image.get_size().y, false, Image.FORMAT_RGBA8) From 454cf3d0db9eadaa5c02779bffcec66d900881ee Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 16 Sep 2022 14:44:55 -0400 Subject: [PATCH 128/154] fixed right clicking group cel button deselecting the button (even though cel is still selected --- src/UI/Timeline/CelButton.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/UI/Timeline/CelButton.gd b/src/UI/Timeline/CelButton.gd index da1127f08853..0c6a6f8499b8 100644 --- a/src/UI/Timeline/CelButton.gd +++ b/src/UI/Timeline/CelButton.gd @@ -90,7 +90,7 @@ func _on_CelButton_pressed() -> void: elif Input.is_action_just_released("right_mouse"): if is_instance_valid(popup_menu): popup_menu.popup(Rect2(get_global_mouse_position(), Vector2.ONE)) - pressed = !pressed + pressed = !pressed elif Input.is_action_just_released("middle_mouse"): pressed = !pressed _delete_cel_content() From 5e75ebb5564e07604b59068f01cba9ce6bd5b769 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Fri, 16 Sep 2022 14:58:03 -0400 Subject: [PATCH 129/154] frame/layer modification methods comments --- src/Classes/Project.gd | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 9003760dab35..632124056287 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -9,7 +9,9 @@ var tiles: Tiles var undos := 0 # The number of times we added undo properties var fill_color := Color(0) var has_changed := false setget _has_changed_changed -# TODO H1: Comment how these are intended to be modified (or document somehow else?) +# frames and layers Arrays should generally only be modified directly when +# opening/creating a project. When modifiying the current project, use +# the add/remove/move/swap_frames/layers methods var frames := [] # Array of Frames (that contain Cels) var layers := [] # Array of Layers var current_frame := 0 setget _frame_changed @@ -623,7 +625,11 @@ func can_pixel_get_drawn( # Timeline modifications -# TODO H1: Comment how these are meant to be used +# Modifying layers or frames Arrays on the current project should generally only be done +# through these methods. +# These allow you to add/remove/move/swap frames/layers/cels. It updates the Animation Timeline +# UI, and updates indices. These are designed to be reversible, meaning that to undo an add, you +# use remove, and vise versa. To undo a move or swap, use move or swap with the paramaters swapped. func add_frames(new_frames: Array, indices: Array) -> void: # indices should be in ascending order Global.canvas.selection.transform_content_confirm() From 746c610833de982b61108e538b03ae48ae087bfb Mon Sep 17 00:00:00 2001 From: mrtripie <65431647+mrtripie@users.noreply.github.com> Date: Fri, 16 Sep 2022 18:48:57 -0400 Subject: [PATCH 130/154] Removed unneeded size flags --- src/UI/Dialogs/PreviewDialog.tscn | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/UI/Dialogs/PreviewDialog.tscn b/src/UI/Dialogs/PreviewDialog.tscn index bddf8ca55804..61fae68c701f 100644 --- a/src/UI/Dialogs/PreviewDialog.tscn +++ b/src/UI/Dialogs/PreviewDialog.tscn @@ -154,7 +154,6 @@ visible = false margin_left = 155.0 margin_right = 286.0 margin_bottom = 24.0 -size_flags_horizontal = 3 [node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/NewFrameOptions"] margin_top = 5.0 @@ -174,7 +173,6 @@ visible = false margin_left = 155.0 margin_right = 427.0 margin_bottom = 24.0 -size_flags_horizontal = 3 [node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/ReplaceCelOptions"] margin_top = 5.0 From a65441f2fc06b7c5d1bb4bfb80e4a30c58b3c694 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 17 Sep 2022 12:04:47 -0400 Subject: [PATCH 131/154] TODO updates --- src/Autoload/OpenSave.gd | 16 ++++++++-------- src/Classes/BaseCel.gd | 2 +- src/Classes/BaseLayer.gd | 4 ++-- src/Classes/Project.gd | 1 - src/UI/Canvas/Selection.gd | 2 +- src/UI/Timeline/AnimationTimeline.gd | 6 ++---- src/UI/Timeline/CelButton.gd | 4 ++-- src/UI/Timeline/LayerButton.gd | 4 +--- 8 files changed, 17 insertions(+), 22 deletions(-) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index 5f54edddefeb..9027da127136 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -428,12 +428,12 @@ func open_image_as_spritesheet_tab(path: String, image: Image, horiz: int, vert: cropped_image.convert(Image.FORMAT_RGBA8) frame.cels.append(PixelCel.new(cropped_image, 1)) - # TODO L: This for loop doesn't need to exist (its adding cels to layers that never exist): - for _i in range(1, project.layers.size()): - var empty_sprite := Image.new() - empty_sprite.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8) - empty_sprite.fill(Color(0, 0, 0, 0)) - frame.cels.append(PixelCel.new(empty_sprite, 1)) + # TODO L0: This for loop doesn't need to exist (its adding cels to layers that never exist): +# for _i in range(1, project.layers.size()): +# var empty_sprite := Image.new() +# empty_sprite.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8) +# empty_sprite.fill(Color(0, 0, 0, 0)) +# frame.cels.append(PixelCel.new(empty_sprite, 1)) project.frames.append(frame) @@ -468,7 +468,7 @@ func open_image_as_spritesheet_layer( var frame_indices: Array if new_frames_size > project.frames.size(): var required_frames = new_frames_size - project.frames.size() - # TODO L: Is adding the new frames starting after the current frame right? (Maybe its better to start after the last frame) + # TODO L0: Is adding the new frames starting after the current frame right? (Maybe its better to start after the last frame) frame_indices= range(project.current_frame + 1, project.current_frame + required_frames + 1) for i in required_frames: var new_frame := Frame.new() @@ -498,7 +498,7 @@ func open_image_as_spritesheet_layer( else: cels.append(layer.new_empty_cel()) - # TODO L: Maybe this is the better undo/redo order (As sometimes the do and undo steps can't be in the same order like here), should everything be made consistent with this? + # TODO L0: Maybe this is the better undo/redo order (As sometimes the do and undo steps can't be in the same order like here), should everything be made consistent with this? project.undo_redo.add_do_property(project, "current_frame", new_frames_size - 1) project.undo_redo.add_do_property(project, "current_layer", project.layers.size()) project.undo_redo.add_do_method(project, "add_frames", frames, frame_indices) diff --git a/src/Classes/BaseCel.gd b/src/Classes/BaseCel.gd index fb3703660056..66eb1a596455 100644 --- a/src/Classes/BaseCel.gd +++ b/src/Classes/BaseCel.gd @@ -8,7 +8,7 @@ var image_texture: ImageTexture # Methods to Override: -# TODO L: Check if copying cels can use the content methods (Do during/after Linked Cel refactor) +# TODO Later: Check if copying cels can use the content methods (Do during/after Linked Cel refactor) # The content methods deal with the unique content of each cel type. For example, an Image for # PixelLayers, or a Dictionary of settings for a procedural layer type, and null for Groups. diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index 33bc5b256171..4f3f5f01f3bd 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -17,8 +17,8 @@ func is_a_parent_of(layer: BaseLayer) -> bool: return is_a_parent_of(layer.parent) return false -# TODO L: Consider going backwards in get_children functions, to allow breaking (test performance) -# TODO L: Consider combining these into one func with bool, and adding a get_child_count func +# TODO Later: Consider going backwards in get_children functions, to allow breaking (test performance) +# TODO L0: Consider combining these into one func with bool, and adding a get_child_count func func get_children_direct() -> Array: var children := [] for i in range(index): diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 632124056287..6ef1a996b2cf 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -47,7 +47,6 @@ var file_format: int = Export.FileFormat.PNG var was_exported := false var export_overwrite := false -# TODO L: Perhaps animation_tags could get a similar refactoring (In a later PR) var animation_tag_node = preload("res://src/UI/Timeline/AnimationTagUI.tscn") diff --git a/src/UI/Canvas/Selection.gd b/src/UI/Canvas/Selection.gd index 17aa0eae3042..a85e002516a6 100644 --- a/src/UI/Canvas/Selection.gd +++ b/src/UI/Canvas/Selection.gd @@ -71,7 +71,7 @@ func _ready() -> void: # gizmos.append(Gizmo.new(Gizmo.Type.ROTATE)) # Rotation gizmo (temp) -# TODO L: Can't move/resize a selection on a group cel (It just draws a new selection), maybe has to do with can_layer_get_drawn? +# TODO LAsk: Can't move/resize a selection on a group cel (It just draws a new selection), maybe has to do with can_layer_get_drawn? # This is a bug with the selection input in general, also happens with locked Pixel Layers. Ask Overloaded about it func _input(event: InputEvent) -> void: if is_moving_content: diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 4c56cfb5238c..f2d4f95848e3 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -38,7 +38,7 @@ func _ready() -> void: find_node("EndSpacer").size_flags_horizontal = SIZE_EXPAND_FILL timeline_scroll.size_flags_horizontal = SIZE_FILL -# TODO L: See if these two should be kept or done another way: +# TODO Later: See if these two should be kept or done another way: func _notification(what: int) -> void: if what == NOTIFICATION_DRAG_END: drag_highlight.hide() @@ -264,7 +264,7 @@ func delete_frames(frames := []) -> void: project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.commit_action() -# TODO L: Is there any point in frame here being a func parameter? Same with _on_DeleteFrame_presssed above (and maybe more) +# TODO L0: Is there any point in frame here being a func parameter? Same with _on_DeleteFrame_presssed above (and maybe more) func _on_CopyFrame_pressed(frame := -1) -> void: var frames := [] for cel in Global.current_project.selected_cels: @@ -743,8 +743,6 @@ func _on_MergeDownLayer_pressed() -> void: project.undo_redo.create_action("Merge Layer") for f in project.frames: - # TODO Later: top_image here doesn't really need to be a copy if there isn't layer transparency - # though this probably will be rewriten with blend modes anyway... var top_image := Image.new() top_image.copy_from(f.cels[top_layer.index].image) diff --git a/src/UI/Timeline/CelButton.gd b/src/UI/Timeline/CelButton.gd index 0c6a6f8499b8..c831ba9c9255 100644 --- a/src/UI/Timeline/CelButton.gd +++ b/src/UI/Timeline/CelButton.gd @@ -181,7 +181,7 @@ func can_drop_data(_pos, data) -> bool: if typeof(data) == TYPE_ARRAY and data[0] == "Cel": var drag_frame = data[1] var drag_layer = data[2] - # TODO L: Is this part really right? Should't it only matter if they're linked, and we're changing layers? + # TODO Later: Is this part really right? Should't it only matter if they're linked, and we're changing layers? # It would need to add linked cel logic to project move/swap_cel though # I THINK I WILL CHANGE THIS WITH FUTURE LINKED CEL UPDATE (might not need move/swap_cel logic) # If the cel we're dragging or the cel we are targeting are linked, don't allow dragging @@ -192,7 +192,7 @@ func can_drop_data(_pos, data) -> bool: in Global.current_project.layers[drag_layer].linked_cels ) ): - # TODO L: This may be able to be combined with the previous condition depending on the the last TODO + # TODO Later: This may be able to be combined with the previous condition depending on the the last TODO if not (drag_frame == frame and drag_layer == layer): var region: Rect2 if Input.is_action_pressed("ctrl") or layer != drag_layer: # Swap cels diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index fe3f7d13aab4..cdd05aa5ae4c 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -143,8 +143,6 @@ func _save_layer_name(new_name: String) -> void: func _on_ExpandButton_pressed(): - # TODO L: What should happen when the current_layer or selected_cels are children of a layer you collapse? - # Should the current_layer/selection move to ones aren't collapsed? Maybe add to github list of possible later changes Global.current_project.layers[layer].expanded = !Global.current_project.layers[layer].expanded _update_buttons_all_layers() @@ -256,7 +254,7 @@ func can_drop_data(_pos, data) -> bool: func drop_data(_pos, data) -> void: var drop_layer: int = data[1] - var project = Global.current_project # TODO L: perhaps having a project variable for the enitre class would be nice (also for cel/frame buttons) + var project = Global.current_project project.undo_redo.create_action("Change Layer Order") var layers: Array = project.layers # This shouldn't be modified directly From 159ef742658514dde2353cce3410bf940124f221 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 17 Sep 2022 12:11:26 -0400 Subject: [PATCH 132/154] Removed a loop that would never run from open_image_as_spritesheet_tab --- src/Autoload/OpenSave.gd | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index 9027da127136..cef45aeab28c 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -427,16 +427,7 @@ func open_image_as_spritesheet_tab(path: String, image: Image, horiz: int, vert: project.size = cropped_image.get_size() cropped_image.convert(Image.FORMAT_RGBA8) frame.cels.append(PixelCel.new(cropped_image, 1)) - - # TODO L0: This for loop doesn't need to exist (its adding cels to layers that never exist): -# for _i in range(1, project.layers.size()): -# var empty_sprite := Image.new() -# empty_sprite.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8) -# empty_sprite.fill(Color(0, 0, 0, 0)) -# frame.cels.append(PixelCel.new(empty_sprite, 1)) - project.frames.append(frame) - set_new_imported_tab(project, path) From a03d9ff314210682a783751a3b57cdd1b4cf29ca Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 17 Sep 2022 12:14:19 -0400 Subject: [PATCH 133/154] TODO update --- src/Autoload/OpenSave.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index cef45aeab28c..d82d7e1a74bf 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -459,7 +459,7 @@ func open_image_as_spritesheet_layer( var frame_indices: Array if new_frames_size > project.frames.size(): var required_frames = new_frames_size - project.frames.size() - # TODO L0: Is adding the new frames starting after the current frame right? (Maybe its better to start after the last frame) + # TODO LAsk: Is adding the new frames starting after the current frame right? (Maybe its better to start after the last frame) frame_indices= range(project.current_frame + 1, project.current_frame + required_frames + 1) for i in required_frames: var new_frame := Frame.new() From 4ca7b731de38063c673846f85ccd3d3b39144a6e Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 17 Sep 2022 12:28:15 -0400 Subject: [PATCH 134/154] Combined BaseLayer.get_children_direct and get_children_recursive into a single get_children method with a bool for recursive. Added a get_child_count method --- src/Classes/BaseLayer.gd | 33 ++++++++++++++++++---------- src/Classes/Project.gd | 2 +- src/UI/Timeline/AnimationTimeline.gd | 6 ++--- src/UI/Timeline/LayerButton.gd | 8 +++---- 4 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index 4f3f5f01f3bd..af1822a6f6db 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -17,22 +17,31 @@ func is_a_parent_of(layer: BaseLayer) -> bool: return is_a_parent_of(layer.parent) return false -# TODO Later: Consider going backwards in get_children functions, to allow breaking (test performance) -# TODO L0: Consider combining these into one func with bool, and adding a get_child_count func -func get_children_direct() -> Array: +# TODO Later: Consider going backwards in get_children function, to allow breaking (test performance) +func get_children(recursive: bool) -> Array: var children := [] - for i in range(index): - if project.layers[i].parent == self: - children.append(project.layers[i]) + if recursive: + for i in index: + if is_a_parent_of(project.layers[i]): + children.append(project.layers[i]) + else: + for i in index: + if project.layers[i].parent == self: + children.append(project.layers[i]) return children -func get_children_recursive() -> Array: - var children := [] - for i in range(index): - if is_a_parent_of(project.layers[i]): - children.append(project.layers[i]) - return children +func get_child_count(recursive: bool) -> int: + var count := 0 + if recursive: + for i in index: + if is_a_parent_of(project.layers[i]): + count += 1 + else: + for i in index: + if project.layers[i].parent == self: + count += 1 + return count func has_children() -> bool: diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 6ef1a996b2cf..3fdce632b300 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -513,7 +513,7 @@ func toggle_frame_buttons() -> void: func toggle_layer_buttons() -> void: if layers.empty() or current_layer >= layers.size(): return - var child_count: int = layers[current_layer].get_children_recursive().size() + var child_count: int = layers[current_layer].get_child_count(true) Global.disable_button(Global.remove_layer_button, layers[current_layer].is_locked_in_hierarchy() diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index f2d4f95848e3..f484689d3cd8 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -620,7 +620,7 @@ func _on_AddGroup_pressed() -> void: func _on_CloneLayer_pressed() -> void: var project: Project = Global.current_project - var source_layers: Array = project.layers[project.current_layer].get_children_recursive() + var source_layers: Array = project.layers[project.current_layer].get_children(true) source_layers.append(project.layers[project.current_layer]) var clones := [] # Array of Layers @@ -656,7 +656,7 @@ func _on_RemoveLayer_pressed() -> void: if project.layers.size() == 1: return - var layers: Array = project.layers[project.current_layer].get_children_recursive() + var layers: Array = project.layers[project.current_layer].get_children(true) layers.append(project.layers[project.current_layer]) var indices := [] for l in layers: @@ -683,7 +683,7 @@ func _on_RemoveLayer_pressed() -> void: func change_layer_order(up: bool) -> void: var project: Project = Global.current_project var layer: BaseLayer = project.layers[project.current_layer] - var child_count = layer.get_children_recursive().size() + var child_count = layer.get_child_count(true) var from_indices := range(layer.index - child_count, layer.index + 1) var from_parents := [] for l in from_indices: diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index cdd05aa5ae4c..46a16c13394a 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -191,7 +191,7 @@ func _select_current_layer() -> void: func get_drag_data(_position) -> Array: # TODO H1: If keeping this new multi layer drag design, layers here can be reutrned in the array # instead of layer... - var layers := range(layer - Global.current_project.layers[layer].get_children_recursive().size(), layer + 1) + var layers := range(layer - Global.current_project.layers[layer].get_child_count(true), layer + 1) var box := VBoxContainer.new() for i in layers.size(): @@ -259,7 +259,7 @@ func drop_data(_pos, data) -> void: project.undo_redo.create_action("Change Layer Order") var layers: Array = project.layers # This shouldn't be modified directly - var drop_from_indices := range(drop_layer - layers[drop_layer].get_children_recursive().size(), drop_layer + 1 ) + var drop_from_indices := range(drop_layer - layers[drop_layer].get_child_count(true), drop_layer + 1 ) var drop_from_parents := [] for i in range(drop_from_indices.size()): @@ -268,7 +268,7 @@ func drop_data(_pos, data) -> void: if Input.is_action_pressed("ctrl"): # Swap layers # a and b both need "from", "to", and "to_parents" # a is this layer (and children), b is the dropped layers - var a := { "from": range(layer - layers[layer].get_children_recursive().size(), layer + 1) } + var a := { "from": range(layer - layers[layer].get_child_count(true), layer + 1) } var b := { "from": drop_from_indices} if a.from[0] < b.from[0]: @@ -314,7 +314,7 @@ func drop_data(_pos, data) -> void: else: # Place under the layer, if it has children, place after its lowest child if layers[layer].has_children(): - to_index = layers[layer].get_children_recursive()[0].index + to_index = layers[layer].get_children(true)[0].index if layers[layer].is_a_parent_of(layers[drop_layer]): to_index += drop_from_indices.size() From 6348ee24f7b1e48bc2e9eadb2babe57d7ed68125 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 17 Sep 2022 12:58:28 -0400 Subject: [PATCH 135/154] Removed unneeded frame paramaters from _on_DeleteFrame_pressed and _on_CopyFrame_pressed --- src/UI/Timeline/AnimationTimeline.gd | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index f484689d3cd8..d105578f43f0 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -180,10 +180,10 @@ func add_frame() -> void: project.undo_redo.commit_action() -func _on_DeleteFrame_pressed(frame := -1) -> void: +func _on_DeleteFrame_pressed() -> void: var frames := [] for cel in Global.current_project.selected_cels: - frame = cel[0] + var frame: int = cel[0] if not frame in frames: frames.append(frame) frames.sort() @@ -264,11 +264,11 @@ func delete_frames(frames := []) -> void: project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.commit_action() -# TODO L0: Is there any point in frame here being a func parameter? Same with _on_DeleteFrame_presssed above (and maybe more) -func _on_CopyFrame_pressed(frame := -1) -> void: + +func _on_CopyFrame_pressed() -> void: var frames := [] for cel in Global.current_project.selected_cels: - frame = cel[0] + var frame: int = cel[0] if not frame in frames: frames.append(frame) frames.sort() From 470c212478a16ba7e4c5f7c619ff7f007832875a Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 17 Sep 2022 13:17:24 -0400 Subject: [PATCH 136/154] TODO Updates --- src/Autoload/OpenSave.gd | 2 +- src/Classes/Project.gd | 2 +- src/UI/Timeline/LayerButton.gd | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index d82d7e1a74bf..850a959d7cb7 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -489,7 +489,7 @@ func open_image_as_spritesheet_layer( else: cels.append(layer.new_empty_cel()) - # TODO L0: Maybe this is the better undo/redo order (As sometimes the do and undo steps can't be in the same order like here), should everything be made consistent with this? + # TODO Later: Maybe this is the better undo/redo order (As sometimes the do and undo steps can't be in the same order like here), should everything be made consistent with this? project.undo_redo.add_do_property(project, "current_frame", new_frames_size - 1) project.undo_redo.add_do_property(project, "current_layer", project.layers.size()) project.undo_redo.add_do_method(project, "add_frames", frames, frame_indices) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 3fdce632b300..1725d40b0f56 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -406,7 +406,7 @@ func deserialize(dict: Dictionary) -> void: fps = dict.fps _deserialize_metadata(self, dict) -# TODO H1: Consider how these are used: +# TODO LAask: Consider how these are used: func _serialize_metadata(object: Object) -> Dictionary: var metadata := {} for meta in object.get_meta_list(): diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index 46a16c13394a..712676d5c0e7 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -189,7 +189,7 @@ func _select_current_layer() -> void: func get_drag_data(_position) -> Array: - # TODO H1: If keeping this new multi layer drag design, layers here can be reutrned in the array + # TODO Later: If keeping this new multi layer drag design, layers here can be reutrned in the array # instead of layer... var layers := range(layer - Global.current_project.layers[layer].get_child_count(true), layer + 1) From ea8bca0bb678001084b2ac88e7b3559cfcd403e0 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 17 Sep 2022 13:26:56 -0400 Subject: [PATCH 137/154] Removed unneeded code from delete_frames --- src/UI/Timeline/AnimationTimeline.gd | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index d105578f43f0..ca2092c1da4d 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -200,8 +200,7 @@ func delete_frames(frames := []) -> void: elif frames.size() == 0: frames.append(project.current_frame) - var new_frames: Array = project.frames.duplicate() # TODO H: Is new_frames here still REALLY being used? - var current_frame := project.current_frame + var current_frame: int = min(project.current_frame, project.frames.size() - frames.size() - 1) var new_layers: Array = project.duplicate_layers() var frame_correction := 0 # Only needed for tag adjustment @@ -217,11 +216,6 @@ func delete_frames(frames := []) -> void: ) for frame in frames: - var frame_to_delete: Frame = project.frames[frame] - new_frames.erase(frame_to_delete) - if current_frame > 0 && current_frame == new_frames.size(): # If it's the last frame - current_frame -= 1 - # Check if one of the cels of the frame is linked # if they are, unlink them too # this prevents removed cels being kept in linked memory From 762eb5d08ba21612535982c4d0876141fe9ac3fa Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 17 Sep 2022 13:38:36 -0400 Subject: [PATCH 138/154] Made delete_frames variable names more consistent with my other changes --- src/UI/Timeline/AnimationTimeline.gd | 32 +++++++++++++--------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index ca2092c1da4d..b21fbfc1b028 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -190,18 +190,19 @@ func _on_DeleteFrame_pressed() -> void: delete_frames(frames) -func delete_frames(frames := []) -> void: +func delete_frames(indices := []) -> void: var project: Project = Global.current_project if project.frames.size() == 1: return - if frames.size() == project.frames.size(): - frames.remove(frames.size() - 1) # Ensure the project has at least 1 frame - elif frames.size() == 0: - frames.append(project.current_frame) + if indices.size() == project.frames.size(): + indices.remove(indices.size() - 1) # Ensure the project has at least 1 frame + elif indices.size() == 0: + indices.append(project.current_frame) - var current_frame: int = min(project.current_frame, project.frames.size() - frames.size() - 1) + var current_frame: int = min(project.current_frame, project.frames.size() - indices.size() - 1) var new_layers: Array = project.duplicate_layers() + var frames := [] var frame_correction := 0 # Only needed for tag adjustment var new_animation_tags := project.animation_tags.duplicate() @@ -215,41 +216,38 @@ func delete_frames(frames := []) -> void: new_animation_tags[i].to ) - for frame in frames: + for f in indices: + frames.append(project.frames[f]) # Check if one of the cels of the frame is linked # if they are, unlink them too # this prevents removed cels being kept in linked memory for layer in new_layers: for linked in layer.linked_cels: - if linked == project.frames[frame]: + if linked == project.frames[f]: layer.linked_cels.erase(linked) # Loop through the tags to see if the frame is in one - frame -= frame_correction # Erasing made frames indexes 1 step ahead their intended tags + f -= frame_correction # Erasing made frames indexes 1 step ahead their intended tags var tag_correction := 0 # needed when tag is erased for tag_ind in new_animation_tags.size(): var tag = new_animation_tags[tag_ind - tag_correction] - if frame + 1 >= tag.from && frame + 1 <= tag.to: + if f + 1 >= tag.from && f + 1 <= tag.to: if tag.from == tag.to: # If we're deleting the only frame in the tag new_animation_tags.erase(tag) tag_correction += 1 else: tag.to -= 1 - elif frame + 1 < tag.from: + elif f + 1 < tag.from: tag.from -= 1 tag.to -= 1 frame_correction += 1 # Compensation for the next batch - var frame_refs := [] - for f in frames: - frame_refs.append(project.frames[f]) - project.undos += 1 project.undo_redo.create_action("Remove Frame") project.undo_redo.add_do_property(project, "layers", new_layers) project.undo_redo.add_undo_property(project, "layers", Global.current_project.layers) - project.undo_redo.add_do_method(project, "remove_frames", frames) - project.undo_redo.add_undo_method(project, "add_frames", frame_refs, frames) + project.undo_redo.add_do_method(project, "remove_frames", indices) + project.undo_redo.add_undo_method(project, "add_frames", frames, indices) project.undo_redo.add_do_property(project, "animation_tags", new_animation_tags) project.undo_redo.add_undo_property(project, "animation_tags", project.animation_tags) project.undo_redo.add_do_property(project, "current_frame", current_frame) From 01a9346023d9b481fd451798b2979ff7c04c4d27 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 17 Sep 2022 13:42:57 -0400 Subject: [PATCH 139/154] Continuation --- src/UI/Timeline/AnimationTimeline.gd | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index b21fbfc1b028..50577258ca9e 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -181,13 +181,13 @@ func add_frame() -> void: func _on_DeleteFrame_pressed() -> void: - var frames := [] + var indices := [] for cel in Global.current_project.selected_cels: var frame: int = cel[0] - if not frame in frames: - frames.append(frame) - frames.sort() - delete_frames(frames) + if not frame in indices: + indices.append(frame) + indices.sort() + delete_frames(indices) func delete_frames(indices := []) -> void: From 9a93751e82a9a9e7e46a4db73fca9f40e60e492c Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 17 Sep 2022 13:47:08 -0400 Subject: [PATCH 140/154] made variable names in copy_frames more consistent with rest of changes --- src/UI/Timeline/AnimationTimeline.gd | 40 ++++++++++++++-------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 50577258ca9e..7b8c251c3177 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -183,9 +183,9 @@ func add_frame() -> void: func _on_DeleteFrame_pressed() -> void: var indices := [] for cel in Global.current_project.selected_cels: - var frame: int = cel[0] - if not frame in indices: - indices.append(frame) + var f: int = cel[0] + if not f in indices: + indices.append(f) indices.sort() delete_frames(indices) @@ -258,24 +258,24 @@ func delete_frames(indices := []) -> void: func _on_CopyFrame_pressed() -> void: - var frames := [] + var indices := [] for cel in Global.current_project.selected_cels: - var frame: int = cel[0] - if not frame in frames: - frames.append(frame) - frames.sort() - copy_frames(frames) + var f: int = cel[0] + if not f in indices: + indices.append(f) + indices.sort() + copy_frames(indices) -func copy_frames(frames := []) -> void: +func copy_frames(indices := []) -> void: var project: Project = Global.current_project - if frames.size() == 0: - frames.append(project.current_frame) + if indices.size() == 0: + indices.append(project.current_frame) var new_layers: Array = project.duplicate_layers() var copied_frames := [] - var copied_indices := range(frames[-1] + 1, frames[-1] + 1 + frames.size()) + var copied_indices := range(indices[-1] + 1, indices[-1] + 1 + indices.size()) var new_animation_tags := project.animation_tags.duplicate() # Loop through the tags to create new classes for them, so that they won't be the same @@ -288,11 +288,11 @@ func copy_frames(frames := []) -> void: new_animation_tags[i].to ) - for frame in frames: + for f in indices: var new_frame := Frame.new() copied_frames.append(new_frame) - var prev_frame: Frame = project.frames[frame] + var prev_frame: Frame = project.frames[f] new_frame.duration = prev_frame.duration for l_i in range(new_layers.size()): @@ -300,7 +300,7 @@ func copy_frames(frames := []) -> void: var new_cels_linked := true if new_layers[l_i].get("new_cels_linked") else false # Copy the cel, create new cel content if new cels aren't linked - new_frame.cels.append(new_layers[l_i].copy_cel(frame, new_cels_linked)) + new_frame.cels.append(new_layers[l_i].copy_cel(f, new_cels_linked)) if new_cels_linked: # If the link button is pressed new_layers[l_i].linked_cels.append(new_frame) @@ -309,9 +309,9 @@ func copy_frames(frames := []) -> void: # Loop through the tags to see if the frame is in one for tag in new_animation_tags: - if frames[-1] + 1 >= tag.from && frames[-1] + 1 <= tag.to: + if indices[-1] + 1 >= tag.from && indices[-1] + 1 <= tag.to: tag.to += 1 - elif frames[-1] + 1 < tag.from: + elif indices[-1] + 1 < tag.from: tag.from += 1 tag.to += 1 @@ -323,8 +323,8 @@ func copy_frames(frames := []) -> void: project.undo_redo.add_undo_property(project, "layers", project.layers) project.undo_redo.add_do_method(project, "add_frames", copied_frames, copied_indices) project.undo_redo.add_undo_method(project, "remove_frames", copied_indices) - project.undo_redo.add_do_property(project, "current_frame", frames[-1] + 1) - project.undo_redo.add_undo_property(project, "current_frame", frames[-1]) + project.undo_redo.add_do_property(project, "current_frame", indices[-1] + 1) + project.undo_redo.add_undo_property(project, "current_frame", indices[-1]) project.undo_redo.add_do_property(project, "animation_tags", new_animation_tags) project.undo_redo.add_undo_property(project, "animation_tags", project.animation_tags) project.undo_redo.commit_action() From a55b02c3699437c7b8f68044c5b9dd70574e6d10 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 17 Sep 2022 13:56:30 -0400 Subject: [PATCH 141/154] Update TODOs --- src/Classes/BaseLayer.gd | 2 +- src/Classes/Project.gd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index af1822a6f6db..29f40f380b1e 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -82,7 +82,7 @@ func get_layer_path() -> String: # Methods to Override: func serialize() -> Dictionary: - assert(index == project.layers.find(self)) # TODO H2: remove once sure index is synced properly + assert(index == project.layers.find(self)) # TODO Lask: remove once sure index is synced properly return { "name": name, "visible": visible, diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 1725d40b0f56..033521dbdb12 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -673,7 +673,7 @@ func move_frame(from_index: int, to_index: int) -> void: Global.canvas.selection.transform_content_confirm() selected_cels.clear() var frame = frames[from_index] - frames.remove(from_index) # TODO: Maybe the insert(pop_at) trick will work here? + frames.remove(from_index) Global.animation_timeline.project_frame_removed(from_index) frames.insert(to_index, frame) Global.animation_timeline.project_frame_added(to_index) From 4e3ea147614bf4c62d4fc84f2d62e20d405224ca Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 17 Sep 2022 14:22:03 -0400 Subject: [PATCH 142/154] Removed TODOs for after this PR (moved to my notes) --- src/Autoload/OpenSave.gd | 2 -- src/Classes/BaseCel.gd | 2 -- src/Classes/BaseLayer.gd | 4 ++-- src/Classes/Project.gd | 2 +- src/UI/Canvas/Selection.gd | 2 -- src/UI/Timeline/CelButton.gd | 5 ----- src/UI/Timeline/LayerButton.gd | 2 -- 7 files changed, 3 insertions(+), 16 deletions(-) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index 850a959d7cb7..acb861f3d1eb 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -459,7 +459,6 @@ func open_image_as_spritesheet_layer( var frame_indices: Array if new_frames_size > project.frames.size(): var required_frames = new_frames_size - project.frames.size() - # TODO LAsk: Is adding the new frames starting after the current frame right? (Maybe its better to start after the last frame) frame_indices= range(project.current_frame + 1, project.current_frame + required_frames + 1) for i in required_frames: var new_frame := Frame.new() @@ -489,7 +488,6 @@ func open_image_as_spritesheet_layer( else: cels.append(layer.new_empty_cel()) - # TODO Later: Maybe this is the better undo/redo order (As sometimes the do and undo steps can't be in the same order like here), should everything be made consistent with this? project.undo_redo.add_do_property(project, "current_frame", new_frames_size - 1) project.undo_redo.add_do_property(project, "current_layer", project.layers.size()) project.undo_redo.add_do_method(project, "add_frames", frames, frame_indices) diff --git a/src/Classes/BaseCel.gd b/src/Classes/BaseCel.gd index 66eb1a596455..cd5390524965 100644 --- a/src/Classes/BaseCel.gd +++ b/src/Classes/BaseCel.gd @@ -8,8 +8,6 @@ var image_texture: ImageTexture # Methods to Override: -# TODO Later: Check if copying cels can use the content methods (Do during/after Linked Cel refactor) - # The content methods deal with the unique content of each cel type. For example, an Image for # PixelLayers, or a Dictionary of settings for a procedural layer type, and null for Groups. # Can be used fo linking/unlinking cels, copying, and deleting content diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index 29f40f380b1e..b340a107cfc9 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -17,7 +17,7 @@ func is_a_parent_of(layer: BaseLayer) -> bool: return is_a_parent_of(layer.parent) return false -# TODO Later: Consider going backwards in get_children function, to allow breaking (test performance) + func get_children(recursive: bool) -> Array: var children := [] if recursive: @@ -82,7 +82,7 @@ func get_layer_path() -> String: # Methods to Override: func serialize() -> Dictionary: - assert(index == project.layers.find(self)) # TODO Lask: remove once sure index is synced properly + assert(index == project.layers.find(self)) return { "name": name, "visible": visible, diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 033521dbdb12..8e7db2a8c267 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -406,7 +406,7 @@ func deserialize(dict: Dictionary) -> void: fps = dict.fps _deserialize_metadata(self, dict) -# TODO LAask: Consider how these are used: + func _serialize_metadata(object: Object) -> Dictionary: var metadata := {} for meta in object.get_meta_list(): diff --git a/src/UI/Canvas/Selection.gd b/src/UI/Canvas/Selection.gd index a85e002516a6..1d39f117300c 100644 --- a/src/UI/Canvas/Selection.gd +++ b/src/UI/Canvas/Selection.gd @@ -71,8 +71,6 @@ func _ready() -> void: # gizmos.append(Gizmo.new(Gizmo.Type.ROTATE)) # Rotation gizmo (temp) -# TODO LAsk: Can't move/resize a selection on a group cel (It just draws a new selection), maybe has to do with can_layer_get_drawn? -# This is a bug with the selection input in general, also happens with locked Pixel Layers. Ask Overloaded about it func _input(event: InputEvent) -> void: if is_moving_content: if Input.is_action_just_pressed("transformation_confirm"): diff --git a/src/UI/Timeline/CelButton.gd b/src/UI/Timeline/CelButton.gd index c831ba9c9255..f0c4564b7e95 100644 --- a/src/UI/Timeline/CelButton.gd +++ b/src/UI/Timeline/CelButton.gd @@ -181,10 +181,6 @@ func can_drop_data(_pos, data) -> bool: if typeof(data) == TYPE_ARRAY and data[0] == "Cel": var drag_frame = data[1] var drag_layer = data[2] - # TODO Later: Is this part really right? Should't it only matter if they're linked, and we're changing layers? - # It would need to add linked cel logic to project move/swap_cel though - # I THINK I WILL CHANGE THIS WITH FUTURE LINKED CEL UPDATE (might not need move/swap_cel logic) - # If the cel we're dragging or the cel we are targeting are linked, don't allow dragging if Global.current_project.layers[layer] is GroupLayer or not ( Global.current_project.frames[frame] in Global.current_project.layers[layer].linked_cels or ( @@ -192,7 +188,6 @@ func can_drop_data(_pos, data) -> bool: in Global.current_project.layers[drag_layer].linked_cels ) ): - # TODO Later: This may be able to be combined with the previous condition depending on the the last TODO if not (drag_frame == frame and drag_layer == layer): var region: Rect2 if Input.is_action_pressed("ctrl") or layer != drag_layer: # Swap cels diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index 712676d5c0e7..7b5d8c8bc0c9 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -189,8 +189,6 @@ func _select_current_layer() -> void: func get_drag_data(_position) -> Array: - # TODO Later: If keeping this new multi layer drag design, layers here can be reutrned in the array - # instead of layer... var layers := range(layer - Global.current_project.layers[layer].get_child_count(true), layer + 1) var box := VBoxContainer.new() From ca68feb46861b948efb6c82a7b02adcfae4dfab9 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 17 Sep 2022 14:23:52 -0400 Subject: [PATCH 143/154] Fixed crash when pasting image on Group --- src/UI/Canvas/Selection.gd | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/UI/Canvas/Selection.gd b/src/UI/Canvas/Selection.gd index 1d39f117300c..6a702b45de97 100644 --- a/src/UI/Canvas/Selection.gd +++ b/src/UI/Canvas/Selection.gd @@ -642,8 +642,9 @@ func _get_selected_draw_images() -> Array: # Array of Images var images := [] var project: Project = Global.current_project for cel_index in project.selected_cels: - # TODO: Figure this out (Issue when pasting selection to group cel) - var cel: PixelCel = project.frames[cel_index[0]].cels[cel_index[1]] + var cel: BaseCel = project.frames[cel_index[0]].cels[cel_index[1]] + if not cel is PixelCel: + continue if project.layers[cel_index[1]].can_layer_get_drawn(): images.append(cel.image) return images From b2ee8e3c95d5dc68234f6e2cb946c5e242d3ae38 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 17 Sep 2022 14:29:18 -0400 Subject: [PATCH 144/154] Fixed layer .visible check to be is_visible_in_hierarchy() --- src/Autoload/Export.gd | 2 +- src/Classes/BaseLayer.gd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Autoload/Export.gd b/src/Autoload/Export.gd index 604d97bcb4de..92ada952ed04 100644 --- a/src/Autoload/Export.gd +++ b/src/Autoload/Export.gd @@ -411,7 +411,7 @@ func blend_selected_cels(image: Image, frame: Frame, origin: Vector2 = Vector2(0 var cel: PixelCel = frame.cels[cel_ind] - if Global.current_project.layers[layer_i].visible: + if Global.current_project.layers[layer_i].is_visible_in_hierarchy(): var cel_image := Image.new() cel_image.copy_from(cel.image) cel_image.lock() diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index b340a107cfc9..8bbed5747faf 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -55,7 +55,7 @@ func is_expanded_in_hierarchy() -> bool: return parent.expanded and parent.is_expanded_in_hierarchy() return true -# TODO H2: Search for layer visbility/locked checks that should be changed to the hierarchy ones: + func is_visible_in_hierarchy() -> bool: if is_instance_valid(parent) and visible: return parent.is_visible_in_hierarchy() From 553a9ef904dab70a6c3f2ccdf773d7d7912bfa20 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 17 Sep 2022 14:34:06 -0400 Subject: [PATCH 145/154] Removed some drag highlight polish code that didn't work --- src/UI/Timeline/AnimationTimeline.gd | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 7b8c251c3177..eacf36e03759 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -38,16 +38,11 @@ func _ready() -> void: find_node("EndSpacer").size_flags_horizontal = SIZE_EXPAND_FILL timeline_scroll.size_flags_horizontal = SIZE_FILL -# TODO Later: See if these two should be kept or done another way: + func _notification(what: int) -> void: if what == NOTIFICATION_DRAG_END: drag_highlight.hide() -func can_drop_data(_position, _data) -> bool: - drag_highlight.hide() - print ("can drag?") - return false - func _input(event: InputEvent) -> void: var mouse_pos := get_global_mouse_position() From 97c5e6a818cdd09d45426412244bd86e94106f19 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 17 Sep 2022 14:35:21 -0400 Subject: [PATCH 146/154] Removed code from Canvas update_texture and update_selected_cels_textures that was redundant --- src/UI/Canvas/Canvas.gd | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/UI/Canvas/Canvas.gd b/src/UI/Canvas/Canvas.gd index 0a47a466df26..75c593d56208 100644 --- a/src/UI/Canvas/Canvas.gd +++ b/src/UI/Canvas/Canvas.gd @@ -126,15 +126,6 @@ func update_texture(layer_i: int, frame_i := -1, project: Project = Global.curre var current_cel: BaseCel = project.frames[frame_i].cels[layer_i] current_cel.update_texture() - # TODO H2: is this even needed? (Same as below) -# if project == Global.current_project: -# var container_index = Global.frames_container.get_child_count() - 1 - layer_i -# var layer_cel_container = Global.frames_container.get_child(container_index) -# var cel_button = layer_cel_container.get_child(frame_i) -# var cel_texture_rect: TextureRect -# cel_texture_rect = cel_button.find_node("CelTexture") -# cel_texture_rect.texture = current_cel.image_texture - func update_selected_cels_textures(project: Project = Global.current_project) -> void: for cel_index in project.selected_cels: @@ -144,14 +135,6 @@ func update_selected_cels_textures(project: Project = Global.current_project) -> var current_cel: BaseCel = project.frames[frame_index].cels[layer_index] current_cel.update_texture() - # TODO H2: This wasn't working anymore, but is it even needed? (Same as above) -# if project == Global.current_project: -# var container_index = Global.frames_container.get_child_count() - 1 - layer_index -# var layer_cel_container = Global.frames_container.get_child(container_index) -# var cel_button = layer_cel_container.get_child(frame_index) -# var cel_texture_rect: TextureRect = cel_button.find_node("CelTexture") -# cel_texture_rect.texture = current_cel.image_texture - func refresh_onion() -> void: $OnionPast.update() From 14db33955939bd77c68f1f99d4fcbf7821cdb6d4 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 17 Sep 2022 14:42:32 -0400 Subject: [PATCH 147/154] gdformat --- src/Autoload/OpenSave.gd | 15 ++++++----- src/Classes/BaseCel.gd | 2 ++ src/Classes/BaseLayer.gd | 4 +++ src/Classes/GroupCel.gd | 5 +++- src/Classes/GroupLayer.gd | 3 +++ src/Classes/PixelCel.gd | 7 +++-- src/Classes/PixelLayer.gd | 2 ++ src/Classes/Project.gd | 54 ++++++++++++++++++++------------------- 8 files changed, 57 insertions(+), 35 deletions(-) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index acb861f3d1eb..e6966cc64e4f 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -194,7 +194,7 @@ func open_old_pxo_file(file: File, new_project: Project, first_line: String) -> if file_major_version >= 0 and file_minor_version > 6: var global_layer_line := file.get_line() while global_layer_line == ".": - var layer_dict:= { + var layer_dict := { "name": file.get_line(), "visible": file.get_8(), "locked": file.get_8(), @@ -434,7 +434,6 @@ func open_image_as_spritesheet_tab(path: String, image: Image, horiz: int, vert: func open_image_as_spritesheet_layer( _path: String, image: Image, file_name: String, horizontal: int, vertical: int, start_frame: int ) -> void: - # Data needed to slice images horizontal = min(horizontal, image.get_size().x) vertical = min(vertical, image.get_size().y) @@ -451,22 +450,26 @@ func open_image_as_spritesheet_layer( # Initialize undo mechanism project.undos += 1 project.undo_redo.create_action("Add Spritesheet Layer") - var new_layers: Array = project.layers.duplicate() # Used for updating linked_cels lists + var new_layers: Array = project.layers.duplicate() # Used for updating linked_cels lists # Create new frames (if needed) - var new_frames_size = max(project.frames.size(), (start_frame + (vertical * horizontal))) + var new_frames_size = max(project.frames.size(), start_frame + (vertical * horizontal)) var frames := [] var frame_indices: Array if new_frames_size > project.frames.size(): var required_frames = new_frames_size - project.frames.size() - frame_indices= range(project.current_frame + 1, project.current_frame + required_frames + 1) + frame_indices = range( + project.current_frame + 1, project.current_frame + required_frames + 1 + ) for i in required_frames: var new_frame := Frame.new() for l_i in range(project.layers.size()): # Create as many cels as there are layers new_frame.cels.append(project.layers[l_i].new_empty_cel()) if new_layers[l_i].get("new_cels_linked"): new_layers[l_i].linked_cels.append(new_frame) - new_frame.cels[l_i].set_content(new_layers[l_i].linked_cels[0].cels[l_i].get_content()) + new_frame.cels[l_i].set_content( + new_layers[l_i].linked_cels[0].cels[l_i].get_content() + ) new_frame.cels[l_i].image_texture = new_layers[l_i].linked_cels[0].cels[l_i].image_texture frames.append(new_frame) diff --git a/src/Classes/BaseCel.gd b/src/Classes/BaseCel.gd index cd5390524965..4ab249fbb798 100644 --- a/src/Classes/BaseCel.gd +++ b/src/Classes/BaseCel.gd @@ -8,6 +8,7 @@ var image_texture: ImageTexture # Methods to Override: + # The content methods deal with the unique content of each cel type. For example, an Image for # PixelLayers, or a Dictionary of settings for a procedural layer type, and null for Groups. # Can be used fo linking/unlinking cels, copying, and deleting content @@ -24,6 +25,7 @@ func set_content(_content) -> void: func create_empty_content(): return [] + # Can be used for creating copy content for copying cels or unlinking cels func copy_content(): return [] diff --git a/src/Classes/BaseLayer.gd b/src/Classes/BaseLayer.gd index 8bbed5747faf..913d90e8aa38 100644 --- a/src/Classes/BaseLayer.gd +++ b/src/Classes/BaseLayer.gd @@ -9,6 +9,7 @@ var parent: BaseLayer var project var index: int + # Returns true if this is a direct or indirect parent of layer func is_a_parent_of(layer: BaseLayer) -> bool: if layer.parent == self: @@ -79,8 +80,10 @@ func get_layer_path() -> String: return str(parent.get_layer_path(), "/", name) return name + # Methods to Override: + func serialize() -> Dictionary: assert(index == project.layers.find(self)) return { @@ -114,6 +117,7 @@ func new_empty_cel() -> BaseCel: func copy_cel(_frame: int, _linked: bool) -> BaseCel: return null + # Used to copy all cels with cel linking properly set up between this set of copies: func copy_all_cels() -> Array: return [] diff --git a/src/Classes/GroupCel.gd b/src/Classes/GroupCel.gd index f5e1dde0308b..97be403e739d 100644 --- a/src/Classes/GroupCel.gd +++ b/src/Classes/GroupCel.gd @@ -3,6 +3,7 @@ extends BaseCel # A class for the properties of cels in GroupLayers. # The term "cel" comes from "celluloid" (https://en.wikipedia.org/wiki/Cel). + func _init(_opacity := 1.0) -> void: opacity = _opacity image_texture = ImageTexture.new() @@ -10,7 +11,9 @@ func _init(_opacity := 1.0) -> void: func get_image() -> Image: var image = Image.new() - image.create(Global.current_project.size.x, Global.current_project.size.y, false, Image.FORMAT_RGBA8) + image.create( + Global.current_project.size.x, Global.current_project.size.y, false, Image.FORMAT_RGBA8 + ) return image diff --git a/src/Classes/GroupLayer.gd b/src/Classes/GroupLayer.gd index 44fdfa059e24..82c7113c733e 100644 --- a/src/Classes/GroupLayer.gd +++ b/src/Classes/GroupLayer.gd @@ -4,12 +4,15 @@ extends BaseLayer var expanded := true + func _init(_project, _name := "") -> void: project = _project name = _name + # Overridden Methods: + func serialize() -> Dictionary: var data = .serialize() data["type"] = Global.LayerTypes.GROUP diff --git a/src/Classes/PixelCel.gd b/src/Classes/PixelCel.gd index eeb6a74f22a8..0af49acbfc40 100644 --- a/src/Classes/PixelCel.gd +++ b/src/Classes/PixelCel.gd @@ -6,12 +6,13 @@ extends BaseCel var image: Image setget image_changed + func _init(_image := Image.new(), _opacity := 1.0, _image_texture: ImageTexture = null) -> void: if _image_texture: image_texture = _image_texture else: image_texture = ImageTexture.new() - self.image = _image # Set image and call setter + self.image = _image # Set image and call setter opacity = _opacity @@ -38,7 +39,9 @@ func create_empty_content(): func copy_content(): var copy_image := Image.new() - copy_image.create_from_data(image.get_width(), image.get_height(), false, Image.FORMAT_RGBA8, image.get_data()) + copy_image.create_from_data( + image.get_width(), image.get_height(), false, Image.FORMAT_RGBA8, image.get_data() + ) return copy_image diff --git a/src/Classes/PixelLayer.gd b/src/Classes/PixelLayer.gd index 1f7cd2d72b84..41c4d7658688 100644 --- a/src/Classes/PixelLayer.gd +++ b/src/Classes/PixelLayer.gd @@ -5,6 +5,7 @@ extends BaseLayer var new_cels_linked := false var linked_cels := [] # Array of Frames + func _init(_project, _name := "") -> void: project = _project name = _name @@ -12,6 +13,7 @@ func _init(_project, _name := "") -> void: # Overridden Methods: + func serialize() -> Dictionary: var dict = .serialize() dict["type"] = Global.LayerTypes.PIXEL diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 8e7db2a8c267..d6f0fd253f0f 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -12,8 +12,8 @@ var has_changed := false setget _has_changed_changed # frames and layers Arrays should generally only be modified directly when # opening/creating a project. When modifiying the current project, use # the add/remove/move/swap_frames/layers methods -var frames := [] # Array of Frames (that contain Cels) -var layers := [] # Array of Layers +var frames := [] # Array of Frames (that contain Cels) +var layers := [] # Array of Layers var current_frame := 0 setget _frame_changed var current_layer := 0 setget _layer_changed var selected_cels := [[0, 0]] # Array of Arrays of 2 integers (frame & layer) @@ -465,9 +465,7 @@ func _frame_changed(value: int) -> void: var container_child_count: int = Global.frames_container.get_child_count() if layer < container_child_count: - var container = Global.frames_container.get_child( - container_child_count - 1 - layer - ) + var container = Global.frames_container.get_child(container_child_count - 1 - layer) if frame < container.get_child_count(): var cel_button = container.get_child(frame) cel_button.pressed = true @@ -515,19 +513,22 @@ func toggle_layer_buttons() -> void: return var child_count: int = layers[current_layer].get_child_count(true) - Global.disable_button(Global.remove_layer_button, - layers[current_layer].is_locked_in_hierarchy() - or layers.size() == child_count + 1 + Global.disable_button( + Global.remove_layer_button, + layers[current_layer].is_locked_in_hierarchy() or layers.size() == child_count + 1 ) Global.disable_button(Global.move_up_layer_button, current_layer == layers.size() - 1) - Global.disable_button(Global.move_down_layer_button, - current_layer == child_count - and not is_instance_valid(layers[current_layer].parent) + Global.disable_button( + Global.move_down_layer_button, + current_layer == child_count and not is_instance_valid(layers[current_layer].parent) ) - Global.disable_button(Global.merge_down_layer_button, - current_layer == child_count - or layers[current_layer] is GroupLayer - or layers[current_layer - 1] is GroupLayer + Global.disable_button( + Global.merge_down_layer_button, + ( + current_layer == child_count + or layers[current_layer] is GroupLayer + or layers[current_layer - 1] is GroupLayer + ) ) @@ -598,7 +599,7 @@ func duplicate_layers() -> Array: new_layers[i] = new_layers[i].copy() for l in new_layers: if is_instance_valid(l.parent): - l.parent = new_layers[l.parent.index] # Update the parent to the new copy of the parent + l.parent = new_layers[l.parent.index] # Update the parent to the new copy of the parent return new_layers @@ -630,6 +631,7 @@ func can_pixel_get_drawn( # UI, and updates indices. These are designed to be reversible, meaning that to undo an add, you # use remove, and vise versa. To undo a move or swap, use move or swap with the paramaters swapped. + func add_frames(new_frames: Array, indices: Array) -> void: # indices should be in ascending order Global.canvas.selection.transform_content_confirm() selected_cels.clear() @@ -748,12 +750,12 @@ func move_layers(from_indices: Array, to_indices: Array, to_parents: Array) -> v Global.canvas.selection.transform_content_confirm() selected_cels.clear() var removed_layers := [] - var removed_cels := [] # 2D array of cels (an array for each layer removed) + var removed_cels := [] # 2D array of cels (an array for each layer removed) for i in from_indices.size(): # With each removed index, future indices need to be lowered, so subtract by i removed_layers.append(layers.pop_at(from_indices[i] - i)) - removed_layers[i].parent = to_parents[i] # parents must be set before UI created in next loop + removed_layers[i].parent = to_parents[i] # parents must be set before UI created in next loop removed_cels.append([]) for frame in frames: removed_cels[i].append(frame.cels.pop_at(from_indices[i] - i)) @@ -781,12 +783,12 @@ func swap_layers(a: Dictionary, b: Dictionary) -> void: selected_cels.clear() var a_layers := [] var b_layers := [] - var a_cels := [] # 2D array of cels (an array for each layer removed) - var b_cels := [] # 2D array of cels (an array for each layer removed) + var a_cels := [] # 2D array of cels (an array for each layer removed) + var b_cels := [] # 2D array of cels (an array for each layer removed) for i in a.from.size(): a_layers.append(layers.pop_at(a.from[i] - i)) Global.animation_timeline.project_layer_removed(a.from[i] - i) - a_layers[i].parent = a.to_parents[i] # All parents must be set early, before creating buttons + a_layers[i].parent = a.to_parents[i] # All parents must be set early, before creating buttons a_cels.append([]) for frame in frames: a_cels[i].append(frame.cels.pop_at(a.from[i] - i)) @@ -794,7 +796,7 @@ func swap_layers(a: Dictionary, b: Dictionary) -> void: var index = (b.from[i] - i) if a.from[0] > b.from[0] else (b.from[i] - i - a.from.size()) b_layers.append(layers.pop_at(index)) Global.animation_timeline.project_layer_removed(index) - b_layers[i].parent = b.to_parents[i] # All parents must be set early, before creating buttons + b_layers[i].parent = b.to_parents[i] # All parents must be set early, before creating buttons b_cels.append([]) for frame in frames: b_cels[i].append(frame.cels.pop_at(index)) @@ -827,11 +829,11 @@ func move_cel(from_frame: int, to_frame: int, layer: int) -> void: selected_cels.clear() var cel: BaseCel = frames[from_frame].cels[layer] if from_frame < to_frame: - for f in range(from_frame, to_frame): # Forward range - frames[f].cels[layer] = frames[f + 1].cels[layer] # Move left + for f in range(from_frame, to_frame): # Forward range + frames[f].cels[layer] = frames[f + 1].cels[layer] # Move left else: - for f in range(from_frame, to_frame, -1): # Backward range - frames[f].cels[layer] = frames[f - 1].cels[layer] # Move right + for f in range(from_frame, to_frame, -1): # Backward range + frames[f].cels[layer] = frames[f - 1].cels[layer] # Move right frames[to_frame].cels[layer] = cel Global.animation_timeline.project_cel_removed(from_frame, layer) Global.animation_timeline.project_cel_added(to_frame, layer) From 1029dbf3a0d89eec7a7d8cd8bb26f70535284132 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 17 Sep 2022 15:10:39 -0400 Subject: [PATCH 148/154] gdformat --- src/UI/Canvas/CanvasPreview.gd | 5 +- src/UI/Canvas/CurrentFrameDrawer.gd | 5 +- src/UI/Canvas/Selection.gd | 1 + src/UI/Timeline/AnimationTimeline.gd | 58 ++++++++++++--------- src/UI/Timeline/CelButton.gd | 53 ++++++++++++------- src/UI/Timeline/FrameButton.gd | 14 ++--- src/UI/Timeline/LayerButton.gd | 76 ++++++++++++++++------------ 7 files changed, 130 insertions(+), 82 deletions(-) diff --git a/src/UI/Canvas/CanvasPreview.gd b/src/UI/Canvas/CanvasPreview.gd index 455a2acfebab..954f79b3de62 100644 --- a/src/UI/Canvas/CanvasPreview.gd +++ b/src/UI/Canvas/CanvasPreview.gd @@ -23,7 +23,10 @@ func _draw() -> void: if current_cels[i] is GroupCel: continue var modulate_color := Color(1, 1, 1, current_cels[i].opacity) - if i < current_project.layers.size() and current_project.layers[i].is_visible_in_hierarchy(): + if ( + i < current_project.layers.size() + and current_project.layers[i].is_visible_in_hierarchy() + ): draw_texture(current_cels[i].image_texture, Vector2.ZERO, modulate_color) diff --git a/src/UI/Canvas/CurrentFrameDrawer.gd b/src/UI/Canvas/CurrentFrameDrawer.gd index 4285f2dd80e6..5714f99640d6 100644 --- a/src/UI/Canvas/CurrentFrameDrawer.gd +++ b/src/UI/Canvas/CurrentFrameDrawer.gd @@ -6,6 +6,9 @@ func _draw() -> void: for i in range(Global.current_project.layers.size()): if current_cels[i] is GroupCel: continue - if Global.current_project.layers[i].is_visible_in_hierarchy() and current_cels[i].opacity > 0: + if ( + Global.current_project.layers[i].is_visible_in_hierarchy() + and current_cels[i].opacity > 0 + ): var modulate_color := Color(1, 1, 1, current_cels[i].opacity) draw_texture(current_cels[i].image_texture, Vector2.ZERO, modulate_color) diff --git a/src/UI/Canvas/Selection.gd b/src/UI/Canvas/Selection.gd index 6a702b45de97..37d0f89de698 100644 --- a/src/UI/Canvas/Selection.gd +++ b/src/UI/Canvas/Selection.gd @@ -71,6 +71,7 @@ func _ready() -> void: # gizmos.append(Gizmo.new(Gizmo.Type.ROTATE)) # Rotation gizmo (temp) + func _input(event: InputEvent) -> void: if is_moving_content: if Input.is_action_just_pressed("transformation_confirm"): diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index eacf36e03759..914302b89610 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -191,7 +191,7 @@ func delete_frames(indices := []) -> void: return if indices.size() == project.frames.size(): - indices.remove(indices.size() - 1) # Ensure the project has at least 1 frame + indices.remove(indices.size() - 1) # Ensure the project has at least 1 frame elif indices.size() == 0: indices.append(project.current_frame) @@ -299,7 +299,9 @@ func copy_frames(indices := []) -> void: if new_cels_linked: # If the link button is pressed new_layers[l_i].linked_cels.append(new_frame) - new_frame.cels[l_i].set_content(new_layers[l_i].linked_cels[0].cels[l_i].get_content()) + new_frame.cels[l_i].set_content( + new_layers[l_i].linked_cels[0].cels[l_i].get_content() + ) new_frame.cels[l_i].image_texture = new_layers[l_i].linked_cels[0].cels[l_i].image_texture # Loop through the tags to see if the frame is in one @@ -398,6 +400,7 @@ func _on_PlayBackwards_toggled(button_pressed: bool) -> void: play_animation(button_pressed, false) + # Called on each frame of the animation func _on_AnimationTimer_timeout() -> void: if first_frame == last_frame: @@ -610,8 +613,8 @@ func _on_CloneLayer_pressed() -> void: var source_layers: Array = project.layers[project.current_layer].get_children(true) source_layers.append(project.layers[project.current_layer]) - var clones := [] # Array of Layers - var cels := [] # 2D Array of Cels + var clones := [] # Array of Layers + var cels := [] # 2D Array of Cels for sl in source_layers: var cl: BaseLayer = sl.copy() if sl.index == project.current_layer: @@ -629,7 +632,9 @@ func _on_CloneLayer_pressed() -> void: project.undos += 1 project.undo_redo.create_action("Add Layer") - project.undo_redo.add_do_property(project, "current_layer", project.current_layer + clones.size()) + project.undo_redo.add_do_property( + project, "current_layer", project.current_layer + clones.size() + ) project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) project.undo_redo.add_do_method(project, "add_layers", clones, indices, cels) project.undo_redo.add_undo_method(project, "remove_layers", indices) @@ -665,6 +670,7 @@ func _on_RemoveLayer_pressed() -> void: project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.commit_action() + # Move the layer up or down in layer order and/or reparent to be deeper/shallower in the # layer hierarchy depending on its current index and parent func change_layer_order(up: bool) -> void: @@ -676,14 +682,14 @@ func change_layer_order(up: bool) -> void: for l in from_indices: from_parents.append(project.layers[l].parent) var to_parents := from_parents.duplicate() - var to_index = layer.index - child_count # the index where the LOWEST shifted layer should end up + var to_index = layer.index - child_count # the index where the LOWEST shifted layer should end up if up: var above_layer: BaseLayer = project.layers[project.current_layer + 1] - if layer.parent == above_layer: # Above is the parent, leave the parent and go up + if layer.parent == above_layer: # Above is the parent, leave the parent and go up to_parents[-1] = above_layer.parent to_index = to_index + 1 - elif layer.parent != above_layer.parent: # Above layer must be deeper in the hierarchy + elif layer.parent != above_layer.parent: # Above layer must be deeper in the hierarchy # Move layer 1 level deeper in hierarchy. Done by setting its parent to the parent of # above_layer, and if that is multiple levels, drop levels until its just 1 to_parents[-1] = above_layer.parent @@ -693,15 +699,15 @@ func change_layer_order(up: bool) -> void: to_parents[-1] = above_layer else: to_index = to_index + 1 - else: # Down - if layer.index == child_count: # If at the very bottom of the layer stack + else: # Down + if layer.index == child_count: # If at the very bottom of the layer stack if not is_instance_valid(layer.parent): return - to_parents[-1] = layer.parent.parent # Drop a level in the hierarchy + to_parents[-1] = layer.parent.parent # Drop a level in the hierarchy else: var below_layer: BaseLayer = project.layers[project.current_layer - 1 - child_count] - if layer.parent != below_layer.parent: # If there is a hierarchy change - to_parents[-1] = layer.parent.parent # Drop a level in the hierarchy + if layer.parent != below_layer.parent: # If there is a hierarchy change + to_parents[-1] = layer.parent.parent # Drop a level in the hierarchy elif below_layer.accepts_child(layer): to_parents[-1] = below_layer to_index = to_index - 1 @@ -714,7 +720,9 @@ func change_layer_order(up: bool) -> void: project.undo_redo.add_do_property(project, "current_layer", to_index + child_count) project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) project.undo_redo.add_do_method(project, "move_layers", from_indices, to_indices, to_parents) - project.undo_redo.add_undo_method(project, "move_layers", to_indices, from_indices, from_parents) + project.undo_redo.add_undo_method( + project, "move_layers", to_indices, from_indices, from_parents + ) project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.commit_action() @@ -723,7 +731,7 @@ func change_layer_order(up: bool) -> void: func _on_MergeDownLayer_pressed() -> void: var project: Project = Global.current_project var top_layer: PixelLayer = project.layers[project.current_layer] - var bottom_layer : PixelLayer = project.layers[project.current_layer - 1] + var bottom_layer: PixelLayer = project.layers[project.current_layer - 1] var new_linked_cels: Array = bottom_layer.linked_cels.duplicate() project.undos += 1 @@ -753,9 +761,13 @@ func _on_MergeDownLayer_pressed() -> void: and f in bottom_layer.linked_cels ): new_linked_cels.erase(f) - project.undo_redo.add_do_property(f.cels[bottom_layer.index], "image_texture", ImageTexture.new()) + project.undo_redo.add_do_property( + f.cels[bottom_layer.index], "image_texture", ImageTexture.new() + ) project.undo_redo.add_undo_property( - f.cels[bottom_layer.index], "image_texture", f.cels[bottom_layer.index].image_texture + f.cels[bottom_layer.index], + "image_texture", + f.cels[bottom_layer.index].image_texture ) project.undo_redo.add_do_property(f.cels[bottom_layer.index], "image", bottom_image) project.undo_redo.add_undo_property( @@ -778,7 +790,9 @@ func _on_MergeDownLayer_pressed() -> void: project.undo_redo.add_do_property(bottom_layer, "linked_cels", new_linked_cels) project.undo_redo.add_undo_property(bottom_layer, "linked_cels", bottom_layer.linked_cels) project.undo_redo.add_do_method(project, "remove_layers", [top_layer.index]) - project.undo_redo.add_undo_method(project, "add_layers", [top_layer], [top_layer.index], [top_cels]) + project.undo_redo.add_undo_method( + project, "add_layers", [top_layer], [top_layer.index], [top_cels] + ) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.commit_action() @@ -828,16 +842,12 @@ func project_changed() -> void: var container_child_count: int = Global.frames_container.get_child_count() if layer < container_child_count: - var container = Global.frames_container.get_child( - container_child_count - 1 - layer - ) + var container = Global.frames_container.get_child(container_child_count - 1 - layer) if frame < container.get_child_count(): var cel_button = container.get_child(frame) cel_button.pressed = true - var layer_button = Global.layers_container.get_child( - container_child_count - 1 - layer - ) + var layer_button = Global.layers_container.get_child(container_child_count - 1 - layer) layer_button.pressed = true diff --git a/src/UI/Timeline/CelButton.gd b/src/UI/Timeline/CelButton.gd index f0c4564b7e95..253c7667be85 100644 --- a/src/UI/Timeline/CelButton.gd +++ b/src/UI/Timeline/CelButton.gd @@ -9,6 +9,7 @@ var cel: BaseCel onready var popup_menu: PopupMenu = get_node_or_null("PopupMenu") onready var linked_indicator: Polygon2D = get_node_or_null("LinkedIndicator") + func _ready() -> void: button_setup() @@ -123,7 +124,9 @@ func _on_PopupMenu_id_pressed(id: int) -> void: # If there are already linked cels, set the current cel's image # to the first linked cel's image var linked_cel: BaseCel = project.layers[layer].linked_cels[0].cels[layer] - project.undo_redo.add_do_property(cel, "image_texture", linked_cel.image_texture) + project.undo_redo.add_do_property( + cel, "image_texture", linked_cel.image_texture + ) project.undo_redo.add_undo_property(cel, "image_texture", cel.image_texture) project.undo_redo.add_do_method(cel, "set_content", linked_cel.get_content()) project.undo_redo.add_undo_method(cel, "set_content", cel.get_content()) @@ -134,10 +137,18 @@ func _on_PopupMenu_id_pressed(id: int) -> void: ) # Remove and add a new cel button to update appearance (can't use self.button_setup # because there is no guarantee that it will be the exact same cel button instance) - project.undo_redo.add_do_method(Global.animation_timeline, "project_cel_removed", frame, layer) - project.undo_redo.add_undo_method(Global.animation_timeline, "project_cel_removed", frame, layer) - project.undo_redo.add_do_method(Global.animation_timeline, "project_cel_added", frame, layer) - project.undo_redo.add_undo_method(Global.animation_timeline, "project_cel_added", frame, layer) + project.undo_redo.add_do_method( + Global.animation_timeline, "project_cel_removed", frame, layer + ) + project.undo_redo.add_undo_method( + Global.animation_timeline, "project_cel_removed", frame, layer + ) + project.undo_redo.add_do_method( + Global.animation_timeline, "project_cel_added", frame, layer + ) + project.undo_redo.add_undo_method( + Global.animation_timeline, "project_cel_added", frame, layer + ) project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) @@ -181,22 +192,28 @@ func can_drop_data(_pos, data) -> bool: if typeof(data) == TYPE_ARRAY and data[0] == "Cel": var drag_frame = data[1] var drag_layer = data[2] - if Global.current_project.layers[layer] is GroupLayer or not ( - Global.current_project.frames[frame] in Global.current_project.layers[layer].linked_cels - or ( - Global.current_project.frames[drag_frame] - in Global.current_project.layers[drag_layer].linked_cels + if ( + Global.current_project.layers[layer] is GroupLayer + or not ( + ( + Global.current_project.frames[frame] + in Global.current_project.layers[layer].linked_cels + ) + or ( + Global.current_project.frames[drag_frame] + in Global.current_project.layers[drag_layer].linked_cels + ) ) ): if not (drag_frame == frame and drag_layer == layer): var region: Rect2 - if Input.is_action_pressed("ctrl") or layer != drag_layer: # Swap cels + if Input.is_action_pressed("ctrl") or layer != drag_layer: # Swap cels region = get_global_rect() - else: # Move cels - if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): # Left + else: # Move cels + if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): # Left region = _get_region_rect(-0.125, 0.125) region.position.x -= 2 # Container spacing - else: # Right + else: # Right region = _get_region_rect(0.875, 1.125) region.position.x += 2 # Container spacing Global.animation_timeline.drag_highlight.rect_global_position = region.position @@ -214,14 +231,14 @@ func drop_data(_pos, data) -> void: var project = Global.current_project project.undo_redo.create_action("Move Cels") - if Input.is_action_pressed("ctrl") or layer != drop_layer: # Swap cels + if Input.is_action_pressed("ctrl") or layer != drop_layer: # Swap cels project.undo_redo.add_do_method(project, "swap_cel", frame, layer, drop_frame, drop_layer) project.undo_redo.add_undo_method(project, "swap_cel", frame, layer, drop_frame, drop_layer) - else: # Move cels + else: # Move cels var to_frame: int - if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): # Left + if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): # Left to_frame = frame - else: # Right + else: # Right to_frame = frame + 1 if drop_frame < frame: to_frame -= 1 diff --git a/src/UI/Timeline/FrameButton.gd b/src/UI/Timeline/FrameButton.gd index 45ef298f15e7..c1900994581b 100644 --- a/src/UI/Timeline/FrameButton.gd +++ b/src/UI/Timeline/FrameButton.gd @@ -117,11 +117,11 @@ func get_drag_data(_position) -> Array: func can_drop_data(_pos, data) -> bool: if typeof(data) == TYPE_ARRAY: if data[0] == "Frame": - if data[1] != frame: # Can't move to same frame + if data[1] != frame: # Can't move to same frame var region: Rect2 - if Input.is_action_pressed("ctrl"): # Swap frames + if Input.is_action_pressed("ctrl"): # Swap frames region = get_global_rect() - else: # Move frames + else: # Move frames if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): region = _get_region_rect(-0.125, 0.125) region.position.x -= 2 # Container spacing @@ -140,14 +140,14 @@ func drop_data(_pos, data) -> void: var drop_frame = data[1] var project = Global.current_project project.undo_redo.create_action("Change Frame Order") - if Input.is_action_pressed("ctrl"): # Swap frames + if Input.is_action_pressed("ctrl"): # Swap frames project.undo_redo.add_do_method(project, "swap_frame", frame, drop_frame) project.undo_redo.add_undo_method(project, "swap_frame", frame, drop_frame) - else: # Move frames + else: # Move frames var to_frame: int - if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): # Left + if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): # Left to_frame = frame - else: # Right + else: # Right to_frame = frame + 1 if drop_frame < frame: to_frame -= 1 diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index 7b5d8c8bc0c9..40adc4d5ca6f 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -15,6 +15,7 @@ onready var linked_button: BaseButton = find_node("LinkButton") export var hide_expand_button := true + func _ready() -> void: rect_min_size.y = Global.animation_timeline.cel_size @@ -30,9 +31,9 @@ func _ready() -> void: var hierarchy_depth: int = Global.current_project.layers[layer].get_hierarchy_depth() hierarchy_spacer.rect_min_size.x = hierarchy_depth * HIERARCHY_DEPTH_PIXEL_SHIFT - if Global.control.theme.get_color("font_color", "Button").v > 0.5: # Light text is dark theme + if Global.control.theme.get_color("font_color", "Button").v > 0.5: # Light text is dark theme self_modulate.v = 1 + hierarchy_depth * 0.4 - else: # Dark text should be light theme + else: # Dark text should be light theme self_modulate.v = 1 - hierarchy_depth * 0.075 _update_buttons() @@ -72,6 +73,7 @@ func _update_buttons() -> void: if Global.current_project.layers[layer].parent.is_locked_in_hierarchy(): lock_button.modulate.a = 0.33 + # Used when pressing a button on this changes the appearnce of other layers (ie: expand or visible) func _update_buttons_all_layers() -> void: for layer_button in Global.layers_container.get_children(): @@ -85,7 +87,11 @@ func _draw() -> void: if hierarchy_spacer.rect_size.x > 0.1: var color := Color(1, 1, 1, 0.33) color.v = round(Global.control.theme.get_color("font_color", "Button").v) - var x = hierarchy_spacer.rect_global_position.x - rect_global_position.x + hierarchy_spacer.rect_size.x + var x = ( + hierarchy_spacer.rect_global_position.x + - rect_global_position.x + + hierarchy_spacer.rect_size.x + ) draw_line(Vector2(x, 0), Vector2(x, rect_size.y), color) @@ -189,7 +195,9 @@ func _select_current_layer() -> void: func get_drag_data(_position) -> Array: - var layers := range(layer - Global.current_project.layers[layer].get_child_count(true), layer + 1) + var layers := range( + layer - Global.current_project.layers[layer].get_child_count(true), layer + 1 + ) var box := VBoxContainer.new() for i in layers.size(): @@ -216,29 +224,30 @@ func can_drop_data(_pos, data) -> bool: var region: Rect2 var depth: int = Global.current_project.layers[layer].get_hierarchy_depth() - if Input.is_action_pressed("ctrl"): # Swap layers + if Input.is_action_pressed("ctrl"): # Swap layers if drag_layer.is_a_parent_of(curr_layer) or curr_layer.is_a_parent_of(drag_layer): Global.animation_timeline.drag_highlight.visible = false return false region = get_global_rect() - else: # Shift layers + else: # Shift layers if drag_layer.is_a_parent_of(curr_layer): Global.animation_timeline.drag_highlight.visible = false return false # If accepted as a child, is it in the center region? - if (Global.current_project.layers[layer].accepts_child(data[1]) - and _get_region_rect(0.25, 0.75).has_point(get_global_mouse_position()) - ): - # Drawn regions are adusted a bit from actual to clearify drop position - region = _get_region_rect(0.15, 0.85) - depth += 1 + if ( + Global.current_project.layers[layer].accepts_child(data[1]) + and _get_region_rect(0.25, 0.75).has_point(get_global_mouse_position()) + ): + # Drawn regions are adusted a bit from actual to clearify drop position + region = _get_region_rect(0.15, 0.85) + depth += 1 else: # Top or bottom region? if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): - region = _get_region_rect(-0.1, 0.15) + region = _get_region_rect(-0.1, 0.15) else: - region = _get_region_rect(0.85, 1.1) + region = _get_region_rect(0.85, 1.1) # Shift drawn region to the right a bit for hierarchy depth visualization: region.position.x += depth * HIERARCHY_DEPTH_PIXEL_SHIFT region.size.x -= depth * HIERARCHY_DEPTH_PIXEL_SHIFT @@ -255,26 +264,28 @@ func drop_data(_pos, data) -> void: var project = Global.current_project project.undo_redo.create_action("Change Layer Order") - var layers: Array = project.layers # This shouldn't be modified directly + var layers: Array = project.layers # This shouldn't be modified directly - var drop_from_indices := range(drop_layer - layers[drop_layer].get_child_count(true), drop_layer + 1 ) + var drop_from_indices := range( + drop_layer - layers[drop_layer].get_child_count(true), drop_layer + 1 + ) var drop_from_parents := [] for i in range(drop_from_indices.size()): drop_from_parents.append(layers[drop_from_indices[i]].parent) - if Input.is_action_pressed("ctrl"): # Swap layers + if Input.is_action_pressed("ctrl"): # Swap layers # a and b both need "from", "to", and "to_parents" # a is this layer (and children), b is the dropped layers - var a := { "from": range(layer - layers[layer].get_child_count(true), layer + 1) } - var b := { "from": drop_from_indices} + var a := {"from": range(layer - layers[layer].get_child_count(true), layer + 1)} + var b := {"from": drop_from_indices} if a.from[0] < b.from[0]: - a["to"] = range(b.from[-1] + 1 - a.from.size(), b.from[-1] + 1) # Size of a, starting from end of b - b["to"] = range(a.from[0], a.from[0] + b.from.size()) # Size of b, starting from beginning of a + a["to"] = range(b.from[-1] + 1 - a.from.size(), b.from[-1] + 1) # Size of a, starting from end of b + b["to"] = range(a.from[0], a.from[0] + b.from.size()) # Size of b, starting from beginning of a else: - a["to"] = range(b.from[0], b.from[0] + a.from.size()) # Size of a, starting from beginning of b - b["to"] = range(a.from[-1] + 1 - b.from.size(), a.from[-1] + 1) # Size of b, starting from end of a + a["to"] = range(b.from[0], b.from[0] + a.from.size()) # Size of a, starting from beginning of b + b["to"] = range(a.from[-1] + 1 - b.from.size(), a.from[-1] + 1) # Size of b, starting from end of a var a_from_parents := [] for l in a.from: @@ -289,19 +300,22 @@ func drop_data(_pos, data) -> void: b.to_parents[-1] = a_from_parents[-1] project.undo_redo.add_do_method(project, "swap_layers", a, b) - project.undo_redo.add_undo_method(project, "swap_layers", - { "from": a.to, "to": a.from, "to_parents": a_from_parents }, - { "from": b.to, "to": drop_from_indices, "to_parents": drop_from_parents } + project.undo_redo.add_undo_method( + project, + "swap_layers", + {"from": a.to, "to": a.from, "to_parents": a_from_parents}, + {"from": b.to, "to": drop_from_indices, "to_parents": drop_from_parents} ) - else: # Move layers - var to_index: int # the index where the LOWEST moved layer should end up + else: # Move layers + var to_index: int # the index where the LOWEST moved layer should end up var to_parent: BaseLayer # If accepted as a child, is it in the center region? - if (layers[layer].accepts_child(data[1]) - and _get_region_rect(0.25, 0.75).has_point(get_global_mouse_position()) - ): + if ( + layers[layer].accepts_child(data[1]) + and _get_region_rect(0.25, 0.75).has_point(get_global_mouse_position()) + ): to_index = layer to_parent = layers[layer] else: From b8a98e2a7f1c5c7b17419094af4ac6e1e456bad1 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 17 Sep 2022 15:27:19 -0400 Subject: [PATCH 149/154] gdlint fixes --- src/UI/Timeline/LayerButton.gd | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index 40adc4d5ca6f..e6902843f6c2 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -5,6 +5,8 @@ const HIERARCHY_DEPTH_PIXEL_SHIFT = 8 var layer := 0 +export var hide_expand_button := true + onready var expand_button: BaseButton = find_node("ExpandButton") onready var visibility_button: BaseButton = find_node("VisibilityButton") onready var lock_button: BaseButton = find_node("LockButton") @@ -13,8 +15,6 @@ onready var line_edit: LineEdit = find_node("LineEdit") onready var hierarchy_spacer: Control = find_node("HierarchySpacer") onready var linked_button: BaseButton = find_node("LinkButton") -export var hide_expand_button := true - func _ready() -> void: rect_min_size.y = Global.animation_timeline.cel_size @@ -36,10 +36,10 @@ func _ready() -> void: else: # Dark text should be light theme self_modulate.v = 1 - hierarchy_depth * 0.075 - _update_buttons() + update_buttons() -func _update_buttons() -> void: +func update_buttons() -> void: if hide_expand_button: expand_button.mouse_filter = Control.MOUSE_FILTER_IGNORE expand_button.get_child(0).visible = false # Hide the TextureRect @@ -77,7 +77,7 @@ func _update_buttons() -> void: # Used when pressing a button on this changes the appearnce of other layers (ie: expand or visible) func _update_buttons_all_layers() -> void: for layer_button in Global.layers_container.get_children(): - layer_button._update_buttons() + layer_button.update_buttons() var expanded = Global.current_project.layers[layer_button.layer].is_expanded_in_hierarchy() layer_button.visible = expanded Global.frames_container.get_child(layer_button.get_index()).visible = expanded @@ -182,7 +182,7 @@ func _on_LinkButton_pressed() -> void: ) container.get_child(Global.current_project.current_frame).button_setup() - _update_buttons() + update_buttons() func _select_current_layer() -> void: @@ -281,11 +281,11 @@ func drop_data(_pos, data) -> void: var b := {"from": drop_from_indices} if a.from[0] < b.from[0]: - a["to"] = range(b.from[-1] + 1 - a.from.size(), b.from[-1] + 1) # Size of a, starting from end of b - b["to"] = range(a.from[0], a.from[0] + b.from.size()) # Size of b, starting from beginning of a + a["to"] = range(b.from[-1] + 1 - a.from.size(), b.from[-1] + 1) # Size of a, start from end of b + b["to"] = range(a.from[0], a.from[0] + b.from.size()) # Size of b, start from beginning of a else: - a["to"] = range(b.from[0], b.from[0] + a.from.size()) # Size of a, starting from beginning of b - b["to"] = range(a.from[-1] + 1 - b.from.size(), a.from[-1] + 1) # Size of b, starting from end of a + a["to"] = range(b.from[0], b.from[0] + a.from.size()) # Size of a, start from beginning of b + b["to"] = range(a.from[-1] + 1 - b.from.size(), a.from[-1] + 1) # Size of b, start from end of a var a_from_parents := [] for l in a.from: From 2c9d1e00013c502a8e08fa9d7c2b0ffc2df5da36 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 17 Sep 2022 15:38:31 -0400 Subject: [PATCH 150/154] Fixed Cel button not having its linked indicator show when enabling new cels linked on a layer other than the current layer --- src/UI/Timeline/LayerButton.gd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index e6902843f6c2..095b63581afe 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -3,10 +3,10 @@ extends Button const HIERARCHY_DEPTH_PIXEL_SHIFT = 8 -var layer := 0 - export var hide_expand_button := true +var layer := 0 + onready var expand_button: BaseButton = find_node("ExpandButton") onready var visibility_button: BaseButton = find_node("VisibilityButton") onready var lock_button: BaseButton = find_node("LockButton") @@ -178,7 +178,7 @@ func _on_LinkButton_pressed() -> void: Global.current_project.frames[Global.current_project.current_frame] ) var container = Global.frames_container.get_child( - Global.frames_container.get_child_count() - 1 - Global.current_project.current_layer + Global.frames_container.get_child_count() - 1 - layer ) container.get_child(Global.current_project.current_frame).button_setup() From 69572b2cb621ba60bc7aa892c6d9bed8026e0b78 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 17 Sep 2022 16:35:58 -0400 Subject: [PATCH 151/154] Fixed crop image and centralize image --- src/Autoload/DrawingAlgos.gd | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Autoload/DrawingAlgos.gd b/src/Autoload/DrawingAlgos.gd index 1c01154614e1..a8ec4c71c791 100644 --- a/src/Autoload/DrawingAlgos.gd +++ b/src/Autoload/DrawingAlgos.gd @@ -451,6 +451,8 @@ func centralize() -> void: # Find used rect of the current frame (across all of the layers) var used_rect := Rect2() for cel in Global.current_project.frames[Global.current_project.current_frame].cels: + if not cel is PixelCel: + continue var cel_rect: Rect2 = cel.image.get_used_rect() if not cel_rect.has_no_area(): used_rect = cel_rect if used_rect.has_no_area() else used_rect.merge(cel_rect) @@ -459,14 +461,16 @@ func centralize() -> void: var offset: Vector2 = (0.5 * (Global.current_project.size - used_rect.size)).floor() general_do_centralize() - for c in Global.current_project.frames[Global.current_project.current_frame].cels: + for cel in Global.current_project.frames[Global.current_project.current_frame].cels: + if not cel is PixelCel: + continue var sprite := Image.new() sprite.create( Global.current_project.size.x, Global.current_project.size.y, false, Image.FORMAT_RGBA8 ) - sprite.blend_rect(c.image, used_rect, offset) - Global.current_project.undo_redo.add_do_property(c.image, "data", sprite.data) - Global.current_project.undo_redo.add_undo_property(c.image, "data", c.image.data) + sprite.blend_rect(cel.image, used_rect, offset) + Global.current_project.undo_redo.add_do_property(cel.image, "data", sprite.data) + Global.current_project.undo_redo.add_undo_property(cel.image, "data", cel.image.data) general_undo_centralize() @@ -475,6 +479,8 @@ func crop_image() -> void: var used_rect := Rect2() for f in Global.current_project.frames: for cel in f.cels: + if not cel is PixelCel: + continue cel.image.unlock() # May be unneeded now, but keep it just in case var cel_used_rect: Rect2 = cel.image.get_used_rect() if cel_used_rect == Rect2(0, 0, 0, 0): # If the cel has no content @@ -495,6 +501,8 @@ func crop_image() -> void: # Loop through all the cels to crop them for f in Global.current_project.frames: for cel in f.cels: + if not cel is PixelCel: + continue var sprite: Image = cel.image.get_rect(used_rect) Global.current_project.undo_redo.add_do_property(cel.image, "data", sprite.data) Global.current_project.undo_redo.add_undo_property(cel.image, "data", cel.image.data) From 39e7ecd76402d8371ce9e1fd0d10bdac736b7af5 Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sat, 17 Sep 2022 18:00:40 -0400 Subject: [PATCH 152/154] Added '# gdlint: ignore=max-public-methods' to the top of Project' --- src/Classes/Project.gd | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index d6f0fd253f0f..7fd37e56587f 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -1,3 +1,4 @@ +# gdlint: ignore=max-public-methods class_name Project extends Reference # A class for project properties. From 67aaa62d25e1dc42a14d97b1c3e00f91d471e3df Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sun, 25 Sep 2022 11:30:05 -0400 Subject: [PATCH 153/154] Fixed dragging cels to layer of different type crash --- src/UI/Timeline/CelButton.gd | 56 +++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/src/UI/Timeline/CelButton.gd b/src/UI/Timeline/CelButton.gd index 253c7667be85..39b6f47a4c1b 100644 --- a/src/UI/Timeline/CelButton.gd +++ b/src/UI/Timeline/CelButton.gd @@ -189,37 +189,39 @@ func get_drag_data(_position) -> Array: func can_drop_data(_pos, data) -> bool: + var project: Project = Global.current_project if typeof(data) == TYPE_ARRAY and data[0] == "Cel": var drag_frame = data[1] var drag_layer = data[2] - if ( - Global.current_project.layers[layer] is GroupLayer - or not ( - ( - Global.current_project.frames[frame] - in Global.current_project.layers[layer].linked_cels - ) - or ( - Global.current_project.frames[drag_frame] - in Global.current_project.layers[drag_layer].linked_cels + if project.layers[drag_layer].get_script() == project.layers[layer].get_script(): + if ( + project.layers[layer] is GroupLayer + or not ( + ( + project.frames[frame] + in project.layers[layer].linked_cels + ) + or ( + project.frames[drag_frame] + in project.layers[drag_layer].linked_cels + ) ) - ) - ): - if not (drag_frame == frame and drag_layer == layer): - var region: Rect2 - if Input.is_action_pressed("ctrl") or layer != drag_layer: # Swap cels - region = get_global_rect() - else: # Move cels - if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): # Left - region = _get_region_rect(-0.125, 0.125) - region.position.x -= 2 # Container spacing - else: # Right - region = _get_region_rect(0.875, 1.125) - region.position.x += 2 # Container spacing - Global.animation_timeline.drag_highlight.rect_global_position = region.position - Global.animation_timeline.drag_highlight.rect_size = region.size - Global.animation_timeline.drag_highlight.visible = true - return true + ): + if not (drag_frame == frame and drag_layer == layer): + var region: Rect2 + if Input.is_action_pressed("ctrl") or layer != drag_layer: # Swap cels + region = get_global_rect() + else: # Move cels + if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): # Left + region = _get_region_rect(-0.125, 0.125) + region.position.x -= 2 # Container spacing + else: # Right + region = _get_region_rect(0.875, 1.125) + region.position.x += 2 # Container spacing + Global.animation_timeline.drag_highlight.rect_global_position = region.position + Global.animation_timeline.drag_highlight.rect_size = region.size + Global.animation_timeline.drag_highlight.visible = true + return true Global.animation_timeline.drag_highlight.visible = false return false From b6a6017628184e9175de99f06fde03521e52dfef Mon Sep 17 00:00:00 2001 From: MrTriPie Date: Sun, 25 Sep 2022 11:32:14 -0400 Subject: [PATCH 154/154] Formatted CelButton.gd --- src/UI/Timeline/CelButton.gd | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/UI/Timeline/CelButton.gd b/src/UI/Timeline/CelButton.gd index 39b6f47a4c1b..9257330676cc 100644 --- a/src/UI/Timeline/CelButton.gd +++ b/src/UI/Timeline/CelButton.gd @@ -197,14 +197,8 @@ func can_drop_data(_pos, data) -> bool: if ( project.layers[layer] is GroupLayer or not ( - ( - project.frames[frame] - in project.layers[layer].linked_cels - ) - or ( - project.frames[drag_frame] - in project.layers[drag_layer].linked_cels - ) + (project.frames[frame] in project.layers[layer].linked_cels) + or (project.frames[drag_frame] in project.layers[drag_layer].linked_cels) ) ): if not (drag_frame == frame and drag_layer == layer):