diff options
Diffstat (limited to 'scene')
88 files changed, 3685 insertions, 4932 deletions
diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp index ded86702ef..819b06e095 100644 --- a/scene/2d/particles_2d.cpp +++ b/scene/2d/particles_2d.cpp @@ -507,7 +507,13 @@ void Particles2D::_notification(int p_what) { } - for(int i=0;i<particle_count;i++) { + int start_particle = (int)(time * (float)particle_count / lifetime); + + for (int id=0;id<particle_count;++id) { + int i = start_particle + id; + if (i >= particle_count) { + i -= particle_count; + } Particle &p=pdata[i]; if (!p.active) diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 78b5e23da0..308aa8402f 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -250,7 +250,7 @@ void RigidBody2D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap if (!E) { E = contact_monitor->body_map.insert(objid,BodyState()); - E->get().rc=0; +// E->get().rc=0; E->get().in_scene=node && node->is_inside_scene(); if (node) { node->connect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene,make_binds(objid)); @@ -260,8 +260,9 @@ void RigidBody2D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap } } + //E->get().rc++; } - E->get().rc++; + if (node) E->get().shapes.insert(ShapePair(p_body_shape,p_local_shape)); @@ -272,24 +273,26 @@ void RigidBody2D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap } else { - E->get().rc--; + //E->get().rc--; if (node) E->get().shapes.erase(ShapePair(p_body_shape,p_local_shape)); - if (E->get().rc==0) { + bool in_scene = E->get().in_scene; + + if (E->get().shapes.empty()) { if (node) { node->disconnect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene); node->disconnect(SceneStringNames::get_singleton()->exit_scene,this,SceneStringNames::get_singleton()->_body_exit_scene); - if (E->get().in_scene) + if (in_scene) emit_signal(SceneStringNames::get_singleton()->body_exit,obj); } contact_monitor->body_map.erase(E); } - if (node && E->get().in_scene) { + if (node && in_scene) { emit_signal(SceneStringNames::get_singleton()->body_exit_shape,objid,obj,p_body_shape,p_local_shape); } @@ -381,6 +384,7 @@ void RigidBody2D::_direct_state_changed(Object *p_state) { //process remotions + for(int i=0;i<toremove_count;i++) { _body_inout(0,toremove[i].body_id,toremove[i].pair.body_shape,toremove[i].pair.local_shape); @@ -388,6 +392,7 @@ void RigidBody2D::_direct_state_changed(Object *p_state) { //process aditions + for(int i=0;i<toadd_count;i++) { _body_inout(1,toadd[i].id,toadd[i].shape,toadd[i].local_shape); @@ -920,6 +925,8 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { normal=rest_info.normal; collider=rest_info.collider_id; collider_vel=rest_info.linear_velocity; + collider_shape=rest_info.shape; + collider_metadata=rest_info.metadata; } } @@ -1008,6 +1015,20 @@ ObjectID KinematicBody2D::get_collider() const { return collider; } + +int KinematicBody2D::get_collider_shape() const { + + ERR_FAIL_COND_V(!colliding,0); + return collider_shape; +} + +Variant KinematicBody2D::get_collider_metadata() const { + + ERR_FAIL_COND_V(!colliding,0); + return collider_metadata; + +} + void KinematicBody2D::set_collide_with_static_bodies(bool p_enable) { collide_static=p_enable; @@ -1071,6 +1092,8 @@ void KinematicBody2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_collision_normal"),&KinematicBody2D::get_collision_normal); ObjectTypeDB::bind_method(_MD("get_collider_velocity"),&KinematicBody2D::get_collider_velocity); ObjectTypeDB::bind_method(_MD("get_collider:Object"),&KinematicBody2D::_get_collider); + ObjectTypeDB::bind_method(_MD("get_collider_shape"),&KinematicBody2D::get_collider_shape); + ObjectTypeDB::bind_method(_MD("get_collider_metadata"),&KinematicBody2D::get_collider_metadata); ObjectTypeDB::bind_method(_MD("set_collide_with_static_bodies","enable"),&KinematicBody2D::set_collide_with_static_bodies); @@ -1107,6 +1130,8 @@ KinematicBody2D::KinematicBody2D() : PhysicsBody2D(Physics2DServer::BODY_MODE_KI colliding=false; collider=0; + collider_shape=0; + margin=0.08; } KinematicBody2D::~KinematicBody2D() { diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index 7e3fd978a0..e429ca1432 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -156,7 +156,7 @@ private: }; struct BodyState { - int rc; + //int rc; bool in_scene; VSet<ShapePair> shapes; }; @@ -254,7 +254,8 @@ class KinematicBody2D : public PhysicsBody2D { Vector2 normal; Vector2 collider_vel; ObjectID collider; - + int collider_shape; + Variant collider_metadata; Variant _get_collider() const; @@ -273,6 +274,8 @@ public: Vector2 get_collision_normal() const; Vector2 get_collider_velocity() const; ObjectID get_collider() const; + int get_collider_shape() const; + Variant get_collider_metadata() const; void set_collide_with_static_bodies(bool p_enable); bool can_collide_with_static_bodies() const; diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp index 7d033ed87f..8c3bbfdfc9 100644 --- a/scene/2d/sprite.cpp +++ b/scene/2d/sprite.cpp @@ -64,20 +64,20 @@ void Sprite::_notification(int p_what) { break; */ - Size2i s; - Rect2i src_rect; + Size2 s; + Rect2 src_rect; if (region) { s=region_rect.size; src_rect=region_rect; } else { - s = texture->get_size(); - s=s/Size2i(hframes,vframes); + s = Size2(texture->get_size()); + s=s/Size2(hframes,vframes); src_rect.size=s; - src_rect.pos.x+=(frame%hframes)*s.x; - src_rect.pos.y+=(frame/hframes)*s.y; + src_rect.pos.x+=float(frame%hframes)*s.x; + src_rect.pos.y+=float(frame/hframes)*s.y; } @@ -85,7 +85,7 @@ void Sprite::_notification(int p_what) { if (centered) ofs-=s/2; - Rect2i dst_rect(ofs,s); + Rect2 dst_rect(ofs,s); if (hflip) dst_rect.size.x=-dst_rect.size.x; diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 6403454588..eb04ca924f 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -106,9 +106,9 @@ Ref<TileSet> TileMap::get_tileset() const { return tile_set; } -void TileMap::set_cell_size(int p_size) { +void TileMap::set_cell_size(Size2 p_size) { - ERR_FAIL_COND(p_size<1); + ERR_FAIL_COND(p_size.x<1 || p_size.y<1); _clear_quadrants(); cell_size=p_size; @@ -117,7 +117,7 @@ void TileMap::set_cell_size(int p_size) { } -int TileMap::get_cell_size() const { +Size2 TileMap::get_cell_size() const { return cell_size; } @@ -171,6 +171,7 @@ void TileMap::_update_dirty_quadrants() { VisualServer *vs = VisualServer::get_singleton(); Physics2DServer *ps = Physics2DServer::get_singleton(); + Vector2 tofs = get_cell_draw_offset(); while (dirty_quadrant_list.first()) { @@ -178,6 +179,7 @@ void TileMap::_update_dirty_quadrants() { vs->canvas_item_clear(q.canvas_item); ps->body_clear_shapes(q.static_body); + int shape_idx=0; for(int i=0;i<q.cells.size();i++) { @@ -189,7 +191,7 @@ void TileMap::_update_dirty_quadrants() { Ref<Texture> tex = tile_set->tile_get_texture(c.id); Vector2 tile_ofs = tile_set->tile_get_texture_offset(c.id); - Vector2 offset = Point2( E->key().x, E->key().y )*cell_size - q.pos; + Vector2 offset = _map_to_world(E->key().x, E->key().y) - q.pos + tofs; if (!tex.is_valid()) continue; @@ -258,6 +260,8 @@ void TileMap::_update_dirty_quadrants() { ps->body_add_shape(q.static_body,shape->get_rid(),xform); + ps->body_set_shape_metadata(q.static_body,shape_idx++,Vector2(E->key().x,E->key().y)); + } } } @@ -299,17 +303,22 @@ void TileMap::_recompute_rect_cache() { for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) { - Rect2 r( Point2(E->key().x, E->key().y)*cell_size*quadrant_size, Size2(1,1)*cell_size*quadrant_size ); + Rect2 r; + r.pos=_map_to_world(E->key().x*quadrant_size, E->key().y*quadrant_size); + r.expand_to( _map_to_world(E->key().x*quadrant_size+quadrant_size, E->key().y*quadrant_size) ); + r.expand_to( _map_to_world(E->key().x*quadrant_size+quadrant_size, E->key().y*quadrant_size+quadrant_size) ); + r.expand_to( _map_to_world(E->key().x*quadrant_size, E->key().y*quadrant_size+quadrant_size) ); if (E==quadrant_map.front()) r_total=r; else r_total=r_total.merge(r); } + if (r_total==Rect2()) { rect_cache=Rect2(-10,-10,20,20); } else { - rect_cache=r_total; + rect_cache=r_total.grow(MAX(cell_size.x,cell_size.y)*quadrant_size); } item_rect_changed(); @@ -323,8 +332,10 @@ void TileMap::_recompute_rect_cache() { Map<TileMap::PosKey,TileMap::Quadrant>::Element *TileMap::_create_quadrant(const PosKey& p_qk) { Matrix32 xform; - xform.set_origin(Point2(p_qk.x,p_qk.y)*quadrant_size*cell_size); + //xform.set_origin(Point2(p_qk.x,p_qk.y)*cell_size*quadrant_size); Quadrant q; + q.pos = _map_to_world(p_qk.x*quadrant_size,p_qk.y*quadrant_size); + xform.set_origin( q.pos ); q.canvas_item = VisualServer::get_singleton()->canvas_item_create(); VisualServer::get_singleton()->canvas_item_set_parent( q.canvas_item, get_canvas_item() ); VisualServer::get_singleton()->canvas_item_set_transform( q.canvas_item, xform ); @@ -341,7 +352,6 @@ Map<TileMap::PosKey,TileMap::Quadrant>::Element *TileMap::_create_quadrant(const } Physics2DServer::get_singleton()->body_set_state(q.static_body,Physics2DServer::BODY_STATE_TRANSFORM,xform); - q.pos=Vector2(p_qk.x,p_qk.y)*quadrant_size*cell_size; rect_cache_dirty=true; quadrant_order_dirty=true; @@ -478,8 +488,11 @@ void TileMap::_recreate_quadrants() { } Q->get().cells.insert(E->key()); - + _make_quadrant_dirty(Q); } + + + } void TileMap::_clear_quadrants() { @@ -614,6 +627,152 @@ uint32_t TileMap::get_collision_layer_mask() const { return collision_layer; } +void TileMap::set_mode(Mode p_mode) { + + _clear_quadrants(); + mode=p_mode; + _recreate_quadrants(); + emit_signal("settings_changed"); +} + +TileMap::Mode TileMap::get_mode() const { + return mode; +} + +void TileMap::set_half_offset(HalfOffset p_half_offset) { + + _clear_quadrants(); + half_offset=p_half_offset; + _recreate_quadrants(); + emit_signal("settings_changed"); +} + +Vector2 TileMap::get_cell_draw_offset() const { + + switch(mode) { + + case MODE_SQUARE: { + + return Vector2(); + } break; + case MODE_ISOMETRIC: { + + return Vector2(-cell_size.x*0.5,0); + + } break; + case MODE_CUSTOM: { + + Vector2 min; + min.x = MIN(custom_transform[0].x,min.x); + min.y = MIN(custom_transform[0].y,min.y); + min.x = MIN(custom_transform[1].x,min.x); + min.y = MIN(custom_transform[1].y,min.y); + return min; + } break; + } + + return Vector2(); + +} + +TileMap::HalfOffset TileMap::get_half_offset() const { + return half_offset; +} + +Matrix32 TileMap::get_cell_transform() const { + + switch(mode) { + + case MODE_SQUARE: { + + Matrix32 m; + m[0]*=cell_size.x; + m[1]*=cell_size.y; + return m; + } break; + case MODE_ISOMETRIC: { + + //isometric only makes sense when y is positive in both x and y vectors, otherwise + //the drawing of tiles will overlap + Matrix32 m; + m[0]=Vector2(cell_size.x*0.5,cell_size.y*0.5); + m[1]=Vector2(-cell_size.x*0.5,cell_size.y*0.5); + return m; + + } break; + case MODE_CUSTOM: { + + return custom_transform; + } break; + } + + return Matrix32(); +} + +void TileMap::set_custom_transform(const Matrix32& p_xform) { + + _clear_quadrants(); + custom_transform=p_xform; + _recreate_quadrants(); + emit_signal("settings_changed"); + +} + +Matrix32 TileMap::get_custom_transform() const{ + + return custom_transform; +} + +Vector2 TileMap::_map_to_world(int x,int y,bool p_ignore_ofs) const { + + Vector2 ret = get_cell_transform().xform(Vector2(x,y)); + if (!p_ignore_ofs) { + switch(half_offset) { + + case HALF_OFFSET_X: { + if (ABS(y)&1) { + + ret+=get_cell_transform()[0]*0.5; + } + } break; + case HALF_OFFSET_Y: { + if (ABS(x)&1) { + ret+=get_cell_transform()[1]*0.5; + } + } break; + default: {} + } + } + return ret; +} +Vector2 TileMap::map_to_world(const Vector2& p_pos,bool p_ignore_ofs) const { + + return _map_to_world(p_pos.x,p_pos.y,p_ignore_ofs); +} +Vector2 TileMap::world_to_map(const Vector2& p_pos) const{ + + Vector2 ret = get_cell_transform().affine_inverse().xform(p_pos); + + + switch(half_offset) { + + case HALF_OFFSET_X: { + if (int(ret.y)&1) { + + ret.x-=0.5; + } + } break; + case HALF_OFFSET_Y: { + if (int(ret.x)&1) { + ret.y-=0.5; + } + } break; + default: {} + } + + return ret.floor(); +} + void TileMap::_bind_methods() { @@ -621,10 +780,21 @@ void TileMap::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_tileset","tileset:TileSet"),&TileMap::set_tileset); ObjectTypeDB::bind_method(_MD("get_tileset:TileSet"),&TileMap::get_tileset); + ObjectTypeDB::bind_method(_MD("set_mode","mode"),&TileMap::set_mode); + ObjectTypeDB::bind_method(_MD("get_mode"),&TileMap::get_mode); + + ObjectTypeDB::bind_method(_MD("set_half_offset","half_offset"),&TileMap::set_half_offset); + ObjectTypeDB::bind_method(_MD("get_half_offset"),&TileMap::get_half_offset); + + ObjectTypeDB::bind_method(_MD("set_custom_transform","custom_transform"),&TileMap::set_custom_transform); + ObjectTypeDB::bind_method(_MD("get_custom_transform"),&TileMap::get_custom_transform); ObjectTypeDB::bind_method(_MD("set_cell_size","size"),&TileMap::set_cell_size); ObjectTypeDB::bind_method(_MD("get_cell_size"),&TileMap::get_cell_size); + ObjectTypeDB::bind_method(_MD("_set_old_cell_size","size"),&TileMap::_set_old_cell_size); + ObjectTypeDB::bind_method(_MD("_get_old_cell_size"),&TileMap::_get_old_cell_size); + ObjectTypeDB::bind_method(_MD("set_quadrant_size","size"),&TileMap::set_quadrant_size); ObjectTypeDB::bind_method(_MD("get_quadrant_size"),&TileMap::get_quadrant_size); @@ -650,6 +820,9 @@ void TileMap::_bind_methods() { ObjectTypeDB::bind_method(_MD("clear"),&TileMap::clear); + ObjectTypeDB::bind_method(_MD("map_to_world","mappos","ignore_half_ofs"),&TileMap::map_to_world,DEFVAL(false)); + ObjectTypeDB::bind_method(_MD("world_to_map","worldpos"),&TileMap::world_to_map); + ObjectTypeDB::bind_method(_MD("_clear_quadrants"),&TileMap::_clear_quadrants); ObjectTypeDB::bind_method(_MD("_recreate_quadrants"),&TileMap::_recreate_quadrants); ObjectTypeDB::bind_method(_MD("_update_dirty_quadrants"),&TileMap::_update_dirty_quadrants); @@ -657,17 +830,28 @@ void TileMap::_bind_methods() { ObjectTypeDB::bind_method(_MD("_set_tile_data"),&TileMap::_set_tile_data); ObjectTypeDB::bind_method(_MD("_get_tile_data"),&TileMap::_get_tile_data); - ADD_PROPERTY( PropertyInfo(Variant::INT,"cell_size",PROPERTY_HINT_RANGE,"1,8192,1"),_SCS("set_cell_size"),_SCS("get_cell_size")); - ADD_PROPERTY( PropertyInfo(Variant::INT,"quadrant_size",PROPERTY_HINT_RANGE,"1,128,1"),_SCS("set_quadrant_size"),_SCS("get_quadrant_size")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Square,Isometric,Custom"),_SCS("set_mode"),_SCS("get_mode")); ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"tile_set",PROPERTY_HINT_RESOURCE_TYPE,"TileSet"),_SCS("set_tileset"),_SCS("get_tileset")); - ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"tile_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_tile_data"),_SCS("_get_tile_data")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"cell_size",PROPERTY_HINT_RANGE,"1,8192,1",0),_SCS("_set_old_cell_size"),_SCS("_get_old_cell_size")); + ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"cell/size",PROPERTY_HINT_RANGE,"1,8192,1"),_SCS("set_cell_size"),_SCS("get_cell_size")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/quadrant_size",PROPERTY_HINT_RANGE,"1,128,1"),_SCS("set_quadrant_size"),_SCS("get_quadrant_size")); + ADD_PROPERTY( PropertyInfo(Variant::MATRIX32,"cell/custom_transform"),_SCS("set_custom_transform"),_SCS("get_custom_transform")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/half_offset",PROPERTY_HINT_ENUM,"Offset X,Offset Y,Disabled"),_SCS("set_half_offset"),_SCS("get_half_offset")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_friction"),_SCS("get_collision_friction")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_bounce"),_SCS("get_collision_bounce")); ADD_PROPERTY( PropertyInfo(Variant::INT,"collision/layers",PROPERTY_HINT_ALL_FLAGS),_SCS("set_collision_layer_mask"),_SCS("get_collision_layer_mask")); + ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"tile_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_tile_data"),_SCS("_get_tile_data")); ADD_SIGNAL(MethodInfo("settings_changed")); BIND_CONSTANT( INVALID_CELL ); + BIND_CONSTANT( MODE_SQUARE ); + BIND_CONSTANT( MODE_ISOMETRIC ); + BIND_CONSTANT( MODE_CUSTOM ); + BIND_CONSTANT( HALF_OFFSET_X ); + BIND_CONSTANT( HALF_OFFSET_Y ); + BIND_CONSTANT( HALF_OFFSET_DISABLED ); + } TileMap::TileMap() { @@ -678,12 +862,14 @@ TileMap::TileMap() { pending_update=false; quadrant_order_dirty=false; quadrant_size=16; - cell_size=64; + cell_size=Size2(64,64); center_x=false; center_y=false; collision_layer=1; friction=1; bounce=0; + mode=MODE_SQUARE; + half_offset=HALF_OFFSET_DISABLED; fp_adjust=0.01; fp_adjust=0.01; diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index d21437e30f..4e9e2e7e97 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -37,12 +37,30 @@ class TileMap : public Node2D { OBJ_TYPE( TileMap, Node2D ); +public: + + enum Mode { + MODE_SQUARE, + MODE_ISOMETRIC, + MODE_CUSTOM + }; + + enum HalfOffset { + HALF_OFFSET_X, + HALF_OFFSET_Y, + HALF_OFFSET_DISABLED, + }; +private: Ref<TileSet> tile_set; - int cell_size; + Size2i cell_size; int quadrant_size; bool center_x,center_y; + Mode mode; + Matrix32 custom_transform; + HalfOffset half_offset; + union PosKey { @@ -117,6 +135,12 @@ class TileMap : public Node2D { void _set_tile_data(const DVector<int>& p_data); DVector<int> _get_tile_data() const; + + void _set_old_cell_size(int p_size) { set_cell_size(Size2(p_size,p_size)); } + int _get_old_cell_size() const { return cell_size.x; } + + _FORCE_INLINE_ Vector2 _map_to_world(int p_x,int p_y,bool p_ignore_ofs=false) const; + protected: @@ -132,8 +156,8 @@ public: void set_tileset(const Ref<TileSet>& p_tileset); Ref<TileSet> get_tileset() const; - void set_cell_size(int p_size); - int get_cell_size() const; + void set_cell_size(Size2 p_size); + Size2 get_cell_size() const; void set_quadrant_size(int p_size); int get_quadrant_size() const; @@ -159,10 +183,28 @@ public: void set_collision_bounce(float p_bounce); float get_collision_bounce() const; + void set_mode(Mode p_mode); + Mode get_mode() const; + + void set_half_offset(HalfOffset p_half_offset); + HalfOffset get_half_offset() const; + + void set_custom_transform(const Matrix32& p_xform); + Matrix32 get_custom_transform() const; + + Matrix32 get_cell_transform() const; + Vector2 get_cell_draw_offset() const; + + Vector2 map_to_world(const Vector2& p_pos, bool p_ignore_ofs=false) const; + Vector2 world_to_map(const Vector2& p_pos) const; + void clear(); TileMap(); ~TileMap(); }; +VARIANT_ENUM_CAST(TileMap::Mode); +VARIANT_ENUM_CAST(TileMap::HalfOffset); + #endif // TILE_MAP_H diff --git a/scene/2d/y_sort.cpp b/scene/2d/y_sort.cpp new file mode 100644 index 0000000000..d441abfaf1 --- /dev/null +++ b/scene/2d/y_sort.cpp @@ -0,0 +1,29 @@ +#include "y_sort.h" + + + +void YSort::set_sort_enabled(bool p_enabled) { + + sort_enabled=p_enabled; + VS::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(),sort_enabled); +} + +bool YSort::is_sort_enabled() const { + + return sort_enabled; +} + +void YSort::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_sort_enabled","enabled"),&YSort::set_sort_enabled); + ObjectTypeDB::bind_method(_MD("is_sort_enabled"),&YSort::is_sort_enabled); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"sort/enabled"),_SCS("set_sort_enabled"),_SCS("is_sort_enabled")); +} + + +YSort::YSort() { + + sort_enabled=true; + VS::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(),true); +} diff --git a/scene/2d/y_sort.h b/scene/2d/y_sort.h new file mode 100644 index 0000000000..6d04a67e42 --- /dev/null +++ b/scene/2d/y_sort.h @@ -0,0 +1,17 @@ +#ifndef Y_SORT_H +#define Y_SORT_H + +#include "scene/2d/node_2d.h" + +class YSort : public Node2D { + OBJ_TYPE(YSort,Node2D); + bool sort_enabled; + static void _bind_methods(); +public: + + void set_sort_enabled(bool p_enabled); + bool is_sort_enabled() const; + YSort(); +}; + +#endif // Y_SORT_H diff --git a/scene/3d/SCsub b/scene/3d/SCsub index 6789851aab..3c2144bedc 100644 --- a/scene/3d/SCsub +++ b/scene/3d/SCsub @@ -1,7 +1,6 @@ Import('env') -print("V: "+env["disable_3d"]) if (env["disable_3d"]=="yes"): env.scene_sources.append("3d/spatial.cpp") diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp index f5895453cc..7370c36eb7 100644 --- a/scene/3d/area.cpp +++ b/scene/3d/area.cpp @@ -255,16 +255,6 @@ 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() { @@ -289,8 +279,6 @@ 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); @@ -310,7 +298,6 @@ 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")); } @@ -323,7 +310,7 @@ Area::Area() : CollisionObject(PhysicsServer::get_singleton()->area_create(),tru density=0.1; priority=0; monitoring=false; - ray_pickable=false; + set_ray_pickable(false); set_enable_monitoring(true); } diff --git a/scene/3d/area.h b/scene/3d/area.h index 92b5d39f59..5558e2c719 100644 --- a/scene/3d/area.h +++ b/scene/3d/area.h @@ -52,7 +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); @@ -109,9 +109,6 @@ 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/baked_light_instance.cpp b/scene/3d/baked_light_instance.cpp index c1cc1f6b68..b55093a779 100644 --- a/scene/3d/baked_light_instance.cpp +++ b/scene/3d/baked_light_instance.cpp @@ -63,3 +63,81 @@ BakedLightInstance::BakedLightInstance() { } +///////////////////////// + + +void BakedLightSampler::set_param(Param p_param,float p_value) { + ERR_FAIL_INDEX(p_param,PARAM_MAX); + params[p_param]=p_value; + VS::get_singleton()->baked_light_sampler_set_param(base,VS::BakedLightSamplerParam(p_param),p_value); +} + +float BakedLightSampler::get_param(Param p_param) const{ + + ERR_FAIL_INDEX_V(p_param,PARAM_MAX,0); + return params[p_param]; + +} + +void BakedLightSampler::set_resolution(int p_resolution){ + + ERR_FAIL_COND(p_resolution<4 && p_resolution>32); + resolution=p_resolution; + VS::get_singleton()->baked_light_sampler_set_resolution(base,resolution); +} +int BakedLightSampler::get_resolution() const { + + return resolution; +} + +AABB BakedLightSampler::get_aabb() const { + + float r = get_param(PARAM_RADIUS); + return AABB( Vector3(-r,-r,-r),Vector3(r*2,r*2,r*2)); +} +DVector<Face3> BakedLightSampler::get_faces(uint32_t p_usage_flags) const { + return DVector<Face3>(); +} + +void BakedLightSampler::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_param","param","value"),&BakedLightSampler::set_param); + ObjectTypeDB::bind_method(_MD("get_param","param"),&BakedLightSampler::get_param); + + ObjectTypeDB::bind_method(_MD("set_resolution","resolution"),&BakedLightSampler::set_resolution); + ObjectTypeDB::bind_method(_MD("get_resolution"),&BakedLightSampler::get_resolution); + + + BIND_CONSTANT( PARAM_RADIUS ); + BIND_CONSTANT( PARAM_STRENGTH ); + BIND_CONSTANT( PARAM_ATTENUATION ); + BIND_CONSTANT( PARAM_DETAIL_RATIO ); + BIND_CONSTANT( PARAM_MAX ); + + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/radius",PROPERTY_HINT_RANGE,"0.01,1024,0.01"),_SCS("set_param"),_SCS("get_param"),PARAM_RADIUS); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/strength",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param"),_SCS("get_param"),PARAM_STRENGTH); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/attenuation",PROPERTY_HINT_EXP_EASING),_SCS("set_param"),_SCS("get_param"),PARAM_ATTENUATION); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/detail_ratio",PROPERTY_HINT_RANGE,"0.01,1.0,0.01"),_SCS("set_param"),_SCS("get_param"),PARAM_DETAIL_RATIO); +// ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/detail_ratio",PROPERTY_HINT_RANGE,"0,20,1"),_SCS("set_param"),_SCS("get_param"),PARAM_DETAIL_RATIO); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"params/resolution",PROPERTY_HINT_RANGE,"4,32,1"),_SCS("set_resolution"),_SCS("get_resolution")); + +} + +BakedLightSampler::BakedLightSampler() { + + base = VS::get_singleton()->baked_light_sampler_create(); + set_base(base); + + params[PARAM_RADIUS]=1.0; + params[PARAM_STRENGTH]=1.0; + params[PARAM_ATTENUATION]=1.0; + params[PARAM_DETAIL_RATIO]=0.1; + resolution=16; + + +} + +BakedLightSampler::~BakedLightSampler(){ + + VS::get_singleton()->free(base); +} diff --git a/scene/3d/baked_light_instance.h b/scene/3d/baked_light_instance.h index b904ced9a7..0694c813ce 100644 --- a/scene/3d/baked_light_instance.h +++ b/scene/3d/baked_light_instance.h @@ -30,4 +30,46 @@ public: BakedLightInstance(); }; + + +class BakedLightSampler : public VisualInstance { + OBJ_TYPE(BakedLightSampler,VisualInstance); + + +public: + + enum Param { + PARAM_RADIUS=VS::BAKED_LIGHT_SAMPLER_RADIUS, + PARAM_STRENGTH=VS::BAKED_LIGHT_SAMPLER_STRENGTH, + PARAM_ATTENUATION=VS::BAKED_LIGHT_SAMPLER_ATTENUATION, + PARAM_DETAIL_RATIO=VS::BAKED_LIGHT_SAMPLER_DETAIL_RATIO, + PARAM_MAX=VS::BAKED_LIGHT_SAMPLER_MAX + }; + + + +protected: + + RID base; + float params[PARAM_MAX]; + int resolution; + static void _bind_methods(); +public: + + virtual AABB get_aabb() const; + virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const; + + void set_param(Param p_param,float p_value); + float get_param(Param p_param) const; + + void set_resolution(int p_resolution); + int get_resolution() const; + + BakedLightSampler(); + ~BakedLightSampler(); +}; + +VARIANT_ENUM_CAST( BakedLightSampler::Param ); + + #endif // BAKED_LIGHT_H diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp index 4245bfa2c9..ab28c0c8d4 100644 --- a/scene/3d/camera.cpp +++ b/scene/3d/camera.cpp @@ -219,11 +219,14 @@ void Camera::_notification(int p_what) { } + camera_group = "_vp_cameras"+itos(get_viewport()->get_instance_ID()); + add_to_group(camera_group); if (viewport_ptr) viewport_ptr->cameras.insert(this); if (current) make_current(); + } break; case NOTIFICATION_TRANSFORM_CHANGED: { @@ -241,6 +244,8 @@ void Camera::_notification(int p_what) { if (viewport_ptr) viewport_ptr->cameras.erase(this); viewport_ptr=NULL; + remove_from_group(camera_group); + } break; case NOTIFICATION_BECAME_CURRENT: { @@ -262,7 +267,7 @@ void Camera::_notification(int p_what) { Transform Camera::get_camera_transform() const { - return get_global_transform(); + return get_global_transform().orthonormalized(); } void Camera::set_perspective(float p_fovy_degrees, float p_z_near, float p_z_far) { @@ -314,6 +319,20 @@ void Camera::make_current() { //get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,camera_group,"_camera_make_current",this); } + +void Camera::_camera_make_next_current(Node *p_exclude) { + + if (this==p_exclude) + return; + if (!is_inside_scene()) + return; + if (get_viewport()->get_camera()!=NULL) + return; + + make_current(); +} + + void Camera::clear_current() { current=false; @@ -321,8 +340,12 @@ void Camera::clear_current() { return; if (viewport_ptr) { - if (viewport_ptr->get_camera()==this) + if (viewport_ptr->get_camera()==this) { viewport_ptr->_set_camera(NULL); + //a group is used beause this needs to be in order to be deterministic + get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,camera_group,"_camera_make_next_current",this); + + } } } @@ -444,7 +467,15 @@ Vector3 Camera::project_local_ray_normal(const Point2& p_pos) const { ERR_FAIL_COND_V(!is_inside_scene(),Vector3()); } + +#if 0 Size2 viewport_size = viewport_ptr->get_visible_rect().size; + Vector2 cpos = p_pos; +#else + + Size2 viewport_size = viewport_ptr->get_camera_rect_size(); + Vector2 cpos = viewport_ptr->get_camera_coords(p_pos); +#endif Vector3 ray; @@ -456,10 +487,9 @@ Vector3 Camera::project_local_ray_normal(const Point2& p_pos) const { 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(); + ray=Vector3( ((cpos.x/viewport_size.width)*2.0-1.0)*screen_w, ((1.0-(cpos.y/viewport_size.height))*2.0-1.0)*screen_h,-near).normalized(); } - return ray; }; @@ -471,8 +501,14 @@ Vector3 Camera::project_ray_origin(const Point2& p_pos) const { ERR_FAIL_COND_V(!is_inside_scene(),Vector3()); } +#if 0 Size2 viewport_size = viewport_ptr->get_visible_rect().size; + Vector2 cpos = p_pos; +#else + Size2 viewport_size = viewport_ptr->get_camera_rect_size(); + Vector2 cpos = viewport_ptr->get_camera_coords(p_pos); +#endif ERR_FAIL_COND_V( viewport_size.y == 0, Vector3() ); // float aspect = viewport_size.x / viewport_size.y; @@ -482,7 +518,7 @@ Vector3 Camera::project_ray_origin(const Point2& p_pos) const { return get_camera_transform().origin; } else { - Vector2 pos = p_pos / viewport_size; + Vector2 pos = cpos / viewport_size; float vsize,hsize; if (keep_aspect==KEEP_WIDTH) { vsize = size/viewport_size.get_aspect(); @@ -636,6 +672,7 @@ void Camera::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_environment:Environment"),&Camera::get_environment); 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_next_current"),&Camera::_camera_make_next_current); //ObjectTypeDB::bind_method( _MD("_camera_make_current"),&Camera::_camera_make_current ); BIND_CONSTANT( PROJECTION_PERSPECTIVE ); @@ -695,7 +732,7 @@ Vector<Plane> Camera::get_frustum() const { else cm.set_orthogonal(size,viewport_size.get_aspect(),near,far,keep_aspect==KEEP_WIDTH); - return cm.get_projection_planes(get_global_transform()); + return cm.get_projection_planes(get_camera_transform()); } @@ -704,7 +741,7 @@ Vector<Plane> Camera::get_frustum() const { void Camera::look_at(const Vector3& p_target, const Vector3& p_up_normal) { Transform lookat; - lookat.origin=get_global_transform().origin; + lookat.origin=get_camera_transform().origin; lookat=lookat.looking_at(p_target,p_up_normal); set_global_transform(lookat); } @@ -732,7 +769,8 @@ Camera::Camera() { mode=PROJECTION_PERSPECTIVE; set_perspective(60.0,0.1,100.0); keep_aspect=KEEP_HEIGHT; - layers=0xFFFFFFFF; + layers=0xfffff; + VisualServer::get_singleton()->camera_set_visible_layers(camera,layers); //active=false; } diff --git a/scene/3d/camera.h b/scene/3d/camera.h index 014c7cb520..bac8173bb7 100644 --- a/scene/3d/camera.h +++ b/scene/3d/camera.h @@ -66,6 +66,8 @@ private: RID camera; RID scenario_id; + String camera_group; + uint32_t layers; Viewport *viewport_ptr; @@ -74,6 +76,7 @@ private: virtual bool _can_gizmo_scale() const; virtual RES _get_gizmo_geometry() const; + void _camera_make_next_current(Node *p_exclude); //void _camera_make_current(Node *p_camera); diff --git a/scene/3d/car_body.cpp b/scene/3d/car_body.cpp deleted file mode 100644 index a21598b07c..0000000000 --- a/scene/3d/car_body.cpp +++ /dev/null @@ -1,741 +0,0 @@ -/*************************************************************************/ -/* car_body.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "car_body.h" - -#define DEG2RADMUL (Math_PI/180.0) -#define RAD2DEGMUL (180.0/Math_PI) - -void CarWheel::_notification(int p_what) { - - - if (p_what==NOTIFICATION_ENTER_SCENE) { - - if (!get_parent()) - return; - CarBody *cb = get_parent()->cast_to<CarBody>(); - if (!cb) - return; - body=cb; - local_xform=get_transform(); - cb->wheels.push_back(this); - } - if (p_what==NOTIFICATION_EXIT_SCENE) { - - if (!get_parent()) - return; - CarBody *cb = get_parent()->cast_to<CarBody>(); - if (!cb) - return; - cb->wheels.erase(this); - body=NULL; - } -} - -void CarWheel::set_side_friction(real_t p_friction) { - - side_friction=p_friction; -} -void CarWheel::set_forward_friction(real_t p_friction) { - - forward_friction=p_friction; -} -void CarWheel::set_travel(real_t p_travel) { - - travel=p_travel; - update_gizmo(); - -} -void CarWheel::set_radius(real_t p_radius) { - - radius=p_radius; - update_gizmo(); - -} -void CarWheel::set_resting_frac(real_t p_frac) { - - resting_frac=p_frac; -} -void CarWheel::set_damping_frac(real_t p_frac) { - - damping_frac=p_frac; -} -void CarWheel::set_num_rays(real_t p_rays) { - - num_rays=p_rays; -} - -real_t CarWheel::get_side_friction() const{ - - return side_friction; -} -real_t CarWheel::get_forward_friction() const{ - - return forward_friction; -} -real_t CarWheel::get_travel() const{ - - return travel; -} -real_t CarWheel::get_radius() const{ - - return radius; -} -real_t CarWheel::get_resting_frac() const{ - - return resting_frac; -} -real_t CarWheel::get_damping_frac() const{ - - return damping_frac; -} - -int CarWheel::get_num_rays() const{ - - return num_rays; -} - - -void CarWheel::update(real_t dt) { - - - if (dt <= 0.0f) - return; - - float origAngVel = angVel; - - if (locked) - { - angVel = 0; - torque = 0; - } - else - { - - float wheelMass = 0.03f * body->mass; - float inertia = 0.5f * (radius * radius) * wheelMass; - - angVel += torque * dt / inertia; - torque = 0; - - // prevent friction from reversing dir - todo do this better - // by limiting the torque - if (((origAngVel > angVelForGrip) && (angVel < angVelForGrip)) || - ((origAngVel < angVelForGrip) && (angVel > angVelForGrip))) - angVel = angVelForGrip; - - angVel += driveTorque * dt / inertia; - driveTorque = 0; - - float maxAngVel = 200; - print_line("angvel: "+rtos(angVel)); - angVel = CLAMP(angVel, -maxAngVel, maxAngVel); - - axisAngle += Math::rad2deg(dt * angVel); - } -} - -bool CarWheel::add_forces(PhysicsDirectBodyState *s) { - - - Vector3 force; - - PhysicsDirectSpaceState *space = s->get_space_state(); - - Transform world = s->get_transform() * local_xform; - - // OpenGl has differnet row/column order for matrixes than XNA has .. - //Vector3 wheelFwd = world.get_basis().get_axis(Vector3::AXIS_Z); - //Vector3 wheelFwd = RotationMatrix(mSteerAngle, worldAxis) * carBody.GetOrientation().GetCol(0); - Vector3 wheelUp = world.get_basis().get_axis(Vector3::AXIS_Y); - Vector3 wheelFwd = Matrix3(wheelUp,Math::deg2rad(steerAngle)).xform( world.get_basis().get_axis(Vector3::AXIS_Z) ); - Vector3 wheelLeft = -wheelUp.cross(wheelFwd).normalized(); - Vector3 worldPos = world.origin; - Vector3 worldAxis = wheelUp; - - // start of ray - float rayLen = 2.0f * radius + travel; - Vector3 wheelRayEnd = worldPos - radius * worldAxis; - Vector3 wheelRayBegin = wheelRayEnd + rayLen * worldAxis; - //wheelRayEnd = -rayLen * worldAxis; - - //Assert(PhysicsSystem.CurrentPhysicsSystem); - - - ///Assert(collSystem); - /// - const int maxNumRays = 32; - - int numRaysUse = MIN(num_rays, maxNumRays); - - // adjust the start position of the ray - divide the wheel into numRays+2 - // rays, but don't use the first/last. - float deltaFwd = (2.0f * radius) / (numRaysUse + 1); - float deltaFwdStart = deltaFwd; - - float fracs[maxNumRays]; - Vector3 segmentEnds[maxNumRays]; - Vector3 groundPositions[maxNumRays]; - Vector3 groundNormals[maxNumRays]; - - - lastOnFloor = false; - int bestIRay = 0; - int iRay; - - - for (iRay = 0; iRay < numRaysUse; ++iRay) - { - fracs[iRay] = 1e20; - // work out the offset relative to the middle ray - float distFwd = (deltaFwdStart + iRay * deltaFwd) - radius; - float zOffset = radius * (1.0f - (float)Math::cos( Math::deg2rad( 90.0f * (distFwd / radius)))); - - segmentEnds[iRay] = wheelRayEnd + distFwd * wheelFwd + zOffset * wheelUp; - - - PhysicsDirectSpaceState::RayResult rr; - - bool collided = space->intersect_ray(wheelRayBegin,segmentEnds[iRay],rr,body->exclude); - - - if (collided){ - lastOnFloor = true; - groundPositions[iRay]=rr.position; - groundNormals[iRay]=rr.normal; - fracs[iRay] = ((wheelRayBegin-rr.position).length() / (wheelRayBegin-wheelRayEnd).length()); - if (fracs[iRay] < fracs[bestIRay]) - bestIRay = iRay; - } - } - - - if (!lastOnFloor) - return false; - - //Assert(bestIRay < numRays); - - // use the best one - Vector3 groundPos = groundPositions[bestIRay]; - float frac = fracs[bestIRay]; - - // const Vector3 groundNormal = (worldPos - segments[bestIRay].GetEnd()).NormaliseSafe(); - // const Vector3 groundNormal = groundNormals[bestIRay]; - - - Vector3 groundNormal = worldAxis; - - if (numRaysUse > 1) - { - for (iRay = 0; iRay < numRaysUse; ++iRay) - { - if (fracs[iRay] <= 1.0f) - { - groundNormal += (1.0f - fracs[iRay]) * (worldPos - segmentEnds[iRay]); - } - } - - groundNormal.normalize(); - - } - else - { - groundNormal = groundNormals[bestIRay]; - } - - - - float spring = (body->mass/body->wheels.size()) * s->get_total_gravity().length() / (resting_frac * travel); - - float displacement = rayLen * (1.0f - frac); - displacement = CLAMP(displacement, 0, travel); - - - - float displacementForceMag = displacement * spring; - - // reduce force when suspension is par to ground - displacementForceMag *= groundNormals[bestIRay].dot(worldAxis); - - // apply damping - float damping = 2.0f * (float)Math::sqrt(spring * body->mass); - damping /= body->wheels.size(); // assume wheels act together - damping *= damping_frac; // a bit bouncy - - float upSpeed = (displacement - lastDisplacement) / s->get_step(); - - float dampingForceMag = upSpeed * damping; - - float totalForceMag = displacementForceMag + dampingForceMag; - - if (totalForceMag < 0.0f) totalForceMag = 0.0f; - - Vector3 extraForce = totalForceMag * worldAxis; - - - force += extraForce; - // side-slip friction and drive force. Work out wheel- and floor-relative coordinate frame - Vector3 groundUp = groundNormal; - Vector3 groundLeft = groundNormal.cross(wheelFwd).normalized(); - - Vector3 groundFwd = groundLeft.cross(groundUp); - - Vector3 wheelPointVel = s->get_linear_velocity() + - (s->get_angular_velocity()).cross(s->get_transform().basis.xform(local_xform.origin));// * mPos); - - Vector3 rimVel = -angVel * wheelLeft.cross(groundPos - worldPos); - wheelPointVel += rimVel; - - // if sitting on another body then adjust for its velocity. - /*if (worldBody != null) - { - Vector3 worldVel = worldBody.Velocity + - Vector3.Cross(worldBody.AngularVelocity, groundPos - worldBody.Position); - - wheelPointVel -= worldVel; - }*/ - - // sideways forces - float noslipVel = 0.2f; - float slipVel = 0.4f; - float slipFactor = 0.7f; - - float smallVel = 3; - float friction = side_friction; - - float sideVel = wheelPointVel.dot(groundLeft); - - if ((sideVel > slipVel) || (sideVel < -slipVel)) - friction *= slipFactor; - else - if ((sideVel > noslipVel) || (sideVel < -noslipVel)) - friction *= 1.0f - (1.0f - slipFactor) * (Math::absf(sideVel) - noslipVel) / (slipVel - noslipVel); - - if (sideVel < 0.0f) - friction *= -1.0f; - - if (Math::absf(sideVel) < smallVel) - friction *= Math::absf(sideVel) / smallVel; - - float sideForce = -friction * totalForceMag; - - extraForce = sideForce * groundLeft; - force += extraForce; - // fwd/back forces - friction = forward_friction; - float fwdVel = wheelPointVel.dot(groundFwd); - - if ((fwdVel > slipVel) || (fwdVel < -slipVel)) - friction *= slipFactor; - else - if ((fwdVel > noslipVel) || (fwdVel < -noslipVel)) - friction *= 1.0f - (1.0f - slipFactor) * (Math::absf(fwdVel) - noslipVel) / (slipVel - noslipVel); - - if (fwdVel < 0.0f) - friction *= -1.0f; - - if (Math::absf(fwdVel) < smallVel) - friction *= Math::absf(fwdVel) / smallVel; - - float fwdForce = -friction * totalForceMag; - - extraForce = fwdForce * groundFwd; - force += extraForce; - - - //if (!force.IsSensible()) - //{ - // TRACE_FILE_IF(ONCE_1) - // TRACE("Bad force in car wheel\n"); - // return true; - //} - - // fwd force also spins the wheel - Vector3 wheelCentreVel = s->get_linear_velocity() + - (s->get_angular_velocity()).cross(s->get_transform().basis.xform(local_xform.origin)); - - angVelForGrip = wheelCentreVel.dot(groundFwd) / radius; - torque += -fwdForce * radius; - - // add force to car -// carBody.AddWorldForce(force, groundPos); - - s->add_force(force,(groundPos-s->get_transform().origin)); - - // add force to the world - /* - if (worldBody != null && !worldBody.Immovable) - { - // todo get the position in the right place... - // also limit the velocity that this force can produce by looking at the - // mass/inertia of the other object - float maxOtherBodyAcc = 500.0f; - float maxOtherBodyForce = maxOtherBodyAcc * worldBody.Mass; - - if (force.LengthSquared() > (maxOtherBodyForce * maxOtherBodyForce)) - force *= maxOtherBodyForce / force.Length(); - - worldBody.AddWorldForce(-force, groundPos); - }*/ - - Transform wheel_xf = local_xform; - wheel_xf.origin += wheelUp * displacement; - wheel_xf.basis = wheel_xf.basis * Matrix3(Vector3(0,1,0),Math::deg2rad(steerAngle)); - //wheel_xf.basis = wheel_xf.basis * Matrix3(wheel_xf.basis[0],-Math::deg2rad(axisAngle)); - - set_transform(wheel_xf); - lastDisplacement=displacement; - return true; - -} - -void CarWheel::set_type_drive(bool p_enable) { - - type_drive=p_enable; -} - -bool CarWheel::is_type_drive() const { - - return type_drive; -} - -void CarWheel::set_type_steer(bool p_enable) { - - type_steer=p_enable; -} - -bool CarWheel::is_type_steer() const { - - return type_steer; -} - - -void CarWheel::_bind_methods() { - - ObjectTypeDB::bind_method(_MD("set_side_friction","friction"),&CarWheel::set_side_friction); - ObjectTypeDB::bind_method(_MD("set_forward_friction","friction"),&CarWheel::set_forward_friction); - ObjectTypeDB::bind_method(_MD("set_travel","distance"),&CarWheel::set_travel); - ObjectTypeDB::bind_method(_MD("set_radius","radius"),&CarWheel::set_radius); - ObjectTypeDB::bind_method(_MD("set_resting_frac","frac"),&CarWheel::set_resting_frac); - ObjectTypeDB::bind_method(_MD("set_damping_frac","frac"),&CarWheel::set_damping_frac); - ObjectTypeDB::bind_method(_MD("set_num_rays","amount"),&CarWheel::set_num_rays); - - ObjectTypeDB::bind_method(_MD("get_side_friction"),&CarWheel::get_side_friction); - ObjectTypeDB::bind_method(_MD("get_forward_friction"),&CarWheel::get_forward_friction); - ObjectTypeDB::bind_method(_MD("get_travel"),&CarWheel::get_travel); - ObjectTypeDB::bind_method(_MD("get_radius"),&CarWheel::get_radius); - ObjectTypeDB::bind_method(_MD("get_resting_frac"),&CarWheel::get_resting_frac); - ObjectTypeDB::bind_method(_MD("get_damping_frac"),&CarWheel::get_damping_frac); - ObjectTypeDB::bind_method(_MD("get_num_rays"),&CarWheel::get_num_rays); - - ObjectTypeDB::bind_method(_MD("set_type_drive","enable"),&CarWheel::set_type_drive); - ObjectTypeDB::bind_method(_MD("is_type_drive"),&CarWheel::is_type_drive); - - ObjectTypeDB::bind_method(_MD("set_type_steer","enable"),&CarWheel::set_type_steer); - ObjectTypeDB::bind_method(_MD("is_type_steer"),&CarWheel::is_type_steer); - - ADD_PROPERTY( PropertyInfo(Variant::BOOL,"type/drive"),_SCS("set_type_drive"),_SCS("is_type_drive")); - ADD_PROPERTY( PropertyInfo(Variant::BOOL,"type/steer"),_SCS("set_type_steer"),_SCS("is_type_steer")); - ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/side_friction",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_side_friction"),_SCS("get_side_friction")); - ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/forward_friction",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_forward_friction"),_SCS("get_forward_friction")); - ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/travel",PROPERTY_HINT_RANGE,"0.01,1024,0.01"),_SCS("set_travel"),_SCS("get_travel")); - ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/radius",PROPERTY_HINT_RANGE,"0.01,1024,0.01"),_SCS("set_radius"),_SCS("get_radius")); - ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/resting_frac",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_resting_frac"),_SCS("get_resting_frac")); - ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/damping_frac",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_damping_frac"),_SCS("get_damping_frac")); - ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/num_rays",PROPERTY_HINT_RANGE,"1,32,1"),_SCS("set_num_rays"),_SCS("get_num_rays")); - -} - -CarWheel::CarWheel() { - - side_friction=4.7; - forward_friction=5.0; - travel=0.2; - radius=0.4; - resting_frac=0.45; - damping_frac=0.3; - num_rays=1; - - angVel = 0.0f; - steerAngle = 0.0f; - torque = 0.0f; - driveTorque = 0.0f; - axisAngle = 0.0f; - upSpeed = 0.0f; - locked = false; - lastDisplacement = 0.0f; - lastOnFloor = false; - angVelForGrip = 0.0f; - angVelForGrip=0; - - type_drive=false; - type_steer=false; - -} - -/// - - -void CarBody::set_max_steer_angle(real_t p_angle) { - - max_steer_angle=p_angle; -} -void CarBody::set_steer_rate(real_t p_rate) { - - steer_rate=p_rate; -} -void CarBody::set_drive_torque(real_t p_torque) { - - drive_torque=p_torque; -} - -real_t CarBody::get_max_steer_angle() const{ - - return max_steer_angle; -} -real_t CarBody::get_steer_rate() const{ - - return steer_rate; -} -real_t CarBody::get_drive_torque() const{ - - return drive_torque; -} - - -void CarBody::set_target_steering(float p_steering) { - - target_steering=p_steering; -} - -void CarBody::set_target_accelerate(float p_accelerate) { - target_accelerate=p_accelerate; -} - -void CarBody::set_hand_brake(float p_amont) { - - hand_brake=p_amont; -} - -real_t CarBody::get_target_steering() const { - - return target_steering; -} -real_t CarBody::get_target_accelerate() const { - - return target_accelerate; -} -real_t CarBody::get_hand_brake() const { - - return hand_brake; -} - - -void CarBody::_direct_state_changed(Object *p_state) { - - PhysicsDirectBodyState *state=p_state->cast_to<PhysicsDirectBodyState>(); - - float dt = state->get_step(); - AABB aabb; - int drive_total=0; - for(int i=0;i<wheels.size();i++) { - CarWheel *w=wheels[i]; - if (i==0) { - aabb.pos=w->local_xform.origin; - } else { - aabb.expand_to(w->local_xform.origin); - } - if (w->type_drive) - drive_total++; - - } - // control inputs - float deltaAccelerate = dt * 4.0f; - - float dAccelerate = target_accelerate - accelerate; - dAccelerate = CLAMP(dAccelerate, -deltaAccelerate, deltaAccelerate); - accelerate += dAccelerate; - - float deltaSteering = dt * steer_rate; - float dSteering = target_steering - steering; - dSteering = CLAMP(dSteering, -deltaSteering, deltaSteering); - steering += dSteering; - - // apply these inputs - float maxTorque = drive_torque; - - float torque_div = drive_total/2; - if (torque_div>0) - maxTorque/=torque_div; - - - float alpha = ABS(max_steer_angle * steering); - float angleSgn = steering > 0.0f ? 1.0f : -1.0f; - - int wheels_on_floor=0; - - for(int i=0;i<wheels.size();i++) { - - CarWheel *w=wheels[i]; - if (w->type_drive) - w->driveTorque+=maxTorque * accelerate; - w->locked = !w->type_steer && (hand_brake > 0.5f); - - if (w->type_steer) { - //steering - - bool inner = (steering > 0 && w->local_xform.origin.x > 0) || (steering < 0 && w->local_xform.origin.x < 0); - - if (inner || alpha==0.0) { - - w->steerAngle = (angleSgn * alpha); - } else { - float dx = aabb.size.z; - float dy = aabb.size.x; - - float beta = Math::atan2(dy, dx + (dy / (float)Math::tan(Math::deg2rad(alpha)))); - beta = Math::rad2deg(beta); - w->steerAngle = (angleSgn * beta); - - } - } - - if (w->add_forces(state)) - wheels_on_floor++; - w->update(dt); - - - } - - print_line("onfloor: "+itos(wheels_on_floor)); - - - set_ignore_transform_notification(true); - set_global_transform(state->get_transform()); - linear_velocity=state->get_linear_velocity(); - angular_velocity=state->get_angular_velocity(); - //active=!state->is_sleeping(); - //if (get_script_instance()) - // get_script_instance()->call("_integrate_forces",state); - set_ignore_transform_notification(false); - - -} - -void CarBody::set_mass(real_t p_mass) { - - mass=p_mass; - PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_MASS,mass); -} - -real_t CarBody::get_mass() const{ - - return mass; -} - - -void CarBody::set_friction(real_t p_friction) { - - friction=p_friction; - PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_FRICTION,friction); -} - -real_t CarBody::get_friction() const{ - - return friction; -} - - -void CarBody::_bind_methods() { - - ObjectTypeDB::bind_method(_MD("set_max_steer_angle","value"),&CarBody::set_max_steer_angle); - ObjectTypeDB::bind_method(_MD("set_steer_rate","rate"),&CarBody::set_steer_rate); - ObjectTypeDB::bind_method(_MD("set_drive_torque","value"),&CarBody::set_drive_torque); - - ObjectTypeDB::bind_method(_MD("get_max_steer_angle"),&CarBody::get_max_steer_angle); - ObjectTypeDB::bind_method(_MD("get_steer_rate"),&CarBody::get_steer_rate); - ObjectTypeDB::bind_method(_MD("get_drive_torque"),&CarBody::get_drive_torque); - - ObjectTypeDB::bind_method(_MD("set_target_steering","amount"),&CarBody::set_target_steering); - ObjectTypeDB::bind_method(_MD("set_target_accelerate","amount"),&CarBody::set_target_accelerate); - ObjectTypeDB::bind_method(_MD("set_hand_brake","amount"),&CarBody::set_hand_brake); - - ObjectTypeDB::bind_method(_MD("get_target_steering"),&CarBody::get_target_steering); - ObjectTypeDB::bind_method(_MD("get_target_accelerate"),&CarBody::get_target_accelerate); - ObjectTypeDB::bind_method(_MD("get_hand_brake"),&CarBody::get_hand_brake); - - ObjectTypeDB::bind_method(_MD("set_mass","mass"),&CarBody::set_mass); - ObjectTypeDB::bind_method(_MD("get_mass"),&CarBody::get_mass); - - ObjectTypeDB::bind_method(_MD("set_friction","friction"),&CarBody::set_friction); - ObjectTypeDB::bind_method(_MD("get_friction"),&CarBody::get_friction); - - ObjectTypeDB::bind_method(_MD("_direct_state_changed"),&CarBody::_direct_state_changed); - - 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")); - - ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/max_steer_angle",PROPERTY_HINT_RANGE,"1,90,1"),_SCS("set_max_steer_angle"),_SCS("get_max_steer_angle")); - ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/drive_torque",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_drive_torque"),_SCS("get_drive_torque")); - ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/steer_rate",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_steer_rate"),_SCS("get_steer_rate")); - - ADD_PROPERTY( PropertyInfo(Variant::REAL,"drive/target_steering",PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_target_steering"),_SCS("get_target_steering")); - ADD_PROPERTY( PropertyInfo(Variant::REAL,"drive/target_accelerate",PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_target_accelerate"),_SCS("get_target_accelerate")); - ADD_PROPERTY( PropertyInfo(Variant::REAL,"drive/hand_brake",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_hand_brake"),_SCS("get_hand_brake")); - -} - -CarBody::CarBody() : PhysicsBody(PhysicsServer::BODY_MODE_RIGID) { - - forward_drive=true; - backward_drive=true; - max_steer_angle=30; - steer_rate=1; - drive_torque=520; - - target_steering=0; - target_accelerate=0; - hand_brake=0; - - steering=0; - accelerate=0; - - mass=1; - friction=1; - - ccd=false; -// can_sleep=true; - - - - - exclude.insert(get_rid()); - PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(),this,"_direct_state_changed"); - - -} diff --git a/scene/3d/car_body.h b/scene/3d/car_body.h deleted file mode 100644 index 87eb047bcf..0000000000 --- a/scene/3d/car_body.h +++ /dev/null @@ -1,170 +0,0 @@ -/*************************************************************************/ -/* car_body.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef CAR_BODY_H -#define CAR_BODY_H - -#include "scene/3d/physics_body.h" - - -class CarBody; - -class CarWheel : public Spatial { - - OBJ_TYPE(CarWheel,Spatial); - -friend class CarBody; - real_t side_friction; - real_t forward_friction; - real_t travel; - real_t radius; - real_t resting_frac; - real_t damping_frac; - int num_rays; - Transform local_xform; - - CarBody *body; - - float angVel; - float steerAngle; - float torque; - float driveTorque; - float axisAngle; - float upSpeed; // speed relative to the car - bool locked; - // last frame stuff - float lastDisplacement; - float angVelForGrip; - bool lastOnFloor; - - bool type_drive; - bool type_steer; - - -protected: - void update(real_t dt); - bool add_forces(PhysicsDirectBodyState *s); - void _notification(int p_what); - static void _bind_methods(); - -public: - - void set_side_friction(real_t p_friction); - void set_forward_friction(real_t p_friction); - void set_travel(real_t p_travel); - void set_radius(real_t p_radius); - void set_resting_frac(real_t p_frac); - void set_damping_frac(real_t p_frac); - void set_num_rays(real_t p_rays); - - real_t get_side_friction() const; - real_t get_forward_friction() const; - real_t get_travel() const; - real_t get_radius() const; - real_t get_resting_frac() const; - real_t get_damping_frac() const; - int get_num_rays() const; - - void set_type_drive(bool p_enable); - bool is_type_drive() const; - - void set_type_steer(bool p_enable); - bool is_type_steer() const; - - CarWheel(); - -}; - - - -class CarBody : public PhysicsBody { - - OBJ_TYPE(CarBody,PhysicsBody); - - real_t mass; - real_t friction; - - Vector3 linear_velocity; - Vector3 angular_velocity; - bool ccd; - - real_t max_steer_angle; - real_t steer_rate; - int wheel_num_rays; - real_t drive_torque; - -// control stuff - real_t target_steering; - real_t target_accelerate; - - bool forward_drive; - bool backward_drive; - - real_t steering; - real_t accelerate; - real_t hand_brake; - Set<RID> exclude; - - -friend class CarWheel; - Vector<CarWheel*> wheels; - - static void _bind_methods(); - - void _direct_state_changed(Object *p_state); -public: - - - void set_mass(real_t p_mass); - real_t get_mass() const; - - void set_friction(real_t p_friction); - real_t get_friction() const; - - void set_max_steer_angle(real_t p_angle); - void set_steer_rate(real_t p_rate); - void set_drive_torque(real_t p_torque); - - real_t get_max_steer_angle() const; - real_t get_steer_rate() const; - real_t get_drive_torque() const; - - - void set_target_steering(float p_steering); - void set_target_accelerate(float p_accelerate); - void set_hand_brake(float p_amont); - - real_t get_target_steering() const; - real_t get_target_accelerate() const; - real_t get_hand_brake() const; - - - CarBody(); -}; - -#endif // CAR_BODY_H diff --git a/scene/3d/collision_object.cpp b/scene/3d/collision_object.cpp index 06564f5c49..e9d3e73906 100644 --- a/scene/3d/collision_object.cpp +++ b/scene/3d/collision_object.cpp @@ -53,8 +53,9 @@ void CollisionObject::_notification(int p_what) { } else PhysicsServer::get_singleton()->body_set_space(rid,space); + _update_pickable(); //get space - } + }; case NOTIFICATION_TRANSFORM_CHANGED: { @@ -64,6 +65,11 @@ void CollisionObject::_notification(int p_what) { PhysicsServer::get_singleton()->body_set_state(rid,PhysicsServer::BODY_STATE_TRANSFORM,get_global_transform()); } break; + case NOTIFICATION_VISIBILITY_CHANGED: { + + _update_pickable(); + + } break; case NOTIFICATION_EXIT_WORLD: { if (area) { @@ -91,11 +97,11 @@ void CollisionObject::_update_shapes() { continue; if (area) PhysicsServer::get_singleton()->area_add_shape(rid,shapes[i].shape->get_rid(),shapes[i].xform); - else { + else { PhysicsServer::get_singleton()->body_add_shape(rid,shapes[i].shape->get_rid(),shapes[i].xform); - if (shapes[i].trigger) - PhysicsServer::get_singleton()->body_set_shape_as_trigger(rid,i,shapes[i].trigger); - } + if (shapes[i].trigger) + PhysicsServer::get_singleton()->body_set_shape_as_trigger(rid,i,shapes[i].trigger); + } } } @@ -160,18 +166,18 @@ void CollisionObject::_get_property_list( List<PropertyInfo> *p_list) const { String path="shapes/"+itos(i)+"/"; p_list->push_back( PropertyInfo(Variant::OBJECT,path+"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape",PROPERTY_USAGE_NOEDITOR) ); p_list->push_back( PropertyInfo(Variant::TRANSFORM,path+"transform",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) ); - p_list->push_back( PropertyInfo(Variant::BOOL,path+"trigger",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) ); + p_list->push_back( PropertyInfo(Variant::BOOL,path+"trigger",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) ); } } -void CollisionObject::_input_event(const InputEvent& p_input_event,const Vector3& p_pos, const Vector3& p_normal, int p_shape) { +void CollisionObject::_input_event(Node *p_camera, 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); + get_script_instance()->call(SceneStringNames::get_singleton()->_input_event,p_camera,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); + emit_signal(SceneStringNames::get_singleton()->input_event,p_camera,p_input_event,p_pos,p_normal,p_shape); } void CollisionObject::_mouse_enter() { @@ -192,6 +198,28 @@ void CollisionObject::_mouse_exit() { } +void CollisionObject::_update_pickable() { + if (!is_inside_scene()) + return; + bool pickable = ray_pickable && is_inside_scene() && is_visible(); + if (area) + PhysicsServer::get_singleton()->area_set_ray_pickable(rid,pickable); + else + PhysicsServer::get_singleton()->body_set_ray_pickable(rid,pickable); +} + +void CollisionObject::set_ray_pickable(bool p_ray_pickable) { + + ray_pickable=p_ray_pickable; + _update_pickable(); + +} + +bool CollisionObject::is_ray_pickable() const { + + return ray_pickable; +} + void CollisionObject::_bind_methods() { @@ -206,15 +234,18 @@ 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_ray_pickable","ray_pickable"),&CollisionObject::set_ray_pickable); + ObjectTypeDB::bind_method(_MD("is_ray_pickable"),&CollisionObject::is_ray_pickable); 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"))); + BIND_VMETHOD( MethodInfo("_input_event",PropertyInfo(Variant::OBJECT,"camera"),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("input_event",PropertyInfo(Variant::OBJECT,"camera"),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/ray_pickable"),_SCS("set_ray_pickable"),_SCS("is_ray_pickable")); ADD_PROPERTY(PropertyInfo(Variant::BOOL,"input/capture_on_drag"),_SCS("set_capture_input_on_drag"),_SCS("get_capture_input_on_drag")); } @@ -296,6 +327,8 @@ CollisionObject::CollisionObject(RID p_rid, bool p_area) { rid=p_rid; area=p_area; + capture_input_on_drag=false; + ray_pickable=true; if (p_area) { PhysicsServer::get_singleton()->area_attach_object_instance_ID(rid,get_instance_ID()); } else { @@ -321,6 +354,7 @@ CollisionObject::CollisionObject() { capture_input_on_drag=false; + ray_pickable=true; //owner= diff --git a/scene/3d/collision_object.h b/scene/3d/collision_object.h index afd73aa9cc..eafce2c82c 100644 --- a/scene/3d/collision_object.h +++ b/scene/3d/collision_object.h @@ -51,9 +51,10 @@ class CollisionObject : public Spatial { }; bool capture_input_on_drag; - + bool ray_pickable; Vector<ShapeData> shapes; + void _update_pickable(); void _update_shapes(); friend class CollisionShape; @@ -69,7 +70,7 @@ protected: 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 _input_event(Node* p_camera,const InputEvent& p_input_event,const Vector3& p_pos, const Vector3& p_normal, int p_shape); virtual void _mouse_enter(); virtual void _mouse_exit(); @@ -87,9 +88,13 @@ 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_ray_pickable(bool p_ray_pickable); + bool is_ray_pickable() 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/editable_shape.cpp b/scene/3d/editable_shape.cpp deleted file mode 100644 index ab3f832028..0000000000 --- a/scene/3d/editable_shape.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/*************************************************************************/ -/* editable_shape.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "editable_shape.h" - - -void EditableShape::_notification(int p_what) { - - - -} - - -void EditableShape::set_bsp_tree(const BSP_Tree& p_bsp) { - - bsp=p_bsp; -} - -void EditableShape::set_shape(const Ref<Shape>& p_shape) { - - shape=p_shape; -} - - - -EditableShape::EditableShape() -{ -} - - - -///////////////////////// - - -void EditableSphere::set_radius(float p_radius) { - - radius=p_radius; - update_gizmo(); - _change_notify("params/radius"); -} - - -float EditableSphere::get_radius() const{ - - return radius; -} - - -void EditableSphere::_bind_methods() { - - ObjectTypeDB::bind_method(_MD("set_radius","radius"),&EditableSphere::set_radius); - ObjectTypeDB::bind_method(_MD("get_radius"),&EditableSphere::get_radius); - - ADD_PROPERTY( PropertyInfo(Variant::REAL,"params/radius",PROPERTY_HINT_EXP_RANGE,"0.001,16384,0.001"),_SCS("set_radius"),_SCS("get_radius")); -} - -EditableSphere::EditableSphere() { - - radius=1.0; -} diff --git a/scene/3d/editable_shape.h b/scene/3d/editable_shape.h deleted file mode 100644 index 9accea575c..0000000000 --- a/scene/3d/editable_shape.h +++ /dev/null @@ -1,73 +0,0 @@ -/*************************************************************************/ -/* editable_shape.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef EDITABLE_SHAPE_H -#define EDITABLE_SHAPE_H - -#include "scene/3d/spatial.h" -#include "scene/resources/shape.h" - -class EditableShape : public Spatial { - - OBJ_TYPE(EditableShape,Spatial); - - //can hold either of those - BSP_Tree bsp; - Ref<Shape> shape; - - void _update_parent(); -protected: - - void _notification(int p_what); - - void set_bsp_tree(const BSP_Tree& p_bsp); - void set_shape(const Ref<Shape>& p_shape); -public: - EditableShape(); -}; - - -class EditableSphere : public EditableShape { - - OBJ_TYPE( EditableSphere, EditableShape ); - - - float radius; -protected: - - static void _bind_methods(); -public: - - void set_radius(float p_radius); - float get_radius() const; - - EditableSphere(); -}; - - -#endif // EDITABLE_SHAPE_H diff --git a/scene/3d/follow_camera.cpp b/scene/3d/follow_camera.cpp deleted file mode 100644 index e7ced6c2ba..0000000000 --- a/scene/3d/follow_camera.cpp +++ /dev/null @@ -1,778 +0,0 @@ -/*************************************************************************/ -/* follow_camera.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "follow_camera.h" - - -#include "physics_body.h" -#include "scene/resources/surface_tool.h" - -void FollowCamera::_set_initial_orbit(const Vector2& p_orbit) { - - initial_orbit=p_orbit; - set_orbit(p_orbit); -} - - - -void FollowCamera::_clear_queries() { - - if (!queries_active) - return; -#if 0 - for(int i=0;i<3;i++) - PhysicsServer::get_singleton()->query_clear(clip_ray[i].query); -#endif - queries_active=false; - -} - -void FollowCamera::_compute_camera() { - - // update the transform with the next proposed transform (camera is 1 logic frame delayed) - - /* - float time = get_root_node()->get_frame_time(); - Vector3 oldp = accepted.get_origin(); - Vector3 newp = proposed.get_origin(); - - float frame_dist = time * - if (oldp.distance_to(newp) > - */ - - float time = get_process_delta_time(); - bool noblend=false; - - if (clip) { - - if ((clip_ray[0].clipped==clip_ray[2].clipped || fullclip) && clip_ray[1].clipped) { - //all have been clipped - proposed_pos=clip_ray[1].clip_pos-extraclip*(proposed_pos-target_pos).normalized(); - if (clip_ray[0].clipped) - fullclip=true; - noblend=true; - - - } else { - - - //Vector3 rel=follow_pos-target_pos; - - if (clip_ray[0].clipped && !clip_ray[2].clipped) { - - float distance = target_pos.distance_to(clip_ray[0].clip_pos); - real_t amount = 1.0-(distance/clip_len); - amount = CLAMP(amount,0,1)*autoturn_speed*time; - if (clip_ray[1].clipped) - amount*=2.0; - //rotate_rel=Matrix3(Vector3(0,1,0),amount).xform(rel); - rotate_orbit(Vector2(0,amount)); - - } else if (clip_ray[2].clipped && !clip_ray[0].clipped) { - - float distance = target_pos.distance_to(clip_ray[2].clip_pos); - real_t amount = 1.0-(distance/clip_len); - amount = CLAMP(amount,0,1)*autoturn_speed*time; - if (clip_ray[1].clipped) - amount*=2.0; - rotate_orbit(Vector2(0,-amount)); - } - - fullclip=false; - - } - } - - - Vector3 base_pos = get_global_transform().origin; - Vector3 pull_from = base_pos; - pull_from.y+=height; // height compensate - - - - Vector3 camera_target; - if (use_lookat_target) { - - camera_target = lookat_target; - } else { - camera_target = base_pos; - }; - - Transform proposed; - proposed.set_look_at(proposed_pos,camera_target,up_vector); - proposed = proposed * Transform(Matrix3(Vector3(1,0,0),Math::deg2rad(inclination)),Vector3()); //inclination - - - accepted=proposed; - if (smooth && !noblend) { - - - Vector3 vec1 = accepted.origin; - Vector3 vec2 = final.origin; - final.origin = vec2.linear_interpolate(vec1, MIN(1,smooth_pos_ratio * time));; - - Quat q1 = accepted.basis; - Quat q2 = final.basis; - final.basis = q2.slerp(q1, MIN(1,smooth_rot_ratio * time)); - - } else { - final=accepted; - } - - _update_camera(); - - // calculate the next proposed transform - - - Vector3 new_pos; - - { /*follow code*/ - - - - /* calculate some variables */ - - Vector3 rel = follow_pos - pull_from; - - float l = rel.length(); - Vector3 rel_n = (l > 0) ? (rel/l) : Vector3(); - float ang = Math::acos(rel_n.dot( Vector3(0,1,0) )); - - Vector3 tangent = rel_n; - tangent.y=0; // get rid of y - if (tangent.length_squared() < CMP_EPSILON2) - tangent=Vector3(0,0,1); // use Z as tangent if rel is parallel to y - else - tangent.normalize(); - - /* now start applying the rules */ - - //clip distance - if (l > max_distance) - l=max_distance; - if (l < min_distance) - l=min_distance; - - //fix angle - - float ang_min = Math_PI * 0.5 + Math::deg2rad(min_orbit_x); - float ang_max = Math_PI * 0.5 + Math::deg2rad(max_orbit_x); - - if (ang<ang_min) - ang=ang_min; - if (ang>ang_max) - ang=ang_max; - - /* finally, rebuild the validated camera position */ - - new_pos=Vector3(0,Math::cos(ang),0); - new_pos+=tangent*Math::sin(ang); - new_pos*=l; - new_pos+=pull_from; - follow_pos=new_pos; - - } - - proposed_pos=new_pos; - - Vector3 rel = new_pos-camera_target; - - - if (clip) { - - Vector<RID> exclude; - exclude.push_back(target_body); - - for(int i=0;i<3;i++) { - - clip_ray[i].clipped=false; - clip_ray[i].clip_pos=Vector3(); - clip_ray[i].cast_pos=camera_target; - - Vector3 cast_to = camera_target+Matrix3(Vector3(0,1,0),Math::deg2rad(autoturn_tolerance*(i-1.0))).xform(rel); - - - if (i!=1) { - - Vector3 side = rel.cross(Vector3(0,1,0)).normalized()*(i-1.0); - clip_ray[i].cast_pos+side*target_width+rel.normalized()*target_width; - - Vector3 d = -rel; - d.rotate(Vector3(0,1,0),Math::deg2rad(get_fov())*(i-1.0)); - Plane p(new_pos,new_pos+d,new_pos+Vector3(0,1,0)); //fov clipping plane, build a face and use it as plane, facing doesn't matter - Vector3 intersect; - if (p.intersects_segment(clip_ray[i].cast_pos,cast_to,&intersect)) - cast_to=intersect; - - } else { - - cast_to+=rel.normalized()*extraclip; - } - - // PhysicsServer::get_singleton()->query_intersection(clip_ray[i].query,get_world()->get_space(),exclude); - // PhysicsServer::get_singleton()->query_intersection_segment(clip_ray[i].query,clip_ray[i].cast_pos,cast_to); - - - - - } - - queries_active=true; - } else { - - _clear_queries(); - } - target_pos=camera_target; - clip_len=rel.length(); - -} - -void FollowCamera::set_use_lookat_target(bool p_use, const Vector3 &p_lookat) { - - use_lookat_target = p_use; - lookat_target = p_lookat; -}; - - -void FollowCamera::_notification(int p_what) { - - switch(p_what) { - - case NOTIFICATION_PROCESS: { - - - _compute_camera(); - } break; - - case NOTIFICATION_ENTER_WORLD: { - - set_orbit(orbit); - set_distance(distance); - - accepted=final=get_global_transform(); - proposed_pos=accepted.origin; - - target_body = RID(); -/* - Node* parent = get_parent(); - while (parent) { - PhysicsBody* p = parent->cast_to<PhysicsBody>(); - if (p) { - target_body = p->get_body(); - break; - }; - parent = parent->get_parent(); - }; -*/ - set_process(true); - - } break; - case NOTIFICATION_TRANSFORM_CHANGED: { - - } break; - case NOTIFICATION_EXIT_WORLD: { - - distance=get_distance(); - orbit=get_orbit(); - _clear_queries(); - - } break; - case NOTIFICATION_BECAME_CURRENT: { - - set_process(true); - } break; - case NOTIFICATION_LOST_CURRENT: { - - set_process(false); - _clear_queries(); - - } break; - } - -} - - - -void FollowCamera::set_orbit(const Vector2& p_orbit) { - - orbit=p_orbit; - - if(is_inside_scene()) { - - Vector3 char_pos = get_global_transform().origin; - char_pos.y+=height; - float d = char_pos.distance_to(follow_pos); - - Matrix3 m; - m.rotate(Vector3(0,1,0),orbit.y); - m.rotate(Vector3(1,0,0),orbit.x); - - follow_pos=char_pos + m.get_axis(2) * d; - - } - - update_gizmo(); - -} -void FollowCamera::set_orbit_x(float p_x) { - - orbit.x=p_x; - if(is_inside_scene()) - set_orbit(Vector2( p_x, get_orbit().y )); -} -void FollowCamera::set_orbit_y(float p_y) { - - - orbit.y=p_y; - if(is_inside_scene()) - set_orbit(Vector2( get_orbit().x, p_y )); - -} -Vector2 FollowCamera::get_orbit() const { - - - if (is_inside_scene()) { - - Vector3 char_pos = get_global_transform().origin; - char_pos.y+=height; - Vector3 rel = (follow_pos - char_pos).normalized(); - Vector2 ret_orbit; - ret_orbit.x = Math::acos( Vector3(0,1,0).dot( rel ) ) - Math_PI * 0.5; - ret_orbit.y = Math::atan2(rel.x,rel.z); - return ret_orbit; - } - return orbit; -} - -void FollowCamera::rotate_orbit(const Vector2& p_relative) { - - if (is_inside_scene()) { - - Matrix3 m; - m.rotate(Vector3(0,1,0),Math::deg2rad(p_relative.y)); - m.rotate(Vector3(1,0,0),Math::deg2rad(p_relative.x)); - - Vector3 char_pos = get_global_transform().origin; - char_pos.y+=height; - Vector3 rel = (follow_pos - char_pos); - rel = m.xform(rel); - follow_pos=char_pos+rel; - - } - - orbit+=p_relative; - update_gizmo(); -} - -void FollowCamera::set_height(float p_height) { - - - height=p_height; - update_gizmo(); -} - -float FollowCamera::get_height() const { - - return height; - -} - -void FollowCamera::set_max_orbit_x(float p_max) { - - max_orbit_x=p_max; - update_gizmo(); -} - -float FollowCamera::get_max_orbit_x() const { - - return max_orbit_x; -} - -void FollowCamera::set_min_orbit_x(float p_min) { - - min_orbit_x=p_min; - update_gizmo(); -} - -float FollowCamera::get_min_orbit_x() const { - - return min_orbit_x; -} - -float FollowCamera::get_min_distance() const { - - return min_distance; -} -float FollowCamera::get_max_distance() const { - - return max_distance; -} - -void FollowCamera::set_min_distance(float p_min) { - - min_distance=p_min; - update_gizmo(); -} - -void FollowCamera::set_max_distance(float p_max) { - - max_distance = p_max; - update_gizmo(); -} - - -void FollowCamera::set_distance(float p_distance) { - - if (is_inside_scene()) { - - Vector3 char_pos = get_global_transform().origin; - char_pos.y+=height; - Vector3 rel = (follow_pos - char_pos).normalized(); - rel*=p_distance; - follow_pos=char_pos+rel; - - } - - distance=p_distance; -} - -float FollowCamera::get_distance() const { - - if (is_inside_scene()) { - - Vector3 char_pos = get_global_transform().origin; - char_pos.y+=height; - return (follow_pos - char_pos).length(); - - } - - return distance; -} - -void FollowCamera::set_clip(bool p_enabled) { - - - clip=p_enabled; - - if (!p_enabled) - _clear_queries(); -} - -bool FollowCamera::has_clip() const { - - return clip; - -} - - -void FollowCamera::set_autoturn(bool p_enabled) { - - - autoturn=p_enabled; -} - -bool FollowCamera::has_autoturn() const { - - return autoturn; - -} - -void FollowCamera::set_autoturn_tolerance(float p_degrees) { - - - autoturn_tolerance=p_degrees; -} -float FollowCamera::get_autoturn_tolerance() const { - - - return autoturn_tolerance; -} - -void FollowCamera::set_inclination(float p_degrees) { - - - inclination=p_degrees; -} -float FollowCamera::get_inclination() const { - - - return inclination; -} - - -void FollowCamera::set_autoturn_speed(float p_speed) { - - - autoturn_speed=p_speed; -} - -float FollowCamera::get_autoturn_speed() const { - - return autoturn_speed; - -} - - -RES FollowCamera::_get_gizmo_geometry() const { - - Ref<SurfaceTool> surface_tool( memnew( SurfaceTool )); - - Ref<FixedMaterial> mat( memnew( FixedMaterial )); - - mat->set_parameter( FixedMaterial::PARAM_DIFFUSE,Color(1.0,0.5,1.0,0.3) ); - mat->set_line_width(4); - mat->set_flag(Material::FLAG_DOUBLE_SIDED,true); - mat->set_flag(Material::FLAG_UNSHADED,true); -// mat->set_hint(Material::HINT_NO_DEPTH_DRAW,true); - - surface_tool->begin(Mesh::PRIMITIVE_LINES); - surface_tool->set_material(mat); - - - int steps=16; - - Vector3 base_up = Matrix3(Vector3(1,0,0),Math::deg2rad(max_orbit_x)).get_axis(2); - Vector3 base_down = Matrix3(Vector3(1,0,0),Math::deg2rad(min_orbit_x)).get_axis(2); - - Vector3 ofs(0,height,0); - - for(int i=0;i<steps;i++) { - - - Matrix3 rot(Vector3(0,1,0),Math_PI*2*float(i)/steps); - Matrix3 rot2(Vector3(0,1,0),Math_PI*2*float(i+1)/steps); - - Vector3 up = rot.xform(base_up); - Vector3 up2 = rot2.xform(base_up); - - Vector3 down = rot.xform(base_down); - Vector3 down2 = rot2.xform(base_down); - - surface_tool->add_vertex(ofs+up*min_distance); - surface_tool->add_vertex(ofs+up*max_distance); - surface_tool->add_vertex(ofs+up*min_distance); - surface_tool->add_vertex(ofs+up2*min_distance); - surface_tool->add_vertex(ofs+up*max_distance); - surface_tool->add_vertex(ofs+up2*max_distance); - - surface_tool->add_vertex(ofs+down*min_distance); - surface_tool->add_vertex(ofs+down*max_distance); - surface_tool->add_vertex(ofs+down*min_distance); - surface_tool->add_vertex(ofs+down2*min_distance); - surface_tool->add_vertex(ofs+down*max_distance); - surface_tool->add_vertex(ofs+down2*max_distance); - - int substeps = 8; - - for(int j=0;j<substeps;j++) { - - Vector3 a = up.linear_interpolate(down,float(j)/substeps).normalized()*max_distance; - Vector3 b = up.linear_interpolate(down,float(j+1)/substeps).normalized()*max_distance; - Vector3 am = up.linear_interpolate(down,float(j)/substeps).normalized()*min_distance; - Vector3 bm = up.linear_interpolate(down,float(j+1)/substeps).normalized()*min_distance; - - surface_tool->add_vertex(ofs+a); - surface_tool->add_vertex(ofs+b); - surface_tool->add_vertex(ofs+am); - surface_tool->add_vertex(ofs+bm); - - } - } - - - return surface_tool->commit(); - - -} - - -void FollowCamera::_bind_methods() { - - ObjectTypeDB::bind_method(_MD("_set_initial_orbit","orbit"),&FollowCamera::_set_initial_orbit); - ObjectTypeDB::bind_method(_MD("set_orbit","orbit"),&FollowCamera::set_orbit); - ObjectTypeDB::bind_method(_MD("get_orbit"),&FollowCamera::get_orbit); - ObjectTypeDB::bind_method(_MD("set_orbit_x","x"),&FollowCamera::set_orbit_x); - ObjectTypeDB::bind_method(_MD("set_orbit_y","y"),&FollowCamera::set_orbit_y); - ObjectTypeDB::bind_method(_MD("set_min_orbit_x","x"),&FollowCamera::set_min_orbit_x); - ObjectTypeDB::bind_method(_MD("get_min_orbit_x"),&FollowCamera::get_min_orbit_x); - ObjectTypeDB::bind_method(_MD("set_max_orbit_x","x"),&FollowCamera::set_max_orbit_x); - ObjectTypeDB::bind_method(_MD("get_max_orbit_x"),&FollowCamera::get_max_orbit_x); - ObjectTypeDB::bind_method(_MD("set_height","height"),&FollowCamera::set_height); - ObjectTypeDB::bind_method(_MD("get_height"),&FollowCamera::get_height); - ObjectTypeDB::bind_method(_MD("set_inclination","inclination"),&FollowCamera::set_inclination); - ObjectTypeDB::bind_method(_MD("get_inclination"),&FollowCamera::get_inclination); - - ObjectTypeDB::bind_method(_MD("rotate_orbit"),&FollowCamera::rotate_orbit); - ObjectTypeDB::bind_method(_MD("set_distance","distance"),&FollowCamera::set_distance); - ObjectTypeDB::bind_method(_MD("get_distance"),&FollowCamera::get_distance); - ObjectTypeDB::bind_method(_MD("set_max_distance","max_distance"),&FollowCamera::set_max_distance); - ObjectTypeDB::bind_method(_MD("get_max_distance"),&FollowCamera::get_max_distance); - ObjectTypeDB::bind_method(_MD("set_min_distance","min_distance"),&FollowCamera::set_min_distance); - ObjectTypeDB::bind_method(_MD("get_min_distance"),&FollowCamera::get_min_distance); - ObjectTypeDB::bind_method(_MD("set_clip","enable"),&FollowCamera::set_clip); - ObjectTypeDB::bind_method(_MD("has_clip"),&FollowCamera::has_clip); - ObjectTypeDB::bind_method(_MD("set_autoturn","enable"),&FollowCamera::set_autoturn); - ObjectTypeDB::bind_method(_MD("has_autoturn"),&FollowCamera::has_autoturn); - ObjectTypeDB::bind_method(_MD("set_autoturn_tolerance","degrees"),&FollowCamera::set_autoturn_tolerance); - ObjectTypeDB::bind_method(_MD("get_autoturn_tolerance"),&FollowCamera::get_autoturn_tolerance); - ObjectTypeDB::bind_method(_MD("set_autoturn_speed","speed"),&FollowCamera::set_autoturn_speed); - ObjectTypeDB::bind_method(_MD("get_autoturn_speed"),&FollowCamera::get_autoturn_speed); - ObjectTypeDB::bind_method(_MD("set_smoothing","enable"),&FollowCamera::set_smoothing); - ObjectTypeDB::bind_method(_MD("has_smoothing"),&FollowCamera::has_smoothing); - ObjectTypeDB::bind_method(_MD("set_rotation_smoothing","amount"),&FollowCamera::set_rotation_smoothing); - ObjectTypeDB::bind_method(_MD("get_rotation_smoothing"),&FollowCamera::get_rotation_smoothing); - ObjectTypeDB::bind_method(_MD("set_translation_smoothing","amount"),&FollowCamera::set_translation_smoothing); - ObjectTypeDB::bind_method(_MD("get_translation_smoothing"),&FollowCamera::get_translation_smoothing); - ObjectTypeDB::bind_method(_MD("set_use_lookat_target","use","lookat"),&FollowCamera::set_use_lookat_target, DEFVAL(Vector3())); - ObjectTypeDB::bind_method(_MD("set_up_vector","vector"),&FollowCamera::set_up_vector); - ObjectTypeDB::bind_method(_MD("get_up_vector"),&FollowCamera::get_up_vector); - - ObjectTypeDB::bind_method(_MD("_ray_collision"),&FollowCamera::_ray_collision); - - ADD_PROPERTY( PropertyInfo( Variant::VECTOR2, "orbit" ), _SCS("_set_initial_orbit"),_SCS("get_orbit") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "height", PROPERTY_HINT_RANGE,"-1024,1024,0.01" ), _SCS("set_height"), _SCS("get_height") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "inclination", PROPERTY_HINT_RANGE,"-90,90,0.01" ), _SCS("set_inclination"), _SCS("get_inclination") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "max_orbit_x", PROPERTY_HINT_RANGE,"-90,90,0.01" ), _SCS("set_max_orbit_x"), _SCS("get_max_orbit_x") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "min_orbit_x", PROPERTY_HINT_RANGE,"-90,90,0.01" ), _SCS("set_min_orbit_x"), _SCS("get_min_orbit_x") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "min_distance", PROPERTY_HINT_RANGE,"0,100,0.01" ), _SCS("set_min_distance"), _SCS("get_min_distance") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "max_distance", PROPERTY_HINT_RANGE,"0,100,0.01" ), _SCS("set_max_distance"), _SCS("get_max_distance") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "distance", PROPERTY_HINT_RANGE,"0.01,1024,0,01"), _SCS("set_distance"), _SCS("get_distance") ); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "clip"), _SCS("set_clip"), _SCS("has_clip") ); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "autoturn"), _SCS("set_autoturn"), _SCS("has_autoturn") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "autoturn_tolerance", PROPERTY_HINT_RANGE,"1,90,0.01") , _SCS("set_autoturn_tolerance"), _SCS("get_autoturn_tolerance") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "autoturn_speed", PROPERTY_HINT_RANGE,"1,90,0.01"), _SCS("set_autoturn_speed"), _SCS("get_autoturn_speed") ); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "smoothing"), _SCS("set_smoothing"), _SCS("has_smoothing") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "translation_smooth", PROPERTY_HINT_RANGE,"0.01,128,0.01"), _SCS("set_translation_smoothing"), _SCS("get_translation_smoothing") ); - ADD_PROPERTY( PropertyInfo( Variant::REAL, "rotation_smooth", PROPERTY_HINT_RANGE,"0.01,128,0.01"), _SCS("set_rotation_smoothing"), _SCS("get_rotation_smoothing") ); - - -} - -void FollowCamera::_ray_collision(Vector3 p_point, Vector3 p_normal, int p_subindex, ObjectID p_against,int p_idx) { - - clip_ray[p_idx].clip_pos=p_point; - clip_ray[p_idx].clipped=true; - -}; - -Transform FollowCamera::get_camera_transform() const { - - return final; -} - -void FollowCamera::set_smoothing(bool p_enable) { - - smooth=p_enable; -} - -bool FollowCamera::has_smoothing() const { - - return smooth; -} - -void FollowCamera::set_translation_smoothing(float p_amount) { - - smooth_pos_ratio=p_amount; -} -float FollowCamera::get_translation_smoothing() const { - - return smooth_pos_ratio; -} - -void FollowCamera::set_rotation_smoothing(float p_amount) { - - smooth_rot_ratio=p_amount; - -} - -void FollowCamera::set_up_vector(const Vector3& p_up) { - - up_vector=p_up; -} - -Vector3 FollowCamera::get_up_vector() const{ - - return up_vector; -} - -float FollowCamera::get_rotation_smoothing() const { - - return smooth_pos_ratio; - -} - - -FollowCamera::FollowCamera() { - - - height=1; - - orbit=Vector2(0,0); - up_vector=Vector3(0,1,0); - - distance=3; - min_distance=2; - max_distance=5; - - autoturn=true; - autoturn_tolerance=10; - autoturn_speed=80; - - min_orbit_x=-50; - max_orbit_x=70; - inclination=0; - target_width=0.3; - - clip=true; - use_lookat_target = false; - extraclip=0.3; - fullclip=false; - - smooth=true; - smooth_rot_ratio=10; - smooth_pos_ratio=10; - - - for(int i=0;i<3;i++) { -// clip_ray[i].query=PhysicsServer::get_singleton()->query_create(this, "_ray_collision", i, true); - clip_ray[i].clipped=false; - } - - queries_active=false; - - -} - -FollowCamera::~FollowCamera() { - - for(int i=0;i<3;i++) { - PhysicsServer::get_singleton()->free(clip_ray[i].query); - } - - -} diff --git a/scene/3d/follow_camera.h b/scene/3d/follow_camera.h deleted file mode 100644 index 10912eb606..0000000000 --- a/scene/3d/follow_camera.h +++ /dev/null @@ -1,180 +0,0 @@ -/*************************************************************************/ -/* follow_camera.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef FOLLOW_CAMERA_H -#define FOLLOW_CAMERA_H - -#include "scene/3d/camera.h" - -class FollowCamera : public Camera { - - OBJ_TYPE( FollowCamera, Camera ); - -private: - - - //used for follow - Vector3 follow_pos; - //used for fixed - Vector2 initial_orbit; - Vector2 orbit; - float distance; - - float height; - float target_width; - - float min_distance; - float max_distance; - - float max_orbit_x; - float min_orbit_x; - - float inclination; - float extraclip; - bool fullclip; - - bool clip; - bool autoturn; - float autoturn_tolerance; - float autoturn_speed; - - bool smooth; - float smooth_rot_ratio; - float smooth_pos_ratio; - - - - struct ClipRay { - RID query; - bool clipped; - Vector3 cast_pos; - Vector3 clip_pos; - }; - - ClipRay clip_ray[3]; - Vector3 target_pos; - float clip_len; - - Vector3 up_vector; - - - virtual RES _get_gizmo_geometry() const; - - Transform ted; - Vector3 proposed_pos; - Transform accepted; - Transform final; - RID target_body; - - bool use_lookat_target; - Vector3 lookat_target; - - void _compute_camera(); - - bool queries_active; - void _clear_queries(); - - void _set_initial_orbit(const Vector2& p_orbit); - -protected: - - virtual void _request_camera_update() {} //ignore - - void _notification(int p_what); - - static void _bind_methods(); - - void _ray_collision(Vector3 p_point, Vector3 p_normal, int p_subindex, ObjectID p_against,int p_idx); - -public: - - - void set_orbit(const Vector2& p_orbit); - void set_orbit_x(float p_x); - void set_orbit_y(float p_y); - Vector2 get_orbit() const; - - void set_height(float p_height); - float get_height() const; - - void set_inclination(float p_degrees); - float get_inclination() const; - - void set_max_orbit_x(float p_max); - float get_max_orbit_x() const; - - void set_min_orbit_x(float p_min); - float get_min_orbit_x() const; - - void rotate_orbit(const Vector2& p_relative); - - void set_distance(float p_distance); - float get_distance() const; - - float get_min_distance() const; - float get_max_distance() const; - void set_min_distance(float p_min); - void set_max_distance(float p_max); - - /** FINISH THIS AND CLEAN IT UP */ - - void set_clip(bool p_enabled); - bool has_clip() const; - - void set_autoturn(bool p_enabled); - bool has_autoturn() const; - - void set_autoturn_tolerance(float p_degrees); - float get_autoturn_tolerance() const; - - void set_autoturn_speed(float p_speed); - float get_autoturn_speed() const; - - void set_smoothing(bool p_enable); - bool has_smoothing() const; - - void set_translation_smoothing(float p_amount); - float get_translation_smoothing() const; - - void set_rotation_smoothing(float p_amount); - float get_rotation_smoothing() const; - - void set_use_lookat_target(bool p_use, const Vector3 &p_lookat = Vector3()); - - void set_up_vector(const Vector3& p_up); - Vector3 get_up_vector() const; - - virtual Transform get_camera_transform() const; - - FollowCamera(); - ~FollowCamera(); -}; - - - -#endif // FOLLOW_CAMERA_H diff --git a/scene/3d/immediate_geometry.cpp b/scene/3d/immediate_geometry.cpp index 1459f2c362..a4206894ff 100644 --- a/scene/3d/immediate_geometry.cpp +++ b/scene/3d/immediate_geometry.cpp @@ -72,6 +72,53 @@ DVector<Face3> ImmediateGeometry::get_faces(uint32_t p_usage_flags) const { return DVector<Face3>(); } + + +void ImmediateGeometry::add_sphere(int p_lats,int p_lons,float p_radius) { + + for(int i = 1; i <= p_lats; i++) { + double lat0 = Math_PI * (-0.5 + (double) (i - 1) / p_lats); + double z0 = Math::sin(lat0); + double zr0 = Math::cos(lat0); + + double lat1 = Math_PI * (-0.5 + (double) i / p_lats); + double z1 = Math::sin(lat1); + double zr1 = Math::cos(lat1); + + for(int j = p_lons; j >= 1; j--) { + + double lng0 = 2 * Math_PI * (double) (j - 1) / p_lons; + double x0 = Math::cos(lng0); + double y0 = Math::sin(lng0); + + double lng1 = 2 * Math_PI * (double) (j) / p_lons; + double x1 = Math::cos(lng1); + double y1 = Math::sin(lng1); + + + Vector3 v[4]={ + Vector3(x1 * zr0, z0, y1 *zr0), + Vector3(x1 * zr1, z1, y1 *zr1), + Vector3(x0 * zr1, z1, y0 *zr1), + Vector3(x0 * zr0, z0, y0 *zr0) + }; + +#define ADD_POINT(m_idx)\ + set_normal(v[m_idx]);\ + add_vertex(v[m_idx]*p_radius); + + ADD_POINT(0); + ADD_POINT(1); + ADD_POINT(2); + + ADD_POINT(2); + ADD_POINT(3); + ADD_POINT(0); + } + } + +} + void ImmediateGeometry::_bind_methods() { ObjectTypeDB::bind_method(_MD("begin","primitive","texture:Texture"),&ImmediateGeometry::begin); @@ -81,11 +128,14 @@ void ImmediateGeometry::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_uv","uv"),&ImmediateGeometry::set_uv); ObjectTypeDB::bind_method(_MD("set_uv2","uv"),&ImmediateGeometry::set_uv2); ObjectTypeDB::bind_method(_MD("add_vertex","color"),&ImmediateGeometry::add_vertex); + ObjectTypeDB::bind_method(_MD("add_sphere","lats","lons","radius"),&ImmediateGeometry::add_sphere); ObjectTypeDB::bind_method(_MD("end"),&ImmediateGeometry::end); ObjectTypeDB::bind_method(_MD("clear"),&ImmediateGeometry::clear); } + + ImmediateGeometry::ImmediateGeometry() { im = VisualServer::get_singleton()->immediate_create(); diff --git a/scene/3d/immediate_geometry.h b/scene/3d/immediate_geometry.h index 2db81134c6..beb8ea8214 100644 --- a/scene/3d/immediate_geometry.h +++ b/scene/3d/immediate_geometry.h @@ -31,6 +31,11 @@ public: void end(); void clear(); + + void add_sphere(int p_lats,int p_lons,float p_radius); + + + virtual AABB get_aabb() const; virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const; diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp index 1efc74e672..e51a9764f6 100644 --- a/scene/3d/light.cpp +++ b/scene/3d/light.cpp @@ -429,10 +429,42 @@ void Light::approximate_opengl_attenuation(float p_constant, float p_linear, flo } + +void Light::_update_visibility() { + + if (!is_inside_scene()) + return; + + +bool editor_ok=true; + +#ifdef TOOLS_ENABLED + if (editor_only) { + if (!get_scene()->is_editor_hint()) { + editor_ok=false; + } else { + editor_ok = (get_scene()->get_edited_scene_root() && (this==get_scene()->get_edited_scene_root() || get_owner()==get_scene()->get_edited_scene_root())); + } + } +#endif + + VS::get_singleton()->instance_light_set_enabled(get_instance(),is_visible() && enabled && editor_ok); + _change_notify("geometry/visible"); + +} + + +void Light::_notification(int p_what) { + + if (p_what==NOTIFICATION_ENTER_SCENE || p_what==NOTIFICATION_VISIBILITY_CHANGED) { + _update_visibility(); + } +} + void Light::set_enabled(bool p_enabled) { enabled=p_enabled; - VS::get_singleton()->instance_light_set_enabled(get_instance(),enabled); + _update_visibility(); } bool Light::is_enabled() const{ @@ -440,6 +472,17 @@ bool Light::is_enabled() const{ return enabled; } +void Light::set_editor_only(bool p_editor_only) { + + editor_only=p_editor_only; + _update_visibility(); +} + +bool Light::is_editor_only() const{ + + return editor_only; +} + void Light::_bind_methods() { @@ -457,9 +500,12 @@ void Light::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_bake_mode"), &Light::get_bake_mode ); ObjectTypeDB::bind_method(_MD("set_enabled","enabled"), &Light::set_enabled ); ObjectTypeDB::bind_method(_MD("is_enabled"), &Light::is_enabled ); + ObjectTypeDB::bind_method(_MD("set_editor_only","editor_only"), &Light::set_editor_only ); + ObjectTypeDB::bind_method(_MD("is_editor_only"), &Light::is_editor_only ); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "params/enabled"), _SCS("set_enabled"), _SCS("is_enabled")); + ADD_PROPERTY( PropertyInfo( Variant::BOOL, "params/editor_only"), _SCS("set_editor_only"), _SCS("is_editor_only")); ADD_PROPERTY( PropertyInfo( Variant::INT, "params/bake_mode",PROPERTY_HINT_ENUM,"Disabled,Indirect,Indirect+Shadows,Full"), _SCS("set_bake_mode"), _SCS("get_bake_mode")); ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/energy", PROPERTY_HINT_EXP_RANGE, "0,64,0.01"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_ENERGY ); /* @@ -531,6 +577,7 @@ Light::Light(VisualServer::LightType p_type) { set_project_shadows( false ); set_base(light); enabled=true; + editor_only=false; bake_mode=BAKE_MODE_DISABLED; } @@ -622,7 +669,7 @@ void SpotLight::_bind_methods() { ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_ATTENUATION ); ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/spot_angle", PROPERTY_HINT_RANGE, "0.01,89.9,0.01"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SPOT_ANGLE ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/spot_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_ATTENUATION ); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/spot_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SPOT_ATTENUATION ); } diff --git a/scene/3d/light.h b/scene/3d/light.h index 8e7395fd84..6fb57a269b 100644 --- a/scene/3d/light.h +++ b/scene/3d/light.h @@ -92,8 +92,10 @@ private: VisualServer::LightType type; bool shadows; bool enabled; + bool editor_only; Operator op; - + + void _update_visibility(); // bind helpers protected: @@ -104,6 +106,7 @@ protected: virtual RES _get_gizmo_geometry() const; static void _bind_methods(); + void _notification(int p_what); Light(VisualServer::LightType p_type); @@ -132,6 +135,9 @@ public: void set_enabled(bool p_enabled); bool is_enabled() const; + void set_editor_only(bool p_editor_only); + bool is_editor_only() const; + virtual AABB get_aabb() const; virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const; diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp index 40981d468e..72d63fa006 100644 --- a/scene/3d/mesh_instance.cpp +++ b/scene/3d/mesh_instance.cpp @@ -30,7 +30,7 @@ #include "skeleton.h" #include "physics_body.h" - +#include "body_shape.h" bool MeshInstance::_set(const StringName& p_name, const Variant& p_value) { @@ -181,6 +181,11 @@ void MeshInstance::create_trimesh_collision() { add_child(static_body); if (get_owner()) static_body->set_owner( get_owner() ); + CollisionShape *cshape = memnew( CollisionShape ); + cshape->set_shape(static_body->get_shape(0)); + static_body->add_child(cshape); + if (get_owner()) + cshape->set_owner( get_owner() ); } @@ -210,6 +215,12 @@ void MeshInstance::create_convex_collision() { add_child(static_body); if (get_owner()) static_body->set_owner( get_owner() ); + CollisionShape *cshape = memnew( CollisionShape ); + cshape->set_shape(static_body->get_shape(0)); + static_body->add_child(cshape); + if (get_owner()) + cshape->set_owner( get_owner() ); + } @@ -229,9 +240,9 @@ void MeshInstance::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_skeleton_path:NodePath"),&MeshInstance::get_skeleton_path); ObjectTypeDB::bind_method(_MD("get_aabb"),&MeshInstance::get_aabb); ObjectTypeDB::bind_method(_MD("create_trimesh_collision"),&MeshInstance::create_trimesh_collision); - ObjectTypeDB::set_method_flags("MeshInstance","create_trimesh_collision",METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); + ObjectTypeDB::set_method_flags("MeshInstance","create_trimesh_collision",METHOD_FLAGS_DEFAULT); ObjectTypeDB::bind_method(_MD("create_convex_collision"),&MeshInstance::create_convex_collision); - ObjectTypeDB::set_method_flags("MeshInstance","create_convex_collision",METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); + ObjectTypeDB::set_method_flags("MeshInstance","create_convex_collision",METHOD_FLAGS_DEFAULT); ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "mesh/mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh" ), _SCS("set_mesh"), _SCS("get_mesh")); ADD_PROPERTY( PropertyInfo (Variant::NODE_PATH, "mesh/skeleton"), _SCS("set_skeleton_path"), _SCS("get_skeleton_path")); } diff --git a/scene/3d/navigation.cpp b/scene/3d/navigation.cpp index d2abdad079..d22198d47e 100644 --- a/scene/3d/navigation.cpp +++ b/scene/3d/navigation.cpp @@ -21,6 +21,7 @@ void Navigation::_navmesh_link(int p_id) { List<Polygon>::Element *P=nm.polygons.push_back(Polygon()); Polygon &p=P->get(); + p.owner=&nm; Vector<int> poly = nm.navmesh->get_polygon(i); int plen=poly.size(); @@ -145,13 +146,14 @@ void Navigation::_navmesh_unlink(int p_id) { } -int Navigation::navmesh_create(const Ref<NavigationMesh>& p_mesh,const Transform& p_xform) { +int Navigation::navmesh_create(const Ref<NavigationMesh>& p_mesh, const Transform& p_xform, Object *p_owner) { int id = last_id++; NavMesh nm; nm.linked=false; nm.navmesh=p_mesh; nm.xform=p_xform; + nm.owner=p_owner; navmesh_map[id]=nm; _navmesh_link(id); @@ -453,6 +455,7 @@ Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vec bool use_collision=false; Vector3 closest_point; float closest_point_d=1e20; + NavMesh *closest_navmesh=NULL; for (Map<int,NavMesh>::Element*E=navmesh_map.front();E;E=E->next()) { @@ -471,10 +474,12 @@ Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vec closest_point=inters; use_collision=true; closest_point_d=p_from.distance_to(inters); + closest_navmesh=p.owner; } else if (closest_point_d > inters.distance_to(p_from)){ closest_point=inters; closest_point_d=p_from.distance_to(inters); + closest_navmesh=p.owner; } } } @@ -492,6 +497,7 @@ Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vec closest_point_d=d; closest_point=b; + closest_navmesh=p.owner; } } @@ -499,6 +505,10 @@ Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vec } } + if (closest_navmesh && closest_navmesh->owner) { + //print_line("navmesh is: "+closest_navmesh->owner->cast_to<Node>()->get_name()); + } + return closest_point; } @@ -577,7 +587,7 @@ Vector3 Navigation::get_up_vector() const{ void Navigation::_bind_methods() { - ObjectTypeDB::bind_method(_MD("navmesh_create","mesh:NavigationMesh","xform"),&Navigation::navmesh_create); + ObjectTypeDB::bind_method(_MD("navmesh_create","mesh:NavigationMesh","xform","owner"),&Navigation::navmesh_create,DEFVAL(Variant())); ObjectTypeDB::bind_method(_MD("navmesh_set_transform","id","xform"),&Navigation::navmesh_set_transform); ObjectTypeDB::bind_method(_MD("navmesh_remove","id"),&Navigation::navmesh_remove); diff --git a/scene/3d/navigation.h b/scene/3d/navigation.h index e8a97a6591..9b6cf5fbc4 100644 --- a/scene/3d/navigation.h +++ b/scene/3d/navigation.h @@ -41,6 +41,8 @@ class Navigation : public Spatial { }; + struct NavMesh; + struct Polygon { @@ -57,6 +59,8 @@ class Navigation : public Spatial { float distance; int prev_edge; + + NavMesh *owner; }; @@ -74,6 +78,7 @@ class Navigation : public Spatial { struct NavMesh { + Object *owner; Transform xform; bool linked; Ref<NavigationMesh> navmesh; @@ -124,7 +129,7 @@ public: Vector3 get_up_vector() const; //API should be as dynamic as possible - int navmesh_create(const Ref<NavigationMesh>& p_mesh,const Transform& p_xform); + int navmesh_create(const Ref<NavigationMesh>& p_mesh,const Transform& p_xform,Object* p_owner=NULL); void navmesh_set_transform(int p_id, const Transform& p_xform); void navmesh_remove(int p_id); diff --git a/scene/3d/navigation_mesh.cpp b/scene/3d/navigation_mesh.cpp index cf2e22a573..db416f24dd 100644 --- a/scene/3d/navigation_mesh.cpp +++ b/scene/3d/navigation_mesh.cpp @@ -129,7 +129,7 @@ void NavigationMeshInstance::set_enabled(bool p_enabled) { if (navmesh.is_valid()) { - nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation)); + nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation),this); } } @@ -162,7 +162,7 @@ void NavigationMeshInstance::_notification(int p_what) { if (enabled && navmesh.is_valid()) { - nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation)); + nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation),this); } break; } @@ -205,7 +205,7 @@ void NavigationMeshInstance::set_navigation_mesh(const Ref<NavigationMesh>& p_na navmesh=p_navmesh; if (navigation && navmesh.is_valid() && enabled) { - nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation)); + nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation),this); } update_gizmo(); diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index a99964cc54..15ec60514a 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -245,7 +245,7 @@ void RigidBody::_body_inout(int p_status, ObjectID p_instance, int p_body_shape, if (!E) { E = contact_monitor->body_map.insert(objid,BodyState()); - E->get().rc=0; + //E->get().rc=0; E->get().in_scene=node && node->is_inside_scene(); if (node) { node->connect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene,make_binds(objid)); @@ -256,7 +256,7 @@ void RigidBody::_body_inout(int p_status, ObjectID p_instance, int p_body_shape, } } - E->get().rc++; + //E->get().rc++; if (node) E->get().shapes.insert(ShapePair(p_body_shape,p_local_shape)); @@ -267,24 +267,26 @@ void RigidBody::_body_inout(int p_status, ObjectID p_instance, int p_body_shape, } else { - E->get().rc--; + //E->get().rc--; if (node) E->get().shapes.erase(ShapePair(p_body_shape,p_local_shape)); - if (E->get().rc==0) { + bool in_scene = E->get().in_scene; + + if (E->get().shapes.empty()) { if (node) { node->disconnect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene); node->disconnect(SceneStringNames::get_singleton()->exit_scene,this,SceneStringNames::get_singleton()->_body_exit_scene); - if (E->get().in_scene) + if (in_scene) emit_signal(SceneStringNames::get_singleton()->body_exit,obj); } contact_monitor->body_map.erase(E); } - if (node && E->get().in_scene) { + if (node && in_scene) { emit_signal(SceneStringNames::get_singleton()->body_exit_shape,objid,obj,p_body_shape,p_local_shape); } @@ -965,6 +967,7 @@ Vector3 KinematicBody::move(const Vector3& p_motion) { normal=rest.normal; collider=rest.collider_id; collider_vel=rest.linear_velocity; + collider_shape=rest.shape; } } @@ -1053,7 +1056,12 @@ ObjectID KinematicBody::get_collider() const { ERR_FAIL_COND_V(!colliding,0); return collider; } +int KinematicBody::get_collider_shape() const { + + ERR_FAIL_COND_V(!colliding,-1); + return collider_shape; +} void KinematicBody::set_collide_with_static_bodies(bool p_enable) { collide_static=p_enable; @@ -1117,6 +1125,7 @@ void KinematicBody::_bind_methods() { 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("get_collider_shape"),&KinematicBody::get_collider_shape); ObjectTypeDB::bind_method(_MD("set_collide_with_static_bodies","enable"),&KinematicBody::set_collide_with_static_bodies); @@ -1153,6 +1162,7 @@ KinematicBody::KinematicBody() : PhysicsBody(PhysicsServer::BODY_MODE_KINEMATIC) colliding=false; collider=0; margin=0.001; + collider_shape=0; } KinematicBody::~KinematicBody() { diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index 442921302e..a19ad48c87 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -162,7 +162,7 @@ private: }; struct BodyState { - int rc; + //int rc; bool in_scene; VSet<ShapePair> shapes; }; @@ -266,6 +266,8 @@ class KinematicBody : public PhysicsBody { Vector3 normal; Vector3 collider_vel; ObjectID collider; + int collider_shape; + Variant _get_collider() const; @@ -291,6 +293,7 @@ public: Vector3 get_collision_normal() const; Vector3 get_collider_velocity() const; ObjectID get_collider() const; + int get_collider_shape() const; void set_collide_with_static_bodies(bool p_enable); bool can_collide_with_static_bodies() const; diff --git a/scene/3d/physics_joint.cpp b/scene/3d/physics_joint.cpp index 341b02314d..8a79e17d87 100644 --- a/scene/3d/physics_joint.cpp +++ b/scene/3d/physics_joint.cpp @@ -66,6 +66,9 @@ void Joint::_update_joint(bool p_only_free) { joint = _configure_joint(body_a,body_b); + if (joint.is_valid()) + PhysicsServer::get_singleton()->joint_set_solver_priority(joint,solver_priority); + if (body_b && joint.is_valid()) { ba=body_a->get_rid(); @@ -107,6 +110,20 @@ NodePath Joint::get_node_b() const{ } +void Joint::set_solver_priority(int p_priority) { + + solver_priority=p_priority; + if (joint.is_valid()) + PhysicsServer::get_singleton()->joint_set_solver_priority(joint,solver_priority); + +} + +int Joint::get_solver_priority() const { + + return solver_priority; +} + + void Joint::_notification(int p_what) { switch(p_what) { @@ -117,8 +134,6 @@ void Joint::_notification(int p_what) { case NOTIFICATION_EXIT_SCENE: { if (joint.is_valid()) { _update_joint(true); - - PhysicsServer::get_singleton()->free(joint); joint=RID(); } @@ -138,9 +153,13 @@ void Joint::_bind_methods() { ObjectTypeDB::bind_method( _MD("set_node_b","node"), &Joint::set_node_b ); ObjectTypeDB::bind_method( _MD("get_node_b"), &Joint::get_node_b ); + ObjectTypeDB::bind_method( _MD("set_solver_priority","priority"), &Joint::set_solver_priority ); + ObjectTypeDB::bind_method( _MD("get_solver_priority"), &Joint::get_solver_priority ); 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") ); + ADD_PROPERTY( PropertyInfo( Variant::INT, "solver/priority",PROPERTY_HINT_RANGE,"1,8,1"), _SCS("set_solver_priority"),_SCS("get_solver_priority") ); + } @@ -148,7 +167,7 @@ void Joint::_bind_methods() { Joint::Joint() { - + solver_priority=1; } diff --git a/scene/3d/physics_joint.h b/scene/3d/physics_joint.h index 6daa06da2b..32bec1bd6f 100644 --- a/scene/3d/physics_joint.h +++ b/scene/3d/physics_joint.h @@ -44,6 +44,8 @@ class Joint : public Spatial { NodePath a; NodePath b; + int solver_priority; + protected: @@ -62,6 +64,9 @@ public: void set_node_b(const NodePath& p_node_b); NodePath get_node_b() const; + void set_solver_priority(int p_priority); + int get_solver_priority() const; + RID get_joint() const { return joint; } Joint(); diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp index 858ee4e4ad..737f7d2dce 100644 --- a/scene/3d/skeleton.cpp +++ b/scene/3d/skeleton.cpp @@ -237,6 +237,21 @@ Transform Skeleton::get_bone_transform(int p_bone) const { return bones[p_bone].pose_global * bones[p_bone].rest_global_inverse; } + +void Skeleton::set_bone_global_pose(int p_bone,const Transform& p_pose) { + + ERR_FAIL_INDEX(p_bone,bones.size()); + if (bones[p_bone].parent==-1) { + + set_bone_pose(p_bone,bones[p_bone].rest.inverse() * p_pose); + } else { + + set_bone_pose(p_bone, bones[p_bone].rest.inverse() * (get_bone_global_pose(bones[p_bone].parent).affine_inverse() * p_pose)); + + } + +} + Transform Skeleton::get_bone_global_pose(int p_bone) const { ERR_FAIL_INDEX_V(p_bone,bones.size(),Transform()); @@ -519,6 +534,7 @@ void Skeleton::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_bone_pose","bone_idx"),&Skeleton::get_bone_pose); ObjectTypeDB::bind_method(_MD("set_bone_pose","bone_idx","pose"),&Skeleton::set_bone_pose); + ObjectTypeDB::bind_method(_MD("set_bone_global_pose","bone_idx","pose"),&Skeleton::set_bone_global_pose); ObjectTypeDB::bind_method(_MD("get_bone_global_pose","bone_idx"),&Skeleton::get_bone_global_pose); ObjectTypeDB::bind_method(_MD("get_bone_custom_pose","bone_idx"),&Skeleton::get_bone_custom_pose); diff --git a/scene/3d/skeleton.h b/scene/3d/skeleton.h index 3e0ab0afd7..c61946a4c7 100644 --- a/scene/3d/skeleton.h +++ b/scene/3d/skeleton.h @@ -118,6 +118,8 @@ public: Transform get_bone_transform(int p_bone) const; Transform get_bone_global_pose(int p_bone) const; + void set_bone_global_pose(int p_bone,const Transform& p_pose); + void set_bone_enabled(int p_bone, bool p_enabled); bool is_bone_enabled(int p_bone) const; diff --git a/scene/3d/vehicle_body.cpp b/scene/3d/vehicle_body.cpp index 07abd1dcd2..4cf905e4ee 100644 --- a/scene/3d/vehicle_body.cpp +++ b/scene/3d/vehicle_body.cpp @@ -179,7 +179,7 @@ void VehicleWheel::set_damping_compression(float p_value){ } float VehicleWheel::get_damping_compression() const{ - return m_wheelsDampingRelaxation; + return m_wheelsDampingCompression; } void VehicleWheel::set_damping_relaxation(float p_value){ @@ -745,11 +745,12 @@ void VehicleBody::_update_friction(PhysicsDirectBodyState *s) { { if (engine_force != 0.f) { - rollingFriction = engine_force* s->get_step(); + rollingFriction = -engine_force* s->get_step(); } else { real_t defaultRollingFrictionImpulse = 0.f; - real_t maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse; + float cbrake = MAX(wheelInfo.m_brake,brake); + real_t maxImpulse = cbrake ? cbrake : defaultRollingFrictionImpulse; btVehicleWheelContactPoint contactPt(s,wheelInfo.m_raycastInfo.m_groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,m_forwardWS[wheel],maxImpulse); rollingFriction = _calc_rolling_friction(contactPt); } @@ -1009,9 +1010,9 @@ void VehicleBody::_bind_methods(){ 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,"motion/engine_force",PROPERTY_HINT_RANGE,"0.00,1024.0,0.01"),_SCS("set_engine_force"),_SCS("get_engine_force")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/brake",PROPERTY_HINT_RANGE,"0.0,1.0,0.01"),_SCS("set_brake"),_SCS("get_brake")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/steering",PROPERTY_HINT_RANGE,"-180,180.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")); diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp index af535e139f..398fbdea82 100644 --- a/scene/3d/visual_instance.cpp +++ b/scene/3d/visual_instance.cpp @@ -50,17 +50,24 @@ void VisualInstance::_notification(int p_what) { // CHECK ROOM Spatial * parent = get_parent_spatial(); Room *room=NULL; + bool is_geom = cast_to<GeometryInstance>(); while(parent) { room = parent->cast_to<Room>(); if (room) break; - else - parent=parent->get_parent_spatial(); + + if (is_geom && parent->cast_to<BakedLightSampler>()) { + VS::get_singleton()->instance_geometry_set_baked_light_sampler(get_instance(),parent->cast_to<BakedLightSampler>()->get_instance()); + break; + } + + parent=parent->get_parent_spatial(); } + if (room) { VisualServer::get_singleton()->instance_set_room(instance,room->get_instance()); @@ -85,6 +92,7 @@ void VisualInstance::_notification(int p_what) { VisualServer::get_singleton()->instance_set_scenario( instance, RID() ); VisualServer::get_singleton()->instance_set_room(instance,RID()); VisualServer::get_singleton()->instance_attach_skeleton( instance, RID() ); + VS::get_singleton()->instance_geometry_set_baked_light_sampler(instance, RID() ); } break; diff --git a/scene/3d/visual_instance.h b/scene/3d/visual_instance.h index bbb49a2e78..e9fefe1ba0 100644 --- a/scene/3d/visual_instance.h +++ b/scene/3d/visual_instance.h @@ -47,6 +47,7 @@ class VisualInstance : public Spatial { RID _get_visual_instance_rid() const; + protected: diff --git a/scene/SCsub b/scene/SCsub index 28fb358106..8c4f0499c4 100644 --- a/scene/SCsub +++ b/scene/SCsub @@ -15,7 +15,7 @@ SConscript('resources/SCsub'); SConscript('io/SCsub'); -lib = env.Library("scene",env.scene_sources, LIBSUFFIX=env['platform_libsuffix']) +lib = env.Library("scene",env.scene_sources) env.Prepend(LIBS=[lib]) diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 030f3f27e0..9a3c7e71ec 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -180,6 +180,10 @@ void AnimationPlayer::_get_property_list( List<PropertyInfo> *p_list) const { } +void AnimationPlayer::advance(float p_time) { + + _animation_process( p_time ); +} void AnimationPlayer::_notification(int p_what) { @@ -923,7 +927,7 @@ void AnimationPlayer::play(const StringName& p_name, float p_custom_blend, float StringName next=animation_get_next(p_name); - if (next!=StringName()) { + if (next!=StringName() && animation_set.has(next)) { queue(next); } } @@ -1227,6 +1231,8 @@ void AnimationPlayer::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_current_animation_pos"),&AnimationPlayer::get_current_animation_pos); ObjectTypeDB::bind_method(_MD("get_current_animation_length"),&AnimationPlayer::get_current_animation_length); + ObjectTypeDB::bind_method(_MD("advance","delta"),&AnimationPlayer::advance); + ADD_PROPERTY( PropertyInfo( Variant::INT, "playback/process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), _SCS("set_animation_process_mode"), _SCS("get_animation_process_mode")); ADD_PROPERTY( PropertyInfo( Variant::REAL, "playback/default_blend_time", PROPERTY_HINT_RANGE, "0,4096,0.01"), _SCS("set_default_blend_time"), _SCS("get_default_blend_time")); diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index 51c000d4d8..038c43d569 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -283,6 +283,8 @@ public: float get_current_animation_pos() const; float get_current_animation_length() const; + void advance(float p_time); + void set_root(const NodePath& p_root); NodePath get_root() const; diff --git a/scene/audio/event_player.cpp b/scene/audio/event_player.cpp index 6bad94bf0e..e5b2be53ca 100644 --- a/scene/audio/event_player.cpp +++ b/scene/audio/event_player.cpp @@ -280,8 +280,8 @@ float EventPlayer::get_channel_last_note_time(int p_channel) const { void EventPlayer::_bind_methods() { - ObjectTypeDB::bind_method(_MD("set_stream","stream:Stream"),&EventPlayer::set_stream); - ObjectTypeDB::bind_method(_MD("get_stream:Stream"),&EventPlayer::get_stream); + ObjectTypeDB::bind_method(_MD("set_stream","stream:EventStream"),&EventPlayer::set_stream); + ObjectTypeDB::bind_method(_MD("get_stream:EventStream"),&EventPlayer::get_stream); ObjectTypeDB::bind_method(_MD("play"),&EventPlayer::play); ObjectTypeDB::bind_method(_MD("stop"),&EventPlayer::stop); diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index ac2417d539..7745ce11fc 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -55,6 +55,9 @@ void BaseButton::_input_event(InputEvent p_event) { if (b.pressed) { if (!toggle_mode) { //mouse press attempt + + status.press_attempt=true; + status.pressing_inside=true; pressed(); emit_signal("pressed"); @@ -71,8 +74,15 @@ void BaseButton::_input_event(InputEvent p_event) { } + } else { + + if (status.press_attempt &&status.pressing_inside) { + pressed(); + emit_signal("pressed"); + } + status.press_attempt=false; } - + update(); break; } diff --git a/scene/gui/button_group.cpp b/scene/gui/button_group.cpp index 65cfd03505..58b323c24d 100644 --- a/scene/gui/button_group.cpp +++ b/scene/gui/button_group.cpp @@ -67,6 +67,9 @@ Array ButtonGroup::_get_button_list() const { List<BaseButton*> b; get_button_list(&b); + + b.sort_custom<Node::Comparator>(); + Array arr; arr.resize(b.size()); diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index ac0ded03ab..90393a1296 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -297,7 +297,7 @@ void AcceptDialog::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_label"),&AcceptDialog::get_label); ObjectTypeDB::bind_method(_MD("set_hide_on_ok","enabled"),&AcceptDialog::set_hide_on_ok); ObjectTypeDB::bind_method(_MD("get_hide_on_ok"),&AcceptDialog::get_hide_on_ok); - ObjectTypeDB::bind_method(_MD("add_button:Button","text","right","action"),&AcceptDialog::add_cancel,DEFVAL(false),DEFVAL("")); + ObjectTypeDB::bind_method(_MD("add_button:Button","text","right","action"),&AcceptDialog::add_button,DEFVAL(false),DEFVAL("")); ObjectTypeDB::bind_method(_MD("add_cancel:Button","name"),&AcceptDialog::add_cancel); ObjectTypeDB::bind_method(_MD("_builtin_text_entered"),&AcceptDialog::_builtin_text_entered); ObjectTypeDB::bind_method(_MD("register_text_enter:LineEdit","line_edit"),&AcceptDialog::register_text_enter); diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index b7918994d8..36940655d4 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -397,6 +397,7 @@ void Label::regenerate_word_cache() { } + if (current=='\n') { insert_newline=true; } else { @@ -446,7 +447,7 @@ void Label::regenerate_word_cache() { } - total_char_cache -= line_count + 1; // do not count new lines (including the first one) + //total_char_cache -= line_count + 1; // do not count new lines (including the first one) if (!autowrap) { @@ -535,7 +536,7 @@ void Label::set_percent_visible(float p_percent) { if (p_percent<0) set_visible_characters(-1); else - set_visible_characters(get_total_character_count()*p_percent); + set_visible_characters(get_total_character_count()*p_percent); percent_visible=p_percent; } diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index c2dc1318c9..0ba3bdb7c6 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -855,7 +855,7 @@ void PopupMenu::_bind_methods() { ObjectTypeDB::bind_method(_MD("add_item","label","id","accel"),&PopupMenu::add_item,DEFVAL(-1),DEFVAL(0)); ObjectTypeDB::bind_method(_MD("add_icon_check_item","texture","label","id","accel"),&PopupMenu::add_icon_check_item,DEFVAL(-1),DEFVAL(0)); ObjectTypeDB::bind_method(_MD("add_check_item","label","id","accel"),&PopupMenu::add_check_item,DEFVAL(-1),DEFVAL(0)); - ObjectTypeDB::bind_method(_MD("add_submenu_item","label","submenu","id"),&PopupMenu::add_check_item,DEFVAL(-1)); + ObjectTypeDB::bind_method(_MD("add_submenu_item","label","submenu","id"),&PopupMenu::add_submenu_item,DEFVAL(-1)); ObjectTypeDB::bind_method(_MD("set_item_text","idx","text"),&PopupMenu::set_item_text); ObjectTypeDB::bind_method(_MD("set_item_icon","idx","icon"),&PopupMenu::set_item_icon); ObjectTypeDB::bind_method(_MD("set_item_accelerator","idx","accel"),&PopupMenu::set_item_accelerator); diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 9084983a4c..a39c61ecac 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -1438,8 +1438,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ if (p_button==BUTTON_LEFT) { /* process selection */ - if (p_doubleclick && (!c.editable || c.mode==TreeItem::CELL_MODE_CUSTOM || c.mode==TreeItem::CELL_MODE_ICON)) { - + if (p_doubleclick && (!c.editable || c.mode==TreeItem::CELL_MODE_CUSTOM || c.mode==TreeItem::CELL_MODE_ICON || c.mode==TreeItem::CELL_MODE_CHECK)) { emit_signal("item_activated"); return -1; diff --git a/scene/io/scene_format_object.cpp b/scene/io/scene_format_object.cpp deleted file mode 100644 index 6ffae30282..0000000000 --- a/scene/io/scene_format_object.cpp +++ /dev/null @@ -1,851 +0,0 @@ -/*************************************************************************/ -/* scene_format_object.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "scene_format_object.h" -#include "print_string.h" -#include "globals.h" -#include "scene/resources/packed_scene.h" -#include "io/resource_loader.h" - -#ifdef OLD_SCENE_FORMAT_ENABLED - -void SceneFormatSaverObject::save_node(const Node* p_root,const Node* p_node,const Node* p_owner,ObjectFormatSaver *p_saver,String p_base_path,uint32_t p_flags,Map<const Node*,uint32_t>& owner_id) const { - - if (p_node!=p_root && p_node->get_owner()==NULL) - return; - - - if (p_flags&SceneSaver::FLAG_BUNDLE_INSTANCED_SCENES || p_node->get_owner() == p_owner || p_node == p_owner ) { - - Dictionary d; - if (p_root!=p_node) { - d["path"]=p_root->get_path_to(p_node->get_parent()); - } - - d["name"]=p_node->get_name(); - - /* Connections */ - - List<MethodInfo> signal_list; - - p_node->get_signal_list(&signal_list); - - int conn_count=0; - - Set<Node::Connection> exclude_connections; - - if (!(p_flags&SceneSaver::FLAG_BUNDLE_INSTANCED_SCENES)) { - - Vector<Node::Connection> ex = p_node->get_instance_connections(); - for(int i=0;i<ex.size();i++) { - exclude_connections.insert(ex[i]); - } - } - - for (List<MethodInfo>::Element *S=signal_list.front();S;S=S->next()) { - - List<Node::Connection> connections; - p_node->get_signal_connection_list(S->get().name,&connections); - for(List<Node::Connection>::Element *E=connections.front();E;E=E->next()) { - - Node::Connection &c=E->get(); - if (!(c.flags&Object::CONNECT_PERSIST)) - continue; - if (exclude_connections.has(c)) - continue; - - Node *target = c.target->cast_to<Node>(); - if (!target) - continue; //connected to something not a node, ignoring - - Dictionary cd; - cd["signal"]=c.signal; - cd["target"]=p_node->get_path_to(target); - cd["method"]=c.method; - cd["realtime"]=!(c.flags&Object::CONNECT_DEFERRED); - if (c.binds.size()) - cd["binds"]=c.binds; - d["connection/"+itos(conn_count+1)]=cd; - - conn_count++; - } - } - - d["connection_count"]=conn_count; - if (owner_id.has(p_node->get_owner())) { - - d["owner"]=owner_id[p_node->get_owner()]; - } - - /* Groups */ - - DVector<String> group_array; - List<Node::GroupInfo> groups; - p_node->get_groups(&groups); - Set<StringName> exclude_groups; - - if (!(p_flags&SceneSaver::FLAG_BUNDLE_INSTANCED_SCENES)) { - //generate groups to exclude (came from instance) - Vector<StringName> eg; - eg=p_node->get_instance_groups(); - for(int i=0;i<eg.size();i++) - exclude_groups.insert(eg[i]); - } - - for(List<Node::GroupInfo>::Element*E=groups.front();E;E=E->next()) { - - if (E->get().persistent && !exclude_groups.has(E->get().name)) - group_array.push_back(E->get().name); - } - - if (group_array.size()) - d["groups"]=group_array; - - /* Save */ - - if (p_owner!=p_node && p_node->get_filename()!="") { - - String instance_path; - if (p_flags&SceneSaver::FLAG_RELATIVE_PATHS) - instance_path=p_base_path.path_to_file(Globals::get_singleton()->localize_path(p_node->get_filename())); - else - instance_path=p_node->get_filename(); - d["instance"]=instance_path; - - if (p_flags&SceneSaver::FLAG_BUNDLE_INSTANCED_SCENES) { - - int id = owner_id.size(); - d["owner_id"]=id; - owner_id[p_node]=id; - - p_saver->save(p_node,d); - - //owner change! - for (int i=0;i<p_node->get_child_count();i++) { - - save_node(p_root,p_node->get_child(i),p_node,p_saver,p_base_path,p_flags,owner_id); - } - return; - - } else { - DVector<String> prop_names; - Array prop_values; - - List<PropertyInfo> properties; - p_node->get_property_list(&properties); - - //instance state makes sure that only changes to instance are saved - Dictionary instance_state=p_node->get_instance_state(); - - for(List<PropertyInfo>::Element *E=properties.front();E;E=E->next()) { - - if (!(E->get().usage&PROPERTY_USAGE_STORAGE)) - continue; - - String name=E->get().name; - Variant value=p_node->get(E->get().name); - - if (!instance_state.has(name)) - continue; // did not change since it was loaded, not save - if (value==instance_state[name]) - continue; - prop_names.push_back( name ); - prop_values.push_back( value ); - - } - - d["override_names"]=prop_names; - d["override_values"]=prop_values; - - p_saver->save(NULL,d); - } - } else { - - p_saver->save(p_node,d); - } - } - - for (int i=0;i<p_node->get_child_count();i++) { - - save_node(p_root,p_node->get_child(i),p_owner,p_saver,p_base_path,p_flags,owner_id); - } -} - - -Error SceneFormatSaverObject::save(const String &p_path,const Node* p_scene,uint32_t p_flags,const Ref<OptimizedSaver> &p_optimizer) { - - String extension=p_path.extension(); - if (extension=="scn") - extension="bin"; - if (extension=="xscn") - extension="xml"; - - String local_path=Globals::get_singleton()->localize_path(p_path); - uint32_t saver_flags=0; - if (p_flags&SceneSaver::FLAG_RELATIVE_PATHS) - saver_flags|=ObjectSaver::FLAG_RELATIVE_PATHS; - if (p_flags&SceneSaver::FLAG_BUNDLE_RESOURCES) - saver_flags|=ObjectSaver::FLAG_BUNDLE_RESOURCES; - if (p_flags&SceneSaver::FLAG_OMIT_EDITOR_PROPERTIES) - saver_flags|=ObjectSaver::FLAG_OMIT_EDITOR_PROPERTIES; - if (p_flags&SceneSaver::FLAG_SAVE_BIG_ENDIAN) - saver_flags|=ObjectSaver::FLAG_SAVE_BIG_ENDIAN; - - ObjectFormatSaver *saver = ObjectSaver::instance_format_saver(local_path,"SCENE",extension,saver_flags,p_optimizer); - - ERR_FAIL_COND_V(!saver,ERR_FILE_UNRECOGNIZED); - - /* SAVE SCENE */ - - Map<const Node*,uint32_t> node_id_map; - save_node(p_scene,p_scene,p_scene,saver,local_path,p_flags,node_id_map); - - memdelete(saver); - - return OK; -} - -void SceneFormatSaverObject::get_recognized_extensions(List<String> *p_extensions) const { - - p_extensions->push_back("xml"); - p_extensions->push_back("scn"); - p_extensions->push_back("xscn"); - -// ObjectSaver::get_recognized_extensions(p_extensions); -} - - -///////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////// - -void SceneFormatLoaderObject::_apply_meta(Node *node, const Variant&meta, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,Map<uint32_t,Node*>& owner_map) { - - r_err = OK; - - - Dictionary d=meta; - - if (!d.has("name")) { - - r_err=ERR_WTF; - memdelete(node); - ERR_FAIL_COND(!d.has("name")); - } - - - node->set_name(d["name"]); - int connection_count=d.has("connection_count")?d["connection_count"].operator int():0; - - - for (int i=0;i<connection_count;i++) { - - Dictionary cd=d["connection/"+itos(i+1)]; - - ERR_CONTINUE(!cd.has("target")); - ERR_CONTINUE(!cd.has("method")); - ERR_CONTINUE(!cd.has("realtime")); - ERR_CONTINUE(!cd.has("signal")); - - ConnectionItem ci; - - ci.node=node; - ci.target=cd["target"]; - ci.method=cd["method"]; - ci.signal=cd["signal"]; - ci.realtime=cd["realtime"]; - if (cd.has("binds")) - ci.binds=cd["binds"]; - - connections.push_back(ci); - - } - - DVector<String> groups=d.has("groups")?d["groups"].operator DVector<String>():DVector<String>(); - for (int i=0;i<groups.size();i++) { - - node->add_to_group(groups[i],true); - } - -} - - - -Ref<SceneInteractiveLoader> SceneFormatLoaderObject::load_interactive(const String &p_path,bool p_save_root_state) { - - SceneInteractiveLoaderObject *sil = memnew( SceneInteractiveLoaderObject(p_path,p_save_root_state) ); - - if (sil->error!=OK) { - - memdelete( sil ); - return Ref<SceneInteractiveLoader>(); - } - - return Ref<SceneInteractiveLoader>( sil ); - -} - - -Node* SceneFormatLoaderObject::load_node(Object *obj, const Variant& meta, Node *p_root, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,bool p_save_instance_state,Map<uint32_t,Node*>& owner_map) { - - r_err = OK; - - Node *node=obj->cast_to<Node>(); - - _apply_meta(node,meta,p_loader,connections,r_err,owner_map); - if (r_err!=OK) - return NULL; - - Dictionary d=meta; - - if (p_root) { - NodePath path=d.has("path")?d["path"].operator NodePath():NodePath("."); - - Node *parent=p_root->get_node(path); - if (!parent) { - memdelete(node); - r_err=ERR_FILE_CORRUPT; - ERR_FAIL_COND_V(!parent,NULL); - } - - parent->add_child(node); - - if (d.has("owner_id")) { - //is owner - owner_map[d["owner_id"]]=node; - if (d.has("instance")) - node->set_filename(d["instance"]); - - } - - if (d.has("owner")) { - - uint32_t owner = d["owner"]; - ERR_FAIL_COND_V(!owner_map.has(owner),NULL); - node->set_owner(owner_map[owner]); - } else { - - node->set_owner(p_root); - } - } - - return node; -} - -void SceneFormatLoaderObject::_apply_connections(List<ConnectionItem>& connections) { - - int idx=0; - for (List<ConnectionItem>::Element *E=connections.front();E;E=E->next()) { - - ConnectionItem &ci=E->get(); - Node *target = ci.node->get_node(ci.target); - ERR_CONTINUE(!target); - ci.node->connect(ci.signal,target,ci.method,ci.binds,(ci.realtime?0:Object::CONNECT_DEFERRED)|Object::CONNECT_PERSIST); - idx++; - } - -} - -Node* SceneFormatLoaderObject::load(const String &p_path,bool p_save_instance_state) { - - List<ConnectionItem> connections; - - String extension=p_path.extension(); - if (extension=="scn") - extension="bin"; - if (extension=="xscn") - extension="xml"; - - String local_path = Globals::get_singleton()->localize_path(p_path); - - ObjectFormatLoader *loader = ObjectLoader::instance_format_loader(local_path,"SCENE",extension); - - ERR_EXPLAIN("Couldn't load scene: "+p_path); - ERR_FAIL_COND_V(!loader,NULL); - - Node *root=NULL; - Map<uint32_t,Node*> owner_map; - - while(true) { - - Object *obj=NULL; - Variant metav; - Error r_err=loader->load(&obj,metav); - - if (r_err == ERR_SKIP) { - continue; - }; - - if (r_err==ERR_FILE_EOF) { - memdelete(loader); - ERR_FAIL_COND_V(!root,NULL); - _apply_connections(connections); - return root; - } - - if (r_err || (!obj && metav.get_type()==Variant::NIL)) { - memdelete(loader); - ERR_EXPLAIN("Object Loader Failed for Scene: "+p_path) ; - ERR_FAIL_COND_V( r_err, NULL); - ERR_EXPLAIN("Object Loader Failed for Scene: "+p_path) ; - ERR_FAIL_COND_V( !obj && metav.get_type()==Variant::NIL,NULL); - } - - if (obj) { - if (obj->cast_to<Node>()) { - - Error err; - Node* node = load_node(obj, metav, root, loader,connections,err,p_save_instance_state,owner_map); - if (err) - memdelete(loader); - - ERR_FAIL_COND_V( err, NULL ); - if (!root) - root=node; - } else { - - memdelete(loader); - ERR_FAIL_V( NULL ); - - } - } else { - - // check for instance - Dictionary meta=metav; - if (meta.has("instance")) { - if (!root) { - - memdelete(loader); - ERR_FAIL_COND_V(!root,NULL); - } - - String path = meta["instance"]; - - if (path.find("://")==-1 && path.is_rel_path()) { - // path is relative to file being loaded, so convert to a resource path - path=Globals::get_singleton()->localize_path( - local_path.get_base_dir()+"/"+path); - } - - - Node *scene = SceneLoader::load(path); - - if (!scene) { - - Ref<PackedScene> sd = ResourceLoader::load(path); - if (sd.is_valid()) { - - scene=sd->instance(); - } - } - - - if (!scene) { - - memdelete(loader); - ERR_FAIL_COND_V(!scene,NULL); - } - - if (p_save_instance_state) - scene->generate_instance_state(); - - - Error err; - _apply_meta(scene,metav,loader,connections,err,owner_map); - if (err!=OK) { - memdelete(loader); - ERR_FAIL_COND_V(err!=OK,NULL); - } - - Node *parent=root; - - if (meta.has("path")) - parent=root->get_node(meta["path"]); - - - if (!parent) { - - memdelete(loader); - ERR_FAIL_COND_V(!parent,NULL); - } - - - if (meta.has("override_names") && meta.has("override_values")) { - - DVector<String> override_names=meta["override_names"]; - Array override_values=meta["override_values"]; - - int len = override_names.size(); - if ( len > 0 && len == override_values.size() ) { - - DVector<String>::Read names = override_names.read(); - - for(int i=0;i<len;i++) { - - scene->set(names[i],override_values[i]); - } - - } - - } - - scene->set_filename(path); - - parent->add_child(scene); - scene->set_owner(root); - } - } - } - - return NULL; -} - -void SceneFormatLoaderObject::get_recognized_extensions(List<String> *p_extensions) const { - - p_extensions->push_back("xml"); - p_extensions->push_back("scn"); - p_extensions->push_back("xscn"); - -// ObjectLoader::get_recognized_extensions(p_extensions); - -} - - - -/////////////////////////////////////////////////// - - -void SceneInteractiveLoaderObject::_apply_meta(Node *node, const Variant&meta, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,Map<uint32_t,Node*>& owner_map) { - - r_err = OK; - - - Dictionary d=meta; - - if (!d.has("name")) { - - r_err=ERR_WTF; - memdelete(node); - ERR_FAIL_COND(!d.has("name")); - } - - - node->set_name(d["name"]); - int connection_count=d.has("connection_count")?d["connection_count"].operator int():0; - - - for (int i=0;i<connection_count;i++) { - - Dictionary cd=d["connection/"+itos(i+1)]; - - ERR_CONTINUE(!cd.has("target")); - ERR_CONTINUE(!cd.has("method")); - ERR_CONTINUE(!cd.has("realtime")); - ERR_CONTINUE(!cd.has("signal")); - - ConnectionItem ci; - - ci.node=node; - ci.target=cd["target"]; - ci.method=cd["method"]; - ci.signal=cd["signal"]; - ci.realtime=cd["realtime"]; - if (cd.has("binds")) - ci.binds=cd["binds"]; - - connections.push_back(ci); - - } - - DVector<String> groups=d.has("groups")?d["groups"].operator DVector<String>():DVector<String>(); - for (int i=0;i<groups.size();i++) { - - node->add_to_group(groups[i],true); - } - -} - - - -Node* SceneInteractiveLoaderObject::load_node(Object *obj, const Variant& meta, Node *p_root, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,bool p_save_instance_state,Map<uint32_t,Node*>& owner_map) { - - r_err = OK; - - Node *node=obj->cast_to<Node>(); - - _apply_meta(node,meta,p_loader,connections,r_err,owner_map); - if (r_err!=OK) - return NULL; - - Dictionary d=meta; - - if (p_root) { - NodePath path=d.has("path")?d["path"].operator NodePath():NodePath("."); - - Node *parent=p_root->get_node(path); - if (!parent) { - memdelete(node); - r_err=ERR_FILE_CORRUPT; - ERR_FAIL_COND_V(!parent,NULL); - } - - parent->add_child(node); - - if (d.has("owner_id")) { - //is owner - owner_map[d["owner_id"]]=node; - if (d.has("instance")) - node->set_filename(d["instance"]); - - } - - if (d.has("owner")) { - - uint32_t owner = d["owner"]; - ERR_FAIL_COND_V(!owner_map.has(owner),NULL); - node->set_owner(owner_map[owner]); - } else { - - node->set_owner(p_root); - } - } - - return node; -} - -void SceneInteractiveLoaderObject::_apply_connections(List<ConnectionItem>& connections) { - - int idx=0; - for (List<ConnectionItem>::Element *E=connections.front();E;E=E->next()) { - - ConnectionItem &ci=E->get(); - Node *target = ci.node->get_node(ci.target); - ERR_CONTINUE(!target); - ci.node->connect(ci.signal,target,ci.method,ci.binds,(ci.realtime?0:Object::CONNECT_DEFERRED)|Object::CONNECT_PERSIST); - idx++; - } - -} - -SceneInteractiveLoaderObject::SceneInteractiveLoaderObject(const String &p_path,bool p_save_root_state) { - - error=OK; - path=p_path; - save_instance_state=p_save_root_state; - node_path=p_path; - root=NULL; - stage_max=1; - stage=0; - - - String extension=p_path.extension(); - if (extension=="scn") - extension="bin"; - if (extension=="xscn") - extension="xml"; - - local_path = Globals::get_singleton()->localize_path(p_path); - - loader = ObjectLoader::instance_format_loader(local_path,"SCENE",extension); - - if (!loader) { - - error=ERR_CANT_OPEN; - } - ERR_EXPLAIN("Couldn't load scene: "+p_path); - ERR_FAIL_COND(!loader); - -} - - - -void SceneInteractiveLoaderObject::set_local_path(const String& p_local_path) { - - node_path=p_local_path; -} - -Node *SceneInteractiveLoaderObject::get_scene() { - - if (error==ERR_FILE_EOF) - return root; - return NULL; -} -Error SceneInteractiveLoaderObject::poll() { - - if (error!=OK) - return error; - - Object *obj=NULL; - Variant metav; - Error r_err=loader->load(&obj,metav); - - - if (r_err == ERR_SKIP) { - stage++; - return OK; - }; - - if (r_err==ERR_FILE_EOF) { - memdelete(loader); - error=ERR_FILE_CORRUPT; - ERR_FAIL_COND_V(!root,ERR_FILE_CORRUPT); - _apply_connections(connections); - error=ERR_FILE_EOF; - if (root) - root->set_filename(node_path); - return error; - } - - if (r_err || (!obj && metav.get_type()==Variant::NIL)) { - memdelete(loader); - error=ERR_FILE_CORRUPT; - ERR_EXPLAIN("Object Loader Failed for Scene: "+path); - ERR_FAIL_COND_V( r_err, ERR_FILE_CORRUPT); - ERR_EXPLAIN("Object Loader Failed for Scene: "+path); - ERR_FAIL_COND_V( !obj && metav.get_type()==Variant::NIL,ERR_FILE_CORRUPT); - } - - if (obj) { - if (obj->cast_to<Node>()) { - - Error err; - Node* node = load_node(obj, metav, root, loader,connections,err,save_instance_state,owner_map); - if (err) { - error=ERR_FILE_CORRUPT; - memdelete(loader); - } - - ERR_FAIL_COND_V( err, ERR_FILE_CORRUPT ); - if (!root) - root=node; - } else { - - error=ERR_FILE_CORRUPT; - memdelete(loader); - ERR_EXPLAIN("Loaded something not a node.. (?)"); - ERR_FAIL_V( ERR_FILE_CORRUPT ); - - } - } else { - - // check for instance - Dictionary meta=metav; - if (meta.has("instance")) { - - if (!root) { - - error=ERR_FILE_CORRUPT; - memdelete(loader); - ERR_FAIL_COND_V(!root,ERR_FILE_CORRUPT); - } - - String path = meta["instance"]; - - if (path.find("://")==-1 && path.is_rel_path()) { - // path is relative to file being loaded, so convert to a resource path - path=Globals::get_singleton()->localize_path( - local_path.get_base_dir()+"/"+path); - } - - Node *scene = SceneLoader::load(path); - - if (!scene) { - - error=ERR_FILE_CORRUPT; - memdelete(loader); - ERR_FAIL_COND_V(!scene,ERR_FILE_CORRUPT); - } - - if (save_instance_state) - scene->generate_instance_state(); - - - Error err; - _apply_meta(scene,metav,loader,connections,err,owner_map); - if (err!=OK) { - error=ERR_FILE_CORRUPT; - memdelete(loader); - ERR_FAIL_COND_V(err!=OK,ERR_FILE_CORRUPT); - } - - Node *parent=root; - - if (meta.has("path")) - parent=root->get_node(meta["path"]); - - - if (!parent) { - - error=ERR_FILE_CORRUPT; - memdelete(loader); - ERR_FAIL_COND_V(!parent,ERR_FILE_CORRUPT); - } - - - if (meta.has("override_names") && meta.has("override_values")) { - - DVector<String> override_names=meta["override_names"]; - Array override_values=meta["override_values"]; - - int len = override_names.size(); - if ( len > 0 && len == override_values.size() ) { - - DVector<String>::Read names = override_names.read(); - - for(int i=0;i<len;i++) { - - scene->set(names[i],override_values[i]); - } - - } - - } - - scene->set_filename(path); - - parent->add_child(scene); - scene->set_owner(root); - } - } - - stage++; - error=OK; - return error; - -} -int SceneInteractiveLoaderObject::get_stage() const { - - return stage; -} -int SceneInteractiveLoaderObject::get_stage_count() const { - - return stage_max; -} - - -#endif diff --git a/scene/io/scene_format_object.h b/scene/io/scene_format_object.h deleted file mode 100644 index 3f0bbd4627..0000000000 --- a/scene/io/scene_format_object.h +++ /dev/null @@ -1,128 +0,0 @@ -/*************************************************************************/ -/* scene_format_object.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef SCENE_FORMAT_OBJECT_H -#define SCENE_FORMAT_OBJECT_H - - -#include "scene/main/node.h" -#include "scene/io/scene_saver.h" -#include "scene/io/scene_loader.h" -#include "io/object_saver.h" -#include "io/object_loader.h" -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ - - -#ifdef OLD_SCENE_FORMAT_ENABLED - -class SceneFormatSaverObject : public SceneFormatSaver { - - void save_node(const Node* p_root,const Node* p_node,const Node* p_owner,ObjectFormatSaver *p_saver,String p_base_path,uint32_t p_flags,Map<const Node*,uint32_t>& owner_id) const; - -public: - - virtual Error save(const String &p_path,const Node* p_scenezz,uint32_t p_flags=0,const Ref<OptimizedSaver> &p_optimizer=Ref<OptimizedSaver>()); - virtual void get_recognized_extensions(List<String> *p_extensions) const; - virtual ~SceneFormatSaverObject() {} -}; - - - -class SceneFormatLoaderObject : public SceneFormatLoader { - - - struct ConnectionItem { - Node *node; - NodePath target; - StringName method; - StringName signal; - Vector<Variant> binds; - bool realtime; - }; - - Node* load_node(Object *obj, const Variant& meta, Node *p_root, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,bool p_root_scene_hint,Map<uint32_t,Node*>& owner_map); - void _apply_connections(List<ConnectionItem>& connections); - void _apply_meta(Node *node, const Variant& meta, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,Map<uint32_t,Node*>& owner_map); - -public: - - virtual Ref<SceneInteractiveLoader> load_interactive(const String &p_path,bool p_root_scene_hint=false); - virtual Node* load(const String &p_path,bool p_save_root_state=false); - virtual void get_recognized_extensions(List<String> *p_extensions) const; - -}; - - -class SceneInteractiveLoaderObject : public SceneInteractiveLoader { - - OBJ_TYPE(SceneInteractiveLoaderObject,SceneInteractiveLoader); - - struct ConnectionItem { - Node *node; - NodePath target; - StringName method; - StringName signal; - Vector<Variant> binds; - bool realtime; - }; - ObjectFormatLoader *loader; - String path; - String node_path; - String local_path; - Error error; - bool save_instance_state; - List<ConnectionItem> connections; - Map<uint32_t,Node*> owner_map; - Node *root; - int stage_max; - int stage; - - - Node* load_node(Object *obj, const Variant& meta, Node *p_root, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,bool p_root_scene_hint,Map<uint32_t,Node*>& owner_map); - void _apply_connections(List<ConnectionItem>& connections); - void _apply_meta(Node *node, const Variant& meta, ObjectFormatLoader *p_loader,List<ConnectionItem>& connections,Error& r_err,Map<uint32_t,Node*>& owner_map); - -friend class SceneFormatLoaderObject; -public: - - virtual void set_local_path(const String& p_local_path); - virtual Node *get_scene(); - virtual Error poll(); - virtual int get_stage() const; - virtual int get_stage_count() const; - - - SceneInteractiveLoaderObject(const String &p_path,bool p_save_root_state=false); -}; - - - -#endif -#endif diff --git a/scene/io/scene_format_script.cpp b/scene/io/scene_format_script.cpp deleted file mode 100644 index a6f1596d2b..0000000000 --- a/scene/io/scene_format_script.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/*************************************************************************/ -/* scene_format_script.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "scene_format_script.h" -#if 0 -Node* SceneFormatLoaderScript::load(const String &p_path,bool p_save_instance_state) { - - Ref<Script> script = ResourceLoader::load(p_path); - ERR_EXPLAIN("Can't load script-based scene: "+p_path); - ERR_FAIL_COND_V(script.is_null(),NULL); - ERR_EXPLAIN("Script does not instance in a node: "+p_path); - ERR_FAIL_COND_V(script->get_node_type()=="",NULL); - String node_type=script->get_node_type(); - Object *obj = ObjectTypeDB::instance(node_type); - ERR_EXPLAIN("Unknown node type for instancing '"+node_type+"' in script: "+p_path); - ERR_FAIL_COND_V(!obj,NULL); - Node *node = obj->cast_to<Node>(); - if (!node) - memdelete(obj); - ERR_EXPLAIN("Node type '"+node_type+"' not of type 'Node'' in script: "+p_path); - ERR_FAIL_COND_V(!node,NULL); - - node->set_script(script.get_ref_ptr()); - - return node; -} - -void SceneFormatLoaderScript::get_recognized_extensions(List<String> *p_extensions) const { - - for (int i=0;i<ScriptServer::get_language_count();i++) { - - ScriptServer::get_language(i)->get_recognized_extensions(p_extensions); - } -} - - -SceneFormatLoaderScript::SceneFormatLoaderScript() -{ -} -#endif diff --git a/scene/io/scene_format_script.h b/scene/io/scene_format_script.h deleted file mode 100644 index 9bfcc0b1e3..0000000000 --- a/scene/io/scene_format_script.h +++ /dev/null @@ -1,45 +0,0 @@ -/*************************************************************************/ -/* scene_format_script.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef SCENE_FORMAT_SCRIPT_H -#define SCENE_FORMAT_SCRIPT_H - -#include "scene/io/scene_loader.h" -#include "io/resource_loader.h" -#if 0 - -class SceneFormatLoaderScript : public SceneFormatLoader { -public: - - virtual Node* load(const String &p_path,bool p_save_instance_state=false); - virtual void get_recognized_extensions(List<String> *p_extensions) const; - - SceneFormatLoaderScript(); -}; -#endif -#endif // SCENE_FORMAT_SCRIPT_H diff --git a/scene/io/scene_loader.cpp b/scene/io/scene_loader.cpp deleted file mode 100644 index 8615e64ae9..0000000000 --- a/scene/io/scene_loader.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/*************************************************************************/ -/* scene_loader.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "scene_loader.h" -#include "globals.h" -#include "path_remap.h" - -#ifdef OLD_SCENE_FORMAT_ENABLED - -SceneFormatLoader *SceneLoader::loader[MAX_LOADERS]; - -int SceneLoader::loader_count=0; - - -void SceneInteractiveLoader::_bind_methods() { - - ObjectTypeDB::bind_method(_MD("get_scene"),&SceneInteractiveLoader::get_scene); - ObjectTypeDB::bind_method(_MD("poll"),&SceneInteractiveLoader::poll); - ObjectTypeDB::bind_method(_MD("get_stage"),&SceneInteractiveLoader::get_stage); - ObjectTypeDB::bind_method(_MD("get_stage_count"),&SceneInteractiveLoader::get_stage_count); -} - -class SceneInteractiveLoaderDefault : public SceneInteractiveLoader { - - OBJ_TYPE( SceneInteractiveLoaderDefault, SceneInteractiveLoader ); -public: - Node *scene; - - virtual void set_local_path(const String& p_local_path) { scene->set_filename(p_local_path); } - virtual Node *get_scene() { return scene; } - virtual Error poll() { return ERR_FILE_EOF; } - virtual int get_stage() const { return 1; } - virtual int get_stage_count() const { return 1; } - - SceneInteractiveLoaderDefault() {} -}; - - -Ref<SceneInteractiveLoader> SceneFormatLoader::load_interactive(const String &p_path,bool p_root_scene_hint) { - - Node *scene = load(p_path,p_root_scene_hint); - if (!scene) - return Ref<SceneInteractiveLoader>(); - Ref<SceneInteractiveLoaderDefault> sil = Ref<SceneInteractiveLoaderDefault>( memnew( SceneInteractiveLoaderDefault )); - sil->scene=scene; - return sil; -} - - - -bool SceneFormatLoader::recognize(const String& p_extension) const { - - - List<String> extensions; - get_recognized_extensions(&extensions); - for (List<String>::Element *E=extensions.front();E;E=E->next()) { - - if (E->get().nocasecmp_to(p_extension.extension())==0) - return true; - } - - return false; -} - -Ref<SceneInteractiveLoader> SceneLoader::load_interactive(const String &p_path,bool p_save_root_state) { - - String local_path=Globals::get_singleton()->localize_path(p_path); - - String remapped_path = PathRemap::get_singleton()->get_remap(local_path); - String extension=remapped_path.extension(); - - for (int i=0;i<loader_count;i++) { - - if (!loader[i]->recognize(extension)) - continue; - Ref<SceneInteractiveLoader> il = loader[i]->load_interactive(remapped_path,p_save_root_state); - - if (il.is_null() && remapped_path!=local_path) - il = loader[i]->load_interactive(local_path,p_save_root_state); - - ERR_EXPLAIN("Error loading scene: "+local_path); - ERR_FAIL_COND_V(il.is_null(),Ref<SceneInteractiveLoader>()); - il->set_local_path(local_path); - - return il; - } - - ERR_EXPLAIN("No loader found for scene: "+p_path); - ERR_FAIL_V(Ref<SceneInteractiveLoader>()); - return Ref<SceneInteractiveLoader>(); -} - -Node* SceneLoader::load(const String &p_path,bool p_root_scene_hint) { - - String local_path=Globals::get_singleton()->localize_path(p_path); - - String remapped_path = PathRemap::get_singleton()->get_remap(local_path); - String extension=remapped_path.extension(); - - for (int i=0;i<loader_count;i++) { - - if (!loader[i]->recognize(extension)) - continue; - Node*node = loader[i]->load(remapped_path,p_root_scene_hint); - - if (!node && remapped_path!=local_path) - node = loader[i]->load(local_path,p_root_scene_hint); - - ERR_EXPLAIN("Error loading scene: "+local_path); - ERR_FAIL_COND_V(!node,NULL); - node->set_filename(local_path); - - return node; - } - - ERR_EXPLAIN("No loader found for scene: "+p_path); - ERR_FAIL_V(NULL); -} - -void SceneLoader::get_recognized_extensions(List<String> *p_extensions) { - - for (int i=0;i<loader_count;i++) { - - loader[i]->get_recognized_extensions(p_extensions); - } - -} - -void SceneLoader::add_scene_format_loader(SceneFormatLoader *p_format_loader) { - - ERR_FAIL_COND( loader_count >= MAX_LOADERS ); - loader[loader_count++]=p_format_loader; -} - - -#endif diff --git a/scene/io/scene_loader.h b/scene/io/scene_loader.h deleted file mode 100644 index 2562fc0520..0000000000 --- a/scene/io/scene_loader.h +++ /dev/null @@ -1,90 +0,0 @@ -/*************************************************************************/ -/* scene_loader.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef SCENE_LOADER_H -#define SCENE_LOADER_H - -#include "scene/main/node.h" - -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ - -#ifdef OLD_SCENE_FORMAT_ENABLED - -class SceneInteractiveLoader : public Reference { - - OBJ_TYPE(SceneInteractiveLoader,Reference); -protected: - - static void _bind_methods(); -public: - - virtual void set_local_path(const String& p_local_path)=0; - virtual Node *get_scene()=0; - virtual Error poll()=0; - virtual int get_stage() const=0; - virtual int get_stage_count() const=0; - - - SceneInteractiveLoader() {} -}; - -class SceneFormatLoader { -public: - - virtual Ref<SceneInteractiveLoader> load_interactive(const String &p_path,bool p_root_scene_hint=false); - virtual Node* load(const String &p_path,bool p_root_scene_hint=false)=0; - virtual void get_recognized_extensions(List<String> *p_extensions) const=0; - bool recognize(const String& p_extension) const; - - virtual ~SceneFormatLoader() {} -}; - -class SceneLoader { - - enum { - MAX_LOADERS=64 - }; - - static SceneFormatLoader *loader[MAX_LOADERS]; - static int loader_count; - -public: - - static Ref<SceneInteractiveLoader> load_interactive(const String &p_path,bool p_save_root_state=false); - static Node* load(const String &p_path,bool p_save_root_state=false); - static void add_scene_format_loader(SceneFormatLoader *p_format_loader); - static void get_recognized_extensions(List<String> *p_extensions); - - -}; - -#endif - -#endif diff --git a/scene/io/scene_saver.cpp b/scene/io/scene_saver.cpp deleted file mode 100644 index f1b503ef27..0000000000 --- a/scene/io/scene_saver.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/*************************************************************************/ -/* scene_saver.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "scene_saver.h" -#include "print_string.h" - -#ifdef OLD_SCENE_FORMAT_ENABLED -SceneFormatSaver *SceneSaver::saver[MAX_SAVERS]; - -int SceneSaver::saver_count=0; - -bool SceneFormatSaver::recognize(const String& p_extension) const { - - - List<String> extensions; - get_recognized_extensions(&extensions); - for (List<String>::Element *E=extensions.front();E;E=E->next()) { - - - if (E->get().nocasecmp_to(p_extension.extension())==0) - return true; - } - - return false; -} - -Error SceneSaver::save(const String &p_path,const Node* p_scene,uint32_t p_flags,const Ref<OptimizedSaver> &p_optimizer) { - - String extension=p_path.extension(); - Error err=ERR_FILE_UNRECOGNIZED; - bool recognized=false; - - for (int i=0;i<saver_count;i++) { - - if (!saver[i]->recognize(extension)) - continue; - recognized=true; - err = saver[i]->save(p_path,p_scene,p_flags,p_optimizer); - if (err == OK ) - return OK; - } - - if (err) { - if (!recognized) { - ERR_EXPLAIN("No saver format found for scene: "+p_path); - } else { - ERR_EXPLAIN("Couldn't save scene: "+p_path); - } - ERR_FAIL_V(err); - } - - return err; -} - -void SceneSaver::get_recognized_extensions(List<String> *p_extensions) { - - for (int i=0;i<saver_count;i++) { - - saver[i]->get_recognized_extensions(p_extensions); - } -} - -void SceneSaver::add_scene_format_saver(SceneFormatSaver *p_format_saver) { - - ERR_FAIL_COND( saver_count >= MAX_SAVERS ); - saver[saver_count++]=p_format_saver; -} - -#endif diff --git a/scene/io/scene_saver.h b/scene/io/scene_saver.h deleted file mode 100644 index 3028dce133..0000000000 --- a/scene/io/scene_saver.h +++ /dev/null @@ -1,80 +0,0 @@ -/*************************************************************************/ -/* scene_saver.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef SCENE_SAVER_H -#define SCENE_SAVER_H - -#include "scene/main/node.h" -#include "io/object_saver.h" -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ - - -#ifdef OLD_SCENE_FORMAT_ENABLED - -class SceneFormatSaver { -public: - - virtual Error save(const String &p_path,const Node* p_scen,uint32_t p_flags=0,const Ref<OptimizedSaver> &p_optimizer=Ref<OptimizedSaver>())=0; - virtual void get_recognized_extensions(List<String> *p_extensions) const=0; - bool recognize(const String& p_extension) const; - virtual ~SceneFormatSaver() {} -}; - - - - -class SceneSaver { - - enum { - MAX_SAVERS=64 - }; - - static SceneFormatSaver *saver[MAX_SAVERS]; - static int saver_count; - -public: - enum SaverFlags { - - FLAG_RELATIVE_PATHS=1, - FLAG_BUNDLE_RESOURCES=2, - FLAG_BUNDLE_INSTANCED_SCENES=4, - FLAG_OMIT_EDITOR_PROPERTIES=8, - FLAG_SAVE_BIG_ENDIAN=16 - }; - - static Error save(const String &p_path,const Node* p_scenezz,uint32_t p_flags=0,const Ref<OptimizedSaver> &p_optimizer=Ref<OptimizedSaver>()); - static void add_scene_format_saver(SceneFormatSaver *p_format_saver); - static void get_recognized_extensions(List<String> *p_extensions); -}; - - - -#endif -#endif diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 5d89ee80f1..e511a057c5 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -28,7 +28,6 @@ /*************************************************************************/ #include "node.h" #include "print_string.h" -#include "scene/io/scene_loader.h" #include "message_queue.h" #include "scene/scene_string_names.h" #include "scene/resources/packed_scene.h" diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp index bcdc50c880..c51974167d 100644 --- a/scene/main/scene_main_loop.cpp +++ b/scene/main/scene_main_loop.cpp @@ -968,6 +968,18 @@ void SceneMainLoop::set_screen_stretch(StretchMode p_mode,StretchAspect p_aspect } +#ifdef TOOLS_ENABLED +void SceneMainLoop::set_edited_scene_root(Node *p_node) { + edited_scene_root=p_node; +} + +Node *SceneMainLoop::get_edited_scene_root() const { + + return edited_scene_root; +} +#endif + + void SceneMainLoop::_bind_methods() { @@ -983,6 +995,10 @@ void SceneMainLoop::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_editor_hint","enable"),&SceneMainLoop::set_editor_hint); ObjectTypeDB::bind_method(_MD("is_editor_hint"),&SceneMainLoop::is_editor_hint); +#ifdef TOOLS_ENABLED + ObjectTypeDB::bind_method(_MD("set_edited_scene_root","scene"),&SceneMainLoop::set_edited_scene_root); + ObjectTypeDB::bind_method(_MD("get_edited_scene_root"),&SceneMainLoop::get_edited_scene_root); +#endif ObjectTypeDB::bind_method(_MD("set_pause","enable"),&SceneMainLoop::set_pause); ObjectTypeDB::bind_method(_MD("is_paused"),&SceneMainLoop::is_paused); @@ -1069,6 +1085,10 @@ SceneMainLoop::SceneMainLoop() { root->set_physics_object_picking(GLOBAL_DEF("physics/enable_object_picking",true)); +#ifdef TOOLS_ENABLED + edited_scene_root=NULL; +#endif + ADD_SIGNAL( MethodInfo("idle_frame")); ADD_SIGNAL( MethodInfo("fixed_frame")); diff --git a/scene/main/scene_main_loop.h b/scene/main/scene_main_loop.h index 493644d2bc..bfa755ff7c 100644 --- a/scene/main/scene_main_loop.h +++ b/scene/main/scene_main_loop.h @@ -102,6 +102,9 @@ private: int64_t current_frame; int node_count; +#ifdef TOOLS_ENABLED + Node *edited_scene_root; +#endif struct UGCall { StringName group; @@ -223,6 +226,13 @@ public: void set_screen_stretch(StretchMode p_mode,StretchAspect p_aspect,const Size2 p_minsize); + //void change_scene(const String& p_path); + //Node *get_loaded_scene(); + +#ifdef TOOLS_ENABLED + void set_edited_scene_root(Node *p_node); + Node *get_edited_scene_root() const; +#endif SceneMainLoop(); ~SceneMainLoop(); diff --git a/scene/main/timer.cpp b/scene/main/timer.cpp index 25d1c8530e..8e80f868c6 100644 --- a/scene/main/timer.cpp +++ b/scene/main/timer.cpp @@ -36,8 +36,12 @@ void Timer::_notification(int p_what) { case NOTIFICATION_READY: { - if (autostart) - start(); + if (autostart) { +#ifdef TOOLS_ENABLED + if (get_scene()->is_editor_hint() && get_scene()->get_edited_scene_root() && (get_scene()->get_edited_scene_root()==this || get_scene()->get_edited_scene_root()->is_a_parent_of(this))) + break; +#endif start(); + } } break; case NOTIFICATION_PROCESS: { diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 92dcef803c..6b7ed66463 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -95,8 +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); + //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); @@ -135,7 +135,9 @@ void Viewport::_update_rect() { } vr.width=rect.size.width; vr.height=rect.size.height; + VisualServer::get_singleton()->viewport_set_rect(viewport,vr); + last_vp_rect=rect; if (canvas_item.is_valid()) { VisualServer::get_singleton()->canvas_item_set_custom_rect(canvas_item,true,rect); @@ -164,6 +166,9 @@ void Viewport::_parent_visibility_changed() { Control *c = parent->cast_to<Control>(); VisualServer::get_singleton()->canvas_item_set_visible(canvas_item,c->is_visible()); + + _update_listener(); + _update_listener_2d(); } @@ -394,7 +399,7 @@ void Viewport::_notification(int p_what) { if (obj) { CollisionObject *co = obj->cast_to<CollisionObject>(); if (co) { - co->_input_event(ev,Vector3(),Vector3(),0); + co->_input_event(camera,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; @@ -416,7 +421,7 @@ void Viewport::_notification(int p_what) { if (last_id) { if (ObjectDB::get_instance(last_id)) { //good, exists - last_object->_input_event(ev,result.position,result.normal,result.shape); + last_object->_input_event(camera,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; } @@ -440,10 +445,13 @@ void Viewport::_notification(int p_what) { 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); + + co->_input_event(camera,ev,result.position,result.normal,result.shape); last_object=co; last_id=result.collider_id; new_collider=last_id; @@ -507,6 +515,7 @@ void Viewport::set_rect(const Rect2& p_rect) { if (rect==p_rect) return; rect=p_rect; + _update_rect(); _update_stretch_transform(); @@ -541,7 +550,7 @@ Rect2 Viewport::get_rect() const { void Viewport::_update_listener() { - if (is_inside_scene() && audio_listener && camera) { + if (is_inside_scene() && audio_listener && camera && (!get_parent() || (get_parent()->cast_to<Control>() && get_parent()->cast_to<Control>()->is_visible()))) { SpatialSoundServer::get_singleton()->listener_set_space(listener,find_world()->get_sound_space()); } else { SpatialSoundServer::get_singleton()->listener_set_space(listener,RID()); @@ -552,7 +561,7 @@ void Viewport::_update_listener() { void Viewport::_update_listener_2d() { - if (is_inside_scene() && audio_listener_2d) + if (is_inside_scene() && audio_listener && (!get_parent() || (get_parent()->cast_to<Control>() && get_parent()->cast_to<Control>()->is_visible()))) SpatialSound2DServer::get_singleton()->listener_set_space(listener_2d,find_world_2d()->get_sound_space()); else SpatialSound2DServer::get_singleton()->listener_set_space(listener_2d,RID()); @@ -1023,13 +1032,16 @@ void Viewport::_make_input_local(InputEvent& ev) { Matrix32 ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); Vector2 g = ai.xform(Vector2(ev.mouse_motion.global_x,ev.mouse_motion.global_y)); Vector2 l = ai.xform(Vector2(ev.mouse_motion.x,ev.mouse_motion.y)); - Vector2 r = ai.xform(Vector2(ev.mouse_motion.relative_x,ev.mouse_motion.relative_y)); + Vector2 r = ai.basis_xform(Vector2(ev.mouse_motion.relative_x,ev.mouse_motion.relative_y)); + Vector2 s = ai.basis_xform(Vector2(ev.mouse_motion.speed_x,ev.mouse_motion.speed_y)); ev.mouse_motion.x=l.x; ev.mouse_motion.y=l.y; ev.mouse_motion.global_x=g.x; ev.mouse_motion.global_y=g.y; ev.mouse_motion.relative_x=r.x; ev.mouse_motion.relative_y=r.y; + ev.mouse_motion.speed_x=s.x; + ev.mouse_motion.speed_y=s.y; } break; case InputEvent::SCREEN_TOUCH: { @@ -1044,8 +1056,8 @@ void Viewport::_make_input_local(InputEvent& ev) { Matrix32 ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); Vector2 t = ai.xform(Vector2(ev.screen_drag.x,ev.screen_drag.y)); - Vector2 r = ai.xform(Vector2(ev.screen_drag.relative_x,ev.screen_drag.relative_y)); - Vector2 s = ai.xform(Vector2(ev.screen_drag.speed_x,ev.screen_drag.speed_y)); + Vector2 r = ai.basis_xform(Vector2(ev.screen_drag.relative_x,ev.screen_drag.relative_y)); + Vector2 s = ai.basis_xform(Vector2(ev.screen_drag.speed_x,ev.screen_drag.speed_y)); ev.screen_drag.x=t.x; ev.screen_drag.y=t.y; ev.screen_drag.relative_x=r.x; @@ -1179,6 +1191,21 @@ void Viewport::set_physics_object_picking(bool p_enable) { } + +Vector2 Viewport::get_camera_coords(const Vector2 &p_viewport_coords) const { + + Matrix32 xf = get_final_transform(); + return xf.xform(p_viewport_coords); + + +} + +Vector2 Viewport::get_camera_rect_size() const { + + return last_vp_rect.size; +} + + bool Viewport::get_physics_object_picking() { diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 5d68438f0d..37f1b357c6 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -110,6 +110,7 @@ friend class RenderTargetTexture; Size2 size_override_size; Size2 size_override_margin; + Rect2 last_vp_rect; bool transparent_bg; bool render_target_vflip; @@ -229,6 +230,10 @@ public: RenderTargetUpdateMode get_render_target_update_mode() const; Ref<RenderTargetTexture> get_render_target_texture() const; + + Vector2 get_camera_coords(const Vector2& p_viewport_coords) const; + Vector2 get_camera_rect_size() const; + void queue_screen_capture(); Image get_screen_capture() const; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 2a1cca6a3a..f3b13f30bf 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -32,7 +32,7 @@ #include "scene/io/resource_format_image.h" #include "scene/io/resource_format_wav.h" -#include "scene/io/scene_format_script.h" +//#include "scene/io/scene_format_script.h" #include "resources/default_theme/default_theme.h" #include "object_type_db.h" #include "scene/main/canvas_layer.h" @@ -100,6 +100,7 @@ #include "scene/2d/sample_player_2d.h" #include "scene/2d/screen_button.h" #include "scene/2d/remote_transform_2d.h" +#include "scene/2d/y_sort.h" #include "scene/2d/position_2d.h" #include "scene/2d/tile_map.h" @@ -119,7 +120,7 @@ #include "scene/resources/scene_preloader.h" #include "scene/main/timer.h" -#include "scene/io/scene_format_object.h" + #include "scene/audio/stream_player.h" #include "scene/audio/event_player.h" #include "scene/audio/sound_room_params.h" @@ -141,7 +142,7 @@ #include "scene/resources/mesh_library.h" -#include "scene/resources/image_path_finder.h" + #include "scene/resources/polygon_path_finder.h" #include "scene/resources/sample.h" @@ -173,9 +174,8 @@ #ifndef _3D_DISABLED #include "scene/3d/camera.h" -#include "scene/3d/editable_shape.h" + #include "scene/3d/interpolated_camera.h" -#include "scene/3d/follow_camera.h" #include "scene/3d/position_3d.h" #include "scene/3d/test_cube.h" #include "scene/3d/mesh_instance.h" @@ -185,7 +185,7 @@ #include "scene/3d/portal.h" #include "scene/resources/environment.h" #include "scene/3d/physics_body.h" -#include "scene/3d/car_body.h" + #include "scene/3d/vehicle_body.h" #include "scene/3d/body_shape.h" #include "scene/3d/area.h" @@ -203,7 +203,7 @@ #include "scene/3d/collision_polygon.h" #endif -#include "scene/scene_binds.h" + static ResourceFormatLoaderImage *resource_loader_image=NULL; static ResourceFormatLoaderWAV *resource_loader_wav=NULL; @@ -215,15 +215,6 @@ static ResourceFormatLoaderBitMap *resource_loader_bitmap=NULL; #endif static ResourceFormatLoaderTheme *resource_loader_theme=NULL; static ResourceFormatLoaderShader *resource_loader_shader=NULL; -#ifdef OLD_SCENE_FORMAT_ENABLED -static SceneFormatSaverObject *scene_saver_object=NULL; -static SceneFormatLoaderObject *scene_loader_object=NULL; -//static SceneFormatLoaderScript *scene_loader_script=NULL; -#endif - -#ifdef OLD_SCENE_FORMAT_ENABLED -SceneIO *scene_io=NULL; -#endif //static SceneStringNames *string_names; @@ -235,13 +226,6 @@ void register_scene_types() { Node::init_node_hrcr(); -#ifdef OLD_SCENE_FORMAT_ENABLED - ObjectTypeDB::register_type<SceneIO>(); - ObjectTypeDB::register_virtual_type<SceneInteractiveLoader>(); - scene_io = memnew( SceneIO ); - Globals::get_singleton()->add_singleton(Globals::Singleton("SceneIO",scene_io)); -#endif - resource_loader_image = memnew( ResourceFormatLoaderImage ); ResourceLoader::add_resource_format_loader( resource_loader_image ); @@ -262,16 +246,6 @@ void register_scene_types() { resource_loader_shader = memnew( ResourceFormatLoaderShader ); ResourceLoader::add_resource_format_loader( resource_loader_shader ); -#ifdef OLD_SCENE_FORMAT_ENABLED - scene_saver_object=memnew( SceneFormatSaverObject ); - SceneSaver::add_scene_format_saver(scene_saver_object); - - scene_loader_object=memnew( SceneFormatLoaderObject ); - SceneLoader::add_scene_format_loader(scene_loader_object); - -// scene_loader_script=memnew( SceneFormatLoaderScript ); -// SceneLoader::add_scene_format_loader(scene_loader_script); -#endif make_default_theme(); @@ -378,7 +352,6 @@ void register_scene_types() { ObjectTypeDB::register_type<BoneAttachment>(); ObjectTypeDB::register_virtual_type<VisualInstance>(); ObjectTypeDB::register_type<Camera>(); - ObjectTypeDB::register_type<FollowCamera>(); ObjectTypeDB::register_type<InterpolatedCamera>(); ObjectTypeDB::register_type<TestCube>(); ObjectTypeDB::register_type<MeshInstance>(); @@ -404,8 +377,8 @@ void register_scene_types() { ObjectTypeDB::register_type<StaticBody>(); ObjectTypeDB::register_type<RigidBody>(); ObjectTypeDB::register_type<KinematicBody>(); - ObjectTypeDB::register_type<CarBody>(); - ObjectTypeDB::register_type<CarWheel>(); + + ObjectTypeDB::register_type<VehicleBody>(); ObjectTypeDB::register_type<VehicleWheel>(); ObjectTypeDB::register_type<Area>(); @@ -413,8 +386,6 @@ void register_scene_types() { ObjectTypeDB::register_type<CollisionShape>(); ObjectTypeDB::register_type<CollisionPolygon>(); ObjectTypeDB::register_type<RayCast>(); - ObjectTypeDB::register_virtual_type<EditableShape>(); - ObjectTypeDB::register_type<EditableSphere>(); ObjectTypeDB::register_type<MultiMeshInstance>(); ObjectTypeDB::register_type<Room>(); ObjectTypeDB::register_type<Curve3D>(); @@ -423,6 +394,7 @@ void register_scene_types() { ObjectTypeDB::register_type<VisibilityNotifier>(); ObjectTypeDB::register_type<VisibilityEnabler>(); ObjectTypeDB::register_type<BakedLightInstance>(); + ObjectTypeDB::register_type<BakedLightSampler>(); ObjectTypeDB::register_type<WorldEnvironment>(); //scenariofx @@ -491,6 +463,7 @@ void register_scene_types() { ObjectTypeDB::register_type<VisibilityNotifier2D>(); ObjectTypeDB::register_type<VisibilityEnabler2D>(); ObjectTypeDB::register_type<Polygon2D>(); + ObjectTypeDB::register_type<YSort>(); ObjectTypeDB::set_type_enabled("CollisionShape2D",false); ObjectTypeDB::set_type_enabled("CollisionPolygon2D",false); @@ -559,7 +532,7 @@ void register_scene_types() { ObjectTypeDB::register_type<StyleBoxFlat>(); ObjectTypeDB::register_type<StyleBoxImageMask>(); ObjectTypeDB::register_type<Theme>(); - ObjectTypeDB::register_type<ImagePathFinder>(); + ObjectTypeDB::register_type<PolygonPathFinder>(); ObjectTypeDB::register_type<BitMap>(); @@ -590,10 +563,6 @@ void register_scene_types() { OS::get_singleton()->yield(); //may take time to init ObjectTypeDB::register_type<PackedScene>(); -#ifdef OLD_SCENE_FORMAT_ENABLED - ObjectTypeDB::register_type<ScenePreloader>(); -#endif - ObjectTypeDB::register_type<SceneMainLoop>(); @@ -617,11 +586,5 @@ void unregister_scene_types() { memdelete( resource_loader_theme ); memdelete( resource_loader_shader ); -#ifdef OLD_SCENE_FORMAT_ENABLED - memdelete( scene_saver_object ); - memdelete( scene_loader_object ); -// memdelete( scene_loader_script ); - memdelete( scene_io ); -#endif SceneStringNames::free(); } diff --git a/scene/resources/SCsub b/scene/resources/SCsub index 87bd33e00e..eaa282ae1a 100644 --- a/scene/resources/SCsub +++ b/scene/resources/SCsub @@ -1,6 +1,7 @@ Import('env') env.add_source_files(env.scene_sources,"*.cpp") +env.add_source_files(env.scene_sources,"*.c") Export('env') diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 67f45ced2b..e6359f920b 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -1716,7 +1716,7 @@ void Animation::clear() { } -void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,float p_alowed_angular_err) { +void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,float p_alowed_angular_err,float p_max_optimizable_angle) { ERR_FAIL_INDEX(p_idx,tracks.size()); ERR_FAIL_COND(tracks[p_idx]->type!=TYPE_TRANSFORM); @@ -1779,6 +1779,7 @@ void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,fl } else { + Quat r02 = (q0.inverse() * q2).normalized(); Quat r01 = (q0.inverse() * q1).normalized(); @@ -1788,6 +1789,9 @@ void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,fl r02.get_axis_and_angle(v02,a02); r01.get_axis_and_angle(v01,a01); + if (Math::abs(a02)>p_max_optimizable_angle) + continue; + if (v01.dot(v02)<0) { //make sure both rotations go the same way to compare v02=-v02; @@ -1905,7 +1909,7 @@ void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,fl } -void Animation::optimize(float p_allowed_linear_err,float p_allowed_angular_err) { +void Animation::optimize(float p_allowed_linear_err,float p_allowed_angular_err,float p_angle_max) { int total_tt=0; @@ -1913,7 +1917,7 @@ void Animation::optimize(float p_allowed_linear_err,float p_allowed_angular_err) for(int i=0;i<tracks.size();i++) { if (tracks[i]->type==TYPE_TRANSFORM) - _transform_track_optimize(i,p_allowed_linear_err,p_allowed_angular_err); + _transform_track_optimize(i,p_allowed_linear_err,p_allowed_angular_err,p_angle_max); } diff --git a/scene/resources/animation.h b/scene/resources/animation.h index 4c4e2f0275..0c0290295a 100644 --- a/scene/resources/animation.h +++ b/scene/resources/animation.h @@ -204,7 +204,7 @@ private: return idxr; } - void _transform_track_optimize(int p_idx, float p_allowed_err=0.05, float p_alowed_angular_err=0.01); + void _transform_track_optimize(int p_idx, float p_allowed_err=0.05, float p_alowed_angular_err=0.01,float p_max_optimizable_angle=Math_PI*0.125); protected: @@ -271,7 +271,7 @@ public: void clear(); - void optimize(float p_allowed_linear_err=0.05,float p_allowed_angular_err=0.01); + void optimize(float p_allowed_linear_err=0.05,float p_allowed_angular_err=0.01,float p_max_optimizable_angle=Math_PI*0.125); Animation(); ~Animation(); diff --git a/scene/resources/baked_light.cpp b/scene/resources/baked_light.cpp index 647c8df5d4..226edec9ae 100644 --- a/scene/resources/baked_light.cpp +++ b/scene/resources/baked_light.cpp @@ -23,6 +23,27 @@ DVector<uint8_t> BakedLight::get_octree() const { return VS::get_singleton()->baked_light_get_octree(baked_light); } +void BakedLight::set_light(const DVector<uint8_t>& p_light) { + + VS::get_singleton()->baked_light_set_light(baked_light,p_light); +} + +DVector<uint8_t> BakedLight::get_light() const { + + return VS::get_singleton()->baked_light_get_light(baked_light); +} + + +void BakedLight::set_sampler_octree(const DVector<int>& p_sampler_octree) { + + VS::get_singleton()->baked_light_set_sampler_octree(baked_light,p_sampler_octree); +} + +DVector<int> BakedLight::get_sampler_octree() const { + + return VS::get_singleton()->baked_light_get_sampler_octree(baked_light); +} + @@ -199,6 +220,43 @@ float BakedLight::get_normal_damp() const { return normal_damp; } +void BakedLight::set_tint(float p_margin) { + tint=p_margin; +} + +float BakedLight::get_tint() const { + + return tint; +} + +void BakedLight::set_saturation(float p_margin) { + saturation=p_margin; +} + +float BakedLight::get_saturation() const { + + return saturation; +} + +void BakedLight::set_ao_radius(float p_ao_radius) { + ao_radius=p_ao_radius; +} + +float BakedLight::get_ao_radius() const { + return ao_radius; +} + +void BakedLight::set_ao_strength(float p_ao_strength) { + + ao_strength=p_ao_strength; +} + +float BakedLight::get_ao_strength() const { + + return ao_strength; +} + + void BakedLight::set_energy_multiplier(float p_multiplier){ energy_multiply=p_multiplier; @@ -329,6 +387,13 @@ void BakedLight::_bind_methods(){ ObjectTypeDB::bind_method(_MD("set_octree","octree"),&BakedLight::set_octree); ObjectTypeDB::bind_method(_MD("get_octree"),&BakedLight::get_octree); + ObjectTypeDB::bind_method(_MD("set_light","light"),&BakedLight::set_light); + ObjectTypeDB::bind_method(_MD("get_light"),&BakedLight::get_light); + + ObjectTypeDB::bind_method(_MD("set_sampler_octree","sampler_octree"),&BakedLight::set_sampler_octree); + ObjectTypeDB::bind_method(_MD("get_sampler_octree"),&BakedLight::get_sampler_octree); + + ObjectTypeDB::bind_method(_MD("add_lightmap","texture:Texture","gen_size"),&BakedLight::add_lightmap); ObjectTypeDB::bind_method(_MD("erase_lightmap","id"),&BakedLight::erase_lightmap); ObjectTypeDB::bind_method(_MD("clear_lightmaps"),&BakedLight::clear_lightmaps); @@ -357,6 +422,18 @@ void BakedLight::_bind_methods(){ ObjectTypeDB::bind_method(_MD("set_normal_damp","normal_damp"),&BakedLight::set_normal_damp); ObjectTypeDB::bind_method(_MD("get_normal_damp"),&BakedLight::get_normal_damp); + ObjectTypeDB::bind_method(_MD("set_tint","tint"),&BakedLight::set_tint); + ObjectTypeDB::bind_method(_MD("get_tint"),&BakedLight::get_tint); + + ObjectTypeDB::bind_method(_MD("set_saturation","saturation"),&BakedLight::set_saturation); + ObjectTypeDB::bind_method(_MD("get_saturation"),&BakedLight::get_saturation); + + ObjectTypeDB::bind_method(_MD("set_ao_radius","ao_radius"),&BakedLight::set_ao_radius); + ObjectTypeDB::bind_method(_MD("get_ao_radius"),&BakedLight::get_ao_radius); + + ObjectTypeDB::bind_method(_MD("set_ao_strength","ao_strength"),&BakedLight::set_ao_strength); + ObjectTypeDB::bind_method(_MD("get_ao_strength"),&BakedLight::get_ao_strength); + ObjectTypeDB::bind_method(_MD("set_format","format"),&BakedLight::set_format); ObjectTypeDB::bind_method(_MD("get_format"),&BakedLight::get_format); @@ -384,17 +461,24 @@ void BakedLight::_bind_methods(){ ADD_PROPERTY( PropertyInfo(Variant::REAL,"baking/plot_size",PROPERTY_HINT_RANGE,"1.0,16.0,0.01"),_SCS("set_plot_size"),_SCS("get_plot_size")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"baking/energy_mult",PROPERTY_HINT_RANGE,"0.01,4096.0,0.01"),_SCS("set_energy_multiplier"),_SCS("get_energy_multiplier")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"baking/gamma_adjust",PROPERTY_HINT_EXP_EASING),_SCS("set_gamma_adjust"),_SCS("get_gamma_adjust")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"baking/saturation",PROPERTY_HINT_RANGE,"0,8,0.01"),_SCS("set_saturation"),_SCS("get_saturation")); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/diffuse"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_DIFFUSE); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/specular"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_SPECULAR); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/translucent"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_TRANSLUCENT); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/conserve_energy"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_CONSERVE_ENERGY); + ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/linear_color"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_LINEAR_COLOR); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"lightmap/use_only_uv2"),_SCS("set_transfer_lightmaps_only_to_uv2"),_SCS("get_transfer_lightmaps_only_to_uv2")); ADD_PROPERTY( PropertyInfo(Variant::RAW_ARRAY,"octree",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_octree"),_SCS("get_octree")); + ADD_PROPERTY( PropertyInfo(Variant::RAW_ARRAY,"light",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_light"),_SCS("get_light")); + ADD_PROPERTY( PropertyInfo(Variant::INT_ARRAY,"sampler_octree",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_sampler_octree"),_SCS("get_sampler_octree")); ADD_PROPERTY( PropertyInfo(Variant::ARRAY,"lightmaps",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_lightmap_data"),_SCS("_get_lightmap_data")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/cell_margin",PROPERTY_HINT_RANGE,"0.01,0.8,0.01"),_SCS("set_cell_extra_margin"),_SCS("get_cell_extra_margin")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/edge_damp",PROPERTY_HINT_RANGE,"0.0,8.0,0.1"),_SCS("set_edge_damp"),_SCS("get_edge_damp")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/normal_damp",PROPERTY_HINT_RANGE,"0.0,1.0,0.01"),_SCS("set_normal_damp"),_SCS("get_normal_damp")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/light_tint",PROPERTY_HINT_RANGE,"0.0,1.0,0.01"),_SCS("set_tint"),_SCS("get_tint")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/ao_radius",PROPERTY_HINT_RANGE,"0.0,16.0,0.01"),_SCS("set_ao_radius"),_SCS("get_ao_radius")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/ao_strength",PROPERTY_HINT_RANGE,"0.0,1.0,0.01"),_SCS("set_ao_strength"),_SCS("get_ao_strength")); BIND_CONSTANT( MODE_OCTREE ); BIND_CONSTANT( MODE_LIGHTMAPS ); @@ -415,18 +499,24 @@ BakedLight::BakedLight() { lattice_subdiv=4; plot_size=2.5; bounces=1; - energy_multiply=1.0; - gamma_adjust=1.0; + energy_multiply=2.0; + gamma_adjust=0.7; cell_extra_margin=0.05; edge_damp=0.0; normal_damp=0.0; + saturation=1; + tint=0.0; + ao_radius=2.5; + ao_strength=0.7; format=FORMAT_RGB; transfer_only_uv2=false; + flags[BAKE_DIFFUSE]=true; flags[BAKE_SPECULAR]=false; flags[BAKE_TRANSLUCENT]=true; flags[BAKE_CONSERVE_ENERGY]=false; + flags[BAKE_LINEAR_COLOR]=false; mode=MODE_OCTREE; baked_light=VS::get_singleton()->baked_light_create(); diff --git a/scene/resources/baked_light.h b/scene/resources/baked_light.h index 57ed7d7aee..41e1e5f9e0 100644 --- a/scene/resources/baked_light.h +++ b/scene/resources/baked_light.h @@ -26,6 +26,7 @@ public: BAKE_SPECULAR, BAKE_TRANSLUCENT, BAKE_CONSERVE_ENERGY, + BAKE_LINEAR_COLOR, BAKE_MAX }; @@ -50,6 +51,10 @@ private: float cell_extra_margin; float edge_damp; float normal_damp; + float tint; + float ao_radius; + float ao_strength; + float saturation; int bounces; bool transfer_only_uv2; Format format; @@ -99,6 +104,18 @@ public: void set_normal_damp(float p_margin); float get_normal_damp() const; + void set_tint(float p_margin); + float get_tint() const; + + void set_saturation(float p_saturation); + float get_saturation() const; + + void set_ao_radius(float p_ao_radius); + float get_ao_radius() const; + + void set_ao_strength(float p_ao_strength); + float get_ao_strength() const; + void set_bake_flag(BakeFlags p_flags,bool p_enable); bool get_bake_flag(BakeFlags p_flags) const; @@ -114,6 +131,14 @@ public: void set_octree(const DVector<uint8_t>& p_octree); DVector<uint8_t> get_octree() const; + void set_light(const DVector<uint8_t>& p_light); + DVector<uint8_t> get_light() const; + + void set_sampler_octree(const DVector<int>& p_sampler_octree); + DVector<int> get_sampler_octree() const; + + + void add_lightmap(const Ref<Texture> &p_texture,Size2 p_gen_size=Size2(256,256)); void set_lightmap_gen_size(int p_idx,const Size2& p_size); Size2 get_lightmap_gen_size(int p_idx) const; diff --git a/scene/resources/image_path_finder.cpp b/scene/resources/image_path_finder.cpp deleted file mode 100644 index 1a7758789c..0000000000 --- a/scene/resources/image_path_finder.cpp +++ /dev/null @@ -1,427 +0,0 @@ -/*************************************************************************/ -/* image_path_finder.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "image_path_finder.h"
-
-
-void ImagePathFinder::_unlock() {
-
- lock=DVector<Cell>::Write();
- cells=NULL;
-
-}
-
-void ImagePathFinder::_lock() {
-
- lock = cell_data.write();
- cells=lock.ptr();
-
-}
-
-
-bool ImagePathFinder::_can_go_straigth(const Point2& p_from, const Point2& p_to) const {
-
- int x1=p_from.x;
- int y1=p_from.y;
- int x2=p_to.x;
- int y2=p_to.y;
-
-#define _TEST_VALID \
- {\
- uint32_t ofs=drawy*width+drawx;\
- if (cells[ofs].solid) {\
- if (!((drawx>0 && cells[ofs-1].visited) ||\
- (drawx<width-1 && cells[ofs+1].visited) ||\
- (drawy>0 && cells[ofs-width].visited) ||\
- (drawy<height-1 && cells[ofs+width].visited))) {\
- return false;\
- }\
- }\
- }\
-
-
- int n, deltax, deltay, sgndeltax, sgndeltay, deltaxabs, deltayabs, x, y, drawx, drawy;
- deltax = x2 - x1;
- deltay = y2 - y1;
- deltaxabs = ABS(deltax);
- deltayabs = ABS(deltay);
- sgndeltax = SGN(deltax);
- sgndeltay = SGN(deltay);
- x = deltayabs >> 1;
- y = deltaxabs >> 1;
- drawx = x1;
- drawy = y1;
- int pc=0;
-
- _TEST_VALID
-
- if(deltaxabs >= deltayabs) {
- for(n = 0; n < deltaxabs; n++) {
- y += deltayabs;
- if(y >= deltaxabs){
- y -= deltaxabs;
- drawy += sgndeltay;
- }
- drawx += sgndeltax;
- _TEST_VALID
- }
- } else {
- for(n = 0; n < deltayabs; n++) {
- x += deltaxabs;
- if(x >= deltayabs) {
- x -= deltayabs;
- drawx += sgndeltax;
- }
- drawy += sgndeltay;
- _TEST_VALID
- }
- }
- return true;
-
-
-}
-
-bool ImagePathFinder::_is_linear_path(const Point2& p_from, const Point2& p_to) {
-
- int x1=p_from.x;
- int y1=p_from.y;
- int x2=p_to.x;
- int y2=p_to.y;
-
-#define _TEST_CELL \
- if (cells[drawy*width+drawx].solid)\
- return false;
-
-
- int n, deltax, deltay, sgndeltax, sgndeltay, deltaxabs, deltayabs, x, y, drawx, drawy;
- deltax = x2 - x1;
- deltay = y2 - y1;
- deltaxabs = ABS(deltax);
- deltayabs = ABS(deltay);
- sgndeltax = SGN(deltax);
- sgndeltay = SGN(deltay);
- x = deltayabs >> 1;
- y = deltaxabs >> 1;
- drawx = x1;
- drawy = y1;
- int pc=0;
-
- _TEST_CELL
-
- if(deltaxabs >= deltayabs) {
- for(n = 0; n < deltaxabs; n++) {
- y += deltayabs;
- if(y >= deltaxabs){
- y -= deltaxabs;
- drawy += sgndeltay;
- }
- drawx += sgndeltax;
- _TEST_CELL
- }
- } else {
- for(n = 0; n < deltayabs; n++) {
- x += deltaxabs;
- if(x >= deltayabs) {
- x -= deltayabs;
- drawx += sgndeltax;
- }
- drawy += sgndeltay;
- _TEST_CELL
- }
- }
- return true;
-}
-
-
-DVector<Point2> ImagePathFinder::find_path(const Point2& p_from, const Point2& p_to,bool p_optimize) {
-
-
- Point2i from=p_from;
- Point2i to=p_to;
-
- ERR_FAIL_COND_V(from.x < 0,DVector<Point2>());
- ERR_FAIL_COND_V(from.y < 0,DVector<Point2>());
- ERR_FAIL_COND_V(from.x >=width,DVector<Point2>());
- ERR_FAIL_COND_V(from.y >=height,DVector<Point2>());
- ERR_FAIL_COND_V(to.x < 0,DVector<Point2>());
- ERR_FAIL_COND_V(to.y < 0,DVector<Point2>());
- ERR_FAIL_COND_V(to.x >=width,DVector<Point2>());
- ERR_FAIL_COND_V(to.y >=height,DVector<Point2>());
-
- if (from==to) {
- DVector<Point2> p;
- p.push_back(from);
- return p;
- }
-
- _lock();
-
-
- if (p_optimize) { //try a line first
-
- if (_is_linear_path(p_from,p_to)) {
- _unlock();
- DVector<Point2> p;
- p.push_back(from);
- p.push_back(to);
- return p;
- }
- }
-
-
- //clear all
- for(int i=0;i<width*height;i++) {
-
- bool s = cells[i].solid;
- cells[i].data=0;
- cells[i].solid=s;
- }
-
-#define CELL_INDEX(m_p) (m_p.y*width+m_p.x)
-#define CELL_COST(m_p) (cells[CELL_INDEX(m_p)].cost+( ABS(m_p.x-to.x)+ABS(m_p.y-to.y))*10)
-
-
- Set<Point2i> pending;
- pending.insert(from);
-
- //helper constants
- static const Point2i neighbour_rel[8]={
- Point2i(-1,-1), //0
- Point2i(-1, 0), //1
- Point2i(-1,+1), //2
- Point2i( 0,-1), //3
- Point2i( 0,+1), //4
- Point2i(+1,-1), //5
- Point2i(+1, 0), //6
- Point2i(+1,+1) }; //7
-
- static const int neighbour_cost[8]={
- 14,
- 10,
- 14,
- 10,
- 10,
- 14,
- 10,
- 14
- };
-
- static const int neighbour_parent[8]={
- 7,
- 6,
- 5,
- 4,
- 3,
- 2,
- 1,
- 0,
- };
-
- while(true) {
-
- if (pending.size() == 0) {
- _unlock();
- return DVector<Point2>(); // points don't connect
- }
- Point2i current;
- int lc=0x7FFFFFFF;
- { //find the one with the least cost
-
- Set<Point2i>::Element *Efound=NULL;
- for (Set<Point2i>::Element *E=pending.front();E;E=E->next()) {
-
- int cc =CELL_COST(E->get());
- if (cc<lc) {
- lc=cc;
- current=E->get();
- Efound=E;
-
- }
-
- }
- pending.erase(Efound);
- }
-
- Cell &c = cells[CELL_INDEX(current)];
-
- //search around other cells
-
-
- int accum_cost = (from==current) ? 0 : cells[CELL_INDEX((current + neighbour_rel[c.parent]))].cost;
-
- bool done=false;
-
- for(int i=0;i<8;i++) {
-
- Point2i neighbour=current+neighbour_rel[i];
- if (neighbour.x<0 || neighbour.y<0 || neighbour.x>=width || neighbour.y>=height)
- continue;
-
- Cell &n = cells[CELL_INDEX(neighbour)];
- if (n.solid)
- continue; //no good
-
- int cost = neighbour_cost[i]+accum_cost;
-
- if (n.visited && n.cost < cost)
- continue;
-
- n.cost=cost;
- n.parent=neighbour_parent[i];
- n.visited=true;
- pending.insert(neighbour);
- if (neighbour==to)
- done=true;
-
- }
-
- if (done)
- break;
- }
-
-
- // go througuh poins twice, first compute amount, then add them
-
- Point2i current=to;
- int pcount=0;
-
- while(true) {
-
- Cell &c = cells[CELL_INDEX(current)];
- c.visited=true;
- pcount++;
- if (current==from)
- break;
- current+=neighbour_rel[ c.parent ];
- }
-
- //now place them in an array
- DVector<Vector2> result;
- result.resize(pcount);
-
- DVector<Vector2>::Write res=result.write();
-
- current=to;
- int pidx=pcount-1;
-
- while(true) {
-
- Cell &c = cells[CELL_INDEX(current)];
- res[pidx]=current;
- pidx--;
- if (current==from)
- break;
- current+=neighbour_rel[ c.parent ];
- }
-
-
- //simplify..
-
-
- if (p_optimize) {
-
- int p=pcount-1;
- while(p>0) {
-
-
- int limit=p;
- while(limit>0) {
-
- limit--;
- if (!_can_go_straigth(res[p],res[limit]))
- break;
- }
-
-
- if (limit<p-1) {
- int diff = p-limit-1;
- pcount-=diff;
- for(int i=limit+1;i<pcount;i++) {
-
- res[i]=res[i+diff];
- }
- }
- p=limit;
- }
- }
-
- res=DVector<Vector2>::Write();
- result.resize(pcount);
- return result;
-}
-
-Size2 ImagePathFinder::get_size() const {
-
- return Size2(width,height);
-}
-bool ImagePathFinder::is_solid(const Point2& p_pos) {
-
-
- Point2i pos = p_pos;
-
- ERR_FAIL_COND_V(pos.x<0,true);
- ERR_FAIL_COND_V(pos.y<0,true);
- ERR_FAIL_COND_V(pos.x>=width,true);
- ERR_FAIL_COND_V(pos.y>=height,true);
-
- return cell_data[pos.y*width+pos.x].solid;
-}
-
-void ImagePathFinder::create_from_image_alpha(const Image& p_image) {
-
- ERR_FAIL_COND(p_image.get_format() != Image::FORMAT_RGBA);
- width = p_image.get_width();
- height = p_image.get_height();
- DVector<uint8_t> data = p_image.get_data();
- cell_data.resize(width * height);
- DVector<uint8_t>::Read read = data.read();
- DVector<Cell>::Write write = cell_data.write();
- for (int i=0; i<width * height; i++) {
- Cell cell;
- cell.data = 0;
- cell.solid = read[i*4+3] < 128;
- write[i] = cell;
- };
-};
-
-
-void ImagePathFinder::_bind_methods() {
-
- ObjectTypeDB::bind_method(_MD("find_path","from","to","optimize"),&ImagePathFinder::find_path,DEFVAL(false));
- ObjectTypeDB::bind_method(_MD("get_size"),&ImagePathFinder::get_size);
- ObjectTypeDB::bind_method(_MD("is_solid","pos"),&ImagePathFinder::is_solid);
- ObjectTypeDB::bind_method(_MD("create_from_image_alpha"),&ImagePathFinder::create_from_image_alpha);
-}
-
-ImagePathFinder::ImagePathFinder()
-{
-
- cells=NULL;
- width=0;
- height=0;
-}
diff --git a/scene/resources/image_path_finder.h b/scene/resources/image_path_finder.h deleted file mode 100644 index e975ea5ed9..0000000000 --- a/scene/resources/image_path_finder.h +++ /dev/null @@ -1,84 +0,0 @@ -/*************************************************************************/ -/* image_path_finder.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef IMAGE_PATH_FINDER_H
-#define IMAGE_PATH_FINDER_H
-
-#include "resource.h"
-
-class ImagePathFinder : public Resource{
-
-
- OBJ_TYPE(ImagePathFinder,Resource);
- union Cell {
-
- struct {
- bool solid:1;
- bool visited:1;
- bool final:1;
- uint8_t parent:3;
- uint32_t cost:26;
- };
-
- uint32_t data;
- };
-
-
-
-
-
- DVector<Cell>::Write lock;
- DVector<Cell> cell_data;
-
- uint32_t width;
- uint32_t height;
- Cell* cells; //when unlocked
-
- void _unlock();
- void _lock();
-
-
- _FORCE_INLINE_ bool _can_go_straigth(const Point2& p_from, const Point2& p_to) const;
- _FORCE_INLINE_ bool _is_linear_path(const Point2& p_from, const Point2& p_to);
-
-protected:
-
- static void _bind_methods();
-public:
-
- DVector<Point2> find_path(const Point2& p_from, const Point2& p_to,bool p_optimize=false);
- Size2 get_size() const;
- bool is_solid(const Point2& p_pos);
- void create_from_image_alpha(const Image& p_image);
-
-
-
- ImagePathFinder();
-};
-
-#endif // IMAGE_PATH_FINDER_H
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 2314926b2b..2c278f4fed 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -36,7 +36,8 @@ static const char*_flag_names[Material::FLAG_MAX]={ "invert_faces", "unshaded", "on_top", - "lightmap_on_uv2" + "lightmap_on_uv2", + "colarray_is_srgb" }; @@ -46,7 +47,8 @@ static const Material::Flag _flag_indices[Material::FLAG_MAX]={ Material::FLAG_INVERT_FACES, Material::FLAG_UNSHADED, Material::FLAG_ONTOP, - Material::FLAG_LIGHTMAP_ON_UV2 + Material::FLAG_LIGHTMAP_ON_UV2, + Material::FLAG_COLOR_ARRAY_SRGB, }; @@ -132,6 +134,8 @@ void Material::_bind_methods() { BIND_CONSTANT( FLAG_INVERT_FACES ); BIND_CONSTANT( FLAG_UNSHADED ); BIND_CONSTANT( FLAG_ONTOP ); + BIND_CONSTANT( FLAG_LIGHTMAP_ON_UV2 ); + BIND_CONSTANT( FLAG_COLOR_ARRAY_SRGB ); BIND_CONSTANT( FLAG_MAX ); BIND_CONSTANT( DEPTH_DRAW_ALWAYS ); @@ -156,6 +160,8 @@ Material::Material(const RID& p_material) { flags[FLAG_INVERT_FACES]=false; flags[FLAG_UNSHADED]=false; flags[FLAG_ONTOP]=false; + flags[FLAG_LIGHTMAP_ON_UV2]=true; + flags[FLAG_COLOR_ARRAY_SRGB]=false; depth_draw_mode=DEPTH_DRAW_OPAQUE_ONLY; @@ -316,14 +322,14 @@ Transform FixedMaterial::get_uv_transform() const { void FixedMaterial::set_fixed_flag(FixedFlag p_flag, bool p_value) { - ERR_FAIL_INDEX(p_flag,4); + ERR_FAIL_INDEX(p_flag,5); fixed_flags[p_flag]=p_value; VisualServer::get_singleton()->fixed_material_set_flag(material,(VS::FixedMaterialFlags)p_flag,p_value); } bool FixedMaterial::get_fixed_flag(FixedFlag p_flag) const { - ERR_FAIL_INDEX_V(p_flag,4,false); + ERR_FAIL_INDEX_V(p_flag,5,false); return fixed_flags[p_flag]; } @@ -371,6 +377,7 @@ void FixedMaterial::_bind_methods() { ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/use_color_array" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_USE_COLOR_ARRAY); ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/use_point_size" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_USE_POINT_SIZE); ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/discard_alpha" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_DISCARD_ALPHA); + ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/use_xy_normalmap" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_USE_XY_NORMALMAP); ADD_PROPERTYI( PropertyInfo( Variant::COLOR, "params/diffuse" ), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_DIFFUSE); ADD_PROPERTYI( PropertyInfo( Variant::COLOR, "params/specular", PROPERTY_HINT_COLOR_NO_ALPHA ), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SPECULAR ); ADD_PROPERTYI( PropertyInfo( Variant::COLOR, "params/emission", PROPERTY_HINT_COLOR_NO_ALPHA ), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_EMISSION ); @@ -426,11 +433,14 @@ FixedMaterial::FixedMaterial() : Material(VS::get_singleton()->fixed_material_cr param[PARAM_SHADE_PARAM]=0.5; param[PARAM_DETAIL]=1.0; - + set_flag(FLAG_COLOR_ARRAY_SRGB,true); fixed_flags[FLAG_USE_ALPHA]=false; fixed_flags[FLAG_USE_COLOR_ARRAY]=false; fixed_flags[FLAG_USE_POINT_SIZE]=false; + fixed_flags[FLAG_USE_XY_NORMALMAP]=false; + fixed_flags[FLAG_DISCARD_ALPHA]=false; + for(int i=0;i<PARAM_MAX;i++) { @@ -540,6 +550,10 @@ void ShaderMaterial::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_shader","shader:Shader"), &ShaderMaterial::set_shader ); ObjectTypeDB::bind_method(_MD("get_shader:Shader"), &ShaderMaterial::get_shader ); + + ObjectTypeDB::bind_method(_MD("set_shader_param","param","value:var"), &ShaderMaterial::set_shader_param); + ObjectTypeDB::bind_method(_MD("get_shader_param:var","param"), &ShaderMaterial::get_shader_param); + ObjectTypeDB::bind_method(_MD("_shader_changed"), &ShaderMaterial::_shader_changed ); } @@ -585,6 +599,8 @@ ParticleSystemMaterial::ParticleSystemMaterial() :Material(VisualServer::get_sin set_depth_draw_mode(DEPTH_DRAW_NEVER); VisualServer::get_singleton()->fixed_material_set_flag(material,VS::FIXED_MATERIAL_FLAG_USE_ALPHA,true); VisualServer::get_singleton()->fixed_material_set_flag(material,VS::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,true); + set_flag(FLAG_COLOR_ARRAY_SRGB,true); + } ParticleSystemMaterial::~ParticleSystemMaterial() { @@ -655,6 +671,8 @@ UnshadedMaterial::UnshadedMaterial() :Material(VisualServer::get_singleton()->fi set_flag(FLAG_UNSHADED,true); set_use_alpha(true); + set_flag(FLAG_COLOR_ARRAY_SRGB,true); + } UnshadedMaterial::~UnshadedMaterial() { diff --git a/scene/resources/material.h b/scene/resources/material.h index 23ecb18fac..9c3feede08 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -54,6 +54,7 @@ public: FLAG_UNSHADED = VS::MATERIAL_FLAG_UNSHADED, FLAG_ONTOP = VS::MATERIAL_FLAG_ONTOP, FLAG_LIGHTMAP_ON_UV2 = VS::MATERIAL_FLAG_LIGHTMAP_ON_UV2, + FLAG_COLOR_ARRAY_SRGB = VS::MATERIAL_FLAG_COLOR_ARRAY_SRGB, FLAG_MAX = VS::MATERIAL_FLAG_MAX }; @@ -141,7 +142,9 @@ public: FLAG_USE_ALPHA=VS::FIXED_MATERIAL_FLAG_USE_ALPHA, FLAG_USE_COLOR_ARRAY=VS::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY, FLAG_USE_POINT_SIZE=VS::FIXED_MATERIAL_FLAG_USE_POINT_SIZE, - FLAG_DISCARD_ALPHA=VS::FIXED_MATERIAL_FLAG_DISCARD_ALPHA + FLAG_DISCARD_ALPHA=VS::FIXED_MATERIAL_FLAG_DISCARD_ALPHA, + FLAG_USE_XY_NORMALMAP=VS::FIXED_MATERIAL_FLAG_USE_XY_NORMALMAP, + FLAG_MAX=VS::FIXED_MATERIAL_FLAG_MAX }; enum LightShader { @@ -166,7 +169,7 @@ private: Ref<Texture> texture_param[PARAM_MAX]; TexCoordMode texture_texcoord[PARAM_MAX]; LightShader light_shader; - bool fixed_flags[3]; + bool fixed_flags[FLAG_MAX]; float point_size; diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index c6e492fcb3..3aeccdc551 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -29,6 +29,7 @@ #include "mesh.h" #include "scene/resources/concave_polygon_shape.h" #include "scene/resources/convex_polygon_shape.h" +#include "surface_tool.h" static const char*_array_name[]={ "vertex_array", @@ -648,6 +649,30 @@ void Mesh::center_geometry() { } +void Mesh::regen_normalmaps() { + + + Vector< Ref<SurfaceTool> > surfs; + for(int i=0;i<get_surface_count();i++) { + + Ref<SurfaceTool> st = memnew( SurfaceTool ); + st->create_from(Ref<Mesh>(this),i); + surfs.push_back(st); + } + + while (get_surface_count()) { + surface_remove(0); + } + + for(int i=0;i<surfs.size();i++) { + + surfs[i]->generate_tangents(); + surfs[i]->commit(Ref<Mesh>(this)); + } +} + + + Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { if (triangle_mesh.is_valid()) @@ -740,6 +765,8 @@ void Mesh::_bind_methods() { ObjectTypeDB::bind_method(_MD("surface_get_name","surf_idx"),&Mesh::surface_get_name); ObjectTypeDB::bind_method(_MD("center_geometry"),&Mesh::center_geometry); ObjectTypeDB::set_method_flags(get_type_static(),_SCS("center_geometry"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); + ObjectTypeDB::bind_method(_MD("regen_normalmaps"),&Mesh::regen_normalmaps); + ObjectTypeDB::set_method_flags(get_type_static(),_SCS("regen_normalmaps"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); ObjectTypeDB::bind_method(_MD("set_custom_aabb","aabb"),&Mesh::set_custom_aabb); ObjectTypeDB::bind_method(_MD("get_custom_aabb"),&Mesh::get_custom_aabb); diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index 5243163a4d..d6ab6a1198 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -167,6 +167,7 @@ public: Ref<Shape> create_convex_shape() const; void center_geometry(); + void regen_normalmaps(); DVector<Face3> get_faces() const; Ref<TriangleMesh> generate_triangle_mesh() const; diff --git a/scene/resources/mikktspace.c b/scene/resources/mikktspace.c new file mode 100644 index 0000000000..62aa2da251 --- /dev/null +++ b/scene/resources/mikktspace.c @@ -0,0 +1,1890 @@ +/** \file mikktspace/mikktspace.c + * \ingroup mikktspace + */ +/** + * Copyright (C) 2011 by Morten S. Mikkelsen + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +#include <assert.h> +#include <stdio.h> +#include <math.h> +#include <string.h> +#include <float.h> +#include <stdlib.h> + +#include "mikktspace.h" + +#define TFALSE 0 +#define TTRUE 1 + +#ifndef M_PI +#define M_PI 3.1415926535897932384626433832795 +#endif + +#define INTERNAL_RND_SORT_SEED 39871946 + +// internal structure +typedef struct { + float x, y, z; +} SVec3; + +static tbool veq( const SVec3 v1, const SVec3 v2 ) +{ + return (v1.x == v2.x) && (v1.y == v2.y) && (v1.z == v2.z); +} + +static SVec3 vadd( const SVec3 v1, const SVec3 v2 ) +{ + SVec3 vRes; + + vRes.x = v1.x + v2.x; + vRes.y = v1.y + v2.y; + vRes.z = v1.z + v2.z; + + return vRes; +} + + +static SVec3 vsub( const SVec3 v1, const SVec3 v2 ) +{ + SVec3 vRes; + + vRes.x = v1.x - v2.x; + vRes.y = v1.y - v2.y; + vRes.z = v1.z - v2.z; + + return vRes; +} + +static SVec3 vscale(const float fS, const SVec3 v) +{ + SVec3 vRes; + + vRes.x = fS * v.x; + vRes.y = fS * v.y; + vRes.z = fS * v.z; + + return vRes; +} + +static float LengthSquared( const SVec3 v ) +{ + return v.x*v.x + v.y*v.y + v.z*v.z; +} + +static float Length( const SVec3 v ) +{ + return sqrtf(LengthSquared(v)); +} + +static SVec3 Normalize( const SVec3 v ) +{ + return vscale(1 / Length(v), v); +} + +static float vdot( const SVec3 v1, const SVec3 v2) +{ + return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z; +} + + +static tbool NotZero(const float fX) +{ + // could possibly use FLT_EPSILON instead + return fabsf(fX) > FLT_MIN; +} + +static tbool VNotZero(const SVec3 v) +{ + // might change this to an epsilon based test + return NotZero(v.x) || NotZero(v.y) || NotZero(v.z); +} + + + +typedef struct { + int iNrFaces; + int * pTriMembers; +} SSubGroup; + +typedef struct { + int iNrFaces; + int * pFaceIndices; + int iVertexRepresentitive; + tbool bOrientPreservering; +} SGroup; + +// +#define MARK_DEGENERATE 1 +#define QUAD_ONE_DEGEN_TRI 2 +#define GROUP_WITH_ANY 4 +#define ORIENT_PRESERVING 8 + + + +typedef struct { + int FaceNeighbors[3]; + SGroup * AssignedGroup[3]; + + // normalized first order face derivatives + SVec3 vOs, vOt; + float fMagS, fMagT; // original magnitudes + + // determines if the current and the next triangle are a quad. + int iOrgFaceNumber; + int iFlag, iTSpacesOffs; + unsigned char vert_num[4]; +} STriInfo; + +typedef struct { + SVec3 vOs; + float fMagS; + SVec3 vOt; + float fMagT; + int iCounter; // this is to average back into quads. + tbool bOrient; +} STSpace; + +static int GenerateInitialVerticesIndexList(STriInfo pTriInfos[], int piTriList_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn); +static void GenerateSharedVerticesIndexList(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn); +static void InitTriInfo(STriInfo pTriInfos[], const int piTriListIn[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn); +static int Build4RuleGroups(STriInfo pTriInfos[], SGroup pGroups[], int piGroupTrianglesBuffer[], const int piTriListIn[], const int iNrTrianglesIn); +static tbool GenerateTSpaces(STSpace psTspace[], const STriInfo pTriInfos[], const SGroup pGroups[], + const int iNrActiveGroups, const int piTriListIn[], const float fThresCos, + const SMikkTSpaceContext * pContext); + +static int MakeIndex(const int iFace, const int iVert) +{ + assert(iVert>=0 && iVert<4 && iFace>=0); + return (iFace<<2) | (iVert&0x3); +} + +static void IndexToData(int * piFace, int * piVert, const int iIndexIn) +{ + piVert[0] = iIndexIn&0x3; + piFace[0] = iIndexIn>>2; +} + +static STSpace AvgTSpace(const STSpace * pTS0, const STSpace * pTS1) +{ + STSpace ts_res; + + // this if is important. Due to floating point precision + // averaging when ts0==ts1 will cause a slight difference + // which results in tangent space splits later on + if (pTS0->fMagS==pTS1->fMagS && pTS0->fMagT==pTS1->fMagT && + veq(pTS0->vOs,pTS1->vOs) && veq(pTS0->vOt, pTS1->vOt)) + { + ts_res.fMagS = pTS0->fMagS; + ts_res.fMagT = pTS0->fMagT; + ts_res.vOs = pTS0->vOs; + ts_res.vOt = pTS0->vOt; + } + else + { + ts_res.fMagS = 0.5f*(pTS0->fMagS+pTS1->fMagS); + ts_res.fMagT = 0.5f*(pTS0->fMagT+pTS1->fMagT); + ts_res.vOs = vadd(pTS0->vOs,pTS1->vOs); + ts_res.vOt = vadd(pTS0->vOt,pTS1->vOt); + if ( VNotZero(ts_res.vOs) ) ts_res.vOs = Normalize(ts_res.vOs); + if ( VNotZero(ts_res.vOt) ) ts_res.vOt = Normalize(ts_res.vOt); + } + + return ts_res; +} + + + +static SVec3 GetPosition(const SMikkTSpaceContext * pContext, const int index); +static SVec3 GetNormal(const SMikkTSpaceContext * pContext, const int index); +static SVec3 GetTexCoord(const SMikkTSpaceContext * pContext, const int index); + + +// degen triangles +static void DegenPrologue(STriInfo pTriInfos[], int piTriList_out[], const int iNrTrianglesIn, const int iTotTris); +static void DegenEpilogue(STSpace psTspace[], STriInfo pTriInfos[], int piTriListIn[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn, const int iTotTris); + + +tbool genTangSpaceDefault(const SMikkTSpaceContext * pContext) +{ + return genTangSpace(pContext, 180.0f); +} + +tbool genTangSpace(const SMikkTSpaceContext * pContext, const float fAngularThreshold) +{ + // count nr_triangles + int * piTriListIn = NULL, * piGroupTrianglesBuffer = NULL; + STriInfo * pTriInfos = NULL; + SGroup * pGroups = NULL; + STSpace * psTspace = NULL; + int iNrTrianglesIn = 0, f=0, t=0, i=0; + int iNrTSPaces = 0, iTotTris = 0, iDegenTriangles = 0, iNrMaxGroups = 0; + int iNrActiveGroups = 0, index = 0; + const int iNrFaces = pContext->m_pInterface->m_getNumFaces(pContext); + tbool bRes = TFALSE; + const float fThresCos = (float) cos((fAngularThreshold*(float)M_PI)/180.0f); + + // verify all call-backs have been set + if ( pContext->m_pInterface->m_getNumFaces==NULL || + pContext->m_pInterface->m_getNumVerticesOfFace==NULL || + pContext->m_pInterface->m_getPosition==NULL || + pContext->m_pInterface->m_getNormal==NULL || + pContext->m_pInterface->m_getTexCoord==NULL ) + return TFALSE; + + // count triangles on supported faces + for (f=0; f<iNrFaces; f++) + { + const int verts = pContext->m_pInterface->m_getNumVerticesOfFace(pContext, f); + if (verts==3) ++iNrTrianglesIn; + else if (verts==4) iNrTrianglesIn += 2; + } + if (iNrTrianglesIn<=0) return TFALSE; + + // allocate memory for an index list + piTriListIn = (int *) malloc(sizeof(int)*3*iNrTrianglesIn); + pTriInfos = (STriInfo *) malloc(sizeof(STriInfo)*iNrTrianglesIn); + if (piTriListIn==NULL || pTriInfos==NULL) + { + if (piTriListIn!=NULL) free(piTriListIn); + if (pTriInfos!=NULL) free(pTriInfos); + return TFALSE; + } + + // make an initial triangle --> face index list + iNrTSPaces = GenerateInitialVerticesIndexList(pTriInfos, piTriListIn, pContext, iNrTrianglesIn); + + // make a welded index list of identical positions and attributes (pos, norm, texc) + //printf("gen welded index list begin\n"); + GenerateSharedVerticesIndexList(piTriListIn, pContext, iNrTrianglesIn); + //printf("gen welded index list end\n"); + + // Mark all degenerate triangles + iTotTris = iNrTrianglesIn; + iDegenTriangles = 0; + for (t=0; t<iTotTris; t++) + { + const int i0 = piTriListIn[t*3+0]; + const int i1 = piTriListIn[t*3+1]; + const int i2 = piTriListIn[t*3+2]; + const SVec3 p0 = GetPosition(pContext, i0); + const SVec3 p1 = GetPosition(pContext, i1); + const SVec3 p2 = GetPosition(pContext, i2); + if (veq(p0,p1) || veq(p0,p2) || veq(p1,p2)) // degenerate + { + pTriInfos[t].iFlag |= MARK_DEGENERATE; + ++iDegenTriangles; + } + } + iNrTrianglesIn = iTotTris - iDegenTriangles; + + // mark all triangle pairs that belong to a quad with only one + // good triangle. These need special treatment in DegenEpilogue(). + // Additionally, move all good triangles to the start of + // pTriInfos[] and piTriListIn[] without changing order and + // put the degenerate triangles last. + DegenPrologue(pTriInfos, piTriListIn, iNrTrianglesIn, iTotTris); + + + // evaluate triangle level attributes and neighbor list + //printf("gen neighbors list begin\n"); + InitTriInfo(pTriInfos, piTriListIn, pContext, iNrTrianglesIn); + //printf("gen neighbors list end\n"); + + + // based on the 4 rules, identify groups based on connectivity + iNrMaxGroups = iNrTrianglesIn*3; + pGroups = (SGroup *) malloc(sizeof(SGroup)*iNrMaxGroups); + piGroupTrianglesBuffer = (int *) malloc(sizeof(int)*iNrTrianglesIn*3); + if (pGroups==NULL || piGroupTrianglesBuffer==NULL) + { + if (pGroups!=NULL) free(pGroups); + if (piGroupTrianglesBuffer!=NULL) free(piGroupTrianglesBuffer); + free(piTriListIn); + free(pTriInfos); + return TFALSE; + } + //printf("gen 4rule groups begin\n"); + iNrActiveGroups = + Build4RuleGroups(pTriInfos, pGroups, piGroupTrianglesBuffer, piTriListIn, iNrTrianglesIn); + //printf("gen 4rule groups end\n"); + + // + + psTspace = (STSpace *) malloc(sizeof(STSpace)*iNrTSPaces); + if (psTspace==NULL) + { + free(piTriListIn); + free(pTriInfos); + free(pGroups); + free(piGroupTrianglesBuffer); + return TFALSE; + } + memset(psTspace, 0, sizeof(STSpace)*iNrTSPaces); + for (t=0; t<iNrTSPaces; t++) + { + psTspace[t].vOs.x=1.0f; psTspace[t].vOs.y=0.0f; psTspace[t].vOs.z=0.0f; psTspace[t].fMagS = 1.0f; + psTspace[t].vOt.x=0.0f; psTspace[t].vOt.y=1.0f; psTspace[t].vOt.z=0.0f; psTspace[t].fMagT = 1.0f; + } + + // make tspaces, each group is split up into subgroups if necessary + // based on fAngularThreshold. Finally a tangent space is made for + // every resulting subgroup + //printf("gen tspaces begin\n"); + bRes = GenerateTSpaces(psTspace, pTriInfos, pGroups, iNrActiveGroups, piTriListIn, fThresCos, pContext); + //printf("gen tspaces end\n"); + + // clean up + free(pGroups); + free(piGroupTrianglesBuffer); + + if (!bRes) // if an allocation in GenerateTSpaces() failed + { + // clean up and return false + free(pTriInfos); free(piTriListIn); free(psTspace); + return TFALSE; + } + + + // degenerate quads with one good triangle will be fixed by copying a space from + // the good triangle to the coinciding vertex. + // all other degenerate triangles will just copy a space from any good triangle + // with the same welded index in piTriListIn[]. + DegenEpilogue(psTspace, pTriInfos, piTriListIn, pContext, iNrTrianglesIn, iTotTris); + + free(pTriInfos); free(piTriListIn); + + index = 0; + for (f=0; f<iNrFaces; f++) + { + const int verts = pContext->m_pInterface->m_getNumVerticesOfFace(pContext, f); + if (verts!=3 && verts!=4) continue; + + + // I've decided to let degenerate triangles and group-with-anythings + // vary between left/right hand coordinate systems at the vertices. + // All healthy triangles on the other hand are built to always be either or. + + /*// force the coordinate system orientation to be uniform for every face. + // (this is already the case for good triangles but not for + // degenerate ones and those with bGroupWithAnything==true) + bool bOrient = psTspace[index].bOrient; + if (psTspace[index].iCounter == 0) // tspace was not derived from a group + { + // look for a space created in GenerateTSpaces() by iCounter>0 + bool bNotFound = true; + int i=1; + while (i<verts && bNotFound) + { + if (psTspace[index+i].iCounter > 0) bNotFound=false; + else ++i; + } + if (!bNotFound) bOrient = psTspace[index+i].bOrient; + }*/ + + // set data + for (i=0; i<verts; i++) + { + const STSpace * pTSpace = &psTspace[index]; + float tang[] = {pTSpace->vOs.x, pTSpace->vOs.y, pTSpace->vOs.z}; + float bitang[] = {pTSpace->vOt.x, pTSpace->vOt.y, pTSpace->vOt.z}; + if (pContext->m_pInterface->m_setTSpace!=NULL) + pContext->m_pInterface->m_setTSpace(pContext, tang, bitang, pTSpace->fMagS, pTSpace->fMagT, pTSpace->bOrient, f, i); + if (pContext->m_pInterface->m_setTSpaceBasic!=NULL) + pContext->m_pInterface->m_setTSpaceBasic(pContext, tang, pTSpace->bOrient==TTRUE ? 1.0f : (-1.0f), f, i); + + ++index; + } + } + + free(psTspace); + + + return TTRUE; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +typedef struct { + float vert[3]; + int index; +} STmpVert; + +static const int g_iCells = 2048; + +#ifdef _MSC_VER + #define NOINLINE __declspec(noinline) +#else + #define NOINLINE __attribute__ ((noinline)) +#endif + +// it is IMPORTANT that this function is called to evaluate the hash since +// inlining could potentially reorder instructions and generate different +// results for the same effective input value fVal. +static NOINLINE int FindGridCell(const float fMin, const float fMax, const float fVal) +{ + const float fIndex = g_iCells * ((fVal-fMin)/(fMax-fMin)); + const int iIndex = (int)fIndex; + return iIndex < g_iCells ? (iIndex >= 0 ? iIndex : 0) : (g_iCells - 1); +} + +static void MergeVertsFast(int piTriList_in_and_out[], STmpVert pTmpVert[], const SMikkTSpaceContext * pContext, const int iL_in, const int iR_in); +static void MergeVertsSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int pTable[], const int iEntries); +static void GenerateSharedVerticesIndexListSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn); + +static void GenerateSharedVerticesIndexList(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn) +{ + + // Generate bounding box + int * piHashTable=NULL, * piHashCount=NULL, * piHashOffsets=NULL, * piHashCount2=NULL; + STmpVert * pTmpVert = NULL; + int i=0, iChannel=0, k=0, e=0; + int iMaxCount=0; + SVec3 vMin = GetPosition(pContext, 0), vMax = vMin, vDim; + float fMin, fMax; + for (i=1; i<(iNrTrianglesIn*3); i++) + { + const int index = piTriList_in_and_out[i]; + + const SVec3 vP = GetPosition(pContext, index); + if (vMin.x > vP.x) vMin.x = vP.x; + else if (vMax.x < vP.x) vMax.x = vP.x; + if (vMin.y > vP.y) vMin.y = vP.y; + else if (vMax.y < vP.y) vMax.y = vP.y; + if (vMin.z > vP.z) vMin.z = vP.z; + else if (vMax.z < vP.z) vMax.z = vP.z; + } + + vDim = vsub(vMax,vMin); + iChannel = 0; + fMin = vMin.x; fMax=vMax.x; + if (vDim.y>vDim.x && vDim.y>vDim.z) + { + iChannel=1; + fMin = vMin.y, fMax=vMax.y; + } + else if (vDim.z>vDim.x) + { + iChannel=2; + fMin = vMin.z, fMax=vMax.z; + } + + // make allocations + piHashTable = (int *) malloc(sizeof(int)*iNrTrianglesIn*3); + piHashCount = (int *) malloc(sizeof(int)*g_iCells); + piHashOffsets = (int *) malloc(sizeof(int)*g_iCells); + piHashCount2 = (int *) malloc(sizeof(int)*g_iCells); + + if (piHashTable==NULL || piHashCount==NULL || piHashOffsets==NULL || piHashCount2==NULL) + { + if (piHashTable!=NULL) free(piHashTable); + if (piHashCount!=NULL) free(piHashCount); + if (piHashOffsets!=NULL) free(piHashOffsets); + if (piHashCount2!=NULL) free(piHashCount2); + GenerateSharedVerticesIndexListSlow(piTriList_in_and_out, pContext, iNrTrianglesIn); + return; + } + memset(piHashCount, 0, sizeof(int)*g_iCells); + memset(piHashCount2, 0, sizeof(int)*g_iCells); + + // count amount of elements in each cell unit + for (i=0; i<(iNrTrianglesIn*3); i++) + { + const int index = piTriList_in_and_out[i]; + const SVec3 vP = GetPosition(pContext, index); + const float fVal = iChannel==0 ? vP.x : (iChannel==1 ? vP.y : vP.z); + const int iCell = FindGridCell(fMin, fMax, fVal); + ++piHashCount[iCell]; + } + + // evaluate start index of each cell. + piHashOffsets[0]=0; + for (k=1; k<g_iCells; k++) + piHashOffsets[k]=piHashOffsets[k-1]+piHashCount[k-1]; + + // insert vertices + for (i=0; i<(iNrTrianglesIn*3); i++) + { + const int index = piTriList_in_and_out[i]; + const SVec3 vP = GetPosition(pContext, index); + const float fVal = iChannel==0 ? vP.x : (iChannel==1 ? vP.y : vP.z); + const int iCell = FindGridCell(fMin, fMax, fVal); + int * pTable = NULL; + + assert(piHashCount2[iCell]<piHashCount[iCell]); + pTable = &piHashTable[piHashOffsets[iCell]]; + pTable[piHashCount2[iCell]] = i; // vertex i has been inserted. + ++piHashCount2[iCell]; + } + for (k=0; k<g_iCells; k++) + assert(piHashCount2[k] == piHashCount[k]); // verify the count + free(piHashCount2); + + // find maximum amount of entries in any hash entry + iMaxCount = piHashCount[0]; + for (k=1; k<g_iCells; k++) + if (iMaxCount<piHashCount[k]) + iMaxCount=piHashCount[k]; + pTmpVert = (STmpVert *) malloc(sizeof(STmpVert)*iMaxCount); + + + // complete the merge + for (k=0; k<g_iCells; k++) + { + // extract table of cell k and amount of entries in it + int * pTable = &piHashTable[piHashOffsets[k]]; + const int iEntries = piHashCount[k]; + if (iEntries < 2) continue; + + if (pTmpVert!=NULL) + { + for (e=0; e<iEntries; e++) + { + int i = pTable[e]; + const SVec3 vP = GetPosition(pContext, piTriList_in_and_out[i]); + pTmpVert[e].vert[0] = vP.x; pTmpVert[e].vert[1] = vP.y; + pTmpVert[e].vert[2] = vP.z; pTmpVert[e].index = i; + } + MergeVertsFast(piTriList_in_and_out, pTmpVert, pContext, 0, iEntries-1); + } + else + MergeVertsSlow(piTriList_in_and_out, pContext, pTable, iEntries); + } + + if (pTmpVert!=NULL) { free(pTmpVert); } + free(piHashTable); + free(piHashCount); + free(piHashOffsets); +} + +static void MergeVertsFast(int piTriList_in_and_out[], STmpVert pTmpVert[], const SMikkTSpaceContext * pContext, const int iL_in, const int iR_in) +{ + // make bbox + int c=0, l=0, channel=0; + float fvMin[3], fvMax[3]; + float dx=0, dy=0, dz=0, fSep=0; + for (c=0; c<3; c++) + { fvMin[c]=pTmpVert[iL_in].vert[c]; fvMax[c]=fvMin[c]; } + for (l=(iL_in+1); l<=iR_in; l++) + for (c=0; c<3; c++) + if (fvMin[c]>pTmpVert[l].vert[c]) fvMin[c]=pTmpVert[l].vert[c]; + else if (fvMax[c]<pTmpVert[l].vert[c]) fvMax[c]=pTmpVert[l].vert[c]; + + dx = fvMax[0]-fvMin[0]; + dy = fvMax[1]-fvMin[1]; + dz = fvMax[2]-fvMin[2]; + + channel = 0; + if (dy>dx && dy>dz) channel=1; + else if (dz>dx) channel=2; + + fSep = 0.5f*(fvMax[channel]+fvMin[channel]); + + // terminate recursion when the separation/average value + // is no longer strictly between fMin and fMax values. + if (fSep>=fvMax[channel] || fSep<=fvMin[channel]) + { + // complete the weld + for (l=iL_in; l<=iR_in; l++) + { + int i = pTmpVert[l].index; + const int index = piTriList_in_and_out[i]; + const SVec3 vP = GetPosition(pContext, index); + const SVec3 vN = GetNormal(pContext, index); + const SVec3 vT = GetTexCoord(pContext, index); + + tbool bNotFound = TTRUE; + int l2=iL_in, i2rec=-1; + while (l2<l && bNotFound) + { + const int i2 = pTmpVert[l2].index; + const int index2 = piTriList_in_and_out[i2]; + const SVec3 vP2 = GetPosition(pContext, index2); + const SVec3 vN2 = GetNormal(pContext, index2); + const SVec3 vT2 = GetTexCoord(pContext, index2); + i2rec=i2; + + //if (vP==vP2 && vN==vN2 && vT==vT2) + if (vP.x==vP2.x && vP.y==vP2.y && vP.z==vP2.z && + vN.x==vN2.x && vN.y==vN2.y && vN.z==vN2.z && + vT.x==vT2.x && vT.y==vT2.y && vT.z==vT2.z) + bNotFound = TFALSE; + else + ++l2; + } + + // merge if previously found + if (!bNotFound) + piTriList_in_and_out[i] = piTriList_in_and_out[i2rec]; + } + } + else + { + int iL=iL_in, iR=iR_in; + assert((iR_in-iL_in)>0); // at least 2 entries + + // separate (by fSep) all points between iL_in and iR_in in pTmpVert[] + while (iL < iR) + { + tbool bReadyLeftSwap = TFALSE, bReadyRightSwap = TFALSE; + while ((!bReadyLeftSwap) && iL<iR) + { + assert(iL>=iL_in && iL<=iR_in); + bReadyLeftSwap = !(pTmpVert[iL].vert[channel]<fSep); + if (!bReadyLeftSwap) ++iL; + } + while ((!bReadyRightSwap) && iL<iR) + { + assert(iR>=iL_in && iR<=iR_in); + bReadyRightSwap = pTmpVert[iR].vert[channel]<fSep; + if (!bReadyRightSwap) --iR; + } + assert( (iL<iR) || !(bReadyLeftSwap && bReadyRightSwap) ); + + if (bReadyLeftSwap && bReadyRightSwap) + { + const STmpVert sTmp = pTmpVert[iL]; + assert(iL<iR); + pTmpVert[iL] = pTmpVert[iR]; + pTmpVert[iR] = sTmp; + ++iL; --iR; + } + } + + assert(iL==(iR+1) || (iL==iR)); + if (iL==iR) + { + const tbool bReadyRightSwap = pTmpVert[iR].vert[channel]<fSep; + if (bReadyRightSwap) ++iL; + else --iR; + } + + // only need to weld when there is more than 1 instance of the (x,y,z) + if (iL_in < iR) + MergeVertsFast(piTriList_in_and_out, pTmpVert, pContext, iL_in, iR); // weld all left of fSep + if (iL < iR_in) + MergeVertsFast(piTriList_in_and_out, pTmpVert, pContext, iL, iR_in); // weld all right of (or equal to) fSep + } +} + +static void MergeVertsSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int pTable[], const int iEntries) +{ + // this can be optimized further using a tree structure or more hashing. + int e=0; + for (e=0; e<iEntries; e++) + { + int i = pTable[e]; + const int index = piTriList_in_and_out[i]; + const SVec3 vP = GetPosition(pContext, index); + const SVec3 vN = GetNormal(pContext, index); + const SVec3 vT = GetTexCoord(pContext, index); + + tbool bNotFound = TTRUE; + int e2=0, i2rec=-1; + while (e2<e && bNotFound) + { + const int i2 = pTable[e2]; + const int index2 = piTriList_in_and_out[i2]; + const SVec3 vP2 = GetPosition(pContext, index2); + const SVec3 vN2 = GetNormal(pContext, index2); + const SVec3 vT2 = GetTexCoord(pContext, index2); + i2rec = i2; + + if (veq(vP,vP2) && veq(vN,vN2) && veq(vT,vT2)) + bNotFound = TFALSE; + else + ++e2; + } + + // merge if previously found + if (!bNotFound) + piTriList_in_and_out[i] = piTriList_in_and_out[i2rec]; + } +} + +static void GenerateSharedVerticesIndexListSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn) +{ + int iNumUniqueVerts = 0, t=0, i=0; + for (t=0; t<iNrTrianglesIn; t++) + { + for (i=0; i<3; i++) + { + const int offs = t*3 + i; + const int index = piTriList_in_and_out[offs]; + + const SVec3 vP = GetPosition(pContext, index); + const SVec3 vN = GetNormal(pContext, index); + const SVec3 vT = GetTexCoord(pContext, index); + + tbool bFound = TFALSE; + int t2=0, index2rec=-1; + while (!bFound && t2<=t) + { + int j=0; + while (!bFound && j<3) + { + const int index2 = piTriList_in_and_out[t2*3 + j]; + const SVec3 vP2 = GetPosition(pContext, index2); + const SVec3 vN2 = GetNormal(pContext, index2); + const SVec3 vT2 = GetTexCoord(pContext, index2); + + if (veq(vP,vP2) && veq(vN,vN2) && veq(vT,vT2)) + bFound = TTRUE; + else + ++j; + } + if (!bFound) ++t2; + } + + assert(bFound); + // if we found our own + if (index2rec == index) { ++iNumUniqueVerts; } + + piTriList_in_and_out[offs] = index2rec; + } + } +} + +static int GenerateInitialVerticesIndexList(STriInfo pTriInfos[], int piTriList_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn) +{ + int iTSpacesOffs = 0, f=0, t=0; + int iDstTriIndex = 0; + for (f=0; f<pContext->m_pInterface->m_getNumFaces(pContext); f++) + { + const int verts = pContext->m_pInterface->m_getNumVerticesOfFace(pContext, f); + if (verts!=3 && verts!=4) continue; + + pTriInfos[iDstTriIndex].iOrgFaceNumber = f; + pTriInfos[iDstTriIndex].iTSpacesOffs = iTSpacesOffs; + + if (verts==3) + { + unsigned char * pVerts = pTriInfos[iDstTriIndex].vert_num; + pVerts[0]=0; pVerts[1]=1; pVerts[2]=2; + piTriList_out[iDstTriIndex*3+0] = MakeIndex(f, 0); + piTriList_out[iDstTriIndex*3+1] = MakeIndex(f, 1); + piTriList_out[iDstTriIndex*3+2] = MakeIndex(f, 2); + ++iDstTriIndex; // next + } + else + { + { + pTriInfos[iDstTriIndex+1].iOrgFaceNumber = f; + pTriInfos[iDstTriIndex+1].iTSpacesOffs = iTSpacesOffs; + } + + { + // need an order independent way to evaluate + // tspace on quads. This is done by splitting + // along the shortest diagonal. + const int i0 = MakeIndex(f, 0); + const int i1 = MakeIndex(f, 1); + const int i2 = MakeIndex(f, 2); + const int i3 = MakeIndex(f, 3); + const SVec3 T0 = GetTexCoord(pContext, i0); + const SVec3 T1 = GetTexCoord(pContext, i1); + const SVec3 T2 = GetTexCoord(pContext, i2); + const SVec3 T3 = GetTexCoord(pContext, i3); + const float distSQ_02 = LengthSquared(vsub(T2,T0)); + const float distSQ_13 = LengthSquared(vsub(T3,T1)); + tbool bQuadDiagIs_02; + if (distSQ_02<distSQ_13) + bQuadDiagIs_02 = TTRUE; + else if (distSQ_13<distSQ_02) + bQuadDiagIs_02 = TFALSE; + else + { + const SVec3 P0 = GetPosition(pContext, i0); + const SVec3 P1 = GetPosition(pContext, i1); + const SVec3 P2 = GetPosition(pContext, i2); + const SVec3 P3 = GetPosition(pContext, i3); + const float distSQ_02 = LengthSquared(vsub(P2,P0)); + const float distSQ_13 = LengthSquared(vsub(P3,P1)); + + bQuadDiagIs_02 = distSQ_13<distSQ_02 ? TFALSE : TTRUE; + } + + if (bQuadDiagIs_02) + { + { + unsigned char * pVerts_A = pTriInfos[iDstTriIndex].vert_num; + pVerts_A[0]=0; pVerts_A[1]=1; pVerts_A[2]=2; + } + piTriList_out[iDstTriIndex*3+0] = i0; + piTriList_out[iDstTriIndex*3+1] = i1; + piTriList_out[iDstTriIndex*3+2] = i2; + ++iDstTriIndex; // next + { + unsigned char * pVerts_B = pTriInfos[iDstTriIndex].vert_num; + pVerts_B[0]=0; pVerts_B[1]=2; pVerts_B[2]=3; + } + piTriList_out[iDstTriIndex*3+0] = i0; + piTriList_out[iDstTriIndex*3+1] = i2; + piTriList_out[iDstTriIndex*3+2] = i3; + ++iDstTriIndex; // next + } + else + { + { + unsigned char * pVerts_A = pTriInfos[iDstTriIndex].vert_num; + pVerts_A[0]=0; pVerts_A[1]=1; pVerts_A[2]=3; + } + piTriList_out[iDstTriIndex*3+0] = i0; + piTriList_out[iDstTriIndex*3+1] = i1; + piTriList_out[iDstTriIndex*3+2] = i3; + ++iDstTriIndex; // next + { + unsigned char * pVerts_B = pTriInfos[iDstTriIndex].vert_num; + pVerts_B[0]=1; pVerts_B[1]=2; pVerts_B[2]=3; + } + piTriList_out[iDstTriIndex*3+0] = i1; + piTriList_out[iDstTriIndex*3+1] = i2; + piTriList_out[iDstTriIndex*3+2] = i3; + ++iDstTriIndex; // next + } + } + } + + iTSpacesOffs += verts; + assert(iDstTriIndex<=iNrTrianglesIn); + } + + for (t=0; t<iNrTrianglesIn; t++) + pTriInfos[t].iFlag = 0; + + // return total amount of tspaces + return iTSpacesOffs; +} + +static SVec3 GetPosition(const SMikkTSpaceContext * pContext, const int index) +{ + int iF, iI; + SVec3 res; float pos[3]; + IndexToData(&iF, &iI, index); + pContext->m_pInterface->m_getPosition(pContext, pos, iF, iI); + res.x=pos[0]; res.y=pos[1]; res.z=pos[2]; + return res; +} + +static SVec3 GetNormal(const SMikkTSpaceContext * pContext, const int index) +{ + int iF, iI; + SVec3 res; float norm[3]; + IndexToData(&iF, &iI, index); + pContext->m_pInterface->m_getNormal(pContext, norm, iF, iI); + res.x=norm[0]; res.y=norm[1]; res.z=norm[2]; + return res; +} + +static SVec3 GetTexCoord(const SMikkTSpaceContext * pContext, const int index) +{ + int iF, iI; + SVec3 res; float texc[2]; + IndexToData(&iF, &iI, index); + pContext->m_pInterface->m_getTexCoord(pContext, texc, iF, iI); + res.x=texc[0]; res.y=texc[1]; res.z=1.0f; + return res; +} + +///////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////// + +typedef union { + struct + { + int i0, i1, f; + }; + int array[3]; +} SEdge; + +static void BuildNeighborsFast(STriInfo pTriInfos[], SEdge * pEdges, const int piTriListIn[], const int iNrTrianglesIn); +static void BuildNeighborsSlow(STriInfo pTriInfos[], const int piTriListIn[], const int iNrTrianglesIn); + +// returns the texture area times 2 +static float CalcTexArea(const SMikkTSpaceContext * pContext, const int indices[]) +{ + const SVec3 t1 = GetTexCoord(pContext, indices[0]); + const SVec3 t2 = GetTexCoord(pContext, indices[1]); + const SVec3 t3 = GetTexCoord(pContext, indices[2]); + + const float t21x = t2.x-t1.x; + const float t21y = t2.y-t1.y; + const float t31x = t3.x-t1.x; + const float t31y = t3.y-t1.y; + + const float fSignedAreaSTx2 = t21x*t31y - t21y*t31x; + + return fSignedAreaSTx2<0 ? (-fSignedAreaSTx2) : fSignedAreaSTx2; +} + +static void InitTriInfo(STriInfo pTriInfos[], const int piTriListIn[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn) +{ + int f=0, i=0, t=0; + // pTriInfos[f].iFlag is cleared in GenerateInitialVerticesIndexList() which is called before this function. + + // generate neighbor info list + for (f=0; f<iNrTrianglesIn; f++) + for (i=0; i<3; i++) + { + pTriInfos[f].FaceNeighbors[i] = -1; + pTriInfos[f].AssignedGroup[i] = NULL; + + pTriInfos[f].vOs.x=0.0f; pTriInfos[f].vOs.y=0.0f; pTriInfos[f].vOs.z=0.0f; + pTriInfos[f].vOt.x=0.0f; pTriInfos[f].vOt.y=0.0f; pTriInfos[f].vOt.z=0.0f; + pTriInfos[f].fMagS = 0; + pTriInfos[f].fMagT = 0; + + // assumed bad + pTriInfos[f].iFlag |= GROUP_WITH_ANY; + } + + // evaluate first order derivatives + for (f=0; f<iNrTrianglesIn; f++) + { + // initial values + const SVec3 v1 = GetPosition(pContext, piTriListIn[f*3+0]); + const SVec3 v2 = GetPosition(pContext, piTriListIn[f*3+1]); + const SVec3 v3 = GetPosition(pContext, piTriListIn[f*3+2]); + const SVec3 t1 = GetTexCoord(pContext, piTriListIn[f*3+0]); + const SVec3 t2 = GetTexCoord(pContext, piTriListIn[f*3+1]); + const SVec3 t3 = GetTexCoord(pContext, piTriListIn[f*3+2]); + + const float t21x = t2.x-t1.x; + const float t21y = t2.y-t1.y; + const float t31x = t3.x-t1.x; + const float t31y = t3.y-t1.y; + const SVec3 d1 = vsub(v2,v1); + const SVec3 d2 = vsub(v3,v1); + + const float fSignedAreaSTx2 = t21x*t31y - t21y*t31x; + //assert(fSignedAreaSTx2!=0); + SVec3 vOs = vsub(vscale(t31y,d1), vscale(t21y,d2)); // eq 18 + SVec3 vOt = vadd(vscale(-t31x,d1), vscale(t21x,d2)); // eq 19 + + pTriInfos[f].iFlag |= (fSignedAreaSTx2>0 ? ORIENT_PRESERVING : 0); + + if ( NotZero(fSignedAreaSTx2) ) + { + const float fAbsArea = fabsf(fSignedAreaSTx2); + const float fLenOs = Length(vOs); + const float fLenOt = Length(vOt); + const float fS = (pTriInfos[f].iFlag&ORIENT_PRESERVING)==0 ? (-1.0f) : 1.0f; + if ( NotZero(fLenOs) ) pTriInfos[f].vOs = vscale(fS/fLenOs, vOs); + if ( NotZero(fLenOt) ) pTriInfos[f].vOt = vscale(fS/fLenOt, vOt); + + // evaluate magnitudes prior to normalization of vOs and vOt + pTriInfos[f].fMagS = fLenOs / fAbsArea; + pTriInfos[f].fMagT = fLenOt / fAbsArea; + + // if this is a good triangle + if ( NotZero(pTriInfos[f].fMagS) && NotZero(pTriInfos[f].fMagT)) + pTriInfos[f].iFlag &= (~GROUP_WITH_ANY); + } + } + + // force otherwise healthy quads to a fixed orientation + while (t<(iNrTrianglesIn-1)) + { + const int iFO_a = pTriInfos[t].iOrgFaceNumber; + const int iFO_b = pTriInfos[t+1].iOrgFaceNumber; + if (iFO_a==iFO_b) // this is a quad + { + const tbool bIsDeg_a = (pTriInfos[t].iFlag&MARK_DEGENERATE)!=0 ? TTRUE : TFALSE; + const tbool bIsDeg_b = (pTriInfos[t+1].iFlag&MARK_DEGENERATE)!=0 ? TTRUE : TFALSE; + + // bad triangles should already have been removed by + // DegenPrologue(), but just in case check bIsDeg_a and bIsDeg_a are false + if ((bIsDeg_a||bIsDeg_b)==TFALSE) + { + const tbool bOrientA = (pTriInfos[t].iFlag&ORIENT_PRESERVING)!=0 ? TTRUE : TFALSE; + const tbool bOrientB = (pTriInfos[t+1].iFlag&ORIENT_PRESERVING)!=0 ? TTRUE : TFALSE; + // if this happens the quad has extremely bad mapping!! + if (bOrientA!=bOrientB) + { + //printf("found quad with bad mapping\n"); + tbool bChooseOrientFirstTri = TFALSE; + if ((pTriInfos[t+1].iFlag&GROUP_WITH_ANY)!=0) bChooseOrientFirstTri = TTRUE; + else if ( CalcTexArea(pContext, &piTriListIn[t*3+0]) >= CalcTexArea(pContext, &piTriListIn[(t+1)*3+0]) ) + bChooseOrientFirstTri = TTRUE; + + // force match + { + const int t0 = bChooseOrientFirstTri ? t : (t+1); + const int t1 = bChooseOrientFirstTri ? (t+1) : t; + pTriInfos[t1].iFlag &= (~ORIENT_PRESERVING); // clear first + pTriInfos[t1].iFlag |= (pTriInfos[t0].iFlag&ORIENT_PRESERVING); // copy bit + } + } + } + t += 2; + } + else + ++t; + } + + // match up edge pairs + { + SEdge * pEdges = (SEdge *) malloc(sizeof(SEdge)*iNrTrianglesIn*3); + if (pEdges==NULL) + BuildNeighborsSlow(pTriInfos, piTriListIn, iNrTrianglesIn); + else + { + BuildNeighborsFast(pTriInfos, pEdges, piTriListIn, iNrTrianglesIn); + + free(pEdges); + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////// + +static tbool AssignRecur(const int piTriListIn[], STriInfo psTriInfos[], const int iMyTriIndex, SGroup * pGroup); +static void AddTriToGroup(SGroup * pGroup, const int iTriIndex); + +static int Build4RuleGroups(STriInfo pTriInfos[], SGroup pGroups[], int piGroupTrianglesBuffer[], const int piTriListIn[], const int iNrTrianglesIn) +{ + const int iNrMaxGroups = iNrTrianglesIn*3; + int iNrActiveGroups = 0; + int iOffset = 0, f=0, i=0; + (void)iNrMaxGroups; /* quiet warnings in non debug mode */ + for (f=0; f<iNrTrianglesIn; f++) + { + for (i=0; i<3; i++) + { + // if not assigned to a group + if ((pTriInfos[f].iFlag&GROUP_WITH_ANY)==0 && pTriInfos[f].AssignedGroup[i]==NULL) + { + tbool bOrPre; + int neigh_indexL, neigh_indexR; + const int vert_index = piTriListIn[f*3+i]; + assert(iNrActiveGroups<iNrMaxGroups); + pTriInfos[f].AssignedGroup[i] = &pGroups[iNrActiveGroups]; + pTriInfos[f].AssignedGroup[i]->iVertexRepresentitive = vert_index; + pTriInfos[f].AssignedGroup[i]->bOrientPreservering = (pTriInfos[f].iFlag&ORIENT_PRESERVING)!=0; + pTriInfos[f].AssignedGroup[i]->iNrFaces = 0; + pTriInfos[f].AssignedGroup[i]->pFaceIndices = &piGroupTrianglesBuffer[iOffset]; + ++iNrActiveGroups; + + AddTriToGroup(pTriInfos[f].AssignedGroup[i], f); + bOrPre = (pTriInfos[f].iFlag&ORIENT_PRESERVING)!=0 ? TTRUE : TFALSE; + neigh_indexL = pTriInfos[f].FaceNeighbors[i]; + neigh_indexR = pTriInfos[f].FaceNeighbors[i>0?(i-1):2]; + if (neigh_indexL>=0) // neighbor + { + const tbool bAnswer = + AssignRecur(piTriListIn, pTriInfos, neigh_indexL, + pTriInfos[f].AssignedGroup[i] ); + + const tbool bOrPre2 = (pTriInfos[neigh_indexL].iFlag&ORIENT_PRESERVING)!=0 ? TTRUE : TFALSE; + const tbool bDiff = bOrPre!=bOrPre2 ? TTRUE : TFALSE; + assert(bAnswer || bDiff); + (void)bAnswer, (void)bDiff; /* quiet warnings in non debug mode */ + } + if (neigh_indexR>=0) // neighbor + { + const tbool bAnswer = + AssignRecur(piTriListIn, pTriInfos, neigh_indexR, + pTriInfos[f].AssignedGroup[i] ); + + const tbool bOrPre2 = (pTriInfos[neigh_indexR].iFlag&ORIENT_PRESERVING)!=0 ? TTRUE : TFALSE; + const tbool bDiff = bOrPre!=bOrPre2 ? TTRUE : TFALSE; + assert(bAnswer || bDiff); + (void)bAnswer, (void)bDiff; /* quiet warnings in non debug mode */ + } + + // update offset + iOffset += pTriInfos[f].AssignedGroup[i]->iNrFaces; + // since the groups are disjoint a triangle can never + // belong to more than 3 groups. Subsequently something + // is completely screwed if this assertion ever hits. + assert(iOffset <= iNrMaxGroups); + } + } + } + + return iNrActiveGroups; +} + +static void AddTriToGroup(SGroup * pGroup, const int iTriIndex) +{ + pGroup->pFaceIndices[pGroup->iNrFaces] = iTriIndex; + ++pGroup->iNrFaces; +} + +static tbool AssignRecur(const int piTriListIn[], STriInfo psTriInfos[], + const int iMyTriIndex, SGroup * pGroup) +{ + STriInfo * pMyTriInfo = &psTriInfos[iMyTriIndex]; + + // track down vertex + const int iVertRep = pGroup->iVertexRepresentitive; + const int * pVerts = &piTriListIn[3*iMyTriIndex+0]; + int i=-1; + if (pVerts[0]==iVertRep) i=0; + else if (pVerts[1]==iVertRep) i=1; + else if (pVerts[2]==iVertRep) i=2; + assert(i>=0 && i<3); + + // early out + if (pMyTriInfo->AssignedGroup[i] == pGroup) return TTRUE; + else if (pMyTriInfo->AssignedGroup[i]!=NULL) return TFALSE; + if ((pMyTriInfo->iFlag&GROUP_WITH_ANY)!=0) + { + // first to group with a group-with-anything triangle + // determines it's orientation. + // This is the only existing order dependency in the code!! + if ( pMyTriInfo->AssignedGroup[0] == NULL && + pMyTriInfo->AssignedGroup[1] == NULL && + pMyTriInfo->AssignedGroup[2] == NULL ) + { + pMyTriInfo->iFlag &= (~ORIENT_PRESERVING); + pMyTriInfo->iFlag |= (pGroup->bOrientPreservering ? ORIENT_PRESERVING : 0); + } + } + { + const tbool bOrient = (pMyTriInfo->iFlag&ORIENT_PRESERVING)!=0 ? TTRUE : TFALSE; + if (bOrient != pGroup->bOrientPreservering) return TFALSE; + } + + AddTriToGroup(pGroup, iMyTriIndex); + pMyTriInfo->AssignedGroup[i] = pGroup; + + { + const int neigh_indexL = pMyTriInfo->FaceNeighbors[i]; + const int neigh_indexR = pMyTriInfo->FaceNeighbors[i>0?(i-1):2]; + if (neigh_indexL>=0) + AssignRecur(piTriListIn, psTriInfos, neigh_indexL, pGroup); + if (neigh_indexR>=0) + AssignRecur(piTriListIn, psTriInfos, neigh_indexR, pGroup); + } + + + + return TTRUE; +} + +///////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////// + +static tbool CompareSubGroups(const SSubGroup * pg1, const SSubGroup * pg2); +static void QuickSort(int* pSortBuffer, int iLeft, int iRight, unsigned int uSeed); +static STSpace EvalTspace(int face_indices[], const int iFaces, const int piTriListIn[], const STriInfo pTriInfos[], const SMikkTSpaceContext * pContext, const int iVertexRepresentitive); + +static tbool GenerateTSpaces(STSpace psTspace[], const STriInfo pTriInfos[], const SGroup pGroups[], + const int iNrActiveGroups, const int piTriListIn[], const float fThresCos, + const SMikkTSpaceContext * pContext) +{ + STSpace * pSubGroupTspace = NULL; + SSubGroup * pUniSubGroups = NULL; + int * pTmpMembers = NULL; + int iMaxNrFaces=0, iUniqueTspaces=0, g=0, i=0; + for (g=0; g<iNrActiveGroups; g++) + if (iMaxNrFaces < pGroups[g].iNrFaces) + iMaxNrFaces = pGroups[g].iNrFaces; + + if (iMaxNrFaces == 0) return TTRUE; + + // make initial allocations + pSubGroupTspace = (STSpace *) malloc(sizeof(STSpace)*iMaxNrFaces); + pUniSubGroups = (SSubGroup *) malloc(sizeof(SSubGroup)*iMaxNrFaces); + pTmpMembers = (int *) malloc(sizeof(int)*iMaxNrFaces); + if (pSubGroupTspace==NULL || pUniSubGroups==NULL || pTmpMembers==NULL) + { + if (pSubGroupTspace!=NULL) free(pSubGroupTspace); + if (pUniSubGroups!=NULL) free(pUniSubGroups); + if (pTmpMembers!=NULL) free(pTmpMembers); + return TFALSE; + } + + + iUniqueTspaces = 0; + for (g=0; g<iNrActiveGroups; g++) + { + const SGroup * pGroup = &pGroups[g]; + int iUniqueSubGroups = 0, s=0; + + for (i=0; i<pGroup->iNrFaces; i++) // triangles + { + const int f = pGroup->pFaceIndices[i]; // triangle number + int index=-1, iVertIndex=-1, iOF_1=-1, iMembers=0, j=0, l=0; + SSubGroup tmp_group; + tbool bFound; + SVec3 n, vOs, vOt; + if (pTriInfos[f].AssignedGroup[0]==pGroup) index=0; + else if (pTriInfos[f].AssignedGroup[1]==pGroup) index=1; + else if (pTriInfos[f].AssignedGroup[2]==pGroup) index=2; + assert(index>=0 && index<3); + + iVertIndex = piTriListIn[f*3+index]; + assert(iVertIndex==pGroup->iVertexRepresentitive); + + // is normalized already + n = GetNormal(pContext, iVertIndex); + + // project + vOs = vsub(pTriInfos[f].vOs, vscale(vdot(n,pTriInfos[f].vOs), n)); + vOt = vsub(pTriInfos[f].vOt, vscale(vdot(n,pTriInfos[f].vOt), n)); + if ( VNotZero(vOs) ) vOs = Normalize(vOs); + if ( VNotZero(vOt) ) vOt = Normalize(vOt); + + // original face number + iOF_1 = pTriInfos[f].iOrgFaceNumber; + + iMembers = 0; + for (j=0; j<pGroup->iNrFaces; j++) + { + const int t = pGroup->pFaceIndices[j]; // triangle number + const int iOF_2 = pTriInfos[t].iOrgFaceNumber; + + // project + SVec3 vOs2 = vsub(pTriInfos[t].vOs, vscale(vdot(n,pTriInfos[t].vOs), n)); + SVec3 vOt2 = vsub(pTriInfos[t].vOt, vscale(vdot(n,pTriInfos[t].vOt), n)); + if ( VNotZero(vOs2) ) vOs2 = Normalize(vOs2); + if ( VNotZero(vOt2) ) vOt2 = Normalize(vOt2); + + { + const tbool bAny = ( (pTriInfos[f].iFlag | pTriInfos[t].iFlag) & GROUP_WITH_ANY )!=0 ? TTRUE : TFALSE; + // make sure triangles which belong to the same quad are joined. + const tbool bSameOrgFace = iOF_1==iOF_2 ? TTRUE : TFALSE; + + const float fCosS = vdot(vOs,vOs2); + const float fCosT = vdot(vOt,vOt2); + + assert(f!=t || bSameOrgFace); // sanity check + if (bAny || bSameOrgFace || (fCosS>fThresCos && fCosT>fThresCos)) + pTmpMembers[iMembers++] = t; + } + } + + // sort pTmpMembers + tmp_group.iNrFaces = iMembers; + tmp_group.pTriMembers = pTmpMembers; + if (iMembers>1) + { + unsigned int uSeed = INTERNAL_RND_SORT_SEED; // could replace with a random seed? + QuickSort(pTmpMembers, 0, iMembers-1, uSeed); + } + + // look for an existing match + bFound = TFALSE; + l=0; + while (l<iUniqueSubGroups && !bFound) + { + bFound = CompareSubGroups(&tmp_group, &pUniSubGroups[l]); + if (!bFound) ++l; + } + + // assign tangent space index + assert(bFound || l==iUniqueSubGroups); + //piTempTangIndices[f*3+index] = iUniqueTspaces+l; + + // if no match was found we allocate a new subgroup + if (!bFound) + { + // insert new subgroup + int * pIndices = (int *) malloc(sizeof(int)*iMembers); + if (pIndices==NULL) + { + // clean up and return false + int s=0; + for (s=0; s<iUniqueSubGroups; s++) + free(pUniSubGroups[s].pTriMembers); + free(pUniSubGroups); + free(pTmpMembers); + free(pSubGroupTspace); + return TFALSE; + } + pUniSubGroups[iUniqueSubGroups].iNrFaces = iMembers; + pUniSubGroups[iUniqueSubGroups].pTriMembers = pIndices; + memcpy(pIndices, tmp_group.pTriMembers, iMembers*sizeof(int)); + pSubGroupTspace[iUniqueSubGroups] = + EvalTspace(tmp_group.pTriMembers, iMembers, piTriListIn, pTriInfos, pContext, pGroup->iVertexRepresentitive); + ++iUniqueSubGroups; + } + + // output tspace + { + const int iOffs = pTriInfos[f].iTSpacesOffs; + const int iVert = pTriInfos[f].vert_num[index]; + STSpace * pTS_out = &psTspace[iOffs+iVert]; + assert(pTS_out->iCounter<2); + assert(((pTriInfos[f].iFlag&ORIENT_PRESERVING)!=0) == pGroup->bOrientPreservering); + if (pTS_out->iCounter==1) + { + *pTS_out = AvgTSpace(pTS_out, &pSubGroupTspace[l]); + pTS_out->iCounter = 2; // update counter + pTS_out->bOrient = pGroup->bOrientPreservering; + } + else + { + assert(pTS_out->iCounter==0); + *pTS_out = pSubGroupTspace[l]; + pTS_out->iCounter = 1; // update counter + pTS_out->bOrient = pGroup->bOrientPreservering; + } + } + } + + // clean up and offset iUniqueTspaces + for (s=0; s<iUniqueSubGroups; s++) + free(pUniSubGroups[s].pTriMembers); + iUniqueTspaces += iUniqueSubGroups; + } + + // clean up + free(pUniSubGroups); + free(pTmpMembers); + free(pSubGroupTspace); + + return TTRUE; +} + +static STSpace EvalTspace(int face_indices[], const int iFaces, const int piTriListIn[], const STriInfo pTriInfos[], + const SMikkTSpaceContext * pContext, const int iVertexRepresentitive) +{ + STSpace res; + float fAngleSum = 0; + int face=0; + res.vOs.x=0.0f; res.vOs.y=0.0f; res.vOs.z=0.0f; + res.vOt.x=0.0f; res.vOt.y=0.0f; res.vOt.z=0.0f; + res.fMagS = 0; res.fMagT = 0; + + for (face=0; face<iFaces; face++) + { + const int f = face_indices[face]; + + // only valid triangles get to add their contribution + if ( (pTriInfos[f].iFlag&GROUP_WITH_ANY)==0 ) + { + SVec3 n, vOs, vOt, p0, p1, p2, v1, v2; + float fCos, fAngle, fMagS, fMagT; + int i=-1, index=-1, i0=-1, i1=-1, i2=-1; + if (piTriListIn[3*f+0]==iVertexRepresentitive) i=0; + else if (piTriListIn[3*f+1]==iVertexRepresentitive) i=1; + else if (piTriListIn[3*f+2]==iVertexRepresentitive) i=2; + assert(i>=0 && i<3); + + // project + index = piTriListIn[3*f+i]; + n = GetNormal(pContext, index); + vOs = vsub(pTriInfos[f].vOs, vscale(vdot(n,pTriInfos[f].vOs), n)); + vOt = vsub(pTriInfos[f].vOt, vscale(vdot(n,pTriInfos[f].vOt), n)); + if ( VNotZero(vOs) ) vOs = Normalize(vOs); + if ( VNotZero(vOt) ) vOt = Normalize(vOt); + + i2 = piTriListIn[3*f + (i<2?(i+1):0)]; + i1 = piTriListIn[3*f + i]; + i0 = piTriListIn[3*f + (i>0?(i-1):2)]; + + p0 = GetPosition(pContext, i0); + p1 = GetPosition(pContext, i1); + p2 = GetPosition(pContext, i2); + v1 = vsub(p0,p1); + v2 = vsub(p2,p1); + + // project + v1 = vsub(v1, vscale(vdot(n,v1),n)); if ( VNotZero(v1) ) v1 = Normalize(v1); + v2 = vsub(v2, vscale(vdot(n,v2),n)); if ( VNotZero(v2) ) v2 = Normalize(v2); + + // weight contribution by the angle + // between the two edge vectors + fCos = vdot(v1,v2); fCos=fCos>1?1:(fCos<(-1) ? (-1) : fCos); + fAngle = (float) acos(fCos); + fMagS = pTriInfos[f].fMagS; + fMagT = pTriInfos[f].fMagT; + + res.vOs=vadd(res.vOs, vscale(fAngle,vOs)); + res.vOt=vadd(res.vOt,vscale(fAngle,vOt)); + res.fMagS+=(fAngle*fMagS); + res.fMagT+=(fAngle*fMagT); + fAngleSum += fAngle; + } + } + + // normalize + if ( VNotZero(res.vOs) ) res.vOs = Normalize(res.vOs); + if ( VNotZero(res.vOt) ) res.vOt = Normalize(res.vOt); + if (fAngleSum>0) + { + res.fMagS /= fAngleSum; + res.fMagT /= fAngleSum; + } + + return res; +} + +static tbool CompareSubGroups(const SSubGroup * pg1, const SSubGroup * pg2) +{ + tbool bStillSame=TTRUE; + int i=0; + if (pg1->iNrFaces!=pg2->iNrFaces) return TFALSE; + while (i<pg1->iNrFaces && bStillSame) + { + bStillSame = pg1->pTriMembers[i]==pg2->pTriMembers[i] ? TTRUE : TFALSE; + if (bStillSame) ++i; + } + return bStillSame; +} + +static void QuickSort(int* pSortBuffer, int iLeft, int iRight, unsigned int uSeed) +{ + int iL, iR, n, index, iMid, iTmp; + + // Random + unsigned int t=uSeed&31; + t=(uSeed<<t)|(uSeed>>(32-t)); + uSeed=uSeed+t+3; + // Random end + + iL=iLeft; iR=iRight; + n = (iR-iL)+1; + assert(n>=0); + index = (int) (uSeed%n); + + iMid=pSortBuffer[index + iL]; + + + do + { + while (pSortBuffer[iL] < iMid) + ++iL; + while (pSortBuffer[iR] > iMid) + --iR; + + if (iL <= iR) + { + iTmp = pSortBuffer[iL]; + pSortBuffer[iL] = pSortBuffer[iR]; + pSortBuffer[iR] = iTmp; + ++iL; --iR; + } + } + while (iL <= iR); + + if (iLeft < iR) + QuickSort(pSortBuffer, iLeft, iR, uSeed); + if (iL < iRight) + QuickSort(pSortBuffer, iL, iRight, uSeed); +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// + +static void QuickSortEdges(SEdge * pSortBuffer, int iLeft, int iRight, const int channel, unsigned int uSeed); +static void GetEdge(int * i0_out, int * i1_out, int * edgenum_out, const int indices[], const int i0_in, const int i1_in); + +static void BuildNeighborsFast(STriInfo pTriInfos[], SEdge * pEdges, const int piTriListIn[], const int iNrTrianglesIn) +{ + // build array of edges + unsigned int uSeed = INTERNAL_RND_SORT_SEED; // could replace with a random seed? + int iEntries=0, iCurStartIndex=-1, f=0, i=0; + for (f=0; f<iNrTrianglesIn; f++) + for (i=0; i<3; i++) + { + const int i0 = piTriListIn[f*3+i]; + const int i1 = piTriListIn[f*3+(i<2?(i+1):0)]; + pEdges[f*3+i].i0 = i0 < i1 ? i0 : i1; // put minimum index in i0 + pEdges[f*3+i].i1 = !(i0 < i1) ? i0 : i1; // put maximum index in i1 + pEdges[f*3+i].f = f; // record face number + } + + // sort over all edges by i0, this is the pricy one. + QuickSortEdges(pEdges, 0, iNrTrianglesIn*3-1, 0, uSeed); // sort channel 0 which is i0 + + // sub sort over i1, should be fast. + // could replace this with a 64 bit int sort over (i0,i1) + // with i0 as msb in the quicksort call above. + iEntries = iNrTrianglesIn*3; + iCurStartIndex = 0; + for (i=1; i<iEntries; i++) + { + if (pEdges[iCurStartIndex].i0 != pEdges[i].i0) + { + const int iL = iCurStartIndex; + const int iR = i-1; + //const int iElems = i-iL; + iCurStartIndex = i; + QuickSortEdges(pEdges, iL, iR, 1, uSeed); // sort channel 1 which is i1 + } + } + + // sub sort over f, which should be fast. + // this step is to remain compliant with BuildNeighborsSlow() when + // more than 2 triangles use the same edge (such as a butterfly topology). + iCurStartIndex = 0; + for (i=1; i<iEntries; i++) + { + if (pEdges[iCurStartIndex].i0 != pEdges[i].i0 || pEdges[iCurStartIndex].i1 != pEdges[i].i1) + { + const int iL = iCurStartIndex; + const int iR = i-1; + //const int iElems = i-iL; + iCurStartIndex = i; + QuickSortEdges(pEdges, iL, iR, 2, uSeed); // sort channel 2 which is f + } + } + + // pair up, adjacent triangles + for (i=0; i<iEntries; i++) + { + const int i0=pEdges[i].i0; + const int i1=pEdges[i].i1; + const int f = pEdges[i].f; + tbool bUnassigned_A; + + int i0_A, i1_A; + int edgenum_A, edgenum_B=0; // 0,1 or 2 + GetEdge(&i0_A, &i1_A, &edgenum_A, &piTriListIn[f*3], i0, i1); // resolve index ordering and edge_num + bUnassigned_A = pTriInfos[f].FaceNeighbors[edgenum_A] == -1 ? TTRUE : TFALSE; + + if (bUnassigned_A) + { + // get true index ordering + int j=i+1, t; + tbool bNotFound = TTRUE; + while (j<iEntries && i0==pEdges[j].i0 && i1==pEdges[j].i1 && bNotFound) + { + tbool bUnassigned_B; + int i0_B, i1_B; + t = pEdges[j].f; + // flip i0_B and i1_B + GetEdge(&i1_B, &i0_B, &edgenum_B, &piTriListIn[t*3], pEdges[j].i0, pEdges[j].i1); // resolve index ordering and edge_num + //assert(!(i0_A==i1_B && i1_A==i0_B)); + bUnassigned_B = pTriInfos[t].FaceNeighbors[edgenum_B]==-1 ? TTRUE : TFALSE; + if (i0_A==i0_B && i1_A==i1_B && bUnassigned_B) + bNotFound = TFALSE; + else + ++j; + } + + if (!bNotFound) + { + int t = pEdges[j].f; + pTriInfos[f].FaceNeighbors[edgenum_A] = t; + //assert(pTriInfos[t].FaceNeighbors[edgenum_B]==-1); + pTriInfos[t].FaceNeighbors[edgenum_B] = f; + } + } + } +} + +static void BuildNeighborsSlow(STriInfo pTriInfos[], const int piTriListIn[], const int iNrTrianglesIn) +{ + int f=0, i=0; + for (f=0; f<iNrTrianglesIn; f++) + { + for (i=0; i<3; i++) + { + // if unassigned + if (pTriInfos[f].FaceNeighbors[i] == -1) + { + const int i0_A = piTriListIn[f*3+i]; + const int i1_A = piTriListIn[f*3+(i<2?(i+1):0)]; + + // search for a neighbor + tbool bFound = TFALSE; + int t=0, j=0; + while (!bFound && t<iNrTrianglesIn) + { + if (t!=f) + { + j=0; + while (!bFound && j<3) + { + // in rev order + const int i1_B = piTriListIn[t*3+j]; + const int i0_B = piTriListIn[t*3+(j<2?(j+1):0)]; + //assert(!(i0_A==i1_B && i1_A==i0_B)); + if (i0_A==i0_B && i1_A==i1_B) + bFound = TTRUE; + else + ++j; + } + } + + if (!bFound) ++t; + } + + // assign neighbors + if (bFound) + { + pTriInfos[f].FaceNeighbors[i] = t; + //assert(pTriInfos[t].FaceNeighbors[j]==-1); + pTriInfos[t].FaceNeighbors[j] = f; + } + } + } + } +} + +static void QuickSortEdges(SEdge * pSortBuffer, int iLeft, int iRight, const int channel, unsigned int uSeed) +{ + unsigned int t; + int iL, iR, n, index, iMid; + + // early out + SEdge sTmp; + const int iElems = iRight-iLeft+1; + if (iElems<2) return; + else if (iElems==2) + { + if (pSortBuffer[iLeft].array[channel] > pSortBuffer[iRight].array[channel]) + { + sTmp = pSortBuffer[iLeft]; + pSortBuffer[iLeft] = pSortBuffer[iRight]; + pSortBuffer[iRight] = sTmp; + } + return; + } + + // Random + t=uSeed&31; + t=(uSeed<<t)|(uSeed>>(32-t)); + uSeed=uSeed+t+3; + // Random end + + iL=iLeft, iR=iRight; + n = (iR-iL)+1; + assert(n>=0); + index = (int) (uSeed%n); + + iMid=pSortBuffer[index + iL].array[channel]; + + do + { + while (pSortBuffer[iL].array[channel] < iMid) + ++iL; + while (pSortBuffer[iR].array[channel] > iMid) + --iR; + + if (iL <= iR) + { + sTmp = pSortBuffer[iL]; + pSortBuffer[iL] = pSortBuffer[iR]; + pSortBuffer[iR] = sTmp; + ++iL; --iR; + } + } + while (iL <= iR); + + if (iLeft < iR) + QuickSortEdges(pSortBuffer, iLeft, iR, channel, uSeed); + if (iL < iRight) + QuickSortEdges(pSortBuffer, iL, iRight, channel, uSeed); +} + +// resolve ordering and edge number +static void GetEdge(int * i0_out, int * i1_out, int * edgenum_out, const int indices[], const int i0_in, const int i1_in) +{ + *edgenum_out = -1; + + // test if first index is on the edge + if (indices[0]==i0_in || indices[0]==i1_in) + { + // test if second index is on the edge + if (indices[1]==i0_in || indices[1]==i1_in) + { + edgenum_out[0]=0; // first edge + i0_out[0]=indices[0]; + i1_out[0]=indices[1]; + } + else + { + edgenum_out[0]=2; // third edge + i0_out[0]=indices[2]; + i1_out[0]=indices[0]; + } + } + else + { + // only second and third index is on the edge + edgenum_out[0]=1; // second edge + i0_out[0]=indices[1]; + i1_out[0]=indices[2]; + } +} + + +///////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////// Degenerate triangles //////////////////////////////////// + +static void DegenPrologue(STriInfo pTriInfos[], int piTriList_out[], const int iNrTrianglesIn, const int iTotTris) +{ + int iNextGoodTriangleSearchIndex=-1; + tbool bStillFindingGoodOnes; + + // locate quads with only one good triangle + int t=0; + while (t<(iTotTris-1)) + { + const int iFO_a = pTriInfos[t].iOrgFaceNumber; + const int iFO_b = pTriInfos[t+1].iOrgFaceNumber; + if (iFO_a==iFO_b) // this is a quad + { + const tbool bIsDeg_a = (pTriInfos[t].iFlag&MARK_DEGENERATE)!=0 ? TTRUE : TFALSE; + const tbool bIsDeg_b = (pTriInfos[t+1].iFlag&MARK_DEGENERATE)!=0 ? TTRUE : TFALSE; + if ((bIsDeg_a^bIsDeg_b)!=0) + { + pTriInfos[t].iFlag |= QUAD_ONE_DEGEN_TRI; + pTriInfos[t+1].iFlag |= QUAD_ONE_DEGEN_TRI; + } + t += 2; + } + else + ++t; + } + + // reorder list so all degen triangles are moved to the back + // without reordering the good triangles + iNextGoodTriangleSearchIndex = 1; + t=0; + bStillFindingGoodOnes = TTRUE; + while (t<iNrTrianglesIn && bStillFindingGoodOnes) + { + const tbool bIsGood = (pTriInfos[t].iFlag&MARK_DEGENERATE)==0 ? TTRUE : TFALSE; + if (bIsGood) + { + if (iNextGoodTriangleSearchIndex < (t+2)) + iNextGoodTriangleSearchIndex = t+2; + } + else + { + int t0, t1; + // search for the first good triangle. + tbool bJustADegenerate = TTRUE; + while (bJustADegenerate && iNextGoodTriangleSearchIndex<iTotTris) + { + const tbool bIsGood = (pTriInfos[iNextGoodTriangleSearchIndex].iFlag&MARK_DEGENERATE)==0 ? TTRUE : TFALSE; + if (bIsGood) bJustADegenerate=TFALSE; + else ++iNextGoodTriangleSearchIndex; + } + + t0 = t; + t1 = iNextGoodTriangleSearchIndex; + ++iNextGoodTriangleSearchIndex; + assert(iNextGoodTriangleSearchIndex > (t+1)); + + // swap triangle t0 and t1 + if (!bJustADegenerate) + { + int i=0; + for (i=0; i<3; i++) + { + const int index = piTriList_out[t0*3+i]; + piTriList_out[t0*3+i] = piTriList_out[t1*3+i]; + piTriList_out[t1*3+i] = index; + } + { + const STriInfo tri_info = pTriInfos[t0]; + pTriInfos[t0] = pTriInfos[t1]; + pTriInfos[t1] = tri_info; + } + } + else + bStillFindingGoodOnes = TFALSE; // this is not supposed to happen + } + + if (bStillFindingGoodOnes) ++t; + } + + assert(bStillFindingGoodOnes); // code will still work. + assert(iNrTrianglesIn == t); +} + +static void DegenEpilogue(STSpace psTspace[], STriInfo pTriInfos[], int piTriListIn[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn, const int iTotTris) +{ + int t=0, i=0; + // deal with degenerate triangles + // punishment for degenerate triangles is O(N^2) + for (t=iNrTrianglesIn; t<iTotTris; t++) + { + // degenerate triangles on a quad with one good triangle are skipped + // here but processed in the next loop + const tbool bSkip = (pTriInfos[t].iFlag&QUAD_ONE_DEGEN_TRI)!=0 ? TTRUE : TFALSE; + + if (!bSkip) + { + for (i=0; i<3; i++) + { + const int index1 = piTriListIn[t*3+i]; + // search through the good triangles + tbool bNotFound = TTRUE; + int j=0; + while (bNotFound && j<(3*iNrTrianglesIn)) + { + const int index2 = piTriListIn[j]; + if (index1==index2) bNotFound=TFALSE; + else ++j; + } + + if (!bNotFound) + { + const int iTri = j/3; + const int iVert = j%3; + const int iSrcVert=pTriInfos[iTri].vert_num[iVert]; + const int iSrcOffs=pTriInfos[iTri].iTSpacesOffs; + const int iDstVert=pTriInfos[t].vert_num[i]; + const int iDstOffs=pTriInfos[t].iTSpacesOffs; + + // copy tspace + psTspace[iDstOffs+iDstVert] = psTspace[iSrcOffs+iSrcVert]; + } + } + } + } + + // deal with degenerate quads with one good triangle + for (t=0; t<iNrTrianglesIn; t++) + { + // this triangle belongs to a quad where the + // other triangle is degenerate + if ( (pTriInfos[t].iFlag&QUAD_ONE_DEGEN_TRI)!=0 ) + { + SVec3 vDstP; + int iOrgF=-1, i=0; + tbool bNotFound; + unsigned char * pV = pTriInfos[t].vert_num; + int iFlag = (1<<pV[0]) | (1<<pV[1]) | (1<<pV[2]); + int iMissingIndex = 0; + if ((iFlag&2)==0) iMissingIndex=1; + else if ((iFlag&4)==0) iMissingIndex=2; + else if ((iFlag&8)==0) iMissingIndex=3; + + iOrgF = pTriInfos[t].iOrgFaceNumber; + vDstP = GetPosition(pContext, MakeIndex(iOrgF, iMissingIndex)); + bNotFound = TTRUE; + i=0; + while (bNotFound && i<3) + { + const int iVert = pV[i]; + const SVec3 vSrcP = GetPosition(pContext, MakeIndex(iOrgF, iVert)); + if (veq(vSrcP, vDstP)==TTRUE) + { + const int iOffs = pTriInfos[t].iTSpacesOffs; + psTspace[iOffs+iMissingIndex] = psTspace[iOffs+iVert]; + bNotFound=TFALSE; + } + else + ++i; + } + assert(!bNotFound); + } + } +} diff --git a/scene/resources/mikktspace.h b/scene/resources/mikktspace.h new file mode 100644 index 0000000000..52c44a713c --- /dev/null +++ b/scene/resources/mikktspace.h @@ -0,0 +1,145 @@ +/** \file mikktspace/mikktspace.h + * \ingroup mikktspace + */ +/** + * Copyright (C) 2011 by Morten S. Mikkelsen + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +#ifndef __MIKKTSPACE_H__ +#define __MIKKTSPACE_H__ + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Author: Morten S. Mikkelsen + * Version: 1.0 + * + * The files mikktspace.h and mikktspace.c are designed to be + * stand-alone files and it is important that they are kept this way. + * Not having dependencies on structures/classes/libraries specific + * to the program, in which they are used, allows them to be copied + * and used as is into any tool, program or plugin. + * The code is designed to consistently generate the same + * tangent spaces, for a given mesh, in any tool in which it is used. + * This is done by performing an internal welding step and subsequently an order-independent evaluation + * of tangent space for meshes consisting of triangles and quads. + * This means faces can be received in any order and the same is true for + * the order of vertices of each face. The generated result will not be affected + * by such reordering. Additionally, whether degenerate (vertices or texture coordinates) + * primitives are present or not will not affect the generated results either. + * Once tangent space calculation is done the vertices of degenerate primitives will simply + * inherit tangent space from neighboring non degenerate primitives. + * The analysis behind this implementation can be found in my master's thesis + * which is available for download --> http://image.diku.dk/projects/media/morten.mikkelsen.08.pdf + * Note that though the tangent spaces at the vertices are generated in an order-independent way, + * by this implementation, the interpolated tangent space is still affected by which diagonal is + * chosen to split each quad. A sensible solution is to have your tools pipeline always + * split quads by the shortest diagonal. This choice is order-independent and works with mirroring. + * If these have the same length then compare the diagonals defined by the texture coordinates. + * XNormal which is a tool for baking normal maps allows you to write your own tangent space plugin + * and also quad triangulator plugin. + */ + + +typedef int tbool; +typedef struct SMikkTSpaceContext SMikkTSpaceContext; + +typedef struct { + // Returns the number of faces (triangles/quads) on the mesh to be processed. + int (*m_getNumFaces)(const SMikkTSpaceContext * pContext); + + // Returns the number of vertices on face number iFace + // iFace is a number in the range {0, 1, ..., getNumFaces()-1} + int (*m_getNumVerticesOfFace)(const SMikkTSpaceContext * pContext, const int iFace); + + // returns the position/normal/texcoord of the referenced face of vertex number iVert. + // iVert is in the range {0,1,2} for triangles and {0,1,2,3} for quads. + void (*m_getPosition)(const SMikkTSpaceContext * pContext, float fvPosOut[], const int iFace, const int iVert); + void (*m_getNormal)(const SMikkTSpaceContext * pContext, float fvNormOut[], const int iFace, const int iVert); + void (*m_getTexCoord)(const SMikkTSpaceContext * pContext, float fvTexcOut[], const int iFace, const int iVert); + + // either (or both) of the two setTSpace callbacks can be set. + // The call-back m_setTSpaceBasic() is sufficient for basic normal mapping. + + // This function is used to return the tangent and fSign to the application. + // fvTangent is a unit length vector. + // For normal maps it is sufficient to use the following simplified version of the bitangent which is generated at pixel/vertex level. + // bitangent = fSign * cross(vN, tangent); + // Note that the results are returned unindexed. It is possible to generate a new index list + // But averaging/overwriting tangent spaces by using an already existing index list WILL produce INCRORRECT results. + // DO NOT! use an already existing index list. + void (*m_setTSpaceBasic)(const SMikkTSpaceContext * pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert); + + // This function is used to return tangent space results to the application. + // fvTangent and fvBiTangent are unit length vectors and fMagS and fMagT are their + // true magnitudes which can be used for relief mapping effects. + // fvBiTangent is the "real" bitangent and thus may not be perpendicular to fvTangent. + // However, both are perpendicular to the vertex normal. + // For normal maps it is sufficient to use the following simplified version of the bitangent which is generated at pixel/vertex level. + // fSign = bIsOrientationPreserving ? 1.0f : (-1.0f); + // bitangent = fSign * cross(vN, tangent); + // Note that the results are returned unindexed. It is possible to generate a new index list + // But averaging/overwriting tangent spaces by using an already existing index list WILL produce INCRORRECT results. + // DO NOT! use an already existing index list. + void (*m_setTSpace)(const SMikkTSpaceContext * pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT, + const tbool bIsOrientationPreserving, const int iFace, const int iVert); +} SMikkTSpaceInterface; + +struct SMikkTSpaceContext +{ + SMikkTSpaceInterface * m_pInterface; // initialized with callback functions + void * m_pUserData; // pointer to client side mesh data etc. (passed as the first parameter with every interface call) +}; + +// these are both thread safe! +tbool genTangSpaceDefault(const SMikkTSpaceContext * pContext); // Default (recommended) fAngularThreshold is 180 degrees (which means threshold disabled) +tbool genTangSpace(const SMikkTSpaceContext * pContext, const float fAngularThreshold); + + +// To avoid visual errors (distortions/unwanted hard edges in lighting), when using sampled normal maps, the +// normal map sampler must use the exact inverse of the pixel shader transformation. +// The most efficient transformation we can possibly do in the pixel shader is +// achieved by using, directly, the "unnormalized" interpolated tangent, bitangent and vertex normal: vT, vB and vN. +// pixel shader (fast transform out) +// vNout = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN ); +// where vNt is the tangent space normal. The normal map sampler must likewise use the +// interpolated and "unnormalized" tangent, bitangent and vertex normal to be compliant with the pixel shader. +// sampler does (exact inverse of pixel shader): +// float3 row0 = cross(vB, vN); +// float3 row1 = cross(vN, vT); +// float3 row2 = cross(vT, vB); +// float fSign = dot(vT, row0)<0 ? -1 : 1; +// vNt = normalize( fSign * float3(dot(vNout,row0), dot(vNout,row1), dot(vNout,row2)) ); +// where vNout is the sampled normal in some chosen 3D space. +// +// Should you choose to reconstruct the bitangent in the pixel shader instead +// of the vertex shader, as explained earlier, then be sure to do this in the normal map sampler also. +// Finally, beware of quad triangulations. If the normal map sampler doesn't use the same triangulation of +// quads as your renderer then problems will occur since the interpolated tangent spaces will differ +// eventhough the vertex level tangent spaces match. This can be solved either by triangulating before +// sampling/exporting or by using the order-independent choice of diagonal for splitting quads suggested earlier. +// However, this must be used both by the sampler and your tools/rendering pipeline. + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index 3bd7314778..75a1b765ee 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -29,6 +29,9 @@ #include "packed_scene.h" #include "globals.h" #include "io/resource_loader.h" +#include "scene/3d/spatial.h" +#include "scene/gui/control.h" +#include "scene/2d/node_2d.h" bool PackedScene::can_instance() const { @@ -80,9 +83,28 @@ Node *PackedScene::instance(bool p_gen_edit_state) const { } else { //create anew Object * obj = ObjectTypeDB::instance(snames[ n.type ]); - ERR_FAIL_COND_V(!obj,NULL); + if (!obj || !obj->cast_to<Node>()) { + if (obj) { + memdelete(obj); + obj=NULL; + } + WARN_PRINT(String("Warning node of type "+snames[n.type].operator String()+" does not exist.").ascii().get_data()); + if (n.parent>=0 && n.parent<nc && ret_nodes[n.parent]) { + if (ret_nodes[n.parent]->cast_to<Spatial>()) { + obj = memnew( Spatial ); + } else if (ret_nodes[n.parent]->cast_to<Control>()) { + obj = memnew( Control ); + } else if (ret_nodes[n.parent]->cast_to<Node2D>()) { + obj = memnew( Node2D ); + } + + } + if (!obj) { + obj = memnew( Node ); + } + } + node = obj->cast_to<Node>(); - ERR_FAIL_COND_V(!node,NULL); } @@ -225,22 +247,34 @@ Error PackedScene::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map< p_node->get_property_list(&plist); for (List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) { - if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) + + if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) { continue; + } String name = E->get().name; Variant value = p_node->get( E->get().name ); - if (E->get().usage & PROPERTY_USAGE_STORE_IF_NONZERO && value.is_zero()) + if (E->get().usage & PROPERTY_USAGE_STORE_IF_NONZERO && value.is_zero()) { continue; + } if (nd.instance>=0) { //only save changed properties in instance - if (!instance_state.has(name)) + /* + // this was commented because it would not save properties created from within script + // done with _get_property_list, that are not in the original node. + // if some property is not saved, check again + + if (!instance_state.has(name)) { + print_line("skip not in instance"); continue; - if (instance_state[name]==value) + }*/ + + if (instance_state[name]==value) { continue; + } } diff --git a/scene/resources/scene_preloader.cpp b/scene/resources/scene_preloader.cpp index 59d8cae970..e37a2c4967 100644 --- a/scene/resources/scene_preloader.cpp +++ b/scene/resources/scene_preloader.cpp @@ -26,430 +26,429 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "scene_preloader.h"
-#include "scene/io/scene_loader.h"
-#include "globals.h"
-
-bool ScenePreloader::can_instance() const {
-
- return nodes.size()>0;
-}
-
-Node *ScenePreloader::instance() const {
-
- int nc = nodes.size();
- ERR_FAIL_COND_V(nc==0,NULL);
-
- const StringName*snames=NULL;
- int sname_count=names.size();
- if (sname_count)
- snames=&names[0];
-
- const Variant*props=NULL;
- int prop_count=variants.size();
- if (prop_count)
- props=&variants[0];
-
- Vector<Variant> properties;
-
- const NodeData *nd = &nodes[0];
-
- Node **ret_nodes=(Node**)alloca( sizeof(Node*)*nc );
-
- for(int i=0;i<nc;i++) {
-
- const NodeData &n=nd[i];
-
-
- if (!ObjectTypeDB::is_type_enabled(snames[n.type])) {
- ret_nodes[i]=NULL;
- continue;
- }
-
- Object * obj = ObjectTypeDB::instance(snames[ n.type ]);
- ERR_FAIL_COND_V(!obj,NULL);
- Node *node = obj->cast_to<Node>();
- ERR_FAIL_COND_V(!node,NULL);
-
- int nprop_count=n.properties.size();
- if (nprop_count) {
-
- const NodeData::Property* nprops=&n.properties[0];
-
- for(int j=0;j<nprop_count;j++) {
-
- bool valid;
- node->set(snames[ nprops[j].name ],props[ nprops[j].value ],&valid);
- }
-
-
- }
-
- node->set_name( snames[ n.name ] );
- ret_nodes[i]=node;
- if (i>0) {
- ERR_FAIL_INDEX_V(n.parent,i,NULL);
- ERR_FAIL_COND_V(!ret_nodes[n.parent],NULL);
- ret_nodes[n.parent]->add_child(node);
- }
- }
-
-
- //do connections
-
- int cc = connections.size();
- const ConnectionData *cdata = connections.ptr();
-
- for(int i=0;i<cc;i++) {
-
- const ConnectionData &c=cdata[i];
- ERR_FAIL_INDEX_V( c.from, nc, NULL );
- ERR_FAIL_INDEX_V( c.to, nc, NULL );
-
- Vector<Variant> binds;
- if (c.binds.size()) {
- binds.resize(c.binds.size());
- for(int j=0;j<c.binds.size();j++)
- binds[j]=props[ c.binds[j] ];
- }
-
- if (!ret_nodes[c.from] || !ret_nodes[c.to])
- continue;
- ret_nodes[c.from]->connect( snames[ c.signal], ret_nodes[ c.to ], snames[ c.method], binds,CONNECT_PERSIST );
- }
-
- return ret_nodes[0];
-
-}
-
-
-static int _nm_get_string(const String& p_string, Map<StringName,int> &name_map) {
-
- if (name_map.has(p_string))
- return name_map[p_string];
-
- int idx = name_map.size();
- name_map[p_string]=idx;
- return idx;
-}
-
-static int _vm_get_variant(const Variant& p_variant, HashMap<Variant,int,VariantHasher> &variant_map) {
-
- if (variant_map.has(p_variant))
- return variant_map[p_variant];
-
- int idx = variant_map.size();
- variant_map[p_variant]=idx;
- return idx;
-}
-
-void ScenePreloader::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<StringName,int> &name_map,HashMap<Variant,int,VariantHasher> &variant_map,Map<Node*,int> &node_map) {
-
- if (p_node!=p_owner && !p_node->get_owner())
- return;
-
- NodeData nd;
- nd.name=_nm_get_string(p_node->get_name(),name_map);
- nd.type=_nm_get_string(p_node->get_type(),name_map);
- nd.parent=p_parent_idx;
-
- List<PropertyInfo> plist;
- p_node->get_property_list(&plist);
- for (List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) {
-
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
- continue;
-
- NodeData::Property prop;
- prop.name=_nm_get_string(E->get().name,name_map);
- prop.value=_vm_get_variant( p_node->get( E->get().name ), variant_map);
- nd.properties.push_back(prop);
- }
-
- int idx = nodes.size();
- node_map[p_node]=idx;
- nodes.push_back(nd);
-
- for(int i=0;i<p_node->get_child_count();i++) {
-
- Node *c=p_node->get_child(i);
- _parse_node(p_owner,c,idx,name_map,variant_map,node_map);
- }
-
-
-
-}
-
-void ScenePreloader::_parse_connections(Node *p_node, Map<StringName,int> &name_map,HashMap<Variant,int,VariantHasher> &variant_map,Map<Node*,int> &node_map,bool p_instance) {
-
-
- List<MethodInfo> signals;
- p_node->get_signal_list(&signals);
-
- for(List<MethodInfo>::Element *E=signals.front();E;E=E->next()) {
-
- List<Node::Connection> conns;
- p_node->get_signal_connection_list(E->get().name,&conns);
- for(List<Node::Connection>::Element *F=conns.front();F;F=F->next()) {
-
- const Node::Connection &c = F->get();
- if (!(c.flags&CONNECT_PERSIST))
- continue;
- Node *n=c.target->cast_to<Node>();
- if (!n)
- continue;
-
- if (!node_map.has(n))
- continue;
-
- ConnectionData cd;
- cd.from=node_map[p_node];
- cd.to=node_map[n];
- cd.method=_nm_get_string(c.method,name_map);
- cd.signal=_nm_get_string(c.signal,name_map);
- for(int i=0;i<c.binds.size();i++) {
-
- cd.binds.push_back( _vm_get_variant(c.binds[i],variant_map));
- }
- connections.push_back(cd);
- }
- }
-
-}
-
-
-Error ScenePreloader::load_scene(const String& p_path) {
-
- return ERR_CANT_OPEN;
-#if 0
- if (path==p_path)
- return OK;
-
- String p=Globals::get_singleton()->localize_path(p_path);
- clear();
-
- Node *scene = SceneLoader::load(p);
-
- ERR_FAIL_COND_V(!scene,ERR_CANT_OPEN);
-
- path=p;
-
- Map<StringName,int> name_map;
- HashMap<Variant,int,VariantHasher> variant_map;
- Map<Node*,int> node_map;
-
- _parse_node(scene,scene,-1,name_map,variant_map,node_map);
-
-
- names.resize(name_map.size());
-
- for(Map<StringName,int>::Element *E=name_map.front();E;E=E->next()) {
-
- names[E->get()]=E->key();
- }
-
- variants.resize(variant_map.size());
- const Variant *K=NULL;
- while((K=variant_map.next(K))) {
-
- int idx = variant_map[*K];
- variants[idx]=*K;
- }
-
-
- memdelete(scene); // <- me falto esto :(
- return OK;
-#endif
-}
-
-String ScenePreloader::get_scene_path() const {
-
- return path;
-}
-
-void ScenePreloader::clear() {
-
- names.clear();
- variants.clear();
- nodes.clear();
- connections.clear();
-
-}
-
-void ScenePreloader::_set_bundled_scene(const Dictionary& d) {
-
-
- ERR_FAIL_COND( !d.has("names"));
- ERR_FAIL_COND( !d.has("variants"));
- ERR_FAIL_COND( !d.has("node_count"));
- ERR_FAIL_COND( !d.has("nodes"));
- ERR_FAIL_COND( !d.has("conn_count"));
- ERR_FAIL_COND( !d.has("conns"));
- ERR_FAIL_COND( !d.has("path"));
-
- DVector<String> snames = d["names"];
- if (snames.size()) {
-
- int namecount = snames.size();
- names.resize(namecount);
- DVector<String>::Read r =snames.read();
- for(int i=0;i<names.size();i++)
- names[i]=r[i];
- }
-
- Array svariants = d["variants"];
-
- if (svariants.size()) {
- int varcount=svariants.size();
- variants.resize(varcount);
- for(int i=0;i<varcount;i++) {
-
- variants[i]=svariants[i];
- }
-
- } else {
- variants.clear();
- }
-
- nodes.resize(d["node_count"]);
- int nc=nodes.size();
- if (nc) {
- DVector<int> snodes = d["nodes"];
- DVector<int>::Read r = snodes.read();
- int idx=0;
- for(int i=0;i<nc;i++) {
- NodeData &nd = nodes[i];
- nd.parent=r[idx++];
- nd.type=r[idx++];
- nd.name=r[idx++];
- nd.properties.resize(r[idx++]);
- for(int j=0;j<nd.properties.size();j++) {
-
- nd.properties[j].name=r[idx++];
- nd.properties[j].value=r[idx++];
- }
- }
-
- }
-
- connections.resize(d["conn_count"]);
- int cc=connections.size();
-
- if (cc) {
-
- DVector<int> sconns = d["conns"];
- DVector<int>::Read r = sconns.read();
- int idx=0;
- for(int i=0;i<nc;i++) {
- ConnectionData &cd = connections[nc];
- cd.from=r[idx++];
- cd.to=r[idx++];
- cd.signal=r[idx++];
- cd.method=r[idx++];
- cd.binds.resize(r[idx++]);
- for(int j=0;j<cd.binds.size();j++) {
-
- cd.binds[j]=r[idx++];
- }
- }
-
- }
-
-
-
- path=d["path"];
-
-}
-
-Dictionary ScenePreloader::_get_bundled_scene() const {
-
- DVector<String> rnames;
- rnames.resize(names.size());
-
- if (names.size()) {
-
- DVector<String>::Write r=rnames.write();
-
- for(int i=0;i<names.size();i++)
- r[i]=names[i];
- }
-
- Dictionary d;
- d["names"]=rnames;
- d["variants"]=variants;
-
- Vector<int> rnodes;
- d["node_count"]=nodes.size();
-
- for(int i=0;i<nodes.size();i++) {
-
- const NodeData &nd=nodes[i];
- rnodes.push_back(nd.parent);
- rnodes.push_back(nd.type);
- rnodes.push_back(nd.name);
- rnodes.push_back(nd.properties.size());
- for(int j=0;j<nd.properties.size();j++) {
-
- rnodes.push_back(nd.properties[j].name);
- rnodes.push_back(nd.properties[j].value);
- }
- }
-
- d["nodes"]=rnodes;
-
- Vector<int> rconns;
- d["conn_count"]=connections.size();
-
- for(int i=0;i<connections.size();i++) {
-
- const ConnectionData &cd=connections[i];
- rconns.push_back(cd.from);
- rconns.push_back(cd.to);
- rconns.push_back(cd.signal);
- rconns.push_back(cd.method);
- rconns.push_back(cd.binds.size());
- for(int j=0;j<cd.binds.size();i++)
- rconns.push_back(cd.binds[j]);
-
- }
-
- d["conns"]=rconns;
-
- d["path"]=path;
-
- return d;
-
-
-}
-
-void ScenePreloader::_bind_methods() {
-
- ObjectTypeDB::bind_method(_MD("load_scene","path"),&ScenePreloader::load_scene);
- ObjectTypeDB::bind_method(_MD("get_scene_path"),&ScenePreloader::get_scene_path);
- ObjectTypeDB::bind_method(_MD("instance:Node"),&ScenePreloader::instance);
- ObjectTypeDB::bind_method(_MD("can_instance"),&ScenePreloader::can_instance);
- ObjectTypeDB::bind_method(_MD("_set_bundled_scene"),&ScenePreloader::_set_bundled_scene);
- ObjectTypeDB::bind_method(_MD("_get_bundled_scene"),&ScenePreloader::_get_bundled_scene);
-
- ADD_PROPERTY( PropertyInfo(Variant::DICTIONARY,"_bundled",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_BUNDLE),_SCS("_set_bundled_scene"),_SCS("_get_bundled_scene"));
-#if 0
- List<String> extensions;
- SceneLoader::get_recognized_extensions(&extensions);
- String exthint;
- for (List<String>::Element*E=extensions.front();E;E=E->next()) {
-
- if (exthint!="")
- exthint+=",";
- exthint+="*."+E->get();
- }
-
- exthint+="; Scenes";
-
- ADD_PROPERTY( PropertyInfo(Variant::STRING,"scene",PROPERTY_HINT_FILE,exthint),_SCS("load_scene"),_SCS("get_scene_path"));
-#endif
-}
-
-ScenePreloader::ScenePreloader() {
-
-
-}
+#include "scene_preloader.h" +#include "globals.h" + +bool ScenePreloader::can_instance() const { + + return nodes.size()>0; +} + +Node *ScenePreloader::instance() const { + + int nc = nodes.size(); + ERR_FAIL_COND_V(nc==0,NULL); + + const StringName*snames=NULL; + int sname_count=names.size(); + if (sname_count) + snames=&names[0]; + + const Variant*props=NULL; + int prop_count=variants.size(); + if (prop_count) + props=&variants[0]; + + Vector<Variant> properties; + + const NodeData *nd = &nodes[0]; + + Node **ret_nodes=(Node**)alloca( sizeof(Node*)*nc ); + + for(int i=0;i<nc;i++) { + + const NodeData &n=nd[i]; + + + if (!ObjectTypeDB::is_type_enabled(snames[n.type])) { + ret_nodes[i]=NULL; + continue; + } + + Object * obj = ObjectTypeDB::instance(snames[ n.type ]); + ERR_FAIL_COND_V(!obj,NULL); + Node *node = obj->cast_to<Node>(); + ERR_FAIL_COND_V(!node,NULL); + + int nprop_count=n.properties.size(); + if (nprop_count) { + + const NodeData::Property* nprops=&n.properties[0]; + + for(int j=0;j<nprop_count;j++) { + + bool valid; + node->set(snames[ nprops[j].name ],props[ nprops[j].value ],&valid); + } + + + } + + node->set_name( snames[ n.name ] ); + ret_nodes[i]=node; + if (i>0) { + ERR_FAIL_INDEX_V(n.parent,i,NULL); + ERR_FAIL_COND_V(!ret_nodes[n.parent],NULL); + ret_nodes[n.parent]->add_child(node); + } + } + + + //do connections + + int cc = connections.size(); + const ConnectionData *cdata = connections.ptr(); + + for(int i=0;i<cc;i++) { + + const ConnectionData &c=cdata[i]; + ERR_FAIL_INDEX_V( c.from, nc, NULL ); + ERR_FAIL_INDEX_V( c.to, nc, NULL ); + + Vector<Variant> binds; + if (c.binds.size()) { + binds.resize(c.binds.size()); + for(int j=0;j<c.binds.size();j++) + binds[j]=props[ c.binds[j] ]; + } + + if (!ret_nodes[c.from] || !ret_nodes[c.to]) + continue; + ret_nodes[c.from]->connect( snames[ c.signal], ret_nodes[ c.to ], snames[ c.method], binds,CONNECT_PERSIST ); + } + + return ret_nodes[0]; + +} + + +static int _nm_get_string(const String& p_string, Map<StringName,int> &name_map) { + + if (name_map.has(p_string)) + return name_map[p_string]; + + int idx = name_map.size(); + name_map[p_string]=idx; + return idx; +} + +static int _vm_get_variant(const Variant& p_variant, HashMap<Variant,int,VariantHasher> &variant_map) { + + if (variant_map.has(p_variant)) + return variant_map[p_variant]; + + int idx = variant_map.size(); + variant_map[p_variant]=idx; + return idx; +} + +void ScenePreloader::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<StringName,int> &name_map,HashMap<Variant,int,VariantHasher> &variant_map,Map<Node*,int> &node_map) { + + if (p_node!=p_owner && !p_node->get_owner()) + return; + + NodeData nd; + nd.name=_nm_get_string(p_node->get_name(),name_map); + nd.type=_nm_get_string(p_node->get_type(),name_map); + nd.parent=p_parent_idx; + + List<PropertyInfo> plist; + p_node->get_property_list(&plist); + for (List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) { + + if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) + continue; + + NodeData::Property prop; + prop.name=_nm_get_string(E->get().name,name_map); + prop.value=_vm_get_variant( p_node->get( E->get().name ), variant_map); + nd.properties.push_back(prop); + } + + int idx = nodes.size(); + node_map[p_node]=idx; + nodes.push_back(nd); + + for(int i=0;i<p_node->get_child_count();i++) { + + Node *c=p_node->get_child(i); + _parse_node(p_owner,c,idx,name_map,variant_map,node_map); + } + + + +} + +void ScenePreloader::_parse_connections(Node *p_node, Map<StringName,int> &name_map,HashMap<Variant,int,VariantHasher> &variant_map,Map<Node*,int> &node_map,bool p_instance) { + + + List<MethodInfo> signals; + p_node->get_signal_list(&signals); + + for(List<MethodInfo>::Element *E=signals.front();E;E=E->next()) { + + List<Node::Connection> conns; + p_node->get_signal_connection_list(E->get().name,&conns); + for(List<Node::Connection>::Element *F=conns.front();F;F=F->next()) { + + const Node::Connection &c = F->get(); + if (!(c.flags&CONNECT_PERSIST)) + continue; + Node *n=c.target->cast_to<Node>(); + if (!n) + continue; + + if (!node_map.has(n)) + continue; + + ConnectionData cd; + cd.from=node_map[p_node]; + cd.to=node_map[n]; + cd.method=_nm_get_string(c.method,name_map); + cd.signal=_nm_get_string(c.signal,name_map); + for(int i=0;i<c.binds.size();i++) { + + cd.binds.push_back( _vm_get_variant(c.binds[i],variant_map)); + } + connections.push_back(cd); + } + } + +} + + +Error ScenePreloader::load_scene(const String& p_path) { + + return ERR_CANT_OPEN; +#if 0 + if (path==p_path) + return OK; + + String p=Globals::get_singleton()->localize_path(p_path); + clear(); + + Node *scene = SceneLoader::load(p); + + ERR_FAIL_COND_V(!scene,ERR_CANT_OPEN); + + path=p; + + Map<StringName,int> name_map; + HashMap<Variant,int,VariantHasher> variant_map; + Map<Node*,int> node_map; + + _parse_node(scene,scene,-1,name_map,variant_map,node_map); + + + names.resize(name_map.size()); + + for(Map<StringName,int>::Element *E=name_map.front();E;E=E->next()) { + + names[E->get()]=E->key(); + } + + variants.resize(variant_map.size()); + const Variant *K=NULL; + while((K=variant_map.next(K))) { + + int idx = variant_map[*K]; + variants[idx]=*K; + } + + + memdelete(scene); // <- me falto esto :( + return OK; +#endif +} + +String ScenePreloader::get_scene_path() const { + + return path; +} + +void ScenePreloader::clear() { + + names.clear(); + variants.clear(); + nodes.clear(); + connections.clear(); + +} + +void ScenePreloader::_set_bundled_scene(const Dictionary& d) { + + + ERR_FAIL_COND( !d.has("names")); + ERR_FAIL_COND( !d.has("variants")); + ERR_FAIL_COND( !d.has("node_count")); + ERR_FAIL_COND( !d.has("nodes")); + ERR_FAIL_COND( !d.has("conn_count")); + ERR_FAIL_COND( !d.has("conns")); + ERR_FAIL_COND( !d.has("path")); + + DVector<String> snames = d["names"]; + if (snames.size()) { + + int namecount = snames.size(); + names.resize(namecount); + DVector<String>::Read r =snames.read(); + for(int i=0;i<names.size();i++) + names[i]=r[i]; + } + + Array svariants = d["variants"]; + + if (svariants.size()) { + int varcount=svariants.size(); + variants.resize(varcount); + for(int i=0;i<varcount;i++) { + + variants[i]=svariants[i]; + } + + } else { + variants.clear(); + } + + nodes.resize(d["node_count"]); + int nc=nodes.size(); + if (nc) { + DVector<int> snodes = d["nodes"]; + DVector<int>::Read r = snodes.read(); + int idx=0; + for(int i=0;i<nc;i++) { + NodeData &nd = nodes[i]; + nd.parent=r[idx++]; + nd.type=r[idx++]; + nd.name=r[idx++]; + nd.properties.resize(r[idx++]); + for(int j=0;j<nd.properties.size();j++) { + + nd.properties[j].name=r[idx++]; + nd.properties[j].value=r[idx++]; + } + } + + } + + connections.resize(d["conn_count"]); + int cc=connections.size(); + + if (cc) { + + DVector<int> sconns = d["conns"]; + DVector<int>::Read r = sconns.read(); + int idx=0; + for(int i=0;i<nc;i++) { + ConnectionData &cd = connections[nc]; + cd.from=r[idx++]; + cd.to=r[idx++]; + cd.signal=r[idx++]; + cd.method=r[idx++]; + cd.binds.resize(r[idx++]); + for(int j=0;j<cd.binds.size();j++) { + + cd.binds[j]=r[idx++]; + } + } + + } + + + + path=d["path"]; + +} + +Dictionary ScenePreloader::_get_bundled_scene() const { + + DVector<String> rnames; + rnames.resize(names.size()); + + if (names.size()) { + + DVector<String>::Write r=rnames.write(); + + for(int i=0;i<names.size();i++) + r[i]=names[i]; + } + + Dictionary d; + d["names"]=rnames; + d["variants"]=variants; + + Vector<int> rnodes; + d["node_count"]=nodes.size(); + + for(int i=0;i<nodes.size();i++) { + + const NodeData &nd=nodes[i]; + rnodes.push_back(nd.parent); + rnodes.push_back(nd.type); + rnodes.push_back(nd.name); + rnodes.push_back(nd.properties.size()); + for(int j=0;j<nd.properties.size();j++) { + + rnodes.push_back(nd.properties[j].name); + rnodes.push_back(nd.properties[j].value); + } + } + + d["nodes"]=rnodes; + + Vector<int> rconns; + d["conn_count"]=connections.size(); + + for(int i=0;i<connections.size();i++) { + + const ConnectionData &cd=connections[i]; + rconns.push_back(cd.from); + rconns.push_back(cd.to); + rconns.push_back(cd.signal); + rconns.push_back(cd.method); + rconns.push_back(cd.binds.size()); + for(int j=0;j<cd.binds.size();i++) + rconns.push_back(cd.binds[j]); + + } + + d["conns"]=rconns; + + d["path"]=path; + + return d; + + +} + +void ScenePreloader::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("load_scene","path"),&ScenePreloader::load_scene); + ObjectTypeDB::bind_method(_MD("get_scene_path"),&ScenePreloader::get_scene_path); + ObjectTypeDB::bind_method(_MD("instance:Node"),&ScenePreloader::instance); + ObjectTypeDB::bind_method(_MD("can_instance"),&ScenePreloader::can_instance); + ObjectTypeDB::bind_method(_MD("_set_bundled_scene"),&ScenePreloader::_set_bundled_scene); + ObjectTypeDB::bind_method(_MD("_get_bundled_scene"),&ScenePreloader::_get_bundled_scene); + + ADD_PROPERTY( PropertyInfo(Variant::DICTIONARY,"_bundled",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_BUNDLE),_SCS("_set_bundled_scene"),_SCS("_get_bundled_scene")); +#if 0 + List<String> extensions; + SceneLoader::get_recognized_extensions(&extensions); + String exthint; + for (List<String>::Element*E=extensions.front();E;E=E->next()) { + + if (exthint!="") + exthint+=","; + exthint+="*."+E->get(); + } + + exthint+="; Scenes"; + + ADD_PROPERTY( PropertyInfo(Variant::STRING,"scene",PROPERTY_HINT_FILE,exthint),_SCS("load_scene"),_SCS("get_scene_path")); +#endif +} + +ScenePreloader::ScenePreloader() { + + +} diff --git a/scene/resources/shader_graph.cpp b/scene/resources/shader_graph.cpp index df5fee81a8..3ed6cebf07 100644 --- a/scene/resources/shader_graph.cpp +++ b/scene/resources/shader_graph.cpp @@ -148,8 +148,8 @@ void ShaderGraph::_bind_methods() { ObjectTypeDB::bind_method(_MD("node_set_pos"),&ShaderGraph::node_set_pos ); ObjectTypeDB::bind_method(_MD("node_get_pos"),&ShaderGraph::node_get_pos ); - ObjectTypeDB::bind_method(_MD("node_get_param"),&ShaderGraph::node_get_type); - ObjectTypeDB::bind_method(_MD("node_get_type"),&ShaderGraph::node_get_param); + ObjectTypeDB::bind_method(_MD("node_get_param"),&ShaderGraph::node_get_param); + ObjectTypeDB::bind_method(_MD("node_get_type"),&ShaderGraph::node_get_type); ObjectTypeDB::bind_method(_MD("connect"),&ShaderGraph::connect ); ObjectTypeDB::bind_method(_MD("disconnect"),&ShaderGraph::disconnect ); diff --git a/scene/resources/shape_2d.cpp b/scene/resources/shape_2d.cpp index ca891920da..738b642d43 100644 --- a/scene/resources/shape_2d.cpp +++ b/scene/resources/shape_2d.cpp @@ -109,7 +109,7 @@ void Shape2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("collide","local_xform","with_shape:Shape2D","shape_xform"),&Shape2D::collide); ObjectTypeDB::bind_method(_MD("collide_with_motion","local_xform","local_motion","with_shape:Shape2D","shape_xform","shape_motion"),&Shape2D::collide_with_motion); ObjectTypeDB::bind_method(_MD("collide_and_get_contacts:var","local_xform","with_shape:Shape2D","shape_xform"),&Shape2D::collide_and_get_contacts); - ObjectTypeDB::bind_method(_MD("collide_with_motion_and_get_contacts:var","local_xform","local_motion","with_shape:Shape2D","shape_xform","shape_motion"),&Shape2D::collide_and_get_contacts); + ObjectTypeDB::bind_method(_MD("collide_with_motion_and_get_contacts:var","local_xform","local_motion","with_shape:Shape2D","shape_xform","shape_motion"),&Shape2D::collide_with_motion_and_get_contacts); ADD_PROPERTY( PropertyInfo(Variant::REAL,"custom_solver_bias",PROPERTY_HINT_RANGE,"0,1,0.001"),_SCS("set_custom_solver_bias"),_SCS("get_custom_solver_bias")); } diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index 2856101674..dd39205932 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -105,7 +105,7 @@ void SurfaceTool::add_vertex( const Vector3& p_vertex) { vtx.weights=last_weights; vtx.bones=last_bones; vtx.tangent=last_tangent.normal; - vtx.binormal=last_tangent.normal.cross(last_normal).normalized() * last_tangent.d; + vtx.binormal=last_normal.cross(last_tangent.normal).normalized() * last_tangent.d; vertex_array.push_back(vtx); first=false; format|=Mesh::ARRAY_FORMAT_VERTEX; @@ -299,7 +299,9 @@ Ref<Mesh> SurfaceTool::commit(const Ref<Mesh>& p_existing) { w[idx+0]=v.tangent.x; w[idx+1]=v.tangent.y; w[idx+2]=v.tangent.z; - float d = v.binormal.dot(v.normal.cross(v.tangent)); + + //float d = v.tangent.dot(v.binormal,v.normal); + float d = v.binormal.dot( v.normal.cross(v.tangent)); w[idx+3]=d<0 ? -1 : 1; } @@ -565,6 +567,7 @@ void SurfaceTool::create_from(const Ref<Mesh>& p_existing, int p_surface) { clear(); primitive=p_existing->surface_get_primitive_type(p_surface); _create_list(p_existing,p_surface,&vertex_array,&index_array,format); + material=p_existing->surface_get_material(p_surface); } @@ -611,165 +614,96 @@ void SurfaceTool::append_from(const Ref<Mesh>& p_existing, int p_surface,const T } +//mikktspace callbacks +int SurfaceTool::mikktGetNumFaces(const SMikkTSpaceContext * pContext) { -void SurfaceTool::generate_tangents() { - - ERR_FAIL_COND(!(format&Mesh::ARRAY_FORMAT_TEX_UV)); - ERR_FAIL_COND(!(format&Mesh::ARRAY_FORMAT_NORMAL)); - - - if (index_array.size()) { - - Vector<List<Vertex>::Element*> vtx; - vtx.resize(vertex_array.size()); - int idx=0; - for (List<Vertex>::Element *E=vertex_array.front();E;E=E->next()) { - vtx[idx++]=E; - E->get().binormal=Vector3(); - E->get().tangent=Vector3(); - } - - for (List<int>::Element *E=index_array.front();E;) { - - int i[3]; - i[0]=E->get(); - E=E->next(); - ERR_FAIL_COND(!E); - i[1]=E->get(); - E=E->next(); - ERR_FAIL_COND(!E); - i[2]=E->get(); - E=E->next(); - ERR_FAIL_COND(!E); - - - Vector3 v1 = vtx[ i[0] ]->get().vertex; - Vector3 v2 = vtx[ i[1] ]->get().vertex; - Vector3 v3 = vtx[ i[2] ]->get().vertex; - - Vector2 w1 = vtx[ i[0] ]->get().uv; - Vector2 w2 = vtx[ i[1] ]->get().uv; - Vector2 w3 = vtx[ i[2] ]->get().uv; - - - float x1 = v2.x - v1.x; - float x2 = v3.x - v1.x; - float y1 = v2.y - v1.y; - float y2 = v3.y - v1.y; - float z1 = v2.z - v1.z; - float z2 = v3.z - v1.z; - - float s1 = w2.x - w1.x; - float s2 = w3.x - w1.x; - float t1 = w2.y - w1.y; - float t2 = w3.y - w1.y; - - float r = (s1 * t2 - s2 * t1); - - Vector3 binormal,tangent; - - if (r==0) { - binormal=Vector3(0,0,0); - tangent=Vector3(0,0,0); - } else { - tangent = Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, - (t2 * z1 - t1 * z2) * r); - binormal = Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, - (s1 * z2 - s2 * z1) * r); - } - - tangent.normalize(); - binormal.normalize(); - Vector3 normal=Plane( v1, v2, v3 ).normal; - - Vector3 tangentp = tangent - normal * normal.dot( tangent ); - Vector3 binormalp = binormal - normal * (normal.dot(binormal)) - tangent * (tangent.dot(binormal)); - - tangentp.normalize(); - binormalp.normalize(); + Vector<List<Vertex>::Element*> &varr = *((Vector<List<Vertex>::Element*>*)pContext->m_pUserData); + return varr.size()/3; +} +int SurfaceTool::mikktGetNumVerticesOfFace(const SMikkTSpaceContext * pContext, const int iFace){ + return 3; //always 3 +} +void SurfaceTool::mikktGetPosition(const SMikkTSpaceContext * pContext, float fvPosOut[], const int iFace, const int iVert){ - for (int j=0;j<3;j++) { - vtx[ i[j] ]->get().binormal+=binormalp; - vtx[ i[j] ]->get().tangent+=tangentp; + Vector<List<Vertex>::Element*> &varr = *((Vector<List<Vertex>::Element*>*)pContext->m_pUserData); + Vector3 v = varr[iFace*3+iVert]->get().vertex; + fvPosOut[0]=v.x; + fvPosOut[1]=v.y; + fvPosOut[2]=v.z; - } - } - for (List<Vertex>::Element *E=vertex_array.front();E;E=E->next()) { - E->get().binormal.normalize(); - E->get().tangent.normalize(); - } +} +void SurfaceTool::mikktGetNormal(const SMikkTSpaceContext * pContext, float fvNormOut[], const int iFace, const int iVert){ - } else { + Vector<List<Vertex>::Element*> &varr = *((Vector<List<Vertex>::Element*>*)pContext->m_pUserData); + Vector3 v = varr[iFace*3+iVert]->get().normal; + fvNormOut[0]=v.x; + fvNormOut[1]=v.y; + fvNormOut[2]=v.z; - for (List<Vertex>::Element *E=vertex_array.front();E;) { +} +void SurfaceTool::mikktGetTexCoord(const SMikkTSpaceContext * pContext, float fvTexcOut[], const int iFace, const int iVert){ - List< Vertex >::Element *v[3]; - v[0]=E; - v[1]=v[0]->next(); - ERR_FAIL_COND(!v[1]); - v[2]=v[1]->next(); - ERR_FAIL_COND(!v[2]); - E=v[2]->next(); + Vector<List<Vertex>::Element*> &varr = *((Vector<List<Vertex>::Element*>*)pContext->m_pUserData); + Vector2 v = varr[iFace*3+iVert]->get().uv; + fvTexcOut[0]=v.x; + //fvTexcOut[1]=v.y; + fvTexcOut[1]=1.0-v.y; - Vector3 v1 = v[0]->get().vertex; - Vector3 v2 = v[1]->get().vertex; - Vector3 v3 = v[2]->get().vertex; +} +void SurfaceTool::mikktSetTSpaceBasic(const SMikkTSpaceContext * pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert){ - Vector2 w1 = v[0]->get().uv; - Vector2 w2 = v[1]->get().uv; - Vector2 w3 = v[2]->get().uv; + Vector<List<Vertex>::Element*> &varr = *((Vector<List<Vertex>::Element*>*)pContext->m_pUserData); + Vertex &vtx = varr[iFace*3+iVert]->get(); + vtx.tangent = Vector3(fvTangent[0],fvTangent[1],fvTangent[2]); + vtx.binormal = vtx.normal.cross(vtx.tangent) * fSign; +} - float x1 = v2.x - v1.x; - float x2 = v3.x - v1.x; - float y1 = v2.y - v1.y; - float y2 = v3.y - v1.y; - float z1 = v2.z - v1.z; - float z2 = v3.z - v1.z; - float s1 = w2.x - w1.x; - float s2 = w3.x - w1.x; - float t1 = w2.y - w1.y; - float t2 = w3.y - w1.y; +void SurfaceTool::generate_tangents() { - float r = (s1 * t2 - s2 * t1); + ERR_FAIL_COND(!(format&Mesh::ARRAY_FORMAT_TEX_UV)); + ERR_FAIL_COND(!(format&Mesh::ARRAY_FORMAT_NORMAL)); - Vector3 binormal,tangent; + bool indexed = index_array.size()>0; + if (indexed) + deindex(); - if (r==0) { - binormal=Vector3(0,0,0); - tangent=Vector3(0,0,0); - } else { - tangent = Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, - (t2 * z1 - t1 * z2) * r); - binormal = Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, - (s1 * z2 - s2 * z1) * r); - } - tangent.normalize(); - binormal.normalize(); - Vector3 normal=Plane( v1, v2, v3 ).normal; + SMikkTSpaceInterface mkif; + mkif.m_getNormal=mikktGetNormal; + mkif.m_getNumFaces=mikktGetNumFaces; + mkif.m_getNumVerticesOfFace=mikktGetNumVerticesOfFace; + mkif.m_getPosition=mikktGetPosition; + mkif.m_getTexCoord=mikktGetTexCoord; + mkif.m_setTSpaceBasic=mikktSetTSpaceBasic; + mkif.m_setTSpace=NULL; - Vector3 tangentp = tangent - normal * normal.dot( tangent ); - Vector3 binormalp = binormal - normal * (normal.dot(binormal)) - tangent * (tangent.dot(binormal)); + SMikkTSpaceContext msc; + msc.m_pInterface=&mkif; - tangentp.normalize(); - binormalp.normalize(); + Vector<List<Vertex>::Element*> vtx; + vtx.resize(vertex_array.size()); + int idx=0; + for (List<Vertex>::Element *E=vertex_array.front();E;E=E->next()) { + vtx[idx++]=E; + E->get().binormal=Vector3(); + E->get().tangent=Vector3(); + } + msc.m_pUserData=&vtx; + bool res = genTangSpaceDefault(&msc); - for (int j=0;j<3;j++) { - v[j]->get().binormal=binormalp; - v[j]->get().tangent=tangentp; + ERR_FAIL_COND(!res); + format|=Mesh::ARRAY_FORMAT_TANGENT; - } - } - } + if (indexed) + index(); - format|=Mesh::ARRAY_FORMAT_TANGENT; } diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h index fe82d3a4ce..fc5940145b 100644 --- a/scene/resources/surface_tool.h +++ b/scene/resources/surface_tool.h @@ -30,7 +30,7 @@ #define SURFACE_TOOL_H #include "scene/resources/mesh.h" - +#include "mikktspace.h" class SurfaceTool : public Reference { @@ -82,6 +82,14 @@ private: void _create_list(const Ref<Mesh>& p_existing, int p_surface, List<Vertex> *r_vertex, List<int> *r_index,int &lformat); + + //mikktspace callbacks + static int mikktGetNumFaces(const SMikkTSpaceContext * pContext); + static int mikktGetNumVerticesOfFace(const SMikkTSpaceContext * pContext, const int iFace); + static void mikktGetPosition(const SMikkTSpaceContext * pContext, float fvPosOut[], const int iFace, const int iVert); + static void mikktGetNormal(const SMikkTSpaceContext * pContext, float fvNormOut[], const int iFace, const int iVert); + static void mikktGetTexCoord(const SMikkTSpaceContext * pContext, float fvTexcOut[], const int iFace, const int iVert); + static void mikktSetTSpaceBasic(const SMikkTSpaceContext * pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert); protected: static void _bind_methods(); diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 5b31ba1f1b..dae055890b 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -79,6 +79,8 @@ void Texture::_bind_methods() { BIND_CONSTANT( FLAG_FILTER ); BIND_CONSTANT( FLAG_VIDEO_SURFACE ); BIND_CONSTANT( FLAGS_DEFAULT ); + BIND_CONSTANT( FLAG_ANISOTROPIC_FILTER ); + BIND_CONSTANT( FLAG_CONVERT_TO_LINEAR ); } @@ -179,7 +181,7 @@ void ImageTexture::_get_property_list( List<PropertyInfo> *p_list) const { - p_list->push_back( PropertyInfo( Variant::INT, "flags", PROPERTY_HINT_FLAGS,"Mipmaps,Repeat,Filter") ); + p_list->push_back( PropertyInfo( Variant::INT, "flags", PROPERTY_HINT_FLAGS,"Mipmaps,Repeat,Filter,Anisotropic,sRGB") ); p_list->push_back( PropertyInfo( Variant::IMAGE, "image", img_hint,String::num(lossy_storage_quality)) ); p_list->push_back( PropertyInfo( Variant::VECTOR2, "size",PROPERTY_HINT_NONE, "")); p_list->push_back( PropertyInfo( Variant::INT, "storage", PROPERTY_HINT_ENUM,"Uncompressed,Compress Lossy,Compress Lossless")); diff --git a/scene/resources/texture.h b/scene/resources/texture.h index 86ff246498..4bb2f6d979 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -52,6 +52,8 @@ public: FLAG_MIPMAPS=VisualServer::TEXTURE_FLAG_MIPMAPS, FLAG_REPEAT=VisualServer::TEXTURE_FLAG_REPEAT, FLAG_FILTER=VisualServer::TEXTURE_FLAG_FILTER, + FLAG_ANISOTROPIC_FILTER=VisualServer::TEXTURE_FLAG_ANISOTROPIC_FILTER, + FLAG_CONVERT_TO_LINEAR=VisualServer::TEXTURE_FLAG_CONVERT_TO_LINEAR, FLAG_VIDEO_SURFACE=VisualServer::TEXTURE_FLAG_VIDEO_SURFACE, FLAGS_DEFAULT=FLAG_MIPMAPS|FLAG_REPEAT|FLAG_FILTER, }; diff --git a/scene/scene_binds.cpp b/scene/scene_binds.cpp deleted file mode 100644 index 5c6a02611f..0000000000 --- a/scene/scene_binds.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/*************************************************************************/ -/* scene_binds.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "scene_binds.h" - - -#ifdef OLD_SCENE_FORMAT_ENABLED -void SceneIO::_bind_methods() { - - ObjectTypeDB::bind_method(_MD("load:Node","path"),&SceneIO::load); - ObjectTypeDB::bind_method(_MD("save","path","scene:Node","flags","optimizer:OptimizedSaver","scene"),&SceneIO::save,DEFVAL(0),DEFVAL(Ref<OptimizedSaver>())); - ObjectTypeDB::bind_method(_MD("load_interactive:SceneInteractiveLoader","path"),&SceneIO::load_interactive); -} - -Node* SceneIO::load(const String& p_scene) { - - return SceneLoader::load(p_scene); -} - -Error SceneIO::save(const String& p_path, Node *p_scene,int p_flags,const Ref<OptimizedSaver> &p_optimizer) { - - return SceneSaver::save(p_path,p_scene,p_flags,p_optimizer); -} - -Ref<SceneInteractiveLoader> SceneIO::load_interactive(const String& p_scene) { - - return SceneLoader::load_interactive(p_scene); -} - -#endif diff --git a/scene/scene_binds.h b/scene/scene_binds.h deleted file mode 100644 index 29e4b9ab60..0000000000 --- a/scene/scene_binds.h +++ /dev/null @@ -1,62 +0,0 @@ -/*************************************************************************/ -/* scene_binds.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef SCENE_BINDS_H -#define SCENE_BINDS_H - -#include "scene/io/scene_loader.h" -#include "scene/io/scene_saver.h" - -#ifdef OLD_SCENE_FORMAT_ENABLED - -class SceneIO : public Object { - - OBJ_TYPE( SceneIO, Object ); -protected: - - static void _bind_methods(); -public: - - enum SaveFlags { - - SAVE_FLAG_RELATIVE_PATHS=SceneSaver::FLAG_RELATIVE_PATHS, - SAVE_FLAG_BUNDLE_RESOURCES=SceneSaver::FLAG_BUNDLE_RESOURCES, - SAVE_FLAG_BUNDLE_INSTANCED_SCENES=SceneSaver::FLAG_BUNDLE_INSTANCED_SCENES, - SAVE_FLAG_OMIT_EDITOR_PROPERTIES=SceneSaver::FLAG_OMIT_EDITOR_PROPERTIES, - SAVE_FLAG_SAVE_BIG_ENDIAN=SceneSaver::FLAG_SAVE_BIG_ENDIAN - }; - - Node* load(const String& p_scene); - Error save(const String& p_path, Node *p_scene,int p_flags=0,const Ref<OptimizedSaver> &p_optimizer=Ref<OptimizedSaver>()); - Ref<SceneInteractiveLoader> load_interactive(const String& p_scene); - - SceneIO() {} -}; - -#endif -#endif // SCENE_BINDS_H |