2016-06-18 14:46:12 +02:00
/*************************************************************************/
/* navigation_mesh.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 14:16:55 +02:00
/* https://godotengine.org */
2016-06-18 14:46:12 +02:00
/*************************************************************************/
2021-01-01 20:13:46 +01:00
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
2016-06-18 14:46:12 +02:00
/* */
/* 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
2014-08-02 03:10:38 +02:00
# include "navigation_mesh.h"
2015-09-20 18:03:46 +02:00
# include "mesh_instance.h"
2017-03-05 16:44:50 +01:00
# include "navigation.h"
2014-08-02 03:10:38 +02:00
2017-03-05 16:44:50 +01:00
void NavigationMesh : : create_from_mesh ( const Ref < Mesh > & p_mesh ) {
2021-03-03 11:29:30 +01:00
ERR_FAIL_COND ( p_mesh . is_null ( ) ) ;
2014-08-02 03:10:38 +02:00
2017-03-05 16:44:50 +01:00
vertices = PoolVector < Vector3 > ( ) ;
2014-08-02 03:10:38 +02:00
clear_polygons ( ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < p_mesh - > get_surface_count ( ) ; i + + ) {
if ( p_mesh - > surface_get_primitive_type ( i ) ! = Mesh : : PRIMITIVE_TRIANGLES )
2014-08-02 03:10:38 +02:00
continue ;
Array arr = p_mesh - > surface_get_arrays ( i ) ;
2017-01-07 22:25:37 +01:00
PoolVector < Vector3 > varr = arr [ Mesh : : ARRAY_VERTEX ] ;
PoolVector < int > iarr = arr [ Mesh : : ARRAY_INDEX ] ;
2017-03-05 16:44:50 +01:00
if ( varr . size ( ) = = 0 | | iarr . size ( ) = = 0 )
2014-08-02 03:10:38 +02:00
continue ;
int from = vertices . size ( ) ;
vertices . append_array ( varr ) ;
int rlen = iarr . size ( ) ;
2017-01-07 22:25:37 +01:00
PoolVector < int > : : Read r = iarr . read ( ) ;
2014-08-02 03:10:38 +02:00
2017-03-05 16:44:50 +01:00
for ( int j = 0 ; j < rlen ; j + = 3 ) {
2014-08-02 03:10:38 +02:00
Vector < int > vi ;
vi . resize ( 3 ) ;
2018-07-25 03:11:03 +02:00
vi . write [ 0 ] = r [ j + 0 ] + from ;
vi . write [ 1 ] = r [ j + 1 ] + from ;
vi . write [ 2 ] = r [ j + 2 ] + from ;
2014-08-02 03:10:38 +02:00
add_polygon ( vi ) ;
}
}
}
2017-02-28 13:10:29 +01:00
void NavigationMesh : : set_sample_partition_type ( int p_value ) {
ERR_FAIL_COND ( p_value > = SAMPLE_PARTITION_MAX ) ;
partition_type = static_cast < SamplePartitionType > ( p_value ) ;
}
int NavigationMesh : : get_sample_partition_type ( ) const {
return static_cast < int > ( partition_type ) ;
}
2019-05-23 08:37:58 +02:00
void NavigationMesh : : set_parsed_geometry_type ( int p_value ) {
ERR_FAIL_COND ( p_value > = PARSED_GEOMETRY_MAX ) ;
parsed_geometry_type = static_cast < ParsedGeometryType > ( p_value ) ;
_change_notify ( ) ;
}
int NavigationMesh : : get_parsed_geometry_type ( ) const {
return parsed_geometry_type ;
}
void NavigationMesh : : set_collision_mask ( uint32_t p_mask ) {
collision_mask = p_mask ;
}
uint32_t NavigationMesh : : get_collision_mask ( ) const {
return collision_mask ;
}
void NavigationMesh : : set_collision_mask_bit ( int p_bit , bool p_value ) {
uint32_t mask = get_collision_mask ( ) ;
if ( p_value )
mask | = 1 < < p_bit ;
else
mask & = ~ ( 1 < < p_bit ) ;
set_collision_mask ( mask ) ;
}
bool NavigationMesh : : get_collision_mask_bit ( int p_bit ) const {
return get_collision_mask ( ) & ( 1 < < p_bit ) ;
}
2019-10-16 11:33:47 +02:00
void NavigationMesh : : set_source_geometry_mode ( int p_geometry_mode ) {
ERR_FAIL_INDEX ( p_geometry_mode , SOURCE_GEOMETRY_MAX ) ;
source_geometry_mode = static_cast < SourceGeometryMode > ( p_geometry_mode ) ;
_change_notify ( ) ;
}
int NavigationMesh : : get_source_geometry_mode ( ) const {
return source_geometry_mode ;
}
void NavigationMesh : : set_source_group_name ( StringName p_group_name ) {
source_group_name = p_group_name ;
}
StringName NavigationMesh : : get_source_group_name ( ) const {
return source_group_name ;
}
2017-02-28 13:10:29 +01:00
void NavigationMesh : : set_cell_size ( float p_value ) {
cell_size = p_value ;
}
float NavigationMesh : : get_cell_size ( ) const {
return cell_size ;
}
void NavigationMesh : : set_cell_height ( float p_value ) {
cell_height = p_value ;
}
float NavigationMesh : : get_cell_height ( ) const {
return cell_height ;
}
void NavigationMesh : : set_agent_height ( float p_value ) {
agent_height = p_value ;
}
float NavigationMesh : : get_agent_height ( ) const {
return agent_height ;
}
void NavigationMesh : : set_agent_radius ( float p_value ) {
agent_radius = p_value ;
}
float NavigationMesh : : get_agent_radius ( ) {
return agent_radius ;
}
void NavigationMesh : : set_agent_max_climb ( float p_value ) {
agent_max_climb = p_value ;
}
float NavigationMesh : : get_agent_max_climb ( ) const {
return agent_max_climb ;
}
void NavigationMesh : : set_agent_max_slope ( float p_value ) {
agent_max_slope = p_value ;
}
float NavigationMesh : : get_agent_max_slope ( ) const {
return agent_max_slope ;
}
void NavigationMesh : : set_region_min_size ( float p_value ) {
region_min_size = p_value ;
}
float NavigationMesh : : get_region_min_size ( ) const {
return region_min_size ;
}
void NavigationMesh : : set_region_merge_size ( float p_value ) {
region_merge_size = p_value ;
}
float NavigationMesh : : get_region_merge_size ( ) const {
return region_merge_size ;
}
void NavigationMesh : : set_edge_max_length ( float p_value ) {
edge_max_length = p_value ;
}
float NavigationMesh : : get_edge_max_length ( ) const {
return edge_max_length ;
}
void NavigationMesh : : set_edge_max_error ( float p_value ) {
edge_max_error = p_value ;
}
float NavigationMesh : : get_edge_max_error ( ) const {
return edge_max_error ;
}
void NavigationMesh : : set_verts_per_poly ( float p_value ) {
verts_per_poly = p_value ;
}
float NavigationMesh : : get_verts_per_poly ( ) const {
return verts_per_poly ;
}
void NavigationMesh : : set_detail_sample_distance ( float p_value ) {
detail_sample_distance = p_value ;
}
float NavigationMesh : : get_detail_sample_distance ( ) const {
return detail_sample_distance ;
}
void NavigationMesh : : set_detail_sample_max_error ( float p_value ) {
detail_sample_max_error = p_value ;
}
float NavigationMesh : : get_detail_sample_max_error ( ) const {
return detail_sample_max_error ;
}
void NavigationMesh : : set_filter_low_hanging_obstacles ( bool p_value ) {
filter_low_hanging_obstacles = p_value ;
}
bool NavigationMesh : : get_filter_low_hanging_obstacles ( ) const {
return filter_low_hanging_obstacles ;
}
void NavigationMesh : : set_filter_ledge_spans ( bool p_value ) {
filter_ledge_spans = p_value ;
}
bool NavigationMesh : : get_filter_ledge_spans ( ) const {
return filter_ledge_spans ;
}
void NavigationMesh : : set_filter_walkable_low_height_spans ( bool p_value ) {
filter_walkable_low_height_spans = p_value ;
}
bool NavigationMesh : : get_filter_walkable_low_height_spans ( ) const {
return filter_walkable_low_height_spans ;
}
2017-03-05 16:44:50 +01:00
void NavigationMesh : : set_vertices ( const PoolVector < Vector3 > & p_vertices ) {
vertices = p_vertices ;
2019-05-23 08:37:58 +02:00
_change_notify ( ) ;
2014-08-02 03:10:38 +02:00
}
2017-03-05 16:44:50 +01:00
PoolVector < Vector3 > NavigationMesh : : get_vertices ( ) const {
2014-08-02 03:10:38 +02:00
return vertices ;
}
2017-03-05 16:44:50 +01:00
void NavigationMesh : : _set_polygons ( const Array & p_array ) {
2014-08-02 03:10:38 +02:00
polygons . resize ( p_array . size ( ) ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < p_array . size ( ) ; i + + ) {
2018-07-25 03:11:03 +02:00
polygons . write [ i ] . indices = p_array [ i ] ;
2014-08-02 03:10:38 +02:00
}
2019-05-23 08:37:58 +02:00
_change_notify ( ) ;
2014-08-02 03:10:38 +02:00
}
Array NavigationMesh : : _get_polygons ( ) const {
Array ret ;
ret . resize ( polygons . size ( ) ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < ret . size ( ) ; i + + ) {
ret [ i ] = polygons [ i ] . indices ;
2014-08-02 03:10:38 +02:00
}
return ret ;
}
2017-03-05 16:44:50 +01:00
void NavigationMesh : : add_polygon ( const Vector < int > & p_polygon ) {
2014-08-02 03:10:38 +02:00
Polygon polygon ;
2017-03-05 16:44:50 +01:00
polygon . indices = p_polygon ;
2014-08-02 03:10:38 +02:00
polygons . push_back ( polygon ) ;
2019-05-23 08:37:58 +02:00
_change_notify ( ) ;
2014-08-02 03:10:38 +02:00
}
2017-03-05 16:44:50 +01:00
int NavigationMesh : : get_polygon_count ( ) const {
2014-08-02 03:10:38 +02:00
return polygons . size ( ) ;
}
2017-03-05 16:44:50 +01:00
Vector < int > NavigationMesh : : get_polygon ( int p_idx ) {
ERR_FAIL_INDEX_V ( p_idx , polygons . size ( ) , Vector < int > ( ) ) ;
2014-08-02 03:10:38 +02:00
return polygons [ p_idx ] . indices ;
}
2017-03-05 16:44:50 +01:00
void NavigationMesh : : clear_polygons ( ) {
2014-08-02 03:10:38 +02:00
polygons . clear ( ) ;
}
2015-09-20 18:03:46 +02:00
Ref < Mesh > NavigationMesh : : get_debug_mesh ( ) {
if ( debug_mesh . is_valid ( ) )
return debug_mesh ;
2017-01-07 22:25:37 +01:00
PoolVector < Vector3 > vertices = get_vertices ( ) ;
2017-03-05 16:44:50 +01:00
PoolVector < Vector3 > : : Read vr = vertices . read ( ) ;
2015-09-20 18:03:46 +02:00
List < Face3 > faces ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < get_polygon_count ( ) ; i + + ) {
2015-09-20 18:03:46 +02:00
Vector < int > p = get_polygon ( i ) ;
2017-03-05 16:44:50 +01:00
for ( int j = 2 ; j < p . size ( ) ; j + + ) {
2015-09-20 18:03:46 +02:00
Face3 f ;
2017-03-05 16:44:50 +01:00
f . vertex [ 0 ] = vr [ p [ 0 ] ] ;
f . vertex [ 1 ] = vr [ p [ j - 1 ] ] ;
f . vertex [ 2 ] = vr [ p [ j ] ] ;
2015-09-20 18:03:46 +02:00
faces . push_back ( f ) ;
}
}
2017-03-05 16:44:50 +01:00
Map < _EdgeKey , bool > edge_map ;
2017-01-07 22:25:37 +01:00
PoolVector < Vector3 > tmeshfaces ;
2017-03-05 16:44:50 +01:00
tmeshfaces . resize ( faces . size ( ) * 3 ) ;
2015-09-20 18:03:46 +02:00
{
2017-03-05 16:44:50 +01:00
PoolVector < Vector3 > : : Write tw = tmeshfaces . write ( ) ;
int tidx = 0 ;
2015-09-20 18:03:46 +02:00
2017-03-05 16:44:50 +01:00
for ( List < Face3 > : : Element * E = faces . front ( ) ; E ; E = E - > next ( ) ) {
2015-09-20 18:03:46 +02:00
const Face3 & f = E - > get ( ) ;
2017-03-05 16:44:50 +01:00
for ( int j = 0 ; j < 3 ; j + + ) {
tw [ tidx + + ] = f . vertex [ j ] ;
2015-09-20 18:03:46 +02:00
_EdgeKey ek ;
2017-06-30 20:47:17 +02:00
ek . from = f . vertex [ j ] . snapped ( Vector3 ( CMP_EPSILON , CMP_EPSILON , CMP_EPSILON ) ) ;
ek . to = f . vertex [ ( j + 1 ) % 3 ] . snapped ( Vector3 ( CMP_EPSILON , CMP_EPSILON , CMP_EPSILON ) ) ;
2017-03-05 16:44:50 +01:00
if ( ek . from < ek . to )
SWAP ( ek . from , ek . to ) ;
2015-09-20 18:03:46 +02:00
2019-02-12 21:10:08 +01:00
Map < _EdgeKey , bool > : : Element * F = edge_map . find ( ek ) ;
2015-09-20 18:03:46 +02:00
2019-02-12 21:10:08 +01:00
if ( F ) {
F - > get ( ) = false ;
2015-09-20 18:03:46 +02:00
} else {
2017-03-05 16:44:50 +01:00
edge_map [ ek ] = true ;
2015-09-20 18:03:46 +02:00
}
}
}
}
List < Vector3 > lines ;
2017-03-05 16:44:50 +01:00
for ( Map < _EdgeKey , bool > : : Element * E = edge_map . front ( ) ; E ; E = E - > next ( ) ) {
2015-09-20 18:03:46 +02:00
if ( E - > get ( ) ) {
lines . push_back ( E - > key ( ) . from ) ;
lines . push_back ( E - > key ( ) . to ) ;
}
}
2017-01-07 22:25:37 +01:00
PoolVector < Vector3 > varr ;
2015-09-20 18:03:46 +02:00
varr . resize ( lines . size ( ) ) ;
{
2017-01-07 22:25:37 +01:00
PoolVector < Vector3 > : : Write w = varr . write ( ) ;
2017-03-05 16:44:50 +01:00
int idx = 0 ;
for ( List < Vector3 > : : Element * E = lines . front ( ) ; E ; E = E - > next ( ) ) {
w [ idx + + ] = E - > get ( ) ;
2015-09-20 18:03:46 +02:00
}
}
2017-06-07 23:18:55 +02:00
debug_mesh = Ref < ArrayMesh > ( memnew ( ArrayMesh ) ) ;
2015-09-20 18:03:46 +02:00
Array arr ;
arr . resize ( Mesh : : ARRAY_MAX ) ;
2017-03-05 16:44:50 +01:00
arr [ Mesh : : ARRAY_VERTEX ] = varr ;
2015-09-20 18:03:46 +02:00
2017-03-05 16:44:50 +01:00
debug_mesh - > add_surface_from_arrays ( Mesh : : PRIMITIVE_LINES , arr ) ;
2015-09-20 18:03:46 +02:00
return debug_mesh ;
}
2014-08-02 03:10:38 +02:00
void NavigationMesh : : _bind_methods ( ) {
2017-02-28 13:10:29 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_sample_partition_type " , " sample_partition_type " ) , & NavigationMesh : : set_sample_partition_type ) ;
ClassDB : : bind_method ( D_METHOD ( " get_sample_partition_type " ) , & NavigationMesh : : get_sample_partition_type ) ;
2019-05-23 08:37:58 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_parsed_geometry_type " , " geometry_type " ) , & NavigationMesh : : set_parsed_geometry_type ) ;
ClassDB : : bind_method ( D_METHOD ( " get_parsed_geometry_type " ) , & NavigationMesh : : get_parsed_geometry_type ) ;
ClassDB : : bind_method ( D_METHOD ( " set_collision_mask " , " mask " ) , & NavigationMesh : : set_collision_mask ) ;
ClassDB : : bind_method ( D_METHOD ( " get_collision_mask " ) , & NavigationMesh : : get_collision_mask ) ;
ClassDB : : bind_method ( D_METHOD ( " set_collision_mask_bit " , " bit " , " value " ) , & NavigationMesh : : set_collision_mask_bit ) ;
ClassDB : : bind_method ( D_METHOD ( " get_collision_mask_bit " , " bit " ) , & NavigationMesh : : get_collision_mask_bit ) ;
2019-10-16 11:33:47 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_source_geometry_mode " , " mask " ) , & NavigationMesh : : set_source_geometry_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " get_source_geometry_mode " ) , & NavigationMesh : : get_source_geometry_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " set_source_group_name " , " mask " ) , & NavigationMesh : : set_source_group_name ) ;
ClassDB : : bind_method ( D_METHOD ( " get_source_group_name " ) , & NavigationMesh : : get_source_group_name ) ;
2017-02-28 13:10:29 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_cell_size " , " cell_size " ) , & NavigationMesh : : set_cell_size ) ;
ClassDB : : bind_method ( D_METHOD ( " get_cell_size " ) , & NavigationMesh : : get_cell_size ) ;
ClassDB : : bind_method ( D_METHOD ( " set_cell_height " , " cell_height " ) , & NavigationMesh : : set_cell_height ) ;
ClassDB : : bind_method ( D_METHOD ( " get_cell_height " ) , & NavigationMesh : : get_cell_height ) ;
ClassDB : : bind_method ( D_METHOD ( " set_agent_height " , " agent_height " ) , & NavigationMesh : : set_agent_height ) ;
ClassDB : : bind_method ( D_METHOD ( " get_agent_height " ) , & NavigationMesh : : get_agent_height ) ;
ClassDB : : bind_method ( D_METHOD ( " set_agent_radius " , " agent_radius " ) , & NavigationMesh : : set_agent_radius ) ;
ClassDB : : bind_method ( D_METHOD ( " get_agent_radius " ) , & NavigationMesh : : get_agent_radius ) ;
ClassDB : : bind_method ( D_METHOD ( " set_agent_max_climb " , " agent_max_climb " ) , & NavigationMesh : : set_agent_max_climb ) ;
ClassDB : : bind_method ( D_METHOD ( " get_agent_max_climb " ) , & NavigationMesh : : get_agent_max_climb ) ;
ClassDB : : bind_method ( D_METHOD ( " set_agent_max_slope " , " agent_max_slope " ) , & NavigationMesh : : set_agent_max_slope ) ;
ClassDB : : bind_method ( D_METHOD ( " get_agent_max_slope " ) , & NavigationMesh : : get_agent_max_slope ) ;
ClassDB : : bind_method ( D_METHOD ( " set_region_min_size " , " region_min_size " ) , & NavigationMesh : : set_region_min_size ) ;
ClassDB : : bind_method ( D_METHOD ( " get_region_min_size " ) , & NavigationMesh : : get_region_min_size ) ;
ClassDB : : bind_method ( D_METHOD ( " set_region_merge_size " , " region_merge_size " ) , & NavigationMesh : : set_region_merge_size ) ;
ClassDB : : bind_method ( D_METHOD ( " get_region_merge_size " ) , & NavigationMesh : : get_region_merge_size ) ;
ClassDB : : bind_method ( D_METHOD ( " set_edge_max_length " , " edge_max_length " ) , & NavigationMesh : : set_edge_max_length ) ;
ClassDB : : bind_method ( D_METHOD ( " get_edge_max_length " ) , & NavigationMesh : : get_edge_max_length ) ;
ClassDB : : bind_method ( D_METHOD ( " set_edge_max_error " , " edge_max_error " ) , & NavigationMesh : : set_edge_max_error ) ;
ClassDB : : bind_method ( D_METHOD ( " get_edge_max_error " ) , & NavigationMesh : : get_edge_max_error ) ;
ClassDB : : bind_method ( D_METHOD ( " set_verts_per_poly " , " verts_per_poly " ) , & NavigationMesh : : set_verts_per_poly ) ;
ClassDB : : bind_method ( D_METHOD ( " get_verts_per_poly " ) , & NavigationMesh : : get_verts_per_poly ) ;
ClassDB : : bind_method ( D_METHOD ( " set_detail_sample_distance " , " detail_sample_dist " ) , & NavigationMesh : : set_detail_sample_distance ) ;
ClassDB : : bind_method ( D_METHOD ( " get_detail_sample_distance " ) , & NavigationMesh : : get_detail_sample_distance ) ;
ClassDB : : bind_method ( D_METHOD ( " set_detail_sample_max_error " , " detail_sample_max_error " ) , & NavigationMesh : : set_detail_sample_max_error ) ;
ClassDB : : bind_method ( D_METHOD ( " get_detail_sample_max_error " ) , & NavigationMesh : : get_detail_sample_max_error ) ;
ClassDB : : bind_method ( D_METHOD ( " set_filter_low_hanging_obstacles " , " filter_low_hanging_obstacles " ) , & NavigationMesh : : set_filter_low_hanging_obstacles ) ;
ClassDB : : bind_method ( D_METHOD ( " get_filter_low_hanging_obstacles " ) , & NavigationMesh : : get_filter_low_hanging_obstacles ) ;
ClassDB : : bind_method ( D_METHOD ( " set_filter_ledge_spans " , " filter_ledge_spans " ) , & NavigationMesh : : set_filter_ledge_spans ) ;
ClassDB : : bind_method ( D_METHOD ( " get_filter_ledge_spans " ) , & NavigationMesh : : get_filter_ledge_spans ) ;
ClassDB : : bind_method ( D_METHOD ( " set_filter_walkable_low_height_spans " , " filter_walkable_low_height_spans " ) , & NavigationMesh : : set_filter_walkable_low_height_spans ) ;
ClassDB : : bind_method ( D_METHOD ( " get_filter_walkable_low_height_spans " ) , & NavigationMesh : : get_filter_walkable_low_height_spans ) ;
2014-08-02 03:10:38 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_vertices " , " vertices " ) , & NavigationMesh : : set_vertices ) ;
ClassDB : : bind_method ( D_METHOD ( " get_vertices " ) , & NavigationMesh : : get_vertices ) ;
2014-08-02 03:10:38 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " add_polygon " , " polygon " ) , & NavigationMesh : : add_polygon ) ;
ClassDB : : bind_method ( D_METHOD ( " get_polygon_count " ) , & NavigationMesh : : get_polygon_count ) ;
ClassDB : : bind_method ( D_METHOD ( " get_polygon " , " idx " ) , & NavigationMesh : : get_polygon ) ;
ClassDB : : bind_method ( D_METHOD ( " clear_polygons " ) , & NavigationMesh : : clear_polygons ) ;
2014-08-02 03:10:38 +02:00
2017-08-13 20:13:48 +02:00
ClassDB : : bind_method ( D_METHOD ( " create_from_mesh " , " mesh " ) , & NavigationMesh : : create_from_mesh ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " _set_polygons " , " polygons " ) , & NavigationMesh : : _set_polygons ) ;
ClassDB : : bind_method ( D_METHOD ( " _get_polygons " ) , & NavigationMesh : : _get_polygons ) ;
2014-08-02 03:10:38 +02:00
2017-02-28 13:10:29 +01:00
BIND_CONSTANT ( SAMPLE_PARTITION_WATERSHED ) ;
BIND_CONSTANT ( SAMPLE_PARTITION_MONOTONE ) ;
BIND_CONSTANT ( SAMPLE_PARTITION_LAYERS ) ;
2019-05-23 08:37:58 +02:00
BIND_CONSTANT ( PARSED_GEOMETRY_MESH_INSTANCES ) ;
BIND_CONSTANT ( PARSED_GEOMETRY_STATIC_COLLIDERS ) ;
BIND_CONSTANT ( PARSED_GEOMETRY_BOTH ) ;
2018-01-11 23:35:12 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : POOL_VECTOR3_ARRAY , " vertices " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL ) , " set_vertices " , " get_vertices " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : ARRAY , " polygons " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL ) , " _set_polygons " , " _get_polygons " ) ;
2017-02-28 13:10:29 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " sample_partition_type/sample_partition_type " , PROPERTY_HINT_ENUM , " Watershed,Monotone,Layers " ) , " set_sample_partition_type " , " get_sample_partition_type " ) ;
2019-05-23 08:37:58 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " geometry/parsed_geometry_type " , PROPERTY_HINT_ENUM , " Mesh Instances,Static Colliders,Both " ) , " set_parsed_geometry_type " , " get_parsed_geometry_type " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " geometry/collision_mask " , PROPERTY_HINT_LAYERS_3D_PHYSICS ) , " set_collision_mask " , " get_collision_mask " ) ;
2019-10-16 11:33:47 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " geometry/source_geometry_mode " , PROPERTY_HINT_ENUM , " Navmesh Children, Group With Children, Group Explicit " ) , " set_source_geometry_mode " , " get_source_geometry_mode " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : STRING , " geometry/source_group_name " ) , " set_source_group_name " , " get_source_group_name " ) ;
2017-02-28 13:10:29 +01:00
2019-05-10 17:03:18 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : REAL , " cell/size " , PROPERTY_HINT_RANGE , " 0.1,1.0,0.01,or_greater " ) , " set_cell_size " , " get_cell_size " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : REAL , " cell/height " , PROPERTY_HINT_RANGE , " 0.1,1.0,0.01,or_greater " ) , " set_cell_height " , " get_cell_height " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : REAL , " agent/height " , PROPERTY_HINT_RANGE , " 0.1,5.0,0.01,or_greater " ) , " set_agent_height " , " get_agent_height " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : REAL , " agent/radius " , PROPERTY_HINT_RANGE , " 0.1,5.0,0.01,or_greater " ) , " set_agent_radius " , " get_agent_radius " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : REAL , " agent/max_climb " , PROPERTY_HINT_RANGE , " 0.1,5.0,0.01,or_greater " ) , " set_agent_max_climb " , " get_agent_max_climb " ) ;
2017-02-28 13:10:29 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : REAL , " agent/max_slope " , PROPERTY_HINT_RANGE , " 0.0,90.0,0.1 " ) , " set_agent_max_slope " , " get_agent_max_slope " ) ;
2019-05-10 17:03:18 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : REAL , " region/min_size " , PROPERTY_HINT_RANGE , " 0.0,150.0,0.01,or_greater " ) , " set_region_min_size " , " get_region_min_size " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : REAL , " region/merge_size " , PROPERTY_HINT_RANGE , " 0.0,150.0,0.01,or_greater " ) , " set_region_merge_size " , " get_region_merge_size " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : REAL , " edge/max_length " , PROPERTY_HINT_RANGE , " 0.0,50.0,0.01,or_greater " ) , " set_edge_max_length " , " get_edge_max_length " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : REAL , " edge/max_error " , PROPERTY_HINT_RANGE , " 0.1,3.0,0.01,or_greater " ) , " set_edge_max_error " , " get_edge_max_error " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : REAL , " polygon/verts_per_poly " , PROPERTY_HINT_RANGE , " 3.0,12.0,1.0,or_greater " ) , " set_verts_per_poly " , " get_verts_per_poly " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : REAL , " detail/sample_distance " , PROPERTY_HINT_RANGE , " 0.0,16.0,0.01,or_greater " ) , " set_detail_sample_distance " , " get_detail_sample_distance " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : REAL , " detail/sample_max_error " , PROPERTY_HINT_RANGE , " 0.0,16.0,0.01,or_greater " ) , " set_detail_sample_max_error " , " get_detail_sample_max_error " ) ;
2017-02-28 13:10:29 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " filter/low_hanging_obstacles " ) , " set_filter_low_hanging_obstacles " , " get_filter_low_hanging_obstacles " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " filter/ledge_spans " ) , " set_filter_ledge_spans " , " get_filter_ledge_spans " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " filter/filter_walkable_low_height_spans " ) , " set_filter_walkable_low_height_spans " , " get_filter_walkable_low_height_spans " ) ;
2014-08-02 03:10:38 +02:00
}
2019-05-23 08:37:58 +02:00
void NavigationMesh : : _validate_property ( PropertyInfo & property ) const {
if ( property . name = = " geometry/collision_mask " ) {
if ( parsed_geometry_type = = PARSED_GEOMETRY_MESH_INSTANCES ) {
property . usage = 0 ;
return ;
}
}
2019-10-16 11:33:47 +02:00
if ( property . name = = " geometry/source_group_name " ) {
if ( source_geometry_mode = = SOURCE_GEOMETRY_NAVMESH_CHILDREN ) {
property . usage = 0 ;
return ;
}
}
2019-05-23 08:37:58 +02:00
}
2014-08-02 03:10:38 +02:00
NavigationMesh : : NavigationMesh ( ) {
2017-02-28 13:10:29 +01:00
cell_size = 0.3f ;
cell_height = 0.2f ;
agent_height = 2.0f ;
agent_radius = 0.6f ;
agent_max_climb = 0.9f ;
agent_max_slope = 45.0f ;
region_min_size = 8.0f ;
region_merge_size = 20.0f ;
edge_max_length = 12.0f ;
edge_max_error = 1.3f ;
verts_per_poly = 6.0f ;
detail_sample_distance = 6.0f ;
detail_sample_max_error = 1.0f ;
partition_type = SAMPLE_PARTITION_WATERSHED ;
2019-05-23 08:37:58 +02:00
parsed_geometry_type = PARSED_GEOMETRY_MESH_INSTANCES ;
collision_mask = 0xFFFFFFFF ;
2019-10-16 11:33:47 +02:00
source_geometry_mode = SOURCE_GEOMETRY_NAVMESH_CHILDREN ;
source_group_name = " navmesh " ;
2017-02-28 13:10:29 +01:00
filter_low_hanging_obstacles = false ;
filter_ledge_spans = false ;
filter_walkable_low_height_spans = false ;
2014-08-02 03:10:38 +02:00
}
void NavigationMeshInstance : : set_enabled ( bool p_enabled ) {
2017-03-05 16:44:50 +01:00
if ( enabled = = p_enabled )
2014-08-02 03:10:38 +02:00
return ;
2017-03-05 16:44:50 +01:00
enabled = p_enabled ;
2014-08-02 03:10:38 +02:00
2014-11-06 01:20:42 +01:00
if ( ! is_inside_tree ( ) )
2014-08-02 03:10:38 +02:00
return ;
if ( ! enabled ) {
2017-03-05 16:44:50 +01:00
if ( nav_id ! = - 1 ) {
2014-08-02 03:10:38 +02:00
navigation - > navmesh_remove ( nav_id ) ;
2017-03-05 16:44:50 +01:00
nav_id = - 1 ;
2014-08-02 03:10:38 +02:00
}
} else {
if ( navigation ) {
if ( navmesh . is_valid ( ) ) {
2017-12-15 21:09:06 +01:00
nav_id = navigation - > navmesh_add ( navmesh , get_relative_transform ( navigation ) , this ) ;
2014-08-02 03:10:38 +02:00
}
}
}
2015-09-20 18:03:46 +02:00
if ( debug_view ) {
2017-08-24 22:58:51 +02:00
MeshInstance * dm = Object : : cast_to < MeshInstance > ( debug_view ) ;
2015-09-20 18:03:46 +02:00
if ( is_enabled ( ) ) {
2017-03-05 16:44:50 +01:00
dm - > set_material_override ( get_tree ( ) - > get_debug_navigation_material ( ) ) ;
2015-09-20 18:03:46 +02:00
} else {
2017-03-05 16:44:50 +01:00
dm - > set_material_override ( get_tree ( ) - > get_debug_navigation_disabled_material ( ) ) ;
2015-09-20 18:03:46 +02:00
}
}
2014-08-02 03:10:38 +02:00
update_gizmo ( ) ;
}
bool NavigationMeshInstance : : is_enabled ( ) const {
return enabled ;
}
/////////////////////////////
void NavigationMeshInstance : : _notification ( int p_what ) {
2017-03-05 16:44:50 +01:00
switch ( p_what ) {
2014-11-06 01:20:42 +01:00
case NOTIFICATION_ENTER_TREE : {
2017-03-05 16:44:50 +01:00
Spatial * c = this ;
while ( c ) {
2017-08-24 22:58:51 +02:00
navigation = Object : : cast_to < Navigation > ( c ) ;
2014-08-02 03:10:38 +02:00
if ( navigation ) {
if ( enabled & & navmesh . is_valid ( ) ) {
2017-12-15 21:09:06 +01:00
nav_id = navigation - > navmesh_add ( navmesh , get_relative_transform ( navigation ) , this ) ;
2014-08-02 03:10:38 +02:00
}
break ;
}
2017-03-05 16:44:50 +01:00
c = c - > get_parent_spatial ( ) ;
2014-08-02 03:10:38 +02:00
}
2015-09-20 18:03:46 +02:00
if ( navmesh . is_valid ( ) & & get_tree ( ) - > is_debugging_navigation_hint ( ) ) {
2017-03-05 16:44:50 +01:00
MeshInstance * dm = memnew ( MeshInstance ) ;
dm - > set_mesh ( navmesh - > get_debug_mesh ( ) ) ;
2015-09-20 18:03:46 +02:00
if ( is_enabled ( ) ) {
2017-03-05 16:44:50 +01:00
dm - > set_material_override ( get_tree ( ) - > get_debug_navigation_material ( ) ) ;
2015-09-20 18:03:46 +02:00
} else {
2017-03-05 16:44:50 +01:00
dm - > set_material_override ( get_tree ( ) - > get_debug_navigation_disabled_material ( ) ) ;
2015-09-20 18:03:46 +02:00
}
add_child ( dm ) ;
2017-03-05 16:44:50 +01:00
debug_view = dm ;
2015-09-20 18:03:46 +02:00
}
2014-08-02 03:10:38 +02:00
} break ;
case NOTIFICATION_TRANSFORM_CHANGED : {
2017-03-05 16:44:50 +01:00
if ( navigation & & nav_id ! = - 1 ) {
navigation - > navmesh_set_transform ( nav_id , get_relative_transform ( navigation ) ) ;
2014-08-02 03:10:38 +02:00
}
} break ;
2014-11-06 01:20:42 +01:00
case NOTIFICATION_EXIT_TREE : {
2014-08-02 03:10:38 +02:00
if ( navigation ) {
2017-03-05 16:44:50 +01:00
if ( nav_id ! = - 1 ) {
2014-08-02 03:10:38 +02:00
navigation - > navmesh_remove ( nav_id ) ;
2017-03-05 16:44:50 +01:00
nav_id = - 1 ;
2014-08-02 03:10:38 +02:00
}
}
2015-09-20 18:03:46 +02:00
if ( debug_view ) {
debug_view - > queue_delete ( ) ;
2021-05-04 16:00:45 +02:00
debug_view = nullptr ;
2015-09-20 18:03:46 +02:00
}
2021-05-04 16:00:45 +02:00
navigation = nullptr ;
2014-08-02 03:10:38 +02:00
} break ;
}
}
2017-03-05 16:44:50 +01:00
void NavigationMeshInstance : : set_navigation_mesh ( const Ref < NavigationMesh > & p_navmesh ) {
if ( p_navmesh = = navmesh )
2014-08-02 03:10:38 +02:00
return ;
2017-03-05 16:44:50 +01:00
if ( navigation & & nav_id ! = - 1 ) {
2014-08-02 03:10:38 +02:00
navigation - > navmesh_remove ( nav_id ) ;
2017-03-05 16:44:50 +01:00
nav_id = - 1 ;
2014-08-02 03:10:38 +02:00
}
2019-05-23 08:37:58 +02:00
if ( navmesh . is_valid ( ) ) {
navmesh - > remove_change_receptor ( this ) ;
}
2017-03-05 16:44:50 +01:00
navmesh = p_navmesh ;
2014-08-02 03:10:38 +02:00
2019-05-23 08:37:58 +02:00
if ( navmesh . is_valid ( ) ) {
navmesh - > add_change_receptor ( this ) ;
}
2014-08-02 03:10:38 +02:00
if ( navigation & & navmesh . is_valid ( ) & & enabled ) {
2017-12-15 21:09:06 +01:00
nav_id = navigation - > navmesh_add ( navmesh , get_relative_transform ( navigation ) , this ) ;
2014-08-02 03:10:38 +02:00
}
2017-03-05 16:44:50 +01:00
2016-12-29 12:16:36 +01:00
if ( debug_view & & navmesh . is_valid ( ) ) {
2017-08-24 22:58:51 +02:00
Object : : cast_to < MeshInstance > ( debug_view ) - > set_mesh ( navmesh - > get_debug_mesh ( ) ) ;
2016-12-29 12:16:36 +01:00
}
2017-03-05 16:44:50 +01:00
2014-08-02 03:10:38 +02:00
update_gizmo ( ) ;
2016-05-17 23:27:15 +02:00
update_configuration_warning ( ) ;
2014-08-02 03:10:38 +02:00
}
2017-03-05 16:44:50 +01:00
Ref < NavigationMesh > NavigationMeshInstance : : get_navigation_mesh ( ) const {
2014-08-02 03:10:38 +02:00
return navmesh ;
}
2016-05-17 23:27:15 +02:00
String NavigationMeshInstance : : get_configuration_warning ( ) const {
2017-01-13 14:45:50 +01:00
if ( ! is_visible_in_tree ( ) | | ! is_inside_tree ( ) )
2016-05-17 23:27:15 +02:00
return String ( ) ;
2020-03-22 09:31:09 +01:00
String warning = Spatial : : get_configuration_warning ( ) ;
2016-05-17 23:27:15 +02:00
if ( ! navmesh . is_valid ( ) ) {
2020-03-22 09:31:09 +01:00
if ( warning ! = String ( ) ) {
warning + = " \n \n " ;
}
warning + = TTR ( " A NavigationMesh resource must be set or created for this node to work. " ) ;
return warning ;
2016-05-17 23:27:15 +02:00
}
2017-03-05 16:44:50 +01:00
const Spatial * c = this ;
while ( c ) {
2017-08-24 22:58:51 +02:00
if ( Object : : cast_to < Navigation > ( c ) )
2020-03-22 09:31:09 +01:00
return warning ;
2016-05-17 23:27:15 +02:00
2017-08-24 22:58:51 +02:00
c = Object : : cast_to < Spatial > ( c - > get_parent ( ) ) ;
2016-05-17 23:27:15 +02:00
}
2020-03-22 09:31:09 +01:00
if ( warning ! = String ( ) ) {
warning + = " \n \n " ;
}
warning + = TTR ( " NavigationMeshInstance must be a child or grandchild to a Navigation node. It only provides navigation data. " ) ;
return warning ;
2016-05-17 23:27:15 +02:00
}
2014-08-02 03:10:38 +02:00
void NavigationMeshInstance : : _bind_methods ( ) {
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_navigation_mesh " , " navmesh " ) , & NavigationMeshInstance : : set_navigation_mesh ) ;
ClassDB : : bind_method ( D_METHOD ( " get_navigation_mesh " ) , & NavigationMeshInstance : : get_navigation_mesh ) ;
2014-08-02 03:10:38 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_enabled " , " enabled " ) , & NavigationMeshInstance : : set_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_enabled " ) , & NavigationMeshInstance : : is_enabled ) ;
2014-08-02 03:10:38 +02:00
2017-03-05 16:44:50 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " navmesh " , PROPERTY_HINT_RESOURCE_TYPE , " NavigationMesh " ) , " set_navigation_mesh " , " get_navigation_mesh " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " enabled " ) , " set_enabled " , " is_enabled " ) ;
2014-08-02 03:10:38 +02:00
}
2019-05-23 08:37:58 +02:00
void NavigationMeshInstance : : _changed_callback ( Object * p_changed , const char * p_prop ) {
update_gizmo ( ) ;
update_configuration_warning ( ) ;
}
2014-08-02 03:10:38 +02:00
NavigationMeshInstance : : NavigationMeshInstance ( ) {
2021-05-04 16:00:45 +02:00
debug_view = nullptr ;
navigation = nullptr ;
2017-03-05 16:44:50 +01:00
nav_id = - 1 ;
enabled = true ;
2017-01-13 00:35:46 +01:00
set_notify_transform ( true ) ;
2014-08-02 03:10:38 +02:00
}
2019-05-23 08:37:58 +02:00
NavigationMeshInstance : : ~ NavigationMeshInstance ( ) {
if ( navmesh . is_valid ( ) )
navmesh - > remove_change_receptor ( this ) ;
}