2016-06-18 14:46:12 +02:00
/**************************************************************************/
2020-03-27 08:44:44 +01:00
/* navigation_region_2d.cpp */
2016-06-18 14:46:12 +02:00
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
2018-01-05 00:50:27 +01:00
2020-03-27 08:44:44 +01:00
# include "navigation_region_2d.h"
2017-04-28 18:29:15 +02:00
2023-01-10 07:14:16 +01:00
# include "core/math/geometry_2d.h"
2022-02-12 02:46:22 +01:00
# include "scene/resources/world_2d.h"
2020-03-27 19:21:27 +01:00
# include "servers/navigation_server_2d.h"
2017-04-28 18:29:15 +02:00
2023-10-23 03:55:35 +02:00
RID NavigationRegion2D : : get_rid ( ) const {
return region ;
}
2020-02-28 08:05:04 +01:00
void NavigationRegion2D : : set_enabled ( bool p_enabled ) {
2020-05-14 16:41:43 +02:00
if ( enabled = = p_enabled ) {
2015-02-14 16:09:52 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2022-08-21 04:21:01 +02:00
2015-02-14 16:09:52 +01:00
enabled = p_enabled ;
2023-07-06 23:01:19 +02:00
NavigationServer2D : : get_singleton ( ) - > region_set_enabled ( region , enabled ) ;
2015-02-14 16:09:52 +01:00
2022-07-01 18:58:03 +02:00
# ifdef DEBUG_ENABLED
2023-05-17 19:50:01 +02:00
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) | | NavigationServer2D : : get_singleton ( ) - > get_debug_navigation_enabled ( ) ) {
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2020-05-14 16:41:43 +02:00
}
2022-07-01 18:58:03 +02:00
# endif // DEBUG_ENABLED
2015-02-14 16:09:52 +01:00
}
2020-02-28 08:05:04 +01:00
bool NavigationRegion2D : : is_enabled ( ) const {
2015-02-14 16:09:52 +01:00
return enabled ;
}
2023-04-01 01:49:43 +02:00
void NavigationRegion2D : : set_use_edge_connections ( bool p_enabled ) {
if ( use_edge_connections = = p_enabled ) {
return ;
}
use_edge_connections = p_enabled ;
NavigationServer2D : : get_singleton ( ) - > region_set_use_edge_connections ( region , use_edge_connections ) ;
}
bool NavigationRegion2D : : get_use_edge_connections ( ) const {
return use_edge_connections ;
}
2022-06-14 23:34:43 +02:00
void NavigationRegion2D : : set_navigation_layers ( uint32_t p_navigation_layers ) {
2022-08-21 04:21:01 +02:00
if ( navigation_layers = = p_navigation_layers ) {
return ;
}
navigation_layers = p_navigation_layers ;
NavigationServer2D : : get_singleton ( ) - > region_set_navigation_layers ( region , navigation_layers ) ;
2021-03-08 20:56:33 +01:00
}
2022-06-14 23:34:43 +02:00
uint32_t NavigationRegion2D : : get_navigation_layers ( ) const {
2022-08-21 04:21:01 +02:00
return navigation_layers ;
2021-03-08 20:56:33 +01:00
}
2022-06-19 13:23:13 +02:00
void NavigationRegion2D : : set_navigation_layer_value ( int p_layer_number , bool p_value ) {
ERR_FAIL_COND_MSG ( p_layer_number < 1 , " Navigation layer number must be between 1 and 32 inclusive. " ) ;
ERR_FAIL_COND_MSG ( p_layer_number > 32 , " Navigation layer number must be between 1 and 32 inclusive. " ) ;
2022-08-21 04:21:01 +02:00
2022-06-19 13:23:13 +02:00
uint32_t _navigation_layers = get_navigation_layers ( ) ;
2022-08-21 04:21:01 +02:00
2022-06-19 13:23:13 +02:00
if ( p_value ) {
_navigation_layers | = 1 < < ( p_layer_number - 1 ) ;
} else {
_navigation_layers & = ~ ( 1 < < ( p_layer_number - 1 ) ) ;
}
2022-08-21 04:21:01 +02:00
2022-06-19 13:23:13 +02:00
set_navigation_layers ( _navigation_layers ) ;
}
bool NavigationRegion2D : : get_navigation_layer_value ( int p_layer_number ) const {
ERR_FAIL_COND_V_MSG ( p_layer_number < 1 , false , " Navigation layer number must be between 1 and 32 inclusive. " ) ;
ERR_FAIL_COND_V_MSG ( p_layer_number > 32 , false , " Navigation layer number must be between 1 and 32 inclusive. " ) ;
2022-08-21 04:21:01 +02:00
2022-06-19 13:23:13 +02:00
return get_navigation_layers ( ) & ( 1 < < ( p_layer_number - 1 ) ) ;
}
2022-06-06 05:24:11 +02:00
void NavigationRegion2D : : set_enter_cost ( real_t p_enter_cost ) {
ERR_FAIL_COND_MSG ( p_enter_cost < 0.0 , " The enter_cost must be positive. " ) ;
2022-08-21 04:21:01 +02:00
if ( Math : : is_equal_approx ( enter_cost , p_enter_cost ) ) {
return ;
}
enter_cost = p_enter_cost ;
NavigationServer2D : : get_singleton ( ) - > region_set_enter_cost ( region , enter_cost ) ;
2022-06-06 05:24:11 +02:00
}
real_t NavigationRegion2D : : get_enter_cost ( ) const {
return enter_cost ;
}
void NavigationRegion2D : : set_travel_cost ( real_t p_travel_cost ) {
ERR_FAIL_COND_MSG ( p_travel_cost < 0.0 , " The travel_cost must be positive. " ) ;
2022-08-21 04:21:01 +02:00
if ( Math : : is_equal_approx ( travel_cost , p_travel_cost ) ) {
return ;
}
travel_cost = p_travel_cost ;
2022-08-07 19:40:33 +02:00
NavigationServer2D : : get_singleton ( ) - > region_set_travel_cost ( region , travel_cost ) ;
2022-06-06 05:24:11 +02:00
}
real_t NavigationRegion2D : : get_travel_cost ( ) const {
return travel_cost ;
}
2022-04-30 13:27:30 +02:00
RID NavigationRegion2D : : get_region_rid ( ) const {
2023-10-23 03:55:35 +02:00
return get_rid ( ) ;
2022-04-30 13:27:30 +02:00
}
2019-10-21 23:37:07 +02:00
# ifdef TOOLS_ENABLED
2020-02-28 08:05:04 +01:00
Rect2 NavigationRegion2D : : _edit_get_rect ( ) const {
2022-12-11 18:02:35 +01:00
return navigation_polygon . is_valid ( ) ? navigation_polygon - > _edit_get_rect ( ) : Rect2 ( ) ;
2017-12-27 09:28:02 +01:00
}
2020-02-28 08:05:04 +01:00
bool NavigationRegion2D : : _edit_is_selected_on_click ( const Point2 & p_point , double p_tolerance ) const {
2022-12-11 18:02:35 +01:00
return navigation_polygon . is_valid ( ) ? navigation_polygon - > _edit_is_selected_on_click ( p_point , p_tolerance ) : false ;
2017-12-27 09:28:02 +01:00
}
2019-10-21 23:37:07 +02:00
# endif
2017-12-27 09:28:02 +01:00
2020-02-28 08:05:04 +01:00
void NavigationRegion2D : : _notification ( int p_what ) {
2015-02-14 16:09:52 +01:00
switch ( p_what ) {
case NOTIFICATION_ENTER_TREE : {
2023-05-17 16:24:09 +02:00
_region_enter_navigation_map ( ) ;
2015-02-14 16:09:52 +01:00
} break ;
2022-02-15 18:06:48 +01:00
2015-02-14 16:09:52 +01:00
case NOTIFICATION_TRANSFORM_CHANGED : {
2023-04-05 02:15:25 +02:00
set_physics_process_internal ( true ) ;
2015-02-14 16:09:52 +01:00
} break ;
2022-02-15 18:06:48 +01:00
2024-05-25 22:14:27 +02:00
case NOTIFICATION_VISIBILITY_CHANGED : {
# ifdef DEBUG_ENABLED
if ( debug_instance_rid . is_valid ( ) ) {
RS : : get_singleton ( ) - > canvas_item_set_visible ( debug_instance_rid , is_visible_in_tree ( ) ) ;
}
# endif // DEBUG_ENABLED
} break ;
2015-02-14 16:09:52 +01:00
case NOTIFICATION_EXIT_TREE : {
2023-05-17 16:24:09 +02:00
_region_exit_navigation_map ( ) ;
2024-05-25 22:14:27 +02:00
# ifdef DEBUG_ENABLED
_free_debug ( ) ;
# endif // DEBUG_ENABLED
2015-02-14 16:09:52 +01:00
} break ;
2022-02-15 18:06:48 +01:00
2023-04-05 02:15:25 +02:00
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS : {
set_physics_process_internal ( false ) ;
2023-11-23 07:23:15 +01:00
_region_update_transform ( ) ;
2023-04-05 02:15:25 +02:00
} break ;
2015-02-14 16:09:52 +01:00
case NOTIFICATION_DRAW : {
2022-07-01 18:58:03 +02:00
# ifdef DEBUG_ENABLED
2023-02-13 04:35:42 +01:00
if ( is_inside_tree ( ) & & ( Engine : : get_singleton ( ) - > is_editor_hint ( ) | | NavigationServer2D : : get_singleton ( ) - > get_debug_enabled ( ) ) & & navigation_polygon . is_valid ( ) ) {
2023-05-17 19:50:01 +02:00
_update_debug_mesh ( ) ;
_update_debug_edge_connections_mesh ( ) ;
2024-02-23 11:22:29 +01:00
_update_debug_baking_rect ( ) ;
2015-02-14 16:09:52 +01:00
}
2022-07-01 18:58:03 +02:00
# endif // DEBUG_ENABLED
2015-02-14 16:09:52 +01:00
} break ;
}
}
2022-12-11 18:02:35 +01:00
void NavigationRegion2D : : set_navigation_polygon ( const Ref < NavigationPolygon > & p_navigation_polygon ) {
if ( navigation_polygon . is_valid ( ) ) {
2023-07-03 21:29:37 +02:00
navigation_polygon - > disconnect_changed ( callable_mp ( this , & NavigationRegion2D : : _navigation_polygon_changed ) ) ;
2015-02-14 16:09:52 +01:00
}
2020-01-10 12:22:34 +01:00
2022-12-11 18:02:35 +01:00
navigation_polygon = p_navigation_polygon ;
2024-05-25 22:14:27 +02:00
# ifdef DEBUG_ENABLED
debug_mesh_dirty = true ;
# endif // DEBUG_ENABLED
2022-12-11 18:02:35 +01:00
NavigationServer2D : : get_singleton ( ) - > region_set_navigation_polygon ( region , p_navigation_polygon ) ;
2020-01-10 12:22:34 +01:00
2022-12-11 18:02:35 +01:00
if ( navigation_polygon . is_valid ( ) ) {
2023-07-03 21:29:37 +02:00
navigation_polygon - > connect_changed ( callable_mp ( this , & NavigationRegion2D : : _navigation_polygon_changed ) ) ;
2015-02-14 16:09:52 +01:00
}
2022-12-11 18:02:35 +01:00
_navigation_polygon_changed ( ) ;
2015-02-14 16:09:52 +01:00
2020-10-29 11:01:28 +01:00
update_configuration_warnings ( ) ;
2015-02-14 16:09:52 +01:00
}
2020-02-28 08:05:04 +01:00
Ref < NavigationPolygon > NavigationRegion2D : : get_navigation_polygon ( ) const {
2022-12-11 18:02:35 +01:00
return navigation_polygon ;
2015-02-14 16:09:52 +01:00
}
2023-05-17 16:24:09 +02:00
void NavigationRegion2D : : set_navigation_map ( RID p_navigation_map ) {
if ( map_override = = p_navigation_map ) {
return ;
}
map_override = p_navigation_map ;
NavigationServer2D : : get_singleton ( ) - > region_set_map ( region , map_override ) ;
}
RID NavigationRegion2D : : get_navigation_map ( ) const {
if ( map_override . is_valid ( ) ) {
return map_override ;
} else if ( is_inside_tree ( ) ) {
return get_world_2d ( ) - > get_navigation_map ( ) ;
}
return RID ( ) ;
}
2023-08-17 18:32:30 +02:00
void NavigationRegion2D : : bake_navigation_polygon ( bool p_on_thread ) {
ERR_FAIL_COND_MSG ( ! Thread : : is_main_thread ( ) , " The SceneTree can only be parsed on the main thread. Call this function from the main thread or use call_deferred(). " ) ;
ERR_FAIL_COND_MSG ( ! navigation_polygon . is_valid ( ) , " Baking the navigation polygon requires a valid `NavigationPolygon` resource. " ) ;
Ref < NavigationMeshSourceGeometryData2D > source_geometry_data ;
source_geometry_data . instantiate ( ) ;
NavigationServer2D : : get_singleton ( ) - > parse_source_geometry_data ( navigation_polygon , source_geometry_data , this ) ;
if ( p_on_thread ) {
NavigationServer2D : : get_singleton ( ) - > bake_from_source_geometry_data_async ( navigation_polygon , source_geometry_data , callable_mp ( this , & NavigationRegion2D : : _bake_finished ) . bind ( navigation_polygon ) ) ;
} else {
NavigationServer2D : : get_singleton ( ) - > bake_from_source_geometry_data ( navigation_polygon , source_geometry_data , callable_mp ( this , & NavigationRegion2D : : _bake_finished ) . bind ( navigation_polygon ) ) ;
}
}
void NavigationRegion2D : : _bake_finished ( Ref < NavigationPolygon > p_navigation_polygon ) {
if ( ! Thread : : is_main_thread ( ) ) {
2023-12-18 15:46:56 +01:00
callable_mp ( this , & NavigationRegion2D : : _bake_finished ) . call_deferred ( p_navigation_polygon ) ;
2023-08-17 18:32:30 +02:00
return ;
}
set_navigation_polygon ( p_navigation_polygon ) ;
emit_signal ( SNAME ( " bake_finished " ) ) ;
}
2024-01-29 22:28:01 +01:00
bool NavigationRegion2D : : is_baking ( ) const {
return NavigationServer2D : : get_singleton ( ) - > is_baking_navigation_polygon ( navigation_polygon ) ;
}
2022-12-11 18:02:35 +01:00
void NavigationRegion2D : : _navigation_polygon_changed ( ) {
2020-05-14 16:41:43 +02:00
if ( is_inside_tree ( ) & & ( Engine : : get_singleton ( ) - > is_editor_hint ( ) | | get_tree ( ) - > is_debugging_navigation_hint ( ) ) ) {
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2020-05-14 16:41:43 +02:00
}
2022-12-11 18:02:35 +01:00
if ( navigation_polygon . is_valid ( ) ) {
NavigationServer2D : : get_singleton ( ) - > region_set_navigation_polygon ( region , navigation_polygon ) ;
2022-05-18 13:36:18 +02:00
}
2015-02-14 16:09:52 +01:00
}
2022-07-01 18:58:03 +02:00
# ifdef DEBUG_ENABLED
2023-05-17 19:50:01 +02:00
void NavigationRegion2D : : _navigation_map_changed ( RID p_map ) {
2022-07-01 18:58:03 +02:00
if ( is_inside_tree ( ) & & get_world_2d ( ) - > get_navigation_map ( ) = = p_map ) {
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2021-03-15 12:45:28 +01:00
}
}
2023-05-17 19:50:01 +02:00
# endif // DEBUG_ENABLED
2015-02-14 16:09:52 +01:00
2024-02-10 02:47:00 +01:00
# ifdef DEBUG_ENABLED
void NavigationRegion2D : : _navigation_debug_changed ( ) {
if ( is_inside_tree ( ) ) {
queue_redraw ( ) ;
}
}
# endif // DEBUG_ENABLED
2024-02-17 19:03:21 +01:00
PackedStringArray NavigationRegion2D : : get_configuration_warnings ( ) const {
PackedStringArray warnings = Node2D : : get_configuration_warnings ( ) ;
2020-05-14 22:59:27 +02:00
2020-10-29 11:01:28 +01:00
if ( is_visible_in_tree ( ) & & is_inside_tree ( ) ) {
2022-12-11 18:02:35 +01:00
if ( ! navigation_polygon . is_valid ( ) ) {
2022-03-28 15:24:14 +02:00
warnings . push_back ( RTR ( " A NavigationMesh resource must be set or created for this node to work. Please set a property or draw a polygon. " ) ) ;
2020-05-14 22:59:27 +02:00
}
2016-05-17 23:27:15 +02:00
}
2020-10-29 11:01:28 +01:00
return warnings ;
2016-05-17 23:27:15 +02:00
}
2020-02-28 08:05:04 +01:00
void NavigationRegion2D : : _bind_methods ( ) {
2023-10-23 03:55:35 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_rid " ) , & NavigationRegion2D : : get_rid ) ;
2022-12-11 18:02:35 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_navigation_polygon " , " navigation_polygon " ) , & NavigationRegion2D : : set_navigation_polygon ) ;
2020-02-28 08:05:04 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_navigation_polygon " ) , & NavigationRegion2D : : get_navigation_polygon ) ;
2015-02-14 16:09:52 +01:00
2020-02-28 08:05:04 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_enabled " , " enabled " ) , & NavigationRegion2D : : set_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_enabled " ) , & NavigationRegion2D : : is_enabled ) ;
2015-02-14 16:09:52 +01:00
2023-05-17 16:24:09 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_navigation_map " , " navigation_map " ) , & NavigationRegion2D : : set_navigation_map ) ;
ClassDB : : bind_method ( D_METHOD ( " get_navigation_map " ) , & NavigationRegion2D : : get_navigation_map ) ;
2023-04-01 01:49:43 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_use_edge_connections " , " enabled " ) , & NavigationRegion2D : : set_use_edge_connections ) ;
ClassDB : : bind_method ( D_METHOD ( " get_use_edge_connections " ) , & NavigationRegion2D : : get_use_edge_connections ) ;
2022-06-14 23:34:43 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_navigation_layers " , " navigation_layers " ) , & NavigationRegion2D : : set_navigation_layers ) ;
ClassDB : : bind_method ( D_METHOD ( " get_navigation_layers " ) , & NavigationRegion2D : : get_navigation_layers ) ;
2021-03-08 20:56:33 +01:00
2022-06-19 13:23:13 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_navigation_layer_value " , " layer_number " , " value " ) , & NavigationRegion2D : : set_navigation_layer_value ) ;
ClassDB : : bind_method ( D_METHOD ( " get_navigation_layer_value " , " layer_number " ) , & NavigationRegion2D : : get_navigation_layer_value ) ;
2022-04-30 13:27:30 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_region_rid " ) , & NavigationRegion2D : : get_region_rid ) ;
2022-06-06 05:24:11 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_enter_cost " , " enter_cost " ) , & NavigationRegion2D : : set_enter_cost ) ;
ClassDB : : bind_method ( D_METHOD ( " get_enter_cost " ) , & NavigationRegion2D : : get_enter_cost ) ;
ClassDB : : bind_method ( D_METHOD ( " set_travel_cost " , " travel_cost " ) , & NavigationRegion2D : : set_travel_cost ) ;
ClassDB : : bind_method ( D_METHOD ( " get_travel_cost " ) , & NavigationRegion2D : : get_travel_cost ) ;
2023-08-17 18:32:30 +02:00
ClassDB : : bind_method ( D_METHOD ( " bake_navigation_polygon " , " on_thread " ) , & NavigationRegion2D : : bake_navigation_polygon , DEFVAL ( true ) ) ;
2024-01-29 22:28:01 +01:00
ClassDB : : bind_method ( D_METHOD ( " is_baking " ) , & NavigationRegion2D : : is_baking ) ;
2023-08-17 18:32:30 +02:00
2022-12-11 18:02:35 +01:00
ClassDB : : bind_method ( D_METHOD ( " _navigation_polygon_changed " ) , & NavigationRegion2D : : _navigation_polygon_changed ) ;
2015-02-14 16:09:52 +01:00
2022-12-11 18:02:35 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " navigation_polygon " , PROPERTY_HINT_RESOURCE_TYPE , " NavigationPolygon " ) , " set_navigation_polygon " , " get_navigation_polygon " ) ;
2017-02-12 01:11:37 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " enabled " ) , " set_enabled " , " is_enabled " ) ;
2023-04-01 01:49:43 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " use_edge_connections " ) , " set_use_edge_connections " , " get_use_edge_connections " ) ;
2022-06-14 23:34:43 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " navigation_layers " , PROPERTY_HINT_LAYERS_2D_NAVIGATION ) , " set_navigation_layers " , " get_navigation_layers " ) ;
2022-06-06 05:24:11 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : FLOAT , " enter_cost " ) , " set_enter_cost " , " get_enter_cost " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : FLOAT , " travel_cost " ) , " set_travel_cost " , " get_travel_cost " ) ;
2023-08-17 18:32:30 +02:00
ADD_SIGNAL ( MethodInfo ( " navigation_polygon_changed " ) ) ;
ADD_SIGNAL ( MethodInfo ( " bake_finished " ) ) ;
2015-02-14 16:09:52 +01:00
}
2022-12-18 05:07:10 +01:00
# ifndef DISABLE_DEPRECATED
// Compatibility with earlier 4.0 betas.
bool NavigationRegion2D : : _set ( const StringName & p_name , const Variant & p_value ) {
if ( p_name = = " navpoly " ) {
set_navigation_polygon ( p_value ) ;
return true ;
}
return false ;
}
bool NavigationRegion2D : : _get ( const StringName & p_name , Variant & r_ret ) const {
if ( p_name = = " navpoly " ) {
r_ret = get_navigation_polygon ( ) ;
return true ;
}
return false ;
}
# endif // DISABLE_DEPRECATED
2020-02-28 08:05:04 +01:00
NavigationRegion2D : : NavigationRegion2D ( ) {
2017-01-13 00:35:46 +01:00
set_notify_transform ( true ) ;
2023-01-26 13:17:26 +01:00
set_hide_clip_children ( true ) ;
2022-10-01 07:49:39 +02:00
2020-03-27 19:21:27 +01:00
region = NavigationServer2D : : get_singleton ( ) - > region_create ( ) ;
2022-10-01 07:49:39 +02:00
NavigationServer2D : : get_singleton ( ) - > region_set_owner_id ( region , get_instance_id ( ) ) ;
2022-06-06 05:24:11 +02:00
NavigationServer2D : : get_singleton ( ) - > region_set_enter_cost ( region , get_enter_cost ( ) ) ;
NavigationServer2D : : get_singleton ( ) - > region_set_travel_cost ( region , get_travel_cost ( ) ) ;
2023-10-23 03:55:35 +02:00
NavigationServer2D : : get_singleton ( ) - > region_set_navigation_layers ( region , navigation_layers ) ;
NavigationServer2D : : get_singleton ( ) - > region_set_use_edge_connections ( region , use_edge_connections ) ;
NavigationServer2D : : get_singleton ( ) - > region_set_enabled ( region , enabled ) ;
2022-07-01 18:58:03 +02:00
# ifdef DEBUG_ENABLED
2023-05-17 19:50:01 +02:00
NavigationServer2D : : get_singleton ( ) - > connect ( SNAME ( " map_changed " ) , callable_mp ( this , & NavigationRegion2D : : _navigation_map_changed ) ) ;
2024-02-10 02:47:00 +01:00
NavigationServer2D : : get_singleton ( ) - > connect ( SNAME ( " navigation_debug_changed " ) , callable_mp ( this , & NavigationRegion2D : : _navigation_debug_changed ) ) ;
2022-07-01 18:58:03 +02:00
# endif // DEBUG_ENABLED
2020-01-10 12:22:34 +01:00
}
2020-02-28 08:05:04 +01:00
NavigationRegion2D : : ~ NavigationRegion2D ( ) {
2022-12-12 18:42:37 +01:00
ERR_FAIL_NULL ( NavigationServer2D : : get_singleton ( ) ) ;
2020-03-27 19:21:27 +01:00
NavigationServer2D : : get_singleton ( ) - > free ( region ) ;
2022-07-01 18:58:03 +02:00
# ifdef DEBUG_ENABLED
2023-05-17 19:50:01 +02:00
NavigationServer2D : : get_singleton ( ) - > disconnect ( SNAME ( " map_changed " ) , callable_mp ( this , & NavigationRegion2D : : _navigation_map_changed ) ) ;
2024-02-10 02:47:00 +01:00
NavigationServer2D : : get_singleton ( ) - > disconnect ( SNAME ( " navigation_debug_changed " ) , callable_mp ( this , & NavigationRegion2D : : _navigation_debug_changed ) ) ;
2022-07-01 18:58:03 +02:00
# endif // DEBUG_ENABLED
2015-02-14 16:09:52 +01:00
}
2023-01-10 07:14:16 +01:00
2023-05-17 16:24:09 +02:00
void NavigationRegion2D : : _region_enter_navigation_map ( ) {
if ( ! is_inside_tree ( ) ) {
return ;
}
2023-10-15 05:17:57 +02:00
if ( map_override . is_valid ( ) ) {
NavigationServer2D : : get_singleton ( ) - > region_set_map ( region , map_override ) ;
} else {
NavigationServer2D : : get_singleton ( ) - > region_set_map ( region , get_world_2d ( ) - > get_navigation_map ( ) ) ;
2023-05-17 16:24:09 +02:00
}
current_global_transform = get_global_transform ( ) ;
NavigationServer2D : : get_singleton ( ) - > region_set_transform ( region , current_global_transform ) ;
2023-10-15 05:17:57 +02:00
NavigationServer2D : : get_singleton ( ) - > region_set_enabled ( region , enabled ) ;
2023-05-17 16:24:09 +02:00
queue_redraw ( ) ;
}
void NavigationRegion2D : : _region_exit_navigation_map ( ) {
NavigationServer2D : : get_singleton ( ) - > region_set_map ( region , RID ( ) ) ;
}
void NavigationRegion2D : : _region_update_transform ( ) {
if ( ! is_inside_tree ( ) ) {
return ;
}
Transform2D new_global_transform = get_global_transform ( ) ;
if ( current_global_transform ! = new_global_transform ) {
current_global_transform = new_global_transform ;
NavigationServer2D : : get_singleton ( ) - > region_set_transform ( region , current_global_transform ) ;
}
queue_redraw ( ) ;
}
2023-05-17 19:50:01 +02:00
# ifdef DEBUG_ENABLED
void NavigationRegion2D : : _update_debug_mesh ( ) {
2024-05-25 22:14:27 +02:00
if ( ! is_inside_tree ( ) ) {
_free_debug ( ) ;
2023-05-17 19:50:01 +02:00
return ;
}
const NavigationServer2D * ns2d = NavigationServer2D : : get_singleton ( ) ;
2024-05-25 22:14:27 +02:00
RenderingServer * rs = RenderingServer : : get_singleton ( ) ;
if ( ! debug_instance_rid . is_valid ( ) ) {
debug_instance_rid = rs - > canvas_item_create ( ) ;
}
if ( ! debug_mesh_rid . is_valid ( ) ) {
debug_mesh_rid = rs - > mesh_create ( ) ;
}
const Transform2D region_gt = get_global_transform ( ) ;
rs - > canvas_item_set_parent ( debug_instance_rid , get_world_2d ( ) - > get_canvas ( ) ) ;
rs - > canvas_item_set_transform ( debug_instance_rid , region_gt ) ;
if ( ! debug_mesh_dirty ) {
return ;
}
rs - > mesh_clear ( debug_mesh_rid ) ;
debug_mesh_dirty = false ;
const Vector < Vector2 > & vertices = navigation_polygon - > get_vertices ( ) ;
if ( vertices . size ( ) < 3 ) {
return ;
}
int polygon_count = navigation_polygon - > get_polygon_count ( ) ;
if ( polygon_count = = 0 ) {
return ;
}
2023-05-17 19:50:01 +02:00
bool enabled_geometry_face_random_color = ns2d - > get_debug_navigation_enable_geometry_face_random_color ( ) ;
bool enabled_edge_lines = ns2d - > get_debug_navigation_enable_edge_lines ( ) ;
Color debug_face_color = ns2d - > get_debug_navigation_geometry_face_color ( ) ;
Color debug_edge_color = ns2d - > get_debug_navigation_geometry_edge_color ( ) ;
if ( ! enabled ) {
debug_face_color = ns2d - > get_debug_navigation_geometry_face_disabled_color ( ) ;
debug_edge_color = ns2d - > get_debug_navigation_geometry_edge_disabled_color ( ) ;
}
2024-05-25 22:14:27 +02:00
int vertex_count = 0 ;
int line_count = 0 ;
for ( int i = 0 ; i < polygon_count ; i + + ) {
const Vector < int > & polygon = navigation_polygon - > get_polygon ( i ) ;
int polygon_size = polygon . size ( ) ;
if ( polygon_size < 3 ) {
continue ;
}
line_count + = polygon_size * 2 ;
vertex_count + = ( polygon_size - 2 ) * 3 ;
}
Vector < Vector2 > face_vertex_array ;
face_vertex_array . resize ( vertex_count ) ;
Vector < Color > face_color_array ;
if ( enabled_geometry_face_random_color ) {
face_color_array . resize ( vertex_count ) ;
}
Vector < Vector2 > line_vertex_array ;
if ( enabled_edge_lines ) {
line_vertex_array . resize ( line_count ) ;
}
2023-05-17 19:50:01 +02:00
RandomPCG rand ;
2024-05-25 22:14:27 +02:00
Color polygon_color = debug_face_color ;
2023-05-17 19:50:01 +02:00
2024-05-25 22:14:27 +02:00
int face_vertex_index = 0 ;
int line_vertex_index = 0 ;
Vector2 * face_vertex_array_ptrw = face_vertex_array . ptrw ( ) ;
Color * face_color_array_ptrw = face_color_array . ptrw ( ) ;
Vector2 * line_vertex_array_ptrw = line_vertex_array . ptrw ( ) ;
for ( int polygon_index = 0 ; polygon_index < polygon_count ; polygon_index + + ) {
const Vector < int > & polygon_indices = navigation_polygon - > get_polygon ( polygon_index ) ;
int polygon_indices_size = polygon_indices . size ( ) ;
if ( polygon_indices_size < 3 ) {
continue ;
2023-05-17 19:50:01 +02:00
}
if ( enabled_geometry_face_random_color ) {
2024-05-25 22:14:27 +02:00
// Generate the polygon color, slightly randomly modified from the settings one.
polygon_color . set_hsv ( debug_face_color . get_h ( ) + rand . random ( - 1.0 , 1.0 ) * 0.1 , debug_face_color . get_s ( ) , debug_face_color . get_v ( ) + rand . random ( - 1.0 , 1.0 ) * 0.2 ) ;
polygon_color . a = debug_face_color . a ;
2023-05-17 19:50:01 +02:00
}
2024-05-25 22:14:27 +02:00
for ( int polygon_indices_index = 0 ; polygon_indices_index < polygon_indices_size - 2 ; polygon_indices_index + + ) {
face_vertex_array_ptrw [ face_vertex_index ] = vertices [ polygon_indices [ 0 ] ] ;
face_vertex_array_ptrw [ face_vertex_index + 1 ] = vertices [ polygon_indices [ polygon_indices_index + 1 ] ] ;
face_vertex_array_ptrw [ face_vertex_index + 2 ] = vertices [ polygon_indices [ polygon_indices_index + 2 ] ] ;
if ( enabled_geometry_face_random_color ) {
face_color_array_ptrw [ face_vertex_index ] = polygon_color ;
face_color_array_ptrw [ face_vertex_index + 1 ] = polygon_color ;
face_color_array_ptrw [ face_vertex_index + 2 ] = polygon_color ;
}
face_vertex_index + = 3 ;
}
2023-05-17 19:50:01 +02:00
if ( enabled_edge_lines ) {
2024-05-25 22:14:27 +02:00
for ( int polygon_indices_index = 0 ; polygon_indices_index < polygon_indices_size ; polygon_indices_index + + ) {
line_vertex_array_ptrw [ line_vertex_index ] = vertices [ polygon_indices [ polygon_indices_index ] ] ;
line_vertex_index + = 1 ;
if ( polygon_indices_index + 1 = = polygon_indices_size ) {
line_vertex_array_ptrw [ line_vertex_index ] = vertices [ polygon_indices [ 0 ] ] ;
line_vertex_index + = 1 ;
} else {
line_vertex_array_ptrw [ line_vertex_index ] = vertices [ polygon_indices [ polygon_indices_index + 1 ] ] ;
line_vertex_index + = 1 ;
}
}
2023-05-17 19:50:01 +02:00
}
}
2024-05-25 22:14:27 +02:00
if ( ! enabled_geometry_face_random_color ) {
face_color_array . resize ( face_vertex_array . size ( ) ) ;
face_color_array . fill ( debug_face_color ) ;
}
Array face_mesh_array ;
face_mesh_array . resize ( Mesh : : ARRAY_MAX ) ;
face_mesh_array [ Mesh : : ARRAY_VERTEX ] = face_vertex_array ;
face_mesh_array [ Mesh : : ARRAY_COLOR ] = face_color_array ;
rs - > mesh_add_surface_from_arrays ( debug_mesh_rid , RS : : PRIMITIVE_TRIANGLES , face_mesh_array , Array ( ) , Dictionary ( ) , RS : : ARRAY_FLAG_USE_2D_VERTICES ) ;
if ( enabled_edge_lines ) {
Vector < Color > line_color_array ;
line_color_array . resize ( line_vertex_array . size ( ) ) ;
line_color_array . fill ( debug_edge_color ) ;
Array line_mesh_array ;
line_mesh_array . resize ( Mesh : : ARRAY_MAX ) ;
line_mesh_array [ Mesh : : ARRAY_VERTEX ] = line_vertex_array ;
line_mesh_array [ Mesh : : ARRAY_COLOR ] = line_color_array ;
rs - > mesh_add_surface_from_arrays ( debug_mesh_rid , RS : : PRIMITIVE_LINES , line_mesh_array , Array ( ) , Dictionary ( ) , RS : : ARRAY_FLAG_USE_2D_VERTICES ) ;
}
rs - > canvas_item_add_mesh ( debug_instance_rid , debug_mesh_rid , Transform2D ( ) ) ;
rs - > canvas_item_set_visible ( debug_instance_rid , is_visible_in_tree ( ) ) ;
2023-05-17 19:50:01 +02:00
}
# endif // DEBUG_ENABLED
# ifdef DEBUG_ENABLED
void NavigationRegion2D : : _update_debug_edge_connections_mesh ( ) {
const NavigationServer2D * ns2d = NavigationServer2D : : get_singleton ( ) ;
bool enable_edge_connections = use_edge_connections & & ns2d - > get_debug_navigation_enable_edge_connections ( ) & & ns2d - > map_get_use_edge_connections ( get_world_2d ( ) - > get_navigation_map ( ) ) ;
if ( enable_edge_connections ) {
Color debug_edge_connection_color = ns2d - > get_debug_navigation_edge_connection_color ( ) ;
// Draw the region edge connections.
Transform2D xform = get_global_transform ( ) ;
real_t radius = ns2d - > map_get_edge_connection_margin ( get_world_2d ( ) - > get_navigation_map ( ) ) / 2.0 ;
for ( int i = 0 ; i < ns2d - > region_get_connections_count ( region ) ; i + + ) {
// Two main points
Vector2 a = ns2d - > region_get_connection_pathway_start ( region , i ) ;
a = xform . affine_inverse ( ) . xform ( a ) ;
Vector2 b = ns2d - > region_get_connection_pathway_end ( region , i ) ;
b = xform . affine_inverse ( ) . xform ( b ) ;
draw_line ( a , b , debug_edge_connection_color ) ;
// Draw a circle to illustrate the margins.
real_t angle = a . angle_to_point ( b ) ;
draw_arc ( a , radius , angle + Math_PI / 2.0 , angle - Math_PI / 2.0 + Math_TAU , 10 , debug_edge_connection_color ) ;
draw_arc ( b , radius , angle - Math_PI / 2.0 , angle + Math_PI / 2.0 , 10 , debug_edge_connection_color ) ;
}
}
}
# endif // DEBUG_ENABLED
2024-02-23 11:22:29 +01:00
# ifdef DEBUG_ENABLED
void NavigationRegion2D : : _update_debug_baking_rect ( ) {
Rect2 baking_rect = get_navigation_polygon ( ) - > get_baking_rect ( ) ;
if ( baking_rect . has_area ( ) ) {
Vector2 baking_rect_offset = get_navigation_polygon ( ) - > get_baking_rect_offset ( ) ;
Rect2 debug_baking_rect = Rect2 ( baking_rect . position . x + baking_rect_offset . x , baking_rect . position . y + baking_rect_offset . y , baking_rect . size . x , baking_rect . size . y ) ;
Color debug_baking_rect_color = Color ( 0.8 , 0.5 , 0.7 , 0.1 ) ;
draw_rect ( debug_baking_rect , debug_baking_rect_color ) ;
}
}
# endif // DEBUG_ENABLED
2024-05-25 22:14:27 +02:00
# ifdef DEBUG_ENABLED
void NavigationRegion2D : : _free_debug ( ) {
RenderingServer * rs = RenderingServer : : get_singleton ( ) ;
ERR_FAIL_NULL ( rs ) ;
if ( debug_instance_rid . is_valid ( ) ) {
rs - > canvas_item_clear ( debug_instance_rid ) ;
rs - > free ( debug_instance_rid ) ;
debug_instance_rid = RID ( ) ;
}
if ( debug_mesh_rid . is_valid ( ) ) {
rs - > free ( debug_mesh_rid ) ;
debug_mesh_rid = RID ( ) ;
}
}
# endif // DEBUG_ENABLED