summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/SCsub2
-rw-r--r--core/make_binders.py103
-rw-r--r--doc/classes/CanvasItem.xml7
-rw-r--r--doc/classes/RemoteTransform.xml7
-rw-r--r--doc/classes/RemoteTransform2D.xml7
-rw-r--r--editor/editor_node.cpp9
-rw-r--r--editor/editor_node.h2
-rw-r--r--editor/plugins/curve_editor_plugin.cpp19
-rw-r--r--editor/plugins/curve_editor_plugin.h2
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp21
-rw-r--r--modules/mono/build_scripts/solution_builder.py10
-rw-r--r--modules/mono/class_db_api_json.cpp242
-rw-r--r--modules/mono/class_db_api_json.h39
-rw-r--r--modules/mono/csharp_script.cpp13
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.sln35
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.cpp25
-rw-r--r--modules/recast/register_types.cpp7
-rw-r--r--platform/javascript/detect.py9
-rw-r--r--platform/javascript/os_javascript.cpp17
-rw-r--r--platform/javascript/os_javascript.h1
-rw-r--r--platform/osx/os_osx.h1
-rw-r--r--platform/osx/os_osx.mm18
-rw-r--r--platform/windows/os_windows.cpp18
-rw-r--r--platform/windows/os_windows.h1
-rw-r--r--platform/x11/os_x11.cpp18
-rw-r--r--platform/x11/os_x11.h1
-rw-r--r--scene/2d/canvas_item.cpp52
-rw-r--r--scene/2d/canvas_item.h2
-rw-r--r--scene/2d/remote_transform_2d.cpp7
-rw-r--r--scene/2d/remote_transform_2d.h2
-rw-r--r--scene/3d/remote_transform.cpp7
-rw-r--r--scene/3d/remote_transform.h2
-rw-r--r--scene/gui/text_edit.cpp2
-rw-r--r--scene/main/http_request.cpp37
-rw-r--r--scene/main/http_request.h13
-rw-r--r--servers/visual/shader_language.cpp6
36 files changed, 684 insertions, 80 deletions
diff --git a/core/SCsub b/core/SCsub
index bf1b34bebe..85e5f1b089 100644
--- a/core/SCsub
+++ b/core/SCsub
@@ -142,7 +142,7 @@ env.Depends("#core/io/certs_compressed.gen.h", ["#thirdparty/certs/ca-certificat
env.CommandNoCache("#core/io/certs_compressed.gen.h", "#thirdparty/certs/ca-certificates.crt", run_in_subprocess(core_builders.make_certs_header))
# Make binders
-env.CommandNoCache(['method_bind.gen.inc', 'method_bind_ext.gen.inc'], 'make_binders.py', run_in_subprocess(make_binders.run))
+env.CommandNoCache(['method_bind.gen.inc', 'method_bind_ext.gen.inc', 'method_bind_free_func.gen.inc'], 'make_binders.py', run_in_subprocess(make_binders.run))
# Authors
env.Depends('#core/authors.gen.h', "../AUTHORS.md")
diff --git a/core/make_binders.py b/core/make_binders.py
index 5c1c66cab6..24901c42a1 100644
--- a/core/make_binders.py
+++ b/core/make_binders.py
@@ -191,6 +191,96 @@ MethodBind* create_method_bind($ifret R$ $ifnoret void$ (T::*p_method)($arg, P@$
"""
+template_typed_free_func = """
+#ifdef TYPED_METHOD_BIND
+template<class T $ifret ,class R$ $ifargs ,$ $arg, class P@$>
+class FunctionBind$argc$$ifret R$$ifconst C$ : public MethodBind {
+public:
+
+ $ifret R$ $ifnoret void$ (*method) ($ifconst const$ T *$ifargs , $$arg, P@$);
+#ifdef DEBUG_METHODS_ENABLED
+ virtual Variant::Type _gen_argument_type(int p_arg) const { return _get_argument_type(p_arg); }
+ virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const {
+ $ifret if (p_arg==-1) return GetTypeInfo<R>::METADATA;$
+ $arg if (p_arg==(@-1)) return GetTypeInfo<P@>::METADATA;
+ $
+ return GodotTypeInfo::METADATA_NONE;
+ }
+ Variant::Type _get_argument_type(int p_argument) const {
+ $ifret if (p_argument==-1) return (Variant::Type)GetTypeInfo<R>::VARIANT_TYPE;$
+ $arg if (p_argument==(@-1)) return (Variant::Type)GetTypeInfo<P@>::VARIANT_TYPE;
+ $
+ return Variant::NIL;
+ }
+ virtual PropertyInfo _gen_argument_type_info(int p_argument) const {
+ $ifret if (p_argument==-1) return GetTypeInfo<R>::get_class_info();$
+ $arg if (p_argument==(@-1)) return GetTypeInfo<P@>::get_class_info();
+ $
+ return PropertyInfo();
+ }
+#endif
+ virtual String get_instance_class() const {
+ return T::get_class_static();
+ }
+
+ virtual Variant call(Object* p_object,const Variant** p_args,int p_arg_count, Variant::CallError& r_error) {
+
+ T *instance=Object::cast_to<T>(p_object);
+ r_error.error=Variant::CallError::CALL_OK;
+#ifdef DEBUG_METHODS_ENABLED
+
+ ERR_FAIL_COND_V(!instance,Variant());
+ if (p_arg_count>get_argument_count()) {
+ r_error.error=Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.argument=get_argument_count();
+ return Variant();
+
+ }
+ if (p_arg_count<(get_argument_count()-get_default_argument_count())) {
+
+ r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument=get_argument_count()-get_default_argument_count();
+ return Variant();
+ }
+ $arg CHECK_ARG(@);
+ $
+#endif
+ $ifret Variant ret = $(method)(instance$ifargs , $$arg, _VC(@)$);
+ $ifret return Variant(ret);$
+ $ifnoret return Variant();$
+ }
+
+#ifdef PTRCALL_ENABLED
+ virtual void ptrcall(Object*p_object,const void** p_args,void *r_ret) {
+
+ T *instance=Object::cast_to<T>(p_object);
+ $ifret PtrToArg<R>::encode( $ (method)(instance$ifargs , $$arg, PtrToArg<P@>::convert(p_args[@-1])$) $ifret ,r_ret)$ ;
+ }
+#endif
+ FunctionBind$argc$$ifret R$$ifconst C$ () {
+#ifdef DEBUG_METHODS_ENABLED
+ _set_const($ifconst true$$ifnoconst false$);
+ _generate_argument_types($argc$);
+#else
+ set_argument_count($argc$);
+#endif
+
+ $ifret _set_returns(true); $
+ };
+};
+
+template<class T $ifret ,class R$ $ifargs ,$ $arg, class P@$>
+MethodBind* create_method_bind($ifret R$ $ifnoret void$ (*p_method)($ifconst const$ T *$ifargs , $$arg, P@$) ) {
+
+ FunctionBind$argc$$ifret R$$ifconst C$<T $ifret ,R$ $ifargs ,$ $arg, P@$> * a = memnew( (FunctionBind$argc$$ifret R$$ifconst C$<T $ifret ,R$ $ifargs ,$ $arg, P@$>) );
+ a->method=p_method;
+ return a;
+}
+#endif
+"""
+
+
+
def make_version(template, nargs, argmax, const, ret):
intext = template
@@ -259,6 +349,9 @@ def run(target, source, env):
versions_ext = 6
text = ""
text_ext = ""
+ text_free_func = "#ifndef METHOD_BIND_FREE_FUNC_H\n#define METHOD_BIND_FREE_FUNC_H\n"
+ text_free_func += "\n//including this header file allows method binding to use free functions\n"
+ text_free_func += "//note that the free function must have a pointer to an instance of the class as its first parameter\n"
for i in range(0, versions + 1):
@@ -276,12 +369,22 @@ def run(target, source, env):
else:
text += t
+ text_free_func += make_version(template_typed_free_func, i, versions, False, False)
+ text_free_func += make_version(template_typed_free_func, i, versions, False, True)
+ text_free_func += make_version(template_typed_free_func, i, versions, True, False)
+ text_free_func += make_version(template_typed_free_func, i, versions, True, True)
+
+ text_free_func += "#endif"
+
with open(target[0], "w") as f:
f.write(text)
with open(target[1], "w") as f:
f.write(text_ext)
+ with open(target[2], "w") as f:
+ f.write(text_free_func)
+
if __name__ == '__main__':
from platform_methods import subprocess_main
diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml
index 5ac825ddcd..79e3676068 100644
--- a/doc/classes/CanvasItem.xml
+++ b/doc/classes/CanvasItem.xml
@@ -223,8 +223,13 @@
</argument>
<argument index="2" name="filled" type="bool" default="true">
</argument>
+ <argument index="3" name="width" type="float" default="1.0">
+ </argument>
+ <argument index="4" name="antialiased" type="bool" default="false">
+ </argument>
<description>
- Draws a colored rectangle.
+ Draws a rectangle. If [code]filled[/code] is [code]true[/code], the rectangle will be filled with the [code]color[/code] specified. If [code]filled[/code] is [code]false[/code], the rectangle will be drawn as a stroke with the [code]color[/code] and [code]width[/code] specified. If [code]antialiased[/code] is [code]true[/code], the lines will be antialiased.
+ [b]Note:[/b] [code]width[/code] and [code]antialiased[/code] are only effective if [code]filled[/code] is [code]false[/code].
</description>
</method>
<method name="draw_set_transform">
diff --git a/doc/classes/RemoteTransform.xml b/doc/classes/RemoteTransform.xml
index 4628ef8519..377f9cc34b 100644
--- a/doc/classes/RemoteTransform.xml
+++ b/doc/classes/RemoteTransform.xml
@@ -10,6 +10,13 @@
<tutorials>
</tutorials>
<methods>
+ <method name="force_update_cache">
+ <return type="void">
+ </return>
+ <description>
+ [RemoteTransform] caches the remote node. It may not notice if the remote node disappears; [method force_update_cache] forces it to update the cache again.
+ </description>
+ </method>
</methods>
<members>
<member name="remote_path" type="NodePath" setter="set_remote_node" getter="get_remote_node" default="NodePath(&quot;&quot;)">
diff --git a/doc/classes/RemoteTransform2D.xml b/doc/classes/RemoteTransform2D.xml
index 6a317724a0..f5d509782f 100644
--- a/doc/classes/RemoteTransform2D.xml
+++ b/doc/classes/RemoteTransform2D.xml
@@ -10,6 +10,13 @@
<tutorials>
</tutorials>
<methods>
+ <method name="force_update_cache">
+ <return type="void">
+ </return>
+ <description>
+ [RemoteTransform2D] caches the remote node. It may not notice if the remote node disappears; [method force_update_cache] forces it to update the cache again.
+ </description>
+ </method>
</methods>
<members>
<member name="remote_path" type="NodePath" setter="set_remote_node" getter="get_remote_node" default="NodePath(&quot;&quot;)">
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 1e9cb2f88d..3431930b8b 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -3713,6 +3713,11 @@ void EditorNode::show_warning(const String &p_text, const String &p_title) {
warning->popup_centered_minsize();
}
+void EditorNode::_copy_warning(const String &p_str) {
+
+ OS::get_singleton()->set_clipboard(warning->get_text());
+}
+
void EditorNode::_dock_select_input(const Ref<InputEvent> &p_input) {
Ref<InputEventMouse> me = p_input;
@@ -5192,6 +5197,8 @@ void EditorNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("_inherit_imported"), &EditorNode::_inherit_imported);
ClassDB::bind_method(D_METHOD("_dim_timeout"), &EditorNode::_dim_timeout);
+ ClassDB::bind_method("_copy_warning", &EditorNode::_copy_warning);
+
ClassDB::bind_method(D_METHOD("_resources_reimported"), &EditorNode::_resources_reimported);
ClassDB::bind_method(D_METHOD("_bottom_panel_raise_toggled"), &EditorNode::_bottom_panel_raise_toggled);
@@ -5793,7 +5800,9 @@ EditorNode::EditorNode() {
feature_profile_manager->connect("current_feature_profile_changed", this, "_feature_profile_changed");
warning = memnew(AcceptDialog);
+ warning->add_button(TTR("Copy Text"), true, "copy");
gui_base->add_child(warning);
+ warning->connect("custom_action", this, "_copy_warning");
ED_SHORTCUT("editor/next_tab", TTR("Next tab"), KEY_MASK_CMD + KEY_TAB);
ED_SHORTCUT("editor/prev_tab", TTR("Previous tab"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_TAB);
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 733f29c8ff..5dabe529f9 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -782,6 +782,8 @@ public:
void show_accept(const String &p_text, const String &p_title);
void show_warning(const String &p_text, const String &p_title = "Warning!");
+ void _copy_warning(const String &p_str);
+
Error export_preset(const String &p_preset, const String &p_path, bool p_debug, const String &p_password, bool p_quit_after = false);
static void register_editor_types();
diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp
index d2d2b8f130..33f685892c 100644
--- a/editor/plugins/curve_editor_plugin.cpp
+++ b/editor/plugins/curve_editor_plugin.cpp
@@ -715,7 +715,7 @@ void CurveEditor::_draw() {
if (_hover_point != -1) {
const Color hover_color = line_color;
Vector2 pos = curve.get_point_position(_hover_point);
- stroke_rect(Rect2(get_view_pos(pos), Vector2(1, 1)).grow(_hover_radius), hover_color);
+ draw_rect(Rect2(get_view_pos(pos), Vector2(1, 1)).grow(_hover_radius), hover_color, false, Math::round(EDSCALE));
}
// Help text
@@ -726,23 +726,6 @@ void CurveEditor::_draw() {
}
}
-// TODO That should be part of the drawing API...
-void CurveEditor::stroke_rect(Rect2 rect, Color color) {
-
- // a---b
- // | |
- // c---d
- Vector2 a(rect.position);
- Vector2 b(rect.position.x + rect.size.x, rect.position.y);
- Vector2 c(rect.position.x, rect.position.y + rect.size.y);
- Vector2 d(rect.position + rect.size);
-
- draw_line(a, b, color, Math::round(EDSCALE));
- draw_line(b, d, color, Math::round(EDSCALE));
- draw_line(d, c, color, Math::round(EDSCALE));
- draw_line(c, a, color, Math::round(EDSCALE));
-}
-
void CurveEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_gui_input"), &CurveEditor::on_gui_input);
ClassDB::bind_method(D_METHOD("_on_preset_item_selected"), &CurveEditor::on_preset_item_selected);
diff --git a/editor/plugins/curve_editor_plugin.h b/editor/plugins/curve_editor_plugin.h
index be774a9696..2e2bf1c26f 100644
--- a/editor/plugins/curve_editor_plugin.h
+++ b/editor/plugins/curve_editor_plugin.h
@@ -97,8 +97,6 @@ private:
void _draw();
- void stroke_rect(Rect2 rect, Color color);
-
private:
Transform2D _world_to_view;
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index fc72f25b04..66663d0cd9 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -2348,23 +2348,6 @@ void SpatialEditorViewport::_notification(int p_what) {
}
}
-// TODO That should be part of the drawing API...
-static void stroke_rect(CanvasItem &ci, Rect2 rect, Color color, real_t width = 1.0) {
-
- // a---b
- // | |
- // c---d
- Vector2 a(rect.position);
- Vector2 b(rect.position.x + rect.size.x, rect.position.y);
- Vector2 c(rect.position.x, rect.position.y + rect.size.y);
- Vector2 d(rect.position + rect.size);
-
- ci.draw_line(a, b, color, width);
- ci.draw_line(b, d, color, width);
- ci.draw_line(d, c, color, width);
- ci.draw_line(c, a, color, width);
-}
-
static void draw_indicator_bar(Control &surface, real_t fill, Ref<Texture> icon) {
// Adjust bar size from control height
@@ -2379,7 +2362,7 @@ static void draw_indicator_bar(Control &surface, real_t fill, Ref<Texture> icon)
// Draw both neutral dark and bright colors to account this
surface.draw_rect(r, Color(1, 1, 1, 0.2));
surface.draw_rect(Rect2(r.position.x, r.position.y + r.size.y - sy, r.size.x, sy), Color(1, 1, 1, 0.6));
- stroke_rect(surface, r.grow(1), Color(0, 0, 0, 0.7));
+ surface.draw_rect(r.grow(1), Color(0, 0, 0, 0.7), false, Math::round(EDSCALE));
Vector2 icon_size = icon->get_size();
Vector2 icon_pos = Vector2(r.position.x - (icon_size.x - r.size.x) / 2, r.position.y + r.size.y + 2);
@@ -2460,7 +2443,7 @@ void SpatialEditorViewport::_draw() {
draw_rect = Rect2(Vector2(), s).clip(draw_rect);
- stroke_rect(*surface, draw_rect, Color(0.6, 0.6, 0.1, 0.5), 2.0);
+ surface->draw_rect(draw_rect, Color(0.6, 0.6, 0.1, 0.5), false, Math::round(2 * EDSCALE));
} else {
diff --git a/modules/mono/build_scripts/solution_builder.py b/modules/mono/build_scripts/solution_builder.py
index 9f549a10ed..147dce45d9 100644
--- a/modules/mono/build_scripts/solution_builder.py
+++ b/modules/mono/build_scripts/solution_builder.py
@@ -112,6 +112,11 @@ def find_msbuild_windows(env):
mono_bin_dir = os.path.join(mono_root, 'bin')
msbuild_mono = os.path.join(mono_bin_dir, 'msbuild.bat')
+ msbuild_tools_path = find_msbuild_tools_path_reg()
+
+ if msbuild_tools_path:
+ return (os.path.join(msbuild_tools_path, 'MSBuild.exe'), framework_path, {})
+
if os.path.isfile(msbuild_mono):
# The (Csc/Vbc/Fsc)ToolExe environment variables are required when
# building with Mono's MSBuild. They must point to the batch files
@@ -123,11 +128,6 @@ def find_msbuild_windows(env):
}
return (msbuild_mono, framework_path, mono_msbuild_env)
- msbuild_tools_path = find_msbuild_tools_path_reg()
-
- if msbuild_tools_path:
- return (os.path.join(msbuild_tools_path, 'MSBuild.exe'), framework_path, {})
-
return None
diff --git a/modules/mono/class_db_api_json.cpp b/modules/mono/class_db_api_json.cpp
new file mode 100644
index 0000000000..71ccdb7aab
--- /dev/null
+++ b/modules/mono/class_db_api_json.cpp
@@ -0,0 +1,242 @@
+/*************************************************************************/
+/* class_db_api_json.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "class_db_api_json.h"
+
+#include "core/io/json.h"
+#include "core/os/file_access.h"
+#include "core/project_settings.h"
+#include "core/version.h"
+
+void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
+ Dictionary classes_dict;
+
+ List<StringName> names;
+
+ const StringName *k = NULL;
+
+ while ((k = ClassDB::classes.next(k))) {
+
+ names.push_back(*k);
+ }
+ //must be alphabetically sorted for hash to compute
+ names.sort_custom<StringName::AlphCompare>();
+
+ for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+
+ ClassDB::ClassInfo *t = ClassDB::classes.getptr(E->get());
+ ERR_FAIL_COND(!t);
+ if (t->api != p_api || !t->exposed)
+ continue;
+
+ Dictionary class_dict;
+ classes_dict[t->name] = class_dict;
+
+ class_dict["inherits"] = t->inherits;
+
+ { //methods
+
+ List<StringName> snames;
+
+ k = NULL;
+
+ while ((k = t->method_map.next(k))) {
+
+ snames.push_back(*k);
+ }
+
+ snames.sort_custom<StringName::AlphCompare>();
+
+ Array methods;
+
+ for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
+ Dictionary method_dict;
+ methods.push_back(method_dict);
+
+ MethodBind *mb = t->method_map[F->get()];
+ method_dict["name"] = mb->get_name();
+ method_dict["argument_count"] = mb->get_argument_count();
+ method_dict["return_type"] = mb->get_argument_type(-1);
+
+ Array arguments;
+ method_dict["arguments"] = arguments;
+
+ for (int i = 0; i < mb->get_argument_count(); i++) {
+ Dictionary argument_dict;
+ arguments.push_back(argument_dict);
+ const PropertyInfo info = mb->get_argument_info(i);
+ argument_dict["type"] = info.type;
+ argument_dict["name"] = info.name;
+ argument_dict["hint"] = info.hint;
+ argument_dict["hint_string"] = info.hint_string;
+ }
+
+ method_dict["default_argument_count"] = mb->get_default_argument_count();
+
+ Array default_arguments;
+ method_dict["default_arguments"] = default_arguments;
+
+ for (int i = 0; i < mb->get_default_argument_count(); i++) {
+ Dictionary default_argument_dict;
+ default_arguments.push_back(default_argument_dict);
+ //hash should not change, i hope for tis
+ Variant da = mb->get_default_argument(i);
+ default_argument_dict["value"] = da;
+ }
+
+ method_dict["hint_flags"] = mb->get_hint_flags();
+ }
+
+ if (!methods.empty()) {
+ class_dict["methods"] = methods;
+ }
+ }
+
+ { //constants
+
+ List<StringName> snames;
+
+ k = NULL;
+
+ while ((k = t->constant_map.next(k))) {
+
+ snames.push_back(*k);
+ }
+
+ snames.sort_custom<StringName::AlphCompare>();
+
+ Array constants;
+
+ for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
+ Dictionary constant_dict;
+ constants.push_back(constant_dict);
+
+ constant_dict["name"] = F->get();
+ constant_dict["value"] = t->constant_map[F->get()];
+ }
+
+ if (!constants.empty()) {
+ class_dict["constants"] = constants;
+ }
+ }
+
+ { //signals
+
+ List<StringName> snames;
+
+ k = NULL;
+
+ while ((k = t->signal_map.next(k))) {
+
+ snames.push_back(*k);
+ }
+
+ snames.sort_custom<StringName::AlphCompare>();
+
+ Array signals;
+
+ for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
+ Dictionary signal_dict;
+ signals.push_back(signal_dict);
+
+ MethodInfo &mi = t->signal_map[F->get()];
+ signal_dict["name"] = F->get();
+
+ Array arguments;
+ signal_dict["arguments"] = arguments;
+ for (int i = 0; i < mi.arguments.size(); i++) {
+ Dictionary argument_dict;
+ arguments.push_back(argument_dict);
+ argument_dict["type"] = mi.arguments[i].type;
+ }
+ }
+
+ if (!signals.empty()) {
+ class_dict["signals"] = signals;
+ }
+ }
+
+ { //properties
+
+ List<StringName> snames;
+
+ k = NULL;
+
+ while ((k = t->property_setget.next(k))) {
+
+ snames.push_back(*k);
+ }
+
+ snames.sort_custom<StringName::AlphCompare>();
+
+ Array properties;
+
+ for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
+ Dictionary property_dict;
+ properties.push_back(property_dict);
+
+ ClassDB::PropertySetGet *psg = t->property_setget.getptr(F->get());
+
+ property_dict["name"] = F->get();
+ property_dict["setter"] = psg->setter;
+ property_dict["getter"] = psg->getter;
+ }
+
+ if (!properties.empty()) {
+ class_dict["property_setget"] = properties;
+ }
+ }
+
+ Array property_list;
+
+ //property list
+ for (List<PropertyInfo>::Element *F = t->property_list.front(); F; F = F->next()) {
+ Dictionary property_dict;
+ property_list.push_back(property_dict);
+
+ property_dict["name"] = F->get().name;
+ property_dict["type"] = F->get().type;
+ property_dict["hint"] = F->get().hint;
+ property_dict["hint_string"] = F->get().hint_string;
+ property_dict["usage"] = F->get().usage;
+ }
+
+ if (!property_list.empty()) {
+ class_dict["property_list"] = property_list;
+ }
+ }
+
+ FileAccessRef f = FileAccess::open(p_output_file, FileAccess::WRITE);
+ ERR_FAIL_COND(!f);
+ f->store_string(JSON::print(classes_dict, /*indent: */ "\t"));
+ f->close();
+
+ print_line(String() + "ClassDB API JSON written to: " + ProjectSettings::get_singleton()->globalize_path(p_output_file));
+}
diff --git a/modules/mono/class_db_api_json.h b/modules/mono/class_db_api_json.h
new file mode 100644
index 0000000000..0aa9c20930
--- /dev/null
+++ b/modules/mono/class_db_api_json.h
@@ -0,0 +1,39 @@
+/*************************************************************************/
+/* class_db_api_json.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef CLASS_DB_API_JSON_H
+#define CLASS_DB_API_JSON_H
+
+#include "core/class_db.h"
+#include "core/ustring.h"
+
+void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api);
+
+#endif // CLASS_DB_API_JSON_H
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 7492816f18..1add697997 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -44,6 +44,10 @@
#include "editor/editor_node.h"
#endif
+#ifdef DEBUG_METHODS_ENABLED
+#include "class_db_api_json.h"
+#endif
+
#include "editor/editor_internal_calls.h"
#include "godotsharp_dirs.h"
#include "mono_gd/gd_mono_class.h"
@@ -98,6 +102,15 @@ Error CSharpLanguage::execute_file(const String &p_path) {
void CSharpLanguage::init() {
+#ifdef DEBUG_METHODS_ENABLED
+ if (OS::get_singleton()->get_cmdline_args().find("--class_db_to_json")) {
+ class_db_api_to_json("user://class_db_api.json", ClassDB::API_CORE);
+#ifdef TOOLS_ENABLED
+ class_db_api_to_json("user://class_db_api_editor.json", ClassDB::API_EDITOR);
+#endif
+ }
+#endif
+
gdmono = memnew(GDMono);
gdmono->initialize();
diff --git a/modules/mono/editor/GodotTools/GodotTools.sln b/modules/mono/editor/GodotTools/GodotTools.sln
new file mode 100644
index 0000000000..6f7d44bec2
--- /dev/null
+++ b/modules/mono/editor/GodotTools/GodotTools.sln
@@ -0,0 +1,35 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools.ProjectEditor", "GodotTools.ProjectEditor\GodotTools.ProjectEditor.csproj", "{A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools", "GodotTools\GodotTools.csproj", "{27B00618-A6F2-4828-B922-05CAEB08C286}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools.Core", "GodotTools.Core\GodotTools.Core.csproj", "{639E48BD-44E5-4091-8EDD-22D36DC0768D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools.BuildLogger", "GodotTools.BuildLogger\GodotTools.BuildLogger.csproj", "{6CE9A984-37B1-4F8A-8FE9-609F05F071B3}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}.Release|Any CPU.Build.0 = Release|Any CPU
+ {27B00618-A6F2-4828-B922-05CAEB08C286}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {27B00618-A6F2-4828-B922-05CAEB08C286}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {27B00618-A6F2-4828-B922-05CAEB08C286}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {27B00618-A6F2-4828-B922-05CAEB08C286}.Release|Any CPU.Build.0 = Release|Any CPU
+ {639E48BD-44E5-4091-8EDD-22D36DC0768D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {639E48BD-44E5-4091-8EDD-22D36DC0768D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {639E48BD-44E5-4091-8EDD-22D36DC0768D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {639E48BD-44E5-4091-8EDD-22D36DC0768D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6CE9A984-37B1-4F8A-8FE9-609F05F071B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6CE9A984-37B1-4F8A-8FE9-609F05F071B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6CE9A984-37B1-4F8A-8FE9-609F05F071B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6CE9A984-37B1-4F8A-8FE9-609F05F071B3}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp
index 8e63ef3563..761c7f6fcb 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.cpp
+++ b/modules/mono/mono_gd/gd_mono_assembly.cpp
@@ -46,20 +46,6 @@ bool GDMonoAssembly::in_preload = false;
Vector<String> GDMonoAssembly::search_dirs;
-static String _get_expected_api_build_config() {
-#ifdef TOOLS_ENABLED
- return "Debug";
-#else
-
-#ifdef DEBUG_ENABLED
- return "Debug";
-#else
- return "Release";
-#endif
-
-#endif
-}
-
void GDMonoAssembly::fill_search_dirs(Vector<String> &r_search_dirs, const String &p_custom_config, const String &p_custom_bcl_dir) {
String framework_dir;
@@ -81,11 +67,14 @@ void GDMonoAssembly::fill_search_dirs(Vector<String> &r_search_dirs, const Strin
r_search_dirs.push_back(GodotSharpDirs::get_res_temp_assemblies_dir());
}
- String api_config = p_custom_config.empty() ? _get_expected_api_build_config() :
- (p_custom_config == "Release" ? "Release" : "Debug");
- r_search_dirs.push_back(GodotSharpDirs::get_res_assemblies_base_dir().plus_file(api_config));
+ if (p_custom_config.empty()) {
+ r_search_dirs.push_back(GodotSharpDirs::get_res_assemblies_dir());
+ } else {
+ String api_config = p_custom_config == "Release" ? "Release" : "Debug";
+ r_search_dirs.push_back(GodotSharpDirs::get_res_assemblies_base_dir().plus_file(api_config));
+ }
- r_search_dirs.push_back(GodotSharpDirs::get_res_assemblies_dir());
+ r_search_dirs.push_back(GodotSharpDirs::get_res_assemblies_base_dir());
r_search_dirs.push_back(OS::get_singleton()->get_resource_dir());
r_search_dirs.push_back(OS::get_singleton()->get_executable_path().get_base_dir());
diff --git a/modules/recast/register_types.cpp b/modules/recast/register_types.cpp
index 247d7f6144..44129fbb61 100644
--- a/modules/recast/register_types.cpp
+++ b/modules/recast/register_types.cpp
@@ -40,7 +40,14 @@ void register_recast_types() {
#ifdef TOOLS_ENABLED
EditorPlugins::add_by_type<NavigationMeshEditorPlugin>();
_nav_mesh_generator = memnew(EditorNavigationMeshGenerator);
+
+ ClassDB::APIType prev_api = ClassDB::get_current_api();
+ ClassDB::set_current_api(ClassDB::API_EDITOR);
+
ClassDB::register_class<EditorNavigationMeshGenerator>();
+
+ ClassDB::set_current_api(prev_api);
+
Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationMeshGenerator", EditorNavigationMeshGenerator::get_singleton()));
#endif
}
diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py
index c6afa02c6d..10680ad1f5 100644
--- a/platform/javascript/detect.py
+++ b/platform/javascript/detect.py
@@ -69,9 +69,14 @@ def configure(env):
exec(f.read(), em_config)
except StandardError as e:
raise RuntimeError("Emscripten configuration file '%s' is invalid:\n%s" % (em_config_file, e))
- if 'BINARYEN_ROOT' not in em_config and 'EMSCRIPTEN_ROOT' not in em_config:
+ if 'BINARYEN_ROOT' in em_config and os.path.isdir(os.path.join(em_config.get('BINARYEN_ROOT'), 'emscripten')):
+ # New style, emscripten path as a subfolder of BINARYEN_ROOT
+ env.PrependENVPath('PATH', os.path.join(em_config.get('BINARYEN_ROOT'), 'emscripten'))
+ elif 'EMSCRIPTEN_ROOT' in em_config:
+ # Old style (but can be there as a result from previous activation, so do last)
+ env.PrependENVPath('PATH', em_config.get('EMSCRIPTEN_ROOT'))
+ else:
raise RuntimeError("'BINARYEN_ROOT' or 'EMSCRIPTEN_ROOT' missing in Emscripten configuration file '%s'" % em_config_file)
- env.PrependENVPath('PATH', em_config.get('BINARYEN_ROOT', em_config.get('EMSCRIPTEN_ROOT')))
env['CC'] = 'emcc'
env['CXX'] = 'em++'
diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp
index d96ffc3a55..5363cd4af7 100644
--- a/platform/javascript/os_javascript.cpp
+++ b/platform/javascript/os_javascript.cpp
@@ -448,6 +448,18 @@ void OS_JavaScript::set_cursor_shape(CursorShape p_shape) {
void OS_JavaScript::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
if (p_cursor.is_valid()) {
+
+ Map<CursorShape, Vector<Variant> >::Element *cursor_c = cursors_cache.find(p_shape);
+
+ if (cursor_c) {
+ if (cursor_c->get()[0] == p_cursor && cursor_c->get()[1] == p_hotspot) {
+ set_cursor_shape(p_shape);
+ return;
+ }
+
+ cursors_cache.erase(p_shape);
+ }
+
Ref<Texture> texture = p_cursor;
Ref<AtlasTexture> atlas_texture = p_cursor;
Ref<Image> image;
@@ -551,6 +563,11 @@ void OS_JavaScript::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_s
cursors[p_shape] = url;
+ Vector<Variant> params;
+ params.push_back(p_cursor);
+ params.push_back(p_hotspot);
+ cursors_cache.insert(p_shape, params);
+
} else if (cursors[p_shape] != "") {
/* clang-format off */
EM_ASM({
diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h
index 9635465c0d..10676c49f7 100644
--- a/platform/javascript/os_javascript.h
+++ b/platform/javascript/os_javascript.h
@@ -52,6 +52,7 @@ class OS_JavaScript : public OS_Unix {
Ref<InputEventKey> deferred_key_event;
CursorShape cursor_shape;
String cursors[CURSOR_MAX];
+ Map<CursorShape, Vector<Variant> > cursors_cache;
Point2 touches[32];
Point2i last_click_pos;
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index 1e996608af..a83d5084ed 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -119,6 +119,7 @@ public:
CursorShape cursor_shape;
NSCursor *cursors[CURSOR_MAX];
+ Map<CursorShape, Vector<Variant> > cursors_cache;
MouseMode mouse_mode;
String title;
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 4f84ae9c50..726882438b 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -1770,7 +1770,20 @@ OS::CursorShape OS_OSX::get_cursor_shape() const {
}
void OS_OSX::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
+
if (p_cursor.is_valid()) {
+
+ Map<CursorShape, Vector<Variant> >::Element *cursor_c = cursors_cache.find(p_shape);
+
+ if (cursor_c) {
+ if (cursor_c->get()[0] == p_cursor && cursor_c->get()[1] == p_hotspot) {
+ set_cursor_shape(p_shape);
+ return;
+ }
+
+ cursors_cache.erase(p_shape);
+ }
+
Ref<Texture> texture = p_cursor;
Ref<AtlasTexture> atlas_texture = p_cursor;
Ref<Image> image;
@@ -1855,6 +1868,11 @@ void OS_OSX::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, c
[cursors[p_shape] release];
cursors[p_shape] = cursor;
+ Vector<Variant> params;
+ params.push_back(p_cursor);
+ params.push_back(p_hotspot);
+ cursors_cache.insert(p_shape, params);
+
if (p_shape == cursor_shape) {
if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) {
[cursor set];
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 0a9cfc0214..745f3ce379 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -2367,7 +2367,20 @@ OS::CursorShape OS_Windows::get_cursor_shape() const {
}
void OS_Windows::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
+
if (p_cursor.is_valid()) {
+
+ Map<CursorShape, Vector<Variant> >::Element *cursor_c = cursors_cache.find(p_shape);
+
+ if (cursor_c) {
+ if (cursor_c->get()[0] == p_cursor && cursor_c->get()[1] == p_hotspot) {
+ set_cursor_shape(p_shape);
+ return;
+ }
+
+ cursors_cache.erase(p_shape);
+ }
+
Ref<Texture> texture = p_cursor;
Ref<AtlasTexture> atlas_texture = p_cursor;
Ref<Image> image;
@@ -2450,6 +2463,11 @@ void OS_Windows::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shap
cursors[p_shape] = CreateIconIndirect(&iconinfo);
+ Vector<Variant> params;
+ params.push_back(p_cursor);
+ params.push_back(p_hotspot);
+ cursors_cache.insert(p_shape, params);
+
if (p_shape == cursor_shape) {
if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) {
SetCursor(cursors[p_shape]);
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index fc8ad1b188..ce55328173 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -155,6 +155,7 @@ class OS_Windows : public OS {
HCURSOR cursors[CURSOR_MAX] = { NULL };
CursorShape cursor_shape;
+ Map<CursorShape, Vector<Variant> > cursors_cache;
InputDefault *input;
JoypadWindows *joypad;
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 624efe8815..9b35648046 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -2878,7 +2878,20 @@ OS::CursorShape OS_X11::get_cursor_shape() const {
}
void OS_X11::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
+
if (p_cursor.is_valid()) {
+
+ Map<CursorShape, Vector<Variant> >::Element *cursor_c = cursors_cache.find(p_shape);
+
+ if (cursor_c) {
+ if (cursor_c->get()[0] == p_cursor && cursor_c->get()[1] == p_hotspot) {
+ set_cursor_shape(p_shape);
+ return;
+ }
+
+ cursors_cache.erase(p_shape);
+ }
+
Ref<Texture> texture = p_cursor;
Ref<AtlasTexture> atlas_texture = p_cursor;
Ref<Image> image;
@@ -2947,6 +2960,11 @@ void OS_X11::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, c
// Save it for a further usage
cursors[p_shape] = XcursorImageLoadCursor(x11_display, cursor_image);
+ Vector<Variant> params;
+ params.push_back(p_cursor);
+ params.push_back(p_hotspot);
+ cursors_cache.insert(p_shape, params);
+
if (p_shape == current_cursor) {
if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) {
XDefineCursor(x11_display, x11_window, cursors[p_shape]);
diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h
index 510487b599..a4c22cf08a 100644
--- a/platform/x11/os_x11.h
+++ b/platform/x11/os_x11.h
@@ -170,6 +170,7 @@ class OS_X11 : public OS_Unix {
Cursor cursors[CURSOR_MAX];
Cursor null_cursor;
CursorShape current_cursor;
+ Map<CursorShape, Vector<Variant> > cursors_cache;
InputDefault *input;
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index 23f6404e3e..7d1cf957ed 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -759,7 +759,7 @@ void CanvasItem::draw_multiline_colors(const Vector<Point2> &p_points, const Vec
VisualServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, p_colors, p_width, p_antialiased);
}
-void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled) {
+void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled, float p_width, bool p_antialiased) {
if (!drawing) {
ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
@@ -767,13 +767,53 @@ void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_fil
}
if (p_filled) {
+ if (p_width != 1.0) {
+ WARN_PRINT("The draw_rect() \"width\" argument has no effect when \"filled\" is \"true\".");
+ }
+
+ if (p_antialiased) {
+ WARN_PRINT("The draw_rect() \"antialiased\" argument has no effect when \"filled\" is \"true\".");
+ }
VisualServer::get_singleton()->canvas_item_add_rect(canvas_item, p_rect, p_color);
} else {
- VisualServer::get_singleton()->canvas_item_add_line(canvas_item, p_rect.position, p_rect.position + Size2(p_rect.size.width, 0), p_color);
- VisualServer::get_singleton()->canvas_item_add_line(canvas_item, p_rect.position, p_rect.position + Size2(0, p_rect.size.height), p_color);
- VisualServer::get_singleton()->canvas_item_add_line(canvas_item, p_rect.position + Point2(0, p_rect.size.height), p_rect.position + p_rect.size, p_color);
- VisualServer::get_singleton()->canvas_item_add_line(canvas_item, p_rect.position + Point2(p_rect.size.width, 0), p_rect.position + p_rect.size, p_color);
+ // Thick lines are offset depending on their width to avoid partial overlapping.
+ // Thin lines don't require an offset, so don't apply one in this case
+ float offset;
+ if (p_width >= 2) {
+ offset = p_width / 2.0;
+ } else {
+ offset = 0.0;
+ }
+
+ VisualServer::get_singleton()->canvas_item_add_line(
+ canvas_item,
+ p_rect.position + Point2(-offset, 0),
+ p_rect.position + Size2(p_rect.size.width + offset, 0),
+ p_color,
+ p_width,
+ p_antialiased);
+ VisualServer::get_singleton()->canvas_item_add_line(
+ canvas_item,
+ p_rect.position + Point2(0, offset),
+ p_rect.position + Size2(0, p_rect.size.height - offset),
+ p_color,
+ p_width,
+ p_antialiased);
+ VisualServer::get_singleton()->canvas_item_add_line(
+ canvas_item,
+ p_rect.position + Point2(-offset, p_rect.size.height),
+ p_rect.position + Size2(p_rect.size.width + offset, p_rect.size.height),
+ p_color,
+ p_width,
+ p_antialiased);
+ VisualServer::get_singleton()->canvas_item_add_line(
+ canvas_item,
+ p_rect.position + Point2(p_rect.size.width, offset),
+ p_rect.position + Size2(p_rect.size.width, p_rect.size.height - offset),
+ p_color,
+ p_width,
+ p_antialiased);
}
}
@@ -1158,7 +1198,7 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_polyline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_polyline_colors, DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_multiline", "points", "color", "width", "antialiased"), &CanvasItem::draw_multiline, DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_multiline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_multiline_colors, DEFVAL(1.0), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("draw_rect", "rect", "color", "filled"), &CanvasItem::draw_rect, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("draw_rect", "rect", "color", "filled", "width", "antialiased"), &CanvasItem::draw_rect, DEFVAL(true), DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_circle", "position", "radius", "color"), &CanvasItem::draw_circle);
ClassDB::bind_method(D_METHOD("draw_texture", "texture", "position", "modulate", "normal_map"), &CanvasItem::draw_texture, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("draw_texture_rect", "texture", "rect", "tile", "modulate", "transpose", "normal_map"), &CanvasItem::draw_texture_rect, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()));
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index 2604eb04e4..9c6799a441 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -307,7 +307,7 @@ public:
void draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false);
void draw_multiline(const Vector<Point2> &p_points, const Color &p_color, float p_width = 1.0, bool p_antialiased = false);
void draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false);
- void draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled = true);
+ void draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled = true, float p_width = 1.0, bool p_antialiased = false);
void draw_circle(const Point2 &p_pos, float p_radius, const Color &p_color);
void draw_texture(const Ref<Texture> &p_texture, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1, 1), const Ref<Texture> &p_normal_map = Ref<Texture>());
void draw_texture_rect(const Ref<Texture> &p_texture, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>());
diff --git a/scene/2d/remote_transform_2d.cpp b/scene/2d/remote_transform_2d.cpp
index 1c38a91877..fe8cc5a5fc 100644
--- a/scene/2d/remote_transform_2d.cpp
+++ b/scene/2d/remote_transform_2d.cpp
@@ -110,7 +110,7 @@ void RemoteTransform2D::_notification(int p_what) {
switch (p_what) {
- case NOTIFICATION_READY: {
+ case NOTIFICATION_ENTER_TREE: {
_update_cache();
@@ -180,6 +180,10 @@ bool RemoteTransform2D::get_update_scale() const {
return update_remote_scale;
}
+void RemoteTransform2D::force_update_cache() {
+ _update_cache();
+}
+
String RemoteTransform2D::get_configuration_warning() const {
if (!has_node(remote_node) || !Object::cast_to<Node2D>(get_node(remote_node))) {
@@ -193,6 +197,7 @@ void RemoteTransform2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_remote_node", "path"), &RemoteTransform2D::set_remote_node);
ClassDB::bind_method(D_METHOD("get_remote_node"), &RemoteTransform2D::get_remote_node);
+ ClassDB::bind_method(D_METHOD("force_update_cache"), &RemoteTransform2D::force_update_cache);
ClassDB::bind_method(D_METHOD("set_use_global_coordinates", "use_global_coordinates"), &RemoteTransform2D::set_use_global_coordinates);
ClassDB::bind_method(D_METHOD("get_use_global_coordinates"), &RemoteTransform2D::get_use_global_coordinates);
diff --git a/scene/2d/remote_transform_2d.h b/scene/2d/remote_transform_2d.h
index 16a5417592..e85fe33fc6 100644
--- a/scene/2d/remote_transform_2d.h
+++ b/scene/2d/remote_transform_2d.h
@@ -69,6 +69,8 @@ public:
void set_update_scale(const bool p_update);
bool get_update_scale() const;
+ void force_update_cache();
+
virtual String get_configuration_warning() const;
RemoteTransform2D();
diff --git a/scene/3d/remote_transform.cpp b/scene/3d/remote_transform.cpp
index 28c6fbf5f7..76b0b0c92f 100644
--- a/scene/3d/remote_transform.cpp
+++ b/scene/3d/remote_transform.cpp
@@ -105,7 +105,7 @@ void RemoteTransform::_notification(int p_what) {
switch (p_what) {
- case NOTIFICATION_READY: {
+ case NOTIFICATION_ENTER_TREE: {
_update_cache();
@@ -174,6 +174,10 @@ bool RemoteTransform::get_update_scale() const {
return update_remote_scale;
}
+void RemoteTransform::force_update_cache() {
+ _update_cache();
+}
+
String RemoteTransform::get_configuration_warning() const {
if (!has_node(remote_node) || !Object::cast_to<Spatial>(get_node(remote_node))) {
@@ -187,6 +191,7 @@ void RemoteTransform::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_remote_node", "path"), &RemoteTransform::set_remote_node);
ClassDB::bind_method(D_METHOD("get_remote_node"), &RemoteTransform::get_remote_node);
+ ClassDB::bind_method(D_METHOD("force_update_cache"), &RemoteTransform::force_update_cache);
ClassDB::bind_method(D_METHOD("set_use_global_coordinates", "use_global_coordinates"), &RemoteTransform::set_use_global_coordinates);
ClassDB::bind_method(D_METHOD("get_use_global_coordinates"), &RemoteTransform::get_use_global_coordinates);
diff --git a/scene/3d/remote_transform.h b/scene/3d/remote_transform.h
index b737a4f858..07e01284e5 100644
--- a/scene/3d/remote_transform.h
+++ b/scene/3d/remote_transform.h
@@ -68,6 +68,8 @@ public:
void set_update_scale(const bool p_update);
bool get_update_scale() const;
+ void force_update_cache();
+
virtual String get_configuration_warning() const;
RemoteTransform();
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 7a937843ab..ff0c723141 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -683,7 +683,7 @@ void TextEdit::_notification(int p_what) {
}
if (line_length_guideline) {
- int x = xmargin_beg + cache.font->get_char_size('0').width * line_length_guideline_col - cursor.x_ofs;
+ int x = xmargin_beg + (int)cache.font->get_char_size('0').width * line_length_guideline_col - cursor.x_ofs;
if (x > xmargin_beg && x < xmargin_end) {
VisualServer::get_singleton()->canvas_item_add_line(ci, Point2(x, 0), Point2(x, size.height), cache.line_length_guideline_color);
}
diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp
index 88b942ee45..05bd911014 100644
--- a/scene/main/http_request.cpp
+++ b/scene/main/http_request.cpp
@@ -96,6 +96,11 @@ Error HTTPRequest::request(const String &p_url, const Vector<String> &p_custom_h
ERR_FAIL_V(ERR_BUSY);
}
+ if (timeout > 0) {
+ timer->stop();
+ timer->start(timeout);
+ }
+
method = p_method;
Error err = _parse_url(p_url);
@@ -153,6 +158,8 @@ void HTTPRequest::_thread_func(void *p_userdata) {
void HTTPRequest::cancel_request() {
+ timer->stop();
+
if (!requesting)
return;
@@ -479,6 +486,23 @@ int HTTPRequest::get_body_size() const {
return body_len;
}
+void HTTPRequest::set_timeout(int p_timeout) {
+
+ ERR_FAIL_COND(p_timeout < 0);
+ timeout = p_timeout;
+}
+
+int HTTPRequest::get_timeout() {
+
+ return timeout;
+}
+
+void HTTPRequest::_timeout() {
+
+ cancel_request();
+ call_deferred("_request_done", RESULT_TIMEOUT, 0, PoolStringArray(), PoolByteArray());
+}
+
void HTTPRequest::_bind_methods() {
ClassDB::bind_method(D_METHOD("request", "url", "custom_headers", "ssl_validate_domain", "method", "request_data"), &HTTPRequest::request, DEFVAL(PoolStringArray()), DEFVAL(true), DEFVAL(HTTPClient::METHOD_GET), DEFVAL(String()));
@@ -504,10 +528,16 @@ void HTTPRequest::_bind_methods() {
ClassDB::bind_method(D_METHOD("_redirect_request"), &HTTPRequest::_redirect_request);
ClassDB::bind_method(D_METHOD("_request_done"), &HTTPRequest::_request_done);
+ ClassDB::bind_method(D_METHOD("set_timeout", "timeout"), &HTTPRequest::set_timeout);
+ ClassDB::bind_method(D_METHOD("get_timeout"), &HTTPRequest::get_timeout);
+
+ ClassDB::bind_method(D_METHOD("_timeout"), &HTTPRequest::_timeout);
+
ADD_PROPERTY(PropertyInfo(Variant::STRING, "download_file", PROPERTY_HINT_FILE), "set_download_file", "get_download_file");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_threads"), "set_use_threads", "is_using_threads");
ADD_PROPERTY(PropertyInfo(Variant::INT, "body_size_limit", PROPERTY_HINT_RANGE, "-1,2000000000"), "set_body_size_limit", "get_body_size_limit");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_redirects", PROPERTY_HINT_RANGE, "-1,64"), "set_max_redirects", "get_max_redirects");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "timeout", PROPERTY_HINT_RANGE, "0,86400"), "set_timeout", "get_timeout");
ADD_SIGNAL(MethodInfo("request_completed", PropertyInfo(Variant::INT, "result"), PropertyInfo(Variant::INT, "response_code"), PropertyInfo(Variant::POOL_STRING_ARRAY, "headers"), PropertyInfo(Variant::POOL_BYTE_ARRAY, "body")));
@@ -524,6 +554,7 @@ void HTTPRequest::_bind_methods() {
BIND_ENUM_CONSTANT(RESULT_DOWNLOAD_FILE_CANT_OPEN);
BIND_ENUM_CONSTANT(RESULT_DOWNLOAD_FILE_WRITE_ERROR);
BIND_ENUM_CONSTANT(RESULT_REDIRECT_LIMIT_REACHED);
+ BIND_ENUM_CONSTANT(RESULT_TIMEOUT);
}
HTTPRequest::HTTPRequest() {
@@ -546,6 +577,12 @@ HTTPRequest::HTTPRequest() {
downloaded = 0;
body_size_limit = -1;
file = NULL;
+
+ timer = memnew(Timer);
+ timer->set_one_shot(true);
+ timer->connect("timeout", this, "_timeout");
+ add_child(timer);
+ timeout = 0;
}
HTTPRequest::~HTTPRequest() {
diff --git a/scene/main/http_request.h b/scene/main/http_request.h
index 2e58d579ba..f1f91235a6 100644
--- a/scene/main/http_request.h
+++ b/scene/main/http_request.h
@@ -35,6 +35,7 @@
#include "core/os/file_access.h"
#include "core/os/thread.h"
#include "node.h"
+#include "scene/main/timer.h"
class HTTPRequest : public Node {
@@ -53,7 +54,8 @@ public:
RESULT_REQUEST_FAILED,
RESULT_DOWNLOAD_FILE_CANT_OPEN,
RESULT_DOWNLOAD_FILE_WRITE_ERROR,
- RESULT_REDIRECT_LIMIT_REACHED
+ RESULT_REDIRECT_LIMIT_REACHED,
+ RESULT_TIMEOUT
};
@@ -92,6 +94,8 @@ private:
int max_redirects;
+ int timeout;
+
void _redirect_request(const String &p_new_url);
bool _handle_response(bool *ret_value);
@@ -128,6 +132,13 @@ public:
void set_max_redirects(int p_max);
int get_max_redirects() const;
+ Timer *timer;
+
+ void set_timeout(int p_timeout);
+ int get_timeout();
+
+ void _timeout();
+
int get_downloaded_bytes() const;
int get_body_size() const;
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 63b5f206f2..393c065b7d 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -1918,9 +1918,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "all", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID } },
{ "all", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID } },
- { "not", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID } },
- { "not", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID } },
- { "not", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID } },
+ { "not", TYPE_BVEC2, { TYPE_BVEC2, TYPE_VOID } },
+ { "not", TYPE_BVEC3, { TYPE_BVEC3, TYPE_VOID } },
+ { "not", TYPE_BVEC4, { TYPE_BVEC4, TYPE_VOID } },
//builtins - texture
{ "textureSize", TYPE_IVEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID } },