summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/bind/core_bind.cpp11
-rw-r--r--core/bind/core_bind.h2
-rw-r--r--core/color.cpp12
-rw-r--r--core/error_macros.h5
-rw-r--r--core/global_constants.cpp3
-rw-r--r--core/io/http_client.cpp8
-rw-r--r--core/io/resource_format_xml.cpp1
-rw-r--r--core/math/aabb.h18
-rw-r--r--core/math/octree.h12
-rw-r--r--core/os/keyboard.cpp2
-rw-r--r--core/os/keyboard.h2
-rw-r--r--core/os/memory.h8
-rw-r--r--core/os/os.cpp4
-rw-r--r--core/os/os.h1
-rw-r--r--core/range_iterator.cpp169
-rw-r--r--core/range_iterator.h72
-rw-r--r--core/register_core_types.cpp4
-rw-r--r--core/typedefs.h32
-rw-r--r--core/ustring.cpp31
-rw-r--r--core/ustring.h2
-rw-r--r--core/vector.h35
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));