/*************************************************************************/ /* joints_2d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 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. */ /*************************************************************************/ #include "joints_2d.h" #include "servers/physics_2d_server.h" #include "physics_body_2d.h" void Joint2D::_update_joint() { if (!is_inside_tree()) return; if (joint.is_valid()) { Physics2DServer::get_singleton()->free(joint); } joint=RID(); joint = _configure_joint(); Physics2DServer::get_singleton()->get_singleton()->joint_set_param(joint,Physics2DServer::JOINT_PARAM_BIAS,bias); } void Joint2D::set_node_a(const NodePath& p_node_a) { if (a==p_node_a) return; a=p_node_a; _update_joint(); } NodePath Joint2D::get_node_a() const{ return a; } void Joint2D::set_node_b(const NodePath& p_node_b){ if (b==p_node_b) return; b=p_node_b; _update_joint(); } NodePath Joint2D::get_node_b() const{ return b; } void Joint2D::_notification(int p_what) { switch(p_what) { case NOTIFICATION_READY: { _update_joint(); } break; case NOTIFICATION_EXIT_TREE: { if (joint.is_valid()) { Physics2DServer::get_singleton()->free(joint); joint=RID(); } } break; } } void Joint2D::set_bias(real_t p_bias) { bias=p_bias; if (joint.is_valid()) Physics2DServer::get_singleton()->get_singleton()->joint_set_param(joint,Physics2DServer::JOINT_PARAM_BIAS,bias); } real_t Joint2D::get_bias() const{ return bias; } void Joint2D::set_exclude_nodes_from_collision(bool p_enable) { if (exclude_from_collision==p_enable) return; exclude_from_collision=p_enable; _update_joint(); } bool Joint2D::get_exclude_nodes_from_collision() const{ return exclude_from_collision; } void Joint2D::_bind_methods() { ClassDB::bind_method( _MD("set_node_a","node"), &Joint2D::set_node_a ); ClassDB::bind_method( _MD("get_node_a"), &Joint2D::get_node_a ); ClassDB::bind_method( _MD("set_node_b","node"), &Joint2D::set_node_b ); ClassDB::bind_method( _MD("get_node_b"), &Joint2D::get_node_b ); ClassDB::bind_method( _MD("set_bias","bias"), &Joint2D::set_bias ); ClassDB::bind_method( _MD("get_bias"), &Joint2D::get_bias ); ClassDB::bind_method( _MD("set_exclude_nodes_from_collision","enable"), &Joint2D::set_exclude_nodes_from_collision ); ClassDB::bind_method( _MD("get_exclude_nodes_from_collision"), &Joint2D::get_exclude_nodes_from_collision ); ADD_PROPERTY( PropertyInfo( Variant::NODE_PATH, "node_a"), _SCS("set_node_a"),_SCS("get_node_a") ); ADD_PROPERTY( PropertyInfo( Variant::NODE_PATH, "node_b"), _SCS("set_node_b"),_SCS("get_node_b") ); ADD_PROPERTY( PropertyInfo( Variant::REAL, "bias",PROPERTY_HINT_RANGE,"0,0.9,0.001"), _SCS("set_bias"),_SCS("get_bias") ); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "disable_collision"), _SCS("set_exclude_nodes_from_collision"),_SCS("get_exclude_nodes_from_collision") ); } Joint2D::Joint2D() { bias=0; exclude_from_collision=true; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void PinJoint2D::_notification(int p_what) { switch(p_what) { case NOTIFICATION_DRAW: { if (!is_inside_tree()) break; if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) { break; } draw_line(Point2(-10,0),Point2(+10,0),Color(0.7,0.6,0.0,0.5),3); draw_line(Point2(0,-10),Point2(0,+10),Color(0.7,0.6,0.0,0.5),3); } break; } } RID PinJoint2D::_configure_joint() { Node *node_a = has_node( get_node_a() ) ? get_node( get_node_a() ) : (Node*)NULL; Node *node_b = has_node( get_node_b() ) ? get_node( get_node_b() ) : (Node*)NULL; if (!node_a && !node_b) return RID(); PhysicsBody2D *body_a=node_a ? node_a->cast_to() : (PhysicsBody2D*)NULL; PhysicsBody2D *body_b=node_b ? node_b->cast_to() : (PhysicsBody2D*)NULL; if (!body_a && !body_b) return RID(); if (!body_a) { SWAP(body_a,body_b); } else if (body_b) { //add a collision exception between both if (get_exclude_nodes_from_collision()) Physics2DServer::get_singleton()->body_add_collision_exception(body_a->get_rid(),body_b->get_rid()); else Physics2DServer::get_singleton()->body_remove_collision_exception(body_a->get_rid(),body_b->get_rid()); } RID pj = Physics2DServer::get_singleton()->pin_joint_create(get_global_transform().get_origin(),body_a->get_rid(),body_b?body_b->get_rid():RID()); Physics2DServer::get_singleton()->pin_joint_set_param(pj, Physics2DServer::PIN_JOINT_SOFTNESS, softness); return pj; } void PinJoint2D::set_softness(real_t p_softness) { softness=p_softness; update(); if (get_joint().is_valid()) Physics2DServer::get_singleton()->pin_joint_set_param(get_joint(), Physics2DServer::PIN_JOINT_SOFTNESS, p_softness); } real_t PinJoint2D::get_softness() const { return softness; } void PinJoint2D::_bind_methods() { ClassDB::bind_method(_MD("set_softness","softness"), &PinJoint2D::set_softness); ClassDB::bind_method(_MD("get_softness"), &PinJoint2D::get_softness); ADD_PROPERTY( PropertyInfo( Variant::REAL, "softness", PROPERTY_HINT_EXP_RANGE,"0.00,16,0.01"), _SCS("set_softness"), _SCS("get_softness")); } PinJoint2D::PinJoint2D() { softness = 0; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void GrooveJoint2D::_notification(int p_what) { switch(p_what) { case NOTIFICATION_DRAW: { if (!is_inside_tree()) break; if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) { break; } draw_line(Point2(-10,0),Point2(+10,0),Color(0.7,0.6,0.0,0.5),3); draw_line(Point2(-10,length),Point2(+10,length),Color(0.7,0.6,0.0,0.5),3); draw_line(Point2(0,0),Point2(0,length),Color(0.7,0.6,0.0,0.5),3); draw_line(Point2(-10,initial_offset),Point2(+10,initial_offset),Color(0.8,0.8,0.9,0.5),5); } break; } } RID GrooveJoint2D::_configure_joint(){ Node *node_a = has_node( get_node_a() ) ? get_node( get_node_a() ) : (Node*)NULL; Node *node_b = has_node( get_node_b() ) ? get_node( get_node_b() ) : (Node*)NULL; if (!node_a || !node_b) return RID(); PhysicsBody2D *body_a=node_a->cast_to(); PhysicsBody2D *body_b=node_b->cast_to(); if (!body_a || !body_b) return RID(); if (get_exclude_nodes_from_collision()) Physics2DServer::get_singleton()->body_add_collision_exception(body_a->get_rid(),body_b->get_rid()); else Physics2DServer::get_singleton()->body_remove_collision_exception(body_a->get_rid(),body_b->get_rid()); Matrix32 gt = get_global_transform(); Vector2 groove_A1 = gt.get_origin(); Vector2 groove_A2 = gt.xform( Vector2(0,length) ); Vector2 anchor_B = gt.xform( Vector2(0,initial_offset) ); return Physics2DServer::get_singleton()->groove_joint_create(groove_A1,groove_A2,anchor_B,body_a->get_rid(),body_b->get_rid()); } void GrooveJoint2D::set_length(real_t p_length) { length=p_length; update(); } real_t GrooveJoint2D::get_length() const { return length; } void GrooveJoint2D::set_initial_offset(real_t p_initial_offset) { initial_offset=p_initial_offset; update(); } real_t GrooveJoint2D::get_initial_offset() const { return initial_offset; } void GrooveJoint2D::_bind_methods() { ClassDB::bind_method(_MD("set_length","length"),&GrooveJoint2D::set_length); ClassDB::bind_method(_MD("get_length"),&GrooveJoint2D::get_length); ClassDB::bind_method(_MD("set_initial_offset","offset"),&GrooveJoint2D::set_initial_offset); ClassDB::bind_method(_MD("get_initial_offset"),&GrooveJoint2D::get_initial_offset); ADD_PROPERTY( PropertyInfo( Variant::REAL, "length", PROPERTY_HINT_EXP_RANGE,"1,65535,1"), _SCS("set_length"),_SCS("get_length")); ADD_PROPERTY( PropertyInfo( Variant::REAL, "initial_offset", PROPERTY_HINT_EXP_RANGE,"1,65535,1"), _SCS("set_initial_offset"),_SCS("get_initial_offset")); } GrooveJoint2D::GrooveJoint2D() { length=50; initial_offset=25; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void DampedSpringJoint2D::_notification(int p_what) { switch(p_what) { case NOTIFICATION_DRAW: { if (!is_inside_tree()) break; if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) { break; } draw_line(Point2(-10,0),Point2(+10,0),Color(0.7,0.6,0.0,0.5),3); draw_line(Point2(-10,length),Point2(+10,length),Color(0.7,0.6,0.0,0.5),3); draw_line(Point2(0,0),Point2(0,length),Color(0.7,0.6,0.0,0.5),3); } break; } } RID DampedSpringJoint2D::_configure_joint(){ Node *node_a = has_node( get_node_a() ) ? get_node( get_node_a() ) : (Node*)NULL; Node *node_b = has_node( get_node_b() ) ? get_node( get_node_b() ) : (Node*)NULL; if (!node_a || !node_b) return RID(); PhysicsBody2D *body_a=node_a->cast_to(); PhysicsBody2D *body_b=node_b->cast_to(); if (!body_a || !body_b) return RID(); if (get_exclude_nodes_from_collision()) Physics2DServer::get_singleton()->body_add_collision_exception(body_a->get_rid(),body_b->get_rid()); else Physics2DServer::get_singleton()->body_remove_collision_exception(body_a->get_rid(),body_b->get_rid()); Matrix32 gt = get_global_transform(); Vector2 anchor_A = gt.get_origin(); Vector2 anchor_B = gt.xform( Vector2(0,length) ); RID dsj = Physics2DServer::get_singleton()->damped_spring_joint_create(anchor_A,anchor_B,body_a->get_rid(),body_b->get_rid()); if (rest_length) Physics2DServer::get_singleton()->damped_string_joint_set_param(dsj,Physics2DServer::DAMPED_STRING_REST_LENGTH,rest_length); Physics2DServer::get_singleton()->damped_string_joint_set_param(dsj,Physics2DServer::DAMPED_STRING_STIFFNESS,stiffness); Physics2DServer::get_singleton()->damped_string_joint_set_param(dsj,Physics2DServer::DAMPED_STRING_DAMPING,damping); return dsj; } void DampedSpringJoint2D::set_length(real_t p_length) { length=p_length; update(); } real_t DampedSpringJoint2D::get_length() const { return length; } void DampedSpringJoint2D::set_rest_length(real_t p_rest_length) { rest_length=p_rest_length; update(); if (get_joint().is_valid()) Physics2DServer::get_singleton()->damped_string_joint_set_param(get_joint(),Physics2DServer::DAMPED_STRING_REST_LENGTH,p_rest_length?p_rest_length:length); } real_t DampedSpringJoint2D::get_rest_length() const { return rest_length; } void DampedSpringJoint2D::set_stiffness(real_t p_stiffness) { stiffness=p_stiffness; update(); if (get_joint().is_valid()) Physics2DServer::get_singleton()->damped_string_joint_set_param(get_joint(),Physics2DServer::DAMPED_STRING_STIFFNESS,p_stiffness); } real_t DampedSpringJoint2D::get_stiffness() const { return stiffness; } void DampedSpringJoint2D::set_damping(real_t p_damping) { damping=p_damping; update(); if (get_joint().is_valid()) Physics2DServer::get_singleton()->damped_string_joint_set_param(get_joint(),Physics2DServer::DAMPED_STRING_DAMPING,p_damping); } real_t DampedSpringJoint2D::get_damping() const { return damping; } void DampedSpringJoint2D::_bind_methods() { ClassDB::bind_method(_MD("set_length","length"),&DampedSpringJoint2D::set_length); ClassDB::bind_method(_MD("get_length"),&DampedSpringJoint2D::get_length); ClassDB::bind_method(_MD("set_rest_length","rest_length"),&DampedSpringJoint2D::set_rest_length); ClassDB::bind_method(_MD("get_rest_length"),&DampedSpringJoint2D::get_rest_length); ClassDB::bind_method(_MD("set_stiffness","stiffness"),&DampedSpringJoint2D::set_stiffness); ClassDB::bind_method(_MD("get_stiffness"),&DampedSpringJoint2D::get_stiffness); ClassDB::bind_method(_MD("set_damping","damping"),&DampedSpringJoint2D::set_damping); ClassDB::bind_method(_MD("get_damping"),&DampedSpringJoint2D::get_damping); ADD_PROPERTY( PropertyInfo( Variant::REAL, "length", PROPERTY_HINT_EXP_RANGE,"1,65535,1"), _SCS("set_length"),_SCS("get_length")); ADD_PROPERTY( PropertyInfo( Variant::REAL, "rest_length", PROPERTY_HINT_EXP_RANGE,"0,65535,1"), _SCS("set_rest_length"),_SCS("get_rest_length")); ADD_PROPERTY( PropertyInfo( Variant::REAL, "stiffness", PROPERTY_HINT_EXP_RANGE,"0.1,64,0.1"), _SCS("set_stiffness"),_SCS("get_stiffness")); ADD_PROPERTY( PropertyInfo( Variant::REAL, "damping", PROPERTY_HINT_EXP_RANGE,"0.01,16,0.01"), _SCS("set_damping"),_SCS("get_damping")); } DampedSpringJoint2D::DampedSpringJoint2D() { length=50; rest_length=0; stiffness=20; damping=1; }