diff options
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("")"> 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("")"> 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 } }, |