2014-02-10 02:10:30 +01:00
/*************************************************************************/
/* grid_map.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 14:16:55 +02:00
/* https://godotengine.org */
2014-02-10 02:10:30 +01:00
/*************************************************************************/
2019-01-01 12:53:14 +01:00
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
2014-02-10 02:10:30 +01: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-02-10 02:10:30 +01:00
# include "grid_map.h"
2017-02-15 12:29:46 +01:00
2018-09-11 18:13:45 +02:00
# include "core/io/marshalls.h"
2018-09-27 11:24:41 +02:00
# include "core/message_queue.h"
# include "scene/3d/light.h"
2016-04-20 20:19:05 +02:00
# include "scene/resources/mesh_library.h"
2018-09-27 11:24:41 +02:00
# include "scene/resources/surface_tool.h"
2017-03-05 16:44:50 +01:00
# include "scene/scene_string_names.h"
2018-09-27 11:24:41 +02:00
# include "servers/visual_server.h"
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
bool GridMap : : _set ( const StringName & p_name , const Variant & p_value ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
String name = p_name ;
2014-02-10 02:10:30 +01:00
2018-01-11 23:35:12 +01:00
if ( name = = " data " ) {
2014-02-10 02:10:30 +01:00
Dictionary d = p_value ;
if ( d . has ( " cells " ) ) {
2017-01-07 22:25:37 +01:00
PoolVector < int > cells = d [ " cells " ] ;
2017-03-05 16:44:50 +01:00
int amount = cells . size ( ) ;
2017-01-07 22:25:37 +01:00
PoolVector < int > : : Read r = cells . read ( ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( amount % 3 , false ) ; // not even
2017-01-14 18:03:38 +01:00
cell_map . clear ( ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < amount / 3 ; i + + ) {
2014-02-10 02:10:30 +01:00
IndexKey ik ;
2017-03-05 16:44:50 +01:00
ik . key = decode_uint64 ( ( const uint8_t * ) & r [ i * 3 ] ) ;
2014-02-10 02:10:30 +01:00
Cell cell ;
2017-03-05 16:44:50 +01:00
cell . cell = decode_uint32 ( ( const uint8_t * ) & r [ i * 3 + 2 ] ) ;
cell_map [ ik ] = cell ;
2014-02-10 02:10:30 +01:00
}
}
2018-09-27 11:24:41 +02:00
2014-02-10 02:10:30 +01:00
_recreate_octant_data ( ) ;
2018-09-27 11:24:41 +02:00
2017-12-18 04:34:48 +01:00
} else if ( name = = " baked_meshes " ) {
clear_baked_meshes ( ) ;
Array meshes = p_value ;
for ( int i = 0 ; i < meshes . size ( ) ; i + + ) {
BakedMesh bm ;
bm . mesh = meshes [ i ] ;
ERR_CONTINUE ( ! bm . mesh . is_valid ( ) ) ;
bm . instance = VS : : get_singleton ( ) - > instance_create ( ) ;
VS : : get_singleton ( ) - > get_singleton ( ) - > instance_set_base ( bm . instance , bm . mesh - > get_rid ( ) ) ;
VS : : get_singleton ( ) - > instance_attach_object_instance_id ( bm . instance , get_instance_id ( ) ) ;
if ( is_inside_tree ( ) ) {
VS : : get_singleton ( ) - > instance_set_scenario ( bm . instance , get_world ( ) - > get_scenario ( ) ) ;
VS : : get_singleton ( ) - > instance_set_transform ( bm . instance , get_global_transform ( ) ) ;
}
baked_meshes . push_back ( bm ) ;
}
_recreate_octant_data ( ) ;
2014-02-10 02:10:30 +01:00
2018-09-27 11:24:41 +02:00
} else {
2014-02-10 02:10:30 +01:00
return false ;
2018-09-27 11:24:41 +02:00
}
2014-02-10 02:10:30 +01:00
return true ;
}
2017-03-05 16:44:50 +01:00
bool GridMap : : _get ( const StringName & p_name , Variant & r_ret ) const {
String name = p_name ;
2018-01-11 23:35:12 +01:00
if ( name = = " data " ) {
2014-02-10 02:10:30 +01:00
Dictionary d ;
2017-01-07 22:25:37 +01:00
PoolVector < int > cells ;
2017-03-05 16:44:50 +01:00
cells . resize ( cell_map . size ( ) * 3 ) ;
2014-02-10 02:10:30 +01:00
{
2017-01-07 22:25:37 +01:00
PoolVector < int > : : Write w = cells . write ( ) ;
2017-03-05 16:44:50 +01:00
int i = 0 ;
for ( Map < IndexKey , Cell > : : Element * E = cell_map . front ( ) ; E ; E = E - > next ( ) , i + + ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
encode_uint64 ( E - > key ( ) . key , ( uint8_t * ) & w [ i * 3 ] ) ;
encode_uint32 ( E - > get ( ) . cell , ( uint8_t * ) & w [ i * 3 + 2 ] ) ;
2014-02-10 02:10:30 +01:00
}
}
2017-03-05 16:44:50 +01:00
d [ " cells " ] = cells ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
r_ret = d ;
2017-12-18 04:34:48 +01:00
} else if ( name = = " baked_meshes " ) {
Array ret ;
ret . resize ( baked_meshes . size ( ) ) ;
for ( int i = 0 ; i < baked_meshes . size ( ) ; i + + ) {
ret . push_back ( baked_meshes [ i ] . mesh ) ;
}
r_ret = ret ;
2014-02-10 02:10:30 +01:00
} else
return false ;
return true ;
}
2017-03-05 16:44:50 +01:00
void GridMap : : _get_property_list ( List < PropertyInfo > * p_list ) const {
2014-02-10 02:10:30 +01:00
2017-12-18 04:34:48 +01:00
if ( baked_meshes . size ( ) ) {
p_list - > push_back ( PropertyInfo ( Variant : : ARRAY , " baked_meshes " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_STORAGE ) ) ;
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
p_list - > push_back ( PropertyInfo ( Variant : : DICTIONARY , " data " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_STORAGE ) ) ;
2014-02-10 02:10:30 +01:00
}
2017-12-28 16:13:45 +01:00
void GridMap : : set_collision_layer ( uint32_t p_layer ) {
collision_layer = p_layer ;
_reset_physic_bodies_collision_filters ( ) ;
}
uint32_t GridMap : : get_collision_layer ( ) const {
return collision_layer ;
}
void GridMap : : set_collision_mask ( uint32_t p_mask ) {
collision_mask = p_mask ;
_reset_physic_bodies_collision_filters ( ) ;
}
uint32_t GridMap : : get_collision_mask ( ) const {
return collision_mask ;
}
void GridMap : : 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 GridMap : : get_collision_mask_bit ( int p_bit ) const {
return get_collision_mask ( ) & ( 1 < < p_bit ) ;
}
void GridMap : : set_collision_layer_bit ( int p_bit , bool p_value ) {
uint32_t mask = get_collision_layer ( ) ;
if ( p_value )
mask | = 1 < < p_bit ;
else
mask & = ~ ( 1 < < p_bit ) ;
set_collision_layer ( mask ) ;
}
bool GridMap : : get_collision_layer_bit ( int p_bit ) const {
return get_collision_layer ( ) & ( 1 < < p_bit ) ;
}
2018-08-22 08:10:54 +02:00
# ifndef DISABLE_DEPRECATED
2017-03-05 16:44:50 +01:00
void GridMap : : set_theme ( const Ref < MeshLibrary > & p_theme ) {
2014-02-10 02:10:30 +01:00
2019-08-11 10:49:53 +02:00
WARN_DEPRECATED_MSG ( " GridMap.theme/set_theme() is deprecated and will be removed in a future version. Use GridMap.mesh_library/set_mesh_library() instead. " ) ;
2018-08-29 20:14:27 +02:00
2018-08-22 08:10:54 +02:00
set_mesh_library ( p_theme ) ;
}
Ref < MeshLibrary > GridMap : : get_theme ( ) const {
2019-08-11 10:49:53 +02:00
WARN_DEPRECATED_MSG ( " GridMap.theme/get_theme() is deprecated and will be removed in a future version. Use GridMap.mesh_library/get_mesh_library() instead. " ) ;
2018-08-29 20:14:27 +02:00
2018-08-22 08:10:54 +02:00
return get_mesh_library ( ) ;
}
# endif // DISABLE_DEPRECATED
void GridMap : : set_mesh_library ( const Ref < MeshLibrary > & p_mesh_library ) {
if ( ! mesh_library . is_null ( ) )
mesh_library - > unregister_owner ( this ) ;
mesh_library = p_mesh_library ;
if ( ! mesh_library . is_null ( ) )
mesh_library - > register_owner ( this ) ;
2014-02-10 02:10:30 +01:00
_recreate_octant_data ( ) ;
2018-08-22 08:10:54 +02:00
_change_notify ( " mesh_library " ) ;
2014-02-10 02:10:30 +01:00
}
2018-08-22 08:10:54 +02:00
Ref < MeshLibrary > GridMap : : get_mesh_library ( ) const {
2014-02-10 02:10:30 +01:00
2018-08-22 08:10:54 +02:00
return mesh_library ;
2014-02-10 02:10:30 +01:00
}
2017-08-27 21:00:59 +02:00
void GridMap : : set_cell_size ( const Vector3 & p_size ) {
2014-02-10 02:10:30 +01:00
2017-08-29 13:47:29 +02:00
ERR_FAIL_COND ( p_size . x < 0.001 | | p_size . y < 0.001 | | p_size . z < 0.001 ) ;
2017-03-05 16:44:50 +01:00
cell_size = p_size ;
2014-02-10 02:10:30 +01:00
_recreate_octant_data ( ) ;
}
2017-08-27 21:00:59 +02:00
Vector3 GridMap : : get_cell_size ( ) const {
2014-02-10 02:10:30 +01:00
return cell_size ;
}
2017-03-05 16:44:50 +01:00
void GridMap : : set_octant_size ( int p_size ) {
2014-02-10 02:10:30 +01:00
2019-06-21 11:34:32 +02:00
ERR_FAIL_COND ( p_size = = 0 ) ;
2017-03-05 16:44:50 +01:00
octant_size = p_size ;
2014-02-10 02:10:30 +01:00
_recreate_octant_data ( ) ;
}
2017-03-05 16:44:50 +01:00
int GridMap : : get_octant_size ( ) const {
2014-02-10 02:10:30 +01:00
return octant_size ;
}
void GridMap : : set_center_x ( bool p_enable ) {
2017-03-05 16:44:50 +01:00
center_x = p_enable ;
2014-02-10 02:10:30 +01:00
_recreate_octant_data ( ) ;
}
bool GridMap : : get_center_x ( ) const {
return center_x ;
}
void GridMap : : set_center_y ( bool p_enable ) {
2017-03-05 16:44:50 +01:00
center_y = p_enable ;
2014-02-10 02:10:30 +01:00
_recreate_octant_data ( ) ;
}
bool GridMap : : get_center_y ( ) const {
return center_y ;
}
void GridMap : : set_center_z ( bool p_enable ) {
2017-03-05 16:44:50 +01:00
center_z = p_enable ;
2014-02-10 02:10:30 +01:00
_recreate_octant_data ( ) ;
}
bool GridMap : : get_center_z ( ) const {
return center_z ;
}
2017-03-05 16:44:50 +01:00
void GridMap : : set_cell_item ( int p_x , int p_y , int p_z , int p_item , int p_rot ) {
2014-02-10 02:10:30 +01:00
2017-12-18 04:34:48 +01:00
if ( baked_meshes . size ( ) & & ! recreating_octants ) {
//if you set a cell item, baked meshes go good bye
clear_baked_meshes ( ) ;
_recreate_octant_data ( ) ;
}
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( ABS ( p_x ) , 1 < < 20 ) ;
ERR_FAIL_INDEX ( ABS ( p_y ) , 1 < < 20 ) ;
ERR_FAIL_INDEX ( ABS ( p_z ) , 1 < < 20 ) ;
2014-02-10 02:10:30 +01:00
IndexKey key ;
2017-03-05 16:44:50 +01:00
key . x = p_x ;
key . y = p_y ;
key . z = p_z ;
2014-02-10 02:10:30 +01:00
OctantKey ok ;
2017-03-05 16:44:50 +01:00
ok . x = p_x / octant_size ;
ok . y = p_y / octant_size ;
ok . z = p_z / octant_size ;
2014-02-10 02:10:30 +01:00
2017-08-27 21:00:59 +02:00
if ( p_item < 0 ) {
//erase
if ( cell_map . has ( key ) ) {
OctantKey octantkey = ok ;
2014-02-10 02:10:30 +01:00
2017-08-27 21:00:59 +02:00
ERR_FAIL_COND ( ! octant_map . has ( octantkey ) ) ;
Octant & g = * octant_map [ octantkey ] ;
g . cells . erase ( key ) ;
2017-03-05 16:44:50 +01:00
g . dirty = true ;
2017-08-27 21:00:59 +02:00
cell_map . erase ( key ) ;
_queue_octants_dirty ( ) ;
2014-02-10 02:10:30 +01:00
}
return ;
2017-08-27 21:00:59 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
OctantKey octantkey = ok ;
2014-02-10 02:10:30 +01:00
if ( ! octant_map . has ( octantkey ) ) {
2017-08-27 21:00:59 +02:00
//create octant because it does not exist
2017-03-05 16:44:50 +01:00
Octant * g = memnew ( Octant ) ;
g - > dirty = true ;
2014-02-10 02:10:30 +01:00
g - > static_body = PhysicsServer : : get_singleton ( ) - > body_create ( PhysicsServer : : BODY_MODE_STATIC ) ;
2017-08-07 12:17:31 +02:00
PhysicsServer : : get_singleton ( ) - > body_attach_object_instance_id ( g - > static_body , get_instance_id ( ) ) ;
2017-12-28 16:13:45 +01:00
PhysicsServer : : get_singleton ( ) - > body_set_collision_layer ( g - > static_body , collision_layer ) ;
PhysicsServer : : get_singleton ( ) - > body_set_collision_mask ( g - > static_body , collision_mask ) ;
2017-03-05 16:44:50 +01:00
SceneTree * st = SceneTree : : get_singleton ( ) ;
2015-09-20 18:03:46 +02:00
if ( st & & st - > is_debugging_collisions_hint ( ) ) {
2017-03-05 16:44:50 +01:00
g - > collision_debug = VisualServer : : get_singleton ( ) - > mesh_create ( ) ;
g - > collision_debug_instance = VisualServer : : get_singleton ( ) - > instance_create ( ) ;
VisualServer : : get_singleton ( ) - > instance_set_base ( g - > collision_debug_instance , g - > collision_debug ) ;
2015-09-20 18:03:46 +02:00
}
2017-03-05 16:44:50 +01:00
octant_map [ octantkey ] = g ;
2014-02-10 02:10:30 +01:00
2017-08-27 21:00:59 +02:00
if ( is_inside_world ( ) ) {
_octant_enter_world ( octantkey ) ;
_octant_transform ( octantkey ) ;
2014-02-10 02:10:30 +01:00
}
}
2017-08-27 21:00:59 +02:00
Octant & g = * octant_map [ octantkey ] ;
g . cells . insert ( key ) ;
2017-03-05 16:44:50 +01:00
g . dirty = true ;
2017-08-27 21:00:59 +02:00
_queue_octants_dirty ( ) ;
2014-02-10 02:10:30 +01:00
2017-08-27 21:00:59 +02:00
Cell c ;
2017-03-05 16:44:50 +01:00
c . item = p_item ;
c . rot = p_rot ;
2017-08-27 21:00:59 +02:00
cell_map [ key ] = c ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
int GridMap : : get_cell_item ( int p_x , int p_y , int p_z ) const {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( ABS ( p_x ) , 1 < < 20 , INVALID_CELL_ITEM ) ;
ERR_FAIL_INDEX_V ( ABS ( p_y ) , 1 < < 20 , INVALID_CELL_ITEM ) ;
ERR_FAIL_INDEX_V ( ABS ( p_z ) , 1 < < 20 , INVALID_CELL_ITEM ) ;
2014-02-10 02:10:30 +01:00
IndexKey key ;
2017-03-05 16:44:50 +01:00
key . x = p_x ;
key . y = p_y ;
key . z = p_z ;
2014-02-10 02:10:30 +01:00
if ( ! cell_map . has ( key ) )
return INVALID_CELL_ITEM ;
return cell_map [ key ] . item ;
}
2017-03-05 16:44:50 +01:00
int GridMap : : get_cell_item_orientation ( int p_x , int p_y , int p_z ) const {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( ABS ( p_x ) , 1 < < 20 , - 1 ) ;
ERR_FAIL_INDEX_V ( ABS ( p_y ) , 1 < < 20 , - 1 ) ;
ERR_FAIL_INDEX_V ( ABS ( p_z ) , 1 < < 20 , - 1 ) ;
2014-02-10 02:10:30 +01:00
IndexKey key ;
2017-03-05 16:44:50 +01:00
key . x = p_x ;
key . y = p_y ;
key . z = p_z ;
2014-02-10 02:10:30 +01:00
if ( ! cell_map . has ( key ) )
return - 1 ;
return cell_map [ key ] . rot ;
}
2017-10-07 13:30:58 +02:00
Vector3 GridMap : : world_to_map ( const Vector3 & p_world_pos ) const {
Vector3 map_pos = p_world_pos / cell_size ;
map_pos . x = floor ( map_pos . x ) ;
map_pos . y = floor ( map_pos . y ) ;
map_pos . z = floor ( map_pos . z ) ;
return map_pos ;
}
Vector3 GridMap : : map_to_world ( int p_x , int p_y , int p_z ) const {
Vector3 offset = _get_offset ( ) ;
Vector3 world_pos (
p_x * cell_size . x + offset . x ,
p_y * cell_size . y + offset . y ,
p_z * cell_size . z + offset . z ) ;
return world_pos ;
}
2017-08-27 21:00:59 +02:00
void GridMap : : _octant_transform ( const OctantKey & p_key ) {
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! octant_map . has ( p_key ) ) ;
2017-03-05 16:44:50 +01:00
Octant & g = * octant_map [ p_key ] ;
PhysicsServer : : get_singleton ( ) - > body_set_state ( g . static_body , PhysicsServer : : BODY_STATE_TRANSFORM , get_global_transform ( ) ) ;
2014-02-10 02:10:30 +01:00
2015-09-20 18:03:46 +02:00
if ( g . collision_debug_instance . is_valid ( ) ) {
2017-03-05 16:44:50 +01:00
VS : : get_singleton ( ) - > instance_set_transform ( g . collision_debug_instance , get_global_transform ( ) ) ;
2015-09-20 18:03:46 +02:00
}
2014-02-10 02:10:30 +01:00
2017-08-27 21:00:59 +02:00
for ( int i = 0 ; i < g . multimesh_instances . size ( ) ; i + + ) {
VS : : get_singleton ( ) - > instance_set_transform ( g . multimesh_instances [ i ] . instance , get_global_transform ( ) ) ;
2014-02-10 02:10:30 +01:00
}
}
2017-08-27 21:00:59 +02:00
bool GridMap : : _octant_update ( const OctantKey & p_key ) {
ERR_FAIL_COND_V ( ! octant_map . has ( p_key ) , false ) ;
2017-03-05 16:44:50 +01:00
Octant & g = * octant_map [ p_key ] ;
2017-08-27 21:00:59 +02:00
if ( ! g . dirty )
return false ;
2014-02-10 02:10:30 +01:00
2017-08-27 21:00:59 +02:00
//erase body shapes
PhysicsServer : : get_singleton ( ) - > body_clear_shapes ( g . static_body ) ;
2015-09-20 18:03:46 +02:00
2017-08-27 21:00:59 +02:00
//erase body shapes debug
if ( g . collision_debug . is_valid ( ) ) {
2014-02-10 02:10:30 +01:00
2017-08-27 21:00:59 +02:00
VS : : get_singleton ( ) - > mesh_clear ( g . collision_debug ) ;
2014-02-10 02:10:30 +01:00
}
2017-08-27 21:00:59 +02:00
//erase navigation
2016-04-20 20:19:05 +02:00
if ( navigation ) {
2017-03-05 16:44:50 +01:00
for ( Map < IndexKey , Octant : : NavMesh > : : Element * E = g . navmesh_ids . front ( ) ; E ; E = E - > next ( ) ) {
2017-08-27 21:00:59 +02:00
navigation - > navmesh_remove ( E - > get ( ) . id ) ;
2016-04-20 20:19:05 +02:00
}
g . navmesh_ids . clear ( ) ;
}
2014-02-10 02:10:30 +01:00
2017-08-27 21:00:59 +02:00
//erase multimeshes
2014-02-10 02:10:30 +01:00
2017-08-27 21:00:59 +02:00
for ( int i = 0 ; i < g . multimesh_instances . size ( ) ; i + + ) {
2014-02-10 02:10:30 +01:00
2017-08-27 21:00:59 +02:00
VS : : get_singleton ( ) - > free ( g . multimesh_instances [ i ] . instance ) ;
VS : : get_singleton ( ) - > free ( g . multimesh_instances [ i ] . multimesh ) ;
}
g . multimesh_instances . clear ( ) ;
2015-09-20 18:03:46 +02:00
2017-08-27 21:00:59 +02:00
if ( g . cells . size ( ) = = 0 ) {
//octant no longer needed
_octant_clean_up ( p_key ) ;
return true ;
2015-09-20 18:03:46 +02:00
}
2017-01-07 22:25:37 +01:00
PoolVector < Vector3 > col_debug ;
2015-09-20 18:03:46 +02:00
2016-04-20 20:19:05 +02:00
/*
* foreach item in this octant ,
* set item ' s multimesh ' s instance count to number of cells which have this item
* and set said multimesh bounding box to one containing all cells which have this item
*/
2014-02-10 02:10:30 +01:00
2017-08-27 21:00:59 +02:00
Map < int , List < Pair < Transform , IndexKey > > > multimesh_items ;
2014-02-10 02:10:30 +01:00
2017-08-27 21:00:59 +02:00
for ( Set < IndexKey > : : Element * E = g . cells . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 02:10:30 +01:00
2017-08-27 21:00:59 +02:00
ERR_CONTINUE ( ! cell_map . has ( E - > get ( ) ) ) ;
const Cell & c = cell_map [ E - > get ( ) ] ;
2018-08-22 08:10:54 +02:00
if ( ! mesh_library . is_valid ( ) | | ! mesh_library - > has_item ( c . item ) )
2017-08-27 21:00:59 +02:00
continue ;
2014-02-10 02:10:30 +01:00
2017-08-27 21:00:59 +02:00
Vector3 cellpos = Vector3 ( E - > get ( ) . x , E - > get ( ) . y , E - > get ( ) . z ) ;
2017-10-07 13:30:58 +02:00
Vector3 ofs = _get_offset ( ) ;
2014-02-10 02:10:30 +01:00
2017-08-27 21:00:59 +02:00
Transform xform ;
2014-02-10 02:10:30 +01:00
2017-08-27 21:00:59 +02:00
xform . basis . set_orthogonal_index ( c . rot ) ;
xform . set_origin ( cellpos * cell_size + ofs ) ;
xform . basis . scale ( Vector3 ( cell_scale , cell_scale , cell_scale ) ) ;
2017-12-20 15:09:56 +01:00
if ( baked_meshes . size ( ) = = 0 ) {
2018-08-22 08:10:54 +02:00
if ( mesh_library - > get_item_mesh ( c . item ) . is_valid ( ) ) {
2017-12-19 13:55:01 +01:00
if ( ! multimesh_items . has ( c . item ) ) {
multimesh_items [ c . item ] = List < Pair < Transform , IndexKey > > ( ) ;
}
Pair < Transform , IndexKey > p ;
p . first = xform ;
p . second = E - > get ( ) ;
multimesh_items [ c . item ] . push_back ( p ) ;
2014-02-10 02:10:30 +01:00
}
2017-08-27 21:00:59 +02:00
}
2014-02-10 02:10:30 +01:00
2018-08-22 08:10:54 +02:00
Vector < MeshLibrary : : ShapeData > shapes = mesh_library - > get_item_shapes ( c . item ) ;
2017-08-27 21:00:59 +02:00
// add the item's shape at given xform to octant's static_body
for ( int i = 0 ; i < shapes . size ( ) ; i + + ) {
// add the item's shape
if ( ! shapes [ i ] . shape . is_valid ( ) )
continue ;
PhysicsServer : : get_singleton ( ) - > body_add_shape ( g . static_body , shapes [ i ] . shape - > get_rid ( ) , xform * shapes [ i ] . local_transform ) ;
if ( g . collision_debug . is_valid ( ) ) {
2018-07-25 03:11:03 +02:00
shapes . write [ i ] . shape - > add_vertices_to_array ( col_debug , xform * shapes [ i ] . local_transform ) ;
2017-08-27 21:00:59 +02:00
}
}
2014-02-10 02:10:30 +01:00
2017-08-27 21:00:59 +02:00
// add the item's navmesh at given xform to GridMap's Navigation ancestor
2018-08-22 08:10:54 +02:00
Ref < NavigationMesh > navmesh = mesh_library - > get_item_navmesh ( c . item ) ;
2017-08-27 21:00:59 +02:00
if ( navmesh . is_valid ( ) ) {
Octant : : NavMesh nm ;
2019-02-26 14:38:23 +01:00
nm . xform = xform * mesh_library - > get_item_navmesh_transform ( c . item ) ;
2014-02-10 02:10:30 +01:00
2017-08-27 21:00:59 +02:00
if ( navigation ) {
2017-12-15 21:09:06 +01:00
nm . id = navigation - > navmesh_add ( navmesh , xform , this ) ;
2017-08-27 21:00:59 +02:00
} else {
nm . id = - 1 ;
2014-02-10 02:10:30 +01:00
}
2017-08-27 21:00:59 +02:00
g . navmesh_ids [ E - > get ( ) ] = nm ;
}
}
2014-02-10 02:10:30 +01:00
2017-12-18 04:34:48 +01:00
//update multimeshes, only if not baked
if ( baked_meshes . size ( ) = = 0 ) {
2014-02-10 02:10:30 +01:00
2017-12-18 04:34:48 +01:00
for ( Map < int , List < Pair < Transform , IndexKey > > > : : Element * E = multimesh_items . front ( ) ; E ; E = E - > next ( ) ) {
Octant : : MultimeshInstance mmi ;
2014-02-10 02:10:30 +01:00
2017-12-18 04:34:48 +01:00
RID mm = VS : : get_singleton ( ) - > multimesh_create ( ) ;
VS : : get_singleton ( ) - > multimesh_allocate ( mm , E - > get ( ) . size ( ) , VS : : MULTIMESH_TRANSFORM_3D , VS : : MULTIMESH_COLOR_NONE ) ;
2018-08-22 08:10:54 +02:00
VS : : get_singleton ( ) - > multimesh_set_mesh ( mm , mesh_library - > get_item_mesh ( E - > key ( ) ) - > get_rid ( ) ) ;
2017-12-18 04:34:48 +01:00
int idx = 0 ;
for ( List < Pair < Transform , IndexKey > > : : Element * F = E - > get ( ) . front ( ) ; F ; F = F - > next ( ) ) {
VS : : get_singleton ( ) - > multimesh_instance_set_transform ( mm , idx , F - > get ( ) . first ) ;
2017-08-27 21:00:59 +02:00
# ifdef TOOLS_ENABLED
2017-12-18 04:34:48 +01:00
Octant : : MultimeshInstance : : Item it ;
it . index = idx ;
it . transform = F - > get ( ) . first ;
it . key = F - > get ( ) . second ;
mmi . items . push_back ( it ) ;
2017-08-27 21:00:59 +02:00
# endif
2016-04-20 20:19:05 +02:00
2017-12-18 04:34:48 +01:00
idx + + ;
}
2014-02-10 02:10:30 +01:00
2017-12-18 04:34:48 +01:00
RID instance = VS : : get_singleton ( ) - > instance_create ( ) ;
VS : : get_singleton ( ) - > instance_set_base ( instance , mm ) ;
2017-08-27 21:00:59 +02:00
2017-12-18 04:34:48 +01:00
if ( is_inside_tree ( ) ) {
VS : : get_singleton ( ) - > instance_set_scenario ( instance , get_world ( ) - > get_scenario ( ) ) ;
VS : : get_singleton ( ) - > instance_set_transform ( instance , get_global_transform ( ) ) ;
}
2017-08-27 21:00:59 +02:00
2017-12-18 04:34:48 +01:00
mmi . multimesh = mm ;
mmi . instance = instance ;
2017-08-27 21:00:59 +02:00
2017-12-18 04:34:48 +01:00
g . multimesh_instances . push_back ( mmi ) ;
}
2014-02-10 02:10:30 +01:00
}
2015-09-20 18:03:46 +02:00
if ( col_debug . size ( ) ) {
Array arr ;
arr . resize ( VS : : ARRAY_MAX ) ;
2017-03-05 16:44:50 +01:00
arr [ VS : : ARRAY_VERTEX ] = col_debug ;
2015-09-20 18:03:46 +02:00
2017-03-05 16:44:50 +01:00
VS : : get_singleton ( ) - > mesh_add_surface_from_arrays ( g . collision_debug , VS : : PRIMITIVE_LINES , arr ) ;
SceneTree * st = SceneTree : : get_singleton ( ) ;
2015-09-20 18:03:46 +02:00
if ( st ) {
2017-03-05 16:44:50 +01:00
VS : : get_singleton ( ) - > mesh_surface_set_material ( g . collision_debug , 0 , st - > get_debug_collision_material ( ) - > get_rid ( ) ) ;
2015-09-20 18:03:46 +02:00
}
}
2017-03-05 16:44:50 +01:00
g . dirty = false ;
2017-08-27 21:00:59 +02:00
return false ;
}
2017-12-28 16:13:45 +01:00
void GridMap : : _reset_physic_bodies_collision_filters ( ) {
for ( Map < OctantKey , Octant * > : : Element * E = octant_map . front ( ) ; E ; E = E - > next ( ) ) {
PhysicsServer : : get_singleton ( ) - > body_set_collision_layer ( E - > get ( ) - > static_body , collision_layer ) ;
PhysicsServer : : get_singleton ( ) - > body_set_collision_mask ( E - > get ( ) - > static_body , collision_mask ) ;
}
}
2017-08-27 21:00:59 +02:00
void GridMap : : _octant_enter_world ( const OctantKey & p_key ) {
ERR_FAIL_COND ( ! octant_map . has ( p_key ) ) ;
Octant & g = * octant_map [ p_key ] ;
PhysicsServer : : get_singleton ( ) - > body_set_state ( g . static_body , PhysicsServer : : BODY_STATE_TRANSFORM , get_global_transform ( ) ) ;
PhysicsServer : : get_singleton ( ) - > body_set_space ( g . static_body , get_world ( ) - > get_space ( ) ) ;
if ( g . collision_debug_instance . is_valid ( ) ) {
VS : : get_singleton ( ) - > instance_set_scenario ( g . collision_debug_instance , get_world ( ) - > get_scenario ( ) ) ;
VS : : get_singleton ( ) - > instance_set_transform ( g . collision_debug_instance , get_global_transform ( ) ) ;
}
for ( int i = 0 ; i < g . multimesh_instances . size ( ) ; i + + ) {
VS : : get_singleton ( ) - > instance_set_scenario ( g . multimesh_instances [ i ] . instance , get_world ( ) - > get_scenario ( ) ) ;
VS : : get_singleton ( ) - > instance_set_transform ( g . multimesh_instances [ i ] . instance , get_global_transform ( ) ) ;
}
2018-08-22 08:10:54 +02:00
if ( navigation & & mesh_library . is_valid ( ) ) {
2017-08-27 21:00:59 +02:00
for ( Map < IndexKey , Octant : : NavMesh > : : Element * F = g . navmesh_ids . front ( ) ; F ; F = F - > next ( ) ) {
if ( cell_map . has ( F - > key ( ) ) & & F - > get ( ) . id < 0 ) {
2018-08-22 08:10:54 +02:00
Ref < NavigationMesh > nm = mesh_library - > get_item_navmesh ( cell_map [ F - > key ( ) ] . item ) ;
2017-08-27 21:00:59 +02:00
if ( nm . is_valid ( ) ) {
2017-12-15 21:09:06 +01:00
F - > get ( ) . id = navigation - > navmesh_add ( nm , F - > get ( ) . xform , this ) ;
2017-08-27 21:00:59 +02:00
}
}
}
}
2014-02-10 02:10:30 +01:00
}
void GridMap : : _octant_exit_world ( const OctantKey & p_key ) {
ERR_FAIL_COND ( ! octant_map . has ( p_key ) ) ;
2017-03-05 16:44:50 +01:00
Octant & g = * octant_map [ p_key ] ;
PhysicsServer : : get_singleton ( ) - > body_set_state ( g . static_body , PhysicsServer : : BODY_STATE_TRANSFORM , get_global_transform ( ) ) ;
PhysicsServer : : get_singleton ( ) - > body_set_space ( g . static_body , RID ( ) ) ;
2014-02-10 02:10:30 +01:00
2015-09-20 18:03:46 +02:00
if ( g . collision_debug_instance . is_valid ( ) ) {
2017-03-05 16:44:50 +01:00
VS : : get_singleton ( ) - > instance_set_scenario ( g . collision_debug_instance , RID ( ) ) ;
2015-09-20 18:03:46 +02:00
}
2017-08-27 21:00:59 +02:00
for ( int i = 0 ; i < g . multimesh_instances . size ( ) ; i + + ) {
VS : : get_singleton ( ) - > instance_set_scenario ( g . multimesh_instances [ i ] . instance , RID ( ) ) ;
}
if ( navigation ) {
for ( Map < IndexKey , Octant : : NavMesh > : : Element * F = g . navmesh_ids . front ( ) ; F ; F = F - > next ( ) ) {
2014-02-10 02:10:30 +01:00
2017-08-27 21:00:59 +02:00
if ( F - > get ( ) . id > = 0 ) {
navigation - > navmesh_remove ( F - > get ( ) . id ) ;
F - > get ( ) . id = - 1 ;
}
}
2014-02-10 02:10:30 +01:00
}
}
2017-08-27 21:00:59 +02:00
void GridMap : : _octant_clean_up ( const OctantKey & p_key ) {
ERR_FAIL_COND ( ! octant_map . has ( p_key ) ) ;
Octant & g = * octant_map [ p_key ] ;
if ( g . collision_debug . is_valid ( ) )
VS : : get_singleton ( ) - > free ( g . collision_debug ) ;
if ( g . collision_debug_instance . is_valid ( ) )
VS : : get_singleton ( ) - > free ( g . collision_debug_instance ) ;
PhysicsServer : : get_singleton ( ) - > free ( g . static_body ) ;
//erase navigation
if ( navigation ) {
for ( Map < IndexKey , Octant : : NavMesh > : : Element * E = g . navmesh_ids . front ( ) ; E ; E = E - > next ( ) ) {
navigation - > navmesh_remove ( E - > get ( ) . id ) ;
}
g . navmesh_ids . clear ( ) ;
}
//erase multimeshes
for ( int i = 0 ; i < g . multimesh_instances . size ( ) ; i + + ) {
VS : : get_singleton ( ) - > free ( g . multimesh_instances [ i ] . instance ) ;
VS : : get_singleton ( ) - > free ( g . multimesh_instances [ i ] . multimesh ) ;
}
g . multimesh_instances . clear ( ) ;
}
2014-02-10 02:10:30 +01:00
void GridMap : : _notification ( int p_what ) {
2017-03-05 16:44:50 +01:00
switch ( p_what ) {
2014-02-10 02:10:30 +01:00
case NOTIFICATION_ENTER_WORLD : {
2017-08-27 21:00:59 +02:00
Spatial * c = this ;
while ( c ) {
navigation = Object : : cast_to < Navigation > ( c ) ;
if ( navigation ) {
break ;
}
2014-02-10 02:10:30 +01:00
2017-08-27 21:00:59 +02:00
c = Object : : cast_to < Spatial > ( c - > get_parent ( ) ) ;
}
2014-06-11 15:41:03 +02:00
2017-03-05 16:44:50 +01:00
last_transform = get_global_transform ( ) ;
2014-06-11 15:41:03 +02:00
2017-08-27 21:00:59 +02:00
for ( Map < OctantKey , Octant * > : : Element * E = octant_map . front ( ) ; E ; E = E - > next ( ) ) {
_octant_enter_world ( E - > key ( ) ) ;
}
2017-12-18 04:34:48 +01:00
for ( int i = 0 ; i < baked_meshes . size ( ) ; i + + ) {
VS : : get_singleton ( ) - > instance_set_scenario ( baked_meshes [ i ] . instance , get_world ( ) - > get_scenario ( ) ) ;
VS : : get_singleton ( ) - > instance_set_transform ( baked_meshes [ i ] . instance , get_global_transform ( ) ) ;
}
2014-02-10 02:10:30 +01:00
} break ;
case NOTIFICATION_TRANSFORM_CHANGED : {
Transform new_xform = get_global_transform ( ) ;
2017-03-05 16:44:50 +01:00
if ( new_xform = = last_transform )
2014-02-10 02:10:30 +01:00
break ;
//update run
2017-03-05 16:44:50 +01:00
for ( Map < OctantKey , Octant * > : : Element * E = octant_map . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 02:10:30 +01:00
_octant_transform ( E - > key ( ) ) ;
}
2017-03-05 16:44:50 +01:00
last_transform = new_xform ;
2014-02-10 02:10:30 +01:00
2017-12-18 04:34:48 +01:00
for ( int i = 0 ; i < baked_meshes . size ( ) ; i + + ) {
VS : : get_singleton ( ) - > instance_set_transform ( baked_meshes [ i ] . instance , get_global_transform ( ) ) ;
}
2014-02-10 02:10:30 +01:00
} break ;
case NOTIFICATION_EXIT_WORLD : {
2017-03-05 16:44:50 +01:00
for ( Map < OctantKey , Octant * > : : Element * E = octant_map . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 02:10:30 +01:00
_octant_exit_world ( E - > key ( ) ) ;
}
2017-03-05 16:44:50 +01:00
navigation = NULL ;
2016-04-20 20:19:05 +02:00
2017-08-27 21:00:59 +02:00
//_queue_octants_dirty(MAP_DIRTY_INSTANCES|MAP_DIRTY_TRANSFORMS);
//_update_octants_callback();
//_update_area_instances();
2017-12-18 04:34:48 +01:00
for ( int i = 0 ; i < baked_meshes . size ( ) ; i + + ) {
VS : : get_singleton ( ) - > instance_set_scenario ( baked_meshes [ i ] . instance , RID ( ) ) ;
}
2017-08-27 21:00:59 +02:00
2016-04-20 20:19:05 +02:00
} break ;
2017-09-04 22:52:44 +02:00
case NOTIFICATION_VISIBILITY_CHANGED : {
_update_visibility ( ) ;
} break ;
}
}
void GridMap : : _update_visibility ( ) {
if ( ! is_inside_tree ( ) )
return ;
_change_notify ( " visible " ) ;
for ( Map < OctantKey , Octant * > : : Element * e = octant_map . front ( ) ; e ; e = e - > next ( ) ) {
Octant * octant = e - > value ( ) ;
for ( int i = 0 ; i < octant - > multimesh_instances . size ( ) ; i + + ) {
2018-07-25 03:11:03 +02:00
const Octant : : MultimeshInstance & mi = octant - > multimesh_instances [ i ] ;
2017-09-04 22:52:44 +02:00
VS : : get_singleton ( ) - > instance_set_visible ( mi . instance , is_visible ( ) ) ;
}
2014-02-10 02:10:30 +01:00
}
}
2017-08-27 21:00:59 +02:00
void GridMap : : _queue_octants_dirty ( ) {
2014-02-10 02:10:30 +01:00
if ( awaiting_update )
2016-03-09 00:00:52 +01:00
return ;
2014-02-10 02:10:30 +01:00
2017-08-27 21:00:59 +02:00
MessageQueue : : get_singleton ( ) - > push_call ( this , " _update_octants_callback " ) ;
awaiting_update = true ;
2014-02-10 02:10:30 +01:00
}
void GridMap : : _recreate_octant_data ( ) {
2017-12-18 04:34:48 +01:00
recreating_octants = true ;
2017-03-05 16:44:50 +01:00
Map < IndexKey , Cell > cell_copy = cell_map ;
2017-08-26 05:40:45 +02:00
_clear_internal ( ) ;
2017-03-05 16:44:50 +01:00
for ( Map < IndexKey , Cell > : : Element * E = cell_copy . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
set_cell_item ( E - > key ( ) . x , E - > key ( ) . y , E - > key ( ) . z , E - > get ( ) . item , E - > get ( ) . rot ) ;
2014-02-10 02:10:30 +01:00
}
2017-12-18 04:34:48 +01:00
recreating_octants = false ;
2014-02-10 02:10:30 +01:00
}
2017-08-26 05:40:45 +02:00
void GridMap : : _clear_internal ( ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( Map < OctantKey , Octant * > : : Element * E = octant_map . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 02:10:30 +01:00
if ( is_inside_world ( ) )
_octant_exit_world ( E - > key ( ) ) ;
2017-08-27 21:00:59 +02:00
_octant_clean_up ( E - > key ( ) ) ;
2014-02-10 02:10:30 +01:00
memdelete ( E - > get ( ) ) ;
}
octant_map . clear ( ) ;
cell_map . clear ( ) ;
}
void GridMap : : clear ( ) {
_clear_internal ( ) ;
2017-12-18 04:34:48 +01:00
clear_baked_meshes ( ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void GridMap : : resource_changed ( const RES & p_res ) {
2014-02-10 02:10:30 +01:00
_recreate_octant_data ( ) ;
}
2017-08-27 21:00:59 +02:00
void GridMap : : _update_octants_callback ( ) {
2014-02-10 02:10:30 +01:00
if ( ! awaiting_update )
return ;
2017-08-27 21:00:59 +02:00
List < OctantKey > to_delete ;
2017-03-05 16:44:50 +01:00
for ( Map < OctantKey , Octant * > : : Element * E = octant_map . front ( ) ; E ; E = E - > next ( ) ) {
2017-08-27 21:00:59 +02:00
if ( _octant_update ( E - > key ( ) ) ) {
to_delete . push_back ( E - > key ( ) ) ;
}
}
while ( to_delete . front ( ) ) {
octant_map . erase ( to_delete . front ( ) - > get ( ) ) ;
to_delete . pop_back ( ) ;
2014-02-10 02:10:30 +01:00
}
2017-09-04 22:52:44 +02:00
_update_visibility ( ) ;
2017-03-05 16:44:50 +01:00
awaiting_update = false ;
2014-02-10 02:10:30 +01:00
}
void GridMap : : _bind_methods ( ) {
2017-12-28 16:13:45 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_collision_layer " , " layer " ) , & GridMap : : set_collision_layer ) ;
ClassDB : : bind_method ( D_METHOD ( " get_collision_layer " ) , & GridMap : : get_collision_layer ) ;
ClassDB : : bind_method ( D_METHOD ( " set_collision_mask " , " mask " ) , & GridMap : : set_collision_mask ) ;
ClassDB : : bind_method ( D_METHOD ( " get_collision_mask " ) , & GridMap : : get_collision_mask ) ;
ClassDB : : bind_method ( D_METHOD ( " set_collision_mask_bit " , " bit " , " value " ) , & GridMap : : set_collision_mask_bit ) ;
ClassDB : : bind_method ( D_METHOD ( " get_collision_mask_bit " , " bit " ) , & GridMap : : get_collision_mask_bit ) ;
ClassDB : : bind_method ( D_METHOD ( " set_collision_layer_bit " , " bit " , " value " ) , & GridMap : : set_collision_layer_bit ) ;
ClassDB : : bind_method ( D_METHOD ( " get_collision_layer_bit " , " bit " ) , & GridMap : : get_collision_layer_bit ) ;
2018-08-22 08:10:54 +02:00
# ifndef DISABLE_DEPRECATED
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_theme " , " theme " ) , & GridMap : : set_theme ) ;
ClassDB : : bind_method ( D_METHOD ( " get_theme " ) , & GridMap : : get_theme ) ;
2018-08-22 08:10:54 +02:00
# endif // DISABLE_DEPRECATED
ClassDB : : bind_method ( D_METHOD ( " set_mesh_library " , " mesh_library " ) , & GridMap : : set_mesh_library ) ;
ClassDB : : bind_method ( D_METHOD ( " get_mesh_library " ) , & GridMap : : get_mesh_library ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_cell_size " , " size " ) , & GridMap : : set_cell_size ) ;
ClassDB : : bind_method ( D_METHOD ( " get_cell_size " ) , & GridMap : : get_cell_size ) ;
2014-02-10 02:10:30 +01:00
2018-01-11 23:35:12 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_cell_scale " , " scale " ) , & GridMap : : set_cell_scale ) ;
ClassDB : : bind_method ( D_METHOD ( " get_cell_scale " ) , & GridMap : : get_cell_scale ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_octant_size " , " size " ) , & GridMap : : set_octant_size ) ;
ClassDB : : bind_method ( D_METHOD ( " get_octant_size " ) , & GridMap : : get_octant_size ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_cell_item " , " x " , " y " , " z " , " item " , " orientation " ) , & GridMap : : set_cell_item , DEFVAL ( 0 ) ) ;
ClassDB : : bind_method ( D_METHOD ( " get_cell_item " , " x " , " y " , " z " ) , & GridMap : : get_cell_item ) ;
ClassDB : : bind_method ( D_METHOD ( " get_cell_item_orientation " , " x " , " y " , " z " ) , & GridMap : : get_cell_item_orientation ) ;
2014-02-10 02:10:30 +01:00
2017-10-07 13:30:58 +02:00
ClassDB : : bind_method ( D_METHOD ( " world_to_map " , " pos " ) , & GridMap : : world_to_map ) ;
ClassDB : : bind_method ( D_METHOD ( " map_to_world " , " x " , " y " , " z " ) , & GridMap : : map_to_world ) ;
2017-08-27 21:00:59 +02:00
ClassDB : : bind_method ( D_METHOD ( " _update_octants_callback " ) , & GridMap : : _update_octants_callback ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " resource_changed " , " resource " ) , & GridMap : : resource_changed ) ;
ClassDB : : bind_method ( D_METHOD ( " set_center_x " , " enable " ) , & GridMap : : set_center_x ) ;
ClassDB : : bind_method ( D_METHOD ( " get_center_x " ) , & GridMap : : get_center_x ) ;
ClassDB : : bind_method ( D_METHOD ( " set_center_y " , " enable " ) , & GridMap : : set_center_y ) ;
ClassDB : : bind_method ( D_METHOD ( " get_center_y " ) , & GridMap : : get_center_y ) ;
ClassDB : : bind_method ( D_METHOD ( " set_center_z " , " enable " ) , & GridMap : : set_center_z ) ;
ClassDB : : bind_method ( D_METHOD ( " get_center_z " ) , & GridMap : : get_center_z ) ;
ClassDB : : bind_method ( D_METHOD ( " set_clip " , " enabled " , " clipabove " , " floor " , " axis " ) , & GridMap : : set_clip , DEFVAL ( true ) , DEFVAL ( 0 ) , DEFVAL ( Vector3 : : AXIS_X ) ) ;
ClassDB : : bind_method ( D_METHOD ( " clear " ) , & GridMap : : clear ) ;
2017-10-05 15:34:34 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_used_cells " ) , & GridMap : : get_used_cells ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_meshes " ) , & GridMap : : get_meshes ) ;
2017-12-18 04:34:48 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_bake_meshes " ) , & GridMap : : get_bake_meshes ) ;
ClassDB : : bind_method ( D_METHOD ( " get_bake_mesh_instance " , " idx " ) , & GridMap : : get_bake_mesh_instance ) ;
ClassDB : : bind_method ( D_METHOD ( " clear_baked_meshes " ) , & GridMap : : clear_baked_meshes ) ;
ClassDB : : bind_method ( D_METHOD ( " make_baked_meshes " , " gen_lightmap_uv " , " lightmap_uv_texel_size " ) , & GridMap : : make_baked_meshes , DEFVAL ( false ) , DEFVAL ( 0.1 ) ) ;
2017-03-05 16:44:50 +01:00
2018-08-22 08:10:54 +02:00
# ifndef DISABLE_DEPRECATED
2018-11-08 15:30:02 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " theme " , PROPERTY_HINT_RESOURCE_TYPE , " MeshLibrary " , 0 ) , " set_theme " , " get_theme " ) ;
2018-08-22 08:10:54 +02:00
# endif // DISABLE_DEPRECATED
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " mesh_library " , PROPERTY_HINT_RESOURCE_TYPE , " MeshLibrary " ) , " set_mesh_library " , " get_mesh_library " ) ;
2018-01-11 23:35:12 +01:00
ADD_GROUP ( " Cell " , " cell_ " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : VECTOR3 , " cell_size " ) , " set_cell_size " , " get_cell_size " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " cell_octant_size " , PROPERTY_HINT_RANGE , " 1,1024,1 " ) , " set_octant_size " , " get_octant_size " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " cell_center_x " ) , " set_center_x " , " get_center_x " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " cell_center_y " ) , " set_center_y " , " get_center_y " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " cell_center_z " ) , " set_center_z " , " get_center_z " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : REAL , " cell_scale " ) , " set_cell_scale " , " get_cell_scale " ) ;
2017-12-28 16:13:45 +01:00
ADD_GROUP ( " Collision " , " collision_ " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " collision_layer " , PROPERTY_HINT_LAYERS_3D_PHYSICS ) , " set_collision_layer " , " get_collision_layer " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " collision_mask " , PROPERTY_HINT_LAYERS_3D_PHYSICS ) , " set_collision_mask " , " get_collision_mask " ) ;
2017-03-05 16:44:50 +01:00
BIND_CONSTANT ( INVALID_CELL_ITEM ) ;
2014-02-10 02:10:30 +01:00
}
void GridMap : : set_clip ( bool p_enabled , bool p_clip_above , int p_floor , Vector3 : : Axis p_axis ) {
if ( ! p_enabled & & ! clip )
return ;
2017-03-05 16:44:50 +01:00
if ( clip & & p_enabled & & clip_floor = = p_floor & & p_clip_above = = clip_above & & p_axis = = clip_axis )
2014-02-10 02:10:30 +01:00
return ;
2017-03-05 16:44:50 +01:00
clip = p_enabled ;
clip_floor = p_floor ;
clip_axis = p_axis ;
clip_above = p_clip_above ;
2014-02-10 02:10:30 +01:00
//make it all update
2017-03-05 16:44:50 +01:00
for ( Map < OctantKey , Octant * > : : Element * E = octant_map . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Octant * g = E - > get ( ) ;
g - > dirty = true ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
awaiting_update = true ;
2017-08-27 21:00:59 +02:00
_update_octants_callback ( ) ;
2014-02-10 02:10:30 +01:00
}
void GridMap : : set_cell_scale ( float p_scale ) {
2017-03-05 16:44:50 +01:00
cell_scale = p_scale ;
2017-10-07 13:30:58 +02:00
_recreate_octant_data ( ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
float GridMap : : get_cell_scale ( ) const {
2014-02-10 02:10:30 +01:00
return cell_scale ;
}
2017-10-05 15:34:34 +02:00
Array GridMap : : get_used_cells ( ) const {
Array a ;
a . resize ( cell_map . size ( ) ) ;
int i = 0 ;
for ( Map < IndexKey , Cell > : : Element * E = cell_map . front ( ) ; E ; E = E - > next ( ) ) {
Vector3 p ( E - > key ( ) . x , E - > key ( ) . y , E - > key ( ) . z ) ;
a [ i + + ] = p ;
}
return a ;
}
2017-02-15 12:29:46 +01:00
Array GridMap : : get_meshes ( ) {
2014-06-11 15:41:03 +02:00
2018-08-22 08:10:54 +02:00
if ( mesh_library . is_null ( ) )
2014-06-11 15:41:03 +02:00
return Array ( ) ;
2017-10-07 13:30:58 +02:00
Vector3 ofs = _get_offset ( ) ;
2014-06-11 15:41:03 +02:00
Array meshes ;
2017-03-05 16:44:50 +01:00
for ( Map < IndexKey , Cell > : : Element * E = cell_map . front ( ) ; E ; E = E - > next ( ) ) {
2014-06-11 15:41:03 +02:00
int id = E - > get ( ) . item ;
2018-08-22 08:10:54 +02:00
if ( ! mesh_library - > has_item ( id ) )
2014-06-11 15:41:03 +02:00
continue ;
2018-08-22 08:10:54 +02:00
Ref < Mesh > mesh = mesh_library - > get_item_mesh ( id ) ;
2014-06-11 15:41:03 +02:00
if ( mesh . is_null ( ) )
continue ;
2017-03-05 16:44:50 +01:00
IndexKey ik = E - > key ( ) ;
2014-06-11 15:41:03 +02:00
2017-03-05 16:44:50 +01:00
Vector3 cellpos = Vector3 ( ik . x , ik . y , ik . z ) ;
2014-06-11 15:41:03 +02:00
Transform xform ;
xform . basis . set_orthogonal_index ( E - > get ( ) . rot ) ;
2017-03-05 16:44:50 +01:00
xform . set_origin ( cellpos * cell_size + ofs ) ;
xform . basis . scale ( Vector3 ( cell_scale , cell_scale , cell_scale ) ) ;
2014-06-11 15:41:03 +02:00
meshes . push_back ( xform ) ;
meshes . push_back ( mesh ) ;
}
return meshes ;
}
2017-10-07 13:30:58 +02:00
Vector3 GridMap : : _get_offset ( ) const {
return Vector3 (
cell_size . x * 0.5 * int ( center_x ) ,
cell_size . y * 0.5 * int ( center_y ) ,
cell_size . z * 0.5 * int ( center_z ) ) ;
}
2017-12-18 04:34:48 +01:00
void GridMap : : clear_baked_meshes ( ) {
for ( int i = 0 ; i < baked_meshes . size ( ) ; i + + ) {
VS : : get_singleton ( ) - > free ( baked_meshes [ i ] . instance ) ;
}
baked_meshes . clear ( ) ;
_recreate_octant_data ( ) ;
}
void GridMap : : make_baked_meshes ( bool p_gen_lightmap_uv , float p_lightmap_uv_texel_size ) {
2018-08-22 08:10:54 +02:00
if ( ! mesh_library . is_valid ( ) )
2017-12-18 04:34:48 +01:00
return ;
//generate
Map < OctantKey , Map < Ref < Material > , Ref < SurfaceTool > > > surface_map ;
for ( Map < IndexKey , Cell > : : Element * E = cell_map . front ( ) ; E ; E = E - > next ( ) ) {
IndexKey key = E - > key ( ) ;
int item = E - > get ( ) . item ;
2018-08-22 08:10:54 +02:00
if ( ! mesh_library - > has_item ( item ) )
2017-12-18 04:34:48 +01:00
continue ;
2018-08-22 08:10:54 +02:00
Ref < Mesh > mesh = mesh_library - > get_item_mesh ( item ) ;
2017-12-18 04:34:48 +01:00
if ( ! mesh . is_valid ( ) )
continue ;
Vector3 cellpos = Vector3 ( key . x , key . y , key . z ) ;
Vector3 ofs = _get_offset ( ) ;
Transform xform ;
xform . basis . set_orthogonal_index ( E - > get ( ) . rot ) ;
xform . set_origin ( cellpos * cell_size + ofs ) ;
xform . basis . scale ( Vector3 ( cell_scale , cell_scale , cell_scale ) ) ;
OctantKey ok ;
ok . x = key . x / octant_size ;
ok . y = key . y / octant_size ;
ok . z = key . z / octant_size ;
if ( ! surface_map . has ( ok ) ) {
surface_map [ ok ] = Map < Ref < Material > , Ref < SurfaceTool > > ( ) ;
}
Map < Ref < Material > , Ref < SurfaceTool > > & mat_map = surface_map [ ok ] ;
for ( int i = 0 ; i < mesh - > get_surface_count ( ) ; i + + ) {
if ( mesh - > surface_get_primitive_type ( i ) ! = Mesh : : PRIMITIVE_TRIANGLES )
continue ;
Ref < Material > surf_mat = mesh - > surface_get_material ( i ) ;
if ( ! mat_map . has ( surf_mat ) ) {
Ref < SurfaceTool > st ;
st . instance ( ) ;
st - > begin ( Mesh : : PRIMITIVE_TRIANGLES ) ;
st - > set_material ( surf_mat ) ;
mat_map [ surf_mat ] = st ;
}
mat_map [ surf_mat ] - > append_from ( mesh , i , xform ) ;
}
}
for ( Map < OctantKey , Map < Ref < Material > , Ref < SurfaceTool > > > : : Element * E = surface_map . front ( ) ; E ; E = E - > next ( ) ) {
Ref < ArrayMesh > mesh ;
mesh . instance ( ) ;
for ( Map < Ref < Material > , Ref < SurfaceTool > > : : Element * F = E - > get ( ) . front ( ) ; F ; F = F - > next ( ) ) {
F - > get ( ) - > commit ( mesh ) ;
}
BakedMesh bm ;
bm . mesh = mesh ;
bm . instance = VS : : get_singleton ( ) - > instance_create ( ) ;
VS : : get_singleton ( ) - > get_singleton ( ) - > instance_set_base ( bm . instance , bm . mesh - > get_rid ( ) ) ;
VS : : get_singleton ( ) - > instance_attach_object_instance_id ( bm . instance , get_instance_id ( ) ) ;
if ( is_inside_tree ( ) ) {
VS : : get_singleton ( ) - > instance_set_scenario ( bm . instance , get_world ( ) - > get_scenario ( ) ) ;
VS : : get_singleton ( ) - > instance_set_transform ( bm . instance , get_global_transform ( ) ) ;
}
if ( p_gen_lightmap_uv ) {
mesh - > lightmap_unwrap ( get_global_transform ( ) , p_lightmap_uv_texel_size ) ;
}
baked_meshes . push_back ( bm ) ;
}
_recreate_octant_data ( ) ;
}
Array GridMap : : get_bake_meshes ( ) {
if ( ! baked_meshes . size ( ) ) {
make_baked_meshes ( true ) ;
}
Array arr ;
for ( int i = 0 ; i < baked_meshes . size ( ) ; i + + ) {
arr . push_back ( baked_meshes [ i ] . mesh ) ;
arr . push_back ( Transform ( ) ) ;
}
return arr ;
}
RID GridMap : : get_bake_mesh_instance ( int p_idx ) {
ERR_FAIL_INDEX_V ( p_idx , baked_meshes . size ( ) , RID ( ) ) ;
return baked_meshes [ p_idx ] . instance ;
}
2014-02-10 02:10:30 +01:00
GridMap : : GridMap ( ) {
2017-12-28 16:13:45 +01:00
collision_layer = 1 ;
collision_mask = 1 ;
2017-08-27 21:00:59 +02:00
cell_size = Vector3 ( 2 , 2 , 2 ) ;
2017-12-18 04:34:48 +01:00
octant_size = 8 ;
2017-03-05 16:44:50 +01:00
awaiting_update = false ;
_in_tree = false ;
center_x = true ;
center_y = true ;
center_z = true ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
clip = false ;
clip_floor = 0 ;
clip_axis = Vector3 : : AXIS_Z ;
clip_above = true ;
cell_scale = 1.0 ;
2014-02-10 02:10:30 +01:00
2016-06-10 12:47:38 +02:00
navigation = NULL ;
2017-01-13 00:35:46 +01:00
set_notify_transform ( true ) ;
2017-12-18 04:34:48 +01:00
recreating_octants = false ;
2014-02-10 02:10:30 +01:00
}
GridMap : : ~ GridMap ( ) {
2018-08-22 08:10:54 +02:00
if ( ! mesh_library . is_null ( ) )
mesh_library - > unregister_owner ( this ) ;
2014-02-10 02:10:30 +01:00
clear ( ) ;
}