extends ConfirmationDialog enum ImageImportOptions { NEW_TAB, SPRITESHEET_TAB, SPRITESHEET_LAYER, NEW_FRAME, REPLACE_FRAME, NEW_LAYER, PALETTE, BRUSH, PATTERN } enum BrushTypes { FILE, PROJECT, RANDOM } var path: String var image: Image var current_import_option: int = ImageImportOptions.NEW_TAB var spritesheet_horizontal := 1 var spritesheet_vertical := 1 var brush_type: int = BrushTypes.FILE var opened_once = false var is_master: bool = false var hiding: bool = false onready var texture_rect: TextureRect = $VBoxContainer/CenterContainer/TextureRect onready var image_size_label: Label = $VBoxContainer/SizeContainer/ImageSizeLabel onready var frame_size_label: Label = $VBoxContainer/SizeContainer/FrameSizeLabel 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 new_layer_options = $VBoxContainer/HBoxContainer/NewLayerOptions onready var new_brush_options = $VBoxContainer/HBoxContainer/NewBrushOptions onready var new_brush_name = $VBoxContainer/HBoxContainer/NewBrushOptions/BrushName onready var import_options: OptionButton = $VBoxContainer/HBoxContainer/ImportOption onready var apply_all: CheckBox = $VBoxContainer/ApplyAll func _on_PreviewDialog_about_to_show() -> void: if opened_once: return opened_once = true # # order as in ImageImportOptions enum import_options.add_item("New tab") import_options.add_item("Spritesheet (new tab)") import_options.add_item("Spritesheet (new layer)") import_options.add_item("New frame") import_options.add_item("Replace frame") import_options.add_item("New layer") import_options.add_item("New palette") import_options.add_item("New brush") import_options.add_item("New pattern") var img_texture := ImageTexture.new() img_texture.create_from_image(image, 0) texture_rect.texture = img_texture spritesheet_tab_options.get_node("HorizontalFrames").max_value = min( spritesheet_tab_options.get_node("HorizontalFrames").max_value, image.get_size().x ) spritesheet_tab_options.get_node("VerticalFrames").max_value = min( spritesheet_tab_options.get_node("VerticalFrames").max_value, image.get_size().y ) image_size_label.text = ( tr("Image Size") + ": " + str(image.get_size().x) + "×" + str(image.get_size().y) ) frame_size_label.text = ( tr("Frame Size") + ": " + str(image.get_size().x) + "×" + str(image.get_size().y) ) if OpenSave.preview_dialogs.size() > 1: apply_all.visible = true func _on_PreviewDialog_popup_hide() -> void: if hiding: # if the popup is hiding because of master return elif is_master: # if the master is closed then close others too for child in Global.control.get_children(): if "PreviewDialog" in child.name: OpenSave.preview_dialogs.erase(child) child.queue_free() else: # dialogs being closed separately OpenSave.preview_dialogs.erase(self) queue_free() # Call Global.dialog_open() only if it's the only preview dialog opened if OpenSave.preview_dialogs.size() != 0: return Global.dialog_open(false) func _on_PreviewDialog_confirmed() -> void: if is_master: # if the master is confirmed then confirm others too is_master = false synchronize() for child in Global.control.get_children(): if "PreviewDialog" in child.name: child.emit_signal("confirmed") else: if current_import_option == ImageImportOptions.NEW_TAB: OpenSave.open_image_as_new_tab(path, image) elif current_import_option == ImageImportOptions.SPRITESHEET_TAB: OpenSave.open_image_as_spritesheet_tab( path, image, spritesheet_horizontal, spritesheet_vertical ) elif current_import_option == ImageImportOptions.SPRITESHEET_LAYER: var frame_index: int = spritesheet_lay_opt.get_node("AtFrameSpinbox").value - 1 OpenSave.open_image_as_spritesheet_layer( path, image, path.get_basename().get_file(), spritesheet_horizontal, spritesheet_vertical, frame_index ) elif current_import_option == ImageImportOptions.NEW_FRAME: 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.NEW_LAYER: var frame_index: int = new_layer_options.get_node("AtFrameSpinbox").value - 1 OpenSave.open_image_as_new_layer(image, path.get_basename().get_file(), frame_index) elif current_import_option == ImageImportOptions.PALETTE: Palettes.import_palette_from_path(path) elif current_import_option == ImageImportOptions.BRUSH: add_brush() elif current_import_option == ImageImportOptions.PATTERN: var file_name_ext: String = path.get_file() file_name_ext = file_name_replace(file_name_ext, "Patterns") var file_name: String = file_name_ext.get_basename() image.convert(Image.FORMAT_RGBA8) Global.patterns_popup.add(image, file_name) # Copy the image file into the "pixelorama/Patterns" directory var location := "Patterns".plus_file(file_name_ext) var dir = Directory.new() dir.copy(path, Global.directory_module.xdg_data_home.plus_file(location)) func _on_ApplyAll_toggled(pressed) -> void: is_master = pressed # below 4 (and the last) line is needed for correct popup placement var old_rect = get_rect() disconnect("popup_hide", self, "_on_PreviewDialog_popup_hide") hide() connect("popup_hide", self, "_on_PreviewDialog_popup_hide") for child in Global.control.get_children(): if child != self and "PreviewDialog" in child.name: child.hiding = pressed if pressed: child.hide() synchronize() else: child.popup_centered() popup(old_rect) # needed for correct popup_order func synchronize() -> void: for child in Global.control.get_children(): if child != self and "PreviewDialog" in child.name: var dialog = child #sync modes var id = current_import_option dialog.import_options.select(id) dialog.import_options.emit_signal("item_selected", id) #sync properties (if any) if ( id == ImageImportOptions.SPRITESHEET_TAB or id == ImageImportOptions.SPRITESHEET_LAYER ): dialog.spritesheet_tab_options.get_node("HorizontalFrames").value = min( spritesheet_tab_options.get_node("HorizontalFrames").value, image.get_size().x ) dialog.spritesheet_tab_options.get_node("VerticalFrames").value = min( spritesheet_tab_options.get_node("VerticalFrames").value, image.get_size().y ) if id == ImageImportOptions.SPRITESHEET_LAYER: dialog.spritesheet_lay_opt.get_node("AtFrameSpinbox").value = (spritesheet_lay_opt.get_node( "AtFrameSpinbox" ).value) elif id == ImageImportOptions.NEW_FRAME: dialog.new_frame_options.get_node("AtLayerSpinbox").value = (new_frame_options.get_node( "AtLayerSpinbox" ).value) elif id == ImageImportOptions.REPLACE_FRAME: dialog.replace_frame_options.get_node("AtLayerSpinbox").value = (replace_frame_options.get_node( "AtLayerSpinbox" ).value) dialog.replace_frame_options.get_node("AtFrameSpinbox").value = (replace_frame_options.get_node( "AtFrameSpinbox" ).value) elif id == ImageImportOptions.NEW_LAYER: dialog.new_layer_options.get_node("AtFrameSpinbox").value = (new_layer_options.get_node( "AtFrameSpinbox" ).value) elif id == ImageImportOptions.BRUSH: var type = new_brush_options.get_node("BrushTypeOption").selected dialog.new_brush_options.get_node("BrushTypeOption").select(type) dialog.new_brush_options.get_node("BrushTypeOption").emit_signal( "item_selected", type ) func _on_ImportOption_item_selected(id: int) -> void: current_import_option = id frame_size_label.visible = false spritesheet_tab_options.visible = false spritesheet_lay_opt.visible = false new_frame_options.visible = false replace_frame_options.visible = false new_layer_options.visible = false new_brush_options.visible = false texture_rect.get_child(0).visible = false texture_rect.get_child(1).visible = false rect_size.x = 550 if id == ImageImportOptions.SPRITESHEET_TAB: frame_size_label.visible = true spritesheet_tab_options.visible = true texture_rect.get_child(0).visible = true texture_rect.get_child(1).visible = true rect_size.x = spritesheet_tab_options.rect_size.x elif id == ImageImportOptions.SPRITESHEET_LAYER: frame_size_label.visible = true spritesheet_tab_options.visible = true spritesheet_lay_opt.visible = true texture_rect.get_child(0).visible = true texture_rect.get_child(1).visible = true rect_size.x = spritesheet_lay_opt.rect_size.x elif id == ImageImportOptions.NEW_FRAME: new_frame_options.visible = true new_frame_options.get_node("AtLayerSpinbox").max_value = ( Global.current_project.layers.size() - 1 ) elif id == ImageImportOptions.REPLACE_FRAME: replace_frame_options.visible = true replace_frame_options.get_node("AtLayerSpinbox").max_value = ( Global.current_project.layers.size() - 1 ) var at_frame_spinbox: SpinBox = replace_frame_options.get_node("AtFrameSpinbox") at_frame_spinbox.max_value = Global.current_project.frames.size() elif id == ImageImportOptions.NEW_LAYER: new_layer_options.visible = true new_layer_options.get_node("AtFrameSpinbox").max_value = Global.current_project.frames.size() elif id == ImageImportOptions.BRUSH: new_brush_options.visible = true func _on_HorizontalFrames_value_changed(value: int) -> void: spritesheet_horizontal = value for child in texture_rect.get_node("HorizLines").get_children(): child.queue_free() spritesheet_frame_value_changed(value, false) func _on_VerticalFrames_value_changed(value: int) -> void: spritesheet_vertical = value for child in texture_rect.get_node("VerticalLines").get_children(): child.queue_free() spritesheet_frame_value_changed(value, true) func spritesheet_frame_value_changed(value: int, vertical: bool) -> void: var image_size_y = texture_rect.rect_size.y var image_size_x = texture_rect.rect_size.x if image.get_size().x > image.get_size().y: var scale_ratio = image.get_size().x / image_size_x image_size_y = image.get_size().y / scale_ratio else: var scale_ratio = image.get_size().y / image_size_y image_size_x = image.get_size().x / scale_ratio var offset_x = (texture_rect.rect_size.x - image_size_x) / 2 var offset_y = (texture_rect.rect_size.y - image_size_y) / 2 if value > 1: var line_distance if vertical: line_distance = image_size_y / value else: line_distance = image_size_x / value for i in range(1, value): var line_2d := Line2D.new() line_2d.width = 1 line_2d.position = Vector2.ZERO if vertical: line_2d.add_point(Vector2(offset_x, i * line_distance + offset_y)) line_2d.add_point(Vector2(image_size_x + offset_x, i * line_distance + offset_y)) texture_rect.get_node("VerticalLines").add_child(line_2d) else: line_2d.add_point(Vector2(i * line_distance + offset_x, offset_y)) line_2d.add_point(Vector2(i * line_distance + offset_x, image_size_y + offset_y)) texture_rect.get_node("HorizLines").add_child(line_2d) var frame_width = floor(image.get_size().x / spritesheet_horizontal) var frame_height = floor(image.get_size().y / spritesheet_vertical) frame_size_label.text = tr("Frame Size") + ": " + str(frame_width) + "×" + str(frame_height) func _on_BrushTypeOption_item_selected(index: int) -> void: brush_type = index new_brush_name.visible = false if brush_type == BrushTypes.RANDOM: new_brush_name.visible = true func add_brush() -> void: image.convert(Image.FORMAT_RGBA8) if brush_type == BrushTypes.FILE: var file_name_ext: String = path.get_file() file_name_ext = file_name_replace(file_name_ext, "Brushes") var file_name: String = file_name_ext.get_basename() Brushes.add_file_brush([image], file_name) # Copy the image file into the "pixelorama/Brushes" directory var location := "Brushes".plus_file(file_name_ext) var dir = Directory.new() dir.copy(path, Global.directory_module.xdg_data_home.plus_file(location)) elif brush_type == BrushTypes.PROJECT: var file_name: String = path.get_file().get_basename() Global.current_project.brushes.append(image) Brushes.add_project_brush(image, file_name) elif brush_type == BrushTypes.RANDOM: var brush_name = new_brush_name.get_node("BrushNameLineEdit").text.to_lower() if !brush_name.is_valid_filename(): return var dir := Directory.new() dir.open(Global.directory_module.xdg_data_home.plus_file("Brushes")) if !dir.dir_exists(brush_name): dir.make_dir(brush_name) dir.open(Global.directory_module.xdg_data_home.plus_file("Brushes").plus_file(brush_name)) var random_brushes := [] dir.list_dir_begin() var curr_file := dir.get_next() while curr_file != "": if curr_file.begins_with("~") and brush_name in curr_file: random_brushes.append(curr_file) curr_file = dir.get_next() dir.list_dir_end() var file_ext: String = path.get_file().get_extension() var index: int = random_brushes.size() + 1 var file_name = "~" + brush_name + str(index) + "." + file_ext var location := "Brushes".plus_file(brush_name).plus_file(file_name) dir.copy(path, Global.directory_module.xdg_data_home.plus_file(location)) # Checks if the file already exists # If it does, add a number to its name, for example # "Brush_Name" will become "Brush_Name (2)", "Brush_Name (3)", etc. func file_name_replace(name: String, folder: String) -> String: var i := 1 var file_ext = name.get_extension() var temp_name := name var dir := Directory.new() dir.open(Global.directory_module.xdg_data_home.plus_file(folder)) while dir.file_exists(temp_name): i += 1 temp_name = name.get_basename() + " (%s)" % i temp_name += "." + file_ext name = temp_name return name