diff options
Diffstat (limited to 'core')
| -rw-r--r-- | core/array.cpp | 11 | ||||
| -rw-r--r-- | core/array.h | 2 | ||||
| -rw-r--r-- | core/class_db.cpp | 8 | ||||
| -rw-r--r-- | core/io/resource_format_binary.cpp | 3 | ||||
| -rw-r--r-- | core/list.h | 48 | ||||
| -rw-r--r-- | core/math/camera_matrix.cpp | 86 | ||||
| -rw-r--r-- | core/math/camera_matrix.h | 2 | ||||
| -rw-r--r-- | core/math/matrix3.cpp | 15 | ||||
| -rw-r--r-- | core/math/matrix3.h | 2 | ||||
| -rw-r--r-- | core/math/transform.cpp | 12 | ||||
| -rw-r--r-- | core/object.h | 12 | ||||
| -rw-r--r-- | core/project_settings.cpp | 10 | ||||
| -rw-r--r-- | core/resource.cpp | 3 | ||||
| -rw-r--r-- | core/script_language.h | 1 | ||||
| -rw-r--r-- | core/string_buffer.cpp | 102 | ||||
| -rw-r--r-- | core/string_buffer.h | 82 | ||||
| -rw-r--r-- | core/string_builder.cpp | 94 | ||||
| -rw-r--r-- | core/string_builder.h | 79 | ||||
| -rw-r--r-- | core/variant_call.cpp | 2 | ||||
| -rw-r--r-- | core/variant_parser.cpp | 22 |
20 files changed, 496 insertions, 100 deletions
diff --git a/core/array.cpp b/core/array.cpp index c35bf5bf0c..2e3fbf858d 100644 --- a/core/array.cpp +++ b/core/array.cpp @@ -210,6 +210,17 @@ const Variant &Array::get(int p_idx) const { return operator[](p_idx); } +Array Array::duplicate() const { + + Array new_arr; + int element_count = size(); + new_arr.resize(element_count); + for (int i = 0; i < element_count; i++) { + new_arr[i] = get(i); + } + + return new_arr; +} struct _ArrayVariantSort { _FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const { diff --git a/core/array.h b/core/array.h index 777116ab56..8a647dd13b 100644 --- a/core/array.h +++ b/core/array.h @@ -84,6 +84,8 @@ public: Variant pop_back(); Variant pop_front(); + Array duplicate() const; + Array(const Array &p_from); Array(); ~Array(); diff --git a/core/class_db.cpp b/core/class_db.cpp index 872e466e72..f5ddd9c761 100644 --- a/core/class_db.cpp +++ b/core/class_db.cpp @@ -536,11 +536,9 @@ void ClassDB::get_method_list(StringName p_class, List<MethodInfo> *p_methods, b minfo.return_val = method->get_return_info(); minfo.flags = method->get_hint_flags(); - int defval_count = method->get_default_argument_count(); - minfo.default_arguments.resize(defval_count); - - for (int i = 0; i < defval_count; i++) { - minfo.default_arguments[i] = method->get_default_argument(defval_count - i - 1); + for (int i = 0; i < method->get_argument_count(); i++) { + if (method->has_default_argument(i)) + minfo.default_arguments.push_back(method->get_default_argument(i)); } p_methods->push_back(minfo); diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index c5909981ea..084d8ffcab 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -1117,6 +1117,9 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons memdelete(f); } ERR_FAIL_COND_V(!fw, ERR_CANT_CREATE); + + uint8_t magic[4] = { 'R', 'S', 'R', 'C' }; + fw->store_buffer(magic, 4); } bool big_endian = f->get_32(); diff --git a/core/list.h b/core/list.h index a67287a9ab..da201e9868 100644 --- a/core/list.h +++ b/core/list.h @@ -291,6 +291,54 @@ public: erase(_data->first); } + Element *insert_after(Element *p_element, const T &p_value) { + CRASH_COND(p_element && (!_data || p_element->data != _data)); + + if (!p_element) { + return push_back(p_value); + } + + Element *n = memnew_allocator(Element, A); + n->value = (T &)p_value; + n->prev_ptr = p_element; + n->next_ptr = p_element->next_ptr; + n->data = _data; + + if (!p_element->next_ptr) { + _data->last = n; + } + + p_element->next_ptr = n; + + _data->size_cache++; + + return n; + } + + Element *insert_before(Element *p_element, const T &p_value) { + CRASH_COND(p_element && (!_data || p_element->data != _data)); + + if (!p_element) { + return push_back(p_value); + } + + Element *n = memnew_allocator(Element, A); + n->value = (T &)p_value; + n->prev_ptr = p_element->prev_ptr; + n->next_ptr = p_element; + n->data = _data; + + if (!p_element->prev_ptr) { + _data->first = n; + } + + p_element->prev_ptr = n; + + _data->size_cache++; + + return n; + } + /** * find an element in the list, */ diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp index 0512cdd798..572a6c5239 100644 --- a/core/math/camera_matrix.cpp +++ b/core/math/camera_matrix.cpp @@ -265,76 +265,28 @@ void CameraMatrix::get_viewport_size(real_t &r_width, real_t &r_height) const { bool CameraMatrix::get_endpoints(const Transform &p_transform, Vector3 *p_8points) const { - const real_t *matrix = (const real_t *)this->matrix; - - ///////--- Near Plane ---/////// - Plane near_plane = Plane(matrix[3] + matrix[2], - matrix[7] + matrix[6], - matrix[11] + matrix[10], - -matrix[15] - matrix[14]); - near_plane.normalize(); - - ///////--- Far Plane ---/////// - Plane far_plane = Plane(matrix[2] - matrix[3], - matrix[6] - matrix[7], - matrix[10] - matrix[11], - matrix[15] - matrix[14]); - far_plane.normalize(); - - ///////--- Right Plane ---/////// - Plane right_plane = Plane(matrix[0] - matrix[3], - matrix[4] - matrix[7], - matrix[8] - matrix[11], - -matrix[15] + matrix[12]); - right_plane.normalize(); - - ///////--- Top Plane ---/////// - Plane top_plane = Plane(matrix[1] - matrix[3], - matrix[5] - matrix[7], - matrix[9] - matrix[11], - -matrix[15] + matrix[13]); - top_plane.normalize(); - - Vector3 near_endpoint_left, near_endpoint_right; - Vector3 far_endpoint_left, far_endpoint_right; - - bool res = near_plane.intersect_3(right_plane, top_plane, &near_endpoint_right); - ERR_FAIL_COND_V(!res, false); - - res = far_plane.intersect_3(right_plane, top_plane, &far_endpoint_right); - ERR_FAIL_COND_V(!res, false); - - if ((matrix[8] == 0) && (matrix[9] == 0)) { - near_endpoint_left = near_endpoint_right; - near_endpoint_left.x = -near_endpoint_left.x; - - far_endpoint_left = far_endpoint_right; - far_endpoint_left.x = -far_endpoint_left.x; - } else { - ///////--- Left Plane ---/////// - Plane left_plane = Plane(matrix[0] + matrix[3], - matrix[4] + matrix[7], - matrix[8] + matrix[11], - -matrix[15] - matrix[12]); - left_plane.normalize(); + Vector<Plane> planes = get_projection_planes(Transform()); + const Planes intersections[8][3]={ + {PLANE_FAR,PLANE_LEFT,PLANE_TOP}, + {PLANE_FAR,PLANE_LEFT,PLANE_BOTTOM}, + {PLANE_FAR,PLANE_RIGHT,PLANE_TOP}, + {PLANE_FAR,PLANE_RIGHT,PLANE_BOTTOM}, + {PLANE_NEAR,PLANE_LEFT,PLANE_TOP}, + {PLANE_NEAR,PLANE_LEFT,PLANE_BOTTOM}, + {PLANE_NEAR,PLANE_RIGHT,PLANE_TOP}, + {PLANE_NEAR,PLANE_RIGHT,PLANE_BOTTOM}, + }; - res = near_plane.intersect_3(left_plane, top_plane, &near_endpoint_left); - ERR_FAIL_COND_V(!res, false); + for(int i=0;i<8;i++) { - res = far_plane.intersect_3(left_plane, top_plane, &far_endpoint_left); + Vector3 point; + bool res = planes[intersections[i][0]].intersect_3(planes[intersections[i][1]],planes[intersections[i][2]], &point); ERR_FAIL_COND_V(!res, false); + p_8points[i]=p_transform.xform(point); } - p_8points[0] = p_transform.xform(Vector3(near_endpoint_right.x, near_endpoint_right.y, near_endpoint_right.z)); - p_8points[1] = p_transform.xform(Vector3(near_endpoint_right.x, -near_endpoint_right.y, near_endpoint_right.z)); - p_8points[2] = p_transform.xform(Vector3(near_endpoint_left.x, near_endpoint_left.y, near_endpoint_left.z)); - p_8points[3] = p_transform.xform(Vector3(near_endpoint_left.x, -near_endpoint_left.y, near_endpoint_left.z)); - p_8points[4] = p_transform.xform(Vector3(far_endpoint_right.x, far_endpoint_right.y, far_endpoint_right.z)); - p_8points[5] = p_transform.xform(Vector3(far_endpoint_right.x, -far_endpoint_right.y, far_endpoint_right.z)); - p_8points[6] = p_transform.xform(Vector3(far_endpoint_left.x, far_endpoint_left.y, far_endpoint_left.z)); - p_8points[7] = p_transform.xform(Vector3(far_endpoint_left.x, -far_endpoint_left.y, far_endpoint_left.z)); - return true; + } Vector<Plane> CameraMatrix::get_projection_planes(const Transform &p_transform) const { @@ -610,6 +562,12 @@ int CameraMatrix::get_pixels_per_meter(int p_for_pixel_width) const { return int((result.x * 0.5 + 0.5) * p_for_pixel_width); } +bool CameraMatrix::is_orthogonal() const { + + return matrix[3][3]==1.0; +} + + real_t CameraMatrix::get_fov() const { const real_t *matrix = (const real_t *)this->matrix; diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h index 175d0cdb1b..87cc4b95b8 100644 --- a/core/math/camera_matrix.h +++ b/core/math/camera_matrix.h @@ -69,6 +69,7 @@ struct CameraMatrix { real_t get_z_near() const; real_t get_aspect() const; real_t get_fov() const; + bool is_orthogonal() const; Vector<Plane> get_projection_planes(const Transform &p_transform) const; @@ -83,6 +84,7 @@ struct CameraMatrix { Plane xform4(const Plane &p_vec4) const; _FORCE_INLINE_ Vector3 xform(const Vector3 &p_vec3) const; + operator String() const; void scale_translate_to_fit(const Rect3 &p_aabb); diff --git a/core/math/matrix3.cpp b/core/math/matrix3.cpp index 9732a1ff37..4051de7afb 100644 --- a/core/math/matrix3.cpp +++ b/core/math/matrix3.cpp @@ -234,7 +234,22 @@ Basis Basis::scaled(const Vector3 &p_scale) const { return m; } +void Basis::set_scale(const Vector3 &p_scale) { + + set_axis(0, get_axis(0).normalized() * p_scale.x); + set_axis(1, get_axis(1).normalized() * p_scale.y); + set_axis(2, get_axis(2).normalized() * p_scale.z); +} + Vector3 Basis::get_scale() const { + + return Vector3( + Vector3(elements[0][0], elements[1][0], elements[2][0]).length(), + Vector3(elements[0][1], elements[1][1], elements[2][1]).length(), + Vector3(elements[0][2], elements[1][2], elements[2][2]).length()); +} + +Vector3 Basis::get_signed_scale() const { // FIXME: We are assuming M = R.S (R is rotation and S is scaling), and use polar decomposition to extract R and S. // A polar decomposition is M = O.P, where O is an orthogonal matrix (meaning rotation and reflection) and // P is a positive semi-definite matrix (meaning it contains absolute values of scaling along its diagonal). diff --git a/core/math/matrix3.h b/core/math/matrix3.h index 9c9080ac46..23429888e0 100644 --- a/core/math/matrix3.h +++ b/core/math/matrix3.h @@ -97,7 +97,9 @@ public: void scale(const Vector3 &p_scale); Basis scaled(const Vector3 &p_scale) const; + void set_scale(const Vector3 &p_scale); Vector3 get_scale() const; + Vector3 get_signed_scale() const; // transposed dot products _FORCE_INLINE_ real_t tdotx(const Vector3 &v) const { diff --git a/core/math/transform.cpp b/core/math/transform.cpp index 60df69a509..638a39ab73 100644 --- a/core/math/transform.cpp +++ b/core/math/transform.cpp @@ -118,17 +118,17 @@ Transform Transform::interpolate_with(const Transform &p_transform, real_t p_c) /* not sure if very "efficient" but good enough? */ - Vector3 src_scale = basis.get_scale(); - Quat src_rot = basis; + Vector3 src_scale = basis.get_signed_scale(); + Quat src_rot = basis.orthonormalized(); Vector3 src_loc = origin; - Vector3 dst_scale = p_transform.basis.get_scale(); + Vector3 dst_scale = p_transform.basis.get_signed_scale(); Quat dst_rot = p_transform.basis; Vector3 dst_loc = p_transform.origin; - Transform dst; - dst.basis = src_rot.slerp(dst_rot, p_c); - dst.basis.scale(src_scale.linear_interpolate(dst_scale, p_c)); + Transform dst; //this could be made faster by using a single function in Basis.. + dst.basis = src_rot.slerp(dst_rot, p_c).normalized(); + dst.basis.set_scale(src_scale.linear_interpolate(dst_scale, p_c)); dst.origin = src_loc.linear_interpolate(dst_loc, p_c); return dst; diff --git a/core/object.h b/core/object.h index 6e1ed4308e..644e2b8270 100644 --- a/core/object.h +++ b/core/object.h @@ -567,12 +567,6 @@ public: template <class T> static T *cast_to(Object *p_object) { -#ifdef DEBUG_ENABLED - // TODO there are some legitimate reasons to pass NULL as p_object. - // we need to figure out how to deal with that in debug mode. - // This code will return NULL for a NULL input in release mode also. - ERR_FAIL_COND_V(p_object == NULL, NULL); -#endif #ifndef NO_SAFE_CAST return dynamic_cast<T *>(p_object); #else @@ -587,12 +581,6 @@ public: template <class T> static const T *cast_to(const Object *p_object) { -#ifdef DEBUG_ENABLED - // TODO there are some legitimate reasons to pass NULL as p_object. - // we need to figure out how to deal with that in debug mode. - // This code will return NULL for a NULL input in release mode also. - ERR_FAIL_COND_V(p_object == NULL, NULL); -#endif #ifndef NO_SAFE_CAST return dynamic_cast<const T *>(p_object); #else diff --git a/core/project_settings.cpp b/core/project_settings.cpp index a74917162b..23e4961138 100644 --- a/core/project_settings.cpp +++ b/core/project_settings.cpp @@ -114,7 +114,15 @@ String ProjectSettings::globalize_path(const String &p_path) const { return p_path.replace("res:/", resource_path); }; return p_path.replace("res://", ""); - }; + } else if (p_path.begins_with("user://")) { + + String data_dir = OS::get_singleton()->get_data_dir(); + if (data_dir != "") { + + return p_path.replace("user:/", data_dir); + }; + return p_path.replace("user://", ""); + } return p_path; } diff --git a/core/resource.cpp b/core/resource.cpp index 37d42226b4..78e20bada4 100644 --- a/core/resource.cpp +++ b/core/resource.cpp @@ -69,12 +69,11 @@ void Resource::set_path(const String &p_path, bool p_take_over) { ResourceCache::resources.get(p_path)->set_name(""); ResourceCache::lock->write_unlock(); } else { - ERR_EXPLAIN("Another resource is loaded from path: " + p_path); - ResourceCache::lock->read_lock(); bool exists = ResourceCache::resources.has(p_path); ResourceCache::lock->read_unlock(); + ERR_EXPLAIN("Another resource is loaded from path: " + p_path); ERR_FAIL_COND(exists); } } diff --git a/core/script_language.h b/core/script_language.h index 342d8c8072..2261737f9a 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -206,6 +206,7 @@ public: virtual int find_function(const String &p_function, const String &p_code) const = 0; virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const = 0; virtual Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { return ERR_UNAVAILABLE; } + virtual bool overrides_external_editor() { return false; } virtual Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, bool &r_force, String &r_call_hint) { return ERR_UNAVAILABLE; } diff --git a/core/string_buffer.cpp b/core/string_buffer.cpp new file mode 100644 index 0000000000..195068f887 --- /dev/null +++ b/core/string_buffer.cpp @@ -0,0 +1,102 @@ +/*************************************************************************/ +/* string_buffer.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* 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 "string_buffer.h" + +#include <string.h> + +StringBuffer &StringBuffer::append(CharType p_char) { + reserve(string_length + 2); + current_buffer_ptr()[string_length++] = p_char; + return *this; +} + +StringBuffer &StringBuffer::append(const String &p_string) { + return append(p_string.c_str()); +} + +StringBuffer &StringBuffer::append(const char *p_str) { + int len = strlen(p_str); + reserve(string_length + len + 1); + + CharType *buf = current_buffer_ptr(); + for (const char *c_ptr = p_str; c_ptr; ++c_ptr) { + buf[string_length++] = *c_ptr; + } + return *this; +} + +StringBuffer &StringBuffer::append(const CharType *p_str, int p_clip_to_len) { + int len = 0; + while ((p_clip_to_len < 0 || len < p_clip_to_len) && p_str[len]) { + ++len; + } + reserve(string_length + len + 1); + memcpy(&(current_buffer_ptr()[string_length]), p_str, len * sizeof(CharType)); + string_length += len; + + return *this; +} + +StringBuffer &StringBuffer::reserve(int p_size) { + if (p_size < SHORT_BUFFER_SIZE || p_size < buffer.size()) + return *this; + + bool need_copy = string_length > 0 && buffer.empty(); + buffer.resize(next_power_of_2(p_size)); + if (need_copy) { + memcpy(buffer.ptr(), short_buffer, string_length * sizeof(CharType)); + } + + return *this; +} + +int StringBuffer::length() const { + return string_length; +} + +String StringBuffer::as_string() { + current_buffer_ptr()[string_length] = '\0'; + if (buffer.empty()) { + return String(short_buffer); + } else { + buffer.resize(string_length + 1); + return buffer; + } +} + +double StringBuffer::as_double() { + current_buffer_ptr()[string_length] = '\0'; + return String::to_double(current_buffer_ptr()); +} + +int64_t StringBuffer::as_int() { + current_buffer_ptr()[string_length] = '\0'; + return String::to_int(current_buffer_ptr()); +} diff --git a/core/string_buffer.h b/core/string_buffer.h new file mode 100644 index 0000000000..3f36249148 --- /dev/null +++ b/core/string_buffer.h @@ -0,0 +1,82 @@ +/*************************************************************************/ +/* string_buffer.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* 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 STRING_BUFFER_H +#define STRING_BUFFER_H + +#include "ustring.h" + +class StringBuffer { + static const int SHORT_BUFFER_SIZE = 64; + + CharType short_buffer[SHORT_BUFFER_SIZE]; + String buffer; + int string_length = 0; + + _FORCE_INLINE_ CharType *current_buffer_ptr() { + return static_cast<Vector<CharType> &>(buffer).empty() ? short_buffer : buffer.ptr(); + } + +public: + StringBuffer &append(CharType p_char); + StringBuffer &append(const String &p_string); + StringBuffer &append(const char *p_str); + StringBuffer &append(const CharType *p_str, int p_clip_to_len = -1); + + _FORCE_INLINE_ void operator+=(CharType p_char) { + append(p_char); + } + + _FORCE_INLINE_ void operator+=(const String &p_string) { + append(p_string); + } + + _FORCE_INLINE_ void operator+=(const char *p_str) { + append(p_str); + } + + _FORCE_INLINE_ void operator+=(const CharType *p_str) { + append(p_str); + } + + StringBuffer &reserve(int p_size); + + int length() const; + + String as_string(); + + double as_double(); + int64_t as_int(); + + _FORCE_INLINE_ operator String() { + return as_string(); + } +}; + +#endif diff --git a/core/string_builder.cpp b/core/string_builder.cpp new file mode 100644 index 0000000000..18c710ed2d --- /dev/null +++ b/core/string_builder.cpp @@ -0,0 +1,94 @@ +/*************************************************************************/ +/* string_builder.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* 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 "string_builder.h" + +#include <string.h> + +StringBuilder &StringBuilder::append(const String &p_string) { + + strings.push_back(p_string); + appended_strings.push_back(-1); + + string_length += p_string.length(); + + return *this; +} + +StringBuilder &StringBuilder::append(const char *p_cstring) { + + int32_t len = strlen(p_cstring); + + c_strings.push_back(p_cstring); + appended_strings.push_back(len); + + string_length += len; + + return *this; +} + +String StringBuilder::as_string() const { + + CharType *buffer = memnew_arr(CharType, string_length); + + int current_position = 0; + + int godot_string_elem = 0; + int c_string_elem = 0; + + for (int i = 0; i < appended_strings.size(); i++) { + if (appended_strings[i] == -1) { + // Godot string + const String &s = strings[godot_string_elem]; + + memcpy(buffer + current_position, s.ptr(), s.length() * sizeof(CharType)); + + current_position += s.length(); + + godot_string_elem++; + } else { + + const char *s = c_strings[c_string_elem]; + + for (int32_t j = 0; j < appended_strings[i]; j++) { + buffer[current_position + j] = s[j]; + } + + current_position += appended_strings[i]; + + c_string_elem++; + } + } + + String final_string = String(buffer, string_length); + + memdelete_arr(buffer); + + return final_string; +} diff --git a/core/string_builder.h b/core/string_builder.h new file mode 100644 index 0000000000..7cf2f07872 --- /dev/null +++ b/core/string_builder.h @@ -0,0 +1,79 @@ +/*************************************************************************/ +/* string_builder.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* 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 STRING_BUILDER_H +#define STRING_BUILDER_H + +#include "core/ustring.h" + +#include "core/vector.h" + +class StringBuilder { + + uint32_t string_length = 0; + + Vector<String> strings; + Vector<const char *> c_strings; + + // -1 means it's a Godot String + // a natural number means C string. + Vector<int32_t> appended_strings; + +public: + StringBuilder &append(const String &p_string); + StringBuilder &append(const char *p_cstring); + + _FORCE_INLINE_ StringBuilder &operator+(const String &p_string) { + return append(p_string); + } + + _FORCE_INLINE_ StringBuilder &operator+(const char *p_cstring) { + return append(p_cstring); + } + + _FORCE_INLINE_ void operator+=(const String &p_string) { + append(p_string); + } + + _FORCE_INLINE_ void operator+=(const char *p_cstring) { + append(p_cstring); + } + + _FORCE_INLINE_ int num_strings_appended() const { + return appended_strings.size(); + } + + String as_string() const; + + _FORCE_INLINE_ operator String() const { + return as_string(); + } +}; + +#endif // STRING_BUILDER_H diff --git a/core/variant_call.cpp b/core/variant_call.cpp index ad15f8f5cb..dc1c24d234 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -481,6 +481,7 @@ struct _VariantCall { VCALL_LOCALMEM1(Array, erase); VCALL_LOCALMEM0(Array, sort); VCALL_LOCALMEM2(Array, sort_custom); + VCALL_LOCALMEM0R(Array, duplicate); VCALL_LOCALMEM0(Array, invert); static void _call_PoolByteArray_get_string_from_ascii(Variant &r_ret, Variant &p_self, const Variant **p_args) { @@ -1575,6 +1576,7 @@ void register_variant_methods() { ADDFUNC0(ARRAY, NIL, Array, sort, varray()); ADDFUNC2(ARRAY, NIL, Array, sort_custom, OBJECT, "obj", STRING, "func", varray()); ADDFUNC0(ARRAY, NIL, Array, invert, varray()); + ADDFUNC0(ARRAY, ARRAY, Array, duplicate, varray()); ADDFUNC0(POOL_BYTE_ARRAY, INT, PoolByteArray, size, varray()); ADDFUNC2(POOL_BYTE_ARRAY, NIL, PoolByteArray, set, INT, "idx", INT, "byte", varray()); diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp index 65c7b7cfec..d60d10cd3a 100644 --- a/core/variant_parser.cpp +++ b/core/variant_parser.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "variant_parser.h" +#include "core/string_buffer.h" #include "io/resource_loader.h" #include "os/input_event.h" #include "os/keyboard.h" @@ -176,14 +177,15 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri }; case '#': { - String color_str = "#"; + StringBuffer color_str; + color_str += '#'; while (true) { CharType ch = p_stream->get_char(); if (p_stream->is_eof()) { r_token.type = TK_EOF; return OK; } else if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) { - color_str += String::chr(ch); + color_str += ch; } else { p_stream->saved = ch; @@ -191,7 +193,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri } } - r_token.value = Color::html(color_str); + r_token.value = Color::html(color_str.as_string()); r_token.type = TK_COLOR; return OK; }; @@ -296,7 +298,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri if (cchar == '-' || (cchar >= '0' && cchar <= '9')) { //a number - String num; + StringBuffer num; #define READING_SIGN 0 #define READING_INT 1 #define READING_DEC 2 @@ -359,7 +361,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri if (reading == READING_DONE) break; - num += String::chr(c); + num += c; c = p_stream->get_char(); } @@ -368,19 +370,19 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri r_token.type = TK_NUMBER; if (is_float) - r_token.value = num.to_double(); + r_token.value = num.as_double(); else - r_token.value = num.to_int(); + r_token.value = num.as_int(); return OK; } else if ((cchar >= 'A' && cchar <= 'Z') || (cchar >= 'a' && cchar <= 'z') || cchar == '_') { - String id; + StringBuffer id; bool first = true; while ((cchar >= 'A' && cchar <= 'Z') || (cchar >= 'a' && cchar <= 'z') || cchar == '_' || (!first && cchar >= '0' && cchar <= '9')) { - id += String::chr(cchar); + id += cchar; cchar = p_stream->get_char(); first = false; } @@ -388,7 +390,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri p_stream->saved = cchar; r_token.type = TK_IDENTIFIER; - r_token.value = id; + r_token.value = id.as_string(); return OK; } else { r_err_str = "Unexpected character."; |