/*************************************************************************/ /* collision_shape_2d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* 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" #include "scene/resources/circle_shape_2d.h" #include "scene/resources/concave_polygon_shape_2d.h" #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" void CollisionShape2D::_add_to_collision_object(Object *p_obj) { if (unparenting) return; CollisionObject2D *co = p_obj->cast_to(); ERR_FAIL_COND(!co); update_shape_index = co->get_shape_count(); co->add_shape(shape, get_transform()); if (trigger) co->set_shape_as_trigger(co->get_shape_count() - 1, true); } void CollisionShape2D::_shape_changed() { update(); _update_parent(); } void CollisionShape2D::_update_parent() { Node *parent = get_parent(); if (!parent) return; CollisionObject2D *co = parent->cast_to(); if (!co) return; co->_update_shapes_from_children(); } void CollisionShape2D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { unparenting = false; can_update_body = get_tree()->is_editor_hint(); if (!get_tree()->is_editor_hint()) { //display above all else set_z_as_relative(false); set_z(VS::CANVAS_ITEM_Z_MAX - 1); } } break; case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { if (!is_inside_tree()) break; if (can_update_body) { _update_parent(); } else if (update_shape_index >= 0) { CollisionObject2D *co = get_parent()->cast_to(); if (co) { co->set_shape_transform(update_shape_index, get_transform()); } } } break; case NOTIFICATION_EXIT_TREE: { can_update_body = false; } break; /* case NOTIFICATION_TRANSFORM_CHANGED: { if (!is_inside_scene()) break; _update_parent(); } break;*/ case NOTIFICATION_DRAW: { if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) { break; } if (!shape.is_valid()) { break; } rect = Rect2(); Color draw_col = get_tree()->get_debug_collisions_color(); shape->draw(get_canvas_item(), draw_col); rect = shape->get_rect(); rect = rect.grow(3); } break; case NOTIFICATION_UNPARENTED: { unparenting = true; _update_parent(); } break; } } void CollisionShape2D::set_shape(const Ref &p_shape) { if (shape.is_valid()) shape->disconnect("changed", this, "_shape_changed"); shape = p_shape; update(); if (is_inside_tree() && can_update_body) _update_parent(); if (is_inside_tree() && !can_update_body && update_shape_index >= 0) { CollisionObject2D *co = get_parent()->cast_to(); if (co) { co->set_shape(update_shape_index, p_shape); } } if (shape.is_valid()) shape->connect("changed", this, "_shape_changed"); update_configuration_warning(); } Ref CollisionShape2D::get_shape() const { return shape; } Rect2 CollisionShape2D::get_item_rect() const { return rect; } void CollisionShape2D::set_trigger(bool p_trigger) { trigger = p_trigger; if (can_update_body) { _update_parent(); } else if (is_inside_tree() && update_shape_index >= 0) { CollisionObject2D *co = get_parent()->cast_to(); if (co) { co->set_shape_as_trigger(update_shape_index, p_trigger); } } } bool CollisionShape2D::is_trigger() const { return trigger; } void CollisionShape2D::_set_update_shape_index(int p_index) { update_shape_index = p_index; } int CollisionShape2D::_get_update_shape_index() const { return update_shape_index; } String CollisionShape2D::get_configuration_warning() const { if (!get_parent()->cast_to()) { 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(); } void CollisionShape2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_shape", "shape"), &CollisionShape2D::set_shape); ObjectTypeDB::bind_method(_MD("get_shape"), &CollisionShape2D::get_shape); ObjectTypeDB::bind_method(_MD("_shape_changed"), &CollisionShape2D::_shape_changed); ObjectTypeDB::bind_method(_MD("_add_to_collision_object"), &CollisionShape2D::_add_to_collision_object); ObjectTypeDB::bind_method(_MD("set_trigger", "enable"), &CollisionShape2D::set_trigger); ObjectTypeDB::bind_method(_MD("is_trigger"), &CollisionShape2D::is_trigger); ObjectTypeDB::bind_method(_MD("_set_update_shape_index", "index"), &CollisionShape2D::_set_update_shape_index); ObjectTypeDB::bind_method(_MD("_get_update_shape_index"), &CollisionShape2D::_get_update_shape_index); ObjectTypeDB::bind_method(_MD("get_collision_object_shape_index"), &CollisionShape2D::get_collision_object_shape_index); ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), _SCS("set_shape"), _SCS("get_shape")); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "trigger"), _SCS("set_trigger"), _SCS("is_trigger")); ADD_PROPERTY(PropertyInfo(Variant::INT, "_update_shape_index", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), _SCS("_set_update_shape_index"), _SCS("_get_update_shape_index")); } CollisionShape2D::CollisionShape2D() { rect = Rect2(-Point2(10, 10), Point2(20, 20)); set_notify_local_transform(true); trigger = false; unparenting = false; can_update_body = false; update_shape_index = -1; }