From 8803acd105570246f6538a8baca08b11be39deaf Mon Sep 17 00:00:00 2001 From: Variable <77773850+Variable-ind@users.noreply.github.com> Date: Tue, 2 Aug 2022 20:57:06 +0500 Subject: [PATCH] Tile mode fixes (Heavy testing required) (#723) * Hide/Show options based on current tile option * Changed a condition for tile mode * Simplified tile detection code * Priortize main tile as nearest if mouse is in it * make tile mode draw behind canvas * Changed a condition * Tiles on top gets detected first... ...in case of overlap * Only display relavant options according to current mode * Update preview according to.. ..current mode * removed print() * Added tile masking * Added tile masking * Compare mask with project size only masks with same size as project are accepted * Formatting * Added the suggestions * Some minor modifications * detect if a mask is loaded or not * Added tile_mask to project * Cosmetics * added path detection * added option to emit signal instead of loading... ... image directly through OpenSave * Added a way to load mask for HTML5 * formatting * formatting * Formatting * set proper way for saving tile_mask * Formatting * removed whitespace --- src/Autoload/HTML5FileExchange.gd | 11 ++- src/Autoload/OpenSave.gd | 14 +++ src/Classes/Project.gd | 11 ++- src/Classes/Tiles.gd | 85 ++++++++++------- src/Tools/Bucket.gd | 2 +- src/UI/Canvas/Canvas.tscn | 1 + src/UI/Dialogs/TileModeOffsetsDialog.gd | 88 ++++++++++++++++- src/UI/Dialogs/TileModeOffsetsDialog.tscn | 110 ++++++++++++++++++---- 8 files changed, 259 insertions(+), 63 deletions(-) diff --git a/src/Autoload/HTML5FileExchange.gd b/src/Autoload/HTML5FileExchange.gd index 00e361c53..3cbedf364 100644 --- a/src/Autoload/HTML5FileExchange.gd +++ b/src/Autoload/HTML5FileExchange.gd @@ -3,6 +3,7 @@ extends Node # Thanks to Pukkah from GitHub for providing the original code signal in_focus +signal image_loaded # emits a signal for returning loaded image info func _ready() -> void: @@ -70,7 +71,9 @@ func _define_js() -> void: ) -func load_image() -> void: +# If (load_directly = false) then image info (image and it's name) +# will not be directly farwarded it to OpenSave +func load_image(load_directly := true): if OS.get_name() != "HTML5" or !OS.has_feature("JavaScript"): return @@ -97,6 +100,7 @@ func load_image() -> void: var image = Image.new() var image_error + var image_info: Dictionary = {} match image_type: "image/png": image_error = image.load_png_from_buffer(image_data) @@ -111,7 +115,10 @@ func load_image() -> void: print("An error occurred while trying to display the image.") return else: - OpenSave.handle_loading_image(image_name, image) + image_info = {"image": image, "name": image_name} + if load_directly: + OpenSave.handle_loading_image(image_name, image) + emit_signal("image_loaded", image_info) func load_shader() -> void: diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index 10e718eb9..7a554f0b7 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -125,6 +125,17 @@ func open_pxo_file(path: String, untitled_backup: bool = false, replace_empty: b new_project.brushes.append(image) Brushes.add_project_brush(image) + if dict.result.has("tile_mask") and dict.result.has("has_mask"): + if dict.result.has_mask: + var t_width = dict.result.tile_mask.size_x + var t_height = dict.result.tile_mask.size_y + var buffer := file.get_buffer(t_width * t_height * 4) + var image := Image.new() + image.create_from_data(t_width, t_height, false, Image.FORMAT_RGBA8, buffer) + new_project.tiles.tile_mask = image + else: + new_project.tiles.reset_mask() + file.close() if !empty_project: Global.projects.append(new_project) @@ -351,6 +362,9 @@ func save_pxo_file( for brush in project.brushes: file.store_buffer(brush.get_data()) + if project.tiles.has_mask: + file.store_buffer(project.tiles.tile_mask.get_data()) + file.close() if OS.get_name() == "HTML5" and OS.has_feature("JavaScript") and !autosave: diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 4f08ad519..8bfb2c800 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -347,6 +347,10 @@ func serialize() -> Dictionary: for brush in brushes: brush_data.append({"size_x": brush.get_size().x, "size_y": brush.get_size().y}) + var tile_mask_data := { + "size_x": tiles.tile_mask.get_size().x, "size_y": tiles.tile_mask.get_size().y + } + var metadata := _serialize_metadata(self) var project_data := { @@ -354,6 +358,8 @@ func serialize() -> Dictionary: "name": name, "size_x": size.x, "size_y": size.y, + "has_mask": tiles.has_mask, + "tile_mask": tile_mask_data, "tile_mode_x_basis_x": tiles.x_basis.x, "tile_mode_x_basis_y": tiles.x_basis.y, "tile_mode_y_basis_x": tiles.y_basis.x, @@ -383,6 +389,8 @@ func deserialize(dict: Dictionary) -> void: size.y = dict.size_y tiles.tile_size = size selection_bitmap = resize_bitmap(selection_bitmap, size) + if dict.has("has_mask"): + tiles.has_mask = dict.has_mask if dict.has("tile_mode_x_basis_x") and dict.has("tile_mode_x_basis_y"): tiles.x_basis.x = dict.tile_mode_x_basis_x tiles.x_basis.y = dict.tile_mode_x_basis_y @@ -494,6 +502,7 @@ func _size_changed(value: Vector2) -> void: else: tiles.y_basis = Vector2(0, value.y) tiles.tile_size = value + tiles.reset_mask() size = value @@ -760,7 +769,7 @@ func can_pixel_get_drawn( if pixel.x < 0 or pixel.y < 0 or pixel.x >= size.x or pixel.y >= size.y: return false - if tiles.mode != Tiles.MODE.NONE and tiles.get_nearest_tile(pixel).position != Vector2.ZERO: + if tiles.mode != Tiles.MODE.NONE and !tiles.has_point(pixel): return false if has_selection: diff --git a/src/Classes/Tiles.gd b/src/Classes/Tiles.gd index 564bc2c72..61779be80 100644 --- a/src/Classes/Tiles.gd +++ b/src/Classes/Tiles.gd @@ -7,12 +7,16 @@ var mode: int = MODE.NONE var x_basis: Vector2 var y_basis: Vector2 var tile_size: Vector2 +var tile_mask := Image.new() +var has_mask := false func _init(size: Vector2): x_basis = Vector2(size.x, 0) y_basis = Vector2(0, size.y) tile_size = size + tile_mask.create(tile_size.x, tile_size.y, false, Image.FORMAT_RGBA8) + tile_mask.fill(Color.white) func get_bounding_rect() -> Rect2: @@ -41,29 +45,36 @@ func get_bounding_rect() -> Rect2: func get_nearest_tile(point: Vector2) -> Rect2: - var tile_to_screen_space := Transform2D(x_basis, y_basis, Vector2.ZERO) - # Transform2D.basis_xform_inv() is broken so compute the inverse explicitly: - # https://github.com/godotengine/godot/issues/58556 - var screen_to_tile_space := tile_to_screen_space.affine_inverse() - var p := point - tile_size / 2.0 + Vector2(0.5, 0.5) # p relative to center of tiles - var p_tile_space := screen_to_tile_space.basis_xform(p) - var tl_tile := tile_to_screen_space.basis_xform(p_tile_space.floor()) - var tr_tile := tl_tile + x_basis - var bl_tile := tl_tile + y_basis - var br_tile := tl_tile + x_basis + y_basis - var tl_tile_dist := (p - tl_tile).length_squared() - var tr_tile_dist := (p - tr_tile).length_squared() - var bl_tile_dist := (p - bl_tile).length_squared() - var br_tile_dist := (p - br_tile).length_squared() - match [tl_tile_dist, tr_tile_dist, bl_tile_dist, br_tile_dist].min(): - tl_tile_dist: - return Rect2(tl_tile, tile_size) - tr_tile_dist: - return Rect2(tr_tile, tile_size) - bl_tile_dist: - return Rect2(bl_tile, tile_size) - _: - return Rect2(br_tile, tile_size) + var positions = Global.canvas.tile_mode.get_tile_positions() + positions.append(Vector2.ZERO) + + var candidates := [] + for pos in positions: + var test_rect = Rect2(pos, tile_size) + if test_rect.has_point(point): + candidates.append(test_rect) + if candidates.empty(): + return Rect2(Vector2.ZERO, tile_size) + + var final := [] + tile_mask.lock() + for candidate in candidates: + var rel_pos = point - candidate.position + if tile_mask.get_pixelv(rel_pos).a == 1.0: + final.append(candidate) + tile_mask.unlock() + + if final.empty(): + return Rect2(Vector2.ZERO, tile_size) + final.sort_custom(self, "sort_by_height") + return final[0] + + +func sort_by_height(a: Rect2, b: Rect2): + if a.position.y > b.position.y: + return false + else: + return true func get_canon_position(position: Vector2) -> Vector2: @@ -76,15 +87,19 @@ func get_canon_position(position: Vector2) -> Vector2: func has_point(point: Vector2) -> bool: - var screen_to_tile_space := Transform2D(x_basis, y_basis, Vector2.ZERO).affine_inverse() - var nearest_tile := get_nearest_tile(point) - var nearest_tile_tile_space := screen_to_tile_space.basis_xform(nearest_tile.position).round() - match mode: - MODE.BOTH: - return abs(nearest_tile_tile_space.x) <= 1 and abs(nearest_tile_tile_space.y) <= 1 - MODE.X_AXIS: - return abs(nearest_tile_tile_space.x) <= 1 and abs(nearest_tile_tile_space.y) == 0 - MODE.Y_AXIS: - return abs(nearest_tile_tile_space.x) == 0 and abs(nearest_tile_tile_space.y) <= 1 - _: - return nearest_tile_tile_space == Vector2.ZERO + var positions = Global.canvas.tile_mode.get_tile_positions() + positions.append(Vector2.ZERO) # The central tile is included manually + tile_mask.lock() + for tile_pos in positions: + var test_rect = Rect2(tile_pos, tile_size) + var rel_pos = point - tile_pos + if test_rect.has_point(point) and tile_mask.get_pixelv(rel_pos).a == 1.0: + return true + tile_mask.unlock() + return false + + +func reset_mask(): + tile_mask.create(tile_size.x, tile_size.y, false, Image.FORMAT_RGBA8) + tile_mask.fill(Color.white) + has_mask = false diff --git a/src/Tools/Bucket.gd b/src/Tools/Bucket.gd index a762a820c..4f799fc0e 100644 --- a/src/Tools/Bucket.gd +++ b/src/Tools/Bucket.gd @@ -145,7 +145,7 @@ func draw_start(position: Vector2) -> void: Global.canvas.selection.transform_content_confirm() if ( !Global.current_project.layers[Global.current_project.current_layer].can_layer_get_drawn() - or Global.current_project.tiles.get_nearest_tile(position).position != Vector2.ZERO + or !Rect2(Vector2.ZERO, Global.current_project.size).has_point(position) ): return if ( diff --git a/src/UI/Canvas/Canvas.tscn b/src/UI/Canvas/Canvas.tscn index 92d2162ec..37a2127fd 100644 --- a/src/UI/Canvas/Canvas.tscn +++ b/src/UI/Canvas/Canvas.tscn @@ -43,6 +43,7 @@ render_target_update_mode = 3 script = ExtResource( 5 ) [node name="TileMode" type="Node2D" parent="."] +show_behind_parent = true material = SubResource( 1 ) script = ExtResource( 4 ) diff --git a/src/UI/Dialogs/TileModeOffsetsDialog.gd b/src/UI/Dialogs/TileModeOffsetsDialog.gd index ccc14ea21..633ed37d8 100644 --- a/src/UI/Dialogs/TileModeOffsetsDialog.gd +++ b/src/UI/Dialogs/TileModeOffsetsDialog.gd @@ -1,26 +1,62 @@ extends ConfirmationDialog -onready var x_basis_x_spinbox: SpinBox = $VBoxContainer/OptionsContainer/XBasisX -onready var x_basis_y_spinbox: SpinBox = $VBoxContainer/OptionsContainer/XBasisY -onready var y_basis_x_spinbox: SpinBox = $VBoxContainer/OptionsContainer/YBasisX -onready var y_basis_y_spinbox: SpinBox = $VBoxContainer/OptionsContainer/YBasisY +onready var x_basis_x_spinbox: SpinBox = $VBoxContainer/HBoxContainer/OptionsContainer/XBasisX +onready var x_basis_y_spinbox: SpinBox = $VBoxContainer/HBoxContainer/OptionsContainer/XBasisY +onready var y_basis_x_spinbox: SpinBox = $VBoxContainer/HBoxContainer/OptionsContainer/YBasisX +onready var y_basis_y_spinbox: SpinBox = $VBoxContainer/HBoxContainer/OptionsContainer/YBasisY onready var preview_rect: Control = $VBoxContainer/AspectRatioContainer/Preview onready var tile_mode: Node2D = $VBoxContainer/AspectRatioContainer/Preview/TileMode +onready var load_button: Button = $VBoxContainer/HBoxContainer/Mask/LoadMask +onready var mask_hint: TextureRect = $VBoxContainer/HBoxContainer/Mask/MaskHint func _on_TileModeOffsetsDialog_about_to_show() -> void: tile_mode.draw_center = true tile_mode.tiles = Tiles.new(Global.current_project.size) tile_mode.tiles.mode = Tiles.MODE.BOTH + if Global.current_project.tiles.mode != Tiles.MODE.NONE: + tile_mode.tiles.mode = Global.current_project.tiles.mode + if Global.current_project.tiles.mode != Tiles.MODE.NONE: + tile_mode.tiles.mode = Global.current_project.tiles.mode tile_mode.tiles.x_basis = Global.current_project.tiles.x_basis tile_mode.tiles.y_basis = Global.current_project.tiles.y_basis x_basis_x_spinbox.value = tile_mode.tiles.x_basis.x x_basis_y_spinbox.value = tile_mode.tiles.x_basis.y y_basis_x_spinbox.value = tile_mode.tiles.y_basis.x y_basis_y_spinbox.value = tile_mode.tiles.y_basis.y + + _show_options() + if Global.current_project.tiles.mode == Tiles.MODE.X_AXIS: + y_basis_x_spinbox.visible = false + y_basis_y_spinbox.visible = false + $VBoxContainer/HBoxContainer/OptionsContainer/YBasisXLabel.visible = false + $VBoxContainer/HBoxContainer/OptionsContainer/YBasisYLabel.visible = false + elif Global.current_project.tiles.mode == Tiles.MODE.Y_AXIS: + x_basis_x_spinbox.visible = false + x_basis_y_spinbox.visible = false + $VBoxContainer/HBoxContainer/OptionsContainer/XBasisXLabel.visible = false + $VBoxContainer/HBoxContainer/OptionsContainer/XBasisYLabel.visible = false + + load_button.text = "Load Mask" + if Global.current_project.tiles.has_mask: + load_button.text = "Loaded" + var tex := ImageTexture.new() + tex.create_from_image(Global.current_project.tiles.tile_mask) + mask_hint.texture = tex update_preview() +func _show_options(): + x_basis_x_spinbox.visible = true + x_basis_y_spinbox.visible = true + y_basis_x_spinbox.visible = true + y_basis_y_spinbox.visible = true + $VBoxContainer/HBoxContainer/OptionsContainer/YBasisXLabel.visible = true + $VBoxContainer/HBoxContainer/OptionsContainer/YBasisYLabel.visible = true + $VBoxContainer/HBoxContainer/OptionsContainer/XBasisXLabel.visible = true + $VBoxContainer/HBoxContainer/OptionsContainer/XBasisYLabel.visible = true + + func _on_TileModeOffsetsDialog_confirmed() -> void: Global.current_project.tiles.x_basis = tile_mode.tiles.x_basis Global.current_project.tiles.y_basis = tile_mode.tiles.y_basis @@ -81,3 +117,47 @@ func _on_Reset_pressed(): y_basis_x_spinbox.value = 0 y_basis_y_spinbox.value = size.y update_preview() + + +func _on_LoadMask_pressed() -> void: + if OS.get_name() == "HTML5": + Html5FileExchange.connect("image_loaded", self, "_on_html_image_loaded") + Html5FileExchange.load_image(false) + else: + $FileDialog.current_dir = Global.current_project.directory_path + $FileDialog.popup_centered() + + +func _on_html_image_loaded(image_info: Dictionary): + if image_info.has("image"): + load_mask(image_info.image) + Html5FileExchange.disconnect("image_loaded", self, "_on_html_image_loaded") + + +func _on_FileDialog_file_selected(path: String) -> void: + var image := Image.new() + var err := image.load(path) + if err != OK: # An error occured + var file_name: String = path.get_file() + Global.error_dialog.set_text( + tr("Can't load file '%s'.\nError code: %s") % [file_name, str(err)] + ) + Global.error_dialog.popup_centered() + Global.dialog_open(true) + return + if image.get_size() != Global.current_project.size: + Global.error_dialog.set_text(tr("The mask must have the same size as the project")) + Global.error_dialog.popup_centered() + Global.dialog_open(true) + return + + load_mask(image) + + +func load_mask(image: Image): + load_button.text = "Loaded" + Global.current_project.tiles.tile_mask = image + Global.current_project.tiles.has_mask = true + var tex := ImageTexture.new() + tex.create_from_image(Global.current_project.tiles.tile_mask) + mask_hint.texture = tex diff --git a/src/UI/Dialogs/TileModeOffsetsDialog.tscn b/src/UI/Dialogs/TileModeOffsetsDialog.tscn index 71d3d46b0..9277456a2 100644 --- a/src/UI/Dialogs/TileModeOffsetsDialog.tscn +++ b/src/UI/Dialogs/TileModeOffsetsDialog.tscn @@ -18,29 +18,33 @@ script = ExtResource( 3 ) [node name="VBoxContainer" type="VBoxContainer" parent="."] margin_left = 8.0 margin_top = 8.0 -margin_right = 208.0 +margin_right = 293.0 margin_bottom = 362.0 [node name="TileModeOffsets" type="Label" parent="VBoxContainer"] -margin_right = 200.0 +margin_right = 285.0 margin_bottom = 14.0 text = "Tile Mode Offsets" -[node name="OptionsContainer" type="GridContainer" parent="VBoxContainer"] +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] margin_top = 18.0 -margin_right = 200.0 +margin_right = 285.0 margin_bottom = 150.0 + +[node name="OptionsContainer" type="GridContainer" parent="VBoxContainer/HBoxContainer"] +margin_right = 137.0 +margin_bottom = 132.0 custom_constants/vseparation = 4 custom_constants/hseparation = 2 columns = 2 -[node name="XBasisXLabel" type="Label" parent="VBoxContainer/OptionsContainer"] +[node name="XBasisXLabel" type="Label" parent="VBoxContainer/HBoxContainer/OptionsContainer"] margin_top = 5.0 margin_right = 61.0 margin_bottom = 19.0 text = "X-basis x:" -[node name="XBasisX" type="SpinBox" parent="VBoxContainer/OptionsContainer"] +[node name="XBasisX" type="SpinBox" parent="VBoxContainer/HBoxContainer/OptionsContainer"] margin_left = 63.0 margin_right = 137.0 margin_bottom = 24.0 @@ -49,13 +53,13 @@ min_value = -16384.0 max_value = 16384.0 suffix = "px" -[node name="XBasisYLabel" type="Label" parent="VBoxContainer/OptionsContainer"] +[node name="XBasisYLabel" type="Label" parent="VBoxContainer/HBoxContainer/OptionsContainer"] margin_top = 33.0 margin_right = 61.0 margin_bottom = 47.0 text = "X-basis y:" -[node name="XBasisY" type="SpinBox" parent="VBoxContainer/OptionsContainer"] +[node name="XBasisY" type="SpinBox" parent="VBoxContainer/HBoxContainer/OptionsContainer"] margin_left = 63.0 margin_top = 28.0 margin_right = 137.0 @@ -65,13 +69,13 @@ min_value = -16384.0 max_value = 16384.0 suffix = "px" -[node name="YBasisXLabel" type="Label" parent="VBoxContainer/OptionsContainer"] +[node name="YBasisXLabel" type="Label" parent="VBoxContainer/HBoxContainer/OptionsContainer"] margin_top = 61.0 margin_right = 61.0 margin_bottom = 75.0 text = "Y-basis x:" -[node name="YBasisX" type="SpinBox" parent="VBoxContainer/OptionsContainer"] +[node name="YBasisX" type="SpinBox" parent="VBoxContainer/HBoxContainer/OptionsContainer"] margin_left = 63.0 margin_top = 56.0 margin_right = 137.0 @@ -81,13 +85,13 @@ min_value = -16384.0 max_value = 16384.0 suffix = "px" -[node name="YBasisYLabel" type="Label" parent="VBoxContainer/OptionsContainer"] +[node name="YBasisYLabel" type="Label" parent="VBoxContainer/HBoxContainer/OptionsContainer"] margin_top = 89.0 margin_right = 61.0 margin_bottom = 103.0 text = "Y-basis y:" -[node name="YBasisY" type="SpinBox" parent="VBoxContainer/OptionsContainer"] +[node name="YBasisY" type="SpinBox" parent="VBoxContainer/HBoxContainer/OptionsContainer"] margin_left = 63.0 margin_top = 84.0 margin_right = 137.0 @@ -97,20 +101,67 @@ min_value = -16384.0 max_value = 16384.0 suffix = "px" -[node name="Reset" type="Button" parent="VBoxContainer/OptionsContainer"] +[node name="Reset" type="Button" parent="VBoxContainer/HBoxContainer/OptionsContainer"] margin_top = 112.0 margin_right = 61.0 margin_bottom = 132.0 text = "Reset" +[node name="VSeparator" type="VSeparator" parent="VBoxContainer/HBoxContainer"] +margin_left = 141.0 +margin_right = 145.0 +margin_bottom = 132.0 + +[node name="Mask" type="VBoxContainer" parent="VBoxContainer/HBoxContainer"] +margin_left = 149.0 +margin_right = 285.0 +margin_bottom = 132.0 +size_flags_horizontal = 3 + +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/Mask"] +margin_right = 136.0 +margin_bottom = 14.0 +text = "Tile Mask" +align = 1 + +[node name="HSeparator" type="HSeparator" parent="VBoxContainer/HBoxContainer/Mask"] +margin_top = 18.0 +margin_right = 136.0 +margin_bottom = 22.0 + +[node name="MaskHint" type="TextureRect" parent="VBoxContainer/HBoxContainer/Mask"] +margin_top = 26.0 +margin_right = 136.0 +margin_bottom = 100.0 +rect_min_size = Vector2( 136, 74 ) +size_flags_vertical = 3 +expand = true +stretch_mode = 6 + +[node name="HSeparator2" type="HSeparator" parent="VBoxContainer/HBoxContainer/Mask"] +margin_top = 104.0 +margin_right = 136.0 +margin_bottom = 108.0 + +[node name="LoadMask" type="Button" parent="VBoxContainer/HBoxContainer/Mask"] +margin_top = 112.0 +margin_right = 136.0 +margin_bottom = 132.0 +rect_min_size = Vector2( 100, 0 ) +hint_tooltip = "Mask will only allow the drawing to remain within it's bounds +(Used for custom tiles)" +text = "Load Mask" +clip_text = true + [node name="AspectRatioContainer" type="AspectRatioContainer" parent="VBoxContainer"] margin_top = 154.0 -margin_right = 200.0 +margin_right = 285.0 margin_bottom = 354.0 size_flags_vertical = 3 [node name="Preview" type="Control" parent="VBoxContainer/AspectRatioContainer"] -margin_right = 200.0 +margin_left = 42.5 +margin_right = 242.5 margin_bottom = 200.0 rect_min_size = Vector2( 200, 200 ) @@ -125,12 +176,31 @@ anchor_bottom = 1.0 margin_right = 0.0 margin_bottom = 0.0 +[node name="FileDialog" type="FileDialog" parent="."] +margin_left = 8.0 +margin_top = 8.0 +margin_right = 293.0 +margin_bottom = 362.0 +rect_min_size = Vector2( 172, 60.2 ) +window_title = "Open a File" +resizable = true +mode = 0 +access = 2 +filters = PoolStringArray( "*.png ; PNG Image" ) +current_dir = "/home/variable/Documents/Godot/Godot projects/Pixelorama-Tile-mode-Fixes" +current_path = "/home/variable/Documents/Godot/Godot projects/Pixelorama-Tile-mode-Fixes/" +__meta__ = { +"_editor_description_": "" +} + [connection signal="about_to_show" from="." to="." method="_on_TileModeOffsetsDialog_about_to_show"] [connection signal="confirmed" from="." to="." method="_on_TileModeOffsetsDialog_confirmed"] [connection signal="item_rect_changed" from="." to="." method="_on_TileModeOffsetsDialog_item_rect_changed"] [connection signal="popup_hide" from="." to="." method="_on_TileModeOffsetsDialog_popup_hide"] -[connection signal="value_changed" from="VBoxContainer/OptionsContainer/XBasisX" to="." method="_on_XBasisX_value_changed"] -[connection signal="value_changed" from="VBoxContainer/OptionsContainer/XBasisY" to="." method="_on_XBasisY_value_changed"] -[connection signal="value_changed" from="VBoxContainer/OptionsContainer/YBasisX" to="." method="_on_YBasisX_value_changed"] -[connection signal="value_changed" from="VBoxContainer/OptionsContainer/YBasisY" to="." method="_on_YBasisY_value_changed"] -[connection signal="pressed" from="VBoxContainer/OptionsContainer/Reset" to="." method="_on_Reset_pressed"] +[connection signal="value_changed" from="VBoxContainer/HBoxContainer/OptionsContainer/XBasisX" to="." method="_on_XBasisX_value_changed"] +[connection signal="value_changed" from="VBoxContainer/HBoxContainer/OptionsContainer/XBasisY" to="." method="_on_XBasisY_value_changed"] +[connection signal="value_changed" from="VBoxContainer/HBoxContainer/OptionsContainer/YBasisX" to="." method="_on_YBasisX_value_changed"] +[connection signal="value_changed" from="VBoxContainer/HBoxContainer/OptionsContainer/YBasisY" to="." method="_on_YBasisY_value_changed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/OptionsContainer/Reset" to="." method="_on_Reset_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/Mask/LoadMask" to="." method="_on_LoadMask_pressed"] +[connection signal="file_selected" from="FileDialog" to="." method="_on_FileDialog_file_selected"]