diff --git a/project.godot b/project.godot index 9fdb71a..a486ae5 100644 --- a/project.godot +++ b/project.godot @@ -33,6 +33,7 @@ gdscript/warnings/standalone_expression=0 gdscript/warnings/incompatible_ternary=0 gdscript/warnings/static_called_on_instance=0 gdscript/warnings/assert_always_false=0 +gdscript/warnings/integer_division=0 [display] diff --git a/source/match/TerrainNavigation.gd b/source/match/TerrainNavigation.gd index 478ceac..4b97ca8 100644 --- a/source/match/TerrainNavigation.gd +++ b/source/match/TerrainNavigation.gd @@ -4,6 +4,7 @@ const DOMAIN = Constants.Match.Navigation.Domain.TERRAIN var _earliest_frame_to_perform_next_rebake = null var _is_baking = false +var _map_geometry = NavigationMeshSourceGeometryData3D.new() @onready var navigation_map_rid = get_world_3d().navigation_map @@ -20,7 +21,6 @@ func _ready(): ) NavigationServer3D.map_force_update(navigation_map_rid) MatchSignals.schedule_navigation_rebake.connect(_on_schedule_navigation_rebake) - _navigation_region.bake_finished.connect(_on_bake_finished) func _process(_delta): @@ -31,7 +31,7 @@ func _process(_delta): ): _is_baking = true _earliest_frame_to_perform_next_rebake = null - _navigation_region.bake_navigation_mesh(true) + _rebake() func bake(): @@ -39,7 +39,46 @@ func bake(): _navigation_region.navigation_mesh.get_polygon_count() == 0, "bake() should be called exactly once - during runtime" ) - _navigation_region.bake_navigation_mesh(false) + NavigationServer3D.parse_source_geometry_data( + _navigation_region.navigation_mesh, _map_geometry, get_tree().root + ) + for node in get_tree().get_nodes_in_group("terrain_navigation_input"): + node.remove_from_group("terrain_navigation_input") + NavigationServer3D.bake_from_source_geometry_data( + _navigation_region.navigation_mesh, _map_geometry + ) + _sync_navmesh_changes() + + +func _rebake(): + # parse geometry other than map itself + var full_geometry = NavigationMeshSourceGeometryData3D.new() + NavigationServer3D.parse_source_geometry_data( + _navigation_region.navigation_mesh, full_geometry, get_tree().root + ) + + # add pre-parsed map geometry manually + # TODO: get rid of it when NavigationServer3D.parse_source_geometry_data() adds `append` param + var new_indices = full_geometry.get_indices() + var original_indices_num = new_indices.size() + var new_vertices = full_geometry.get_vertices() + var original_vertices_num = new_vertices.size() + new_indices.append_array(_map_geometry.get_indices()) + new_vertices.append_array(_map_geometry.get_vertices()) + for i in range(original_indices_num, new_indices.size()): + new_indices[i] += original_vertices_num / 3 + full_geometry.set_indices(new_indices) + full_geometry.set_vertices(new_vertices) + + NavigationServer3D.bake_from_source_geometry_data_async( + _navigation_region.navigation_mesh, full_geometry, _on_bake_finished + ) + + +# TODO: remove whenever Godot fixes that on its side +func _sync_navmesh_changes(): + """this function forces synchronization between server-level primitives and nodes""" + _navigation_region.navigation_mesh = _navigation_region.navigation_mesh func _safety_checks(): @@ -74,4 +113,5 @@ func _on_schedule_navigation_rebake(domain): func _on_bake_finished(): + _sync_navmesh_changes() _is_baking = false