2014-02-10 02:10:30 +01:00
/*************************************************************************/
/* collision_shape_2d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
2017-01-01 22:01:57 +01:00
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
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. */
/*************************************************************************/
# include "collision_shape_2d.h"
# include "collision_object_2d.h"
# include "scene/resources/capsule_shape_2d.h"
2017-03-05 16:44:50 +01:00
# include "scene/resources/circle_shape_2d.h"
2014-02-10 02:10:30 +01:00
# include "scene/resources/concave_polygon_shape_2d.h"
2017-03-05 16:44:50 +01:00
# include "scene/resources/convex_polygon_shape_2d.h"
# include "scene/resources/rectangle_shape_2d.h"
# include "scene/resources/segment_shape_2d.h"
# include "scene/resources/shape_line_2d.h"
2014-02-10 02:10:30 +01:00
void CollisionShape2D : : _add_to_collision_object ( Object * p_obj ) {
2014-03-15 06:58:53 +01:00
if ( unparenting )
return ;
2014-02-10 02:10:30 +01:00
CollisionObject2D * co = p_obj - > cast_to < CollisionObject2D > ( ) ;
ERR_FAIL_COND ( ! co ) ;
2017-03-05 16:44:50 +01:00
update_shape_index = co - > get_shape_count ( ) ;
co - > add_shape ( shape , get_transform ( ) ) ;
2014-02-10 02:10:30 +01:00
if ( trigger )
2017-03-05 16:44:50 +01:00
co - > set_shape_as_trigger ( co - > get_shape_count ( ) - 1 , true ) ;
2014-02-10 02:10:30 +01:00
}
void CollisionShape2D : : _shape_changed ( ) {
update ( ) ;
_update_parent ( ) ;
}
void CollisionShape2D : : _update_parent ( ) {
Node * parent = get_parent ( ) ;
if ( ! parent )
return ;
CollisionObject2D * co = parent - > cast_to < CollisionObject2D > ( ) ;
if ( ! co )
return ;
co - > _update_shapes_from_children ( ) ;
}
void CollisionShape2D : : _notification ( int p_what ) {
2017-03-05 16:44:50 +01:00
switch ( p_what ) {
2014-02-10 02:10:30 +01:00
2014-11-06 01:20:42 +01:00
case NOTIFICATION_ENTER_TREE : {
2017-03-05 16:44:50 +01:00
unparenting = false ;
can_update_body = get_tree ( ) - > is_editor_hint ( ) ;
2015-12-12 12:11:36 +01:00
if ( ! get_tree ( ) - > is_editor_hint ( ) ) {
//display above all else
set_z_as_relative ( false ) ;
2017-03-05 16:44:50 +01:00
set_z ( VS : : CANVAS_ITEM_Z_MAX - 1 ) ;
2015-12-12 12:11:36 +01:00
}
2015-09-16 03:07:03 +02:00
2014-09-22 05:50:48 +02:00
} break ;
2014-02-10 02:10:30 +01:00
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED : {
2014-11-06 01:20:42 +01:00
if ( ! is_inside_tree ( ) )
2014-02-10 02:10:30 +01:00
break ;
2015-09-16 03:07:03 +02:00
if ( can_update_body ) {
_update_parent ( ) ;
2017-03-05 16:44:50 +01:00
} else if ( update_shape_index > = 0 ) {
2015-09-16 03:07:03 +02:00
CollisionObject2D * co = get_parent ( ) - > cast_to < CollisionObject2D > ( ) ;
if ( co ) {
2017-03-05 16:44:50 +01:00
co - > set_shape_transform ( update_shape_index , get_transform ( ) ) ;
2015-09-16 03:07:03 +02:00
}
}
} break ;
case NOTIFICATION_EXIT_TREE : {
2017-03-05 16:44:50 +01:00
can_update_body = false ;
2014-02-10 02:10:30 +01:00
} break ;
/*
case NOTIFICATION_TRANSFORM_CHANGED : {
if ( ! is_inside_scene ( ) )
break ;
_update_parent ( ) ;
} break ; */
case NOTIFICATION_DRAW : {
2015-09-20 18:03:46 +02:00
if ( ! get_tree ( ) - > is_editor_hint ( ) & & ! get_tree ( ) - > is_debugging_collisions_hint ( ) ) {
2015-09-19 04:10:58 +02:00
break ;
2015-09-20 18:03:46 +02:00
}
2015-09-19 04:10:58 +02:00
2015-09-23 02:30:08 +02:00
if ( ! shape . is_valid ( ) ) {
break ;
}
2017-03-05 16:44:50 +01:00
rect = Rect2 ( ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Color draw_col = get_tree ( ) - > get_debug_collisions_color ( ) ;
shape - > draw ( get_canvas_item ( ) , draw_col ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
rect = shape - > get_rect ( ) ;
rect = rect . grow ( 3 ) ;
2014-02-10 02:10:30 +01:00
} break ;
2014-03-15 06:58:53 +01:00
case NOTIFICATION_UNPARENTED : {
unparenting = true ;
_update_parent ( ) ;
} break ;
2014-02-10 02:10:30 +01:00
}
}
2017-03-05 16:44:50 +01:00
void CollisionShape2D : : set_shape ( const Ref < Shape2D > & p_shape ) {
2014-02-10 02:10:30 +01:00
if ( shape . is_valid ( ) )
2017-03-05 16:44:50 +01:00
shape - > disconnect ( " changed " , this , " _shape_changed " ) ;
shape = p_shape ;
2014-02-10 02:10:30 +01:00
update ( ) ;
2015-09-16 03:07:03 +02:00
if ( is_inside_tree ( ) & & can_update_body )
_update_parent ( ) ;
2017-03-05 16:44:50 +01:00
if ( is_inside_tree ( ) & & ! can_update_body & & update_shape_index > = 0 ) {
2015-09-16 03:07:03 +02:00
CollisionObject2D * co = get_parent ( ) - > cast_to < CollisionObject2D > ( ) ;
if ( co ) {
2017-03-05 16:44:50 +01:00
co - > set_shape ( update_shape_index , p_shape ) ;
2015-09-16 03:07:03 +02:00
}
}
2014-02-10 02:10:30 +01:00
if ( shape . is_valid ( ) )
2017-03-05 16:44:50 +01:00
shape - > connect ( " changed " , this , " _shape_changed " ) ;
2014-02-10 02:10:30 +01:00
2017-01-22 14:09:41 +01:00
update_configuration_warning ( ) ;
2014-02-10 02:10:30 +01:00
}
Ref < Shape2D > CollisionShape2D : : get_shape ( ) const {
return shape ;
}
Rect2 CollisionShape2D : : get_item_rect ( ) const {
return rect ;
}
void CollisionShape2D : : set_trigger ( bool p_trigger ) {
2017-03-05 16:44:50 +01:00
trigger = p_trigger ;
2015-09-16 03:07:03 +02:00
if ( can_update_body ) {
_update_parent ( ) ;
2017-03-05 16:44:50 +01:00
} else if ( is_inside_tree ( ) & & update_shape_index > = 0 ) {
2015-09-16 03:07:03 +02:00
CollisionObject2D * co = get_parent ( ) - > cast_to < CollisionObject2D > ( ) ;
if ( co ) {
2017-03-05 16:44:50 +01:00
co - > set_shape_as_trigger ( update_shape_index , p_trigger ) ;
2015-09-16 03:07:03 +02:00
}
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
bool CollisionShape2D : : is_trigger ( ) const {
2014-02-10 02:10:30 +01:00
return trigger ;
}
2015-09-16 03:07:03 +02:00
void CollisionShape2D : : _set_update_shape_index ( int p_index ) {
2017-03-05 16:44:50 +01:00
update_shape_index = p_index ;
2015-09-16 03:07:03 +02:00
}
2017-03-05 16:44:50 +01:00
int CollisionShape2D : : _get_update_shape_index ( ) const {
2015-09-16 03:07:03 +02:00
return update_shape_index ;
}
2016-05-17 23:27:15 +02:00
String CollisionShape2D : : get_configuration_warning ( ) const {
if ( ! get_parent ( ) - > cast_to < CollisionObject2D > ( ) ) {
return TTR ( " CollisionShape2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape. " ) ;
}
if ( ! shape . is_valid ( ) ) {
return TTR ( " A shape must be provided for CollisionShape2D to function. Please create a shape resource for it! " ) ;
}
return String ( ) ;
}
2014-02-10 02:10:30 +01:00
void CollisionShape2D : : _bind_methods ( ) {
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_shape " , " shape " ) , & CollisionShape2D : : set_shape ) ;
ClassDB : : bind_method ( D_METHOD ( " get_shape " ) , & CollisionShape2D : : get_shape ) ;
ClassDB : : bind_method ( D_METHOD ( " _shape_changed " ) , & CollisionShape2D : : _shape_changed ) ;
ClassDB : : bind_method ( D_METHOD ( " _add_to_collision_object " ) , & CollisionShape2D : : _add_to_collision_object ) ;
ClassDB : : bind_method ( D_METHOD ( " set_trigger " , " enable " ) , & CollisionShape2D : : set_trigger ) ;
ClassDB : : bind_method ( D_METHOD ( " is_trigger " ) , & CollisionShape2D : : is_trigger ) ;
2015-09-16 03:07:03 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " _set_update_shape_index " , " index " ) , & CollisionShape2D : : _set_update_shape_index ) ;
ClassDB : : bind_method ( D_METHOD ( " _get_update_shape_index " ) , & CollisionShape2D : : _get_update_shape_index ) ;
2015-09-16 03:07:03 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_collision_object_shape_index " ) , & CollisionShape2D : : get_collision_object_shape_index ) ;
2015-09-16 03:07:03 +02:00
2017-03-05 16:44:50 +01:00
ADD_PROPERTYNZ ( PropertyInfo ( Variant : : OBJECT , " shape " , PROPERTY_HINT_RESOURCE_TYPE , " Shape2D " ) , " set_shape " , " get_shape " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " trigger " ) , " set_trigger " , " is_trigger " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " _update_shape_index " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_NOEDITOR ) , " _set_update_shape_index " , " _get_update_shape_index " ) ;
2014-02-10 02:10:30 +01:00
}
CollisionShape2D : : CollisionShape2D ( ) {
2017-03-05 16:44:50 +01:00
rect = Rect2 ( - Point2 ( 10 , 10 ) , Point2 ( 20 , 20 ) ) ;
2015-09-16 03:07:03 +02:00
set_notify_local_transform ( true ) ;
2017-03-05 16:44:50 +01:00
trigger = false ;
2014-03-15 06:58:53 +01:00
unparenting = false ;
2015-09-16 03:07:03 +02:00
can_update_body = false ;
2017-03-05 16:44:50 +01:00
update_shape_index = - 1 ;
2014-02-10 02:10:30 +01:00
}