diff options
Diffstat (limited to 'core')
| -rw-r--r-- | core/bind/core_bind.cpp | 11 | ||||
| -rw-r--r-- | core/bind/core_bind.h | 2 | ||||
| -rw-r--r-- | core/color.cpp | 12 | ||||
| -rw-r--r-- | core/error_macros.h | 5 | ||||
| -rw-r--r-- | core/global_constants.cpp | 3 | ||||
| -rw-r--r-- | core/io/http_client.cpp | 8 | ||||
| -rw-r--r-- | core/io/resource_format_xml.cpp | 1 | ||||
| -rw-r--r-- | core/math/aabb.h | 18 | ||||
| -rw-r--r-- | core/math/octree.h | 12 | ||||
| -rw-r--r-- | core/os/keyboard.cpp | 2 | ||||
| -rw-r--r-- | core/os/keyboard.h | 2 | ||||
| -rw-r--r-- | core/os/memory.h | 8 | ||||
| -rw-r--r-- | core/os/os.cpp | 4 | ||||
| -rw-r--r-- | core/os/os.h | 1 | ||||
| -rw-r--r-- | core/range_iterator.cpp | 169 | ||||
| -rw-r--r-- | core/range_iterator.h | 72 | ||||
| -rw-r--r-- | core/register_core_types.cpp | 4 | ||||
| -rw-r--r-- | core/typedefs.h | 32 | ||||
| -rw-r--r-- | core/ustring.cpp | 31 | ||||
| -rw-r--r-- | core/ustring.h | 2 | ||||
| -rw-r--r-- | core/vector.h | 35 |
21 files changed, 390 insertions, 44 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index b291ee396b..aff047177c 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -55,11 +55,17 @@ bool _ResourceLoader::has(const String &p_path) { return ResourceCache::has(local_path); }; +Ref<ResourceImportMetadata> _ResourceLoader::load_import_metadata(const String& p_path) { + + return ResourceLoader::load_import_metadata(p_path); +} + void _ResourceLoader::_bind_methods() { ObjectTypeDB::bind_method(_MD("load_interactive:ResourceInteractiveLoader","path","type_hint"),&_ResourceLoader::load_interactive,DEFVAL("")); ObjectTypeDB::bind_method(_MD("load:Resource","path","type_hint", "p_no_cache"),&_ResourceLoader::load,DEFVAL(""), DEFVAL(false)); + ObjectTypeDB::bind_method(_MD("load_import_metadata:ResourceImportMetadata","path"),&_ResourceLoader::load_import_metadata); ObjectTypeDB::bind_method(_MD("get_recognized_extensions_for_type","type"),&_ResourceLoader::get_recognized_extensions_for_type); ObjectTypeDB::bind_method(_MD("set_abort_on_missing_resources","abort"),&_ResourceLoader::set_abort_on_missing_resources); ObjectTypeDB::bind_method(_MD("get_dependencies","path"),&_ResourceLoader::get_dependencies); @@ -689,6 +695,10 @@ void _OS::native_video_pause() { OS::get_singleton()->native_video_pause(); }; +void _OS::native_video_unpause() { + OS::get_singleton()->native_video_unpause(); +}; + void _OS::native_video_stop() { OS::get_singleton()->native_video_stop(); @@ -874,6 +884,7 @@ void _OS::_bind_methods() { ObjectTypeDB::bind_method(_MD("native_video_is_playing"),&_OS::native_video_is_playing); ObjectTypeDB::bind_method(_MD("native_video_stop"),&_OS::native_video_stop); ObjectTypeDB::bind_method(_MD("native_video_pause"),&_OS::native_video_pause); + ObjectTypeDB::bind_method(_MD("native_video_unpause"),&_OS::native_video_unpause); ObjectTypeDB::bind_method(_MD("get_scancode_string","code"),&_OS::get_scancode_string); ObjectTypeDB::bind_method(_MD("is_scancode_unicode","code"),&_OS::is_scancode_unicode); diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 30cc93fa11..2c43390d3c 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -26,6 +26,7 @@ public: void set_abort_on_missing_resources(bool p_abort); StringArray get_dependencies(const String& p_path); bool has(const String& p_path); + Ref<ResourceImportMetadata> load_import_metadata(const String& p_path); _ResourceLoader(); }; @@ -131,6 +132,7 @@ public: Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track); bool native_video_is_playing(); void native_video_pause(); + void native_video_unpause(); void native_video_stop(); void set_iterations_per_second(int p_ips); diff --git a/core/color.cpp b/core/color.cpp index c53de360bc..56a550c024 100644 --- a/core/color.cpp +++ b/core/color.cpp @@ -117,29 +117,31 @@ void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) { } p_h *=6.0; + p_h = Math::fmod(p_h,6); i = Math::floor( p_h ); + f = p_h - i; p = p_v * ( 1 - p_s ); q = p_v * ( 1 - p_s * f ); t = p_v * ( 1 - p_s * ( 1 - f ) ); switch( i ) { - case 0: + case 0: // Red is the dominant color r = p_v; g = t; b = p; break; - case 1: + case 1: // Green is the dominant color r = q; g = p_v; b = p; break; - case 2: + case 2: r = p; g = p_v; b = t; break; - case 3: + case 3: // Blue is the dominant color r = p; g = q; b = p_v; @@ -149,7 +151,7 @@ void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) { g = p; b = p_v; break; - default: // cap_se 5: + default: // (5) Red is the dominant color r = p_v; g = p; b = q; diff --git a/core/error_macros.h b/core/error_macros.h index cafbf0c16e..47b1de5df3 100644 --- a/core/error_macros.h +++ b/core/error_macros.h @@ -223,5 +223,10 @@ extern bool _err_error_exists; } \ +#define WARN_PRINTS(m_string) \ + { \ + _err_print_error(FUNCTION_STR,__FILE__,__LINE__,String(m_string).utf8().get_data(),ERR_HANDLER_WARNING); \ + _err_error_exists=false;\ + } \ #endif diff --git a/core/global_constants.cpp b/core/global_constants.cpp index c306744d35..130fca1b2a 100644 --- a/core/global_constants.cpp +++ b/core/global_constants.cpp @@ -106,7 +106,7 @@ static _GlobalConstant _global_constants[]={ BIND_GLOBAL_CONSTANT( KEY_KP_ENTER ), BIND_GLOBAL_CONSTANT( KEY_KP_MULTIPLY ), BIND_GLOBAL_CONSTANT( KEY_KP_DIVIDE ), - BIND_GLOBAL_CONSTANT( KEY_KP_SUBSTRACT ), + BIND_GLOBAL_CONSTANT( KEY_KP_SUBTRACT ), BIND_GLOBAL_CONSTANT( KEY_KP_PERIOD ), BIND_GLOBAL_CONSTANT( KEY_KP_ADD ), BIND_GLOBAL_CONSTANT( KEY_KP_0 ), @@ -432,6 +432,7 @@ static _GlobalConstant _global_constants[]={ BIND_GLOBAL_CONSTANT( ERR_FILE_EOF ), BIND_GLOBAL_CONSTANT( ERR_CANT_OPEN ), ///< Can't open a resource/socket/file BIND_GLOBAL_CONSTANT( ERR_CANT_CREATE ), + BIND_GLOBAL_CONSTANT( ERR_PARSE_ERROR ), BIND_GLOBAL_CONSTANT( ERROR_QUERY_FAILED ), BIND_GLOBAL_CONSTANT( ERR_ALREADY_IN_USE ), BIND_GLOBAL_CONSTANT( ERR_LOCKED ), ///< resource is locked diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index 19a7286dcf..b070e52f0a 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -306,8 +306,8 @@ Error HTTPClient::poll(){ for(int i=0;i<responses.size();i++) { - String s = responses[i].strip_edges(); - s = s.to_lower(); + String header = responses[i].strip_edges(); + String s = header.to_lower(); if (s.length()==0) continue; if (s.begins_with("content-length:")) { @@ -316,7 +316,7 @@ Error HTTPClient::poll(){ } if (s.begins_with("transfer-encoding:")) { - String encoding = s.substr(s.find(":")+1,s.length()).strip_edges(); + String encoding = header.substr(header.find(":")+1,header.length()).strip_edges(); //print_line("TRANSFER ENCODING: "+encoding); if (encoding=="chunked") { chunked=true; @@ -330,7 +330,7 @@ Error HTTPClient::poll(){ response_num=num.to_int(); } else { - response_headers.push_back(s); + response_headers.push_back(header); } } diff --git a/core/io/resource_format_xml.cpp b/core/io/resource_format_xml.cpp index 8c8d79948a..03b77a4aab 100644 --- a/core/io/resource_format_xml.cpp +++ b/core/io/resource_format_xml.cpp @@ -1796,6 +1796,7 @@ Error ResourceInteractiveLoaderXML::rename_dependencies(FileAccess *p_f, const S fw->store_8(c); c=f->get_8(); } + f->close(); bool all_ok = fw->get_error()==OK; diff --git a/core/math/aabb.h b/core/math/aabb.h index 7c9c3081ac..0fada859c0 100644 --- a/core/math/aabb.h +++ b/core/math/aabb.h @@ -66,6 +66,7 @@ public: bool operator!=(const AABB& p_rval) const; _FORCE_INLINE_ bool intersects(const AABB& p_aabb) const; /// Both AABBs overlap + _FORCE_INLINE_ bool intersects_inclusive(const AABB& p_aabb) const; /// Both AABBs (or their faces) overlap _FORCE_INLINE_ bool encloses(const AABB & p_aabb) const; /// p_aabb is completely inside this AABB merge(const AABB& p_with) const; @@ -126,6 +127,23 @@ inline bool AABB::intersects(const AABB& p_aabb) const { return true; } +inline bool AABB::intersects_inclusive(const AABB& p_aabb) const { + + if ( pos.x > (p_aabb.pos.x + p_aabb.size.x) ) + return false; + if ( (pos.x+size.x) < p_aabb.pos.x ) + return false; + if ( pos.y > (p_aabb.pos.y + p_aabb.size.y) ) + return false; + if ( (pos.y+size.y) < p_aabb.pos.y ) + return false; + if ( pos.z > (p_aabb.pos.z + p_aabb.size.z) ) + return false; + if ( (pos.z+size.z) < p_aabb.pos.z ) + return false; + + return true; +} inline bool AABB::encloses(const AABB & p_aabb) const { diff --git a/core/math/octree.h b/core/math/octree.h index b51c4bcba7..69edf80e09 100644 --- a/core/math/octree.h +++ b/core/math/octree.h @@ -201,7 +201,7 @@ private: _FORCE_INLINE_ void _pair_check(PairData *p_pair) { - bool intersect=p_pair->A->aabb.intersects( p_pair->B->aabb ); + bool intersect=p_pair->A->aabb.intersects_inclusive( p_pair->B->aabb ); if (intersect!=p_pair->intersect) { @@ -480,7 +480,7 @@ void Octree<T,use_pairs,AL>::_insert_element(Element *p_element,Octant *p_octant if (p_octant->children[i]) { /* element exists, go straight to it */ - if (p_octant->children[i]->aabb.intersects( p_element->aabb ) ) { + if (p_octant->children[i]->aabb.intersects_inclusive( p_element->aabb ) ) { _insert_element( p_element, p_octant->children[i] ); splits++; } @@ -497,7 +497,7 @@ void Octree<T,use_pairs,AL>::_insert_element(Element *p_element,Octant *p_octant if (i&4) aabb.pos.z+=aabb.size.z; - if (aabb.intersects( p_element->aabb) ) { + if (aabb.intersects_inclusive( p_element->aabb) ) { /* if actually intersects, create the child */ Octant *child = memnew_allocator( Octant, AL ); @@ -1146,7 +1146,7 @@ void Octree<T,use_pairs,AL>::_cull_AABB(Octant *p_octant,const AABB& p_aabb, T** continue; e->last_pass=pass; - if (p_aabb.intersects(e->aabb)) { + if (p_aabb.intersects_inclusive(e->aabb)) { if (*p_result_idx<p_result_max) { @@ -1175,7 +1175,7 @@ void Octree<T,use_pairs,AL>::_cull_AABB(Octant *p_octant,const AABB& p_aabb, T** continue; e->last_pass=pass; - if (p_aabb.intersects(e->aabb)) { + if (p_aabb.intersects_inclusive(e->aabb)) { if (*p_result_idx<p_result_max) { @@ -1193,7 +1193,7 @@ void Octree<T,use_pairs,AL>::_cull_AABB(Octant *p_octant,const AABB& p_aabb, T** for (int i=0;i<8;i++) { - if (p_octant->children[i] && p_octant->children[i]->aabb.intersects(p_aabb)) { + if (p_octant->children[i] && p_octant->children[i]->aabb.intersects_inclusive(p_aabb)) { _cull_AABB(p_octant->children[i],p_aabb, p_result_array,p_result_idx,p_result_max,p_subindex_array,p_mask); } } diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp index 633aa06a9a..4c0a074a07 100644 --- a/core/os/keyboard.cpp +++ b/core/os/keyboard.cpp @@ -82,7 +82,7 @@ static const _KeyCodeText _keycodes[]={ {KEY_KP_ENTER ,"Kp Enter"}, {KEY_KP_MULTIPLY ,"Kp Multiply"}, {KEY_KP_DIVIDE ,"Kp Divide"}, - {KEY_KP_SUBSTRACT ,"Kp Substract"}, + {KEY_KP_SUBTRACT ,"Kp Subtract"}, {KEY_KP_PERIOD ,"Kp Period"}, {KEY_KP_ADD ,"Kp Add"}, {KEY_KP_0 ,"Kp 0"}, diff --git a/core/os/keyboard.h b/core/os/keyboard.h index 69e74d1252..0848f8c28e 100644 --- a/core/os/keyboard.h +++ b/core/os/keyboard.h @@ -98,7 +98,7 @@ enum KeyList { KEY_KP_ENTER=SPKEY | 0x80, KEY_KP_MULTIPLY=SPKEY | 0x81, KEY_KP_DIVIDE=SPKEY | 0x82, - KEY_KP_SUBSTRACT=SPKEY | 0x83, + KEY_KP_SUBTRACT=SPKEY | 0x83, KEY_KP_PERIOD=SPKEY | 0x84, KEY_KP_ADD=SPKEY | 0x85, KEY_KP_0=SPKEY | 0x86, diff --git a/core/os/memory.h b/core/os/memory.h index 98b973bc06..8eb5ceccb6 100644 --- a/core/os/memory.h +++ b/core/os/memory.h @@ -308,11 +308,11 @@ T* memnew_arr_template(size_t p_elements,const char *p_descr="") { same strategy used by std::vector, and the DVector class, so it should be safe.*/ size_t len = sizeof(T) * p_elements; - unsigned int *mem = (unsigned int*)Memory::alloc_static( len + DEFAULT_ALIGNMENT, p_descr ); + unsigned int *mem = (unsigned int*)Memory::alloc_static( len + MAX(sizeof(size_t), DEFAULT_ALIGNMENT), p_descr ); T *failptr=0; //get rid of a warning ERR_FAIL_COND_V( !mem, failptr ); *mem=p_elements; - mem = (unsigned int *)( ((uint8_t*)mem) + DEFAULT_ALIGNMENT); + mem = (unsigned int *)( ((uint8_t*)mem) + MAX(sizeof(size_t), DEFAULT_ALIGNMENT)); T* elems = (T*)mem; /* call operator new */ @@ -331,14 +331,14 @@ T* memnew_arr_template(size_t p_elements,const char *p_descr="") { template<typename T> size_t memarr_len(const T *p_class) { - uint8_t* ptr = ((uint8_t*)p_class) - DEFAULT_ALIGNMENT; + uint8_t* ptr = ((uint8_t*)p_class) - MAX(sizeof(size_t), DEFAULT_ALIGNMENT); return *(size_t*)ptr; } template<typename T> void memdelete_arr(T *p_class) { - unsigned int * elems = (unsigned int*)(((uint8_t*)p_class) - DEFAULT_ALIGNMENT); + unsigned int * elems = (unsigned int*)(((uint8_t*)p_class) - MAX(sizeof(size_t), DEFAULT_ALIGNMENT)); for (unsigned int i=0;i<*elems;i++) { diff --git a/core/os/os.cpp b/core/os/os.cpp index 0bc06c8375..1aee6d9aa2 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -478,6 +478,10 @@ void OS::native_video_pause() { }; +void OS::native_video_unpause() { + +}; + void OS::native_video_stop() { }; diff --git a/core/os/os.h b/core/os/os.h index 0d4edb035d..a80b81bfa2 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -376,6 +376,7 @@ public: virtual Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track); virtual bool native_video_is_playing() const; virtual void native_video_pause(); + virtual void native_video_unpause(); virtual void native_video_stop(); virtual bool can_use_threads() const; diff --git a/core/range_iterator.cpp b/core/range_iterator.cpp new file mode 100644 index 0000000000..9534e011d7 --- /dev/null +++ b/core/range_iterator.cpp @@ -0,0 +1,169 @@ +/*************************************************************************/ +/* range_iterator.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "range_iterator.h" +#include "object_type_db.h" + +void RangeIterator::_bind_methods() { + ObjectTypeDB::bind_method(_MD("_iter_init","arg"),&RangeIterator::_iter_init); + ObjectTypeDB::bind_method(_MD("_iter_next","arg"),&RangeIterator::_iter_next); + ObjectTypeDB::bind_method(_MD("_iter_get","arg"),&RangeIterator::_iter_get); + ObjectTypeDB::bind_method(_MD("is_finished"),&RangeIterator::is_finished); + ObjectTypeDB::bind_method(_MD("to_array"),&RangeIterator::to_array); + ObjectTypeDB::bind_method(_MD("set_range","arg1","arg2","arg3"),&RangeIterator::_set_range,DEFVAL(Variant()),DEFVAL(Variant())); +} + +bool RangeIterator::_iter_init(Variant arg) { + return !is_finished(); +} + +bool RangeIterator::_iter_next(Variant arg) { + current += step; + return !is_finished(); +} + +Variant RangeIterator::_iter_get(Variant arg) { + return Variant(current); +} + +bool RangeIterator::is_finished() { + if(step > 0) + { + return current >= stop; + } + else + { + return current <= stop; + } +} + +Array RangeIterator::to_array() { + if (step==0) { + ERR_EXPLAIN("step is zero!"); + ERR_FAIL_V(Array()); + } + + Array arr(true); + if (current >= stop && step > 0) { + return arr; + } + if (current <= stop && step < 0) { + return arr; + } + + //calculate how many + int count=0; + if (step > 0) { + count=((stop-current-1)/step)+1; + } else { + count=((current-stop-1)/-step)+1; + } + + arr.resize(count); + + if (step > 0) { + int idx=0; + for(int i=current;i<stop;i+=step) { + arr[idx++]=i; + } + } else { + int idx=0; + for(int i=current;i>stop;i+=step) { + arr[idx++]=i; + } + } + + return arr; +} + +void RangeIterator::set_range(int stop) { + this->current = 0; + this->stop = stop; + this->step = (stop > 0)?(1):(-1); +} + +void RangeIterator::set_range(int start, int stop) { + this->current = start; + this->stop = stop; + this->step = (stop > start)?(1):(-1); +} + +void RangeIterator::set_range(int start, int stop, int step) { + if(step == 0) + { + ERR_EXPLAIN("step is zero!"); + ERR_FAIL(); + } + + this->current = start; + this->stop = stop; + this->step = step; +} + +Ref<RangeIterator> RangeIterator::_set_range(Variant arg1, Variant arg2, Variant arg3) +{ + bool valid = true; + if(arg1.get_type() == Variant::INT) + { + if(arg2.get_type() == Variant::INT) + { + if(arg3.get_type() == Variant::INT) set_range((int)arg1, (int)arg2, (int)arg3); // (start, end, step) + else if(arg3.get_type() == Variant::NIL) set_range((int)arg1, (int)arg2); // (start, end) + else valid = false; + } + else if(arg2.get_type() == Variant::NIL) set_range((int)arg1); // (end) + else valid = false; + } + else valid = false; + + if(!valid) + { + ERR_EXPLAIN("Invalid type in function 'set_range' in base 'RangeIterator'. Expected 1, 2, or 3 ints."); + ERR_FAIL_V(Ref<RangeIterator>()); + } + return Ref<RangeIterator>(this); +} + +RangeIterator::RangeIterator() { + current = 0; + stop = 0; + step = 0; +} + +RangeIterator::RangeIterator(int stop) { + set_range(stop); +} + +RangeIterator::RangeIterator(int start, int stop) { + set_range(start, stop); +} + +RangeIterator::RangeIterator(int start, int stop, int step) { + set_range(start, stop, step); +} diff --git a/core/range_iterator.h b/core/range_iterator.h new file mode 100644 index 0000000000..c3e38a9094 --- /dev/null +++ b/core/range_iterator.h @@ -0,0 +1,72 @@ +/*************************************************************************/ +/* range_iterator.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef RANGE_ITERATOR_H +#define RANGE_ITERATOR_H + +#include "reference.h" +#include "variant.h" +#include "array.h" + +class RangeIterator : public Reference +{ +protected: + OBJ_TYPE( RangeIterator, Reference ); + + static void _bind_methods(); + +private: + int current; + int stop; + int step; + + bool _iter_init(Variant arg); + bool _iter_next(Variant arg); + Variant _iter_get(Variant arg); + +public: + + bool is_finished(); + + Array to_array(); + + void set_range(int stop); + void set_range(int start, int stop); + void set_range(int start, int stop, int step); + + Ref<RangeIterator> _set_range(Variant arg1, Variant arg2 = Variant(), Variant arg3 = Variant()); + + void _init(Variant arg1, Variant arg2, Variant arg3); + + RangeIterator(); + RangeIterator(int stop); + RangeIterator(int start, int stop); + RangeIterator(int start, int stop, int step); +}; + +#endif // RANGE_ITERATOR_H diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index d977ea3e18..c516059cfb 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -51,6 +51,8 @@ #include "packed_data_container.h" #include "func_ref.h" #include "input_map.h" +#include "undo_redo.h" +#include "range_iterator.h" #ifdef XML_ENABLED static ResourceFormatSaverXML *resource_saver_xml=NULL; @@ -128,6 +130,8 @@ void register_core_types() { // ObjectTypeDB::register_type<OptimizedSaver>(); ObjectTypeDB::register_type<Translation>(); ObjectTypeDB::register_type<PHashTranslation>(); + ObjectTypeDB::register_type<UndoRedo>(); + ObjectTypeDB::register_type<RangeIterator>(); ObjectTypeDB::register_type<HTTPClient>(); diff --git a/core/typedefs.h b/core/typedefs.h index 1ca7a4f66d..48acca326e 100644 --- a/core/typedefs.h +++ b/core/typedefs.h @@ -74,7 +74,7 @@ #endif #ifndef DEFAULT_ALIGNMENT -#define DEFAULT_ALIGNMENT 16 +#define DEFAULT_ALIGNMENT 1 #endif @@ -154,6 +154,23 @@ inline void __swap_tmpl(T &x, T &y ) { ((m_hex>='A' && m_hex<='F')?(10+m_hex-'A'):\ ((m_hex>='a' && m_hex<='f')?(10+m_hex-'a'):0))) +// Macro to check whether we are compiled by clang +// and we have a specific builtin +#if defined(__llvm__) && defined(__has_builtin) + #define _llvm_has_builtin(x) __has_builtin(x) +#else + #define _llvm_has_builtin(x) 0 +#endif + +#if (defined(__GNUC__) && (__GNUC__ >= 5)) || _llvm_has_builtin(__builtin_mul_overflow) +# define _mul_overflow __builtin_mul_overflow +#endif + +#if (defined(__GNUC__) && (__GNUC__ >= 5)) || _llvm_has_builtin(__builtin_add_overflow) +# define _add_overflow __builtin_add_overflow +#endif + + @@ -167,6 +184,19 @@ static _FORCE_INLINE_ unsigned int nearest_power_of_2(unsigned int x) { x |= x >> 4; x |= x >> 8; x |= x >> 16; + + return ++x; +} + +template<class T> +static _FORCE_INLINE_ T nearest_power_of_2_templated(T x) { + + --x; + // If the compiler is smart, it unrolls this loop + // If its dumb, this is a bit slow. + for (size_t i = 0; i < sizeof(T); i++) + x |= x >> (1 << i); + return ++x; } diff --git a/core/ustring.cpp b/core/ustring.cpp index ee750c39e5..1017fc0ca3 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -507,26 +507,35 @@ String String::capitalize() const { return cap; } -String String::camelcase_to_underscore() const { +String String::camelcase_to_underscore(bool lowercase) const { const CharType * cstr = c_str(); - String newString; + String new_string; const char A = 'A', Z = 'Z'; - int startIndex = 0; + const char a = 'a', z = 'z'; + int start_index = 0; - for ( int i = 1; i < this->size()-1; i++ ) { - bool isCapital = cstr[i] >= A && cstr[i] <= Z; + for ( size_t i = 1; i < this->size(); i++ ) { + bool is_upper = cstr[i] >= A && cstr[i] <= Z; + bool are_next_2_lower = false; + bool was_precedent_upper = cstr[i-1] >= A && cstr[i-1] <= Z; - if ( isCapital ) { - newString += "_" + this->substr(startIndex, i-startIndex); - startIndex = i; + if (i+2 < this->size()) { + are_next_2_lower = cstr[i+1] >= a && cstr[i+1] <= z && cstr[i+2] >= a && cstr[i+2] <= z; } - } - newString += "_" + this->substr(startIndex, this->size()-startIndex); + bool should_split = ((is_upper && !was_precedent_upper) || (was_precedent_upper && is_upper && are_next_2_lower)); + if (should_split) { + new_string += this->substr(start_index, i - start_index) + "_"; + start_index = i; + } + } - return newString; + new_string += this->substr(start_index, this->size() - start_index); + return lowercase ? new_string.to_lower() : new_string; } + + int String::get_slice_count(String p_splitter) const{ if (empty()) diff --git a/core/ustring.h b/core/ustring.h index 9276afa0f7..e65103ff99 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -149,7 +149,7 @@ public: static double to_double(const CharType* p_str, const CharType **r_end=NULL); static int64_t to_int(const CharType* p_str,int p_len=-1); String capitalize() const; - String camelcase_to_underscore() const; + String camelcase_to_underscore(bool lowercase=true) const; int get_slice_count(String p_splitter) const; String get_slice(String p_splitter,int p_slice) const; diff --git a/core/vector.h b/core/vector.h index 641721f401..398d7f1bd5 100644 --- a/core/vector.h +++ b/core/vector.h @@ -68,11 +68,26 @@ class Vector { return reinterpret_cast<T*>(_ptr); } - - _FORCE_INLINE_ int _get_alloc_size(int p_elements) const { - - return nearest_power_of_2(p_elements*sizeof(T)+sizeof(SafeRefCount)+sizeof(int)); - } + + _FORCE_INLINE_ size_t _get_alloc_size(size_t p_elements) const { + return nearest_power_of_2_templated(p_elements*sizeof(T)+sizeof(SafeRefCount)+sizeof(int)); + } + + _FORCE_INLINE_ bool _get_alloc_size_checked(size_t p_elements, size_t *out) const { +#if defined(_add_overflow) && defined(_mul_overflow) + size_t o; + size_t p; + if (_mul_overflow(p_elements, sizeof(T), &o)) return false; + if (_add_overflow(o, sizeof(SafeRefCount)+sizeof(int), &p)) return false; + *out = nearest_power_of_2_templated(p); + return true; +#else + // Speed is more important than correctness here, do the operations unchecked + // and hope the best + *out = _get_alloc_size(p_elements); + return true; +#endif + } void _unref(void *p_data); @@ -257,19 +272,21 @@ Error Vector<T>::resize(int p_size) { // possibly changing size, copy on write _copy_on_write(); + size_t alloc_size; + ERR_FAIL_COND_V(!_get_alloc_size_checked(p_size, &alloc_size), ERR_OUT_OF_MEMORY); + if (p_size>size()) { if (size()==0) { // alloc from scratch - void* ptr=memalloc(_get_alloc_size(p_size)); + void* ptr=memalloc(alloc_size); ERR_FAIL_COND_V( !ptr ,ERR_OUT_OF_MEMORY); _ptr=(T*)((uint8_t*)ptr+sizeof(int)+sizeof(SafeRefCount)); _get_refcount()->init(); // init refcount *_get_size()=0; // init size (currently, none) } else { - - void *_ptrnew = (T*)memrealloc((uint8_t*)_ptr-sizeof(int)-sizeof(SafeRefCount),_get_alloc_size(p_size)); + void *_ptrnew = (T*)memrealloc((uint8_t*)_ptr-sizeof(int)-sizeof(SafeRefCount), alloc_size); ERR_FAIL_COND_V( !_ptrnew ,ERR_OUT_OF_MEMORY); _ptr=(T*)((uint8_t*)_ptrnew+sizeof(int)+sizeof(SafeRefCount)); } @@ -293,7 +310,7 @@ Error Vector<T>::resize(int p_size) { t->~T(); } - void *_ptrnew = (T*)memrealloc((uint8_t*)_ptr-sizeof(int)-sizeof(SafeRefCount),_get_alloc_size(p_size)); + void *_ptrnew = (T*)memrealloc((uint8_t*)_ptr-sizeof(int)-sizeof(SafeRefCount), alloc_size); ERR_FAIL_COND_V( !_ptrnew ,ERR_OUT_OF_MEMORY); _ptr=(T*)((uint8_t*)_ptrnew+sizeof(int)+sizeof(SafeRefCount)); |