summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.mailmap26
-rw-r--r--core/bind/core_bind.cpp6
-rw-r--r--core/color.cpp109
-rw-r--r--core/color.h12
-rw-r--r--core/io/resource_loader.cpp3
-rw-r--r--core/object.h1
-rw-r--r--core/script_debugger_local.cpp5
-rw-r--r--core/script_debugger_local.h1
-rw-r--r--core/script_debugger_remote.cpp83
-rw-r--r--core/script_debugger_remote.h1
-rw-r--r--core/script_language.h4
-rw-r--r--core/undo_redo.cpp20
-rw-r--r--core/undo_redo.h4
-rw-r--r--doc/classes/@GDScript.xml6
-rw-r--r--doc/classes/Area.xml8
-rw-r--r--doc/classes/Area2D.xml8
-rw-r--r--doc/classes/BaseButton.xml4
-rw-r--r--doc/classes/Color.xml3
-rw-r--r--doc/classes/Control.xml12
-rw-r--r--doc/classes/EditorSettings.xml2
-rw-r--r--doc/classes/KinematicBody.xml2
-rw-r--r--doc/classes/Label.xml1
-rw-r--r--doc/classes/LineEdit.xml4
-rw-r--r--doc/classes/RigidBody.xml2
-rw-r--r--doc/classes/RigidBody2D.xml2
-rw-r--r--doc/classes/UndoRedo.xml14
-rw-r--r--doc/classes/VehicleBody.xml17
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp28
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp2
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp2
-rw-r--r--drivers/gles3/shader_compiler_gles3.cpp2
-rw-r--r--drivers/gles3/shaders/effect_blur.glsl2
-rw-r--r--drivers/gles3/shaders/scene.glsl8
-rw-r--r--drivers/unix/os_unix.cpp24
-rw-r--r--editor/code_editor.cpp19
-rw-r--r--editor/editor_data.cpp16
-rw-r--r--editor/editor_data.h4
-rw-r--r--editor/editor_fonts.cpp61
-rw-r--r--editor/editor_node.cpp2
-rw-r--r--editor/editor_settings.cpp26
-rw-r--r--editor/editor_settings.h2
-rw-r--r--editor/editor_themes.cpp91
-rw-r--r--editor/import/resource_importer_bitmask.cpp2
-rw-r--r--editor/import/resource_importer_wav.cpp12
-rw-r--r--editor/plugins/baked_lightmap_editor_plugin.cpp2
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp110
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h1
-rw-r--r--editor/plugins/gi_probe_editor_plugin.cpp2
-rw-r--r--editor/plugins/script_editor_plugin.cpp32
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp2
-rw-r--r--editor/plugins/tile_set_editor_plugin.cpp9
-rw-r--r--editor/plugins/tile_set_editor_plugin.h1
-rw-r--r--editor/progress_dialog.cpp2
-rw-r--r--editor/scene_tree_dock.cpp42
-rw-r--r--editor/scene_tree_dock.h1
-rw-r--r--editor/script_editor_debugger.cpp20
-rw-r--r--main/main.cpp10
-rw-r--r--modules/bullet/collision_object_bullet.cpp6
-rw-r--r--modules/bullet/collision_object_bullet.h2
-rw-r--r--modules/bullet/rigid_body_bullet.cpp6
-rw-r--r--modules/bullet/shape_bullet.cpp7
-rw-r--r--modules/bullet/shape_bullet.h1
-rw-r--r--modules/bullet/space_bullet.cpp101
-rw-r--r--modules/bullet/space_bullet.h13
-rw-r--r--modules/gdnative/gdnative/string.cpp264
-rw-r--r--modules/gdnative/gdnative/transform.cpp4
-rw-r--r--modules/gdnative/gdnative_api.json82
-rw-r--r--modules/gdnative/include/gdnative/string.h32
-rw-r--r--modules/gdnative/include/gdnative/transform.h4
-rw-r--r--modules/gdnative/pluginscript/pluginscript_language.cpp8
-rw-r--r--modules/gdscript/gdscript.h4
-rw-r--r--modules/mono/csharp_script.cpp72
-rw-r--r--modules/mono/csharp_script.h4
-rw-r--r--modules/mono/editor/bindings_generator.cpp58
-rw-r--r--modules/mono/editor/bindings_generator.h3
-rw-r--r--modules/mono/editor/godotsharp_editor.cpp7
-rw-r--r--modules/mono/glue/cs_files/Color.cs26
-rw-r--r--modules/mono/glue/cs_files/DebuggingUtils.cs77
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp2
-rw-r--r--modules/mono/mono_gd/gd_mono_class.cpp14
-rw-r--r--modules/mono/mono_gd/gd_mono_class.h6
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp73
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.h24
-rw-r--r--modules/regex/regex.cpp27
-rw-r--r--platform/android/build.gradle.template1
-rw-r--r--platform/android/java/src/org/godotengine/godot/Godot.java5
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotView.java2
-rw-r--r--platform/android/os_android.cpp32
-rw-r--r--platform/iphone/export/export.cpp2
-rw-r--r--platform/osx/export/export.cpp22
-rw-r--r--platform/osx/os_osx.h18
-rw-r--r--platform/osx/os_osx.mm197
-rw-r--r--platform/windows/os_windows.cpp7
-rw-r--r--scene/2d/camera_2d.cpp12
-rw-r--r--scene/3d/baked_lightmap.cpp2
-rw-r--r--scene/3d/gi_probe.cpp2
-rw-r--r--scene/3d/particles.cpp17
-rw-r--r--scene/3d/physics_body.h5
-rw-r--r--scene/3d/vehicle_body.cpp75
-rw-r--r--scene/3d/vehicle_body.h19
-rw-r--r--scene/animation/animation_player.cpp2
-rw-r--r--scene/gui/base_button.cpp4
-rw-r--r--scene/gui/control.cpp18
-rw-r--r--scene/gui/line_edit.cpp4
-rw-r--r--scene/gui/text_edit.cpp47
-rw-r--r--scene/main/node.cpp11
-rw-r--r--scene/resources/bit_mask.cpp4
-rw-r--r--scene/resources/dynamic_font.cpp15
-rw-r--r--scene/resources/packed_scene.cpp4
-rw-r--r--scene/resources/tile_set.cpp3
110 files changed, 1435 insertions, 919 deletions
diff --git a/.mailmap b/.mailmap
new file mode 100644
index 0000000000..b37cd2884d
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1,26 @@
+Andrea Catania <info@andreacatania.com>
+Andreas Haas <liu.gam3@gmail.com>
+Andreas Haas <Hinsbart@users.noreply.github.com>
+Andreas Haas <entenflugstuhl@gmail.com>
+Ariel Manzur <ariel@godotengine.org>
+Ariel Manzur <ariel@okamstudio.com>
+Bastiaan Olij <mux213@gmail.com>
+Bernhard Liebl <poke1024@gmx.de>
+Bernhard Liebl <poke1024@gmx.org>
+Geequlim <geequlim@gmail.com>
+Ignacio Etcheverry <ignalfonsore@gmail.com>
+Indah Sylvia <ISylvox@yahoo.com>
+Jakub Grzesik <kubecz3k@gmail.com>
+Juan Linietsky <reduzio@gmail.com>
+Juan Linietsky <juan@okamstudio.com>
+Juan Linietsky <reduz@Juans-MBP.fibertel.com.ar>
+Julian Murgia <the.straton@gmail.com>
+Leon Krause <eska@eska.me>
+Leon Krause <eska@eska.me> <eska014@users.noreply.github.com>
+Marcelo Fernandez <marcelofg55@gmail.com>
+Mariano Javier Suligoy <marianognu.easyrpg@gmail.com>
+Paul Batty <p_batty@hotmail.co.uk>
+Poommetee Ketson <poommetee@protonmail.com>
+Saracen <SaracenOne@gmail.com>
+Thomas Herzog <therzog@mail.de>
+Zher Huei Lee <lee.zh.92@gmail.com>
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 2921626f3a..c7b08b8242 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -2466,7 +2466,13 @@ Array _ClassDB::get_method_list(StringName p_class, bool p_no_inheritance) const
Array ret;
for (List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) {
+#ifdef DEBUG_METHODS_ENABLED
ret.push_back(E->get().operator Dictionary());
+#else
+ Dictionary dict;
+ dict["name"] = E->get().name;
+ ret.push_back(dict);
+#endif
}
return ret;
diff --git a/core/color.cpp b/core/color.cpp
index 7278b5c4ee..b708f15d69 100644
--- a/core/color.cpp
+++ b/core/color.cpp
@@ -396,7 +396,7 @@ String Color::to_html(bool p_alpha) const {
txt += _to_hex(g);
txt += _to_hex(b);
if (p_alpha)
- txt = _to_hex(a) + txt;
+ txt += _to_hex(a);
return txt;
}
@@ -413,96 +413,95 @@ Color::operator String() const {
Color Color::operator+(const Color &p_color) const {
return Color(
- CLAMP(r + p_color.r, 0.0, 1.0),
- CLAMP(g + p_color.g, 0.0, 1.0),
- CLAMP(b + p_color.b, 0.0, 1.0),
- CLAMP(a + p_color.a, 0.0, 1.0));
+ r + p_color.r,
+ g + p_color.g,
+ b + p_color.b,
+ a + p_color.a);
}
void Color::operator+=(const Color &p_color) {
- r = CLAMP(r + p_color.r, 0.0, 1.0);
- g = CLAMP(g + p_color.g, 0.0, 1.0);
- b = CLAMP(b + p_color.b, 0.0, 1.0);
- a = CLAMP(a + p_color.a, 0.0, 1.0);
+ r = r + p_color.r;
+ g = g + p_color.g;
+ b = b + p_color.b;
+ a = a + p_color.a;
}
Color Color::operator-(const Color &p_color) const {
return Color(
- CLAMP(r - p_color.r, 0.0, 1.0),
- CLAMP(g - p_color.g, 0.0, 1.0),
- CLAMP(b - p_color.b, 0.0, 1.0),
- CLAMP(a - p_color.a, 0.0, 1.0));
+ r - p_color.r,
+ g - p_color.g,
+ b - p_color.b,
+ a - p_color.a);
}
void Color::operator-=(const Color &p_color) {
- r = CLAMP(r - p_color.r, 0.0, 1.0);
- g = CLAMP(g - p_color.g, 0.0, 1.0);
- b = CLAMP(b - p_color.b, 0.0, 1.0);
- a = CLAMP(a - p_color.a, 0.0, 1.0);
+ r = r - p_color.r;
+ g = g - p_color.g;
+ b = b - p_color.b;
+ a = a - p_color.a;
}
Color Color::operator*(const Color &p_color) const {
return Color(
- CLAMP(r * p_color.r, 0.0, 1.0),
- CLAMP(g * p_color.g, 0.0, 1.0),
- CLAMP(b * p_color.b, 0.0, 1.0),
- CLAMP(a * p_color.a, 0.0, 1.0));
+ r * p_color.r,
+ g * p_color.g,
+ b * p_color.b,
+ a * p_color.a);
}
Color Color::operator*(const real_t &rvalue) const {
return Color(
- CLAMP(r * rvalue, 0.0, 1.0),
- CLAMP(g * rvalue, 0.0, 1.0),
- CLAMP(b * rvalue, 0.0, 1.0),
- CLAMP(a * rvalue, 0.0, 1.0));
+ r * rvalue,
+ g * rvalue,
+ b * rvalue,
+ a * rvalue);
}
void Color::operator*=(const Color &p_color) {
- r = CLAMP(r * p_color.r, 0.0, 1.0);
- g = CLAMP(g * p_color.g, 0.0, 1.0);
- b = CLAMP(b * p_color.b, 0.0, 1.0);
- a = CLAMP(a * p_color.a, 0.0, 1.0);
+ r = r * p_color.r;
+ g = g * p_color.g;
+ b = b * p_color.b;
+ a = a * p_color.a;
}
void Color::operator*=(const real_t &rvalue) {
- r = CLAMP(r * rvalue, 0.0, 1.0);
- g = CLAMP(g * rvalue, 0.0, 1.0);
- b = CLAMP(b * rvalue, 0.0, 1.0);
- a = CLAMP(a * rvalue, 0.0, 1.0);
-};
+ r = r * rvalue;
+ g = g * rvalue;
+ b = b * rvalue;
+ a = a * rvalue;
+}
Color Color::operator/(const Color &p_color) const {
return Color(
- p_color.r == 0 ? 1 : CLAMP(r / p_color.r, 0.0, 1.0),
- p_color.g == 0 ? 1 : CLAMP(g / p_color.g, 0.0, 1.0),
- p_color.b == 0 ? 1 : CLAMP(b / p_color.b, 0.0, 1.0),
- p_color.a == 0 ? 1 : CLAMP(a / p_color.a, 0.0, 1.0));
+ r / p_color.r,
+ g / p_color.g,
+ b / p_color.b,
+ a / p_color.a);
}
Color Color::operator/(const real_t &rvalue) const {
- if (rvalue == 0) return Color(1.0, 1.0, 1.0, 1.0);
return Color(
- CLAMP(r / rvalue, 0.0, 1.0),
- CLAMP(g / rvalue, 0.0, 1.0),
- CLAMP(b / rvalue, 0.0, 1.0),
- CLAMP(a / rvalue, 0.0, 1.0));
+ r / rvalue,
+ g / rvalue,
+ b / rvalue,
+ a / rvalue);
}
void Color::operator/=(const Color &p_color) {
- r = p_color.r == 0 ? 1 : CLAMP(r / p_color.r, 0.0, 1.0);
- g = p_color.g == 0 ? 1 : CLAMP(g / p_color.g, 0.0, 1.0);
- b = p_color.b == 0 ? 1 : CLAMP(b / p_color.b, 0.0, 1.0);
- a = p_color.a == 0 ? 1 : CLAMP(a / p_color.a, 0.0, 1.0);
+ r = r / p_color.r;
+ g = g / p_color.g;
+ b = b / p_color.b;
+ a = a / p_color.a;
}
void Color::operator/=(const real_t &rvalue) {
@@ -513,18 +512,18 @@ void Color::operator/=(const real_t &rvalue) {
b = 1.0;
a = 1.0;
} else {
- r = CLAMP(r / rvalue, 0.0, 1.0);
- g = CLAMP(g / rvalue, 0.0, 1.0);
- b = CLAMP(b / rvalue, 0.0, 1.0);
- a = CLAMP(a / rvalue, 0.0, 1.0);
+ r = r / rvalue;
+ g = g / rvalue;
+ b = b / rvalue;
+ a = a / rvalue;
}
};
Color Color::operator-() const {
return Color(
- CLAMP(1.0 - r, 0.0, 1.0),
- CLAMP(1.0 - g, 0.0, 1.0),
- CLAMP(1.0 - b, 0.0, 1.0),
- CLAMP(1.0 - a, 0.0, 1.0));
+ 1.0 - r,
+ 1.0 - g,
+ 1.0 - b,
+ 1.0 - a);
}
diff --git a/core/color.h b/core/color.h
index 0ff4fe6edd..9af8fb0a78 100644
--- a/core/color.h
+++ b/core/color.h
@@ -105,18 +105,18 @@ struct Color {
_FORCE_INLINE_ Color darkened(float p_amount) const {
Color res = *this;
- res.r = CLAMP(res.r * (1.0f - p_amount), 0.0, 1.0);
- res.g = CLAMP(res.g * (1.0f - p_amount), 0.0, 1.0);
- res.b = CLAMP(res.b * (1.0f - p_amount), 0.0, 1.0);
+ res.r = res.r * (1.0f - p_amount);
+ res.g = res.g * (1.0f - p_amount);
+ res.b = res.b * (1.0f - p_amount);
return res;
}
_FORCE_INLINE_ Color lightened(float p_amount) const {
Color res = *this;
- res.r = CLAMP(res.r + (1.0f - res.r) * p_amount, 0.0, 1.0);
- res.g = CLAMP(res.g + (1.0f - res.g) * p_amount, 0.0, 1.0);
- res.b = CLAMP(res.b + (1.0f - res.b) * p_amount, 0.0, 1.0);
+ res.r = res.r + (1.0f - res.r) * p_amount;
+ res.g = res.g + (1.0f - res.g) * p_amount;
+ res.b = res.b + (1.0f - res.b) * p_amount;
return res;
}
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 87add585eb..1351030d1e 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -202,7 +202,8 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p
if (OS::get_singleton()->is_stdout_verbose())
print_line("load resource: " + local_path + " (cached)");
-
+ if (r_error)
+ *r_error = OK;
return RES(ResourceCache::get(local_path));
}
diff --git a/core/object.h b/core/object.h
index 5de87b8a7d..98ce62551b 100644
--- a/core/object.h
+++ b/core/object.h
@@ -111,6 +111,7 @@ enum PropertyUsageFlags {
PROPERTY_USAGE_CLASS_IS_ENUM = 1 << 18,
PROPERTY_USAGE_NIL_IS_VARIANT = 1 << 19,
PROPERTY_USAGE_INTERNAL = 1 << 20,
+ PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE = 1 << 21, // If the object is duplicated also this property will be duplicated
PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK,
PROPERTY_USAGE_DEFAULT_INTL = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK | PROPERTY_USAGE_INTERNATIONALIZED,
diff --git a/core/script_debugger_local.cpp b/core/script_debugger_local.cpp
index 57463a662d..0da377453e 100644
--- a/core/script_debugger_local.cpp
+++ b/core/script_debugger_local.cpp
@@ -294,6 +294,11 @@ void ScriptDebuggerLocal::send_message(const String &p_message, const Array &p_a
print_line("MESSAGE: '" + p_message + "' - " + String(Variant(p_args)));
}
+void ScriptDebuggerLocal::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type, const Vector<ScriptLanguage::StackInfo> &p_stack_info) {
+
+ print_line("ERROR: '" + (p_descr.empty() ? p_err : p_descr) + "'");
+}
+
ScriptDebuggerLocal::ScriptDebuggerLocal() {
profiling = false;
diff --git a/core/script_debugger_local.h b/core/script_debugger_local.h
index c93120331d..c87bc90bb4 100644
--- a/core/script_debugger_local.h
+++ b/core/script_debugger_local.h
@@ -44,6 +44,7 @@ class ScriptDebuggerLocal : public ScriptDebugger {
public:
void debug(ScriptLanguage *p_script, bool p_can_continue);
virtual void send_message(const String &p_message, const Array &p_args);
+ virtual void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type, const Vector<ScriptLanguage::StackInfo> &p_stack_info);
virtual bool is_profiling() const { return profiling; }
virtual void add_profiling_frame_data(const StringName &p_name, const Array &p_data) {}
diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp
index e3dc8eb53a..a297bb738f 100644
--- a/core/script_debugger_remote.cpp
+++ b/core/script_debugger_remote.cpp
@@ -432,22 +432,6 @@ void ScriptDebuggerRemote::_err_handler(void *ud, const char *p_func, const char
if (p_type == ERR_HANDLER_SCRIPT)
return; //ignore script errors, those go through debugger
- ScriptDebuggerRemote *sdr = (ScriptDebuggerRemote *)ud;
-
- OutputError oe;
- oe.error = p_err;
- oe.error_descr = p_descr;
- oe.source_file = p_file;
- oe.source_line = p_line;
- oe.source_func = p_func;
- oe.warning = p_type == ERR_HANDLER_WARNING;
- uint64_t time = OS::get_singleton()->get_ticks_msec();
- oe.hr = time / 3600000;
- oe.min = (time / 60000) % 60;
- oe.sec = (time / 1000) % 60;
- oe.msec = time % 1000;
- Array cstack;
-
Vector<ScriptLanguage::StackInfo> si;
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
@@ -456,32 +440,8 @@ void ScriptDebuggerRemote::_err_handler(void *ud, const char *p_func, const char
break;
}
- cstack.resize(si.size() * 2);
- for (int i = 0; i < si.size(); i++) {
- String path;
- int line = 0;
- if (si[i].script.is_valid()) {
- path = si[i].script->get_path();
- line = si[i].line;
- }
- cstack[i * 2 + 0] = path;
- cstack[i * 2 + 1] = line;
- }
-
- oe.callstack = cstack;
-
- sdr->mutex->lock();
-
- if (!sdr->locking && sdr->tcp_client->is_connected_to_host()) {
-
- if (sdr->errors.size() >= sdr->max_errors_per_frame) {
- sdr->n_errors_dropped++;
- } else {
- sdr->errors.push_back(oe);
- }
- }
-
- sdr->mutex->unlock();
+ ScriptDebuggerRemote *sdr = (ScriptDebuggerRemote *)ud;
+ sdr->send_error(p_func, p_file, p_line, p_err, p_descr, p_type, si);
}
bool ScriptDebuggerRemote::_parse_live_edit(const Array &p_command) {
@@ -928,6 +888,45 @@ void ScriptDebuggerRemote::send_message(const String &p_message, const Array &p_
mutex->unlock();
}
+void ScriptDebuggerRemote::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type, const Vector<ScriptLanguage::StackInfo> &p_stack_info) {
+
+ OutputError oe;
+ oe.error = p_err;
+ oe.error_descr = p_descr;
+ oe.source_file = p_file;
+ oe.source_line = p_line;
+ oe.source_func = p_func;
+ oe.warning = p_type == ERR_HANDLER_WARNING;
+ uint64_t time = OS::get_singleton()->get_ticks_msec();
+ oe.hr = time / 3600000;
+ oe.min = (time / 60000) % 60;
+ oe.sec = (time / 1000) % 60;
+ oe.msec = time % 1000;
+ Array cstack;
+
+ cstack.resize(p_stack_info.size() * 3);
+ for (int i = 0; i < p_stack_info.size(); i++) {
+ cstack[i * 3 + 0] = p_stack_info[i].file;
+ cstack[i * 3 + 1] = p_stack_info[i].func;
+ cstack[i * 3 + 2] = p_stack_info[i].line;
+ }
+
+ oe.callstack = cstack;
+
+ mutex->lock();
+
+ if (!locking && tcp_client->is_connected_to_host()) {
+
+ if (errors.size() >= max_errors_per_frame) {
+ n_errors_dropped++;
+ } else {
+ errors.push_back(oe);
+ }
+ }
+
+ mutex->unlock();
+}
+
void ScriptDebuggerRemote::_print_handler(void *p_this, const String &p_string, bool p_error) {
ScriptDebuggerRemote *sdr = (ScriptDebuggerRemote *)p_this;
diff --git a/core/script_debugger_remote.h b/core/script_debugger_remote.h
index 924d5de2c4..2c4e29f172 100644
--- a/core/script_debugger_remote.h
+++ b/core/script_debugger_remote.h
@@ -157,6 +157,7 @@ public:
virtual void request_quit();
virtual void send_message(const String &p_message, const Array &p_args);
+ virtual void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type, const Vector<ScriptLanguage::StackInfo> &p_stack_info);
virtual void set_request_scene_tree_message_func(RequestSceneTreeMessageFunc p_func, void *p_udata);
virtual void set_live_edit_funcs(LiveEditFuncs *p_funcs);
diff --git a/core/script_language.h b/core/script_language.h
index 6bf2129f9b..66614a293c 100644
--- a/core/script_language.h
+++ b/core/script_language.h
@@ -254,7 +254,8 @@ public:
virtual String debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems = -1, int p_max_depth = -1) = 0;
struct StackInfo {
- Ref<Script> script;
+ String file;
+ String func;
int line;
};
@@ -391,6 +392,7 @@ public:
ScriptLanguage *get_break_language() const;
virtual void send_message(const String &p_message, const Array &p_args) = 0;
+ virtual void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type, const Vector<ScriptLanguage::StackInfo> &p_stack_info) = 0;
virtual bool is_remote() const { return false; }
virtual void request_quit() {}
diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp
index a105fba290..b3f9dd818d 100644
--- a/core/undo_redo.cpp
+++ b/core/undo_redo.cpp
@@ -246,13 +246,6 @@ void UndoRedo::commit_action() {
redo(); // perform action
- if (max_steps > 0 && actions.size() > max_steps) {
- //clear early steps
-
- while (actions.size() > max_steps)
- _pop_history_tail();
- }
-
if (callback && actions.size() > 0) {
callback(callback_ud, actions[actions.size() - 1].name);
}
@@ -347,16 +340,6 @@ String UndoRedo::get_current_action_name() const {
return actions[current_action].name;
}
-void UndoRedo::set_max_steps(int p_max_steps) {
-
- max_steps = p_max_steps;
-}
-
-int UndoRedo::get_max_steps() const {
-
- return max_steps;
-}
-
uint64_t UndoRedo::get_version() const {
return version;
@@ -385,7 +368,6 @@ UndoRedo::UndoRedo() {
version = 1;
action_level = 0;
current_action = -1;
- max_steps = -1;
merge_mode = MERGE_DISABLE;
callback = NULL;
callback_ud = NULL;
@@ -510,8 +492,6 @@ void UndoRedo::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear_history"), &UndoRedo::clear_history);
ClassDB::bind_method(D_METHOD("get_current_action_name"), &UndoRedo::get_current_action_name);
ClassDB::bind_method(D_METHOD("get_version"), &UndoRedo::get_version);
- ClassDB::bind_method(D_METHOD("set_max_steps", "max_steps"), &UndoRedo::set_max_steps);
- ClassDB::bind_method(D_METHOD("get_max_steps"), &UndoRedo::get_max_steps);
ClassDB::bind_method(D_METHOD("redo"), &UndoRedo::redo);
ClassDB::bind_method(D_METHOD("undo"), &UndoRedo::undo);
diff --git a/core/undo_redo.h b/core/undo_redo.h
index 5d7ab782d6..a373296b73 100644
--- a/core/undo_redo.h
+++ b/core/undo_redo.h
@@ -79,7 +79,6 @@ private:
Vector<Action> actions;
int current_action;
int action_level;
- int max_steps;
MergeMode merge_mode;
uint64_t version;
@@ -115,9 +114,6 @@ public:
String get_current_action_name() const;
void clear_history();
- void set_max_steps(int p_max_steps);
- int get_max_steps() const;
-
uint64_t get_version() const;
void set_commit_notify_callback(CommitNotifyCallback p_callback, void *p_ud);
diff --git a/doc/classes/@GDScript.xml b/doc/classes/@GDScript.xml
index cd05c83347..c98a80ca8c 100644
--- a/doc/classes/@GDScript.xml
+++ b/doc/classes/@GDScript.xml
@@ -41,10 +41,12 @@
<argument index="1" name="alpha" type="float">
</argument>
<description>
- Returns color [code]name[/code] with [code]alpha[/code] ranging from 0 to 1. Note: [code]name[/code] is defined in color_names.inc.
+ Returns a color according to the standardised [code]name[/code] with [code]alpha[/code] ranging from 0 to 1.
[codeblock]
- red = ColorN('red')
+ red = ColorN("red", 1)
[/codeblock]
+ Supported color names:
+ "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige", "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown", "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflower", "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod", "darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen", "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen", "darkslateblue", "darkslategray", "darkturquoise", "darkviolet", "deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick", "floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite", "gold", "goldenrod", "gray", "webgray", "green", "webgreen", "greenyellow", "honeydew", "hotpink", "indianred", "indigo", "ivory", "khaki", "lavender", "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral", "lightcyan", "lightgoldenrod", "lightgray", "lightgreen", "lightpink", "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta", "maroon", "webmaroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple", "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise", "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin", "navajowhite", "navyblue", "oldlace", "olive", "olivedrab", "orange", "orangered", "orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred", "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue", "purple", "webpurple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown", "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue", "slateblue", "slategray", "snow", "springgreen", "steelblue", "tan", "teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white", "whitesmoke", "yellow", "yellowgreen".
</description>
</method>
<method name="abs">
diff --git a/doc/classes/Area.xml b/doc/classes/Area.xml
index b74e767fd2..58fa99f7da 100644
--- a/doc/classes/Area.xml
+++ b/doc/classes/Area.xml
@@ -33,14 +33,14 @@
<return type="Array">
</return>
<description>
- Returns a list of intersecting [code]Area[/code]s.
+ Returns a list of intersecting [code]Area[/code]s. For performance reasons (collisions are all processed at the same time) this list is modified once during the physics step, not immediately after objects are moved. Consider using signals instead.
</description>
</method>
<method name="get_overlapping_bodies" qualifiers="const">
<return type="Array">
</return>
<description>
- Returns a list of intersecting [PhysicsBody]s.
+ Returns a list of intersecting [PhysicsBody]s. For performance reasons (collisions are all processed at the same time) this list is modified once during the physics step, not immediately after objects are moved. Consider using signals instead.
</description>
</method>
<method name="overlaps_area" qualifiers="const">
@@ -49,7 +49,7 @@
<argument index="0" name="area" type="Node">
</argument>
<description>
- If [code]true[/code] the given area overlaps the Area.
+ If [code]true[/code] the given area overlaps the Area. Note that the result of this test is not immediate after moving objects. For performance, list of overlaps is updated once per frame and before the physics step. Consider using signals instead.
</description>
</method>
<method name="overlaps_body" qualifiers="const">
@@ -58,7 +58,7 @@
<argument index="0" name="body" type="Node">
</argument>
<description>
- If [code]true[/code] the given body overlaps the Area.
+ If [code]true[/code] the given body overlaps the Area. Note that the result of this test is not immediate after moving objects. For performance, list of overlaps is updated once per frame and before the physics step. Consider using signals instead.
</description>
</method>
<method name="set_collision_layer_bit">
diff --git a/doc/classes/Area2D.xml b/doc/classes/Area2D.xml
index 6a3f0e7645..ca395321e3 100644
--- a/doc/classes/Area2D.xml
+++ b/doc/classes/Area2D.xml
@@ -33,14 +33,14 @@
<return type="Array">
</return>
<description>
- Returns a list of intersecting [code]Area2D[/code]s.
+ Returns a list of intersecting [code]Area2D[/code]s. For performance reasons (collisions are all processed at the same time) this list is modified once during the physics step, not immediately after objects are moved. Consider using signals instead.
</description>
</method>
<method name="get_overlapping_bodies" qualifiers="const">
<return type="Array">
</return>
<description>
- Returns a list of intersecting [PhysicsBody2D]s.
+ Returns a list of intersecting [PhysicsBody2D]s. For performance reasons (collisions are all processed at the same time) this list is modified once during the physics step, not immediately after objects are moved. Consider using signals instead.
</description>
</method>
<method name="overlaps_area" qualifiers="const">
@@ -49,7 +49,7 @@
<argument index="0" name="area" type="Node">
</argument>
<description>
- If [code]true[/code] the given area overlaps the Area2D.
+ If [code]true[/code] the given area overlaps the Area2D. Note that the result of this test is not immediate after moving objects. For performance, list of overlaps is updated once per frame and before the physics step. Consider using signals instead.
</description>
</method>
<method name="overlaps_body" qualifiers="const">
@@ -58,7 +58,7 @@
<argument index="0" name="body" type="Node">
</argument>
<description>
- If [code]true[/code] the given body overlaps the Area2D.
+ If [code]true[/code] the given body overlaps the Area2D. Note that the result of this test is not immediate after moving objects. For performance, list of overlaps is updated once per frame and before the physics step. Consider using signals instead.
</description>
</method>
<method name="set_collision_layer_bit">
diff --git a/doc/classes/BaseButton.xml b/doc/classes/BaseButton.xml
index 7f1aaa6822..9dd3cf0eff 100644
--- a/doc/classes/BaseButton.xml
+++ b/doc/classes/BaseButton.xml
@@ -21,7 +21,7 @@
<method name="_toggled" qualifiers="virtual">
<return type="void">
</return>
- <argument index="0" name="pressed" type="bool">
+ <argument index="0" name="button_pressed" type="bool">
</argument>
<description>
Called when button is toggled (only if toggle_mode is active).
@@ -82,7 +82,7 @@
</description>
</signal>
<signal name="toggled">
- <argument index="0" name="pressed" type="bool">
+ <argument index="0" name="button_pressed" type="bool">
</argument>
<description>
This signal is emitted when the button was just toggled between pressed and normal states (only if toggle_mode is active). The new state is contained in the [i]pressed[/i] argument.
diff --git a/doc/classes/Color.xml b/doc/classes/Color.xml
index 6fa7ed0a86..ef555537a1 100644
--- a/doc/classes/Color.xml
+++ b/doc/classes/Color.xml
@@ -5,6 +5,7 @@
</brief_description>
<description>
A color is represented as red, green and blue (r,g,b) components. Additionally, "a" represents the alpha component, often used for transparency. Values are in floating point and usually range from 0 to 1. Some methods (such as set_modulate(color)) may accept values &gt; 1.
+ You can also create a color from standardised color names with [method @GDScript.ColorN].
</description>
<tutorials>
</tutorials>
@@ -63,7 +64,7 @@
<argument index="0" name="from" type="String">
</argument>
<description>
- Constructs a color from an HTML hexadecimal color string in ARGB or RGB format.
+ Constructs a color from an HTML hexadecimal color string in ARGB or RGB format. See also [method @GDScript.ColorN].
The following string formats are supported:
[code]"#ff00ff00"[/code] - ARGB format with '#'
[code]"ff00ff00"[/code] - ARGB format
diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml
index 680e008ff1..214f78afab 100644
--- a/doc/classes/Control.xml
+++ b/doc/classes/Control.xml
@@ -632,7 +632,7 @@
Distance between the node's top edge and its parent container, based on [member anchor_top].
</member>
<member name="mouse_filter" type="int" setter="set_mouse_filter" getter="get_mouse_filter" enum="Control.MouseFilter">
- Controls whether the control will be able to receive mouse button input events through [Control._gui_input] and how these events should be handled. Use one of the [code]MOUSE_FILTER_*[/code] constants. See the constants to learn what each does.
+ Controls whether the control will be able to receive mouse button input events through [method _gui_input] and how these events should be handled. Use one of the [code]MOUSE_FILTER_*[/code] constants. See the constants to learn what each does.
</member>
<member name="rect_clip_content" type="bool" setter="set_clip_contents" getter="is_clipping_contents">
</member>
@@ -697,12 +697,12 @@
</signal>
<signal name="mouse_entered">
<description>
- Emitted when the mouse enters the control's [code]Rect[/code] area.
+ Emitted when the mouse enters the control's [code]Rect[/code] area, provided its [member mouse_filter] lets the event reach it.
</description>
</signal>
<signal name="mouse_exited">
<description>
- Emitted when the mouse leaves the control's [code]Rect[/code] area.
+ Emitted when the mouse leaves the control's [code]Rect[/code] area, provided its [member mouse_filter] lets the event reach it.
</description>
</signal>
<signal name="resized">
@@ -870,13 +870,13 @@
Tells the parent [Container] to align the node with its end, either the bottom or the right edge. It doesn't work with the fill or expand size flags. Use with [member size_flags_horizontal] and [member size_flags_vertical].
</constant>
<constant name="MOUSE_FILTER_STOP" value="0" enum="MouseFilter">
- The control will receive mouse button input events through [method Control._gui_input] if clicked on. These events are automatically marked as handled and they will not propogate further to other controls.
+ The control will receive mouse button input events through [method _gui_input] if clicked on. These events are automatically marked as handled and they will not propagate further to other controls.
</constant>
<constant name="MOUSE_FILTER_PASS" value="1" enum="MouseFilter">
- The control will receive mouse button input events through [method Control._gui_input] if clicked on. If this control does not handle the event, the parent control (if any) will be considered for a mouse click, and so on until there is no more parent control to potentially handle it. Even if no control handled it at all, the event will still be handled automatically.
+ The control will receive mouse button input events through [method _gui_input] if clicked on. If this control does not handle the event, the parent control (if any) will be considered for a mouse click, and so on until there is no more parent control to potentially handle it. Even if no control handled it at all, the event will still be handled automatically.
</constant>
<constant name="MOUSE_FILTER_IGNORE" value="2" enum="MouseFilter">
- The control will not receive mouse button input events through [method Control._gui_input] and will not block other controls from receiving these events. These events will also not be handled automatically.
+ The control will not receive mouse button input events through [method _gui_input] and will not block other controls from receiving these events. These events will also not be handled automatically.
</constant>
<constant name="GROW_DIRECTION_BEGIN" value="0" enum="GrowDirection">
</constant>
diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml
index 174b62fde0..da6ecebcba 100644
--- a/doc/classes/EditorSettings.xml
+++ b/doc/classes/EditorSettings.xml
@@ -126,6 +126,8 @@
</argument>
<argument index="1" name="value" type="Variant">
</argument>
+ <argument index="2" name="update_current" type="bool">
+ </argument>
<description>
</description>
</method>
diff --git a/doc/classes/KinematicBody.xml b/doc/classes/KinematicBody.xml
index d1dc236d40..92d648537c 100644
--- a/doc/classes/KinematicBody.xml
+++ b/doc/classes/KinematicBody.xml
@@ -82,7 +82,7 @@
<description>
Moves the body along a vector. If the body collides with another, it will slide along the other body rather than stop immediately. If the other body is a [code]KinematicBody[/code] or [RigidBody], it will also be affected by the motion of the other body. You can use this to make moving or rotating platforms, or to make nodes push other nodes.
[code]linear_velocity[/code] is a value in pixels per second. Unlike in for example [method move_and_collide], you should [i]not[/i] multiply it with [code]delta[/code] — this is done by the method.
- [code]floor_normal[/code] is the up direction, used to determine what is a wall and what is a floor or a ceiling. If set to the default value of [code]Vector2(0, 0)[/code], everything is considered a wall. This is useful for topdown games.
+ [code]floor_normal[/code] is the up direction, used to determine what is a wall and what is a floor or a ceiling. If set to the default value of [code]Vector3(0, 0, 0)[/code], everything is considered a wall. This is useful for topdown games.
If the body is standing on a slope and the horizontal speed (relative to the floor's speed) goes below [code]slope_stop_min_velocity[/code], the body will stop completely. This prevents the body from sliding down slopes when you include gravity in [code]linear_velocity[/code]. When set to lower values, the body will not be able to stand still on steep slopes.
If the body collides, it will change direction a maximum of [code]max_bounces[/code] times before it stops.
[code]floor_max_angle[/code] is the maximum angle (in radians) where a slope is still considered a floor (or a ceiling), rather than a wall. The default value equals 45 degrees.
diff --git a/doc/classes/Label.xml b/doc/classes/Label.xml
index 089b81164b..bfc130634d 100644
--- a/doc/classes/Label.xml
+++ b/doc/classes/Label.xml
@@ -5,6 +5,7 @@
</brief_description>
<description>
Label displays plain text on the screen. It gives you control over the horizontal and vertical alignment, and can wrap the text inside the node's bounding rectangle. It doesn't support bold, italics or other formatting. For that, use [RichTextLabel] instead.
+ Note that contrarily to most other [Control]s, Label's [member Control.mouse_filter] defaults to MOUSE_FILTER_IGNORE (i.e. it doesn't react to mouse input events).
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml
index 4434a7b7e2..c28b722eb3 100644
--- a/doc/classes/LineEdit.xml
+++ b/doc/classes/LineEdit.xml
@@ -131,14 +131,14 @@
</members>
<signals>
<signal name="text_changed">
- <argument index="0" name="text" type="String">
+ <argument index="0" name="new_text" type="String">
</argument>
<description>
Emitted when the text changes.
</description>
</signal>
<signal name="text_entered">
- <argument index="0" name="text" type="String">
+ <argument index="0" name="new_text" type="String">
</argument>
<description>
Emitted when the user presses KEY_ENTER on the [code]LineEdit[/code].
diff --git a/doc/classes/RigidBody.xml b/doc/classes/RigidBody.xml
index 3c54f29c15..335112f5d7 100644
--- a/doc/classes/RigidBody.xml
+++ b/doc/classes/RigidBody.xml
@@ -39,7 +39,7 @@
<return type="Array">
</return>
<description>
- Return a list of the bodies colliding with this one. By default, number of max contacts reported is at 0 , see [method set_max_contacts_reported] to increase it.
+ Return a list of the bodies colliding with this one. By default, number of max contacts reported is at 0 , see [method set_max_contacts_reported] to increase it. Note that the result of this test is not immediate after moving objects. For performance, list of collisions is updated once per frame and before the physics step. Consider using signals instead.
</description>
</method>
<method name="set_axis_velocity">
diff --git a/doc/classes/RigidBody2D.xml b/doc/classes/RigidBody2D.xml
index c11e118df5..991e0fa3f4 100644
--- a/doc/classes/RigidBody2D.xml
+++ b/doc/classes/RigidBody2D.xml
@@ -67,7 +67,7 @@
<return type="Array">
</return>
<description>
- Returns a list of the bodies colliding with this one. Use [member contacts_reported] to set the maximum number reported. You must also set [member contact_monitor] to [code]true[/code].
+ Returns a list of the bodies colliding with this one. Use [member contacts_reported] to set the maximum number reported. You must also set [member contact_monitor] to [code]true[/code]. Note that the result of this test is not immediate after moving objects. For performance, list of collisions is updated once per frame and before the physics step. Consider using signals instead.
</description>
</method>
<method name="get_inertia" qualifiers="const">
diff --git a/doc/classes/UndoRedo.xml b/doc/classes/UndoRedo.xml
index f0d69b9b7f..3cd88dafe3 100644
--- a/doc/classes/UndoRedo.xml
+++ b/doc/classes/UndoRedo.xml
@@ -108,12 +108,6 @@
Get the name of the current action.
</description>
</method>
- <method name="get_max_steps" qualifiers="const">
- <return type="int">
- </return>
- <description>
- </description>
- </method>
<method name="get_version" qualifiers="const">
<return type="int">
</return>
@@ -128,14 +122,6 @@
<description>
</description>
</method>
- <method name="set_max_steps">
- <return type="void">
- </return>
- <argument index="0" name="max_steps" type="int">
- </argument>
- <description>
- </description>
- </method>
<method name="undo">
<return type="void">
</return>
diff --git a/doc/classes/VehicleBody.xml b/doc/classes/VehicleBody.xml
index 77916a7e9f..4256ddd674 100644
--- a/doc/classes/VehicleBody.xml
+++ b/doc/classes/VehicleBody.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VehicleBody" inherits="PhysicsBody" category="Core" version="3.0-beta">
+<class name="VehicleBody" inherits="RigidBody" category="Core" version="3.0-beta">
<brief_description>
</brief_description>
<description>
@@ -9,27 +9,12 @@
<demos>
</demos>
<methods>
- <method name="get_linear_velocity" qualifiers="const">
- <return type="Vector3">
- </return>
- <description>
- Returns the VehicleBody's velocity vector. To get the absolute speed in scalar value, get the length of the return vector in pixels/second. Example:
- [codeblock]
- # vehicle is an instance of VehicleBody
- var speed = vehicle.get_linear_velocity().length()
- [/codeblock]
- </description>
- </method>
</methods>
<members>
<member name="brake" type="float" setter="set_brake" getter="get_brake">
</member>
<member name="engine_force" type="float" setter="set_engine_force" getter="get_engine_force">
</member>
- <member name="friction" type="float" setter="set_friction" getter="get_friction">
- </member>
- <member name="mass" type="float" setter="set_mass" getter="get_mass">
- </member>
<member name="steering" type="float" setter="set_steering" getter="get_steering">
</member>
</members>
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index 4dcbdf4190..37a2450377 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -1175,28 +1175,46 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
} else {
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
}
} break;
case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_ADD: {
glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_SRC_ALPHA, GL_ONE);
+ } else {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
+ }
} break;
case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_SUB: {
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_SRC_ALPHA, GL_ONE);
+ } else {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
+ }
} break;
case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MUL: {
glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_DST_COLOR, GL_ZERO);
+ if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
+ glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_DST_ALPHA, GL_ZERO);
+ } else {
+ glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ZERO, GL_ONE);
+ }
+
} break;
case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_PMALPHA: {
glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
+ glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ } else {
+ glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
+ }
+
} break;
}
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index 99ba0860bd..b43deab58f 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -345,7 +345,7 @@ void RasterizerGLES3::blit_render_target_to_screen(RID p_render_target, const Re
glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->fbo);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
- glBlitFramebuffer(0, 0, rt->width, rt->height, p_screen_rect.position.x, win_size.height - p_screen_rect.position.y - p_screen_rect.size.height, p_screen_rect.position.x + p_screen_rect.size.width, win_size.height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ glBlitFramebuffer(0, 0, rt->width, rt->height, p_screen_rect.position.x, win_size.height - p_screen_rect.position.y - p_screen_rect.size.height, p_screen_rect.position.x + p_screen_rect.size.width, win_size.height - p_screen_rect.position.y, GL_COLOR_BUFFER_BIT, GL_NEAREST);
#else
canvas->canvas_begin();
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index b63ebcba54..3255726c1f 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -7251,8 +7251,6 @@ void RasterizerStorageGLES3::initialize() {
config.force_vertex_shading = GLOBAL_GET("rendering/quality/shading/force_vertex_shading");
- GLOBAL_DEF("rendering/quality/depth_prepass/disable", false);
-
String renderer = (const char *)glGetString(GL_RENDERER);
config.no_depth_prepass = !bool(GLOBAL_GET("rendering/quality/depth_prepass/enable"));
diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp
index 875946f089..ada7acb879 100644
--- a/drivers/gles3/shader_compiler_gles3.cpp
+++ b/drivers/gles3/shader_compiler_gles3.cpp
@@ -715,7 +715,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_CANVAS_ITEM].renames["WORLD_MATRIX"] = "modelview_matrix";
actions[VS::SHADER_CANVAS_ITEM].renames["PROJECTION_MATRIX"] = "projection_matrix";
- actions[VS::SHADER_CANVAS_ITEM].renames["EXTRA_MATRIX"] == "extra_matrix";
+ actions[VS::SHADER_CANVAS_ITEM].renames["EXTRA_MATRIX"] = "extra_matrix";
actions[VS::SHADER_CANVAS_ITEM].renames["TIME"] = "time";
actions[VS::SHADER_CANVAS_ITEM].renames["AT_LIGHT_PASS"] = "at_light_pass";
actions[VS::SHADER_CANVAS_ITEM].renames["INSTANCE_CUSTOM"] = "instance_custom";
diff --git a/drivers/gles3/shaders/effect_blur.glsl b/drivers/gles3/shaders/effect_blur.glsl
index b5f98a1244..c8567b4d53 100644
--- a/drivers/gles3/shaders/effect_blur.glsl
+++ b/drivers/gles3/shaders/effect_blur.glsl
@@ -214,7 +214,7 @@ void main() {
vec4 color_accum = vec4(0.0);
- float max_accum=0;
+ float max_accum=0.0;
for(int i=0;i<dof_kernel_size;i++) {
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 1aa28d0fd5..d3644bffdd 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -904,7 +904,7 @@ float G_GGX_anisotropic_2cos(float cos_theta_m, float alpha_x, float alpha_y, fl
float sin2 = (1.0-cos2);
float s_x = alpha_x * cos_phi;
float s_y = alpha_y * sin_phi;
- return 1.0 / (cos_theta_m + sqrt(cos2 + (s_x*s_x + s_y*s_y)*sin2 ));
+ return 1.0 / max(cos_theta_m + sqrt(cos2 + (s_x*s_x + s_y*s_y)*sin2 ), 0.001);
}
float D_GGX_anisotropic(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) {
@@ -913,7 +913,7 @@ float D_GGX_anisotropic(float cos_theta_m, float alpha_x, float alpha_y, float c
float r_x = cos_phi/alpha_x;
float r_y = sin_phi/alpha_y;
float d = cos2 + sin2*(r_x * r_x + r_y * r_y);
- return 1.0 / (M_PI * alpha_x * alpha_y * d * d );
+ return 1.0 / max(M_PI * alpha_x * alpha_y * d * d, 0.001);
}
@@ -1307,7 +1307,7 @@ void reflection_process(int idx, vec3 vertex, vec3 normal,vec3 binormal, vec3 ta
//make blend more rounded
blend=mix(length(inner_pos),blend,blend);
blend*=blend;
- blend=1.001-blend;
+ blend=max(0.0, 1.0-blend);
if (reflections[idx].params.x>0.0){// compute reflection
@@ -1476,7 +1476,7 @@ void gi_probe_compute(mediump sampler3D probe, mat4 probe_xform, vec3 bounds,vec
}
vec3 blendv = abs(probe_pos/bounds * 2.0 - 1.0);
- float blend = 1.001-max(blendv.x,max(blendv.y,blendv.z));
+ float blend = clamp(1.0-max(blendv.x,max(blendv.y,blendv.z)), 0.0, 1.0);
//float blend=1.0;
float max_distance = length(bounds);
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 0f30e3afdb..5f45f06c79 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -53,6 +53,7 @@
#if defined(__FreeBSD__) || defined(__OpenBSD__)
#include <sys/param.h>
+#include <sys/sysctl.h>
#endif
#include "project_settings.h"
#include <assert.h>
@@ -298,17 +299,7 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bo
args.push_back((char *)cs[i].get_data()); // shitty C cast
args.push_back(0);
-#ifdef __FreeBSD__
- if (p_path.find("/") != -1) {
- // exec name contains path so use it
- execv(p_path.utf8().get_data(), &args[0]);
- } else {
- // use program name and search through PATH to find it
- execvp(getprogname(), &args[0]);
- }
-#else
execvp(p_path.utf8().get_data(), &args[0]);
-#endif
// still alive? something failed..
fprintf(stderr, "**ERROR** OS_Unix::execute - Could not create child process while executing: %s\n", p_path.utf8().get_data());
abort();
@@ -462,12 +453,23 @@ String OS_Unix::get_executable_path() const {
return OS::get_executable_path();
}
return b;
-#elif defined(__FreeBSD__) || defined(__OpenBSD__)
+#elif defined(__OpenBSD__)
char resolved_path[MAXPATHLEN];
realpath(OS::get_executable_path().utf8().get_data(), resolved_path);
return String(resolved_path);
+#elif defined(__FreeBSD__)
+ int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
+ char buf[MAXPATHLEN];
+ size_t len = sizeof(buf);
+ if (sysctl(mib, 4, buf, &len, NULL, 0) != 0) {
+ WARN_PRINT("Couldn't get executable path from sysctl");
+ return OS::get_executable_path();
+ }
+ String b;
+ b.parse_utf8(buf);
+ return b;
#elif defined(__APPLE__)
char temp_path[1];
uint32_t buff_size = 1;
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index feb5bf2a8f..3e079cb3ca 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -1034,7 +1034,7 @@ void CodeTextEditor::_reset_zoom() {
Ref<DynamicFont> font = text_editor->get_font("font"); // reset source font size to default
if (font.is_valid()) {
- EditorSettings::get_singleton()->set("interface/editor/source_font_size", 14);
+ EditorSettings::get_singleton()->set("interface/editor/code_font_size", 14);
font->set_size(14);
}
}
@@ -1098,7 +1098,7 @@ bool CodeTextEditor::_add_font_size(int p_delta) {
if (font.is_valid()) {
int new_size = CLAMP(font->get_size() + p_delta, 8 * EDSCALE, 96 * EDSCALE);
if (new_size != font->get_size()) {
- EditorSettings::get_singleton()->set("interface/editor/source_font_size", new_size / EDSCALE);
+ EditorSettings::get_singleton()->set("interface/editor/code_font_size", new_size / EDSCALE);
font->set_size(new_size);
}
@@ -1140,20 +1140,7 @@ void CodeTextEditor::set_error(const String &p_error) {
void CodeTextEditor::_update_font() {
- // FONTS
- String editor_font = EDITOR_DEF("text_editor/theme/font", "");
- bool font_overridden = false;
- if (editor_font != "") {
- Ref<Font> fnt = ResourceLoader::load(editor_font);
- if (fnt.is_valid()) {
- text_editor->add_font_override("font", fnt);
- font_overridden = true;
- }
- }
- if (!font_overridden) {
-
- text_editor->add_font_override("font", get_font("source", "EditorFonts"));
- }
+ text_editor->add_font_override("font", get_font("source", "EditorFonts"));
}
void CodeTextEditor::_on_settings_change() {
diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp
index 9e8521e0fe..374688f2db 100644
--- a/editor/editor_data.cpp
+++ b/editor/editor_data.cpp
@@ -38,7 +38,7 @@
#include "project_settings.h"
#include "scene/resources/packed_scene.h"
-void EditorHistory::_cleanup_history() {
+void EditorHistory::cleanup_history() {
for (int i = 0; i < history.size(); i++) {
@@ -48,8 +48,14 @@ void EditorHistory::_cleanup_history() {
if (!history[i].path[j].ref.is_null())
continue;
- if (ObjectDB::get_instance(history[i].path[j].object))
- continue; //has isntance, try next
+ Object *obj = ObjectDB::get_instance(history[i].path[j].object);
+ if (obj) {
+ Node *n = Object::cast_to<Node>(obj);
+ if (n && n->is_inside_tree())
+ continue;
+ if (!n) // Possibly still alive
+ continue;
+ }
if (j <= history[i].level) {
//before or equal level, complete fail
@@ -152,7 +158,7 @@ bool EditorHistory::is_at_end() const {
bool EditorHistory::next() {
- _cleanup_history();
+ cleanup_history();
if ((current + 1) < history.size())
current++;
@@ -164,7 +170,7 @@ bool EditorHistory::next() {
bool EditorHistory::previous() {
- _cleanup_history();
+ cleanup_history();
if (current > 0)
current--;
diff --git a/editor/editor_data.h b/editor/editor_data.h
index eacde04134..844145853d 100644
--- a/editor/editor_data.h
+++ b/editor/editor_data.h
@@ -70,11 +70,11 @@ class EditorHistory {
Variant value;
};
- void _cleanup_history();
-
void _add_object(ObjectID p_object, const String &p_property, int p_level_change);
public:
+ void cleanup_history();
+
bool is_at_beginning() const;
bool is_at_end() const;
diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp
index c970ae355b..a58257962a 100644
--- a/editor/editor_fonts.cpp
+++ b/editor/editor_fonts.cpp
@@ -85,10 +85,24 @@ static Ref<BitmapFont> make_font(int p_height, int p_ascent, int p_valign, int p
m_name->set_spacing(DynamicFont::SPACING_BOTTOM, -EDSCALE); \
MAKE_FALLBACKS(m_name);
+#define MAKE_SOURCE_FONT(m_name, m_size) \
+ Ref<DynamicFont> m_name; \
+ m_name.instance(); \
+ m_name->set_size(m_size); \
+ if (CustomFontSource.is_valid()) { \
+ m_name->set_font_data(CustomFontSource); \
+ m_name->add_fallback(dfmono); \
+ } else { \
+ m_name->set_font_data(dfmono); \
+ } \
+ m_name->set_spacing(DynamicFont::SPACING_TOP, -EDSCALE); \
+ m_name->set_spacing(DynamicFont::SPACING_BOTTOM, -EDSCALE); \
+ MAKE_FALLBACKS(m_name);
+
void editor_register_fonts(Ref<Theme> p_theme) {
/* Custom font */
- String custom_font = EditorSettings::get_singleton()->get("interface/editor/custom_font");
+ String custom_font = EditorSettings::get_singleton()->get("interface/editor/main_font");
Ref<DynamicFontData> CustomFont;
if (custom_font.length() > 0) {
CustomFont.instance();
@@ -96,6 +110,15 @@ void editor_register_fonts(Ref<Theme> p_theme) {
CustomFont->set_force_autohinter(true); //just looks better..i think?
}
+ /* Custom source code font */
+
+ String custom_font_source = EditorSettings::get_singleton()->get("interface/editor/code_font");
+ Ref<DynamicFontData> CustomFontSource;
+ if (custom_font_source.length() > 0) {
+ CustomFontSource.instance();
+ CustomFontSource->set_font_path(custom_font_source);
+ }
+
/* Droid Sans */
Ref<DynamicFontData> DefaultFont;
@@ -135,7 +158,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
dfmono->set_font_ptr(_font_Hack_Regular, _font_Hack_Regular_size);
//dfd->set_force_autohinter(true); //just looks better..i think?
- int default_font_size = int(EditorSettings::get_singleton()->get("interface/editor/font_size")) * EDSCALE;
+ int default_font_size = int(EditorSettings::get_singleton()->get("interface/editor/main_font_size")) * EDSCALE;
MAKE_DEFAULT_FONT(df, default_font_size);
p_theme->set_default_theme_font(df);
@@ -153,41 +176,15 @@ void editor_register_fonts(Ref<Theme> p_theme) {
MAKE_DEFAULT_FONT(df_rulers, 8 * EDSCALE);
p_theme->set_font("rulers", "EditorFonts", df_rulers);
- Ref<DynamicFont> df_code;
- df_code.instance();
- df_code->set_size(int(EditorSettings::get_singleton()->get("interface/editor/source_font_size")) * EDSCALE);
- df_code->set_font_data(dfmono);
- MAKE_FALLBACKS(df_code);
-
+ MAKE_SOURCE_FONT(df_code, int(EditorSettings::get_singleton()->get("interface/editor/code_font_size")) * EDSCALE);
p_theme->set_font("source", "EditorFonts", df_code);
- Ref<DynamicFont> df_doc_code;
- df_doc_code.instance();
- df_doc_code->set_size(int(EDITOR_DEF("text_editor/help/help_source_font_size", 14)) * EDSCALE);
- df_doc_code->set_spacing(DynamicFont::SPACING_TOP, -EDSCALE);
- df_doc_code->set_spacing(DynamicFont::SPACING_BOTTOM, -EDSCALE);
- df_doc_code->set_font_data(dfmono);
- MAKE_FALLBACKS(df_doc_code);
-
+ MAKE_SOURCE_FONT(df_doc_code, int(EDITOR_DEF("text_editor/help/help_source_font_size", 14)) * EDSCALE);
p_theme->set_font("doc_source", "EditorFonts", df_doc_code);
- Ref<DynamicFont> df_output_code;
- df_output_code.instance();
- df_output_code->set_size(int(EDITOR_DEF("run/output/font_size", 13)) * EDSCALE);
- df_output_code->set_spacing(DynamicFont::SPACING_TOP, -EDSCALE);
- df_output_code->set_spacing(DynamicFont::SPACING_BOTTOM, -EDSCALE);
- df_output_code->set_font_data(dfmono);
- MAKE_FALLBACKS(df_output_code);
-
+ MAKE_SOURCE_FONT(df_output_code, int(EDITOR_DEF("run/output/font_size", 13)) * EDSCALE);
p_theme->set_font("output_source", "EditorFonts", df_output_code);
- Ref<DynamicFont> df_text_editor_status_code;
- df_text_editor_status_code.instance();
- df_text_editor_status_code->set_size(14 * EDSCALE);
- df_text_editor_status_code->set_spacing(DynamicFont::SPACING_TOP, -EDSCALE);
- df_text_editor_status_code->set_spacing(DynamicFont::SPACING_BOTTOM, -EDSCALE);
- df_text_editor_status_code->set_font_data(dfmono);
- MAKE_FALLBACKS(df_text_editor_status_code);
-
+ MAKE_SOURCE_FONT(df_text_editor_status_code, 14 * EDSCALE);
p_theme->set_font("status_source", "EditorFonts", df_text_editor_status_code);
}
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index f480883867..2b62faf218 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -1398,7 +1398,7 @@ void EditorNode::_property_editor_forward() {
}
void EditorNode::_property_editor_back() {
- if (editor_history.previous())
+ if (editor_history.previous() || editor_history.get_path_size() == 1)
_edit_current();
}
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index bcdd232260..d3e3269c42 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -281,12 +281,14 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("interface/editor/hidpi_mode", 0);
hints["interface/editor/hidpi_mode"] = PropertyInfo(Variant::INT, "interface/editor/hidpi_mode", PROPERTY_HINT_ENUM, "Auto,VeryLoDPI,LoDPI,MidDPI,HiDPI", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
_initial_set("interface/scene_tabs/show_script_button", false);
- _initial_set("interface/editor/font_size", 14);
- hints["interface/editor/font_size"] = PropertyInfo(Variant::INT, "interface/editor/font_size", PROPERTY_HINT_RANGE, "10,40,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
- _initial_set("interface/editor/source_font_size", 14);
- hints["interface/editor/source_font_size"] = PropertyInfo(Variant::INT, "interface/editor/source_font_size", PROPERTY_HINT_RANGE, "8,96,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
- _initial_set("interface/editor/custom_font", "");
- hints["interface/editor/custom_font"] = PropertyInfo(Variant::STRING, "interface/editor/custom_font", PROPERTY_HINT_GLOBAL_FILE, "*.ttf,*.otf", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
+ _initial_set("interface/editor/main_font_size", 14);
+ hints["interface/editor/main_font_size"] = PropertyInfo(Variant::INT, "interface/editor/main_font_size", PROPERTY_HINT_RANGE, "10,40,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
+ _initial_set("interface/editor/code_font_size", 14);
+ hints["interface/editor/code_font_size"] = PropertyInfo(Variant::INT, "interface/editor/code_font_size", PROPERTY_HINT_RANGE, "8,96,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
+ _initial_set("interface/editor/main_font", "");
+ hints["interface/editor/main_font"] = PropertyInfo(Variant::STRING, "interface/editor/main_font", PROPERTY_HINT_GLOBAL_FILE, "*.ttf,*.otf", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
+ _initial_set("interface/editor/code_font", "");
+ hints["interface/editor/code_font"] = PropertyInfo(Variant::STRING, "interface/editor/code_font", PROPERTY_HINT_GLOBAL_FILE, "*.ttf,*.otf", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
_initial_set("interface/editor/dim_editor_on_dialog_popup", true);
_initial_set("interface/editor/dim_amount", 0.6f);
hints["interface/editor/dim_amount"] = PropertyInfo(Variant::REAL, "interface/editor/dim_amount", PROPERTY_HINT_RANGE, "0,1,0.01", PROPERTY_USAGE_DEFAULT);
@@ -375,8 +377,6 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
hints["text_editor/cursor/caret_blink_speed"] = PropertyInfo(Variant::REAL, "text_editor/cursor/caret_blink_speed", PROPERTY_HINT_RANGE, "0.1, 10, 0.1");
_initial_set("text_editor/cursor/right_click_moves_caret", true);
- _initial_set("text_editor/theme/font", "");
- hints["text_editor/theme/font"] = PropertyInfo(Variant::STRING, "text_editor/theme/font", PROPERTY_HINT_GLOBAL_FILE, "*.font,*.tres,*.res");
_initial_set("text_editor/completion/auto_brace_complete", false);
_initial_set("text_editor/completion/put_callhint_tooltip_below_current_line", true);
_initial_set("text_editor/completion/callhint_tooltip_offset", Vector2());
@@ -992,13 +992,17 @@ void EditorSettings::raise_order(const String &p_setting) {
props[p_setting].order = ++last_order;
}
-void EditorSettings::set_initial_value(const StringName &p_setting, const Variant &p_value) {
+void EditorSettings::set_initial_value(const StringName &p_setting, const Variant &p_value, bool p_update_current) {
_THREAD_SAFE_METHOD_
if (!props.has(p_setting))
return;
- _initial_set(p_setting, p_value);
+ props[p_setting].initial = p_value;
+ props[p_setting].has_default_value = true;
+ if (p_update_current) {
+ set(p_setting, p_value);
+ }
}
Variant _EDITOR_DEF(const String &p_setting, const Variant &p_default) {
@@ -1432,7 +1436,7 @@ void EditorSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_setting", "name", "value"), &EditorSettings::set_setting);
ClassDB::bind_method(D_METHOD("get_setting", "name"), &EditorSettings::get_setting);
ClassDB::bind_method(D_METHOD("erase", "property"), &EditorSettings::erase);
- ClassDB::bind_method(D_METHOD("set_initial_value", "name", "value"), &EditorSettings::set_initial_value);
+ ClassDB::bind_method(D_METHOD("set_initial_value", "name", "value", "update_current"), &EditorSettings::set_initial_value);
ClassDB::bind_method(D_METHOD("property_can_revert", "name"), &EditorSettings::property_can_revert);
ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &EditorSettings::property_get_revert);
ClassDB::bind_method(D_METHOD("add_property_info", "info"), &EditorSettings::_add_property_info_bind);
diff --git a/editor/editor_settings.h b/editor/editor_settings.h
index 5fc49de0a7..914316ee61 100644
--- a/editor/editor_settings.h
+++ b/editor/editor_settings.h
@@ -145,7 +145,7 @@ public:
bool has_setting(const String &p_setting) const;
void erase(const String &p_setting);
void raise_order(const String &p_setting);
- void set_initial_value(const StringName &p_setting, const Variant &p_value);
+ void set_initial_value(const StringName &p_setting, const Variant &p_value, bool update_current = false);
void set_manually(const StringName &p_setting, const Variant &p_value, bool p_emit_signal = false) {
if (p_emit_signal)
_set(p_setting, p_value);
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 0ebcef8e5e..9fda9d2ff6 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -1063,38 +1063,67 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
EditorSettings *setting = EditorSettings::get_singleton();
String text_editor_color_theme = setting->get("text_editor/theme/color_theme");
if (text_editor_color_theme == "Adaptive") {
- setting->set_initial_value("text_editor/highlighting/symbol_color", symbol_color);
- setting->set_initial_value("text_editor/highlighting/keyword_color", keyword_color);
- setting->set_initial_value("text_editor/highlighting/base_type_color", basetype_color);
- setting->set_initial_value("text_editor/highlighting/engine_type_color", type_color);
- setting->set_initial_value("text_editor/highlighting/comment_color", comment_color);
- setting->set_initial_value("text_editor/highlighting/string_color", string_color);
- setting->set_initial_value("text_editor/highlighting/background_color", background_color);
- setting->set_initial_value("text_editor/highlighting/completion_background_color", completion_background_color);
- setting->set_initial_value("text_editor/highlighting/completion_selected_color", completion_selected_color);
- setting->set_initial_value("text_editor/highlighting/completion_existing_color", completion_existing_color);
- setting->set_initial_value("text_editor/highlighting/completion_scroll_color", completion_scroll_color);
- setting->set_initial_value("text_editor/highlighting/completion_font_color", completion_font_color);
- setting->set_initial_value("text_editor/highlighting/text_color", text_color);
- setting->set_initial_value("text_editor/highlighting/line_number_color", line_number_color);
- setting->set_initial_value("text_editor/highlighting/caret_color", caret_color);
- setting->set_initial_value("text_editor/highlighting/caret_background_color", caret_background_color);
- setting->set_initial_value("text_editor/highlighting/text_selected_color", text_selected_color);
- setting->set_initial_value("text_editor/highlighting/selection_color", selection_color);
- setting->set_initial_value("text_editor/highlighting/brace_mismatch_color", brace_mismatch_color);
- setting->set_initial_value("text_editor/highlighting/current_line_color", current_line_color);
- setting->set_initial_value("text_editor/highlighting/line_length_guideline_color", line_length_guideline_color);
- setting->set_initial_value("text_editor/highlighting/word_highlighted_color", word_highlighted_color);
- setting->set_initial_value("text_editor/highlighting/number_color", number_color);
- setting->set_initial_value("text_editor/highlighting/function_color", function_color);
- setting->set_initial_value("text_editor/highlighting/member_variable_color", member_variable_color);
- setting->set_initial_value("text_editor/highlighting/mark_color", mark_color);
- setting->set_initial_value("text_editor/highlighting/breakpoint_color", breakpoint_color);
- setting->set_initial_value("text_editor/highlighting/code_folding_color", code_folding_color);
- setting->set_initial_value("text_editor/highlighting/search_result_color", search_result_color);
- setting->set_initial_value("text_editor/highlighting/search_result_border_color", search_result_border_color);
+ setting->set_initial_value("text_editor/highlighting/symbol_color", symbol_color, true);
+ setting->set_initial_value("text_editor/highlighting/keyword_color", keyword_color, true);
+ setting->set_initial_value("text_editor/highlighting/base_type_color", basetype_color, true);
+ setting->set_initial_value("text_editor/highlighting/engine_type_color", type_color, true);
+ setting->set_initial_value("text_editor/highlighting/comment_color", comment_color, true);
+ setting->set_initial_value("text_editor/highlighting/string_color", string_color, true);
+ setting->set_initial_value("text_editor/highlighting/background_color", background_color, true);
+ setting->set_initial_value("text_editor/highlighting/completion_background_color", completion_background_color, true);
+ setting->set_initial_value("text_editor/highlighting/completion_selected_color", completion_selected_color, true);
+ setting->set_initial_value("text_editor/highlighting/completion_existing_color", completion_existing_color, true);
+ setting->set_initial_value("text_editor/highlighting/completion_scroll_color", completion_scroll_color, true);
+ setting->set_initial_value("text_editor/highlighting/completion_font_color", completion_font_color, true);
+ setting->set_initial_value("text_editor/highlighting/text_color", text_color, true);
+ setting->set_initial_value("text_editor/highlighting/line_number_color", line_number_color, true);
+ setting->set_initial_value("text_editor/highlighting/caret_color", caret_color, true);
+ setting->set_initial_value("text_editor/highlighting/caret_background_color", caret_background_color, true);
+ setting->set_initial_value("text_editor/highlighting/text_selected_color", text_selected_color, true);
+ setting->set_initial_value("text_editor/highlighting/selection_color", selection_color, true);
+ setting->set_initial_value("text_editor/highlighting/brace_mismatch_color", brace_mismatch_color, true);
+ setting->set_initial_value("text_editor/highlighting/current_line_color", current_line_color, true);
+ setting->set_initial_value("text_editor/highlighting/line_length_guideline_color", line_length_guideline_color, true);
+ setting->set_initial_value("text_editor/highlighting/word_highlighted_color", word_highlighted_color, true);
+ setting->set_initial_value("text_editor/highlighting/number_color", number_color, true);
+ setting->set_initial_value("text_editor/highlighting/function_color", function_color, true);
+ setting->set_initial_value("text_editor/highlighting/member_variable_color", member_variable_color, true);
+ setting->set_initial_value("text_editor/highlighting/mark_color", mark_color, true);
+ setting->set_initial_value("text_editor/highlighting/breakpoint_color", breakpoint_color, true);
+ setting->set_initial_value("text_editor/highlighting/code_folding_color", code_folding_color, true);
+ setting->set_initial_value("text_editor/highlighting/search_result_color", search_result_color, true);
+ setting->set_initial_value("text_editor/highlighting/search_result_border_color", search_result_border_color, true);
} else if (text_editor_color_theme == "Default") {
- setting->load_text_editor_theme();
+ setting->set_initial_value("text_editor/highlighting/symbol_color", Color::html("badfff"), true);
+ setting->set_initial_value("text_editor/highlighting/keyword_color", Color::html("ffffb3"), true);
+ setting->set_initial_value("text_editor/highlighting/base_type_color", Color::html("a4ffd4"), true);
+ setting->set_initial_value("text_editor/highlighting/engine_type_color", Color::html("83d3ff"), true);
+ setting->set_initial_value("text_editor/highlighting/comment_color", Color::html("676767"), true);
+ setting->set_initial_value("text_editor/highlighting/string_color", Color::html("ef6ebe"), true);
+ setting->set_initial_value("text_editor/highlighting/background_color", Color::html("3b000000"), true);
+ setting->set_initial_value("text_editor/highlighting/completion_background_color", Color::html("2C2A32"), true);
+ setting->set_initial_value("text_editor/highlighting/completion_selected_color", Color::html("434244"), true);
+ setting->set_initial_value("text_editor/highlighting/completion_existing_color", Color::html("21dfdfdf"), true);
+ setting->set_initial_value("text_editor/highlighting/completion_scroll_color", Color::html("ffffff"), true);
+ setting->set_initial_value("text_editor/highlighting/completion_font_color", Color::html("aaaaaa"), true);
+ setting->set_initial_value("text_editor/highlighting/text_color", Color::html("aaaaaa"), true);
+ setting->set_initial_value("text_editor/highlighting/line_number_color", Color::html("66aaaaaa"), true);
+ setting->set_initial_value("text_editor/highlighting/caret_color", Color::html("aaaaaa"), true);
+ setting->set_initial_value("text_editor/highlighting/caret_background_color", Color::html("000000"), true);
+ setting->set_initial_value("text_editor/highlighting/text_selected_color", Color::html("000000"), true);
+ setting->set_initial_value("text_editor/highlighting/selection_color", Color::html("6ca9c2"), true);
+ setting->set_initial_value("text_editor/highlighting/brace_mismatch_color", Color(1, 0.2, 0.2), true);
+ setting->set_initial_value("text_editor/highlighting/current_line_color", Color(0.3, 0.5, 0.8, 0.15), true);
+ setting->set_initial_value("text_editor/highlighting/line_length_guideline_color", Color(0.3, 0.5, 0.8, 0.1), true);
+ setting->set_initial_value("text_editor/highlighting/word_highlighted_color", Color(0.8, 0.9, 0.9, 0.15), true);
+ setting->set_initial_value("text_editor/highlighting/number_color", Color::html("EB9532"), true);
+ setting->set_initial_value("text_editor/highlighting/function_color", Color::html("66a2ce"), true);
+ setting->set_initial_value("text_editor/highlighting/member_variable_color", Color::html("e64e59"), true);
+ setting->set_initial_value("text_editor/highlighting/mark_color", Color(1.0, 0.4, 0.4, 0.4), true);
+ setting->set_initial_value("text_editor/highlighting/breakpoint_color", Color(0.8, 0.8, 0.4, 0.2), true);
+ setting->set_initial_value("text_editor/highlighting/code_folding_color", Color(0.8, 0.8, 0.8, 0.8), true);
+ setting->set_initial_value("text_editor/highlighting/search_result_color", Color(0.05, 0.25, 0.05, 1), true);
+ setting->set_initial_value("text_editor/highlighting/search_result_border_color", Color(0.1, 0.45, 0.1, 1), true);
}
return theme;
diff --git a/editor/import/resource_importer_bitmask.cpp b/editor/import/resource_importer_bitmask.cpp
index 3d2959c598..a5d3959952 100644
--- a/editor/import/resource_importer_bitmask.cpp
+++ b/editor/import/resource_importer_bitmask.cpp
@@ -77,7 +77,7 @@ Error ResourceImporterBitMap::import(const String &p_source_file, const String &
bit = c.a > threshold;
}
- bitmap->set_bit(Vector2(i, j), bit);
+ bitmap->set_bit(Vector2(j, i), bit);
}
}
diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp
index 12aa0bb33c..03155b3a48 100644
--- a/editor/import/resource_importer_wav.cpp
+++ b/editor/import/resource_importer_wav.cpp
@@ -268,9 +268,15 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
for (int i = 0; i < 10; i++)
file->get_32(); // i wish to know why should i do this... no doc!
- loop = file->get_32() ? AudioStreamSample::LOOP_PING_PONG : AudioStreamSample::LOOP_FORWARD;
- loop_begin = file->get_32();
- loop_end = file->get_32();
+ // only read 0x00 (loop forward) and 0x01 (loop ping-pong) and skip anything else because
+ // it's not supported (loop backward), reserved for future uses or sampler specific
+ // from https://sites.google.com/site/musicgapi/technical-documents/wav-file-format#smpl (loop type values table)
+ int loop_type = file->get_32();
+ if (loop_type == 0x00 || loop_type == 0x01) {
+ loop = loop_type ? AudioStreamSample::LOOP_PING_PONG : AudioStreamSample::LOOP_FORWARD;
+ loop_begin = file->get_32();
+ loop_end = file->get_32();
+ }
}
file->seek(file_pos + chunksize);
}
diff --git a/editor/plugins/baked_lightmap_editor_plugin.cpp b/editor/plugins/baked_lightmap_editor_plugin.cpp
index af175c3493..59b79bd070 100644
--- a/editor/plugins/baked_lightmap_editor_plugin.cpp
+++ b/editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -90,7 +90,7 @@ void BakedLightmapEditorPlugin::bake_func_begin(int p_steps) {
bool BakedLightmapEditorPlugin::bake_func_step(int p_step, const String &p_description) {
ERR_FAIL_COND_V(tmp_progress == NULL, false);
- return tmp_progress->step(p_description, p_step);
+ return tmp_progress->step(p_description, p_step, false);
}
void BakedLightmapEditorPlugin::bake_func_end() {
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 2a46aba207..bd5e5c7355 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -4435,6 +4435,7 @@ void CanvasItemEditorViewport::_on_change_type_closed() {
void CanvasItemEditorViewport::_create_preview(const Vector<String> &files) const {
label->set_position(get_global_position() + Point2(14, 14) * EDSCALE);
label_desc->set_position(label->get_position() + Point2(0, label->get_size().height));
+ bool add_preview = false;
for (int i = 0; i < files.size(); i++) {
String path = files[i];
RES res = ResourceLoader::load(path);
@@ -4456,9 +4457,12 @@ void CanvasItemEditorViewport::_create_preview(const Vector<String> &files) cons
}
}
}
- editor->get_scene_root()->add_child(preview_node);
+ add_preview = true;
}
}
+
+ if (add_preview)
+ editor->get_scene_root()->add_child(preview_node);
}
void CanvasItemEditorViewport::_remove_preview() {
@@ -4603,6 +4607,14 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons
void CanvasItemEditorViewport::_perform_drop_data() {
_remove_preview();
+ // Without root dropping multiple files is not allowed
+ if (!target_node && selected_files.size() > 1) {
+ accept->get_ok()->set_text(TTR("Ok"));
+ accept->set_text(TTR("Cannot instantiate multiple nodes without root."));
+ accept->popup_centered_minsize();
+ return;
+ }
+
Vector<String> error_files;
editor_data->get_undo_redo().create_action(TTR("Create Node"));
@@ -4613,30 +4625,40 @@ void CanvasItemEditorViewport::_perform_drop_data() {
if (res.is_null()) {
continue;
}
- Ref<Texture> texture = Ref<Texture>(Object::cast_to<Texture>(*res));
Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
- if (texture != NULL) {
- Node *child;
- if (default_type == "Light2D")
- child = memnew(Light2D);
- else if (default_type == "Particles2D")
- child = memnew(Particles2D);
- else if (default_type == "Polygon2D")
- child = memnew(Polygon2D);
- else if (default_type == "TouchScreenButton")
- child = memnew(TouchScreenButton);
- else if (default_type == "TextureRect")
- child = memnew(TextureRect);
- else if (default_type == "NinePatchRect")
- child = memnew(NinePatchRect);
- else
- child = memnew(Sprite); // default
-
- _create_nodes(target_node, child, path, drop_pos);
- } else if (scene != NULL) {
- bool success = _create_instance(target_node, path, drop_pos);
- if (!success) {
- error_files.push_back(path);
+ if (scene != NULL && scene.is_valid()) {
+ if (!target_node) {
+ // Without root node act the same as "Load Inherited Scene"
+ Error err = EditorNode::get_singleton()->load_scene(path, false, true);
+ if (err != OK) {
+ error_files.push_back(path);
+ }
+ } else {
+ bool success = _create_instance(target_node, path, drop_pos);
+ if (!success) {
+ error_files.push_back(path);
+ }
+ }
+ } else {
+ Ref<Texture> texture = Ref<Texture>(Object::cast_to<Texture>(*res));
+ if (texture != NULL && texture.is_valid()) {
+ Node *child;
+ if (default_type == "Light2D")
+ child = memnew(Light2D);
+ else if (default_type == "Particles2D")
+ child = memnew(Particles2D);
+ else if (default_type == "Polygon2D")
+ child = memnew(Polygon2D);
+ else if (default_type == "TouchScreenButton")
+ child = memnew(TouchScreenButton);
+ else if (default_type == "TextureRect")
+ child = memnew(TextureRect);
+ else if (default_type == "NinePatchRect")
+ child = memnew(NinePatchRect);
+ else
+ child = memnew(Sprite); // default
+
+ _create_nodes(target_node, child, path, drop_pos);
}
}
}
@@ -4661,14 +4683,14 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian
if (String(d["type"]) == "files") {
Vector<String> files = d["files"];
bool can_instance = false;
- for (int i = 0; i < files.size(); i++) { // check if dragged files contain resource or scene can be created at least one
+ for (int i = 0; i < files.size(); i++) { // check if dragged files contain resource or scene can be created at least once
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]);
+ Ref<PackedScene> sdata = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
Node *instanced_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
if (!instanced_scene) {
continue;
@@ -4682,7 +4704,7 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian
type == "StreamTexture" ||
type == "AtlasTexture" ||
type == "LargeTexture") {
- Ref<Texture> texture = ResourceLoader::load(files[i]);
+ Ref<Texture> texture = Ref<Texture>(Object::cast_to<Texture>(*res));
if (texture.is_valid() == false) {
continue;
}
@@ -4708,6 +4730,7 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian
}
void CanvasItemEditorViewport::_show_resource_type_selector() {
+ _remove_preview();
List<BaseButton *> btn_list;
button_group->get_buttons(&btn_list);
@@ -4719,6 +4742,17 @@ void CanvasItemEditorViewport::_show_resource_type_selector() {
selector->popup_centered_minsize();
}
+bool CanvasItemEditorViewport::_only_packed_scenes_selected() const {
+
+ for (int i = 0; i < selected_files.size(); ++i) {
+ if (ResourceLoader::load(selected_files[i])->get_class() != "PackedScene") {
+ return false;
+ }
+ }
+
+ return true;
+}
+
void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p_data) {
bool is_shift = Input::get_singleton()->is_key_pressed(KEY_SHIFT);
bool is_alt = Input::get_singleton()->is_key_pressed(KEY_ALT);
@@ -4728,6 +4762,8 @@ void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p
if (d.has("type") && String(d["type"]) == "files") {
selected_files = d["files"];
}
+ if (selected_files.size() == 0)
+ return;
List<Node *> list = editor->get_editor_selection()->get_selected_node_list();
if (list.size() == 0) {
@@ -4737,25 +4773,19 @@ void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p
} else {
drop_pos = p_point;
target_node = NULL;
- _show_resource_type_selector();
- 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();
+ if (list.size() > 0) {
+ target_node = list[0];
+ if (is_shift && target_node != editor->get_edited_scene()) {
+ target_node = target_node->get_parent();
+ }
}
+
drop_pos = p_point;
- if (is_alt) {
+ if (is_alt && !_only_packed_scenes_selected()) {
_show_resource_type_selector();
} else {
_perform_drop_data();
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index 5be71bfc28..ace87f9fe2 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -576,6 +576,7 @@ class CanvasItemEditorViewport : public Control {
void _remove_preview();
bool _cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node);
+ bool _only_packed_scenes_selected() const;
void _create_nodes(Node *parent, Node *child, String &path, const Point2 &p_point);
bool _create_instance(Node *parent, String &path, const Point2 &p_point);
void _perform_drop_data();
diff --git a/editor/plugins/gi_probe_editor_plugin.cpp b/editor/plugins/gi_probe_editor_plugin.cpp
index 42aad7a8a1..06da64b181 100644
--- a/editor/plugins/gi_probe_editor_plugin.cpp
+++ b/editor/plugins/gi_probe_editor_plugin.cpp
@@ -73,7 +73,7 @@ void GIProbeEditorPlugin::bake_func_begin(int p_steps) {
void GIProbeEditorPlugin::bake_func_step(int p_step, const String &p_description) {
ERR_FAIL_COND(tmp_progress == NULL);
- tmp_progress->step(p_description, p_step);
+ tmp_progress->step(p_description, p_step, false);
}
void GIProbeEditorPlugin::bake_func_end() {
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index bc986cee9c..f99768400f 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -313,24 +313,22 @@ void ScriptEditor::_goto_script_line2(int p_line) {
void ScriptEditor::_goto_script_line(REF p_script, int p_line) {
- editor->push_item(p_script.ptr());
+ Ref<Script> script = Object::cast_to<Script>(*p_script);
+ if (!script.is_null() && script->get_path().is_resource_file()) {
+ if (edit(p_script, p_line, 0)) {
+ editor->push_item(p_script.ptr());
- if (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor"))) {
-
- Ref<Script> script = Object::cast_to<Script>(*p_script);
- if (!script.is_null() && script->get_path().is_resource_file())
- edit(p_script, p_line, 0);
- }
-
- int selected = tab_container->get_current_tab();
- if (selected < 0 || selected >= tab_container->get_child_count())
- return;
+ int selected = tab_container->get_current_tab();
+ if (selected < 0 || selected >= tab_container->get_child_count())
+ return;
- ScriptEditorBase *current = Object::cast_to<ScriptEditorBase>(tab_container->get_child(selected));
- if (!current)
- return;
+ ScriptEditorBase *current = Object::cast_to<ScriptEditorBase>(tab_container->get_child(selected));
+ if (!current)
+ return;
- current->goto_line(p_line, true);
+ current->goto_line(p_line, true);
+ }
+ }
}
void ScriptEditor::_update_history_arrows() {
@@ -514,7 +512,6 @@ void ScriptEditor::_close_tab(int p_idx, bool p_save) {
if (p_save) {
apply_scripts();
}
- current->clear_edit_menu();
notify_script_close(current->get_edited_script());
} else {
EditorHelp *help = Object::cast_to<EditorHelp>(tab_container->get_child(selected));
@@ -540,6 +537,9 @@ void ScriptEditor::_close_tab(int p_idx, bool p_save) {
}
int idx = tab_container->get_current_tab();
+ if (current) {
+ current->clear_edit_menu();
+ }
memdelete(tselected);
if (idx >= tab_container->get_child_count())
idx = tab_container->get_child_count() - 1;
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index 535ce79b30..b677017371 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -3915,7 +3915,7 @@ void SpatialEditor::set_state(const Dictionary &p_state) {
if (d.has("snap_enabled")) {
snap_enabled = d["snap_enabled"];
- tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_pressed(d["snap_enabled"]);
+ tool_option_button[TOOL_OPT_USE_SNAP]->set_pressed(d["snap_enabled"]);
}
if (d.has("translate_snap"))
diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp
index 08679b781a..612bdb1d2a 100644
--- a/editor/plugins/tile_set_editor_plugin.cpp
+++ b/editor/plugins/tile_set_editor_plugin.cpp
@@ -583,6 +583,14 @@ void AutotileEditor::_notification(int p_what) {
}
}
+void AutotileEditor::_changed_callback(Object *p_changed, const char *p_prop) {
+ if (p_prop == StringName("texture") || p_prop == StringName("is_autotile")) {
+ edit(tile_set.ptr());
+ autotile_list->update();
+ workspace->update();
+ }
+}
+
void AutotileEditor::_on_autotile_selected(int p_index) {
if (get_current_tile() >= 0) {
@@ -1581,6 +1589,7 @@ Vector2 AutotileEditor::snap_point(const Vector2 &point) {
void AutotileEditor::edit(Object *p_node) {
tile_set = Ref<TileSet>(Object::cast_to<TileSet>(p_node));
+ tile_set->add_change_receptor(this);
helper->set_tileset(tile_set);
autotile_list->clear();
diff --git a/editor/plugins/tile_set_editor_plugin.h b/editor/plugins/tile_set_editor_plugin.h
index 9bd3e23181..93d403deea 100644
--- a/editor/plugins/tile_set_editor_plugin.h
+++ b/editor/plugins/tile_set_editor_plugin.h
@@ -124,6 +124,7 @@ class AutotileEditor : public Control {
protected:
static void _bind_methods();
void _notification(int p_what);
+ virtual void _changed_callback(Object *p_changed, const char *p_prop);
private:
void _on_autotile_selected(int p_index);
diff --git a/editor/progress_dialog.cpp b/editor/progress_dialog.cpp
index 5d79b8f94c..f735ef97db 100644
--- a/editor/progress_dialog.cpp
+++ b/editor/progress_dialog.cpp
@@ -200,7 +200,7 @@ bool ProgressDialog::task_step(const String &p_task, const String &p_state, int
if (!p_force_redraw) {
uint64_t tus = OS::get_singleton()->get_ticks_usec();
- if (tus - last_progress_tick < 50000) //50ms
+ if (tus - last_progress_tick < 200000) //200ms
return cancelled;
}
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 1f732992d5..98871d5193 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -237,13 +237,20 @@ void SceneTreeDock::_replace_with_branch_scene(const String &p_file, Node *base)
Node *parent = base->get_parent();
int pos = base->get_index();
- memdelete(base);
+ parent->remove_child(base);
parent->add_child(instanced_scene);
parent->move_child(instanced_scene, pos);
instanced_scene->set_owner(edited_scene);
editor_selection->clear();
editor_selection->add_node(instanced_scene);
scene_tree->set_selected(instanced_scene);
+
+ // Delete the node as late as possible because before another one is selected
+ // an editor plugin could be referencing it to do something with it before
+ // switching to another (or to none); and since some steps of changing the
+ // editor state are deferred, the safest thing is to do this is as the last
+ // step of this function and also by enqueing instead of memdelete()-ing it here
+ base->queue_delete();
}
bool SceneTreeDock::_cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node) {
@@ -343,8 +350,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
if (existing.is_valid()) {
const RefPtr empty;
selected->set_script(empty);
- button_create_script->show();
- button_clear_script->hide();
+ _update_script_button();
}
} break;
@@ -1204,8 +1210,7 @@ void SceneTreeDock::_script_created(Ref<Script> p_script) {
return;
selected->set_script(p_script.get_ref_ptr());
editor->push_item(p_script.operator->());
- button_create_script->hide();
- button_clear_script->show();
+ _update_script_button();
}
void SceneTreeDock::_delete_confirm() {
@@ -1285,17 +1290,15 @@ void SceneTreeDock::_delete_confirm() {
editor->get_viewport_control()->update();
editor->push_item(NULL);
-}
-void SceneTreeDock::_selection_changed() {
-
- int selection_size = EditorNode::get_singleton()->get_editor_selection()->get_selection().size();
- if (selection_size > 1) {
- //automatically turn on multi-edit
- _tool_selected(TOOL_MULTI_EDIT);
- }
+ // Fixes the EditorHistory from still offering deleted notes
+ EditorHistory *editor_history = EditorNode::get_singleton()->get_editor_history();
+ editor_history->cleanup_history();
+ EditorNode::get_singleton()->call("_prepare_history");
+}
- if (selection_size == 1) {
+void SceneTreeDock::_update_script_button() {
+ if (EditorNode::get_singleton()->get_editor_selection()->get_selection().size() == 1) {
if (EditorNode::get_singleton()->get_editor_selection()->get_selection().front()->key()->get_script().is_null()) {
button_create_script->show();
button_clear_script->hide();
@@ -1309,6 +1312,16 @@ void SceneTreeDock::_selection_changed() {
}
}
+void SceneTreeDock::_selection_changed() {
+
+ int selection_size = EditorNode::get_singleton()->get_editor_selection()->get_selection().size();
+ if (selection_size > 1) {
+ //automatically turn on multi-edit
+ _tool_selected(TOOL_MULTI_EDIT);
+ }
+ _update_script_button();
+}
+
void SceneTreeDock::_create() {
if (current_option == TOOL_NEW) {
@@ -1643,6 +1656,7 @@ void SceneTreeDock::_script_dropped(String p_file, NodePath p_to) {
Node *n = get_node(p_to);
if (n) {
n->set_script(scr.get_ref_ptr());
+ _update_script_button();
}
}
diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h
index f5234fc547..0a68aa7dc2 100644
--- a/editor/scene_tree_dock.h
+++ b/editor/scene_tree_dock.h
@@ -160,6 +160,7 @@ class SceneTreeDock : public VBoxContainer {
bool _validate_no_foreign();
void _selection_changed();
+ void _update_script_button();
void _fill_path_renames(Vector<StringName> base_path, Vector<StringName> new_base_path, Node *p_node, List<Pair<NodePath, NodePath> > *p_renames);
diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp
index e993c2fd46..629b5b63fb 100644
--- a/editor/script_editor_debugger.cpp
+++ b/editor/script_editor_debugger.cpp
@@ -1053,6 +1053,8 @@ void ScriptEditorDebugger::_notification(int p_what) {
break;
};
+ const uint64_t until = OS::get_singleton()->get_ticks_msec() + 20;
+
while (ppeer->get_available_packet_count() > 0) {
if (pending_in_queue) {
@@ -1117,6 +1119,9 @@ void ScriptEditorDebugger::_notification(int p_what) {
break;
}
}
+
+ if (OS::get_singleton()->get_ticks_msec() > until)
+ break;
}
} break;
@@ -1611,30 +1616,33 @@ void ScriptEditorDebugger::_error_selected(int p_idx) {
error_stack->clear();
Array st = error_list->get_item_metadata(p_idx);
- for (int i = 0; i < st.size(); i += 2) {
+ for (int i = 0; i < st.size(); i += 3) {
String script = st[i];
- int line = st[i + 1];
+ String func = st[i + 1];
+ int line = st[i + 2];
Array md;
md.push_back(st[i]);
md.push_back(st[i + 1]);
+ md.push_back(st[i + 2]);
- String str = script.get_file() + ":" + itos(line);
+ String str = func + " in " + script.get_file() + ":line " + itos(line);
error_stack->add_item(str);
error_stack->set_item_metadata(error_stack->get_item_count() - 1, md);
- error_stack->set_item_tooltip(error_stack->get_item_count() - 1, TTR("File:") + " " + String(st[i]) + "\n" + TTR("Line:") + " " + itos(line));
+ error_stack->set_item_tooltip(error_stack->get_item_count() - 1,
+ TTR("File:") + " " + script + "\n" + TTR("Function:") + " " + func + "\n" + TTR("Line:") + " " + itos(line));
}
}
void ScriptEditorDebugger::_error_stack_selected(int p_idx) {
Array arr = error_stack->get_item_metadata(p_idx);
- if (arr.size() != 2)
+ if (arr.size() != 3)
return;
Ref<Script> s = ResourceLoader::load(arr[0]);
- emit_signal("goto_script_line", s, int(arr[1]) - 1);
+ emit_signal("goto_script_line", s, int(arr[2]) - 1);
}
void ScriptEditorDebugger::set_hide_on_stop(bool p_hide) {
diff --git a/main/main.cpp b/main/main.cpp
index 48537dc3a7..0b231b9d30 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -1845,11 +1845,6 @@ void Main::cleanup() {
EditorNode::unregister_editor_types();
#endif
- if (audio_server) {
- audio_server->finish();
- memdelete(audio_server);
- }
-
if (arvr_server) {
// cleanup now before we pull the rug from underneath...
memdelete(arvr_server);
@@ -1861,6 +1856,11 @@ void Main::cleanup() {
unregister_scene_types();
unregister_server_types();
+ if (audio_server) {
+ audio_server->finish();
+ memdelete(audio_server);
+ }
+
OS::get_singleton()->finalize();
finalize_physics();
diff --git a/modules/bullet/collision_object_bullet.cpp b/modules/bullet/collision_object_bullet.cpp
index b3dfc2eecf..873c9c31b7 100644
--- a/modules/bullet/collision_object_bullet.cpp
+++ b/modules/bullet/collision_object_bullet.cpp
@@ -49,7 +49,9 @@
CollisionObjectBullet::ShapeWrapper::~ShapeWrapper() {}
void CollisionObjectBullet::ShapeWrapper::set_transform(const Transform &p_transform) {
+ G_TO_B(p_transform.get_basis().get_scale(), scale);
G_TO_B(p_transform, transform);
+ UNSCALE_BT_BASIS(transform);
}
void CollisionObjectBullet::ShapeWrapper::set_transform(const btTransform &p_transform) {
transform = p_transform;
@@ -235,7 +237,7 @@ void RigidCollisionObjectBullet::set_shape_transform(int p_index, const Transfor
ERR_FAIL_INDEX(p_index, get_shape_count());
shapes[p_index].set_transform(p_transform);
- on_shapes_changed();
+ on_shape_changed(shapes[p_index].shape);
}
void RigidCollisionObjectBullet::remove_shape(ShapeBullet *p_shape) {
@@ -320,7 +322,7 @@ void RigidCollisionObjectBullet::on_shapes_changed() {
shpWrapper = &shapes[i];
if (shpWrapper->active) {
if (!shpWrapper->bt_shape) {
- shpWrapper->bt_shape = shpWrapper->shape->create_bt_shape();
+ shpWrapper->bt_shape = shpWrapper->shape->create_bt_shape(shpWrapper->scale);
}
compoundShape->addChildShape(shpWrapper->transform, shpWrapper->bt_shape);
} else {
diff --git a/modules/bullet/collision_object_bullet.h b/modules/bullet/collision_object_bullet.h
index a9b8aee019..506976eabf 100644
--- a/modules/bullet/collision_object_bullet.h
+++ b/modules/bullet/collision_object_bullet.h
@@ -72,6 +72,7 @@ public:
ShapeBullet *shape;
btCollisionShape *bt_shape;
btTransform transform;
+ btVector3 scale;
bool active;
ShapeWrapper() :
@@ -102,6 +103,7 @@ public:
shape = otherShape.shape;
bt_shape = otherShape.bt_shape;
transform = otherShape.transform;
+ scale = otherShape.scale;
active = otherShape.active;
}
diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp
index 0e293a38a6..f2115a5d50 100644
--- a/modules/bullet/rigid_body_bullet.cpp
+++ b/modules/bullet/rigid_body_bullet.cpp
@@ -204,7 +204,7 @@ void RigidBodyBullet::KinematicUtilities::copyAllOwnerShapes() {
const CollisionObjectBullet::ShapeWrapper *shape_wrapper;
- btVector3 owner_body_scale(owner->get_bt_body_scale());
+ btVector3 owner_scale(owner->get_bt_body_scale());
for (int i = shapes_count - 1; 0 <= i; --i) {
shape_wrapper = &shapes_wrappers[i];
@@ -213,14 +213,14 @@ void RigidBodyBullet::KinematicUtilities::copyAllOwnerShapes() {
}
shapes[i].transform = shape_wrapper->transform;
- shapes[i].transform.getOrigin() *= owner_body_scale;
+ shapes[i].transform.getOrigin() *= owner_scale;
switch (shape_wrapper->shape->get_type()) {
case PhysicsServer::SHAPE_SPHERE:
case PhysicsServer::SHAPE_BOX:
case PhysicsServer::SHAPE_CAPSULE:
case PhysicsServer::SHAPE_CONVEX_POLYGON:
case PhysicsServer::SHAPE_RAY: {
- shapes[i].shape = static_cast<btConvexShape *>(shape_wrapper->shape->create_bt_shape(owner_body_scale, safe_margin));
+ shapes[i].shape = static_cast<btConvexShape *>(shape_wrapper->shape->create_bt_shape(owner_scale * shape_wrapper->scale, safe_margin));
} break;
default:
WARN_PRINT("This shape is not supported to be kinematic!");
diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp
index ee1cc418bc..27eac4e6ee 100644
--- a/modules/bullet/shape_bullet.cpp
+++ b/modules/bullet/shape_bullet.cpp
@@ -48,11 +48,6 @@ ShapeBullet::ShapeBullet() {}
ShapeBullet::~ShapeBullet() {}
-btCollisionShape *ShapeBullet::create_bt_shape() {
- btVector3 s(1, 1, 1);
- return create_bt_shape(s);
-}
-
btCollisionShape *ShapeBullet::create_bt_shape(const Vector3 &p_implicit_scale, real_t p_margin) {
btVector3 s;
G_TO_B(p_implicit_scale, s);
@@ -82,7 +77,7 @@ void ShapeBullet::add_owner(ShapeOwnerBullet *p_owner) {
void ShapeBullet::remove_owner(ShapeOwnerBullet *p_owner, bool p_permanentlyFromThisBody) {
Map<ShapeOwnerBullet *, int>::Element *E = owners.find(p_owner);
- ERR_FAIL_COND(!E);
+ if (!E) return;
E->get()--;
if (p_permanentlyFromThisBody || 0 >= E->get()) {
owners.erase(E);
diff --git a/modules/bullet/shape_bullet.h b/modules/bullet/shape_bullet.h
index 12fa9754bd..4a03c0f014 100644
--- a/modules/bullet/shape_bullet.h
+++ b/modules/bullet/shape_bullet.h
@@ -62,7 +62,6 @@ public:
ShapeBullet();
virtual ~ShapeBullet();
- btCollisionShape *create_bt_shape();
btCollisionShape *create_bt_shape(const Vector3 &p_implicit_scale, real_t p_margin = 0);
virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0) = 0;
diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp
index 83dd055760..d60d8ba0e2 100644
--- a/modules/bullet/space_bullet.cpp
+++ b/modules/bullet/space_bullet.cpp
@@ -857,31 +857,31 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f
btVector3 recover_initial_position(0, 0, 0);
{ /// Phase one - multi shapes depenetration using margin
for (int t(RECOVERING_MOVEMENT_CYCLES); 0 < t; --t) {
- if (recover_from_penetration(p_body, body_safe_position, RECOVERING_MOVEMENT_SCALE, recover_initial_position)) {
-
- // Add recover position to "From" and "To" transforms
- body_safe_position.getOrigin() += recover_initial_position;
- } else {
+ if (!recover_from_penetration(p_body, body_safe_position, RECOVERING_MOVEMENT_SCALE, recover_initial_position)) {
break;
}
}
+
+ // Add recover movement in order to make it safe
+ body_safe_position.getOrigin() += recover_initial_position;
}
#endif
- btVector3 recovered_motion;
- G_TO_B(p_motion, recovered_motion);
- const int shape_count(p_body->get_shape_count());
+ btVector3 motion;
+ G_TO_B(p_motion, motion);
{ /// phase two - sweep test, from a secure position without margin
+ const int shape_count(p_body->get_shape_count());
+
#if debug_test_motion
-//Vector3 sup_line;
-//B_TO_G(body_safe_position.getOrigin(), sup_line);
-//motionVec->clear();
-//motionVec->begin(Mesh::PRIMITIVE_LINES, NULL);
-//motionVec->add_vertex(sup_line);
-//motionVec->add_vertex(sup_line + p_motion * 10);
-//motionVec->end();
+ Vector3 sup_line;
+ B_TO_G(body_safe_position.getOrigin(), sup_line);
+ motionVec->clear();
+ motionVec->begin(Mesh::PRIMITIVE_LINES, NULL);
+ motionVec->add_vertex(sup_line);
+ motionVec->add_vertex(sup_line + p_motion * 10);
+ motionVec->end();
#endif
for (int shIndex = 0; shIndex < shape_count; ++shIndex) {
@@ -898,7 +898,7 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f
btTransform shape_world_from = body_safe_position * p_body->get_kinematic_utilities()->shapes[shIndex].transform;
btTransform shape_world_to(shape_world_from);
- shape_world_to.getOrigin() += recovered_motion;
+ shape_world_to.getOrigin() += motion;
GodotKinClosestConvexResultCallback btResult(shape_world_from.getOrigin(), shape_world_to.getOrigin(), p_body, IGNORE_AREAS_TRUE);
btResult.m_collisionFilterGroup = p_body->get_collision_layer();
@@ -909,27 +909,30 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f
if (btResult.hasHit()) {
/// Since for each sweep test I fix the motion of new shapes in base the recover result,
/// if another shape will hit something it means that has a deepest penetration respect the previous shape
- recovered_motion *= btResult.m_closestHitFraction;
+ motion *= btResult.m_closestHitFraction;
}
}
+
+ body_safe_position.getOrigin() += motion;
}
bool has_penetration = false;
{ /// Phase three - Recover + contact test with margin
+ btVector3 delta_recover_movement(0, 0, 0);
RecoverResult r_recover_result;
bool l_has_penetration;
real_t l_penetration_distance = 1e20;
for (int t(RECOVERING_MOVEMENT_CYCLES); 0 < t; --t) {
- l_has_penetration = recover_from_penetration(p_body, body_safe_position, RECOVERING_MOVEMENT_SCALE, recovered_motion, &r_recover_result);
+ l_has_penetration = recover_from_penetration(p_body, body_safe_position, RECOVERING_MOVEMENT_SCALE, delta_recover_movement, &r_recover_result);
if (r_result) {
#if PERFORM_INITIAL_UNSTACK
- B_TO_G(recovered_motion + recover_initial_position, r_result->motion);
+ B_TO_G(motion + delta_recover_movement + recover_initial_position, r_result->motion);
#else
- B_TO_G(recovered_motion, r_result->motion);
+ B_TO_G(motion + delta_recover_movement, r_result->motion);
#endif
if (l_has_penetration) {
has_penetration = true;
@@ -942,7 +945,8 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f
const btRigidBody *btRigid = static_cast<const btRigidBody *>(r_recover_result.other_collision_object);
CollisionObjectBullet *collisionObject = static_cast<CollisionObjectBullet *>(btRigid->getUserPointer());
- r_result->remainder = p_motion - r_result->motion; // is the remaining movements
+ B_TO_G(motion, r_result->remainder); // is the remaining movements
+ r_result->remainder = p_motion - r_result->remainder;
B_TO_G(r_recover_result.pointWorld, r_result->collision_point);
B_TO_G(r_recover_result.normal, r_result->collision_normal);
B_TO_G(btRigid->getVelocityInLocalPoint(r_recover_result.pointWorld - btRigid->getWorldTransform().getOrigin()), r_result->collider_velocity); // It calculates velocity at point and assign it using special function Bullet_to_Godot
@@ -961,17 +965,14 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f
//}
#if debug_test_motion
-//Vector3 sup_line2;
-//B_TO_G(recovered_motion, sup_line2);
-////Vector3 sup_pos;
-////B_TO_G( pt.getPositionWorldOnB(), sup_pos);
-//normalLine->clear();
-//normalLine->begin(Mesh::PRIMITIVE_LINES, NULL);
-//normalLine->add_vertex(r_result->collision_point);
-//normalLine->add_vertex(r_result->collision_point + r_result->collision_normal * 10);
-//normalLine->end();
+ Vector3 sup_line2;
+ B_TO_G(motion, sup_line2);
+ normalLine->clear();
+ normalLine->begin(Mesh::PRIMITIVE_LINES, NULL);
+ normalLine->add_vertex(r_result->collision_point);
+ normalLine->add_vertex(r_result->collision_point + r_result->collision_normal * 10);
+ normalLine->end();
#endif
-
} else {
r_result->remainder = Vector3();
}
@@ -1019,7 +1020,7 @@ public:
}
};
-bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, btVector3 &r_recover_position, RecoverResult *r_recover_result) {
+bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result) {
RecoverPenetrationBroadPhaseCallback recover_broad_result(p_body->get_bt_collision_object(), p_body->get_collision_layer(), p_body->get_collision_mask());
@@ -1043,7 +1044,7 @@ bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTran
body_shape_position = p_body_position * kin_shape.transform;
body_shape_position_recovered = body_shape_position;
- body_shape_position_recovered.getOrigin() += r_recover_position;
+ body_shape_position_recovered.getOrigin() += r_delta_recover_movement;
kin_shape.shape->getAabb(body_shape_position_recovered, minAabb, maxAabb);
dynamicsWorld->getBroadphase()->aabbTest(minAabb, maxAabb, recover_broad_result);
@@ -1060,24 +1061,24 @@ bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTran
for (int x = cs->getNumChildShapes() - 1; 0 <= x; --x) {
if (cs->getChildShape(x)->isConvex()) {
- if (RFP_convex_convex_test(kin_shape.shape, static_cast<const btConvexShape *>(cs->getChildShape(x)), otherObject, x, body_shape_position_recovered, otherObject->getWorldTransform() * cs->getChildTransform(x), p_recover_movement_scale, r_recover_position, r_recover_result)) {
+ if (RFP_convex_convex_test(kin_shape.shape, static_cast<const btConvexShape *>(cs->getChildShape(x)), otherObject, x, body_shape_position, otherObject->getWorldTransform() * cs->getChildTransform(x), p_recover_movement_scale, r_delta_recover_movement, r_recover_result)) {
penetration = true;
}
} else {
- if (RFP_convex_world_test(kin_shape.shape, cs->getChildShape(x), p_body->get_bt_collision_object(), otherObject, kinIndex, x, body_shape_position_recovered, otherObject->getWorldTransform() * cs->getChildTransform(x), p_recover_movement_scale, r_recover_position, r_recover_result)) {
+ if (RFP_convex_world_test(kin_shape.shape, cs->getChildShape(x), p_body->get_bt_collision_object(), otherObject, kinIndex, x, body_shape_position, otherObject->getWorldTransform() * cs->getChildTransform(x), p_recover_movement_scale, r_delta_recover_movement, r_recover_result)) {
penetration = true;
}
}
}
} else if (otherObject->getCollisionShape()->isConvex()) { /// Execute GJK test against object shape
- if (RFP_convex_convex_test(kin_shape.shape, static_cast<const btConvexShape *>(otherObject->getCollisionShape()), otherObject, 0, body_shape_position_recovered, otherObject->getWorldTransform(), p_recover_movement_scale, r_recover_position, r_recover_result)) {
+ if (RFP_convex_convex_test(kin_shape.shape, static_cast<const btConvexShape *>(otherObject->getCollisionShape()), otherObject, 0, body_shape_position, otherObject->getWorldTransform(), p_recover_movement_scale, r_delta_recover_movement, r_recover_result)) {
penetration = true;
}
} else {
- if (RFP_convex_world_test(kin_shape.shape, otherObject->getCollisionShape(), p_body->get_bt_collision_object(), otherObject, kinIndex, 0, body_shape_position_recovered, otherObject->getWorldTransform(), p_recover_movement_scale, r_recover_position, r_recover_result)) {
+ if (RFP_convex_world_test(kin_shape.shape, otherObject->getCollisionShape(), p_body->get_bt_collision_object(), otherObject, kinIndex, 0, body_shape_position, otherObject->getWorldTransform(), p_recover_movement_scale, r_delta_recover_movement, r_recover_result)) {
penetration = true;
}
@@ -1085,26 +1086,15 @@ bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTran
}
}
-#if debug_test_motion
- Vector3 pos;
- B_TO_G(p_body_position.getOrigin(), pos);
- Vector3 sup_line;
- B_TO_G(sum_recover_normals, sup_line);
- motionVec->clear();
- motionVec->begin(Mesh::PRIMITIVE_LINES, NULL);
- motionVec->add_vertex(pos);
- motionVec->add_vertex(pos + (sup_line * 10));
- motionVec->end();
-#endif
-
return penetration;
}
-bool SpaceBullet::RFP_convex_convex_test(const btConvexShape *p_shapeA, const btConvexShape *p_shapeB, btCollisionObject *p_objectB, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_recover_movement_scale, btVector3 &r_recover_position, RecoverResult *r_recover_result) {
+bool SpaceBullet::RFP_convex_convex_test(const btConvexShape *p_shapeA, const btConvexShape *p_shapeB, btCollisionObject *p_objectB, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result) {
// Initialize GJK input
btGjkPairDetector::ClosestPointInput gjk_input;
gjk_input.m_transformA = p_transformA;
+ gjk_input.m_transformA.getOrigin() += r_delta_recover_movement;
gjk_input.m_transformB = p_transformB;
// Perform GJK test
@@ -1113,7 +1103,7 @@ bool SpaceBullet::RFP_convex_convex_test(const btConvexShape *p_shapeA, const bt
gjk_pair_detector.getClosestPoints(gjk_input, result, 0);
if (0 > result.m_distance) {
// Has penetration
- r_recover_position += result.m_normalOnBInWorld * (result.m_distance * -1 * p_recover_movement_scale);
+ r_delta_recover_movement += result.m_normalOnBInWorld * (result.m_distance * -1 * p_recover_movement_scale);
if (r_recover_result) {
if (result.m_distance < r_recover_result->penetration_distance) {
@@ -1130,11 +1120,14 @@ bool SpaceBullet::RFP_convex_convex_test(const btConvexShape *p_shapeA, const bt
return false;
}
-bool SpaceBullet::RFP_convex_world_test(const btConvexShape *p_shapeA, const btCollisionShape *p_shapeB, btCollisionObject *p_objectA, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_recover_movement_scale, btVector3 &r_recover_position, RecoverResult *r_recover_result) {
+bool SpaceBullet::RFP_convex_world_test(const btConvexShape *p_shapeA, const btCollisionShape *p_shapeB, btCollisionObject *p_objectA, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result) {
/// Contact test
- btCollisionObjectWrapper obA(NULL, p_shapeA, p_objectA, p_transformA, -1, p_shapeId_A);
+ btTransform tA(p_transformA);
+ tA.getOrigin() += r_delta_recover_movement;
+
+ btCollisionObjectWrapper obA(NULL, p_shapeA, p_objectA, tA, -1, p_shapeId_A);
btCollisionObjectWrapper obB(NULL, p_shapeB, p_objectB, p_transformB, -1, p_shapeId_B);
btCollisionAlgorithm *algorithm = dispatcher->findAlgorithm(&obA, &obB, NULL, BT_CLOSEST_POINT_ALGORITHMS);
@@ -1147,7 +1140,7 @@ bool SpaceBullet::RFP_convex_world_test(const btConvexShape *p_shapeA, const btC
dispatcher->freeCollisionAlgorithm(algorithm);
if (contactPointResult.hasHit()) {
- r_recover_position += contactPointResult.m_pointNormalWorld * (contactPointResult.m_penetration_distance * -1 * p_recover_movement_scale);
+ r_delta_recover_movement += contactPointResult.m_pointNormalWorld * (contactPointResult.m_penetration_distance * -1 * p_recover_movement_scale);
if (r_recover_result) {
if (contactPointResult.m_penetration_distance < r_recover_result->penetration_distance) {
diff --git a/modules/bullet/space_bullet.h b/modules/bullet/space_bullet.h
index 8d31ab765b..0aeb407dcc 100644
--- a/modules/bullet/space_bullet.h
+++ b/modules/bullet/space_bullet.h
@@ -191,15 +191,20 @@ private:
RecoverResult() :
hasPenetration(false),
- penetration_distance(1e20) {}
+ normal(0, 0, 0),
+ pointWorld(0, 0, 0),
+ penetration_distance(1e20),
+ other_compound_shape_index(0),
+ other_collision_object(NULL),
+ local_shape_most_recovered(0) {}
};
- bool recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_from, btScalar p_recover_movement_scale, btVector3 &r_recover_position, RecoverResult *r_recover_result = NULL);
+ bool recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_from, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = NULL);
/// This is an API that recover a kinematic object from penetration
/// This allow only Convex Convex test and it always use GJK algorithm, With this API we don't benefit of Bullet special accelerated functions
- bool RFP_convex_convex_test(const btConvexShape *p_shapeA, const btConvexShape *p_shapeB, btCollisionObject *p_objectB, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_movement_scale, btVector3 &r_recover_position, RecoverResult *r_recover_result = NULL);
+ bool RFP_convex_convex_test(const btConvexShape *p_shapeA, const btConvexShape *p_shapeB, btCollisionObject *p_objectB, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = NULL);
/// This is an API that recover a kinematic object from penetration
/// Using this we leave Bullet to select the best algorithm, For example GJK in case we have Convex Convex, or a Bullet accelerated algorithm
- bool RFP_convex_world_test(const btConvexShape *p_shapeA, const btCollisionShape *p_shapeB, btCollisionObject *p_objectA, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_movement_scale, btVector3 &r_recover_position, RecoverResult *r_recover_result = NULL);
+ bool RFP_convex_world_test(const btConvexShape *p_shapeA, const btCollisionShape *p_shapeB, btCollisionObject *p_objectA, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = NULL);
};
#endif
diff --git a/modules/gdnative/gdnative/string.cpp b/modules/gdnative/gdnative/string.cpp
index 350dc540f7..9ce2b1406d 100644
--- a/modules/gdnative/gdnative/string.cpp
+++ b/modules/gdnative/gdnative/string.cpp
@@ -40,6 +40,24 @@
extern "C" {
#endif
+godot_int GDAPI godot_char_string_length(const godot_char_string *p_cs) {
+ const CharString *cs = (const CharString *)p_cs;
+
+ return cs->length();
+}
+
+const char GDAPI *godot_char_string_get_data(const godot_char_string *p_cs) {
+ const CharString *cs = (const CharString *)p_cs;
+
+ return cs->get_data();
+}
+
+void GDAPI godot_char_string_destroy(godot_char_string *p_cs) {
+ CharString *cs = (CharString *)p_cs;
+
+ cs->~CharString();
+}
+
void GDAPI godot_string_new(godot_string *r_dest) {
String *dest = (String *)r_dest;
memnew_placement(dest, String);
@@ -51,35 +69,11 @@ void GDAPI godot_string_new_copy(godot_string *r_dest, const godot_string *p_src
memnew_placement(dest, String(*src));
}
-void GDAPI godot_string_new_data(godot_string *r_dest, const char *p_contents, const int p_size) {
- String *dest = (String *)r_dest;
- memnew_placement(dest, String(String::utf8(p_contents, p_size)));
-}
-
-void GDAPI godot_string_new_unicode_data(godot_string *r_dest, const wchar_t *p_contents, const int p_size) {
+void GDAPI godot_string_new_with_wide_string(godot_string *r_dest, const wchar_t *p_contents, const int p_size) {
String *dest = (String *)r_dest;
memnew_placement(dest, String(p_contents, p_size));
}
-void GDAPI godot_string_get_data(const godot_string *p_self, char *p_dest, int *p_size) {
- String *self = (String *)p_self;
-
- if (p_size) {
- // we have a length pointer, that means we either want to know
- // the length or want to write *p_size bytes into a buffer
-
- CharString utf8_string = self->utf8();
-
- int len = utf8_string.length();
-
- if (p_dest) {
- memcpy(p_dest, utf8_string.get_data(), *p_size);
- } else {
- *p_size = len;
- }
- }
-}
-
wchar_t GDAPI *godot_string_operator_index(godot_string *p_self, const godot_int p_idx) {
String *self = (String *)p_self;
return &(self->operator[](p_idx));
@@ -90,7 +84,7 @@ wchar_t GDAPI godot_string_operator_index_const(const godot_string *p_self, cons
return self->operator[](p_idx);
}
-const wchar_t GDAPI *godot_string_unicode_str(const godot_string *p_self) {
+const wchar_t GDAPI *godot_string_wide_str(const godot_string *p_self) {
const String *self = (const String *)p_self;
return self->c_str();
}
@@ -130,6 +124,26 @@ godot_int GDAPI godot_string_length(const godot_string *p_self) {
/* Helpers */
+signed char GDAPI godot_string_casecmp_to(const godot_string *p_self, const godot_string *p_str) {
+ const String *self = (const String *)p_self;
+ const String *str = (const String *)p_str;
+
+ return self->casecmp_to(*str);
+}
+
+signed char GDAPI godot_string_nocasecmp_to(const godot_string *p_self, const godot_string *p_str) {
+ const String *self = (const String *)p_self;
+ const String *str = (const String *)p_str;
+
+ return self->nocasecmp_to(*str);
+}
+signed char GDAPI godot_string_naturalnocasecmp_to(const godot_string *p_self, const godot_string *p_str) {
+ const String *self = (const String *)p_self;
+ const String *str = (const String *)p_str;
+
+ return self->naturalnocasecmp_to(*str);
+}
+
godot_bool GDAPI godot_string_begins_with(const godot_string *p_self, const godot_string *p_string) {
const String *self = (const String *)p_self;
const String *string = (const String *)p_string;
@@ -534,7 +548,7 @@ godot_string GDAPI godot_string_capitalize(const godot_string *p_self) {
memnew_placement(&result, String(self->capitalize()));
return result;
-};
+}
godot_string GDAPI godot_string_camelcase_to_underscore(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -542,7 +556,7 @@ godot_string GDAPI godot_string_camelcase_to_underscore(const godot_string *p_se
memnew_placement(&result, String(self->camelcase_to_underscore(false)));
return result;
-};
+}
godot_string GDAPI godot_string_camelcase_to_underscore_lowercased(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -550,45 +564,45 @@ godot_string GDAPI godot_string_camelcase_to_underscore_lowercased(const godot_s
memnew_placement(&result, String(self->camelcase_to_underscore()));
return result;
-};
+}
double GDAPI godot_string_char_to_double(const char *p_what) {
return String::to_double(p_what);
-};
+}
godot_int GDAPI godot_string_char_to_int(const char *p_what) {
return String::to_int(p_what);
-};
+}
int64_t GDAPI godot_string_wchar_to_int(const wchar_t *p_str) {
return String::to_int(p_str);
-};
+}
godot_int GDAPI godot_string_char_to_int_with_len(const char *p_what, godot_int p_len) {
return String::to_int(p_what, p_len);
-};
+}
int64_t GDAPI godot_string_char_to_int64_with_len(const wchar_t *p_str, int p_len) {
return String::to_int(p_str, p_len);
-};
+}
int64_t GDAPI godot_string_hex_to_int64(const godot_string *p_self) {
const String *self = (const String *)p_self;
return self->hex_to_int64(false);
-};
+}
int64_t GDAPI godot_string_hex_to_int64_with_prefix(const godot_string *p_self) {
const String *self = (const String *)p_self;
return self->hex_to_int64();
-};
+}
int64_t GDAPI godot_string_to_int64(const godot_string *p_self) {
const String *self = (const String *)p_self;
return self->to_int64();
-};
+}
double GDAPI godot_string_unicode_char_to_double(const wchar_t *p_str, const wchar_t **r_end) {
return String::to_double(p_str, r_end);
@@ -601,7 +615,7 @@ godot_string GDAPI godot_string_get_slice(const godot_string *p_self, godot_stri
memnew_placement(&result, String(self->get_slice(*splitter, p_slice)));
return result;
-};
+}
godot_string GDAPI godot_string_get_slicec(const godot_string *p_self, wchar_t p_splitter, godot_int p_slice) {
const String *self = (const String *)p_self;
@@ -609,7 +623,7 @@ godot_string GDAPI godot_string_get_slicec(const godot_string *p_self, wchar_t p
memnew_placement(&result, String(self->get_slicec(p_splitter, p_slice)));
return result;
-};
+}
godot_array GDAPI godot_string_split(const godot_string *p_self, const godot_string *p_splitter) {
const String *self = (const String *)p_self;
@@ -625,7 +639,7 @@ godot_array GDAPI godot_string_split(const godot_string *p_self, const godot_str
}
return result;
-};
+}
godot_array GDAPI godot_string_split_allow_empty(const godot_string *p_self, const godot_string *p_splitter) {
const String *self = (const String *)p_self;
@@ -641,7 +655,7 @@ godot_array GDAPI godot_string_split_allow_empty(const godot_string *p_self, con
}
return result;
-};
+}
godot_array GDAPI godot_string_split_floats(const godot_string *p_self, const godot_string *p_splitter) {
const String *self = (const String *)p_self;
@@ -657,7 +671,7 @@ godot_array GDAPI godot_string_split_floats(const godot_string *p_self, const go
}
return result;
-};
+}
godot_array GDAPI godot_string_split_floats_allows_empty(const godot_string *p_self, const godot_string *p_splitter) {
const String *self = (const String *)p_self;
@@ -673,7 +687,7 @@ godot_array GDAPI godot_string_split_floats_allows_empty(const godot_string *p_s
}
return result;
-};
+}
godot_array GDAPI godot_string_split_floats_mk(const godot_string *p_self, const godot_array *p_splitters) {
const String *self = (const String *)p_self;
@@ -696,7 +710,7 @@ godot_array GDAPI godot_string_split_floats_mk(const godot_string *p_self, const
}
return result;
-};
+}
godot_array GDAPI godot_string_split_floats_mk_allows_empty(const godot_string *p_self, const godot_array *p_splitters) {
const String *self = (const String *)p_self;
@@ -719,7 +733,7 @@ godot_array GDAPI godot_string_split_floats_mk_allows_empty(const godot_string *
}
return result;
-};
+}
godot_array GDAPI godot_string_split_ints(const godot_string *p_self, const godot_string *p_splitter) {
const String *self = (const String *)p_self;
@@ -735,7 +749,7 @@ godot_array GDAPI godot_string_split_ints(const godot_string *p_self, const godo
}
return result;
-};
+}
godot_array GDAPI godot_string_split_ints_allows_empty(const godot_string *p_self, const godot_string *p_splitter) {
const String *self = (const String *)p_self;
@@ -751,7 +765,7 @@ godot_array GDAPI godot_string_split_ints_allows_empty(const godot_string *p_sel
}
return result;
-};
+}
godot_array GDAPI godot_string_split_ints_mk(const godot_string *p_self, const godot_array *p_splitters) {
const String *self = (const String *)p_self;
@@ -774,7 +788,7 @@ godot_array GDAPI godot_string_split_ints_mk(const godot_string *p_self, const g
}
return result;
-};
+}
godot_array GDAPI godot_string_split_ints_mk_allows_empty(const godot_string *p_self, const godot_array *p_splitters) {
const String *self = (const String *)p_self;
@@ -797,7 +811,7 @@ godot_array GDAPI godot_string_split_ints_mk_allows_empty(const godot_string *p_
}
return result;
-};
+}
godot_array GDAPI godot_string_split_spaces(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -812,22 +826,22 @@ godot_array GDAPI godot_string_split_spaces(const godot_string *p_self) {
}
return result;
-};
+}
godot_int GDAPI godot_string_get_slice_count(const godot_string *p_self, godot_string p_splitter) {
const String *self = (const String *)p_self;
String *splitter = (String *)&p_splitter;
return self->get_slice_count(*splitter);
-};
+}
wchar_t GDAPI godot_string_char_lowercase(wchar_t p_char) {
return String::char_lowercase(p_char);
-};
+}
wchar_t GDAPI godot_string_char_uppercase(wchar_t p_char) {
return String::char_uppercase(p_char);
-};
+}
godot_string GDAPI godot_string_to_lower(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -835,7 +849,7 @@ godot_string GDAPI godot_string_to_lower(const godot_string *p_self) {
memnew_placement(&result, String(self->to_lower()));
return result;
-};
+}
godot_string GDAPI godot_string_to_upper(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -843,7 +857,7 @@ godot_string GDAPI godot_string_to_upper(const godot_string *p_self) {
memnew_placement(&result, String(self->to_upper()));
return result;
-};
+}
godot_string GDAPI godot_string_get_basename(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -851,7 +865,7 @@ godot_string GDAPI godot_string_get_basename(const godot_string *p_self) {
memnew_placement(&result, String(self->get_basename()));
return result;
-};
+}
godot_string GDAPI godot_string_get_extension(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -859,7 +873,7 @@ godot_string GDAPI godot_string_get_extension(const godot_string *p_self) {
memnew_placement(&result, String(self->get_extension()));
return result;
-};
+}
godot_string GDAPI godot_string_left(const godot_string *p_self, godot_int p_pos) {
const String *self = (const String *)p_self;
@@ -867,13 +881,13 @@ godot_string GDAPI godot_string_left(const godot_string *p_self, godot_int p_pos
memnew_placement(&result, String(self->left(p_pos)));
return result;
-};
+}
wchar_t GDAPI godot_string_ord_at(const godot_string *p_self, godot_int p_idx) {
const String *self = (const String *)p_self;
return self->ord_at(p_idx);
-};
+}
godot_string GDAPI godot_string_plus_file(const godot_string *p_self, const godot_string *p_file) {
const String *self = (const String *)p_self;
@@ -882,7 +896,7 @@ godot_string GDAPI godot_string_plus_file(const godot_string *p_self, const godo
memnew_placement(&result, String(self->plus_file(*file)));
return result;
-};
+}
godot_string GDAPI godot_string_right(const godot_string *p_self, godot_int p_pos) {
const String *self = (const String *)p_self;
@@ -890,7 +904,7 @@ godot_string GDAPI godot_string_right(const godot_string *p_self, godot_int p_po
memnew_placement(&result, String(self->right(p_pos)));
return result;
-};
+}
godot_string GDAPI godot_string_strip_edges(const godot_string *p_self, godot_bool p_left, godot_bool p_right) {
const String *self = (const String *)p_self;
@@ -898,7 +912,7 @@ godot_string GDAPI godot_string_strip_edges(const godot_string *p_self, godot_bo
memnew_placement(&result, String(self->strip_edges(p_left, p_right)));
return result;
-};
+}
godot_string GDAPI godot_string_strip_escapes(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -906,94 +920,96 @@ godot_string GDAPI godot_string_strip_escapes(const godot_string *p_self) {
memnew_placement(&result, String(self->strip_escapes()));
return result;
-};
+}
void GDAPI godot_string_erase(godot_string *p_self, godot_int p_pos, godot_int p_chars) {
String *self = (String *)p_self;
return self->erase(p_pos, p_chars);
-};
+}
-void GDAPI godot_string_ascii(godot_string *p_self, char *result) {
- String *self = (String *)p_self;
- Vector<char> return_value = self->ascii();
+godot_char_string GDAPI godot_string_ascii(const godot_string *p_self) {
+ const String *self = (const String *)p_self;
+ godot_char_string result;
- for (int i = 0; i < return_value.size(); i++) {
- result[i] = return_value[i];
- }
+ memnew_placement(&result, String(self->ascii()));
+
+ return result;
}
-void GDAPI godot_string_ascii_extended(godot_string *p_self, char *result) {
- String *self = (String *)p_self;
- Vector<char> return_value = self->ascii(true);
+godot_char_string GDAPI godot_string_ascii_extended(const godot_string *p_self) {
+ const String *self = (const String *)p_self;
- for (int i = 0; i < return_value.size(); i++) {
- result[i] = return_value[i];
- }
+ godot_char_string result;
+
+ memnew_placement(&result, String(self->ascii(true)));
+
+ return result;
}
-void GDAPI godot_string_utf8(godot_string *p_self, char *result) {
- String *self = (String *)p_self;
- Vector<char> return_value = self->utf8();
+godot_char_string GDAPI godot_string_utf8(const godot_string *p_self) {
+ const String *self = (const String *)p_self;
- for (int i = 0; i < return_value.size(); i++) {
- result[i] = return_value[i];
- }
+ godot_char_string result;
+
+ memnew_placement(&result, String(self->utf8()));
+
+ return result;
}
godot_bool GDAPI godot_string_parse_utf8(godot_string *p_self, const char *p_utf8) {
String *self = (String *)p_self;
return self->parse_utf8(p_utf8);
-};
+}
godot_bool GDAPI godot_string_parse_utf8_with_len(godot_string *p_self, const char *p_utf8, godot_int p_len) {
String *self = (String *)p_self;
return self->parse_utf8(p_utf8, p_len);
-};
+}
godot_string GDAPI godot_string_chars_to_utf8(const char *p_utf8) {
godot_string result;
memnew_placement(&result, String(String::utf8(p_utf8)));
return result;
-};
+}
godot_string GDAPI godot_string_chars_to_utf8_with_len(const char *p_utf8, godot_int p_len) {
godot_string result;
memnew_placement(&result, String(String::utf8(p_utf8, p_len)));
return result;
-};
+}
uint32_t GDAPI godot_string_hash(const godot_string *p_self) {
const String *self = (const String *)p_self;
return self->hash();
-};
+}
uint64_t GDAPI godot_string_hash64(const godot_string *p_self) {
const String *self = (const String *)p_self;
return self->hash64();
-};
+}
uint32_t GDAPI godot_string_hash_chars(const char *p_cstr) {
return String::hash(p_cstr);
-};
+}
uint32_t GDAPI godot_string_hash_chars_with_len(const char *p_cstr, godot_int p_len) {
return String::hash(p_cstr, p_len);
-};
+}
uint32_t GDAPI godot_string_hash_utf8_chars(const wchar_t *p_str) {
return String::hash(p_str);
-};
+}
uint32_t GDAPI godot_string_hash_utf8_chars_with_len(const wchar_t *p_str, godot_int p_len) {
return String::hash(p_str, p_len);
-};
+}
godot_pool_byte_array GDAPI godot_string_md5_buffer(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -1010,7 +1026,7 @@ godot_pool_byte_array GDAPI godot_string_md5_buffer(const godot_string *p_self)
}
return result;
-};
+}
godot_string GDAPI godot_string_md5_text(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -1018,7 +1034,7 @@ godot_string GDAPI godot_string_md5_text(const godot_string *p_self) {
memnew_placement(&result, String(self->md5_text()));
return result;
-};
+}
godot_pool_byte_array GDAPI godot_string_sha256_buffer(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -1035,7 +1051,7 @@ godot_pool_byte_array GDAPI godot_string_sha256_buffer(const godot_string *p_sel
}
return result;
-};
+}
godot_string GDAPI godot_string_sha256_text(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -1043,13 +1059,13 @@ godot_string GDAPI godot_string_sha256_text(const godot_string *p_self) {
memnew_placement(&result, String(self->sha256_text()));
return result;
-};
+}
godot_bool godot_string_empty(const godot_string *p_self) {
const String *self = (const String *)p_self;
return self->empty();
-};
+}
// path functions
godot_string GDAPI godot_string_get_base_dir(const godot_string *p_self) {
@@ -1059,7 +1075,7 @@ godot_string GDAPI godot_string_get_base_dir(const godot_string *p_self) {
memnew_placement(&result, String(return_value));
return result;
-};
+}
godot_string GDAPI godot_string_get_file(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -1068,7 +1084,7 @@ godot_string GDAPI godot_string_get_file(const godot_string *p_self) {
memnew_placement(&result, String(return_value));
return result;
-};
+}
godot_string GDAPI godot_string_humanize_size(size_t p_size) {
godot_string result;
@@ -1076,25 +1092,25 @@ godot_string GDAPI godot_string_humanize_size(size_t p_size) {
memnew_placement(&result, String(return_value));
return result;
-};
+}
godot_bool GDAPI godot_string_is_abs_path(const godot_string *p_self) {
const String *self = (const String *)p_self;
return self->is_abs_path();
-};
+}
godot_bool GDAPI godot_string_is_rel_path(const godot_string *p_self) {
const String *self = (const String *)p_self;
return self->is_rel_path();
-};
+}
godot_bool GDAPI godot_string_is_resource_file(const godot_string *p_self) {
const String *self = (const String *)p_self;
return self->is_resource_file();
-};
+}
godot_string GDAPI godot_string_path_to(const godot_string *p_self, const godot_string *p_path) {
const String *self = (const String *)p_self;
@@ -1104,7 +1120,7 @@ godot_string GDAPI godot_string_path_to(const godot_string *p_self, const godot_
memnew_placement(&result, String(return_value));
return result;
-};
+}
godot_string GDAPI godot_string_path_to_file(const godot_string *p_self, const godot_string *p_path) {
const String *self = (const String *)p_self;
@@ -1114,7 +1130,7 @@ godot_string GDAPI godot_string_path_to_file(const godot_string *p_self, const g
memnew_placement(&result, String(return_value));
return result;
-};
+}
godot_string GDAPI godot_string_simplify_path(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -1123,7 +1139,7 @@ godot_string GDAPI godot_string_simplify_path(const godot_string *p_self) {
memnew_placement(&result, String(return_value));
return result;
-};
+}
godot_string GDAPI godot_string_c_escape(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -1132,7 +1148,7 @@ godot_string GDAPI godot_string_c_escape(const godot_string *p_self) {
memnew_placement(&result, String(return_value));
return result;
-};
+}
godot_string GDAPI godot_string_c_escape_multiline(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -1141,7 +1157,7 @@ godot_string GDAPI godot_string_c_escape_multiline(const godot_string *p_self) {
memnew_placement(&result, String(return_value));
return result;
-};
+}
godot_string GDAPI godot_string_c_unescape(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -1150,7 +1166,7 @@ godot_string GDAPI godot_string_c_unescape(const godot_string *p_self) {
memnew_placement(&result, String(return_value));
return result;
-};
+}
godot_string GDAPI godot_string_http_escape(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -1159,7 +1175,7 @@ godot_string GDAPI godot_string_http_escape(const godot_string *p_self) {
memnew_placement(&result, String(return_value));
return result;
-};
+}
godot_string GDAPI godot_string_http_unescape(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -1168,7 +1184,7 @@ godot_string GDAPI godot_string_http_unescape(const godot_string *p_self) {
memnew_placement(&result, String(return_value));
return result;
-};
+}
godot_string GDAPI godot_string_json_escape(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -1177,7 +1193,7 @@ godot_string GDAPI godot_string_json_escape(const godot_string *p_self) {
memnew_placement(&result, String(return_value));
return result;
-};
+}
godot_string GDAPI godot_string_word_wrap(const godot_string *p_self, godot_int p_chars_per_line) {
const String *self = (const String *)p_self;
@@ -1186,7 +1202,7 @@ godot_string GDAPI godot_string_word_wrap(const godot_string *p_self, godot_int
memnew_placement(&result, String(return_value));
return result;
-};
+}
godot_string GDAPI godot_string_xml_escape(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -1195,7 +1211,7 @@ godot_string GDAPI godot_string_xml_escape(const godot_string *p_self) {
memnew_placement(&result, String(return_value));
return result;
-};
+}
godot_string GDAPI godot_string_xml_escape_with_quotes(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -1204,7 +1220,7 @@ godot_string GDAPI godot_string_xml_escape_with_quotes(const godot_string *p_sel
memnew_placement(&result, String(return_value));
return result;
-};
+}
godot_string GDAPI godot_string_xml_unescape(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -1213,7 +1229,7 @@ godot_string GDAPI godot_string_xml_unescape(const godot_string *p_self) {
memnew_placement(&result, String(return_value));
return result;
-};
+}
godot_string GDAPI godot_string_percent_decode(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -1222,7 +1238,7 @@ godot_string GDAPI godot_string_percent_decode(const godot_string *p_self) {
memnew_placement(&result, String(return_value));
return result;
-};
+}
godot_string GDAPI godot_string_percent_encode(const godot_string *p_self) {
const String *self = (const String *)p_self;
@@ -1231,43 +1247,43 @@ godot_string GDAPI godot_string_percent_encode(const godot_string *p_self) {
memnew_placement(&result, String(return_value));
return result;
-};
+}
godot_bool GDAPI godot_string_is_valid_float(const godot_string *p_self) {
const String *self = (const String *)p_self;
return self->is_valid_float();
-};
+}
godot_bool GDAPI godot_string_is_valid_hex_number(const godot_string *p_self, godot_bool p_with_prefix) {
const String *self = (const String *)p_self;
return self->is_valid_hex_number(p_with_prefix);
-};
+}
godot_bool GDAPI godot_string_is_valid_html_color(const godot_string *p_self) {
const String *self = (const String *)p_self;
return self->is_valid_html_color();
-};
+}
godot_bool GDAPI godot_string_is_valid_identifier(const godot_string *p_self) {
const String *self = (const String *)p_self;
return self->is_valid_identifier();
-};
+}
godot_bool GDAPI godot_string_is_valid_integer(const godot_string *p_self) {
const String *self = (const String *)p_self;
return self->is_valid_integer();
-};
+}
godot_bool GDAPI godot_string_is_valid_ip_address(const godot_string *p_self) {
const String *self = (const String *)p_self;
return self->is_valid_ip_address();
-};
+}
#ifdef __cplusplus
}
diff --git a/modules/gdnative/gdnative/transform.cpp b/modules/gdnative/gdnative/transform.cpp
index 9bd8c99612..715f2e3c08 100644
--- a/modules/gdnative/gdnative/transform.cpp
+++ b/modules/gdnative/gdnative/transform.cpp
@@ -63,7 +63,7 @@ godot_basis GDAPI godot_transform_get_basis(const godot_transform *p_self) {
return dest;
}
-void GDAPI godot_transform_set_basis(godot_transform *p_self, godot_basis *p_v) {
+void GDAPI godot_transform_set_basis(godot_transform *p_self, const godot_basis *p_v) {
Transform *self = (Transform *)p_self;
const Basis *v = (const Basis *)p_v;
self->basis = *v;
@@ -76,7 +76,7 @@ godot_vector3 GDAPI godot_transform_get_origin(const godot_transform *p_self) {
return dest;
}
-void GDAPI godot_transform_set_origin(godot_transform *p_self, godot_vector3 *p_v) {
+void GDAPI godot_transform_set_origin(godot_transform *p_self, const godot_vector3 *p_v) {
Transform *self = (Transform *)p_self;
const Vector3 *v = (const Vector3 *)p_v;
self->origin = *v;
diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json
index 06c6e9f410..6e3cf16758 100644
--- a/modules/gdnative/gdnative_api.json
+++ b/modules/gdnative/gdnative_api.json
@@ -3516,7 +3516,7 @@
"return_type": "void",
"arguments": [
["godot_transform *", "p_self"],
- ["godot_basis *", "p_v"]
+ ["const godot_basis *", "p_v"]
]
},
{
@@ -3531,7 +3531,7 @@
"return_type": "void",
"arguments": [
["godot_transform *", "p_self"],
- ["godot_vector3 *", "p_v"]
+ ["const godot_vector3 *", "p_v"]
]
},
{
@@ -4324,45 +4324,48 @@
]
},
{
- "name": "godot_string_new",
- "return_type": "void",
+ "name": "godot_char_string_length",
+ "return_type": "godot_int",
"arguments": [
- ["godot_string *", "r_dest"]
+ ["const godot_char_string *", "p_cs"]
]
},
{
- "name": "godot_string_new_copy",
+ "name": "godot_char_string_get_data",
+ "return_type": "const char *",
+ "arguments": [
+ ["const godot_char_string *", "p_cs"]
+ ]
+ },
+ {
+ "name": "godot_char_string_destroy",
"return_type": "void",
"arguments": [
- ["godot_string *", "r_dest"],
- ["const godot_string *", "p_src"]
+ ["godot_char_string *", "p_cs"]
]
},
{
- "name": "godot_string_new_data",
+ "name": "godot_string_new",
"return_type": "void",
"arguments": [
- ["godot_string *", "r_dest"],
- ["const char *", "p_contents"],
- ["const int", "p_size"]
+ ["godot_string *", "r_dest"]
]
},
{
- "name": "godot_string_new_unicode_data",
+ "name": "godot_string_new_copy",
"return_type": "void",
"arguments": [
["godot_string *", "r_dest"],
- ["const wchar_t *", "p_contents"],
- ["const int", "p_size"]
+ ["const godot_string *", "p_src"]
]
},
{
- "name": "godot_string_get_data",
+ "name": "godot_string_new_with_wide_string",
"return_type": "void",
"arguments": [
- ["const godot_string *", "p_self"],
- ["char *", "p_dest"],
- ["int *", "p_size"]
+ ["godot_string *", "r_dest"],
+ ["const wchar_t *", "p_contents"],
+ ["const int", "p_size"]
]
},
{
@@ -4382,7 +4385,7 @@
]
},
{
- "name": "godot_string_unicode_str",
+ "name": "godot_string_wide_str",
"return_type": "const wchar_t *",
"arguments": [
["const godot_string *", "p_self"]
@@ -4420,6 +4423,30 @@
]
},
{
+ "name": "godot_string_casecmp_to",
+ "return_type": "signed char",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_string *", "p_str"]
+ ]
+ },
+ {
+ "name": "godot_string_nocasecmp_to",
+ "return_type": "signed char",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_string *", "p_str"]
+ ]
+ },
+ {
+ "name": "godot_string_naturalnocasecmp_to",
+ "return_type": "signed char",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["const godot_string *", "p_str"]
+ ]
+ },
+ {
"name": "godot_string_begins_with",
"return_type": "godot_bool",
"arguments": [
@@ -5125,26 +5152,23 @@
},
{
"name": "godot_string_ascii",
- "return_type": "void",
+ "return_type": "godot_char_string",
"arguments": [
- ["godot_string *", "p_self"],
- ["char *", "result"]
+ ["const godot_string *", "p_self"]
]
},
{
"name": "godot_string_ascii_extended",
- "return_type": "void",
+ "return_type": "godot_char_string",
"arguments": [
- ["godot_string *", "p_self"],
- ["char *", "result"]
+ ["const godot_string *", "p_self"]
]
},
{
"name": "godot_string_utf8",
- "return_type": "void",
+ "return_type": "godot_char_string",
"arguments": [
- ["godot_string *", "p_self"],
- ["char *", "result"]
+ ["const godot_string *", "p_self"]
]
},
{
diff --git a/modules/gdnative/include/gdnative/string.h b/modules/gdnative/include/gdnative/string.h
index 080c0aa171..73245160c1 100644
--- a/modules/gdnative/include/gdnative/string.h
+++ b/modules/gdnative/include/gdnative/string.h
@@ -38,13 +38,24 @@ extern "C" {
#include <stdint.h>
#include <wchar.h>
+typedef wchar_t godot_char_type;
+
#define GODOT_STRING_SIZE sizeof(void *)
+#define GODOT_CHAR_STRING_SIZE sizeof(void *)
#ifndef GODOT_CORE_API_GODOT_STRING_TYPE_DEFINED
#define GODOT_CORE_API_GODOT_STRING_TYPE_DEFINED
typedef struct {
uint8_t _dont_touch_that[GODOT_STRING_SIZE];
} godot_string;
+
+#endif
+
+#ifndef GODOT_CORE_API_GODOT_CHAR_STRING_TYPE_DEFINED
+#define GODOT_CORE_API_GODOT_CHAR_STRING_TYPE_DEFINED
+typedef struct {
+ uint8_t _dont_touch_that[GODOT_CHAR_STRING_SIZE];
+} godot_char_string;
#endif
// reduce extern "C" nesting for VS2013
@@ -60,16 +71,17 @@ typedef struct {
extern "C" {
#endif
+godot_int GDAPI godot_char_string_length(const godot_char_string *p_cs);
+const char GDAPI *godot_char_string_get_data(const godot_char_string *p_cs);
+void GDAPI godot_char_string_destroy(godot_char_string *p_cs);
+
void GDAPI godot_string_new(godot_string *r_dest);
void GDAPI godot_string_new_copy(godot_string *r_dest, const godot_string *p_src);
-void GDAPI godot_string_new_data(godot_string *r_dest, const char *p_contents, const int p_size);
-void GDAPI godot_string_new_unicode_data(godot_string *r_dest, const wchar_t *p_contents, const int p_size);
-
-void GDAPI godot_string_get_data(const godot_string *p_self, char *p_dest, int *p_size);
+void GDAPI godot_string_new_with_wide_string(godot_string *r_dest, const wchar_t *p_contents, const int p_size);
wchar_t GDAPI *godot_string_operator_index(godot_string *p_self, const godot_int p_idx);
wchar_t GDAPI godot_string_operator_index_const(const godot_string *p_self, const godot_int p_idx);
-const wchar_t GDAPI *godot_string_unicode_str(const godot_string *p_self);
+const wchar_t GDAPI *godot_string_wide_str(const godot_string *p_self);
godot_bool GDAPI godot_string_operator_equal(const godot_string *p_self, const godot_string *p_b);
godot_bool GDAPI godot_string_operator_less(const godot_string *p_self, const godot_string *p_b);
@@ -81,6 +93,10 @@ godot_int GDAPI godot_string_length(const godot_string *p_self);
/* Helpers */
+signed char GDAPI godot_string_casecmp_to(const godot_string *p_self, const godot_string *p_str);
+signed char GDAPI godot_string_nocasecmp_to(const godot_string *p_self, const godot_string *p_str);
+signed char GDAPI godot_string_naturalnocasecmp_to(const godot_string *p_self, const godot_string *p_str);
+
godot_bool GDAPI godot_string_begins_with(const godot_string *p_self, const godot_string *p_string);
godot_bool GDAPI godot_string_begins_with_char_array(const godot_string *p_self, const char *p_char_array);
godot_array GDAPI godot_string_bigrams(const godot_string *p_self);
@@ -177,9 +193,9 @@ godot_string GDAPI godot_string_strip_escapes(const godot_string *p_self);
void GDAPI godot_string_erase(godot_string *p_self, godot_int p_pos, godot_int p_chars);
-void GDAPI godot_string_ascii(godot_string *p_self, char *result);
-void GDAPI godot_string_ascii_extended(godot_string *p_self, char *result);
-void GDAPI godot_string_utf8(godot_string *p_self, char *result);
+godot_char_string GDAPI godot_string_ascii(const godot_string *p_self);
+godot_char_string GDAPI godot_string_ascii_extended(const godot_string *p_self);
+godot_char_string GDAPI godot_string_utf8(const godot_string *p_self);
godot_bool GDAPI godot_string_parse_utf8(godot_string *p_self, const char *p_utf8);
godot_bool GDAPI godot_string_parse_utf8_with_len(godot_string *p_self, const char *p_utf8, godot_int p_len);
godot_string GDAPI godot_string_chars_to_utf8(const char *p_utf8);
diff --git a/modules/gdnative/include/gdnative/transform.h b/modules/gdnative/include/gdnative/transform.h
index 10a242b205..a646da146a 100644
--- a/modules/gdnative/include/gdnative/transform.h
+++ b/modules/gdnative/include/gdnative/transform.h
@@ -64,10 +64,10 @@ void GDAPI godot_transform_new_with_axis_origin(godot_transform *r_dest, const g
void GDAPI godot_transform_new(godot_transform *r_dest, const godot_basis *p_basis, const godot_vector3 *p_origin);
godot_basis GDAPI godot_transform_get_basis(const godot_transform *p_self);
-void GDAPI godot_transform_set_basis(godot_transform *p_self, godot_basis *p_v);
+void GDAPI godot_transform_set_basis(godot_transform *p_self, const godot_basis *p_v);
godot_vector3 GDAPI godot_transform_get_origin(const godot_transform *p_self);
-void GDAPI godot_transform_set_origin(godot_transform *p_self, godot_vector3 *p_v);
+void GDAPI godot_transform_set_origin(godot_transform *p_self, const godot_vector3 *p_v);
godot_string GDAPI godot_transform_as_string(const godot_transform *p_self);
diff --git a/modules/gdnative/pluginscript/pluginscript_language.cpp b/modules/gdnative/pluginscript/pluginscript_language.cpp
index 2405afc677..8101ebc6f3 100644
--- a/modules/gdnative/pluginscript/pluginscript_language.cpp
+++ b/modules/gdnative/pluginscript/pluginscript_language.cpp
@@ -45,7 +45,11 @@ void PluginScriptLanguage::init() {
}
String PluginScriptLanguage::get_type() const {
- return String(_desc.type);
+ // We should use _desc.type here, however the returned type is used to
+ // query ClassDB which would complain given the type is not registered
+ // from his point of view...
+ // To solve this we just use a more generic (but present in ClassDB) type.
+ return String("PluginScript");
}
String PluginScriptLanguage::get_extension() const {
@@ -168,7 +172,7 @@ Error PluginScriptLanguage::complete_code(const String &p_code, const String &p_
for (int i = 0; i < options.size(); i++) {
r_options->push_back(String(options[i]));
}
- Error err = *(Error *)tmp;
+ Error err = *(Error *)&tmp;
return err;
}
return ERR_UNAVAILABLE;
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index b5bbaa6dc9..9566e3b32e 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -349,7 +349,9 @@ public:
csi.resize(_debug_call_stack_pos);
for (int i = 0; i < _debug_call_stack_pos; i++) {
csi[_debug_call_stack_pos - i - 1].line = _call_stack[i].line ? *_call_stack[i].line : 0;
- csi[_debug_call_stack_pos - i - 1].script = Ref<GDScript>(_call_stack[i].function->get_script());
+ if (_call_stack[i].function)
+ csi[_debug_call_stack_pos - i - 1].func = _call_stack[i].function->get_name();
+ csi[_debug_call_stack_pos - i - 1].file = _call_stack[i].function->get_script()->get_path();
}
return csi;
}
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 949c636050..db2d0a9780 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -445,6 +445,72 @@ String CSharpLanguage::_get_indentation() const {
return "\t";
}
+Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info() {
+
+ // Printing an error here will result in endless recursion, so we must be careful
+
+ if (!gdmono->is_runtime_initialized() && GDMono::get_singleton()->get_api_assembly())
+ return Vector<StackInfo>();
+
+ MonoObject *stack_trace = mono_object_new(mono_domain_get(), CACHED_CLASS(System_Diagnostics_StackTrace)->get_mono_ptr());
+
+ MonoBoolean need_file_info = true;
+ void *ctor_args[1] = { &need_file_info };
+
+ CACHED_METHOD(System_Diagnostics_StackTrace, ctor_bool)->invoke_raw(stack_trace, ctor_args);
+
+ Vector<StackInfo> si;
+ si = stack_trace_get_info(stack_trace);
+
+ return si;
+}
+
+Vector<ScriptLanguage::StackInfo> CSharpLanguage::stack_trace_get_info(MonoObject *p_stack_trace) {
+
+ // Printing an error here could result in endless recursion, so we must be careful
+
+ MonoObject *exc = NULL;
+
+ GDMonoUtils::StackTrace_GetFrames st_get_frames = CACHED_METHOD_THUNK(System_Diagnostics_StackTrace, GetFrames);
+ MonoArray *frames = st_get_frames(p_stack_trace, &exc);
+
+ if (exc) {
+ GDMonoUtils::print_unhandled_exception(exc, true /* fail silently to avoid endless recursion */);
+ return Vector<StackInfo>();
+ }
+
+ int frame_count = mono_array_length(frames);
+
+ if (frame_count <= 0)
+ return Vector<StackInfo>();
+
+ GDMonoUtils::DebugUtils_StackFrameInfo get_sf_info = CACHED_METHOD_THUNK(DebuggingUtils, GetStackFrameInfo);
+
+ Vector<StackInfo> si;
+ si.resize(frame_count);
+
+ for (int i = 0; i < frame_count; i++) {
+ StackInfo &sif = si[i];
+ MonoObject *frame = mono_array_get(frames, MonoObject *, i);
+
+ MonoString *file_name;
+ int file_line_num;
+ MonoString *method_decl;
+ get_sf_info(frame, &file_name, &file_line_num, &method_decl, &exc);
+
+ if (exc) {
+ GDMonoUtils::print_unhandled_exception(exc, true /* fail silently to avoid endless recursion */);
+ return Vector<StackInfo>();
+ }
+
+ sif.file = GDMonoMarshal::mono_string_to_godot(file_name);
+ sif.line = file_line_num;
+ sif.func = GDMonoMarshal::mono_string_to_godot(method_decl);
+ }
+
+ return si;
+}
+
void CSharpLanguage::frame() {
const Ref<MonoGCHandle> &task_scheduler_handle = GDMonoUtils::mono_cache.task_scheduler_handle;
@@ -1049,7 +1115,7 @@ bool CSharpInstance::has_method(const StringName &p_method) const {
GDMonoClass *top = script->script_class;
while (top && top != script->native) {
- if (top->has_method(p_method)) {
+ if (top->has_fetched_method_unknown_params(p_method)) {
return true;
}
@@ -1227,7 +1293,7 @@ ScriptInstance::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method)
GDMonoClass *top = script->script_class;
while (top && top != script->native) {
- GDMonoMethod *method = top->get_method(p_method);
+ GDMonoMethod *method = top->get_fetched_method_unknown_params(p_method);
if (method && !method->is_static())
return _member_get_rpc_mode(method);
@@ -1848,7 +1914,7 @@ void CSharpScript::set_source_code(const String &p_code) {
bool CSharpScript::has_method(const StringName &p_method) const {
- return script_class->has_method(p_method);
+ return script_class->has_fetched_method_unknown_params(p_method);
}
Error CSharpScript::reload(bool p_keep_state) {
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 171601f3d8..3ce8a9b64e 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -303,7 +303,7 @@ public:
/* TODO */ virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {}
/* TODO */ virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {}
/* TODO */ virtual String debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth) { return ""; }
- /* TODO */ virtual Vector<StackInfo> debug_get_current_stack_info() { return Vector<StackInfo>(); }
+ virtual Vector<StackInfo> debug_get_current_stack_info();
/* PROFILING FUNCTIONS */
/* TODO */ virtual void profiling_start() {}
@@ -335,6 +335,8 @@ public:
virtual void *alloc_instance_binding_data(Object *p_object);
virtual void free_instance_binding_data(void *p_data);
+ Vector<StackInfo> stack_trace_get_info(MonoObject *p_stack_trace);
+
CSharpLanguage();
~CSharpLanguage();
};
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 2205ac4e98..800e3b723b 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -448,14 +448,14 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo
compile_items.push_back(output_file);
}
- for (Map<StringName, TypeInterface>::Element *E = obj_types.front(); E; E = E->next()) {
- const TypeInterface &itype = E->get();
+ for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) {
+ const TypeInterface &itype = E.get();
if (itype.api_type == ClassDB::API_EDITOR)
continue;
- String output_file = path_join(obj_type_dir, E->get().proxy_name + ".cs");
- Error err = _generate_cs_type(E->get(), output_file);
+ String output_file = path_join(obj_type_dir, itype.proxy_name + ".cs");
+ Error err = _generate_cs_type(itype, output_file);
if (err == ERR_SKIP)
continue;
@@ -580,14 +580,14 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir,
if (!solution.set_path(p_output_dir))
return ERR_FILE_NOT_FOUND;
- for (Map<StringName, TypeInterface>::Element *E = obj_types.front(); E; E = E->next()) {
- const TypeInterface &itype = E->get();
+ for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) {
+ const TypeInterface &itype = E.get();
if (itype.api_type != ClassDB::API_EDITOR)
continue;
- String output_file = path_join(obj_type_dir, E->get().proxy_name + ".cs");
- Error err = _generate_cs_type(E->get(), output_file);
+ String output_file = path_join(obj_type_dir, itype.proxy_name + ".cs");
+ Error err = _generate_cs_type(itype, output_file);
if (err == ERR_SKIP)
continue;
@@ -945,7 +945,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
return ERR_BUG;
}
- Map<StringName, TypeInterface>::Element *object_itype = obj_types.find("Object");
+ OrderedHashMap<StringName, TypeInterface>::Element object_itype = obj_types.find("Object");
if (!object_itype) {
ERR_PRINT("BUG: Object type interface not found!");
@@ -953,7 +953,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
}
output.push_back(MEMBER_BEGIN "public " CS_CLASS_SIGNALAWAITER " ToSignal(");
- output.push_back(object_itype->get().cs_type);
+ output.push_back(object_itype.get().cs_type);
output.push_back(" source, string signal)\n" OPEN_BLOCK_L2
"return new " CS_CLASS_SIGNALAWAITER "(source, signal, this);\n" CLOSE_BLOCK_L2);
}
@@ -999,9 +999,9 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
// Search it in base types too
const TypeInterface *current_type = &p_itype;
while (!setter && current_type->base_name != StringName()) {
- Map<StringName, TypeInterface>::Element *base_match = obj_types.find(current_type->base_name);
- ERR_FAIL_NULL_V(base_match, ERR_BUG);
- current_type = &base_match->get();
+ OrderedHashMap<StringName, TypeInterface>::Element base_match = obj_types.find(current_type->base_name);
+ ERR_FAIL_COND_V(!base_match, ERR_BUG);
+ current_type = &base_match.get();
setter = current_type->find_method_by_name(p_iprop.setter);
}
@@ -1010,9 +1010,9 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
// Search it in base types too
current_type = &p_itype;
while (!getter && current_type->base_name != StringName()) {
- Map<StringName, TypeInterface>::Element *base_match = obj_types.find(current_type->base_name);
- ERR_FAIL_NULL_V(base_match, ERR_BUG);
- current_type = &base_match->get();
+ OrderedHashMap<StringName, TypeInterface>::Element base_match = obj_types.find(current_type->base_name);
+ ERR_FAIL_COND_V(!base_match, ERR_BUG);
+ current_type = &base_match.get();
getter = current_type->find_method_by_name(p_iprop.getter);
}
@@ -1324,8 +1324,8 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
generated_icall_funcs.clear();
- for (Map<StringName, TypeInterface>::Element *type_elem = obj_types.front(); type_elem; type_elem = type_elem->next()) {
- const TypeInterface &itype = type_elem->get();
+ for (OrderedHashMap<StringName, TypeInterface>::Element type_elem = obj_types.front(); type_elem; type_elem = type_elem.next()) {
+ const TypeInterface &itype = type_elem.get();
List<InternalCall> &custom_icalls = itype.api_type == ClassDB::API_EDITOR ? editor_custom_icalls : core_custom_icalls;
@@ -1631,20 +1631,20 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_by_name_or_null(const StringName &p_cname) {
- const Map<StringName, TypeInterface>::Element *match = builtin_types.find(p_cname);
+ const Map<StringName, TypeInterface>::Element *builtin_type_match = builtin_types.find(p_cname);
- if (match)
- return &match->get();
+ if (builtin_type_match)
+ return &builtin_type_match->get();
- match = obj_types.find(p_cname);
+ const OrderedHashMap<StringName, TypeInterface>::Element obj_type_match = obj_types.find(p_cname);
- if (match)
- return &match->get();
+ if (obj_type_match)
+ return &obj_type_match.get();
- match = enum_types.find(p_cname);
+ const Map<StringName, TypeInterface>::Element *enum_match = enum_types.find(p_cname);
- if (match)
- return &match->get();
+ if (enum_match)
+ return &enum_match->get();
return NULL;
}
@@ -2484,8 +2484,8 @@ void BindingsGenerator::initialize() {
_generate_header_icalls();
- for (Map<StringName, TypeInterface>::Element *E = obj_types.front(); E; E = E->next())
- _generate_method_icalls(E->get());
+ for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next())
+ _generate_method_icalls(E.get());
_generate_method_icalls(builtin_types["NodePath"]);
_generate_method_icalls(builtin_types["RID"]);
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index 717a6b7a6b..8929b45cce 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -429,10 +429,11 @@ class BindingsGenerator {
static bool verbose_output;
+ OrderedHashMap<StringName, TypeInterface> obj_types;
+
Map<StringName, TypeInterface> placeholder_types;
Map<StringName, TypeInterface> builtin_types;
Map<StringName, TypeInterface> enum_types;
- Map<StringName, TypeInterface> obj_types;
List<EnumInterface> global_enums;
List<ConstantInterface> global_constants;
diff --git a/modules/mono/editor/godotsharp_editor.cpp b/modules/mono/editor/godotsharp_editor.cpp
index da0a7b4fbd..9e48da68c1 100644
--- a/modules/mono/editor/godotsharp_editor.cpp
+++ b/modules/mono/editor/godotsharp_editor.cpp
@@ -151,7 +151,7 @@ Error GodotSharpEditor::open_in_external_editor(const Ref<Script> &p_script, int
if (p_line >= 0) {
args.push_back("-g");
- args.push_back(script_path + ":" + itos(p_line) + ":" + itos(p_col));
+ args.push_back(script_path + ":" + itos(p_line + 1) + ":" + itos(p_col));
} else {
args.push_back(script_path);
}
@@ -170,6 +170,11 @@ Error GodotSharpEditor::open_in_external_editor(const Ref<Script> &p_script, int
monodevel_instance = memnew(MonoDevelopInstance(GodotSharpDirs::get_project_sln_path()));
String script_path = ProjectSettings::get_singleton()->globalize_path(p_script->get_path());
+
+ if (p_line >= 0) {
+ script_path += ";" + itos(p_line + 1) + ";" + itos(p_col);
+ }
+
monodevel_instance->execute(script_path);
} break;
default:
diff --git a/modules/mono/glue/cs_files/Color.cs b/modules/mono/glue/cs_files/Color.cs
index db0e1fb744..f9e31e9703 100644
--- a/modules/mono/glue/cs_files/Color.cs
+++ b/modules/mono/glue/cs_files/Color.cs
@@ -336,7 +336,7 @@ namespace Godot
this.r = (rgba & 0xFF) / 255.0f;
}
- private static float _parse_col(string str, int ofs)
+ private static int _parse_col(string str, int ofs)
{
int ig = 0;
@@ -415,17 +415,17 @@ namespace Godot
if (alpha)
{
- if ((int)_parse_col(color, 0) < 0)
+ if (_parse_col(color, 0) < 0)
return false;
}
int from = alpha ? 2 : 0;
- if ((int)_parse_col(color, from + 0) < 0)
+ if (_parse_col(color, from + 0) < 0)
return false;
- if ((int)_parse_col(color, from + 2) < 0)
+ if (_parse_col(color, from + 2) < 0)
return false;
- if ((int)_parse_col(color, from + 4) < 0)
+ if (_parse_col(color, from + 4) < 0)
return false;
return true;
@@ -467,10 +467,10 @@ namespace Godot
if (alpha)
{
- a = _parse_col(rgba, 0);
+ a = _parse_col(rgba, 0) / 255f;
if (a < 0)
- throw new ArgumentOutOfRangeException("Invalid color code. Alpha is " + a + " but zero or greater is expected: " + rgba);
+ throw new ArgumentOutOfRangeException("Invalid color code. Alpha part is not valid hexadecimal: " + rgba);
}
else
{
@@ -479,20 +479,20 @@ namespace Godot
int from = alpha ? 2 : 0;
- r = _parse_col(rgba, from + 0);
+ r = _parse_col(rgba, from + 0) / 255f;
if (r < 0)
- throw new ArgumentOutOfRangeException("Invalid color code. Red is " + r + " but zero or greater is expected: " + rgba);
+ throw new ArgumentOutOfRangeException("Invalid color code. Red part is not valid hexadecimal: " + rgba);
- g = _parse_col(rgba, from + 2);
+ g = _parse_col(rgba, from + 2) / 255f;
if (g < 0)
- throw new ArgumentOutOfRangeException("Invalid color code. Green is " + g + " but zero or greater is expected: " + rgba);
+ throw new ArgumentOutOfRangeException("Invalid color code. Green part is not valid hexadecimal: " + rgba);
- b = _parse_col(rgba, from + 4);
+ b = _parse_col(rgba, from + 4) / 255f;
if (b < 0)
- throw new ArgumentOutOfRangeException("Invalid color code. Blue is " + b + " but zero or greater is expected: " + rgba);
+ throw new ArgumentOutOfRangeException("Invalid color code. Blue part is not valid hexadecimal: " + rgba);
}
public static bool operator ==(Color left, Color right)
diff --git a/modules/mono/glue/cs_files/DebuggingUtils.cs b/modules/mono/glue/cs_files/DebuggingUtils.cs
new file mode 100644
index 0000000000..ced78f658d
--- /dev/null
+++ b/modules/mono/glue/cs_files/DebuggingUtils.cs
@@ -0,0 +1,77 @@
+using System;
+using System.Diagnostics;
+using System.Reflection;
+using System.Text;
+
+namespace Godot
+{
+ internal static class DebuggingUtils
+ {
+ internal static void AppendTypeName(this StringBuilder sb, Type type)
+ {
+ if (type.IsPrimitive)
+ sb.Append(type.Name);
+ else if (type == typeof(void))
+ sb.Append("void");
+ else
+ sb.Append(type.ToString());
+
+ sb.Append(" ");
+ }
+
+ public static void GetStackFrameInfo(StackFrame frame, out string fileName, out int fileLineNumber, out string methodDecl)
+ {
+ fileName = frame.GetFileName();
+ fileLineNumber = frame.GetFileLineNumber();
+
+ MethodBase methodBase = frame.GetMethod();
+
+ StringBuilder sb = new StringBuilder();
+
+ if (methodBase is MethodInfo methodInfo)
+ sb.AppendTypeName(methodInfo.ReturnType);
+
+ sb.Append(methodBase.DeclaringType.FullName);
+ sb.Append(".");
+ sb.Append(methodBase.Name);
+
+ if (methodBase.IsGenericMethod)
+ {
+ Type[] genericParams = methodBase.GetGenericArguments();
+
+ sb.Append("<");
+
+ for (int j = 0; j < genericParams.Length; j++)
+ {
+ if (j > 0)
+ sb.Append(", ");
+
+ sb.AppendTypeName(genericParams[j]);
+ }
+
+ sb.Append(">");
+ }
+
+ sb.Append("(");
+
+ bool varArgs = (methodBase.CallingConvention & CallingConventions.VarArgs) != 0;
+
+ ParameterInfo[] parameter = methodBase.GetParameters();
+
+ for (int i = 0; i < parameter.Length; i++)
+ {
+ if (i > 0)
+ sb.Append(", ");
+
+ if (i == parameter.Length - 1 && varArgs)
+ sb.Append("params ");
+
+ sb.AppendTypeName(parameter[i].ParameterType);
+ }
+
+ sb.Append(")");
+
+ methodDecl = sb.ToString();
+ }
+ }
+}
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index d4df7e0cb2..6c07c90f79 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -226,7 +226,7 @@ void GDMono::initialize() {
mono_install_unhandled_exception_hook(gdmono_unhandled_exception_hook, NULL);
- OS::get_singleton()->print("Mono: ALL IS GOOD\n");
+ OS::get_singleton()->print("Mono: INITIALIZED\n");
}
#ifndef MONO_GLUE_DISABLED
diff --git a/modules/mono/mono_gd/gd_mono_class.cpp b/modules/mono/mono_gd/gd_mono_class.cpp
index d3315568cb..b826352f02 100644
--- a/modules/mono/mono_gd/gd_mono_class.cpp
+++ b/modules/mono/mono_gd/gd_mono_class.cpp
@@ -89,11 +89,6 @@ Vector<MonoClassField *> GDMonoClass::get_enum_fields() {
}
#endif
-bool GDMonoClass::has_method(const StringName &p_name) {
-
- return get_method(p_name) != NULL;
-}
-
bool GDMonoClass::has_attribute(GDMonoClass *p_attr_class) {
#ifdef DEBUG_ENABLED
@@ -225,7 +220,7 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base
methods_fetched = true;
}
-GDMonoMethod *GDMonoClass::get_method(const StringName &p_name) {
+GDMonoMethod *GDMonoClass::get_fetched_method_unknown_params(const StringName &p_name) {
ERR_FAIL_COND_V(!methods_fetched, NULL);
@@ -239,6 +234,11 @@ GDMonoMethod *GDMonoClass::get_method(const StringName &p_name) {
return NULL;
}
+bool GDMonoClass::has_fetched_method_unknown_params(const StringName &p_name) {
+
+ return get_fetched_method_unknown_params(p_name) != NULL;
+}
+
GDMonoMethod *GDMonoClass::get_method(const StringName &p_name, int p_params_count) {
MethodKey key = MethodKey(p_name, p_params_count);
@@ -303,6 +303,8 @@ GDMonoMethod *GDMonoClass::get_method_with_desc(const String &p_description, boo
MonoMethod *method = mono_method_desc_search_in_class(desc, mono_class);
mono_method_desc_free(desc);
+ ERR_FAIL_COND_V(mono_method_get_class(method) != mono_class, NULL);
+
return get_method(method);
}
diff --git a/modules/mono/mono_gd/gd_mono_class.h b/modules/mono/mono_gd/gd_mono_class.h
index b6052ac0ed..f5895be144 100644
--- a/modules/mono/mono_gd/gd_mono_class.h
+++ b/modules/mono/mono_gd/gd_mono_class.h
@@ -112,7 +112,8 @@ public:
Vector<MonoClassField *> get_enum_fields();
#endif
- bool has_method(const StringName &p_name);
+ GDMonoMethod *get_fetched_method_unknown_params(const StringName &p_name);
+ bool has_fetched_method_unknown_params(const StringName &p_name);
bool has_attribute(GDMonoClass *p_attr_class);
MonoObject *get_attribute(GDMonoClass *p_attr_class);
@@ -120,8 +121,7 @@ public:
void fetch_attributes();
void fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base);
- GDMonoMethod *get_method(const StringName &p_name);
- GDMonoMethod *get_method(const StringName &p_name, int p_params_count);
+ GDMonoMethod *get_method(const StringName &p_name, int p_params_count = 0);
GDMonoMethod *get_method(MonoMethod *p_raw_method);
GDMonoMethod *get_method(MonoMethod *p_raw_method, const StringName &p_name);
GDMonoMethod *get_method(MonoMethod *p_raw_method, const StringName &p_name, int p_params_count);
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index ff999b36f2..d02c73978e 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -31,6 +31,7 @@
#include "gd_mono_utils.h"
#include "os/dir_access.h"
+#include "os/os.h"
#include "project_settings.h"
#include "reference.h"
@@ -53,6 +54,7 @@ MonoCache mono_cache;
#define CACHE_NS_CLASS_AND_CHECK(m_ns, m_class, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.class_##m_ns##_##m_class, m_val)
#define CACHE_RAW_MONO_CLASS_AND_CHECK(m_class, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.rawclass_##m_class, m_val)
#define CACHE_FIELD_AND_CHECK(m_class, m_field, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.field_##m_class##_##m_field, m_val)
+#define CACHE_METHOD_AND_CHECK(m_class, m_method, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.method_##m_class##_##m_method, m_val)
#define CACHE_METHOD_THUNK_AND_CHECK(m_class, m_method, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.methodthunk_##m_class##_##m_method, m_val)
void MonoCache::clear_members() {
@@ -72,6 +74,13 @@ void MonoCache::clear_members() {
class_String = NULL;
class_IntPtr = NULL;
+#ifdef DEBUG_ENABLED
+ class_System_Diagnostics_StackTrace = NULL;
+ methodthunk_System_Diagnostics_StackTrace_GetFrames = NULL;
+ method_System_Diagnostics_StackTrace_ctor_bool = NULL;
+ method_System_Diagnostics_StackTrace_ctor_Exception_bool = NULL;
+#endif
+
rawclass_Dictionary = NULL;
class_Vector2 = NULL;
@@ -94,6 +103,11 @@ void MonoCache::clear_members() {
class_WeakRef = NULL;
class_MarshalUtils = NULL;
+#ifdef DEBUG_ENABLED
+ class_DebuggingUtils = NULL;
+ methodthunk_DebuggingUtils_GetStackFrameInfo = NULL;
+#endif
+
class_ExportAttribute = NULL;
field_ExportAttribute_hint = NULL;
field_ExportAttribute_hintString = NULL;
@@ -137,6 +151,13 @@ void update_corlib_cache() {
CACHE_CLASS_AND_CHECK(double, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_double_class()));
CACHE_CLASS_AND_CHECK(String, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_string_class()));
CACHE_CLASS_AND_CHECK(IntPtr, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_intptr_class()));
+
+#ifdef DEBUG_ENABLED
+ CACHE_CLASS_AND_CHECK(System_Diagnostics_StackTrace, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Diagnostics", "StackTrace"));
+ CACHE_METHOD_THUNK_AND_CHECK(System_Diagnostics_StackTrace, GetFrames, (StackTrace_GetFrames)CACHED_CLASS(System_Diagnostics_StackTrace)->get_method("GetFrames")->get_thunk());
+ CACHE_METHOD_AND_CHECK(System_Diagnostics_StackTrace, ctor_bool, CACHED_CLASS(System_Diagnostics_StackTrace)->get_method_with_desc("System.Diagnostics.StackTrace:.ctor(bool)", true));
+ CACHE_METHOD_AND_CHECK(System_Diagnostics_StackTrace, ctor_Exception_bool, CACHED_CLASS(System_Diagnostics_StackTrace)->get_method_with_desc("System.Diagnostics.StackTrace:.ctor(System.Exception,bool)", true));
+#endif
}
void update_godot_api_cache() {
@@ -161,6 +182,10 @@ void update_godot_api_cache() {
CACHE_CLASS_AND_CHECK(WeakRef, GODOT_API_CLASS(WeakRef));
CACHE_CLASS_AND_CHECK(MarshalUtils, GODOT_API_CLASS(MarshalUtils));
+#ifdef DEBUG_ENABLED
+ CACHE_CLASS_AND_CHECK(DebuggingUtils, GODOT_API_CLASS(DebuggingUtils));
+#endif
+
// Attributes
CACHE_CLASS_AND_CHECK(ExportAttribute, GODOT_API_CLASS(ExportAttribute));
CACHE_FIELD_AND_CHECK(ExportAttribute, hint, CACHED_CLASS(ExportAttribute)->get_field("hint"));
@@ -183,6 +208,10 @@ void update_godot_api_cache() {
CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, FailureCallback, (SignalAwaiter_FailureCallback)GODOT_API_CLASS(SignalAwaiter)->get_method("FailureCallback", 0)->get_thunk());
CACHE_METHOD_THUNK_AND_CHECK(GodotTaskScheduler, Activate, (GodotTaskScheduler_Activate)GODOT_API_CLASS(GodotTaskScheduler)->get_method("Activate", 0)->get_thunk());
+#ifdef DEBUG_ENABLED
+ CACHE_METHOD_THUNK_AND_CHECK(DebuggingUtils, GetStackFrameInfo, (DebugUtils_StackFrameInfo)GODOT_API_CLASS(DebuggingUtils)->get_method("GetStackFrameInfo", 4)->get_thunk());
+#endif
+
{
/*
* TODO Right now we only support Dictionary<object, object>.
@@ -366,9 +395,47 @@ String get_exception_name_and_message(MonoObject *p_ex) {
return res;
}
-void print_unhandled_exception(MonoObject *p_ex) {
- ERR_PRINT(GDMonoUtils::get_exception_name_and_message(p_ex).utf8());
- mono_print_unhandled_exception(p_ex);
+void print_unhandled_exception(MonoObject *p_exc) {
+ print_unhandled_exception(p_exc, false);
+}
+
+void print_unhandled_exception(MonoObject *p_exc, bool p_recursion_caution) {
+ mono_print_unhandled_exception(p_exc);
+#ifdef DEBUG_ENABLED
+ GDMonoClass *st_klass = CACHED_CLASS(System_Diagnostics_StackTrace);
+ MonoObject *stack_trace = mono_object_new(mono_domain_get(), st_klass->get_mono_ptr());
+
+ MonoBoolean need_file_info = true;
+ void *ctor_args[2] = { p_exc, &need_file_info };
+
+ MonoObject *unexpected_exc = NULL;
+ CACHED_METHOD(System_Diagnostics_StackTrace, ctor_Exception_bool)->invoke_raw(stack_trace, ctor_args, &unexpected_exc);
+
+ if (unexpected_exc != NULL) {
+ mono_print_unhandled_exception(unexpected_exc);
+
+ if (p_recursion_caution) {
+ // Called from CSharpLanguage::get_current_stack_info,
+ // so printing an error here could result in endless recursion
+ OS::get_singleton()->printerr("Mono: Method GDMonoUtils::print_unhandled_exception failed");
+ return;
+ } else {
+ ERR_FAIL();
+ }
+ }
+
+ Vector<ScriptLanguage::StackInfo> si;
+ if (stack_trace != NULL && !p_recursion_caution)
+ si = CSharpLanguage::get_singleton()->stack_trace_get_info(stack_trace);
+
+ String file = si.size() ? si[0].file : __FILE__;
+ String func = si.size() ? si[0].func : FUNCTION_STR;
+ int line = si.size() ? si[0].line : __LINE__;
+ String error_msg = "Unhandled exception";
+ String exc_msg = GDMonoUtils::get_exception_name_and_message(p_exc);
+
+ ScriptDebugger::get_singleton()->send_error(func, file, line, error_msg, exc_msg, ERR_HANDLER_ERROR, si);
+#endif
}
} // namespace GDMonoUtils
diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h
index 284585856e..597397eced 100644
--- a/modules/mono/mono_gd/gd_mono_utils.h
+++ b/modules/mono/mono_gd/gd_mono_utils.h
@@ -46,13 +46,10 @@ typedef MonoObject *(*MarshalUtils_ArraysToDict)(MonoArray *, MonoArray *, MonoO
typedef MonoObject *(*SignalAwaiter_SignalCallback)(MonoObject *, MonoArray **, MonoObject **);
typedef MonoObject *(*SignalAwaiter_FailureCallback)(MonoObject *, MonoObject **);
typedef MonoObject *(*GodotTaskScheduler_Activate)(MonoObject *, MonoObject **);
+typedef MonoArray *(*StackTrace_GetFrames)(MonoObject *, MonoObject **);
+typedef void (*DebugUtils_StackFrameInfo)(MonoObject *, MonoString **, int *, MonoString **, MonoObject **);
struct MonoCache {
- // Format for cached classes in the Godot namespace: class_<Class>
- // Macro: CACHED_CLASS(<Class>)
-
- // Format for cached classes in a different namespace: class_<Namespace>_<Class>
- // Macro: CACHED_NS_CLASS(<Namespace>, <Class>)
// -----------------------------------------------
// corlib classes
@@ -73,6 +70,13 @@ struct MonoCache {
GDMonoClass *class_String;
GDMonoClass *class_IntPtr;
+#ifdef DEBUG_ENABLED
+ GDMonoClass *class_System_Diagnostics_StackTrace;
+ StackTrace_GetFrames methodthunk_System_Diagnostics_StackTrace_GetFrames;
+ GDMonoMethod *method_System_Diagnostics_StackTrace_ctor_bool;
+ GDMonoMethod *method_System_Diagnostics_StackTrace_ctor_Exception_bool;
+#endif
+
MonoClass *rawclass_Dictionary;
// -----------------------------------------------
@@ -96,6 +100,11 @@ struct MonoCache {
GDMonoClass *class_WeakRef;
GDMonoClass *class_MarshalUtils;
+#ifdef DEBUG_ENABLED
+ GDMonoClass *class_DebuggingUtils;
+ DebugUtils_StackFrameInfo methodthunk_DebuggingUtils_GetStackFrameInfo;
+#endif
+
GDMonoClass *class_ExportAttribute;
GDMonoField *field_ExportAttribute_hint;
GDMonoField *field_ExportAttribute_hintString;
@@ -167,7 +176,8 @@ MonoDomain *create_domain(const String &p_friendly_name);
String get_exception_name_and_message(MonoObject *p_ex);
-void print_unhandled_exception(MonoObject *p_ex);
+void print_unhandled_exception(MonoObject *p_exc);
+void print_unhandled_exception(MonoObject *p_exc, bool p_recursion_caution);
} // namespace GDMonoUtils
@@ -175,9 +185,9 @@ void print_unhandled_exception(MonoObject *p_ex);
#define CACHED_CLASS(m_class) (GDMonoUtils::mono_cache.class_##m_class)
#define CACHED_CLASS_RAW(m_class) (GDMonoUtils::mono_cache.class_##m_class->get_mono_ptr())
-#define CACHED_NS_CLASS(m_ns, m_class) (GDMonoUtils::mono_cache.class_##m_ns##_##m_class)
#define CACHED_RAW_MONO_CLASS(m_class) (GDMonoUtils::mono_cache.rawclass_##m_class)
#define CACHED_FIELD(m_class, m_field) (GDMonoUtils::mono_cache.field_##m_class##_##m_field)
+#define CACHED_METHOD(m_class, m_method) (GDMonoUtils::mono_cache.method_##m_class##_##m_method)
#define CACHED_METHOD_THUNK(m_class, m_method) (GDMonoUtils::mono_cache.methodthunk_##m_class##_##m_method)
#ifdef REAL_T_IS_DOUBLE
diff --git a/modules/regex/regex.cpp b/modules/regex/regex.cpp
index 9bcbc4c4ea..3fe7e36d45 100644
--- a/modules/regex/regex.cpp
+++ b/modules/regex/regex.cpp
@@ -343,15 +343,20 @@ String RegEx::sub(const String &p_subject, const String &p_replacement, bool p_a
ERR_FAIL_COND_V(!is_valid(), String());
- String output;
- output.resize(p_subject.length());
+ // safety_zone is the number of chars we allocate in addition to the number of chars expected in order to
+ // guard against the PCRE API writing one additional \0 at the end. PCRE's API docs are unclear on whether
+ // PCRE understands outlength in pcre2_substitute() as counting an implicit additional terminating char or
+ // not. always allocating one char more than telling PCRE has us on the safe side.
+ const int safety_zone = 1;
+
+ PCRE2_SIZE olength = p_subject.length() + 1; // space for output string and one terminating \0 character
+ Vector<CharType> output;
+ output.resize(olength + safety_zone);
uint32_t flags = PCRE2_SUBSTITUTE_OVERFLOW_LENGTH;
if (p_all)
flags |= PCRE2_SUBSTITUTE_GLOBAL;
- PCRE2_SIZE olength = output.length();
-
PCRE2_SIZE length = p_subject.length();
if (p_end >= 0 && (uint32_t)p_end < length)
length = p_end;
@@ -363,15 +368,15 @@ String RegEx::sub(const String &p_subject, const String &p_replacement, bool p_a
pcre2_match_context_16 *mctx = pcre2_match_context_create_16(gctx);
PCRE2_SPTR16 s = (PCRE2_SPTR16)p_subject.c_str();
PCRE2_SPTR16 r = (PCRE2_SPTR16)p_replacement.c_str();
- PCRE2_UCHAR16 *o = (PCRE2_UCHAR16 *)output.c_str();
+ PCRE2_UCHAR16 *o = (PCRE2_UCHAR16 *)output.ptrw();
pcre2_match_data_16 *match = pcre2_match_data_create_from_pattern_16(c, gctx);
int res = pcre2_substitute_16(c, s, length, p_offset, flags, match, mctx, r, p_replacement.length(), o, &olength);
if (res == PCRE2_ERROR_NOMEMORY) {
- output.resize(olength);
- o = (PCRE2_UCHAR16 *)output.c_str();
+ output.resize(olength + safety_zone);
+ o = (PCRE2_UCHAR16 *)output.ptrw();
res = pcre2_substitute_16(c, s, length, p_offset, flags, match, mctx, r, p_replacement.length(), o, &olength);
}
@@ -388,15 +393,15 @@ String RegEx::sub(const String &p_subject, const String &p_replacement, bool p_a
pcre2_match_context_32 *mctx = pcre2_match_context_create_32(gctx);
PCRE2_SPTR32 s = (PCRE2_SPTR32)p_subject.c_str();
PCRE2_SPTR32 r = (PCRE2_SPTR32)p_replacement.c_str();
- PCRE2_UCHAR32 *o = (PCRE2_UCHAR32 *)output.c_str();
+ PCRE2_UCHAR32 *o = (PCRE2_UCHAR32 *)output.ptrw();
pcre2_match_data_32 *match = pcre2_match_data_create_from_pattern_32(c, gctx);
int res = pcre2_substitute_32(c, s, length, p_offset, flags, match, mctx, r, p_replacement.length(), o, &olength);
if (res == PCRE2_ERROR_NOMEMORY) {
- output.resize(olength);
- o = (PCRE2_UCHAR32 *)output.c_str();
+ output.resize(olength + safety_zone);
+ o = (PCRE2_UCHAR32 *)output.ptrw();
res = pcre2_substitute_32(c, s, length, p_offset, flags, match, mctx, r, p_replacement.length(), o, &olength);
}
@@ -407,7 +412,7 @@ String RegEx::sub(const String &p_subject, const String &p_replacement, bool p_a
return String();
}
- return output;
+ return String(output.ptr(), olength);
}
bool RegEx::is_valid() const {
diff --git a/platform/android/build.gradle.template b/platform/android/build.gradle.template
index 89189ef1a0..7269e658b4 100644
--- a/platform/android/build.gradle.template
+++ b/platform/android/build.gradle.template
@@ -15,6 +15,7 @@ allprojects {
repositories {
jcenter()
mavenCentral()
+ google()
$$GRADLE_REPOSITORY_URLS$$
}
}
diff --git a/platform/android/java/src/org/godotengine/godot/Godot.java b/platform/android/java/src/org/godotengine/godot/Godot.java
index 37f25cc839..b5b0afb9e0 100644
--- a/platform/android/java/src/org/godotengine/godot/Godot.java
+++ b/platform/android/java/src/org/godotengine/godot/Godot.java
@@ -828,7 +828,6 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
//@Override public boolean dispatchTouchEvent (MotionEvent event) {
public boolean gotTouchEvent(final MotionEvent event) {
- super.onTouchEvent(event);
final int evcount = event.getPointerCount();
if (evcount == 0)
return true;
@@ -842,6 +841,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
arr[i * 3 + 1] = (int)event.getX(i);
arr[i * 3 + 2] = (int)event.getY(i);
}
+ final int pointer_idx = event.getPointerId(event.getActionIndex());
//System.out.printf("gaction: %d\n",event.getAction());
final int action = event.getAction() & MotionEvent.ACTION_MASK;
@@ -862,13 +862,10 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
*/
} break;
case MotionEvent.ACTION_POINTER_UP: {
- final int indexPointUp = event.getActionIndex();
- final int pointer_idx = event.getPointerId(indexPointUp);
GodotLib.touch(4, pointer_idx, evcount, arr);
//System.out.printf("%d - s.up at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
} break;
case MotionEvent.ACTION_POINTER_DOWN: {
- int pointer_idx = event.getActionIndex();
GodotLib.touch(3, pointer_idx, evcount, arr);
//System.out.printf("%d - s.down at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
} break;
diff --git a/platform/android/java/src/org/godotengine/godot/GodotView.java b/platform/android/java/src/org/godotengine/godot/GodotView.java
index ca4895a2be..0222758c2b 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotView.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotView.java
@@ -110,7 +110,7 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
@Override
public boolean onTouchEvent(MotionEvent event) {
-
+ super.onTouchEvent(event);
return activity.gotTouchEvent(event);
};
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 93272a1000..23811f963a 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -444,25 +444,27 @@ void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos>
}
touch.clear();
}
-
} break;
- case 3: { // add tuchi
-
- ERR_FAIL_INDEX(p_pointer, p_points.size());
+ case 3: { // add touch
- TouchPos tp = p_points[p_pointer];
- touch.push_back(tp);
+ for (int i = 0; i < p_points.size(); i++) {
+ if (p_points[i].id == p_pointer) {
+ TouchPos tp = p_points[i];
+ touch.push_back(tp);
- Ref<InputEventScreenTouch> ev;
- ev.instance();
+ Ref<InputEventScreenTouch> ev;
+ ev.instance();
- ev->set_index(tp.id);
- ev->set_pressed(true);
- ev->set_position(tp.pos);
- input->parse_input_event(ev);
+ ev->set_index(tp.id);
+ ev->set_pressed(true);
+ ev->set_position(tp.pos);
+ input->parse_input_event(ev);
+ break;
+ }
+ }
} break;
- case 4: {
+ case 4: { // remove touch
for (int i = 0; i < touch.size(); i++) {
if (touch[i].id == p_pointer) {
@@ -474,10 +476,10 @@ void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos>
ev->set_position(touch[i].pos);
input->parse_input_event(ev);
touch.remove(i);
- i--;
+
+ break;
}
}
-
} break;
}
}
diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp
index 99d44f3b5e..e3119814f4 100644
--- a/platform/iphone/export/export.cpp
+++ b/platform/iphone/export/export.cpp
@@ -407,7 +407,7 @@ Error EditorExportPlatformIOS::_export_loading_screens(const Ref<EditorExportPre
Error err = da->copy(loading_screen_file, p_dest_dir + info.export_name);
if (err) {
memdelete(da);
- String err_str = String("Failed to export loading screen: ") + loading_screen_file;
+ String err_str = String("Failed to export loading screen (") + info.preset_key + ") from path: " + loading_screen_file;
ERR_PRINT(err_str.utf8().get_data());
return err;
}
diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp
index 23ca1e3fb9..c4efa1f0ff 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/osx/export/export.cpp
@@ -359,6 +359,11 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
}
if (err == OK) {
+ print_line("Creating " + tmp_app_path_name + "/Contents/Frameworks");
+ err = tmp_app_path->make_dir_recursive(tmp_app_path_name + "/Contents/Frameworks");
+ }
+
+ if (err == OK) {
print_line("Creating " + tmp_app_path_name + "/Contents/Resources");
err = tmp_app_path->make_dir_recursive(tmp_app_path_name + "/Contents/Resources");
}
@@ -502,10 +507,23 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
if (use_dmg()) {
String pack_path = tmp_app_path_name + "/Contents/Resources/" + pkg_name + ".pck";
- err = save_pack(p_preset, pack_path);
+ Vector<SharedObject> shared_objects;
+ Error err = save_pack(p_preset, pack_path, &shared_objects);
// see if we can code sign our new package
String identity = p_preset->get("codesign/identity");
+
+ if (err == OK) {
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ for (int i = 0; i < shared_objects.size(); i++) {
+ da->copy(shared_objects[i].path, tmp_app_path_name + "/Contents/Frameworks/" + shared_objects[i].path.get_file());
+ if (err == OK && identity != "") {
+ err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Frameworks/" + shared_objects[i].path.get_file());
+ }
+ }
+ memdelete(da);
+ }
+
if (err == OK && identity != "") {
ep.step("Code signing bundle", 2);
@@ -582,7 +600,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
ERR_CONTINUE(file.empty());
zipOpenNewFileInZip(dst_pkg_zip,
- (pkg_name + ".app/Contents/MacOS/").plus_file(shared_objects[i].path.get_file()).utf8().get_data(),
+ (pkg_name + ".app/Contents/Frameworks/").plus_file(shared_objects[i].path.get_file()).utf8().get_data(),
NULL,
NULL,
0,
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index 9423b6e1d6..a1869497ef 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -52,6 +52,21 @@
class OS_OSX : public OS_Unix {
public:
+ enum {
+ KEY_EVENT_BUFFER_SIZE = 512
+ };
+
+ struct KeyEvent {
+ unsigned int osx_state;
+ bool pressed;
+ bool echo;
+ uint32_t scancode;
+ uint32_t unicode;
+ };
+
+ KeyEvent key_event_buffer[KEY_EVENT_BUFFER_SIZE];
+ int key_event_pos;
+
bool force_quit;
// rasterizer seems to no longer be given to visual server, its using GLES3 directly?
//Rasterizer *rasterizer;
@@ -72,6 +87,7 @@ public:
CGEventSourceRef eventSource;
void process_events();
+ void process_key_events();
void *framework;
// pthread_key_t current;
@@ -139,6 +155,8 @@ public:
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
+ virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false);
+
virtual void set_cursor_shape(CursorShape p_shape);
virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 19f33c814f..d0cc115f0e 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -39,6 +39,8 @@
#include "servers/visual/visual_server_raster.h"
#include "version_generated.gen.h"
+#include <mach-o/dyld.h>
+
#include <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
#include <IOKit/IOCFPlugIn.h>
@@ -49,6 +51,7 @@
#include <os/log.h>
#endif
+#include <dlfcn.h>
#include <fcntl.h>
#include <libproc.h>
#include <stdio.h>
@@ -404,13 +407,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange {
NSEvent *event = [NSApp currentEvent];
- Ref<InputEventKey> k;
- k.instance();
-
- get_key_modifier_state([event modifierFlags], k);
- k->set_pressed(true);
- k->set_echo(false);
- k->set_scancode(0);
NSString *characters;
if ([aString isKindOfClass:[NSAttributedString class]]) {
@@ -435,8 +431,15 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
if ((codepoint & 0xFF00) == 0xF700)
continue;
- k->set_unicode(codepoint);
- OS_OSX::singleton->push_input(k);
+ OS_OSX::KeyEvent ke;
+
+ ke.osx_state = [event modifierFlags];
+ ke.pressed = true;
+ ke.echo = false;
+ ke.scancode = 0;
+ ke.unicode = codepoint;
+
+ OS_OSX::singleton->key_event_buffer[OS_OSX::singleton->key_event_pos++] = ke;
}
[self cancelComposition];
}
@@ -785,80 +788,87 @@ static int translateKey(unsigned int key) {
- (void)keyDown:(NSEvent *)event {
- Ref<InputEventKey> k;
- k.instance();
-
- get_key_modifier_state([event modifierFlags], k);
- k->set_pressed(true);
- k->set_scancode(latin_keyboard_keycode_convert(translateKey([event keyCode])));
- k->set_echo([event isARepeat]);
+ //disable raw input in IME mode
+ if (!imeMode) {
+ OS_OSX::KeyEvent ke;
- NSString *characters = [event characters];
- NSUInteger i, length = [characters length];
+ ke.osx_state = [event modifierFlags];
+ ke.pressed = true;
+ ke.echo = [event isARepeat];
+ ke.scancode = latin_keyboard_keycode_convert(translateKey([event keyCode]));
+ ke.unicode = 0;
- //disable raw input in IME mode
- if (!imeMode)
- OS_OSX::singleton->push_input(k);
+ OS_OSX::singleton->key_event_buffer[OS_OSX::singleton->key_event_pos++] = ke;
+ }
if ((OS_OSX::singleton->im_position.x != 0) && (OS_OSX::singleton->im_position.y != 0))
[self interpretKeyEvents:[NSArray arrayWithObject:event]];
}
- (void)flagsChanged:(NSEvent *)event {
- Ref<InputEventKey> k;
- k.instance();
- int key = [event keyCode];
- int mod = [event modifierFlags];
+ if (!imeMode) {
+ OS_OSX::KeyEvent ke;
- if (key == 0x36 || key == 0x37) {
- if (mod & NSEventModifierFlagCommand) {
- mod &= ~NSEventModifierFlagCommand;
- k->set_pressed(true);
- } else {
- k->set_pressed(false);
- }
- } else if (key == 0x38 || key == 0x3c) {
- if (mod & NSEventModifierFlagShift) {
- mod &= ~NSEventModifierFlagShift;
- k->set_pressed(true);
- } else {
- k->set_pressed(false);
- }
- } else if (key == 0x3a || key == 0x3d) {
- if (mod & NSEventModifierFlagOption) {
- mod &= ~NSEventModifierFlagOption;
- k->set_pressed(true);
- } else {
- k->set_pressed(false);
- }
- } else if (key == 0x3b || key == 0x3e) {
- if (mod & NSEventModifierFlagControl) {
- mod &= ~NSEventModifierFlagControl;
- k->set_pressed(true);
+ ke.echo = false;
+
+ int key = [event keyCode];
+ int mod = [event modifierFlags];
+
+ if (key == 0x36 || key == 0x37) {
+ if (mod & NSEventModifierFlagCommand) {
+ mod &= ~NSEventModifierFlagCommand;
+ ke.pressed = true;
+ } else {
+ ke.pressed = false;
+ }
+ } else if (key == 0x38 || key == 0x3c) {
+ if (mod & NSEventModifierFlagShift) {
+ mod &= ~NSEventModifierFlagShift;
+ ke.pressed = true;
+ } else {
+ ke.pressed = false;
+ }
+ } else if (key == 0x3a || key == 0x3d) {
+ if (mod & NSEventModifierFlagOption) {
+ mod &= ~NSEventModifierFlagOption;
+ ke.pressed = true;
+ } else {
+ ke.pressed = false;
+ }
+ } else if (key == 0x3b || key == 0x3e) {
+ if (mod & NSEventModifierFlagControl) {
+ mod &= ~NSEventModifierFlagControl;
+ ke.pressed = true;
+ } else {
+ ke.pressed = false;
+ }
} else {
- k->set_pressed(false);
+ return;
}
- } else {
- return;
- }
- get_key_modifier_state(mod, k);
- k->set_scancode(latin_keyboard_keycode_convert(translateKey(key)));
+ ke.osx_state = mod;
+ ke.scancode = latin_keyboard_keycode_convert(translateKey(key));
+ ke.unicode = 0;
- OS_OSX::singleton->push_input(k);
+ OS_OSX::singleton->key_event_buffer[OS_OSX::singleton->key_event_pos++] = ke;
+ }
}
- (void)keyUp:(NSEvent *)event {
- Ref<InputEventKey> k;
- k.instance();
+ if (!imeMode) {
- get_key_modifier_state([event modifierFlags], k);
- k->set_pressed(false);
- k->set_scancode(latin_keyboard_keycode_convert(translateKey([event keyCode])));
+ OS_OSX::KeyEvent ke;
- OS_OSX::singleton->push_input(k);
+ ke.osx_state = [event modifierFlags];
+ ke.pressed = false;
+ ke.echo = false;
+ ke.scancode = latin_keyboard_keycode_convert(translateKey([event keyCode]));
+ ke.unicode = 0;
+
+ OS_OSX::singleton->key_event_buffer[OS_OSX::singleton->key_event_pos++] = ke;
+ }
}
inline void sendScrollEvent(int button, double factor, int modifierFlags) {
@@ -1262,6 +1272,28 @@ void OS_OSX::alert(const String &p_alert, const String &p_title) {
[window release];
}
+Error OS_OSX::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) {
+
+ String path = p_path;
+
+ if (!FileAccess::exists(path)) {
+ //this code exists so gdnative can load .dylib files from within the executable path
+ path = get_executable_path().get_base_dir().plus_file(p_path.get_file());
+ }
+
+ if (!FileAccess::exists(path)) {
+ //this code exists so gdnative can load .dylib files from a standard macOS location
+ path = get_executable_path().get_base_dir().plus_file("../Frameworks").plus_file(p_path.get_file());
+ }
+
+ p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
+ if (!p_library_handle) {
+ ERR_EXPLAIN("Can't open dynamic library: " + p_path + ". Error: " + dlerror());
+ ERR_FAIL_V(ERR_CANT_OPEN);
+ }
+ return OK;
+}
+
void OS_OSX::set_cursor_shape(CursorShape p_shape) {
if (cursor_shape == p_shape)
@@ -2035,11 +2067,49 @@ void OS_OSX::process_events() {
[NSApp sendEvent:event];
}
+ process_key_events();
[autoreleasePool drain];
autoreleasePool = [[NSAutoreleasePool alloc] init];
}
+void OS_OSX::process_key_events() {
+
+ Ref<InputEventKey> k;
+ for (int i = 0; i < key_event_pos; i++) {
+
+ KeyEvent &ke = key_event_buffer[i];
+
+ if ((i == 0 && ke.scancode == 0) || (i > 0 && key_event_buffer[i - 1].scancode == 0)) {
+ k.instance();
+
+ get_key_modifier_state(ke.osx_state, k);
+ k->set_pressed(ke.pressed);
+ k->set_echo(ke.echo);
+ k->set_scancode(0);
+ k->set_unicode(ke.unicode);
+
+ push_input(k);
+ }
+ if (ke.scancode != 0) {
+ k.instance();
+
+ get_key_modifier_state(ke.osx_state, k);
+ k->set_pressed(ke.pressed);
+ k->set_echo(ke.echo);
+ k->set_scancode(ke.scancode);
+
+ if (i + 1 < key_event_pos && key_event_buffer[i + 1].scancode == 0) {
+ k->set_unicode(key_event_buffer[i + 1].unicode);
+ }
+
+ push_input(k);
+ }
+ }
+
+ key_event_pos = 0;
+}
+
void OS_OSX::push_input(const Ref<InputEvent> &p_event) {
Ref<InputEvent> ev = p_event;
@@ -2159,6 +2229,7 @@ OS_OSX *OS_OSX::singleton = NULL;
OS_OSX::OS_OSX() {
+ key_event_pos = 0;
mouse_mode = OS::MOUSE_MODE_VISIBLE;
main_loop = NULL;
singleton = this;
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 4f4b225b14..5736ae1585 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -462,6 +462,7 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL:
case WM_LBUTTONDBLCLK:
+ case WM_MBUTTONDBLCLK:
case WM_RBUTTONDBLCLK:
/*case WM_XBUTTONDOWN:
case WM_XBUTTONUP: */ {
@@ -520,6 +521,12 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
mb->set_button_index(2);
mb->set_doubleclick(true);
} break;
+ case WM_MBUTTONDBLCLK: {
+
+ mb->set_pressed(true);
+ mb->set_button_index(3);
+ mb->set_doubleclick(true);
+ } break;
case WM_MOUSEWHEEL: {
mb->set_pressed(true);
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index 0a6d80d49c..006347d30a 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -143,7 +143,7 @@ Transform2D Camera2D::get_camera_transform() {
if (smoothing_enabled && !Engine::get_singleton()->is_editor_hint()) {
- float c = smoothing * get_physics_process_delta_time();
+ float c = smoothing * get_process_delta_time();
smoothed_camera_pos = ((camera_pos - smoothed_camera_pos) * c) + smoothed_camera_pos;
ret_camera_pos = smoothed_camera_pos;
//camera_pos=camera_pos*(1.0-smoothing)+new_camera_pos*smoothing;
@@ -217,14 +217,14 @@ void Camera2D::_notification(int p_what) {
switch (p_what) {
- case NOTIFICATION_PHYSICS_PROCESS: {
+ case NOTIFICATION_INTERNAL_PROCESS: {
_update_scroll();
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
- if (!is_physics_processing())
+ if (!is_processing_internal())
_update_scroll();
} break;
@@ -246,7 +246,7 @@ void Camera2D::_notification(int p_what) {
add_to_group(canvas_group_name);
if (Engine::get_singleton()->is_editor_hint()) {
- set_physics_process(false);
+ set_process_internal(false);
}
_update_scroll();
@@ -503,9 +503,9 @@ void Camera2D::set_follow_smoothing(float p_speed) {
smoothing = p_speed;
if (smoothing > 0 && !(is_inside_tree() && Engine::get_singleton()->is_editor_hint()))
- set_physics_process(true);
+ set_process_internal(true);
else
- set_physics_process(false);
+ set_process_internal(false);
}
float Camera2D::get_follow_smoothing() const {
diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp
index 96eb7eb6f4..9d77951bff 100644
--- a/scene/3d/baked_lightmap.cpp
+++ b/scene/3d/baked_lightmap.cpp
@@ -784,7 +784,7 @@ void BakedLightmap::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::REAL, "capture_cell_size", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_capture_cell_size", "get_capture_cell_size");
ADD_GROUP("Data", "");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "image_path", PROPERTY_HINT_DIR), "set_image_path", "get_image_path");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_data", PROPERTY_HINT_RESOURCE_TYPE, "BakedIndirectLightData"), "set_light_data", "get_light_data");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_data", PROPERTY_HINT_RESOURCE_TYPE, "BakedLightmapData"), "set_light_data", "get_light_data");
BIND_ENUM_CONSTANT(BAKE_QUALITY_LOW);
BIND_ENUM_CONSTANT(BAKE_QUALITY_MEDIUM);
diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp
index ce9e801385..4ad2eb60ee 100644
--- a/scene/3d/gi_probe.cpp
+++ b/scene/3d/gi_probe.cpp
@@ -535,7 +535,7 @@ void GIProbe::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::REAL, "normal_bias", PROPERTY_HINT_RANGE, "0,4,0.001"), "set_normal_bias", "get_normal_bias");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "compress"), "set_compress", "is_compressed");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "data", PROPERTY_HINT_RESOURCE_TYPE, "GIProbeData"), "set_probe_data", "get_probe_data");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "data", PROPERTY_HINT_RESOURCE_TYPE, "GIProbeData", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE), "set_probe_data", "get_probe_data");
BIND_ENUM_CONSTANT(SUBDIV_64);
BIND_ENUM_CONSTANT(SUBDIV_128);
diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp
index 219464ae1f..8617bbc2f6 100644
--- a/scene/3d/particles.cpp
+++ b/scene/3d/particles.cpp
@@ -1597,4 +1597,21 @@ ParticlesMaterial::ParticlesMaterial() :
}
ParticlesMaterial::~ParticlesMaterial() {
+
+ if (material_mutex)
+ material_mutex->lock();
+
+ if (shader_map.has(current_key)) {
+ shader_map[current_key].users--;
+ if (shader_map[current_key].users == 0) {
+ //deallocate shader, as it's no longer in use
+ VS::get_singleton()->free(shader_map[current_key].shader);
+ shader_map.erase(current_key);
+ }
+
+ VS::get_singleton()->material_set_shader(_get_material(), RID());
+ }
+
+ if (material_mutex)
+ material_mutex->unlock();
}
diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h
index 332eb3c740..c7556c0c5f 100644
--- a/scene/3d/physics_body.h
+++ b/scene/3d/physics_body.h
@@ -115,7 +115,7 @@ public:
MODE_KINEMATIC,
};
-private:
+protected:
bool can_sleep;
PhysicsDirectBodyState *state;
Mode mode;
@@ -178,9 +178,8 @@ private:
void _body_exit_tree(ObjectID p_id);
void _body_inout(int p_status, ObjectID p_instance, int p_body_shape, int p_local_shape);
- void _direct_state_changed(Object *p_state);
+ virtual void _direct_state_changed(Object *p_state);
-protected:
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/3d/vehicle_body.cpp b/scene/3d/vehicle_body.cpp
index bc968b0a5f..aeee51c4b2 100644
--- a/scene/3d/vehicle_body.cpp
+++ b/scene/3d/vehicle_body.cpp
@@ -375,7 +375,7 @@ void VehicleBody::_update_wheel(int p_idx, PhysicsDirectBodyState *s) {
Basis steeringMat(up, steering);
- Basis rotatingMat(right, -wheel.m_rotation);
+ Basis rotatingMat(right, wheel.m_rotation);
/*
if (p_idx==1)
@@ -816,26 +816,24 @@ void VehicleBody::_update_friction(PhysicsDirectBodyState *s) {
void VehicleBody::_direct_state_changed(Object *p_state) {
- PhysicsDirectBodyState *s = Object::cast_to<PhysicsDirectBodyState>(p_state);
+ RigidBody::_direct_state_changed(p_state);
- set_ignore_transform_notification(true);
- set_global_transform(s->get_transform());
- set_ignore_transform_notification(false);
+ state = Object::cast_to<PhysicsDirectBodyState>(p_state);
- float step = s->get_step();
+ float step = state->get_step();
for (int i = 0; i < wheels.size(); i++) {
- _update_wheel(i, s);
+ _update_wheel(i, state);
}
for (int i = 0; i < wheels.size(); i++) {
- _ray_cast(i, s);
- wheels[i]->set_transform(s->get_transform().inverse() * wheels[i]->m_worldTransform);
+ _ray_cast(i, state);
+ wheels[i]->set_transform(state->get_transform().inverse() * wheels[i]->m_worldTransform);
}
- _update_suspension(s);
+ _update_suspension(state);
for (int i = 0; i < wheels.size(); i++) {
@@ -848,21 +846,21 @@ void VehicleBody::_direct_state_changed(Object *p_state) {
suspensionForce = wheel.m_maxSuspensionForce;
}
Vector3 impulse = wheel.m_raycastInfo.m_contactNormalWS * suspensionForce * step;
- Vector3 relpos = wheel.m_raycastInfo.m_contactPointWS - s->get_transform().origin;
+ Vector3 relpos = wheel.m_raycastInfo.m_contactPointWS - state->get_transform().origin;
- s->apply_impulse(relpos, impulse);
+ state->apply_impulse(relpos, impulse);
//getRigidBody()->applyImpulse(impulse, relpos);
}
- _update_friction(s);
+ _update_friction(state);
for (int i = 0; i < wheels.size(); i++) {
VehicleWheel &wheel = *wheels[i];
- Vector3 relpos = wheel.m_raycastInfo.m_hardPointWS - s->get_transform().origin;
- Vector3 vel = s->get_linear_velocity() + (s->get_angular_velocity()).cross(relpos); // * mPos);
+ Vector3 relpos = wheel.m_raycastInfo.m_hardPointWS - state->get_transform().origin;
+ Vector3 vel = state->get_linear_velocity() + (state->get_angular_velocity()).cross(relpos); // * mPos);
if (wheel.m_raycastInfo.m_isInContact) {
- const Transform &chassisWorldTransform = s->get_transform();
+ const Transform &chassisWorldTransform = state->get_transform();
Vector3 fwd(
chassisWorldTransform.basis[0][Vector3::AXIS_Z],
@@ -883,29 +881,8 @@ void VehicleBody::_direct_state_changed(Object *p_state) {
wheel.m_deltaRotation *= real_t(0.99); //damping of rotation when not in contact
}
- linear_velocity = s->get_linear_velocity();
-}
-
-void VehicleBody::set_mass(real_t p_mass) {
-
- mass = p_mass;
- PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_MASS, mass);
-}
-
-real_t VehicleBody::get_mass() const {
- return mass;
-}
-
-void VehicleBody::set_friction(real_t p_friction) {
-
- friction = p_friction;
- PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, friction);
-}
-
-real_t VehicleBody::get_friction() const {
-
- return friction;
+ state = NULL;
}
void VehicleBody::set_engine_force(float p_engine_force) {
@@ -936,18 +913,8 @@ float VehicleBody::get_steering() const {
return m_steeringValue;
}
-Vector3 VehicleBody::get_linear_velocity() const {
- return linear_velocity;
-}
-
void VehicleBody::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_mass", "mass"), &VehicleBody::set_mass);
- ClassDB::bind_method(D_METHOD("get_mass"), &VehicleBody::get_mass);
-
- ClassDB::bind_method(D_METHOD("set_friction", "friction"), &VehicleBody::set_friction);
- ClassDB::bind_method(D_METHOD("get_friction"), &VehicleBody::get_friction);
-
ClassDB::bind_method(D_METHOD("set_engine_force", "engine_force"), &VehicleBody::set_engine_force);
ClassDB::bind_method(D_METHOD("get_engine_force"), &VehicleBody::get_engine_force);
@@ -957,21 +924,14 @@ void VehicleBody::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_steering", "steering"), &VehicleBody::set_steering);
ClassDB::bind_method(D_METHOD("get_steering"), &VehicleBody::get_steering);
- ClassDB::bind_method(D_METHOD("get_linear_velocity"), &VehicleBody::get_linear_velocity);
-
- ClassDB::bind_method(D_METHOD("_direct_state_changed"), &VehicleBody::_direct_state_changed);
-
ADD_GROUP("Motion", "");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "engine_force", PROPERTY_HINT_RANGE, "0.00,1024.0,0.01"), "set_engine_force", "get_engine_force");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "brake", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_brake", "get_brake");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "steering", PROPERTY_HINT_RANGE, "-180,180.0,0.01"), "set_steering", "get_steering");
- ADD_GROUP("Mass", "");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "mass", PROPERTY_HINT_RANGE, "0.01,65536,0.01"), "set_mass", "get_mass");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "friction", PROPERTY_HINT_RANGE, "0.01,1,0.01"), "set_friction", "get_friction");
}
VehicleBody::VehicleBody() :
- PhysicsBody(PhysicsServer::BODY_MODE_RIGID) {
+ RigidBody() {
m_pitchControl = 0;
m_currentVehicleSpeedKmHour = real_t(0.);
@@ -982,10 +942,11 @@ VehicleBody::VehicleBody() :
friction = 1;
+ state = NULL;
ccd = false;
exclude.insert(get_rid());
- PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed");
+ //PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed");
set_mass(40);
}
diff --git a/scene/3d/vehicle_body.h b/scene/3d/vehicle_body.h
index 1c7dacf5ac..7810a42e8a 100644
--- a/scene/3d/vehicle_body.h
+++ b/scene/3d/vehicle_body.h
@@ -139,20 +139,13 @@ public:
VehicleWheel();
};
-class VehicleBody : public PhysicsBody {
+class VehicleBody : public RigidBody {
- GDCLASS(VehicleBody, PhysicsBody);
-
- real_t mass;
- real_t friction;
+ GDCLASS(VehicleBody, RigidBody);
float engine_force;
float brake;
- Vector3 linear_velocity;
- Vector3 angular_velocity;
- bool ccd;
-
real_t m_pitchControl;
real_t m_steeringValue;
real_t m_currentVehicleSpeedKmHour;
@@ -192,12 +185,6 @@ class VehicleBody : public PhysicsBody {
void _direct_state_changed(Object *p_state);
public:
- void set_mass(real_t p_mass);
- real_t get_mass() const;
-
- void set_friction(real_t p_friction);
- real_t get_friction() const;
-
void set_engine_force(float p_engine_force);
float get_engine_force() const;
@@ -207,8 +194,6 @@ public:
void set_steering(float p_steering);
float get_steering() const;
- Vector3 get_linear_velocity() const;
-
VehicleBody();
};
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index f56e8fa9e3..7d909d0cb3 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -158,7 +158,7 @@ void AnimationPlayer::_get_property_list(List<PropertyInfo> *p_list) const {
for (Map<StringName, AnimationData>::Element *E = animation_set.front(); E; E = E->next()) {
- anim_names.push_back(PropertyInfo(Variant::OBJECT, "anims/" + String(E->key()), PROPERTY_HINT_RESOURCE_TYPE, "Animation", PROPERTY_USAGE_NOEDITOR));
+ anim_names.push_back(PropertyInfo(Variant::OBJECT, "anims/" + String(E->key()), PROPERTY_HINT_RESOURCE_TYPE, "Animation", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE));
if (E->get().next != StringName())
anim_names.push_back(PropertyInfo(Variant::STRING, "next/" + String(E->key()), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
names.push_back(E->key());
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index d765248cca..8b9469021c 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -504,12 +504,12 @@ void BaseButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_button_group"), &BaseButton::get_button_group);
BIND_VMETHOD(MethodInfo("_pressed"));
- BIND_VMETHOD(MethodInfo("_toggled", PropertyInfo(Variant::BOOL, "pressed")));
+ BIND_VMETHOD(MethodInfo("_toggled", PropertyInfo(Variant::BOOL, "button_pressed")));
ADD_SIGNAL(MethodInfo("pressed"));
ADD_SIGNAL(MethodInfo("button_up"));
ADD_SIGNAL(MethodInfo("button_down"));
- ADD_SIGNAL(MethodInfo("toggled", PropertyInfo(Variant::BOOL, "pressed")));
+ ADD_SIGNAL(MethodInfo("toggled", PropertyInfo(Variant::BOOL, "button_pressed")));
ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "toggle_mode"), "set_toggle_mode", "is_toggle_mode");
ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed");
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 979a65f455..6503d1fb6d 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -1357,24 +1357,32 @@ float Control::_a2s(float p_val, float p_anchor, float p_range) const {
}
void Control::set_anchor(Margin p_margin, float p_anchor, bool p_keep_margin, bool p_push_opposite_anchor) {
- bool pushed = false;
+ float parent_range = _get_parent_range((p_margin == MARGIN_LEFT || p_margin == MARGIN_RIGHT) ? 0 : 1);
+ float previous_margin_pos = data.margin[p_margin] + data.anchor[p_margin] * parent_range;
+ float previous_opposite_margin_pos = data.margin[(p_margin + 2) % 4] + data.anchor[(p_margin + 2) % 4] * parent_range;
+
data.anchor[p_margin] = CLAMP(p_anchor, 0.0, 1.0);
if (((p_margin == MARGIN_LEFT || p_margin == MARGIN_TOP) && data.anchor[p_margin] > data.anchor[(p_margin + 2) % 4]) ||
((p_margin == MARGIN_RIGHT || p_margin == MARGIN_BOTTOM) && data.anchor[p_margin] < data.anchor[(p_margin + 2) % 4])) {
if (p_push_opposite_anchor) {
data.anchor[(p_margin + 2) % 4] = data.anchor[p_margin];
- pushed = true;
} else {
data.anchor[p_margin] = data.anchor[(p_margin + 2) % 4];
}
}
- if (is_inside_tree()) {
- if (p_keep_margin) {
- _size_changed();
+ if (!p_keep_margin) {
+ data.margin[p_margin] = _s2a(previous_margin_pos, data.anchor[p_margin], parent_range);
+ if (p_push_opposite_anchor) {
+ data.margin[(p_margin + 2) % 4] = _s2a(previous_opposite_margin_pos, data.anchor[(p_margin + 2) % 4], parent_range);
}
}
+
+ if (is_inside_tree()) {
+ _size_changed();
+ }
+
update();
_change_notify();
}
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 53f609723f..97f740a4ba 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -1413,8 +1413,8 @@ void LineEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_context_menu_enabled", "enable"), &LineEdit::set_context_menu_enabled);
ClassDB::bind_method(D_METHOD("is_context_menu_enabled"), &LineEdit::is_context_menu_enabled);
- ADD_SIGNAL(MethodInfo("text_changed", PropertyInfo(Variant::STRING, "text")));
- ADD_SIGNAL(MethodInfo("text_entered", PropertyInfo(Variant::STRING, "text")));
+ ADD_SIGNAL(MethodInfo("text_changed", PropertyInfo(Variant::STRING, "new_text")));
+ ADD_SIGNAL(MethodInfo("text_entered", PropertyInfo(Variant::STRING, "new_text")));
BIND_ENUM_CONSTANT(ALIGN_LEFT);
BIND_ENUM_CONSTANT(ALIGN_CENTER);
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index a3f59b54fc..aa4310da46 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -883,7 +883,7 @@ void TextEdit::_notification(int p_what) {
}
// give visual indication of empty selected line
- if (selection.active && line >= selection.from_line && line <= selection.to_line) {
+ if (selection.active && line >= selection.from_line && line <= selection.to_line && char_margin >= xmargin_beg) {
int char_w = cache.font->get_char_size(' ').width;
VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, char_w, get_row_height()), cache.selection_color);
}
@@ -4467,31 +4467,44 @@ bool TextEdit::search(const String &p_key, uint32_t p_search_flags, int p_from_l
int pos_from = 0;
int last_pos = -1;
- while ((last_pos = (p_search_flags & SEARCH_MATCH_CASE) ? text_line.find(p_key, pos_from) : text_line.findn(p_key, pos_from)) != -1) {
- if (p_search_flags & SEARCH_BACKWARDS) {
+ while (true) {
- if (last_pos > from_column)
- break;
- pos = last_pos;
+ while ((last_pos = (p_search_flags & SEARCH_MATCH_CASE) ? text_line.find(p_key, pos_from) : text_line.findn(p_key, pos_from)) != -1) {
- } else {
+ if (p_search_flags & SEARCH_BACKWARDS) {
- if (last_pos >= from_column) {
+ if (last_pos > from_column)
+ break;
pos = last_pos;
- break;
+
+ } else {
+
+ if (last_pos >= from_column) {
+ pos = last_pos;
+ break;
+ }
}
+
+ pos_from = last_pos + p_key.length();
}
- pos_from = last_pos + p_key.length();
- }
+ bool is_match = true;
+
+ if (pos != -1 && (p_search_flags & SEARCH_WHOLE_WORDS)) {
+ //validate for whole words
+ if (pos > 0 && _is_text_char(text_line[pos - 1]))
+ is_match = false;
+ else if (pos + p_key.length() < text_line.length() && _is_text_char(text_line[pos + p_key.length()]))
+ is_match = false;
+ }
+
+ if (is_match || last_pos == -1 || pos == -1) {
+ break;
+ }
- if (pos != -1 && (p_search_flags & SEARCH_WHOLE_WORDS)) {
- //validate for whole words
- if (pos > 0 && _is_text_char(text_line[pos - 1]))
- pos = -1;
- else if (_is_text_char(text_line[pos + p_key.length()]))
- pos = -1;
+ pos_from = pos + 1;
+ pos = -1;
}
if (pos != -1)
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index a36f398024..bc03d322b6 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -2169,7 +2169,16 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const
value = Array(value).duplicate();
}
- current_node->set(name, value);
+ if (E->get().usage & PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE) {
+
+ Resource *res = Object::cast_to<Resource>(value);
+ if (res) // Duplicate only if it's a resource
+ current_node->set(name, res->duplicate());
+
+ } else {
+
+ current_node->set(name, value);
+ }
}
}
diff --git a/scene/resources/bit_mask.cpp b/scene/resources/bit_mask.cpp
index e99db8d9cb..e9e15a2532 100644
--- a/scene/resources/bit_mask.cpp
+++ b/scene/resources/bit_mask.cpp
@@ -81,7 +81,7 @@ void BitMap::set_bit_rect(const Rect2 &p_rect, bool p_value) {
if (p_value)
b |= (1 << bbit);
else
- b &= !(1 << bbit);
+ b &= ~(1 << bbit);
data[bbyte] = b;
}
@@ -127,7 +127,7 @@ void BitMap::set_bit(const Point2 &p_pos, bool p_value) {
if (p_value)
b |= (1 << bbit);
else
- b &= !(1 << bbit);
+ b &= ~(1 << bbit);
bitmask[bbyte] = b;
}
diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp
index 575c222cc1..b35a9ae963 100644
--- a/scene/resources/dynamic_font.cpp
+++ b/scene/resources/dynamic_font.cpp
@@ -631,6 +631,7 @@ bool DynamicFontAtSize::update_oversampling() {
textures.clear();
char_map.clear();
oversampling = font_oversampling;
+ valid = false;
_load();
return true;
@@ -973,14 +974,26 @@ void DynamicFont::finish_dynamic_fonts() {
void DynamicFont::update_oversampling() {
+ Vector<Ref<DynamicFont> > changed;
+
+ if (dynamic_font_mutex)
+ dynamic_font_mutex->lock();
+
SelfList<DynamicFont> *E = dynamic_fonts.first();
while (E) {
if (E->self()->data_at_size.is_valid() && E->self()->data_at_size->update_oversampling()) {
- E->self()->emit_changed();
+ changed.push_back(E->self());
}
E = E->next();
}
+
+ if (dynamic_font_mutex)
+ dynamic_font_mutex->unlock();
+
+ for (int i = 0; i < changed.size(); i++) {
+ changed[i]->emit_changed();
+ }
}
/////////////////////////
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index c13a72698b..dd8d0e2141 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -235,6 +235,7 @@ Node *SceneState::instance(GenEditState p_edit_state) const {
if (p_edit_state == GEN_EDIT_STATE_MAIN) {
//for the main scene, use the resource as is
res->configure_for_local_scene(base, resources_local_to_scene);
+ resources_local_to_scene[res] = res;
} else {
//for instances, a copy must be made
@@ -244,9 +245,6 @@ Node *SceneState::instance(GenEditState p_edit_state) const {
res = local_dupe;
value = local_dupe;
}
-
- //this here may reference nodes not iniialized so this line is commented and used after loading all nodes
- //res->setup_local_to_scene();
}
//must make a copy, because this res is local to scene
}
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 710612d5f4..4d200f5548 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -309,6 +309,7 @@ void TileSet::tile_set_texture(int p_id, const Ref<Texture> &p_texture) {
ERR_FAIL_COND(!tile_map.has(p_id));
tile_map[p_id].texture = p_texture;
emit_changed();
+ _change_notify("texture");
}
Ref<Texture> TileSet::tile_get_texture(int p_id) const {
@@ -386,8 +387,8 @@ void TileSet::tile_set_is_autotile(int p_id, bool p_is_autotile) {
ERR_FAIL_COND(!tile_map.has(p_id));
tile_map[p_id].is_autotile = p_is_autotile;
- _change_notify("");
emit_changed();
+ _change_notify("is_autotile");
}
bool TileSet::tile_get_is_autotile(int p_id) const {