Created a Projects class

A Project class contains project-specific data like name, undo_redo, frames, layers, tags and brushes. These variables have been moved from Global. This is the first step towards multiple tab support, where each tab will be a different Project.
This commit is contained in:
OverloadedOrama 2020-06-04 21:05:36 +03:00
parent 9d38cbd13e
commit 4e111a7ac0
21 changed files with 656 additions and 627 deletions

View file

@ -86,7 +86,7 @@ func draw_brush(sprite : Image, pos : Vector2, color : Color, current_mouse_butt
var brush_index : int = Global.custom_brush_indexes[current_mouse_button]
var custom_brush_image : Image
if brush_type != Global.Brush_Types.RANDOM_FILE:
custom_brush_image = Global.custom_brush_images[current_mouse_button]
custom_brush_image = Global.current_project.brush_images[current_mouse_button]
else: # Handle random brush
var brush_button = Global.file_brush_container.get_child(brush_index + 3)
var random_index = randi() % brush_button.random_brushes.size()
@ -145,7 +145,7 @@ func draw_brush(sprite : Image, pos : Vector2, color : Color, current_mouse_butt
else: # if it's transparent - if it's the eraser
var custom_brush := Image.new()
custom_brush.copy_from(Global.custom_brushes[brush_index])
custom_brush.copy_from(Global.current_project.brushes[brush_index])
custom_brush_size = custom_brush.get_size()
custom_brush.resize(custom_brush_size.x * brush_size, custom_brush_size.y * brush_size, Image.INTERPOLATE_NEAREST)
var custom_brush_blended = Global.blend_image_with_color(custom_brush, color, 1)

View file

@ -24,22 +24,18 @@ var config_cache := ConfigFile.new()
var XDGDataPaths = preload("res://src/XDGDataPaths.gd")
var directory_module : Reference
var projects := [] # Array of Projects
var current_project : Project
var current_project_index := 0 setget project_changed
# Indices are as in the Direction enum
# This is the total time the key for
# that direction has been pressed.
var key_move_press_time := [0.0, 0.0, 0.0, 0.0]
var loaded_locales : Array
var undo_redo : UndoRedo
var undos := 0 # The number of times we added undo properties
var project_has_changed := false # Checks if the user has made changes to the project
# Canvas related stuff
var frames := [] setget frames_changed
var layers := [] setget layers_changed
var layers_changed_skip := false
var current_frame := 0 setget frame_changed
var current_layer := 0 setget layer_changed
var can_draw := false
@ -51,9 +47,7 @@ var cursor_image = preload("res://assets/graphics/cursor_icons/cursor.png")
var left_cursor_tool_texture : ImageTexture
var right_cursor_tool_texture : ImageTexture
var selected_pixels := []
var image_clipboard : Image
var animation_tags := [] setget animation_tags_changed
var play_only_tags := true
var theme_type : int = Theme_Types.DARK
@ -116,10 +110,7 @@ var left_circle_points := []
var right_circle_points := []
var brushes_from_files := 0
var custom_brushes := []
var custom_brush_indexes := [-1, -1]
var custom_brush_images := [Image.new(), Image.new()]
var custom_brush_textures := [ImageTexture.new(), ImageTexture.new()]
# Patterns
var patterns := []
@ -238,8 +229,8 @@ func _ready() -> void:
# The fact that root_dir is set earlier than this is important
# XDGDataDirs depends on it nyaa
directory_module = XDGDataPaths.new()
undo_redo = UndoRedo.new()
projects.append(Project.new())
current_project = projects[0]
image_clipboard = Image.new()
var root = get_tree().get_root()
@ -361,8 +352,6 @@ func _ready() -> void:
error_dialog = find_node_by_name(root, "ErrorDialog")
layers.append(Layer.new())
# Thanks to https://godotengine.org/qa/17524/how-to-find-an-instanced-scene-by-its-name
func find_node_by_name(root : Node, node_name : String) -> Node:
@ -386,28 +375,28 @@ func notification_label(text : String) -> void:
func general_undo() -> void:
undos -= 1
var action_name := undo_redo.get_current_action_name()
current_project.undos -= 1
var action_name : String = current_project.undo_redo.get_current_action_name()
notification_label("Undo: %s" % action_name)
func general_redo() -> void:
if undos < undo_redo.get_version(): # If we did undo and then redo
undos = undo_redo.get_version()
if current_project.undos < current_project.undo_redo.get_version(): # If we did undo and then redo
current_project.undos = current_project.undo_redo.get_version()
if control.redone:
var action_name := undo_redo.get_current_action_name()
var action_name : String = current_project.undo_redo.get_current_action_name()
notification_label("Redo: %s" % action_name)
func undo(_frame_index := -1, _layer_index := -1) -> void:
general_undo()
var action_name := undo_redo.get_current_action_name()
var action_name : String = current_project.undo_redo.get_current_action_name()
if action_name == "Draw" or action_name == "Rectangle Select" or action_name == "Scale" or action_name == "Merge Layer" or action_name == "Link Cel" or action_name == "Unlink Cel":
if _layer_index > -1 and _frame_index > -1:
canvas.update_texture(_layer_index, _frame_index)
else:
for i in frames.size():
for j in layers.size():
for i in current_project.frames.size():
for j in current_project.layers.size():
canvas.update_texture(j, i)
if action_name == "Scale":
@ -415,40 +404,40 @@ func undo(_frame_index := -1, _layer_index := -1) -> void:
elif "Frame" in action_name:
# This actually means that frames.size is one, but it hasn't been updated yet
if frames.size() == 2: # Stop animating
if current_project.frames.size() == 2: # Stop animating
play_forward.pressed = false
play_backwards.pressed = false
animation_timer.stop()
canvas.update()
if !project_has_changed:
project_has_changed = true
if !current_project.has_changed:
current_project.has_changed = true
self.window_title = window_title + "(*)"
func redo(_frame_index := -1, _layer_index := -1) -> void:
general_redo()
var action_name := undo_redo.get_current_action_name()
var action_name : String = current_project.undo_redo.get_current_action_name()
if action_name == "Draw" or action_name == "Rectangle Select" or action_name == "Scale" or action_name == "Merge Layer" or action_name == "Link Cel" or action_name == "Unlink Cel":
if _layer_index > -1 and _frame_index > -1:
canvas.update_texture(_layer_index, _frame_index)
else:
for i in frames.size():
for j in layers.size():
for i in current_project.frames.size():
for j in current_project.layers.size():
canvas.update_texture(j, i)
if action_name == "Scale":
canvas.camera_zoom()
elif "Frame" in action_name:
if frames.size() == 1: # Stop animating
if current_project.frames.size() == 1: # Stop animating
play_forward.pressed = false
play_backwards.pressed = false
animation_timer.stop()
canvas.update()
if !project_has_changed:
project_has_changed = true
if !current_project.has_changed:
current_project.has_changed = true
self.window_title = window_title + "(*)"
@ -457,52 +446,15 @@ func title_changed(value : String) -> void:
OS.set_window_title(value)
func frames_changed(value : Array) -> void:
frames = value
for container in frames_container.get_children():
for button in container.get_children():
container.remove_child(button)
button.queue_free()
frames_container.remove_child(container)
for frame_id in frame_ids.get_children():
frame_ids.remove_child(frame_id)
frame_id.queue_free()
for i in range(layers.size() - 1, -1, -1):
frames_container.add_child(layers[i].frame_container)
for j in range(frames.size()):
var label := Label.new()
label.rect_min_size.x = 36
label.align = Label.ALIGN_CENTER
label.text = str(j + 1)
frame_ids.add_child(label)
for i in range(layers.size() - 1, -1, -1):
var cel_button = load("res://src/UI/Timeline/CelButton.tscn").instance()
cel_button.frame = j
cel_button.layer = i
cel_button.get_child(0).texture = frames[j].cels[i].image_texture
layers[i].frame_container.add_child(cel_button)
# This is useful in case tagged frames get deleted 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
animation_timeline.first_frame = 0
animation_timeline.last_frame = frames.size() - 1
if play_only_tags:
for tag in animation_tags:
if current_frame + 1 >= tag.from && current_frame + 1 <= tag.to:
animation_timeline.first_frame = tag.from - 1
animation_timeline.last_frame = min(frames.size() - 1, tag.to - 1)
func project_changed(value : int) -> void:
current_project_index = value
current_project = projects[value]
func clear_frames() -> void:
frames.clear()
animation_tags.clear()
self.animation_tags = animation_tags # To execute animation_tags_changed()
current_project.frames.clear()
current_project.animation_tags.clear()
current_project.animation_tags = current_project.animation_tags # To execute animation_tags_changed()
# Stop playing the animation
play_backwards.pressed = false
@ -514,120 +466,7 @@ func clear_frames() -> void:
control.get_node("ExportDialog").was_exported = false
control.file_menu.set_item_text(3, tr("Save..."))
control.file_menu.set_item_text(6, tr("Export..."))
undo_redo.clear_history(false)
func layers_changed(value : Array) -> void:
layers = value
if layers_changed_skip:
layers_changed_skip = false
return
for container in layers_container.get_children():
container.queue_free()
for container in frames_container.get_children():
for button in container.get_children():
container.remove_child(button)
button.queue_free()
frames_container.remove_child(container)
for i in range(layers.size() - 1, -1, -1):
var layer_container = load("res://src/UI/Timeline/LayerButton.tscn").instance()
layer_container.i = i
if layers[i].name == tr("Layer") + " 0":
layers[i].name = tr("Layer") + " %s" % i
layers_container.add_child(layer_container)
layer_container.label.text = layers[i].name
layer_container.line_edit.text = layers[i].name
frames_container.add_child(layers[i].frame_container)
for j in range(frames.size()):
var cel_button = load("res://src/UI/Timeline/CelButton.tscn").instance()
cel_button.frame = j
cel_button.layer = i
cel_button.get_child(0).texture = frames[j].cels[i].image_texture
layers[i].frame_container.add_child(cel_button)
var layer_button = layers_container.get_child(layers_container.get_child_count() - 1 - current_layer)
layer_button.pressed = true
self.current_frame = current_frame # Call frame_changed to update UI
if layers[current_layer].locked:
disable_button(remove_layer_button, true)
if layers.size() == 1:
disable_button(remove_layer_button, true)
disable_button(move_up_layer_button, true)
disable_button(move_down_layer_button, true)
disable_button(merge_down_layer_button, true)
elif !layers[current_layer].locked:
disable_button(remove_layer_button, false)
func frame_changed(value : int) -> void:
current_frame = value
current_frame_mark_label.text = "%s/%s" % [str(current_frame + 1), frames.size()]
for i in frames.size(): # De-select all the other frames
var text_color := Color.white
if theme_type == Theme_Types.CARAMEL || theme_type == Theme_Types.LIGHT:
text_color = Color.black
frame_ids.get_child(i).add_color_override("font_color", text_color)
for layer in layers:
if i < layer.frame_container.get_child_count():
layer.frame_container.get_child(i).pressed = false
# Select the new frame
frame_ids.get_child(current_frame).add_color_override("font_color", control.theme.get_color("Selected Color", "Label"))
if current_frame < layers[current_layer].frame_container.get_child_count():
layers[current_layer].frame_container.get_child(current_frame).pressed = true
if frames.size() == 1:
disable_button(remove_frame_button, true)
elif !layers[current_layer].locked:
disable_button(remove_frame_button, false)
Global.canvas.update()
Global.transparent_checker._ready() # To update the rect size
func layer_changed(value : int) -> void:
current_layer = value
if current_frame < frames.size():
layer_opacity_slider.value = frames[current_frame].cels[current_layer].opacity * 100
layer_opacity_spinbox.value = frames[current_frame].cels[current_layer].opacity * 100
for container in layers_container.get_children():
container.pressed = false
if current_layer < layers_container.get_child_count():
var layer_button = layers_container.get_child(layers_container.get_child_count() - 1 - current_layer)
layer_button.pressed = true
if current_layer < layers.size() - 1:
disable_button(move_up_layer_button, false)
else:
disable_button(move_up_layer_button, true)
if current_layer > 0:
disable_button(move_down_layer_button, false)
disable_button(merge_down_layer_button, false)
else:
disable_button(move_down_layer_button, true)
disable_button(merge_down_layer_button, true)
if current_layer < layers.size():
if layers[current_layer].locked:
disable_button(remove_layer_button, true)
else:
if layers.size() > 1:
disable_button(remove_layer_button, false)
yield(get_tree().create_timer(0.01), "timeout")
self.current_frame = current_frame # Call frame_changed to update UI
current_project.undo_redo.clear_history(false)
func dialog_open(open : bool) -> void:
@ -668,39 +507,6 @@ func change_button_texturerect(texture_button : TextureRect, new_file_name : Str
texture_button.texture = load(directory_path.plus_file(new_file_name))
func animation_tags_changed(value : Array) -> void:
animation_tags = value
for child in tag_container.get_children():
child.queue_free()
for tag in animation_tags:
var tag_c : Container = load("res://src/UI/Timeline/AnimationTag.tscn").instance()
tag_container.add_child(tag_c)
var tag_position := tag_container.get_child_count() - 1
tag_container.move_child(tag_c, tag_position)
tag_c.get_node("Label").text = tag.name
tag_c.get_node("Label").modulate = tag.color
tag_c.get_node("Line2D").default_color = tag.color
tag_c.rect_position.x = (tag.from - 1) * 39 + tag.from
var size : int = tag.to - tag.from
tag_c.rect_min_size.x = (size + 1) * 39
tag_c.get_node("Line2D").points[2] = Vector2(tag_c.rect_min_size.x, 0)
tag_c.get_node("Line2D").points[3] = Vector2(tag_c.rect_min_size.x, 32)
# 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
animation_timeline.first_frame = 0
animation_timeline.last_frame = frames.size() - 1
if play_only_tags:
for tag in animation_tags:
if current_frame + 1 >= tag.from && current_frame + 1 <= tag.to:
animation_timeline.first_frame = tag.from - 1
animation_timeline.last_frame = min(frames.size() - 1, tag.to - 1)
func update_hint_tooltips() -> void:
var root = get_tree().get_root()
@ -785,7 +591,7 @@ func create_brush_button(brush_img : Image, brush_type := Brush_Types.CUSTOM, hi
var brush_container
var brush_button = load("res://src/UI/BrushButton.tscn").instance()
brush_button.brush_type = brush_type
brush_button.custom_brush_index = custom_brushes.size() - 1
brush_button.custom_brush_index = current_project.brushes.size() - 1
if brush_type == Brush_Types.FILE || brush_type == Brush_Types.RANDOM_FILE:
brush_container = file_brush_container
else:
@ -809,7 +615,7 @@ func remove_brush_buttons() -> void:
func undo_custom_brush(_brush_button : BaseButton = null) -> void:
general_undo()
var action_name := undo_redo.get_current_action_name()
var action_name : String = current_project.undo_redo.get_current_action_name()
if action_name == "Delete Custom Brush":
project_brush_container.add_child(_brush_button)
project_brush_container.move_child(_brush_button, _brush_button.custom_brush_index - brushes_from_files)
@ -818,7 +624,7 @@ func undo_custom_brush(_brush_button : BaseButton = null) -> void:
func redo_custom_brush(_brush_button : BaseButton = null) -> void:
general_redo()
var action_name := undo_redo.get_current_action_name()
var action_name : String = current_project.undo_redo.get_current_action_name()
if action_name == "Delete Custom Brush":
project_brush_container.remove_child(_brush_button)
@ -842,13 +648,13 @@ func update_custom_brush(mouse_button : int) -> void:
right_circle_points = plot_circle(brush_sizes[1])
else:
var custom_brush := Image.new()
custom_brush.copy_from(custom_brushes[custom_brush_indexes[mouse_button]])
custom_brush.copy_from(current_project.brushes[custom_brush_indexes[mouse_button]])
var custom_brush_size = custom_brush.get_size()
custom_brush.resize(custom_brush_size.x * brush_sizes[mouse_button], custom_brush_size.y * brush_sizes[mouse_button], Image.INTERPOLATE_NEAREST)
custom_brush_images[mouse_button] = blend_image_with_color(custom_brush, color_pickers[mouse_button].color, interpolate_spinboxes[mouse_button].value / 100)
custom_brush_textures[mouse_button].create_from_image(custom_brush_images[mouse_button], 0)
current_project.brush_images[mouse_button] = blend_image_with_color(custom_brush, color_pickers[mouse_button].color, interpolate_spinboxes[mouse_button].value / 100)
current_project.brush_textures[mouse_button].create_from_image(current_project.brush_images[mouse_button], 0)
brush_type_buttons[mouse_button].get_child(0).texture = custom_brush_textures[mouse_button]
brush_type_buttons[mouse_button].get_child(0).texture = current_project.brush_textures[mouse_button]
func blend_image_with_color(image : Image, color : Color, interpolate_factor : float) -> Image:
@ -902,4 +708,5 @@ func _exit_tree() -> void:
config_cache.save("user://cache.ini")
# Thanks to qarmin from GitHub for pointing this out
undo_redo.free()
for project in projects:
project.undo_redo.free()

View file

@ -111,7 +111,7 @@ func add_randomised_brush(fpaths : Array, tooltip_name : String) -> void:
# The index which this random brush will be at
var next_random_brush_index := Global.file_brush_container.get_child_count()
Global.custom_brushes.append(first_image)
Global.current_project.brushes.append(first_image)
Global.create_brush_button(first_image, Global.Brush_Types.RANDOM_FILE, tooltip_name)
# # Process the rest
for remaining_image in loaded_images:
@ -127,7 +127,7 @@ func add_plain_brush(path: String, tooltip_name: String) -> void:
return
# do the standard conversion thing...
image.convert(Image.FORMAT_RGBA8)
Global.custom_brushes.append(image)
Global.current_project.brushes.append(image)
Global.create_brush_button(image, Global.Brush_Types.FILE, tooltip_name)
@ -214,7 +214,7 @@ func import_brushes(priority_ordered_search_path: Array) -> void:
# Mark this as a processed relpath
processed_subdir_paths[nonrandomised_subdir][relative_path] = true
Global.brushes_from_files = Global.custom_brushes.size()
Global.brushes_from_files = Global.current_project.brushes.size()
func import_patterns(priority_ordered_search_path: Array) -> void:

View file

@ -53,7 +53,7 @@ func open_pxo_file(path : String, untitled_backup : bool = false) -> void:
new_guides = false
var frame := 0
Global.layers.clear()
Global.current_project.layers.clear()
var linked_cels := []
if file_major_version >= 0 and file_minor_version > 6:
@ -66,7 +66,7 @@ func open_pxo_file(path : String, untitled_backup : bool = false) -> void:
linked_cels.append(file.get_var())
var l := Layer.new(layer_name, layer_visibility, layer_lock, HBoxContainer.new(), layer_new_cels_linked, [])
Global.layers.append(l)
Global.current_project.layers.append(l)
global_layer_line = file.get_line()
var frame_line := file.get_line()
@ -84,7 +84,7 @@ func open_pxo_file(path : String, untitled_backup : bool = false) -> void:
var layer_name_old_version = file.get_line()
if frame == 0:
var l := Layer.new(layer_name_old_version)
Global.layers.append(l)
Global.current_project.layers.append(l)
var cel_opacity := 1.0
if file_major_version >= 0 and file_minor_version > 5:
cel_opacity = file.get_float()
@ -94,7 +94,7 @@ func open_pxo_file(path : String, untitled_backup : bool = false) -> void:
frame_class.cels.append(Cel.new(image, cel_opacity))
if file_major_version >= 0 and file_minor_version >= 7:
if frame in linked_cels[layer_i]:
Global.layers[layer_i].linked_cels.append(frame_class)
Global.current_project.layers[layer_i].linked_cels.append(frame_class)
layer_i += 1
layer_line = file.get_line()
@ -115,14 +115,14 @@ func open_pxo_file(path : String, untitled_backup : bool = false) -> void:
guide_line = file.get_line()
Global.canvas.size = Vector2(width, height)
Global.frames.append(frame_class)
Global.current_project.frames.append(frame_class)
frame_line = file.get_line()
frame += 1
Global.frames = Global.frames # Just to call Global.frames_changed
Global.current_layer = Global.layers.size() - 1
Global.current_frame = frame - 1
Global.layers = Global.layers # Just to call Global.layers_changed
Global.current_project.frames = Global.current_project.frames # Just to call Global.frames_changed
Global.current_project.current_layer = Global.current_project.layers.size() - 1
Global.current_project.current_frame = frame - 1
Global.current_project.layers = Global.current_project.layers # Just to call Global.layers_changed
if new_guides:
var guide_line := file.get_line() # "guideline" no pun intended
@ -155,7 +155,7 @@ func open_pxo_file(path : String, untitled_backup : bool = false) -> void:
Global.color_pickers[1].get_picker().add_preset(color)
# Load custom brushes
Global.custom_brushes.resize(Global.brushes_from_files)
Global.current_project.brushes.resize(Global.brushes_from_files)
Global.remove_brush_buttons()
var brush_line := file.get_line()
@ -165,7 +165,7 @@ func open_pxo_file(path : String, untitled_backup : bool = false) -> void:
var buffer := file.get_buffer(b_width * b_height * 4)
var image := Image.new()
image.create_from_data(b_width, b_height, false, Image.FORMAT_RGBA8, buffer)
Global.custom_brushes.append(image)
Global.current_project.brushes.append(image)
Global.create_brush_button(image)
brush_line = file.get_line()
@ -176,8 +176,8 @@ func open_pxo_file(path : String, untitled_backup : bool = false) -> void:
var tag_color : Color = file.get_var()
var tag_from := file.get_8()
var tag_to := file.get_8()
Global.animation_tags.append(AnimationTag.new(tag_name, tag_color, tag_from, tag_to))
Global.animation_tags = Global.animation_tags # To execute animation_tags_changed()
Global.current_project.animation_tags.append(AnimationTag.new(tag_name, tag_color, tag_from, tag_to))
Global.current_project.animation_tags = Global.current_project.animation_tags # To execute animation_tags_changed()
tag_line = file.get_line()
file.close()
@ -187,7 +187,7 @@ func open_pxo_file(path : String, untitled_backup : bool = false) -> void:
# Untitled backup should not change window title and save path
current_save_path = path
Global.window_title = path.get_file() + " - Pixelorama " + Global.current_version
Global.project_has_changed = false
Global.current_project.has_changed = false
func save_pxo_file(path : String, autosave : bool) -> void:
@ -198,7 +198,7 @@ func save_pxo_file(path : String, autosave : bool) -> void:
file.store_line(Global.current_version)
# Store Global layers
for layer in Global.layers:
for layer in Global.current_project.layers:
file.store_line(".")
file.store_line(layer.name)
file.store_8(layer.visible)
@ -206,13 +206,13 @@ func save_pxo_file(path : String, autosave : bool) -> void:
file.store_8(layer.new_cels_linked)
var linked_cels := []
for frame in layer.linked_cels:
linked_cels.append(Global.frames.find(frame))
linked_cels.append(Global.current_project.frames.find(frame))
file.store_var(linked_cels) # Linked cels as cel numbers
file.store_line("END_GLOBAL_LAYERS")
# Store frames
for frame in Global.frames:
for frame in Global.current_project.frames:
file.store_line("--")
file.store_16(Global.canvas.size.x)
file.store_16(Global.canvas.size.y)
@ -248,8 +248,8 @@ func save_pxo_file(path : String, autosave : bool) -> void:
file.store_8(right_brush_size)
# Save custom brushes
for i in range(Global.brushes_from_files, Global.custom_brushes.size()):
var brush = Global.custom_brushes[i]
for i in range(Global.brushes_from_files, Global.current_project.brushes.size()):
var brush = Global.current_project.brushes[i]
file.store_line("/")
file.store_16(brush.get_size().x)
file.store_16(brush.get_size().y)
@ -257,7 +257,7 @@ func save_pxo_file(path : String, autosave : bool) -> void:
file.store_line("END_BRUSHES")
# Store animation tags
for tag in Global.animation_tags:
for tag in Global.current_project.animation_tags:
file.store_line(".T/")
file.store_line(tag.name)
file.store_var(tag.color)
@ -267,8 +267,8 @@ func save_pxo_file(path : String, autosave : bool) -> void:
file.close()
if Global.project_has_changed and not autosave:
Global.project_has_changed = false
if Global.current_project.has_changed and not autosave:
Global.current_project.has_changed = false
if autosave:
Global.notification_label("File autosaved")
@ -342,7 +342,7 @@ func reload_backup_file(project_path : String, backup_path : String) -> void:
if project_path != backup_path:
current_save_path = project_path
Global.window_title = project_path.get_file() + " - Pixelorama(*) " + Global.current_version
Global.project_has_changed = true
Global.current_project.has_changed = true
Global.notification_label("Backup reloaded")