diff options
73 files changed, 3350 insertions, 689 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index fd6a91d125..ec159da00f 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -479,10 +479,54 @@ void _OS::print_all_textures_by_size() { print_line(E->get().path+" - "+String::humanize_size(E->get().vram)+" ("+E->get().size+") - total:"+String::humanize_size(total) ); total-=E->get().vram; } +} +void _OS::print_resources_by_type(const Vector<String>& p_types) { + Map<String,int> type_count; + + List<Ref<Resource> > resources; + ResourceCache::get_cached_resources(&resources); + + List<Ref<Resource> > rsrc; + ResourceCache::get_cached_resources(&rsrc); + + for (List<Ref<Resource> >::Element *E=rsrc.front();E;E=E->next()) { + + Ref<Resource> r = E->get(); + + bool found = false; + + for (int i=0; i<p_types.size(); i++) { + if (r->is_type(p_types[i])) + found = true; + } + if (!found) + continue; + + if (!type_count.has(r->get_type())) { + type_count[r->get_type()]=0; + } + + + type_count[r->get_type()]++; + + print_line(r->get_type()+": "+r->get_path()); + + List<String> metas; + r->get_meta_list(&metas); + for (List<String>::Element* me = metas.front(); me; me = me->next()) { + print_line(" "+String(me->get()) + ": " + r->get_meta(me->get())); + }; + } + + for(Map<String,int>::Element *E=type_count.front();E;E=E->next()) { + + print_line(E->key()+" count: "+itos(E->get())); + } + +}; -} void _OS::print_all_resources(const String& p_to_file ) { @@ -509,9 +553,9 @@ float _OS::get_frames_per_second() const { return OS::get_singleton()->get_frames_per_second(); } -Error _OS::native_video_play(String p_path) { +Error _OS::native_video_play(String p_path, float p_volume) { - return OS::get_singleton()->native_video_play(p_path); + return OS::get_singleton()->native_video_play(p_path, p_volume); }; bool _OS::native_video_is_playing() { @@ -614,6 +658,7 @@ void _OS::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_frames_per_second"),&_OS::get_frames_per_second); ObjectTypeDB::bind_method(_MD("print_all_textures_by_size"),&_OS::print_all_textures_by_size); + ObjectTypeDB::bind_method(_MD("print_resources_by_type"),&_OS::print_resources_by_type); ObjectTypeDB::bind_method(_MD("native_video_play"),&_OS::native_video_play); ObjectTypeDB::bind_method(_MD("native_video_is_playing"),&_OS::native_video_is_playing); diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index f5c94dcf06..18eb594760 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -98,7 +98,7 @@ public: bool is_video_mode_resizable(int p_screen=0) const; Array get_fullscreen_mode_list(int p_screen=0) const; - Error native_video_play(String p_path); + Error native_video_play(String p_path, float p_volume); bool native_video_is_playing(); void native_video_pause(); void native_video_stop(); @@ -139,6 +139,7 @@ public: void print_resources_in_use(bool p_short=false); void print_all_resources(const String& p_to_file); void print_all_textures_by_size(); + void print_resources_by_type(const Vector<String>& p_types); bool has_touchscreen_ui_hint() const; diff --git a/core/hash_map.h b/core/hash_map.h index 02a6600c3b..da8f038490 100644 --- a/core/hash_map.h +++ b/core/hash_map.h @@ -285,14 +285,12 @@ public: } void set( const Pair& p_pair ) { - + + Entry *e=NULL; if (!hash_table) make_hash_table(); // if no table, make one else - check_hash_table(); // perform mantenience routine - - /* As said, i want to have only one get_entry */ - Entry *e = const_cast<Entry*>( get_entry(p_pair.key) ); + e = const_cast<Entry*>( get_entry(p_pair.key) ); /* if we made it up to here, the pair doesn't exist, create and assign */ @@ -301,6 +299,7 @@ public: e=create_entry(p_pair.key); if (!e) return; + check_hash_table(); // perform mantenience routine } e->pair.data = p_pair.data; @@ -478,12 +477,11 @@ public: } inline TData& operator[](const TKey& p_key ) { //assignment + Entry *e=NULL; if (!hash_table) make_hash_table(); // if no table, make one else - check_hash_table(); // perform mantenience routine - - Entry *e = const_cast<Entry*>( get_entry(p_key) ); + e = const_cast<Entry*>( get_entry(p_key) ); /* if we made it up to here, the pair doesn't exist, create */ if (!e) { @@ -491,6 +489,7 @@ public: e=create_entry(p_key); if (!e) return *(TData*)NULL; /* panic! */ + check_hash_table(); // perform mantenience routine } return e->pair.data; diff --git a/core/hashfuncs.h b/core/hashfuncs.h index 6dae82bc55..3b6715a4cd 100644 --- a/core/hashfuncs.h +++ b/core/hashfuncs.h @@ -54,9 +54,9 @@ static inline uint32_t hash_djb2(const char *p_cstr) { return hash; } -static inline uint32_t hash_djb2_buffer(uint8_t *p_buff, int p_len) { +static inline uint32_t hash_djb2_buffer(const uint8_t *p_buff, int p_len,uint32_t p_prev=5381) { - uint32_t hash = 5381; + uint32_t hash = p_prev; for(int i=0;i<p_len;i++) hash = ((hash << 5) + hash) + p_buff[i]; /* hash * 33 + c */ diff --git a/core/math/geometry.h b/core/math/geometry.h index 826e4697b5..5b21c25bec 100644 --- a/core/math/geometry.h +++ b/core/math/geometry.h @@ -695,6 +695,86 @@ public: } + + static inline Vector<Vector3> clip_polygon(const Vector<Vector3>& polygon,const Plane& p_plane) { + + enum LocationCache { + LOC_INSIDE=1, + LOC_BOUNDARY=0, + LOC_OUTSIDE=-1 + }; + + if (polygon.size()==0) + return polygon; + + int *location_cache = (int*)alloca(sizeof(int)*polygon.size()); + int inside_count = 0; + int outside_count = 0; + + for (int a = 0; a < polygon.size(); a++) { + //float p_plane.d = (*this) * polygon[a]; + float dist = p_plane.distance_to(polygon[a]); + if (dist <-CMP_POINT_IN_PLANE_EPSILON) { + location_cache[a] = LOC_INSIDE; + inside_count++; + } else { + if (dist > CMP_POINT_IN_PLANE_EPSILON) { + location_cache[a] = LOC_OUTSIDE; + outside_count++; + } else { + location_cache[a] = LOC_BOUNDARY; + } + } + } + + if (outside_count == 0) { + + return polygon; // no changes + + } else if (inside_count == 0) { + + return Vector<Vector3>(); //empty + } + +// long count = 0; + long previous = polygon.size() - 1; + + Vector<Vector3> clipped; + + for (int index = 0; index < polygon.size(); index++) { + int loc = location_cache[index]; + if (loc == LOC_OUTSIDE) { + if (location_cache[previous] == LOC_INSIDE) { + const Vector3& v1 = polygon[previous]; + const Vector3& v2 = polygon[index]; + + Vector3 segment= v1 - v2; + double den=p_plane.normal.dot( segment ); + double dist=p_plane.distance_to( v1 ) / den; + dist=-dist; + clipped.push_back( v1 + segment * dist ); + } + } else { + const Vector3& v1 = polygon[index]; + if ((loc == LOC_INSIDE) && (location_cache[previous] == LOC_OUTSIDE)) { + const Vector3& v2 = polygon[previous]; + Vector3 segment= v1 - v2; + double den=p_plane.normal.dot( segment ); + double dist=p_plane.distance_to( v1 ) / den; + dist=-dist; + clipped.push_back( v1 + segment * dist ); + } + + clipped.push_back(v1); + } + + previous = index; + } + + return clipped; + } + + static Vector<int> triangulate_polygon(const Vector<Vector2>& p_polygon) { Vector<int> triangles; diff --git a/core/os/main_loop.h b/core/os/main_loop.h index b84d2841e1..6eb5881175 100644 --- a/core/os/main_loop.h +++ b/core/os/main_loop.h @@ -50,7 +50,8 @@ public: NOTIFICATION_WM_FOCUS_IN = 5, NOTIFICATION_WM_FOCUS_OUT = 6, NOTIFICATION_WM_QUIT_REQUEST = 7, - NOTIFICATION_WM_UNFOCUS_REQUEST = 8 + NOTIFICATION_WM_UNFOCUS_REQUEST = 8, + NOTIFICATION_OS_MEMORY_WARNING = 9, }; virtual void input_event( const InputEvent& p_event ); diff --git a/core/os/os.cpp b/core/os/os.cpp index 65d6ed50b2..11290409d5 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -225,7 +225,7 @@ void OS::print_all_resources(String p_to_file) { void OS::print_resources_in_use(bool p_short) { - //ResourceCache::dump(NULL,p_short); + ResourceCache::dump(NULL,p_short); } void OS::dump_resources_to_file(const char* p_file) { @@ -438,7 +438,7 @@ int OS::get_processor_count() const { return 1; } -Error OS::native_video_play(String p_path) { +Error OS::native_video_play(String p_path, float p_volume) { return FAILED; }; diff --git a/core/os/os.h b/core/os/os.h index e7fe0cb09e..24e2b4f2d4 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -321,7 +321,7 @@ public: virtual String get_unique_ID() const; - virtual Error native_video_play(String p_path); + virtual Error native_video_play(String p_path, float p_volume); virtual bool native_video_is_playing() const; virtual void native_video_pause(); virtual void native_video_stop(); diff --git a/core/variant.cpp b/core/variant.cpp index 6b3b25a103..fdb14c0c0f 100644 --- a/core/variant.cpp +++ b/core/variant.cpp @@ -1337,6 +1337,10 @@ Variant::operator Matrix3() const { if (type==MATRIX3) return *_data._matrix3; + else if (type==QUAT) + return *reinterpret_cast<const Quat*>(_data._mem); + else if (type==TRANSFORM) + return _data._transform->basis; else return Matrix3(); } @@ -1345,6 +1349,10 @@ Variant::operator Quat() const { if (type==QUAT) return *reinterpret_cast<const Quat*>(_data._mem); + else if (type==MATRIX3) + return *_data._matrix3; + else if (type==TRANSFORM) + return _data._transform->basis; else return Quat(); } @@ -1357,6 +1365,8 @@ Variant::operator Transform() const { return *_data._transform; else if (type==MATRIX3) return Transform(*_data._matrix3,Vector3()); + else if (type==QUAT) + return Transform(Matrix3(*reinterpret_cast<const Quat*>(_data._mem)),Vector3()); else return Transform(); } diff --git a/demos/2d/platformer/stage.xml b/demos/2d/platformer/stage.xml index cf9a5ff44a..952c21e936 100644 --- a/demos/2d/platformer/stage.xml +++ b/demos/2d/platformer/stage.xml @@ -3,15 +3,15 @@ <ext_resource path="res://music.ogg" type="AudioStream"></ext_resource> <ext_resource path="res://tileset.xml" type="TileSet"></ext_resource> <ext_resource path="res://coin.xml" type="PackedScene"></ext_resource> - <ext_resource path="res://player.xml" type="PackedScene"></ext_resource> + <ext_resource path="res://seesaw.xml" type="PackedScene"></ext_resource> <ext_resource path="res://enemy.xml" type="PackedScene"></ext_resource> <ext_resource path="res://moving_platform.xml" type="PackedScene"></ext_resource> - <ext_resource path="res://seesaw.xml" type="PackedScene"></ext_resource> + <ext_resource path="res://player.xml" type="PackedScene"></ext_resource> <ext_resource path="res://parallax_bg.xml" type="PackedScene"></ext_resource> <main_resource> <dictionary name="_bundled" shared="false"> <string> "names" </string> - <string_array len="118"> + <string_array len="119"> <string> "stage" </string> <string> "Node" </string> <string> "__meta__" </string> @@ -28,6 +28,7 @@ <string> "quadrant_size" </string> <string> "tile_set" </string> <string> "tile_data" </string> + <string> "collision_layers" </string> <string> "coins" </string> <string> "coin" </string> <string> "Area2D" </string> @@ -138,7 +139,7 @@ <string> "node_count" </string> <int> 66 </int> <string> "variants" </string> - <array len="95" shared="false"> + <array len="96" shared="false"> <dictionary shared="false"> <string> "__editor_plugin_states__" </string> <dictionary shared="false"> @@ -260,6 +261,7 @@ <int> 16 </int> <resource resource_type="TileSet" path="res://tileset.xml"> </resource> <int_array len="1998"> 0, 2, 70, 536870914, 71, 10, 72, 10, 73, 10, 74, 10, 75, 10, 76, 10, 77, 10, 78, 10, 65536, 2, 65606, 536870914, 65607, 10, 65608, 10, 65609, 10, 65610, 10, 65611, 10, 65612, 10, 65613, 10, 65614, 10, 131072, 2, 131142, 536870914, 131143, 10, 131144, 10, 131145, 10, 131146, 10, 131147, 10, 131148, 10, 131149, 10, 131150, 10, 196608, 2, 196626, 9, 196678, 536870914, 196679, 10, 196680, 10, 196681, 10, 196682, 10, 196683, 10, 196684, 10, 196685, 10, 196686, 10, 262144, 2, 262162, 8, 262214, 536870914, 262215, 10, 262216, 10, 262217, 10, 262218, 10, 262219, 10, 262220, 10, 262221, 10, 262222, 10, 327680, 2, 327697, 536870921, 327698, 7, 327733, 9, 327750, 536870914, 327751, 10, 327752, 10, 327753, 10, 327754, 10, 327755, 10, 327756, 10, 327757, 10, 327758, 10, 393216, 2, 393233, 536870920, 393234, 7, 393257, 9, 393269, 7, 393286, 536870914, 393287, 10, 393288, 10, 393289, 10, 393290, 10, 393291, 10, 393292, 10, 393293, 10, 393294, 10, 458752, 2, 458769, 7, 458770, 8, 458790, 9, 458793, 8, 458805, 8, 458822, 536870914, 458823, 10, 458824, 10, 458825, 10, 458826, 10, 458827, 10, 458828, 10, 458829, 10, 458830, 10, 524288, 4, 524289, 1, 524304, 536870913, 524305, 536870918, 524306, 6, 524307, 5, 524308, 1, 524326, 8, 524329, 7, 524341, 7, 524358, 536870914, 524359, 10, 524360, 10, 524361, 10, 524362, 10, 524363, 10, 524364, 10, 524365, 10, 524366, 10, 589824, 10, 589825, 13, 589840, 536870914, 589841, 10, 589842, 10, 589843, 10, 589844, 2, 589862, 7, 589865, 7, 589876, 536870913, 589877, 6, 589878, 1, 589894, 536870914, 589895, 10, 589896, 10, 589897, 10, 589898, 10, 589899, 10, 589900, 10, 589901, 10, 589902, 10, 655360, 2, 655376, 536870914, 655377, 10, 655378, 10, 655379, 10, 655380, 2, 655398, 7, 655401, 8, 655412, 536870925, 655413, 11, 655414, 13, 655430, 536870914, 655431, 10, 655432, 10, 655433, 10, 655434, 10, 655435, 10, 655436, 10, 655437, 10, 655438, 10, 720896, 2, 720912, 536870914, 720913, 10, 720914, 10, 720915, 10, 720916, 2, 720934, 8, 720937, 7, 720958, 536870913, 720959, 5, 720960, 536870917, 720961, 5, 720962, 5, 720963, 536870917, 720964, 5, 720965, 0, 720966, 536870916, 720967, 10, 720968, 10, 720969, 10, 720970, 10, 720971, 10, 720972, 10, 720973, 10, 720974, 10, 786432, 2, 786437, 9, 786448, 536870914, 786449, 10, 786450, 10, 786451, 10, 786452, 2, 786464, 536870913, 786465, 1, 786470, 7, 786473, 7, 786474, 536870924, 786475, 1, 786494, 536870914, 786495, 10, 786496, 10, 786497, 10, 786498, 10, 786499, 10, 786500, 10, 786501, 10, 786502, 10, 786503, 10, 786504, 10, 786505, 10, 786506, 10, 786507, 10, 786508, 10, 786509, 10, 851968, 2, 851973, 7, 851984, 536870914, 851985, 10, 851986, 10, 851987, 10, 851988, 2, 851996, 536870913, 851997, 1, 852000, 536870914, 852001, 3, 852006, 7, 852009, 536870913, 852011, 2, 852030, 536870914, 852031, 10, 852032, 10, 852033, 10, 852034, 10, 852035, 10, 852036, 10, 852037, 10, 852038, 10, 852039, 10, 852040, 10, 852041, 10, 852042, 10, 852043, 10, 852044, 10, 852045, 10, 917504, 2, 917506, 9, 917509, 7, 917512, 536870921, 917520, 536870925, 917521, 11, 917522, 11, 917523, 11, 917524, 13, 917532, 536870925, 917533, 13, 917536, 536870914, 917537, 4, 917538, 1, 917540, 536870913, 917541, 0, 917542, 1, 917545, 536870914, 917546, 10, 917547, 4, 917548, 1, 917566, 536870914, 917567, 10, 917568, 10, 917569, 10, 917570, 10, 917571, 10, 917572, 10, 917573, 10, 917574, 10, 917575, 10, 917576, 10, 917577, 10, 917578, 10, 917579, 10, 917580, 10, 917581, 10, 983040, 2, 983042, 7, 983045, 7, 983048, 536870920, 983050, 536870913, 983051, 1, 983064, 536870913, 983065, 1, 983072, 536870914, 983073, 10, 983074, 4, 983075, 0, 983076, 536870916, 983077, 10, 983078, 4, 983079, 536870912, 983080, 536870912, 983081, 536870916, 983082, 10, 983083, 10, 983084, 2, 983095, 9, 983102, 536870914, 983103, 10, 983104, 10, 983105, 10, 983106, 10, 983107, 10, 983108, 10, 983109, 10, 983110, 10, 983111, 10, 983112, 10, 983113, 10, 983114, 10, 983115, 10, 983116, 10, 983117, 10, 1048576, 2, 1048578, 8, 1048581, 8, 1048584, 536870919, 1048586, 536870925, 1048587, 13, 1048600, 536870925, 1048601, 13, 1048604, 9, 1048608, 536870925, 1048609, 536870923, 1048610, 536870923, 1048611, 536870923, 1048612, 10, 1048613, 10, 1048614, 10, 1048615, 10, 1048616, 10, 1048617, 10, 1048618, 10, 1048619, 10, 1048620, 4, 1048621, 1, 1048630, 536870921, 1048631, 8, 1048638, 536870914, 1048639, 10, 1048640, 10, 1048641, 10, 1048642, 10, 1048643, 10, 1048644, 10, 1048645, 10, 1048646, 10, 1048647, 10, 1048648, 10, 1048649, 10, 1048650, 10, 1048651, 10, 1048652, 10, 1048653, 10, 1114112, 4, 1114113, 0, 1114114, 6, 1114115, 0, 1114116, 0, 1114117, 6, 1114118, 1, 1114120, 536870920, 1114128, 536870913, 1114129, 5, 1114130, 536870917, 1114131, 5, 1114132, 0, 1114133, 1, 1114140, 7, 1114141, 536870921, 1114148, 536870914, 1114149, 10, 1114150, 10, 1114151, 10, 1114152, 10, 1114153, 10, 1114154, 10, 1114155, 10, 1114156, 10, 1114157, 2, 1114166, 536870920, 1114167, 8, 1114174, 536870914, 1114175, 10, 1114176, 10, 1114177, 10, 1114178, 10, 1114179, 10, 1114180, 10, 1114181, 10, 1114182, 10, 1114183, 10, 1114184, 10, 1114185, 10, 1114186, 10, 1114187, 10, 1114188, 10, 1179648, 10, 1179649, 10, 1179650, 10, 1179651, 10, 1179652, 10, 1179653, 10, 1179654, 2, 1179656, 536870919, 1179663, 536870915, 1179665, 10, 1179666, 10, 1179667, 10, 1179668, 10, 1179669, 4, 1179670, 12, 1179675, 9, 1179676, 8, 1179677, 8, 1179684, 536870914, 1179685, 10, 1179686, 10, 1179687, 10, 1179688, 10, 1179689, 10, 1179690, 10, 1179691, 10, 1179692, 10, 1179693, 4, 1179694, 1, 1179701, 9, 1179702, 536870919, 1179703, 7, 1179710, 536870914, 1179711, 10, 1179712, 10, 1179713, 10, 1179714, 10, 1179715, 10, 1179716, 10, 1179717, 10, 1179718, 10, 1179719, 10, 1179720, 10, 1179721, 10, 1179722, 10, 1245184, 10, 1245185, 10, 1245186, 10, 1245187, 10, 1245188, 10, 1245189, 10, 1245190, 2, 1245192, 536870919, 1245199, 536870913, 1245200, 536870916, 1245201, 10, 1245202, 10, 1245203, 10, 1245204, 10, 1245205, 10, 1245207, 1, 1245211, 7, 1245212, 7, 1245213, 536870920, 1245220, 536870914, 1245221, 10, 1245222, 10, 1245223, 10, 1245224, 10, 1245225, 10, 1245226, 10, 1245227, 10, 1245228, 10, 1245229, 10, 1245230, 2, 1245237, 8, 1245238, 536870919, 1245239, 8, 1245240, 536870921, 1245246, 536870914, 1245247, 10, 1245248, 10, 1245249, 10, 1245250, 10, 1245251, 10, 1245252, 10, 1245253, 10, 1245254, 10, 1245255, 10, 1245256, 10, 1245257, 10, 1245258, 10, 1310720, 10, 1310721, 10, 1310722, 10, 1310723, 10, 1310724, 10, 1310725, 10, 1310726, 2, 1310728, 536870920, 1310730, 536870913, 1310731, 1, 1310734, 536870913, 1310735, 536870916, 1310736, 10, 1310737, 10, 1310738, 10, 1310739, 10, 1310740, 10, 1310741, 10, 1310742, 10, 1310743, 4, 1310744, 1, 1310747, 8, 1310748, 7, 1310749, 536870919, 1310756, 536870914, 1310757, 10, 1310758, 10, 1310759, 10, 1310760, 10, 1310761, 10, 1310762, 10, 1310763, 10, 1310764, 10, 1310765, 10, 1310766, 4, 1310767, 5, 1310768, 12, 1310773, 7, 1310774, 536870919, 1310775, 7, 1310776, 536870919, 1310782, 536870914, 1310783, 10, 1310784, 10, 1310785, 10, 1310786, 10, 1310787, 10, 1310788, 10, 1310789, 10, 1310790, 10, 1310791, 10, 1310792, 10, 1310793, 10, 1376256, 10, 1376257, 10, 1376258, 10, 1376259, 10, 1376260, 10, 1376261, 10, 1376262, 4, 1376263, 0, 1376264, 536870918, 1376265, 0, 1376266, 536870916, 1376267, 4, 1376268, 0, 1376269, 0, 1376270, 536870916, 1376271, 10, 1376272, 10, 1376273, 10, 1376274, 10, 1376275, 10, 1376276, 10, 1376277, 10, 1376278, 10, 1376279, 10, 1376280, 4, 1376281, 12, 1376283, 8, 1376284, 8, 1376285, 536870920, 1376287, 536870924, 1376288, 0, 1376289, 5, 1376290, 536870917, 1376291, 0, 1376292, 536870916, 1376293, 10, 1376294, 10, 1376295, 10, 1376296, 10, 1376297, 10, 1376298, 10, 1376299, 10, 1376300, 10, 1376301, 10, 1376302, 10, 1376303, 10, 1376305, 12, 1376309, 7, 1376310, 536870920, 1376311, 7, 1376312, 536870920, 1376318, 536870914, 1376319, 10, 1376320, 10, 1376321, 10, 1376322, 10, 1376323, 10, 1376324, 10, 1376325, 10, 1376326, 10, 1376327, 10, 1376328, 10, 1441792, 10, 1441793, 10, 1441794, 10, 1441795, 10, 1441796, 10, 1441797, 10, 1441798, 10, 1441799, 10, 1441800, 10, 1441801, 10, 1441802, 10, 1441803, 10, 1441804, 10, 1441805, 10, 1441806, 10, 1441807, 10, 1441808, 10, 1441809, 10, 1441810, 10, 1441811, 10, 1441812, 10, 1441813, 10, 1441814, 10, 1441815, 10, 1441816, 10, 1441818, 0, 1441819, 6, 1441820, 6, 1441821, 536870918, 1441822, 5, 1441824, 10, 1441825, 10, 1441826, 10, 1441827, 10, 1441828, 10, 1441829, 10, 1441830, 10, 1441831, 10, 1441832, 10, 1441833, 10, 1441834, 10, 1441835, 10, 1441836, 10, 1441837, 10, 1441838, 10, 1441839, 10, 1441840, 10, 1441842, 0, 1441843, 0, 1441844, 0, 1441845, 6, 1441846, 536870918, 1441847, 6, 1441848, 536870918, 1441849, 0, 1441850, 5, 1441851, 536870917, 1441852, 5, 1441853, 0, 1441854, 536870916, 1441855, 10, 1441856, 10, 1441857, 10, 1441858, 10, 1441859, 10, 1441860, 10, 1441861, 10, 1441862, 10, 1441863, 10, 1507328, 10, 1507329, 10, 1507330, 10, 1507331, 10, 1507332, 10, 1507333, 10, 1507334, 10, 1507335, 10, 1507336, 10, 1507337, 10, 1507338, 10, 1507339, 10, 1507340, 10, 1507341, 10, 1507342, 10, 1507343, 10, 1507344, 10, 1507345, 10, 1507346, 10, 1507347, 10, 1507348, 10, 1507349, 10, 1507350, 10, 1507351, 10, 1507352, 10, 1507353, 10, 1507354, 10, 1507355, 10, 1507356, 10, 1507357, 10, 1507358, 10, 1507359, 10, 1507360, 10, 1507361, 10, 1507362, 10, 1507363, 10, 1507364, 10, 1507365, 10, 1507366, 10, 1507367, 10, 1507368, 10, 1507369, 10, 1507370, 10, 1507371, 10, 1507372, 10, 1507373, 10, 1507374, 10, 1507375, 10, 1507376, 10, 1507377, 10, 1507378, 10, 1507379, 10, 1507380, 10, 1507381, 10, 1507382, 10, 1507383, 10, 1507384, 10, 1507385, 10, 1507386, 10, 1507387, 10, 1507388, 10, 1507389, 10, 1507390, 10, 1507391, 10, 1507392, 10, 1507393, 10, 1507394, 10, 1507395, 10, 1507396, 10, 1507397, 10, 1507398, 10, 1507399, 10, 1572864, 10, 1572865, 10, 1572866, 10, 1572867, 10, 1572868, 10, 1572869, 10, 1572870, 10, 1572871, 10, 1572872, 10, 1572873, 10, 1572874, 10, 1572875, 10, 1572876, 10, 1572877, 10, 1572878, 10, 1572879, 10, 1572880, 10, 1572881, 10, 1572882, 10, 1572883, 10, 1572884, 10, 1572885, 10, 1572886, 10, 1572887, 10, 1572888, 10, 1572889, 10, 1572890, 10, 1572891, 10, 1572892, 10, 1572893, 10, 1572894, 10, 1572895, 10, 1572896, 10, 1572897, 10, 1572898, 10, 1572899, 10, 1572900, 10, 1572901, 10, 1572902, 10, 1572903, 10, 1572904, 10, 1572905, 10, 1572906, 10, 1572907, 10, 1572908, 10, 1572909, 10, 1572910, 10, 1572911, 10, 1572912, 10, 1572913, 10, 1572914, 10, 1572915, 10, 1572916, 10, 1572917, 10, 1572918, 10, 1572919, 10, 1572920, 10, 1572921, 10, 1572922, 10, 1572923, 10, 1572924, 10, 1572925, 10, 1572926, 10, 1572927, 10, 1572928, 10, 1572929, 10, 1572930, 10, 1572931, 10, 1572932, 10, 1572933, 10, 1572934, 10, 1572935, 10, 1638400, 10, 1638401, 10, 1638402, 10, 1638403, 10, 1638404, 10, 1638405, 10, 1638406, 10, 1638407, 10, 1638408, 10, 1638409, 10, 1638410, 10, 1638411, 10, 1638412, 10, 1638413, 10, 1638414, 10, 1638415, 10, 1638416, 10, 1638417, 10, 1638418, 10, 1638419, 10, 1638420, 10, 1638421, 10, 1638422, 10, 1638423, 10, 1638424, 10, 1638425, 10, 1638426, 10, 1638427, 10, 1638428, 10, 1638429, 10, 1638430, 10, 1638431, 10, 1638432, 10, 1638433, 10, 1638434, 10, 1638435, 10, 1638436, 10, 1638437, 10, 1638438, 10, 1638439, 10, 1638440, 10, 1638441, 10, 1638442, 10, 1638443, 10, 1638444, 10, 1638445, 10, 1638446, 10, 1638447, 10, 1638448, 10, 1638449, 10, 1638450, 10, 1638451, 10, 1638452, 10, 1638453, 10, 1638454, 10, 1638455, 10, 1638456, 10, 1638457, 10, 1638458, 10, 1638459, 10, 1638460, 10, 1638461, 10, 1638462, 10, 1638463, 10, 1638464, 10, 1638465, 10, 1638466, 10, 1638467, 10, 1638468, 10, 1638469, 10, 1638470, 10, 1638471, 10, 1703952, 10, 1703953, 10, 1703954, 10, 1703955, 10, 1703956, 10, 1703957, 10, 1703958, 10, 1703959, 10, 1703960, 10, 1703961, 10, 1703962, 10, 1703963, 10, 1703964, 10, 1703965, 10, 1703966, 10, 1703967, 10, 1703968, 10, 1703969, 10, 1703970, 10, 1703971, 10, 1703972, 10, 1703973, 10, 1703974, 10, 1703975, 10, 1703976, 10, 1703977, 10, 1703978, 10, 1703979, 10, 1703980, 10, 1703981, 10, 1703982, 10, 1703983, 10, 1703984, 10, 1703985, 10, 1703986, 10, 1703987, 10, 1703988, 10, 1703989, 10, 1703990, 10, 1703991, 10, 1703992, 10, 1703993, 10, 1703994, 10, 1703995, 10, 1703996, 10, 1703997, 10, 1703998, 10, 1703999, 10, 1704000, 10, 1704001, 10, 1704002, 10, 1704003, 10, 1704004, 10, 1704005, 10, 1704006, 10, 1704007, 10, 1769488, 10, 1769489, 10, 1769490, 10, 1769491, 10, 1769492, 10, 1769493, 10, 1769494, 10, 1769495, 10, 1769496, 10, 1769497, 10, 1769498, 10, 1769499, 10, 1769500, 10, 1769501, 10, 1769502, 10, 1769503, 10, 1769504, 10, 1769505, 10, 1769506, 10, 1769507, 10, 1769508, 10, 1769509, 10, 1769510, 10, 1769511, 10, 1769512, 10, 1769513, 10, 1769514, 10, 1769515, 10, 1769516, 10, 1769517, 10, 1769518, 10, 1769519, 10, 1769520, 10, 1769521, 10, 1769522, 10, 1769523, 10, 1769524, 10, 1769525, 10, 1769526, 10, 1769527, 10, 1769528, 10, 1769529, 10, 1769530, 10, 1769531, 10, 1769532, 10, 1769533, 10, 1769534, 10, 1769535, 10, 1769536, 10, 1769537, 10, 1769538, 10, 1769539, 10, 1769540, 10, 1769541, 10 </int_array> + <int> 1 </int> <dictionary shared="false"> <string> "_edit_lock_" </string> <bool> True </bool> @@ -352,7 +354,7 @@ <real> -1 </real> </array> <string> "nodes" </string> - <int_array len="688"> -1, -1, 1, 0, -1, 1, 2, 0, 0, 0, 0, 4, 3, -1, 12, 5, 1, 6, 2, 7, 2, 8, 3, 9, 4, 10, 5, 11, 6, 12, 7, 13, 8, 14, 9, 15, 10, 2, 11, 0, 0, 0, 1, 16, -1, 1, 2, 12, 0, 2, 0, 18, 17, 13, 1, 9, 14, 0, 2, 0, 18, 19, 13, 1, 9, 15, 0, 2, 0, 18, 20, 13, 1, 9, 16, 0, 2, 0, 18, 21, 13, 1, 9, 17, 0, 2, 0, 18, 22, 13, 1, 9, 18, 0, 2, 0, 18, 23, 13, 1, 9, 19, 0, 2, 0, 18, 24, 13, 1, 9, 20, 0, 2, 0, 18, 25, 13, 1, 9, 21, 0, 2, 0, 18, 26, 13, 1, 9, 22, 0, 2, 0, 18, 27, 13, 1, 9, 23, 0, 2, 0, 18, 28, 13, 1, 9, 24, 0, 2, 0, 18, 29, 13, 1, 9, 25, 0, 2, 0, 18, 30, 13, 1, 9, 26, 0, 2, 0, 18, 31, 13, 1, 9, 27, 0, 2, 0, 18, 32, 13, 1, 9, 28, 0, 2, 0, 18, 33, 13, 1, 9, 29, 0, 2, 0, 18, 34, 13, 1, 9, 30, 0, 2, 0, 18, 35, 13, 1, 9, 31, 0, 2, 0, 18, 36, 13, 1, 9, 32, 0, 2, 0, 18, 37, 13, 1, 9, 33, 0, 2, 0, 18, 38, 13, 1, 9, 34, 0, 2, 0, 18, 39, 13, 1, 9, 35, 0, 2, 0, 18, 40, 13, 1, 9, 36, 0, 2, 0, 18, 41, 13, 1, 9, 37, 0, 2, 0, 18, 42, 13, 1, 9, 38, 0, 2, 0, 18, 43, 13, 1, 9, 39, 0, 2, 0, 18, 44, 13, 1, 9, 40, 0, 2, 0, 18, 45, 13, 1, 9, 41, 0, 2, 0, 18, 46, 13, 1, 9, 42, 0, 2, 0, 18, 47, 13, 1, 9, 43, 0, 2, 0, 18, 48, 13, 1, 9, 44, 0, 2, 0, 18, 49, 13, 1, 9, 45, 0, 2, 0, 18, 50, 13, 1, 9, 46, 0, 2, 0, 18, 51, 13, 1, 9, 47, 0, 2, 0, 18, 52, 13, 1, 9, 48, 0, 2, 0, 18, 53, 13, 1, 9, 49, 0, 2, 0, 18, 54, 13, 1, 9, 50, 0, 2, 0, 18, 55, 13, 1, 9, 51, 0, 2, 0, 18, 56, 13, 1, 9, 52, 0, 2, 0, 18, 57, 13, 1, 9, 53, 0, 2, 0, 18, 58, 13, 1, 9, 54, 0, 2, 0, 18, 59, 13, 1, 9, 55, 0, 0, 0, 61, 60, 56, 1, 9, 57, 0, 0, 0, 1, 62, -1, 0, 0, 46, 0, 64, 63, 58, 3, 9, 59, 65, 60, 66, 61, 0, 46, 0, 64, 67, 58, 3, 9, 62, 65, 63, 66, 64, 0, 46, 0, 64, 68, 58, 3, 9, 65, 65, 66, 66, 64, 0, 46, 0, 64, 69, 67, 1, 9, 68, 0, 0, 0, 71, 70, -1, 6, 72, 69, 73, 3, 74, 1, 75, 70, 76, 1, 77, 3, 0, 0, 0, 1, 78, -1, 0, 0, 52, 0, 61, 79, 71, 1, 9, 72, 0, 52, 0, 61, 80, 71, 1, 9, 73, 0, 52, 0, 61, 81, 71, 1, 9, 74, 0, 52, 0, 61, 82, 71, 1, 9, 75, 0, 52, 0, 61, 83, 71, 1, 9, 76, 0, 52, 0, 61, 84, 71, 1, 9, 77, 0, 52, 0, 61, 85, 71, 1, 9, 78, 0, 52, 0, 61, 86, 71, 1, 9, 79, 0, 52, 0, 61, 87, 71, 1, 9, 80, 0, 52, 0, 61, 88, 71, 1, 9, 81, 0, 52, 0, 61, 89, 71, 1, 9, 82, 0, 0, 0, 91, 90, 83, 0, 0, 0, 0, 92, 92, -1, 29, 5, 1, 6, 2, 7, 2, 8, 3, 93, 84, 94, 85, 95, 86, 96, 87, 97, 88, 98, 88, 99, 88, 100, 88, 101, 1, 102, 1, 103, 89, 104, 2, 105, 5, 106, 90, 107, 2, 108, 91, 109, 5, 110, 3, 111, 3, 112, 92, 113, 93, 114, 93, 115, 1, 116, 3, 117, 94, 0 </int_array> + <int_array len="690"> -1, -1, 1, 0, -1, 1, 2, 0, 0, 0, 0, 4, 3, -1, 13, 5, 1, 6, 2, 7, 2, 8, 3, 9, 4, 10, 5, 11, 6, 12, 7, 13, 8, 14, 9, 15, 10, 16, 11, 2, 12, 0, 0, 0, 1, 17, -1, 1, 2, 13, 0, 2, 0, 19, 18, 14, 1, 9, 15, 0, 2, 0, 19, 20, 14, 1, 9, 16, 0, 2, 0, 19, 21, 14, 1, 9, 17, 0, 2, 0, 19, 22, 14, 1, 9, 18, 0, 2, 0, 19, 23, 14, 1, 9, 19, 0, 2, 0, 19, 24, 14, 1, 9, 20, 0, 2, 0, 19, 25, 14, 1, 9, 21, 0, 2, 0, 19, 26, 14, 1, 9, 22, 0, 2, 0, 19, 27, 14, 1, 9, 23, 0, 2, 0, 19, 28, 14, 1, 9, 24, 0, 2, 0, 19, 29, 14, 1, 9, 25, 0, 2, 0, 19, 30, 14, 1, 9, 26, 0, 2, 0, 19, 31, 14, 1, 9, 27, 0, 2, 0, 19, 32, 14, 1, 9, 28, 0, 2, 0, 19, 33, 14, 1, 9, 29, 0, 2, 0, 19, 34, 14, 1, 9, 30, 0, 2, 0, 19, 35, 14, 1, 9, 31, 0, 2, 0, 19, 36, 14, 1, 9, 32, 0, 2, 0, 19, 37, 14, 1, 9, 33, 0, 2, 0, 19, 38, 14, 1, 9, 34, 0, 2, 0, 19, 39, 14, 1, 9, 35, 0, 2, 0, 19, 40, 14, 1, 9, 36, 0, 2, 0, 19, 41, 14, 1, 9, 37, 0, 2, 0, 19, 42, 14, 1, 9, 38, 0, 2, 0, 19, 43, 14, 1, 9, 39, 0, 2, 0, 19, 44, 14, 1, 9, 40, 0, 2, 0, 19, 45, 14, 1, 9, 41, 0, 2, 0, 19, 46, 14, 1, 9, 42, 0, 2, 0, 19, 47, 14, 1, 9, 43, 0, 2, 0, 19, 48, 14, 1, 9, 44, 0, 2, 0, 19, 49, 14, 1, 9, 45, 0, 2, 0, 19, 50, 14, 1, 9, 46, 0, 2, 0, 19, 51, 14, 1, 9, 47, 0, 2, 0, 19, 52, 14, 1, 9, 48, 0, 2, 0, 19, 53, 14, 1, 9, 49, 0, 2, 0, 19, 54, 14, 1, 9, 50, 0, 2, 0, 19, 55, 14, 1, 9, 51, 0, 2, 0, 19, 56, 14, 1, 9, 52, 0, 2, 0, 19, 57, 14, 1, 9, 53, 0, 2, 0, 19, 58, 14, 1, 9, 54, 0, 2, 0, 19, 59, 14, 1, 9, 55, 0, 2, 0, 19, 60, 14, 1, 9, 56, 0, 0, 0, 62, 61, 57, 1, 9, 58, 0, 0, 0, 1, 63, -1, 0, 0, 46, 0, 65, 64, 59, 3, 9, 60, 66, 61, 67, 62, 0, 46, 0, 65, 68, 59, 3, 9, 63, 66, 64, 67, 65, 0, 46, 0, 65, 69, 59, 3, 9, 66, 66, 67, 67, 65, 0, 46, 0, 65, 70, 68, 1, 9, 69, 0, 0, 0, 72, 71, -1, 6, 73, 70, 74, 3, 75, 1, 76, 71, 77, 1, 78, 3, 0, 0, 0, 1, 79, -1, 0, 0, 52, 0, 62, 80, 72, 1, 9, 73, 0, 52, 0, 62, 81, 72, 1, 9, 74, 0, 52, 0, 62, 82, 72, 1, 9, 75, 0, 52, 0, 62, 83, 72, 1, 9, 76, 0, 52, 0, 62, 84, 72, 1, 9, 77, 0, 52, 0, 62, 85, 72, 1, 9, 78, 0, 52, 0, 62, 86, 72, 1, 9, 79, 0, 52, 0, 62, 87, 72, 1, 9, 80, 0, 52, 0, 62, 88, 72, 1, 9, 81, 0, 52, 0, 62, 89, 72, 1, 9, 82, 0, 52, 0, 62, 90, 72, 1, 9, 83, 0, 0, 0, 92, 91, 84, 0, 0, 0, 0, 93, 93, -1, 29, 5, 1, 6, 2, 7, 2, 8, 3, 94, 85, 95, 86, 96, 87, 97, 88, 98, 89, 99, 89, 100, 89, 101, 89, 102, 1, 103, 1, 104, 90, 105, 2, 106, 5, 107, 91, 108, 2, 109, 92, 110, 5, 111, 3, 112, 3, 113, 93, 114, 94, 115, 94, 116, 1, 117, 3, 118, 95, 0 </int_array> <string> "conns" </string> <int_array len="0"> </int_array> </dictionary> diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index 2fffbb823e..f43b43bd77 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -952,7 +952,11 @@ void RasterizerGLES2::texture_set_flags(RID p_texture,uint32_t p_flags) { Texture *texture = texture_owner.get( p_texture ); ERR_FAIL_COND(!texture); - ERR_FAIL_COND(texture->render_target); + if (texture->render_target) { + + p_flags&=VS::TEXTURE_FLAG_FILTER;//can change only filter + } + glActiveTexture(GL_TEXTURE0); glBindTexture(texture->target, texture->tex_id); @@ -5180,6 +5184,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans + bool stores_glow = !shadow && (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) && !p_alpha_pass; bool prev_blend=false; glDisable(GL_BLEND); @@ -5200,7 +5205,6 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans if (!shadow) { if (texscreen_used && !texscreen_copied && material->shader_cache && material->shader_cache->valid && material->shader_cache->has_texscreen) { - texscreen_copied=true; _copy_to_texscreen(); @@ -5247,11 +5251,15 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans if (!*e->additive_ptr) { additive=false; - *e->additive_ptr=true; + *e->additive_ptr=true; } else { additive=true; } + if (stores_glow) + material_shader.set_conditional(MaterialShaderGLES2::USE_GLOW,!additive); + + bool desired_blend=false; VS::MaterialBlendMode desired_blend_mode=VS::MATERIAL_BLEND_MODE_MIX; @@ -5894,7 +5902,7 @@ void RasterizerGLES2::end_scene() { glDisable(GL_BLEND); current_blend_mode=VS::MATERIAL_BLEND_MODE_MIX; - material_shader.set_conditional(MaterialShaderGLES2::USE_GLOW,current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]); + //material_shader.set_conditional(MaterialShaderGLES2::USE_GLOW,current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]); opaque_render_list.sort_mat_light_type_flags(); _render_list_forward(&opaque_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting); @@ -5950,12 +5958,15 @@ void RasterizerGLES2::end_scene() { glBindFramebuffer(GL_FRAMEBUFFER, current_rt?current_rt->fbo:base_framebuffer); + Size2 size; if (current_rt) { glBindFramebuffer(GL_FRAMEBUFFER, current_rt->fbo); glViewport( 0,0,viewport.width,viewport.height); + size=Size2(viewport.width,viewport.height); } else { glBindFramebuffer(GL_FRAMEBUFFER, base_framebuffer); glViewport( viewport.x, window_size.height-(viewport.height+viewport.y), viewport.width,viewport.height ); + size=Size2(viewport.width,viewport.height); } //time to copy!!! @@ -5964,6 +5975,7 @@ void RasterizerGLES2::end_scene() { copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW,current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]); copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,current_env && current_env->fx_enabled[VS::ENV_FX_HDR]); copy_shader.set_conditional(CopyShaderGLES2::USE_NO_ALPHA,true); + copy_shader.set_conditional(CopyShaderGLES2::USE_FXAA,current_env && current_env->fx_enabled[VS::ENV_FX_FXAA]); copy_shader.bind(); //copy_shader.set_uniform(CopyShaderGLES2::SOURCE,0); @@ -5985,6 +5997,9 @@ void RasterizerGLES2::end_scene() { } + if (current_env && current_env->fx_enabled[VS::ENV_FX_FXAA]) + copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,Size2(1.0/size.x,1.0/size.y)); + if (current_env && current_env->fx_enabled[VS::ENV_FX_BCS]) { @@ -6008,6 +6023,7 @@ void RasterizerGLES2::end_scene() { copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW,false); copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,false); copy_shader.set_conditional(CopyShaderGLES2::USE_NO_ALPHA,false); + copy_shader.set_conditional(CopyShaderGLES2::USE_FXAA,false); material_shader.set_conditional(MaterialShaderGLES2::USE_HDR,false); diff --git a/drivers/gles2/shaders/copy.glsl b/drivers/gles2/shaders/copy.glsl index d4b0c31b7d..bea651bceb 100644 --- a/drivers/gles2/shaders/copy.glsl +++ b/drivers/gles2/shaders/copy.glsl @@ -110,6 +110,11 @@ uniform sampler2D source_vd_lum; #endif +//endif +#elif defined(USE_FXAA) + +uniform vec2 pixel_size; + #endif #ifdef USE_ENERGY @@ -129,6 +134,55 @@ void main() { vec4 color = texture2D( source, uv_interp ); #endif + +#ifdef USE_FXAA + +#define FXAA_REDUCE_MIN (1.0/ 128.0) +#define FXAA_REDUCE_MUL (1.0 / 8.0) +#define FXAA_SPAN_MAX 8.0 + + { + vec3 rgbNW = texture2D(source, uv_interp + vec2(-1.0, -1.0) * pixel_size).xyz; + vec3 rgbNE = texture2D(source, uv_interp + vec2(1.0, -1.0) * pixel_size).xyz; + vec3 rgbSW = texture2D(source, uv_interp + vec2(-1.0, 1.0) * pixel_size).xyz; + vec3 rgbSE = texture2D(source, uv_interp + vec2(1.0, 1.0) * pixel_size).xyz; + vec3 rgbM = color.rgb; + vec3 luma = vec3(0.299, 0.587, 0.114); + float lumaNW = dot(rgbNW, luma); + float lumaNE = dot(rgbNE, luma); + float lumaSW = dot(rgbSW, luma); + float lumaSE = dot(rgbSE, luma); + float lumaM = dot(rgbM, luma); + float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); + float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); + + vec2 dir; + dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); + dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); + + float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * + (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); + + float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce); + dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), + max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), + dir * rcpDirMin)) * pixel_size; + + vec3 rgbA = 0.5 * ( + texture2D(source, uv_interp + dir * (1.0 / 3.0 - 0.5)).xyz + + texture2D(source, uv_interp + dir * (2.0 / 3.0 - 0.5)).xyz); + vec3 rgbB = rgbA * 0.5 + 0.25 * ( + texture2D(source, uv_interp + dir * -0.5).xyz + + texture2D(source, uv_interp + dir * 0.5).xyz); + + float lumaB = dot(rgbB, luma); + if ((lumaB < lumaMin) || (lumaB > lumaMax)) + color.rgb = rgbA; + else + color.rgb = rgbB; + } + +#endif //color.rg=uv_interp; #ifdef USE_BCS @@ -195,7 +249,16 @@ void main() { vec4 glow = texture2D( glow_source, uv2_interp ); +#if 1 +//ifdef USE_GLOW_SCREEN + + color.rgb = clamp((color.rgb + glow.rgb) - (color.rgb * glow.rgb), 0.0, 1.0); + +#else color.rgb+=glow.rgb; +#endif + + #endif diff --git a/drivers/openssl/stream_peer_openssl.cpp b/drivers/openssl/stream_peer_openssl.cpp index 0151ced3b8..ef07f11334 100644 --- a/drivers/openssl/stream_peer_openssl.cpp +++ b/drivers/openssl/stream_peer_openssl.cpp @@ -362,6 +362,7 @@ Error StreamPeerOpenSSL::connect(Ref<StreamPeer> p_base, bool p_validate_certs, print_line("CONNECTION RESULT: "+itos(result)); if (result<1) { + ERR_print_errors_fp(stdout); _print_error(result); } diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp index 65b10399f8..c6183aadc4 100644 --- a/modules/gdscript/gd_script.cpp +++ b/modules/gdscript/gd_script.cpp @@ -2153,6 +2153,7 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const { "and", "or", "export", + "assert", 0}; diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 3a101515da..5bc433e85f 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -676,7 +676,7 @@ String OS_Android::get_unique_ID() const { return OS::get_unique_ID(); } -Error OS_Android::native_video_play(String p_path) { +Error OS_Android::native_video_play(String p_path, float p_volume) { if (video_play_func) video_play_func(p_path); return OK; @@ -719,6 +719,11 @@ OS_Android::OS_Android(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, OpenURIFu get_locale_func=p_get_locale_func; get_model_func=p_get_model_func; get_unique_id_func=p_get_unique_id; + + video_play_func = p_video_play_func; + video_is_playing_func = p_video_is_playing_func; + video_pause_func = p_video_pause_func; + video_stop_func = p_video_stop_func; show_virtual_keyboard_func = p_show_vk; hide_virtual_keyboard_func = p_hide_vk; diff --git a/platform/android/os_android.h b/platform/android/os_android.h index 76139c8a2d..e6d0f7eded 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -208,7 +208,7 @@ public: void process_event(InputEvent p_event); void init_video_mode(int p_video_width,int p_video_height); - virtual Error native_video_play(String p_path); + virtual Error native_video_play(String p_path, float p_volume); virtual bool native_video_is_playing(); virtual void native_video_pause(); virtual void native_video_stop(); diff --git a/platform/iphone/app_delegate.mm b/platform/iphone/app_delegate.mm index 56cb73ba7b..c5ac5d9263 100644 --- a/platform/iphone/app_delegate.mm +++ b/platform/iphone/app_delegate.mm @@ -165,6 +165,7 @@ static int frame_count = 0; - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { printf("****************** did receive memory warning!\n"); + OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_OS_MEMORY_WARNING); }; - (void)applicationDidFinishLaunching:(UIApplication*)application { diff --git a/platform/iphone/gl_view.mm b/platform/iphone/gl_view.mm index 402c755094..c482c36a30 100755 --- a/platform/iphone/gl_view.mm +++ b/platform/iphone/gl_view.mm @@ -32,6 +32,7 @@ #include "os_iphone.h" #include "core/os/keyboard.h" #include "core/globals.h" +#include "servers/audio_server.h" #import "gl_view.h" @@ -48,6 +49,9 @@ int gl_view_base_fb; static String keyboard_text; static GLView* _instance = NULL; +static bool video_found_error = false; +static float video_previous_volume = 0.0f; + void _show_keyboard(String p_existing) { keyboard_text = p_existing; printf("instance on show is %p\n", _instance); @@ -60,8 +64,13 @@ void _hide_keyboard() { keyboard_text = ""; }; -bool _play_video(String p_path) { +bool _play_video(String p_path, float p_volume) { + float player_volume = p_volume * AudioServer::get_singleton()->get_singleton()->get_stream_global_volume_scale(); + video_previous_volume = [[MPMusicPlayerController applicationMusicPlayer] volume]; + + [[MPMusicPlayerController applicationMusicPlayer] setVolume: player_volume]; + p_path = Globals::get_singleton()->globalize_path(p_path); NSString* file_path = [[[NSString alloc] initWithUTF8String:p_path.utf8().get_data()] autorelease]; @@ -87,6 +96,8 @@ bool _play_video(String p_path) { bool _is_video_playing() { //NSInteger playback_state = _instance.moviePlayerController.playbackState; + if (video_found_error) + return false; return (_instance.moviePlayerController.playbackState == MPMoviePlaybackStatePlaying); } @@ -97,6 +108,7 @@ void _pause_video() { void _stop_video() { [_instance.moviePlayerController stop]; [_instance.moviePlayerController.view removeFromSuperview]; + [[MPMusicPlayerController applicationMusicPlayer] setVolume: video_previous_volume]; } @implementation GLView @@ -506,13 +518,37 @@ static void clear_touches() { } - (void)moviePlayBackDidFinish:(NSNotification*)notification { + + + NSNumber* reason = [[notification userInfo] objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey]; + switch ([reason intValue]) { + case MPMovieFinishReasonPlaybackEnded: + //NSLog(@"Playback Ended"); + break; + case MPMovieFinishReasonPlaybackError: + //NSLog(@"Playback Error"); + video_found_error = true; + break; + case MPMovieFinishReasonUserExited: + //NSLog(@"User Exited"); + video_found_error = true; + break; + default: + //NSLog(@"Unsupported reason!"); + break; + } + MPMoviePlayerController *player = [notification object]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:player]; + [_instance.moviePlayerController stop]; [_instance.moviePlayerController.view removeFromSuperview]; + + [[MPMusicPlayerController applicationMusicPlayer] setVolume: video_previous_volume]; } @end diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp index 756e8b575e..2ef732183b 100644 --- a/platform/iphone/os_iphone.cpp +++ b/platform/iphone/os_iphone.cpp @@ -485,13 +485,13 @@ String OSIPhone::get_locale() const { return locale_code; } -extern bool _play_video(String p_path); +extern bool _play_video(String p_path, float p_volume); extern bool _is_video_playing(); extern void _pause_video(); extern void _stop_video(); -Error OSIPhone::native_video_play(String p_path) { - if ( _play_video(p_path) ) +Error OSIPhone::native_video_play(String p_path, float p_volume) { + if ( _play_video(p_path, p_volume) ) return OK; return FAILED; } diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h index 643bf2b5e3..14b46816e9 100644 --- a/platform/iphone/os_iphone.h +++ b/platform/iphone/os_iphone.h @@ -184,7 +184,7 @@ public: void set_unique_ID(String p_ID); String get_unique_ID() const; - virtual Error native_video_play(String p_path); + virtual Error native_video_play(String p_path, float p_volume); virtual bool native_video_is_playing() const; virtual void native_video_pause(); virtual void native_video_stop(); diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index a2bee43e58..85adfbbbde 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -224,6 +224,30 @@ Rect2 Node2D::get_item_rect() const { return Rect2(Point2(-32,-32),Size2(64,64)); } +void Node2D::rotate(float p_degrees) { + + set_rot( get_rot() + p_degrees); +} + +void Node2D::move_x(float p_delta,bool p_scaled){ + + Matrix32 t = get_transform(); + Vector2 m = t[0]; + if (!p_scaled) + m.normalize(); + set_pos(t[2]+m*p_delta); +} + +void Node2D::move_y(float p_delta,bool p_scaled){ + + Matrix32 t = get_transform(); + Vector2 m = t[1]; + if (!p_scaled) + m.normalize(); + set_pos(t[2]+m*p_delta); +} + + Point2 Node2D::get_global_pos() const { return get_global_transform().get_origin(); @@ -268,6 +292,10 @@ void Node2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_rot"),&Node2D::get_rot); ObjectTypeDB::bind_method(_MD("get_scale"),&Node2D::get_scale); + ObjectTypeDB::bind_method(_MD("rotate","degrees"),&Node2D::rotate); + ObjectTypeDB::bind_method(_MD("move_local_x","delta","scaled"),&Node2D::move_x,DEFVAL(false)); + ObjectTypeDB::bind_method(_MD("move_local_y","delta","scaled"),&Node2D::move_y,DEFVAL(false)); + ObjectTypeDB::bind_method(_MD("get_global_pos"),&Node2D::get_global_pos); ObjectTypeDB::bind_method(_MD("set_transform","xform"),&Node2D::set_transform); diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h index 8da441dc63..8e1f22c235 100644 --- a/scene/2d/node_2d.h +++ b/scene/2d/node_2d.h @@ -70,6 +70,10 @@ public: void set_rot(float p_angle); void set_scale(const Size2& p_scale); + void rotate(float p_degrees); + void move_x(float p_delta,bool p_scaled=false); + void move_y(float p_delta,bool p_scaled=false); + Point2 get_pos() const; float get_rot() const; Size2 get_scale() const; diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index a1e7195b0a..ecd147afde 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -43,9 +43,27 @@ void PhysicsBody2D::_notification(int p_what) { */ } -PhysicsBody2D::PhysicsBody2D(Physics2DServer::BodyMode p_mode) : CollisionObject2D( Physics2DServer::get_singleton()->body_create(p_mode), false) { +void PhysicsBody2D::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_layer_mask","mask"),&PhysicsBody2D::set_layer_mask); + ObjectTypeDB::bind_method(_MD("get_layer_mask"),&PhysicsBody2D::get_layer_mask); + ADD_PROPERTY(PropertyInfo(Variant::INT,"layers",PROPERTY_HINT_ALL_FLAGS),_SCS("set_layer_mask"),_SCS("get_layer_mask")); +} + +void PhysicsBody2D::set_layer_mask(uint32_t p_mask) { + + mask=p_mask; + Physics2DServer::get_singleton()->body_set_layer_mask(get_rid(),p_mask); +} + +uint32_t PhysicsBody2D::get_layer_mask() const { + return mask; +} + +PhysicsBody2D::PhysicsBody2D(Physics2DServer::BodyMode p_mode) : CollisionObject2D( Physics2DServer::get_singleton()->body_create(p_mode), false) { + mask=1; } @@ -789,7 +807,7 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { for(int i=0;i<get_shape_count();i++) { - if (dss->collide_shape(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i),Vector2(),margin,sr,max_shapes,res_shapes,exclude,0,mask)) + if (dss->collide_shape(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i),Vector2(),margin,sr,max_shapes,res_shapes,exclude,get_layer_mask(),mask)) collided=true; } @@ -834,7 +852,7 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { float lsafe,lunsafe; - bool valid = dss->cast_motion(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i), p_motion, 0,lsafe,lunsafe,exclude,0,mask); + bool valid = dss->cast_motion(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i), p_motion, 0,lsafe,lunsafe,exclude,get_layer_mask(),mask); //print_line("shape: "+itos(i)+" travel:"+rtos(ltravel)); if (!valid) { safe=0; @@ -865,7 +883,7 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { Matrix32 ugt = get_global_transform(); ugt.elements[2]+=p_motion*unsafe; Physics2DDirectSpaceState::ShapeRestInfo rest_info; - bool c2 = dss->rest_info(get_shape(best_shape)->get_rid(), ugt*get_shape_transform(best_shape), Vector2(), margin,&rest_info,exclude,0,mask); + bool c2 = dss->rest_info(get_shape(best_shape)->get_rid(), ugt*get_shape_transform(best_shape), Vector2(), margin,&rest_info,exclude,get_layer_mask(),mask); if (!c2) { //should not happen, but floating point precision is so weird.. colliding=false; @@ -927,7 +945,7 @@ bool KinematicBody2D::can_move_to(const Vector2& p_position, bool p_discrete) { for(int i=0;i<get_shape_count();i++) { - bool col = dss->intersect_shape(get_shape(i)->get_rid(), xform * get_shape_transform(i),motion,0,NULL,0,exclude,0,mask); + bool col = dss->intersect_shape(get_shape(i)->get_rid(), xform * get_shape_transform(i),motion,0,NULL,0,exclude,get_layer_mask(),mask); if (col) return false; } diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index e7b65b1ef3..1319d2e4f0 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -38,12 +38,18 @@ class PhysicsBody2D : public CollisionObject2D { OBJ_TYPE(PhysicsBody2D,CollisionObject2D); + uint32_t mask; protected: void _notification(int p_what); PhysicsBody2D(Physics2DServer::BodyMode p_mode); + + static void _bind_methods(); public: + void set_layer_mask(uint32_t p_mask); + uint32_t get_layer_mask() const; + PhysicsBody2D(); }; diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp index 540c825485..8479338521 100644 --- a/scene/2d/ray_cast_2d.cpp +++ b/scene/2d/ray_cast_2d.cpp @@ -43,6 +43,16 @@ Vector2 RayCast2D::get_cast_to() const{ return cast_to; } +void RayCast2D::set_layer_mask(uint32_t p_mask) { + + layer_mask=p_mask; +} + +uint32_t RayCast2D::get_layer_mask() const { + + return layer_mask; +} + bool RayCast2D::is_colliding() const{ return collided; @@ -152,7 +162,7 @@ void RayCast2D::_notification(int p_what) { Physics2DDirectSpaceState::RayResult rr; - if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr,exclude)) { + if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr,exclude,layer_mask)) { collided=true; against=rr.collider_id; @@ -228,8 +238,12 @@ void RayCast2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("clear_exceptions"),&RayCast2D::clear_exceptions); + ObjectTypeDB::bind_method(_MD("set_layer_mask","mask"),&RayCast2D::set_layer_mask); + ObjectTypeDB::bind_method(_MD("get_layer_mask"),&RayCast2D::get_layer_mask); + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled")); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"cast_to"),_SCS("set_cast_to"),_SCS("get_cast_to")); + ADD_PROPERTY(PropertyInfo(Variant::INT,"layer_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_layer_mask"),_SCS("get_layer_mask")); } RayCast2D::RayCast2D() { @@ -238,5 +252,6 @@ RayCast2D::RayCast2D() { against=0; collided=false; against_shape=0; + layer_mask=1; cast_to=Vector2(0,50); } diff --git a/scene/2d/ray_cast_2d.h b/scene/2d/ray_cast_2d.h index 32b95fbefe..b27fc4bf3d 100644 --- a/scene/2d/ray_cast_2d.h +++ b/scene/2d/ray_cast_2d.h @@ -43,6 +43,7 @@ class RayCast2D : public Node2D { Vector2 collision_point; Vector2 collision_normal; Set<RID> exclude; + uint32_t layer_mask; Vector2 cast_to; @@ -58,6 +59,9 @@ public: void set_cast_to(const Vector2& p_point); Vector2 get_cast_to() const; + void set_layer_mask(uint32_t p_mask); + uint32_t get_layer_mask() const; + bool is_colliding() const; Object *get_collider() const; int get_collider_shape() const; diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index c8711f10ac..6fe8b8c4c2 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -315,6 +315,7 @@ Map<TileMap::PosKey,TileMap::Quadrant>::Element *TileMap::_create_quadrant(const VisualServer::get_singleton()->canvas_item_set_parent( q.canvas_item, get_canvas_item() ); VisualServer::get_singleton()->canvas_item_set_transform( q.canvas_item, xform ); q.static_body=Physics2DServer::get_singleton()->body_create(Physics2DServer::BODY_MODE_STATIC); + Physics2DServer::get_singleton()->body_set_layer_mask(q.static_body,collision_layer); if (is_inside_scene()) { xform = get_global_transform() * xform; RID space = get_world_2d()->get_space(); @@ -545,6 +546,22 @@ Rect2 TileMap::get_item_rect() const { return rect_cache; } +void TileMap::set_collision_layer_mask(uint32_t p_layer) { + + collision_layer=p_layer; + for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) { + + Quadrant &q=E->get(); + Physics2DServer::get_singleton()->body_set_layer_mask(q.static_body,collision_layer); + } +} + +uint32_t TileMap::get_collision_layer_mask() const { + + return collision_layer; +} + + void TileMap::_bind_methods() { @@ -564,6 +581,8 @@ void TileMap::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_center_y","enable"),&TileMap::set_center_y); ObjectTypeDB::bind_method(_MD("get_center_y"),&TileMap::get_center_y); + ObjectTypeDB::bind_method(_MD("set_collision_layer_mask","mask"),&TileMap::set_collision_layer_mask); + ObjectTypeDB::bind_method(_MD("get_collision_layer_mask"),&TileMap::get_collision_layer_mask); ObjectTypeDB::bind_method(_MD("set_cell","x","y","tile","flip_x","flip_y"),&TileMap::set_cell,DEFVAL(false),DEFVAL(false)); ObjectTypeDB::bind_method(_MD("get_cell","x","y"),&TileMap::get_cell); @@ -583,6 +602,7 @@ void TileMap::_bind_methods() { 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::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,"collision_layers",PROPERTY_HINT_ALL_FLAGS),_SCS("set_collision_layer_mask"),_SCS("get_collision_layer_mask")); ADD_SIGNAL(MethodInfo("settings_changed")); @@ -599,6 +619,7 @@ TileMap::TileMap() { cell_size=64; center_x=false; center_y=false; + collision_layer=1; fp_adjust=0.01; fp_adjust=0.01; diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index a2414382c6..9265a7b55e 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -98,6 +98,7 @@ class TileMap : public Node2D { Rect2 rect_cache; bool rect_cache_dirty; float fp_adjust; + uint32_t collision_layer; Map<PosKey,Quadrant>::Element *_create_quadrant(const PosKey& p_qk); @@ -145,6 +146,9 @@ public: Rect2 get_item_rect() const; + void set_collision_layer_mask(uint32_t p_layer); + uint32_t get_collision_layer_mask() const; + void clear(); TileMap(); diff --git a/scene/3d/baked_light.cpp b/scene/3d/baked_light.cpp new file mode 100644 index 0000000000..55832b7c18 --- /dev/null +++ b/scene/3d/baked_light.cpp @@ -0,0 +1,7 @@ +#include "baked_light.h" +#include "mesh_instance.h" + +BakedLight::BakedLight() { + + +} diff --git a/scene/3d/baked_light.h b/scene/3d/baked_light.h new file mode 100644 index 0000000000..a6f997afe9 --- /dev/null +++ b/scene/3d/baked_light.h @@ -0,0 +1,15 @@ +#ifndef BAKED_LIGHT_H +#define BAKED_LIGHT_H + +#include "scene/3d/spatial.h" +class BakedLightBaker; + + +class BakedLight : public Spatial { + OBJ_TYPE(BakedLight,Spatial); + +public: + BakedLight(); +}; + +#endif // BAKED_LIGHT_H diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 0733a9196e..2a1a5972a9 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -632,6 +632,16 @@ bool RigidBody::is_contact_monitor_enabled() const { return contact_monitor!=NULL; } +void RigidBody::set_axis_lock(AxisLock p_lock) { + + axis_lock=p_lock; + PhysicsServer::get_singleton()->body_set_axis_lock(get_rid(),PhysicsServer::BodyAxisLock(axis_lock)); +} + +RigidBody::AxisLock RigidBody::get_axis_lock() const { + + return axis_lock; +} void RigidBody::_bind_methods() { @@ -682,6 +692,9 @@ void RigidBody::_bind_methods() { ObjectTypeDB::bind_method(_MD("_body_enter_scene"),&RigidBody::_body_enter_scene); ObjectTypeDB::bind_method(_MD("_body_exit_scene"),&RigidBody::_body_exit_scene); + ObjectTypeDB::bind_method(_MD("set_axis_lock","axis_lock"),&RigidBody::set_axis_lock); + ObjectTypeDB::bind_method(_MD("get_axis_lock"),&RigidBody::get_axis_lock); + BIND_VMETHOD(MethodInfo("_integrate_forces",PropertyInfo(Variant::OBJECT,"state:PhysicsDirectBodyState"))); ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Rigid,Static,Character,Kinematic"),_SCS("set_mode"),_SCS("get_mode")); @@ -695,6 +708,7 @@ void RigidBody::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::BOOL,"contact_monitor"),_SCS("set_contact_monitor"),_SCS("is_contact_monitor_enabled")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"active"),_SCS("set_active"),_SCS("is_active")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"can_sleep"),_SCS("set_can_sleep"),_SCS("is_able_to_sleep")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"axis_lock",PROPERTY_HINT_ENUM,"Disabled,Lock X,Lock Y,Lock Z"),_SCS("set_axis_lock"),_SCS("get_axis_lock")); ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"velocity/linear"),_SCS("set_linear_velocity"),_SCS("get_linear_velocity")); ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"velocity/angular"),_SCS("set_angular_velocity"),_SCS("get_angular_velocity")); @@ -727,6 +741,8 @@ RigidBody::RigidBody() : PhysicsBody(PhysicsServer::BODY_MODE_RIGID) { contact_monitor=NULL; can_sleep=true; + axis_lock = AXIS_LOCK_DISABLED; + PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(),this,"_direct_state_changed"); } diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index a5faa9857b..6695ee719a 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -94,6 +94,14 @@ public: MODE_CHARACTER, MODE_KINEMATIC, }; + + enum AxisLock { + AXIS_LOCK_DISABLED, + AXIS_LOCK_X, + AXIS_LOCK_Y, + AXIS_LOCK_Z, + }; + private: bool can_sleep; @@ -109,6 +117,8 @@ private: bool active; bool ccd; + AxisLock axis_lock; + int max_contacts_reported; @@ -208,6 +218,10 @@ public: void set_use_continuous_collision_detection(bool p_enable); bool is_using_continuous_collision_detection() const; + void set_axis_lock(AxisLock p_lock); + AxisLock get_axis_lock() const; + + void apply_impulse(const Vector3& p_pos, const Vector3& p_impulse); RigidBody(); @@ -216,4 +230,5 @@ public: }; VARIANT_ENUM_CAST(RigidBody::Mode); +VARIANT_ENUM_CAST(RigidBody::AxisLock); #endif // PHYSICS_BODY__H diff --git a/scene/3d/visual_instance.h b/scene/3d/visual_instance.h index 4e652912c6..afb9ed70f8 100644 --- a/scene/3d/visual_instance.h +++ b/scene/3d/visual_instance.h @@ -91,6 +91,7 @@ public: FLAG_BILLBOARD_FIX_Y=VS::INSTANCE_FLAG_BILLBOARD_FIX_Y, FLAG_DEPH_SCALE=VS::INSTANCE_FLAG_DEPH_SCALE, FLAG_VISIBLE_IN_ALL_ROOMS=VS::INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS, + FLAG_USE_BAKED_LIGHT_VOLUME=VS::INSTANCE_FLAG_USE_BAKED_LIGHT_VOLUME, FLAG_MAX=VS::INSTANCE_FLAG_MAX, }; diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index c659447c23..15d3dccb71 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -907,8 +907,8 @@ void AnimationPlayer::play(const StringName& p_name, float p_custom_blend, float } } - c.current.pos=p_from_end ? c.current.from->animation->get_length() : 0; c.current.from=&animation_set[name]; + c.current.pos=p_from_end ? c.current.from->animation->get_length() : 0; c.current.speed_scale=p_custom_scale; c.assigned=p_name; diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 5ac278a38e..241d66fce4 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -1512,6 +1512,10 @@ void RichTextLabel::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_selection_enabled","enabled"),&RichTextLabel::set_selection_enabled); ObjectTypeDB::bind_method(_MD("is_selection_enabled"),&RichTextLabel::is_selection_enabled); + ObjectTypeDB::bind_method(_MD("parse_bbcode", "bbcode"),&RichTextLabel::parse_bbcode); + ObjectTypeDB::bind_method(_MD("append_bbcode", "bbcode"),&RichTextLabel::append_bbcode); + + ADD_SIGNAL( MethodInfo("meta_clicked",PropertyInfo(Variant::NIL,"meta"))); BIND_CONSTANT( ALIGN_LEFT ); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 0bbc2dc695..91769bbb82 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -728,6 +728,7 @@ void Viewport::set_as_render_target(bool p_enable){ render_target_texture_rid=RID(); } + render_target_texture->set_flags(render_target_texture->flags); render_target_texture->emit_changed(); } @@ -773,6 +774,18 @@ bool Viewport::get_render_target_vflip() const{ } +void Viewport::set_render_target_filter(bool p_enable) { + + render_target_texture->set_flags(p_enable?int(Texture::FLAG_FILTER):int(0)); + +} + +bool Viewport::get_render_target_filter() const{ + + return (render_target_texture->get_flags()&Texture::FLAG_FILTER)!=0; +} + + Matrix32 Viewport::_get_input_pre_xform() const { Matrix32 pre_xf; @@ -990,6 +1003,9 @@ void Viewport::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_render_target_vflip","enable"), &Viewport::set_render_target_vflip); ObjectTypeDB::bind_method(_MD("get_render_target_vflip"), &Viewport::get_render_target_vflip); + ObjectTypeDB::bind_method(_MD("set_render_target_filter","enable"), &Viewport::set_render_target_filter); + ObjectTypeDB::bind_method(_MD("get_render_target_filter"), &Viewport::get_render_target_filter); + ObjectTypeDB::bind_method(_MD("set_render_target_update_mode","mode"), &Viewport::set_render_target_update_mode); ObjectTypeDB::bind_method(_MD("get_render_target_update_mode"), &Viewport::get_render_target_update_mode); @@ -1020,6 +1036,7 @@ void Viewport::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transparent_bg"), _SCS("set_transparent_background"), _SCS("has_transparent_background") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/enabled"), _SCS("set_as_render_target"), _SCS("is_set_as_render_target") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/v_flip"), _SCS("set_render_target_vflip"), _SCS("get_render_target_vflip") ); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/filter"), _SCS("set_render_target_filter"), _SCS("get_render_target_filter") ); ADD_PROPERTY( PropertyInfo(Variant::INT,"render_target/update_mode",PROPERTY_HINT_ENUM,"Disabled,Once,When Visible,Always"), _SCS("set_render_target_update_mode"), _SCS("get_render_target_update_mode") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"audio_listener/enable_2d"), _SCS("set_as_audio_listener_2d"), _SCS("is_audio_listener_2d") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"audio_listener/enable_3d"), _SCS("set_as_audio_listener"), _SCS("is_audio_listener") ); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index cc7f93cfa3..d54b489843 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -113,6 +113,7 @@ friend class RenderTargetTexture; bool transparent_bg; bool render_target_vflip; + bool render_target_filter; void _update_rect(); @@ -210,6 +211,9 @@ public: void set_render_target_vflip(bool p_enable); bool get_render_target_vflip() const; + void set_render_target_filter(bool p_enable); + bool get_render_target_filter() const; + void set_render_target_update_mode(RenderTargetUpdateMode p_mode); RenderTargetUpdateMode get_render_target_update_mode() const; Ref<RenderTargetTexture> get_render_target_texture() const; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 8fd39b0d74..b30ad2d71f 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -187,6 +187,7 @@ #include "scene/3d/area.h" #include "scene/3d/physics_joint.h" #include "scene/3d/multimesh_instance.h" +#include "scene/3d/baked_light.h" #include "scene/3d/ray_cast.h" #include "scene/3d/spatial_sample_player.h" #include "scene/3d/spatial_stream_player.h" @@ -401,7 +402,7 @@ void register_scene_types() { ObjectTypeDB::register_type<PathFollow>(); ObjectTypeDB::register_type<VisibilityNotifier>(); ObjectTypeDB::register_type<VisibilityEnabler>(); - + ObjectTypeDB::register_type<BakedLight>(); ObjectTypeDB::register_type<WorldEnvironment>(); //scenariofx diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index 3e12c7a5b5..0c55d22dbe 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -101,6 +101,8 @@ void Environment::_bind_methods() { ObjectTypeDB::bind_method(_MD("fx_set_param","param","value"),&Environment::fx_set_param); ObjectTypeDB::bind_method(_MD("fx_get_param","param"),&Environment::fx_get_param); + ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"fxaa/enabled"),_SCS("set_enable_fx"),_SCS("is_fx_enabled"), FX_FXAA); + ADD_PROPERTY( PropertyInfo(Variant::INT,"background/mode",PROPERTY_HINT_ENUM,"Keep,Default Color,Color,Texture,Cubemap,Texture RGBE,Cubemap RGBE"),_SCS("set_background"),_SCS("get_background")); ADD_PROPERTYI( PropertyInfo(Variant::COLOR,"background/color"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_COLOR); ADD_PROPERTYI( PropertyInfo(Variant::OBJECT,"background/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_TEXTURE); @@ -181,6 +183,7 @@ void Environment::_bind_methods() { BIND_CONSTANT( BG_PARAM_MAX ); + BIND_CONSTANT( FX_FXAA ); BIND_CONSTANT( FX_GLOW ); BIND_CONSTANT( FX_DOF_BLUR ); BIND_CONSTANT( FX_HDR ); diff --git a/scene/resources/environment.h b/scene/resources/environment.h index c94c81b694..b90a043634 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -60,6 +60,7 @@ public: }; enum Fx { + FX_FXAA=VS::ENV_FX_FXAA, FX_GLOW=VS::ENV_FX_GLOW, FX_DOF_BLUR=VS::ENV_FX_DOF_BLUR, FX_HDR=VS::ENV_FX_HDR, diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 6d0a1cf76b..c6e492fcb3 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -92,10 +92,17 @@ bool Mesh::_set(const StringName& p_name, const Variant& p_value) { return true; } - if (sname.begins_with("materials/")) { - - int idx=sname.get_slice("/",1).to_int()-1; - surface_set_material(idx,p_value); + if (sname.begins_with("surface_")) { + + int sl=sname.find("/"); + if (sl==-1) + return false; + int idx=sname.substr(8,sl-8).to_int()-1; + String what = sname.get_slice("/",1); + if (what=="material") + surface_set_material(idx,p_value); + else if (what=="name") + surface_set_name(idx,p_value); return true; } @@ -166,10 +173,17 @@ bool Mesh::_get(const StringName& p_name,Variant &r_ret) const { r_ret = get_morph_target_mode(); return true; - } else if (sname.begins_with("materials/")) { - - int idx=sname.get_slice("/",1).to_int()-1; - r_ret=surface_get_material(idx); + } else if (sname.begins_with("surface_")) { + + int sl=sname.find("/"); + if (sl==-1) + return false; + int idx=sname.substr(8,sl-8).to_int()-1; + String what = sname.get_slice("/",1); + if (what=="material") + r_ret=surface_get_material(idx); + else if (what=="name") + r_ret=surface_get_name(idx); return true; } else if (sname=="custom_aabb/custom_aabb") { @@ -210,7 +224,8 @@ void Mesh::_get_property_list( List<PropertyInfo> *p_list) const { for (int i=0;i<surfaces.size();i++) { p_list->push_back( PropertyInfo( Variant::DICTIONARY,"surfaces/"+itos(i), PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR ) ); - p_list->push_back( PropertyInfo( Variant::OBJECT,"materials/"+itos(i+1), PROPERTY_HINT_RESOURCE_TYPE,"Material",PROPERTY_USAGE_EDITOR ) ); + p_list->push_back( PropertyInfo( Variant::STRING,"surface_"+itos(i+1)+"/name", PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR ) ); + p_list->push_back( PropertyInfo( Variant::OBJECT,"surface_"+itos(i+1)+"/material", PROPERTY_HINT_RESOURCE_TYPE,"Material",PROPERTY_USAGE_EDITOR ) ); } p_list->push_back( PropertyInfo( Variant::_AABB,"custom_aabb/custom_aabb" ) ); diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index d0c159e9f0..2856101674 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -32,57 +32,56 @@ #define EQ_VERTEX_DIST 0.00001 +bool SurfaceTool::Vertex::operator==(const Vertex& p_b) const { -bool SurfaceTool::compare(const Vertex& p_a,const Vertex& p_b) const { - if (p_a.vertex.distance_to(p_b.vertex)>EQ_VERTEX_DIST) + if (vertex!=p_b.vertex) return false; - if (format&Mesh::ARRAY_FORMAT_TEX_UV) { + if (uv!=p_b.uv) + return false; - if (p_a.uv.distance_to(p_b.uv)>EQ_VERTEX_DIST) - return false; - } + if (uv2!=p_b.uv2) + return false; - if (format&Mesh::ARRAY_FORMAT_TEX_UV2) { + if (normal!=p_b.normal) + return false; - if (p_a.uv2.distance_to(p_b.uv2)>EQ_VERTEX_DIST) - return false; - } + if (binormal!=p_b.binormal) + return false; - if (format&Mesh::ARRAY_FORMAT_NORMAL) { - if (p_a.normal.distance_to(p_b.normal)>EQ_VERTEX_DIST) - return false; - } + if (color!=p_b.color) + return false; - if (format&Mesh::ARRAY_FORMAT_TANGENT) { - if (p_a.binormal.distance_to(p_b.binormal)>EQ_VERTEX_DIST) - return false; - if (p_a.tangent.distance_to(p_b.tangent)>EQ_VERTEX_DIST) + if (bones.size()!=p_b.bones.size()) + return false; + + for(int i=0;i<bones.size();i++) { + if (bones[i]!=p_b.bones[i]) return false; } - if (format&Mesh::ARRAY_FORMAT_COLOR) { - if (p_a.color!=p_b.color) + for(int i=0;i<weights.size();i++) { + if (weights[i]!=p_b.weights[i]) return false; } - if (format&Mesh::ARRAY_FORMAT_BONES) { - for(int i=0;i<4;i++) { - if (Math::abs(p_a.bones[i]-p_b.bones[i])>CMP_EPSILON) - return false; - } - } + return true; +} - if (format&Mesh::ARRAY_FORMAT_WEIGHTS) { - for(int i=0;i<4;i++) { - if (Math::abs(p_a.weights[i]-p_b.weights[i])>CMP_EPSILON) - return false; - } - } +uint32_t SurfaceTool::VertexHasher::hash(const Vertex &p_vtx) { - return true; + uint32_t h = hash_djb2_buffer((const uint8_t*)&p_vtx.vertex,sizeof(real_t)*3); + h = hash_djb2_buffer((const uint8_t*)&p_vtx.normal,sizeof(real_t)*3,h); + h = hash_djb2_buffer((const uint8_t*)&p_vtx.binormal,sizeof(real_t)*3,h); + h = hash_djb2_buffer((const uint8_t*)&p_vtx.tangent,sizeof(real_t)*3,h); + h = hash_djb2_buffer((const uint8_t*)&p_vtx.uv,sizeof(real_t)*2,h); + h = hash_djb2_buffer((const uint8_t*)&p_vtx.uv2,sizeof(real_t)*2,h); + h = hash_djb2_buffer((const uint8_t*)&p_vtx.color,sizeof(real_t)*4,h); + h = hash_djb2_buffer((const uint8_t*)p_vtx.bones.ptr(),p_vtx.bones.size()*sizeof(int),h); + h = hash_djb2_buffer((const uint8_t*)p_vtx.weights.ptr(),p_vtx.weights.size()*sizeof(float),h); + return h; } void SurfaceTool::begin(Mesh::PrimitiveType p_primitive) { @@ -186,6 +185,17 @@ void SurfaceTool::add_weights( const Vector<float>& p_weights) { } +void SurfaceTool::add_smooth_group(bool p_smooth) { + + ERR_FAIL_COND(!begun); + if (index_array.size()) { + smooth_groups[index_array.size()]=p_smooth; + } else { + + smooth_groups[vertex_array.size()]=p_smooth; + } +} + void SurfaceTool::add_index( int p_index) { @@ -377,79 +387,53 @@ Ref<Mesh> SurfaceTool::commit(const Ref<Mesh>& p_existing) { void SurfaceTool::index() { -#if 0 - printf("indexing..\n"); - ERR_FAIL_COND( format & Surface::ARRAY_FORMAT_INDEX ); // already indexed - - index_array.clear(); - DVector< Vertex > indexed_vertex_array; + if (index_array.size()) + return; //already indexed - int vertex_array_len = vertex_array.size(); - vertex_array.read_lock(); - const Vertex*vertex_array_ptr = vertex_array.read(); - for (int i=0;i<vertex_array_len;i++) { + HashMap<Vertex,int,VertexHasher> indices; + List<Vertex> new_vertices; - int index_pos=-1; + for(List< Vertex >::Element *E=vertex_array.front();E;E=E->next()) { - int indexed_vertex_array_len=indexed_vertex_array.size(); - - if (indexed_vertex_array_len) { - - indexed_vertex_array.read_lock(); - const Vertex* indexed_vertex_array_ptr=indexed_vertex_array.read(); - - for (int j=0;j<indexed_vertex_array_len;j++) { - - if (vertex_array_ptr[i].same_as(indexed_vertex_array_ptr[j])) { - - index_pos=j; - break; - } - } - - indexed_vertex_array.read_unlock(); - } - - if (index_pos==-1) { - - index_pos=indexed_vertex_array.size(); - indexed_vertex_array.push_back(vertex_array_ptr[i]); + int *idxptr=indices.getptr(E->get()); + int idx; + if (!idxptr) { + idx=indices.size(); + new_vertices.push_back(E->get()); + indices[E->get()]=idx; } else { - - indexed_vertex_array.write_lock(); - indexed_vertex_array.write()[index_pos].normal+=vertex_array_ptr[i].normal; - indexed_vertex_array.write()[index_pos].binormal+=vertex_array_ptr[i].binormal; - indexed_vertex_array.write()[index_pos].tangent+=vertex_array_ptr[i].tangent; - indexed_vertex_array.write_unlock(); + idx=*idxptr; } - index_array.push_back(index_pos); - } - - int idxvertsize=indexed_vertex_array.size(); - indexed_vertex_array.write_lock(); - Vertex* idxvert=indexed_vertex_array.write(); - for (int i=0;i<idxvertsize;i++) { + index_array.push_back(idx); - idxvert[i].normal.normalize(); - idxvert[i].tangent.normalize(); - idxvert[i].binormal.normalize(); } - indexed_vertex_array.write_unlock(); - vertex_array.read_unlock(); - - format|=Surface::ARRAY_FORMAT_INDEX; - vertex_array=indexed_vertex_array; + vertex_array.clear(); + vertex_array=new_vertices; - printf("indexing.. end\n"); -#endif + format|=Mesh::ARRAY_FORMAT_INDEX; } void SurfaceTool::deindex() { + if (index_array.size()==0) + return; //nothing to deindex + Vector< Vertex > varr; + varr.resize(vertex_array.size()); + int idx=0; + for (List< Vertex >::Element *E=vertex_array.front();E;E=E->next()) { + varr[idx++]=E->get(); + } + vertex_array.clear(); + for (List<int>::Element *E=index_array.front();E;E=E->next()) { + + ERR_FAIL_INDEX(E->get(),varr.size()); + vertex_array.push_back(varr[E->get()]); + } + format&=~Mesh::ARRAY_FORMAT_INDEX; } @@ -631,80 +615,250 @@ void SurfaceTool::append_from(const Ref<Mesh>& p_existing, int p_surface,const T void SurfaceTool::generate_tangents() { ERR_FAIL_COND(!(format&Mesh::ARRAY_FORMAT_TEX_UV)); + ERR_FAIL_COND(!(format&Mesh::ARRAY_FORMAT_NORMAL)); -#if 0 - int len=vertex_array.size(); - vertex_array.write_lock(); - Vertex *vertexptr=vertex_array.write(); - - for (int i=0;i<len/3;i++) { + 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(); + } - Vector3 v1 = vertexptr[i*3+0].vertex; - Vector3 v2 = vertexptr[i*3+1].vertex; - Vector3 v3 = vertexptr[i*3+2].vertex; + 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); + } - Vector3 w1 = vertexptr[i*3+0].uv[0]; - Vector3 w2 = vertexptr[i*3+1].uv[0]; - Vector3 w3 = vertexptr[i*3+2].uv[0]; + 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)); - 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; + tangentp.normalize(); + binormalp.normalize(); - 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); + for (int j=0;j<3;j++) { + vtx[ i[j] ]->get().binormal+=binormalp; + vtx[ i[j] ]->get().tangent+=tangentp; - 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); + for (List<Vertex>::Element *E=vertex_array.front();E;E=E->next()) { + E->get().binormal.normalize(); + E->get().tangent.normalize(); } - 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)); + } else { + - tangentp.normalize(); - binormalp.normalize(); + for (List<Vertex>::Element *E=vertex_array.front();E;) { + 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(); - for (int j=0;j<3;j++) { - vertexptr[i*3+j].normal=normal; - vertexptr[i*3+j].binormal=binormalp; - vertexptr[i*3+j].tangent=tangentp; + Vector3 v1 = v[0]->get().vertex; + Vector3 v2 = v[1]->get().vertex; + Vector3 v3 = v[2]->get().vertex; + + Vector2 w1 = v[0]->get().uv; + Vector2 w2 = v[1]->get().uv; + Vector2 w3 = v[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(); + + + for (int j=0;j<3;j++) { + v[j]->get().binormal=binormalp; + v[j]->get().tangent=tangentp; + + } } } - format|=Surface::ARRAY_FORMAT_TANGENT; - printf("adding tangents to the format\n"); + format|=Mesh::ARRAY_FORMAT_TANGENT; - vertex_array.write_unlock(); -#endif } -void SurfaceTool::generate_flat_normals() { +void SurfaceTool::generate_normals() { -} -void SurfaceTool::generate_smooth_normals() { + ERR_FAIL_COND(primitive!=Mesh::PRIMITIVE_TRIANGLES); + + bool was_indexed=index_array.size(); + + deindex(); + + HashMap<Vertex,Vector3,VertexHasher> vertex_hash; + + int count=0; + bool smooth=false; + if (smooth_groups.has(0)) + smooth=smooth_groups[0]; + + print_line("SMOOTH BEGIN? "+itos(smooth)); + + List< Vertex >::Element *B=vertex_array.front(); + for(List< Vertex >::Element *E=B;E;) { + + 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(); + + Vector3 normal = Plane(v[0]->get().vertex,v[1]->get().vertex,v[2]->get().vertex).normal; + + if (smooth) { + + for(int i=0;i<3;i++) { + + Vector3 *lv=vertex_hash.getptr(v[i]->get()); + if (!lv) { + vertex_hash.set(v[i]->get(),normal); + } else { + (*lv)+=normal; + } + } + } else { + + for(int i=0;i<3;i++) { + + v[i]->get().normal=normal; + + } + } + count+=3; + + if (smooth_groups.has(count) || !E) { + + if (vertex_hash.size()) { + + while (B!=E) { + + + Vector3* lv=vertex_hash.getptr(B->get()); + if (lv) { + B->get().normal=lv->normalized(); + } + + B=B->next(); + } + + } else { + B=E; + } + + vertex_hash.clear(); + if (E) { + smooth=smooth_groups[count]; + print_line("SMOOTH AT "+itos(count)+": "+itos(smooth)); + + } + } + + } + + format|=Mesh::ARRAY_FORMAT_NORMAL; + + if (was_indexed) { + index(); + smooth_groups.clear(); + } } @@ -722,6 +876,7 @@ void SurfaceTool::clear() { last_weights.clear(); index_array.clear(); vertex_array.clear(); + smooth_groups.clear(); } @@ -736,12 +891,12 @@ void SurfaceTool::_bind_methods() { ObjectTypeDB::bind_method(_MD("add_uv2","uv2"),&SurfaceTool::add_uv2); ObjectTypeDB::bind_method(_MD("add_bones","bones"),&SurfaceTool::add_bones); ObjectTypeDB::bind_method(_MD("add_weights","weights"),&SurfaceTool::add_weights); + ObjectTypeDB::bind_method(_MD("add_smooth_group","smooth"),&SurfaceTool::add_smooth_group); ObjectTypeDB::bind_method(_MD("set_material","material:Material"),&SurfaceTool::set_material); ObjectTypeDB::bind_method(_MD("index"),&SurfaceTool::index); ObjectTypeDB::bind_method(_MD("deindex"),&SurfaceTool::deindex); - ObjectTypeDB::bind_method(_MD("generate_flat_normals"),&SurfaceTool::generate_flat_normals); - ObjectTypeDB::bind_method(_MD("generate_smooth_normals"),&SurfaceTool::generate_smooth_normals); - ObjectTypeDB::bind_method(_MD("generate_tangents"),&SurfaceTool::generate_tangents); + ///ObjectTypeDB::bind_method(_MD("generate_flat_normals"),&SurfaceTool::generate_flat_normals); + ObjectTypeDB::bind_method(_MD("generate_normals"),&SurfaceTool::generate_normals); ObjectTypeDB::bind_method(_MD("commit:Mesh","existing:Mesh"),&SurfaceTool::commit,DEFVAL( RefPtr() )); ObjectTypeDB::bind_method(_MD("clear"),&SurfaceTool::clear); diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h index 8f0fcaa01a..fe82d3a4ce 100644 --- a/scene/resources/surface_tool.h +++ b/scene/resources/surface_tool.h @@ -49,12 +49,17 @@ public: Vector<int> bones; Vector<float> weights; + bool operator==(const Vertex& p_vertex) const; + Vertex() { } }; private: - bool compare(const Vertex& p_a,const Vertex& p_b) const; + + struct VertexHasher { + static _FORCE_INLINE_ uint32_t hash(const Vertex &p_vtx); + }; bool begun; bool first; @@ -64,6 +69,7 @@ private: //arrays List< Vertex > vertex_array; List< int > index_array; + Map<int,bool> smooth_groups; //memory Color last_color; @@ -92,13 +98,13 @@ public: void add_uv2( const Vector2& p_uv); void add_bones( const Vector<int>& p_indices); void add_weights( const Vector<float>& p_weights); + void add_smooth_group(bool p_smooth); void add_index( int p_index); void index(); void deindex(); - void generate_flat_normals(); - void generate_smooth_normals(); + void generate_normals(); void generate_tangents(); void add_to_format(int p_flags) { format|=p_flags; } diff --git a/servers/audio/audio_mixer_sw.cpp b/servers/audio/audio_mixer_sw.cpp index 2ca0c5e93a..873e19823a 100644 --- a/servers/audio/audio_mixer_sw.cpp +++ b/servers/audio/audio_mixer_sw.cpp @@ -35,7 +35,7 @@ #define NO_REVERB #endif -template<class Depth,bool is_stereo,bool use_filter,bool use_fx,AudioMixerSW::InterpolationType type,AudioMixerSW::MixChannels mix_mode> +template<class Depth,bool is_stereo,bool is_ima_adpcm,bool use_filter,bool use_fx,AudioMixerSW::InterpolationType type,AudioMixerSW::MixChannels mix_mode> void AudioMixerSW::do_resample(const Depth* p_src, int32_t *p_dst, ResamplerState *p_state) { // this function will be compiled branchless by any decent compiler @@ -48,37 +48,110 @@ void AudioMixerSW::do_resample(const Depth* p_src, int32_t *p_dst, ResamplerStat if (is_stereo) pos<<=1; - final=p_src[pos]; - if (is_stereo) - final_r=p_src[pos+1]; + if (is_ima_adpcm) { - if (sizeof(Depth)==1) { /* conditions will not exist anymore when compiled! */ - final<<=8; - if (is_stereo) - final_r<<=8; - } + int sample_pos = pos + p_state->ima_adpcm->window_ofs; - if (type==INTERPOLATION_LINEAR) { + while(sample_pos>p_state->ima_adpcm->last_nibble) { - if (is_stereo) { - next=p_src[pos+2]; - next_r=p_src[pos+3]; - } else { - next=p_src[pos+1]; + static const int16_t _ima_adpcm_step_table[89] = { + 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, + 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, + 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, + 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, + 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, + 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, + 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, + 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, + 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 + }; + + static const int8_t _ima_adpcm_index_table[16] = { + -1, -1, -1, -1, 2, 4, 6, 8, + -1, -1, -1, -1, 2, 4, 6, 8 + }; + + int16_t nibble,signed_nibble,diff,step; + + p_state->ima_adpcm->last_nibble++; + const uint8_t *src_ptr=p_state->ima_adpcm->ptr; + + nibble = (p_state->ima_adpcm->last_nibble&1)? + (src_ptr[p_state->ima_adpcm->last_nibble>>1]>>4):(src_ptr[p_state->ima_adpcm->last_nibble>>1]&0xF); + step=_ima_adpcm_step_table[p_state->ima_adpcm->step_index]; + + p_state->ima_adpcm->step_index += _ima_adpcm_index_table[nibble]; + if (p_state->ima_adpcm->step_index<0) + p_state->ima_adpcm->step_index=0; + if (p_state->ima_adpcm->step_index>88) + p_state->ima_adpcm->step_index=88; + + /* + signed_nibble = (nibble&7) * ((nibble&8)?-1:1); + diff = (2 * signed_nibble + 1) * step / 4; */ + + diff = step >> 3 ; + if (nibble & 1) + diff += step >> 2 ; + if (nibble & 2) + diff += step >> 1 ; + if (nibble & 4) + diff += step ; + if (nibble & 8) + diff = -diff ; + + p_state->ima_adpcm->predictor+=diff; + if (p_state->ima_adpcm->predictor<-0x8000) + p_state->ima_adpcm->predictor=-0x8000; + else if (p_state->ima_adpcm->predictor>0x7FFF) + p_state->ima_adpcm->predictor=0x7FFF; + + + /* store loop if there */ + if (p_state->ima_adpcm->last_nibble==p_state->ima_adpcm->loop_pos) { + + p_state->ima_adpcm->loop_step_index = p_state->ima_adpcm->step_index; + p_state->ima_adpcm->loop_predictor = p_state->ima_adpcm->predictor; + } + } - if (sizeof(Depth)==1) { - next<<=8; + final=p_state->ima_adpcm->predictor; + + } else { + final=p_src[pos]; + if (is_stereo) + final_r=p_src[pos+1]; + + if (sizeof(Depth)==1) { /* conditions will not exist anymore when compiled! */ + final<<=8; if (is_stereo) - next_r<<=8; + final_r<<=8; } - int32_t frac=int32_t(p_state->pos&MIX_FRAC_MASK); + if (type==INTERPOLATION_LINEAR) { - final=final+((next-final)*frac >> MIX_FRAC_BITS); - if (is_stereo) - final_r=final_r+((next_r-final_r)*frac >> MIX_FRAC_BITS); + if (is_stereo) { + + next=p_src[pos+2]; + next_r=p_src[pos+3]; + } else { + next=p_src[pos+1]; + } + + if (sizeof(Depth)==1) { + next<<=8; + if (is_stereo) + next_r<<=8; + } + + int32_t frac=int32_t(p_state->pos&MIX_FRAC_MASK); + + final=final+((next-final)*frac >> MIX_FRAC_BITS); + if (is_stereo) + final_r=final_r+((next_r-final_r)*frac >> MIX_FRAC_BITS); + } } if (use_filter) { @@ -314,6 +387,15 @@ void AudioMixerSW::mix_channel(Channel& c) { rstate.filter_l=&c.mix.filter_l; rstate.filter_r=&c.mix.filter_r; + if (format==AS::SAMPLE_FORMAT_IMA_ADPCM) { + + rstate.ima_adpcm=&c.mix.ima_adpcm; + if (loop_format!=AS::SAMPLE_LOOP_NONE) { + c.mix.ima_adpcm.loop_pos=loop_begin_fp>>MIX_FRAC_BITS; + loop_format=AS::SAMPLE_LOOP_FORWARD; + } + } + while (todo>0) { int64_t limit=0; @@ -354,7 +436,14 @@ void AudioMixerSW::mix_channel(Channel& c) { } else { /* go to loop-begin */ - c.mix.offset=loop_begin_fp+(c.mix.offset-loop_end_fp); + if (format==AS::SAMPLE_FORMAT_IMA_ADPCM) { + c.mix.ima_adpcm.step_index=c.mix.ima_adpcm.loop_step_index; + c.mix.ima_adpcm.predictor=c.mix.ima_adpcm.loop_predictor; + c.mix.ima_adpcm.last_nibble=loop_begin_fp>>MIX_FRAC_BITS; + c.mix.offset=loop_begin_fp; + } else { + c.mix.offset=loop_begin_fp+(c.mix.offset-loop_end_fp); + } } } else { @@ -393,48 +482,48 @@ void AudioMixerSW::mix_channel(Channel& c) { /* Macros to call the resample function for all possibilities, creating a dedicated-non branchy function call for each thanks to template magic*/ -#define CALL_RESAMPLE_FUNC( m_depth, m_stereo, m_use_filter, m_use_fx, m_interp, m_mode)\ - do_resample<m_depth,m_stereo,m_use_filter,m_use_fx,m_interp, m_mode>(\ +#define CALL_RESAMPLE_FUNC( m_depth, m_stereo, m_ima_adpcm, m_use_filter, m_use_fx, m_interp, m_mode)\ + do_resample<m_depth,m_stereo,m_ima_adpcm, m_use_filter,m_use_fx,m_interp, m_mode>(\ src_ptr,\ dst_buff,&rstate); -#define CALL_RESAMPLE_INTERP( m_depth, m_stereo, m_use_filter, m_use_fx, m_interp, m_mode)\ +#define CALL_RESAMPLE_INTERP( m_depth, m_stereo, m_ima_adpcm, m_use_filter, m_use_fx, m_interp, m_mode)\ if(m_interp==INTERPOLATION_RAW) {\ - CALL_RESAMPLE_FUNC(m_depth,m_stereo,m_use_filter,m_use_fx,INTERPOLATION_RAW,m_mode);\ + CALL_RESAMPLE_FUNC(m_depth,m_stereo, m_ima_adpcm,m_use_filter,m_use_fx,INTERPOLATION_RAW,m_mode);\ } else if(m_interp==INTERPOLATION_LINEAR) {\ - CALL_RESAMPLE_FUNC(m_depth,m_stereo,m_use_filter,m_use_fx,INTERPOLATION_LINEAR,m_mode);\ + CALL_RESAMPLE_FUNC(m_depth,m_stereo, m_ima_adpcm,m_use_filter,m_use_fx,INTERPOLATION_LINEAR,m_mode);\ } else if(m_interp==INTERPOLATION_CUBIC) {\ - CALL_RESAMPLE_FUNC(m_depth,m_stereo,m_use_filter,m_use_fx,INTERPOLATION_CUBIC,m_mode);\ + CALL_RESAMPLE_FUNC(m_depth,m_stereo, m_ima_adpcm,m_use_filter,m_use_fx,INTERPOLATION_CUBIC,m_mode);\ }\ -#define CALL_RESAMPLE_FX( m_depth, m_stereo, m_use_filter, m_use_fx, m_interp, m_mode)\ +#define CALL_RESAMPLE_FX( m_depth, m_stereo, m_ima_adpcm, m_use_filter, m_use_fx, m_interp, m_mode)\ if(m_use_fx) {\ - CALL_RESAMPLE_INTERP(m_depth,m_stereo,m_use_filter,true,m_interp, m_mode);\ + CALL_RESAMPLE_INTERP(m_depth,m_stereo, m_ima_adpcm,m_use_filter,true,m_interp, m_mode);\ } else {\ - CALL_RESAMPLE_INTERP(m_depth,m_stereo,m_use_filter,false,m_interp, m_mode);\ + CALL_RESAMPLE_INTERP(m_depth,m_stereo, m_ima_adpcm,m_use_filter,false,m_interp, m_mode);\ }\ -#define CALL_RESAMPLE_FILTER( m_depth, m_stereo, m_use_filter, m_use_fx, m_interp, m_mode)\ +#define CALL_RESAMPLE_FILTER( m_depth, m_stereo, m_ima_adpcm, m_use_filter, m_use_fx, m_interp, m_mode)\ if(m_use_filter) {\ - CALL_RESAMPLE_FX(m_depth,m_stereo,true,m_use_fx,m_interp, m_mode);\ + CALL_RESAMPLE_FX(m_depth,m_stereo, m_ima_adpcm,true,m_use_fx,m_interp, m_mode);\ } else {\ - CALL_RESAMPLE_FX(m_depth,m_stereo,false,m_use_fx,m_interp, m_mode);\ + CALL_RESAMPLE_FX(m_depth,m_stereo, m_ima_adpcm,false,m_use_fx,m_interp, m_mode);\ }\ -#define CALL_RESAMPLE_STEREO( m_depth, m_stereo, m_use_filter, m_use_fx, m_interp, m_mode)\ +#define CALL_RESAMPLE_STEREO( m_depth, m_stereo, m_ima_adpcm, m_use_filter, m_use_fx, m_interp, m_mode)\ if(m_stereo) {\ - CALL_RESAMPLE_FILTER(m_depth,true,m_use_filter,m_use_fx,m_interp, m_mode);\ + CALL_RESAMPLE_FILTER(m_depth,true,m_ima_adpcm, m_use_filter,m_use_fx,m_interp, m_mode);\ } else {\ - CALL_RESAMPLE_FILTER(m_depth,false,m_use_filter,m_use_fx,m_interp, m_mode);\ + CALL_RESAMPLE_FILTER(m_depth,false,m_ima_adpcm,m_use_filter,m_use_fx,m_interp, m_mode);\ }\ -#define CALL_RESAMPLE_MODE( m_depth, m_stereo, m_use_filter, m_use_fx, m_interp, m_mode)\ +#define CALL_RESAMPLE_MODE( m_depth, m_stereo, m_ima_adpcm, m_use_filter, m_use_fx, m_interp, m_mode)\ if(m_mode==MIX_STEREO) {\ - CALL_RESAMPLE_STEREO(m_depth,m_stereo,m_use_filter,m_use_fx,m_interp, MIX_STEREO);\ + CALL_RESAMPLE_STEREO(m_depth,m_stereo, m_ima_adpcm,m_use_filter,m_use_fx,m_interp, MIX_STEREO);\ } else {\ - CALL_RESAMPLE_STEREO(m_depth,m_stereo,m_use_filter,m_use_fx,m_interp, MIX_QUAD);\ + CALL_RESAMPLE_STEREO(m_depth,m_stereo, m_ima_adpcm,m_use_filter,m_use_fx,m_interp, MIX_QUAD);\ }\ @@ -443,11 +532,17 @@ void AudioMixerSW::mix_channel(Channel& c) { if (format==AS::SAMPLE_FORMAT_PCM8) { int8_t *src_ptr = &((int8_t*)data)[(c.mix.offset >> MIX_FRAC_BITS)<<(is_stereo?1:0) ]; - CALL_RESAMPLE_MODE(int8_t,is_stereo,use_filter,use_fx,interpolation_type,mix_channels); + CALL_RESAMPLE_MODE(int8_t,is_stereo,false,use_filter,use_fx,interpolation_type,mix_channels); } else if (format==AS::SAMPLE_FORMAT_PCM16) { int16_t *src_ptr = &((int16_t*)data)[(c.mix.offset >> MIX_FRAC_BITS)<<(is_stereo?1:0) ]; - CALL_RESAMPLE_MODE(int16_t,is_stereo,use_filter,use_fx,interpolation_type,mix_channels); + CALL_RESAMPLE_MODE(int16_t,is_stereo,false,use_filter,use_fx,interpolation_type,mix_channels); + + } else if (format==AS::SAMPLE_FORMAT_IMA_ADPCM) { + c.mix.ima_adpcm.window_ofs=c.mix.offset>>MIX_FRAC_BITS; + c.mix.ima_adpcm.ptr=(const uint8_t*)data; + int8_t *src_ptr = &((int8_t*)data)[(c.mix.offset >> MIX_FRAC_BITS)<<(is_stereo?1:0) ]; + CALL_RESAMPLE_MODE(int8_t,false,true,use_filter,use_fx,interpolation_type,mix_channels); } @@ -669,6 +764,19 @@ AudioMixer::ChannelID AudioMixerSW::channel_alloc(RID p_sample) { c.had_prev_reverb=false; c.had_prev_vol=false; + + if (sample_manager->sample_get_format(c.sample)==AudioServer::SAMPLE_FORMAT_IMA_ADPCM) { + + c.mix.ima_adpcm.step_index=0; + c.mix.ima_adpcm.predictor=0; + c.mix.ima_adpcm.loop_step_index=0; + c.mix.ima_adpcm.loop_predictor=0; + c.mix.ima_adpcm.last_nibble=-1; + c.mix.ima_adpcm.loop_pos=0x7FFFFFFF; + c.mix.ima_adpcm.window_ofs=0; + c.mix.ima_adpcm.ptr=NULL; + } + ChannelID ret_id = index+c.check*MAX_CHANNELS; return ret_id; diff --git a/servers/audio/audio_mixer_sw.h b/servers/audio/audio_mixer_sw.h index eb3feee1c8..d3caf03089 100644 --- a/servers/audio/audio_mixer_sw.h +++ b/servers/audio/audio_mixer_sw.h @@ -73,6 +73,7 @@ private: MAX_REVERBS=4 }; + struct Channel { RID sample; @@ -93,6 +94,19 @@ private: float ha[2],hb[2]; } filter_l,filter_r; + struct IMA_ADPCM_State { + + int16_t step_index; + int32_t predictor; + /* values at loop point */ + int16_t loop_step_index; + int32_t loop_predictor; + int32_t last_nibble; + int32_t loop_pos; + int32_t window_ofs; + const uint8_t *ptr; + } ima_adpcm; + } mix; float vol; @@ -163,17 +177,20 @@ private: int32_t chorus_vol_inc[4]; + Channel::Mix::Filter *filter_l; Channel::Mix::Filter *filter_r; Channel::Filter::Coefs coefs; Channel::Filter::Coefs coefs_inc; + Channel::Mix::IMA_ADPCM_State *ima_adpcm; + int32_t *reverb_buffer; }; - template<class Depth,bool is_stereo,bool use_filter,bool use_fx,InterpolationType type,MixChannels> + template<class Depth,bool is_stereo,bool use_filter,bool is_ima_adpcm,bool use_fx,InterpolationType type,MixChannels> _FORCE_INLINE_ void do_resample(const Depth* p_src, int32_t *p_dst, ResamplerState *p_state); MixChannels mix_channels; diff --git a/servers/audio/sample_manager_sw.cpp b/servers/audio/sample_manager_sw.cpp index 2c065a9375..5a5aa1a34c 100644 --- a/servers/audio/sample_manager_sw.cpp +++ b/servers/audio/sample_manager_sw.cpp @@ -46,8 +46,13 @@ RID SampleManagerMallocSW::sample_create(AS::SampleFormat p_format, bool p_stere datalen*=2; if (p_format==AS::SAMPLE_FORMAT_PCM16) datalen*=2; - else if (p_format==AS::SAMPLE_FORMAT_IMA_ADPCM) + else if (p_format==AS::SAMPLE_FORMAT_IMA_ADPCM) { + if (datalen&1) { + datalen++; + } datalen/=2; + datalen+=4; + } #define SAMPLE_EXTRA 16 s->data = memalloc(datalen+SAMPLE_EXTRA); //help the interpolator by allocating a little more.. @@ -128,11 +133,13 @@ void SampleManagerMallocSW::sample_set_data(RID p_sample, const DVector<uint8_t> int buff_size=p_buffer.size(); ERR_FAIL_COND(buff_size==0); + ERR_EXPLAIN("Sample buffer size does not match sample size."); ERR_FAIL_COND(s->length_bytes!=buff_size); DVector<uint8_t>::Read buffer_r=p_buffer.read(); const uint8_t *src = buffer_r.ptr(); uint8_t *dst = (uint8_t*)s->data; + print_line("set data: "+itos(s->length_bytes)); for(int i=0;i<s->length_bytes;i++) { diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp index f0f72b471c..52edc0faa7 100644 --- a/servers/physics/body_sw.cpp +++ b/servers/physics/body_sw.cpp @@ -425,6 +425,27 @@ void BodySW::integrate_velocities(real_t p_step) { return; } + + + //apply axis lock + if (axis_lock!=PhysicsServer::BODY_AXIS_LOCK_DISABLED) { + + + int axis=axis_lock-1; + for(int i=0;i<3;i++) { + if (i==axis) { + linear_velocity[i]=0; + biased_linear_velocity[i]=0; + } else { + + angular_velocity[i]=0; + biased_angular_velocity[i]=0; + } + } + + } + + Vector3 total_angular_velocity = angular_velocity+biased_angular_velocity; @@ -441,7 +462,11 @@ void BodySW::integrate_velocities(real_t p_step) { } Vector3 total_linear_velocity=linear_velocity+biased_linear_velocity; - + /*for(int i=0;i<3;i++) { + if (axis_lock&(1<<i)) { + transform.origin[i]=0.0; + } + }*/ transform.origin+=total_linear_velocity * p_step; @@ -614,6 +639,7 @@ BodySW::BodySW() : CollisionObjectSW(TYPE_BODY), active_list(this), inertia_upda continuous_cd=false; can_sleep=false; fi_callback=NULL; + axis_lock=PhysicsServer::BODY_AXIS_LOCK_DISABLED; } diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h index 9f0bbc00cf..8923899278 100644 --- a/servers/physics/body_sw.h +++ b/servers/physics/body_sw.h @@ -26,323 +26,328 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef BODY_SW_H
-#define BODY_SW_H
-
-#include "collision_object_sw.h"
-#include "vset.h"
-#include "area_sw.h"
-
-class ConstraintSW;
-
-
-class BodySW : public CollisionObjectSW {
-
-
- PhysicsServer::BodyMode mode;
-
- Vector3 linear_velocity;
- Vector3 angular_velocity;
-
- Vector3 biased_linear_velocity;
- Vector3 biased_angular_velocity;
- real_t mass;
- real_t bounce;
- real_t friction;
-
- real_t _inv_mass;
- Vector3 _inv_inertia;
- Matrix3 _inv_inertia_tensor;
-
- Vector3 gravity;
- real_t density;
-
- real_t still_time;
-
- Vector3 applied_force;
- Vector3 applied_torque;
-
- SelfList<BodySW> active_list;
- SelfList<BodySW> inertia_update_list;
- SelfList<BodySW> direct_state_query_list;
-
- VSet<RID> exceptions;
- bool omit_force_integration;
- bool active;
- bool simulated_motion;
- bool continuous_cd;
- bool can_sleep;
- void _update_inertia();
- virtual void _shapes_changed();
-
- Map<ConstraintSW*,int> constraint_map;
-
- struct AreaCMP {
-
- AreaSW *area;
- _FORCE_INLINE_ bool operator<(const AreaCMP& p_cmp) const { return area->get_self() < p_cmp.area->get_self() ; }
- _FORCE_INLINE_ AreaCMP() {}
- _FORCE_INLINE_ AreaCMP(AreaSW *p_area) { area=p_area;}
- };
-
-
- VSet<AreaCMP> areas;
-
- struct Contact {
-
-
- Vector3 local_pos;
- Vector3 local_normal;
- float depth;
- int local_shape;
- Vector3 collider_pos;
- int collider_shape;
- ObjectID collider_instance_id;
- RID collider;
- Vector3 collider_velocity_at_pos;
- };
-
- Vector<Contact> contacts; //no contacts by default
- int contact_count;
-
- struct ForceIntegrationCallback {
-
- ObjectID id;
- StringName method;
- Variant udata;
- };
-
- ForceIntegrationCallback *fi_callback;
-
-
- uint64_t island_step;
- BodySW *island_next;
- BodySW *island_list_next;
-
- _FORCE_INLINE_ void _compute_area_gravity(const AreaSW *p_area);
-
- _FORCE_INLINE_ void _update_inertia_tensor();
-
-friend class PhysicsDirectBodyStateSW; // i give up, too many functions to expose
-
-public:
-
-
- void set_force_integration_callback(ObjectID p_id,const StringName& p_method,const Variant& p_udata=Variant());
-
-
- _FORCE_INLINE_ void add_area(AreaSW *p_area) { areas.insert(AreaCMP(p_area)); }
- _FORCE_INLINE_ void remove_area(AreaSW *p_area) { areas.erase(AreaCMP(p_area)); }
-
- _FORCE_INLINE_ void set_max_contacts_reported(int p_size) { contacts.resize(p_size); contact_count=0; }
- _FORCE_INLINE_ int get_max_contacts_reported() const { return contacts.size(); }
-
- _FORCE_INLINE_ bool can_report_contacts() const { return !contacts.empty(); }
- _FORCE_INLINE_ void add_contact(const Vector3& p_local_pos,const Vector3& p_local_normal, float p_depth, int p_local_shape, const Vector3& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector3& p_collider_velocity_at_pos);
-
-
- _FORCE_INLINE_ void add_exception(const RID& p_exception) { exceptions.insert(p_exception);}
- _FORCE_INLINE_ void remove_exception(const RID& p_exception) { exceptions.erase(p_exception);}
- _FORCE_INLINE_ bool has_exception(const RID& p_exception) const { return exceptions.has(p_exception);}
- _FORCE_INLINE_ const VSet<RID>& get_exceptions() const { return exceptions;}
-
- _FORCE_INLINE_ uint64_t get_island_step() const { return island_step; }
- _FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step=p_step; }
-
- _FORCE_INLINE_ BodySW* get_island_next() const { return island_next; }
- _FORCE_INLINE_ void set_island_next(BodySW* p_next) { island_next=p_next; }
-
- _FORCE_INLINE_ BodySW* get_island_list_next() const { return island_list_next; }
- _FORCE_INLINE_ void set_island_list_next(BodySW* p_next) { island_list_next=p_next; }
-
- _FORCE_INLINE_ void add_constraint(ConstraintSW* p_constraint, int p_pos) { constraint_map[p_constraint]=p_pos; }
- _FORCE_INLINE_ void remove_constraint(ConstraintSW* p_constraint) { constraint_map.erase(p_constraint); }
- const Map<ConstraintSW*,int>& get_constraint_map() const { return constraint_map; }
-
- _FORCE_INLINE_ void set_omit_force_integration(bool p_omit_force_integration) { omit_force_integration=p_omit_force_integration; }
- _FORCE_INLINE_ bool get_omit_force_integration() const { return omit_force_integration; }
-
- _FORCE_INLINE_ void set_linear_velocity(const Vector3& p_velocity) {linear_velocity=p_velocity; }
- _FORCE_INLINE_ Vector3 get_linear_velocity() const { return linear_velocity; }
-
- _FORCE_INLINE_ void set_angular_velocity(const Vector3& p_velocity) { angular_velocity=p_velocity; }
- _FORCE_INLINE_ Vector3 get_angular_velocity() const { return angular_velocity; }
-
- _FORCE_INLINE_ const Vector3& get_biased_linear_velocity() const { return biased_linear_velocity; }
- _FORCE_INLINE_ const Vector3& get_biased_angular_velocity() const { return biased_angular_velocity; }
-
- _FORCE_INLINE_ void apply_impulse(const Vector3& p_pos, const Vector3& p_j) {
-
- linear_velocity += p_j * _inv_mass;
- angular_velocity += _inv_inertia_tensor.xform( p_pos.cross(p_j) );
- }
-
- _FORCE_INLINE_ void apply_bias_impulse(const Vector3& p_pos, const Vector3& p_j) {
-
- biased_linear_velocity += p_j * _inv_mass;
- biased_angular_velocity += _inv_inertia_tensor.xform( p_pos.cross(p_j) );
- }
-
- _FORCE_INLINE_ void apply_torque_impulse(const Vector3& p_j) {
-
- angular_velocity += _inv_inertia_tensor.xform(p_j);
- }
-
- _FORCE_INLINE_ void add_force(const Vector3& p_force, const Vector3& p_pos) {
-
- applied_force += p_force;
- applied_torque += p_pos.cross(p_force);
- }
-
- void set_active(bool p_active);
- _FORCE_INLINE_ bool is_active() const { return active; }
-
- void set_param(PhysicsServer::BodyParameter p_param, float);
- float get_param(PhysicsServer::BodyParameter p_param) const;
-
- void set_mode(PhysicsServer::BodyMode p_mode);
- PhysicsServer::BodyMode get_mode() const;
-
- void set_state(PhysicsServer::BodyState p_state, const Variant& p_variant);
- Variant get_state(PhysicsServer::BodyState p_state) const;
-
- void set_applied_force(const Vector3& p_force) { applied_force=p_force; }
- Vector3 get_applied_force() const { return applied_force; }
-
- void set_applied_torque(const Vector3& p_torque) { applied_torque=p_torque; }
- Vector3 get_applied_torque() const { return applied_torque; }
-
- _FORCE_INLINE_ void set_continuous_collision_detection(bool p_enable) { continuous_cd=p_enable; }
- _FORCE_INLINE_ bool is_continuous_collision_detection_enabled() const { return continuous_cd; }
-
- void set_space(SpaceSW *p_space);
-
- void update_inertias();
-
- _FORCE_INLINE_ real_t get_inv_mass() const { return _inv_mass; }
- _FORCE_INLINE_ Vector3 get_inv_inertia() const { return _inv_inertia; }
- _FORCE_INLINE_ Matrix3 get_inv_inertia_tensor() const { return _inv_inertia_tensor; }
- _FORCE_INLINE_ real_t get_friction() const { return friction; }
- _FORCE_INLINE_ Vector3 get_gravity() const { return gravity; }
- _FORCE_INLINE_ real_t get_density() const { return density; }
- _FORCE_INLINE_ real_t get_bounce() const { return bounce; }
-
- void integrate_forces(real_t p_step);
- void integrate_velocities(real_t p_step);
-
- void simulate_motion(const Transform& p_xform,real_t p_step);
- void call_queries();
- void wakeup_neighbours();
-
- bool sleep_test(real_t p_step);
-
- BodySW();
- ~BodySW();
-
-};
-
-
-//add contact inline
-
-void BodySW::add_contact(const Vector3& p_local_pos,const Vector3& p_local_normal, float p_depth, int p_local_shape, const Vector3& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector3& p_collider_velocity_at_pos) {
-
- int c_max=contacts.size();
-
- if (c_max==0)
- return;
-
- Contact *c = &contacts[0];
-
-
- int idx=-1;
-
- if (contact_count<c_max) {
- idx=contact_count++;
- } else {
-
- float least_depth=1e20;
- int least_deep=-1;
- for(int i=0;i<c_max;i++) {
-
- if (i==0 || c[i].depth<least_depth) {
- least_deep=i;
- least_depth=c[i].depth;
- }
- }
-
- if (least_deep>=0 && least_depth<p_depth) {
-
- idx=least_deep;
- }
- if (idx==-1)
- return; //none least deepe than this
- }
-
- c[idx].local_pos=p_local_pos;
- c[idx].local_normal=p_local_normal;
- c[idx].depth=p_depth;
- c[idx].local_shape=p_local_shape;
- c[idx].collider_pos=p_collider_pos;
- c[idx].collider_shape=p_collider_shape;
- c[idx].collider_instance_id=p_collider_instance_id;
- c[idx].collider=p_collider;
- c[idx].collider_velocity_at_pos=p_collider_velocity_at_pos;
-
-}
-
-
-class PhysicsDirectBodyStateSW : public PhysicsDirectBodyState {
-
- OBJ_TYPE( PhysicsDirectBodyStateSW, PhysicsDirectBodyState );
-
-public:
-
- static PhysicsDirectBodyStateSW *singleton;
- BodySW *body;
- real_t step;
-
- virtual Vector3 get_total_gravity() const { return body->get_gravity(); } // get gravity vector working on this body space/area
- virtual float get_total_density() const { return body->get_density(); } // get density of this body space/area
-
- virtual float get_inverse_mass() const { return body->get_inv_mass(); } // get the mass
- virtual Vector3 get_inverse_inertia() const { return body->get_inv_inertia(); } // get density of this body space
- virtual Matrix3 get_inverse_inertia_tensor() const { return body->get_inv_inertia_tensor(); } // get density of this body space
-
- virtual void set_linear_velocity(const Vector3& p_velocity) { body->set_linear_velocity(p_velocity); }
- virtual Vector3 get_linear_velocity() const { return body->get_linear_velocity(); }
-
- virtual void set_angular_velocity(const Vector3& p_velocity) { body->set_angular_velocity(p_velocity); }
- virtual Vector3 get_angular_velocity() const { return body->get_angular_velocity(); }
-
- virtual void set_transform(const Transform& p_transform) { body->set_state(PhysicsServer::BODY_STATE_TRANSFORM,p_transform); }
- virtual Transform get_transform() const { return body->get_transform(); }
-
- virtual void add_force(const Vector3& p_force, const Vector3& p_pos) { body->add_force(p_force,p_pos); }
-
- virtual void set_sleep_state(bool p_enable) { body->set_active(!p_enable); }
- virtual bool is_sleeping() const { return !body->is_active(); }
-
- virtual int get_contact_count() const { return body->contact_count; }
-
- virtual Vector3 get_contact_local_pos(int p_contact_idx) const {
- ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector3());
- return body->contacts[p_contact_idx].local_pos;
- }
- virtual Vector3 get_contact_local_normal(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector3()); return body->contacts[p_contact_idx].local_normal; }
- virtual int get_contact_local_shape(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,-1); return body->contacts[p_contact_idx].local_shape; }
-
- virtual RID get_contact_collider(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,RID()); return body->contacts[p_contact_idx].collider; }
- virtual Vector3 get_contact_collider_pos(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector3()); return body->contacts[p_contact_idx].collider_pos; }
- virtual ObjectID get_contact_collider_id(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,0); return body->contacts[p_contact_idx].collider_instance_id; }
- virtual int get_contact_collider_shape(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,0); return body->contacts[p_contact_idx].collider_shape; }
- virtual Vector3 get_contact_collider_velocity_at_pos(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector3()); return body->contacts[p_contact_idx].collider_velocity_at_pos; }
-
- virtual PhysicsDirectSpaceState* get_space_state();
-
-
- virtual real_t get_step() const { return step; }
- PhysicsDirectBodyStateSW() { singleton=this; body=NULL; }
-};
-
-
-#endif // BODY__SW_H
+#ifndef BODY_SW_H +#define BODY_SW_H + +#include "collision_object_sw.h" +#include "vset.h" +#include "area_sw.h" + +class ConstraintSW; + + +class BodySW : public CollisionObjectSW { + + + PhysicsServer::BodyMode mode; + + Vector3 linear_velocity; + Vector3 angular_velocity; + + Vector3 biased_linear_velocity; + Vector3 biased_angular_velocity; + real_t mass; + real_t bounce; + real_t friction; + + PhysicsServer::BodyAxisLock axis_lock; + + real_t _inv_mass; + Vector3 _inv_inertia; + Matrix3 _inv_inertia_tensor; + + Vector3 gravity; + real_t density; + + real_t still_time; + + Vector3 applied_force; + Vector3 applied_torque; + + SelfList<BodySW> active_list; + SelfList<BodySW> inertia_update_list; + SelfList<BodySW> direct_state_query_list; + + VSet<RID> exceptions; + bool omit_force_integration; + bool active; + bool simulated_motion; + bool continuous_cd; + bool can_sleep; + void _update_inertia(); + virtual void _shapes_changed(); + + Map<ConstraintSW*,int> constraint_map; + + struct AreaCMP { + + AreaSW *area; + _FORCE_INLINE_ bool operator<(const AreaCMP& p_cmp) const { return area->get_self() < p_cmp.area->get_self() ; } + _FORCE_INLINE_ AreaCMP() {} + _FORCE_INLINE_ AreaCMP(AreaSW *p_area) { area=p_area;} + }; + + + VSet<AreaCMP> areas; + + struct Contact { + + + Vector3 local_pos; + Vector3 local_normal; + float depth; + int local_shape; + Vector3 collider_pos; + int collider_shape; + ObjectID collider_instance_id; + RID collider; + Vector3 collider_velocity_at_pos; + }; + + Vector<Contact> contacts; //no contacts by default + int contact_count; + + struct ForceIntegrationCallback { + + ObjectID id; + StringName method; + Variant udata; + }; + + ForceIntegrationCallback *fi_callback; + + + uint64_t island_step; + BodySW *island_next; + BodySW *island_list_next; + + _FORCE_INLINE_ void _compute_area_gravity(const AreaSW *p_area); + + _FORCE_INLINE_ void _update_inertia_tensor(); + +friend class PhysicsDirectBodyStateSW; // i give up, too many functions to expose + +public: + + + void set_force_integration_callback(ObjectID p_id,const StringName& p_method,const Variant& p_udata=Variant()); + + + _FORCE_INLINE_ void add_area(AreaSW *p_area) { areas.insert(AreaCMP(p_area)); } + _FORCE_INLINE_ void remove_area(AreaSW *p_area) { areas.erase(AreaCMP(p_area)); } + + _FORCE_INLINE_ void set_max_contacts_reported(int p_size) { contacts.resize(p_size); contact_count=0; } + _FORCE_INLINE_ int get_max_contacts_reported() const { return contacts.size(); } + + _FORCE_INLINE_ bool can_report_contacts() const { return !contacts.empty(); } + _FORCE_INLINE_ void add_contact(const Vector3& p_local_pos,const Vector3& p_local_normal, float p_depth, int p_local_shape, const Vector3& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector3& p_collider_velocity_at_pos); + + + _FORCE_INLINE_ void add_exception(const RID& p_exception) { exceptions.insert(p_exception);} + _FORCE_INLINE_ void remove_exception(const RID& p_exception) { exceptions.erase(p_exception);} + _FORCE_INLINE_ bool has_exception(const RID& p_exception) const { return exceptions.has(p_exception);} + _FORCE_INLINE_ const VSet<RID>& get_exceptions() const { return exceptions;} + + _FORCE_INLINE_ uint64_t get_island_step() const { return island_step; } + _FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step=p_step; } + + _FORCE_INLINE_ BodySW* get_island_next() const { return island_next; } + _FORCE_INLINE_ void set_island_next(BodySW* p_next) { island_next=p_next; } + + _FORCE_INLINE_ BodySW* get_island_list_next() const { return island_list_next; } + _FORCE_INLINE_ void set_island_list_next(BodySW* p_next) { island_list_next=p_next; } + + _FORCE_INLINE_ void add_constraint(ConstraintSW* p_constraint, int p_pos) { constraint_map[p_constraint]=p_pos; } + _FORCE_INLINE_ void remove_constraint(ConstraintSW* p_constraint) { constraint_map.erase(p_constraint); } + const Map<ConstraintSW*,int>& get_constraint_map() const { return constraint_map; } + + _FORCE_INLINE_ void set_omit_force_integration(bool p_omit_force_integration) { omit_force_integration=p_omit_force_integration; } + _FORCE_INLINE_ bool get_omit_force_integration() const { return omit_force_integration; } + + _FORCE_INLINE_ void set_linear_velocity(const Vector3& p_velocity) {linear_velocity=p_velocity; } + _FORCE_INLINE_ Vector3 get_linear_velocity() const { return linear_velocity; } + + _FORCE_INLINE_ void set_angular_velocity(const Vector3& p_velocity) { angular_velocity=p_velocity; } + _FORCE_INLINE_ Vector3 get_angular_velocity() const { return angular_velocity; } + + _FORCE_INLINE_ const Vector3& get_biased_linear_velocity() const { return biased_linear_velocity; } + _FORCE_INLINE_ const Vector3& get_biased_angular_velocity() const { return biased_angular_velocity; } + + _FORCE_INLINE_ void apply_impulse(const Vector3& p_pos, const Vector3& p_j) { + + linear_velocity += p_j * _inv_mass; + angular_velocity += _inv_inertia_tensor.xform( p_pos.cross(p_j) ); + } + + _FORCE_INLINE_ void apply_bias_impulse(const Vector3& p_pos, const Vector3& p_j) { + + biased_linear_velocity += p_j * _inv_mass; + biased_angular_velocity += _inv_inertia_tensor.xform( p_pos.cross(p_j) ); + } + + _FORCE_INLINE_ void apply_torque_impulse(const Vector3& p_j) { + + angular_velocity += _inv_inertia_tensor.xform(p_j); + } + + _FORCE_INLINE_ void add_force(const Vector3& p_force, const Vector3& p_pos) { + + applied_force += p_force; + applied_torque += p_pos.cross(p_force); + } + + void set_active(bool p_active); + _FORCE_INLINE_ bool is_active() const { return active; } + + void set_param(PhysicsServer::BodyParameter p_param, float); + float get_param(PhysicsServer::BodyParameter p_param) const; + + void set_mode(PhysicsServer::BodyMode p_mode); + PhysicsServer::BodyMode get_mode() const; + + void set_state(PhysicsServer::BodyState p_state, const Variant& p_variant); + Variant get_state(PhysicsServer::BodyState p_state) const; + + void set_applied_force(const Vector3& p_force) { applied_force=p_force; } + Vector3 get_applied_force() const { return applied_force; } + + void set_applied_torque(const Vector3& p_torque) { applied_torque=p_torque; } + Vector3 get_applied_torque() const { return applied_torque; } + + _FORCE_INLINE_ void set_continuous_collision_detection(bool p_enable) { continuous_cd=p_enable; } + _FORCE_INLINE_ bool is_continuous_collision_detection_enabled() const { return continuous_cd; } + + void set_space(SpaceSW *p_space); + + void update_inertias(); + + _FORCE_INLINE_ real_t get_inv_mass() const { return _inv_mass; } + _FORCE_INLINE_ Vector3 get_inv_inertia() const { return _inv_inertia; } + _FORCE_INLINE_ Matrix3 get_inv_inertia_tensor() const { return _inv_inertia_tensor; } + _FORCE_INLINE_ real_t get_friction() const { return friction; } + _FORCE_INLINE_ Vector3 get_gravity() const { return gravity; } + _FORCE_INLINE_ real_t get_density() const { return density; } + _FORCE_INLINE_ real_t get_bounce() const { return bounce; } + + _FORCE_INLINE_ void set_axis_lock(PhysicsServer::BodyAxisLock p_lock) { axis_lock=p_lock; } + _FORCE_INLINE_ PhysicsServer::BodyAxisLock get_axis_lock() const { return axis_lock; } + + void integrate_forces(real_t p_step); + void integrate_velocities(real_t p_step); + + void simulate_motion(const Transform& p_xform,real_t p_step); + void call_queries(); + void wakeup_neighbours(); + + bool sleep_test(real_t p_step); + + BodySW(); + ~BodySW(); + +}; + + +//add contact inline + +void BodySW::add_contact(const Vector3& p_local_pos,const Vector3& p_local_normal, float p_depth, int p_local_shape, const Vector3& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector3& p_collider_velocity_at_pos) { + + int c_max=contacts.size(); + + if (c_max==0) + return; + + Contact *c = &contacts[0]; + + + int idx=-1; + + if (contact_count<c_max) { + idx=contact_count++; + } else { + + float least_depth=1e20; + int least_deep=-1; + for(int i=0;i<c_max;i++) { + + if (i==0 || c[i].depth<least_depth) { + least_deep=i; + least_depth=c[i].depth; + } + } + + if (least_deep>=0 && least_depth<p_depth) { + + idx=least_deep; + } + if (idx==-1) + return; //none least deepe than this + } + + c[idx].local_pos=p_local_pos; + c[idx].local_normal=p_local_normal; + c[idx].depth=p_depth; + c[idx].local_shape=p_local_shape; + c[idx].collider_pos=p_collider_pos; + c[idx].collider_shape=p_collider_shape; + c[idx].collider_instance_id=p_collider_instance_id; + c[idx].collider=p_collider; + c[idx].collider_velocity_at_pos=p_collider_velocity_at_pos; + +} + + +class PhysicsDirectBodyStateSW : public PhysicsDirectBodyState { + + OBJ_TYPE( PhysicsDirectBodyStateSW, PhysicsDirectBodyState ); + +public: + + static PhysicsDirectBodyStateSW *singleton; + BodySW *body; + real_t step; + + virtual Vector3 get_total_gravity() const { return body->get_gravity(); } // get gravity vector working on this body space/area + virtual float get_total_density() const { return body->get_density(); } // get density of this body space/area + + virtual float get_inverse_mass() const { return body->get_inv_mass(); } // get the mass + virtual Vector3 get_inverse_inertia() const { return body->get_inv_inertia(); } // get density of this body space + virtual Matrix3 get_inverse_inertia_tensor() const { return body->get_inv_inertia_tensor(); } // get density of this body space + + virtual void set_linear_velocity(const Vector3& p_velocity) { body->set_linear_velocity(p_velocity); } + virtual Vector3 get_linear_velocity() const { return body->get_linear_velocity(); } + + virtual void set_angular_velocity(const Vector3& p_velocity) { body->set_angular_velocity(p_velocity); } + virtual Vector3 get_angular_velocity() const { return body->get_angular_velocity(); } + + virtual void set_transform(const Transform& p_transform) { body->set_state(PhysicsServer::BODY_STATE_TRANSFORM,p_transform); } + virtual Transform get_transform() const { return body->get_transform(); } + + virtual void add_force(const Vector3& p_force, const Vector3& p_pos) { body->add_force(p_force,p_pos); } + + virtual void set_sleep_state(bool p_enable) { body->set_active(!p_enable); } + virtual bool is_sleeping() const { return !body->is_active(); } + + virtual int get_contact_count() const { return body->contact_count; } + + virtual Vector3 get_contact_local_pos(int p_contact_idx) const { + ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector3()); + return body->contacts[p_contact_idx].local_pos; + } + virtual Vector3 get_contact_local_normal(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector3()); return body->contacts[p_contact_idx].local_normal; } + virtual int get_contact_local_shape(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,-1); return body->contacts[p_contact_idx].local_shape; } + + virtual RID get_contact_collider(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,RID()); return body->contacts[p_contact_idx].collider; } + virtual Vector3 get_contact_collider_pos(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector3()); return body->contacts[p_contact_idx].collider_pos; } + virtual ObjectID get_contact_collider_id(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,0); return body->contacts[p_contact_idx].collider_instance_id; } + virtual int get_contact_collider_shape(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,0); return body->contacts[p_contact_idx].collider_shape; } + virtual Vector3 get_contact_collider_velocity_at_pos(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector3()); return body->contacts[p_contact_idx].collider_velocity_at_pos; } + + virtual PhysicsDirectSpaceState* get_space_state(); + + + virtual real_t get_step() const { return step; } + PhysicsDirectBodyStateSW() { singleton=this; body=NULL; } +}; + + +#endif // BODY__SW_H diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp index 072f11aa52..aff60b5881 100644 --- a/servers/physics/physics_server_sw.cpp +++ b/servers/physics/physics_server_sw.cpp @@ -695,6 +695,25 @@ void PhysicsServerSW::body_set_axis_velocity(RID p_body, const Vector3& p_axis_v }; + +void PhysicsServerSW::body_set_axis_lock(RID p_body,BodyAxisLock p_lock) { + + BodySW *body = body_owner.get(p_body); + ERR_FAIL_COND(!body); + body->set_axis_lock(p_lock); + +} + +PhysicsServerSW::BodyAxisLock PhysicsServerSW::body_get_axis_lock(RID p_body) const{ + + const BodySW *body = body_owner.get(p_body); + ERR_FAIL_COND_V(!body,BODY_AXIS_LOCK_DISABLED); + return body->get_axis_lock(); + +} + + + void PhysicsServerSW::body_add_collision_exception(RID p_body, RID p_body_b) { BodySW *body = body_owner.get(p_body); diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h index 2a46ba65fb..0822d76936 100644 --- a/servers/physics/physics_server_sw.h +++ b/servers/physics/physics_server_sw.h @@ -167,6 +167,9 @@ public: virtual void body_apply_impulse(RID p_body, const Vector3& p_pos, const Vector3& p_impulse); virtual void body_set_axis_velocity(RID p_body, const Vector3& p_axis_velocity); + virtual void body_set_axis_lock(RID p_body,BodyAxisLock p_lock); + virtual BodyAxisLock body_get_axis_lock(RID p_body) const; + virtual void body_add_collision_exception(RID p_body, RID p_body_b); virtual void body_remove_collision_exception(RID p_body, RID p_body_b); virtual void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions); diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp index 669240b8da..ee169cde28 100644 --- a/servers/physics_2d/body_pair_2d_sw.cpp +++ b/servers/physics_2d/body_pair_2d_sw.cpp @@ -234,7 +234,7 @@ bool BodyPair2DSW::setup(float p_step) { //cannot collide - if (A->is_shape_set_as_trigger(shape_A) || B->is_shape_set_as_trigger(shape_B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode()<=Physics2DServer::BODY_MODE_KINEMATIC && B->get_mode()<=Physics2DServer::BODY_MODE_KINEMATIC)) { + if ((A->get_layer_mask()&B->get_layer_mask())==0 || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode()<=Physics2DServer::BODY_MODE_KINEMATIC && B->get_mode()<=Physics2DServer::BODY_MODE_KINEMATIC)) { collided=false; return false; } @@ -343,6 +343,11 @@ bool BodyPair2DSW::setup(float p_step) { } } + if (A->is_shape_set_as_trigger(shape_A) || B->is_shape_set_as_trigger(shape_B)) { + c.active=false; + collided=false; + } + // Precompute normal mass, tangent mass, and bias. real_t rnA = c.rA.dot(c.normal); real_t rnB = c.rB.dot(c.normal); diff --git a/servers/physics_2d/collision_object_2d_sw.cpp b/servers/physics_2d/collision_object_2d_sw.cpp index e07dca472b..277a286144 100644 --- a/servers/physics_2d/collision_object_2d_sw.cpp +++ b/servers/physics_2d/collision_object_2d_sw.cpp @@ -219,4 +219,5 @@ CollisionObject2DSW::CollisionObject2DSW(Type p_type) { space=NULL; instance_id=0; user_mask=0; + layer_mask=1; } diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h index 8138cfcc69..cc7f8f50bd 100644 --- a/servers/physics_2d/collision_object_2d_sw.h +++ b/servers/physics_2d/collision_object_2d_sw.h @@ -66,6 +66,7 @@ private: Matrix32 transform; Matrix32 inv_transform; uint32_t user_mask; + uint32_t layer_mask; bool _static; void _update_shapes(); @@ -121,6 +122,9 @@ public: void set_user_mask(uint32_t p_mask) {user_mask=p_mask;} _FORCE_INLINE_ uint32_t get_user_mask() const { return user_mask; } + void set_layer_mask(uint32_t p_mask) {layer_mask=p_mask;} + _FORCE_INLINE_ uint32_t get_layer_mask() const { return layer_mask; } + void remove_shape(Shape2DSW *p_shape); void remove_shape(int p_index); diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp index ee29d3aeff..2171a9c2c4 100644 --- a/servers/physics_2d/physics_2d_server_sw.cpp +++ b/servers/physics_2d/physics_2d_server_sw.cpp @@ -652,6 +652,22 @@ uint32_t Physics2DServerSW::body_get_object_instance_ID(RID p_body) const { return body->get_instance_id(); }; +void Physics2DServerSW::body_set_layer_mask(RID p_body, uint32_t p_flags) { + + Body2DSW *body = body_owner.get(p_body); + ERR_FAIL_COND(!body); + body->set_layer_mask(p_flags); + +}; + +uint32_t Physics2DServerSW::body_get_layer_mask(RID p_body, uint32_t p_flags) const { + + Body2DSW *body = body_owner.get(p_body); + ERR_FAIL_COND_V(!body,0); + + return body->get_layer_mask(); +}; + void Physics2DServerSW::body_set_user_mask(RID p_body, uint32_t p_flags) { diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h index e50bb0ab96..09ca029127 100644 --- a/servers/physics_2d/physics_2d_server_sw.h +++ b/servers/physics_2d/physics_2d_server_sw.h @@ -161,6 +161,9 @@ public: virtual void body_set_continuous_collision_detection_mode(RID p_body,CCDMode p_mode); virtual CCDMode body_get_continuous_collision_detection_mode(RID p_body) const; + virtual void body_set_layer_mask(RID p_body, uint32_t p_mask); + virtual uint32_t body_get_layer_mask(RID p_body, uint32_t p_mask) const; + virtual void body_set_user_mask(RID p_body, uint32_t p_mask); virtual uint32_t body_get_user_mask(RID p_body, uint32_t p_mask) const; diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index d1aec92984..5fbf828c38 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -31,9 +31,9 @@ #include "physics_2d_server_sw.h" -_FORCE_INLINE_ static bool _match_object_type_query(CollisionObject2DSW *p_object, uint32_t p_user_mask, uint32_t p_type_mask) { +_FORCE_INLINE_ static bool _match_object_type_query(CollisionObject2DSW *p_object, uint32_t p_layer_mask, uint32_t p_type_mask) { - if (p_user_mask && !(p_object->get_user_mask()&p_user_mask)) + if ((p_object->get_layer_mask()&p_layer_mask)==0) return false; if (p_object->get_type()==CollisionObject2DSW::TYPE_AREA && !(p_type_mask&Physics2DDirectSpaceState::TYPE_MASK_AREA)) @@ -45,7 +45,7 @@ _FORCE_INLINE_ static bool _match_object_type_query(CollisionObject2DSW *p_objec } -bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2& p_from, const Vector2& p_to,RayResult &r_result,const Set<RID>& p_exclude,uint32_t p_user_mask,uint32_t p_object_type_mask) { +bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2& p_from, const Vector2& p_to,RayResult &r_result,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { @@ -70,7 +70,7 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2& p_from, const Vec for(int i=0;i<amount;i++) { - if (!_match_object_type_query(space->intersection_query_results[i],p_user_mask,p_object_type_mask)) + if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask)) continue; if (p_exclude.has( space->intersection_query_results[i]->get_self())) @@ -135,7 +135,7 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2& p_from, const Vec } -int Physics2DDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude,uint32_t p_user_mask,uint32_t p_object_type_mask) { +int Physics2DDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { if (p_result_max<=0) return 0; @@ -153,7 +153,7 @@ int Physics2DDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Matri for(int i=0;i<amount;i++) { - if (!_match_object_type_query(space->intersection_query_results[i],p_user_mask,p_object_type_mask)) + if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask)) continue; if (p_exclude.has( space->intersection_query_results[i]->get_self())) @@ -182,7 +182,7 @@ int Physics2DDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Matri -bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude,uint32_t p_user_mask,uint32_t p_object_type_mask) { +bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { @@ -204,7 +204,7 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32 for(int i=0;i<amount;i++) { - if (!_match_object_type_query(space->intersection_query_results[i],p_user_mask,p_object_type_mask)) + if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask)) continue; if (p_exclude.has( space->intersection_query_results[i]->get_self())) @@ -267,7 +267,7 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32 } -bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,Vector2 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude,uint32_t p_user_mask,uint32_t p_object_type_mask) { +bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,Vector2 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { if (p_result_max<=0) @@ -301,7 +301,7 @@ bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Matrix32& p_s for(int i=0;i<amount;i++) { - if (!_match_object_type_query(space->intersection_query_results[i],p_user_mask,p_object_type_mask)) + if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask)) continue; const CollisionObject2DSW *col_obj=space->intersection_query_results[i]; @@ -353,7 +353,7 @@ static void _rest_cbk_result(const Vector2& p_point_A,const Vector2& p_point_B,v } -bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude,uint32_t p_user_mask,uint32_t p_object_type_mask) { +bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { Shape2DSW *shape = static_cast<Physics2DServerSW*>(Physics2DServer::get_singleton())->shape_owner.get(p_shape); @@ -373,7 +373,7 @@ bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Matrix32& p_shape for(int i=0;i<amount;i++) { - if (!_match_object_type_query(space->intersection_query_results[i],p_user_mask,p_object_type_mask)) + if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask)) continue; const CollisionObject2DSW *col_obj=space->intersection_query_results[i]; diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h index 9d3dfae9b5..bd41097fba 100644 --- a/servers/physics_2d/space_2d_sw.h +++ b/servers/physics_2d/space_2d_sw.h @@ -46,11 +46,11 @@ public: Space2DSW *space; - virtual bool intersect_ray(const Vector2& p_from, const Vector2& p_to,RayResult &r_result,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_user_mask=0,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); - virtual int intersect_shape(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_user_mask=0,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); - virtual bool cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_user_mask=0,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); - virtual bool collide_shape(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,Vector2 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_user_mask=0,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); - virtual bool rest_info(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_user_mask=0,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); + virtual bool intersect_ray(const Vector2& p_from, const Vector2& p_to,RayResult &r_result,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); + virtual int intersect_shape(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); + virtual bool cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); + virtual bool collide_shape(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,Vector2 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); + virtual bool rest_info(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); Physics2DDirectSpaceStateSW(); }; diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp index 0851ad59ef..9cbd7414bd 100644 --- a/servers/physics_2d_server.cpp +++ b/servers/physics_2d_server.cpp @@ -329,8 +329,12 @@ void Physics2DServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("body_get_continuous_collision_detection_mode","body"),&Physics2DServer::body_get_continuous_collision_detection_mode); - //ObjectTypeDB::bind_method(_MD("body_set_user_flags","flags""),&Physics2DServer::body_set_shape,DEFVAL(Matrix32)); - //ObjectTypeDB::bind_method(_MD("body_get_user_flags","body","shape_idx","shape"),&Physics2DServer::body_get_shape); + ObjectTypeDB::bind_method(_MD("body_set_layer_mask","body","mask"),&Physics2DServer::body_set_layer_mask); + ObjectTypeDB::bind_method(_MD("body_get_layer_mask","body"),&Physics2DServer::body_get_layer_mask); + + ObjectTypeDB::bind_method(_MD("body_set_user_mask","body","mask"),&Physics2DServer::body_set_user_mask); + ObjectTypeDB::bind_method(_MD("body_get_user_mask","body"),&Physics2DServer::body_get_user_mask); + ObjectTypeDB::bind_method(_MD("body_set_param","body","param","value"),&Physics2DServer::body_set_param); ObjectTypeDB::bind_method(_MD("body_get_param","body","param"),&Physics2DServer::body_get_param); diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h index 172fa1699b..def1e69992 100644 --- a/servers/physics_2d_server.h +++ b/servers/physics_2d_server.h @@ -88,9 +88,9 @@ class Physics2DDirectSpaceState : public Object { OBJ_TYPE( Physics2DDirectSpaceState, Object ); - Variant _intersect_ray(const Vector2& p_from, const Vector2& p_to,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_user_mask=0); - Variant _intersect_shape(const RID& p_shape, const Matrix32& p_xform,int p_result_max=64,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_user_mask=0); - Variant _cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_user_mask=0); + Variant _intersect_ray(const Vector2& p_from, const Vector2& p_to,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_layers=0); + Variant _intersect_shape(const RID& p_shape, const Matrix32& p_xform,int p_result_max=64,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_layers=0); + Variant _cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_layers=0); protected: @@ -118,7 +118,7 @@ public: int shape; }; - virtual bool intersect_ray(const Vector2& p_from, const Vector2& p_to,RayResult &r_result,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_user_mask=0,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0; + virtual bool intersect_ray(const Vector2& p_from, const Vector2& p_to,RayResult &r_result,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0; struct ShapeResult { @@ -129,13 +129,13 @@ public: }; - virtual int intersect_shape(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_user_mask=0,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0; + virtual int intersect_shape(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0; - virtual bool cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_user_mask=0,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0; + virtual bool cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0; - virtual bool collide_shape(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,Vector2 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_user_mask=0,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0; + virtual bool collide_shape(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,Vector2 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0; struct ShapeRestInfo { @@ -148,7 +148,7 @@ public: }; - virtual bool rest_info(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_user_mask=0,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0; + virtual bool rest_info(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0; Physics2DDirectSpaceState(); @@ -338,6 +338,9 @@ public: virtual void body_set_continuous_collision_detection_mode(RID p_body,CCDMode p_mode)=0; virtual CCDMode body_get_continuous_collision_detection_mode(RID p_body) const=0; + virtual void body_set_layer_mask(RID p_body, uint32_t p_mask)=0; + virtual uint32_t body_get_layer_mask(RID p_body, uint32_t p_mask) const=0; + virtual void body_set_user_mask(RID p_body, uint32_t p_mask)=0; virtual uint32_t body_get_user_mask(RID p_body, uint32_t p_mask) const=0; diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp index f1b4627b6c..69c82519dd 100644 --- a/servers/physics_server.cpp +++ b/servers/physics_server.cpp @@ -315,6 +315,9 @@ void PhysicsServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("body_apply_impulse","body","pos","impulse"),&PhysicsServer::body_apply_impulse); ObjectTypeDB::bind_method(_MD("body_set_axis_velocity","body","axis_velocity"),&PhysicsServer::body_set_axis_velocity); + ObjectTypeDB::bind_method(_MD("body_set_axis_lock","body","axis"),&PhysicsServer::body_set_axis_lock); + ObjectTypeDB::bind_method(_MD("body_get_axis_lock","body"),&PhysicsServer::body_set_axis_lock); + ObjectTypeDB::bind_method(_MD("body_add_collision_exception","body","excepted_body"),&PhysicsServer::body_add_collision_exception); ObjectTypeDB::bind_method(_MD("body_remove_collision_exception","body","excepted_body"),&PhysicsServer::body_remove_collision_exception); // virtual void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions)=0; diff --git a/servers/physics_server.h b/servers/physics_server.h index 4276a4dab8..da51dbc8e1 100644 --- a/servers/physics_server.h +++ b/servers/physics_server.h @@ -341,6 +341,16 @@ public: virtual void body_apply_impulse(RID p_body, const Vector3& p_pos, const Vector3& p_impulse)=0; virtual void body_set_axis_velocity(RID p_body, const Vector3& p_axis_velocity)=0; + enum BodyAxisLock { + BODY_AXIS_LOCK_DISABLED, + BODY_AXIS_LOCK_X, + BODY_AXIS_LOCK_Y, + BODY_AXIS_LOCK_Z, + }; + + virtual void body_set_axis_lock(RID p_body,BodyAxisLock p_lock)=0; + virtual BodyAxisLock body_get_axis_lock(RID p_body) const=0; + //fix virtual void body_add_collision_exception(RID p_body, RID p_body_b)=0; virtual void body_remove_collision_exception(RID p_body, RID p_body_b)=0; @@ -420,6 +430,7 @@ VARIANT_ENUM_CAST( PhysicsServer::AreaSpaceOverrideMode ); VARIANT_ENUM_CAST( PhysicsServer::BodyMode ); VARIANT_ENUM_CAST( PhysicsServer::BodyParameter ); VARIANT_ENUM_CAST( PhysicsServer::BodyState ); +VARIANT_ENUM_CAST( PhysicsServer::BodyAxisLock ); //VARIANT_ENUM_CAST( PhysicsServer::JointParam ); //VARIANT_ENUM_CAST( PhysicsServer::JointType ); //VARIANT_ENUM_CAST( PhysicsServer::DampedStringParam ); diff --git a/servers/visual_server.h b/servers/visual_server.h index 4bf2ecab68..1e540a6753 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -682,6 +682,7 @@ public: virtual Variant environment_get_background_param(RID p_env,EnvironmentBGParam p_param) const=0; enum EnvironmentFx { + ENV_FX_FXAA, ENV_FX_GLOW, ENV_FX_DOF_BLUR, ENV_FX_HDR, @@ -815,6 +816,7 @@ public: INSTANCE_FLAG_RECEIVE_SHADOWS, INSTANCE_FLAG_DEPH_SCALE, INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS, + INSTANCE_FLAG_USE_BAKED_LIGHT_VOLUME, INSTANCE_FLAG_MAX }; diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index fc644e76c5..9821dad872 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -85,12 +85,15 @@ #include "plugins/animation_tree_editor_plugin.h" #include "plugins/tile_set_editor_plugin.h" #include "plugins/animation_player_editor_plugin.h" +#include "plugins/baked_light_editor_plugin.h" // end #include "tools/editor/io_plugins/editor_texture_import_plugin.h" #include "tools/editor/io_plugins/editor_scene_import_plugin.h" #include "tools/editor/io_plugins/editor_font_import_plugin.h" #include "tools/editor/io_plugins/editor_sample_import_plugin.h" #include "tools/editor/io_plugins/editor_translation_import_plugin.h" +#include "tools/editor/io_plugins/editor_mesh_import_plugin.h" + EditorNode *EditorNode::singleton=NULL; @@ -4013,6 +4016,7 @@ EditorNode::EditorNode() { _scene_import->add_importer(_collada_import); editor_import_export->add_import_plugin( _scene_import); editor_import_export->add_import_plugin( Ref<EditorSceneAnimationImportPlugin>( memnew(EditorSceneAnimationImportPlugin(this)))); + editor_import_export->add_import_plugin( Ref<EditorMeshImportPlugin>( memnew(EditorMeshImportPlugin(this)))); editor_import_export->add_import_plugin( Ref<EditorFontImportPlugin>( memnew(EditorFontImportPlugin(this)))); editor_import_export->add_import_plugin( Ref<EditorSampleImportPlugin>( memnew(EditorSampleImportPlugin(this)))); editor_import_export->add_import_plugin( Ref<EditorTranslationImportPlugin>( memnew(EditorTranslationImportPlugin(this)))); @@ -4051,6 +4055,7 @@ EditorNode::EditorNode() { add_editor_plugin( memnew( Particles2DEditorPlugin(this) ) ); add_editor_plugin( memnew( Path2DEditorPlugin(this) ) ); add_editor_plugin( memnew( PathEditorPlugin(this) ) ); + add_editor_plugin( memnew( BakedLightEditorPlugin(this) ) ); for(int i=0;i<EditorPlugins::get_plugin_count();i++) add_editor_plugin( EditorPlugins::create(i,this) ); diff --git a/tools/editor/io_plugins/editor_mesh_import_plugin.cpp b/tools/editor/io_plugins/editor_mesh_import_plugin.cpp new file mode 100644 index 0000000000..d76a778433 --- /dev/null +++ b/tools/editor/io_plugins/editor_mesh_import_plugin.cpp @@ -0,0 +1,555 @@ +#include "editor_mesh_import_plugin.h" + +#include "scene/gui/file_dialog.h" +#include "tools/editor/editor_dir_dialog.h" +#include "tools/editor/editor_node.h" +#include "tools/editor/property_editor.h" +#include "scene/resources/sample.h" +#include "io/resource_saver.h" +#include "os/file_access.h" +#include "io/marshalls.h" +#include "scene/resources/surface_tool.h" + +class _EditorMeshImportOptions : public Object { + + OBJ_TYPE(_EditorMeshImportOptions,Object); +public: + + + bool generate_tangents; + bool generate_normals; + bool flip_faces; + bool smooth_shading; + bool weld_vertices; + bool import_material; + bool import_textures; + float weld_tolerance; + + + bool _set(const StringName& p_name, const Variant& p_value) { + + String n = p_name; + if (n=="generate/tangents") + generate_tangents=p_value; + else if (n=="generate/normals") + generate_normals=p_value; + else if (n=="import/materials") + import_material=p_value; + else if (n=="import/textures") + import_textures=p_value; + else if (n=="force/flip_faces") + flip_faces=p_value; + else if (n=="force/smooth_shading") + smooth_shading=p_value; + else if (n=="force/weld_vertices") + weld_vertices=p_value; + else if (n=="force/weld_tolerance") + weld_tolerance=p_value; + else + return false; + + return true; + + } + + bool _get(const StringName& p_name,Variant &r_ret) const{ + + String n = p_name; + if (n=="generate/tangents") + r_ret=generate_tangents; + else if (n=="generate/normals") + r_ret=generate_normals; + else if (n=="import/materials") + r_ret=import_material; + else if (n=="import/textures") + r_ret=import_textures; + else if (n=="force/flip_faces") + r_ret=flip_faces; + else if (n=="force/smooth_shading") + r_ret=smooth_shading; + else if (n=="force/weld_vertices") + r_ret=weld_vertices; + else if (n=="force/weld_tolerance") + r_ret=weld_tolerance; + else + return false; + + return true; + + } + void _get_property_list( List<PropertyInfo> *p_list) const{ + + p_list->push_back(PropertyInfo(Variant::BOOL,"generate/tangents")); + p_list->push_back(PropertyInfo(Variant::BOOL,"generate/normals")); + //not for nowp + //p_list->push_back(PropertyInfo(Variant::BOOL,"import/materials")); + //p_list->push_back(PropertyInfo(Variant::BOOL,"import/textures")); + p_list->push_back(PropertyInfo(Variant::BOOL,"force/flip_faces")); + p_list->push_back(PropertyInfo(Variant::BOOL,"force/smooth_shading")); + p_list->push_back(PropertyInfo(Variant::BOOL,"force/weld_vertices")); + p_list->push_back(PropertyInfo(Variant::REAL,"force/weld_tolerance",PROPERTY_HINT_RANGE,"0.00001,16,0.00001")); + //p_list->push_back(PropertyInfo(Variant::BOOL,"compress/enable")); + //p_list->push_back(PropertyInfo(Variant::INT,"compress/bitrate",PROPERTY_HINT_ENUM,"64,96,128,192")); + + + } + + + static void _bind_methods() { + + + ADD_SIGNAL( MethodInfo("changed")); + } + + + _EditorMeshImportOptions() { + + generate_tangents=true; + generate_normals=true; + flip_faces=false; + smooth_shading=false; + weld_vertices=true; + weld_tolerance=0.0001; + import_material=false; + import_textures=false; + + } + + +}; + +class EditorMeshImportDialog : public ConfirmationDialog { + + OBJ_TYPE(EditorMeshImportDialog,ConfirmationDialog); + + EditorMeshImportPlugin *plugin; + + LineEdit *import_path; + LineEdit *save_path; + FileDialog *file_select; + EditorDirDialog *save_select; + ConfirmationDialog *error_dialog; + PropertyEditor *option_editor; + + _EditorMeshImportOptions *options; + + +public: + + void _choose_files(const Vector<String>& p_path) { + + String files; + for(int i=0;i<p_path.size();i++) { + + if (i>0) + files+=","; + files+=p_path[i]; + } + /* + if (p_path.size()) { + String srctex=p_path[0]; + String ipath = EditorImportDB::get_singleton()->find_source_path(srctex); + + if (ipath!="") + save_path->set_text(ipath.get_base_dir()); + }*/ + import_path->set_text(files); + + } + void _choose_save_dir(const String& p_path) { + + save_path->set_text(p_path); + } + + void _browse() { + + file_select->popup_centered_ratio(); + } + + void _browse_target() { + + save_select->popup_centered_ratio(); + + } + + + void popup_import(const String& p_path) { + + popup_centered(Size2(400,400)); + if (p_path!="") { + + Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_path); + ERR_FAIL_COND(!rimd.is_valid()); + + save_path->set_text(p_path.get_base_dir()); + List<String> opts; + rimd->get_options(&opts); + for(List<String>::Element *E=opts.front();E;E=E->next()) { + + options->_set(E->get(),rimd->get_option(E->get())); + } + + String src = ""; + for(int i=0;i<rimd->get_source_count();i++) { + if (i>0) + src+=","; + src+=EditorImportPlugin::expand_source_path(rimd->get_source_path(i)); + } + import_path->set_text(src); + } + } + + + void _import() { + + Vector<String> meshes = import_path->get_text().split(","); + + if (meshes.size()==0) { + error_dialog->set_text("No meshes to import!"); + error_dialog->popup_centered(Size2(200,100)); + } + + for(int i=0;i<meshes.size();i++) { + + Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata ); + + List<PropertyInfo> pl; + options->_get_property_list(&pl); + for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) { + + Variant v; + String opt=E->get().name; + options->_get(opt,v); + imd->set_option(opt,v); + + } + + imd->add_source(EditorImportPlugin::validate_source_path(meshes[i])); + + String dst = save_path->get_text(); + if (dst=="") { + error_dialog->set_text("Save path is empty!"); + error_dialog->popup_centered(Size2(200,100)); + } + + dst = dst.plus_file(meshes[i].get_file().basename()+".msh"); + + Error err = plugin->import(dst,imd); + } + + hide(); + + } + + + void _notification(int p_what) { + + + if (p_what==NOTIFICATION_ENTER_SCENE) { + + option_editor->edit(options); + } + } + + static void _bind_methods() { + + + ObjectTypeDB::bind_method("_choose_files",&EditorMeshImportDialog::_choose_files); + ObjectTypeDB::bind_method("_choose_save_dir",&EditorMeshImportDialog::_choose_save_dir); + ObjectTypeDB::bind_method("_import",&EditorMeshImportDialog::_import); + ObjectTypeDB::bind_method("_browse",&EditorMeshImportDialog::_browse); + ObjectTypeDB::bind_method("_browse_target",&EditorMeshImportDialog::_browse_target); + // ADD_SIGNAL( MethodInfo("imported",PropertyInfo(Variant::OBJECT,"scene")) ); + } + + EditorMeshImportDialog(EditorMeshImportPlugin *p_plugin) { + + plugin=p_plugin; + + + set_title("Single Mesh Import"); + + VBoxContainer *vbc = memnew( VBoxContainer ); + add_child(vbc); + set_child_rect(vbc); + + + HBoxContainer *hbc = memnew( HBoxContainer ); + vbc->add_margin_child("Source Mesh(es):",hbc); + + import_path = memnew( LineEdit ); + import_path->set_h_size_flags(SIZE_EXPAND_FILL); + hbc->add_child(import_path); + + Button * import_choose = memnew( Button ); + import_choose->set_text(" .. "); + hbc->add_child(import_choose); + + import_choose->connect("pressed", this,"_browse"); + + hbc = memnew( HBoxContainer ); + vbc->add_margin_child("Target Path:",hbc); + + save_path = memnew( LineEdit ); + save_path->set_h_size_flags(SIZE_EXPAND_FILL); + hbc->add_child(save_path); + + Button * save_choose = memnew( Button ); + save_choose->set_text(" .. "); + hbc->add_child(save_choose); + + save_choose->connect("pressed", this,"_browse_target"); + + file_select = memnew(FileDialog); + file_select->set_access(FileDialog::ACCESS_FILESYSTEM); + add_child(file_select); + file_select->set_mode(FileDialog::MODE_OPEN_FILES); + file_select->connect("files_selected", this,"_choose_files"); + file_select->add_filter("*.obj ; Wavefront OBJ"); + save_select = memnew( EditorDirDialog ); + add_child(save_select); + + // save_select->set_mode(FileDialog::MODE_OPEN_DIR); + save_select->connect("dir_selected", this,"_choose_save_dir"); + + get_ok()->connect("pressed", this,"_import"); + get_ok()->set_text("Import"); + + + error_dialog = memnew ( ConfirmationDialog ); + add_child(error_dialog); + error_dialog->get_ok()->set_text("Accept"); + // error_dialog->get_cancel()->hide(); + + set_hide_on_ok(false); + options = memnew( _EditorMeshImportOptions ); + + option_editor = memnew( PropertyEditor ); + option_editor->hide_top_label(); + vbc->add_margin_child("Options:",option_editor,true); + } + + ~EditorMeshImportDialog() { + memdelete(options); + } + +}; + + +String EditorMeshImportPlugin::get_name() const { + + return "mesh"; +} +String EditorMeshImportPlugin::get_visible_name() const{ + + return "3D Mesh"; +} +void EditorMeshImportPlugin::import_dialog(const String& p_from){ + + dialog->popup_import(p_from); +} +Error EditorMeshImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from){ + + + ERR_FAIL_COND_V(p_from->get_source_count()!=1,ERR_INVALID_PARAMETER); + + Ref<ResourceImportMetadata> from=p_from; + + String src_path=EditorImportPlugin::expand_source_path(from->get_source_path(0)); + FileAccessRef f = FileAccess::open(src_path,FileAccess::READ); + ERR_FAIL_COND_V(!f,ERR_CANT_OPEN); + + Ref<Mesh> mesh; + Map<String,Ref<Material> > name_map; + + if (FileAccess::exists(p_path)) { + mesh=ResourceLoader::load(p_path,"Mesh"); + if (mesh.is_valid()) { + for(int i=0;i<mesh->get_surface_count();i++) { + + if (!mesh->surface_get_material(i).is_valid()) + continue; + String name; + if (mesh->surface_get_name(i)!="") + name=mesh->surface_get_name(i); + else + name="Surface "+itos(i+1); + + name_map[name]=mesh->surface_get_material(i); + } + + while(mesh->get_surface_count()) { + mesh->surface_remove(0); + } + } + } + + if (!mesh.is_valid()) + mesh = Ref<Mesh>( memnew( Mesh ) ); + + + bool generate_normals=from->get_option("generate/normals"); + bool generate_tangents=from->get_option("generate/tangents"); + bool flip_faces=from->get_option("force/flip_faces"); + bool force_smooth=from->get_option("force/smooth_shading"); + bool weld_vertices=from->get_option("force/weld_vertices"); + float weld_tolerance=from->get_option("force/weld_tolerance"); + Vector<Vector3> vertices; + Vector<Vector3> normals; + Vector<Vector2> uvs; + String name; + + Ref<SurfaceTool> surf_tool = memnew( SurfaceTool) ; + surf_tool->begin(Mesh::PRIMITIVE_TRIANGLES); + if (force_smooth) + surf_tool->add_smooth_group(true); + int has_index_data=false; + + while(true) { + + + String l = f->get_line().strip_edges(); + + if (l.begins_with("v ")) { + //vertex + Vector<String> v = l.split(" ",false); + ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA); + Vector3 vtx; + vtx.x=v[1].to_float(); + vtx.y=v[2].to_float(); + vtx.z=v[3].to_float(); + vertices.push_back(vtx); + } else if (l.begins_with("vt ")) { + //uv + Vector<String> v = l.split(" ",false); + ERR_FAIL_COND_V(v.size()<3,ERR_INVALID_DATA); + Vector2 uv; + uv.x=v[1].to_float(); + uv.y=v[2].to_float(); + uvs.push_back(uv); + + } else if (l.begins_with("vn ")) { + //normal + Vector<String> v = l.split(" ",false); + ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA); + Vector3 nrm; + nrm.x=v[1].to_float(); + nrm.y=v[2].to_float(); + nrm.z=v[3].to_float(); + normals.push_back(nrm); + } if (l.begins_with("f ")) { + //vertex + + has_index_data=true; + Vector<String> v = l.split(" ",false); + ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA); + + //not very fast, could be sped up + + + Vector<String> face[3]; + face[0] = v[1].split("/"); + face[1] = v[2].split("/"); + ERR_FAIL_COND_V(face[0].size()==0,ERR_PARSE_ERROR); + ERR_FAIL_COND_V(face[0].size()!=face[1].size(),ERR_PARSE_ERROR); + for(int i=2;i<v.size()-1;i++) { + + face[2] = v[i+1].split("/"); + ERR_FAIL_COND_V(face[0].size()!=face[2].size(),ERR_PARSE_ERROR); + for(int j=0;j<3;j++) { + + int idx=j; + + if (!flip_faces && idx<2) { + idx=1^idx; + } + + + if (face[idx].size()==3) { + int norm = face[idx][2].to_int()-1; + ERR_FAIL_INDEX_V(norm,normals.size(),ERR_PARSE_ERROR); + surf_tool->add_normal(normals[norm]); + } + + if (face[idx].size()>=2 && face[idx][1]!=String()) { + + int uv = face[idx][1].to_int()-1; + ERR_FAIL_INDEX_V(uv,uvs.size(),ERR_PARSE_ERROR); + surf_tool->add_uv(uvs[uv]); + } + + int vtx = face[idx][0].to_int()-1; + print_line("vtx: "+itos(vtx)+"/"+itos(vertices.size())); + ERR_FAIL_INDEX_V(vtx,vertices.size(),ERR_PARSE_ERROR); + + Vector3 vertex = vertices[vtx]; + if (weld_vertices) + vertex=vertex.snapped(weld_tolerance); + surf_tool->add_vertex(vertex); + } + + face[1]=face[2]; + } + } else if (l.begins_with("s ") && !force_smooth) { //smoothing + String what = l.substr(2,l.length()).strip_edges(); + if (what=="off") + surf_tool->add_smooth_group(false); + else + surf_tool->add_smooth_group(true); + + } else if (l.begins_with("o ") || f->eof_reached()) { //new surface or done + + if (has_index_data) { + //new object/surface + if (generate_normals || force_smooth) + surf_tool->generate_normals(); + if (uvs.size() && (normals.size() || generate_normals)) + surf_tool->generate_tangents(); + + surf_tool->index(); + mesh = surf_tool->commit(mesh); + if (name=="") + name="Surface "+itos(mesh->get_surface_count()-1); + mesh->surface_set_name(mesh->get_surface_count()-1,name); + name=""; + surf_tool->clear(); + surf_tool->begin(Mesh::PRIMITIVE_TRIANGLES); + if (force_smooth) + surf_tool->add_smooth_group(true); + + has_index_data=false; + + if (f->eof_reached()) + break; + } + + if (l.begins_with("o ")) //name + name=l.substr(2,l.length()).strip_edges(); + } + } + + + from->set_source_md5(0,FileAccess::get_md5(src_path)); + from->set_editor(get_name()); + mesh->set_import_metadata(from); + + //re-apply materials if exist + for(int i=0;i<mesh->get_surface_count();i++) { + + String n = mesh->surface_get_name(i); + if (name_map.has(n)) + mesh->surface_set_material(i,name_map[n]); + } + + Error err = ResourceSaver::save(p_path,mesh); + + return err; +} + + +EditorMeshImportPlugin::EditorMeshImportPlugin(EditorNode* p_editor) { + + dialog = memnew( EditorMeshImportDialog(this)); + p_editor->get_gui_base()->add_child(dialog); +} + diff --git a/tools/editor/io_plugins/editor_mesh_import_plugin.h b/tools/editor/io_plugins/editor_mesh_import_plugin.h new file mode 100644 index 0000000000..014954685d --- /dev/null +++ b/tools/editor/io_plugins/editor_mesh_import_plugin.h @@ -0,0 +1,29 @@ +#ifndef EDITOR_MESH_IMPORT_PLUGIN_H +#define EDITOR_MESH_IMPORT_PLUGIN_H + + +#include "tools/editor/editor_import_export.h" +#include "scene/resources/font.h" + +class EditorNode; +class EditorMeshImportDialog; + +class EditorMeshImportPlugin : public EditorImportPlugin { + + OBJ_TYPE(EditorMeshImportPlugin,EditorImportPlugin); + + EditorMeshImportDialog *dialog; + + +public: + + virtual String get_name() const; + virtual String get_visible_name() const; + virtual void import_dialog(const String& p_from=""); + virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from); + + + EditorMeshImportPlugin(EditorNode* p_editor); +}; + +#endif // EDITOR_MESH_IMPORT_PLUGIN_H diff --git a/tools/editor/io_plugins/editor_sample_import_plugin.cpp b/tools/editor/io_plugins/editor_sample_import_plugin.cpp index 55cba432e3..cd02156eef 100644 --- a/tools/editor/io_plugins/editor_sample_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_sample_import_plugin.cpp @@ -41,6 +41,12 @@ class _EditorSampleImportOptions : public Object { OBJ_TYPE(_EditorSampleImportOptions,Object); public: + enum CompressMode { + COMPRESS_MODE_DISABLED, + COMPRESS_MODE_RAM, + COMPRESS_MODE_DISK + }; + enum CompressBitrate { COMPRESS_64, COMPRESS_96, @@ -57,7 +63,7 @@ public: bool edit_normalize; bool edit_loop; - bool compress_enable; + CompressMode compress_mode; CompressBitrate compress_bitrate; @@ -78,8 +84,8 @@ public: edit_normalize=p_value; else if (n=="edit/loop") edit_loop=p_value; - else if (n=="compress/enable") - compress_enable=p_value; + else if (n=="compress/mode") + compress_mode=CompressMode(int(p_value)); else if (n=="compress/bitrate") compress_bitrate=CompressBitrate(int(p_value)); else @@ -106,8 +112,8 @@ public: r_ret=edit_normalize; else if (n=="edit/loop") r_ret=edit_loop; - else if (n=="compress/enable") - r_ret=compress_enable; + else if (n=="compress/mode") + r_ret=compress_mode; else if (n=="compress/bitrate") r_ret=compress_bitrate; else @@ -125,7 +131,7 @@ public: p_list->push_back(PropertyInfo(Variant::BOOL,"edit/trim")); p_list->push_back(PropertyInfo(Variant::BOOL,"edit/normalize")); p_list->push_back(PropertyInfo(Variant::BOOL,"edit/loop")); - //p_list->push_back(PropertyInfo(Variant::BOOL,"compress/enable")); + p_list->push_back(PropertyInfo(Variant::INT,"compress/mode",PROPERTY_HINT_ENUM,"Disabled,RAM (Ima-ADPCM)")); //p_list->push_back(PropertyInfo(Variant::INT,"compress/bitrate",PROPERTY_HINT_ENUM,"64,96,128,192")); @@ -150,7 +156,7 @@ public: edit_normalize=true; edit_loop=false; - compress_enable=false; + compress_mode=COMPRESS_MODE_DISABLED; compress_bitrate=COMPRESS_128; } @@ -554,7 +560,11 @@ Error EditorSampleImportPlugin::import(const String& p_path, const Ref<ResourceI loop_end=len; } + int compression = from->get_option("compress/mode"); bool force_mono = from->get_option("force/mono"); + if (compression==_EditorSampleImportOptions::COMPRESS_MODE_RAM) + force_mono=true; + if (force_mono && chans==2) { Vector<float> new_data; @@ -575,19 +585,31 @@ Error EditorSampleImportPlugin::import(const String& p_path, const Ref<ResourceI DVector<uint8_t> dst_data; - dst_data.resize( data.size() * (is16?2:1)); - { - DVector<uint8_t>::Write w = dst_data.write(); + Sample::Format dst_format; - int ds=data.size(); - for(int i=0;i<ds;i++) { + if ( compression == _EditorSampleImportOptions::COMPRESS_MODE_RAM) { - if (is16) { - int16_t v = CLAMP(data[i]*32767,-32768,32767); - encode_uint16(v,&w[i*2]); - } else { - int8_t v = CLAMP(data[i]*127,-128,127); - w[i]=v; + dst_format=Sample::FORMAT_IMA_ADPCM; + + _compress_ima_adpcm(data,dst_data); + + } else { + + dst_format=is16?Sample::FORMAT_PCM16:Sample::FORMAT_PCM8; + dst_data.resize( data.size() * (is16?2:1)); + { + DVector<uint8_t>::Write w = dst_data.write(); + + int ds=data.size(); + for(int i=0;i<ds;i++) { + + if (is16) { + int16_t v = CLAMP(data[i]*32767,-32768,32767); + encode_uint16(v,&w[i*2]); + } else { + int8_t v = CLAMP(data[i]*127,-128,127); + w[i]=v; + } } } } @@ -603,7 +625,7 @@ Error EditorSampleImportPlugin::import(const String& p_path, const Ref<ResourceI target = smp; } - target->create(is16?Sample::FORMAT_PCM16:Sample::FORMAT_PCM8,chans==2?true:false,len); + target->create(dst_format,chans==2?true:false,len); target->set_data(dst_data); target->set_mix_rate(rate); target->set_loop_format(loop); @@ -621,6 +643,124 @@ Error EditorSampleImportPlugin::import(const String& p_path, const Ref<ResourceI } +void EditorSampleImportPlugin::_compress_ima_adpcm(const Vector<float>& p_data,DVector<uint8_t>& dst_data) { + + + /*p_sample_data->data = (void*)malloc(len); + xm_s8 *dataptr=(xm_s8*)p_sample_data->data;*/ + + static const int16_t _ima_adpcm_step_table[89] = { + 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, + 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, + 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, + 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, + 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, + 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, + 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, + 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, + 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 + }; + + static const int8_t _ima_adpcm_index_table[16] = { + -1, -1, -1, -1, 2, 4, 6, 8, + -1, -1, -1, -1, 2, 4, 6, 8 + }; + + + int datalen = p_data.size(); + int datamax=datalen; + if (datalen&1) + datalen++; + + dst_data.resize(datalen/2+4); + DVector<uint8_t>::Write w = dst_data.write(); + + + int i,step_idx=0,prev=0; + uint8_t *out = w.ptr(); + //int16_t xm_prev=0; + const float *in=p_data.ptr(); + + + /* initial value is zero */ + *(out++) =0; + *(out++) =0; + /* Table index initial value */ + *(out++) =0; + /* unused */ + *(out++) =0; + + for (i=0;i<datalen;i++) { + int step,diff,vpdiff,signed_nibble,p,mask; + uint8_t nibble; + int16_t xm_sample; + + if (i>=datamax) + xm_sample=0; + else { + + + xm_sample=CLAMP(in[i]*32767.0,-32768,32767); + if (xm_sample==32767 || xm_sample==-32768) + printf("clippy!\n",xm_sample); + } + + // xm_sample=xm_sample+xm_prev; + // xm_prev=xm_sample; + + diff = (int)xm_sample - prev ; + + nibble=0 ; + step = _ima_adpcm_step_table[ step_idx ]; + vpdiff = step >> 3 ; + if (diff < 0) { + nibble=8; + diff=-diff ; + } + mask = 4 ; + while (mask) { + + if (diff >= step) { + + nibble |= mask; + diff -= step; + vpdiff += step; + } + + step >>= 1 ; + mask >>= 1 ; + }; + + if (nibble&8) + prev-=vpdiff ; + else + prev+=vpdiff ; + + if (prev > 32767) { + printf("%i,xms %i, prev %i,diff %i, vpdiff %i, clip up %i\n",i,xm_sample,prev,diff,vpdiff,prev); + prev=32767; + } else if (prev < -32768) { + printf("%i,xms %i, prev %i,diff %i, vpdiff %i, clip down %i\n",i,xm_sample,prev,diff,vpdiff,prev); + prev = -32768 ; + } + + step_idx += _ima_adpcm_index_table[nibble]; + if (step_idx< 0) + step_idx= 0 ; + else if (step_idx> 88) + step_idx= 88 ; + + + if (i&1) { + *out|=nibble<<4; + out++; + } else { + *out=nibble; + } + /*dataptr[i]=prev>>8;*/ + } + +} EditorSampleImportPlugin::EditorSampleImportPlugin(EditorNode* p_editor) { diff --git a/tools/editor/io_plugins/editor_sample_import_plugin.h b/tools/editor/io_plugins/editor_sample_import_plugin.h index a5420671e6..176dece0d5 100644 --- a/tools/editor/io_plugins/editor_sample_import_plugin.h +++ b/tools/editor/io_plugins/editor_sample_import_plugin.h @@ -40,6 +40,7 @@ class EditorSampleImportPlugin : public EditorImportPlugin { OBJ_TYPE(EditorSampleImportPlugin,EditorImportPlugin); EditorSampleImportDialog *dialog; + void _compress_ima_adpcm(const Vector<float>& p_data,DVector<uint8_t>& dst_data); public: virtual String get_name() const; diff --git a/tools/editor/plugins/baked_light_editor_plugin.cpp b/tools/editor/plugins/baked_light_editor_plugin.cpp new file mode 100644 index 0000000000..b1e42e3369 --- /dev/null +++ b/tools/editor/plugins/baked_light_editor_plugin.cpp @@ -0,0 +1,996 @@ +#include "baked_light_editor_plugin.h" +#include "scene/gui/box_container.h" +#include "scene/3d/mesh_instance.h" +#include "scene/3d/light.h" + + +class BakedLightBaker { +public: + + enum { + + ATTENUATION_CURVE_LEN=256 + }; + + struct Octant { + bool leaf; + union { + struct { + float light_accum[3]; + float surface_area; + Octant *next_leaf; + float offset[3]; + }; + Octant* children[8]; + }; + }; + + struct Triangle { + + Vector3 vertices[3]; + Vector2 uv[3]; + }; + + + struct BVH { + + AABB aabb; + Vector3 center; + Triangle *leaf; + BVH*children[2]; + }; + + + struct BVHCmpX { + + bool operator()(const BVH* p_left, const BVH* p_right) const { + + return p_left->center.x < p_right->center.x; + } + }; + + struct BVHCmpY { + + bool operator()(const BVH* p_left, const BVH* p_right) const { + + return p_left->center.y < p_right->center.y; + } + }; + struct BVHCmpZ { + + bool operator()(const BVH* p_left, const BVH* p_right) const { + + return p_left->center.z < p_right->center.z; + } + }; + + + struct DirLight { + + + Vector3 pos; + Vector3 up; + Vector3 left; + Vector3 dir; + Color diffuse; + Color specular; + float energy; + float length; + int rays_thrown; + + }; + + AABB octree_aabb; + Octant *octree; + BVH*bvh; + Vector<Triangle> triangles; + Transform base_inv; + Octant *leaf_list; + int octree_depth; + int cell_count; + uint32_t *ray_stack; + BVH **bvh_stack; + float cell_size; + float plot_size; //multiplied by cell size + Vector<DirLight> directional_lights; + int max_bounces; + + + + void _add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_mat_override,const Transform& p_xform); + void _parse_geometry(Node* p_node); + BVH* _parse_bvh(BVH** p_children,int p_size,int p_depth,int& max_depth); + void _make_bvh(); + void _make_octree(); + void _octree_insert(const AABB& p_aabb,Octant *p_octant,Triangle* p_triangle, int p_depth); + + void _free_octree(Octant *p_octant) { + + if (!p_octant->leaf) { + + for(int i=0;i<8;i++) { + if (p_octant->children[i]) + _free_octree(p_octant->children[i]); + } + } + + memdelete(p_octant); + } + + void _free_bvh(BVH* p_bvh) { + + if (!p_bvh->leaf) { + if (p_bvh->children[0]) + _free_bvh(p_bvh->children[0]); + if (p_bvh->children[1]) + _free_bvh(p_bvh->children[1]); + } + + memdelete(p_bvh); + + } + + void _fix_lights(); + + + void _plot_light(const Vector3& p_plot_pos,const AABB& p_plot_aabb, Octant *p_octant, const AABB& p_aabb,const Color& p_light); + void _throw_ray(const Vector3& p_from, const Vector3& p_to,const Color& p_light,float *p_att_curve,float p_att_curve_len,int p_bounces); + + + void throw_rays(int p_amount); + float get_normalization() const; + + + void bake(Node *p_base); + + + void clear() { + + if (octree) + _free_octree(octree); + if (bvh) + _free_bvh(bvh); + + if (ray_stack) + memdelete_arr(ray_stack); + if (bvh_stack) + memdelete_arr(bvh_stack); + + octree=NULL; + bvh=NULL; + leaf_list=NULL; + cell_count=0; + ray_stack=NULL; + bvh_stack=NULL; + } + + BakedLightBaker() { + octree_depth=8; + octree=NULL; + bvh=NULL; + leaf_list=NULL; + cell_count=0; + ray_stack=NULL; + bvh_stack=NULL; + plot_size=2; + max_bounces=3; + } + + ~BakedLightBaker() { + + clear(); + } + +}; + + +void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_mat_override,const Transform& p_xform) { + + + for(int i=0;i<p_mesh->get_surface_count();i++) { + + if (p_mesh->surface_get_primitive_type(i)!=Mesh::PRIMITIVE_TRIANGLES) + continue; + Ref<Material> mat = p_mat_override.is_valid()?p_mat_override:p_mesh->surface_get_material(i); + + int facecount=0; + + + if (p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_INDEX) { + + facecount=p_mesh->surface_get_array_index_len(i); + } else { + + facecount=p_mesh->surface_get_array_len(i); + } + + ERR_CONTINUE((facecount==0 || (facecount%3)!=0)); + + facecount/=3; + + int tbase=triangles.size(); + triangles.resize(facecount+tbase); + + + Array a = p_mesh->surface_get_arrays(i); + + DVector<Vector3> vertices = a[Mesh::ARRAY_VERTEX]; + DVector<Vector3>::Read vr=vertices.read(); + + if (p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_INDEX) { + + DVector<int> indices = a[Mesh::ARRAY_INDEX]; + DVector<int>::Read ir = indices.read(); + + for(int i=0;i<facecount;i++) { + Triangle &t=triangles[tbase+i]; + t.vertices[0]=p_xform.xform(vr[ ir[i*3+0] ]); + t.vertices[1]=p_xform.xform(vr[ ir[i*3+1] ]); + t.vertices[2]=p_xform.xform(vr[ ir[i*3+2] ]); + } + + } else { + + for(int i=0;i<facecount;i++) { + Triangle &t=triangles[tbase+i]; + t.vertices[0]=p_xform.xform(vr[ i*3+0 ]); + t.vertices[1]=p_xform.xform(vr[ i*3+1 ]); + t.vertices[2]=p_xform.xform(vr[ i*3+2 ]); + } + } + } + +} + + +void BakedLightBaker::_parse_geometry(Node* p_node) { + + if (p_node->cast_to<MeshInstance>()) { + + MeshInstance *meshi=p_node->cast_to<MeshInstance>(); + Ref<Mesh> mesh=meshi->get_mesh(); + if (mesh.is_valid()) { + _add_mesh(mesh,meshi->get_material_override(),base_inv * meshi->get_global_transform()); + } + } + + if (p_node->cast_to<DirectionalLight>()) { + + DirectionalLight *dl=p_node->cast_to<DirectionalLight>(); + + DirLight dirl; + dirl.diffuse=dl->get_color(DirectionalLight::COLOR_DIFFUSE); + dirl.specular=dl->get_color(DirectionalLight::COLOR_SPECULAR); + dirl.energy=dl->get_parameter(DirectionalLight::PARAM_ENERGY); + dirl.pos=dl->get_global_transform().origin; + dirl.up=dl->get_global_transform().basis.get_axis(1).normalized(); + dirl.left=dl->get_global_transform().basis.get_axis(0).normalized(); + dirl.dir=-dl->get_global_transform().basis.get_axis(2).normalized(); + dirl.rays_thrown=0; + directional_lights.push_back(dirl); + + } + + for(int i=0;i<p_node->get_child_count();i++) { + + _parse_geometry(p_node->get_child(i)); + } +} + + +void BakedLightBaker::_fix_lights() { + + + for(int i=0;i<directional_lights.size();i++) { + + DirLight &dl=directional_lights[i]; + float up_max=-1e10; + float dir_max=-1e10; + float left_max=-1e10; + float up_min=1e10; + float dir_min=1e10; + float left_min=1e10; + + for(int j=0;j<triangles.size();j++) { + + for(int k=0;k<3;k++) { + + Vector3 v = triangles[j].vertices[j]; + + float up_d = dl.up.dot(v); + float dir_d = dl.dir.dot(v); + float left_d = dl.left.dot(v); + + if (up_d>up_max) + up_max=up_d; + if (up_d<up_min) + up_min=up_d; + + if (left_d>left_max) + left_max=left_d; + if (left_d<left_min) + left_min=left_d; + + if (dir_d>dir_max) + dir_max=dir_d; + if (dir_d<dir_min) + dir_min=dir_d; + + } + } + + //make a center point, then the upvector and leftvector + dl.pos = dl.left*( left_max+left_min )*0.5 + dl.up*( up_max+up_min )*0.5 + dl.dir*(dir_min-(dir_max-dir_min)); + dl.left*=(left_max-left_min)*0.5; + dl.up*=(up_max-up_min)*0.5; + dl.length = (dir_max - dir_min)*10; //arbitrary number to keep it in scale + + } +} + +BakedLightBaker::BVH* BakedLightBaker::_parse_bvh(BVH** p_children, int p_size, int p_depth, int &max_depth) { + + if (p_depth>max_depth) { + max_depth=p_depth; + } + + if (p_size==1) { + + return p_children[0]; + } else if (p_size==0) { + + return NULL; + } + + + AABB aabb; + aabb=p_children[0]->aabb; + for(int i=1;i<p_size;i++) { + + aabb.merge_with(p_children[i]->aabb); + } + + int li=aabb.get_longest_axis_index(); + + switch(li) { + + case Vector3::AXIS_X: { + SortArray<BVH*,BVHCmpX> sort_x; + sort_x.nth_element(0,p_size,p_size/2,p_children); + //sort_x.sort(&p_bb[p_from],p_size); + } break; + case Vector3::AXIS_Y: { + SortArray<BVH*,BVHCmpY> sort_y; + sort_y.nth_element(0,p_size,p_size/2,p_children); + //sort_y.sort(&p_bb[p_from],p_size); + } break; + case Vector3::AXIS_Z: { + SortArray<BVH*,BVHCmpZ> sort_z; + sort_z.nth_element(0,p_size,p_size/2,p_children); + //sort_z.sort(&p_bb[p_from],p_size); + + } break; + } + + + BVH* left = _parse_bvh(p_children,p_size/2,p_depth+1,max_depth); + BVH* right = _parse_bvh(&p_children[p_size/2],p_size-p_size/2,p_depth+1,max_depth); + + BVH *_new = memnew(BVH); + _new->aabb=aabb; + _new->center=aabb.pos+aabb.size*0.5; + _new->children[0]=left; + _new->children[1]=right; + _new->leaf=NULL; + + return _new; +} + +void BakedLightBaker::_make_bvh() { + + Vector<BVH*> bases; + bases.resize(triangles.size()); + int max_depth=0; + for(int i=0;i<triangles.size();i++) { + bases[i]=memnew( BVH ); + bases[i]->leaf=&triangles[i]; + bases[i]->aabb.pos=triangles[i].vertices[0]; + bases[i]->aabb.expand_to(triangles[i].vertices[1]); + bases[i]->aabb.expand_to(triangles[i].vertices[2]); + bases[i]->center=bases[i]->aabb.pos+bases[i]->aabb.size*0.5; + } + + bvh=_parse_bvh(bases.ptr(),bases.size(),1,max_depth); + ray_stack = memnew_arr(uint32_t,max_depth); + bvh_stack = memnew_arr(BVH*,max_depth); +} + +void BakedLightBaker::_octree_insert(const AABB& p_aabb,Octant *p_octant,Triangle* p_triangle, int p_depth) { + + if (p_octant->leaf) { + + if (p_aabb.has_point(p_triangle->vertices[0]) && p_aabb.has_point(p_triangle->vertices[1]) &&p_aabb.has_point(p_triangle->vertices[2])) { + //face is completely enclosed, add area + p_octant->surface_area+=Face3(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).get_area(); + } else { + //not completely enclosed, will need to be clipped.. + Vector<Vector3> poly; + poly.push_back(p_triangle->vertices[0]); + poly.push_back(p_triangle->vertices[1]); + poly.push_back(p_triangle->vertices[2]); + + //clip + for(int i=0;i<3;i++) { + + //top plane + Plane p(0,0,0,0); + p.normal[i]=1.0; + p.d=p_aabb.pos[i]+p_aabb.size[i]; + poly=Geometry::clip_polygon(poly,p); + + //bottom plane + p.normal[i]=-1.0; + p.d=-p_aabb.pos[i]; + poly=Geometry::clip_polygon(poly,p); + } + //calculate area + for(int i=2;i<poly.size();i++) { + p_octant->surface_area+=Face3(poly[0],poly[i-1],poly[i]).get_area(); + } + } + + } else { + + + for(int i=0;i<8;i++) { + + AABB aabb=p_aabb; + aabb.size*=0.5; + if (i&1) + aabb.pos.x+=aabb.size.x; + if (i&2) + aabb.pos.y+=aabb.size.y; + if (i&4) + aabb.pos.z+=aabb.size.z; + + AABB fit_aabb=aabb; + //fit_aabb=fit_aabb.grow(bvh->aabb.size.x*0.0001); + + if (!Face3(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).intersects_aabb(fit_aabb)) + continue; + + if (!p_octant->children[i]) { + p_octant->children[i]=memnew(Octant); + if (p_depth==0) { + p_octant->children[i]->leaf=true; + p_octant->children[i]->light_accum[0]=0; + p_octant->children[i]->light_accum[1]=0; + p_octant->children[i]->light_accum[2]=0; + p_octant->children[i]->offset[0]=aabb.pos.x+aabb.size.x*0.5; + p_octant->children[i]->offset[1]=aabb.pos.y+aabb.size.y*0.5; + p_octant->children[i]->offset[2]=aabb.pos.z+aabb.size.z*0.5; + p_octant->children[i]->surface_area=0; + p_octant->children[i]->next_leaf=leaf_list; + leaf_list=p_octant->children[i]; + cell_count++; + } else { + + p_octant->children[i]->leaf=false; + for(int j=0;j<8;j++) { + p_octant->children[i]->children[j]=0; + } + } + } + + _octree_insert(aabb,p_octant->children[i],p_triangle,p_depth-1); + } + } +} + + +void BakedLightBaker::_make_octree() { + + AABB base = bvh->aabb; + float lal=base.get_longest_axis_size(); + //must be square because we want square blocks + base.size.x=lal; + base.size.y=lal; + base.size.z=lal; + base.grow_by(lal*0.001); //for precision + octree_aabb=base; + + cell_size=base.size.x; + for(int i=0;i<=octree_depth;i++) + cell_size/=2.0; + + octree = memnew( Octant ); + octree->leaf=false; + for(int i=0;i<8;i++) + octree->children[i]=NULL; + + for(int i=0;i<triangles.size();i++) { + + _octree_insert(octree_aabb,octree,&triangles[i],octree_depth-1); + } + +} + + +void BakedLightBaker::_plot_light(const Vector3& p_plot_pos,const AABB& p_plot_aabb, Octant *p_octant, const AABB& p_aabb,const Color& p_light) { + + + if (p_octant->leaf) { + + float r=cell_size*plot_size; + Vector3 center=p_aabb.pos+p_aabb.size*0.5; + float d = p_plot_pos.distance_to(center); + if (d>r) + return; //oh crap! outside radius + float intensity = 1.0 - (d/r)*(d/r); //not gauss but.. + p_octant->light_accum[0]+=p_light.r*intensity; + p_octant->light_accum[1]+=p_light.g*intensity; + p_octant->light_accum[2]+=p_light.b*intensity; + + } else { + + for(int i=0;i<8;i++) { + + if (!p_octant->children[i]) + continue; + + AABB aabb=p_aabb; + aabb.size*=0.5; + if (i&1) + aabb.pos.x+=aabb.size.x; + if (i&2) + aabb.pos.y+=aabb.size.y; + if (i&4) + aabb.pos.z+=aabb.size.z; + + + if (!aabb.intersects(p_plot_aabb)) + continue; + + _plot_light(p_plot_pos,p_plot_aabb,p_octant->children[i],aabb,p_light); + + } + + } +} + + +void BakedLightBaker::_throw_ray(const Vector3& p_begin, const Vector3& p_end,const Color& p_light,float *p_att_curve,float p_att_curve_len,int p_bounces) { + + + uint32_t* stack = ray_stack; + BVH **bstack = bvh_stack; + + enum { + TEST_AABB_BIT=0, + VISIT_LEFT_BIT=1, + VISIT_RIGHT_BIT=2, + VISIT_DONE_BIT=3, + + + }; + + Vector3 n = (p_end-p_begin).normalized(); + real_t d=1e10; + bool inters=false; + Vector3 r_normal; + Vector3 r_point; + + //for(int i=0;i<max_depth;i++) + // stack[i]=0; + + int level=0; + //AABB ray_aabb; + //ray_aabb.pos=p_begin; + //ray_aabb.expand_to(p_end); + + + const BVH *bvhptr = bvh; + + bstack[0]=bvh; + stack[0]=TEST_AABB_BIT; + + + while(true) { + + uint32_t mode = stack[level]; + const BVH &b = *bstack[level]; + bool done=false; + + switch(mode) { + case TEST_AABB_BIT: { + + if (b.leaf) { + + + Face3 f3(b.leaf->vertices[0],b.leaf->vertices[1],b.leaf->vertices[2]); + + + Vector3 res; + + if (f3.intersects_segment(p_begin,p_end,&res)) { + + + float nd = n.dot(res); + if (nd<d) { + + d=nd; + r_point=res; + r_normal=f3.get_plane().get_normal(); + inters=true; + } + + } + + stack[level]=VISIT_DONE_BIT; + } else { + + + bool valid = b.aabb.intersects_segment(p_begin,p_end); + // bool valid = b.aabb.intersects(ray_aabb); + + if (!valid) { + + stack[level]=VISIT_DONE_BIT; + + } else { + + stack[level]=VISIT_LEFT_BIT; + } + } + + } continue; + case VISIT_LEFT_BIT: { + + stack[level]=VISIT_RIGHT_BIT; + bstack[level+1]=b.children[0]; + stack[level+1]=TEST_AABB_BIT; + level++; + + } continue; + case VISIT_RIGHT_BIT: { + + stack[level]=VISIT_DONE_BIT; + bstack[level+1]=b.children[1]; + stack[level+1]=TEST_AABB_BIT; + level++; + } continue; + case VISIT_DONE_BIT: { + + if (level==0) { + done=true; + break; + } else + level--; + + } continue; + } + + + if (done) + break; + } + + + if (inters) { + + //print_line("collision!"); + if (n.dot(r_normal)>0) + r_normal=-r_normal; + + //ok... + Color diffuse_at_point(0.8,0.8,0.8); + Color specular_at_point(0.8,0.8,0.8); + + AABB aabb; + aabb.pos=r_point; + aabb.pos-=Vector3(1,1,1)*cell_size*plot_size; + aabb.size=Vector3(2,2,2)*cell_size*plot_size; + + _plot_light(r_point,aabb,octree,octree_aabb,p_light); + + } + +} + + + + + + +float BakedLightBaker::get_normalization() const { + + float nrg=0; + for(int i=0;i<directional_lights.size();i++) { + + const DirLight &dl=directional_lights[i]; + float total_area = dl.left.length()*2*dl.up.length()*2; + float cell_area = cell_size*cell_size;; + nrg+= dl.energy * (dl.rays_thrown * cell_area / total_area); + nrg*=5; + } + + return nrg; +} + +void BakedLightBaker::throw_rays(int p_amount) { + + + + for(int i=0;i<directional_lights.size();i++) { + + DirLight &dl=directional_lights[i]; + + float sr = Math::sqrt(p_amount); + float aspect = dl.up.length()/dl.left.length(); + + + for(int j=0;j<p_amount;j++) { + Vector3 from = dl.pos; + from+=dl.up*(Math::randf()*2.0-1.0); + from+=dl.left*(Math::randf()*2.0-1.0); + Vector3 to = from+dl.dir*dl.length; + Color col=dl.diffuse; + col.r*=dl.energy; + col.g*=dl.energy; + col.b*=dl.energy; + dl.rays_thrown++; + _throw_ray(from,to,col,NULL,0,max_bounces); + } + + + } +} + + + + + + + + + + + + + +void BakedLightBaker::bake(Node* p_node) { + + cell_count=0; + + _parse_geometry(p_node); + _fix_lights(); + _make_bvh(); + _make_octree(); + +} + + + + +void BakedLightEditor::_node_removed(Node *p_node) { + + if(p_node==node) { + node=NULL; + p_node->remove_child(preview); + preview->set_mesh(Ref<Mesh>()); + hide(); + } + +} + + + +void BakedLightEditor::_menu_option(int p_option) { + + + switch(p_option) { + + + case MENU_OPTION_BAKE: { + + ERR_FAIL_COND(!node); + preview->set_mesh(Ref<Mesh>()); + baker->base_inv=node->get_global_transform().affine_inverse(); + baker->bake(node); + baker->throw_rays(100000); + float norm = baker->get_normalization(); + float max_lum=0; + + print_line("CELLS: "+itos(baker->cell_count)); + DVector<Color> colors; + DVector<Vector3> vertices; + colors.resize(baker->cell_count*36); + vertices.resize(baker->cell_count*36); + + + { + DVector<Color>::Write cw=colors.write(); + DVector<Vector3>::Write vw=vertices.write(); + BakedLightBaker::Octant *oct = baker->leaf_list; + int vert_idx=0; + + while(oct) { + + Color color; + color.r=oct->light_accum[0]/norm; + color.g=oct->light_accum[1]/norm; + color.b=oct->light_accum[2]/norm; + float lum = color.get_v(); + if (lum>max_lum) + max_lum=lum; + + for (int i=0;i<6;i++) { + + + Vector3 face_points[4]; + for (int j=0;j<4;j++) { + + float v[3]; + v[0]=1.0; + v[1]=1-2*((j>>1)&1); + v[2]=v[1]*(1-2*(j&1)); + + for (int k=0;k<3;k++) { + + if (i<3) + face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1); + else + face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1); + } + } + + for(int j=0;j<4;j++) { + face_points[j]*=baker->cell_size; + face_points[j]+=Vector3(oct->offset[0],oct->offset[1],oct->offset[2]); + } + +#define ADD_VTX(m_idx) \ + vw[vert_idx]=face_points[m_idx]; \ + cw[vert_idx]=color; \ + vert_idx++; + + //tri 1 + ADD_VTX(0); + ADD_VTX(1); + ADD_VTX(2); + //tri 2 + ADD_VTX(2); + ADD_VTX(3); + ADD_VTX(0); + +#undef ADD_VTX + + } + + oct=oct->next_leaf; + } + + + } + + print_line("max lum: "+rtos(max_lum)); + Array a; + a.resize(Mesh::ARRAY_MAX); + a[Mesh::ARRAY_VERTEX]=vertices; + a[Mesh::ARRAY_COLOR]=colors; + + Ref<FixedMaterial> matcol = memnew( FixedMaterial ); + matcol->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY,true); + matcol->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true); + matcol->set_flag(FixedMaterial::FLAG_UNSHADED,true); + matcol->set_flag(FixedMaterial::FLAG_DOUBLE_SIDED,true); + matcol->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(1,1,1)); + Ref<Mesh> m = memnew( Mesh ); + m->add_surface(Mesh::PRIMITIVE_TRIANGLES,a); + m->surface_set_material(0,matcol); + preview->set_mesh(m); + + + + + + } break; + case MENU_OPTION_CLEAR: { + + + + } break; + + } +} + + +void BakedLightEditor::edit(BakedLight *p_baked_light) { + + if (node==p_baked_light) + return; + if (node) { + node->remove_child(preview); + } + + node=p_baked_light; + + if (node) + node->add_child(preview); + +} + + + +void BakedLightEditor::_bind_methods() { + + ObjectTypeDB::bind_method("_menu_option",&BakedLightEditor::_menu_option); +} + +BakedLightEditor::BakedLightEditor() { + + + options = memnew( MenuButton ); + + options->set_text("BakedLight"); + options->get_popup()->add_item("Bake..",MENU_OPTION_BAKE); + options->get_popup()->add_item("Clear",MENU_OPTION_CLEAR); + options->get_popup()->connect("item_pressed", this,"_menu_option"); + + + err_dialog = memnew( AcceptDialog ); + add_child(err_dialog); + node=NULL; + baker = memnew( BakedLightBaker ); + preview = memnew( MeshInstance ); +} + +BakedLightEditor::~BakedLightEditor() { + + memdelete(baker); +} + +void BakedLightEditorPlugin::edit(Object *p_object) { + + baked_light_editor->edit(p_object->cast_to<BakedLight>()); +} + +bool BakedLightEditorPlugin::handles(Object *p_object) const { + + return p_object->is_type("BakedLight"); +} + +void BakedLightEditorPlugin::make_visible(bool p_visible) { + + if (p_visible) { + baked_light_editor->show(); + baked_light_editor->options->show(); + } else { + + baked_light_editor->hide(); + baked_light_editor->options->show(); + baked_light_editor->edit(NULL); + if (baked_light_editor->node) { + baked_light_editor->node->remove_child(baked_light_editor->preview); + baked_light_editor->node=NULL; + } + } + +} + +BakedLightEditorPlugin::BakedLightEditorPlugin(EditorNode *p_node) { + + editor=p_node; + baked_light_editor = memnew( BakedLightEditor ); + editor->get_viewport()->add_child(baked_light_editor); + add_custom_control(CONTAINER_SPATIAL_EDITOR_MENU,baked_light_editor->options); + baked_light_editor->hide(); + baked_light_editor->options->hide(); +} + + +BakedLightEditorPlugin::~BakedLightEditorPlugin() +{ +} + + diff --git a/tools/editor/plugins/baked_light_editor_plugin.h b/tools/editor/plugins/baked_light_editor_plugin.h new file mode 100644 index 0000000000..698d3f825f --- /dev/null +++ b/tools/editor/plugins/baked_light_editor_plugin.h @@ -0,0 +1,70 @@ +#ifndef BAKED_LIGHT_EDITOR_PLUGIN_H +#define BAKED_LIGHT_EDITOR_PLUGIN_H + +#include "tools/editor/editor_plugin.h" +#include "tools/editor/editor_node.h" +#include "scene/3d/baked_light.h" +#include "scene/gui/spin_box.h" + +/** + @author Juan Linietsky <reduzio@gmail.com> +*/ + + +class BakedLightBaker; +class MeshInstance; + +class BakedLightEditor : public Control { + + OBJ_TYPE(BakedLightEditor, Control ); + + + MeshInstance *preview; + BakedLightBaker *baker; + AcceptDialog *err_dialog; + + MenuButton * options; + BakedLight *node; + + enum Menu { + + MENU_OPTION_BAKE, + MENU_OPTION_CLEAR + }; + + void _menu_option(int); + +friend class BakedLightEditorPlugin; +protected: + void _node_removed(Node *p_node); + static void _bind_methods(); +public: + + void edit(BakedLight *p_baked_light); + BakedLightEditor(); + ~BakedLightEditor(); +}; + +class BakedLightEditorPlugin : public EditorPlugin { + + OBJ_TYPE( BakedLightEditorPlugin, EditorPlugin ); + + BakedLightEditor *baked_light_editor; + EditorNode *editor; + +public: + + virtual String get_name() const { return "BakedLight"; } + bool has_main_screen() const { return false; } + virtual void edit(Object *p_node); + virtual bool handles(Object *p_node) const; + virtual void make_visible(bool p_visible); + + BakedLightEditorPlugin(EditorNode *p_node); + ~BakedLightEditorPlugin(); + +}; + +#endif // MULTIMESH_EDITOR_PLUGIN_H + + diff --git a/tools/editor/plugins/sample_editor_plugin.cpp b/tools/editor/plugins/sample_editor_plugin.cpp index f55d6640c2..e3fad58a89 100644 --- a/tools/editor/plugins/sample_editor_plugin.cpp +++ b/tools/editor/plugins/sample_editor_plugin.cpp @@ -95,93 +95,98 @@ void SampleEditor::generate_preview_texture(const Ref<Sample>& p_sample,Ref<Imag if (len<1) return; - for(int i=0;i<w;i++) { - // i trust gcc will optimize this loop - float max[2]={-1e10,-1e10}; - float min[2]={1e10,1e10}; - int c=stereo?2:1; - int from = i*len/w; - int to = (i+1)*len/w; - if (to>=len) - to=len-1; - - if (_16) { - const int16_t*src =(const int16_t*)sdata; - - for(int j=0;j<c;j++) { - - for(int k=from;k<=to;k++) { - - float v = src[k*c+j]/32768.0; - if (v>max[j]) - max[j]=v; - if (v<min[j]) - min[j]=v; + if (p_sample->get_format()==Sample::FORMAT_IMA_ADPCM) { + + + } else { + for(int i=0;i<w;i++) { + // i trust gcc will optimize this loop + float max[2]={-1e10,-1e10}; + float min[2]={1e10,1e10}; + int c=stereo?2:1; + int from = i*len/w; + int to = (i+1)*len/w; + if (to>=len) + to=len-1; + + if (_16) { + const int16_t*src =(const int16_t*)sdata; + + for(int j=0;j<c;j++) { + + for(int k=from;k<=to;k++) { + + float v = src[k*c+j]/32768.0; + if (v>max[j]) + max[j]=v; + if (v<min[j]) + min[j]=v; + } + } + } else { - } - } else { + const int8_t*src =(const int8_t*)sdata; - const int8_t*src =(const int8_t*)sdata; + for(int j=0;j<c;j++) { - for(int j=0;j<c;j++) { + for(int k=from;k<=to;k++) { - for(int k=from;k<=to;k++) { + float v = src[k*c+j]/128.0; + if (v>max[j]) + max[j]=v; + if (v<min[j]) + min[j]=v; + } - float v = src[k*c+j]/128.0; - if (v>max[j]) - max[j]=v; - if (v<min[j]) - min[j]=v; } - } - } - if (!stereo) { - for(int j=0;j<h;j++) { - float v = (j/(float)h) * 2.0 - 1.0; - uint8_t* imgofs = &imgw[(j*w+i)*3]; - if (v>min[0] && v<max[0]) { - imgofs[0]=255; - imgofs[1]=150; - imgofs[2]=80; - } else { - imgofs[0]=0; - imgofs[1]=0; - imgofs[2]=0; + if (!stereo) { + for(int j=0;j<h;j++) { + float v = (j/(float)h) * 2.0 - 1.0; + uint8_t* imgofs = &imgw[(j*w+i)*3]; + if (v>min[0] && v<max[0]) { + imgofs[0]=255; + imgofs[1]=150; + imgofs[2]=80; + } else { + imgofs[0]=0; + imgofs[1]=0; + imgofs[2]=0; + } } - } - } else { - - for(int j=0;j<h;j++) { - - int half,ofs; - float v; - if (j<(h/2)) { - half=0; - ofs=0; - v = (j/(float)(h/2)) * 2.0 - 1.0; - } else { - half=1; - ofs=h/2; - v = ((j-(h/2))/(float)(h/2)) * 2.0 - 1.0; + } else { + + for(int j=0;j<h;j++) { + + int half,ofs; + float v; + if (j<(h/2)) { + half=0; + ofs=0; + v = (j/(float)(h/2)) * 2.0 - 1.0; + } else { + half=1; + ofs=h/2; + v = ((j-(h/2))/(float)(h/2)) * 2.0 - 1.0; + } + + uint8_t* imgofs = &imgw[(j*w+i)*3]; + if (v>min[half] && v<max[half]) { + imgofs[0]=255; + imgofs[1]=150; + imgofs[2]=80; + } else { + imgofs[0]=0; + imgofs[1]=0; + imgofs[2]=0; + } } - uint8_t* imgofs = &imgw[(j*w+i)*3]; - if (v>min[half] && v<max[half]) { - imgofs[0]=255; - imgofs[1]=150; - imgofs[2]=80; - } else { - imgofs[0]=0; - imgofs[1]=0; - imgofs[2]=0; - } } } - } imgdata = DVector<uint8_t>::Write(); diff --git a/tools/editor/plugins/sample_library_editor_plugin.cpp b/tools/editor/plugins/sample_library_editor_plugin.cpp index 86ac1671ae..84143dcd4b 100644 --- a/tools/editor/plugins/sample_library_editor_plugin.cpp +++ b/tools/editor/plugins/sample_library_editor_plugin.cpp @@ -262,7 +262,7 @@ void SampleLibraryEditor::_update_library() { ti->set_editable(2,false); ti->set_selectable(2,false); Ref<Sample> s = sample_library->get_sample(E->get()); - ti->set_text(2,String()+/*itos(s->get_length())+" frames ("+String::num(s->get_length()/(float)s->get_mix_rate(),2)+" s), "+*/(s->get_format()==Sample::FORMAT_PCM16?"16 Bits, ":"8 bits, ")+(s->is_stereo()?"Stereo":"Mono")); + ti->set_text(2,String()+/*itos(s->get_length())+" frames ("+String::num(s->get_length()/(float)s->get_mix_rate(),2)+" s), "+*/(s->get_format()==Sample::FORMAT_PCM16?"16 Bits, ":(s->get_format()==Sample::FORMAT_PCM8?"8 bits, ":"IMA-ADPCM,"))+(s->is_stereo()?"Stereo":"Mono")); ti->set_cell_mode(3,TreeItem::CELL_MODE_RANGE); ti->set_range_config(3,-60,24,0.01); diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp index 8c16207887..2087345888 100644 --- a/tools/editor/property_editor.cpp +++ b/tools/editor/property_editor.cpp @@ -261,12 +261,12 @@ bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Ty for(int i=0;i<2;i++) { Point2 ofs(4,4); - ofs.y+=16*i; + ofs.y+=22*i; for(int j=0;j<10;j++) { - CheckButton *c=checks20[i*10+j]; + Button *c=checks20[i*10+j]; Point2 o=ofs; - o.x+=j*16; + o.x+=j*22; if (j>=5) o.x+=4; c->set_pos(o); @@ -277,7 +277,7 @@ bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Ty } - set_size(checks20[19]->get_pos()+Size2(12,17)); + set_size(checks20[19]->get_pos()+Size2(20,25)); } else if (hint==PROPERTY_HINT_EXP_EASING) { @@ -1560,7 +1560,9 @@ CustomPropertyEditor::CustomPropertyEditor() { } for(int i=0;i<20;i++) { - checks20[i]=memnew( CheckButton ); + checks20[i]=memnew( Button ); + checks20[i]->set_toggle_mode(true); + checks20[i]->set_focus_mode(FOCUS_NONE); add_child(checks20[i]); checks20[i]->hide(); checks20[i]->connect("pressed",this,"_action_pressed",make_binds(i)); diff --git a/tools/editor/property_editor.h b/tools/editor/property_editor.h index 7ee14679c1..f13deab1ae 100644 --- a/tools/editor/property_editor.h +++ b/tools/editor/property_editor.h @@ -92,7 +92,7 @@ class CustomPropertyEditor : public Popup { ColorPicker *color_picker; TextEdit *text_edit; bool read_only; - CheckButton *checks20[20]; + Button *checks20[20]; Control *easing_draw; |