diff --git a/FileHandler.gd b/FileHandler.gd index d797f00d..5be7d1a6 100644 --- a/FileHandler.gd +++ b/FileHandler.gd @@ -17,60 +17,50 @@ static func create_directory_if_missing(path: String): if success != OK: print("Error: Could not create data folder:", path) -static func generate_unique_file_name(base_name: String, extension: String, destination_folder: String) -> String: - var unique_name: String = base_name - var counter: int = 1 - var new_file_path: String = destination_folder.plus_file(unique_name + "." + extension) - - while File.new().file_exists(new_file_path): - unique_name = base_name + "_" + str(counter) - new_file_path = destination_folder.plus_file(unique_name + "." + extension) - counter += 1 - return unique_name + "." + extension +static func find_file_duplicate(directory_path: String, target_name: String, target_content: PoolByteArray, relative_path: String): + var dir = Directory.new() + if dir.open(directory_path) == OK: + dir.list_dir_begin(true) + var file_name = dir.get_next() + while file_name != "": + var full_path = directory_path.plus_file(file_name) + var current_relative_path = relative_path.plus_file(file_name) + if dir.current_is_dir(): + var found_path = find_file_duplicate(full_path, target_name, target_content, current_relative_path) + if found_path != "": + dir.list_dir_end() + return found_path + if file_name == target_name: + var file = File.new() + file.open(full_path, File.READ) + var file_content = file.get_buffer(file.get_len()) + file.close() + if file_content == target_content: + dir.list_dir_end() + return current_relative_path + file_name = dir.get_next() + return "" -static func copy_supported_image_file(file_path: String, destintation_dir: String) -> String: - # These are all supported file types in Godot but may not be supported - # by other marker programs. - var supported_image_extensions: Array = ["png", "jpg", "jpeg", "bmp", "tga"] +static func find_image_duplicates(file_path: String, destintation_dir: String) -> String: + # These are all supported file types in Godot that are not supported + # by other marker programs. "jpg", "jpeg", "bmp", "tga" var file_name: String = file_path.get_file() var file_extension: String = file_name.get_extension().to_lower() - if not supported_image_extensions.has(file_extension): - print("File is not a supported image type. Please choose a png, jpg, jpeg, bmp, or tga.") + if not file_extension == "png": + print("File is not a supported image type. Please choose a png") return "" - create_directory_if_missing(destintation_dir) - var destination_path: String = destintation_dir.plus_file(file_name) var file: File = File.new() - - if file.file_exists(destination_path): - file.open(file_path, File.READ) - var original_size: int = file.get_len() - var original_mod_time: int = file.get_modified_time(file_name) - file.close() - - file.open(destination_path, File.READ) - var destination_size: int = file.get_len() - var destination_mod_time: int = file.get_modified_time(file_name) - file.close() - - if original_size == destination_size and original_mod_time == destination_mod_time: - return destination_path - else: - var base_name: String = file_name.get_basename() - var extension: String = file_name.get_extension() - var unique_name: String = generate_unique_file_name(base_name, extension, destintation_dir) - destination_path = destintation_dir.plus_file(unique_name) - file.open(file_path, File.READ) - var content: PoolByteArray = file.get_buffer(file.get_len()) - file.close() + var file_content = file.get_buffer(file.get_len()) + var relative_path = find_file_duplicate(destintation_dir, file_name, file_content, "") + return relative_path + - var result: int = file.open(destination_path, File.WRITE) +static func copy_file(file_path: String, destination_path: String): + var dir = Directory.new() + var result = dir.copy(file_path, destination_path) if result == OK: - file.store_buffer(content) - file.close() print("File imported successfully.") - return destination_path else: print("Failed to import file.") - return "" diff --git a/Spatial.gd b/Spatial.gd index 0999a9c8..b93b6ff3 100644 --- a/Spatial.gd +++ b/Spatial.gd @@ -12,7 +12,7 @@ var edit_panel_open: bool = false # This is the path to the texture that will be used for the next created 3d-path # object or icon object in the UI -var next_texture_path: String = "" +var next_texture_id: int = 0 # A pointer to the trail object that any new nodes should be appended to. If # the value is null then a new trail will be created the next time a trail point @@ -340,9 +340,18 @@ func decode_context_packet(spb: StreamPeerBuffer): if self.map_id != old_map_id: print("New Map") + var old_textue_path: String = "" + if self.next_texture_id != 0: + old_textue_path = self.waypoint_data.get_textures()[self.next_texture_id] print("Saving Old Map") print("Loading New Map") load_waypoint_markers(self.map_id) + if old_textue_path != "": + self.next_texture_id = get_texture_index(old_textue_path) + if self.next_texture_id == -1: + self.waypoint_data.add_textures().set_filepath(old_textue_path) + self.next_texture_id = self.waypoint_data.get_textures().size() - 1 + reset_minimap_masks() @@ -558,7 +567,7 @@ func apply_category_visibility_to_nodes(category_item: TreeItem): category_data.category2d.visible = category_data.is_visible -func gen_new_trail(waypoint_trail: Waypoint.Trail, category_item: TreeItem) -> PoolStringArray: +func gen_new_trail(waypoint_trail: Waypoint.Trail, category_item: TreeItem) -> Array: # Create the texture to use from an image file # TODO: We want to be able to cache this data so that if a texture is used # by multiple objects we only need to keep ony copy of it in memory. #22. @@ -567,7 +576,8 @@ func gen_new_trail(waypoint_trail: Waypoint.Trail, category_item: TreeItem) -> P # srgb to render properly. Issue #23. var texture_id: int = waypoint_trail.get_texture_id() if texture_id == null: - print("Warning: No texture found in " , category_item.get_metadata(0).waypoint_category.get_name()) + var category_data = category_item.get_metadata(0) + print("Warning: No texture found in " , category_data.waypoint_category.get_name()) var texture_path: String = self.marker_file_dir + self.waypoint_data.get_textures()[texture_id].get_filepath() var texture_file = File.new() var image = Image.new() @@ -597,16 +607,18 @@ func gen_new_trail(waypoint_trail: Waypoint.Trail, category_item: TreeItem) -> P new_trail2d.refresh_points() category_data.category2d.add_trail2d(new_trail2d) - return PoolStringArray([new_trail3d, new_trail2d]) + return Array([new_trail3d, new_trail2d]) func gen_new_icon(waypoint_icon: Waypoint.Icon, category_item: TreeItem): var texture_id: int = waypoint_icon.get_texture_id() if texture_id == null: - print("Warning: No texture found in " , category_item.get_metadata(0).waypoint_category.get_name()) + var category_data = category_item.get_metadata(0) + print("Warning: No texture found in " , category_data.waypoint_category.get_name()) var texture_path: String = self.marker_file_dir + self.waypoint_data.get_textures()[texture_id].get_filepath() var position = waypoint_icon.get_position() if position == null: - print("Warning: No position found for icon ", category_item.get_metadata(0).waypoint_category.get_name()) + var category_data = category_item.get_metadata(0) + print("Warning: No position found for icon ", category_data.waypoint_category.get_name()) return var position_vector = Vector3(position.get_x(), position.get_y(), -position.get_z()) var new_icon = icon_scene.instance() @@ -752,7 +764,7 @@ func clear_adjustment_nodes(): # Update Waypoint datum ################################################################################ func get_texture_index(path: String) -> int: - for i in self.waypoint_data.get_textures().size: + for i in self.waypoint_data.get_textures().size(): if path == self.waypoint_data.get_textures()[i].get_filepath(): return i return -1 @@ -908,13 +920,23 @@ func _on_ChangeTexture_pressed(): # Set the file that will be used to create a new trail or icon when a new trail # or icon is created. ################################################################################ +var temp_image_file_path: String = "" + func _on_TexturePathOpen_file_selected(path: String): - var data_dir: String = self.marker_file_dir.plus_file("Data") - var new_texture_path: String = FileHandler.copy_supported_image_file(path, data_dir) - if new_texture_path != "": - self.next_texture_path = new_texture_path - else: - print("Warning: Error on selected file") + var new_texture_path: String = FileHandler.find_image_duplicates(path, self.marker_file_dir) + if new_texture_path == "": + self.temp_image_file_path = path + $Control/Dialogs/TexturePathOpen.hide() + $Control/Dialogs/TexturePathSave.show() + $Control/Dialogs/TexturePathSave.set_current_file(path.get_file()) + self.next_texture_id = get_texture_index(path) + +func _on_TexturePathSave_file_selected(path): + FileHandler.copy_file(self.temp_image_file_path, path) + var prefix = self.marker_file_dir + var relative_path = path.substr(prefix.length(), path.length() - prefix.length()) + self.waypoint_data.add_textures().set_filepath(relative_path) + self.next_texture_id = self.waypoint_data.get_textures().size() - 1 ################################################################################ # Null out the currently active trail so that a new one is created the next time @@ -935,13 +957,7 @@ func _on_NewIcon_pressed(): position.set_x(self.player_position.x) position.set_y(self.player_position.y) position.set_z(-self.player_position.z) - var texture_id: int = get_texture_index(self.next_texture_path) - if texture_id != -1: - waypoint_icon.set_texture_id(texture_id) - else: - self.waypoint_data.get_textures().add_textures().set_filepath(self.next_texture_path) - texture_id = self.waypoint_data.get_textures().add_textures().size() - 1 - waypoint_icon.set_texture_id(texture_id) + waypoint_icon.set_texture_id(self.next_texture_id) gen_new_icon(waypoint_icon, self.currently_active_category) # A new trail point is created @@ -956,13 +972,7 @@ func _on_NewTrailPoint_pressed(): trail_data.add_points_x(self.player_position.x) trail_data.add_points_y(self.player_position.y) trail_data.add_points_z(-self.player_position.z) - var texture_id: int = get_texture_index(self.next_texture_path) - if texture_id != -1: - waypoint_trail.set_texture_id(texture_id) - else: - self.waypoint_data.get_textures().add_textures().set_filepath(self.next_texture_path) - texture_id = self.waypoint_data.get_textures().add_textures().size() - 1 - waypoint_trail.set_texture_id(texture_id) + waypoint_trail.set_texture_id(self.next_texture_id) var new_trails: PoolStringArray = gen_new_trail(waypoint_trail, self.currently_active_category) self.currently_active_trail3d = new_trails[0] self.currently_active_trail2d = new_trails[1] diff --git a/Spatial.tscn b/Spatial.tscn index 22a1adfc..a4f24471 100644 --- a/Spatial.tscn +++ b/Spatial.tscn @@ -489,10 +489,10 @@ __meta__ = { } [node name="TexturePathOpen" type="FileDialog" parent="Control/Dialogs"] -margin_left = 740.978 -margin_top = 139.437 -margin_right = 1343.98 -margin_bottom = 602.437 +margin_left = 327.0 +margin_top = 97.0 +margin_right = 930.0 +margin_bottom = 560.0 window_title = "Open a File" mode = 0 access = 1 @@ -503,6 +503,19 @@ __meta__ = { "_edit_use_anchors_": false } +[node name="TexturePathSave" type="FileDialog" parent="Control/Dialogs"] +margin_left = 327.0 +margin_top = 967.0 +margin_right = 930.0 +margin_bottom = 560.0 +access = 1 +filters = PoolStringArray( "*.png" ) +current_dir = "user://protobins" +current_path = "user://protobins/" +__meta__ = { +"_edit_use_anchors_": false +} + [node name="SaveDialog" type="FileDialog" parent="Control/Dialogs"] margin_left = 180.169 margin_top = 105.833 @@ -913,6 +926,8 @@ material/0 = SubResource( 4 ) [connection signal="value_changed" from="Control/Dialogs/RangesDialog/GridContainer/SpinBox7" to="Control/Dialogs/RangesDialog" method="on_change"] [connection signal="file_selected" from="Control/Dialogs/TexturePathOpen" to="." method="_on_TexturePathOpen_file_selected"] [connection signal="hide" from="Control/Dialogs/TexturePathOpen" to="." method="_on_Dialog_hide"] +[connection signal="file_selected" from="Control/Dialogs/TexturePathSave" to="." method="_on_TexturePathSave_file_selected"] +[connection signal="hide" from="Control/Dialogs/TexturePathSave" to="." method="_on_Dialog_hide"] [connection signal="file_selected" from="Control/Dialogs/SaveDialog" to="." method="_on_SaveDialog_file_selected"] [connection signal="hide" from="Control/Dialogs/SaveDialog" to="." method="_on_Dialog_hide"] [connection signal="hide" from="Control/Dialogs/NodeEditorDialog" to="." method="_on_NodeEditorDialog_hide"]