diff --git a/Spatial.gd b/Spatial.gd
index f7218f16..0c2d60ec 100644
--- a/Spatial.gd
+++ b/Spatial.gd
@@ -58,6 +58,9 @@ const CategoryData = preload("res://CategoryData.gd")
const Waypoint = preload("res://waypoint.gd")
const FileHandler = preload("res://FileHandler.gd")
+# File path for the the json that contains a hash of the data files
+const HASH_BY_MAP_ID_FILEPATH: String = "user://hash_by_map_id.json"
+
##########Node Connections###########
onready var markers_ui := $Control/Dialogs/CategoriesDialog/MarkersUI as Tree
onready var markers_3d := $Markers3D as Spatial
@@ -341,9 +344,10 @@ 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")
+ if old_map_id != 0 and not read_hash(old_map_id) == make_hash(self.waypoint_data.to_bytes()):
+ print("Saving Old Map")
+ old_textue_path = self.waypoint_data.get_textures()[self.next_texture_id]
+ save_map_data(old_map_id)
print("Loading New Map")
load_waypoint_markers(self.map_id)
if old_textue_path != "":
@@ -390,7 +394,7 @@ func reset_2D_minimap_masks(category2d: Node2D, compass_corner1: Vector2, compas
reset_2D_minimap_masks(subcategory, compass_corner1, compass_corner2)
func reset_3D_minimap_masks(category: Spatial):
- for trail in category.trails:
+ for trail in category.trails3d:
trail.get_node("MeshInstance").material_override.set_shader_param("map_size", Vector2(self.compass_width, self.compass_height))
for icon in category.icons:
icon.material_override.set_shader_param("map_size", Vector2(self.compass_width, self.compass_height))
@@ -399,11 +403,14 @@ func reset_3D_minimap_masks(category: Spatial):
var waypoint_data = Waypoint.Waypoint.new()
-var marker_file_dir = "user://protobins/"
+# We save the marker data in this directory when the files are have been split
+# by Map ID. All changes made by the editor are automatically saved in these
+# files prior to export.
+var unsaved_markers_dir = "user://protobin_by_map_id/"
var marker_file_path = ""
-func load_waypoint_markers(map_id):
- self.marker_file_path = self.marker_file_dir + String(map_id) + ".data"
+func load_waypoint_markers(map_id_to_load: int):
+ self.marker_file_path = self.unsaved_markers_dir + String(map_id_to_load) + ".bin"
self.waypoint_data = Waypoint.Waypoint.new()
clear_map_markers()
init_category_tree()
@@ -548,6 +555,7 @@ func _waypoint_categories_to_godot_nodes(item: TreeItem, waypoint_category: Wayp
for icon in waypoint_category.get_icon():
gen_new_icon(icon, category_item)
+
for category_child in waypoint_category.get_children():
_waypoint_categories_to_godot_nodes(category_item, category_child, godot_category3d, godot_category2d, true)
@@ -596,7 +604,7 @@ func gen_new_trail(waypoint_trail: Waypoint.Trail, category_item: TreeItem) -> A
new_trail3d.refresh_mesh()
new_trail3d.set_texture(texture)
var category_data = category_item.get_metadata(0)
- category_data.category3d.add_trail(new_trail3d)
+ category_data.category3d.add_trail3d(new_trail3d)
# Create a new 2D Trail
@@ -628,31 +636,45 @@ func gen_new_icon(waypoint_icon: Waypoint.Icon, category_item: TreeItem):
var category_data = category_item.get_metadata(0)
category_data.category3d.add_icon(new_icon)
-# This function take all of the currently rendered objects and converts it into
-# the data format that is saved/loaded from.
-func data_from_renderview():
- var icons_data = []
- var paths_data = []
-
- for icon in $Icons.get_children():
- icons_data.append({
- "position": [icon.translation.x, icon.translation.y, -icon.translation.z],
- "texture": icon.texture_path
- })
-
- for path in $Paths.get_children():
- #print(path)
- var points = []
- for point in range(path.get_point_count()):
- var point_position:Vector3 = path.get_point_position(point)
- points.append([point_position.x, point_position.y, -point_position.z])
- paths_data.append({
- "points": points,
- "texture": path.texture_path
- })
-
- var data_out = {"icons": icons_data, "paths": paths_data}
- return data_out
+################################################################################
+# Section of functions for saving data to file
+################################################################################
+func save_map_data(map_id: int):
+ var packed_bytes = self.waypoint_data.to_bytes()
+ var file = File.new()
+ file.open(self.marker_file_path, file.WRITE)
+ file.store_buffer(packed_bytes)
+
+func make_hash(data: PoolByteArray) -> String:
+ var ctx = HashingContext.new()
+ ctx.start(HashingContext.HASH_MD5)
+ ctx.update(data)
+ var res: PoolByteArray = ctx.finish()
+ return res.hex_encode()
+
+
+# Save all hashes
+func save_hashes():
+ var file = File.new()
+ var data = {}
+ var dir = Directory.new()
+ dir.open(self.unsaved_markers_dir)
+ dir.list_dir_begin()
+ var file_name = dir.get_next()
+ while file_name != "":
+ if dir.file_exists(file_name):
+ file.open(file_name, File.READ)
+ data[file_name.get_basename()] = make_hash(file.get_buffer(file.get_len()))
+ file_name = dir.get_next()
+ file.open(HASH_BY_MAP_ID_FILEPATH, File.WRITE)
+ file.store_string(JSON.print(data))
+
+func read_hash(map_id: int) -> String:
+ var file = File.new()
+ if not file.file_exists(HASH_BY_MAP_ID_FILEPATH):
+ return ""
+ file.open(HASH_BY_MAP_ID_FILEPATH, File.READ)
+ return JSON.parse(file.get_as_text()).result.get(String(map_id), "")
################################################################################
# Adjustment and gizmo functions
@@ -1043,6 +1065,8 @@ func _on_ReverseTrailDirection_pressed():
func _on_ExitButton_pressed():
+ if not read_hash(self.map_id) == make_hash(self.waypoint_data.to_bytes()):
+ save_map_data(self.map_id)
exit_burrito()
@@ -1069,3 +1093,17 @@ func _on_MarkersUI_item_edited():
func _on_ImportPath_pressed():
$Control/Dialogs/ImportPackDialog.show()
+
+
+func _on_ImportPackDialog_dir_selected(dir):
+ var user_data_dir = str(OS.get_user_data_dir())
+ var args: PoolStringArray = [
+ "--input-taco-path", dir,
+ # TODO: This line is not working as intended and needs to be investigated
+ # "--input-waypoint-path", user_data_dir.plus_file("protobin"),
+ "--output-waypoint-path", user_data_dir.plus_file("protobin"),
+ "--output-split-waypoint-path", ProjectSettings.globalize_path(self.unsaved_markers_dir)
+ ]
+ FileHandler.call_xml_converter(args)
+ save_hashes()
+ load_waypoint_markers(self.map_id)
diff --git a/Spatial.tscn b/Spatial.tscn
index 4f484ba5..6d3dfc86 100644
--- a/Spatial.tscn
+++ b/Spatial.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=19 format=2]
+[gd_scene load_steps=18 format=2]
[ext_resource path="res://Spatial.gd" type="Script" id=1]
[ext_resource path="res://shaders/range_indicators.shader" type="Shader" id=2]
@@ -12,7 +12,6 @@
[ext_resource path="res://icon_new_point.png" type="Texture" id=11]
[ext_resource path="res://SettingsDialog.gd" type="Script" id=12]
[ext_resource path="res://Category3D.gd" type="Script" id=13]
-[ext_resource path="res://ImportPackDialog.gd" type="Script" id=14]
[ext_resource path="res://Category2D.gd" type="Script" id=15]
[sub_resource type="Shader" id=1]
@@ -193,7 +192,6 @@ mode = 2
access = 2
current_dir = ""
current_path = ""
-script = ExtResource( 14 )
__meta__ = {
"_edit_use_anchors_": false
}
@@ -886,7 +884,7 @@ material/0 = SubResource( 4 )
[connection signal="pressed" from="Control/GlobalMenuButton/EditorQuckPanel/HBoxContainer/NewTrailPoint" to="." method="_on_NewTrailPoint_pressed"]
[connection signal="pressed" from="Control/GlobalMenuButton/EditorQuckPanel/HBoxContainer/NewIcon" to="." method="_on_NewIcon_pressed"]
[connection signal="pressed" from="Control/GlobalMenuButton/EditorQuckPanel/HBoxContainer/AdjustPoints" to="." method="_on_AdjustNodesButton_pressed"]
-[connection signal="dir_selected" from="Control/Dialogs/ImportPackDialog" to="Control/Dialogs/ImportPackDialog" method="_on_FileDialog_dir_selected"]
+[connection signal="dir_selected" from="Control/Dialogs/ImportPackDialog" to="." method="_on_ImportPackDialog_dir_selected"]
[connection signal="hide" from="Control/Dialogs/ImportPackDialog" to="." method="_on_Dialog_hide"]
[connection signal="hide" from="Control/Dialogs/MainMenu" to="." method="_on_Dialog_hide"]
[connection signal="pressed" from="Control/Dialogs/MainMenu/ScrollContainer/VBoxContainer/LoadTrail" to="." method="_on_LoadTrail_pressed"]
@@ -913,7 +911,6 @@ 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/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"]
[connection signal="pressed" from="Control/Dialogs/NodeEditorDialog/ScrollContainer/VBoxContainer/DeleteNode" to="." method="_on_DeleteNode_pressed"]
diff --git a/waypoint.gd b/waypoint.gd
index 2cea1d5a..00c6e815 100644
--- a/waypoint.gd
+++ b/waypoint.gd
@@ -804,6 +804,11 @@ class Category:
service.field = _tip_description
data[_tip_description.tag] = service
+ _id = PBField.new("id", PB_DATA_TYPE.BYTES, PB_RULE.OPTIONAL, 8, true, DEFAULT_VALUES_3[PB_DATA_TYPE.BYTES])
+ service = PBServiceField.new()
+ service.field = _id
+ data[_id.tag] = service
+
var data = {}
var _name: PBField
@@ -875,6 +880,15 @@ class Category:
func set_tip_description(value : String) -> void:
_tip_description.value = value
+ var _id: PBField
+ func get_id() -> PoolByteArray:
+ return _id.value
+ func clear_id() -> void:
+ data[8].state = PB_SERVICE_STATE.UNFILLED
+ _id.value = DEFAULT_VALUES_3[PB_DATA_TYPE.BYTES]
+ func set_id(value : PoolByteArray) -> void:
+ _id.value = value
+
func to_string() -> String:
return PBPacker.message_to_string(data)
@@ -948,16 +962,16 @@ class Icon:
service.func_ref = funcref(self, "new_euler_rotation")
data[_euler_rotation.tag] = service
- _achievement_bit = PBField.new("achievement_bit", PB_DATA_TYPE.FIXED32, PB_RULE.OPTIONAL, 16, true, DEFAULT_VALUES_3[PB_DATA_TYPE.FIXED32])
- service = PBServiceField.new()
- service.field = _achievement_bit
- data[_achievement_bit.tag] = service
-
- _achievement_id = PBField.new("achievement_id", PB_DATA_TYPE.INT32, PB_RULE.OPTIONAL, 17, true, DEFAULT_VALUES_3[PB_DATA_TYPE.INT32])
+ _achievement_id = PBField.new("achievement_id", PB_DATA_TYPE.INT32, PB_RULE.OPTIONAL, 16, true, DEFAULT_VALUES_3[PB_DATA_TYPE.INT32])
service = PBServiceField.new()
service.field = _achievement_id
data[_achievement_id.tag] = service
+ _achievement_bit_index = PBField.new("achievement_bit_index", PB_DATA_TYPE.INT32, PB_RULE.OPTIONAL, 17, true, DEFAULT_VALUES_3[PB_DATA_TYPE.INT32])
+ service = PBServiceField.new()
+ service.field = _achievement_bit_index
+ data[_achievement_bit_index.tag] = service
+
_disable_player_cutout = PBField.new("disable_player_cutout", PB_DATA_TYPE.BOOL, PB_RULE.OPTIONAL, 19, true, DEFAULT_VALUES_3[PB_DATA_TYPE.BOOL])
service = PBServiceField.new()
service.field = _disable_player_cutout
@@ -993,10 +1007,9 @@ class Icon:
service.field = _tip_name
data[_tip_name.tag] = service
- _rgba_color = PBField.new("rgba_color", PB_DATA_TYPE.MESSAGE, PB_RULE.OPTIONAL, 26, true, DEFAULT_VALUES_3[PB_DATA_TYPE.MESSAGE])
+ _rgba_color = PBField.new("rgba_color", PB_DATA_TYPE.FIXED32, PB_RULE.OPTIONAL, 26, true, DEFAULT_VALUES_3[PB_DATA_TYPE.FIXED32])
service = PBServiceField.new()
service.field = _rgba_color
- service.func_ref = funcref(self, "new_rgba_color")
data[_rgba_color.tag] = service
_festival_filter = PBField.new("festival_filter", PB_DATA_TYPE.MESSAGE, PB_RULE.OPTIONAL, 27, true, DEFAULT_VALUES_3[PB_DATA_TYPE.MESSAGE])
@@ -1070,11 +1083,6 @@ class Icon:
service.field = _bhdraft__schedule_duration
data[_bhdraft__schedule_duration.tag] = service
- _category = PBField.new("category", PB_DATA_TYPE.BOOL, PB_RULE.OPTIONAL, 2054, true, DEFAULT_VALUES_3[PB_DATA_TYPE.BOOL])
- service = PBServiceField.new()
- service.field = _category
- data[_category.tag] = service
-
var data = {}
var _texture_id: PBField
@@ -1161,24 +1169,24 @@ class Icon:
_euler_rotation.value = EulerRotation.new()
return _euler_rotation.value
- var _achievement_bit: PBField
- func get_achievement_bit() -> int:
- return _achievement_bit.value
- func clear_achievement_bit() -> void:
- data[16].state = PB_SERVICE_STATE.UNFILLED
- _achievement_bit.value = DEFAULT_VALUES_3[PB_DATA_TYPE.FIXED32]
- func set_achievement_bit(value : int) -> void:
- _achievement_bit.value = value
-
var _achievement_id: PBField
func get_achievement_id() -> int:
return _achievement_id.value
func clear_achievement_id() -> void:
- data[17].state = PB_SERVICE_STATE.UNFILLED
+ data[16].state = PB_SERVICE_STATE.UNFILLED
_achievement_id.value = DEFAULT_VALUES_3[PB_DATA_TYPE.INT32]
func set_achievement_id(value : int) -> void:
_achievement_id.value = value
+ var _achievement_bit_index: PBField
+ func get_achievement_bit_index() -> int:
+ return _achievement_bit_index.value
+ func clear_achievement_bit_index() -> void:
+ data[17].state = PB_SERVICE_STATE.UNFILLED
+ _achievement_bit_index.value = DEFAULT_VALUES_3[PB_DATA_TYPE.INT32]
+ func set_achievement_bit_index(value : int) -> void:
+ _achievement_bit_index.value = value
+
var _disable_player_cutout: PBField
func get_disable_player_cutout() -> bool:
return _disable_player_cutout.value
@@ -1243,14 +1251,13 @@ class Icon:
_tip_name.value = value
var _rgba_color: PBField
- func get_rgba_color() -> RGBAColor:
+ func get_rgba_color() -> int:
return _rgba_color.value
func clear_rgba_color() -> void:
data[26].state = PB_SERVICE_STATE.UNFILLED
- _rgba_color.value = DEFAULT_VALUES_3[PB_DATA_TYPE.MESSAGE]
- func new_rgba_color() -> RGBAColor:
- _rgba_color.value = RGBAColor.new()
- return _rgba_color.value
+ _rgba_color.value = DEFAULT_VALUES_3[PB_DATA_TYPE.FIXED32]
+ func set_rgba_color(value : int) -> void:
+ _rgba_color.value = value
var _festival_filter: PBField
func get_festival_filter() -> FestivalFilter:
@@ -1375,15 +1382,6 @@ class Icon:
func set_bhdraft__schedule_duration(value : float) -> void:
_bhdraft__schedule_duration.value = value
- var _category: PBField
- func get_category() -> bool:
- return _category.value
- func clear_category() -> void:
- data[2054].state = PB_SERVICE_STATE.UNFILLED
- _category.value = DEFAULT_VALUES_3[PB_DATA_TYPE.BOOL]
- func set_category(value : bool) -> void:
- _category.value = value
-
func to_string() -> String:
return PBPacker.message_to_string(data)
@@ -1445,16 +1443,16 @@ class Trail:
service.field = _animation_speed
data[_animation_speed.tag] = service
- _achievement_bit = PBField.new("achievement_bit", PB_DATA_TYPE.FIXED32, PB_RULE.OPTIONAL, 16, true, DEFAULT_VALUES_3[PB_DATA_TYPE.FIXED32])
- service = PBServiceField.new()
- service.field = _achievement_bit
- data[_achievement_bit.tag] = service
-
- _achievement_id = PBField.new("achievement_id", PB_DATA_TYPE.INT32, PB_RULE.OPTIONAL, 17, true, DEFAULT_VALUES_3[PB_DATA_TYPE.INT32])
+ _achievement_id = PBField.new("achievement_id", PB_DATA_TYPE.INT32, PB_RULE.OPTIONAL, 16, true, DEFAULT_VALUES_3[PB_DATA_TYPE.INT32])
service = PBServiceField.new()
service.field = _achievement_id
data[_achievement_id.tag] = service
+ _achievement_bit_index = PBField.new("achievement_bit_index", PB_DATA_TYPE.INT32, PB_RULE.OPTIONAL, 17, true, DEFAULT_VALUES_3[PB_DATA_TYPE.INT32])
+ service = PBServiceField.new()
+ service.field = _achievement_bit_index
+ data[_achievement_bit_index.tag] = service
+
_disable_player_cutout = PBField.new("disable_player_cutout", PB_DATA_TYPE.BOOL, PB_RULE.OPTIONAL, 19, true, DEFAULT_VALUES_3[PB_DATA_TYPE.BOOL])
service = PBServiceField.new()
service.field = _disable_player_cutout
@@ -1470,10 +1468,9 @@ class Trail:
service.field = _scale
data[_scale.tag] = service
- _rgba_color = PBField.new("rgba_color", PB_DATA_TYPE.MESSAGE, PB_RULE.OPTIONAL, 22, true, DEFAULT_VALUES_3[PB_DATA_TYPE.MESSAGE])
+ _rgba_color = PBField.new("rgba_color", PB_DATA_TYPE.FIXED32, PB_RULE.OPTIONAL, 22, true, DEFAULT_VALUES_3[PB_DATA_TYPE.FIXED32])
service = PBServiceField.new()
service.field = _rgba_color
- service.func_ref = funcref(self, "new_rgba_color")
data[_rgba_color.tag] = service
_festival_filter = PBField.new("festival_filter", PB_DATA_TYPE.MESSAGE, PB_RULE.OPTIONAL, 23, true, DEFAULT_VALUES_3[PB_DATA_TYPE.MESSAGE])
@@ -1547,11 +1544,6 @@ class Trail:
service.field = _bhdraft__schedule_duration
data[_bhdraft__schedule_duration.tag] = service
- _category = PBField.new("category", PB_DATA_TYPE.BOOL, PB_RULE.OPTIONAL, 2054, true, DEFAULT_VALUES_3[PB_DATA_TYPE.BOOL])
- service = PBServiceField.new()
- service.field = _category
- data[_category.tag] = service
-
var data = {}
var _texture_id: PBField
@@ -1618,24 +1610,24 @@ class Trail:
func set_animation_speed(value : float) -> void:
_animation_speed.value = value
- var _achievement_bit: PBField
- func get_achievement_bit() -> int:
- return _achievement_bit.value
- func clear_achievement_bit() -> void:
- data[16].state = PB_SERVICE_STATE.UNFILLED
- _achievement_bit.value = DEFAULT_VALUES_3[PB_DATA_TYPE.FIXED32]
- func set_achievement_bit(value : int) -> void:
- _achievement_bit.value = value
-
var _achievement_id: PBField
func get_achievement_id() -> int:
return _achievement_id.value
func clear_achievement_id() -> void:
- data[17].state = PB_SERVICE_STATE.UNFILLED
+ data[16].state = PB_SERVICE_STATE.UNFILLED
_achievement_id.value = DEFAULT_VALUES_3[PB_DATA_TYPE.INT32]
func set_achievement_id(value : int) -> void:
_achievement_id.value = value
+ var _achievement_bit_index: PBField
+ func get_achievement_bit_index() -> int:
+ return _achievement_bit_index.value
+ func clear_achievement_bit_index() -> void:
+ data[17].state = PB_SERVICE_STATE.UNFILLED
+ _achievement_bit_index.value = DEFAULT_VALUES_3[PB_DATA_TYPE.INT32]
+ func set_achievement_bit_index(value : int) -> void:
+ _achievement_bit_index.value = value
+
var _disable_player_cutout: PBField
func get_disable_player_cutout() -> bool:
return _disable_player_cutout.value
@@ -1664,14 +1656,13 @@ class Trail:
_scale.value = value
var _rgba_color: PBField
- func get_rgba_color() -> RGBAColor:
+ func get_rgba_color() -> int:
return _rgba_color.value
func clear_rgba_color() -> void:
data[22].state = PB_SERVICE_STATE.UNFILLED
- _rgba_color.value = DEFAULT_VALUES_3[PB_DATA_TYPE.MESSAGE]
- func new_rgba_color() -> RGBAColor:
- _rgba_color.value = RGBAColor.new()
- return _rgba_color.value
+ _rgba_color.value = DEFAULT_VALUES_3[PB_DATA_TYPE.FIXED32]
+ func set_rgba_color(value : int) -> void:
+ _rgba_color.value = value
var _festival_filter: PBField
func get_festival_filter() -> FestivalFilter:
@@ -1796,56 +1787,6 @@ class Trail:
func set_bhdraft__schedule_duration(value : float) -> void:
_bhdraft__schedule_duration.value = value
- var _category: PBField
- func get_category() -> bool:
- return _category.value
- func clear_category() -> void:
- data[2054].state = PB_SERVICE_STATE.UNFILLED
- _category.value = DEFAULT_VALUES_3[PB_DATA_TYPE.BOOL]
- func set_category(value : bool) -> void:
- _category.value = value
-
- func to_string() -> String:
- return PBPacker.message_to_string(data)
-
- func to_bytes() -> PoolByteArray:
- return PBPacker.pack_message(data)
-
- func from_bytes(bytes : PoolByteArray, offset : int = 0, limit : int = -1) -> int:
- var cur_limit = bytes.size()
- if limit != -1:
- cur_limit = limit
- var result = PBPacker.unpack_message(data, bytes, offset, cur_limit)
- if result == cur_limit:
- if PBPacker.check_required(data):
- if limit == -1:
- return PB_ERR.NO_ERRORS
- else:
- return PB_ERR.REQUIRED_FIELDS
- elif limit == -1 && result > 0:
- return PB_ERR.PARSE_INCOMPLETE
- return result
-
-class RGBAColor:
- func _init():
- var service
-
- _rgba_color = PBField.new("rgba_color", PB_DATA_TYPE.INT32, PB_RULE.OPTIONAL, 1, true, DEFAULT_VALUES_3[PB_DATA_TYPE.INT32])
- service = PBServiceField.new()
- service.field = _rgba_color
- data[_rgba_color.tag] = service
-
- var data = {}
-
- var _rgba_color: PBField
- func get_rgba_color() -> int:
- return _rgba_color.value
- func clear_rgba_color() -> void:
- data[1].state = PB_SERVICE_STATE.UNFILLED
- _rgba_color.value = DEFAULT_VALUES_3[PB_DATA_TYPE.INT32]
- func set_rgba_color(value : int) -> void:
- _rgba_color.value = value
-
func to_string() -> String:
return PBPacker.message_to_string(data)
diff --git a/xml_converter/integration_tests/test_cases/texture_invalid/input/pack/xml_file.xml b/xml_converter/integration_tests/test_cases/texture_invalid/input/pack/xml_file.xml
new file mode 100644
index 00000000..1ef3d4c1
--- /dev/null
+++ b/xml_converter/integration_tests/test_cases/texture_invalid/input/pack/xml_file.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/xml_converter/integration_tests/test_cases/texture_invalid/output_proto/markers.bin b/xml_converter/integration_tests/test_cases/texture_invalid/output_proto/markers.bin
new file mode 100644
index 00000000..e3e57428
Binary files /dev/null and b/xml_converter/integration_tests/test_cases/texture_invalid/output_proto/markers.bin differ
diff --git a/xml_converter/integration_tests/test_cases/texture_invalid/output_xml/xml_file.xml b/xml_converter/integration_tests/test_cases/texture_invalid/output_xml/xml_file.xml
new file mode 100644
index 00000000..995b3617
--- /dev/null
+++ b/xml_converter/integration_tests/test_cases/texture_invalid/output_xml/xml_file.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/xml_converter/integration_tests/test_cases/texture_invalid/testcase.yaml b/xml_converter/integration_tests/test_cases/texture_invalid/testcase.yaml
new file mode 100644
index 00000000..14623cbf
--- /dev/null
+++ b/xml_converter/integration_tests/test_cases/texture_invalid/testcase.yaml
@@ -0,0 +1,7 @@
+input_paths:
+ "pack": "xml"
+expected_stdout: |
+ Warning: File path test_cases/texture_invalid/input/pack/texture_01.png not found.
+ Warning: File path test_cases/texture_invalid/input/pack/texture_01.png not found.
+expected_stderr: |
+expected_returncode: 0