diff options
Diffstat (limited to 'scene')
27 files changed, 2804 insertions, 179 deletions
diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp index 5ab223a1b8..ef63286697 100644 --- a/scene/2d/collision_polygon_2d.cpp +++ b/scene/2d/collision_polygon_2d.cpp @@ -153,6 +153,7 @@ void CollisionPolygon2D::set_build_mode(BuildMode p_mode) { ERR_FAIL_INDEX(p_mode,2); build_mode=p_mode; + _update_parent(); } CollisionPolygon2D::BuildMode CollisionPolygon2D::get_build_mode() const{ @@ -174,7 +175,7 @@ void CollisionPolygon2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_build_mode"),&CollisionPolygon2D::set_build_mode); ObjectTypeDB::bind_method(_MD("get_build_mode"),&CollisionPolygon2D::get_build_mode); - ADD_PROPERTY( PropertyInfo(Variant::INT,"build_mode",PROPERTY_HINT_ENUM,"Automatic,Segments,Solids"),_SCS("set_build_mode"),_SCS("get_build_mode")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"build_mode",PROPERTY_HINT_ENUM,"Solids,Segments"),_SCS("set_build_mode"),_SCS("get_build_mode")); ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon")); } diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index ecd147afde..47d78399b6 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -803,7 +803,7 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { //print_line("margin: "+rtos(margin)); do { - //fill exclude list.. + //motion recover for(int i=0;i<get_shape_count();i++) { diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp index 964a086cf6..f5895453cc 100644 --- a/scene/3d/area.cpp +++ b/scene/3d/area.cpp @@ -255,6 +255,17 @@ bool Area::is_monitoring_enabled() const { } +void Area::set_ray_pickable(bool p_ray_pickable) { + + ray_pickable=p_ray_pickable; + PhysicsServer::get_singleton()->area_set_ray_pickable(get_rid(),p_ray_pickable); +} + +bool Area::is_ray_pickable() const { + + return ray_pickable; +} + void Area::_bind_methods() { ObjectTypeDB::bind_method(_MD("_body_enter_scene","id"),&Area::_body_enter_scene); @@ -278,6 +289,9 @@ void Area::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_priority","priority"),&Area::set_priority); ObjectTypeDB::bind_method(_MD("get_priority"),&Area::get_priority); + ObjectTypeDB::bind_method(_MD("set_ray_pickable","ray_pickable"),&Area::set_ray_pickable); + ObjectTypeDB::bind_method(_MD("is_ray_pickable"),&Area::is_ray_pickable); + ObjectTypeDB::bind_method(_MD("set_enable_monitoring","enable"),&Area::set_enable_monitoring); ObjectTypeDB::bind_method(_MD("is_monitoring_enabled"),&Area::is_monitoring_enabled); @@ -296,6 +310,7 @@ void Area::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::REAL,"density",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_density"),_SCS("get_density")); ADD_PROPERTY( PropertyInfo(Variant::INT,"priority",PROPERTY_HINT_RANGE,"0,128,1"),_SCS("set_priority"),_SCS("get_priority")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitoring"),_SCS("set_enable_monitoring"),_SCS("is_monitoring_enabled")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"ray_pickable"),_SCS("set_ray_pickable"),_SCS("is_ray_pickable")); } @@ -308,6 +323,8 @@ Area::Area() : CollisionObject(PhysicsServer::get_singleton()->area_create(),tru density=0.1; priority=0; monitoring=false; + ray_pickable=false; + set_enable_monitoring(true); } diff --git a/scene/3d/area.h b/scene/3d/area.h index 79e98f9dab..92b5d39f59 100644 --- a/scene/3d/area.h +++ b/scene/3d/area.h @@ -52,6 +52,7 @@ private: real_t density; int priority; bool monitoring; + bool ray_pickable; void _body_inout(int p_status,const RID& p_body, int p_instance, int p_body_shape,int p_area_shape); @@ -108,6 +109,9 @@ public: void set_priority(real_t p_priority); real_t get_priority() const; + void set_ray_pickable(bool p_ray_pickable); + bool is_ray_pickable() const; + void set_enable_monitoring(bool p_enable); bool is_monitoring_enabled() const; diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp index 56fbf358bc..4245bfa2c9 100644 --- a/scene/3d/camera.cpp +++ b/scene/3d/camera.cpp @@ -74,16 +74,18 @@ bool Camera::_set(const StringName& p_name, const Variant& p_value) { mode=PROJECTION_ORTHOGONAL; changed_all=true; - } else if (p_name=="fov") + } else if (p_name=="fov" || p_name=="fovy" || p_name=="fovx") fov=p_value; - else if (p_name=="size") + else if (p_name=="size" || p_name=="sizex" || p_name=="sizey") size=p_value; else if (p_name=="near") near=p_value; else if (p_name=="far") far=p_value; + else if (p_name=="keep_aspect") + set_keep_aspect_mode(KeepAspect(int(p_value))); else if (p_name=="vaspect") - set_use_vertical_aspect(p_value); + set_keep_aspect_mode(p_value?KEEP_WIDTH:KEEP_HEIGHT); else if (p_name=="current") { if (p_value.operator bool()) { make_current(); @@ -107,16 +109,16 @@ bool Camera::_get(const StringName& p_name,Variant &r_ret) const { if (p_name=="projection") { r_ret= mode; - } else if (p_name=="fov") + } else if (p_name=="fov" || p_name=="fovy" || p_name=="fovx") r_ret= fov; - else if (p_name=="size") + else if (p_name=="size" || p_name=="sizex" || p_name=="sizey") r_ret= size; else if (p_name=="near") r_ret= near; else if (p_name=="far") r_ret= far; - else if (p_name=="vaspect") - r_ret= vaspect; + else if (p_name=="keep_aspect") + r_ret= int(keep_aspect); else if (p_name=="current") { if (is_inside_scene() && get_scene()->is_editor_hint()) { @@ -142,19 +144,29 @@ void Camera::_get_property_list( List<PropertyInfo> *p_list) const { case PROJECTION_PERSPECTIVE: { - p_list->push_back( PropertyInfo( Variant::REAL, "fov" , PROPERTY_HINT_RANGE, "1,89,0.1") ); + p_list->push_back( PropertyInfo( Variant::REAL, "fov" , PROPERTY_HINT_RANGE, "1,89,0.1",PROPERTY_USAGE_NOEDITOR) ); + if (keep_aspect==KEEP_WIDTH) + p_list->push_back( PropertyInfo( Variant::REAL, "fovx" , PROPERTY_HINT_RANGE, "1,89,0.1",PROPERTY_USAGE_EDITOR) ); + else + p_list->push_back( PropertyInfo( Variant::REAL, "fovy" , PROPERTY_HINT_RANGE, "1,89,0.1",PROPERTY_USAGE_EDITOR) ); + } break; case PROJECTION_ORTHOGONAL: { - p_list->push_back( PropertyInfo( Variant::REAL, "size" , PROPERTY_HINT_RANGE, "1,16384,0.01" ) ); + p_list->push_back( PropertyInfo( Variant::REAL, "size" , PROPERTY_HINT_RANGE, "1,16384,0.01",PROPERTY_USAGE_NOEDITOR ) ); + if (keep_aspect==KEEP_WIDTH) + p_list->push_back( PropertyInfo( Variant::REAL, "sizex" , PROPERTY_HINT_RANGE, "0.1,16384,0.01",PROPERTY_USAGE_EDITOR) ); + else + p_list->push_back( PropertyInfo( Variant::REAL, "sizey" , PROPERTY_HINT_RANGE, "0.1,16384,0.01",PROPERTY_USAGE_EDITOR) ); + } break; } p_list->push_back( PropertyInfo( Variant::REAL, "near" , PROPERTY_HINT_EXP_RANGE, "0.01,4096.0,0.01") ); p_list->push_back( PropertyInfo( Variant::REAL, "far" , PROPERTY_HINT_EXP_RANGE, "0.01,4096.0,0.01") ); - p_list->push_back( PropertyInfo( Variant::BOOL, "vaspect") ); + p_list->push_back( PropertyInfo( Variant::INT, "keep_aspect",PROPERTY_HINT_ENUM,"Keep Width,Keep Height") ); p_list->push_back( PropertyInfo( Variant::BOOL, "current" ) ); p_list->push_back( PropertyInfo( Variant::INT, "visible_layers",PROPERTY_HINT_ALL_FLAGS ) ); p_list->push_back( PropertyInfo( Variant::OBJECT, "environment",PROPERTY_HINT_RESOURCE_TYPE,"Environment" ) ); @@ -441,7 +453,7 @@ Vector3 Camera::project_local_ray_normal(const Point2& p_pos) const { ray=Vector3(0,0,-1); } else { CameraMatrix cm; - cm.set_perspective(fov,viewport_size.get_aspect(),near,far,vaspect); + cm.set_perspective(fov,viewport_size.get_aspect(),near,far,keep_aspect==KEEP_WIDTH); float screen_w,screen_h; cm.get_viewport_size(screen_w,screen_h); ray=Vector3( ((p_pos.x/viewport_size.width)*2.0-1.0)*screen_w, ((1.0-(p_pos.y/viewport_size.height))*2.0-1.0)*screen_h,-near).normalized(); @@ -472,7 +484,7 @@ Vector3 Camera::project_ray_origin(const Point2& p_pos) const { Vector2 pos = p_pos / viewport_size; float vsize,hsize; - if (vaspect) { + if (keep_aspect==KEEP_WIDTH) { vsize = size/viewport_size.get_aspect(); hsize = size; } else { @@ -503,9 +515,9 @@ Point2 Camera::unproject_position(const Vector3& p_pos) const { if (mode==PROJECTION_ORTHOGONAL) - cm.set_orthogonal(size,viewport_size.get_aspect(),near,far,vaspect); + cm.set_orthogonal(size,viewport_size.get_aspect(),near,far,keep_aspect==KEEP_WIDTH); else - cm.set_perspective(fov,viewport_size.get_aspect(),near,far,vaspect); + cm.set_perspective(fov,viewport_size.get_aspect(),near,far,keep_aspect==KEEP_WIDTH); Plane p(get_camera_transform().xform_inv(p_pos),1.0); @@ -533,9 +545,9 @@ Vector3 Camera::project_position(const Point2& p_point) const { CameraMatrix cm; if (mode==PROJECTION_ORTHOGONAL) - cm.set_orthogonal(size,viewport_size.get_aspect(),near,far,vaspect); + cm.set_orthogonal(size,viewport_size.get_aspect(),near,far,keep_aspect==KEEP_WIDTH); else - cm.set_perspective(fov,viewport_size.get_aspect(),near,far,vaspect); + cm.set_perspective(fov,viewport_size.get_aspect(),near,far,keep_aspect==KEEP_WIDTH); Size2 vp_size; cm.get_viewport_size(vp_size.x,vp_size.y); @@ -583,6 +595,20 @@ Ref<Environment> Camera::get_environment() const { } +void Camera::set_keep_aspect_mode(KeepAspect p_aspect) { + + keep_aspect=p_aspect; + VisualServer::get_singleton()->camera_set_use_vertical_aspect(camera,p_aspect==KEEP_WIDTH); + + _change_notify(); +} + +Camera::KeepAspect Camera::get_keep_aspect_mode() const{ + + return keep_aspect; +} + + void Camera::_bind_methods() { @@ -608,12 +634,16 @@ void Camera::_bind_methods() { ObjectTypeDB::bind_method( _MD("look_at_from_pos","pos","target","up"),&Camera::look_at_from_pos ); ObjectTypeDB::bind_method(_MD("set_environment","env:Environment"),&Camera::set_environment); ObjectTypeDB::bind_method(_MD("get_environment:Environment"),&Camera::get_environment); - ObjectTypeDB::bind_method(_MD("set_use_vertical_aspect","enable"),&Camera::set_use_vertical_aspect); - ObjectTypeDB::bind_method(_MD("is_using_vertical_aspect"),&Camera::is_using_vertical_aspect); + ObjectTypeDB::bind_method(_MD("set_keep_aspect_mode","mode"),&Camera::set_keep_aspect_mode); + ObjectTypeDB::bind_method(_MD("get_keep_aspect_mode"),&Camera::get_keep_aspect_mode); //ObjectTypeDB::bind_method( _MD("_camera_make_current"),&Camera::_camera_make_current ); BIND_CONSTANT( PROJECTION_PERSPECTIVE ); BIND_CONSTANT( PROJECTION_ORTHOGONAL ); + + BIND_CONSTANT( KEEP_WIDTH ); + BIND_CONSTANT( KEEP_HEIGHT ); + } float Camera::get_fov() const { @@ -661,26 +691,15 @@ Vector<Plane> Camera::get_frustum() const { Size2 viewport_size = viewport_ptr->get_visible_rect().size; CameraMatrix cm; if (mode==PROJECTION_PERSPECTIVE) - cm.set_perspective(fov,viewport_size.get_aspect(),near,far,vaspect); + cm.set_perspective(fov,viewport_size.get_aspect(),near,far,keep_aspect==KEEP_WIDTH); else - cm.set_orthogonal(size,viewport_size.get_aspect(),near,far,vaspect); + cm.set_orthogonal(size,viewport_size.get_aspect(),near,far,keep_aspect==KEEP_WIDTH); return cm.get_projection_planes(get_global_transform()); } -void Camera::set_use_vertical_aspect(bool p_enable) { - - vaspect=p_enable; - VisualServer::get_singleton()->camera_set_use_vertical_aspect(camera,p_enable); -} - - -bool Camera::is_using_vertical_aspect() const{ - - return vaspect; -} void Camera::look_at(const Vector3& p_target, const Vector3& p_up_normal) { @@ -712,7 +731,7 @@ Camera::Camera() { force_change=false; mode=PROJECTION_PERSPECTIVE; set_perspective(60.0,0.1,100.0); - vaspect=false; + keep_aspect=KEEP_HEIGHT; layers=0xFFFFFFFF; //active=false; } diff --git a/scene/3d/camera.h b/scene/3d/camera.h index a8599497ac..014c7cb520 100644 --- a/scene/3d/camera.h +++ b/scene/3d/camera.h @@ -46,6 +46,11 @@ public: PROJECTION_ORTHOGONAL }; + enum KeepAspect { + KEEP_WIDTH, + KEEP_HEIGHT + }; + private: bool force_change; @@ -56,7 +61,7 @@ private: float fov; float size; float near,far; - bool vaspect; + KeepAspect keep_aspect; RID camera; RID scenario_id; @@ -126,8 +131,8 @@ public: void set_environment(const Ref<Environment>& p_environment); Ref<Environment> get_environment() const; - void set_use_vertical_aspect(bool p_enable); - bool is_using_vertical_aspect() const; + void set_keep_aspect_mode(KeepAspect p_aspect); + KeepAspect get_keep_aspect_mode() const; void look_at(const Vector3& p_target, const Vector3& p_up_normal); void look_at_from_pos(const Vector3& p_pos,const Vector3& p_target, const Vector3& p_up_normal); @@ -140,5 +145,6 @@ public: VARIANT_ENUM_CAST( Camera::Projection ); +VARIANT_ENUM_CAST( Camera::KeepAspect ); #endif diff --git a/scene/3d/collision_object.cpp b/scene/3d/collision_object.cpp index 7ad10d3222..06564f5c49 100644 --- a/scene/3d/collision_object.cpp +++ b/scene/3d/collision_object.cpp @@ -28,7 +28,7 @@ /*************************************************************************/ #include "collision_object.h" #include "servers/physics_server.h" - +#include "scene/scene_string_names.h" void CollisionObject::_update_shapes_from_children() { shapes.resize(0); @@ -165,6 +165,34 @@ void CollisionObject::_get_property_list( List<PropertyInfo> *p_list) const { } } + +void CollisionObject::_input_event(const InputEvent& p_input_event,const Vector3& p_pos, const Vector3& p_normal, int p_shape) { + + if (get_script_instance()) { + get_script_instance()->call(SceneStringNames::get_singleton()->_input_event,p_input_event,p_pos,p_normal,p_shape); + } + emit_signal(SceneStringNames::get_singleton()->input_event,p_input_event,p_pos,p_normal,p_shape); +} + +void CollisionObject::_mouse_enter() { + + if (get_script_instance()) { + get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_enter); + } + emit_signal(SceneStringNames::get_singleton()->mouse_enter); +} + + +void CollisionObject::_mouse_exit() { + + if (get_script_instance()) { + get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_exit); + } + emit_signal(SceneStringNames::get_singleton()->mouse_exit); + +} + + void CollisionObject::_bind_methods() { ObjectTypeDB::bind_method(_MD("add_shape","shape:Shape","transform"),&CollisionObject::add_shape,DEFVAL(Transform())); @@ -178,8 +206,16 @@ void CollisionObject::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_shape_transform","shape_idx"),&CollisionObject::get_shape_transform); ObjectTypeDB::bind_method(_MD("remove_shape","shape_idx"),&CollisionObject::remove_shape); ObjectTypeDB::bind_method(_MD("clear_shapes"),&CollisionObject::clear_shapes); + ObjectTypeDB::bind_method(_MD("set_capture_input_on_drag","enable"),&CollisionObject::set_capture_input_on_drag); + ObjectTypeDB::bind_method(_MD("get_capture_input_on_drag"),&CollisionObject::get_capture_input_on_drag); ObjectTypeDB::bind_method(_MD("get_rid"),&CollisionObject::get_rid); + BIND_VMETHOD( MethodInfo("_input_event",PropertyInfo(Variant::INPUT_EVENT,"event"),PropertyInfo(Variant::VECTOR3,"click_pos"),PropertyInfo(Variant::VECTOR3,"click_normal"),PropertyInfo(Variant::INT,"shape_idx"))); + ADD_SIGNAL( MethodInfo("input_event",PropertyInfo(Variant::INPUT_EVENT,"event"),PropertyInfo(Variant::VECTOR3,"click_pos"),PropertyInfo(Variant::VECTOR3,"click_normal"),PropertyInfo(Variant::INT,"shape_idx"))); + ADD_SIGNAL( MethodInfo("mouse_enter")); + ADD_SIGNAL( MethodInfo("mouse_exit")); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"input/capture_on_drag"),_SCS("set_capture_input_on_drag"),_SCS("get_capture_input_on_drag")); } @@ -269,10 +305,23 @@ CollisionObject::CollisionObject(RID p_rid, bool p_area) { } +void CollisionObject::set_capture_input_on_drag(bool p_capture) { + + capture_input_on_drag=p_capture; + +} + +bool CollisionObject::get_capture_input_on_drag() const { + + return capture_input_on_drag; +} + CollisionObject::CollisionObject() { + capture_input_on_drag=false; + //owner= //set_transform_notify(true); diff --git a/scene/3d/collision_object.h b/scene/3d/collision_object.h index 54dc6508ab..afd73aa9cc 100644 --- a/scene/3d/collision_object.h +++ b/scene/3d/collision_object.h @@ -50,6 +50,7 @@ class CollisionObject : public Spatial { }; + bool capture_input_on_drag; Vector<ShapeData> shapes; @@ -67,6 +68,11 @@ protected: bool _get(const StringName& p_name,Variant &r_ret) const; void _get_property_list( List<PropertyInfo> *p_list) const; static void _bind_methods(); +friend class Viewport; + virtual void _input_event(const InputEvent& p_input_event,const Vector3& p_pos, const Vector3& p_normal, int p_shape); + virtual void _mouse_enter(); + virtual void _mouse_exit(); + public: @@ -81,6 +87,9 @@ public: void set_shape_as_trigger(int p_shape_idx, bool p_trigger); bool is_shape_set_as_trigger(int p_shape_idx) const; + void set_capture_input_on_drag(bool p_capture); + bool get_capture_input_on_drag() const; + _FORCE_INLINE_ RID get_rid() const { return rid; } CollisionObject(); diff --git a/scene/3d/collision_polygon.cpp b/scene/3d/collision_polygon.cpp new file mode 100644 index 0000000000..5a613f360a --- /dev/null +++ b/scene/3d/collision_polygon.cpp @@ -0,0 +1,206 @@ +#include "collision_polygon.h" + +#include "collision_object.h" +#include "scene/resources/concave_polygon_shape.h" +#include "scene/resources/convex_polygon_shape.h" + +void CollisionPolygon::_add_to_collision_object(Object *p_obj) { + + + CollisionObject *co = p_obj->cast_to<CollisionObject>(); + ERR_FAIL_COND(!co); + + if (polygon.size()==0) + return; + + bool solids=build_mode==BUILD_SOLIDS; + + Vector< Vector<Vector2> > decomp = Geometry::decompose_polygon(polygon); + if (decomp.size()==0) + return; + + if (true || solids) { + + //here comes the sun, lalalala + //decompose concave into multiple convex polygons and add them + for(int i=0;i<decomp.size();i++) { + Ref<ConvexPolygonShape> convex = memnew( ConvexPolygonShape ); + DVector<Vector3> cp; + int cs = decomp[i].size(); + cp.resize(cs*2); + { + DVector<Vector3>::Write w = cp.write(); + int idx=0; + for(int j=0;j<cs;j++) { + + Vector2 d = decomp[i][j]; + w[idx++]=Vector3(d.x,d.y,depth*0.5); + w[idx++]=Vector3(d.x,d.y,-depth*0.5); + } + } + + convex->set_points(cp); + co->add_shape(convex,get_transform()); + + } + + } else { +#if 0 + Ref<ConcavePolygonShape> concave = memnew( ConcavePolygonShape ); + + DVector<Vector2> segments; + segments.resize(polygon.size()*2); + DVector<Vector2>::Write w=segments.write(); + + for(int i=0;i<polygon.size();i++) { + w[(i<<1)+0]=polygon[i]; + w[(i<<1)+1]=polygon[(i+1)%polygon.size()]; + } + + w=DVector<Vector2>::Write(); + concave->set_segments(segments); + + co->add_shape(concave,get_transform()); +#endif + } + + + //co->add_shape(shape,get_transform()); + +} + +void CollisionPolygon::_update_parent() { + + Node *parent = get_parent(); + if (!parent) + return; + CollisionObject *co = parent->cast_to<CollisionObject>(); + if (!co) + return; + co->_update_shapes_from_children(); +} + +void CollisionPolygon::_notification(int p_what) { + + + switch(p_what) { + case NOTIFICATION_TRANSFORM_CHANGED: { + + if (!is_inside_scene()) + break; + _update_parent(); + + } break; +#if 0 + case NOTIFICATION_DRAW: { + for(int i=0;i<polygon.size();i++) { + + Vector2 p = polygon[i]; + Vector2 n = polygon[(i+1)%polygon.size()]; + draw_line(p,n,Color(0,0.6,0.7,0.5),3); + } + + Vector< Vector<Vector2> > decomp = Geometry::decompose_polygon(polygon); +#define DEBUG_DECOMPOSE +#ifdef DEBUG_DECOMPOSE + Color c(0.4,0.9,0.1); + for(int i=0;i<decomp.size();i++) { + + c.set_hsv( Math::fmod(c.get_h() + 0.738,1),c.get_s(),c.get_v(),0.5); + draw_colored_polygon(decomp[i],c); + } +#endif + + } break; +#endif + } +} + +void CollisionPolygon::set_polygon(const Vector<Point2>& p_polygon) { + + polygon=p_polygon; + + for(int i=0;i<polygon.size();i++) { + + Vector3 p1(polygon[i].x,polygon[i].y,depth*0.5); + + if (i==0) + aabb=AABB(p1,Vector3()); + else + aabb.expand_to(p1); + + Vector3 p2(polygon[i].x,polygon[i].y,-depth*0.5); + aabb.expand_to(p2); + + + } + if (aabb==AABB()) { + + aabb=AABB(Vector3(-1,-1,-1),Vector3(2,2,2)); + } else { + aabb.pos-=aabb.size*0.3; + aabb.size+=aabb.size*0.6; + } + _update_parent(); + update_gizmo(); +} + +Vector<Point2> CollisionPolygon::get_polygon() const { + + return polygon; +} + +void CollisionPolygon::set_build_mode(BuildMode p_mode) { + + ERR_FAIL_INDEX(p_mode,2); + build_mode=p_mode; + _update_parent(); +} + +CollisionPolygon::BuildMode CollisionPolygon::get_build_mode() const{ + + return build_mode; +} + +AABB CollisionPolygon::get_item_rect() const { + + return aabb; +} + +void CollisionPolygon::set_depth(float p_depth) { + + depth=p_depth; + _update_parent(); + update_gizmo(); +} + +float CollisionPolygon::get_depth() const { + + return depth; +} + + +void CollisionPolygon::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("_add_to_collision_object"),&CollisionPolygon::_add_to_collision_object); + ObjectTypeDB::bind_method(_MD("set_polygon","polygon"),&CollisionPolygon::set_polygon); + ObjectTypeDB::bind_method(_MD("get_polygon"),&CollisionPolygon::get_polygon); + + ObjectTypeDB::bind_method(_MD("set_depth","depth"),&CollisionPolygon::set_depth); + ObjectTypeDB::bind_method(_MD("get_depth"),&CollisionPolygon::get_depth); + + ObjectTypeDB::bind_method(_MD("set_build_mode"),&CollisionPolygon::set_build_mode); + ObjectTypeDB::bind_method(_MD("get_build_mode"),&CollisionPolygon::get_build_mode); + + ADD_PROPERTY( PropertyInfo(Variant::INT,"build_mode",PROPERTY_HINT_ENUM,"Solids,Triangles"),_SCS("set_build_mode"),_SCS("get_build_mode")); + ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"depth"),_SCS("set_depth"),_SCS("get_depth")); +} + +CollisionPolygon::CollisionPolygon() { + + aabb=AABB(Vector3(-1,-1,-1),Vector3(2,2,2)); + build_mode=BUILD_SOLIDS; + depth=1.0; + +} diff --git a/scene/3d/collision_polygon.h b/scene/3d/collision_polygon.h new file mode 100644 index 0000000000..efb3666778 --- /dev/null +++ b/scene/3d/collision_polygon.h @@ -0,0 +1,50 @@ +#ifndef COLLISION_POLYGON_H +#define COLLISION_POLYGON_H + +#include "scene/3d/spatial.h" +#include "scene/resources/shape.h" + + + +class CollisionPolygon : public Spatial { + + OBJ_TYPE(CollisionPolygon,Spatial); +public: + + enum BuildMode { + BUILD_SOLIDS, + BUILD_TRIANGLES, + }; + +protected: + + + float depth; + AABB aabb; + BuildMode build_mode; + Vector<Point2> polygon; + + void _add_to_collision_object(Object *p_obj); + void _update_parent(); + +protected: + + void _notification(int p_what); + static void _bind_methods(); +public: + + void set_build_mode(BuildMode p_mode); + BuildMode get_build_mode() const; + + void set_depth(float p_depth); + float get_depth() const; + + void set_polygon(const Vector<Point2>& p_polygon); + Vector<Point2> get_polygon() const; + + virtual AABB get_item_rect() const; + CollisionPolygon(); +}; + +VARIANT_ENUM_CAST( CollisionPolygon::BuildMode ); +#endif // COLLISION_POLYGON_H diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 721fd368e1..f5e3ad66ee 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -57,160 +57,111 @@ float PhysicsBody::get_inverse_mass() const { return 0; } -PhysicsBody::PhysicsBody(PhysicsServer::BodyMode p_mode) : CollisionObject( PhysicsServer::get_singleton()->body_create(p_mode), false) { - +void PhysicsBody::set_layer_mask(uint32_t p_mask) { + layer_mask=p_mask; + PhysicsServer::get_singleton()->body_set_layer_mask(get_rid(),p_mask); } -void StaticBody::set_constant_linear_velocity(const Vector3& p_vel) { - - constant_linear_velocity=p_vel; - PhysicsServer::get_singleton()->body_set_state(get_rid(),PhysicsServer::BODY_STATE_LINEAR_VELOCITY,constant_linear_velocity); +uint32_t PhysicsBody::get_layer_mask() const { + return layer_mask; } -void StaticBody::set_constant_angular_velocity(const Vector3& p_vel) { - - constant_angular_velocity=p_vel; - PhysicsServer::get_singleton()->body_set_state(get_rid(),PhysicsServer::BODY_STATE_ANGULAR_VELOCITY,constant_angular_velocity); +void PhysicsBody::_bind_methods() { + ObjectTypeDB::bind_method(_MD("set_layer_mask","mask"),&PhysicsBody::set_layer_mask); + ObjectTypeDB::bind_method(_MD("get_layer_mask"),&PhysicsBody::get_layer_mask); + ADD_PROPERTY(PropertyInfo(Variant::INT,"layers",PROPERTY_HINT_ALL_FLAGS),_SCS("set_layer_mask"),_SCS("get_layer_mask")); } -Vector3 StaticBody::get_constant_linear_velocity() const { - - return constant_linear_velocity; -} -Vector3 StaticBody::get_constant_angular_velocity() const { - - return constant_angular_velocity; -} +PhysicsBody::PhysicsBody(PhysicsServer::BodyMode p_mode) : CollisionObject( PhysicsServer::get_singleton()->body_create(p_mode), false) { -void StaticBody::_state_notify(Object *p_object) { + layer_mask=1; - if (!pre_xform) - return; +} - PhysicsDirectBodyState *p2d = (PhysicsDirectBodyState*)p_object; - setting=true; - Transform new_xform = p2d->get_transform(); - *pre_xform=new_xform; - set_ignore_transform_notification(true); - set_global_transform(new_xform); - set_ignore_transform_notification(false); +void StaticBody::set_friction(real_t p_friction){ - setting=false; + ERR_FAIL_COND(p_friction<0 || p_friction>1); + friction=p_friction; + PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_FRICTION,friction); } +real_t StaticBody::get_friction() const{ -void StaticBody::_update_xform() { - - if (!pre_xform || !pending) - return; - - setting=true; - - - Transform new_xform = get_global_transform(); //obtain the new one + return friction; +} - //set_block_transform_notify(true); - set_ignore_transform_notification(true); - PhysicsServer::get_singleton()->body_set_state(get_rid(),PhysicsServer::BODY_STATE_TRANSFORM,*pre_xform); //then simulate motion! - set_global_transform(*pre_xform); //but restore state to previous one in both visual and physics - set_ignore_transform_notification(false); +void StaticBody::set_bounce(real_t p_bounce){ - PhysicsServer::get_singleton()->body_static_simulate_motion(get_rid(),new_xform); //then simulate motion! + ERR_FAIL_COND(p_bounce<0 || p_bounce>1); - setting=false; - pending=false; + bounce=p_bounce; + PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_BOUNCE,bounce); } +real_t StaticBody::get_bounce() const{ -void StaticBody::_notification(int p_what) { - - switch(p_what) { - - case NOTIFICATION_ENTER_SCENE: { - - if (pre_xform) - *pre_xform = get_global_transform(); - pending=false; - } break; - case NOTIFICATION_TRANSFORM_CHANGED: { + return bounce; +} - if (simulating_motion && !pending && is_inside_scene() && !setting && !get_scene()->is_editor_hint()) { +void StaticBody::set_constant_linear_velocity(const Vector3& p_vel) { - call_deferred(SceneStringNames::get_singleton()->_update_xform); - pending=true; - } + constant_linear_velocity=p_vel; + PhysicsServer::get_singleton()->body_set_state(get_rid(),PhysicsServer::BODY_STATE_LINEAR_VELOCITY,constant_linear_velocity); - } break; - } +} +void StaticBody::set_constant_angular_velocity(const Vector3& p_vel) { + constant_angular_velocity=p_vel; + PhysicsServer::get_singleton()->body_set_state(get_rid(),PhysicsServer::BODY_STATE_ANGULAR_VELOCITY,constant_angular_velocity); } -void StaticBody::set_simulate_motion(bool p_enable) { - - if (p_enable==simulating_motion) - return; - simulating_motion=p_enable; +Vector3 StaticBody::get_constant_linear_velocity() const { - if (p_enable) { - pre_xform = memnew( Transform ); - if (is_inside_scene()) - *pre_xform=get_transform(); -// query = PhysicsServer::get_singleton()->query_create(this,"_state_notify",Variant()); - // PhysicsServer::get_singleton()->query_body_direct_state(query,get_rid()); - PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(),this,"_state_notify"); + return constant_linear_velocity; +} +Vector3 StaticBody::get_constant_angular_velocity() const { - } else { - memdelete( pre_xform ); - pre_xform=NULL; - PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(),NULL,StringName()); - pending=false; - } + return constant_angular_velocity; } -bool StaticBody::is_simulating_motion() const { - return simulating_motion; -} void StaticBody::_bind_methods() { - ObjectTypeDB::bind_method(_MD("set_simulate_motion","enabled"),&StaticBody::set_simulate_motion); - ObjectTypeDB::bind_method(_MD("is_simulating_motion"),&StaticBody::is_simulating_motion); - ObjectTypeDB::bind_method(_MD("_update_xform"),&StaticBody::_update_xform); - ObjectTypeDB::bind_method(_MD("_state_notify"),&StaticBody::_state_notify); ObjectTypeDB::bind_method(_MD("set_constant_linear_velocity","vel"),&StaticBody::set_constant_linear_velocity); ObjectTypeDB::bind_method(_MD("set_constant_angular_velocity","vel"),&StaticBody::set_constant_angular_velocity); ObjectTypeDB::bind_method(_MD("get_constant_linear_velocity"),&StaticBody::get_constant_linear_velocity); ObjectTypeDB::bind_method(_MD("get_constant_angular_velocity"),&StaticBody::get_constant_angular_velocity); - ADD_PROPERTY(PropertyInfo(Variant::BOOL,"simulate_motion"),_SCS("set_simulate_motion"),_SCS("is_simulating_motion")); + ObjectTypeDB::bind_method(_MD("set_friction","friction"),&StaticBody::set_friction); + ObjectTypeDB::bind_method(_MD("get_friction"),&StaticBody::get_friction); + + ObjectTypeDB::bind_method(_MD("set_bounce","bounce"),&StaticBody::set_bounce); + ObjectTypeDB::bind_method(_MD("get_bounce"),&StaticBody::get_bounce); + + ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_friction"),_SCS("get_friction")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_bounce"),_SCS("get_bounce")); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3,"constant_linear_velocity"),_SCS("set_constant_linear_velocity"),_SCS("get_constant_linear_velocity")); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3,"constant_angular_velocity"),_SCS("set_constant_angular_velocity"),_SCS("get_constant_angular_velocity")); } StaticBody::StaticBody() : PhysicsBody(PhysicsServer::BODY_MODE_STATIC) { - simulating_motion=false; - pre_xform=NULL; - setting=false; - pending=false; - //constant_angular_velocity=0; - + bounce=0; + friction=1; } StaticBody::~StaticBody() { - if (pre_xform) - memdelete(pre_xform); - //if (query.is_valid()) - // PhysicsServer::get_singleton()->free(query); + } @@ -768,4 +719,418 @@ RigidBody::~RigidBody() { } +////////////////////////////////////////////////////// +////////////////////////// + + +Variant KinematicBody::_get_collider() const { + + ObjectID oid=get_collider(); + if (oid==0) + return Variant(); + Object *obj = ObjectDB::get_instance(oid); + if (!obj) + return Variant(); + + Reference *ref = obj->cast_to<Reference>(); + if (ref) { + return Ref<Reference>(ref); + } + + return obj; +} + + +bool KinematicBody::_ignores_mode(PhysicsServer::BodyMode p_mode) const { + + switch(p_mode) { + case PhysicsServer::BODY_MODE_STATIC: return !collide_static; + case PhysicsServer::BODY_MODE_KINEMATIC: return !collide_kinematic; + case PhysicsServer::BODY_MODE_RIGID: return !collide_rigid; + case PhysicsServer::BODY_MODE_CHARACTER: return !collide_character; + } + + return true; +} + +Vector3 KinematicBody::move(const Vector3& p_motion) { + + //give me back regular physics engine logic + //this is madness + //and most people using this function will think + //what it does is simpler than using physics + //this took about a week to get right.. + //but is it right? who knows at this point.. + + + colliding=false; + ERR_FAIL_COND_V(!is_inside_scene(),Vector3()); + PhysicsDirectSpaceState *dss = PhysicsServer::get_singleton()->space_get_direct_state(get_world()->get_space()); + ERR_FAIL_COND_V(!dss,Vector3()); + const int max_shapes=32; + Vector3 sr[max_shapes*2]; + int res_shapes; + + Set<RID> exclude; + exclude.insert(get_rid()); + + + //recover first + int recover_attempts=4; + + bool collided=false; + uint32_t mask=0; + if (collide_static) + mask|=PhysicsDirectSpaceState::TYPE_MASK_STATIC_BODY; + if (collide_kinematic) + mask|=PhysicsDirectSpaceState::TYPE_MASK_KINEMATIC_BODY; + if (collide_rigid) + mask|=PhysicsDirectSpaceState::TYPE_MASK_RIGID_BODY; + if (collide_character) + mask|=PhysicsDirectSpaceState::TYPE_MASK_CHARACTER_BODY; + +// print_line("motion: "+p_motion+" margin: "+rtos(margin)); + + //print_line("margin: "+rtos(margin)); + + float m = margin; + //m=0.001; + + do { + + //motion recover + for(int i=0;i<get_shape_count();i++) { + + + if (dss->collide_shape(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i),m,sr,max_shapes,res_shapes,exclude,get_layer_mask(),mask)) { + collided=true; + } + + } + + + + if (!collided) + break; + + //print_line("have to recover"); + Vector3 recover_motion; + bool all_outside=true; + for(int j=0;j<8;j++) { + for(int i=0;i<res_shapes;i++) { + + Vector3 a = sr[i*2+0]; + Vector3 b = sr[i*2+1]; + //print_line(String()+a+" -> "+b); +#if 0 + float d = a.distance_to(b); + + //if (d<margin) + /// continue; + /// + /// + recover_motion+=(b-a)*0.2; +#else + float dist = a.distance_to(b); + if (dist>CMP_EPSILON) { + Vector3 norm = (b-a).normalized(); + if (dist>margin*0.5) + all_outside=false; + float adv = norm.dot(recover_motion); + //print_line(itos(i)+" dist: "+rtos(dist)+" adv: "+rtos(adv)); + recover_motion+=norm*MAX(dist-adv,0)*0.4; + } +#endif + + } + } + + + if (recover_motion==Vector3()) { + collided=false; + break; + } + + //print_line("**** RECOVER: "+recover_motion); + + Transform gt = get_global_transform(); + gt.origin+=recover_motion; + set_global_transform(gt); + + recover_attempts--; + + if (all_outside) + break; + + } while (recover_attempts); + + + //move second + float safe = 1.0; + float unsafe = 1.0; + int best_shape=-1; + + PhysicsDirectSpaceState::ShapeRestInfo rest; + + //print_line("pos: "+get_global_transform().origin); + //print_line("motion: "+p_motion); + + + for(int i=0;i<get_shape_count();i++) { + + + + float lsafe,lunsafe; + PhysicsDirectSpaceState::ShapeRestInfo lrest; + bool valid = dss->cast_motion(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i), p_motion,0, lsafe,lunsafe,exclude,get_layer_mask(),mask,&lrest); + //print_line("shape: "+itos(i)+" travel:"+rtos(ltravel)); + if (!valid) { + safe=0; + unsafe=0; + best_shape=i; //sadly it's the best + //print_line("initial stuck"); + + break; + } + if (lsafe==1.0) { + //print_line("initial free"); + continue; + } + if (lsafe < safe) { + + //print_line("initial at "+rtos(lsafe)); + safe=lsafe; + safe=MAX(0,lsafe-0.01); + unsafe=lunsafe; + best_shape=i; + rest=lrest; + } + } + + + //print_line("best shape: "+itos(best_shape)+" motion "+p_motion); + + if (safe>=1) { + //not collided + colliding=false; + } else { + + colliding=true; + + if (true || (safe==0 && unsafe==0)) { //use it always because it's more precise than GJK + //no advance, use rest info from collision + Transform ugt = get_global_transform(); + ugt.origin+=p_motion*unsafe; + + PhysicsDirectSpaceState::ShapeRestInfo rest_info; + bool c2 = dss->rest_info(get_shape(best_shape)->get_rid(), ugt*get_shape_transform(best_shape), m,&rest,exclude,get_layer_mask(),mask); + if (!c2) { + //should not happen, but floating point precision is so weird.. + colliding=false; + } + + // print_line("Rest Travel: "+rest.normal); + + } + + if (colliding) { + + collision=rest.point; + normal=rest.normal; + collider=rest.collider_id; + collider_vel=rest.linear_velocity; + } + } + + Vector3 motion=p_motion*safe; + //if (colliding) + // motion+=normal*0.001; + Transform gt = get_global_transform(); + gt.origin+=motion; + set_global_transform(gt); + + return p_motion-motion; + +} + +Vector3 KinematicBody::move_to(const Vector3& p_position) { + + return move(p_position-get_global_transform().origin); +} + +bool KinematicBody::can_move_to(const Vector3& p_position, bool p_discrete) { + + ERR_FAIL_COND_V(!is_inside_scene(),false); + PhysicsDirectSpaceState *dss = PhysicsServer::get_singleton()->space_get_direct_state(get_world()->get_space()); + ERR_FAIL_COND_V(!dss,false); + + uint32_t mask=0; + if (collide_static) + mask|=PhysicsDirectSpaceState::TYPE_MASK_STATIC_BODY; + if (collide_kinematic) + mask|=PhysicsDirectSpaceState::TYPE_MASK_KINEMATIC_BODY; + if (collide_rigid) + mask|=PhysicsDirectSpaceState::TYPE_MASK_RIGID_BODY; + if (collide_character) + mask|=PhysicsDirectSpaceState::TYPE_MASK_CHARACTER_BODY; + + Vector3 motion = p_position-get_global_transform().origin; + Transform xform=get_global_transform(); + + if (true || p_discrete) { + + xform.origin+=motion; + motion=Vector3(); + } + + Set<RID> exclude; + exclude.insert(get_rid()); + + //fill exclude list.. + for(int i=0;i<get_shape_count();i++) { + + + bool col = dss->intersect_shape(get_shape(i)->get_rid(), xform * get_shape_transform(i),0,NULL,0,exclude,get_layer_mask(),mask); + if (col) + return false; + } + + return true; +} + +bool KinematicBody::is_colliding() const { + + ERR_FAIL_COND_V(!is_inside_scene(),false); + + return colliding; +} +Vector3 KinematicBody::get_collision_pos() const { + + ERR_FAIL_COND_V(!colliding,Vector3()); + return collision; + +} +Vector3 KinematicBody::get_collision_normal() const { + + ERR_FAIL_COND_V(!colliding,Vector3()); + return normal; + +} + +Vector3 KinematicBody::get_collider_velocity() const { + + return collider_vel; +} + +ObjectID KinematicBody::get_collider() const { + + ERR_FAIL_COND_V(!colliding,0); + return collider; +} + +void KinematicBody::set_collide_with_static_bodies(bool p_enable) { + + collide_static=p_enable; +} +bool KinematicBody::can_collide_with_static_bodies() const { + + return collide_static; +} + +void KinematicBody::set_collide_with_rigid_bodies(bool p_enable) { + + collide_rigid=p_enable; + +} +bool KinematicBody::can_collide_with_rigid_bodies() const { + + + return collide_rigid; +} + +void KinematicBody::set_collide_with_kinematic_bodies(bool p_enable) { + + collide_kinematic=p_enable; + +} +bool KinematicBody::can_collide_with_kinematic_bodies() const { + + return collide_kinematic; +} + +void KinematicBody::set_collide_with_character_bodies(bool p_enable) { + + collide_character=p_enable; +} +bool KinematicBody::can_collide_with_character_bodies() const { + + return collide_character; +} + +void KinematicBody::set_collision_margin(float p_margin) { + + margin=p_margin; +} + +float KinematicBody::get_collision_margin() const{ + + return margin; +} + +void KinematicBody::_bind_methods() { + + + ObjectTypeDB::bind_method(_MD("move","rel_vec"),&KinematicBody::move); + ObjectTypeDB::bind_method(_MD("move_to","position"),&KinematicBody::move_to); + + ObjectTypeDB::bind_method(_MD("can_move_to","position"),&KinematicBody::can_move_to); + + ObjectTypeDB::bind_method(_MD("is_colliding"),&KinematicBody::is_colliding); + + ObjectTypeDB::bind_method(_MD("get_collision_pos"),&KinematicBody::get_collision_pos); + ObjectTypeDB::bind_method(_MD("get_collision_normal"),&KinematicBody::get_collision_normal); + ObjectTypeDB::bind_method(_MD("get_collider_velocity"),&KinematicBody::get_collider_velocity); + ObjectTypeDB::bind_method(_MD("get_collider:Object"),&KinematicBody::_get_collider); + + + ObjectTypeDB::bind_method(_MD("set_collide_with_static_bodies","enable"),&KinematicBody::set_collide_with_static_bodies); + ObjectTypeDB::bind_method(_MD("can_collide_with_static_bodies"),&KinematicBody::can_collide_with_static_bodies); + + ObjectTypeDB::bind_method(_MD("set_collide_with_kinematic_bodies","enable"),&KinematicBody::set_collide_with_kinematic_bodies); + ObjectTypeDB::bind_method(_MD("can_collide_with_kinematic_bodies"),&KinematicBody::can_collide_with_kinematic_bodies); + + ObjectTypeDB::bind_method(_MD("set_collide_with_rigid_bodies","enable"),&KinematicBody::set_collide_with_rigid_bodies); + ObjectTypeDB::bind_method(_MD("can_collide_with_rigid_bodies"),&KinematicBody::can_collide_with_rigid_bodies); + + ObjectTypeDB::bind_method(_MD("set_collide_with_character_bodies","enable"),&KinematicBody::set_collide_with_character_bodies); + ObjectTypeDB::bind_method(_MD("can_collide_with_character_bodies"),&KinematicBody::can_collide_with_character_bodies); + + ObjectTypeDB::bind_method(_MD("set_collision_margin","pixels"),&KinematicBody::set_collision_margin); + ObjectTypeDB::bind_method(_MD("get_collision_margin","pixels"),&KinematicBody::get_collision_margin); + + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collide_with/static"),_SCS("set_collide_with_static_bodies"),_SCS("can_collide_with_static_bodies")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collide_with/kinematic"),_SCS("set_collide_with_kinematic_bodies"),_SCS("can_collide_with_kinematic_bodies")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collide_with/rigid"),_SCS("set_collide_with_rigid_bodies"),_SCS("can_collide_with_rigid_bodies")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collide_with/character"),_SCS("set_collide_with_character_bodies"),_SCS("can_collide_with_character_bodies")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/margin",PROPERTY_HINT_RANGE,"0.001,256,0.001"),_SCS("set_collision_margin"),_SCS("get_collision_margin")); + + +} + +KinematicBody::KinematicBody() : PhysicsBody(PhysicsServer::BODY_MODE_KINEMATIC){ + + collide_static=true; + collide_rigid=true; + collide_kinematic=true; + collide_character=true; + + colliding=false; + collider=0; + margin=0.001; +} +KinematicBody::~KinematicBody() { + + +} + diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index 616288e1f6..0b7a389449 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -38,8 +38,10 @@ class PhysicsBody : public CollisionObject { OBJ_TYPE(PhysicsBody,CollisionObject); + uint32_t layer_mask; protected: + static void _bind_methods(); void _notification(int p_what); PhysicsBody(PhysicsServer::BodyMode p_mode); public: @@ -48,6 +50,10 @@ public: virtual Vector3 get_angular_velocity() const; virtual float get_inverse_mass() const; + void set_layer_mask(uint32_t p_mask); + uint32_t get_layer_mask() const; + + PhysicsBody(); }; @@ -56,25 +62,26 @@ class StaticBody : public PhysicsBody { OBJ_TYPE(StaticBody,PhysicsBody); - Transform *pre_xform; - //RID query; - bool setting; - bool pending; - bool simulating_motion; Vector3 constant_linear_velocity; Vector3 constant_angular_velocity; - void _update_xform(); - void _state_notify(Object *p_object); + + real_t bounce; + real_t friction; + protected: - void _notification(int p_what); static void _bind_methods(); public: - void set_simulate_motion(bool p_enable); - bool is_simulating_motion() const; + + void set_friction(real_t p_friction); + real_t get_friction() const; + + void set_bounce(real_t p_bounce); + real_t get_bounce() const; + void set_constant_linear_velocity(const Vector3& p_vel); void set_constant_angular_velocity(const Vector3& p_vel); @@ -237,4 +244,70 @@ public: VARIANT_ENUM_CAST(RigidBody::Mode); VARIANT_ENUM_CAST(RigidBody::AxisLock); + + + + + +class KinematicBody : public PhysicsBody { + + OBJ_TYPE(KinematicBody,PhysicsBody); + + float margin; + bool collide_static; + bool collide_rigid; + bool collide_kinematic; + bool collide_character; + + bool colliding; + Vector3 collision; + Vector3 normal; + Vector3 collider_vel; + ObjectID collider; + + + Variant _get_collider() const; + + _FORCE_INLINE_ bool _ignores_mode(PhysicsServer::BodyMode) const; +protected: + + static void _bind_methods(); +public: + + enum { + SLIDE_FLAG_FLOOR, + SLIDE_FLAG_WALL, + SLIDE_FLAG_ROOF + }; + + Vector3 move(const Vector3& p_motion); + Vector3 move_to(const Vector3& p_position); + + bool can_move_to(const Vector3& p_position,bool p_discrete=false); + bool is_colliding() const; + Vector3 get_collision_pos() const; + Vector3 get_collision_normal() const; + Vector3 get_collider_velocity() const; + ObjectID get_collider() const; + + void set_collide_with_static_bodies(bool p_enable); + bool can_collide_with_static_bodies() const; + + void set_collide_with_rigid_bodies(bool p_enable); + bool can_collide_with_rigid_bodies() const; + + void set_collide_with_kinematic_bodies(bool p_enable); + bool can_collide_with_kinematic_bodies() const; + + void set_collide_with_character_bodies(bool p_enable); + bool can_collide_with_character_bodies() const; + + void set_collision_margin(float p_margin); + float get_collision_margin() const; + + KinematicBody(); + ~KinematicBody(); + +}; + #endif // PHYSICS_BODY__H diff --git a/scene/3d/physics_joint.cpp b/scene/3d/physics_joint.cpp index 961198c8d4..341b02314d 100644 --- a/scene/3d/physics_joint.cpp +++ b/scene/3d/physics_joint.cpp @@ -27,7 +27,1017 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "physics_joint.h" - + + + +void Joint::_update_joint(bool p_only_free) { + + + if (joint.is_valid()) { + if (ba.is_valid() && bb.is_valid()) + PhysicsServer::get_singleton()->body_remove_collision_exception(ba,bb); + PhysicsServer::get_singleton()->free(joint); + joint=RID(); + ba=RID(); + bb=RID(); + } + + if (p_only_free || !is_inside_scene()) + return; + + 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; + + PhysicsBody *body_a=node_a ? node_a->cast_to<PhysicsBody>() : (PhysicsBody*)NULL; + PhysicsBody *body_b=node_b ? node_b->cast_to<PhysicsBody>() : (PhysicsBody*)NULL; + + if (!body_a && !body_b) + return; + + if (!body_a) { + SWAP(body_a,body_b); + } else if (body_b) { + //add a collision exception between both + PhysicsServer::get_singleton()->body_add_collision_exception(body_a->get_rid(),body_b->get_rid()); + } + + joint = _configure_joint(body_a,body_b); + + if (body_b && joint.is_valid()) { + + ba=body_a->get_rid(); + bb=body_b->get_rid(); + PhysicsServer::get_singleton()->body_add_collision_exception(body_a->get_rid(),body_b->get_rid()); + + } + +} + + +void Joint::set_node_a(const NodePath& p_node_a) { + + + if (a==p_node_a) + return; + + a=p_node_a; + _update_joint(); +} + +NodePath Joint::get_node_a() const{ + + return a; +} + +void Joint::set_node_b(const NodePath& p_node_b){ + + if (b==p_node_b) + return; + b=p_node_b; + _update_joint(); + +} +NodePath Joint::get_node_b() const{ + + + return b; +} + + +void Joint::_notification(int p_what) { + + switch(p_what) { + + case NOTIFICATION_READY: { + _update_joint(); + } break; + case NOTIFICATION_EXIT_SCENE: { + if (joint.is_valid()) { + _update_joint(true); + + + PhysicsServer::get_singleton()->free(joint); + joint=RID(); + } + } break; + + } + +} + + +void Joint::_bind_methods() { + + + ObjectTypeDB::bind_method( _MD("set_node_a","node"), &Joint::set_node_a ); + ObjectTypeDB::bind_method( _MD("get_node_a"), &Joint::get_node_a ); + + ObjectTypeDB::bind_method( _MD("set_node_b","node"), &Joint::set_node_b ); + ObjectTypeDB::bind_method( _MD("get_node_b"), &Joint::get_node_b ); + + + ADD_PROPERTY( PropertyInfo( Variant::NODE_PATH, "nodes/node_a"), _SCS("set_node_a"),_SCS("get_node_a") ); + ADD_PROPERTY( PropertyInfo( Variant::NODE_PATH, "nodes/node_b"), _SCS("set_node_b"),_SCS("get_node_b") ); + +} + + + +Joint::Joint() { + + +} + + +/////////////////////////////////// + +void PinJoint::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_param","param","value"),&PinJoint::set_param); + ObjectTypeDB::bind_method(_MD("get_param","param"),&PinJoint::get_param); + + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/bias",PROPERTY_HINT_RANGE,"0.01,0.99,0.01"),_SCS("set_param"),_SCS("get_param"), PARAM_BIAS ); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/damping",PROPERTY_HINT_RANGE,"0.01,8.0,0.01"),_SCS("set_param"),_SCS("get_param"), PARAM_DAMPING ); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/impulse_clamp",PROPERTY_HINT_RANGE,"0.0,64.0,0.01"),_SCS("set_param"),_SCS("get_param"), PARAM_IMPULSE_CLAMP ); + + BIND_CONSTANT( PARAM_BIAS ); + BIND_CONSTANT( PARAM_DAMPING ); + BIND_CONSTANT( PARAM_IMPULSE_CLAMP ); +} + +void PinJoint::set_param(Param p_param,float p_value){ + + ERR_FAIL_INDEX(p_param,3); + params[p_param]=p_value; + if (get_joint().is_valid()) + PhysicsServer::get_singleton()->pin_joint_set_param(get_joint(),PhysicsServer::PinJointParam(p_param),p_value); +} +float PinJoint::get_param(Param p_param) const{ + + ERR_FAIL_INDEX_V(p_param,3,0); + return params[p_param]; +} + + +RID PinJoint::_configure_joint(PhysicsBody *body_a,PhysicsBody *body_b) { + + + Vector3 pinpos = get_global_transform().origin; + Vector3 local_a = body_a->get_global_transform().affine_inverse().xform(pinpos); + Vector3 local_b; + + if (body_b) + local_b = body_b->get_global_transform().affine_inverse().xform(pinpos); + else + local_b=pinpos; + + RID j = PhysicsServer::get_singleton()->joint_create_pin(body_a->get_rid(),local_a,body_b?body_b->get_rid():RID(),local_b); + for(int i=0;i<3;i++) { + PhysicsServer::get_singleton()->pin_joint_set_param(j,PhysicsServer::PinJointParam(i),params[i]); + } + return j; +} + + +PinJoint::PinJoint() { + + params[PARAM_BIAS]=0.3; + params[PARAM_DAMPING]=1; + params[PARAM_IMPULSE_CLAMP]=0; + +} + + + + +///////////////////////////////////////////////// + + + +/////////////////////////////////// + + +void HingeJoint::_set_upper_limit(float p_limit) { + + set_param(PARAM_LIMIT_UPPER,Math::deg2rad(p_limit)); +} + +float HingeJoint::_get_upper_limit() const { + + return Math::rad2deg(get_param(PARAM_LIMIT_UPPER)); +} + +void HingeJoint::_set_lower_limit(float p_limit) { + + set_param(PARAM_LIMIT_LOWER,Math::deg2rad(p_limit)); + +} + +float HingeJoint::_get_lower_limit() const { + + return Math::rad2deg(get_param(PARAM_LIMIT_LOWER)); + +} + + +void HingeJoint::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_param","param","value"),&HingeJoint::set_param); + ObjectTypeDB::bind_method(_MD("get_param","param"),&HingeJoint::get_param); + + ObjectTypeDB::bind_method(_MD("set_flag","flag","enabled"),&HingeJoint::set_flag); + ObjectTypeDB::bind_method(_MD("get_flag","flag"),&HingeJoint::get_flag); + + ObjectTypeDB::bind_method(_MD("_set_upper_limit","upper_limit"),&HingeJoint::_set_upper_limit); + ObjectTypeDB::bind_method(_MD("_get_upper_limit"),&HingeJoint::_get_upper_limit); + + ObjectTypeDB::bind_method(_MD("_set_lower_limit","lower_limit"),&HingeJoint::_set_lower_limit); + ObjectTypeDB::bind_method(_MD("_get_lower_limit"),&HingeJoint::_get_lower_limit); + + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/bias",PROPERTY_HINT_RANGE,"0.01,0.99,0.01"),_SCS("set_param"),_SCS("get_param"), PARAM_BIAS ); + + ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"angular_limit/enable"),_SCS("set_flag"),_SCS("get_flag"), FLAG_USE_LIMIT ); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_limit/upper",PROPERTY_HINT_RANGE,"-180,180,0.1"),_SCS("_set_upper_limit"),_SCS("_get_upper_limit") ); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_limit/lower",PROPERTY_HINT_RANGE,"-180,180,0.1"),_SCS("_set_lower_limit"),_SCS("_get_lower_limit") ); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_limit/bias",PROPERTY_HINT_RANGE,"0.01,0.99,0.01"),_SCS("set_param"),_SCS("get_param"), PARAM_LIMIT_BIAS ); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_limit/softness",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param"),_SCS("get_param"), PARAM_LIMIT_SOFTNESS ); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_limit/relaxation",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param"),_SCS("get_param"), PARAM_LIMIT_RELAXATION ); + + ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"motor/enable"),_SCS("set_flag"),_SCS("get_flag"), FLAG_ENABLE_MOTOR ); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"motor/target_velocity",PROPERTY_HINT_RANGE,"0.01,4096,0.01"),_SCS("set_param"),_SCS("get_param"), PARAM_MOTOR_TARGET_VELOCITY ); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"motor/max_impulse",PROPERTY_HINT_RANGE,"0.01,1024,0.01"),_SCS("set_param"),_SCS("get_param"), PARAM_MOTOR_MAX_IMPULSE); + + + BIND_CONSTANT( PARAM_BIAS ); + BIND_CONSTANT( PARAM_LIMIT_UPPER ); + BIND_CONSTANT( PARAM_LIMIT_LOWER ); + BIND_CONSTANT( PARAM_LIMIT_BIAS ); + BIND_CONSTANT( PARAM_LIMIT_SOFTNESS ); + BIND_CONSTANT( PARAM_LIMIT_RELAXATION ); + BIND_CONSTANT( PARAM_MOTOR_TARGET_VELOCITY ); + BIND_CONSTANT( PARAM_MOTOR_MAX_IMPULSE ); + BIND_CONSTANT( PARAM_MAX ); + + BIND_CONSTANT( FLAG_USE_LIMIT ); + BIND_CONSTANT( FLAG_ENABLE_MOTOR ); + BIND_CONSTANT( FLAG_MAX ); + +} + +void HingeJoint::set_param(Param p_param,float p_value){ + + ERR_FAIL_INDEX(p_param,PARAM_MAX); + params[p_param]=p_value; + if (get_joint().is_valid()) + PhysicsServer::get_singleton()->hinge_joint_set_param(get_joint(),PhysicsServer::HingeJointParam(p_param),p_value); + + update_gizmo(); + +} +float HingeJoint::get_param(Param p_param) const{ + + ERR_FAIL_INDEX_V(p_param,PARAM_MAX,0); + return params[p_param]; +} + + +void HingeJoint::set_flag(Flag p_flag,bool p_value){ + + ERR_FAIL_INDEX(p_flag,FLAG_MAX); + flags[p_flag]=p_value; + if (get_joint().is_valid()) + PhysicsServer::get_singleton()->hinge_joint_set_flag(get_joint(),PhysicsServer::HingeJointFlag(p_flag),p_value); + + update_gizmo(); +} +bool HingeJoint::get_flag(Flag p_flag) const{ + + ERR_FAIL_INDEX_V(p_flag,FLAG_MAX,false); + return flags[p_flag]; +} + +RID HingeJoint::_configure_joint(PhysicsBody *body_a,PhysicsBody *body_b) { + + + Transform gt = get_global_transform(); + Vector3 hingepos = gt.origin; + Vector3 hingedir = gt.basis.get_axis(2); + + Transform ainv = body_a->get_global_transform().affine_inverse(); + + Transform local_a = ainv * gt; + local_a.orthonormalize(); + Transform local_b = gt; + + if (body_b) { + Transform binv = body_b->get_global_transform().affine_inverse(); + local_b = binv * gt; + } + + local_b.orthonormalize(); + + RID j = PhysicsServer::get_singleton()->joint_create_hinge(body_a->get_rid(),local_a,body_b?body_b->get_rid():RID(),local_b); + for(int i=0;i<PARAM_MAX;i++) { + PhysicsServer::get_singleton()->hinge_joint_set_param(j,PhysicsServer::HingeJointParam(i),params[i]); + } + for(int i=0;i<FLAG_MAX;i++) { + set_flag(Flag(i),flags[i]); + PhysicsServer::get_singleton()->hinge_joint_set_flag(j,PhysicsServer::HingeJointFlag(i),flags[i]); + } + return j; +} + + +HingeJoint::HingeJoint() { + + params[PARAM_BIAS]=0.3; + params[PARAM_LIMIT_UPPER]=Math_PI*0.5; + params[PARAM_LIMIT_LOWER]=-Math_PI*0.5; + params[PARAM_LIMIT_BIAS]=0.3; + params[PARAM_LIMIT_SOFTNESS]=0.9; + params[PARAM_LIMIT_RELAXATION]=1.0; + params[PARAM_MOTOR_TARGET_VELOCITY]=1; + params[PARAM_MOTOR_MAX_IMPULSE]=1; + + + flags[FLAG_USE_LIMIT]=false; + flags[FLAG_ENABLE_MOTOR]=false; + +} + + + + +///////////////////////////////////////////////// + + +////////////////////////////////// + + + +void SliderJoint::_set_upper_limit_angular(float p_limit_angular) { + + set_param(PARAM_ANGULAR_LIMIT_UPPER,Math::deg2rad(p_limit_angular)); +} + +float SliderJoint::_get_upper_limit_angular() const { + + return Math::rad2deg(get_param(PARAM_ANGULAR_LIMIT_UPPER)); +} + +void SliderJoint::_set_lower_limit_angular(float p_limit_angular) { + + set_param(PARAM_ANGULAR_LIMIT_LOWER,Math::deg2rad(p_limit_angular)); + +} + +float SliderJoint::_get_lower_limit_angular() const { + + return Math::rad2deg(get_param(PARAM_ANGULAR_LIMIT_LOWER)); + +} + + +void SliderJoint::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_param","param","value"),&SliderJoint::set_param); + ObjectTypeDB::bind_method(_MD("get_param","param"),&SliderJoint::get_param); + + + ObjectTypeDB::bind_method(_MD("_set_upper_limit_angular","upper_limit_angular"),&SliderJoint::_set_upper_limit_angular); + ObjectTypeDB::bind_method(_MD("_get_upper_limit_angular"),&SliderJoint::_get_upper_limit_angular); + + ObjectTypeDB::bind_method(_MD("_set_lower_limit_angular","lower_limit_angular"),&SliderJoint::_set_lower_limit_angular); + ObjectTypeDB::bind_method(_MD("_get_lower_limit_angular"),&SliderJoint::_get_lower_limit_angular); + + + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_limit/upper_distance",PROPERTY_HINT_RANGE,"-1024,1024,0.01"),_SCS("set_param"),_SCS("get_param"), PARAM_LINEAR_LIMIT_UPPER); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_limit/lower_distance",PROPERTY_HINT_RANGE,"-1024,1024,0.01"),_SCS("set_param"),_SCS("get_param"), PARAM_LINEAR_LIMIT_LOWER); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_limit/softness",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_LINEAR_LIMIT_SOFTNESS); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_limit/restitution",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_LINEAR_LIMIT_RESTITUTION); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_limit/damping",PROPERTY_HINT_RANGE,"0,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_LINEAR_LIMIT_DAMPING); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_motion/softness",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_LINEAR_MOTION_SOFTNESS); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_motion/restitution",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_LINEAR_MOTION_RESTITUTION); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_motion/damping",PROPERTY_HINT_RANGE,"0,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_LINEAR_MOTION_DAMPING); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_ortho/softness",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_LINEAR_ORTHOGONAL_SOFTNESS); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_ortho/restitution",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_LINEAR_ORTHOGONAL_RESTITUTION); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_ortho/damping",PROPERTY_HINT_RANGE,"0,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_LINEAR_ORTHOGONAL_DAMPING); + + ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_limit/upper_angle",PROPERTY_HINT_RANGE,"-180,180,0.1"),_SCS("_set_upper_limit_angular"),_SCS("_get_upper_limit_angular") ); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_limit/lower_angle",PROPERTY_HINT_RANGE,"-180,180,0.1"),_SCS("_set_lower_limit_angular"),_SCS("_get_lower_limit_angular") ); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_limit/softness",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_ANGULAR_LIMIT_SOFTNESS); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_limit/restitution",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_ANGULAR_LIMIT_RESTITUTION); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_limit/damping",PROPERTY_HINT_RANGE,"0,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_ANGULAR_LIMIT_DAMPING); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_motion/softness",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_ANGULAR_MOTION_SOFTNESS); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_motion/restitution",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_ANGULAR_MOTION_RESTITUTION); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_motion/damping",PROPERTY_HINT_RANGE,"0,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_ANGULAR_MOTION_DAMPING); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_ortho/softness",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_ANGULAR_ORTHOGONAL_SOFTNESS); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_ortho/restitution",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_ANGULAR_ORTHOGONAL_RESTITUTION); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_ortho/damping",PROPERTY_HINT_RANGE,"0,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_ANGULAR_ORTHOGONAL_DAMPING); + + + BIND_CONSTANT( PARAM_LINEAR_LIMIT_UPPER); + BIND_CONSTANT( PARAM_LINEAR_LIMIT_LOWER); + BIND_CONSTANT( PARAM_LINEAR_LIMIT_SOFTNESS); + BIND_CONSTANT( PARAM_LINEAR_LIMIT_RESTITUTION); + BIND_CONSTANT( PARAM_LINEAR_LIMIT_DAMPING); + BIND_CONSTANT( PARAM_LINEAR_MOTION_SOFTNESS); + BIND_CONSTANT( PARAM_LINEAR_MOTION_RESTITUTION); + BIND_CONSTANT( PARAM_LINEAR_MOTION_DAMPING); + BIND_CONSTANT( PARAM_LINEAR_ORTHOGONAL_SOFTNESS); + BIND_CONSTANT( PARAM_LINEAR_ORTHOGONAL_RESTITUTION); + BIND_CONSTANT( PARAM_LINEAR_ORTHOGONAL_DAMPING); + + BIND_CONSTANT( PARAM_ANGULAR_LIMIT_UPPER); + BIND_CONSTANT( PARAM_ANGULAR_LIMIT_LOWER); + BIND_CONSTANT( PARAM_ANGULAR_LIMIT_SOFTNESS); + BIND_CONSTANT( PARAM_ANGULAR_LIMIT_RESTITUTION); + BIND_CONSTANT( PARAM_ANGULAR_LIMIT_DAMPING); + BIND_CONSTANT( PARAM_ANGULAR_MOTION_SOFTNESS); + BIND_CONSTANT( PARAM_ANGULAR_MOTION_RESTITUTION); + BIND_CONSTANT( PARAM_ANGULAR_MOTION_DAMPING); + BIND_CONSTANT( PARAM_ANGULAR_ORTHOGONAL_SOFTNESS); + BIND_CONSTANT( PARAM_ANGULAR_ORTHOGONAL_RESTITUTION); + BIND_CONSTANT( PARAM_ANGULAR_ORTHOGONAL_DAMPING); + + BIND_CONSTANT( PARAM_MAX); +} + +void SliderJoint::set_param(Param p_param,float p_value){ + + ERR_FAIL_INDEX(p_param,PARAM_MAX); + params[p_param]=p_value; + if (get_joint().is_valid()) + PhysicsServer::get_singleton()->slider_joint_set_param(get_joint(),PhysicsServer::SliderJointParam(p_param),p_value); + update_gizmo(); + +} +float SliderJoint::get_param(Param p_param) const{ + + ERR_FAIL_INDEX_V(p_param,PARAM_MAX,0); + return params[p_param]; +} + + +RID SliderJoint::_configure_joint(PhysicsBody *body_a,PhysicsBody *body_b) { + + + Transform gt = get_global_transform(); + Vector3 sliderpos = gt.origin; + Vector3 sliderdir = gt.basis.get_axis(2); + + Transform ainv = body_a->get_global_transform().affine_inverse(); + + Transform local_a = ainv * gt; + local_a.orthonormalize(); + Transform local_b = gt; + + if (body_b) { + Transform binv = body_b->get_global_transform().affine_inverse(); + local_b = binv * gt; + } + + local_b.orthonormalize(); + + RID j = PhysicsServer::get_singleton()->joint_create_slider(body_a->get_rid(),local_a,body_b?body_b->get_rid():RID(),local_b); + for(int i=0;i<PARAM_MAX;i++) { + PhysicsServer::get_singleton()->slider_joint_set_param(j,PhysicsServer::SliderJointParam(i),params[i]); + } + + return j; +} + + +SliderJoint::SliderJoint() { + + + + params[ PARAM_LINEAR_LIMIT_UPPER ]=1.0; + params[ PARAM_LINEAR_LIMIT_LOWER ]=-1.0; + params[ PARAM_LINEAR_LIMIT_SOFTNESS ]=1.0; + params[ PARAM_LINEAR_LIMIT_RESTITUTION]=0.7; + params[ PARAM_LINEAR_LIMIT_DAMPING]=1.0; + params[ PARAM_LINEAR_MOTION_SOFTNESS ]=1.0; + params[ PARAM_LINEAR_MOTION_RESTITUTION]=0.7; + params[ PARAM_LINEAR_MOTION_DAMPING]=0;//1.0; + params[ PARAM_LINEAR_ORTHOGONAL_SOFTNESS ]=1.0; + params[ PARAM_LINEAR_ORTHOGONAL_RESTITUTION]=0.7; + params[ PARAM_LINEAR_ORTHOGONAL_DAMPING]=1.0; + + params[ PARAM_ANGULAR_LIMIT_UPPER ]=0 ; + params[ PARAM_ANGULAR_LIMIT_LOWER ]=0 ; + params[ PARAM_ANGULAR_LIMIT_SOFTNESS ]=1.0; + params[ PARAM_ANGULAR_LIMIT_RESTITUTION]=0.7; + params[ PARAM_ANGULAR_LIMIT_DAMPING]=0;//1.0; + params[ PARAM_ANGULAR_MOTION_SOFTNESS ]=1.0; + params[ PARAM_ANGULAR_MOTION_RESTITUTION]=0.7; + params[ PARAM_ANGULAR_MOTION_DAMPING]=1.0; + params[ PARAM_ANGULAR_ORTHOGONAL_SOFTNESS ]=1.0; + params[ PARAM_ANGULAR_ORTHOGONAL_RESTITUTION]=0.7; + params[ PARAM_ANGULAR_ORTHOGONAL_DAMPING]=1.0; +} + + + +////////////////////////////////// + + + +void ConeTwistJoint::_set_swing_span(float p_limit_angular) { + + set_param(PARAM_SWING_SPAN,Math::deg2rad(p_limit_angular)); +} + +float ConeTwistJoint::_get_swing_span() const { + + return Math::rad2deg(get_param(PARAM_SWING_SPAN)); +} + +void ConeTwistJoint::_set_twist_span(float p_limit_angular) { + + set_param(PARAM_TWIST_SPAN,Math::deg2rad(p_limit_angular)); + +} + +float ConeTwistJoint::_get_twist_span() const { + + return Math::rad2deg(get_param(PARAM_TWIST_SPAN)); + +} + + +void ConeTwistJoint::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_param","param","value"),&ConeTwistJoint::set_param); + ObjectTypeDB::bind_method(_MD("get_param","param"),&ConeTwistJoint::get_param); + + + ObjectTypeDB::bind_method(_MD("_set_swing_span","swing_span"),&ConeTwistJoint::_set_swing_span); + ObjectTypeDB::bind_method(_MD("_get_swing_span"),&ConeTwistJoint::_get_swing_span); + + ObjectTypeDB::bind_method(_MD("_set_twist_span","twist_span"),&ConeTwistJoint::_set_twist_span); + ObjectTypeDB::bind_method(_MD("_get_twist_span"),&ConeTwistJoint::_get_twist_span); + + + ADD_PROPERTY( PropertyInfo(Variant::REAL,"swing_span",PROPERTY_HINT_RANGE,"-180,180,0.1"),_SCS("_set_swing_span"),_SCS("_get_swing_span") ); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"twist_span",PROPERTY_HINT_RANGE,"-40000,40000,0.1"),_SCS("_set_twist_span"),_SCS("_get_twist_span") ); + + + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"bias",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_BIAS ); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"softness",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_SOFTNESS); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"relaxation",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_RELAXATION); + + BIND_CONSTANT( PARAM_SWING_SPAN ); + BIND_CONSTANT( PARAM_TWIST_SPAN ); + BIND_CONSTANT( PARAM_BIAS ); + BIND_CONSTANT( PARAM_SOFTNESS ); + BIND_CONSTANT( PARAM_RELAXATION ); + BIND_CONSTANT( PARAM_MAX ); +} + +void ConeTwistJoint::set_param(Param p_param,float p_value){ + + ERR_FAIL_INDEX(p_param,PARAM_MAX); + params[p_param]=p_value; + if (get_joint().is_valid()) + PhysicsServer::get_singleton()->cone_twist_joint_set_param(get_joint(),PhysicsServer::ConeTwistJointParam(p_param),p_value); + + update_gizmo(); +} +float ConeTwistJoint::get_param(Param p_param) const{ + + ERR_FAIL_INDEX_V(p_param,PARAM_MAX,0); + return params[p_param]; +} + + +RID ConeTwistJoint::_configure_joint(PhysicsBody *body_a,PhysicsBody *body_b) { + + + Transform gt = get_global_transform(); + //Vector3 cone_twistpos = gt.origin; + //Vector3 cone_twistdir = gt.basis.get_axis(2); + + Transform ainv = body_a->get_global_transform().affine_inverse(); + + Transform local_a = ainv * gt; + local_a.orthonormalize(); + Transform local_b = gt; + + if (body_b) { + Transform binv = body_b->get_global_transform().affine_inverse(); + local_b = binv * gt; + } + + local_b.orthonormalize(); + + RID j = PhysicsServer::get_singleton()->joint_create_cone_twist(body_a->get_rid(),local_a,body_b?body_b->get_rid():RID(),local_b); + for(int i=0;i<PARAM_MAX;i++) { + PhysicsServer::get_singleton()->cone_twist_joint_set_param(j,PhysicsServer::ConeTwistJointParam(i),params[i]); + } + + return j; +} + + +ConeTwistJoint::ConeTwistJoint() { + + + params[ PARAM_SWING_SPAN ]=Math_PI*0.25; + params[ PARAM_TWIST_SPAN ]=Math_PI; + params[ PARAM_BIAS ]=0.3; + params[ PARAM_SOFTNESS ]=0.8; + params[ PARAM_RELAXATION ]=1.0; + +} + +///////////////////////////////////////////////////////////////////// + + +void Generic6DOFJoint::_set_angular_hi_limit_x(float p_limit_angular) { + + set_param_x(PARAM_ANGULAR_UPPER_LIMIT,Math::deg2rad(p_limit_angular)); +} + +float Generic6DOFJoint::_get_angular_hi_limit_x() const{ + + return Math::rad2deg(get_param_x(PARAM_ANGULAR_UPPER_LIMIT)); + +} + +void Generic6DOFJoint::_set_angular_lo_limit_x(float p_limit_angular) { + + set_param_x(PARAM_ANGULAR_LOWER_LIMIT,Math::deg2rad(p_limit_angular)); +} + +float Generic6DOFJoint::_get_angular_lo_limit_x() const{ + + return Math::rad2deg(get_param_x(PARAM_ANGULAR_LOWER_LIMIT)); + +} + + +void Generic6DOFJoint::_set_angular_hi_limit_y(float p_limit_angular) { + + set_param_y(PARAM_ANGULAR_UPPER_LIMIT,Math::deg2rad(p_limit_angular)); +} + +float Generic6DOFJoint::_get_angular_hi_limit_y() const{ + + return Math::rad2deg(get_param_y(PARAM_ANGULAR_UPPER_LIMIT)); + +} + +void Generic6DOFJoint::_set_angular_lo_limit_y(float p_limit_angular) { + + set_param_y(PARAM_ANGULAR_LOWER_LIMIT,Math::deg2rad(p_limit_angular)); +} + +float Generic6DOFJoint::_get_angular_lo_limit_y() const{ + + return Math::rad2deg(get_param_y(PARAM_ANGULAR_LOWER_LIMIT)); + +} + + +void Generic6DOFJoint::_set_angular_hi_limit_z(float p_limit_angular) { + + set_param_z(PARAM_ANGULAR_UPPER_LIMIT,Math::deg2rad(p_limit_angular)); +} + +float Generic6DOFJoint::_get_angular_hi_limit_z() const{ + + return Math::rad2deg(get_param_z(PARAM_ANGULAR_UPPER_LIMIT)); + +} + +void Generic6DOFJoint::_set_angular_lo_limit_z(float p_limit_angular) { + + set_param_z(PARAM_ANGULAR_LOWER_LIMIT,Math::deg2rad(p_limit_angular)); +} + +float Generic6DOFJoint::_get_angular_lo_limit_z() const{ + + return Math::rad2deg(get_param_z(PARAM_ANGULAR_LOWER_LIMIT)); + +} + + + +void Generic6DOFJoint::_bind_methods(){ + + + ObjectTypeDB::bind_method(_MD("_set_angular_hi_limit_x","angle"),&Generic6DOFJoint::_set_angular_hi_limit_x); + ObjectTypeDB::bind_method(_MD("_get_angular_hi_limit_x"),&Generic6DOFJoint::_get_angular_hi_limit_x); + + ObjectTypeDB::bind_method(_MD("_set_angular_lo_limit_x","angle"),&Generic6DOFJoint::_set_angular_lo_limit_x); + ObjectTypeDB::bind_method(_MD("_get_angular_lo_limit_x"),&Generic6DOFJoint::_get_angular_lo_limit_x); + + ObjectTypeDB::bind_method(_MD("_set_angular_hi_limit_y","angle"),&Generic6DOFJoint::_set_angular_hi_limit_y); + ObjectTypeDB::bind_method(_MD("_get_angular_hi_limit_y"),&Generic6DOFJoint::_get_angular_hi_limit_y); + + ObjectTypeDB::bind_method(_MD("_set_angular_lo_limit_y","angle"),&Generic6DOFJoint::_set_angular_lo_limit_y); + ObjectTypeDB::bind_method(_MD("_get_angular_lo_limit_y"),&Generic6DOFJoint::_get_angular_lo_limit_y); + + ObjectTypeDB::bind_method(_MD("_set_angular_hi_limit_z","angle"),&Generic6DOFJoint::_set_angular_hi_limit_z); + ObjectTypeDB::bind_method(_MD("_get_angular_hi_limit_z"),&Generic6DOFJoint::_get_angular_hi_limit_z); + + ObjectTypeDB::bind_method(_MD("_set_angular_lo_limit_z","angle"),&Generic6DOFJoint::_set_angular_lo_limit_z); + ObjectTypeDB::bind_method(_MD("_get_angular_lo_limit_z"),&Generic6DOFJoint::_get_angular_lo_limit_z); + + ObjectTypeDB::bind_method(_MD("set_param_x","param","value"),&Generic6DOFJoint::set_param_x); + ObjectTypeDB::bind_method(_MD("get_param_x","param"),&Generic6DOFJoint::get_param_x); + + ObjectTypeDB::bind_method(_MD("set_param_y","param","value"),&Generic6DOFJoint::set_param_y); + ObjectTypeDB::bind_method(_MD("get_param_y","param"),&Generic6DOFJoint::get_param_y); + + ObjectTypeDB::bind_method(_MD("set_param_z","param","value"),&Generic6DOFJoint::set_param_z); + ObjectTypeDB::bind_method(_MD("get_param_z","param"),&Generic6DOFJoint::get_param_z); + + ObjectTypeDB::bind_method(_MD("set_flag_x","flag","value"),&Generic6DOFJoint::set_flag_x); + ObjectTypeDB::bind_method(_MD("get_flag_x","flag"),&Generic6DOFJoint::get_flag_x); + + ObjectTypeDB::bind_method(_MD("set_flag_y","flag","value"),&Generic6DOFJoint::set_flag_y); + ObjectTypeDB::bind_method(_MD("get_flag_y","flag"),&Generic6DOFJoint::get_flag_y); + + ObjectTypeDB::bind_method(_MD("set_flag_z","flag","value"),&Generic6DOFJoint::set_flag_z); + ObjectTypeDB::bind_method(_MD("get_flag_z","flag"),&Generic6DOFJoint::get_flag_z); + + + ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"linear_limit_x/enabled"),_SCS("set_flag_x"),_SCS("get_flag_x"),FLAG_ENABLE_LINEAR_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_x/upper_distance"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_LINEAR_UPPER_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_x/lower_distance"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_LINEAR_LOWER_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_x/softness",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_LINEAR_LIMIT_SOFTNESS); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_x/restitution",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_LINEAR_RESTITUTION); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_x/damping",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_LINEAR_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"angular_limit_x/enabled"),_SCS("set_flag_x"),_SCS("get_flag_x"),FLAG_ENABLE_ANGULAR_LIMIT); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"angular_limit_x/upper_angle",PROPERTY_HINT_RANGE,"-180,180,0.01"),_SCS("_set_angular_hi_limit_x"),_SCS("_get_angular_hi_limit_x")); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"angular_limit_x/lower_angle",PROPERTY_HINT_RANGE,"-180,180,0.01"),_SCS("_set_angular_lo_limit_x"),_SCS("_get_angular_lo_limit_x")); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_x/softness",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_ANGULAR_LIMIT_SOFTNESS); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_x/restitution",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_ANGULAR_RESTITUTION); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_x/damping",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_ANGULAR_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_x/force_limit"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_ANGULAR_FORCE_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_x/erp"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_ANGULAR_ERP); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"angular_motor_x/enabled"),_SCS("set_flag_x"),_SCS("get_flag_x"),FLAG_ENABLE_MOTOR); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_motor_x/target_velocity"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_ANGULAR_MOTOR_TARGET_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_motor_x/force_limit"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_ANGULAR_MOTOR_FORCE_LIMIT); + + ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"linear_limit_y/enabled"),_SCS("set_flag_y"),_SCS("get_flag_y"),FLAG_ENABLE_LINEAR_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_y/upper_distance"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_LINEAR_UPPER_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_y/lower_distance"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_LINEAR_LOWER_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_y/softness",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_LINEAR_LIMIT_SOFTNESS); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_y/restitution",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_LINEAR_RESTITUTION); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_y/damping",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_LINEAR_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"angular_limit_y/enabled"),_SCS("set_flag_y"),_SCS("get_flag_y"),FLAG_ENABLE_ANGULAR_LIMIT); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"angular_limit_y/upper_angle",PROPERTY_HINT_RANGE,"-180,180,0.01"),_SCS("_set_angular_hi_limit_y"),_SCS("_get_angular_hi_limit_y")); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"angular_limit_y/lower_angle",PROPERTY_HINT_RANGE,"-180,180,0.01"),_SCS("_set_angular_lo_limit_y"),_SCS("_get_angular_lo_limit_y")); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_y/softness",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_ANGULAR_LIMIT_SOFTNESS); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_y/restitution",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_ANGULAR_RESTITUTION); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_y/damping",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_ANGULAR_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_y/force_limit"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_ANGULAR_FORCE_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_y/erp"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_ANGULAR_ERP); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"angular_motor_y/enabled"),_SCS("set_flag_y"),_SCS("get_flag_y"),FLAG_ENABLE_MOTOR); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_motor_y/target_velocity"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_ANGULAR_MOTOR_TARGET_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_motor_y/force_limit"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_ANGULAR_MOTOR_FORCE_LIMIT); + + ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"linear_limit_z/enabled"),_SCS("set_flag_z"),_SCS("get_flag_z"),FLAG_ENABLE_LINEAR_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_z/upper_distance"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_LINEAR_UPPER_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_z/lower_distance"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_LINEAR_LOWER_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_z/softness",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_LINEAR_LIMIT_SOFTNESS); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_z/restitution",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_LINEAR_RESTITUTION); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_z/damping",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_LINEAR_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"angular_limit_z/enabled"),_SCS("set_flag_z"),_SCS("get_flag_z"),FLAG_ENABLE_ANGULAR_LIMIT); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"angular_limit_z/upper_angle",PROPERTY_HINT_RANGE,"-180,180,0.01"),_SCS("_set_angular_hi_limit_z"),_SCS("_get_angular_hi_limit_z")); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"angular_limit_z/lower_angle",PROPERTY_HINT_RANGE,"-180,180,0.01"),_SCS("_set_angular_lo_limit_z"),_SCS("_get_angular_lo_limit_z")); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_z/softness",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_ANGULAR_LIMIT_SOFTNESS); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_z/restitution",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_ANGULAR_RESTITUTION); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_z/damping",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_ANGULAR_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_z/force_limit"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_ANGULAR_FORCE_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_z/erp"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_ANGULAR_ERP); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"angular_motor_z/enabled"),_SCS("set_flag_z"),_SCS("get_flag_z"),FLAG_ENABLE_MOTOR); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_motor_z/target_velocity"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_ANGULAR_MOTOR_TARGET_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_motor_z/force_limit"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_ANGULAR_MOTOR_FORCE_LIMIT); + + + BIND_CONSTANT( PARAM_LINEAR_LOWER_LIMIT); + BIND_CONSTANT( PARAM_LINEAR_UPPER_LIMIT); + BIND_CONSTANT( PARAM_LINEAR_LIMIT_SOFTNESS); + BIND_CONSTANT( PARAM_LINEAR_RESTITUTION); + BIND_CONSTANT( PARAM_LINEAR_DAMPING); + BIND_CONSTANT( PARAM_ANGULAR_LOWER_LIMIT); + BIND_CONSTANT( PARAM_ANGULAR_UPPER_LIMIT); + BIND_CONSTANT( PARAM_ANGULAR_LIMIT_SOFTNESS); + BIND_CONSTANT( PARAM_ANGULAR_DAMPING); + BIND_CONSTANT( PARAM_ANGULAR_RESTITUTION); + BIND_CONSTANT( PARAM_ANGULAR_FORCE_LIMIT); + BIND_CONSTANT( PARAM_ANGULAR_ERP); + BIND_CONSTANT( PARAM_ANGULAR_MOTOR_TARGET_VELOCITY); + BIND_CONSTANT( PARAM_ANGULAR_MOTOR_FORCE_LIMIT); + BIND_CONSTANT( PARAM_MAX); + + BIND_CONSTANT( FLAG_ENABLE_LINEAR_LIMIT); + BIND_CONSTANT( FLAG_ENABLE_ANGULAR_LIMIT); + BIND_CONSTANT( FLAG_ENABLE_MOTOR); + BIND_CONSTANT( FLAG_MAX ); +} + + +void Generic6DOFJoint::set_param_x(Param p_param,float p_value){ + + ERR_FAIL_INDEX(p_param,PARAM_MAX); + params_x[p_param]=p_value; + if (get_joint().is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(get_joint(),Vector3::AXIS_X,PhysicsServer::G6DOFJointAxisParam(p_param),p_value); + + update_gizmo(); +} +float Generic6DOFJoint::get_param_x(Param p_param) const{ + + ERR_FAIL_INDEX_V(p_param,PARAM_MAX,0); + return params_x[p_param]; +} + +void Generic6DOFJoint::set_param_y(Param p_param,float p_value){ + + ERR_FAIL_INDEX(p_param,PARAM_MAX); + params_y[p_param]=p_value; + if (get_joint().is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(get_joint(),Vector3::AXIS_Y,PhysicsServer::G6DOFJointAxisParam(p_param),p_value); + update_gizmo(); + +} +float Generic6DOFJoint::get_param_y(Param p_param) const{ + + ERR_FAIL_INDEX_V(p_param,PARAM_MAX,0); + return params_y[p_param]; +} + + +void Generic6DOFJoint::set_param_z(Param p_param,float p_value){ + + ERR_FAIL_INDEX(p_param,PARAM_MAX); + params_z[p_param]=p_value; + if (get_joint().is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(get_joint(),Vector3::AXIS_Z,PhysicsServer::G6DOFJointAxisParam(p_param),p_value); + update_gizmo(); +} +float Generic6DOFJoint::get_param_z(Param p_param) const{ + + ERR_FAIL_INDEX_V(p_param,PARAM_MAX,0); + return params_z[p_param]; +} + + +void Generic6DOFJoint::set_flag_x(Flag p_flag,bool p_enabled){ + + ERR_FAIL_INDEX(p_flag,FLAG_MAX); + flags_x[p_flag]=p_enabled; + if (get_joint().is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(get_joint(),Vector3::AXIS_X,PhysicsServer::G6DOFJointAxisFlag(p_flag),p_enabled); + update_gizmo(); + +} +bool Generic6DOFJoint::get_flag_x(Flag p_flag) const{ + + ERR_FAIL_INDEX_V(p_flag,FLAG_MAX,false); + return flags_x[p_flag]; + +} + +void Generic6DOFJoint::set_flag_y(Flag p_flag,bool p_enabled){ + + ERR_FAIL_INDEX(p_flag,FLAG_MAX); + flags_y[p_flag]=p_enabled; + if (get_joint().is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(get_joint(),Vector3::AXIS_Y,PhysicsServer::G6DOFJointAxisFlag(p_flag),p_enabled); + update_gizmo(); +} +bool Generic6DOFJoint::get_flag_y(Flag p_flag) const{ + + ERR_FAIL_INDEX_V(p_flag,FLAG_MAX,false); + return flags_y[p_flag]; + +} + +void Generic6DOFJoint::set_flag_z(Flag p_flag,bool p_enabled){ + + ERR_FAIL_INDEX(p_flag,FLAG_MAX); + flags_z[p_flag]=p_enabled; + if (get_joint().is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(get_joint(),Vector3::AXIS_Z,PhysicsServer::G6DOFJointAxisFlag(p_flag),p_enabled); + update_gizmo(); +} +bool Generic6DOFJoint::get_flag_z(Flag p_flag) const{ + + ERR_FAIL_INDEX_V(p_flag,FLAG_MAX,false); + return flags_z[p_flag]; + +} + +RID Generic6DOFJoint::_configure_joint(PhysicsBody *body_a,PhysicsBody *body_b) { + + + Transform gt = get_global_transform(); + //Vector3 cone_twistpos = gt.origin; + //Vector3 cone_twistdir = gt.basis.get_axis(2); + + Transform ainv = body_a->get_global_transform().affine_inverse(); + + Transform local_a = ainv * gt; + local_a.orthonormalize(); + Transform local_b = gt; + + if (body_b) { + Transform binv = body_b->get_global_transform().affine_inverse(); + local_b = binv * gt; + } + + local_b.orthonormalize(); + + RID j = PhysicsServer::get_singleton()->joint_create_generic_6dof(body_a->get_rid(),local_a,body_b?body_b->get_rid():RID(),local_b); + for(int i=0;i<PARAM_MAX;i++) { + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j,Vector3::AXIS_X,PhysicsServer::G6DOFJointAxisParam(i),params_x[i]); + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j,Vector3::AXIS_Y,PhysicsServer::G6DOFJointAxisParam(i),params_y[i]); + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j,Vector3::AXIS_Z,PhysicsServer::G6DOFJointAxisParam(i),params_z[i]); + } + for(int i=0;i<FLAG_MAX;i++) { + PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j,Vector3::AXIS_X,PhysicsServer::G6DOFJointAxisFlag(i),flags_x[i]); + PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j,Vector3::AXIS_Y,PhysicsServer::G6DOFJointAxisFlag(i),flags_y[i]); + PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j,Vector3::AXIS_Z,PhysicsServer::G6DOFJointAxisFlag(i),flags_z[i]); + } + + return j; +} + + +Generic6DOFJoint::Generic6DOFJoint() { + + set_param_x( PARAM_LINEAR_LOWER_LIMIT,0); + set_param_x( PARAM_LINEAR_UPPER_LIMIT,0); + set_param_x( PARAM_LINEAR_LIMIT_SOFTNESS,0.7); + set_param_x( PARAM_LINEAR_RESTITUTION,0.5); + set_param_x( PARAM_LINEAR_DAMPING,1.0); + set_param_x( PARAM_ANGULAR_LOWER_LIMIT,0); + set_param_x( PARAM_ANGULAR_UPPER_LIMIT,0); + set_param_x( PARAM_ANGULAR_LIMIT_SOFTNESS,0.5f); + set_param_x( PARAM_ANGULAR_DAMPING,1.0f); + set_param_x( PARAM_ANGULAR_RESTITUTION,0); + set_param_x( PARAM_ANGULAR_FORCE_LIMIT,0); + set_param_x( PARAM_ANGULAR_ERP,0.5); + set_param_x( PARAM_ANGULAR_MOTOR_TARGET_VELOCITY,0); + set_param_x( PARAM_ANGULAR_MOTOR_FORCE_LIMIT,300); + + set_flag_x( FLAG_ENABLE_ANGULAR_LIMIT,true); + set_flag_x( FLAG_ENABLE_LINEAR_LIMIT,true); + set_flag_x( FLAG_ENABLE_MOTOR,false); + + set_param_y( PARAM_LINEAR_LOWER_LIMIT,0); + set_param_y( PARAM_LINEAR_UPPER_LIMIT,0); + set_param_y( PARAM_LINEAR_LIMIT_SOFTNESS,0.7); + set_param_y( PARAM_LINEAR_RESTITUTION,0.5); + set_param_y( PARAM_LINEAR_DAMPING,1.0); + set_param_y( PARAM_ANGULAR_LOWER_LIMIT,0); + set_param_y( PARAM_ANGULAR_UPPER_LIMIT,0); + set_param_y( PARAM_ANGULAR_LIMIT_SOFTNESS,0.5f); + set_param_y( PARAM_ANGULAR_DAMPING,1.0f); + set_param_y( PARAM_ANGULAR_RESTITUTION,0); + set_param_y( PARAM_ANGULAR_FORCE_LIMIT,0); + set_param_y( PARAM_ANGULAR_ERP,0.5); + set_param_y( PARAM_ANGULAR_MOTOR_TARGET_VELOCITY,0); + set_param_y( PARAM_ANGULAR_MOTOR_FORCE_LIMIT,300); + + set_flag_y( FLAG_ENABLE_ANGULAR_LIMIT,true); + set_flag_y( FLAG_ENABLE_LINEAR_LIMIT,true); + set_flag_y( FLAG_ENABLE_MOTOR,false); + + + set_param_z( PARAM_LINEAR_LOWER_LIMIT,0); + set_param_z( PARAM_LINEAR_UPPER_LIMIT,0); + set_param_z( PARAM_LINEAR_LIMIT_SOFTNESS,0.7); + set_param_z( PARAM_LINEAR_RESTITUTION,0.5); + set_param_z( PARAM_LINEAR_DAMPING,1.0); + set_param_z( PARAM_ANGULAR_LOWER_LIMIT,0); + set_param_z( PARAM_ANGULAR_UPPER_LIMIT,0); + set_param_z( PARAM_ANGULAR_LIMIT_SOFTNESS,0.5f); + set_param_z( PARAM_ANGULAR_DAMPING,1.0f); + set_param_z( PARAM_ANGULAR_RESTITUTION,0); + set_param_z( PARAM_ANGULAR_FORCE_LIMIT,0); + set_param_z( PARAM_ANGULAR_ERP,0.5); + set_param_z( PARAM_ANGULAR_MOTOR_TARGET_VELOCITY,0); + set_param_z( PARAM_ANGULAR_MOTOR_FORCE_LIMIT,300); + + set_flag_z( FLAG_ENABLE_ANGULAR_LIMIT,true); + set_flag_z( FLAG_ENABLE_LINEAR_LIMIT,true); + set_flag_z( FLAG_ENABLE_MOTOR,false); + +} + + + + #if 0 void PhysicsJoint::_set(const String& p_name, const Variant& p_value) { diff --git a/scene/3d/physics_joint.h b/scene/3d/physics_joint.h index 4a0c609e69..6daa06da2b 100644 --- a/scene/3d/physics_joint.h +++ b/scene/3d/physics_joint.h @@ -32,6 +32,313 @@ #include "scene/3d/spatial.h" #include "scene/3d/physics_body.h" + +class Joint : public Spatial { + + OBJ_TYPE(Joint,Spatial); + + RID ba,bb; + + RID joint; + + NodePath a; + NodePath b; + + +protected: + + void _update_joint(bool p_only_free=false); + + void _notification(int p_what); + + virtual RID _configure_joint(PhysicsBody *body_a,PhysicsBody *body_b)=0; + + static void _bind_methods(); +public: + + void set_node_a(const NodePath& p_node_a); + NodePath get_node_a() const; + + void set_node_b(const NodePath& p_node_b); + NodePath get_node_b() const; + + RID get_joint() const { return joint; } + Joint(); + +}; + +/////////////////////////////////////////// + + +class PinJoint : public Joint { + + OBJ_TYPE(PinJoint,Joint); +public: + + enum Param { + PARAM_BIAS=PhysicsServer::PIN_JOINT_BIAS, + PARAM_DAMPING=PhysicsServer::PIN_JOINT_DAMPING, + PARAM_IMPULSE_CLAMP=PhysicsServer::PIN_JOINT_IMPULSE_CLAMP + }; + +protected: + + float params[3]; + virtual RID _configure_joint(PhysicsBody *body_a, PhysicsBody *body_b); + static void _bind_methods(); +public: + + void set_param(Param p_param,float p_value); + float get_param(Param p_param) const; + + PinJoint(); +}; + +VARIANT_ENUM_CAST(PinJoint::Param); + + +class HingeJoint : public Joint { + + OBJ_TYPE(HingeJoint,Joint); +public: + + enum Param { + PARAM_BIAS=PhysicsServer::HINGE_JOINT_BIAS, + PARAM_LIMIT_UPPER=PhysicsServer::HINGE_JOINT_LIMIT_UPPER, + PARAM_LIMIT_LOWER=PhysicsServer::HINGE_JOINT_LIMIT_LOWER, + PARAM_LIMIT_BIAS=PhysicsServer::HINGE_JOINT_LIMIT_BIAS, + PARAM_LIMIT_SOFTNESS=PhysicsServer::HINGE_JOINT_LIMIT_SOFTNESS, + PARAM_LIMIT_RELAXATION=PhysicsServer::HINGE_JOINT_LIMIT_RELAXATION, + PARAM_MOTOR_TARGET_VELOCITY=PhysicsServer::HINGE_JOINT_MOTOR_TARGET_VELOCITY, + PARAM_MOTOR_MAX_IMPULSE=PhysicsServer::HINGE_JOINT_MOTOR_MAX_IMPULSE, + PARAM_MAX=PhysicsServer::HINGE_JOINT_MAX + }; + + enum Flag { + FLAG_USE_LIMIT=PhysicsServer::HINGE_JOINT_FLAG_USE_LIMIT, + FLAG_ENABLE_MOTOR=PhysicsServer::HINGE_JOINT_FLAG_ENABLE_MOTOR, + FLAG_MAX=PhysicsServer::HINGE_JOINT_FLAG_MAX + }; + + + +protected: + + float params[PARAM_MAX]; + bool flags[FLAG_MAX]; + virtual RID _configure_joint(PhysicsBody *body_a, PhysicsBody *body_b); + static void _bind_methods(); + + void _set_upper_limit(float p_limit); + float _get_upper_limit() const; + + void _set_lower_limit(float p_limit); + float _get_lower_limit() const; + +public: + + void set_param(Param p_param,float p_value); + float get_param(Param p_param) const; + + void set_flag(Flag p_flag,bool p_value); + bool get_flag(Flag p_flag) const; + + HingeJoint(); +}; + +VARIANT_ENUM_CAST(HingeJoint::Param); +VARIANT_ENUM_CAST(HingeJoint::Flag); + + +class SliderJoint : public Joint { + + OBJ_TYPE(SliderJoint,Joint); +public: + + enum Param { + PARAM_LINEAR_LIMIT_UPPER=PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER, + PARAM_LINEAR_LIMIT_LOWER=PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_LOWER, + PARAM_LINEAR_LIMIT_SOFTNESS=PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS, + PARAM_LINEAR_LIMIT_RESTITUTION=PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION, + PARAM_LINEAR_LIMIT_DAMPING=PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_DAMPING, + PARAM_LINEAR_MOTION_SOFTNESS=PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_SOFTNESS, + PARAM_LINEAR_MOTION_RESTITUTION=PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_RESTITUTION, + PARAM_LINEAR_MOTION_DAMPING=PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_DAMPING, + PARAM_LINEAR_ORTHOGONAL_SOFTNESS=PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS, + PARAM_LINEAR_ORTHOGONAL_RESTITUTION=PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION, + PARAM_LINEAR_ORTHOGONAL_DAMPING=PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING, + + PARAM_ANGULAR_LIMIT_UPPER=PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_UPPER, + PARAM_ANGULAR_LIMIT_LOWER=PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_LOWER, + PARAM_ANGULAR_LIMIT_SOFTNESS=PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, + PARAM_ANGULAR_LIMIT_RESTITUTION=PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION, + PARAM_ANGULAR_LIMIT_DAMPING=PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING, + PARAM_ANGULAR_MOTION_SOFTNESS=PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS, + PARAM_ANGULAR_MOTION_RESTITUTION=PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION, + PARAM_ANGULAR_MOTION_DAMPING=PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_DAMPING, + PARAM_ANGULAR_ORTHOGONAL_SOFTNESS=PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS, + PARAM_ANGULAR_ORTHOGONAL_RESTITUTION=PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION, + PARAM_ANGULAR_ORTHOGONAL_DAMPING=PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING, + PARAM_MAX=PhysicsServer::SLIDER_JOINT_MAX + + }; + +protected: + + + + void _set_upper_limit_angular(float p_limit_angular); + float _get_upper_limit_angular() const; + + void _set_lower_limit_angular(float p_limit_angular); + float _get_lower_limit_angular() const; + + float params[PARAM_MAX]; + virtual RID _configure_joint(PhysicsBody *body_a, PhysicsBody *body_b); + static void _bind_methods(); +public: + + void set_param(Param p_param,float p_value); + float get_param(Param p_param) const; + + SliderJoint(); +}; + + +VARIANT_ENUM_CAST(SliderJoint::Param); + + + + +class ConeTwistJoint : public Joint { + + OBJ_TYPE(ConeTwistJoint,Joint); +public: + + enum Param { + + PARAM_SWING_SPAN, + PARAM_TWIST_SPAN, + PARAM_BIAS, + PARAM_SOFTNESS, + PARAM_RELAXATION, + PARAM_MAX + }; + +protected: + + + void _set_swing_span(float p_limit_angular); + float _get_swing_span() const; + + void _set_twist_span(float p_limit_angular); + float _get_twist_span() const; + + float params[PARAM_MAX]; + virtual RID _configure_joint(PhysicsBody *body_a, PhysicsBody *body_b); + static void _bind_methods(); +public: + + void set_param(Param p_param,float p_value); + float get_param(Param p_param) const; + + ConeTwistJoint(); +}; + + +VARIANT_ENUM_CAST(ConeTwistJoint::Param); + + +class Generic6DOFJoint : public Joint { + + OBJ_TYPE(Generic6DOFJoint,Joint); +public: + + enum Param { + + PARAM_LINEAR_LOWER_LIMIT=PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT, + PARAM_LINEAR_UPPER_LIMIT=PhysicsServer::G6DOF_JOINT_LINEAR_UPPER_LIMIT, + PARAM_LINEAR_LIMIT_SOFTNESS=PhysicsServer::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, + PARAM_LINEAR_RESTITUTION=PhysicsServer::G6DOF_JOINT_LINEAR_RESTITUTION, + PARAM_LINEAR_DAMPING=PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING, + PARAM_ANGULAR_LOWER_LIMIT=PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT, + PARAM_ANGULAR_UPPER_LIMIT=PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT, + PARAM_ANGULAR_LIMIT_SOFTNESS=PhysicsServer::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS, + PARAM_ANGULAR_DAMPING=PhysicsServer::G6DOF_JOINT_ANGULAR_DAMPING, + PARAM_ANGULAR_RESTITUTION=PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION, + PARAM_ANGULAR_FORCE_LIMIT=PhysicsServer::G6DOF_JOINT_ANGULAR_FORCE_LIMIT, + PARAM_ANGULAR_ERP=PhysicsServer::G6DOF_JOINT_ANGULAR_ERP, + PARAM_ANGULAR_MOTOR_TARGET_VELOCITY=PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY, + PARAM_ANGULAR_MOTOR_FORCE_LIMIT=PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT, + PARAM_MAX=PhysicsServer::G6DOF_JOINT_MAX, + }; + + enum Flag { + FLAG_ENABLE_LINEAR_LIMIT=PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, + FLAG_ENABLE_ANGULAR_LIMIT=PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, + FLAG_ENABLE_MOTOR=PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_MOTOR, + FLAG_MAX=PhysicsServer::G6DOF_JOINT_FLAG_MAX + }; + + +protected: + + + void _set_angular_hi_limit_x(float p_limit_angular); + float _get_angular_hi_limit_x() const; + + void _set_angular_hi_limit_y(float p_limit_angular); + float _get_angular_hi_limit_y() const; + + void _set_angular_hi_limit_z(float p_limit_angular); + float _get_angular_hi_limit_z() const; + + void _set_angular_lo_limit_x(float p_limit_angular); + float _get_angular_lo_limit_x() const; + + void _set_angular_lo_limit_y(float p_limit_angular); + float _get_angular_lo_limit_y() const; + + void _set_angular_lo_limit_z(float p_limit_angular); + float _get_angular_lo_limit_z() const; + + float params_x[PARAM_MAX]; + bool flags_x[FLAG_MAX]; + float params_y[PARAM_MAX]; + bool flags_y[FLAG_MAX]; + float params_z[PARAM_MAX]; + bool flags_z[FLAG_MAX]; + + virtual RID _configure_joint(PhysicsBody *body_a, PhysicsBody *body_b); + static void _bind_methods(); +public: + + void set_param_x(Param p_param,float p_value); + float get_param_x(Param p_param) const; + + void set_param_y(Param p_param,float p_value); + float get_param_y(Param p_param) const; + + void set_param_z(Param p_param,float p_value); + float get_param_z(Param p_param) const; + + void set_flag_x(Flag p_flag,bool p_enabled); + bool get_flag_x(Flag p_flag) const; + + void set_flag_y(Flag p_flag,bool p_enabled); + bool get_flag_y(Flag p_flag) const; + + void set_flag_z(Flag p_flag,bool p_enabled); + bool get_flag_z(Flag p_flag) const; + + Generic6DOFJoint(); +}; + + +VARIANT_ENUM_CAST(Generic6DOFJoint::Param); +VARIANT_ENUM_CAST(Generic6DOFJoint::Flag); + + #if 0 class PhysicsJoint : public Spatial { diff --git a/scene/3d/vehicle_body.cpp b/scene/3d/vehicle_body.cpp index 7680c1d56c..07abd1dcd2 100644 --- a/scene/3d/vehicle_body.cpp +++ b/scene/3d/vehicle_body.cpp @@ -125,19 +125,161 @@ void VehicleWheel::_update(PhysicsDirectBodyState *s) { } } +void VehicleWheel::set_radius(float p_radius) { + + m_wheelRadius=p_radius; + update_gizmo(); +} + +float VehicleWheel::get_radius() const{ + + return m_wheelRadius; +} + +void VehicleWheel::set_suspension_rest_length(float p_length){ + + m_suspensionRestLength=p_length; + update_gizmo(); +} +float VehicleWheel::get_suspension_rest_length() const{ + + return m_suspensionRestLength; +} + +void VehicleWheel::set_suspension_travel(float p_length){ + + m_maxSuspensionTravelCm=p_length/0.01; +} +float VehicleWheel::get_suspension_travel() const{ + + return m_maxSuspensionTravelCm*0.01; +} + +void VehicleWheel::set_suspension_stiffness(float p_value){ + + m_suspensionStiffness=p_value; +} +float VehicleWheel::get_suspension_stiffness() const{ + + return m_suspensionStiffness; +} + +void VehicleWheel::set_suspension_max_force(float p_value){ + + m_maxSuspensionForce=p_value; +} +float VehicleWheel::get_suspension_max_force() const{ + + return m_maxSuspensionForce; +} + +void VehicleWheel::set_damping_compression(float p_value){ + + m_wheelsDampingCompression=p_value; +} +float VehicleWheel::get_damping_compression() const{ + + return m_wheelsDampingRelaxation; +} + +void VehicleWheel::set_damping_relaxation(float p_value){ + + m_wheelsDampingRelaxation=p_value; +} +float VehicleWheel::get_damping_relaxation() const{ + + return m_wheelsDampingRelaxation; +} + +void VehicleWheel::set_friction_slip(float p_value) { + + m_frictionSlip=p_value; +} +float VehicleWheel::get_friction_slip() const{ + + return m_frictionSlip; +} + + void VehicleWheel::_bind_methods() { + ObjectTypeDB::bind_method(_MD("set_radius","length"),&VehicleWheel::set_radius); + ObjectTypeDB::bind_method(_MD("get_radius"),&VehicleWheel::get_radius); + + ObjectTypeDB::bind_method(_MD("set_suspension_rest_length","length"),&VehicleWheel::set_suspension_rest_length); + ObjectTypeDB::bind_method(_MD("get_suspension_rest_length"),&VehicleWheel::get_suspension_rest_length); + + ObjectTypeDB::bind_method(_MD("set_suspension_travel","length"),&VehicleWheel::set_suspension_travel); + ObjectTypeDB::bind_method(_MD("get_suspension_travel"),&VehicleWheel::get_suspension_travel); + + ObjectTypeDB::bind_method(_MD("set_suspension_stiffness","length"),&VehicleWheel::set_suspension_stiffness); + ObjectTypeDB::bind_method(_MD("get_suspension_stiffness"),&VehicleWheel::get_suspension_stiffness); + + ObjectTypeDB::bind_method(_MD("set_suspension_max_force","length"),&VehicleWheel::set_suspension_max_force); + ObjectTypeDB::bind_method(_MD("get_suspension_max_force"),&VehicleWheel::get_suspension_max_force); + + ObjectTypeDB::bind_method(_MD("set_damping_compression","length"),&VehicleWheel::set_damping_compression); + ObjectTypeDB::bind_method(_MD("get_damping_compression"),&VehicleWheel::get_damping_compression); + + ObjectTypeDB::bind_method(_MD("set_damping_relaxation","length"),&VehicleWheel::set_damping_relaxation); + ObjectTypeDB::bind_method(_MD("get_damping_relaxation"),&VehicleWheel::get_damping_relaxation); + + ObjectTypeDB::bind_method(_MD("set_use_as_traction","enable"),&VehicleWheel::set_use_as_traction); + ObjectTypeDB::bind_method(_MD("is_used_as_traction"),&VehicleWheel::is_used_as_traction); + + ObjectTypeDB::bind_method(_MD("set_use_as_steering","enable"),&VehicleWheel::set_use_as_steering); + ObjectTypeDB::bind_method(_MD("is_used_as_steering"),&VehicleWheel::is_used_as_steering); + + ObjectTypeDB::bind_method(_MD("set_friction_slip","length"),&VehicleWheel::set_friction_slip); + ObjectTypeDB::bind_method(_MD("get_friction_slip"),&VehicleWheel::get_friction_slip); + + + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"type/traction"),_SCS("set_use_as_traction"),_SCS("is_used_as_traction")); + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"type/steering"),_SCS("set_use_as_steering"),_SCS("is_used_as_steering")); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"wheel/radius"),_SCS("set_radius"),_SCS("get_radius")); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"wheel/rest_length"),_SCS("set_suspension_rest_length"),_SCS("get_suspension_rest_length")); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"wheel/friction_slip"),_SCS("set_friction_slip"),_SCS("get_friction_slip")); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"suspension/travel"),_SCS("set_suspension_travel"),_SCS("get_suspension_travel")); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"suspension/stiffness"),_SCS("set_suspension_stiffness"),_SCS("get_suspension_stiffness")); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"suspension/max_force"),_SCS("set_suspension_max_force"),_SCS("get_suspension_max_force")); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"damping/compression"),_SCS("set_damping_compression"),_SCS("get_damping_compression")); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"damping/relaxation"),_SCS("set_damping_relaxation"),_SCS("get_damping_relaxation")); + +} + + +void VehicleWheel::set_use_as_traction(bool p_enable) { + + engine_traction=p_enable; +} + +bool VehicleWheel::is_used_as_traction() const{ + + return engine_traction; +} + + +void VehicleWheel::set_use_as_steering(bool p_enabled){ + + steers=p_enabled; +} + +bool VehicleWheel::is_used_as_steering() const{ + + return steers; } VehicleWheel::VehicleWheel() { + steers=false; + engine_traction=false; m_steering = real_t(0.); - m_engineForce = real_t(0.); + //m_engineForce = real_t(0.); m_rotation = real_t(0.); m_deltaRotation = real_t(0.); m_brake = real_t(0.); @@ -172,6 +314,7 @@ void VehicleBody::_update_wheel_transform(VehicleWheel& wheel ,PhysicsDirectBody //} wheel.m_raycastInfo.m_hardPointWS = chassisTrans.xform( wheel.m_chassisConnectionPointCS ); + //wheel.m_raycastInfo.m_hardPointWS+=s->get_linear_velocity()*s->get_step(); wheel.m_raycastInfo.m_wheelDirectionWS = chassisTrans.get_basis().xform( wheel.m_wheelDirectionCS).normalized(); wheel.m_raycastInfo.m_wheelAxleWS = chassisTrans.get_basis().xform( wheel.m_wheelAxleCS ).normalized(); } @@ -189,12 +332,16 @@ void VehicleBody::_update_wheel(int p_idx,PhysicsDirectBodyState *s) { // up.normalize(); //rotate around steering over de wheelAxleWS - real_t steering = wheel.m_steering; + real_t steering = wheel.steers?m_steeringValue:0.0; + //print_line(itos(p_idx)+": "+rtos(steering)); Matrix3 steeringMat(up,steering); Matrix3 rotatingMat(right,-wheel.m_rotation); +// if (p_idx==1) +// print_line("steeringMat " +steeringMat); + Matrix3 basis2( right[0],up[0],fwd[0], right[1],up[1],fwd[1], @@ -202,9 +349,11 @@ void VehicleBody::_update_wheel(int p_idx,PhysicsDirectBodyState *s) { ); wheel.m_worldTransform.set_basis(steeringMat * rotatingMat * basis2); + //wheel.m_worldTransform.set_basis(basis2 * (steeringMat * rotatingMat)); wheel.m_worldTransform.set_origin( wheel.m_raycastInfo.m_hardPointWS + wheel.m_raycastInfo.m_wheelDirectionWS * wheel.m_raycastInfo.m_suspensionLength ); + } @@ -221,9 +370,10 @@ real_t VehicleBody::_ray_cast(int p_idx,PhysicsDirectBodyState *s) { real_t raylen = wheel.m_suspensionRestLength+wheel.m_wheelRadius; Vector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen); - const Vector3& source = wheel.m_raycastInfo.m_hardPointWS; + Vector3 source = wheel.m_raycastInfo.m_hardPointWS; wheel.m_raycastInfo.m_contactPointWS = source + rayvector; const Vector3& target = wheel.m_raycastInfo.m_contactPointWS; + source-=wheel.m_wheelRadius * wheel.m_raycastInfo.m_wheelDirectionWS; real_t param = real_t(0.); @@ -552,9 +702,10 @@ void VehicleBody::_update_friction(PhysicsDirectBodyState *s) { //const btTransform& wheelTrans = getWheelTransformWS( i ); - Matrix3 wheelBasis0 = wheelInfo.get_global_transform().basis; + Matrix3 wheelBasis0 = wheelInfo.m_worldTransform.basis;//get_global_transform().basis; + m_axle[i] = wheelBasis0.get_axis(Vector3::AXIS_X); - m_axle[i] = wheelInfo.m_raycastInfo.m_wheelAxleWS; + //m_axle[i] = wheelInfo.m_raycastInfo.m_wheelAxleWS; const Vector3& surfNormalWS = wheelInfo.m_raycastInfo.m_contactNormalWS; real_t proj = m_axle[i].dot(surfNormalWS); @@ -592,9 +743,9 @@ void VehicleBody::_update_friction(PhysicsDirectBodyState *s) { if (wheelInfo.m_raycastInfo.m_isInContact) { - if (wheelInfo.m_engineForce != 0.f) + if (engine_force != 0.f) { - rollingFriction = wheelInfo.m_engineForce* s->get_step(); + rollingFriction = engine_force* s->get_step(); } else { real_t defaultRollingFrictionImpulse = 0.f; @@ -721,9 +872,11 @@ void VehicleBody::_direct_state_changed(Object *p_state) { _update_wheel(i,s); } + for(int i=0;i<wheels.size();i++) { _ray_cast(i,s); + wheels[i]->set_transform(s->get_transform().inverse() * wheels[i]->m_worldTransform); } _update_suspension(s); @@ -808,6 +961,35 @@ real_t VehicleBody::get_friction() const{ return friction; } +void VehicleBody::set_engine_force(float p_force) { + + engine_force=p_force; +} + +float VehicleBody::get_engine_force() const{ + + return engine_force; +} + +void VehicleBody::set_brake(float p_brake){ + + brake=p_brake; +} +float VehicleBody::get_brake() const{ + + return brake; +} + +void VehicleBody::set_steering(float p_steering){ + + m_steeringValue=p_steering; +} +float VehicleBody::get_steering() const{ + + return m_steeringValue; +} + + void VehicleBody::_bind_methods(){ ObjectTypeDB::bind_method(_MD("set_mass","mass"),&VehicleBody::set_mass); @@ -816,8 +998,20 @@ void VehicleBody::_bind_methods(){ ObjectTypeDB::bind_method(_MD("set_friction","friction"),&VehicleBody::set_friction); ObjectTypeDB::bind_method(_MD("get_friction"),&VehicleBody::get_friction); + ObjectTypeDB::bind_method(_MD("set_engine_force","engine_force"),&VehicleBody::set_engine_force); + ObjectTypeDB::bind_method(_MD("get_engine_force"),&VehicleBody::get_engine_force); + + ObjectTypeDB::bind_method(_MD("set_brake","brake"),&VehicleBody::set_brake); + ObjectTypeDB::bind_method(_MD("get_brake"),&VehicleBody::get_brake); + + ObjectTypeDB::bind_method(_MD("set_steering","steering"),&VehicleBody::set_steering); + ObjectTypeDB::bind_method(_MD("get_steering"),&VehicleBody::get_steering); + ObjectTypeDB::bind_method(_MD("_direct_state_changed"),&VehicleBody::_direct_state_changed); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/engine_force",PROPERTY_HINT_RANGE,"0.01,1024.0,0.01"),_SCS("set_engine_force"),_SCS("get_engine_force")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/brake",PROPERTY_HINT_RANGE,"0.01,1024.0,0.01"),_SCS("set_brake"),_SCS("get_brake")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/steering",PROPERTY_HINT_RANGE,"0.01,1024.0,0.01"),_SCS("set_steering"),_SCS("get_steering")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"body/mass",PROPERTY_HINT_RANGE,"0.01,65536,0.01"),_SCS("set_mass"),_SCS("get_mass")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"body/friction",PROPERTY_HINT_RANGE,"0.01,1,0.01"),_SCS("set_friction"),_SCS("get_friction")); @@ -833,8 +1027,11 @@ VehicleBody::VehicleBody() : PhysicsBody(PhysicsServer::BODY_MODE_RIGID) { m_currentVehicleSpeedKmHour = real_t(0.); m_steeringValue = real_t(0.); + engine_force=0; + brake=0; + + - mass=1; friction=1; ccd=false; @@ -842,5 +1039,6 @@ VehicleBody::VehicleBody() : PhysicsBody(PhysicsServer::BODY_MODE_RIGID) { exclude.insert(get_rid()); PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(),this,"_direct_state_changed"); + set_mass(40); } diff --git a/scene/3d/vehicle_body.h b/scene/3d/vehicle_body.h index 97137da699..285cca142d 100644 --- a/scene/3d/vehicle_body.h +++ b/scene/3d/vehicle_body.h @@ -14,6 +14,8 @@ friend class VehicleBody; Transform m_worldTransform; Transform local_xform; + bool engine_traction; + bool steers; Vector3 m_chassisConnectionPointCS; //const @@ -39,7 +41,7 @@ friend class VehicleBody; real_t m_rotation; real_t m_deltaRotation; real_t m_rollInfluence; - real_t m_engineForce; + //real_t m_engineForce; real_t m_brake; real_t m_clippedInvContactDotSuspension; @@ -69,6 +71,35 @@ protected: public: + void set_radius(float p_radius); + float get_radius() const; + + void set_suspension_rest_length(float p_length); + float get_suspension_rest_length() const; + + void set_suspension_travel(float p_length); + float get_suspension_travel() const; + + void set_suspension_stiffness(float p_value); + float get_suspension_stiffness() const; + + void set_suspension_max_force(float p_value); + float get_suspension_max_force() const; + + void set_damping_compression(float p_value); + float get_damping_compression() const; + + void set_damping_relaxation(float p_value); + float get_damping_relaxation() const; + + void set_friction_slip(float p_value); + float get_friction_slip() const; + + void set_use_as_traction(bool p_enable); + bool is_used_as_traction() const; + + void set_use_as_steering(bool p_enabled); + bool is_used_as_steering() const; VehicleWheel(); @@ -82,6 +113,9 @@ class VehicleBody : public PhysicsBody { real_t mass; real_t friction; + float engine_force; + float brake; + Vector3 linear_velocity; Vector3 angular_velocity; bool ccd; @@ -135,6 +169,15 @@ public: void set_friction(real_t p_friction); real_t get_friction() const; + void set_engine_force(float p_engine_force); + float get_engine_force() const; + + void set_brake(float p_force); + float get_brake() const; + + void set_steering(float p_steering); + float get_steering() const; + VehicleBody(); }; diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 3c95b102d7..2d6f3cd27a 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -113,7 +113,7 @@ void TabContainer::_input_event(const InputEvent& p_event) { break; } - String s = c->has_meta("_tab_title")?String(XL_MESSAGE(String(c->get_meta("_tab_title")))):String(c->get_name()); + String s = c->has_meta("_tab_name")?String(XL_MESSAGE(String(c->get_meta("_tab_name")))):String(c->get_name()); int tab_width=font->get_string_size(s).width; if (c->has_meta("_tab_icon")) { @@ -220,7 +220,7 @@ void TabContainer::_notification(int p_what) { continue; - String s = c->has_meta("_tab_title")?String(XL_MESSAGE(String(c->get_meta("_tab_title")))):String(c->get_name()); + String s = c->has_meta("_tab_name")?String(XL_MESSAGE(String(c->get_meta("_tab_name")))):String(c->get_name()); w+=font->get_string_size(s).width; if (c->has_meta("_tab_icon")) { Ref<Texture> icon = c->get_meta("_tab_icon"); @@ -284,7 +284,7 @@ void TabContainer::_notification(int p_what) { continue; } - String s = c->has_meta("_tab_title")?String(c->get_meta("_tab_title")):String(c->get_name()); + String s = c->has_meta("_tab_name")?String(c->get_meta("_tab_name")):String(c->get_name()); int w=font->get_string_size(s).width; Ref<Texture> icon; if (c->has_meta("_tab_icon")) { diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp index b7c857b9c7..ae7a4d59a7 100644 --- a/scene/gui/tabs.cpp +++ b/scene/gui/tabs.cpp @@ -278,7 +278,8 @@ void Tabs::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_tab_title","tab_idx"),&Tabs::get_tab_title); ObjectTypeDB::bind_method(_MD("set_tab_icon","tab_idx","icon:Texture"),&Tabs::set_tab_icon); ObjectTypeDB::bind_method(_MD("get_tab_icon:Texture","tab_idx"),&Tabs::get_tab_icon); - ObjectTypeDB::bind_method(_MD("remove_tab","tab_idx","icon:Texture"),&Tabs::remove_tab); + ObjectTypeDB::bind_method(_MD("remove_tab","tab_idx"),&Tabs::remove_tab); + ObjectTypeDB::bind_method(_MD("add_tab","title","icon:Texture"),&Tabs::add_tab); ADD_SIGNAL(MethodInfo("tab_changed",PropertyInfo(Variant::INT,"tab"))); diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index fb85f0c6b7..25f04379ef 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -2787,7 +2787,7 @@ int Tree::get_item_offset(TreeItem *p_item) const { ofs+=compute_item_height(it)+cache.vseparation; - if (it->childs) { + if (it->childs && !it->collapsed) { it=it->childs; diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp index e3bb50a9af..9a1c070529 100644 --- a/scene/gui/video_player.cpp +++ b/scene/gui/video_player.cpp @@ -46,6 +46,7 @@ void VideoPlayer::_notification(int p_notification) { if (paused) return; + stream->update(get_scene()->get_idle_process_time()); while (stream->get_pending_frame_count()) { Image img = stream->pop_frame(); @@ -104,10 +105,6 @@ void VideoPlayer::set_stream(const Ref<VideoStream> &p_stream) { stop(); - if (stream_rid.is_valid()) - AudioServer::get_singleton()->free(stream_rid); - stream_rid=RID(); - texture = Ref<ImageTexture>(memnew(ImageTexture)); stream=p_stream; @@ -115,7 +112,6 @@ void VideoPlayer::set_stream(const Ref<VideoStream> &p_stream) { stream->set_loop(loops); stream->set_paused(paused); - stream_rid=AudioServer::get_singleton()->audio_stream_create(stream->get_audio_stream()); } }; @@ -131,8 +127,6 @@ void VideoPlayer::play() { if (stream.is_null()) return; stream->play(); - AudioServer::get_singleton()->stream_set_active(stream_rid,true); - AudioServer::get_singleton()->stream_set_volume_scale(stream_rid,volume); set_process(true); }; @@ -143,7 +137,6 @@ void VideoPlayer::stop() { if (stream.is_null()) return; - AudioServer::get_singleton()->stream_set_active(stream_rid,false); stream->stop(); set_process(false); }; @@ -173,8 +166,6 @@ bool VideoPlayer::is_paused() const { void VideoPlayer::set_volume(float p_vol) { volume=p_vol; - if (stream_rid.is_valid()) - AudioServer::get_singleton()->stream_set_volume_scale(stream_rid,volume); }; float VideoPlayer::get_volume() const { @@ -213,6 +204,7 @@ float VideoPlayer::get_pos() const { return stream->get_pos(); }; + void VideoPlayer::set_autoplay(bool p_enable) { autoplay=p_enable; @@ -253,7 +245,7 @@ void VideoPlayer::_bind_methods() { ObjectTypeDB::bind_method(_MD("has_expand"), &VideoPlayer::has_expand ); - ADD_PROPERTY( PropertyInfo(Variant::OBJECT, "stream/stream", PROPERTY_HINT_RESOURCE_TYPE,"AudioStream"), _SCS("set_stream"), _SCS("get_stream") ); + ADD_PROPERTY( PropertyInfo(Variant::OBJECT, "stream/stream", PROPERTY_HINT_RESOURCE_TYPE,"VideoStream"), _SCS("set_stream"), _SCS("get_stream") ); // ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/loop"), _SCS("set_loop"), _SCS("has_loop") ); ADD_PROPERTY( PropertyInfo(Variant::REAL, "stream/volume_db", PROPERTY_HINT_RANGE,"-80,24,0.01"), _SCS("set_volume_db"), _SCS("get_volume_db") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/autoplay"), _SCS("set_autoplay"), _SCS("has_autoplay") ); diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp index 1926570885..bcdc50c880 100644 --- a/scene/main/scene_main_loop.cpp +++ b/scene/main/scene_main_loop.cpp @@ -481,8 +481,10 @@ bool SceneMainLoop::iteration(float p_time) { _flush_transform_notifications(); MainLoop::iteration(p_time); - fixed_process_time=p_time; + + emit_signal("fixed_frame"); + _notify_group_pause("fixed_process",Node::NOTIFICATION_FIXED_PROCESS); _flush_ugc(); _flush_transform_notifications(); @@ -507,6 +509,8 @@ bool SceneMainLoop::idle(float p_time){ idle_process_time=p_time; + emit_signal("idle_frame"); + _flush_transform_notifications(); _notify_group_pause("idle_process",Node::NOTIFICATION_PROCESS); @@ -1063,6 +1067,11 @@ SceneMainLoop::SceneMainLoop() { ScriptDebugger::get_singleton()->set_request_scene_tree_message_func(_debugger_request_tree,this); } + root->set_physics_object_picking(GLOBAL_DEF("physics/enable_object_picking",true)); + + ADD_SIGNAL( MethodInfo("idle_frame")); + ADD_SIGNAL( MethodInfo("fixed_frame")); + } diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index ea78ece9dc..92dcef803c 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -36,6 +36,7 @@ #include "scene/gui/control.h" #include "scene/3d/camera.h" #include "scene/3d/spatial_indexer.h" +#include "scene/3d/collision_object.h" @@ -94,6 +95,8 @@ void Viewport::_update_stretch_transform() { if (size_override_stretch && size_override) { + print_line("sive override size "+size_override_size); + print_line("rect size "+rect.size); stretch_transform=Matrix32(); Size2 scale = rect.size/(size_override_size+size_override_margin*2); stretch_transform.scale(scale); @@ -233,6 +236,40 @@ void Viewport::update_worlds() { find_world()->_update(get_scene()->get_frame()); } + +void Viewport::_test_new_mouseover(ObjectID new_collider) { + + if (new_collider!=physics_object_over) { + + if (physics_object_over) { + Object *obj = ObjectDB::get_instance(physics_object_over); + if (obj) { + CollisionObject *co = obj->cast_to<CollisionObject>(); + if (co) { + co->_mouse_exit(); + } + } + } + + if (new_collider) { + Object *obj = ObjectDB::get_instance(new_collider); + if (obj) { + CollisionObject *co = obj->cast_to<CollisionObject>(); + if (co) { + co->_mouse_enter(); + + } + } + + } + + physics_object_over=new_collider; + + } + + +} + void Viewport::_notification(int p_what) { @@ -308,6 +345,155 @@ void Viewport::_notification(int p_what) { remove_from_group("_viewports"); } break; + case NOTIFICATION_FIXED_PROCESS: { + + if (physics_object_picking) { + + Vector2 last_pos(1e20,1e20); + CollisionObject *last_object; + ObjectID last_id=0; + PhysicsDirectSpaceState::RayResult result; + + bool motion_tested=false; + + while(physics_picking_events.size()) { + + InputEvent ev = physics_picking_events.front()->get(); + physics_picking_events.pop_front(); + + Vector2 pos; + switch(ev.type) { + case InputEvent::MOUSE_MOTION: { + pos.x=ev.mouse_motion.x; + pos.y=ev.mouse_motion.y; + motion_tested=true; + physics_last_mousepos=pos; + } break; + case InputEvent::MOUSE_BUTTON: { + pos.x=ev.mouse_button.x; + pos.y=ev.mouse_button.y; + + } break; + case InputEvent::SCREEN_DRAG: { + pos.x=ev.screen_drag.x; + pos.y=ev.screen_drag.y; + } break; + case InputEvent::SCREEN_TOUCH: { + pos.x=ev.screen_touch.x; + pos.y=ev.screen_touch.y; + } break; + + } + + bool captured=false; + + if (physics_object_capture!=0) { + + + Object *obj = ObjectDB::get_instance(physics_object_capture); + if (obj) { + CollisionObject *co = obj->cast_to<CollisionObject>(); + if (co) { + co->_input_event(ev,Vector3(),Vector3(),0); + captured=true; + if (ev.type==InputEvent::MOUSE_BUTTON && ev.mouse_button.button_index==1 && !ev.mouse_button.pressed) { + physics_object_capture=0; + } + + } else { + physics_object_capture=0; + } + } else { + physics_object_capture=0; + } + } + + + if (captured) { + //none + } else if (pos==last_pos) { + + if (last_id) { + if (ObjectDB::get_instance(last_id)) { + //good, exists + last_object->_input_event(ev,result.position,result.normal,result.shape); + if (last_object->get_capture_input_on_drag() && ev.type==InputEvent::MOUSE_BUTTON && ev.mouse_button.button_index==1 && ev.mouse_button.pressed) { + physics_object_capture=last_id; + } + + + } + } + } else { + + + + + if (camera) { + + Vector3 from = camera->project_ray_origin(pos); + Vector3 dir = camera->project_ray_normal(pos); + + PhysicsDirectSpaceState *space = PhysicsServer::get_singleton()->space_get_direct_state(find_world()->get_space()); + if (space) { + + bool col = space->intersect_ray(from,from+dir*10000,result,Set<RID>(),0xFFFFFFFF,0xFFFFFFFF); + ObjectID new_collider=0; + if (col) { + if (result.collider) { + CollisionObject *co = result.collider->cast_to<CollisionObject>(); + if (co) { + co->_input_event(ev,result.position,result.normal,result.shape); + last_object=co; + last_id=result.collider_id; + new_collider=last_id; + if (co->get_capture_input_on_drag() && ev.type==InputEvent::MOUSE_BUTTON && ev.mouse_button.button_index==1 && ev.mouse_button.pressed) { + physics_object_capture=last_id; + } + + } + } + } + + if (ev.type==InputEvent::MOUSE_MOTION) { + _test_new_mouseover(new_collider); + } + } + + last_pos=pos; + } + } + } + + if (!motion_tested && camera && physics_last_mousepos!=Vector2(1e20,1e20)) { + + //test anyway for mouseenter/exit because objects might move + Vector3 from = camera->project_ray_origin(physics_last_mousepos); + Vector3 dir = camera->project_ray_normal(physics_last_mousepos); + + PhysicsDirectSpaceState *space = PhysicsServer::get_singleton()->space_get_direct_state(find_world()->get_space()); + if (space) { + + bool col = space->intersect_ray(from,from+dir*10000,result,Set<RID>(),0xFFFFFFFF,0xFFFFFFFF); + ObjectID new_collider=0; + if (col) { + if (result.collider) { + CollisionObject *co = result.collider->cast_to<CollisionObject>(); + if (co) { + new_collider=result.collider_id; + + } + } + } + + _test_new_mouseover(new_collider); + + } + + } + } + + } break; } } @@ -888,7 +1074,8 @@ void Viewport::_vp_input(const InputEvent& p_ev) { void Viewport::_vp_unhandled_input(const InputEvent& p_ev) { - if (render_target) + + if (render_target && to_screen_rect==Rect2()) return; //if render target, can't get input events //this one handles system input, p_ev are in system coordinates @@ -917,6 +1104,15 @@ void Viewport::unhandled_input(const InputEvent& p_event) { get_scene()->_call_input_pause(unhandled_key_input_group,"_unhandled_key_input",p_event); //call_group(GROUP_CALL_REVERSE|GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"unhandled_key_input","_unhandled_key_input",ev); } + + + if (physics_object_picking && !get_scene()->input_handled) { + + if (p_event.type==InputEvent::MOUSE_BUTTON || p_event.type==InputEvent::MOUSE_MOTION || p_event.type==InputEvent::SCREEN_DRAG || p_event.type==InputEvent::SCREEN_TOUCH) { + physics_picking_events.push_back(p_event); + } + } + } void Viewport::set_use_own_world(bool p_world) { @@ -973,6 +1169,22 @@ Rect2 Viewport::get_render_target_to_screen_rect() const{ return to_screen_rect; } +void Viewport::set_physics_object_picking(bool p_enable) { + + physics_object_picking=p_enable; + set_fixed_process(physics_object_picking); + if (!physics_object_picking) + physics_picking_events.clear(); + + +} + +bool Viewport::get_physics_object_picking() { + + + return physics_object_picking; +} + void Viewport::_bind_methods() { @@ -1028,6 +1240,9 @@ void Viewport::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_render_target_texture:RenderTargetTexture"), &Viewport::get_render_target_texture); + ObjectTypeDB::bind_method(_MD("set_physics_object_picking","enable"), &Viewport::set_physics_object_picking); + ObjectTypeDB::bind_method(_MD("get_physics_object_picking"), &Viewport::get_physics_object_picking); + ObjectTypeDB::bind_method(_MD("get_viewport"), &Viewport::get_viewport); ObjectTypeDB::bind_method(_MD("input","local_event"), &Viewport::input); ObjectTypeDB::bind_method(_MD("unhandled_input","local_event"), &Viewport::unhandled_input); @@ -1037,6 +1252,7 @@ void Viewport::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_use_own_world","enable"), &Viewport::set_use_own_world); ObjectTypeDB::bind_method(_MD("is_using_own_world"), &Viewport::is_using_own_world); + ObjectTypeDB::bind_method(_MD("get_camera:Camera"), &Viewport::get_camera); ObjectTypeDB::bind_method(_MD("set_as_audio_listener","enable"), &Viewport::set_as_audio_listener); ObjectTypeDB::bind_method(_MD("is_audio_listener","enable"), &Viewport::is_audio_listener); @@ -1058,6 +1274,7 @@ void Viewport::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::INT,"render_target/update_mode",PROPERTY_HINT_ENUM,"Disabled,Once,When Visible,Always"), _SCS("set_render_target_update_mode"), _SCS("get_render_target_update_mode") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"audio_listener/enable_2d"), _SCS("set_as_audio_listener_2d"), _SCS("is_audio_listener_2d") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"audio_listener/enable_3d"), _SCS("set_as_audio_listener"), _SCS("is_audio_listener") ); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"physics/object_picking"), _SCS("set_physics_object_picking"), _SCS("get_physics_object_picking") ); ADD_SIGNAL(MethodInfo("size_changed")); @@ -1093,6 +1310,11 @@ Viewport::Viewport() { render_target_update_mode=RENDER_TARGET_UPDATE_WHEN_VISIBLE; render_target_texture = Ref<RenderTargetTexture>( memnew( RenderTargetTexture(this) ) ); + physics_object_picking=false; + physics_object_capture=0; + physics_object_over=0; + physics_last_mousepos=Vector2(1e20,1e20); + String id=itos(get_instance_ID()); input_group = "_vp_input"+id; diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 6feb89b084..5d68438f0d 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -116,6 +116,13 @@ friend class RenderTargetTexture; bool render_target_filter; bool render_target_gen_mipmaps; + bool physics_object_picking; + List<InputEvent> physics_picking_events; + ObjectID physics_object_capture; + ObjectID physics_object_over; + Vector2 physics_last_mousepos; + void _test_new_mouseover(ObjectID new_collider); + void _update_rect(); void _parent_resized(); @@ -234,6 +241,9 @@ public: void set_render_target_to_screen_rect(const Rect2& p_rect); Rect2 get_render_target_to_screen_rect() const; + void set_physics_object_picking(bool p_enable); + bool get_physics_object_picking(); + Viewport(); ~Viewport(); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index f7d6a246e6..08e6ff2e54 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -199,7 +199,7 @@ #include "scene/3d/proximity_group.h" #include "scene/3d/navigation_mesh.h" #include "scene/3d/navigation.h" - +#include "scene/3d/collision_polygon.h" #endif #include "scene/scene_binds.h" @@ -401,6 +401,7 @@ void register_scene_types() { ObjectTypeDB::register_virtual_type<CollisionObject>(); ObjectTypeDB::register_type<StaticBody>(); ObjectTypeDB::register_type<RigidBody>(); + ObjectTypeDB::register_type<KinematicBody>(); ObjectTypeDB::register_type<CarBody>(); ObjectTypeDB::register_type<CarWheel>(); ObjectTypeDB::register_type<VehicleBody>(); @@ -408,6 +409,7 @@ void register_scene_types() { ObjectTypeDB::register_type<Area>(); ObjectTypeDB::register_type<ProximityGroup>(); ObjectTypeDB::register_type<CollisionShape>(); + ObjectTypeDB::register_type<CollisionPolygon>(); ObjectTypeDB::register_type<RayCast>(); ObjectTypeDB::register_virtual_type<EditableShape>(); ObjectTypeDB::register_type<EditableSphere>(); @@ -443,9 +445,17 @@ void register_scene_types() { //ObjectTypeDB::register_type<BodyVolumeBox>(); //ObjectTypeDB::register_type<BodyVolumeCylinder>(); //ObjectTypeDB::register_type<BodyVolumeCapsule>(); - //ObjectTypeDB::register_virtual_type<PhysicsJoint>(); //ObjectTypeDB::register_type<PhysicsJointPin>(); + + ObjectTypeDB::register_virtual_type<Joint>(); + ObjectTypeDB::register_type<PinJoint>(); + ObjectTypeDB::register_type<HingeJoint>(); + ObjectTypeDB::register_type<SliderJoint>(); + ObjectTypeDB::register_type<ConeTwistJoint>(); + ObjectTypeDB::register_type<Generic6DOFJoint>(); + + ObjectTypeDB::register_type<StreamPlayer>(); ObjectTypeDB::register_type<EventPlayer>(); diff --git a/scene/resources/video_stream.h b/scene/resources/video_stream.h index 32bc8670f0..eafacce159 100644 --- a/scene/resources/video_stream.h +++ b/scene/resources/video_stream.h @@ -33,19 +33,37 @@ -class VideoStream : public AudioStreamResampled { +class VideoStream : public Resource { - OBJ_TYPE(VideoStream,AudioStreamResampled); + OBJ_TYPE(VideoStream,Resource); protected: static void _bind_methods(); public: + virtual void stop()=0; + virtual void play()=0; + + virtual bool is_playing() const=0; + + virtual void set_paused(bool p_paused)=0; + virtual bool is_paused(bool p_paused) const=0; + + virtual void set_loop(bool p_enable)=0; + virtual bool has_loop() const=0; + + virtual float get_length() const=0; + + virtual float get_pos() const=0; + virtual void seek_pos(float p_time)=0; + virtual int get_pending_frame_count() const=0; virtual Image pop_frame()=0; virtual Image peek_frame() const=0; + virtual void update(float p_time)=0; + VideoStream(); }; diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp index 0576d5a5b1..1d99eb6d1f 100644 --- a/scene/scene_string_names.cpp +++ b/scene/scene_string_names.cpp @@ -144,5 +144,7 @@ SceneStringNames::SceneStringNames() { baked_light_changed = StaticCString::create("baked_light_changed"); _baked_light_changed = StaticCString::create("_baked_light_changed"); + _mouse_enter=StaticCString::create("_mouse_enter"); + _mouse_exit=StaticCString::create("_mouse_exit"); } diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h index d4de0555ed..dd4f8789c2 100644 --- a/scene/scene_string_names.h +++ b/scene/scene_string_names.h @@ -152,6 +152,10 @@ public: StringName baked_light_changed; StringName _baked_light_changed; + StringName _mouse_enter; + StringName _mouse_exit; + + }; |