2023-01-10 15:26:54 +01:00
/**************************************************************************/
/* area_2d.cpp */
/**************************************************************************/
/* 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
2014-02-10 02:10:30 +01:00
# include "area_2d.h"
# include "scene/scene_string_names.h"
2017-06-19 02:07:32 +02:00
# include "servers/audio_server.h"
2014-02-10 02:10:30 +01:00
# include "servers/physics_2d_server.h"
2017-06-19 02:07:32 +02:00
2014-02-10 02:10:30 +01:00
void Area2D : : set_space_override_mode ( SpaceOverride p_mode ) {
2017-03-05 16:44:50 +01:00
space_override = p_mode ;
Physics2DServer : : get_singleton ( ) - > area_set_space_override_mode ( get_rid ( ) , Physics2DServer : : AreaSpaceOverrideMode ( p_mode ) ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
Area2D : : SpaceOverride Area2D : : get_space_override_mode ( ) const {
2014-02-10 02:10:30 +01:00
return space_override ;
}
2017-03-05 16:44:50 +01:00
void Area2D : : set_gravity_is_point ( bool p_enabled ) {
gravity_is_point = p_enabled ;
Physics2DServer : : get_singleton ( ) - > area_set_param ( get_rid ( ) , Physics2DServer : : AREA_PARAM_GRAVITY_IS_POINT , p_enabled ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
bool Area2D : : is_gravity_a_point ( ) const {
2014-02-10 02:10:30 +01:00
return gravity_is_point ;
}
2017-03-05 16:44:50 +01:00
void Area2D : : set_gravity_distance_scale ( real_t p_scale ) {
gravity_distance_scale = p_scale ;
Physics2DServer : : get_singleton ( ) - > area_set_param ( get_rid ( ) , Physics2DServer : : AREA_PARAM_GRAVITY_DISTANCE_SCALE , p_scale ) ;
2015-04-29 18:06:25 +02:00
}
2017-03-05 16:44:50 +01:00
real_t Area2D : : get_gravity_distance_scale ( ) const {
2015-04-29 18:06:25 +02:00
return gravity_distance_scale ;
}
2017-03-05 16:44:50 +01:00
void Area2D : : set_gravity_vector ( const Vector2 & p_vec ) {
gravity_vec = p_vec ;
Physics2DServer : : get_singleton ( ) - > area_set_param ( get_rid ( ) , Physics2DServer : : AREA_PARAM_GRAVITY_VECTOR , p_vec ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
Vector2 Area2D : : get_gravity_vector ( ) const {
2014-02-10 02:10:30 +01:00
return gravity_vec ;
}
2017-03-05 16:44:50 +01:00
void Area2D : : set_gravity ( real_t p_gravity ) {
gravity = p_gravity ;
Physics2DServer : : get_singleton ( ) - > area_set_param ( get_rid ( ) , Physics2DServer : : AREA_PARAM_GRAVITY , p_gravity ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
real_t Area2D : : get_gravity ( ) const {
2014-02-10 02:10:30 +01:00
return gravity ;
}
2017-03-05 16:44:50 +01:00
void Area2D : : set_linear_damp ( real_t p_linear_damp ) {
linear_damp = p_linear_damp ;
Physics2DServer : : get_singleton ( ) - > area_set_param ( get_rid ( ) , Physics2DServer : : AREA_PARAM_LINEAR_DAMP , p_linear_damp ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
real_t Area2D : : get_linear_damp ( ) const {
2015-01-05 22:37:12 +01:00
return linear_damp ;
}
2017-03-05 16:44:50 +01:00
void Area2D : : set_angular_damp ( real_t p_angular_damp ) {
angular_damp = p_angular_damp ;
Physics2DServer : : get_singleton ( ) - > area_set_param ( get_rid ( ) , Physics2DServer : : AREA_PARAM_ANGULAR_DAMP , p_angular_damp ) ;
2015-01-05 22:37:12 +01:00
}
2017-03-05 16:44:50 +01:00
real_t Area2D : : get_angular_damp ( ) const {
2015-01-05 22:37:12 +01:00
return angular_damp ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void Area2D : : set_priority ( real_t p_priority ) {
priority = p_priority ;
Physics2DServer : : get_singleton ( ) - > area_set_param ( get_rid ( ) , Physics2DServer : : AREA_PARAM_PRIORITY , p_priority ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
real_t Area2D : : get_priority ( ) const {
2014-02-10 02:10:30 +01:00
return priority ;
}
2014-11-06 01:20:42 +01:00
void Area2D : : _body_enter_tree ( ObjectID p_id ) {
2014-02-10 02:10:30 +01:00
Object * obj = ObjectDB : : get_instance ( p_id ) ;
2017-08-24 22:58:51 +02:00
Node * node = Object : : cast_to < Node > ( obj ) ;
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! node ) ;
2017-03-05 16:44:50 +01:00
Map < ObjectID , BodyState > : : Element * E = body_map . find ( p_id ) ;
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! E ) ;
2014-11-06 01:20:42 +01:00
ERR_FAIL_COND ( E - > get ( ) . in_tree ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
E - > get ( ) . in_tree = true ;
emit_signal ( SceneStringNames : : get_singleton ( ) - > body_entered , node ) ;
for ( int i = 0 ; i < E - > get ( ) . shapes . size ( ) ; i + + ) {
2020-10-12 16:37:36 +02:00
emit_signal ( SceneStringNames : : get_singleton ( ) - > body_shape_entered , E - > get ( ) . rid , node , E - > get ( ) . shapes [ i ] . body_shape , E - > get ( ) . shapes [ i ] . area_shape ) ;
2014-02-10 02:10:30 +01:00
}
}
2014-11-06 01:20:42 +01:00
void Area2D : : _body_exit_tree ( ObjectID p_id ) {
2014-02-10 02:10:30 +01:00
Object * obj = ObjectDB : : get_instance ( p_id ) ;
2017-08-24 22:58:51 +02:00
Node * node = Object : : cast_to < Node > ( obj ) ;
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! node ) ;
2017-03-05 16:44:50 +01:00
Map < ObjectID , BodyState > : : Element * E = body_map . find ( p_id ) ;
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! E ) ;
2014-11-06 01:20:42 +01:00
ERR_FAIL_COND ( ! E - > get ( ) . in_tree ) ;
2017-03-05 16:44:50 +01:00
E - > get ( ) . in_tree = false ;
emit_signal ( SceneStringNames : : get_singleton ( ) - > body_exited , node ) ;
for ( int i = 0 ; i < E - > get ( ) . shapes . size ( ) ; i + + ) {
2020-10-12 16:37:36 +02:00
emit_signal ( SceneStringNames : : get_singleton ( ) - > body_shape_exited , E - > get ( ) . rid , node , E - > get ( ) . shapes [ i ] . body_shape , E - > get ( ) . shapes [ i ] . area_shape ) ;
2014-02-10 02:10:30 +01:00
}
}
2017-03-05 16:44:50 +01:00
void Area2D : : _body_inout ( int p_status , const RID & p_body , int p_instance , int p_body_shape , int p_area_shape ) {
bool body_in = p_status = = Physics2DServer : : AREA_BODY_ADDED ;
ObjectID objid = p_instance ;
2014-02-10 02:10:30 +01:00
Object * obj = ObjectDB : : get_instance ( objid ) ;
2017-08-24 22:58:51 +02:00
Node * node = Object : : cast_to < Node > ( obj ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Map < ObjectID , BodyState > : : Element * E = body_map . find ( objid ) ;
2014-02-10 02:10:30 +01:00
2018-11-28 22:40:58 +01:00
if ( ! body_in & & ! E ) {
return ; //does not exist because it was likely removed from the tree
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
locked = true ;
2014-12-07 06:04:20 +01:00
2014-02-10 02:10:30 +01:00
if ( body_in ) {
if ( ! E ) {
2017-03-05 16:44:50 +01:00
E = body_map . insert ( objid , BodyState ( ) ) ;
2020-10-12 16:37:36 +02:00
E - > get ( ) . rid = p_body ;
2017-03-05 16:44:50 +01:00
E - > get ( ) . rc = 0 ;
E - > get ( ) . in_tree = node & & node - > is_inside_tree ( ) ;
2014-02-10 02:10:30 +01:00
if ( node ) {
2017-03-05 16:44:50 +01:00
node - > connect ( SceneStringNames : : get_singleton ( ) - > tree_entered , this , SceneStringNames : : get_singleton ( ) - > _body_enter_tree , make_binds ( objid ) ) ;
2018-01-12 12:28:39 +01:00
node - > connect ( SceneStringNames : : get_singleton ( ) - > tree_exiting , this , SceneStringNames : : get_singleton ( ) - > _body_exit_tree , make_binds ( objid ) ) ;
2014-11-06 01:20:42 +01:00
if ( E - > get ( ) . in_tree ) {
2017-03-05 16:44:50 +01:00
emit_signal ( SceneStringNames : : get_singleton ( ) - > body_entered , node ) ;
2014-02-10 02:10:30 +01:00
}
}
}
E - > get ( ) . rc + + ;
2021-05-05 12:44:11 +02:00
if ( node ) {
2017-03-05 16:44:50 +01:00
E - > get ( ) . shapes . insert ( ShapePair ( p_body_shape , p_area_shape ) ) ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2014-11-06 15:02:40 +01:00
if ( ! node | | E - > get ( ) . in_tree ) {
2020-10-12 16:37:36 +02:00
emit_signal ( SceneStringNames : : get_singleton ( ) - > body_shape_entered , p_body , node , p_body_shape , p_area_shape ) ;
2014-02-10 02:10:30 +01:00
}
} else {
E - > get ( ) . rc - - ;
2021-05-05 12:44:11 +02:00
if ( node ) {
2017-03-05 16:44:50 +01:00
E - > get ( ) . shapes . erase ( ShapePair ( p_body_shape , p_area_shape ) ) ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2020-10-02 17:07:53 +02:00
bool in_tree = E - > get ( ) . in_tree ;
2017-03-05 16:44:50 +01:00
if ( E - > get ( ) . rc = = 0 ) {
2020-10-02 17:07:53 +02:00
body_map . erase ( E ) ;
2014-02-10 02:10:30 +01:00
if ( node ) {
2017-03-05 16:44:50 +01:00
node - > disconnect ( SceneStringNames : : get_singleton ( ) - > tree_entered , this , SceneStringNames : : get_singleton ( ) - > _body_enter_tree ) ;
2018-01-12 12:28:39 +01:00
node - > disconnect ( SceneStringNames : : get_singleton ( ) - > tree_exiting , this , SceneStringNames : : get_singleton ( ) - > _body_exit_tree ) ;
2021-05-05 12:44:11 +02:00
if ( in_tree ) {
2017-03-05 16:44:50 +01:00
emit_signal ( SceneStringNames : : get_singleton ( ) - > body_exited , obj ) ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
}
}
2020-10-02 17:07:53 +02:00
if ( ! node | | in_tree ) {
2020-10-12 16:37:36 +02:00
emit_signal ( SceneStringNames : : get_singleton ( ) - > body_shape_exited , p_body , obj , p_body_shape , p_area_shape ) ;
2014-02-10 02:10:30 +01:00
}
}
2017-03-05 16:44:50 +01:00
locked = false ;
2014-02-10 02:10:30 +01:00
}
2015-03-17 04:45:25 +01:00
void Area2D : : _area_enter_tree ( ObjectID p_id ) {
Object * obj = ObjectDB : : get_instance ( p_id ) ;
2017-08-24 22:58:51 +02:00
Node * node = Object : : cast_to < Node > ( obj ) ;
2015-03-17 04:45:25 +01:00
ERR_FAIL_COND ( ! node ) ;
2017-03-05 16:44:50 +01:00
Map < ObjectID , AreaState > : : Element * E = area_map . find ( p_id ) ;
2015-03-17 04:45:25 +01:00
ERR_FAIL_COND ( ! E ) ;
ERR_FAIL_COND ( E - > get ( ) . in_tree ) ;
2017-03-05 16:44:50 +01:00
E - > get ( ) . in_tree = true ;
emit_signal ( SceneStringNames : : get_singleton ( ) - > area_entered , node ) ;
for ( int i = 0 ; i < E - > get ( ) . shapes . size ( ) ; i + + ) {
2020-10-12 16:37:36 +02:00
emit_signal ( SceneStringNames : : get_singleton ( ) - > area_shape_entered , E - > get ( ) . rid , node , E - > get ( ) . shapes [ i ] . area_shape , E - > get ( ) . shapes [ i ] . self_shape ) ;
2015-03-17 04:45:25 +01:00
}
}
void Area2D : : _area_exit_tree ( ObjectID p_id ) {
Object * obj = ObjectDB : : get_instance ( p_id ) ;
2017-08-24 22:58:51 +02:00
Node * node = Object : : cast_to < Node > ( obj ) ;
2015-03-17 04:45:25 +01:00
ERR_FAIL_COND ( ! node ) ;
2017-03-05 16:44:50 +01:00
Map < ObjectID , AreaState > : : Element * E = area_map . find ( p_id ) ;
2015-03-17 04:45:25 +01:00
ERR_FAIL_COND ( ! E ) ;
ERR_FAIL_COND ( ! E - > get ( ) . in_tree ) ;
2017-03-05 16:44:50 +01:00
E - > get ( ) . in_tree = false ;
emit_signal ( SceneStringNames : : get_singleton ( ) - > area_exited , node ) ;
for ( int i = 0 ; i < E - > get ( ) . shapes . size ( ) ; i + + ) {
2020-10-12 16:37:36 +02:00
emit_signal ( SceneStringNames : : get_singleton ( ) - > area_shape_exited , E - > get ( ) . rid , node , E - > get ( ) . shapes [ i ] . area_shape , E - > get ( ) . shapes [ i ] . self_shape ) ;
2015-03-17 04:45:25 +01:00
}
}
2017-03-05 16:44:50 +01:00
void Area2D : : _area_inout ( int p_status , const RID & p_area , int p_instance , int p_area_shape , int p_self_shape ) {
bool area_in = p_status = = Physics2DServer : : AREA_BODY_ADDED ;
ObjectID objid = p_instance ;
2015-03-17 04:45:25 +01:00
Object * obj = ObjectDB : : get_instance ( objid ) ;
2017-08-24 22:58:51 +02:00
Node * node = Object : : cast_to < Node > ( obj ) ;
2015-03-17 04:45:25 +01:00
2017-03-05 16:44:50 +01:00
Map < ObjectID , AreaState > : : Element * E = area_map . find ( objid ) ;
2015-03-17 04:45:25 +01:00
2019-04-15 04:31:51 +02:00
if ( ! area_in & & ! E ) {
return ; //likely removed from the tree
}
2017-03-05 16:44:50 +01:00
locked = true ;
2015-03-17 04:45:25 +01:00
if ( area_in ) {
if ( ! E ) {
2017-03-05 16:44:50 +01:00
E = area_map . insert ( objid , AreaState ( ) ) ;
2020-10-12 16:37:36 +02:00
E - > get ( ) . rid = p_area ;
2017-03-05 16:44:50 +01:00
E - > get ( ) . rc = 0 ;
E - > get ( ) . in_tree = node & & node - > is_inside_tree ( ) ;
2015-03-17 04:45:25 +01:00
if ( node ) {
2017-03-05 16:44:50 +01:00
node - > connect ( SceneStringNames : : get_singleton ( ) - > tree_entered , this , SceneStringNames : : get_singleton ( ) - > _area_enter_tree , make_binds ( objid ) ) ;
2018-01-12 12:28:39 +01:00
node - > connect ( SceneStringNames : : get_singleton ( ) - > tree_exiting , this , SceneStringNames : : get_singleton ( ) - > _area_exit_tree , make_binds ( objid ) ) ;
2015-03-17 04:45:25 +01:00
if ( E - > get ( ) . in_tree ) {
2017-03-05 16:44:50 +01:00
emit_signal ( SceneStringNames : : get_singleton ( ) - > area_entered , node ) ;
2015-03-17 04:45:25 +01:00
}
}
}
E - > get ( ) . rc + + ;
2021-05-05 12:44:11 +02:00
if ( node ) {
2017-03-05 16:44:50 +01:00
E - > get ( ) . shapes . insert ( AreaShapePair ( p_area_shape , p_self_shape ) ) ;
2021-05-05 12:44:11 +02:00
}
2015-03-17 04:45:25 +01:00
if ( ! node | | E - > get ( ) . in_tree ) {
2020-10-12 16:37:36 +02:00
emit_signal ( SceneStringNames : : get_singleton ( ) - > area_shape_entered , p_area , node , p_area_shape , p_self_shape ) ;
2015-03-17 04:45:25 +01:00
}
} else {
E - > get ( ) . rc - - ;
2021-05-05 12:44:11 +02:00
if ( node ) {
2017-03-05 16:44:50 +01:00
E - > get ( ) . shapes . erase ( AreaShapePair ( p_area_shape , p_self_shape ) ) ;
2021-05-05 12:44:11 +02:00
}
2015-03-17 04:45:25 +01:00
2020-10-02 17:07:53 +02:00
bool in_tree = E - > get ( ) . in_tree ;
2017-03-05 16:44:50 +01:00
if ( E - > get ( ) . rc = = 0 ) {
2020-10-02 17:07:53 +02:00
area_map . erase ( E ) ;
2015-03-17 04:45:25 +01:00
if ( node ) {
2017-03-05 16:44:50 +01:00
node - > disconnect ( SceneStringNames : : get_singleton ( ) - > tree_entered , this , SceneStringNames : : get_singleton ( ) - > _area_enter_tree ) ;
2018-01-12 12:28:39 +01:00
node - > disconnect ( SceneStringNames : : get_singleton ( ) - > tree_exiting , this , SceneStringNames : : get_singleton ( ) - > _area_exit_tree ) ;
2021-05-05 12:44:11 +02:00
if ( in_tree ) {
2017-03-05 16:44:50 +01:00
emit_signal ( SceneStringNames : : get_singleton ( ) - > area_exited , obj ) ;
2021-05-05 12:44:11 +02:00
}
2015-03-17 04:45:25 +01:00
}
}
2020-10-02 17:07:53 +02:00
if ( ! node | | in_tree ) {
2020-10-12 16:37:36 +02:00
emit_signal ( SceneStringNames : : get_singleton ( ) - > area_shape_exited , p_area , obj , p_area_shape , p_self_shape ) ;
2015-03-17 04:45:25 +01:00
}
}
2017-03-05 16:44:50 +01:00
locked = false ;
2015-03-17 04:45:25 +01:00
}
2014-02-10 02:10:30 +01:00
void Area2D : : _clear_monitoring ( ) {
2019-08-08 22:11:48 +02:00
ERR_FAIL_COND_MSG ( locked , " This function can't be used during the in/out signal. " ) ;
2014-02-10 02:10:30 +01:00
2015-03-17 04:45:25 +01:00
{
2017-03-05 16:44:50 +01:00
Map < ObjectID , BodyState > bmcopy = body_map ;
2015-03-17 04:45:25 +01:00
body_map . clear ( ) ;
//disconnect all monitored stuff
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( Map < ObjectID , BodyState > : : Element * E = bmcopy . front ( ) ; E ; E = E - > next ( ) ) {
2015-03-17 04:45:25 +01:00
Object * obj = ObjectDB : : get_instance ( E - > key ( ) ) ;
2017-08-24 22:58:51 +02:00
Node * node = Object : : cast_to < Node > ( obj ) ;
2017-07-10 16:20:56 +02:00
2021-05-05 12:44:11 +02:00
if ( ! node ) { //node may have been deleted in previous frame or at other legiminate point
2017-07-10 16:20:56 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2017-07-10 16:20:56 +02:00
//ERR_CONTINUE(!node);
2017-01-25 20:52:44 +01:00
2017-03-05 16:44:50 +01:00
node - > disconnect ( SceneStringNames : : get_singleton ( ) - > tree_entered , this , SceneStringNames : : get_singleton ( ) - > _body_enter_tree ) ;
2018-01-12 12:28:39 +01:00
node - > disconnect ( SceneStringNames : : get_singleton ( ) - > tree_exiting , this , SceneStringNames : : get_singleton ( ) - > _body_exit_tree ) ;
2017-01-25 20:52:44 +01:00
2021-05-05 12:44:11 +02:00
if ( ! E - > get ( ) . in_tree ) {
2015-03-17 04:45:25 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < E - > get ( ) . shapes . size ( ) ; i + + ) {
2020-10-12 16:37:36 +02:00
emit_signal ( SceneStringNames : : get_singleton ( ) - > body_shape_exited , E - > get ( ) . rid , node , E - > get ( ) . shapes [ i ] . body_shape , E - > get ( ) . shapes [ i ] . area_shape ) ;
2015-03-17 04:45:25 +01:00
}
2017-03-05 16:44:50 +01:00
emit_signal ( SceneStringNames : : get_singleton ( ) - > body_exited , obj ) ;
2014-02-10 02:10:30 +01:00
}
2015-03-17 04:45:25 +01:00
}
{
2017-03-05 16:44:50 +01:00
Map < ObjectID , AreaState > bmcopy = area_map ;
2015-03-17 04:45:25 +01:00
area_map . clear ( ) ;
//disconnect all monitored stuff
2017-03-05 16:44:50 +01:00
for ( Map < ObjectID , AreaState > : : Element * E = bmcopy . front ( ) ; E ; E = E - > next ( ) ) {
2015-03-17 04:45:25 +01:00
Object * obj = ObjectDB : : get_instance ( E - > key ( ) ) ;
2017-08-24 22:58:51 +02:00
Node * node = Object : : cast_to < Node > ( obj ) ;
2015-12-31 15:15:49 +01:00
2021-05-05 12:44:11 +02:00
if ( ! node ) { //node may have been deleted in previous frame or at other legiminate point
2015-12-31 15:15:49 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-12-31 15:15:49 +01:00
//ERR_CONTINUE(!node);
2017-03-05 16:44:50 +01:00
node - > disconnect ( SceneStringNames : : get_singleton ( ) - > tree_entered , this , SceneStringNames : : get_singleton ( ) - > _area_enter_tree ) ;
2018-01-12 12:28:39 +01:00
node - > disconnect ( SceneStringNames : : get_singleton ( ) - > tree_exiting , this , SceneStringNames : : get_singleton ( ) - > _area_exit_tree ) ;
2017-01-25 20:52:44 +01:00
2021-05-05 12:44:11 +02:00
if ( ! E - > get ( ) . in_tree ) {
2015-03-17 04:45:25 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-03-17 04:45:25 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < E - > get ( ) . shapes . size ( ) ; i + + ) {
2020-10-12 16:37:36 +02:00
emit_signal ( SceneStringNames : : get_singleton ( ) - > area_shape_exited , E - > get ( ) . rid , node , E - > get ( ) . shapes [ i ] . area_shape , E - > get ( ) . shapes [ i ] . self_shape ) ;
2015-03-17 04:45:25 +01:00
}
2017-03-05 16:44:50 +01:00
emit_signal ( SceneStringNames : : get_singleton ( ) - > area_exited , obj ) ;
2015-03-17 04:45:25 +01:00
}
2014-02-10 02:10:30 +01:00
}
}
void Area2D : : _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_EXIT_TREE : {
2014-02-10 02:10:30 +01:00
_clear_monitoring ( ) ;
} break ;
}
}
2017-01-14 00:03:51 +01:00
void Area2D : : set_monitoring ( bool p_enable ) {
2021-05-05 12:44:11 +02:00
if ( p_enable = = monitoring ) {
2014-02-10 02:10:30 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
2019-08-08 22:11:48 +02:00
ERR_FAIL_COND_MSG ( locked , " Function blocked during in/out signal. Use set_deferred( \" monitoring \" , true/false). " ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
monitoring = p_enable ;
2014-02-10 02:10:30 +01:00
if ( monitoring ) {
2017-03-05 16:44:50 +01:00
Physics2DServer : : get_singleton ( ) - > area_set_monitor_callback ( get_rid ( ) , this , SceneStringNames : : get_singleton ( ) - > _body_inout ) ;
Physics2DServer : : get_singleton ( ) - > area_set_area_monitor_callback ( get_rid ( ) , this , SceneStringNames : : get_singleton ( ) - > _area_inout ) ;
2015-06-29 05:29:49 +02:00
2014-02-10 02:10:30 +01:00
} else {
2021-05-04 16:00:45 +02:00
Physics2DServer : : get_singleton ( ) - > area_set_monitor_callback ( get_rid ( ) , nullptr , StringName ( ) ) ;
Physics2DServer : : get_singleton ( ) - > area_set_area_monitor_callback ( get_rid ( ) , nullptr , StringName ( ) ) ;
2014-02-10 02:10:30 +01:00
_clear_monitoring ( ) ;
}
}
2017-01-14 00:03:51 +01:00
bool Area2D : : is_monitoring ( ) const {
2014-02-10 02:10:30 +01:00
return monitoring ;
}
2015-03-17 04:45:25 +01:00
void Area2D : : set_monitorable ( bool p_enable ) {
2019-08-08 22:11:48 +02:00
ERR_FAIL_COND_MSG ( locked | | ( is_inside_tree ( ) & & Physics2DServer : : get_singleton ( ) - > is_flushing_queries ( ) ) , " Function blocked during in/out signal. Use set_deferred( \" monitorable \" , true/false). " ) ;
2015-03-17 04:45:25 +01:00
2021-05-05 12:44:11 +02:00
if ( p_enable = = monitorable ) {
2015-03-17 04:45:25 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
2015-03-17 04:45:25 +01:00
2017-03-05 16:44:50 +01:00
monitorable = p_enable ;
2015-03-17 04:45:25 +01:00
2017-03-05 16:44:50 +01:00
Physics2DServer : : get_singleton ( ) - > area_set_monitorable ( get_rid ( ) , monitorable ) ;
2015-03-17 04:45:25 +01:00
}
bool Area2D : : is_monitorable ( ) const {
return monitorable ;
}
2014-11-13 04:53:12 +01:00
Array Area2D : : get_overlapping_bodies ( ) const {
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_V_MSG ( ! monitoring , Array ( ) , " Can't find overlapping bodies when monitoring is off. " ) ;
2014-11-13 04:53:12 +01:00
Array ret ;
ret . resize ( body_map . size ( ) ) ;
2017-03-05 16:44:50 +01:00
int idx = 0 ;
for ( const Map < ObjectID , BodyState > : : Element * E = body_map . front ( ) ; E ; E = E - > next ( ) ) {
2014-11-13 04:53:12 +01:00
Object * obj = ObjectDB : : get_instance ( E - > key ( ) ) ;
if ( ! obj ) {
2017-03-05 16:44:50 +01:00
ret . resize ( ret . size ( ) - 1 ) ; //ops
2014-11-13 04:53:12 +01:00
} else {
2017-03-05 16:44:50 +01:00
ret [ idx + + ] = obj ;
2014-11-13 04:53:12 +01:00
}
}
return ret ;
}
2015-03-17 04:45:25 +01:00
Array Area2D : : get_overlapping_areas ( ) const {
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_V_MSG ( ! monitoring , Array ( ) , " Can't find overlapping bodies when monitoring is off. " ) ;
2015-03-17 04:45:25 +01:00
Array ret ;
ret . resize ( area_map . size ( ) ) ;
2017-03-05 16:44:50 +01:00
int idx = 0 ;
for ( const Map < ObjectID , AreaState > : : Element * E = area_map . front ( ) ; E ; E = E - > next ( ) ) {
2015-03-17 04:45:25 +01:00
Object * obj = ObjectDB : : get_instance ( E - > key ( ) ) ;
if ( ! obj ) {
2017-03-05 16:44:50 +01:00
ret . resize ( ret . size ( ) - 1 ) ; //ops
2015-03-17 04:45:25 +01:00
} else {
2017-03-05 16:44:50 +01:00
ret [ idx + + ] = obj ;
2015-03-17 04:45:25 +01:00
}
}
return ret ;
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
bool Area2D : : overlaps_area ( Node * p_area ) const {
ERR_FAIL_NULL_V ( p_area , false ) ;
2017-08-07 12:17:31 +02:00
const Map < ObjectID , AreaState > : : Element * E = area_map . find ( p_area - > get_instance_id ( ) ) ;
2021-05-05 12:44:11 +02:00
if ( ! E ) {
2015-03-17 13:25:35 +01:00
return false ;
2021-05-05 12:44:11 +02:00
}
2015-03-17 13:25:35 +01:00
return E - > get ( ) . in_tree ;
}
2017-03-05 16:44:50 +01:00
bool Area2D : : overlaps_body ( Node * p_body ) const {
ERR_FAIL_NULL_V ( p_body , false ) ;
2017-08-07 12:17:31 +02:00
const Map < ObjectID , BodyState > : : Element * E = body_map . find ( p_body - > get_instance_id ( ) ) ;
2021-05-05 12:44:11 +02:00
if ( ! E ) {
2015-03-17 13:25:35 +01:00
return false ;
2021-05-05 12:44:11 +02:00
}
2015-03-17 13:25:35 +01:00
return E - > get ( ) . in_tree ;
}
2017-06-19 02:07:32 +02:00
void Area2D : : set_audio_bus_override ( bool p_override ) {
audio_bus_override = p_override ;
}
bool Area2D : : is_overriding_audio_bus ( ) const {
return audio_bus_override ;
}
2017-09-22 18:29:33 +02:00
void Area2D : : set_audio_bus_name ( const StringName & p_audio_bus ) {
2017-06-19 02:07:32 +02:00
audio_bus = p_audio_bus ;
}
2017-09-22 18:29:33 +02:00
StringName Area2D : : get_audio_bus_name ( ) const {
2017-06-19 02:07:32 +02:00
for ( int i = 0 ; i < AudioServer : : get_singleton ( ) - > get_bus_count ( ) ; i + + ) {
if ( AudioServer : : get_singleton ( ) - > get_bus_name ( i ) = = audio_bus ) {
return audio_bus ;
}
}
return " Master " ;
}
void Area2D : : _validate_property ( PropertyInfo & property ) const {
if ( property . name = = " audio_bus_name " ) {
String options ;
for ( int i = 0 ; i < AudioServer : : get_singleton ( ) - > get_bus_count ( ) ; i + + ) {
2021-05-05 12:44:11 +02:00
if ( i > 0 ) {
2017-06-19 02:07:32 +02:00
options + = " , " ;
2021-05-05 12:44:11 +02:00
}
2017-06-19 02:07:32 +02:00
String name = AudioServer : : get_singleton ( ) - > get_bus_name ( i ) ;
options + = name ;
}
property . hint_string = options ;
}
}
2014-02-10 02:10:30 +01:00
void Area2D : : _bind_methods ( ) {
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " _body_enter_tree " , " id " ) , & Area2D : : _body_enter_tree ) ;
ClassDB : : bind_method ( D_METHOD ( " _body_exit_tree " , " id " ) , & Area2D : : _body_exit_tree ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " _area_enter_tree " , " id " ) , & Area2D : : _area_enter_tree ) ;
ClassDB : : bind_method ( D_METHOD ( " _area_exit_tree " , " id " ) , & Area2D : : _area_exit_tree ) ;
2014-02-10 02:10:30 +01:00
2017-09-12 05:33:44 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_space_override_mode " , " space_override_mode " ) , & Area2D : : set_space_override_mode ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_space_override_mode " ) , & Area2D : : get_space_override_mode ) ;
2015-04-29 18:06:25 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_gravity_is_point " , " enable " ) , & Area2D : : set_gravity_is_point ) ;
ClassDB : : bind_method ( D_METHOD ( " is_gravity_a_point " ) , & Area2D : : is_gravity_a_point ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_gravity_distance_scale " , " distance_scale " ) , & Area2D : : set_gravity_distance_scale ) ;
ClassDB : : bind_method ( D_METHOD ( " get_gravity_distance_scale " ) , & Area2D : : get_gravity_distance_scale ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_gravity_vector " , " vector " ) , & Area2D : : set_gravity_vector ) ;
ClassDB : : bind_method ( D_METHOD ( " get_gravity_vector " ) , & Area2D : : get_gravity_vector ) ;
2015-01-05 22:37:12 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_gravity " , " gravity " ) , & Area2D : : set_gravity ) ;
ClassDB : : bind_method ( D_METHOD ( " get_gravity " ) , & Area2D : : get_gravity ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_linear_damp " , " linear_damp " ) , & Area2D : : set_linear_damp ) ;
ClassDB : : bind_method ( D_METHOD ( " get_linear_damp " ) , & Area2D : : get_linear_damp ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_angular_damp " , " angular_damp " ) , & Area2D : : set_angular_damp ) ;
ClassDB : : bind_method ( D_METHOD ( " get_angular_damp " ) , & Area2D : : get_angular_damp ) ;
2015-05-03 21:47:21 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_priority " , " priority " ) , & Area2D : : set_priority ) ;
ClassDB : : bind_method ( D_METHOD ( " get_priority " ) , & Area2D : : get_priority ) ;
2015-05-03 21:47:21 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_monitoring " , " enable " ) , & Area2D : : set_monitoring ) ;
ClassDB : : bind_method ( D_METHOD ( " is_monitoring " ) , & Area2D : : is_monitoring ) ;
2014-11-13 04:53:12 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_monitorable " , " enable " ) , & Area2D : : set_monitorable ) ;
ClassDB : : bind_method ( D_METHOD ( " is_monitorable " ) , & Area2D : : is_monitorable ) ;
2015-03-17 13:25:35 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_overlapping_bodies " ) , & Area2D : : get_overlapping_bodies ) ;
ClassDB : : bind_method ( D_METHOD ( " get_overlapping_areas " ) , & Area2D : : get_overlapping_areas ) ;
2015-03-17 04:45:25 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " overlaps_body " , " body " ) , & Area2D : : overlaps_body ) ;
ClassDB : : bind_method ( D_METHOD ( " overlaps_area " , " area " ) , & Area2D : : overlaps_area ) ;
2015-03-17 04:45:25 +01:00
2017-09-22 18:29:33 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_audio_bus_name " , " name " ) , & Area2D : : set_audio_bus_name ) ;
ClassDB : : bind_method ( D_METHOD ( " get_audio_bus_name " ) , & Area2D : : get_audio_bus_name ) ;
2017-06-19 02:07:32 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_audio_bus_override " , " enable " ) , & Area2D : : set_audio_bus_override ) ;
ClassDB : : bind_method ( D_METHOD ( " is_overriding_audio_bus " ) , & Area2D : : is_overriding_audio_bus ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " _body_inout " ) , & Area2D : : _body_inout ) ;
ClassDB : : bind_method ( D_METHOD ( " _area_inout " ) , & Area2D : : _area_inout ) ;
2014-02-10 02:10:30 +01:00
2021-10-15 17:28:11 +02:00
ADD_SIGNAL ( MethodInfo ( " body_shape_entered " , PropertyInfo ( Variant : : _RID , " body_rid " ) , PropertyInfo ( Variant : : OBJECT , " body " , PROPERTY_HINT_RESOURCE_TYPE , " Node " ) , PropertyInfo ( Variant : : INT , " body_shape_index " ) , PropertyInfo ( Variant : : INT , " local_shape_index " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " body_shape_exited " , PropertyInfo ( Variant : : _RID , " body_rid " ) , PropertyInfo ( Variant : : OBJECT , " body " , PROPERTY_HINT_RESOURCE_TYPE , " Node " ) , PropertyInfo ( Variant : : INT , " body_shape_index " ) , PropertyInfo ( Variant : : INT , " local_shape_index " ) ) ) ;
2019-06-24 21:30:46 +02:00
ADD_SIGNAL ( MethodInfo ( " body_entered " , PropertyInfo ( Variant : : OBJECT , " body " , PROPERTY_HINT_RESOURCE_TYPE , " Node " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " body_exited " , PropertyInfo ( Variant : : OBJECT , " body " , PROPERTY_HINT_RESOURCE_TYPE , " Node " ) ) ) ;
2014-02-10 02:10:30 +01:00
2021-10-15 17:28:11 +02:00
ADD_SIGNAL ( MethodInfo ( " area_shape_entered " , PropertyInfo ( Variant : : _RID , " area_rid " ) , PropertyInfo ( Variant : : OBJECT , " area " , PROPERTY_HINT_RESOURCE_TYPE , " Area2D " ) , PropertyInfo ( Variant : : INT , " area_shape_index " ) , PropertyInfo ( Variant : : INT , " local_shape_index " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " area_shape_exited " , PropertyInfo ( Variant : : _RID , " area_rid " ) , PropertyInfo ( Variant : : OBJECT , " area " , PROPERTY_HINT_RESOURCE_TYPE , " Area2D " ) , PropertyInfo ( Variant : : INT , " area_shape_index " ) , PropertyInfo ( Variant : : INT , " local_shape_index " ) ) ) ;
2017-03-05 16:44:50 +01:00
ADD_SIGNAL ( MethodInfo ( " area_entered " , PropertyInfo ( Variant : : OBJECT , " area " , PROPERTY_HINT_RESOURCE_TYPE , " Area2D " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " area_exited " , PropertyInfo ( Variant : : OBJECT , " area " , PROPERTY_HINT_RESOURCE_TYPE , " Area2D " ) ) ) ;
2014-02-10 02:10:30 +01:00
2021-04-18 02:18:17 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " monitoring " ) , " set_monitoring " , " is_monitoring " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " monitorable " ) , " set_monitorable " , " is_monitorable " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " priority " , PROPERTY_HINT_RANGE , " 0,128,1 " ) , " set_priority " , " get_priority " ) ;
ADD_GROUP ( " Physics Overrides " , " " ) ;
2018-11-08 15:30:02 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " space_override " , PROPERTY_HINT_ENUM , " Disabled,Combine,Combine-Replace,Replace,Replace-Combine " ) , " set_space_override_mode " , " get_space_override_mode " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " gravity_point " ) , " set_gravity_is_point " , " is_gravity_a_point " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : REAL , " gravity_distance_scale " , PROPERTY_HINT_EXP_RANGE , " 0,1024,0.001,or_greater " ) , " set_gravity_distance_scale " , " get_gravity_distance_scale " ) ;
2017-03-05 16:44:50 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : VECTOR2 , " gravity_vec " ) , " set_gravity_vector " , " get_gravity_vector " ) ;
2021-06-03 02:08:57 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : REAL , " gravity " , PROPERTY_HINT_RANGE , " -4096,4096,0.001,or_lesser,or_greater " ) , " set_gravity " , " get_gravity " ) ;
2019-07-31 13:55:38 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : REAL , " linear_damp " , PROPERTY_HINT_RANGE , " 0,100,0.001,or_greater " ) , " set_linear_damp " , " get_linear_damp " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : REAL , " angular_damp " , PROPERTY_HINT_RANGE , " 0,100,0.001,or_greater " ) , " set_angular_damp " , " get_angular_damp " ) ;
2021-04-18 02:18:17 +02:00
2017-06-19 02:07:32 +02:00
ADD_GROUP ( " Audio Bus " , " audio_bus_ " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " audio_bus_override " ) , " set_audio_bus_override " , " is_overriding_audio_bus " ) ;
2017-09-22 18:29:33 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : STRING , " audio_bus_name " , PROPERTY_HINT_ENUM , " " ) , " set_audio_bus_name " , " get_audio_bus_name " ) ;
2017-09-12 05:33:44 +02:00
BIND_ENUM_CONSTANT ( SPACE_OVERRIDE_DISABLED ) ;
BIND_ENUM_CONSTANT ( SPACE_OVERRIDE_COMBINE ) ;
BIND_ENUM_CONSTANT ( SPACE_OVERRIDE_COMBINE_REPLACE ) ;
BIND_ENUM_CONSTANT ( SPACE_OVERRIDE_REPLACE ) ;
BIND_ENUM_CONSTANT ( SPACE_OVERRIDE_REPLACE_COMBINE ) ;
2014-02-10 02:10:30 +01:00
}
2017-12-06 21:36:34 +01:00
Area2D : : Area2D ( ) :
2021-11-09 13:00:07 +01:00
CollisionObject2D ( RID_PRIME ( Physics2DServer : : get_singleton ( ) - > area_create ( ) ) , true ) {
2017-03-05 16:44:50 +01:00
space_override = SPACE_OVERRIDE_DISABLED ;
2017-01-14 18:03:38 +01:00
set_gravity ( 98 ) ;
2017-03-05 16:44:50 +01:00
set_gravity_vector ( Vector2 ( 0 , 1 ) ) ;
gravity_is_point = false ;
gravity_distance_scale = 0 ;
linear_damp = 0.1 ;
angular_damp = 1 ;
locked = false ;
priority = 0 ;
monitoring = false ;
monitorable = false ;
2017-06-19 02:07:32 +02:00
audio_bus_override = false ;
2017-01-14 00:03:51 +01:00
set_monitoring ( true ) ;
2015-03-17 04:45:25 +01:00
set_monitorable ( true ) ;
2014-02-10 02:10:30 +01:00
}
Area2D : : ~ Area2D ( ) {
}