summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/list.h48
-rw-r--r--core/math/matrix3.cpp15
-rw-r--r--core/math/matrix3.h2
-rw-r--r--core/math/transform.cpp12
-rw-r--r--core/object.h12
-rw-r--r--core/resource.cpp3
-rw-r--r--core/script_language.h1
-rw-r--r--core/string_buffer.cpp102
-rw-r--r--core/string_buffer.h82
-rw-r--r--core/string_builder.cpp94
-rw-r--r--core/string_builder.h79
-rw-r--r--core/variant_parser.cpp22
-rw-r--r--doc/base/classes.xml335
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp4
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp66
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h7
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp2
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h2
-rw-r--r--drivers/gles3/shader_compiler_gles3.cpp47
-rw-r--r--drivers/gles3/shaders/canvas.glsl2
-rw-r--r--drivers/gles3/shaders/scene.glsl8
-rw-r--r--drivers/unix/dir_access_unix.cpp44
-rw-r--r--drivers/unix/file_access_unix.cpp91
-rw-r--r--editor/SCsub60
-rw-r--r--editor/editor_about.cpp88
-rw-r--r--editor/editor_about.h1
-rw-r--r--editor/editor_fonts.cpp13
-rw-r--r--editor/editor_help.cpp24
-rw-r--r--editor/editor_log.cpp3
-rw-r--r--editor/editor_node.cpp69
-rw-r--r--editor/editor_node.h3
-rw-r--r--editor/editor_settings.cpp1
-rw-r--r--editor/editor_themes.cpp43
-rw-r--r--editor/filesystem_dock.cpp2
-rw-r--r--editor/import/resource_importer_texture.cpp9
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp87
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h3
-rw-r--r--editor/plugins/cube_grid_theme_editor_plugin.cpp7
-rw-r--r--editor/plugins/script_editor_plugin.cpp27
-rw-r--r--editor/plugins/script_text_editor.cpp9
-rw-r--r--editor/plugins/shader_editor_plugin.cpp2
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp317
-rw-r--r--editor/plugins/spatial_editor_plugin.h35
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp14
-rw-r--r--editor/project_settings_editor.cpp52
-rw-r--r--editor/project_settings_editor.h4
-rw-r--r--editor/quick_open.cpp52
-rw-r--r--editor/quick_open.h1
-rw-r--r--editor/settings_config_dialog.cpp2
-rw-r--r--modules/etc/image_etc.cpp3
-rw-r--r--modules/gdnative/SCsub12
-rw-r--r--modules/gdnative/gdnative.cpp6
-rw-r--r--modules/gdnative/gdnative.h7
-rw-r--r--modules/gdnative/gdnative/array.cpp (renamed from modules/gdnative/godot/array.cpp)2
-rw-r--r--modules/gdnative/gdnative/basis.cpp (renamed from modules/gdnative/godot/basis.cpp)2
-rw-r--r--modules/gdnative/gdnative/color.cpp (renamed from modules/gdnative/godot/color.cpp)2
-rw-r--r--modules/gdnative/gdnative/dictionary.cpp (renamed from modules/gdnative/godot/dictionary.cpp)2
-rw-r--r--modules/gdnative/gdnative/gdnative.cpp (renamed from modules/gdnative/godot/gdnative.cpp)3
-rw-r--r--modules/gdnative/gdnative/node_path.cpp (renamed from modules/gdnative/godot/node_path.cpp)2
-rw-r--r--modules/gdnative/gdnative/plane.cpp (renamed from modules/gdnative/godot/plane.cpp)2
-rw-r--r--modules/gdnative/gdnative/pool_arrays.cpp (renamed from modules/gdnative/godot/pool_arrays.cpp)2
-rw-r--r--modules/gdnative/gdnative/quat.cpp (renamed from modules/gdnative/godot/quat.cpp)2
-rw-r--r--modules/gdnative/gdnative/rect2.cpp (renamed from modules/gdnative/godot/rect2.cpp)2
-rw-r--r--modules/gdnative/gdnative/rect3.cpp (renamed from modules/gdnative/godot/rect3.cpp)2
-rw-r--r--modules/gdnative/gdnative/rid.cpp (renamed from modules/gdnative/godot/rid.cpp)2
-rw-r--r--modules/gdnative/gdnative/string.cpp (renamed from modules/gdnative/godot/string.cpp)2
-rw-r--r--modules/gdnative/gdnative/transform.cpp (renamed from modules/gdnative/godot/transform.cpp)2
-rw-r--r--modules/gdnative/gdnative/transform2d.cpp (renamed from modules/gdnative/godot/transform2d.cpp)2
-rw-r--r--modules/gdnative/gdnative/variant.cpp (renamed from modules/gdnative/godot/variant.cpp)2
-rw-r--r--modules/gdnative/gdnative/vector2.cpp (renamed from modules/gdnative/godot/vector2.cpp)2
-rw-r--r--modules/gdnative/gdnative/vector3.cpp (renamed from modules/gdnative/godot/vector3.cpp)2
-rw-r--r--modules/gdnative/godot/icon.png.import23
-rw-r--r--modules/gdnative/include/gdnative/array.h (renamed from modules/gdnative/godot/array.h)6
-rw-r--r--modules/gdnative/include/gdnative/basis.h (renamed from modules/gdnative/godot/basis.h)6
-rw-r--r--modules/gdnative/include/gdnative/color.h (renamed from modules/gdnative/godot/color.h)4
-rw-r--r--modules/gdnative/include/gdnative/dictionary.h (renamed from modules/gdnative/godot/dictionary.h)6
-rw-r--r--modules/gdnative/include/gdnative/gdnative.h (renamed from modules/gdnative/godot/gdnative.h)60
-rw-r--r--modules/gdnative/include/gdnative/node_path.h (renamed from modules/gdnative/godot/node_path.h)4
-rw-r--r--modules/gdnative/include/gdnative/plane.h (renamed from modules/gdnative/godot/plane.h)4
-rw-r--r--modules/gdnative/include/gdnative/pool_arrays.h (renamed from modules/gdnative/godot/pool_arrays.h)10
-rw-r--r--modules/gdnative/include/gdnative/quat.h (renamed from modules/gdnative/godot/quat.h)4
-rw-r--r--modules/gdnative/include/gdnative/rect2.h (renamed from modules/gdnative/godot/rect2.h)4
-rw-r--r--modules/gdnative/include/gdnative/rect3.h (renamed from modules/gdnative/godot/rect3.h)6
-rw-r--r--modules/gdnative/include/gdnative/rid.h (renamed from modules/gdnative/godot/rid.h)2
-rw-r--r--modules/gdnative/include/gdnative/string.h (renamed from modules/gdnative/godot/string.h)4
-rw-r--r--modules/gdnative/include/gdnative/transform.h (renamed from modules/gdnative/godot/transform.h)8
-rw-r--r--modules/gdnative/include/gdnative/transform2d.h (renamed from modules/gdnative/godot/transform2d.h)6
-rw-r--r--modules/gdnative/include/gdnative/variant.h (renamed from modules/gdnative/godot/variant.h)38
-rw-r--r--modules/gdnative/include/gdnative/vector2.h (renamed from modules/gdnative/godot/vector2.h)2
-rw-r--r--modules/gdnative/include/gdnative/vector3.h (renamed from modules/gdnative/godot/vector3.h)4
-rw-r--r--modules/gdnative/include/nativescript/godot_nativescript.h (renamed from modules/nativescript/godot_nativescript.h)2
-rw-r--r--modules/gdnative/nativescript/SCsub (renamed from modules/nativescript/SCsub)0
-rw-r--r--modules/gdnative/nativescript/api_generator.cpp (renamed from modules/nativescript/api_generator.cpp)0
-rw-r--r--modules/gdnative/nativescript/api_generator.h (renamed from modules/nativescript/api_generator.h)0
-rw-r--r--modules/gdnative/nativescript/godot_nativescript.cpp (renamed from modules/nativescript/godot_nativescript.cpp)8
-rw-r--r--modules/gdnative/nativescript/nativescript.cpp (renamed from modules/nativescript/nativescript.cpp)59
-rw-r--r--modules/gdnative/nativescript/nativescript.h (renamed from modules/nativescript/nativescript.h)5
-rw-r--r--modules/gdnative/nativescript/register_types.cpp (renamed from modules/nativescript/register_types.cpp)0
-rw-r--r--modules/gdnative/nativescript/register_types.h (renamed from modules/nativescript/register_types.h)0
-rw-r--r--modules/gdnative/register_types.cpp176
-rw-r--r--modules/gdscript/gd_script.h1
-rw-r--r--modules/gridmap/grid_map.cpp3
-rw-r--r--modules/nativescript/config.py8
-rw-r--r--modules/visual_script/visual_script.h1
-rw-r--r--modules/visual_script/visual_script_editor.cpp2
-rw-r--r--scene/2d/canvas_item.cpp1
-rw-r--r--scene/3d/physics_body.cpp228
-rw-r--r--scene/3d/physics_body.h52
-rw-r--r--scene/gui/base_button.cpp10
-rw-r--r--scene/gui/graph_node.cpp20
-rw-r--r--scene/gui/graph_node.h6
-rw-r--r--scene/gui/item_list.cpp16
-rw-r--r--scene/gui/item_list.h4
-rw-r--r--scene/gui/line_edit.cpp2
-rw-r--r--scene/gui/rich_text_label.cpp29
-rw-r--r--scene/gui/rich_text_label.h2
-rw-r--r--scene/gui/text_edit.cpp21
-rw-r--r--scene/gui/tree.cpp6
-rw-r--r--scene/register_scene_types.cpp1
-rw-r--r--scene/resources/default_theme/default_theme.cpp1
-rw-r--r--scene/resources/material.cpp11
-rw-r--r--scene/resources/material.h6
-rw-r--r--scene/resources/mesh_library.cpp4
-rw-r--r--scene/resources/mesh_library.h2
-rw-r--r--servers/physics/collision_object_sw.cpp32
-rw-r--r--servers/physics/collision_object_sw.h2
-rw-r--r--servers/physics/physics_server_sw.cpp21
-rw-r--r--servers/physics/physics_server_sw.h4
-rw-r--r--servers/visual/shader_language.cpp136
-rw-r--r--servers/visual/shader_language.h22
130 files changed, 2391 insertions, 787 deletions
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/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/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_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.";
diff --git a/doc/base/classes.xml b/doc/base/classes.xml
index e04ccc724d..8d16585726 100644
--- a/doc/base/classes.xml
+++ b/doc/base/classes.xml
@@ -5670,7 +5670,7 @@
<argument index="1" name="func" type="String">
</argument>
<description>
- Sort the array using a custom method. The arguments are an object that holds the method and the name of such method. The custom method receives two arguments (a pair of elements from the array) and must return true if the first argument is less than the second, and return false otherwise.
+ Sort the array using a custom method. The arguments are an object that holds the method and the name of such method. The custom method receives two arguments (a pair of elements from the array) and must return true if the first argument is less than the second, and return false otherwise. Note: you cannot randomize the return value as the heapsort algorithm expects a deterministic result. Doing so will result in unexpected behavior.
</description>
</method>
</methods>
@@ -19137,6 +19137,12 @@
<description>
</description>
</method>
+ <method name="is_singleton_gdnative" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="set_library_path">
<return type="void">
</return>
@@ -19147,7 +19153,19 @@
<description>
</description>
</method>
+ <method name="set_singleton_gdnative">
+ <return type="void">
+ </return>
+ <argument index="0" name="singleton" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
</methods>
+ <members>
+ <member name="singleton_gdnative" type="bool" setter="set_singleton_gdnative" getter="is_singleton_gdnative" brief="">
+ </member>
+ </members>
<constants>
</constants>
</class>
@@ -20807,7 +20825,7 @@
<description>
</description>
</method>
- <method name="is_resizeable" qualifiers="const">
+ <method name="is_resizable" qualifiers="const">
<return type="bool">
</return>
<description>
@@ -20862,10 +20880,10 @@
<description>
</description>
</method>
- <method name="set_resizeable">
+ <method name="set_resizable">
<return type="void">
</return>
- <argument index="0" name="resizeable" type="bool">
+ <argument index="0" name="resizable" type="bool">
</argument>
<description>
</description>
@@ -20922,7 +20940,7 @@
</method>
</methods>
<members>
- <member name="resizeable" type="bool" setter="set_resizeable" getter="is_resizeable" brief="">
+ <member name="resizable" type="bool" setter="set_resizable" getter="is_resizable" brief="">
</member>
<member name="show_close" type="bool" setter="set_show_close_button" getter="is_close_button_visible" brief="">
</member>
@@ -24844,108 +24862,28 @@
Kinematic Characters: KinematicBody also has an api for moving objects (the [method move] method) while performing collision tests. This makes them really useful to implement characters that collide against a world, but that don't require advanced physics.
</description>
<methods>
- <method name="get_collision_collider" qualifiers="const">
- <return type="Object">
- </return>
- <argument index="0" name="collision" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_collision_collider_id" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="collision" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_collision_collider_metadata" qualifiers="const">
- <return type="Variant">
- </return>
- <argument index="0" name="collision" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_collision_collider_shape" qualifiers="const">
- <return type="Object">
- </return>
- <argument index="0" name="collision" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_collision_collider_shape_index" qualifiers="const">
- <return type="int">
- </return>
- <argument index="0" name="collision" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_collision_collider_velocity" qualifiers="const">
- <return type="Vector3">
- </return>
- <argument index="0" name="collision" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_collision_count" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
- <method name="get_collision_local_shape" qualifiers="const">
- <return type="Object">
- </return>
- <argument index="0" name="collision" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_collision_normal" qualifiers="const">
- <return type="Vector3">
- </return>
- <argument index="0" name="collision" type="int">
- </argument>
- <description>
- </description>
- </method>
- <method name="get_collision_position" qualifiers="const">
+ <method name="get_floor_velocity" qualifiers="const">
<return type="Vector3">
</return>
- <argument index="0" name="collision" type="int">
- </argument>
<description>
</description>
</method>
- <method name="get_collision_remainder" qualifiers="const">
- <return type="Vector3">
+ <method name="get_safe_margin" qualifiers="const">
+ <return type="float">
</return>
- <argument index="0" name="collision" type="int">
- </argument>
<description>
</description>
</method>
- <method name="get_collision_travel" qualifiers="const">
- <return type="Vector3">
+ <method name="get_slide_collision">
+ <return type="KinematicCollision">
</return>
- <argument index="0" name="collision" type="int">
+ <argument index="0" name="slide_idx" type="int">
</argument>
<description>
</description>
</method>
- <method name="get_floor_velocity" qualifiers="const">
- <return type="Vector3">
- </return>
- <description>
- </description>
- </method>
- <method name="get_safe_margin" qualifiers="const">
- <return type="float">
+ <method name="get_slide_count" qualifiers="const">
+ <return type="int">
</return>
<description>
</description>
@@ -24968,22 +24906,12 @@
<description>
</description>
</method>
- <method name="move">
- <return type="Dictionary">
+ <method name="move_and_collide">
+ <return type="KinematicCollision">
</return>
<argument index="0" name="rel_vec" type="Vector3">
</argument>
<description>
- Move the body in the given direction, stopping if there is an obstacle. If as a result of a movement there will be any collision then informations about this collision will be in returned dictionary. Dictionary will contains those keys:
- - "position" - collision position
- - "normal" - collision normal
- - "local_shape" - id of this kinematic body shape that took part in a collision
- - "travel" - traveled movement before being stopped
- - "remainder" - remaining movement before being stopped
- - "collider_id" - id of the collider, it can be used when dealing with [PhysicsServer]
- - "collider" - colliding body
- - "collider_shape_index" - index of the colliding shape, inside collider body "collider_metadata"
- If the body did not intersect anything, then an empty dictionary (dir.empty()==true) is returned instead. Please note that this method is less user friendly than [method move_and_slide]. If you don't want to program each edge case manually, then it's recommended to use [method move_and_slide] instead.
</description>
</method>
<method name="move_and_slide">
@@ -24995,7 +24923,7 @@
</argument>
<argument index="2" name="slope_stop_min_velocity" type="float" default="0.05">
</argument>
- <argument index="3" name="max_bounces" type="int" default="4">
+ <argument index="3" name="max_slides" type="int" default="4">
</argument>
<argument index="4" name="floor_max_angle" type="float" default="0.785398">
</argument>
@@ -25224,6 +25152,106 @@
<constants>
</constants>
</class>
+<class name="KinematicCollision" inherits="Reference" category="Core">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <methods>
+ <method name="get_collider" qualifiers="const">
+ <return type="Object">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_collider_id" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_collider_metadata" qualifiers="const">
+ <return type="Variant">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_collider_shape" qualifiers="const">
+ <return type="Object">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_collider_shape_index" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_collider_velocity" qualifiers="const">
+ <return type="Vector3">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_local_shape" qualifiers="const">
+ <return type="Object">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_normal" qualifiers="const">
+ <return type="Vector3">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_position" qualifiers="const">
+ <return type="Vector3">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_remainder" qualifiers="const">
+ <return type="Vector3">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_travel" qualifiers="const">
+ <return type="Vector3">
+ </return>
+ <description>
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="collider" type="Object" setter="" getter="get_collider" brief="">
+ </member>
+ <member name="collider_id" type="int" setter="" getter="get_collider_id" brief="">
+ </member>
+ <member name="collider_metadata" type="Variant" setter="" getter="get_collider_metadata" brief="">
+ </member>
+ <member name="collider_shape" type="Object" setter="" getter="get_collider_shape" brief="">
+ </member>
+ <member name="collider_shape_index" type="int" setter="" getter="get_collider_shape_index" brief="">
+ </member>
+ <member name="collider_velocity" type="Vector3" setter="" getter="get_collider_velocity" brief="">
+ </member>
+ <member name="local_shape" type="Object" setter="" getter="get_local_shape" brief="">
+ </member>
+ <member name="normal" type="Vector3" setter="" getter="get_normal" brief="">
+ </member>
+ <member name="position" type="Vector3" setter="" getter="get_position" brief="">
+ </member>
+ <member name="remainder" type="Vector3" setter="" getter="get_remainder" brief="">
+ </member>
+ <member name="travel" type="Vector3" setter="" getter="get_travel" brief="">
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
<class name="Label" inherits="Control" category="Core">
<brief_description>
Control that displays formatted text.
@@ -27727,6 +27755,14 @@
Create a new item in the library, supplied an id.
</description>
</method>
+ <method name="find_item_by_name" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="get_item_list" qualifiers="const">
<return type="PoolIntArray">
</return>
@@ -42738,6 +42774,8 @@
</theme_item>
<theme_item name="mono_font" type="Font">
</theme_item>
+ <theme_item name="normal" type="StyleBox">
+ </theme_item>
<theme_item name="normal_font" type="Font">
</theme_item>
<theme_item name="selection_color" type="Color">
@@ -45908,6 +45946,12 @@
<description>
</description>
</method>
+ <method name="get_transmission" qualifiers="const">
+ <return type="Color">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_uv1_offset" qualifiers="const">
<return type="Vector3">
</return>
@@ -46290,6 +46334,14 @@
<description>
</description>
</method>
+ <method name="set_transmission">
+ <return type="void">
+ </return>
+ <argument index="0" name="transmission" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_uv1_offset">
<return type="void">
</return>
@@ -46484,6 +46536,12 @@
</member>
<member name="subsurf_scatter_texture" type="Texture" setter="set_texture" getter="get_texture" brief="">
</member>
+ <member name="transmission" type="Color" setter="set_transmission" getter="get_transmission" brief="">
+ </member>
+ <member name="transmission_enabled" type="bool" setter="set_feature" getter="get_feature" brief="">
+ </member>
+ <member name="transmission_texture" type="Texture" setter="set_texture" getter="get_texture" brief="">
+ </member>
<member name="uv1_offset" type="Vector3" setter="set_uv1_offset" getter="get_uv1_offset" brief="">
</member>
<member name="uv1_scale" type="Vector3" setter="set_uv1_scale" getter="get_uv1_scale" brief="">
@@ -46528,15 +46586,17 @@
</constant>
<constant name="TEXTURE_SUBSURFACE_SCATTERING" value="10">
</constant>
- <constant name="TEXTURE_REFRACTION" value="11">
+ <constant name="TEXTURE_TRANSMISSION" value="11">
+ </constant>
+ <constant name="TEXTURE_REFRACTION" value="12">
</constant>
- <constant name="TEXTURE_DETAIL_MASK" value="12">
+ <constant name="TEXTURE_DETAIL_MASK" value="13">
</constant>
- <constant name="TEXTURE_DETAIL_ALBEDO" value="13">
+ <constant name="TEXTURE_DETAIL_ALBEDO" value="14">
</constant>
- <constant name="TEXTURE_DETAIL_NORMAL" value="14">
+ <constant name="TEXTURE_DETAIL_NORMAL" value="15">
</constant>
- <constant name="TEXTURE_MAX" value="15">
+ <constant name="TEXTURE_MAX" value="16">
</constant>
<constant name="DETAIL_UV_1" value="0">
</constant>
@@ -46560,11 +46620,13 @@
</constant>
<constant name="FEATURE_SUBSURACE_SCATTERING" value="8">
</constant>
- <constant name="FEATURE_REFRACTION" value="9">
+ <constant name="FEATURE_TRANSMISSION" value="9">
+ </constant>
+ <constant name="FEATURE_REFRACTION" value="10">
</constant>
- <constant name="FEATURE_DETAIL" value="10">
+ <constant name="FEATURE_DETAIL" value="11">
</constant>
- <constant name="FEATURE_MAX" value="11">
+ <constant name="FEATURE_MAX" value="12">
</constant>
<constant name="BLEND_MODE_MIX" value="0">
</constant>
@@ -46616,7 +46678,7 @@
</constant>
<constant name="DIFFUSE_LAMBERT" value="0">
</constant>
- <constant name="DIFFUSE_HALF_LAMBERT" value="1">
+ <constant name="DIFFUSE_LAMBERT_WRAP" value="1">
</constant>
<constant name="DIFFUSE_OREN_NAYAR" value="2">
</constant>
@@ -49210,10 +49272,26 @@
</class>
<class name="StyleBoxFlat" inherits="StyleBox" category="Core">
<brief_description>
- Stylebox of a single color.
+ Customizable Stylebox with a given set of parameters. (no texture required)
</brief_description>
<description>
- Stylebox of a single color. Displays the stylebox of a single color, alternatively a border with light/dark colors can be assigned.
+ This stylebox can be used to achieve all kinds of looks without the need of a texture. Those properties are customizable:
+ - Color
+ - Border width (individual width for each border)
+ - Rounded corners (individual radius for each corner)
+ - Shadow
+ About corner radius:
+ Setting corner radius to high values is allowed. As soon as corners would overlap the stylebox will switch to a relative system. Example:
+ [codeblock]
+ height = 30
+ corner_radius_top_left = 50
+ corner_raidus_bottom_left = 100
+ [/codeblock]
+ The relative system now would take the 1:2 ratio of the two left corners to calculate the actual corner width. Both corners added will [b]never[/b] be more than the height. Result:
+ [codeblock]
+ corner_radius_top_left: 10
+ corner_raidus_bottom_left: 20
+ [/codeblock]
</description>
<methods>
<method name="get_aa_size" qualifiers="const">
@@ -49457,46 +49535,69 @@
</methods>
<members>
<member name="anti_aliasing" type="bool" setter="set_anti_aliased" getter="is_anti_aliased" brief="">
+ Anti Aliasing draws a small ring around edges. This ring fades to transparent. As a result edges look much smoother. This is only noticable when using rounded corners.
</member>
<member name="anti_aliasing_size" type="int" setter="set_aa_size" getter="get_aa_size" brief="">
+ This changes the size of the faded ring. Higher values can be used to achieve a "blurry" effect.
</member>
<member name="bg_color" type="Color" setter="set_bg_color" getter="get_bg_color" brief="">
+ The background color of the stylebox.
</member>
<member name="border_blend" type="bool" setter="set_border_blend" getter="get_border_blend" brief="">
+ When set to true, the border will fade into the background color.
</member>
<member name="border_color" type="Color" setter="set_border_color" getter="get_border_color" brief="">
+ Sets the color of the border.
</member>
<member name="border_width_bottom" type="int" setter="set_border_width" getter="get_border_width" brief="">
+ Border width for the bottom border.
</member>
<member name="border_width_left" type="int" setter="set_border_width" getter="get_border_width" brief="">
+ Border width for the left border.
</member>
<member name="border_width_right" type="int" setter="set_border_width" getter="get_border_width" brief="">
+ Border width for the right border.
</member>
<member name="border_width_top" type="int" setter="set_border_width" getter="get_border_width" brief="">
+ Border width for the top border.
</member>
<member name="corner_detail" type="int" setter="set_corner_detail" getter="get_corner_detail" brief="">
+ This sets the amount of vertices used for each corner. Higher values result in rounder corners but take more processing power to compute. When choosing a value you should take the corner radius ([method set_corner_radius]) into account.
+ For corner radius smaller than 10: 4-5 should be enough
+ For corner radius smaller than 30: 8-12 should be enough ...
</member>
<member name="corner_radius_bottom_left" type="int" setter="set_corner_radius" getter="get_corner_radius" brief="">
+ The corner radius of the bottom left corner. When set to 0 the corner is not rounded.
</member>
<member name="corner_radius_bottom_right" type="int" setter="set_corner_radius" getter="get_corner_radius" brief="">
+ The corner radius of the bottom right corner. When set to 0 the corner is not rounded.
</member>
<member name="corner_radius_top_left" type="int" setter="set_corner_radius" getter="get_corner_radius" brief="">
+ The corner radius of the top left corner. When set to 0 the corner is not rounded.
</member>
<member name="corner_radius_top_right" type="int" setter="set_corner_radius" getter="get_corner_radius" brief="">
+ The corner radius of the top right corner. When set to 0 the corner is not rounded.
</member>
<member name="draw_center" type="bool" setter="set_draw_center" getter="is_draw_center_enabled" brief="">
+ Toggels drawing of the inner part of the stylebox.
</member>
<member name="expand_margin_bottom" type="float" setter="set_expand_margin" getter="get_expand_margin" brief="">
+ Expands the stylebox outside of the control rect on the bottom edge. Useful in combination with border_width_bottom. To draw a border outside the control rect.
</member>
<member name="expand_margin_left" type="float" setter="set_expand_margin" getter="get_expand_margin" brief="">
+ Expands the stylebox outside of the control rect on the left edge. Useful in combination with border_width_left. To draw a border outside the control rect.
</member>
<member name="expand_margin_right" type="float" setter="set_expand_margin" getter="get_expand_margin" brief="">
+ Expands the stylebox outside of the control rect on the right edge. Useful in combination with border_width_right. To draw a border outside the control rect.
</member>
<member name="expand_margin_top" type="float" setter="set_expand_margin" getter="get_expand_margin" brief="">
+ Expands the stylebox outside of the control rect on the top edge. Useful in combination with border_width_top. To draw a border outside the control rect.
</member>
<member name="shadow_color" type="Color" setter="set_shadow_color" getter="get_shadow_color" brief="">
+ The color of the shadow. (This has no effect when shadow_size &lt; 1)
</member>
<member name="shadow_size" type="int" setter="set_shadow_size" getter="get_shadow_size" brief="">
+ The shadow size in pixels.
</member>
</members>
<constants>
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index ff0741f425..84f29facf4 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -1115,6 +1115,10 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
_copy_texscreen(Rect2());
}
+ if (shader_ptr->canvas_item.uses_time) {
+ VisualServerRaster::redraw_request();
+ }
+
state.canvas_shader.set_custom_shader(shader_ptr->custom_code_id);
state.canvas_shader.bind();
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 6bef039dd1..2615f9c1b3 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -32,6 +32,7 @@
#include "os/os.h"
#include "project_settings.h"
#include "rasterizer_canvas_gles3.h"
+#include "servers/visual/visual_server_raster.h"
#ifndef GLES_OVER_GL
#define glClearDepth glClearDepthf
@@ -1939,6 +1940,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
bool prev_use_instancing = false;
storage->info.render.draw_call_count += p_element_count;
+ bool prev_opaque_prepass = false;
for (int i = 0; i < p_element_count; i++) {
@@ -2072,6 +2074,13 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
}
}
+ bool use_opaque_prepass = e->sort_key & RenderList::SORT_KEY_OPAQUE_PRE_PASS;
+
+ if (use_opaque_prepass != prev_opaque_prepass) {
+ state.scene_shader.set_conditional(SceneShaderGLES3::USE_OPAQUE_PREPASS, use_opaque_prepass);
+ rebind = true;
+ }
+
bool use_instancing = e->instance->base_type == VS::INSTANCE_MULTIMESH || e->instance->base_type == VS::INSTANCE_PARTICLES;
if (use_instancing != prev_use_instancing) {
@@ -2127,6 +2136,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
prev_shading = shading;
prev_skeleton = skeleton;
prev_use_instancing = use_instancing;
+ prev_opaque_prepass = use_opaque_prepass;
first = false;
}
@@ -2148,9 +2158,10 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
state.scene_shader.set_conditional(SceneShaderGLES3::USE_GI_PROBES, false);
state.scene_shader.set_conditional(SceneShaderGLES3::USE_CONTACT_SHADOWS, false);
state.scene_shader.set_conditional(SceneShaderGLES3::USE_VERTEX_LIGHTING, false);
+ state.scene_shader.set_conditional(SceneShaderGLES3::USE_OPAQUE_PREPASS, false);
}
-void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_shadow) {
+void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_depth_pass) {
RasterizerStorageGLES3::Material *m = NULL;
RID m_src = p_instance->material_override.is_valid() ? p_instance->material_override : (p_material >= 0 ? p_instance->materials[p_material] : p_geometry->material);
@@ -2182,22 +2193,21 @@ void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geo
ERR_FAIL_COND(!m);
- _add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_shadow);
+ _add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_depth_pass);
while (m->next_pass.is_valid()) {
m = storage->material_owner.getornull(m->next_pass);
if (!m || !m->shader || !m->shader->valid)
break;
- _add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_shadow);
+ _add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_depth_pass);
}
}
-void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_shadow) {
+void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_depth_pass) {
bool has_base_alpha = (p_material->shader->spatial.uses_alpha && !p_material->shader->spatial.uses_alpha_scissor) || p_material->shader->spatial.uses_screen_texture;
bool has_blend_alpha = p_material->shader->spatial.blend_mode != RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX;
bool has_alpha = has_base_alpha || has_blend_alpha;
- bool shadow = false;
bool mirror = p_instance->mirror;
bool no_cull = false;
@@ -2217,7 +2227,7 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G
state.used_screen_texture = true;
}
- if (p_shadow) {
+ if (p_depth_pass) {
if (has_blend_alpha || (has_base_alpha && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS))
return; //bye
@@ -2252,14 +2262,14 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G
e->geometry->index = current_geometry_index++;
}
- if (!p_shadow && directional_light && (directional_light->light_ptr->cull_mask & e->instance->layer_mask) == 0) {
+ if (!p_depth_pass && directional_light && (directional_light->light_ptr->cull_mask & e->instance->layer_mask) == 0) {
e->sort_key |= SORT_KEY_NO_DIRECTIONAL_FLAG;
}
e->sort_key |= uint64_t(e->geometry->index) << RenderList::SORT_KEY_GEOMETRY_INDEX_SHIFT;
e->sort_key |= uint64_t(e->instance->base_type) << RenderList::SORT_KEY_GEOMETRY_TYPE_SHIFT;
- if (!p_shadow) {
+ if (!p_depth_pass) {
if (e->material->last_pass != render_pass) {
e->material->last_pass = render_pass;
@@ -2269,17 +2279,6 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G
e->sort_key |= uint64_t(e->material->index) << RenderList::SORT_KEY_MATERIAL_INDEX_SHIFT;
e->sort_key |= uint64_t(e->instance->depth_layer) << RenderList::SORT_KEY_OPAQUE_DEPTH_LAYER_SHIFT;
- if (!has_blend_alpha && has_alpha && p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) {
-
- //if nothing exists, add this element as opaque too
- RenderList::Element *oe = render_list.add_element();
-
- if (!oe)
- return;
-
- copymem(oe, e, sizeof(RenderList::Element));
- }
-
if (e->instance->gi_probe_instances.size()) {
e->sort_key |= SORT_KEY_GI_PROBES_FLAG;
}
@@ -2302,24 +2301,21 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G
//e->light_type=0xFF; // no lights!
- if (shadow || p_material->shader->spatial.unshaded || state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
-
+ if (p_depth_pass || p_material->shader->spatial.unshaded || state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
e->sort_key |= SORT_KEY_UNSHADED_FLAG;
}
- if (!shadow && (p_material->shader->spatial.uses_vertex_lighting || storage->config.force_vertex_shading)) {
+ if (p_depth_pass && p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) {
+ e->sort_key |= RenderList::SORT_KEY_OPAQUE_PRE_PASS;
+ }
+
+ if (!p_depth_pass && (p_material->shader->spatial.uses_vertex_lighting || storage->config.force_vertex_shading)) {
e->sort_key |= SORT_KEY_VERTEX_LIT_FLAG;
}
- if (!shadow && has_alpha && p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) {
- //depth prepass for alpha
- RenderList::Element *eo = render_list.add_element();
-
- eo->instance = e->instance;
- eo->geometry = e->geometry;
- eo->material = e->material;
- eo->sort_key = e->sort_key;
+ if (p_material->shader->spatial.uses_time) {
+ VisualServerRaster::redraw_request();
}
}
@@ -3032,7 +3028,7 @@ void RasterizerSceneGLES3::_copy_texture_to_front_buffer(GLuint p_texture) {
storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false);
}
-void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_shadow) {
+void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass) {
current_geometry_index = 0;
current_material_index = 0;
@@ -3057,7 +3053,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p
int mat_idx = inst->materials[i].is_valid() ? i : -1;
RasterizerStorageGLES3::Surface *s = mesh->surfaces[i];
- _add_geometry(s, inst, NULL, mat_idx, p_shadow);
+ _add_geometry(s, inst, NULL, mat_idx, p_depth_pass);
}
//mesh->last_pass=frame;
@@ -3080,7 +3076,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p
for (int i = 0; i < ssize; i++) {
RasterizerStorageGLES3::Surface *s = mesh->surfaces[i];
- _add_geometry(s, inst, multi_mesh, -1, p_shadow);
+ _add_geometry(s, inst, multi_mesh, -1, p_depth_pass);
}
} break;
@@ -3089,7 +3085,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p
RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getptr(inst->base);
ERR_CONTINUE(!immediate);
- _add_geometry(immediate, inst, NULL, -1, p_shadow);
+ _add_geometry(immediate, inst, NULL, -1, p_depth_pass);
} break;
case VS::INSTANCE_PARTICLES: {
@@ -3111,7 +3107,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p
for (int j = 0; j < ssize; j++) {
RasterizerStorageGLES3::Surface *s = mesh->surfaces[j];
- _add_geometry(s, inst, particles, -1, p_shadow);
+ _add_geometry(s, inst, particles, -1, p_depth_pass);
}
}
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index 5503dba5c4..b3fd6fa2a0 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -664,6 +664,7 @@ public:
//bits 12-8 geometry type
SORT_KEY_GEOMETRY_TYPE_SHIFT = 8,
//bits 0-7 for flags
+ SORT_KEY_OPAQUE_PRE_PASS = 8,
SORT_KEY_CULL_DISABLED_FLAG = 4,
SORT_KEY_SKELETON_FLAG = 2,
SORT_KEY_MIRROR_FLAG = 1
@@ -805,9 +806,9 @@ public:
void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform &p_view_transform, const CameraMatrix &p_projection, GLuint p_base_env, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows);
- _FORCE_INLINE_ void _add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_shadow);
+ _FORCE_INLINE_ void _add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_depth_passs);
- _FORCE_INLINE_ void _add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_shadow);
+ _FORCE_INLINE_ void _add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_depth_pass);
void _draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_scale, float p_energy);
@@ -820,7 +821,7 @@ public:
void _copy_to_front_buffer(Environment *env);
void _copy_texture_to_front_buffer(GLuint p_texture); //used for debug
- void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_shadow);
+ void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass);
void _blur_effect_buffer();
void _render_mrts(Environment *env, const CameraMatrix &p_cam_projection);
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 91ba3aa702..a744abdfa8 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -1584,6 +1584,7 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const {
shaders.actions_canvas.usage_flag_pointers["SCREEN_UV"] = &p_shader->canvas_item.uses_screen_uv;
shaders.actions_canvas.usage_flag_pointers["SCREEN_PIXEL_SIZE"] = &p_shader->canvas_item.uses_screen_uv;
shaders.actions_canvas.usage_flag_pointers["SCREEN_TEXTURE"] = &p_shader->canvas_item.uses_screen_texture;
+ shaders.actions_canvas.usage_flag_pointers["TIME"] = &p_shader->canvas_item.uses_time;
actions = &shaders.actions_canvas;
actions->uniforms = &p_shader->uniforms;
@@ -1632,6 +1633,7 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const {
shaders.actions_scene.usage_flag_pointers["SSS_STRENGTH"] = &p_shader->spatial.uses_sss;
shaders.actions_scene.usage_flag_pointers["DISCARD"] = &p_shader->spatial.uses_discard;
shaders.actions_scene.usage_flag_pointers["SCREEN_TEXTURE"] = &p_shader->spatial.uses_screen_texture;
+ shaders.actions_scene.usage_flag_pointers["TIME"] = &p_shader->spatial.uses_time;
shaders.actions_scene.write_flag_pointers["MODELVIEW_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection;
shaders.actions_scene.write_flag_pointers["PROJECTION_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection;
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index f75b77aabe..b26032dbc4 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -410,6 +410,7 @@ public:
int light_mode;
bool uses_screen_texture;
bool uses_screen_uv;
+ bool uses_time;
} canvas_item;
@@ -449,6 +450,7 @@ public:
bool uses_discard;
bool uses_sss;
bool uses_screen_texture;
+ bool uses_time;
bool writes_modelview_or_projection;
bool uses_vertex_lighting;
diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp
index bdd54543d2..419decce29 100644
--- a/drivers/gles3/shader_compiler_gles3.cpp
+++ b/drivers/gles3/shader_compiler_gles3.cpp
@@ -438,26 +438,44 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
SL::BlockNode *bnode = (SL::BlockNode *)p_node;
//variables
- code += _mktab(p_level - 1) + "{\n";
- for (Map<StringName, SL::BlockNode::Variable>::Element *E = bnode->variables.front(); E; E = E->next()) {
-
- code += _mktab(p_level) + _prestr(E->get().precision) + _typestr(E->get().type) + " " + _mkid(E->key()) + ";\n";
+ if (!bnode->single_statement) {
+ code += _mktab(p_level - 1) + "{\n";
}
-
+
for (int i = 0; i < bnode->statements.size(); i++) {
String scode = _dump_node_code(bnode->statements[i], p_level, r_gen_code, p_actions, p_default_actions);
- if (bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW || bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW) {
- // FIXME: if (A || A) ? I am hesitant to delete one of them, could be copy-paste error.
+ if (bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW || bnode->single_statement ) {
code += scode; //use directly
} else {
code += _mktab(p_level) + scode + ";\n";
}
}
- code += _mktab(p_level - 1) + "}\n";
+ if (!bnode->single_statement) {
+ code += _mktab(p_level - 1) + "}\n";
+ }
} break;
+ case SL::Node::TYPE_VARIABLE_DECLARATION: {
+ SL::VariableDeclarationNode *vdnode = (SL::VariableDeclarationNode *)p_node;
+
+ String declaration = _prestr(vdnode->precision) + _typestr(vdnode->datatype);
+ for(int i=0;i<vdnode->declarations.size();i++) {
+ if (i>0) {
+ declaration+=",";
+ } else {
+ declaration+=" ";
+ }
+ declaration += _mkid(vdnode->declarations[i].name);
+ if (vdnode->declarations[i].initializer) {
+ declaration+="=";
+ declaration+=_dump_node_code(vdnode->declarations[i].initializer, p_level, r_gen_code, p_actions, p_default_actions);
+ }
+ }
+
+ code+=declaration;
+ } break;
case SL::Node::TYPE_VARIABLE: {
SL::VariableNode *vnode = (SL::VariableNode *)p_node;
@@ -600,6 +618,13 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
code += _mktab(p_level) + "while (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions) + ")\n";
code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions);
+ } else if (cfnode->flow_op == SL::FLOW_OP_FOR) {
+
+ String left = _dump_node_code(cfnode->blocks[0], p_level, r_gen_code, p_actions, p_default_actions);
+ String middle = _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions);
+ String right = _dump_node_code(cfnode->expressions[1], p_level, r_gen_code, p_actions, p_default_actions);
+ code += _mktab(p_level) + "for (" +left+";"+middle+";"+right+")\n";
+ code += _dump_node_code(cfnode->blocks[1], p_level + 1, r_gen_code, p_actions, p_default_actions);
} else if (cfnode->flow_op == SL::FLOW_OP_RETURN) {
@@ -611,6 +636,12 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
} else if (cfnode->flow_op == SL::FLOW_OP_DISCARD) {
code = "discard;";
+ } else if (cfnode->flow_op == SL::FLOW_OP_CONTINUE) {
+
+ code = "continue;";
+ } else if (cfnode->flow_op == SL::FLOW_OP_BREAK) {
+
+ code = "break;";
}
} break;
diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index 3bcfd24383..df75191b5f 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -116,7 +116,7 @@ void main() {
#ifdef USE_TEXTURE_RECT
- if (dst_rect.z < 0) { // Transpose is encoded as negative dst_rect.z
+ if (dst_rect.z < 0.0) { // Transpose is encoded as negative dst_rect.z
uv_interp = src_rect.xy + abs(src_rect.zw) * vertex.yx;
} else {
uv_interp = src_rect.xy + abs(src_rect.zw) * vertex;
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 7c60a8ee97..977cee5fcb 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -484,7 +484,7 @@ VERTEX_SHADER_CODE
vec3 directional_diffuse = vec3(0.0);
vec3 directional_specular = vec3(0.0);
- light_compute(normal_interp,-light_direction_attenuation.xyz,-normalize( vertex_interp ),normal_interp,roughness,directional_diffuse,directional_specular);
+ light_compute(normal_interp,-light_direction_attenuation.xyz,-normalize( vertex_interp ),light_color_energy.rgb,roughness,directional_diffuse,directional_specular);
float diff_avg = dot(diffuse_light_interp.rgb,vec3(0.33333));
float diff_dir_avg = dot(directional_diffuse,vec3(0.33333));
@@ -1590,6 +1590,12 @@ FRAGMENT_SHADER_CODE
}
#endif
+#ifdef USE_OPAQUE_PREPASS
+
+ if (alpha<0.99) {
+ discard;
+ }
+#endif
#if defined(ENABLE_NORMALMAP)
diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp
index ddc3b2ed33..a4e4c79dbf 100644
--- a/drivers/unix/dir_access_unix.cpp
+++ b/drivers/unix/dir_access_unix.cpp
@@ -211,36 +211,38 @@ Error DirAccessUnix::make_dir(String p_dir) {
Error DirAccessUnix::change_dir(String p_dir) {
GLOBAL_LOCK_FUNCTION
- p_dir = fix_path(p_dir);
- char real_current_dir_name[2048];
- getcwd(real_current_dir_name, 2048);
- String prev_dir;
- if (prev_dir.parse_utf8(real_current_dir_name))
- prev_dir = real_current_dir_name; //no utf8, maybe latin?
+ // make sure current_dir is valid absolute path
+ if (current_dir == "." || current_dir == "") {
+ char real_current_dir_name[2048];
+ getcwd(real_current_dir_name, 2048);
+ current_dir.parse_utf8(real_current_dir_name);
+ }
- chdir(current_dir.utf8().get_data()); //ascii since this may be unicode or wathever the host os wants
- bool worked = (chdir(p_dir.utf8().get_data()) == 0); // we can only give this utf8
+ if (p_dir == ".") {
+ return OK;
+ }
- String base = _get_root_path();
- if (base != "") {
+ p_dir = fix_path(p_dir);
- getcwd(real_current_dir_name, 2048);
- String new_dir;
- new_dir.parse_utf8(real_current_dir_name);
- if (!new_dir.begins_with(base))
- worked = false;
- }
+ String prev_dir = current_dir;
- if (worked) {
+ if (p_dir.is_rel_path()) {
+ String next_dir = current_dir + "/" + p_dir;
+ next_dir = next_dir.simplify_path();
+ current_dir = next_dir;
+ } else {
+ current_dir = p_dir;
+ }
- getcwd(real_current_dir_name, 2048);
- if (current_dir.parse_utf8(real_current_dir_name))
- current_dir = real_current_dir_name; //no utf8, maybe latin?
+ bool worked = (chdir(current_dir.utf8().get_data()) == 0); // we can only give this utf8
+ if (!worked) {
+ current_dir = prev_dir;
+ return ERR_INVALID_PARAMETER;
}
chdir(prev_dir.utf8().get_data());
- return worked ? OK : ERR_INVALID_PARAMETER;
+ return OK;
}
String DirAccessUnix::get_current_dir() {
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index d5a66d9a1c..db06cce644 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -36,12 +36,17 @@
#include <sys/stat.h>
#include <sys/types.h>
+#if defined(UNIX_ENABLED)
+#include <unistd.h>
+#endif
+
#ifndef ANDROID_ENABLED
#include <sys/statvfs.h>
#endif
#ifdef MSVC
#define S_ISREG(m) ((m)&_S_IFREG)
+#include <io.h>
#endif
#ifndef S_ISREG
#define S_ISREG(m) ((m)&S_IFREG)
@@ -85,13 +90,18 @@ Error FileAccessUnix::_open(const String &p_path, int p_mode_flags) {
//printf("opening %s as %s\n", p_path.utf8().get_data(), path.utf8().get_data());
struct stat st;
- if (stat(path.utf8().get_data(), &st) == 0) {
-
- if (!S_ISREG(st.st_mode))
- return ERR_FILE_CANT_OPEN;
- };
+ int err = stat(path.utf8().get_data(), &st);
+ if (!err) {
+ switch (st.st_mode & S_IFMT) {
+ case S_IFLNK:
+ case S_IFREG:
+ break;
+ default:
+ return ERR_FILE_CANT_OPEN;
+ }
+ }
- if (is_backup_save_enabled() && p_mode_flags & WRITE && !(p_mode_flags & READ)) {
+ if (is_backup_save_enabled() && (p_mode_flags & WRITE) && !(p_mode_flags & READ)) {
save_path = path;
path = path + ".tmp";
//print_line("saving instead to "+path);
@@ -108,15 +118,19 @@ Error FileAccessUnix::_open(const String &p_path, int p_mode_flags) {
return OK;
}
}
+
void FileAccessUnix::close() {
if (!f)
return;
+
fclose(f);
f = NULL;
+
if (close_notification_func) {
close_notification_func(path, flags);
}
+
if (save_path != "") {
//unlink(save_path.utf8().get_data());
@@ -131,10 +145,12 @@ void FileAccessUnix::close() {
ERR_FAIL_COND(rename_error != 0);
}
}
+
bool FileAccessUnix::is_open() const {
return (f != NULL);
}
+
void FileAccessUnix::seek(size_t p_position) {
ERR_FAIL_COND(!f);
@@ -143,29 +159,39 @@ void FileAccessUnix::seek(size_t p_position) {
if (fseek(f, p_position, SEEK_SET))
check_errors();
}
+
void FileAccessUnix::seek_end(int64_t p_position) {
ERR_FAIL_COND(!f);
+
+ last_error = OK;
if (fseek(f, p_position, SEEK_END))
check_errors();
}
+
size_t FileAccessUnix::get_pos() const {
- size_t aux_position = 0;
- if (!(aux_position = ftell(f))) {
+ ERR_FAIL_COND_V(!f, 0);
+
+ last_error = OK;
+ int pos = ftell(f);
+ if (pos < 0) {
check_errors();
- };
- return aux_position;
+ ERR_FAIL_V(0);
+ }
+ return pos;
}
+
size_t FileAccessUnix::get_len() const {
ERR_FAIL_COND_V(!f, 0);
- FileAccessUnix *fau = const_cast<FileAccessUnix *>(this);
- int pos = fau->get_pos();
- fau->seek_end();
- int size = fau->get_pos();
- fau->seek(pos);
+ int pos = ftell(f);
+ ERR_FAIL_COND_V(pos < 0, 0);
+ ERR_FAIL_COND_V(fseek(f, 0, SEEK_END), 0);
+ int size = ftell(f);
+ ERR_FAIL_COND_V(size < 0, 0);
+ ERR_FAIL_COND_V(fseek(f, pos, SEEK_SET), 0);
return size;
}
@@ -202,22 +228,36 @@ Error FileAccessUnix::get_error() const {
void FileAccessUnix::store_8(uint8_t p_dest) {
ERR_FAIL_COND(!f);
- fwrite(&p_dest, 1, 1, f);
+ ERR_FAIL_COND(fwrite(&p_dest, 1, 1, f) != 1);
}
bool FileAccessUnix::file_exists(const String &p_path) {
- FILE *g;
- //printf("opening file %s\n", p_fname.c_str());
+ int err;
+ struct stat st;
String filename = fix_path(p_path);
- g = fopen(filename.utf8().get_data(), "rb");
- if (g == NULL) {
+ // Does the name exist at all?
+ err = stat(filename.utf8().get_data(), &st);
+ if (err)
return false;
- } else {
- fclose(g);
- return true;
+#ifdef UNIX_ENABLED
+ // See if we have access to the file
+ if (access(filename.utf8().get_data(), F_OK))
+ return false;
+#else
+ if (_access(filename.utf8().get_data(), 4) == -1)
+ return false;
+#endif
+
+ // See if this is a regular file
+ switch (st.st_mode & S_IFMT) {
+ case S_IFLNK:
+ case S_IFREG:
+ return true;
+ default:
+ return false;
}
}
@@ -225,9 +265,9 @@ uint64_t FileAccessUnix::_get_modified_time(const String &p_file) {
String file = fix_path(p_file);
struct stat flags;
- bool success = (stat(file.utf8().get_data(), &flags) == 0);
+ int err = stat(file.utf8().get_data(), &flags);
- if (success) {
+ if (!err) {
return flags.st_mtime;
} else {
print_line("ERROR IN: " + p_file);
@@ -249,6 +289,7 @@ FileAccessUnix::FileAccessUnix() {
flags = 0;
last_error = OK;
}
+
FileAccessUnix::~FileAccessUnix() {
close();
diff --git a/editor/SCsub b/editor/SCsub
index 172447147c..0e690cf465 100644
--- a/editor/SCsub
+++ b/editor/SCsub
@@ -155,31 +155,71 @@ def make_authors_header(target, source, env):
g.write("#define _EDITOR_AUTHORS_H\n")
current_section = ""
- name_count = -1
+ reading = False
def close_section():
g.write("\t0\n")
g.write("};\n")
- g.write("#define " + current_section.upper() + "_COUNT " + str(name_count) + "\n")
for line in f:
- if name_count >= 0:
+ if reading:
if line.startswith(" "):
g.write("\t\"" + line.strip() + "\",\n")
- name_count += 1
continue
if line.startswith("## "):
- if name_count >= 0:
+ if reading:
close_section()
- name_count = -1
+ reading = False
for i in range(len(sections)):
if line.strip().endswith(sections[i]):
current_section = sections_id[i]
- name_count = 0
+ reading = True
g.write("static const char *" + current_section + "[] = {\n")
break
- if name_count >= 0:
+ if reading:
+ close_section()
+
+ g.write("#endif\n")
+
+def make_donors_header(target, source, env):
+
+ sections = ["Platinum sponsors", "Gold sponsors", "Mini sponsors", "Gold donors", "Silver donors", "Bronze donors"]
+ sections_id = ["donor_s_plat", "donor_s_gold", "donor_s_mini", "donor_gold", "donor_silver", "donor_bronze"]
+
+ src = source[0].srcnode().abspath
+ dst = target[0].srcnode().abspath
+ f = open_utf8(src, "r")
+ g = open_utf8(dst, "w")
+
+ g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
+ g.write("#ifndef _EDITOR_DONORS_H\n")
+ g.write("#define _EDITOR_DONORS_H\n")
+
+ current_section = ""
+ reading = False
+
+ def close_section():
+ g.write("\t0\n")
+ g.write("};\n")
+
+ for line in f:
+ if reading >= 0:
+ if line.startswith(" "):
+ g.write("\t\"" + line.strip() + "\",\n")
+ continue
+ if line.startswith("## "):
+ if reading:
+ close_section()
+ reading = False
+ for i in range(len(sections)):
+ if line.strip().endswith(sections[i]):
+ current_section = sections_id[i]
+ reading = True
+ g.write("static const char *" + current_section + "[] = {\n")
+ break
+
+ if reading:
close_section()
g.write("#endif\n")
@@ -393,6 +433,10 @@ if (env["tools"] == "yes"):
env.Depends('#editor/authors.gen.h', "../AUTHORS.md")
env.Command('#editor/authors.gen.h', "../AUTHORS.md", make_authors_header)
+ # Donors
+ env.Depends('#editor/donors.gen.h', "../DONORS.md")
+ env.Command('#editor/donors.gen.h', "../DONORS.md", make_donors_header)
+
# License
env.Depends('#editor/license.gen.h', ["../COPYRIGHT.txt", "../LICENSE.txt"])
env.Command('#editor/license.gen.h', ["../COPYRIGHT.txt", "../LICENSE.txt"], make_license_header)
diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp
index 8bd7bfb4bd..a48e6c9057 100644
--- a/editor/editor_about.cpp
+++ b/editor/editor_about.cpp
@@ -30,6 +30,7 @@
#include "editor_about.h"
#include "authors.gen.h"
+#include "donors.gen.h"
#include "license.gen.h"
#include "version.h"
#include "version_hash.gen.h"
@@ -51,6 +52,47 @@ TextureRect *EditorAbout::get_logo() const {
return _logo;
}
+ScrollContainer *EditorAbout::_populate_list(const String &p_name, const List<String> &p_sections, const char **p_src[]) {
+
+ ScrollContainer *sc = memnew(ScrollContainer);
+ sc->set_name(p_name);
+ sc->set_v_size_flags(Control::SIZE_EXPAND);
+
+ VBoxContainer *vbc = memnew(VBoxContainer);
+ vbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ sc->add_child(vbc);
+
+ for (int i = 0; i < p_sections.size(); i++) {
+
+ const char **names_ptr = p_src[i];
+ if (*names_ptr) {
+
+ Label *lbl = memnew(Label);
+ lbl->set_text(p_sections[i]);
+ vbc->add_child(lbl);
+
+ ItemList *il = memnew(ItemList);
+ il->set_max_columns(16);
+ il->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ il->set_same_column_width(true);
+ il->set_auto_height(true);
+ while (*names_ptr) {
+ il->add_item(String::utf8(*names_ptr++), NULL, false);
+ }
+ vbc->add_child(il);
+ if (il->get_item_count() == 2) {
+ il->set_fixed_column_width(200 * EDSCALE);
+ }
+
+ HSeparator *hs = memnew(HSeparator);
+ hs->set_modulate(Color(0, 0, 0, 0));
+ vbc->add_child(hs);
+ }
+ }
+
+ return sc;
+}
+
EditorAbout::EditorAbout() {
set_title(TTR("Thanks from the Godot community!"));
@@ -84,43 +126,29 @@ EditorAbout::EditorAbout() {
tc->set_v_size_flags(Control::SIZE_EXPAND_FILL);
vbc->add_child(tc);
- ScrollContainer *dev_base = memnew(ScrollContainer);
- dev_base->set_name(TTR("Authors"));
- dev_base->set_v_size_flags(Control::SIZE_EXPAND);
- tc->add_child(dev_base);
-
- VBoxContainer *dev_vbc = memnew(VBoxContainer);
- dev_vbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- dev_base->add_child(dev_vbc);
+ // Authors
List<String> dev_sections;
dev_sections.push_back(TTR("Project Founders"));
dev_sections.push_back(TTR("Lead Developer"));
dev_sections.push_back(TTR("Project Manager"));
dev_sections.push_back(TTR("Developers"));
-
const char **dev_src[] = { dev_founders, dev_lead, dev_manager, dev_names };
+ tc->add_child(_populate_list(TTR("Authors"), dev_sections, dev_src));
- for (int i = 0; i < dev_sections.size(); i++) {
-
- Label *lbl = memnew(Label);
- lbl->set_text(dev_sections[i]);
- dev_vbc->add_child(lbl);
-
- ItemList *il = memnew(ItemList);
- il->set_max_columns(16);
- il->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- il->set_fixed_column_width(230 * EDSCALE);
- il->set_auto_height(true);
- const char **dev_names_ptr = dev_src[i];
- while (*dev_names_ptr)
- il->add_item(String::utf8(*dev_names_ptr++), NULL, false);
- dev_vbc->add_child(il);
-
- HSeparator *hs = memnew(HSeparator);
- hs->set_modulate(Color(0, 0, 0, 0));
- dev_vbc->add_child(hs);
- }
+ // Donors
+
+ List<String> donor_sections;
+ donor_sections.push_back(TTR("Platinum Sponsors"));
+ donor_sections.push_back(TTR("Gold Sponsors"));
+ donor_sections.push_back(TTR("Mini Sponsors"));
+ donor_sections.push_back(TTR("Gold Donors"));
+ donor_sections.push_back(TTR("Silver Donors"));
+ donor_sections.push_back(TTR("Bronze Donors"));
+ const char **donor_src[] = { donor_s_plat, donor_s_gold, donor_s_mini, donor_gold, donor_silver, donor_bronze };
+ tc->add_child(_populate_list(TTR("Donors"), donor_sections, donor_src));
+
+ // License
TextEdit *license = memnew(TextEdit);
license->set_name(TTR("License"));
@@ -131,6 +159,8 @@ EditorAbout::EditorAbout() {
license->set_text(String::utf8(about_license));
tc->add_child(license);
+ // Thirdparty License
+
VBoxContainer *license_thirdparty = memnew(VBoxContainer);
license_thirdparty->set_name(TTR("Thirdparty License"));
license_thirdparty->set_h_size_flags(Control::SIZE_EXPAND_FILL);
diff --git a/editor/editor_about.h b/editor/editor_about.h
index d7047c03a3..d455b1f074 100644
--- a/editor/editor_about.h
+++ b/editor/editor_about.h
@@ -52,6 +52,7 @@ class EditorAbout : public AcceptDialog {
private:
void _license_tree_selected();
+ ScrollContainer *_populate_list(const String &p_name, const List<String> &p_sections, const char **p_src[]);
Tree *_tpl_tree;
TextEdit *_tpl_text;
diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp
index 22a9c84d21..3ab3f05906 100644
--- a/editor/editor_fonts.cpp
+++ b/editor/editor_fonts.cpp
@@ -72,11 +72,14 @@ static Ref<BitmapFont> make_font(int p_height, int p_ascent, int p_valign, int p
m_name->add_fallback(FontJapanese); \
m_name->add_fallback(FontFallback);
-#define MAKE_DEFAULT_FONT(m_name, m_size) \
- Ref<DynamicFont> m_name; \
- m_name.instance(); \
- m_name->set_size(m_size); \
- m_name->set_font_data(DefaultFont); \
+// the custom spacings might only work with Noto Sans
+#define MAKE_DEFAULT_FONT(m_name, m_size) \
+ Ref<DynamicFont> m_name; \
+ m_name.instance(); \
+ m_name->set_size(m_size); \
+ m_name->set_font_data(DefaultFont); \
+ m_name->set_spacing(DynamicFont::SPACING_TOP, -1); \
+ m_name->set_spacing(DynamicFont::SPACING_BOTTOM, -1); \
MAKE_FALLBACKS(m_name);
void editor_register_fonts(Ref<Theme> p_theme) {
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index 0e22f0d386..7fa2c53275 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -1712,9 +1712,8 @@ void EditorHelp::_notification(int p_what) {
} break;
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
- Ref<StyleBoxFlat> style(memnew(StyleBoxFlat));
- style->set_bg_color(EditorSettings::get_singleton()->get("text_editor/highlighting/background_color"));
- background_panel->add_style_override("panel", style);
+
+ class_desc->add_color_override("selection_color", EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1)));
} break;
default: break;
@@ -1786,14 +1785,12 @@ EditorHelp::EditorHelp() {
{
background_panel = memnew(Panel);
- Ref<StyleBoxFlat> style(memnew(StyleBoxFlat));
- style->set_bg_color(EditorSettings::get_singleton()->get("text_editor/highlighting/background_color"));
background_panel->set_v_size_flags(SIZE_EXPAND_FILL);
- background_panel->add_style_override("panel", style); //get_stylebox("normal","TextEdit"));
vbc->add_child(background_panel);
class_desc = memnew(RichTextLabel);
background_panel->add_child(class_desc);
- class_desc->set_area_as_parent_rect(8);
+ class_desc->set_area_as_parent_rect();
+ class_desc->add_color_override("selection_color", EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1)));
class_desc->connect("meta_clicked", this, "_class_desc_select");
class_desc->connect("gui_input", this, "_class_desc_input");
}
@@ -1882,8 +1879,13 @@ void EditorHelpBit::_bind_methods() {
void EditorHelpBit::_notification(int p_what) {
- if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
- add_style_override("panel", get_stylebox("ScriptPanel", "EditorStyles"));
+ switch (p_what) {
+ case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
+
+ rich_text->add_color_override("selection_color", EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1)));
+ } break;
+
+ default: break;
}
}
@@ -1897,8 +1899,8 @@ EditorHelpBit::EditorHelpBit() {
rich_text = memnew(RichTextLabel);
add_child(rich_text);
- rich_text->set_area_as_parent_rect(8 * EDSCALE);
+ rich_text->set_area_as_parent_rect();
rich_text->connect("meta_clicked", this, "_meta_clicked");
+ rich_text->add_color_override("selection_color", EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1)));
set_custom_minimum_size(Size2(0, 70 * EDSCALE));
- add_style_override("panel", EditorNode::get_singleton()->get_gui_base()->get_stylebox("ScriptPanel", "EditorStyles"));
}
diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp
index a1f416a17c..35291f8f9e 100644
--- a/editor/editor_log.cpp
+++ b/editor/editor_log.cpp
@@ -59,7 +59,6 @@ void EditorLog::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
- log->add_color_override("default_color", get_color("font_color", "Tree"));
//button->set_icon(get_icon("Console","EditorIcons"));
}
if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
@@ -91,7 +90,7 @@ void EditorLog::add_message(const String &p_msg, bool p_error) {
log->add_newline();
if (p_error) {
- log->push_color(get_color("fg_error", "Editor"));
+ log->push_color(get_color("error_color", "Editor"));
Ref<Texture> icon = get_icon("Error", "EditorIcons");
log->add_image(icon);
//button->set_icon(icon);
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 6b5db7572a..91d2ddcd19 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -283,13 +283,22 @@ void EditorNode::_notification(int p_what) {
scene_tabs->set_tab_close_display_policy((bool(EDITOR_DEF("interface/always_show_close_button_in_scene_tabs", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY));
property_editor->set_enable_capitalize_paths(bool(EDITOR_DEF("interface/capitalize_properties", true)));
Ref<Theme> theme = create_editor_theme(theme_base->get_theme());
+
theme_base->set_theme(theme);
+
gui_base->add_style_override("panel", gui_base->get_stylebox("Background", "EditorStyles"));
play_button_panel->add_style_override("panel", gui_base->get_stylebox("PlayButtonPanel", "EditorStyles"));
scene_root_parent->add_style_override("panel", gui_base->get_stylebox("Content", "EditorStyles"));
bottom_panel->add_style_override("panel", gui_base->get_stylebox("panel", "TabContainer"));
scene_tabs->add_style_override("tab_fg", gui_base->get_stylebox("SceneTabFG", "EditorStyles"));
scene_tabs->add_style_override("tab_bg", gui_base->get_stylebox("SceneTabBG", "EditorStyles"));
+
+ file_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
+ project_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
+ debug_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
+ settings_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
+ help_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
+
if (bool(EDITOR_DEF("interface/scene_tabs/resize_if_many_tabs", true))) {
scene_tabs->set_min_width(int(EDITOR_DEF("interface/scene_tabs/minimum_width", 50)) * EDSCALE);
} else {
@@ -1368,6 +1377,16 @@ void EditorNode::_set_editing_top_editors(Object *p_current_object) {
editor_plugins_over->edit(p_current_object);
}
+static bool overrides_external_editor(Object *p_object) {
+
+ Script *script = Object::cast_to<Script>(p_object);
+
+ if (!script)
+ return false;
+
+ return script->get_language()->overrides_external_editor();
+}
+
void EditorNode::_edit_current() {
uint32_t current = editor_history.get_current();
@@ -1434,7 +1453,7 @@ void EditorNode::_edit_current() {
if (main_plugin) {
// special case if use of external editor is true
- if (main_plugin->get_name() == "Script" && bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor"))) {
+ if (main_plugin->get_name() == "Script" && (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor")) || overrides_external_editor(current_obj))) {
main_plugin->edit(current_obj);
}
@@ -1442,6 +1461,7 @@ void EditorNode::_edit_current() {
// update screen main_plugin
if (!changing_scene) {
+
if (editor_plugin_screen)
editor_plugin_screen->make_visible(false);
editor_plugin_screen = main_plugin;
@@ -2721,6 +2741,14 @@ Dictionary EditorNode::_get_main_scene_state() {
state["property_edit_offset"] = get_property_editor()->get_scene_tree()->get_vscroll_bar()->get_value();
state["saved_version"] = saved_version;
state["node_filter"] = scene_tree_dock->get_filter();
+ int current = -1;
+ for (int i = 0; i < editor_table.size(); i++) {
+ if (editor_plugin_screen == editor_table[i]) {
+ current = i;
+ break;
+ }
+ }
+ state["editor_index"] = current;
return state;
}
@@ -2731,8 +2759,9 @@ void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) {
changing_scene = false;
- if (get_edited_scene()) {
+ if (p_state.has("editor_index")) {
+ int index = p_state["editor_index"];
int current = -1;
for (int i = 0; i < editor_table.size(); i++) {
if (editor_plugin_screen == editor_table[i]) {
@@ -2741,15 +2770,18 @@ void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) {
}
}
- if (current < 2) {
- //use heuristic instead
-
- int n2d = 0, n3d = 0;
- _find_node_types(get_edited_scene(), n2d, n3d);
- if (n2d > n3d) {
- _editor_select(EDITOR_2D);
- } else if (n3d > n2d) {
- _editor_select(EDITOR_3D);
+ if (current < 2) { //if currently in spatial/2d, only switch to spatial/2d. if curently in script, stay there
+ if (index < 2 || !get_edited_scene()) {
+ _editor_select(index);
+ } else {
+ //use heuristic instead
+ int n2d = 0, n3d = 0;
+ _find_node_types(get_edited_scene(), n2d, n3d);
+ if (n2d > n3d) {
+ _editor_select(EDITOR_2D);
+ } else if (n3d > n2d) {
+ _editor_select(EDITOR_3D);
+ }
}
}
}
@@ -4818,9 +4850,10 @@ EditorNode::EditorNode() {
}
file_menu = memnew(MenuButton);
+ file_menu->set_flat(false);
file_menu->set_text(TTR("Scene"));
- left_menu_hb->add_child(file_menu);
file_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
+ left_menu_hb->add_child(file_menu);
prev_scene = memnew(ToolButton);
prev_scene->set_icon(gui_base->get_icon("PrevScene", "EditorIcons"));
@@ -4908,6 +4941,7 @@ EditorNode::EditorNode() {
p->add_item(TTR("Quit"), FILE_QUIT, KEY_MASK_CMD + KEY_Q);
project_menu = memnew(MenuButton);
+ project_menu->set_flat(false);
project_menu->set_tooltip(TTR("Miscellaneous project or scene-wide tools."));
project_menu->set_text(TTR("Project"));
project_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
@@ -4941,9 +4975,11 @@ EditorNode::EditorNode() {
menu_hb->add_child(editor_region);
debug_menu = memnew(MenuButton);
+ debug_menu->set_flat(false);
debug_menu->set_text(TTR("Debug"));
debug_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
left_menu_hb->add_child(debug_menu);
+
p = debug_menu->get_popup();
p->set_hide_on_item_selection(false);
p->add_check_item(TTR("Deploy with Remote Debug"), RUN_DEPLOY_REMOTE_DEBUG);
@@ -4965,9 +5001,10 @@ EditorNode::EditorNode() {
menu_hb->add_spacer();
settings_menu = memnew(MenuButton);
- left_menu_hb->add_child(settings_menu);
+ settings_menu->set_flat(false);
settings_menu->set_text(TTR("Editor"));
settings_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
+ left_menu_hb->add_child(settings_menu);
p = settings_menu->get_popup();
p->add_item(TTR("Editor Settings"), SETTINGS_PREFERENCES);
@@ -4982,10 +5019,12 @@ EditorNode::EditorNode() {
p->add_item(TTR("Manage Export Templates"), SETTINGS_MANAGE_EXPORT_TEMPLATES);
// Help Menu
- MenuButton *help_menu = memnew(MenuButton);
- left_menu_hb->add_child(help_menu);
+ help_menu = memnew(MenuButton);
+ help_menu->set_flat(false);
help_menu->set_text(TTR("Help"));
help_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
+ left_menu_hb->add_child(help_menu);
+
p = help_menu->get_popup();
p->connect("id_pressed", this, "_menu_option");
p->add_icon_item(gui_base->get_icon("ClassList", "EditorIcons"), TTR("Classes"), HELP_CLASSES);
diff --git a/editor/editor_node.h b/editor/editor_node.h
index c3ceee350a..ea74bcbd9d 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -236,11 +236,12 @@ private:
MenuButton *file_menu;
MenuButton *project_menu;
MenuButton *debug_menu;
+ MenuButton *settings_menu;
+ MenuButton *help_menu;
PopupMenu *tool_menu;
ToolButton *export_button;
ToolButton *prev_scene;
MenuButton *object_menu;
- MenuButton *settings_menu;
ToolButton *play_button;
MenuButton *native_play_button;
ToolButton *pause_button;
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 9c9eef848a..db76a27f5f 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -603,7 +603,6 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
hints["text_editor/theme/color_theme"] = PropertyInfo(Variant::STRING, "text_editor/theme/color_theme", PROPERTY_HINT_ENUM, "Default");
set("text_editor/theme/line_spacing", 4);
- set("text_editor/theme/adapted_code_editor_background_color", true);
_load_default_text_editor_theme();
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 8943d5f0dc..19356aad3a 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -198,6 +198,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
bool highlight_tabs = EDITOR_DEF("interface/theme/highlight_tabs", false);
int border_size = EDITOR_DEF("interface/theme/border_size", 1);
+ Color script_bg_color = EDITOR_DEF("text_editor/highlighting/background_color", Color(0, 0, 0, 0));
+
switch (preset) {
case 0: { // Default
highlight_color = Color::html("#699ce8");
@@ -235,8 +237,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
Color dark_color_2 = base_color.linear_interpolate(Color(0, 0, 0, 1), contrast * 1.5);
Color dark_color_3 = base_color.linear_interpolate(Color(0, 0, 0, 1), contrast * 2);
- Color contrast_color_1 = base_color.linear_interpolate((dark_theme ? Color(1, 1, 1, 1) : Color(0, 0, 0, 1)), 0.3);
- Color contrast_color_2 = base_color.linear_interpolate((dark_theme ? Color(1, 1, 1, 1) : Color(0, 0, 0, 1)), 0.5);
+ Color contrast_color_1 = base_color.linear_interpolate((dark_theme ? Color(1, 1, 1, 1) : Color(0, 0, 0, 1)), MAX(contrast, default_contrast));
+ Color contrast_color_2 = base_color.linear_interpolate((dark_theme ? Color(1, 1, 1, 1) : Color(0, 0, 0, 1)), MAX(contrast * 1.5, default_contrast * 1.5));
Color font_color = dark_theme ? Color(1, 1, 1) : Color(0, 0, 0);
Color font_color_disabled = dark_theme ? Color(0.6, 0.6, 0.6) : Color(0.45, 0.45, 0.45);
@@ -279,8 +281,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
editor_register_fonts(theme);
// Editor background
- Ref<StyleBoxFlat> style_panel = make_flat_stylebox(dark_color_2, 4, 4, 4, 4);
- theme->set_stylebox("Background", "EditorStyles", style_panel);
+ theme->set_stylebox("Background", "EditorStyles", make_flat_stylebox(dark_color_2, 4, 4, 4, 4));
// Focus
Ref<StyleBoxFlat> focus_sbt = make_flat_stylebox(contrast_color_1, 4, 4, 4, 4);
@@ -302,12 +303,11 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
Ref<StyleBoxFlat> style_menu_hover_bg = make_flat_stylebox(dark_color_2, 4, 4, 4, 4);
style_menu_hover_border->set_draw_center(false);
- style_menu_hover_border->set_border_width(MARGIN_BOTTOM, border_width);
+ style_menu_hover_border->set_border_width(MARGIN_BOTTOM, 2 * EDSCALE);
style_menu_hover_border->set_border_color_all(highlight_color);
- style_menu_hover_border->set_expand_margin_size(MARGIN_BOTTOM, border_width);
theme->set_stylebox("normal", "MenuButton", style_menu);
- theme->set_stylebox("hover", "MenuButton", style_menu_hover_border);
+ theme->set_stylebox("hover", "MenuButton", style_menu);
theme->set_stylebox("pressed", "MenuButton", style_menu);
theme->set_stylebox("focus", "MenuButton", style_menu);
theme->set_stylebox("disabled", "MenuButton", style_menu);
@@ -333,10 +333,10 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("MenuHover", "EditorStyles", style_menu_hover_border);
// Content of each tab
- Ref<StyleBoxFlat> style_content_panel = make_flat_stylebox(base_color, 4, 5, 4, 4);
+ Ref<StyleBoxFlat> style_content_panel = make_flat_stylebox(base_color, 4, 4, 4, 4);
style_content_panel->set_border_color_all(base_color);
style_content_panel->set_border_width_all(border_width);
- Ref<StyleBoxFlat> style_content_panel_vp = make_flat_stylebox(base_color, border_width, 5, border_width, border_width);
+ Ref<StyleBoxFlat> style_content_panel_vp = make_flat_stylebox(base_color, border_width, 4, border_width, border_width);
style_content_panel_vp->set_border_color_all(base_color);
style_content_panel_vp->set_border_width_all(border_width);
theme->set_stylebox("panel", "TabContainer", style_content_panel);
@@ -357,6 +357,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("pressed", "Button", change_border_color(style_button_type, highlight_color));
theme->set_stylebox("focus", "Button", change_border_color(style_button_type, highlight_color));
theme->set_stylebox("disabled", "Button", style_button_type_disabled);
+
theme->set_color("font_color", "Button", button_font_color);
theme->set_color("font_color_hover", "Button", HIGHLIGHT_COLOR_FONT);
theme->set_color("font_color_pressed", "Button", highlight_color);
@@ -366,13 +367,12 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("icon_color_pressed", "Button", Color(highlight_color.r * 1.15, highlight_color.g * 1.15, highlight_color.b * 1.15, highlight_color.a));
// OptionButton
- Ref<StyleBoxFlat> style_option_button = make_flat_stylebox(dark_color_1, 4, 4, 4, 4);
- style_option_button->set_border_width_all(border_width);
+ theme->set_stylebox("normal", "OptionButton", style_button_type);
theme->set_stylebox("hover", "OptionButton", change_border_color(style_button_type, contrast_color_1));
theme->set_stylebox("pressed", "OptionButton", change_border_color(style_button_type, HIGHLIGHT_COLOR_FONT));
theme->set_stylebox("focus", "OptionButton", change_border_color(style_button_type, highlight_color));
theme->set_stylebox("disabled", "OptionButton", style_button_type_disabled);
- theme->set_stylebox("normal", "OptionButton", style_button_type);
+
theme->set_color("font_color", "OptionButton", button_font_color);
theme->set_color("font_color_hover", "OptionButton", HIGHLIGHT_COLOR_FONT);
theme->set_color("font_color_pressed", "OptionButton", highlight_color);
@@ -385,6 +385,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// CheckButton
theme->set_icon("on", "CheckButton", theme->get_icon("GuiToggleOn", "EditorIcons"));
theme->set_icon("off", "CheckButton", theme->get_icon("GuiToggleOff", "EditorIcons"));
+
theme->set_color("font_color", "CheckButton", button_font_color);
theme->set_color("font_color_hover", "CheckButton", HIGHLIGHT_COLOR_FONT);
theme->set_color("font_color_pressed", "CheckButton", highlight_color);
@@ -424,12 +425,6 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
style_tree_bg->set_border_color_all(dark_color_3);
theme->set_stylebox("bg", "Tree", style_tree_bg);
- // Script background
- Ref<StyleBoxFlat> style_script_bg = make_flat_stylebox(dark_color_1, 0, 0, 0, 0);
- style_script_bg->set_border_width_all(border_width);
- style_script_bg->set_border_color_all(dark_color_3);
- theme->set_stylebox("ScriptPanel", "EditorStyles", style_script_bg);
-
// Tree
theme->set_icon("checked", "Tree", theme->get_icon("GuiChecked", "EditorIcons"));
theme->set_icon("unchecked", "Tree", theme->get_icon("GuiUnchecked", "EditorIcons"));
@@ -441,7 +436,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("custom_button_pressed", "Tree", make_empty_stylebox());
theme->set_stylebox("custom_button_hover", "Tree", style_button_type);
theme->set_color("custom_button_font_highlight", "Tree", HIGHLIGHT_COLOR_FONT);
- theme->set_color("font_color", "Tree", font_color_disabled);
+ theme->set_color("font_color", "Tree", font_color);
theme->set_color("font_color_selected", "Tree", font_color);
Ref<StyleBox> style_tree_btn = make_flat_stylebox(contrast_color_1, 2, 4, 2, 4);
@@ -471,8 +466,6 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("prop_category", "Editor", prop_category_color);
theme->set_color("prop_section", "Editor", prop_section_color);
theme->set_color("prop_subsection", "Editor", prop_subsection_color);
- theme->set_color("fg_selected", "Editor", HIGHLIGHT_COLOR_BG);
- theme->set_color("fg_error", "Editor", error_color);
theme->set_color("drop_position_color", "Tree", highlight_color);
// ItemList
@@ -531,6 +524,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// LineEdit
Ref<StyleBoxFlat> style_line_edit = make_flat_stylebox(dark_color_1, 6, 4, 6, 4);
+ style_line_edit->set_border_width_all(border_width);
style_line_edit = change_border_color(style_line_edit, contrast_color_1);
Ref<StyleBoxFlat> style_line_edit_disabled = change_border_color(style_line_edit, dark_color_1);
style_line_edit_disabled->set_bg_color(Color(0, 0, 0, .1));
@@ -614,11 +608,14 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_icon("grabber_highlight", "VSlider", theme->get_icon("GuiSliderGrabberHl", "EditorIcons"));
//RichTextLabel
- theme->set_color("font_color", "RichTextLabel", font_color);
+ Color rtl_combined_bg_color = dark_color_1.linear_interpolate(script_bg_color, script_bg_color.a);
+ Color rtl_font_color = (rtl_combined_bg_color.r + rtl_combined_bg_color.g + rtl_combined_bg_color.b > 0.5 * 3) ? Color(0, 0, 0) : Color(1, 1, 1);
+ theme->set_color("default_color", "RichTextLabel", rtl_font_color);
theme->set_stylebox("focus", "RichTextLabel", make_empty_stylebox());
+ theme->set_stylebox("normal", "RichTextLabel", make_flat_stylebox(script_bg_color, 6, 6, 6, 6));
// Panel
- theme->set_stylebox("panel", "Panel", style_panel);
+ theme->set_stylebox("panel", "Panel", make_flat_stylebox(dark_color_1, 6, 4, 6, 4));
// Label
theme->set_color("font_color", "Label", font_color);
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index 04036f410a..a66d1724a1 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -1839,7 +1839,7 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
path = "res://";
- add_constant_override("separation", 3);
+ add_constant_override("separation", 4);
}
FileSystemDock::~FileSystemDock() {
diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp
index ade3550daa..f29bdde634 100644
--- a/editor/import/resource_importer_texture.cpp
+++ b/editor/import/resource_importer_texture.cpp
@@ -33,7 +33,7 @@
#include "io/config_file.h"
#include "io/image_loader.h"
#include "scene/resources/texture.h"
-
+#include "editor/editor_node.h"
void ResourceImporterTexture::_texture_reimport_srgb(const Ref<StreamTexture> &p_tex) {
singleton->mutex->lock();
@@ -411,10 +411,14 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String
if (compress_mode == COMPRESS_VIDEO_RAM) {
//must import in all formats, in order of priority (so platform choses the best supported one. IE, etc2 over etc).
//Android, GLES 2.x
+
+ bool ok_on_pc=false;
+
if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_s3tc")) {
_save_stex(image, p_save_path + ".s3tc.stex", compress_mode, lossy, Image::COMPRESS_S3TC, mipmaps, tex_flags, stream, detect_3d, detect_srgb, force_rgbe, detect_normal, force_normal);
r_platform_variants->push_back("s3tc");
+ ok_on_pc=true;
}
if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_etc2")) {
@@ -434,6 +438,9 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String
r_platform_variants->push_back("pvrtc");
}
+ if (!ok_on_pc) {
+ EditorNode::add_io_error("Warning, no suitable PC VRAM compression enabled in Project Settings. This texture will not display correcly on PC.");
+ }
} else {
//import normally
_save_stex(image, p_save_path + ".stex", compress_mode, lossy, Image::COMPRESS_S3TC /*this is ignored */, mipmaps, tex_flags, stream, detect_3d, detect_srgb, force_rgbe, detect_normal, force_normal);
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 3b74601e78..df4598793c 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -1019,6 +1019,51 @@ void CanvasItemEditor::_list_select(const Ref<InputEventMouseButton> &b) {
}
}
+void CanvasItemEditor::_update_cursor() {
+
+ CursorShape c = CURSOR_ARROW;
+ switch (drag) {
+ case DRAG_NONE:
+ if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_MIDDLE) || Input::get_singleton()->is_key_pressed(KEY_SPACE)) {
+ c = CURSOR_DRAG;
+ } else {
+ switch (tool) {
+ case TOOL_MOVE:
+ c = CURSOR_MOVE;
+ break;
+ case TOOL_EDIT_PIVOT:
+ c = CURSOR_CROSS;
+ break;
+ case TOOL_PAN:
+ c = CURSOR_DRAG;
+ break;
+ }
+ }
+ break;
+ case DRAG_LEFT:
+ case DRAG_RIGHT:
+ c = CURSOR_HSIZE;
+ break;
+ case DRAG_TOP:
+ case DRAG_BOTTOM:
+ c = CURSOR_VSIZE;
+ break;
+ case DRAG_TOP_LEFT:
+ case DRAG_BOTTOM_RIGHT:
+ c = CURSOR_FDIAGSIZE;
+ break;
+ case DRAG_TOP_RIGHT:
+ case DRAG_BOTTOM_LEFT:
+ c = CURSOR_BDIAGSIZE;
+ break;
+ case DRAG_ALL:
+ case DRAG_NODE_2D:
+ c = CURSOR_MOVE;
+ break;
+ }
+ viewport->set_default_cursor_shape(c);
+}
+
void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
{
@@ -1457,6 +1502,7 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseMotion> m = p_event;
if (m.is_valid()) {
// Mouse motion event
+ _update_cursor();
if (!viewport->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field()))
viewport->call_deferred("grab_focus");
@@ -3562,29 +3608,31 @@ void CanvasItemEditorViewport::_create_preview(const Vector<String> &files) cons
Sprite *sprite = memnew(Sprite);
sprite->set_texture(texture);
sprite->set_modulate(Color(1, 1, 1, 0.7f));
- preview->add_child(sprite);
+ preview_node->add_child(sprite);
label->show();
label_desc->show();
} else {
if (scene.is_valid()) {
Node *instance = scene->instance();
if (instance) {
- preview->add_child(instance);
+ preview_node->add_child(instance);
}
}
}
- editor->get_scene_root()->add_child(preview);
+ editor->get_scene_root()->add_child(preview_node);
}
}
}
void CanvasItemEditorViewport::_remove_preview() {
- if (preview->get_parent()) {
- editor->get_scene_root()->remove_child(preview);
- for (int i = preview->get_child_count() - 1; i >= 0; i--) {
- Node *node = preview->get_child(i);
- memdelete(node);
+ if (preview_node->get_parent()) {
+ for (int i = preview_node->get_child_count() - 1; i >= 0; i--) {
+ Node *node = preview_node->get_child(i);
+ node->queue_delete();
+ preview_node->remove_child(node);
}
+ editor->get_scene_root()->remove_child(preview_node);
+
label->hide();
label_desc->hide();
}
@@ -3794,11 +3842,11 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian
break;
}
if (can_instance) {
- if (!preview->get_parent()) { // create preview only once
+ if (!preview_node->get_parent()) { // create preview only once
_create_preview(files);
}
Transform2D trans = canvas->get_canvas_transform();
- preview->set_position((p_point - trans.get_origin()) / trans.get_scale().x);
+ preview_node->set_position((p_point - trans.get_origin()) / trans.get_scale().x);
label->set_text(vformat(TTR("Adding %s..."), default_type));
}
return can_instance;
@@ -3820,11 +3868,16 @@ void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p
List<Node *> list = editor->get_editor_selection()->get_selected_node_list();
if (list.size() == 0) {
- accept->get_ok()->set_text(TTR("OK :("));
- accept->set_text(TTR("No parent to instance a child at."));
- accept->popup_centered_minsize();
- _remove_preview();
- return;
+ Node *root_node = editor->get_edited_scene();
+ if (root_node) {
+ list.push_back(root_node);
+ } else {
+ accept->get_ok()->set_text(TTR("OK :("));
+ accept->set_text(TTR("No parent to instance a child at."));
+ accept->popup_centered_minsize();
+ _remove_preview();
+ return;
+ }
}
if (list.size() != 1) {
accept->get_ok()->set_text(TTR("I see.."));
@@ -3891,7 +3944,7 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte
editor = p_node;
editor_data = editor->get_scene_tree_dock()->get_editor_data();
canvas = p_canvas;
- preview = memnew(Node2D);
+ preview_node = memnew(Node2D);
accept = memnew(AcceptDialog);
editor->get_gui_base()->add_child(accept);
@@ -3945,5 +3998,5 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte
}
CanvasItemEditorViewport::~CanvasItemEditorViewport() {
- memdelete(preview);
+ memdelete(preview_node);
}
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index da217007ea..52b4a37a88 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -324,6 +324,7 @@ class CanvasItemEditor : public VBoxContainer {
bool updating_scroll;
void _update_scroll(float);
void _update_scrollbars();
+ void _update_cursor();
void incbeg(float &beg, float &end, float inc, float minsize, bool p_symmetric);
void incend(float &beg, float &end, float inc, float minsize, bool p_symmetric);
@@ -459,7 +460,7 @@ class CanvasItemEditorViewport : public Control {
EditorNode *editor;
EditorData *editor_data;
CanvasItemEditor *canvas;
- Node2D *preview;
+ Node2D *preview_node;
AcceptDialog *accept;
WindowDialog *selector;
Label *selector_label;
diff --git a/editor/plugins/cube_grid_theme_editor_plugin.cpp b/editor/plugins/cube_grid_theme_editor_plugin.cpp
index 08b38c2ca2..1c17daf425 100644
--- a/editor/plugins/cube_grid_theme_editor_plugin.cpp
+++ b/editor/plugins/cube_grid_theme_editor_plugin.cpp
@@ -88,7 +88,7 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library,
if (mesh.is_null())
continue;
- int id = p_library->find_item_name(mi->get_name());
+ int id = p_library->find_item_by_name(mi->get_name());
if (id < 0) {
id = p_library->get_last_unused_item_id();
@@ -111,7 +111,8 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library,
sb->get_shape_owners(&shapes);
for (List<uint32_t>::Element *E = shapes.front(); E; E = E->next()) {
- if (sb->is_shape_owner_disabled(E->get())) continue;
+ if (sb->is_shape_owner_disabled(E->get()))
+ continue;
//Transform shape_transform = sb->shape_owner_get_transform(E->get());
@@ -120,7 +121,7 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library,
for (int k = 0; k < sb->shape_owner_get_shape_count(E->get()); k++) {
Ref<Shape> collision = sb->shape_owner_get_shape(E->get(), k);
- if (collision.is_valid())
+ if (!collision.is_valid())
continue;
MeshLibrary::ShapeData shape_data;
shape_data.shape = collision;
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index a529f152dc..04be1ba4ab 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -972,6 +972,14 @@ void ScriptEditor::_menu_option(int p_option) {
EditorNode::get_singleton()->show_warning("Can't obtain the script for running");
break;
}
+
+ current->apply_code();
+ Error err = scr->reload(false); //hard reload script before running always
+
+ if (err != OK) {
+ EditorNode::get_singleton()->show_warning("Script failed reloading, check console for errors.");
+ return;
+ }
if (!scr->is_tool()) {
EditorNode::get_singleton()->show_warning("Script is not in tool mode, will not be able to run");
@@ -1149,8 +1157,6 @@ void ScriptEditor::_notification(int p_what) {
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
- tab_container->add_style_override("panel", editor->get_gui_base()->get_stylebox("ScriptPanel", "EditorStyles"));
-
help_search->set_icon(get_icon("HelpSearch", "EditorIcons"));
site_search->set_icon(get_icon("Instance", "EditorIcons"));
class_search->set_icon(get_icon("ClassList", "EditorIcons"));
@@ -1417,7 +1423,7 @@ void ScriptEditor::_update_script_colors() {
int non_zero_hist_size = (hist_size == 0) ? 1 : hist_size;
float v = Math::ease((edit_pass - pass) / float(non_zero_hist_size), 0.4);
- script_list->set_item_custom_bg_color(i, hot_color.linear_interpolate(cold_color, v));
+ script_list->set_item_custom_fg_color(i, hot_color.linear_interpolate(cold_color, v));
}
}
}
@@ -1539,8 +1545,14 @@ bool ScriptEditor::edit(const Ref<Script> &p_script, int p_line, int p_col, bool
bool open_dominant = EditorSettings::get_singleton()->get("text_editor/files/open_dominant_script_on_scene_change");
+ if (p_script->get_language()->overrides_external_editor()) {
+ Error err = p_script->get_language()->open_in_external_editor(p_script, p_line >= 0 ? p_line : 0, p_col);
+ if (err != OK)
+ ERR_PRINT("Couldn't open script in the overridden external text editor");
+ return false;
+ }
+
if ((debugger->get_dump_stack_script() != p_script || debugger->get_debug_with_external_editor()) &&
- p_script->get_language()->open_in_external_editor(p_script, p_line >= 0 ? p_line : 0, p_col) == OK &&
p_script->get_path().is_resource_file() &&
bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor"))) {
@@ -2210,7 +2222,6 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
members_overview->set_v_size_flags(SIZE_EXPAND_FILL);
tab_container = memnew(TabContainer);
- tab_container->add_style_override("panel", p_editor->get_gui_base()->get_stylebox("ScriptPanel", "EditorStyles"));
tab_container->set_tabs_visible(false);
script_split->add_child(tab_container);
@@ -2506,9 +2517,9 @@ ScriptEditorPlugin::ScriptEditorPlugin(EditorNode *p_node) {
EDITOR_DEF("text_editor/open_scripts/script_temperature_enabled", true);
EDITOR_DEF("text_editor/open_scripts/highlight_current_script", true);
EDITOR_DEF("text_editor/open_scripts/script_temperature_history_size", 15);
- EDITOR_DEF("text_editor/open_scripts/script_temperature_hot_color", Color(1, 0, 0, 0.3));
- EDITOR_DEF("text_editor/open_scripts/script_temperature_cold_color", Color(0, 0, 1, 0.3));
- EDITOR_DEF("text_editor/open_scripts/current_script_background_color", Color(0.81, 0.81, 0.14, 0.63));
+ EDITOR_DEF("text_editor/open_scripts/script_temperature_hot_color", Color::html("ed5e5e"));
+ EDITOR_DEF("text_editor/open_scripts/script_temperature_cold_color", Color(1, 1, 1, 0.3));
+ EDITOR_DEF("text_editor/open_scripts/current_script_background_color", Color(1, 1, 1, 0.5));
EDITOR_DEF("text_editor/open_scripts/group_help_pages", true);
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "text_editor/open_scripts/sort_scripts_by", PROPERTY_HINT_ENUM, "Name,Path"));
EDITOR_DEF("text_editor/open_scripts/sort_scripts_by", 0);
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index 33890d890d..fae57eb5d2 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -75,14 +75,9 @@ void ScriptTextEditor::_load_theme_settings() {
text_edit->clear_colors();
- /* color from color_theme or from editor color */
-
- Color background_color = EDITOR_DEF("text_editor/highlighting/background_color", Color(0, 0, 0, 0));
- if (EDITOR_DEF("text_editor/theme/adapted_code_editor_background_color", false))
- background_color = get_color("dark_color_1", "Editor");
-
/* keyword color */
- text_edit->add_color_override("background_color", background_color);
+
+ text_edit->add_color_override("background_color", EDITOR_DEF("text_editor/highlighting/background_color", Color(0, 0, 0, 0)));
text_edit->add_color_override("completion_background_color", EDITOR_DEF("text_editor/highlighting/completion_background_color", Color(0, 0, 0, 0)));
text_edit->add_color_override("completion_selected_color", EDITOR_DEF("text_editor/highlighting/completion_selected_color", Color::html("434244")));
text_edit->add_color_override("completion_existing_color", EDITOR_DEF("text_editor/highlighting/completion_existing_color", Color::html("21dfdfdf")));
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 13b0391a87..b02016c273 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -289,6 +289,8 @@ void ShaderEditor::_editor_settings_changed() {
shader_editor->get_text_edit()->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink_speed"));
shader_editor->get_text_edit()->add_constant_override("line_spacing", EditorSettings::get_singleton()->get("text_editor/theme/line_spacing"));
shader_editor->get_text_edit()->cursor_set_block_mode(EditorSettings::get_singleton()->get("text_editor/cursor/block_caret"));
+ shader_editor->get_text_edit()->set_smooth_scroll_enabled(EditorSettings::get_singleton()->get("text_editor/open_scripts/smooth_scrolling"));
+ shader_editor->get_text_edit()->set_v_scroll_speed(EditorSettings::get_singleton()->get("text_editor/open_scripts/v_scroll_speed"));
}
void ShaderEditor::_bind_methods() {
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index d9fc2f32f7..a5f55835f0 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -35,12 +35,15 @@
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
#include "editor/plugins/animation_player_editor_plugin.h"
+#include "editor/plugins/script_editor_plugin.h"
+#include "editor/script_editor_debugger.h"
#include "editor/spatial_editor_gizmos.h"
#include "os/keyboard.h"
#include "print_string.h"
#include "project_settings.h"
#include "scene/3d/camera.h"
#include "scene/3d/visual_instance.h"
+#include "scene/resources/packed_scene.h"
#include "scene/resources/surface_tool.h"
#include "sort.h"
@@ -228,7 +231,7 @@ Vector3 SpatialEditorViewport::_get_camera_normal() const {
return -_get_camera_transform().basis.get_axis(2);
}
-Vector3 SpatialEditorViewport::_get_ray(const Vector2 &p_pos) {
+Vector3 SpatialEditorViewport::_get_ray(const Vector2 &p_pos) const {
return camera->project_ray_normal(p_pos);
}
@@ -700,6 +703,11 @@ void SpatialEditorViewport::_smouseenter() {
surface->grab_focus();
}
+void SpatialEditorViewport::_smouseexit() {
+
+ _remove_preview();
+}
+
void SpatialEditorViewport::_list_select(Ref<InputEventMouseButton> b) {
_find_items_at_pos(b->get_position(), clicked_includes_current, selection_results, b->get_shift());
@@ -1895,6 +1903,7 @@ void SpatialEditorViewport::_notification(int p_what) {
surface->connect("draw", this, "_draw");
surface->connect("gui_input", this, "_sinput");
surface->connect("mouse_entered", this, "_smouseenter");
+ surface->connect("mouse_exited", this, "_smouseexit");
info->add_style_override("panel", get_stylebox("panel", "Panel"));
preview_camera->set_icon(get_icon("Camera", "EditorIcons"));
_init_gizmo_instance(index);
@@ -2425,6 +2434,7 @@ void SpatialEditorViewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("_draw"), &SpatialEditorViewport::_draw);
ClassDB::bind_method(D_METHOD("_smouseenter"), &SpatialEditorViewport::_smouseenter);
+ ClassDB::bind_method(D_METHOD("_smouseexit"), &SpatialEditorViewport::_smouseexit);
ClassDB::bind_method(D_METHOD("_sinput"), &SpatialEditorViewport::_sinput);
ClassDB::bind_method(D_METHOD("_menu_option"), &SpatialEditorViewport::_menu_option);
ClassDB::bind_method(D_METHOD("_toggle_camera_preview"), &SpatialEditorViewport::_toggle_camera_preview);
@@ -2432,6 +2442,8 @@ void SpatialEditorViewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("update_transform_gizmo_view"), &SpatialEditorViewport::update_transform_gizmo_view);
ClassDB::bind_method(D_METHOD("_selection_result_pressed"), &SpatialEditorViewport::_selection_result_pressed);
ClassDB::bind_method(D_METHOD("_selection_menu_hide"), &SpatialEditorViewport::_selection_menu_hide);
+ ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &SpatialEditorViewport::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("drop_data_fw"), &SpatialEditorViewport::drop_data_fw);
ADD_SIGNAL(MethodInfo("toggle_maximize_view", PropertyInfo(Variant::OBJECT, "viewport")));
}
@@ -2481,6 +2493,293 @@ void SpatialEditorViewport::focus_selection() {
cursor.pos = center;
}
+void SpatialEditorViewport::assign_pending_data_pointers(Spatial *p_preview_node, Rect3 *p_preview_bounds, AcceptDialog *p_accept) {
+ preview_node = p_preview_node;
+ preview_bounds = p_preview_bounds;
+ accept = p_accept;
+}
+
+Vector3 SpatialEditorViewport::_get_instance_position(const Point2 &p_pos) const {
+ const float MAX_DISTANCE = 10;
+
+ Vector3 world_ray = _get_ray(p_pos);
+ Vector3 world_pos = _get_ray_pos(p_pos);
+
+ Vector<ObjectID> instances = VisualServer::get_singleton()->instances_cull_ray(world_pos, world_ray, get_tree()->get_root()->get_world()->get_scenario());
+ Set<Ref<SpatialEditorGizmo> > found_gizmos;
+
+ float closest_dist = MAX_DISTANCE;
+
+ Vector3 point = world_pos + world_ray * MAX_DISTANCE;
+ Vector3 normal = Vector3(0.0, 0.0, 0.0);
+
+ for (int i = 0; i < instances.size(); i++) {
+
+ MeshInstance *mesh_instance = Object::cast_to<MeshInstance>(ObjectDB::get_instance(instances[i]));
+
+ if (!mesh_instance)
+ continue;
+
+ Ref<SpatialEditorGizmo> seg = mesh_instance->get_gizmo();
+
+ if ((!seg.is_valid()) || found_gizmos.has(seg)) {
+ continue;
+ }
+
+ found_gizmos.insert(seg);
+
+ int handle = -1;
+ Vector3 hit_point;
+ Vector3 hit_normal;
+ bool inters = seg->intersect_ray(camera, p_pos, hit_point, hit_normal, NULL, false);
+
+ if (!inters)
+ continue;
+
+ float dist = world_pos.distance_to(hit_point);
+
+ if (dist < 0)
+ continue;
+
+ if (dist < closest_dist) {
+ closest_dist = dist;
+ point = hit_point;
+ normal = hit_normal;
+ }
+ }
+ Vector3 center = preview_bounds->get_size() * 0.5;
+ return point + (center * normal);
+}
+
+Rect3 SpatialEditorViewport::_calculate_spatial_bounds(const Spatial *p_parent, const Rect3 p_bounds) {
+ Rect3 bounds = p_bounds;
+ for (int i = 0; i < p_parent->get_child_count(); i++) {
+ Spatial *child = Object::cast_to<Spatial>(p_parent->get_child(i));
+ if (child) {
+ MeshInstance *mesh_instance = Object::cast_to<MeshInstance>(child);
+ if (mesh_instance) {
+ Rect3 mesh_instance_bounds = mesh_instance->get_aabb();
+ mesh_instance_bounds.position += mesh_instance->get_global_transform().origin - p_parent->get_global_transform().origin;
+ bounds.merge_with(mesh_instance_bounds);
+ }
+ bounds = _calculate_spatial_bounds(child, bounds);
+ }
+ }
+ return bounds;
+}
+
+void SpatialEditorViewport::_create_preview(const Vector<String> &files) const {
+ for (int i = 0; i < files.size(); i++) {
+ String path = files[i];
+ RES res = ResourceLoader::load(path);
+ Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
+ if (scene != NULL) {
+ if (scene.is_valid()) {
+ Node *instance = scene->instance();
+ if (instance) {
+ preview_node->add_child(instance);
+ }
+ }
+ editor->get_scene_root()->add_child(preview_node);
+ }
+ }
+ *preview_bounds = _calculate_spatial_bounds(preview_node, Rect3());
+}
+
+void SpatialEditorViewport::_remove_preview() {
+ if (preview_node->get_parent()) {
+ for (int i = preview_node->get_child_count() - 1; i >= 0; i--) {
+ Node *node = preview_node->get_child(i);
+ node->queue_delete();
+ preview_node->remove_child(node);
+ }
+ editor->get_scene_root()->remove_child(preview_node);
+ }
+}
+
+bool SpatialEditorViewport::_cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node) {
+ if (p_desired_node->get_filename() == p_target_scene_path) {
+ return true;
+ }
+
+ int childCount = p_desired_node->get_child_count();
+ for (int i = 0; i < childCount; i++) {
+ Node *child = p_desired_node->get_child(i);
+ if (_cyclical_dependency_exists(p_target_scene_path, child)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool SpatialEditorViewport::_create_instance(Node *parent, String &path, const Point2 &p_point) {
+ Ref<PackedScene> sdata = ResourceLoader::load(path);
+ if (!sdata.is_valid()) { // invalid scene
+ return false;
+ }
+
+ Node *instanced_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
+ if (!instanced_scene) { // error on instancing
+ return false;
+ }
+
+ if (editor->get_edited_scene()->get_filename() != "") { // cyclical instancing
+ if (_cyclical_dependency_exists(editor->get_edited_scene()->get_filename(), instanced_scene)) {
+ memdelete(instanced_scene);
+ return false;
+ }
+ }
+
+ instanced_scene->set_filename(ProjectSettings::get_singleton()->localize_path(path));
+
+ editor_data->get_undo_redo().add_do_method(parent, "add_child", instanced_scene);
+ editor_data->get_undo_redo().add_do_method(instanced_scene, "set_owner", editor->get_edited_scene());
+ editor_data->get_undo_redo().add_do_reference(instanced_scene);
+ editor_data->get_undo_redo().add_undo_method(parent, "remove_child", instanced_scene);
+
+ String new_name = parent->validate_child_name(instanced_scene);
+ ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
+ editor_data->get_undo_redo().add_do_method(sed, "live_debug_instance_node", editor->get_edited_scene()->get_path_to(parent), path, new_name);
+ editor_data->get_undo_redo().add_undo_method(sed, "live_debug_remove_node", NodePath(String(editor->get_edited_scene()->get_path_to(parent)) + "/" + new_name));
+
+ Transform global_transform;
+ Spatial *parent_spatial = Object::cast_to<Spatial>(parent);
+ if (parent_spatial)
+ global_transform = parent_spatial->get_global_transform();
+
+ global_transform.origin = _get_instance_position(p_point);
+
+ editor_data->get_undo_redo().add_do_method(instanced_scene, "set_global_transform", global_transform);
+
+ return true;
+}
+
+void SpatialEditorViewport::_perform_drop_data() {
+ _remove_preview();
+
+ Vector<String> error_files;
+
+ editor_data->get_undo_redo().create_action(TTR("Create Node"));
+
+ for (int i = 0; i < selected_files.size(); i++) {
+ String path = selected_files[i];
+ RES res = ResourceLoader::load(path);
+ if (res.is_null()) {
+ continue;
+ }
+ Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
+ if (scene != NULL) {
+ bool success = _create_instance(target_node, path, drop_pos);
+ if (!success) {
+ error_files.push_back(path);
+ }
+ }
+ }
+
+ editor_data->get_undo_redo().commit_action();
+
+ if (error_files.size() > 0) {
+ String files_str;
+ for (int i = 0; i < error_files.size(); i++) {
+ files_str += error_files[i].get_file().get_basename() + ",";
+ }
+ files_str = files_str.substr(0, files_str.length() - 1);
+ accept->get_ok()->set_text(TTR("Ugh"));
+ accept->set_text(vformat(TTR("Error instancing scene from %s"), files_str.c_str()));
+ accept->popup_centered_minsize();
+ }
+}
+
+bool SpatialEditorViewport::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
+
+ bool can_instance = false;
+
+ if (!preview_node->is_inside_tree()) {
+ Dictionary d = p_data;
+ if (d.has("type") && (String(d["type"]) == "files")) {
+ Vector<String> files = d["files"];
+
+ List<String> scene_extensions;
+ ResourceLoader::get_recognized_extensions_for_type("PackedScene", &scene_extensions);
+
+ for (int i = 0; i < files.size(); i++) {
+ if (scene_extensions.find(files[i].get_extension())) {
+ RES res = ResourceLoader::load(files[i]);
+ if (res.is_null()) {
+ continue;
+ }
+
+ String type = res->get_class();
+ if (type == "PackedScene") {
+ Ref<PackedScene> sdata = ResourceLoader::load(files[i]);
+ Node *instanced_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
+ if (!instanced_scene) {
+ continue;
+ }
+ memdelete(instanced_scene);
+ }
+ can_instance = true;
+ break;
+ }
+ }
+ if (can_instance) {
+ _create_preview(files);
+ }
+ }
+ } else {
+ can_instance = true;
+ }
+
+ if (can_instance) {
+ Transform global_transform = Transform(Basis(), _get_instance_position(p_point));
+ preview_node->set_global_transform(global_transform);
+ }
+
+ return can_instance;
+}
+
+void SpatialEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
+ if (!can_drop_data_fw(p_point, p_data, p_from))
+ return;
+
+ bool is_shift = Input::get_singleton()->is_key_pressed(KEY_SHIFT);
+
+ selected_files.clear();
+ Dictionary d = p_data;
+ if (d.has("type") && String(d["type"]) == "files") {
+ selected_files = d["files"];
+ }
+
+ List<Node *> list = editor->get_editor_selection()->get_selected_node_list();
+ if (list.size() == 0) {
+ Node *root_node = editor->get_edited_scene();
+ if (root_node) {
+ list.push_back(root_node);
+ } else {
+ accept->get_ok()->set_text(TTR("OK :("));
+ accept->set_text(TTR("No parent to instance a child at."));
+ accept->popup_centered_minsize();
+ _remove_preview();
+ return;
+ }
+ }
+ if (list.size() != 1) {
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text(TTR("This operation requires a single selected node."));
+ accept->popup_centered_minsize();
+ _remove_preview();
+ return;
+ }
+
+ target_node = list[0];
+ if (is_shift && target_node != editor->get_edited_scene()) {
+ target_node = target_node->get_parent();
+ }
+ drop_pos = p_point;
+
+ _perform_drop_data();
+}
+
SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, EditorNode *p_editor, int p_index) {
_edit.mode = TRANSFORM_NONE;
@@ -2491,6 +2790,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
index = p_index;
editor = p_editor;
+ editor_data = editor->get_scene_tree_dock()->get_editor_data();
editor_selection = editor->get_editor_selection();
undo_redo = editor->get_undo_redo();
clicked = 0;
@@ -2509,6 +2809,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
c->add_child(viewport);
surface = memnew(Control);
+ surface->set_drag_forwarding(this);
add_child(surface);
surface->set_area_as_parent_rect();
surface->set_clip_contents(true);
@@ -2573,9 +2874,10 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
preview_camera->hide();
preview_camera->connect("toggled", this, "_toggle_camera_preview");
previewing = NULL;
- preview = NULL;
gizmo_scale = 1.0;
+ preview_node = NULL;
+
info = memnew(PanelContainer);
info->set_self_modulate(Color(1, 1, 1, 0.4));
surface->add_child(info);
@@ -2583,6 +2885,8 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
info->add_child(info_label);
info->hide();
+ accept = NULL;
+
freelook_active = false;
selection_menu = memnew(PopupMenu);
@@ -4000,6 +4304,10 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
vs = memnew(VSeparator);
hbc_menu->add_child(vs);
+ // Drag and drop support;
+ preview_node = memnew(Spatial);
+ preview_bounds = Rect3();
+
ED_SHORTCUT("spatial_editor/bottom_view", TTR("Bottom View"), KEY_MASK_ALT + KEY_KP_7);
ED_SHORTCUT("spatial_editor/top_view", TTR("Top View"), KEY_KP_7);
ED_SHORTCUT("spatial_editor/rear_view", TTR("Rear View"), KEY_MASK_ALT + KEY_KP_1);
@@ -4044,6 +4352,9 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
p = view_menu->get_popup();
+ accept = memnew(AcceptDialog);
+ editor->get_gui_base()->add_child(accept);
+
p->add_check_shortcut(ED_SHORTCUT("spatial_editor/1_viewport", TTR("1 Viewport"), KEY_MASK_CMD + KEY_1), MENU_VIEW_USE_1_VIEWPORT);
p->add_check_shortcut(ED_SHORTCUT("spatial_editor/2_viewports", TTR("2 Viewports"), KEY_MASK_CMD + KEY_2), MENU_VIEW_USE_2_VIEWPORTS);
p->add_check_shortcut(ED_SHORTCUT("spatial_editor/2_viewports_alt", TTR("2 Viewports (Alt)"), KEY_MASK_ALT + KEY_MASK_CMD + KEY_2), MENU_VIEW_USE_2_VIEWPORTS_ALT);
@@ -4078,6 +4389,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
viewports[i] = memnew(SpatialEditorViewport(this, editor, i));
viewports[i]->connect("toggle_maximize_view", this, "_toggle_maximize_view");
+ viewports[i]->assign_pending_data_pointers(preview_node, &preview_bounds, accept);
viewport_base->add_child(viewports[i]);
}
//vbc->add_child(viewport_base);
@@ -4212,6 +4524,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
}
SpatialEditor::~SpatialEditor() {
+ memdelete(preview_node);
}
void SpatialEditorPlugin::make_visible(bool p_visible) {
diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h
index 374861b5e7..db5abe2b53 100644
--- a/editor/plugins/spatial_editor_plugin.h
+++ b/editor/plugins/spatial_editor_plugin.h
@@ -106,7 +106,16 @@ private:
void _menu_option(int p_option);
Size2 prev_size;
+ Spatial *preview_node;
+ Rect3 *preview_bounds;
+ Vector<String> selected_files;
+ AcceptDialog *accept;
+
+ Node *target_node;
+ Point2 drop_pos;
+
EditorNode *editor;
+ EditorData *editor_data;
EditorSelection *editor_selection;
UndoRedo *undo_redo;
@@ -143,7 +152,7 @@ private:
ObjectID _select_ray(const Point2 &p_pos, bool p_append, bool &r_includes_current, int *r_gizmo_handle = NULL, bool p_alt_select = false);
void _find_items_at_pos(const Point2 &p_pos, bool &r_includes_current, Vector<_RayResult> &results, bool p_alt_select = false);
Vector3 _get_ray_pos(const Vector2 &p_pos) const;
- Vector3 _get_ray(const Vector2 &p_pos);
+ Vector3 _get_ray(const Vector2 &p_pos) const;
Point2 _point_to_screen(const Vector3 &p_point);
Transform _get_camera_transform() const;
int get_selected_count() const;
@@ -250,6 +259,7 @@ private:
void _draw();
void _smouseenter();
+ void _smouseexit();
void _sinput(const Ref<InputEvent> &p_event);
void _update_freelook(real_t delta);
SpatialEditor *spatial_editor;
@@ -266,6 +276,17 @@ private:
void _list_select(Ref<InputEventMouseButton> b);
Point2i _get_warped_mouse_motion(const Ref<InputEventMouseMotion> &p_ev_mouse_motion) const;
+ Vector3 _get_instance_position(const Point2 &p_pos) const;
+ static Rect3 _calculate_spatial_bounds(const Spatial *p_parent, const Rect3 p_bounds);
+ void _create_preview(const Vector<String> &files) const;
+ void _remove_preview();
+ bool _cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node);
+ bool _create_instance(Node *parent, String &path, const Point2 &p_point);
+ void _perform_drop_data();
+
+ bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
+ void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
+
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -281,6 +302,11 @@ public:
void focus_selection();
+ void assign_pending_data_pointers(
+ Spatial *p_preview_node,
+ Rect3 *p_preview_bounds,
+ AcceptDialog *p_accept);
+
Viewport *get_viewport_node() { return viewport; }
SpatialEditorViewport(SpatialEditor *p_spatial_editor, EditorNode *p_editor, int p_index);
@@ -396,6 +422,10 @@ private:
Ref<SpatialMaterial> indicator_mat;
Ref<SpatialMaterial> cursor_material;
+ // Scene drag and drop support
+ Spatial *preview_node;
+ Rect3 preview_bounds;
+
/*
struct Selected {
AABB aabb;
@@ -442,6 +472,8 @@ private:
MenuButton *transform_menu;
MenuButton *view_menu;
+ AcceptDialog *accept;
+
ConfirmationDialog *snap_dialog;
ConfirmationDialog *xform_dialog;
ConfirmationDialog *settings_dialog;
@@ -559,6 +591,7 @@ public:
Camera *get_camera() { return NULL; }
void edit(Spatial *p_spatial);
void clear();
+
SpatialEditor(EditorNode *p_editor);
~SpatialEditor();
};
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index c2c26bfe6c..7b40f69082 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -244,8 +244,22 @@ void SpriteFramesEditor::_down_pressed() {
void SpriteFramesEditor::_delete_pressed() {
+ ERR_FAIL_COND(!frames->has_animation(edited_anim));
+
if (tree->get_current() < 0)
return;
+
+ int to_delete = tree->get_current();
+ if (to_delete < 0 || to_delete >= frames->get_frame_count(edited_anim)) {
+ return;
+ }
+
+ undo_redo->create_action(TTR("Delete Resource"));
+ undo_redo->add_do_method(frames, "remove_frame", edited_anim, to_delete);
+ undo_redo->add_undo_method(frames, "add_frame", edited_anim, frames->get_frame(edited_anim, to_delete), to_delete);
+ undo_redo->add_do_method(this, "_update_library");
+ undo_redo->add_undo_method(this, "_update_library");
+ undo_redo->commit_action();
}
void SpriteFramesEditor::_animation_select() {
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index 9fd31f818e..49687a504f 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -700,6 +700,8 @@ void ProjectSettingsEditor::_update_actions() {
action->set_meta("__input", ie);
}
}
+
+ _action_check(action_name->get_text());
}
void ProjectSettingsEditor::popup_project_settings() {
@@ -809,28 +811,41 @@ void ProjectSettingsEditor::_item_del() {
undo_redo->commit_action();
}
-void ProjectSettingsEditor::_action_adds(String) {
+void ProjectSettingsEditor::_action_check(String p_action) {
- _action_add();
-}
+ if (p_action == "") {
-void ProjectSettingsEditor::_action_add() {
+ action_add->set_disabled(true);
+ } else {
- String action = action_name->get_text();
- if (action.find("/") != -1 || action.find(":") != -1 || action == "") {
- message->set_text(TTR("Invalid action (anything goes but '/' or ':')."));
- message->popup_centered(Size2(300, 100) * EDSCALE);
- return;
+ if (p_action.find("/") != -1 || p_action.find(":") != -1) {
+ action_add->set_text(TTR("Can't contain '/' or ':'"));
+ action_add->set_disabled(true);
+ return;
+ }
+ if (ProjectSettings::get_singleton()->has("input/" + p_action)) {
+ action_add->set_text(TTR("Already existing"));
+ action_add->set_disabled(true);
+ return;
+ }
+
+ action_add->set_disabled(false);
}
- if (ProjectSettings::get_singleton()->has("input/" + action)) {
- message->set_text(vformat(TTR("Action '%s' already exists!"), action));
- message->popup_centered(Size2(300, 100) * EDSCALE);
- return;
+ action_add->set_text(TTR("Add"));
+}
+
+void ProjectSettingsEditor::_action_adds(String) {
+
+ if (!action_add->is_disabled()) {
+ _action_add();
}
+}
+
+void ProjectSettingsEditor::_action_add() {
Array va;
- String name = "input/" + action;
+ String name = "input/" + action_name->get_text();
undo_redo->create_action(TTR("Add Input Action Event"));
undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, va);
undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", name);
@@ -854,6 +869,7 @@ void ProjectSettingsEditor::_action_add() {
return;
r->select(0);
input_editor->ensure_cursor_is_visible();
+ action_add->set_text(TTR("Add"));
}
void ProjectSettingsEditor::_item_checked(const String &p_item, bool p_check) {
@@ -1336,6 +1352,7 @@ void ProjectSettingsEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_save"), &ProjectSettingsEditor::_save);
ClassDB::bind_method(D_METHOD("_action_add"), &ProjectSettingsEditor::_action_add);
ClassDB::bind_method(D_METHOD("_action_adds"), &ProjectSettingsEditor::_action_adds);
+ ClassDB::bind_method(D_METHOD("_action_check"), &ProjectSettingsEditor::_action_check);
ClassDB::bind_method(D_METHOD("_action_selected"), &ProjectSettingsEditor::_action_selected);
ClassDB::bind_method(D_METHOD("_action_edited"), &ProjectSettingsEditor::_action_edited);
ClassDB::bind_method(D_METHOD("_action_activated"), &ProjectSettingsEditor::_action_activated);
@@ -1482,9 +1499,8 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
get_ok()->set_text(TTR("Close"));
set_hide_on_ok(true);
- message = memnew(ConfirmationDialog);
+ message = memnew(AcceptDialog);
add_child(message);
- message->set_hide_on_ok(true);
Control *input_base = memnew(Control);
input_base->set_name(TTR("Input Map"));
@@ -1500,7 +1516,6 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
l = memnew(Label);
vbc->add_child(l);
- l->set_position(Point2(6, 5) * EDSCALE);
l->set_text(TTR("Action:"));
hbc = memnew(HBoxContainer);
@@ -1510,12 +1525,15 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
action_name->set_h_size_flags(SIZE_EXPAND_FILL);
hbc->add_child(action_name);
action_name->connect("text_entered", this, "_action_adds");
+ action_name->connect("text_changed", this, "_action_check");
add = memnew(Button);
hbc->add_child(add);
add->set_custom_minimum_size(Size2(150, 0) * EDSCALE);
add->set_text(TTR("Add"));
+ add->set_disabled(true);
add->connect("pressed", this, "_action_add");
+ action_add = add;
input_editor = memnew(Tree);
vbc->add_child(input_editor);
diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h
index e58ba9b1c0..7f9b18a968 100644
--- a/editor/project_settings_editor.h
+++ b/editor/project_settings_editor.h
@@ -66,7 +66,7 @@ class ProjectSettingsEditor : public AcceptDialog {
ToolButton *clear_button;
HBoxContainer *add_prop_bar;
- ConfirmationDialog *message;
+ AcceptDialog *message;
LineEdit *category;
LineEdit *property;
OptionButton *type;
@@ -80,6 +80,7 @@ class ProjectSettingsEditor : public AcceptDialog {
MenuButton *popup_copy_to_feature;
LineEdit *action_name;
+ Button *action_add;
Tree *input_editor;
bool setting;
bool updating_translations;
@@ -108,6 +109,7 @@ class ProjectSettingsEditor : public AcceptDialog {
void _add_item(int p_item, Ref<InputEvent> p_exiting_event = NULL);
void _edit_item(Ref<InputEvent> p_exiting_event);
+ void _action_check(String p_action);
void _action_adds(String);
void _action_add();
void _device_input_add();
diff --git a/editor/quick_open.cpp b/editor/quick_open.cpp
index c71cc5af3f..b92ebed167 100644
--- a/editor/quick_open.cpp
+++ b/editor/quick_open.cpp
@@ -171,33 +171,50 @@ void EditorQuickOpen::_parse_fs(EditorFileSystemDirectory *efsd, Vector<Pair<Str
Pair<String, Ref<Texture> > pair;
pair.first = file;
pair.second = get_icon((has_icon(efsd->get_file_type(i), ei) ? efsd->get_file_type(i) : ot), ei);
+ list.push_back(pair);
+ }
+ }
+
+ if (add_directories) {
+ for (int i = 0; i < efsd->get_subdir_count(); i++) {
- if (search_text != String() && list.size() > 0) {
+ _parse_fs(efsd->get_subdir(i), list);
+ }
+ }
+}
- float this_sim = _path_cmp(search_text, file);
- float other_sim = _path_cmp(list[0].first, file);
- int pos = 1;
+Vector<Pair<String, Ref<Texture> > > EditorQuickOpen::_sort_fs(Vector<Pair<String, Ref<Texture> > > &list) {
- while (pos < list.size() && this_sim <= other_sim) {
- other_sim = _path_cmp(list[pos++].first, file);
- }
+ String search_text = search_box->get_text();
+ Vector<Pair<String, Ref<Texture> > > sorted_list;
- pos = this_sim >= other_sim ? pos - 1 : pos;
- list.insert(pos, pair);
+ if (search_text == String() || list.size() == 0)
+ return sorted_list;
- } else {
+ Vector<float> scores;
+ scores.resize(list.size());
+ for (int i = 0; i < list.size(); i++)
+ scores[i] = _path_cmp(search_text, list[i].first);
- list.push_back(pair);
- }
- }
- }
+ while (list.size() > 0) {
- if (add_directories) {
- for (int i = 0; i < efsd->get_subdir_count(); i++) {
+ float best_score = 0.0f;
+ int best_idx = 0;
- _parse_fs(efsd->get_subdir(i), list);
+ for (int i = 0; i < list.size(); i++) {
+ float current_score = scores[i];
+ if (current_score > best_score) {
+ best_score = current_score;
+ best_idx = i;
+ }
}
+
+ sorted_list.push_back(list[best_idx]);
+ list.remove(best_idx);
+ scores.remove(best_idx);
}
+
+ return sorted_list;
}
void EditorQuickOpen::_update_search() {
@@ -208,6 +225,7 @@ void EditorQuickOpen::_update_search() {
Vector<Pair<String, Ref<Texture> > > list;
_parse_fs(efsd, list);
+ list = _sort_fs(list);
for (int i = 0; i < list.size(); i++) {
TreeItem *ti = search_options->create_item(root);
diff --git a/editor/quick_open.h b/editor/quick_open.h
index 3f64dd8cf0..5b91965920 100644
--- a/editor/quick_open.h
+++ b/editor/quick_open.h
@@ -49,6 +49,7 @@ class EditorQuickOpen : public ConfirmationDialog {
void _sbox_input(const Ref<InputEvent> &p_ie);
void _parse_fs(EditorFileSystemDirectory *efsd, Vector<Pair<String, Ref<Texture> > > &list);
+ Vector<Pair<String, Ref<Texture> > > _sort_fs(Vector<Pair<String, Ref<Texture> > > &list);
float _path_cmp(String search, String path) const;
void _confirmed();
diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp
index 623e458aca..05e3feedb5 100644
--- a/editor/settings_config_dialog.cpp
+++ b/editor/settings_config_dialog.cpp
@@ -165,7 +165,7 @@ void EditorSettingsDialog::_update_shortcuts() {
section->set_custom_bg_color(1, get_color("prop_subsection", "Editor"));
}
- if (shortcut_filter.is_subsequence_ofi(sc->get_name())) {
+ if (shortcut_filter.is_subsequence_ofi(sc->get_name()) || shortcut_filter.is_subsequence_ofi(sc->get_as_text())) {
TreeItem *item = shortcuts->create_item(section);
item->set_text(0, sc->get_name());
diff --git a/modules/etc/image_etc.cpp b/modules/etc/image_etc.cpp
index e86fd06d81..dc7d23bbd7 100644
--- a/modules/etc/image_etc.cpp
+++ b/modules/etc/image_etc.cpp
@@ -37,7 +37,6 @@
static Image::Format _get_etc2_mode(Image::DetectChannels format) {
switch (format) {
- case Image::DETECTED_L:
case Image::DETECTED_R:
return Image::FORMAT_ETC2_R11;
@@ -47,7 +46,7 @@ static Image::Format _get_etc2_mode(Image::DetectChannels format) {
case Image::DETECTED_RGB:
return Image::FORMAT_ETC2_RGB8;
- case Image::DETECTED_RGBA:
+ default:
return Image::FORMAT_ETC2_RGBA8;
// TODO: would be nice if we could use FORMAT_ETC2_RGB8A1 for FORMAT_RGBA5551
diff --git a/modules/gdnative/SCsub b/modules/gdnative/SCsub
index 65970d48c1..f386f2b542 100644
--- a/modules/gdnative/SCsub
+++ b/modules/gdnative/SCsub
@@ -2,12 +2,16 @@
Import('env')
-env.add_source_files(env.modules_sources, "*.cpp")
-env.add_source_files(env.modules_sources, "godot/*.cpp")
+gdn_env = env.Clone()
-env.Append(CPPFLAGS=['-DGDAPI_BUILT_IN'])
-env.Append(CPPPATH=['#modules/gdnative/'])
+gdn_env.add_source_files(env.modules_sources, "*.cpp")
+gdn_env.add_source_files(env.modules_sources, "gdnative/*.cpp")
+gdn_env.add_source_files(env.modules_sources, "nativescript/*.cpp")
+
+gdn_env.Append(CPPFLAGS=['-DGDAPI_BUILT_IN'])
+gdn_env.Append(CPPPATH=['#modules/gdnative/include/'])
if "platform" in env and env["platform"] == "x11": # there has to be a better solution?
env.Append(LINKFLAGS=["-rdynamic"])
+
env.use_ptrcall = True
diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp
index ded987557c..6da538844a 100644
--- a/modules/gdnative/gdnative.cpp
+++ b/modules/gdnative/gdnative.cpp
@@ -100,6 +100,11 @@ GDNativeLibrary::~GDNativeLibrary() {
void GDNativeLibrary::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_library_path", "platform", "path"), &GDNativeLibrary::set_library_path);
ClassDB::bind_method(D_METHOD("get_library_path", "platform"), &GDNativeLibrary::get_library_path);
+
+ ClassDB::bind_method(D_METHOD("is_singleton_gdnative"), &GDNativeLibrary::is_singleton_gdnative);
+ ClassDB::bind_method(D_METHOD("set_singleton_gdnative", "singleton"), &GDNativeLibrary::set_singleton_gdnative);
+
+ ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "singleton_gdnative"), "set_singleton_gdnative", "is_singleton_gdnative");
}
bool GDNativeLibrary::_set(const StringName &p_name, const Variant &p_value) {
@@ -175,7 +180,6 @@ GDNative::GDNative() {
}
GDNative::~GDNative() {
- // TODO(karroffel): implement ALL the things!
}
extern "C" void _api_anchor();
diff --git a/modules/gdnative/gdnative.h b/modules/gdnative/gdnative.h
index dc1c3507ec..4753c7efe5 100644
--- a/modules/gdnative/gdnative.h
+++ b/modules/gdnative/gdnative.h
@@ -35,7 +35,7 @@
#include "os/thread_safe.h"
#include "resource.h"
-#include <godot/gdnative.h>
+#include "gdnative/gdnative.h"
class GDNativeLibrary : public Resource {
GDCLASS(GDNativeLibrary, Resource)
@@ -77,6 +77,8 @@ class GDNativeLibrary : public Resource {
String library_paths[NUM_PLATFORMS];
+ bool singleton_gdnative = false;
+
protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
@@ -92,6 +94,9 @@ public:
String get_library_path(StringName p_platform) const;
String get_active_library_path() const;
+
+ _FORCE_INLINE_ bool is_singleton_gdnative() const { return singleton_gdnative; }
+ _FORCE_INLINE_ void set_singleton_gdnative(bool p_singleton) { singleton_gdnative = p_singleton; }
};
typedef godot_variant (*native_call_cb)(void *, godot_string *, godot_array *);
diff --git a/modules/gdnative/godot/array.cpp b/modules/gdnative/gdnative/array.cpp
index c3fde0e954..51c023981f 100644
--- a/modules/gdnative/godot/array.cpp
+++ b/modules/gdnative/gdnative/array.cpp
@@ -27,7 +27,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include <godot/array.h>
+#include "gdnative/array.h"
#include "core/array.h"
#include "core/os/memory.h"
diff --git a/modules/gdnative/godot/basis.cpp b/modules/gdnative/gdnative/basis.cpp
index 1d7aa18a70..b1327cdaef 100644
--- a/modules/gdnative/godot/basis.cpp
+++ b/modules/gdnative/gdnative/basis.cpp
@@ -27,7 +27,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include <godot/basis.h>
+#include "gdnative/basis.h"
#include "core/math/matrix3.h"
#include "core/variant.h"
diff --git a/modules/gdnative/godot/color.cpp b/modules/gdnative/gdnative/color.cpp
index 3677fdc265..3f8912d896 100644
--- a/modules/gdnative/godot/color.cpp
+++ b/modules/gdnative/gdnative/color.cpp
@@ -27,7 +27,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include <godot/color.h>
+#include "gdnative/color.h"
#include "core/color.h"
#include "core/variant.h"
diff --git a/modules/gdnative/godot/dictionary.cpp b/modules/gdnative/gdnative/dictionary.cpp
index 2996cc78a3..ed98cdbb00 100644
--- a/modules/gdnative/godot/dictionary.cpp
+++ b/modules/gdnative/gdnative/dictionary.cpp
@@ -27,7 +27,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include <godot/dictionary.h>
+#include "gdnative/dictionary.h"
#include "core/variant.h"
// core/variant.h before to avoid compile errors with MSVC
diff --git a/modules/gdnative/godot/gdnative.cpp b/modules/gdnative/gdnative/gdnative.cpp
index 7cd52da34d..cf1f6a4f16 100644
--- a/modules/gdnative/godot/gdnative.cpp
+++ b/modules/gdnative/gdnative/gdnative.cpp
@@ -27,11 +27,10 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include <godot/gdnative.h>
+#include "gdnative/gdnative.h"
#include "class_db.h"
#include "error_macros.h"
-#include "gdnative.h"
#include "global_constants.h"
#include "os/os.h"
#include "project_settings.h"
diff --git a/modules/gdnative/godot/node_path.cpp b/modules/gdnative/gdnative/node_path.cpp
index 2309588a81..50fade5b94 100644
--- a/modules/gdnative/godot/node_path.cpp
+++ b/modules/gdnative/gdnative/node_path.cpp
@@ -27,7 +27,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include <godot/node_path.h>
+#include "gdnative/node_path.h"
#include "core/node_path.h"
#include "core/variant.h"
diff --git a/modules/gdnative/godot/plane.cpp b/modules/gdnative/gdnative/plane.cpp
index f3d4b6971e..a5e05ffa6b 100644
--- a/modules/gdnative/godot/plane.cpp
+++ b/modules/gdnative/gdnative/plane.cpp
@@ -27,7 +27,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include <godot/plane.h>
+#include "gdnative/plane.h"
#include "core/math/plane.h"
#include "core/variant.h"
diff --git a/modules/gdnative/godot/pool_arrays.cpp b/modules/gdnative/gdnative/pool_arrays.cpp
index 49bf851051..1393374da2 100644
--- a/modules/gdnative/godot/pool_arrays.cpp
+++ b/modules/gdnative/gdnative/pool_arrays.cpp
@@ -27,7 +27,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include <godot/pool_arrays.h>
+#include "gdnative/pool_arrays.h"
#include "array.h"
#include "core/variant.h"
diff --git a/modules/gdnative/godot/quat.cpp b/modules/gdnative/gdnative/quat.cpp
index e6bea78b60..7db7847da1 100644
--- a/modules/gdnative/godot/quat.cpp
+++ b/modules/gdnative/gdnative/quat.cpp
@@ -27,7 +27,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include <godot/quat.h>
+#include "gdnative/quat.h"
#include "core/math/quat.h"
#include "core/variant.h"
diff --git a/modules/gdnative/godot/rect2.cpp b/modules/gdnative/gdnative/rect2.cpp
index 98e7855dc9..ecd8cce9ca 100644
--- a/modules/gdnative/godot/rect2.cpp
+++ b/modules/gdnative/gdnative/rect2.cpp
@@ -27,7 +27,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include <godot/rect2.h>
+#include "gdnative/rect2.h"
#include "core/math/math_2d.h"
#include "core/variant.h"
diff --git a/modules/gdnative/godot/rect3.cpp b/modules/gdnative/gdnative/rect3.cpp
index 88952ab49c..d34d964db9 100644
--- a/modules/gdnative/godot/rect3.cpp
+++ b/modules/gdnative/gdnative/rect3.cpp
@@ -27,7 +27,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include <godot/rect3.h>
+#include "gdnative/rect3.h"
#include "core/math/rect3.h"
#include "core/variant.h"
diff --git a/modules/gdnative/godot/rid.cpp b/modules/gdnative/gdnative/rid.cpp
index 51c8aaa1b3..f05c39906c 100644
--- a/modules/gdnative/godot/rid.cpp
+++ b/modules/gdnative/gdnative/rid.cpp
@@ -27,7 +27,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include <godot/rid.h>
+#include "gdnative/rid.h"
#include "core/resource.h"
#include "core/rid.h"
diff --git a/modules/gdnative/godot/string.cpp b/modules/gdnative/gdnative/string.cpp
index 1282cf95e5..9b715ce36a 100644
--- a/modules/gdnative/godot/string.cpp
+++ b/modules/gdnative/gdnative/string.cpp
@@ -27,7 +27,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include <godot/string.h>
+#include "gdnative/string.h"
#include "core/variant.h"
#include "string_db.h"
diff --git a/modules/gdnative/godot/transform.cpp b/modules/gdnative/gdnative/transform.cpp
index a965067b77..d7a3e78d3f 100644
--- a/modules/gdnative/godot/transform.cpp
+++ b/modules/gdnative/gdnative/transform.cpp
@@ -27,7 +27,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include <godot/transform.h>
+#include "gdnative/transform.h"
#include "core/math/transform.h"
#include "core/variant.h"
diff --git a/modules/gdnative/godot/transform2d.cpp b/modules/gdnative/gdnative/transform2d.cpp
index 9fc44ecdfa..dcb54f7a53 100644
--- a/modules/gdnative/godot/transform2d.cpp
+++ b/modules/gdnative/gdnative/transform2d.cpp
@@ -27,7 +27,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include <godot/transform2d.h>
+#include "gdnative/transform2d.h"
#include "core/math/math_2d.h"
#include "core/variant.h"
diff --git a/modules/gdnative/godot/variant.cpp b/modules/gdnative/gdnative/variant.cpp
index 582544b3a0..b61f80b1f9 100644
--- a/modules/gdnative/godot/variant.cpp
+++ b/modules/gdnative/gdnative/variant.cpp
@@ -27,7 +27,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include <godot/variant.h>
+#include "gdnative/variant.h"
#include "core/variant.h"
diff --git a/modules/gdnative/godot/vector2.cpp b/modules/gdnative/gdnative/vector2.cpp
index 78ed5f06a9..67f858997f 100644
--- a/modules/gdnative/godot/vector2.cpp
+++ b/modules/gdnative/gdnative/vector2.cpp
@@ -27,7 +27,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include <godot/vector2.h>
+#include "gdnative/vector2.h"
#include "core/math/math_2d.h"
#include "core/variant.h"
diff --git a/modules/gdnative/godot/vector3.cpp b/modules/gdnative/gdnative/vector3.cpp
index 5faeac2864..c85a3f1c08 100644
--- a/modules/gdnative/godot/vector3.cpp
+++ b/modules/gdnative/gdnative/vector3.cpp
@@ -27,7 +27,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include <godot/vector3.h>
+#include "gdnative/vector3.h"
#include "core/variant.h"
#include "core/vector.h"
diff --git a/modules/gdnative/godot/icon.png.import b/modules/gdnative/godot/icon.png.import
deleted file mode 100644
index 27920124f9..0000000000
--- a/modules/gdnative/godot/icon.png.import
+++ /dev/null
@@ -1,23 +0,0 @@
-[remap]
-
-importer="texture"
-type="StreamTexture"
-path="res://.import/icon.png-aa47d037a37fb38b3b7e7828e4eec407.stex"
-
-[params]
-
-compress/mode=0
-compress/lossy_quality=0.7
-compress/hdr_mode=0
-compress/normal_map=0
-flags/repeat=0
-flags/filter=true
-flags/mipmaps=false
-flags/anisotropic=false
-flags/srgb=2
-process/fix_alpha_border=true
-process/premult_alpha=false
-process/HDR_as_SRGB=false
-stream=false
-size_limit=0
-detect_3d=true
diff --git a/modules/gdnative/godot/array.h b/modules/gdnative/include/gdnative/array.h
index 08f73c8785..edab028cba 100644
--- a/modules/gdnative/godot/array.h
+++ b/modules/gdnative/include/gdnative/array.h
@@ -46,10 +46,10 @@ typedef struct {
} godot_array;
#endif
-#include <godot/pool_arrays.h>
-#include <godot/variant.h>
+#include <gdnative/pool_arrays.h>
+#include <gdnative/variant.h>
-#include <godot/gdnative.h>
+#include <gdnative/gdnative.h>
void GDAPI godot_array_new(godot_array *r_dest);
void GDAPI godot_array_new_copy(godot_array *r_dest, const godot_array *p_src);
diff --git a/modules/gdnative/godot/basis.h b/modules/gdnative/include/gdnative/basis.h
index f36d2199de..8ff6a6f541 100644
--- a/modules/gdnative/godot/basis.h
+++ b/modules/gdnative/include/gdnative/basis.h
@@ -45,9 +45,9 @@ typedef struct {
} godot_basis;
#endif
-#include <godot/gdnative.h>
-#include <godot/quat.h>
-#include <godot/vector3.h>
+#include <gdnative/gdnative.h>
+#include <gdnative/quat.h>
+#include <gdnative/vector3.h>
void GDAPI godot_basis_new_with_rows(godot_basis *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis);
void GDAPI godot_basis_new_with_axis_and_angle(godot_basis *r_dest, const godot_vector3 *p_axis, const godot_real p_phi);
diff --git a/modules/gdnative/godot/color.h b/modules/gdnative/include/gdnative/color.h
index 5d550e40b3..90dccf75aa 100644
--- a/modules/gdnative/godot/color.h
+++ b/modules/gdnative/include/gdnative/color.h
@@ -45,8 +45,8 @@ typedef struct {
} godot_color;
#endif
-#include <godot/gdnative.h>
-#include <godot/string.h>
+#include <gdnative/gdnative.h>
+#include <gdnative/string.h>
void GDAPI godot_color_new_rgba(godot_color *r_dest, const godot_real p_r, const godot_real p_g, const godot_real p_b, const godot_real p_a);
void GDAPI godot_color_new_rgb(godot_color *r_dest, const godot_real p_r, const godot_real p_g, const godot_real p_b);
diff --git a/modules/gdnative/godot/dictionary.h b/modules/gdnative/include/gdnative/dictionary.h
index 10d580af08..c85c3f3830 100644
--- a/modules/gdnative/godot/dictionary.h
+++ b/modules/gdnative/include/gdnative/dictionary.h
@@ -45,9 +45,9 @@ typedef struct {
} godot_dictionary;
#endif
-#include <godot/array.h>
-#include <godot/gdnative.h>
-#include <godot/variant.h>
+#include <gdnative/array.h>
+#include <gdnative/gdnative.h>
+#include <gdnative/variant.h>
void GDAPI godot_dictionary_new(godot_dictionary *r_dest);
void GDAPI godot_dictionary_new_copy(godot_dictionary *r_dest, const godot_dictionary *p_src);
diff --git a/modules/gdnative/godot/gdnative.h b/modules/gdnative/include/gdnative/gdnative.h
index c71a7ae1ef..c574c56d5a 100644
--- a/modules/gdnative/godot/gdnative.h
+++ b/modules/gdnative/include/gdnative/gdnative.h
@@ -146,100 +146,74 @@ typedef float godot_real;
/////// Object (forward declared)
typedef void godot_object;
-/////// Brute force forward declarations for the rest
-/*
-typedef struct godot_variant godot_variant;
-typedef struct godot_string godot_string;
-typedef struct godot_vector2 godot_vector2;
-typedef struct godot_rect2 godot_rect2;
-typedef struct godot_vector3 godot_vector3;
-typedef struct godot_transform2d godot_transform2d;
-typedef struct godot_plane godot_plane;
-typedef struct godot_quat godot_quat;
-typedef struct godot_rect3 godot_rect3;
-typedef struct godot_basis godot_basis;
-typedef struct godot_transform godot_transform;
-typedef struct godot_color godot_color;
-typedef struct godot_node_path godot_node_path;
-typedef struct godot_rid godot_rid;
-typedef struct godot_dictionary godot_dictionary;
-typedef struct godot_array godot_array;
-typedef struct godot_pool_byte_array godot_pool_byte_array;
-typedef struct godot_pool_int_array godot_pool_int_array;
-typedef struct godot_pool_real_array godot_pool_real_array;
-typedef struct godot_pool_string_array godot_pool_string_array;
-typedef struct godot_pool_vector2_array godot_pool_vector2_array;
-typedef struct godot_pool_vector3_array godot_pool_vector3_array;
-typedef struct godot_pool_color_array godot_pool_color_array;
-*/
/////// String
-#include <godot/string.h>
+#include <gdnative/string.h>
////// Vector2
-#include <godot/vector2.h>
+#include <gdnative/vector2.h>
////// Rect2
-#include <godot/rect2.h>
+#include <gdnative/rect2.h>
////// Vector3
-#include <godot/vector3.h>
+#include <gdnative/vector3.h>
////// Transform2D
-#include <godot/transform2d.h>
+#include <gdnative/transform2d.h>
/////// Plane
-#include <godot/plane.h>
+#include <gdnative/plane.h>
/////// Quat
-#include <godot/quat.h>
+#include <gdnative/quat.h>
/////// Rect3
-#include <godot/rect3.h>
+#include <gdnative/rect3.h>
/////// Basis
-#include <godot/basis.h>
+#include <gdnative/basis.h>
/////// Transform
-#include <godot/transform.h>
+#include <gdnative/transform.h>
/////// Color
-#include <godot/color.h>
+#include <gdnative/color.h>
/////// NodePath
-#include <godot/node_path.h>
+#include <gdnative/node_path.h>
/////// RID
-#include <godot/rid.h>
+#include <gdnative/rid.h>
/////// Dictionary
-#include <godot/dictionary.h>
+#include <gdnative/dictionary.h>
/////// Array
-#include <godot/array.h>
+#include <gdnative/array.h>
// single API file for Pool*Array
-#include <godot/pool_arrays.h>
+#include <gdnative/pool_arrays.h>
void GDAPI godot_object_destroy(godot_object *p_o);
////// Variant
-#include <godot/variant.h>
+#include <gdnative/variant.h>
////// Singleton API
diff --git a/modules/gdnative/godot/node_path.h b/modules/gdnative/include/gdnative/node_path.h
index 2f71ddd59d..0cfdbc1127 100644
--- a/modules/gdnative/godot/node_path.h
+++ b/modules/gdnative/include/gdnative/node_path.h
@@ -45,8 +45,8 @@ typedef struct {
} godot_node_path;
#endif
-#include <godot/gdnative.h>
-#include <godot/string.h>
+#include <gdnative/gdnative.h>
+#include <gdnative/string.h>
void GDAPI godot_node_path_new(godot_node_path *r_dest, const godot_string *p_from);
void GDAPI godot_node_path_new_copy(godot_node_path *r_dest, const godot_node_path *p_src);
diff --git a/modules/gdnative/godot/plane.h b/modules/gdnative/include/gdnative/plane.h
index 27548c8b0c..6a8915e08b 100644
--- a/modules/gdnative/godot/plane.h
+++ b/modules/gdnative/include/gdnative/plane.h
@@ -45,8 +45,8 @@ typedef struct {
} godot_plane;
#endif
-#include <godot/gdnative.h>
-#include <godot/vector3.h>
+#include <gdnative/gdnative.h>
+#include <gdnative/vector3.h>
void GDAPI godot_plane_new_with_reals(godot_plane *r_dest, const godot_real p_a, const godot_real p_b, const godot_real p_c, const godot_real p_d);
void GDAPI godot_plane_new_with_vectors(godot_plane *r_dest, const godot_vector3 *p_v1, const godot_vector3 *p_v2, const godot_vector3 *p_v3);
diff --git a/modules/gdnative/godot/pool_arrays.h b/modules/gdnative/include/gdnative/pool_arrays.h
index 1b51dca38c..cb1095ee8c 100644
--- a/modules/gdnative/godot/pool_arrays.h
+++ b/modules/gdnative/include/gdnative/pool_arrays.h
@@ -113,12 +113,12 @@ typedef struct {
} godot_pool_color_array;
#endif
-#include <godot/array.h>
-#include <godot/color.h>
-#include <godot/vector2.h>
-#include <godot/vector3.h>
+#include <gdnative/array.h>
+#include <gdnative/color.h>
+#include <gdnative/vector2.h>
+#include <gdnative/vector3.h>
-#include <godot/gdnative.h>
+#include <gdnative/gdnative.h>
// byte
diff --git a/modules/gdnative/godot/quat.h b/modules/gdnative/include/gdnative/quat.h
index 9a3238a337..4ffb96eb26 100644
--- a/modules/gdnative/godot/quat.h
+++ b/modules/gdnative/include/gdnative/quat.h
@@ -45,8 +45,8 @@ typedef struct {
} godot_quat;
#endif
-#include <godot/gdnative.h>
-#include <godot/vector3.h>
+#include <gdnative/gdnative.h>
+#include <gdnative/vector3.h>
void GDAPI godot_quat_new(godot_quat *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_z, const godot_real p_w);
void GDAPI godot_quat_new_with_axis_angle(godot_quat *r_dest, const godot_vector3 *p_axis, const godot_real p_angle);
diff --git a/modules/gdnative/godot/rect2.h b/modules/gdnative/include/gdnative/rect2.h
index 8ceeddf1b4..9e6cf60342 100644
--- a/modules/gdnative/godot/rect2.h
+++ b/modules/gdnative/include/gdnative/rect2.h
@@ -43,8 +43,8 @@ typedef struct godot_rect2 {
} godot_rect2;
#endif
-#include <godot/gdnative.h>
-#include <godot/vector2.h>
+#include <gdnative/gdnative.h>
+#include <gdnative/vector2.h>
void GDAPI godot_rect2_new_with_position_and_size(godot_rect2 *r_dest, const godot_vector2 *p_pos, const godot_vector2 *p_size);
void GDAPI godot_rect2_new(godot_rect2 *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_width, const godot_real p_height);
diff --git a/modules/gdnative/godot/rect3.h b/modules/gdnative/include/gdnative/rect3.h
index ca96aadd5c..f94b6fea25 100644
--- a/modules/gdnative/godot/rect3.h
+++ b/modules/gdnative/include/gdnative/rect3.h
@@ -45,9 +45,9 @@ typedef struct {
} godot_rect3;
#endif
-#include <godot/gdnative.h>
-#include <godot/plane.h>
-#include <godot/vector3.h>
+#include <gdnative/gdnative.h>
+#include <gdnative/plane.h>
+#include <gdnative/vector3.h>
void GDAPI godot_rect3_new(godot_rect3 *r_dest, const godot_vector3 *p_pos, const godot_vector3 *p_size);
diff --git a/modules/gdnative/godot/rid.h b/modules/gdnative/include/gdnative/rid.h
index c56ff38735..d9b5336fc9 100644
--- a/modules/gdnative/godot/rid.h
+++ b/modules/gdnative/include/gdnative/rid.h
@@ -45,7 +45,7 @@ typedef struct {
} godot_rid;
#endif
-#include <godot/gdnative.h>
+#include <gdnative/gdnative.h>
void GDAPI godot_rid_new(godot_rid *r_dest);
diff --git a/modules/gdnative/godot/string.h b/modules/gdnative/include/gdnative/string.h
index 128448e64e..aca23a81d8 100644
--- a/modules/gdnative/godot/string.h
+++ b/modules/gdnative/include/gdnative/string.h
@@ -46,8 +46,8 @@ typedef struct {
} godot_string;
#endif
-#include <godot/gdnative.h>
-#include <godot/variant.h>
+#include <gdnative/gdnative.h>
+#include <gdnative/variant.h>
void GDAPI godot_string_new(godot_string *r_dest);
void GDAPI godot_string_new_copy(godot_string *r_dest, const godot_string *p_src);
diff --git a/modules/gdnative/godot/transform.h b/modules/gdnative/include/gdnative/transform.h
index 60788e3d57..656afae129 100644
--- a/modules/gdnative/godot/transform.h
+++ b/modules/gdnative/include/gdnative/transform.h
@@ -45,10 +45,10 @@ typedef struct {
} godot_transform;
#endif
-#include <godot/basis.h>
-#include <godot/gdnative.h>
-#include <godot/variant.h>
-#include <godot/vector3.h>
+#include <gdnative/basis.h>
+#include <gdnative/gdnative.h>
+#include <gdnative/variant.h>
+#include <gdnative/vector3.h>
void GDAPI godot_transform_new_with_axis_origin(godot_transform *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis, const godot_vector3 *p_origin);
void GDAPI godot_transform_new(godot_transform *r_dest, const godot_basis *p_basis, const godot_vector3 *p_origin);
diff --git a/modules/gdnative/godot/transform2d.h b/modules/gdnative/include/gdnative/transform2d.h
index c0f5725eed..a945868b17 100644
--- a/modules/gdnative/godot/transform2d.h
+++ b/modules/gdnative/include/gdnative/transform2d.h
@@ -45,9 +45,9 @@ typedef struct {
} godot_transform2d;
#endif
-#include <godot/gdnative.h>
-#include <godot/variant.h>
-#include <godot/vector2.h>
+#include <gdnative/gdnative.h>
+#include <gdnative/variant.h>
+#include <gdnative/vector2.h>
void GDAPI godot_transform2d_new(godot_transform2d *r_dest, const godot_real p_rot, const godot_vector2 *p_pos);
void GDAPI godot_transform2d_new_axis_origin(godot_transform2d *r_dest, const godot_vector2 *p_x_axis, const godot_vector2 *p_y_axis, const godot_vector2 *p_origin);
diff --git a/modules/gdnative/godot/variant.h b/modules/gdnative/include/gdnative/variant.h
index 849ba8bda6..969506585d 100644
--- a/modules/gdnative/godot/variant.h
+++ b/modules/gdnative/include/gdnative/variant.h
@@ -99,25 +99,25 @@ typedef struct godot_variant_call_error {
godot_variant_type expected;
} godot_variant_call_error;
-#include <godot/array.h>
-#include <godot/basis.h>
-#include <godot/color.h>
-#include <godot/dictionary.h>
-#include <godot/node_path.h>
-#include <godot/plane.h>
-#include <godot/pool_arrays.h>
-#include <godot/quat.h>
-#include <godot/rect2.h>
-#include <godot/rect3.h>
-#include <godot/rid.h>
-#include <godot/string.h>
-#include <godot/transform.h>
-#include <godot/transform2d.h>
-#include <godot/variant.h>
-#include <godot/vector2.h>
-#include <godot/vector3.h>
-
-#include <godot/gdnative.h>
+#include <gdnative/array.h>
+#include <gdnative/basis.h>
+#include <gdnative/color.h>
+#include <gdnative/dictionary.h>
+#include <gdnative/node_path.h>
+#include <gdnative/plane.h>
+#include <gdnative/pool_arrays.h>
+#include <gdnative/quat.h>
+#include <gdnative/rect2.h>
+#include <gdnative/rect3.h>
+#include <gdnative/rid.h>
+#include <gdnative/string.h>
+#include <gdnative/transform.h>
+#include <gdnative/transform2d.h>
+#include <gdnative/variant.h>
+#include <gdnative/vector2.h>
+#include <gdnative/vector3.h>
+
+#include <gdnative/gdnative.h>
godot_variant_type GDAPI godot_variant_get_type(const godot_variant *p_v);
diff --git a/modules/gdnative/godot/vector2.h b/modules/gdnative/include/gdnative/vector2.h
index 98e9700e32..0af4abae27 100644
--- a/modules/gdnative/godot/vector2.h
+++ b/modules/gdnative/include/gdnative/vector2.h
@@ -45,7 +45,7 @@ typedef struct {
} godot_vector2;
#endif
-#include <godot/gdnative.h>
+#include <gdnative/gdnative.h>
void GDAPI godot_vector2_new(godot_vector2 *r_dest, const godot_real p_x, const godot_real p_y);
diff --git a/modules/gdnative/godot/vector3.h b/modules/gdnative/include/gdnative/vector3.h
index b76ca11a9c..a27d516ec5 100644
--- a/modules/gdnative/godot/vector3.h
+++ b/modules/gdnative/include/gdnative/vector3.h
@@ -45,8 +45,8 @@ typedef struct {
} godot_vector3;
#endif
-#include <godot/basis.h>
-#include <godot/gdnative.h>
+#include <gdnative/basis.h>
+#include <gdnative/gdnative.h>
typedef enum {
GODOT_VECTOR3_AXIS_X,
diff --git a/modules/nativescript/godot_nativescript.h b/modules/gdnative/include/nativescript/godot_nativescript.h
index d1cbf221ec..96f213ead7 100644
--- a/modules/nativescript/godot_nativescript.h
+++ b/modules/gdnative/include/nativescript/godot_nativescript.h
@@ -30,7 +30,7 @@
#ifndef GODOT_NATIVESCRIPT_H
#define GODOT_NATIVESCRIPT_H
-#include <godot/gdnative.h>
+#include <gdnative/gdnative.h>
#ifdef __cplusplus
extern "C" {
diff --git a/modules/nativescript/SCsub b/modules/gdnative/nativescript/SCsub
index e980e40e8e..e980e40e8e 100644
--- a/modules/nativescript/SCsub
+++ b/modules/gdnative/nativescript/SCsub
diff --git a/modules/nativescript/api_generator.cpp b/modules/gdnative/nativescript/api_generator.cpp
index fdd5a2ea19..fdd5a2ea19 100644
--- a/modules/nativescript/api_generator.cpp
+++ b/modules/gdnative/nativescript/api_generator.cpp
diff --git a/modules/nativescript/api_generator.h b/modules/gdnative/nativescript/api_generator.h
index 56c2d786e6..56c2d786e6 100644
--- a/modules/nativescript/api_generator.h
+++ b/modules/gdnative/nativescript/api_generator.h
diff --git a/modules/nativescript/godot_nativescript.cpp b/modules/gdnative/nativescript/godot_nativescript.cpp
index 926b3261b2..61ac13b796 100644
--- a/modules/nativescript/godot_nativescript.cpp
+++ b/modules/gdnative/nativescript/godot_nativescript.cpp
@@ -27,17 +27,17 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "godot_nativescript.h"
-
-#include "nativescript.h"
+#include "nativescript/godot_nativescript.h"
#include "class_db.h"
#include "error_macros.h"
-#include "gdnative.h"
+#include "gdnative/gdnative.h"
#include "global_constants.h"
#include "project_settings.h"
#include "variant.h"
+#include "nativescript.h"
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/modules/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp
index e141080687..b9bd65af53 100644
--- a/modules/nativescript/nativescript.cpp
+++ b/modules/gdnative/nativescript/nativescript.cpp
@@ -29,7 +29,7 @@
/*************************************************************************/
#include "nativescript.h"
-#include "modules/gdnative/godot/gdnative.h"
+#include "gdnative/gdnative.h"
#include "global_constants.h"
#include "io/file_access_encrypted.h"
@@ -315,7 +315,7 @@ void NativeScript::get_script_signal_list(List<MethodInfo> *r_signals) const {
bool NativeScript::get_property_default_value(const StringName &p_property, Variant &r_value) const {
NativeScriptDesc *script_data = get_script_desc();
- Map<StringName, NativeScriptDesc::Property>::Element *P = NULL;
+ OrderedHashMap<StringName, NativeScriptDesc::Property>::Element P;
while (!P && script_data) {
P = script_data->properties.find(p_property);
script_data = script_data->base_data;
@@ -323,7 +323,7 @@ bool NativeScript::get_property_default_value(const StringName &p_property, Vari
if (!P)
return false;
- r_value = P->get().default_value;
+ r_value = P.get().default_value;
return true;
}
@@ -355,23 +355,20 @@ void NativeScript::get_script_method_list(List<MethodInfo> *p_list) const {
void NativeScript::get_script_property_list(List<PropertyInfo> *p_list) const {
NativeScriptDesc *script_data = get_script_desc();
- if (!script_data)
- return;
-
- Set<PropertyInfo> properties;
-
+ Set<StringName> existing_properties;
while (script_data) {
-
- for (Map<StringName, NativeScriptDesc::Property>::Element *E = script_data->properties.front(); E; E = E->next()) {
- properties.insert(E->get().info);
+ List<PropertyInfo>::Element *insert_position = p_list->front();
+ bool insert_before = true;
+
+ for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.front(); E; E = E.next()) {
+ if (!existing_properties.has(E.key())) {
+ insert_position = insert_before ? p_list->insert_before(insert_position, E.get().info) : p_list->insert_after(insert_position, E.get().info);
+ insert_before = false;
+ existing_properties.insert(E.key());
+ }
}
-
script_data = script_data->base_data;
}
-
- for (Set<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
- p_list->push_back(E->get());
- }
}
Variant NativeScript::_new(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
@@ -461,10 +458,10 @@ bool NativeScriptInstance::set(const StringName &p_name, const Variant &p_value)
NativeScriptDesc *script_data = GET_SCRIPT_DESC();
while (script_data) {
- Map<StringName, NativeScriptDesc::Property>::Element *P = script_data->properties.find(p_name);
+ OrderedHashMap<StringName, NativeScriptDesc::Property>::Element P = script_data->properties.find(p_name);
if (P) {
- P->get().setter.set_func((godot_object *)owner,
- P->get().setter.method_data,
+ P.get().setter.set_func((godot_object *)owner,
+ P.get().setter.method_data,
userdata,
(godot_variant *)&p_value);
return true;
@@ -491,11 +488,11 @@ bool NativeScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
NativeScriptDesc *script_data = GET_SCRIPT_DESC();
while (script_data) {
- Map<StringName, NativeScriptDesc::Property>::Element *P = script_data->properties.find(p_name);
+ OrderedHashMap<StringName, NativeScriptDesc::Property>::Element P = script_data->properties.find(p_name);
if (P) {
godot_variant value;
- value = P->get().getter.get_func((godot_object *)owner,
- P->get().getter.method_data,
+ value = P.get().getter.get_func((godot_object *)owner,
+ P.get().getter.method_data,
userdata);
r_ret = *(Variant *)&value;
godot_variant_destroy(&value);
@@ -592,10 +589,10 @@ Variant::Type NativeScriptInstance::get_property_type(const StringName &p_name,
while (script_data) {
- Map<StringName, NativeScriptDesc::Property>::Element *P = script_data->properties.find(p_name);
+ OrderedHashMap<StringName, NativeScriptDesc::Property>::Element P = script_data->properties.find(p_name);
if (P) {
*r_is_valid = true;
- return P->get().info.type;
+ return P.get().info.type;
}
script_data = script_data->base_data;
@@ -706,9 +703,9 @@ NativeScriptInstance::RPCMode NativeScriptInstance::get_rset_mode(const StringNa
while (script_data) {
- Map<StringName, NativeScriptDesc::Property>::Element *E = script_data->properties.find(p_variable);
+ OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.find(p_variable);
if (E) {
- switch (E->get().rset_mode) {
+ switch (E.get().rset_mode) {
case GODOT_METHOD_RPC_MODE_DISABLED:
return RPC_MODE_DISABLED;
case GODOT_METHOD_RPC_MODE_REMOTE:
@@ -796,12 +793,12 @@ void NativeScriptLanguage::_unload_stuff() {
for (Map<StringName, NativeScriptDesc>::Element *C = L->get().front(); C; C = C->next()) {
// free property stuff first
- for (Map<StringName, NativeScriptDesc::Property>::Element *P = C->get().properties.front(); P; P = P->next()) {
- if (P->get().getter.free_func)
- P->get().getter.free_func(P->get().getter.method_data);
+ for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element P = C->get().properties.front(); P; P = P.next()) {
+ if (P.get().getter.free_func)
+ P.get().getter.free_func(P.get().getter.method_data);
- if (P->get().setter.free_func)
- P->get().setter.free_func(P->get().setter.method_data);
+ if (P.get().setter.free_func)
+ P.get().setter.free_func(P.get().setter.method_data);
}
// free method stuff
diff --git a/modules/nativescript/nativescript.h b/modules/gdnative/nativescript/nativescript.h
index 571a3c9cc7..bc7e850d3e 100644
--- a/modules/nativescript/nativescript.h
+++ b/modules/gdnative/nativescript/nativescript.h
@@ -32,14 +32,15 @@
#include "io/resource_loader.h"
#include "io/resource_saver.h"
+#include "ordered_hash_map.h"
#include "os/thread_safe.h"
#include "resource.h"
#include "scene/main/node.h"
#include "script_language.h"
#include "self_list.h"
-#include "godot_nativescript.h"
#include "modules/gdnative/gdnative.h"
+#include <nativescript/godot_nativescript.h>
#ifndef NO_THREADS
#include "os/mutex.h"
@@ -65,7 +66,7 @@ struct NativeScriptDesc {
};
Map<StringName, Method> methods;
- Map<StringName, Property> properties;
+ OrderedHashMap<StringName, Property> properties;
Map<StringName, Signal> signals_; // QtCreator doesn't like the name signals
StringName base;
StringName base_native_type;
diff --git a/modules/nativescript/register_types.cpp b/modules/gdnative/nativescript/register_types.cpp
index b846710ab8..b846710ab8 100644
--- a/modules/nativescript/register_types.cpp
+++ b/modules/gdnative/nativescript/register_types.cpp
diff --git a/modules/nativescript/register_types.h b/modules/gdnative/nativescript/register_types.h
index 7ac558f68f..7ac558f68f 100644
--- a/modules/nativescript/register_types.h
+++ b/modules/gdnative/nativescript/register_types.h
diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp
index 9ad05b7194..d809109987 100644
--- a/modules/gdnative/register_types.cpp
+++ b/modules/gdnative/register_types.cpp
@@ -28,12 +28,99 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "register_types.h"
+#include "gdnative/gdnative.h"
+
#include "gdnative.h"
#include "io/resource_loader.h"
#include "io/resource_saver.h"
+#include "nativescript/register_types.h"
+
+#include "core/engine.h"
#include "core/os/os.h"
+#include "core/project_settings.h"
+
+#ifdef TOOLS_ENABLED
+#include "editor/editor_node.h"
+
+// Class used to discover singleton gdnative files
+
+void actual_discoverer_handler();
+
+class GDNativeSingletonDiscover : public Object {
+ // GDCLASS(GDNativeSingletonDiscover, Object)
+
+ virtual String get_class() const {
+ // okay, this is a really dirty hack.
+ // We're overriding get_class so we can connect it to a signal
+ // This works because get_class is a virtual method, so we don't
+ // need to register a new class to ClassDB just for this one
+ // little signal.
+
+ actual_discoverer_handler();
+
+ return "Object";
+ }
+};
+
+Set<String> get_gdnative_singletons(EditorFileSystemDirectory *p_dir) {
+
+ Set<String> file_paths;
+
+ // check children
+
+ for (int i = 0; i < p_dir->get_file_count(); i++) {
+ String file_name = p_dir->get_file(i);
+ String file_type = p_dir->get_file_type(i);
+
+ if (file_type != "GDNativeLibrary") {
+ continue;
+ }
+
+ Ref<GDNativeLibrary> lib = ResourceLoader::load(p_dir->get_file_path(i));
+ if (lib.is_valid() && lib->is_singleton_gdnative()) {
+ file_paths.insert(p_dir->get_file_path(i));
+ }
+ }
+
+ // check subdirectories
+ for (int i = 0; i < p_dir->get_subdir_count(); i++) {
+ Set<String> paths = get_gdnative_singletons(p_dir->get_subdir(i));
+
+ for (Set<String>::Element *E = paths.front(); E; E = E->next()) {
+ file_paths.insert(E->get());
+ }
+ }
+
+ return file_paths;
+}
+
+void actual_discoverer_handler() {
+ EditorFileSystemDirectory *dir = EditorFileSystem::get_singleton()->get_filesystem();
+
+ Set<String> file_paths = get_gdnative_singletons(dir);
+
+ Array files;
+ files.resize(file_paths.size());
+ int i = 0;
+ for (Set<String>::Element *E = file_paths.front(); E; i++, E = E->next()) {
+ files.set(i, E->get());
+ }
+
+ ProjectSettings::get_singleton()->set("gdnative/singletons", files);
+
+ ProjectSettings::get_singleton()->save();
+}
+
+GDNativeSingletonDiscover *discoverer = NULL;
+
+void discoverer_callback() {
+ discoverer = memnew(GDNativeSingletonDiscover);
+ EditorFileSystem::get_singleton()->connect("filesystem_changed", discoverer, "get_class");
+}
+
+#endif
godot_variant cb_standard_varcall(void *handle, godot_string *p_procedure, godot_array *p_args) {
if (handle == NULL) {
@@ -62,21 +149,110 @@ godot_variant cb_standard_varcall(void *handle, godot_string *p_procedure, godot
return proc(NULL, p_args);
}
+void cb_singleton_call(
+ void *p_handle,
+ godot_string *p_proc_name,
+ void *p_data,
+ int p_num_args,
+ void **p_args,
+ void *r_return) {
+ if (p_handle == NULL) {
+ ERR_PRINT("No valid library handle, can't call singleton procedure");
+ return;
+ }
+
+ void *singleton_proc;
+ Error err = OS::get_singleton()->get_dynamic_library_symbol_handle(
+ p_handle,
+ *(String *)p_proc_name,
+ singleton_proc);
+
+ if (err != OK) {
+ return;
+ }
+
+ void (*singleton_procedure_ptr)() = (void (*)())singleton_proc;
+ singleton_procedure_ptr();
+}
+
GDNativeCallRegistry *GDNativeCallRegistry::singleton;
+Vector<Ref<GDNative> > singleton_gdnatives;
+
void register_gdnative_types() {
+#ifdef TOOLS_ENABLED
+
+ if (Engine::get_singleton()->is_editor_hint()) {
+ EditorNode::add_init_callback(discoverer_callback);
+ }
+#endif
+
ClassDB::register_class<GDNativeLibrary>();
ClassDB::register_class<GDNative>();
GDNativeCallRegistry::singleton = memnew(GDNativeCallRegistry);
GDNativeCallRegistry::singleton->register_native_call_type("standard_varcall", cb_standard_varcall);
+
+ GDNativeCallRegistry::singleton->register_native_raw_call_type("gdnative_singleton_call", cb_singleton_call);
+
+ register_nativescript_types();
+
+ // run singletons
+
+ Array singletons = ProjectSettings::get_singleton()->get("gdnative/singletons");
+
+ singleton_gdnatives.resize(singletons.size());
+
+ for (int i = 0; i < singletons.size(); i++) {
+ String path = singletons[i];
+
+ Ref<GDNativeLibrary> lib = ResourceLoader::load(path);
+
+ singleton_gdnatives[i].instance();
+ singleton_gdnatives[i]->set_library(lib);
+
+ if (!singleton_gdnatives[i]->initialize()) {
+ // Can't initialize. Don't make a native_call then
+ continue;
+ }
+
+ singleton_gdnatives[i]->call_native_raw(
+ "gdnative_singleton_call",
+ "godot_gdnative_singleton",
+ NULL,
+ 0,
+ NULL,
+ NULL);
+ }
}
void unregister_gdnative_types() {
+
+ for (int i = 0; i < singleton_gdnatives.size(); i++) {
+
+ if (singleton_gdnatives[i].is_null()) {
+ continue;
+ }
+
+ if (!singleton_gdnatives[i]->is_initialized()) {
+ continue;
+ }
+
+ singleton_gdnatives[i]->terminate();
+ }
+
+ unregister_nativescript_types();
+
memdelete(GDNativeCallRegistry::singleton);
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ memdelete(discoverer);
+ }
+#endif
+
// This is for printing out the sizes of the core types
/*
diff --git a/modules/gdscript/gd_script.h b/modules/gdscript/gd_script.h
index 6f05a4770b..5e1a8b19ac 100644
--- a/modules/gdscript/gd_script.h
+++ b/modules/gdscript/gd_script.h
@@ -389,7 +389,6 @@ public:
virtual bool can_inherit_from_file() { return true; }
virtual int find_function(const String &p_function, const String &p_code) const;
virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const;
- virtual Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { return OK; }
virtual Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint);
#ifdef TOOLS_ENABLED
virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_base_path, Object *p_owner, LookupResult &r_result);
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index 1b7a9e4061..4f7545a11d 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -396,8 +396,6 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
Map<int, List<Pair<Transform, IndexKey> > > multimesh_items;
- print_line("updating octant " + itos(p_key.x) + ", " + itos(p_key.y) + ", " + itos(p_key.z) + " cells: " + itos(g.cells.size()));
-
for (Set<IndexKey>::Element *E = g.cells.front(); E; E = E->next()) {
ERR_CONTINUE(!cell_map.has(E->get()));
@@ -464,7 +462,6 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
//update multimeshes
for (Map<int, List<Pair<Transform, IndexKey> > >::Element *E = multimesh_items.front(); E; E = E->next()) {
- print_line("multimesh item " + itos(E->key()) + " transforms " + itos(E->get().size()));
Octant::MultimeshInstance mmi;
RID mm = VS::get_singleton()->multimesh_create();
diff --git a/modules/nativescript/config.py b/modules/nativescript/config.py
deleted file mode 100644
index 9f57b9bb74..0000000000
--- a/modules/nativescript/config.py
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-def can_build(platform):
- return True
-
-
-def configure(env):
- env.use_ptrcall = True
diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h
index b2e7a6aa27..297e9e510f 100644
--- a/modules/visual_script/visual_script.h
+++ b/modules/visual_script/visual_script.h
@@ -571,7 +571,6 @@ public:
virtual bool has_named_classes() const;
virtual int find_function(const String &p_function, const String &p_code) const;
virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const;
- virtual Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { return ERR_UNAVAILABLE; }
virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const;
virtual void add_global_constant(const StringName &p_variable, const Variant &p_value);
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index 8386687c9f..37bd730d08 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -523,7 +523,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
if (Object::cast_to<VisualScriptExpression>(*node)) {
Ref<VisualScriptComment> vsc = node;
gnode->set_comment(true);
- gnode->set_resizeable(true);
+ gnode->set_resizable(true);
gnode->set_custom_minimum_size(vsc->get_size() * EDSCALE);
gnode->connect("resize_request", this, "_comment_node_resized", varray(E->get()));
}
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index 4f00966e75..a7c5d1adbb 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -37,6 +37,7 @@
#include "scene/resources/style_box.h"
#include "scene/resources/texture.h"
#include "scene/scene_string_names.h"
+#include "servers/visual/visual_server_raster.h"
#include "servers/visual_server.h"
Mutex *CanvasItemMaterial::material_mutex = NULL;
diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp
index 9590394211..6a8226c0e1 100644
--- a/scene/3d/physics_body.cpp
+++ b/scene/3d/physics_body.cpp
@@ -912,35 +912,24 @@ RigidBody::~RigidBody() {
//////////////////////////////////////////////////////
//////////////////////////
-Dictionary KinematicBody::_move(const Vector3 &p_motion) {
+Ref<KinematicCollision> KinematicBody::_move(const Vector3 &p_motion) {
Collision col;
- if (move(p_motion, col)) {
- Dictionary d;
- d["position"] = col.collision;
- d["normal"] = col.normal;
- d["local_shape"] = col.local_shape;
- d["travel"] = col.travel;
- d["remainder"] = col.remainder;
- d["collider_id"] = col.collider;
- if (col.collider) {
- d["collider"] = ObjectDB::get_instance(col.collider);
- } else {
- d["collider"] = Variant();
+ if (move_and_collide(p_motion, col)) {
+ if (motion_cache.is_null()) {
+ motion_cache.instance();
+ motion_cache->owner = this;
}
- d["collider_velocity"] = col.collider_vel;
- d["collider_shape_index"] = col.collider_shape;
- d["collider_metadata"] = col.collider_metadata;
-
- return d;
+ motion_cache->collision = col;
- } else {
- return Dictionary();
+ return motion_cache;
}
+
+ return Ref<KinematicCollision>();
}
-bool KinematicBody::move(const Vector3 &p_motion, Collision &r_collision) {
+bool KinematicBody::move_and_collide(const Vector3 &p_motion, Collision &r_collision) {
Transform gt = get_global_transform();
PhysicsServer::MotionResult result;
@@ -964,7 +953,7 @@ bool KinematicBody::move(const Vector3 &p_motion, Collision &r_collision) {
return colliding;
}
-Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction, float p_slope_stop_min_velocity, int p_max_bounces, float p_floor_max_angle) {
+Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction, float p_slope_stop_min_velocity, int p_max_slides, float p_floor_max_angle) {
Vector3 motion = (floor_velocity + p_linear_velocity) * get_fixed_process_delta_time();
Vector3 lv = p_linear_velocity;
@@ -975,11 +964,11 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve
colliders.clear();
floor_velocity = Vector3();
- while (p_max_bounces) {
+ while (p_max_slides) {
Collision collision;
- bool collided = move(motion, collision);
+ bool collided = move_and_collide(motion, collision);
if (collided) {
@@ -1017,7 +1006,7 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve
break;
}
- p_max_bounces--;
+ p_max_slides--;
if (motion == Vector3())
break;
}
@@ -1059,79 +1048,36 @@ float KinematicBody::get_safe_margin() const {
return margin;
}
-
-int KinematicBody::get_collision_count() const {
+int KinematicBody::get_slide_count() const {
return colliders.size();
}
-Vector3 KinematicBody::get_collision_position(int p_collision) const {
-
- ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector3());
- return colliders[p_collision].collision;
-}
-Vector3 KinematicBody::get_collision_normal(int p_collision) const {
- ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector3());
- return colliders[p_collision].normal;
+KinematicBody::Collision KinematicBody::get_slide_collision(int p_bounce) const {
+ ERR_FAIL_INDEX_V(p_bounce, colliders.size(), Collision());
+ return colliders[p_bounce];
}
-Vector3 KinematicBody::get_collision_travel(int p_collision) const {
- ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector3());
- return colliders[p_collision].travel;
-}
-Vector3 KinematicBody::get_collision_remainder(int p_collision) const {
- ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector3());
- return colliders[p_collision].remainder;
-}
-Object *KinematicBody::get_collision_local_shape(int p_collision) const {
- ERR_FAIL_INDEX_V(p_collision, colliders.size(), NULL);
- uint32_t owner = shape_find_owner(colliders[p_collision].local_shape);
- return shape_owner_get_owner(owner);
-}
-Object *KinematicBody::get_collision_collider(int p_collision) const {
- ERR_FAIL_INDEX_V(p_collision, colliders.size(), NULL);
+Ref<KinematicCollision> KinematicBody::_get_slide_collision(int p_bounce) {
- if (colliders[p_collision].collider) {
- return ObjectDB::get_instance(colliders[p_collision].collider);
+ ERR_FAIL_INDEX_V(p_bounce, colliders.size(), Ref<KinematicCollision>());
+ if (p_bounce > slide_colliders.size()) {
+ slide_colliders.resize(p_bounce + 1);
}
- return NULL;
-}
-ObjectID KinematicBody::get_collision_collider_id(int p_collision) const {
- ERR_FAIL_INDEX_V(p_collision, colliders.size(), 0);
-
- return colliders[p_collision].collider;
-}
-Object *KinematicBody::get_collision_collider_shape(int p_collision) const {
- ERR_FAIL_INDEX_V(p_collision, colliders.size(), NULL);
- Object *collider = get_collision_collider(p_collision);
- if (collider) {
- CollisionObject *obj2d = Object::cast_to<CollisionObject>(collider);
- if (obj2d) {
- uint32_t owner = shape_find_owner(colliders[p_collision].collider_shape);
- return obj2d->shape_owner_get_owner(owner);
- }
+ if (slide_colliders[p_bounce].is_null()) {
+ slide_colliders[p_bounce].instance();
+ slide_colliders[p_bounce]->owner = this;
}
- return NULL;
-}
-int KinematicBody::get_collision_collider_shape_index(int p_collision) const {
- ERR_FAIL_INDEX_V(p_collision, colliders.size(), -1);
- return colliders[p_collision].collider_shape;
-}
-Vector3 KinematicBody::get_collision_collider_velocity(int p_collision) const {
- ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector3());
- return colliders[p_collision].collider_vel;
-}
-Variant KinematicBody::get_collision_collider_metadata(int p_collision) const {
- ERR_FAIL_INDEX_V(p_collision, colliders.size(), Variant());
- return colliders[p_collision].collider_metadata;
+ slide_colliders[p_bounce]->collision = colliders[p_bounce];
+ return slide_colliders[p_bounce];
}
void KinematicBody::_bind_methods() {
- ClassDB::bind_method(D_METHOD("move", "rel_vec"), &KinematicBody::_move);
- ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "slope_stop_min_velocity", "max_bounces", "floor_max_angle"), &KinematicBody::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(0.05), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)));
+ ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec"), &KinematicBody::_move);
+ ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "slope_stop_min_velocity", "max_slides", "floor_max_angle"), &KinematicBody::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(0.05), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)));
ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec"), &KinematicBody::test_move);
@@ -1143,18 +1089,8 @@ void KinematicBody::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_safe_margin", "pixels"), &KinematicBody::set_safe_margin);
ClassDB::bind_method(D_METHOD("get_safe_margin"), &KinematicBody::get_safe_margin);
- ClassDB::bind_method(D_METHOD("get_collision_count"), &KinematicBody::get_collision_count);
- ClassDB::bind_method(D_METHOD("get_collision_position", "collision"), &KinematicBody::get_collision_position);
- ClassDB::bind_method(D_METHOD("get_collision_normal", "collision"), &KinematicBody::get_collision_normal);
- ClassDB::bind_method(D_METHOD("get_collision_travel", "collision"), &KinematicBody::get_collision_travel);
- ClassDB::bind_method(D_METHOD("get_collision_remainder", "collision"), &KinematicBody::get_collision_remainder);
- ClassDB::bind_method(D_METHOD("get_collision_local_shape", "collision"), &KinematicBody::get_collision_local_shape);
- ClassDB::bind_method(D_METHOD("get_collision_collider", "collision"), &KinematicBody::get_collision_collider);
- ClassDB::bind_method(D_METHOD("get_collision_collider_id", "collision"), &KinematicBody::get_collision_collider_id);
- ClassDB::bind_method(D_METHOD("get_collision_collider_shape", "collision"), &KinematicBody::get_collision_collider_shape);
- ClassDB::bind_method(D_METHOD("get_collision_collider_shape_index", "collision"), &KinematicBody::get_collision_collider_shape_index);
- ClassDB::bind_method(D_METHOD("get_collision_collider_velocity", "collision"), &KinematicBody::get_collision_collider_velocity);
- ClassDB::bind_method(D_METHOD("get_collision_collider_metadata", "collision"), &KinematicBody::get_collision_collider_metadata);
+ ClassDB::bind_method(D_METHOD("get_slide_count"), &KinematicBody::get_slide_count);
+ ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &KinematicBody::_get_slide_collision);
ADD_PROPERTY(PropertyInfo(Variant::REAL, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin");
}
@@ -1169,4 +1105,106 @@ KinematicBody::KinematicBody()
on_wall = false;
}
KinematicBody::~KinematicBody() {
+
+ if (motion_cache.is_valid()) {
+ motion_cache->owner = NULL;
+ }
+
+ for (int i = 0; i < slide_colliders.size(); i++) {
+ if (slide_colliders[i].is_valid()) {
+ slide_colliders[i]->owner = NULL;
+ }
+ }
+}
+///////////////////////////////////////
+
+Vector3 KinematicCollision::get_position() const {
+
+ return collision.collision;
+}
+Vector3 KinematicCollision::get_normal() const {
+ return collision.normal;
+}
+Vector3 KinematicCollision::get_travel() const {
+ return collision.travel;
+}
+Vector3 KinematicCollision::get_remainder() const {
+ return collision.remainder;
+}
+Object *KinematicCollision::get_local_shape() const {
+ ERR_FAIL_COND_V(!owner, NULL);
+ uint32_t ownerid = owner->shape_find_owner(collision.local_shape);
+ return owner->shape_owner_get_owner(ownerid);
+}
+
+Object *KinematicCollision::get_collider() const {
+
+ if (collision.collider) {
+ return ObjectDB::get_instance(collision.collider);
+ }
+
+ return NULL;
+}
+ObjectID KinematicCollision::get_collider_id() const {
+
+ return collision.collider;
+}
+Object *KinematicCollision::get_collider_shape() const {
+
+ Object *collider = get_collider();
+ if (collider) {
+ CollisionObject *obj2d = Object::cast_to<CollisionObject>(collider);
+ if (obj2d) {
+ uint32_t ownerid = obj2d->shape_find_owner(collision.collider_shape);
+ return obj2d->shape_owner_get_owner(ownerid);
+ }
+ }
+
+ return NULL;
+}
+int KinematicCollision::get_collider_shape_index() const {
+
+ return collision.collider_shape;
+}
+Vector3 KinematicCollision::get_collider_velocity() const {
+
+ return collision.collider_vel;
+}
+Variant KinematicCollision::get_collider_metadata() const {
+
+ return Variant();
+}
+
+void KinematicCollision::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("get_position"), &KinematicCollision::get_position);
+ ClassDB::bind_method(D_METHOD("get_normal"), &KinematicCollision::get_normal);
+ ClassDB::bind_method(D_METHOD("get_travel"), &KinematicCollision::get_travel);
+ ClassDB::bind_method(D_METHOD("get_remainder"), &KinematicCollision::get_remainder);
+ ClassDB::bind_method(D_METHOD("get_local_shape"), &KinematicCollision::get_local_shape);
+ ClassDB::bind_method(D_METHOD("get_collider"), &KinematicCollision::get_collider);
+ ClassDB::bind_method(D_METHOD("get_collider_id"), &KinematicCollision::get_collider_id);
+ ClassDB::bind_method(D_METHOD("get_collider_shape"), &KinematicCollision::get_collider_shape);
+ ClassDB::bind_method(D_METHOD("get_collider_shape_index"), &KinematicCollision::get_collider_shape_index);
+ ClassDB::bind_method(D_METHOD("get_collider_velocity"), &KinematicCollision::get_collider_velocity);
+ ClassDB::bind_method(D_METHOD("get_collider_metadata"), &KinematicCollision::get_collider_metadata);
+
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position"), "", "get_position");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "normal"), "", "get_normal");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "travel"), "", "get_travel");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "remainder"), "", "get_remainder");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "local_shape"), "", "get_local_shape");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "collider"), "", "get_collider");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_id"), "", "get_collider_id");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "collider_shape"), "", "get_collider_shape");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_shape_index"), "", "get_collider_shape_index");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "collider_velocity"), "", "get_collider_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::NIL, "collider_metadata", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "", "get_collider_metadata");
+}
+
+KinematicCollision::KinematicCollision() {
+ collision.collider = 0;
+ collision.collider_shape = 0;
+ collision.local_shape = 0;
+ owner = NULL;
}
diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h
index 23d752ad76..f88b3860dc 100644
--- a/scene/3d/physics_body.h
+++ b/scene/3d/physics_body.h
@@ -261,6 +261,8 @@ public:
VARIANT_ENUM_CAST(RigidBody::Mode);
VARIANT_ENUM_CAST(RigidBody::AxisLock);
+class KinematicCollision;
+
class KinematicBody : public PhysicsBody {
GDCLASS(KinematicBody, PhysicsBody);
@@ -286,42 +288,62 @@ private:
bool on_ceiling;
bool on_wall;
Vector<Collision> colliders;
+ Vector<Ref<KinematicCollision> > slide_colliders;
+ Ref<KinematicCollision> motion_cache;
_FORCE_INLINE_ bool _ignores_mode(PhysicsServer::BodyMode) const;
- Dictionary _move(const Vector3 &p_motion);
+ Ref<KinematicCollision> _move(const Vector3 &p_motion);
+ Ref<KinematicCollision> _get_slide_collision(int p_bounce);
protected:
static void _bind_methods();
public:
- bool move(const Vector3 &p_motion, Collision &r_collision);
+ bool move_and_collide(const Vector3 &p_motion, Collision &r_collision);
bool test_move(const Transform &p_from, const Vector3 &p_motion);
void set_safe_margin(float p_margin);
float get_safe_margin() const;
- Vector3 move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction = Vector3(0, 0, 0), float p_slope_stop_min_velocity = 0.05, int p_max_bounces = 4, float p_floor_max_angle = Math::deg2rad((float)45));
+ Vector3 move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction = Vector3(0, 0, 0), float p_slope_stop_min_velocity = 0.05, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45));
bool is_on_floor() const;
bool is_on_wall() const;
bool is_on_ceiling() const;
Vector3 get_floor_velocity() const;
- int get_collision_count() const;
- Vector3 get_collision_position(int p_collision) const;
- Vector3 get_collision_normal(int p_collision) const;
- Vector3 get_collision_travel(int p_collision) const;
- Vector3 get_collision_remainder(int p_collision) const;
- Object *get_collision_local_shape(int p_collision) const;
- Object *get_collision_collider(int p_collision) const;
- ObjectID get_collision_collider_id(int p_collision) const;
- Object *get_collision_collider_shape(int p_collision) const;
- int get_collision_collider_shape_index(int p_collision) const;
- Vector3 get_collision_collider_velocity(int p_collision) const;
- Variant get_collision_collider_metadata(int p_collision) const;
+ int get_slide_count() const;
+ Collision get_slide_collision(int p_bounce) const;
KinematicBody();
~KinematicBody();
};
+class KinematicCollision : public Reference {
+
+ GDCLASS(KinematicCollision, Reference);
+
+ KinematicBody *owner;
+ friend class KinematicBody;
+ KinematicBody::Collision collision;
+
+protected:
+ static void _bind_methods();
+
+public:
+ Vector3 get_position() const;
+ Vector3 get_normal() const;
+ Vector3 get_travel() const;
+ Vector3 get_remainder() const;
+ Object *get_local_shape() const;
+ Object *get_collider() const;
+ ObjectID get_collider_id() const;
+ Object *get_collider_shape() const;
+ int get_collider_shape_index() const;
+ Vector3 get_collider_velocity() const;
+ Variant get_collider_metadata() const;
+
+ KinematicCollision();
+};
+
#endif // PHYSICS_BODY__H
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index 8fd19e8655..5713a35b7a 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -87,14 +87,14 @@ void BaseButton::_gui_input(Ref<InputEvent> p_event) {
status.pressed = !status.pressed;
pressed();
- if (get_script_instance()) {
- Variant::CallError ce;
- get_script_instance()->call(SceneStringNames::get_singleton()->_pressed, NULL, 0, ce);
- }
+
emit_signal("pressed");
_unpress_group();
toggled(status.pressed);
+ if (get_script_instance()) {
+ get_script_instance()->call(SceneStringNames::get_singleton()->_toggled, status.pressed);
+ }
emit_signal("toggled", status.pressed);
}
@@ -143,10 +143,10 @@ void BaseButton::_gui_input(Ref<InputEvent> p_event) {
emit_signal("pressed");
toggled(status.pressed);
- emit_signal("toggled", status.pressed);
if (get_script_instance()) {
get_script_instance()->call(SceneStringNames::get_singleton()->_toggled, status.pressed);
}
+ emit_signal("toggled", status.pressed);
}
_unpress_group();
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 8730be0c06..bef0808fd0 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -270,7 +270,7 @@ void GraphNode::_notification(int p_what) {
}
}
- if (resizeable) {
+ if (resizable) {
draw_texture(resizer, get_size() - resizer->get_size());
}
}
@@ -594,7 +594,7 @@ void GraphNode::_gui_input(const Ref<InputEvent> &p_ev) {
Ref<Texture> resizer = get_icon("resizer");
- if (resizeable && mpos.x > get_size().x - resizer->get_width() && mpos.y > get_size().y - resizer->get_height()) {
+ if (resizable && mpos.x > get_size().x - resizer->get_width() && mpos.y > get_size().y - resizer->get_height()) {
resizing = true;
resizing_from = mpos;
@@ -645,15 +645,15 @@ bool GraphNode::is_comment() const {
return comment;
}
-void GraphNode::set_resizeable(bool p_enable) {
+void GraphNode::set_resizable(bool p_enable) {
- resizeable = p_enable;
+ resizable = p_enable;
update();
}
-bool GraphNode::is_resizeable() const {
+bool GraphNode::is_resizable() const {
- return resizeable;
+ return resizable;
}
void GraphNode::_bind_methods() {
@@ -678,8 +678,8 @@ void GraphNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_comment", "comment"), &GraphNode::set_comment);
ClassDB::bind_method(D_METHOD("is_comment"), &GraphNode::is_comment);
- ClassDB::bind_method(D_METHOD("set_resizeable", "resizeable"), &GraphNode::set_resizeable);
- ClassDB::bind_method(D_METHOD("is_resizeable"), &GraphNode::is_resizeable);
+ ClassDB::bind_method(D_METHOD("set_resizable", "resizable"), &GraphNode::set_resizable);
+ ClassDB::bind_method(D_METHOD("is_resizable"), &GraphNode::is_resizable);
ClassDB::bind_method(D_METHOD("set_selected", "selected"), &GraphNode::set_selected);
ClassDB::bind_method(D_METHOD("is_selected"), &GraphNode::is_selected);
@@ -702,7 +702,7 @@ void GraphNode::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_close"), "set_show_close_button", "is_close_button_visible");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "resizeable"), "set_resizeable", "is_resizeable");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "resizable"), "set_resizable", "is_resizable");
ADD_SIGNAL(MethodInfo("offset_changed"));
ADD_SIGNAL(MethodInfo("dragged", PropertyInfo(Variant::VECTOR2, "from"), PropertyInfo(Variant::VECTOR2, "to")));
@@ -722,7 +722,7 @@ GraphNode::GraphNode() {
connpos_dirty = true;
set_mouse_filter(MOUSE_FILTER_STOP);
comment = false;
- resizeable = false;
+ resizable = false;
resizing = false;
selected = false;
}
diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h
index 416d711aab..a606e47acd 100644
--- a/scene/gui/graph_node.h
+++ b/scene/gui/graph_node.h
@@ -68,7 +68,7 @@ private:
bool show_close;
Vector2 offset;
bool comment;
- bool resizeable;
+ bool resizable;
bool resizing;
Vector2 resizing_from;
@@ -151,8 +151,8 @@ public:
void set_comment(bool p_enable);
bool is_comment() const;
- void set_resizeable(bool p_enable);
- bool is_resizeable() const;
+ void set_resizable(bool p_enable);
+ bool is_resizable() const;
virtual Size2 get_minimum_size() const;
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index f8d82a339c..9a605c98f3 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -151,6 +151,20 @@ Color ItemList::get_item_custom_bg_color(int p_idx) const {
return items[p_idx].custom_bg;
}
+void ItemList::set_item_custom_fg_color(int p_idx, const Color &p_custom_fg_color) {
+
+ ERR_FAIL_INDEX(p_idx, items.size());
+
+ items[p_idx].custom_fg = p_custom_fg_color;
+}
+
+Color ItemList::get_item_custom_fg_color(int p_idx) const {
+
+ ERR_FAIL_INDEX_V(p_idx, items.size(), Color());
+
+ return items[p_idx].custom_fg;
+}
+
void ItemList::set_item_tag_icon(int p_idx, const Ref<Texture> &p_tag_icon) {
ERR_FAIL_INDEX(p_idx, items.size());
@@ -1021,7 +1035,7 @@ void ItemList::_notification(int p_what) {
else
max_len = size.x;
- Color modulate = items[i].selected ? font_color_selected : font_color;
+ Color modulate = items[i].selected ? font_color_selected : (items[i].custom_fg != Color() ? items[i].custom_fg : font_color);
if (items[i].disabled)
modulate.a *= 0.5;
diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h
index 8166975408..673b7d8956 100644
--- a/scene/gui/item_list.h
+++ b/scene/gui/item_list.h
@@ -61,6 +61,7 @@ private:
bool tooltip_enabled;
Variant metadata;
String tooltip;
+ Color custom_fg;
Color custom_bg;
Rect2 rect_cache;
@@ -150,6 +151,9 @@ public:
void set_item_custom_bg_color(int p_idx, const Color &p_custom_bg_color);
Color get_item_custom_bg_color(int p_idx) const;
+ void set_item_custom_fg_color(int p_idx, const Color &p_custom_fg_color);
+ Color get_item_custom_fg_color(int p_idx) const;
+
void select(int p_idx, bool p_single = true);
void unselect(int p_idx);
bool is_selected(int p_idx) const;
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 66b4e6cec1..6a5f56c78c 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -631,7 +631,7 @@ void LineEdit::_notification(int p_what) {
if (has_icon("right_icon")) {
Ref<Texture> r_icon = Control::get_icon("right_icon");
ofs_max -= r_icon->get_width();
- r_icon->draw(ci, Point2(width - r_icon->get_width() - x_ofs, y_ofs), Color(1, 1, 1, disabled_alpha * .9));
+ r_icon->draw(ci, Point2(width - r_icon->get_width() - x_ofs, height / 2 - r_icon->get_height() / 2), Color(1, 1, 1, disabled_alpha * .9));
}
int caret_height = font->get_height() > y_area ? y_area : font->get_height();
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index a3f116c883..ab2c2f445f 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -80,6 +80,10 @@ RichTextLabel::Item *RichTextLabel::_get_next_item(Item *p_item, bool p_free) {
return NULL;
}
+Rect2 RichTextLabel::_get_text_rect() {
+ Ref<StyleBox> style = get_stylebox("normal");
+ return Rect2(style->get_offset(), get_size() - style->get_minimum_size());
+}
void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &y, int p_width, int p_line, ProcessMode p_mode, const Ref<Font> &p_base_font, const Color &p_base_color, const Point2i &p_click_pos, Item **r_click_item, int *r_click_char, bool *r_outside, int p_char_count) {
RID ci;
@@ -583,7 +587,7 @@ void RichTextLabel::_update_scroll() {
int total_height = 0;
if (main->lines.size())
- total_height = main->lines[main->lines.size() - 1].height_accum_cache;
+ total_height = main->lines[main->lines.size() - 1].height_accum_cache + get_stylebox("normal")->get_minimum_size().height;
bool exceeds = total_height > get_size().height && scroll_active;
@@ -641,7 +645,11 @@ void RichTextLabel::_notification(int p_what) {
_update_scroll();
RID ci = get_canvas_item();
+
Size2 size = get_size();
+ Rect2 text_rect = _get_text_rect();
+
+ draw_style_box(get_stylebox("normal"), Rect2(Point2(), size));
if (has_focus()) {
VisualServer::get_singleton()->canvas_item_add_clip_ignore(ci, true);
@@ -657,10 +665,10 @@ void RichTextLabel::_notification(int p_what) {
int total_chars = 0;
while (from_line < main->lines.size()) {
- if (main->lines[from_line].height_accum_cache >= ofs)
+ if (main->lines[from_line].height_accum_cache + _get_text_rect().get_position().y >= ofs)
break;
- from_line++;
total_chars += main->lines[from_line].char_count;
+ from_line++;
}
if (from_line >= main->lines.size())
@@ -672,7 +680,7 @@ void RichTextLabel::_notification(int p_what) {
while (y < size.height && from_line < main->lines.size()) {
- _process_line(main, Point2(), y, size.width - scroll_w, from_line, PROCESS_DRAW, base_font, base_color, Point2i(), NULL, NULL, NULL, total_chars);
+ _process_line(main, text_rect.get_position(), y, text_rect.get_size().width - scroll_w, from_line, PROCESS_DRAW, base_font, base_color, Point2i(), NULL, NULL, NULL, total_chars);
total_chars += main->lines[from_line].char_count;
from_line++;
}
@@ -686,7 +694,7 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item
*r_click_item = NULL;
Size2 size = get_size();
-
+ Rect2 text_rect = _get_text_rect();
int ofs = vscroll->get_value();
//todo, change to binary search
@@ -706,9 +714,9 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item
Ref<Font> base_font = get_font("normal_font");
Color base_color = get_color("default_color");
- while (y < size.height && from_line < p_frame->lines.size()) {
+ while (y < text_rect.get_size().height && from_line < p_frame->lines.size()) {
- _process_line(p_frame, Point2(), y, size.width - scroll_w, from_line, PROCESS_POINTER, base_font, base_color, p_click, r_click_item, r_click_char, r_outside);
+ _process_line(p_frame, text_rect.get_position(), y, text_rect.get_size().width - scroll_w, from_line, PROCESS_POINTER, base_font, base_color, p_click, r_click_item, r_click_char, r_outside);
if (r_click_item && *r_click_item)
return;
from_line++;
@@ -791,7 +799,7 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) {
Ref<InputEventKey> k = p_event;
if (k.is_valid()) {
- if (k->is_pressed() && !k->get_alt() && !k->get_shift() && !k->get_metakey()) {
+ if (k->is_pressed() && !k->get_alt() && !k->get_shift()) {
bool handled = true;
switch (k->get_scancode()) {
case KEY_PAGEUP: {
@@ -1015,13 +1023,14 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) {
//validate invalid lines!s
Size2 size = get_size();
+ Rect2 text_rect = _get_text_rect();
Ref<Font> base_font = get_font("normal_font");
for (int i = p_frame->first_invalid_line; i < p_frame->lines.size(); i++) {
int y = 0;
- _process_line(p_frame, Point2(), y, size.width - scroll_w, i, PROCESS_CACHE, base_font, Color());
+ _process_line(p_frame, text_rect.get_position(), y, text_rect.get_size().width - scroll_w, i, PROCESS_CACHE, base_font, Color());
p_frame->lines[i].height_cache = y;
p_frame->lines[i].height_accum_cache = y;
@@ -1031,7 +1040,7 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) {
int total_height = 0;
if (p_frame->lines.size())
- total_height = p_frame->lines[p_frame->lines.size() - 1].height_accum_cache;
+ total_height = p_frame->lines[p_frame->lines.size() - 1].height_accum_cache + get_stylebox("normal")->get_minimum_size().height;
main->first_invalid_line = p_frame->lines.size();
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index 74bf180b5d..4db2c3a8e9 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -276,6 +276,8 @@ private:
void _gui_input(Ref<InputEvent> p_event);
Item *_get_next_item(Item *p_item, bool p_free = false);
+ Rect2 _get_text_rect();
+
bool use_bbcode;
String bbcode;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index ade665b418..1738e303aa 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -2136,15 +2136,25 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
break;
}
}
- if (auto_indent) {
- // indent once again if previous line will end with ':'
- // (i.e. colon precedes current cursor position)
- if (cursor.column > 0 && text[cursor.line][cursor.column - 1] == ':') {
+
+ bool brace_indent = false;
+
+ // no need to indent if we are going upwards.
+ if (auto_indent && !(k->get_command() && k->get_shift())) {
+ // indent once again if previous line will end with ':' or '{'
+ // (i.e. colon/brace precedes current cursor position)
+ if (cursor.column > 0 && (text[cursor.line][cursor.column - 1] == ':' || text[cursor.line][cursor.column - 1] == '{')) {
if (indent_using_spaces) {
ins += space_indent;
} else {
ins += "\t";
}
+
+ // no need to move the brace below if we are not taking the text with us.
+ if (text[cursor.line][cursor.column] == '}' && !k->get_command()) {
+ brace_indent = true;
+ ins += "\n" + ins.substr(1, ins.length() - 2);
+ }
}
}
@@ -2168,6 +2178,9 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (first_line) {
cursor_set_line(0);
+ } else if (brace_indent) {
+ cursor_set_line(cursor.line - 1);
+ cursor_set_column(text[cursor.line].length());
}
} break;
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 5e15bceb7d..de17416d8e 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -1116,7 +1116,8 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
cache.selected->draw(ci, r);
}
if (text_editor->is_visible_in_tree()) {
- text_editor->set_position(get_global_position() + r.position);
+ Vector2 ofs(0, (text_editor->get_size().height - r.size.height) / 2);
+ text_editor->set_position(get_global_position() + r.position - ofs);
}
}
@@ -2572,7 +2573,8 @@ bool Tree::edit_selected() {
} else if (c.mode == TreeItem::CELL_MODE_STRING || c.mode == TreeItem::CELL_MODE_RANGE || c.mode == TreeItem::CELL_MODE_RANGE_EXPRESSION) {
- Point2i textedpos = get_global_position() + rect.position;
+ Vector2 ofs(0, (text_editor->get_size().height - rect.size.height) / 2);
+ Point2i textedpos = get_global_position() + rect.position - ofs;
text_editor->set_position(textedpos);
text_editor->set_size(rect.size);
text_editor->clear();
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index e01f5e3cdf..69c17f4912 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -378,6 +378,7 @@ void register_scene_types() {
ClassDB::register_virtual_class<CollisionObject>();
ClassDB::register_class<StaticBody>();
ClassDB::register_class<RigidBody>();
+ ClassDB::register_class<KinematicCollision>();
ClassDB::register_class<KinematicBody>();
ClassDB::register_class<VehicleBody>();
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 4ff635edeb..fdea5960e5 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -794,6 +794,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
// RichTextLabel
theme->set_stylebox("focus", "RichTextLabel", focus);
+ theme->set_stylebox("normal", "RichTextLabel", make_stylebox(tree_bg_png, 3, 3, 3, 3));
theme->set_font("normal_font", "RichTextLabel", default_font);
theme->set_font("bold_font", "RichTextLabel", default_font);
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 3d6a10ffc7..a187692bcb 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -65,6 +65,12 @@ RID Material::get_rid() const {
return material;
}
+void Material::_validate_property(PropertyInfo &property) const {
+
+ if (!_can_do_next_pass() && property.name=="next_pass") {
+ property.usage=0;
+ }
+}
void Material::_bind_methods() {
@@ -204,6 +210,11 @@ void ShaderMaterial::get_argument_options(const StringName &p_function, int p_id
Resource::get_argument_options(p_function, p_idx, r_options);
}
+bool ShaderMaterial::_can_do_next_pass() const {
+
+ return shader.is_valid() && shader->get_mode()==Shader::MODE_SPATIAL;
+}
+
ShaderMaterial::ShaderMaterial() {
}
diff --git a/scene/resources/material.h b/scene/resources/material.h
index 4e77ab1ed6..fdb11982a8 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -53,6 +53,9 @@ class Material : public Resource {
protected:
_FORCE_INLINE_ RID _get_material() const { return material; }
static void _bind_methods();
+ virtual bool _can_do_next_pass() const { return false; }
+
+ void _validate_property(PropertyInfo &property) const;
public:
enum {
@@ -84,6 +87,8 @@ protected:
void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const;
+ virtual bool _can_do_next_pass() const;
+
public:
void set_shader(const Ref<Shader> &p_shader);
Ref<Shader> get_shader() const;
@@ -394,6 +399,7 @@ private:
protected:
static void _bind_methods();
void _validate_property(PropertyInfo &property) const;
+ virtual bool _can_do_next_pass() const { return true; }
public:
void set_albedo(const Color &p_albedo);
diff --git a/scene/resources/mesh_library.cpp b/scene/resources/mesh_library.cpp
index 4e1ffd2ab3..833a4c3d22 100644
--- a/scene/resources/mesh_library.cpp
+++ b/scene/resources/mesh_library.cpp
@@ -214,7 +214,7 @@ Vector<int> MeshLibrary::get_item_list() const {
return ret;
}
-int MeshLibrary::find_item_name(const String &p_name) const {
+int MeshLibrary::find_item_by_name(const String &p_name) const {
for (Map<int, Item>::Element *E = item_map.front(); E; E = E->next()) {
@@ -275,6 +275,8 @@ void MeshLibrary::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_item_shapes", "id"), &MeshLibrary::_get_item_shapes);
ClassDB::bind_method(D_METHOD("get_item_preview", "id"), &MeshLibrary::get_item_preview);
ClassDB::bind_method(D_METHOD("remove_item", "id"), &MeshLibrary::remove_item);
+ ClassDB::bind_method(D_METHOD("find_item_by_name", "name"), &MeshLibrary::find_item_by_name);
+
ClassDB::bind_method(D_METHOD("clear"), &MeshLibrary::clear);
ClassDB::bind_method(D_METHOD("get_item_list"), &MeshLibrary::get_item_list);
ClassDB::bind_method(D_METHOD("get_last_unused_item_id"), &MeshLibrary::get_last_unused_item_id);
diff --git a/scene/resources/mesh_library.h b/scene/resources/mesh_library.h
index 99b6b48d61..c5d23ce50f 100644
--- a/scene/resources/mesh_library.h
+++ b/scene/resources/mesh_library.h
@@ -84,7 +84,7 @@ public:
void clear();
- int find_item_name(const String &p_name) const;
+ int find_item_by_name(const String &p_name) const;
Vector<int> get_item_list() const;
int get_last_unused_item_id() const;
diff --git a/servers/physics/collision_object_sw.cpp b/servers/physics/collision_object_sw.cpp
index ab716a8f6e..3af8b542fa 100644
--- a/servers/physics/collision_object_sw.cpp
+++ b/servers/physics/collision_object_sw.cpp
@@ -28,6 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "collision_object_sw.h"
+#include "servers/physics/physics_server_sw.h"
#include "space_sw.h"
void CollisionObjectSW::add_shape(ShapeSW *p_shape, const Transform &p_transform) {
@@ -39,8 +40,12 @@ void CollisionObjectSW::add_shape(ShapeSW *p_shape, const Transform &p_transform
s.bpid = 0; //needs update
shapes.push_back(s);
p_shape->add_owner(this);
- _update_shapes();
- _shapes_changed();
+
+ if (!pending_shape_update_list.in_list()) {
+ PhysicsServerSW::singleton->pending_shape_update_list.add(&pending_shape_update_list);
+ }
+ //_update_shapes();
+ //_shapes_changed();
}
void CollisionObjectSW::set_shape(int p_index, ShapeSW *p_shape) {
@@ -50,8 +55,11 @@ void CollisionObjectSW::set_shape(int p_index, ShapeSW *p_shape) {
shapes[p_index].shape = p_shape;
p_shape->add_owner(this);
- _update_shapes();
- _shapes_changed();
+ if (!pending_shape_update_list.in_list()) {
+ PhysicsServerSW::singleton->pending_shape_update_list.add(&pending_shape_update_list);
+ }
+ //_update_shapes();
+ //_shapes_changed();
}
void CollisionObjectSW::set_shape_transform(int p_index, const Transform &p_transform) {
@@ -59,8 +67,11 @@ void CollisionObjectSW::set_shape_transform(int p_index, const Transform &p_tran
shapes[p_index].xform = p_transform;
shapes[p_index].xform_inv = p_transform.affine_inverse();
- _update_shapes();
- _shapes_changed();
+ if (!pending_shape_update_list.in_list()) {
+ PhysicsServerSW::singleton->pending_shape_update_list.add(&pending_shape_update_list);
+ }
+ //_update_shapes();
+ //_shapes_changed();
}
void CollisionObjectSW::remove_shape(ShapeSW *p_shape) {
@@ -90,7 +101,11 @@ void CollisionObjectSW::remove_shape(int p_index) {
shapes[p_index].shape->remove_owner(this);
shapes.remove(p_index);
- _shapes_changed();
+ if (!pending_shape_update_list.in_list()) {
+ PhysicsServerSW::singleton->pending_shape_update_list.add(&pending_shape_update_list);
+ }
+ //_update_shapes();
+ //_shapes_changed();
}
void CollisionObjectSW::_set_static(bool p_static) {
@@ -202,7 +217,8 @@ void CollisionObjectSW::_shape_changed() {
_shapes_changed();
}
-CollisionObjectSW::CollisionObjectSW(Type p_type) {
+CollisionObjectSW::CollisionObjectSW(Type p_type)
+ : pending_shape_update_list(this) {
_static = true;
type = p_type;
diff --git a/servers/physics/collision_object_sw.h b/servers/physics/collision_object_sw.h
index dc988aae86..67a8a44944 100644
--- a/servers/physics/collision_object_sw.h
+++ b/servers/physics/collision_object_sw.h
@@ -75,6 +75,8 @@ private:
Transform inv_transform;
bool _static;
+ SelfList<CollisionObjectSW> pending_shape_update_list;
+
void _update_shapes();
protected:
diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp
index 8d6f7b3fd8..2d46770924 100644
--- a/servers/physics/physics_server_sw.cpp
+++ b/servers/physics/physics_server_sw.cpp
@@ -763,6 +763,8 @@ void PhysicsServerSW::body_apply_impulse(RID p_body, const Vector3 &p_pos, const
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
+ _update_shapes();
+
body->apply_impulse(p_pos, p_impulse);
body->wakeup();
};
@@ -772,6 +774,8 @@ void PhysicsServerSW::body_apply_torque_impulse(RID p_body, const Vector3 &p_imp
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
+ _update_shapes();
+
body->apply_torque_impulse(p_impulse);
body->wakeup();
};
@@ -781,6 +785,8 @@ void PhysicsServerSW::body_set_axis_velocity(RID p_body, const Vector3 &p_axis_v
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
+ _update_shapes();
+
Vector3 v = body->get_linear_velocity();
Vector3 axis = p_axis_velocity.normalized();
v -= axis * axis.dot(v);
@@ -793,6 +799,7 @@ 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);
body->wakeup();
}
@@ -902,6 +909,8 @@ bool PhysicsServerSW::body_test_motion(RID p_body, const Transform &p_from, cons
ERR_FAIL_COND_V(!body->get_space(), false);
ERR_FAIL_COND_V(body->get_space()->is_locked(), false);
+ _update_shapes();
+
return body->get_space()->test_body_motion(body, p_from, p_motion, p_margin, r_result);
}
@@ -1209,6 +1218,8 @@ bool PhysicsServerSW::generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis p_a
void PhysicsServerSW::free(RID p_rid) {
+ _update_shapes(); //just in case
+
if (shape_owner.owns(p_rid)) {
ShapeSW *shape = shape_owner.get(p_rid);
@@ -1312,6 +1323,8 @@ void PhysicsServerSW::step(real_t p_step) {
if (!active)
return;
+ _update_shapes();
+
doing_sync = false;
last_step = p_step;
@@ -1409,6 +1422,14 @@ int PhysicsServerSW::get_process_info(ProcessInfo p_info) {
return 0;
}
+void PhysicsServerSW::_update_shapes() {
+
+ while (pending_shape_update_list.first()) {
+ pending_shape_update_list.first()->self()->_shape_changed();
+ pending_shape_update_list.remove(pending_shape_update_list.first());
+ }
+}
+
void PhysicsServerSW::_shape_col_cbk(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata) {
CollCbkData *cbk = (CollCbkData *)p_userdata;
diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h
index 2e1fa7065a..99ba302acd 100644
--- a/servers/physics/physics_server_sw.h
+++ b/servers/physics/physics_server_sw.h
@@ -62,6 +62,10 @@ class PhysicsServerSW : public PhysicsServer {
mutable RID_Owner<JointSW> joint_owner;
//void _clear_query(QuerySW *p_query);
+ friend class CollisionObjectSW;
+ SelfList<CollisionObjectSW>::List pending_shape_update_list;
+ void _update_shapes();
+
public:
static PhysicsServerSW *singleton;
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 0684cb1701..c7b02c92f7 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -79,7 +79,11 @@ String ShaderLanguage::get_operator_text(Operator p_op) {
"|",
"^",
"~",
- "++"
+ "++",
+ "--",
+ "?",
+ ":",
+ "++",
"--",
"()",
"construct",
@@ -3116,6 +3120,12 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat
tk = _get_token();
+ VariableDeclarationNode *vardecl = alloc_node<VariableDeclarationNode>();
+ vardecl->datatype=type;
+ vardecl->precision=precision;
+
+ p_block->statements.push_back(vardecl);
+
while (true) {
if (tk.type != TK_IDENTIFIER) {
@@ -3133,8 +3143,14 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat
var.type = type;
var.precision = precision;
var.line = tk_line;
+
p_block->variables[name] = var;
+ VariableDeclarationNode::Declaration decl;
+
+ decl.name=name;
+ decl.initializer=NULL;
+
tk = _get_token();
if (tk.type == TK_OP_ASSIGN) {
@@ -3143,22 +3159,19 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat
if (!n)
return ERR_PARSE_ERROR;
- OperatorNode *assign = alloc_node<OperatorNode>();
- VariableNode *vnode = alloc_node<VariableNode>();
- vnode->name = name;
- vnode->datatype_cache = type;
- assign->arguments.push_back(vnode);
- assign->arguments.push_back(n);
- assign->op = OP_ASSIGN;
- p_block->statements.push_back(assign);
- tk = _get_token();
+ decl.initializer = n;
- if (!_validate_operator(assign)) {
- _set_error("Invalid assignment of '" + get_datatype_name(n->get_datatype()) + "' to '" + get_datatype_name(type) + "'");
+ if (var.type!=n->get_datatype()) {
+ _set_error("Invalid assignment of '" + get_datatype_name(n->get_datatype()) + "' to '" + get_datatype_name(var.type) + "'");
return ERR_PARSE_ERROR;
+
}
+ tk = _get_token();
+
}
+ vardecl->declarations.push_back(decl);
+
if (tk.type == TK_COMMA) {
tk = _get_token();
//another variable
@@ -3221,7 +3234,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat
//if () {}
tk = _get_token();
if (tk.type != TK_PARENTHESIS_OPEN) {
- _set_error("Expected '(' after if");
+ _set_error("Expected '(' after while");
return ERR_PARSE_ERROR;
}
@@ -3243,7 +3256,64 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat
cf->blocks.push_back(block);
p_block->statements.push_back(cf);
- Error err = _parse_block(block, p_builtin_types, true, p_can_break, p_can_continue);
+ Error err = _parse_block(block, p_builtin_types, true, true, true);
+ if (err)
+ return err;
+ } else if (tk.type == TK_CF_FOR) {
+ //if () {}
+ tk = _get_token();
+ if (tk.type != TK_PARENTHESIS_OPEN) {
+ _set_error("Expected '(' after for");
+ return ERR_PARSE_ERROR;
+ }
+
+ ControlFlowNode *cf = alloc_node<ControlFlowNode>();
+ cf->flow_op = FLOW_OP_FOR;
+
+ BlockNode *init_block = alloc_node<BlockNode>();
+ init_block->parent_block = p_block;
+ init_block->single_statement=true;
+ cf->blocks.push_back(init_block);
+ if (_parse_block(init_block,p_builtin_types,true,false,false)!=OK) {
+ return ERR_PARSE_ERROR;
+ }
+
+ Node *n = _parse_and_reduce_expression(init_block, p_builtin_types);
+ if (!n)
+ return ERR_PARSE_ERROR;
+
+ if (n->get_datatype()!=TYPE_BOOL) {
+ _set_error("Middle expression is expected to be boolean.");
+ return ERR_PARSE_ERROR;
+
+ }
+
+ tk = _get_token();
+ if (tk.type != TK_SEMICOLON) {
+ _set_error("Expected ';' after middle expression");
+ return ERR_PARSE_ERROR;
+ }
+
+ cf->expressions.push_back(n);
+
+ n = _parse_and_reduce_expression(init_block, p_builtin_types);
+ if (!n)
+ return ERR_PARSE_ERROR;
+
+ cf->expressions.push_back(n);
+
+ tk = _get_token();
+ if (tk.type != TK_PARENTHESIS_CLOSE) {
+ _set_error("Expected ')' after third expression");
+ return ERR_PARSE_ERROR;
+ }
+
+ BlockNode *block = alloc_node<BlockNode>();
+ block->parent_block = p_block;
+ cf->blocks.push_back(block);
+ p_block->statements.push_back(cf);
+
+ Error err = _parse_block(block, p_builtin_types, true, true, true);
if (err)
return err;
@@ -3320,6 +3390,44 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat
}
p_block->statements.push_back(flow);
+ } else if (tk.type == TK_CF_BREAK) {
+
+
+ if (!p_can_break) {
+ //all is good
+ _set_error("Breaking is not allowed here");
+ }
+
+ ControlFlowNode *flow = alloc_node<ControlFlowNode>();
+ flow->flow_op = FLOW_OP_BREAK;
+
+ pos = _get_tkpos();
+ tk = _get_token();
+ if (tk.type != TK_SEMICOLON) {
+ //all is good
+ _set_error("Expected ';' after break");
+ }
+
+ p_block->statements.push_back(flow);
+ } else if (tk.type == TK_CF_CONTINUE) {
+
+
+ if (!p_can_break) {
+ //all is good
+ _set_error("Contiuning is not allowed here");
+ }
+
+ ControlFlowNode *flow = alloc_node<ControlFlowNode>();
+ flow->flow_op = FLOW_OP_CONTINUE;
+
+ pos = _get_tkpos();
+ tk = _get_token();
+ if (tk.type != TK_SEMICOLON) {
+ //all is good
+ _set_error("Expected ';' after continue");
+ }
+
+ p_block->statements.push_back(flow);
} else {
diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h
index f00b4c5a97..50f5cebeaa 100644
--- a/servers/visual/shader_language.h
+++ b/servers/visual/shader_language.h
@@ -266,6 +266,7 @@ public:
TYPE_FUNCTION,
TYPE_BLOCK,
TYPE_VARIABLE,
+ TYPE_VARIABLE_DECLARATION,
TYPE_CONSTANT,
TYPE_OPERATOR,
TYPE_CONTROL_FLOW,
@@ -315,6 +316,25 @@ public:
}
};
+ struct VariableDeclarationNode : public Node {
+
+ DataPrecision precision;
+ DataType datatype;
+
+ struct Declaration {
+
+ StringName name;
+ Node *initializer;
+ };
+
+ Vector<Declaration> declarations;
+ virtual DataType get_datatype() const { return datatype; }
+
+ VariableDeclarationNode() {
+ type = TYPE_VARIABLE_DECLARATION;
+ }
+ };
+
struct ConstantNode : public Node {
DataType datatype;
@@ -346,10 +366,12 @@ public:
Map<StringName, Variable> variables;
List<Node *> statements;
+ bool single_statement;
BlockNode() {
type = TYPE_BLOCK;
parent_block = NULL;
parent_function = NULL;
+ single_statement=false;
}
};