From 852365c38f3c89c162b87fb06d9733bb552e6287 Mon Sep 17 00:00:00 2001 From: PinyaColada <72302480+PinyaColada@users.noreply.github.com> Date: Mon, 19 Oct 2020 16:57:40 +0200 Subject: [PATCH] Frame properties (#357) * Sync for my local files to my repository * This is frame properties update, it works but I can't be stored while saving or loading and that makes crashes just the beggining :) * I forgot this files :P * Frame Properties update. * Updating frame properties * Update Translations.pot * Changes to CanvasPreview and CelButton change --- Translations/Translations.pot | 12 +++++ src/Autoload/Export.gd | 8 ++-- src/Autoload/Global.gd | 2 + src/Classes/Project.gd | 5 ++- src/Main.tscn | 5 ++- src/UI/Canvas/CanvasPreview.gd | 7 ++- src/UI/Dialogs/ExportDialog.gd | 14 ++++-- src/UI/Timeline/AnimationTimeline.gd | 33 +++++++++++--- src/UI/Timeline/CelButton.gd | 16 ++++++- src/UI/Timeline/CelButton.tscn | 6 ++- src/UI/Timeline/FrameProperties.gd | 29 ++++++++++++ src/UI/Timeline/FrameProperties.tscn | 66 ++++++++++++++++++++++++++++ 12 files changed, 183 insertions(+), 20 deletions(-) create mode 100644 src/UI/Timeline/FrameProperties.gd create mode 100644 src/UI/Timeline/FrameProperties.tscn diff --git a/Translations/Translations.pot b/Translations/Translations.pot index 87f0762f3..162332167 100644 --- a/Translations/Translations.pot +++ b/Translations/Translations.pot @@ -1064,6 +1064,9 @@ msgstr "" msgid "Unlink Cel" msgstr "" +msgid "Frame properties" +msgstr "" + msgid "Layer" msgstr "" @@ -1197,6 +1200,12 @@ msgstr "" msgid "Redo: Delete Frame Tag" msgstr "" +msgid "Undo: Change frame duration" +msgstr "" + +msgid "Redo: Change frame duration" +msgstr "" + msgid "Move Guide" msgstr "" @@ -1428,3 +1437,6 @@ msgstr "" msgid "Move the selected frame to the right." msgstr "" + +msgid "Frame duration" +msgstr "" diff --git a/src/Autoload/Export.gd b/src/Autoload/Export.gd index c2a5d8134..3c7d34f8a 100644 --- a/src/Autoload/Export.gd +++ b/src/Autoload/Export.gd @@ -213,16 +213,16 @@ func export_gif(args: Dictionary) -> void: match direction: AnimationDirection.FORWARD: for i in range(processed_images.size()): - write_frame_to_gif(processed_images[i], Global.animation_timer.wait_time, exporter, args["export_dialog"]) + write_frame_to_gif(processed_images[i], Global.current_project.frame_duration[i] * (1 / Global.animation_timeline.fps), exporter, args["export_dialog"]) AnimationDirection.BACKWARDS: for i in range(processed_images.size() - 1, -1, -1): - write_frame_to_gif(processed_images[i], Global.animation_timer.wait_time, exporter, args["export_dialog"]) + write_frame_to_gif(processed_images[i], Global.current_project.frame_duration[i] * (1 / Global.animation_timeline.fps), exporter, args["export_dialog"]) AnimationDirection.PING_PONG: export_progress_fraction = 100 / (processed_images.size() * 2) for i in range(0, processed_images.size()): - write_frame_to_gif(processed_images[i], Global.animation_timer.wait_time, exporter, args["export_dialog"]) + write_frame_to_gif(processed_images[i], Global.current_project.frame_duration[i] * (1 / Global.animation_timeline.fps), exporter, args["export_dialog"]) for i in range(processed_images.size() - 2, 0, -1): - write_frame_to_gif(processed_images[i], Global.animation_timer.wait_time, exporter, args["export_dialog"]) + write_frame_to_gif(processed_images[i], Global.current_project.frame_duration[i] * (1 / Global.animation_timeline.fps), exporter, args["export_dialog"]) if OS.get_name() == "HTML5": Html5FileExchange.save_gif(exporter.export_file_data(), args["export_paths"][0]) diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index 5074176e3..de05fcab9 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -127,6 +127,7 @@ var patterns_popup : Popup var animation_timeline : Panel var animation_timer : Timer +var frame_properties : ConfirmationDialog var frame_ids : HBoxContainer var current_frame_mark_label : Label var onion_skinning_button : BaseButton @@ -221,6 +222,7 @@ func _ready() -> void: patterns_popup = find_node_by_name(root, "PatternsPopup") animation_timeline = find_node_by_name(root, "AnimationTimeline") + frame_properties = find_node_by_name(root, "FrameProperties") layers_container = find_node_by_name(animation_timeline, "LayersContainer") frames_container = find_node_by_name(animation_timeline, "FramesContainer") diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index dff832cad..b006267ac 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -8,6 +8,7 @@ var undo_redo : UndoRedo var undos := 0 # The number of times we added undo properties var has_changed := false setget has_changed_changed var frames := [] setget frames_changed # Array of Frames (that contain Cels) +var frame_duration := [] var layers := [] setget layers_changed # Array of Layers var current_frame := 0 setget frame_changed var current_layer := 0 setget layer_changed @@ -271,6 +272,7 @@ func serialize() -> Dictionary: "export_directory_path" : directory_path, "export_file_name" : file_name, "export_file_format" : file_format, + "frame_duration" : frame_duration, } return project_data @@ -332,7 +334,8 @@ func deserialize(dict : Dictionary) -> void: file_name = dict.export_file_name if dict.has("export_file_format"): file_format = dict.export_file_format - + if dict.has("frame_duration"): + frame_duration = dict.frame_duration func name_changed(value : String) -> void: name = value diff --git a/src/Main.tscn b/src/Main.tscn index 74c37a592..f1e1a15ec 100644 --- a/src/Main.tscn +++ b/src/Main.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=16 format=2] +[gd_scene load_steps=17 format=2] [ext_resource path="res://assets/themes/dark/theme.tres" type="Theme" id=1] [ext_resource path="res://src/Main.gd" type="Script" id=2] @@ -8,6 +8,7 @@ [ext_resource path="res://src/UI/BrushesPopup.tscn" type="PackedScene" id=6] [ext_resource path="res://src/UI/Dialogs/ImageEffects/ImageEffects.tscn" type="PackedScene" id=7] [ext_resource path="res://src/UI/Dialogs/SaveSpriteHTML5.tscn" type="PackedScene" id=8] +[ext_resource path="res://src/UI/Timeline/FrameProperties.tscn" type="PackedScene" id=9] [ext_resource path="res://src/UI/Dialogs/SaveSprite.tscn" type="PackedScene" id=11] [ext_resource path="res://src/UI/Dialogs/OpenSprite.tscn" type="PackedScene" id=12] [ext_resource path="res://src/UI/Dialogs/SplashDialog.tscn" type="PackedScene" id=27] @@ -109,6 +110,8 @@ popup_exclusive = true dialog_text = "Autosaved backup for %s was found. Do you want to reload it?" +[node name="FrameProperties" parent="Dialogs" instance=ExtResource( 9 )] + [node name="LeftCursor" type="Sprite" parent="."] visible = false diff --git a/src/UI/Canvas/CanvasPreview.gd b/src/UI/Canvas/CanvasPreview.gd index 8eb5b358c..6cd9b613f 100644 --- a/src/UI/Canvas/CanvasPreview.gd +++ b/src/UI/Canvas/CanvasPreview.gd @@ -9,7 +9,7 @@ func _draw() -> void: if frame >= current_project.frames.size(): frame = current_project.current_frame - $AnimationTimer.wait_time = Global.animation_timer.wait_time + $AnimationTimer.wait_time = Global.current_project.frame_duration[frame] * (1 / Global.animation_timeline.fps) if animation_timer.is_stopped(): frame = current_project.current_frame @@ -24,9 +24,12 @@ func _draw() -> void: func _on_AnimationTimer_timeout() -> void: var current_project : Project = Global.current_project - if frame < current_project.frames.size() - 1: frame += 1 else: frame = 0 + + $AnimationTimer.set_one_shot(true) + $AnimationTimer.wait_time = Global.current_project.frame_duration[frame] * (1 / Global.animation_timeline.fps) + $AnimationTimer.start() update() diff --git a/src/UI/Dialogs/ExportDialog.gd b/src/UI/Dialogs/ExportDialog.gd index 334ab1098..1276a39cb 100644 --- a/src/UI/Dialogs/ExportDialog.gd +++ b/src/UI/Dialogs/ExportDialog.gd @@ -148,6 +148,8 @@ func add_animated_preview() -> void: container.add_child(preview) previews.add_child(container) + frame_timer.set_one_shot(true) #The wait_time it can't change correctly if it is playing + frame_timer.wait_time = Global.current_project.frame_duration[animated_preview_current_frame] * (1 / Global.animation_timeline.fps) frame_timer.start() @@ -186,7 +188,6 @@ func set_file_format_selector() -> void: Export.AnimationType.ANIMATED: Export.file_format = Export.FileFormat.GIF file_file_format.selected = Export.FileFormat.GIF - frame_timer.wait_time = Global.animation_timer.wait_time animation_options_animation_options.show() @@ -362,13 +363,15 @@ func _on_FrameTimer_timeout() -> void: animated_preview_current_frame = 0 else: animated_preview_current_frame += 1 - + frame_timer.wait_time = Global.current_project.frame_duration[(animated_preview_current_frame - 1) % (animated_preview_frames.size())] * (1 / Global.animation_timeline.fps) + frame_timer.start() Export.AnimationDirection.BACKWARDS: if animated_preview_current_frame == 0: animated_preview_current_frame = Export.processed_images.size() - 1 else: animated_preview_current_frame -= 1 - + frame_timer.wait_time = Global.current_project.frame_duration[(animated_preview_current_frame + 1) % (animated_preview_frames.size())] * (1 / Global.animation_timeline.fps) + frame_timer.start() Export.AnimationDirection.PING_PONG: match pingpong_direction: Export.AnimationDirection.FORWARD: @@ -379,6 +382,8 @@ func _on_FrameTimer_timeout() -> void: animated_preview_current_frame = 0 else: animated_preview_current_frame += 1 + frame_timer.wait_time = Global.current_project.frame_duration[(animated_preview_current_frame - 1) % (animated_preview_frames.size())] * (1 / Global.animation_timeline.fps) + frame_timer.start() Export.AnimationDirection.BACKWARDS: if animated_preview_current_frame == 0: animated_preview_current_frame += 1 @@ -387,6 +392,9 @@ func _on_FrameTimer_timeout() -> void: pingpong_direction = Export.AnimationDirection.FORWARD else: animated_preview_current_frame -= 1 + frame_timer.wait_time = Global.current_project.frame_duration[(animated_preview_current_frame + 1) % (animated_preview_frames.size())] * (1 / Global.animation_timeline.fps) + frame_timer.start() + func _on_ExportDialog_popup_hide() -> void: diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 247d0797c..3f7538e5d 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -15,6 +15,7 @@ func _ready() -> void: tag_scroll_container = Global.find_node_by_name(self, "TagScroll") timeline_scroll.get_h_scrollbar().connect("value_changed", self, "_h_scroll_changed") Global.animation_timer.wait_time = 1 / fps + Global.current_project.frame_duration.append(1) func _h_scroll_changed(value : float) -> void: @@ -24,10 +25,12 @@ func _h_scroll_changed(value : float) -> void: func add_frame() -> void: + var frame_duration : Array = Global.current_project.frame_duration.duplicate() var frame : Frame = Global.canvas.new_empty_frame() var new_frames : Array = Global.current_project.frames.duplicate() - new_frames.append(frame) var new_layers : Array = Global.current_project.layers.duplicate() + frame_duration.insert(Global.current_project.current_frame + 1, 1) + new_frames.insert(Global.current_project.current_frame + 1, frame) # 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(): @@ -46,12 +49,14 @@ func add_frame() -> void: Global.current_project.undo_redo.add_undo_method(Global, "undo") 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", new_frames.size() - 1) + Global.current_project.undo_redo.add_do_property(Global.current_project, "current_frame", Global.current_project.current_frame + 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, "frame_duration", frame_duration) #Add a 1 in the list of frame_duration 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, "current_frame", Global.current_project.current_frame ) 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, "frame_duration", Global.current_project.frame_duration) Global.current_project.undo_redo.commit_action() @@ -60,7 +65,9 @@ func _on_DeleteFrame_pressed(frame := -1) -> void: return if frame == -1: frame = Global.current_project.current_frame - + + var frame_duration : Array = Global.current_project.frame_duration.duplicate() + frame_duration.remove(frame) var frame_to_delete : Frame = Global.current_project.frames[frame] var new_frames : Array = Global.current_project.frames.duplicate() new_frames.erase(frame_to_delete) @@ -107,11 +114,13 @@ func _on_DeleteFrame_pressed(frame := -1) -> void: 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_do_property(Global.current_project, "frame_duration", frame_duration) #Remove the element of the list of the frame selected 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_undo_property(Global.current_project, "frame_duration", Global.current_project.frame_duration) Global.current_project.undo_redo.add_do_method(Global, "redo") Global.current_project.undo_redo.add_undo_method(Global, "undo") @@ -123,7 +132,8 @@ func _on_CopyFrame_pressed(frame := -1) -> void: frame = Global.current_project.current_frame var new_frame := Frame.new() - + var frame_duration : Array = Global.current_project.frame_duration.duplicate() + frame_duration.insert(frame + 1, 1) var new_frames := Global.current_project.frames.duplicate() new_frames.insert(frame + 1, new_frame) @@ -152,6 +162,7 @@ func _on_CopyFrame_pressed(frame := -1) -> void: 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", frame + 1) 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, "frame_duration", frame_duration) for i in range(Global.current_project.layers.size()): for child in Global.current_project.layers[i].frame_container.get_children(): Global.current_project.undo_redo.add_do_property(child, "pressed", false) @@ -160,6 +171,7 @@ func _on_CopyFrame_pressed(frame := -1) -> void: 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", 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, "frame_duration", Global.current_project.frame_duration) Global.current_project.undo_redo.commit_action() @@ -234,6 +246,8 @@ func _on_AnimationTimer_timeout() -> void: if animation_forward: if Global.current_project.current_frame < last_frame: Global.current_project.current_frame += 1 + Global.animation_timer.wait_time = Global.current_project.frame_duration[Global.current_project.current_frame] * (1/fps) + Global.animation_timer.start() #Change the frame, change the wait time and start a cycle, this is the best way to do it else: match animation_loop: 0: # No loop @@ -242,6 +256,8 @@ func _on_AnimationTimer_timeout() -> void: Global.animation_timer.stop() 1: # Cycle loop Global.current_project.current_frame = first_frame + Global.animation_timer.wait_time = Global.current_project.frame_duration[Global.current_project.current_frame] * (1/fps) + Global.animation_timer.start() 2: # Ping pong loop animation_forward = false _on_AnimationTimer_timeout() @@ -249,6 +265,8 @@ func _on_AnimationTimer_timeout() -> void: else: if Global.current_project.current_frame > first_frame: Global.current_project.current_frame -= 1 + Global.animation_timer.wait_time = Global.current_project.frame_duration[Global.current_project.current_frame] * (1/fps) + Global.animation_timer.start() else: match animation_loop: 0: # No loop @@ -257,6 +275,8 @@ func _on_AnimationTimer_timeout() -> void: Global.animation_timer.stop() 1: # Cycle loop Global.current_project.current_frame = last_frame + Global.animation_timer.wait_time = Global.current_project.frame_duration[Global.current_project.current_frame] * (1/fps) + Global.animation_timer.start() 2: # Ping pong loop animation_forward = true _on_AnimationTimer_timeout() @@ -290,7 +310,8 @@ func play_animation(play : bool, forward_dir : bool) -> void: Global.play_forward.connect("toggled", self, "_on_PlayForward_toggled") if play: - Global.animation_timer.wait_time = 1 / fps + Global.animation_timer.set_one_shot(true) #The wait_time it can't change correctly if it is playing + Global.animation_timer.wait_time = Global.current_project.frame_duration[Global.current_project.current_frame] * (1 / fps) Global.animation_timer.start() animation_forward = forward_dir else: diff --git a/src/UI/Timeline/CelButton.gd b/src/UI/Timeline/CelButton.gd index 55f78c17a..e74ca95a8 100644 --- a/src/UI/Timeline/CelButton.gd +++ b/src/UI/Timeline/CelButton.gd @@ -101,10 +101,22 @@ func _on_PopupMenu_id_pressed(ID : int) -> void: Global.current_project.undo_redo.add_undo_method(Global, "undo") Global.current_project.undo_redo.add_do_method(Global, "redo") Global.current_project.undo_redo.commit_action() - + 5: #Frame Properties + Global.frame_properties.popup_centered() + Global.dialog_open(true) + Global.frame_properties.set_frame_label(frame) + Global.frame_properties.set_frame_dur(Global.current_project.frame_duration[frame]) func change_frame_order(rate : int) -> void: var change = frame + rate + var frame_duration : Array = Global.current_project.frame_duration.duplicate() + if rate > 0: #There is no function in the class Array in godot to make this quickly and this is the fastest way to swap positions I think of + frame_duration.insert(change + 1, frame_duration[frame]) + frame_duration.remove(frame) + else: + frame_duration.insert(change, frame_duration[frame]) + frame_duration.remove(frame + 1) + var new_frames : Array = Global.current_project.frames.duplicate() var temp = new_frames[frame] new_frames[frame] = new_frames[change] @@ -112,12 +124,14 @@ func change_frame_order(rate : int) -> void: 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_do_property(Global.current_project, "frame_duration", frame_duration) if Global.current_project.current_frame == frame: Global.current_project.undo_redo.add_do_property(Global.current_project, "current_frame", change) 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", Global.current_project.frames) + Global.current_project.undo_redo.add_undo_property(Global.current_project, "frame_duration", Global.current_project.frame_duration) Global.current_project.undo_redo.add_undo_method(Global, "undo") Global.current_project.undo_redo.add_do_method(Global, "redo") diff --git a/src/UI/Timeline/CelButton.tscn b/src/UI/Timeline/CelButton.tscn index 54c1c7607..e8fd237c7 100644 --- a/src/UI/Timeline/CelButton.tscn +++ b/src/UI/Timeline/CelButton.tscn @@ -43,10 +43,12 @@ margin_bottom = 0.0 margin_right = 20.0 margin_bottom = 20.0 mouse_default_cursor_shape = 2 -items = [ "Remove Frame", null, 0, false, true, -1, 0, null, "", false, "Clone Frame", null, 0, false, false, -1, 0, null, "", false, "Move Left", null, 0, false, true, -1, 0, null, "", false, "Move Right", null, 0, false, true, -1, 0, null, "", false, "Link Cel", null, 0, false, false, -1, 0, null, "", false ] +items = [ "Remove Frame", null, 0, false, true, -1, 0, null, "", false, "Clone Frame", null, 0, false, false, -1, 0, null, "", false, "Move Left", null, 0, false, true, -1, 0, null, "", false, "Move Right", null, 0, false, true, -1, 0, null, "", false, "Link Cel", null, 0, false, false, -1, 0, null, "", false, "Frame Properties", null, 0, false, false, 5, 0, null, "", false ] +__meta__ = { +"_edit_use_anchors_": false +} [node name="LinkedIndicator" type="Polygon2D" parent="."] -visible = false color = Color( 0.0627451, 0.741176, 0.215686, 1 ) invert_enable = true invert_border = 1.0 diff --git a/src/UI/Timeline/FrameProperties.gd b/src/UI/Timeline/FrameProperties.gd new file mode 100644 index 000000000..1237b510f --- /dev/null +++ b/src/UI/Timeline/FrameProperties.gd @@ -0,0 +1,29 @@ +extends ConfirmationDialog + +onready var frame_num = $VBoxContainer/GridContainer/FrameNum +onready var frame_dur = $VBoxContainer/GridContainer/FrameTime + +func set_frame_label(frame : int) -> void: + frame_num.set_text(str(frame + 1)) + +func set_frame_dur(duration : float) -> void: + frame_dur.set_value(duration) + +func _on_FrameProperties_popup_hide() -> void: + Global.dialog_open(false) + +func _on_FrameProperties_confirmed(): + var frame : int = int(frame_num.get_text()) + var duration : float = frame_dur.get_value() + var frame_duration = Global.current_project.frame_duration.duplicate() + frame_duration[frame - 1] = duration + + Global.current_project.undos += 1 + Global.current_project.undo_redo.create_action("Change frame duration") + + Global.current_project.undo_redo.add_do_property(Global.current_project, "frame_duration", frame_duration) + Global.current_project.undo_redo.add_undo_property(Global.current_project, "frame_duration", Global.current_project.frame_duration) + + Global.current_project.undo_redo.add_do_method(Global, "redo") + Global.current_project.undo_redo.add_undo_method(Global, "undo") + Global.current_project.undo_redo.commit_action() diff --git a/src/UI/Timeline/FrameProperties.tscn b/src/UI/Timeline/FrameProperties.tscn new file mode 100644 index 000000000..7bc933b67 --- /dev/null +++ b/src/UI/Timeline/FrameProperties.tscn @@ -0,0 +1,66 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://src/UI/Timeline/FrameProperties.gd" type="Script" id=1] + +[node name="FrameProperties" type="ConfirmationDialog"] +margin_right = 209.0 +margin_bottom = 137.0 +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +margin_left = 8.0 +margin_top = 8.0 +margin_right = 201.0 +margin_bottom = 101.0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Label" type="Label" parent="VBoxContainer"] +margin_right = 193.0 +margin_bottom = 14.0 +text = "Frame properties" + +[node name="HSeparator" type="HSeparator" parent="VBoxContainer"] +margin_top = 18.0 +margin_right = 193.0 +margin_bottom = 22.0 + +[node name="GridContainer" type="GridContainer" parent="VBoxContainer"] +margin_top = 26.0 +margin_right = 193.0 +margin_bottom = 68.0 +columns = 2 + +[node name="Frame" type="Label" parent="VBoxContainer/GridContainer"] +margin_right = 97.0 +margin_bottom = 14.0 +text = "Frame" + +[node name="FrameNum" type="Label" parent="VBoxContainer/GridContainer"] +margin_left = 101.0 +margin_right = 193.0 +margin_bottom = 14.0 +text = "1" + +[node name="FrameDuration" type="Label" parent="VBoxContainer/GridContainer"] +margin_top = 23.0 +margin_right = 97.0 +margin_bottom = 37.0 +text = "Frame duration" + +[node name="FrameTime" type="SpinBox" parent="VBoxContainer/GridContainer"] +margin_left = 101.0 +margin_top = 18.0 +margin_right = 193.0 +margin_bottom = 42.0 +size_flags_horizontal = 3 +step = 0.05 +value = 2.0 +allow_greater = true +suffix = "x" +[connection signal="confirmed" from="." to="." method="_on_FrameProperties_confirmed"] +[connection signal="popup_hide" from="." to="." method="_on_FrameProperties_popup_hide"]