diff options
199 files changed, 2525 insertions, 741 deletions
diff --git a/.travis.yml b/.travis.yml index 7bf968ba4c..e7a13e3811 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,7 +20,7 @@ cache: matrix: include: - - name: Static checks (clang-format) + - name: Static checks (clang-format) + Documentation checks stage: check env: STATIC_CHECKS=yes os: linux @@ -129,6 +129,7 @@ before_script: script: - if [ "$STATIC_CHECKS" = "yes" ]; then sh ./misc/travis/clang-format.sh; + doc/tools/makerst.py --dry-run doc/classes modules; else scons -j2 CC=$CC CXX=$CXX platform=$PLATFORM tools=$TOOLS target=$TARGET $OPTIONS $EXTRA_ARGS && if [ "$TEST_PROJECT" = "yes" ]; then diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 1544503045..4c8dcc20ea 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -584,6 +584,15 @@ bool _OS::is_vsync_enabled() const { return OS::get_singleton()->is_vsync_enabled(); } +void _OS::set_vsync_via_compositor(bool p_enable) { + OS::get_singleton()->set_vsync_via_compositor(p_enable); +} + +bool _OS::is_vsync_via_compositor_enabled() const { + + return OS::get_singleton()->is_vsync_via_compositor_enabled(); +} + _OS::PowerState _OS::get_power_state() { return _OS::PowerState(OS::get_singleton()->get_power_state()); } @@ -1335,6 +1344,9 @@ void _OS::_bind_methods() { ClassDB::bind_method(D_METHOD("set_use_vsync", "enable"), &_OS::set_use_vsync); ClassDB::bind_method(D_METHOD("is_vsync_enabled"), &_OS::is_vsync_enabled); + ClassDB::bind_method(D_METHOD("set_vsync_via_compositor", "enable"), &_OS::set_vsync_via_compositor); + ClassDB::bind_method(D_METHOD("is_vsync_via_compositor_enabled"), &_OS::is_vsync_via_compositor_enabled); + ClassDB::bind_method(D_METHOD("has_feature", "tag_name"), &_OS::has_feature); ClassDB::bind_method(D_METHOD("get_power_state"), &_OS::get_power_state); @@ -1349,6 +1361,7 @@ void _OS::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "current_screen"), "set_current_screen", "get_current_screen"); ADD_PROPERTY(PropertyInfo(Variant::INT, "exit_code"), "set_exit_code", "get_exit_code"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vsync_enabled"), "set_use_vsync", "is_vsync_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vsync_via_compositor"), "set_vsync_via_compositor", "is_vsync_via_compositor_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "low_processor_usage_mode"), "set_low_processor_usage_mode", "is_in_low_processor_usage_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "low_processor_usage_mode_sleep_usec"), "set_low_processor_usage_mode_sleep_usec", "get_low_processor_usage_mode_sleep_usec"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_screen_on"), "set_keep_screen_on", "is_keep_screen_on"); @@ -1371,6 +1384,7 @@ void _OS::_bind_methods() { ADD_PROPERTY_DEFAULT("current_screen", 0); ADD_PROPERTY_DEFAULT("exit_code", 0); ADD_PROPERTY_DEFAULT("vsync_enabled", true); + ADD_PROPERTY_DEFAULT("vsync_via_compositor", false); ADD_PROPERTY_DEFAULT("low_processor_usage_mode", false); ADD_PROPERTY_DEFAULT("low_processor_usage_mode_sleep_usec", 6900); ADD_PROPERTY_DEFAULT("keep_screen_on", true); diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 18182860c6..d57da36ca5 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -345,6 +345,9 @@ public: void set_use_vsync(bool p_enable); bool is_vsync_enabled() const; + void set_vsync_via_compositor(bool p_enable); + bool is_vsync_via_compositor_enabled() const; + PowerState get_power_state(); int get_power_seconds_left(); int get_power_percent_left(); diff --git a/core/class_db.h b/core/class_db.h index 092469beb7..5df425e662 100644 --- a/core/class_db.h +++ b/core/class_db.h @@ -284,6 +284,15 @@ public: return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 6); } + template <class N, class M> + static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5, const Variant &p_def6, const Variant &p_def7) { + + MethodBind *bind = create_method_bind(p_method); + const Variant *ptr[7] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5, &p_def6, &p_def7 }; + + return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 7); + } + template <class M> static MethodBind *bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const Vector<Variant> &p_default_args = Vector<Variant>()) { diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index 1904c70f42..bfa272e859 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -173,6 +173,7 @@ Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector } status = STATUS_REQUESTING; + head_request = p_method == METHOD_HEAD; return OK; } @@ -228,6 +229,7 @@ Error HTTPClient::request(Method p_method, const String &p_url, const Vector<Str } status = STATUS_REQUESTING; + head_request = p_method == METHOD_HEAD; return OK; } @@ -269,6 +271,7 @@ void HTTPClient::close() { connection.unref(); status = STATUS_DISCONNECTED; + head_request = false; if (resolving != IP::RESOLVER_INVALID_ID) { IP::get_singleton()->erase_resolve_item(resolving); @@ -470,6 +473,12 @@ Error HTTPClient::poll() { } } + // This is a HEAD request, we wont receive anything. + if (head_request) { + body_size = 0; + body_left = 0; + } + if (body_size != -1 || chunked) { status = STATUS_BODY; @@ -724,6 +733,7 @@ HTTPClient::HTTPClient() { tcp_connection.instance(); resolving = IP::RESOLVER_INVALID_ID; status = STATUS_DISCONNECTED; + head_request = false; conn_port = -1; body_size = -1; chunked = false; diff --git a/core/io/http_client.h b/core/io/http_client.h index ce7fe0491b..27c6711bcf 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -166,6 +166,7 @@ private: bool ssl_verify_host; bool blocking; bool handshaking; + bool head_request; Vector<uint8_t> response_str; diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index f3eba44973..6f64543b3e 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -734,26 +734,49 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem String new_path = p_path; - if (translation_remaps.has(new_path)) { + if (translation_remaps.has(p_path)) { + // translation_remaps has the following format: + // { "res://path.png": PoolStringArray( "res://path-ru.png:ru", "res://path-de.png:de" ) } + + // To find the path of the remapped resource, we extract the locale name after + // the last ':' to match the project locale. + // We also fall back in case of regional locales as done in TranslationServer::translate + // (e.g. 'ru_RU' -> 'ru' if the former has no specific mapping). - Vector<String> &v = *translation_remaps.getptr(new_path); String locale = TranslationServer::get_singleton()->get_locale(); - if (r_translation_remapped) { - *r_translation_remapped = true; - } - for (int i = 0; i < v.size(); i++) { + ERR_FAIL_COND_V_MSG(locale.length() < 2, p_path, "Could not remap path '" + p_path + "' for translation as configured locale '" + locale + "' is invalid."); + String lang = TranslationServer::get_language_code(locale); - int split = v[i].find_last(":"); - if (split == -1) - continue; - String l = v[i].right(split + 1).strip_edges(); - if (l == String()) + Vector<String> &res_remaps = *translation_remaps.getptr(new_path); + bool near_match = false; + + for (int i = 0; i < res_remaps.size(); i++) { + int split = res_remaps[i].find_last(":"); + if (split == -1) { continue; + } - if (l.begins_with(locale)) { - new_path = v[i].left(split); + String l = res_remaps[i].right(split + 1).strip_edges(); + if (l == locale) { // Exact match. + new_path = res_remaps[i].left(split); break; + } else if (near_match) { + continue; // Already found near match, keep going for potential exact match. } + + // No exact match (e.g. locale 'ru_RU' but remap is 'ru'), let's look further + // for a near match (same language code, i.e. first 2 or 3 letters before + // regional code, if included). + if (TranslationServer::get_language_code(l) == lang) { + // Language code matches, that's a near match. Keep looking for exact match. + near_match = true; + new_path = res_remaps[i].left(split); + continue; + } + } + + if (r_translation_remapped) { + *r_translation_remapped = true; } } @@ -761,8 +784,8 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem new_path = path_remaps[new_path]; } - if (new_path == p_path) { //did not remap - //try file remap + if (new_path == p_path) { // Did not remap. + // Try file remap. Error err; FileAccess *f = FileAccess::open(p_path + ".remap", FileAccess::READ, &err); diff --git a/core/math/geometry.cpp b/core/math/geometry.cpp index e0ead8446f..ada5107a2c 100644 --- a/core/math/geometry.cpp +++ b/core/math/geometry.cpp @@ -1158,7 +1158,7 @@ Vector<Vector<Point2> > Geometry::_polypath_offset(const Vector<Point2> &p_polyp case END_SQUARE: et = etOpenSquare; break; case END_ROUND: et = etOpenRound; break; } - ClipperOffset co; + ClipperOffset co(2.0, 0.25 * SCALE_FACTOR); // Defaults from ClipperOffset. Path path; // Need to scale points (Clipper's requirement for robust computation). diff --git a/core/os/midi_driver.cpp b/core/os/midi_driver.cpp index 7cb7ae130f..81871d6c4f 100644 --- a/core/os/midi_driver.cpp +++ b/core/os/midi_driver.cpp @@ -33,6 +33,7 @@ #include "core/os/os.h" #include "main/input_default.h" +uint8_t MIDIDriver::last_received_message = 0x00; MIDIDriver *MIDIDriver::singleton = NULL; MIDIDriver *MIDIDriver::get_singleton() { @@ -48,33 +49,42 @@ void MIDIDriver::receive_input_packet(uint64_t timestamp, uint8_t *data, uint32_ Ref<InputEventMIDI> event; event.instance(); + uint32_t param_position = 1; if (length >= 1) { - event->set_channel(data[0] & 0xF); - event->set_message(data[0] >> 4); + if ((data[0] & 0x80) == 0x00) { + // running status + event->set_channel(last_received_message & 0xF); + event->set_message(last_received_message >> 4); + param_position = 0; + } else { + event->set_channel(data[0] & 0xF); + event->set_message(data[0] >> 4); + param_position = 1; + last_received_message = data[0]; + } } switch (event->get_message()) { case MIDI_MESSAGE_AFTERTOUCH: - if (length >= 3) { - event->set_pitch(data[1]); - event->set_pressure(data[2]); + if (length >= 2 + param_position) { + event->set_pitch(data[param_position]); + event->set_pressure(data[param_position + 1]); } break; case MIDI_MESSAGE_CONTROL_CHANGE: - if (length >= 3) { - event->set_controller_number(data[1]); - event->set_controller_value(data[2]); + if (length >= 2 + param_position) { + event->set_controller_number(data[param_position]); + event->set_controller_value(data[param_position + 1]); } break; case MIDI_MESSAGE_NOTE_ON: case MIDI_MESSAGE_NOTE_OFF: - case MIDI_MESSAGE_PITCH_BEND: - if (length >= 3) { - event->set_pitch(data[1]); - event->set_velocity(data[2]); + if (length >= 2 + param_position) { + event->set_pitch(data[param_position]); + event->set_velocity(data[param_position + 1]); if (event->get_message() == MIDI_MESSAGE_NOTE_ON && event->get_velocity() == 0) { // https://www.midi.org/forum/228-writing-midi-software-send-note-off,-or-zero-velocity-note-on @@ -83,15 +93,21 @@ void MIDIDriver::receive_input_packet(uint64_t timestamp, uint8_t *data, uint32_ } break; + case MIDI_MESSAGE_PITCH_BEND: + if (length >= 2 + param_position) { + event->set_pitch((data[param_position + 1] << 7) | data[param_position]); + } + break; + case MIDI_MESSAGE_PROGRAM_CHANGE: - if (length >= 2) { - event->set_instrument(data[1]); + if (length >= 1 + param_position) { + event->set_instrument(data[param_position]); } break; case MIDI_MESSAGE_CHANNEL_PRESSURE: - if (length >= 2) { - event->set_pressure(data[1]); + if (length >= 1 + param_position) { + event->set_pressure(data[param_position]); } break; } diff --git a/core/os/midi_driver.h b/core/os/midi_driver.h index e0e5e2be67..33f49d19f5 100644 --- a/core/os/midi_driver.h +++ b/core/os/midi_driver.h @@ -41,6 +41,7 @@ class MIDIDriver { static MIDIDriver *singleton; + static uint8_t last_received_message; public: static MIDIDriver *get_singleton(); diff --git a/core/os/os.cpp b/core/os/os.cpp index 25889de1b3..2d61417b4f 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -572,6 +572,14 @@ bool OS::is_vsync_enabled() const { return _use_vsync; } +void OS::set_vsync_via_compositor(bool p_enable) { + _vsync_via_compositor = p_enable; +} + +bool OS::is_vsync_via_compositor_enabled() const { + return _vsync_via_compositor; +} + OS::PowerState OS::get_power_state() { return POWERSTATE_UNKNOWN; } diff --git a/core/os/os.h b/core/os/os.h index 687ccaaba5..26db629d7c 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -60,6 +60,9 @@ class OS { bool _allow_hidpi; bool _allow_layered; bool _use_vsync; + bool _vsync_via_compositor; + + char *last_error; void *_stack_bottom; @@ -98,9 +101,10 @@ public: bool maximized; bool always_on_top; bool use_vsync; + bool vsync_via_compositor; bool layered; float get_aspect() const { return (float)width / (float)height; } - VideoMode(int p_width = 1024, int p_height = 600, bool p_fullscreen = false, bool p_resizable = true, bool p_borderless_window = false, bool p_maximized = false, bool p_always_on_top = false, bool p_use_vsync = false) { + VideoMode(int p_width = 1024, int p_height = 600, bool p_fullscreen = false, bool p_resizable = true, bool p_borderless_window = false, bool p_maximized = false, bool p_always_on_top = false, bool p_use_vsync = false, bool p_vsync_via_compositor = false) { width = p_width; height = p_height; fullscreen = p_fullscreen; @@ -109,6 +113,7 @@ public: maximized = p_maximized; always_on_top = p_always_on_top; use_vsync = p_use_vsync; + vsync_via_compositor = p_vsync_via_compositor; layered = false; } }; @@ -507,6 +512,9 @@ public: //real, actual overridable function to switch vsync, which needs to be called from graphics thread if needed virtual void _set_use_vsync(bool p_enable) {} + void set_vsync_via_compositor(bool p_enable); + bool is_vsync_via_compositor_enabled() const; + virtual OS::PowerState get_power_state(); virtual int get_power_seconds_left(); virtual int get_power_percent_left(); diff --git a/core/translation.cpp b/core/translation.cpp index 4a1ac26433..4a662b2590 100644 --- a/core/translation.cpp +++ b/core/translation.cpp @@ -792,11 +792,6 @@ static const char *locale_renames[][2] = { { NULL, NULL } }; -static String get_trimmed_locale(const String &p_locale) { - - return p_locale.substr(0, 2); -} - /////////////////////////////////////////////// PoolVector<String> Translation::_get_messages() const { @@ -846,7 +841,7 @@ void Translation::set_locale(const String &p_locale) { String univ_locale = TranslationServer::standardize_locale(p_locale); if (!TranslationServer::is_locale_valid(univ_locale)) { - String trimmed_locale = get_trimmed_locale(univ_locale); + String trimmed_locale = TranslationServer::get_language_code(univ_locale); ERR_FAIL_COND_MSG(!TranslationServer::is_locale_valid(trimmed_locale), "Invalid locale: " + trimmed_locale + "."); @@ -945,12 +940,29 @@ String TranslationServer::standardize_locale(const String &p_locale) { return univ_locale; } +String TranslationServer::get_language_code(const String &p_locale) { + + ERR_FAIL_COND_V_MSG(p_locale.length() < 2, p_locale, "Invalid locale '" + p_locale + "'."); + // Most language codes are two letters, but some are three, + // so we have to look for a regional code separator ('_' or '-') + // to extract the left part. + // For example we get 'nah_MX' as input and should return 'nah'. + int split = p_locale.find("_"); + if (split == -1) { + split = p_locale.find("-"); + } + if (split == -1) { // No separator, so the locale is already only a language code. + return p_locale; + } + return p_locale.left(split); +} + void TranslationServer::set_locale(const String &p_locale) { String univ_locale = standardize_locale(p_locale); if (!is_locale_valid(univ_locale)) { - String trimmed_locale = get_trimmed_locale(univ_locale); + String trimmed_locale = get_language_code(univ_locale); print_verbose(vformat("Unsupported locale '%s', falling back to '%s'.", p_locale, trimmed_locale)); if (!is_locale_valid(trimmed_locale)) { @@ -1039,11 +1051,13 @@ void TranslationServer::clear() { StringName TranslationServer::translate(const StringName &p_message) const { - //translate using locale + // Match given message against the translation catalog for the project locale. if (!enabled) return p_message; + ERR_FAIL_COND_V_MSG(locale.length() < 2, p_message, "Could not translate message as configured locale '" + locale + "' is invalid."); + // Locale can be of the form 'll_CC', i.e. language code and regional code, // e.g. 'en_US', 'en_GB', etc. It might also be simply 'll', e.g. 'en'. // To find the relevant translation, we look for those with locale starting @@ -1051,67 +1065,78 @@ StringName TranslationServer::translate(const StringName &p_message) const { // form. If not found, we fall back to a near match (another locale with // same language code). + // Note: ResourceLoader::_path_remap reproduces this locale near matching + // logic, so be sure to propagate changes there when changing things here. + StringName res; + String lang = get_language_code(locale); bool near_match = false; - const CharType *lptr = &locale[0]; for (const Set<Ref<Translation> >::Element *E = translations.front(); E; E = E->next()) { - const Ref<Translation> &t = E->get(); - ERR_FAIL_COND_V(t.is_null(), StringName("")); + ERR_FAIL_COND_V(t.is_null(), p_message); String l = t->get_locale(); - if (lptr[0] != l[0] || lptr[1] != l[1]) - continue; // Language code does not match. bool exact_match = (l == locale); - if (!exact_match && near_match) - continue; // Only near-match once, but keep looking for exact matches. + if (!exact_match) { + if (near_match) { + continue; // Only near-match once, but keep looking for exact matches. + } + if (get_language_code(l) != lang) { + continue; // Language code does not match. + } + } StringName r = t->get_message(p_message); - - if (!r) + if (!r) { continue; - + } res = r; - if (exact_match) + if (exact_match) { break; - else + } else { near_match = true; + } } if (!res && fallback.length() >= 2) { // Try again with the fallback locale. - const CharType *fptr = &fallback[0]; + String fallback_lang = get_language_code(fallback); near_match = false; - for (const Set<Ref<Translation> >::Element *E = translations.front(); E; E = E->next()) { + for (const Set<Ref<Translation> >::Element *E = translations.front(); E; E = E->next()) { const Ref<Translation> &t = E->get(); - ERR_FAIL_COND_V(t.is_null(), StringName("")); + ERR_FAIL_COND_V(t.is_null(), p_message); String l = t->get_locale(); - if (fptr[0] != l[0] || fptr[1] != l[1]) - continue; // Language code does not match. bool exact_match = (l == fallback); - if (!exact_match && near_match) - continue; // Only near-match once, but keep looking for exact matches. + if (!exact_match) { + if (near_match) { + continue; // Only near-match once, but keep looking for exact matches. + } + if (get_language_code(l) != fallback_lang) { + continue; // Language code does not match. + } + } StringName r = t->get_message(p_message); - - if (!r) + if (!r) { continue; - + } res = r; - if (exact_match) + if (exact_match) { break; - else + } else { near_match = true; + } } } - if (!res) + if (!res) { return p_message; + } return res; } diff --git a/core/translation.h b/core/translation.h index d172b9ecf2..834374bda6 100644 --- a/core/translation.h +++ b/core/translation.h @@ -105,6 +105,7 @@ public: static Vector<String> get_all_locale_names(); static bool is_locale_valid(const String &p_locale); static String standardize_locale(const String &p_locale); + static String get_language_code(const String &p_locale); void set_tool_translation(const Ref<Translation> &p_translation); StringName tool_translate(const StringName &p_message) const; diff --git a/doc/classes/AABB.xml b/doc/classes/AABB.xml index 61e1ea9b8d..44f1d9a921 100644 --- a/doc/classes/AABB.xml +++ b/doc/classes/AABB.xml @@ -182,6 +182,7 @@ <argument index="0" name="aabb" type="AABB"> </argument> <description> + Returns [code]true[/code] if this [AABB] and [code]aabb[/code] are approximately equal, by calling [code]is_equal_approx[/code] on each component. </description> </method> <method name="merge"> @@ -190,7 +191,7 @@ <argument index="0" name="with" type="AABB"> </argument> <description> - Returns a larger AABB that contains this AABB and [code]with[/code]. + Returns a larger [AABB] that contains both this [AABB] and [code]with[/code]. </description> </method> </methods> diff --git a/doc/classes/Basis.xml b/doc/classes/Basis.xml index df9438e695..5a7fc0a41b 100644 --- a/doc/classes/Basis.xml +++ b/doc/classes/Basis.xml @@ -102,6 +102,7 @@ <argument index="1" name="epsilon" type="float" default="0.00001"> </argument> <description> + Returns [code]true[/code] if this basis and [code]b[/code] are approximately equal, by calling [code]is_equal_approx[/code] on each component. </description> </method> <method name="orthonormalized"> diff --git a/doc/classes/Camera.xml b/doc/classes/Camera.xml index 3b4313b204..aca53d4ed0 100644 --- a/doc/classes/Camera.xml +++ b/doc/classes/Camera.xml @@ -38,12 +38,14 @@ <argument index="0" name="layer" type="int"> </argument> <description> + Returns [code]true[/code] if the given [code]layer[/code] in the [member cull_mask] is enabled, [code]false[/code] otherwise. </description> </method> <method name="get_frustum" qualifiers="const"> <return type="Array"> </return> <description> + Returns the camera's frustum planes in world-space units as an array of [Plane]s in the following order: near, far, left, top, right, bottom. Not to be confused with [member frustum_offset]. </description> </method> <method name="is_position_behind" qualifiers="const"> @@ -109,6 +111,7 @@ <argument index="1" name="enable" type="bool"> </argument> <description> + Enables or disables the given [code]layer[/code] in the [member cull_mask]. </description> </method> <method name="set_frustum"> @@ -123,6 +126,7 @@ <argument index="3" name="z_far" type="float"> </argument> <description> + Sets the camera projection to frustum mode (see [constant PROJECTION_FRUSTUM]), by specifying a [code]size[/code], an [code]offset[/code], and the [code]z_near[/code] and [code]z_far[/code] clip planes in world-space units. </description> </method> <method name="set_orthogonal"> @@ -135,7 +139,7 @@ <argument index="2" name="z_far" type="float"> </argument> <description> - Sets the camera projection to orthogonal mode, by specifying a width and the [code]near[/code] and [code]far[/code] clip planes in worldspace units. (As a hint, 2D games often use this projection, with values specified in pixels) + Sets the camera projection to orthogonal mode (see [constant PROJECTION_ORTHOGONAL]), by specifying a [code]size[/code], and the [code]z_near[/code] and [code]z_far[/code] clip planes in world-space units. (As a hint, 2D games often use this projection, with values specified in pixels.) </description> </method> <method name="set_perspective"> @@ -148,7 +152,7 @@ <argument index="2" name="z_far" type="float"> </argument> <description> - Sets the camera projection to perspective mode, by specifying a [code]fov[/code] angle in degrees (FOV means Field of View), and the [code]near[/code] and [code]far[/code] clip planes in world-space units. + Sets the camera projection to perspective mode (see [constant PROJECTION_PERSPECTIVE]), by specifying a [code]fov[/code] (field of view) angle in degrees, and the [code]z_near[/code] and [code]z_far[/code] clip planes in world-space units. </description> </method> <method name="unproject_position" qualifiers="const"> @@ -169,7 +173,7 @@ If [code]true[/code], the ancestor [Viewport] is currently using this camera. </member> <member name="doppler_tracking" type="int" setter="set_doppler_tracking" getter="get_doppler_tracking" enum="Camera.DopplerTracking" default="0"> - If not [constant DOPPLER_TRACKING_DISABLED], this camera will simulate the Doppler effect for objects changed in particular [code]_process[/code] methods. See [enum DopplerTracking] for possible values. + If not [constant DOPPLER_TRACKING_DISABLED], this camera will simulate the [url=https://en.wikipedia.org/wiki/Doppler_effect]Doppler effect[/url] for objects changed in particular [code]_process[/code] methods. See [enum DopplerTracking] for possible values. </member> <member name="environment" type="Environment" setter="set_environment" getter="get_environment"> The [Environment] to use for this camera. @@ -181,6 +185,7 @@ The camera's field of view angle (in degrees). Only applicable in perspective mode. Since [member keep_aspect] locks one axis, [code]fov[/code] sets the other axis' field of view angle. </member> <member name="frustum_offset" type="Vector2" setter="set_frustum_offset" getter="get_frustum_offset" default="Vector2( 0, 0 )"> + The camera's frustum offset. This can be changed from the default to create "tilted frustum" effects such as [url=https://zdoom.org/wiki/Y-shearing]Y-shearing[/url]. </member> <member name="h_offset" type="float" setter="set_h_offset" getter="get_h_offset" default="0.0"> The horizontal (X) offset of the camera viewport. @@ -218,13 +223,13 @@ Preserves the vertical aspect ratio; also known as Hor+ scaling. This is usually the best option for projects running in landscape mode, as wider aspect ratios will automatically benefit from a wider horizontal FOV. </constant> <constant name="DOPPLER_TRACKING_DISABLED" value="0" enum="DopplerTracking"> - Disables Doppler effect simulation (default). + Disables [url=https://en.wikipedia.org/wiki/Doppler_effect]Doppler effect[/url] simulation (default). </constant> <constant name="DOPPLER_TRACKING_IDLE_STEP" value="1" enum="DopplerTracking"> - Simulate Doppler effect by tracking positions of objects that are changed in [code]_process[/code]. Changes in the relative velocity of this camera compared to those objects affect how Audio is perceived (changing the Audio's [code]pitch shift[/code]). + Simulate [url=https://en.wikipedia.org/wiki/Doppler_effect]Doppler effect[/url] by tracking positions of objects that are changed in [code]_process[/code]. Changes in the relative velocity of this camera compared to those objects affect how Audio is perceived (changing the Audio's [code]pitch shift[/code]). </constant> <constant name="DOPPLER_TRACKING_PHYSICS_STEP" value="2" enum="DopplerTracking"> - Simulate Doppler effect by tracking positions of objects that are changed in [code]_physics_process[/code]. Changes in the relative velocity of this camera compared to those objects affect how Audio is perceived (changing the Audio's [code]pitch shift[/code]). + Simulate [url=https://en.wikipedia.org/wiki/Doppler_effect]Doppler effect[/url] by tracking positions of objects that are changed in [code]_physics_process[/code]. Changes in the relative velocity of this camera compared to those objects affect how Audio is perceived (changing the Audio's [code]pitch shift[/code]). </constant> </constants> </class> diff --git a/doc/classes/Color.xml b/doc/classes/Color.xml index deba30712e..1d4225542a 100644 --- a/doc/classes/Color.xml +++ b/doc/classes/Color.xml @@ -157,6 +157,7 @@ <argument index="0" name="color" type="Color"> </argument> <description> + Returns [code]true[/code] if this color and [code]color[/code] are approximately equal, by running [method @GDScript.is_equal_approx] on each component. </description> </method> <method name="lightened"> diff --git a/doc/classes/DynamicFont.xml b/doc/classes/DynamicFont.xml index 0820d4e1b6..ac8595d783 100644 --- a/doc/classes/DynamicFont.xml +++ b/doc/classes/DynamicFont.xml @@ -4,7 +4,8 @@ DynamicFont renders vector font files at runtime. </brief_description> <description> - DynamicFont renders vector font files (such as TTF or OTF) dynamically at runtime instead of using a prerendered texture atlas like [BitmapFont]. This trades the faster loading time of [BitmapFont]s for the ability to change font parameters like size and spacing during runtime. [DynamicFontData] is used for referencing the font file paths. + DynamicFont renders vector font files (such as TTF or OTF) dynamically at runtime instead of using a prerendered texture atlas like [BitmapFont]. This trades the faster loading time of [BitmapFont]s for the ability to change font parameters like size and spacing during runtime. [DynamicFontData] is used for referencing the font file paths. DynamicFont also supports defining one or more fallbacks fonts, which will be used when displaying a character not supported by the main font. + DynamicFont uses the [url=https://www.freetype.org/]FreeType[/url] library for rasterization. [codeblock] var dynamic_font = DynamicFont.new() dynamic_font.font_data = load("res://BarlowCondensed-Bold.ttf") @@ -46,6 +47,7 @@ <argument index="0" name="type" type="int"> </argument> <description> + Returns the spacing for the given [code]type[/code] (see [enum SpacingType]). </description> </method> <method name="remove_fallback"> @@ -76,6 +78,7 @@ <argument index="1" name="value" type="int"> </argument> <description> + Sets the spacing for [code]type[/code] (see [enum SpacingType]) to [code]value[/code] in pixels (not relative to the font size). </description> </method> </methods> @@ -96,17 +99,20 @@ The font data. </member> <member name="outline_color" type="Color" setter="set_outline_color" getter="get_outline_color" default="Color( 1, 1, 1, 1 )"> + The font outline's color. + [b]Note:[/b] It's recommended to leave this at the default value so that you can adjust it in individual controls. For example, if the outline is made black here, it won't be possible to change its color using a Label's font outline modulate theme item. </member> <member name="outline_size" type="int" setter="set_outline_size" getter="get_outline_size" default="0"> + The font outline's thickness in pixels (not relative to the font size). </member> <member name="size" type="int" setter="set_size" getter="get_size" default="16"> - The font size. + The font size in pixels. </member> <member name="use_filter" type="bool" setter="set_use_filter" getter="get_use_filter" default="false"> - If [code]true[/code], filtering is used. + If [code]true[/code], filtering is used. This makes the font blurry instead of pixelated when scaling it if font oversampling is disabled or ineffective. It's recommended to enable this when using the font in a control whose size changes over time, unless a pixel art aesthetic is desired. </member> <member name="use_mipmaps" type="bool" setter="set_use_mipmaps" getter="get_use_mipmaps" default="false"> - If [code]true[/code], mipmapping is used. + If [code]true[/code], mipmapping is used. This improves the font's appearance when downscaling it if font oversampling is disabled or ineffective. </member> </members> <constants> diff --git a/doc/classes/Line2D.xml b/doc/classes/Line2D.xml index 3cb04b8b89..b11f3e27e5 100644 --- a/doc/classes/Line2D.xml +++ b/doc/classes/Line2D.xml @@ -66,6 +66,9 @@ </method> </methods> <members> + <member name="antialiased" type="bool" setter="set_antialiased" getter="get_antialiased" default="false"> + If [code]true[/code], the line's border will be anti-aliased. + </member> <member name="begin_cap_mode" type="int" setter="set_begin_cap_mode" getter="get_begin_cap_mode" enum="Line2D.LineCapMode" default="0"> Controls the style of the line's first point. Use [code]LINE_CAP_*[/code] constants. </member> diff --git a/doc/classes/Listener.xml b/doc/classes/Listener.xml index 130263a069..ae8c38198f 100644 --- a/doc/classes/Listener.xml +++ b/doc/classes/Listener.xml @@ -1,8 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="Listener" inherits="Spatial" category="Core" version="3.2"> <brief_description> + Overrides the location sounds are heard from. </brief_description> <description> + Once added to the scene tree and enabled using [method make_current], this node will override the location sounds are heard from. This can be used to listen from a location different from the [Camera]. + [b]Note:[/b] There is no 2D equivalent for this node yet. </description> <tutorials> </tutorials> @@ -11,24 +14,29 @@ <return type="void"> </return> <description> + Disables the listener to use the current camera's listener instead. </description> </method> <method name="get_listener_transform" qualifiers="const"> <return type="Transform"> </return> <description> + Returns the listener's global orthonormalized [Transform]. </description> </method> <method name="is_current" qualifiers="const"> <return type="bool"> </return> <description> + Returns [code]true[/code] if the listener was made current using [method make_current], [code]false[/code] otherwise. + [b]Note:[/b] There may be more than one Listener marked as "current" in the scene tree, but only the one that was made current last will be used. </description> </method> <method name="make_current"> <return type="void"> </return> <description> + Enables the listener. This will override the current camera's listener. </description> </method> </methods> diff --git a/doc/classes/MeshLibrary.xml b/doc/classes/MeshLibrary.xml index 44dc4f334f..49278be44e 100644 --- a/doc/classes/MeshLibrary.xml +++ b/doc/classes/MeshLibrary.xml @@ -4,7 +4,7 @@ Library of meshes. </brief_description> <description> - A library of meshes. Contains a list of [Mesh] resources, each with a name and ID. This resource is used in [GridMap]. + A library of meshes. Contains a list of [Mesh] resources, each with a name and ID. Each item can also include collision and navigation shapes. This resource is used in [GridMap]. </description> <tutorials> </tutorials> @@ -22,7 +22,8 @@ <argument index="0" name="id" type="int"> </argument> <description> - Create a new item in the library, supplied as an ID. + Creates a new item in the library with the given ID. + You can get an unused ID from [method get_last_unused_item_id]. </description> </method> <method name="find_item_by_name" qualifiers="const"> @@ -31,13 +32,14 @@ <argument index="0" name="name" type="String"> </argument> <description> + Returns the first item with the given name. </description> </method> <method name="get_item_list" qualifiers="const"> <return type="PoolIntArray"> </return> <description> - Returns the list of items. + Returns the list of item IDs in use. </description> </method> <method name="get_item_mesh" qualifiers="const"> @@ -46,7 +48,7 @@ <argument index="0" name="id" type="int"> </argument> <description> - Returns the mesh of the item. + Returns the item's mesh. </description> </method> <method name="get_item_name" qualifiers="const"> @@ -55,7 +57,7 @@ <argument index="0" name="id" type="int"> </argument> <description> - Returns the name of the item. + Returns the item's name. </description> </method> <method name="get_item_navmesh" qualifiers="const"> @@ -64,6 +66,7 @@ <argument index="0" name="id" type="int"> </argument> <description> + Returns the item's navigation mesh. </description> </method> <method name="get_item_navmesh_transform" qualifiers="const"> @@ -72,6 +75,7 @@ <argument index="0" name="id" type="int"> </argument> <description> + Returns the transform applied to the item's navigation mesh. </description> </method> <method name="get_item_preview" qualifiers="const"> @@ -90,6 +94,8 @@ <argument index="0" name="id" type="int"> </argument> <description> + Returns an item's collision shapes. + The array consists of each [Shape] followed by its [Transform]. </description> </method> <method name="get_last_unused_item_id" qualifiers="const"> @@ -128,6 +134,7 @@ </argument> <description> Sets the item's name. + This name is shown in the editor. It can also be used to look up the item later using [method find_item_by_name]. </description> </method> <method name="set_item_navmesh"> @@ -138,6 +145,7 @@ <argument index="1" name="navmesh" type="NavigationMesh"> </argument> <description> + Sets the item's navigation mesh. </description> </method> <method name="set_item_navmesh_transform"> @@ -148,6 +156,7 @@ <argument index="1" name="navmesh" type="Transform"> </argument> <description> + Sets the transform to apply to the item's navigation mesh. </description> </method> <method name="set_item_preview"> @@ -158,6 +167,7 @@ <argument index="1" name="texture" type="Texture"> </argument> <description> + Sets a texture to use as the item's preview icon in the editor. </description> </method> <method name="set_item_shapes"> @@ -168,6 +178,8 @@ <argument index="1" name="shapes" type="Array"> </argument> <description> + Sets an item's collision shapes. + The array should consist of [Shape] objects, each followed by a [Transform] that will be applied to it. For shapes that should not have a transform, use [constant Transform.IDENTITY]. </description> </method> </methods> diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index 6da0547352..54b4f3df64 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -45,6 +45,8 @@ <return type="void"> </return> <description> + Shuts down system MIDI driver. + [b]Note:[/b] This method is implemented on Linux, macOS and Windows. </description> </method> <method name="delay_msec" qualifiers="const"> @@ -119,6 +121,7 @@ [codeblock] OS.execute("CMD.exe", ["/C", "cd %TEMP% && dir"], true, output) [/codeblock] + [b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows. </description> </method> <method name="find_scancode_from_string" qualifiers="const"> @@ -159,6 +162,7 @@ <description> Returns an array of MIDI device names. The returned array will be empty if the system MIDI driver has not previously been initialised with [method open_midi_inputs]. + [b]Note:[/b] This method is implemented on Linux, macOS and Windows. </description> </method> <method name="get_current_video_driver" qualifiers="const"> @@ -224,6 +228,7 @@ </return> <description> With this function you can get the list of dangerous permissions that have been granted to the Android application. + [b]Note:[/b] This method is implemented on Android. </description> </method> <method name="get_ime_selection" qualifiers="const"> @@ -232,6 +237,7 @@ <description> Returns the IME cursor position (the currently-edited portion of the string) relative to the characters in the composition string. [constant MainLoop.NOTIFICATION_OS_IME_UPDATE] is sent to the application to notify it of changes to the IME cursor position. + [b]Note:[/b] This method is implemented on macOS. </description> </method> <method name="get_ime_text" qualifiers="const"> @@ -240,6 +246,7 @@ <description> Returns the IME intermediate composition string. [constant MainLoop.NOTIFICATION_OS_IME_UPDATE] is sent to the application to notify it of changes to the IME composition string. + [b]Note:[/b] This method is implemented on macOS. </description> </method> <method name="get_latin_keyboard_variant" qualifiers="const"> @@ -248,6 +255,7 @@ <description> Returns the current latin keyboard variant as a String. Possible return values are: [code]"QWERTY"[/code], [code]"AZERTY"[/code], [code]"QZERTY"[/code], [code]"DVORAK"[/code], [code]"NEO"[/code], [code]"COLEMAK"[/code] or [code]"ERROR"[/code]. + [b]Note:[/b] This method is implemented on Linux, macOS and Windows. Returns [code]"QWERTY"[/code] on unsupported platforms. </description> </method> <method name="get_locale" qualifiers="const"> @@ -262,6 +270,7 @@ </return> <description> Returns the model name of the current device. + [b]Note:[/b] This method is implemented on Android and iOS. Returns [code]"GenericDevice"[/code] on unsupported platforms. </description> </method> <method name="get_name" qualifiers="const"> @@ -275,14 +284,16 @@ <return type="int"> </return> <description> - Returns the amount of battery left in the device as a percentage. + Returns the amount of battery left in the device as a percentage. Returns [code]-1[/code] if power state is unknown. + [b]Note:[/b] This method is implemented on Linux, macOS and Windows. </description> </method> <method name="get_power_seconds_left"> <return type="int"> </return> <description> - Returns an estimate of the time left in seconds before the device runs out of battery. + Returns an estimate of the time left in seconds before the device runs out of battery. Returns [code]-1[/code] if power state is unknown. + [b]Note:[/b] This method is implemented on Linux, macOS and Windows. </description> </method> <method name="get_power_state"> @@ -290,6 +301,7 @@ </return> <description> Returns the current state of the device regarding battery and power. See [enum PowerState] constants. + [b]Note:[/b] This method is implemented on Linux, macOS and Windows. </description> </method> <method name="get_process_id" qualifiers="const"> @@ -297,6 +309,7 @@ </return> <description> Returns the project's process ID. + [b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows. </description> </method> <method name="get_processor_count" qualifiers="const"> @@ -345,6 +358,7 @@ xxhdpi - 480 dpi xxxhdpi - 640 dpi [/codeblock] + [b]Note:[/b] This method is implemented on Android, Linux, macOS and Windows. Returns [code]72[/code] on unsupported platforms. </description> </method> <method name="get_screen_position" qualifiers="const"> @@ -393,6 +407,7 @@ </argument> <description> Returns the actual path to commonly used folders across different platforms. Available locations are specified in [enum SystemDir]. + [b]Note:[/b] This method is implemented on Android, Linux, macOS and Windows. </description> </method> <method name="get_system_time_msecs" qualifiers="const"> @@ -519,6 +534,7 @@ </argument> <description> Add a new item with text "label" to global menu. Use "_dock" menu to add item to the macOS dock icon menu. + [b]Note:[/b] This method is implemented on macOS. </description> </method> <method name="global_menu_add_separator"> @@ -528,6 +544,7 @@ </argument> <description> Add a separator between items. Separators also occupy an index. + [b]Note:[/b] This method is implemented on macOS. </description> </method> <method name="global_menu_clear"> @@ -537,6 +554,7 @@ </argument> <description> Clear the global menu, in effect removing all items. + [b]Note:[/b] This method is implemented on macOS. </description> </method> <method name="global_menu_remove_item"> @@ -548,6 +566,7 @@ </argument> <description> Removes the item at index "idx" from the global menu. Note that the indexes of items after the removed item are going to be shifted by one. + [b]Note:[/b] This method is implemented on macOS. </description> </method> <method name="has_environment" qualifiers="const"> @@ -644,6 +663,7 @@ <description> Kill (terminate) the process identified by the given process ID ([code]pid[/code]), e.g. the one returned by [method execute] in non-blocking mode. [b]Note:[/b] This method can also be used to kill processes that were not spawned by the game. + [b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows. </description> </method> <method name="move_window_to_foreground"> @@ -651,6 +671,7 @@ </return> <description> Moves the window to the front. + [b]Note:[/b] This method is implemented on Linux, macOS and Windows. </description> </method> <method name="native_video_is_playing"> @@ -658,6 +679,7 @@ </return> <description> Returns [code]true[/code] if native video is playing. + [b]Note:[/b] This method is implemented on Android and iOS. </description> </method> <method name="native_video_pause"> @@ -665,6 +687,7 @@ </return> <description> Pauses native video playback. + [b]Note:[/b] This method is implemented on Android and iOS. </description> </method> <method name="native_video_play"> @@ -680,7 +703,7 @@ </argument> <description> Plays native video from the specified path, at the given volume and with audio and subtitle tracks. - [b]Note:[/b] This method is only implemented on Android and iOS, and the current Android implementation does not support the [code]volume[/code], [code]audio_track[/code] and [code]subtitle_track[/code] options. + [b]Note:[/b] This method is implemented on Android and iOS, and the current Android implementation does not support the [code]volume[/code], [code]audio_track[/code] and [code]subtitle_track[/code] options. </description> </method> <method name="native_video_stop"> @@ -688,6 +711,7 @@ </return> <description> Stops native video playback. + [b]Note:[/b] This method is implemented on Android and iOS. </description> </method> <method name="native_video_unpause"> @@ -695,6 +719,7 @@ </return> <description> Resumes native video playback. + [b]Note:[/b] This method is implemented on Android and iOS. </description> </method> <method name="open_midi_inputs"> @@ -702,6 +727,7 @@ </return> <description> Initialises the singleton for the system MIDI driver. + [b]Note:[/b] This method is implemented on Linux, macOS and Windows. </description> </method> <method name="print_all_resources"> @@ -743,6 +769,7 @@ </return> <description> Request the user attention to the window. It'll flash the taskbar button on Windows or bounce the dock icon on OSX. + [b]Note:[/b] This method is implemented on Linux, macOS and Windows. </description> </method> <method name="request_permission"> @@ -759,6 +786,7 @@ </return> <description> With this function you can request dangerous permissions since normal permissions are automatically granted at install time in Android application. + [b]Note:[/b] This method is implemented on Android. </description> </method> <method name="set_icon"> @@ -769,6 +797,7 @@ <description> Sets the game's icon using an [Image] resource. The same image is used for window caption, taskbar/dock and window selection dialog. Image is scaled as needed. + [b]Note:[/b] This method is implemented on HTML5, Linux, macOS and Windows. </description> </method> <method name="set_ime_active"> @@ -781,6 +810,7 @@ If active IME handles key events before the application and creates an composition string and suggestion list. Application can retrieve the composition status by using [method get_ime_selection] and [method get_ime_text] functions. Completed composition string is committed when input is finished. + [b]Note:[/b] This method is implemented on Linux, macOS and Windows. </description> </method> <method name="set_ime_position"> @@ -790,6 +820,7 @@ </argument> <description> Sets position of IME suggestion list popup (in window coordinates). + [b]Note:[/b] This method is implemented on Linux, macOS and Windows. </description> </method> <method name="set_native_icon"> @@ -800,7 +831,7 @@ <description> Sets the game's icon using a multi-size platform-specific icon file ([code]*.ico[/code] on Windows and [code]*.icns[/code] on macOS). Appropriate size sub-icons are used for window caption, taskbar/dock and window selection dialog. - [b]Note:[/b] This method is only implemented on macOS and Windows. + [b]Note:[/b] This method is implemented on macOS and Windows. </description> </method> <method name="set_thread_name"> @@ -828,6 +859,7 @@ </argument> <description> Sets whether the window should always be on top. + [b]Note:[/b] This method is implemented on Linux, macOS and Windows. </description> </method> <method name="set_window_title"> @@ -838,6 +870,7 @@ <description> Sets the window title to the specified string. [b]Note:[/b] This should be used sporadically. Don't set this every frame, as that will negatively affect performance on some window managers. + [b]Note:[/b] This method is implemented on HTML5, Linux, macOS and Windows. </description> </method> <method name="shell_open"> @@ -850,6 +883,7 @@ - [code]OS.shell_open("C:\\Users\name\Downloads")[/code] on Windows opens the file explorer at the user's Downloads folder. - [code]OS.shell_open("https://godotengine.org")[/code] opens the default web browser on the official Godot website. - [code]OS.shell_open("mailto:example@example.com")[/code] opens the default email client with the "To" field set to [code]example@example.com[/code]. See [url=https://blog.escapecreative.com/customizing-mailto-links/]Customizing [code]mailto:[/code] Links[/url] for a list of fields that can be added. + [b]Note:[/b] This method is implemented on Android, iOS, HTML5, Linux, macOS and Windows. </description> </method> <method name="show_virtual_keyboard"> @@ -859,6 +893,7 @@ </argument> <description> Shows the virtual keyboard if the platform has one. The [code]existing_text[/code] parameter is useful for implementing your own LineEdit, as it tells the virtual keyboard what text has already been typed (the virtual keyboard uses it for auto-correct and predictions). + [b]Note:[/b] This method is implemented on Android, iOS and UWP. </description> </method> </methods> @@ -893,6 +928,9 @@ <member name="vsync_enabled" type="bool" setter="set_use_vsync" getter="is_vsync_enabled" default="true"> If [code]true[/code], vertical synchronization (Vsync) is enabled. </member> + <member name="vsync_via_compositor" type="bool" setter="set_vsync_via_compositor" getter="is_vsync_via_compositor_enabled" default="false"> + If [code]true[/code] and [code]vsync_enabled[/code] is true, the operating system's window compositor will be used for vsync when the compositor is enabled and the game is in windowed mode. + </member> <member name="window_borderless" type="bool" setter="set_borderless_window" getter="get_borderless_window" default="false"> If [code]true[/code], removes the window frame. [b]Note:[/b] Setting [code]window_borderless[/code] to [code]false[/code] disables per-pixel transparency. @@ -910,6 +948,7 @@ If [code]true[/code], the window background is transparent and window frame is removed. Use [code]get_tree().get_root().set_transparent_background(true)[/code] to disable main viewport background rendering. [b]Note:[/b] This property has no effect if [b]Project > Project Settings > Display > Window > Per-pixel transparency > Allowed[/b] setting is disabled. + [b]Note:[/b] This property is implemented on Linux, macOS and Windows. </member> <member name="window_position" type="Vector2" setter="set_window_position" getter="get_window_position" default="Vector2( 0, 0 )"> The window position relative to the screen, the origin is the top left corner, +Y axis goes to the bottom and +X axis goes to the right. diff --git a/doc/classes/Plane.xml b/doc/classes/Plane.xml index bb72f2734e..f179041327 100644 --- a/doc/classes/Plane.xml +++ b/doc/classes/Plane.xml @@ -122,6 +122,7 @@ <argument index="0" name="plane" type="Plane"> </argument> <description> + Returns [code]true[/code] if this plane and [code]plane[/code] are approximately equal, by running [method @GDScript.is_equal_approx] on each component. </description> </method> <method name="is_point_over"> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 772c2f5073..97af3ec77a 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -431,6 +431,9 @@ <member name="display/window/vsync/use_vsync" type="bool" setter="" getter="" default="true"> If [code]true[/code], enables vertical synchronization. This eliminates tearing that may appear in moving scenes, at the cost of higher input latency and stuttering at lower framerates. If [code]false[/code], vertical synchronization will be disabled, however, many platforms will enforce it regardless (such as mobile platforms and HTML5). </member> + <member name="display/window/vsync/vsync_via_compositor" type="bool" setter="" getter="" default="false"> + If [code]Use Vsync[/code] is enabled and this setting is [code]true[/code], enables vertical synchronization via the operating system's window compositor when in windowed mode and the compositor is enabled. This will prevent stutter in certain situations. (Windows only.) + </member> <member name="editor/script_templates_search_path" type="String" setter="" getter="" default=""res://script_templates""> </member> <member name="editor/search_in_file_extensions" type="PoolStringArray" setter="" getter="" default="PoolStringArray( "gd", "shader" )"> diff --git a/doc/classes/Quat.xml b/doc/classes/Quat.xml index f5ee99d30c..eeb633f480 100644 --- a/doc/classes/Quat.xml +++ b/doc/classes/Quat.xml @@ -100,6 +100,7 @@ <argument index="0" name="quat" type="Quat"> </argument> <description> + Returns [code]true[/code] if this quaterion and [code]quat[/code] are approximately equal, by running [method @GDScript.is_equal_approx] on each component. </description> </method> <method name="is_normalized"> diff --git a/doc/classes/Rect2.xml b/doc/classes/Rect2.xml index 07fa7777fe..90dd996691 100644 --- a/doc/classes/Rect2.xml +++ b/doc/classes/Rect2.xml @@ -143,6 +143,7 @@ <argument index="0" name="rect" type="Rect2"> </argument> <description> + Returns [code]true[/code] if this [Rect2] and [code]rect[/code] are approximately equal, by calling [code]is_equal_approx[/code] on each component. </description> </method> <method name="merge"> @@ -151,7 +152,7 @@ <argument index="0" name="b" type="Rect2"> </argument> <description> - Returns a larger Rect2 that contains this Rect2 and [code]b[/code]. + Returns a larger [Rect2] that contains this [Rect2] and [code]b[/code]. </description> </method> </methods> diff --git a/doc/classes/Script.xml b/doc/classes/Script.xml index e8a88acdb5..91014580d3 100644 --- a/doc/classes/Script.xml +++ b/doc/classes/Script.xml @@ -4,7 +4,7 @@ A class stored as a resource. </brief_description> <description> - A class stored as a resource. A script exends the functionality of all objects that instance it. + A class stored as a resource. A script extends the functionality of all objects that instance it. The [code]new[/code] method of a script subclass creates a new instance. [method Object.set_script] extends an existing object, if that object's class matches one of the script's base classes. </description> <tutorials> diff --git a/doc/classes/Transform.xml b/doc/classes/Transform.xml index 034a1b2f5b..4c4022b3b5 100644 --- a/doc/classes/Transform.xml +++ b/doc/classes/Transform.xml @@ -95,6 +95,7 @@ <argument index="0" name="transform" type="Transform"> </argument> <description> + Returns [code]true[/code] if this transform and [code]transform[/code] are approximately equal, by calling [code]is_equal_approx[/code] on each component. </description> </method> <method name="looking_at"> diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml index 89ccffc2e9..6288bb074c 100644 --- a/doc/classes/Transform2D.xml +++ b/doc/classes/Transform2D.xml @@ -112,6 +112,7 @@ <argument index="0" name="transform" type="Transform2D"> </argument> <description> + Returns [code]true[/code] if this transform and [code]transform[/code] are approximately equal, by calling [code]is_equal_approx[/code] on each component. </description> </method> <method name="orthonormalized"> diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml index 8ae5caf68c..b23c69de60 100644 --- a/doc/classes/Vector2.xml +++ b/doc/classes/Vector2.xml @@ -159,6 +159,7 @@ <argument index="0" name="v" type="Vector2"> </argument> <description> + Returns [code]true[/code] if this vector and [code]v[/code] are approximately equal, by running [method @GDScript.is_equal_approx] on each component. </description> </method> <method name="is_normalized"> diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml index 29c24709e2..d838e6d2f7 100644 --- a/doc/classes/Vector3.xml +++ b/doc/classes/Vector3.xml @@ -135,6 +135,7 @@ <argument index="0" name="v" type="Vector3"> </argument> <description> + Returns [code]true[/code] if this vector and [code]v[/code] are approximately equal, by running [method @GDScript.is_equal_approx] on each component. </description> </method> <method name="is_normalized"> diff --git a/doc/classes/VisualServer.xml b/doc/classes/VisualServer.xml index 895aba2473..3f3996e570 100644 --- a/doc/classes/VisualServer.xml +++ b/doc/classes/VisualServer.xml @@ -411,6 +411,8 @@ </argument> <argument index="9" name="normal_map" type="RID"> </argument> + <argument index="10" name="antialiased" type="bool" default="false"> + </argument> <description> </description> </method> @@ -2604,6 +2606,14 @@ <description> </description> </method> + <method name="multimesh_create"> + <return type="RID"> + </return> + <description> + Creates a new multimesh on the VisualServer and returns an [RID] handle. + Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method. + </description> + </method> <method name="multimesh_get_aabb" qualifiers="const"> <return type="AABB"> </return> diff --git a/doc/tools/makerst.py b/doc/tools/makerst.py index ef38299680..91240e9550 100755 --- a/doc/tools/makerst.py +++ b/doc/tools/makerst.py @@ -14,7 +14,7 @@ GODOT_DOCS_PATTERN = re.compile(r'^http(?:s)?://docs\.godotengine\.org/(?:[a-zA- def print_error(error, state): # type: (str, State) -> None - print(error) + print("ERROR: {}".format(error)) state.errored = True @@ -148,6 +148,8 @@ class State: setter = property.get("setter") or None # Use or None so '' gets turned into None. getter = property.get("getter") or None default_value = property.get("default") or None + if default_value is not None: + default_value = escape_rst(default_value) overridden = property.get("override") or False property_def = PropertyDef(property_name, type_name, setter, getter, property.text, default_value, overridden) @@ -622,6 +624,40 @@ def make_class_list(class_list, columns): # type: (List[str], int) -> None f.close() +def escape_rst(text, until_pos=-1): # type: (str) -> str + # Escape \ character, otherwise it ends up as an escape character in rst + pos = 0 + while True: + pos = text.find('\\', pos, until_pos) + if pos == -1: + break + text = text[:pos] + "\\\\" + text[pos + 1:] + pos += 2 + + # Escape * character to avoid interpreting it as emphasis + pos = 0 + while True: + pos = text.find('*', pos, until_pos) + if pos == -1: + break + text = text[:pos] + "\*" + text[pos + 1:] + pos += 2 + + # Escape _ character at the end of a word to avoid interpreting it as an inline hyperlink + pos = 0 + while True: + pos = text.find('_', pos, until_pos) + if pos == -1: + break + if not text[pos + 1].isalnum(): # don't escape within a snake_case word + text = text[:pos] + "\_" + text[pos + 1:] + pos += 2 + else: + pos += 1 + + return text + + def rstize_text(text, state): # type: (str, State) -> str # Linebreak + tabs in the XML should become two line breaks unless in a "codeblock" pos = 0 @@ -677,36 +713,7 @@ def rstize_text(text, state): # type: (str, State) -> str pos += 2 next_brac_pos = text.find('[') - - # Escape \ character, otherwise it ends up as an escape character in rst - pos = 0 - while True: - pos = text.find('\\', pos, next_brac_pos) - if pos == -1: - break - text = text[:pos] + "\\\\" + text[pos + 1:] - pos += 2 - - # Escape * character to avoid interpreting it as emphasis - pos = 0 - while True: - pos = text.find('*', pos, next_brac_pos) - if pos == -1: - break - text = text[:pos] + "\*" + text[pos + 1:] - pos += 2 - - # Escape _ character at the end of a word to avoid interpreting it as an inline hyperlink - pos = 0 - while True: - pos = text.find('_', pos, next_brac_pos) - if pos == -1: - break - if not text[pos + 1].isalnum(): # don't escape within a snake_case word - text = text[:pos] + "\_" + text[pos + 1:] - pos += 2 - else: - pos += 1 + text = escape_rst(text, next_brac_pos) # Handle [tags] inside_code = False @@ -975,7 +982,11 @@ def make_enum(t, state): # type: (str, State) -> str if c in state.classes and e in state.classes[c].enums: return ":ref:`{0}<enum_{1}_{0}>`".format(e, c) - print_error("Unresolved enum '{}', file: {}".format(t, state.current_class), state) + + # Don't fail for `Vector3.Axis`, as this enum is a special case which is expected not to be resolved. + if "{}.{}".format(c, e) != "Vector3.Axis": + print_error("Unresolved enum '{}', file: {}".format(t, state.current_class), state) + return t diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp index ac54af722c..1db1625194 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.cpp +++ b/drivers/gles2/rasterizer_canvas_gles2.cpp @@ -406,6 +406,66 @@ void RasterizerCanvasGLES2::_draw_generic(GLuint p_primitive, int p_vertex_count glBindBuffer(GL_ARRAY_BUFFER, 0); } +void RasterizerCanvasGLES2::_draw_generic_indices(GLuint p_primitive, const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor) { + + glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer); +#ifndef GLES_OVER_GL + // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData + glBufferData(GL_ARRAY_BUFFER, data.polygon_buffer_size, NULL, GL_DYNAMIC_DRAW); +#endif + + uint32_t buffer_ofs = 0; + + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vector2) * p_vertex_count, p_vertices); + glEnableVertexAttribArray(VS::ARRAY_VERTEX); + glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), NULL); + buffer_ofs += sizeof(Vector2) * p_vertex_count; + + if (p_singlecolor) { + glDisableVertexAttribArray(VS::ARRAY_COLOR); + Color m = *p_colors; + glVertexAttrib4f(VS::ARRAY_COLOR, m.r, m.g, m.b, m.a); + } else if (!p_colors) { + glDisableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); + } else { + glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors); + glEnableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); + buffer_ofs += sizeof(Color) * p_vertex_count; + } + + if (p_uvs) { + glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs); + glEnableVertexAttribArray(VS::ARRAY_TEX_UV); + glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); + buffer_ofs += sizeof(Vector2) * p_vertex_count; + } else { + glDisableVertexAttribArray(VS::ARRAY_TEX_UV); + } + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer); +#ifndef GLES_OVER_GL + // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData + glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer_size, NULL, GL_DYNAMIC_DRAW); +#endif + + if (storage->config.support_32_bits_indices) { //should check for + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(int) * p_index_count, p_indices); + glDrawElements(p_primitive, p_index_count, GL_UNSIGNED_INT, 0); + } else { + uint16_t *index16 = (uint16_t *)alloca(sizeof(uint16_t) * p_index_count); + for (int i = 0; i < p_index_count; i++) { + index16[i] = uint16_t(p_indices[i]); + } + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(uint16_t) * p_index_count, index16); + glDrawElements(p_primitive, p_index_count, GL_UNSIGNED_SHORT, 0); + } + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} + void RasterizerCanvasGLES2::_draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs) { static const GLenum prim[5] = { GL_POINTS, GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_FAN }; @@ -973,7 +1033,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur #ifdef GLES_OVER_GL if (polygon->antialiased) { glEnable(GL_LINE_SMOOTH); - _draw_generic(GL_LINE_LOOP, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1); + _draw_generic_indices(GL_LINE_STRIP, polygon->indices.ptr(), polygon->count, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1); glDisable(GL_LINE_SMOOTH); } #endif diff --git a/drivers/gles2/rasterizer_canvas_gles2.h b/drivers/gles2/rasterizer_canvas_gles2.h index ba636a9763..5df5b10f3c 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.h +++ b/drivers/gles2/rasterizer_canvas_gles2.h @@ -118,6 +118,7 @@ public: _FORCE_INLINE_ void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs); _FORCE_INLINE_ void _draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor, const float *p_weights = NULL, const int *p_bones = NULL); _FORCE_INLINE_ void _draw_generic(GLuint p_primitive, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor); + _FORCE_INLINE_ void _draw_generic_indices(GLuint p_primitive, const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor); _FORCE_INLINE_ void _canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip, RasterizerStorageGLES2::Material *p_material); void _copy_screen(const Rect2 &p_rect); diff --git a/drivers/gles2/shader_gles2.h b/drivers/gles2/shader_gles2.h index c7a6465194..fbca69e0bb 100644 --- a/drivers/gles2/shader_gles2.h +++ b/drivers/gles2/shader_gles2.h @@ -118,10 +118,12 @@ private: uint32_t code_version; bool ok; Version() { - code_version = 0; + id = 0; + vert_id = 0; frag_id = 0; - ok = false; uniform_location = NULL; + code_version = 0; + ok = false; } }; diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl index 25dbbf3c90..930d3cd9d4 100644 --- a/drivers/gles2/shaders/scene.glsl +++ b/drivers/gles2/shaders/scene.glsl @@ -251,12 +251,10 @@ void light_compute( //normalized blinn always unless disabled vec3 H = normalize(V + L); float cNdotH = max(dot(N, H), 0.0); - float cVdotH = max(dot(V, H), 0.0); - float cLdotH = max(dot(L, H), 0.0); float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; - float blinn = pow(cNdotH, shininess); + float blinn = pow(cNdotH, shininess) * cNdotL; blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); - specular_brdf_NL = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75); + specular_brdf_NL = blinn; #endif SRGB_APPROX(specular_brdf_NL) @@ -1270,9 +1268,9 @@ LIGHT_SHADER_CODE //normalized blinn float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; - float blinn = pow(cNdotH, shininess); + float blinn = pow(cNdotH, shininess) * cNdotL; blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); - specular_brdf_NL = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75); + specular_brdf_NL = blinn; #elif defined(SPECULAR_PHONG) @@ -1547,157 +1545,157 @@ FRAGMENT_SHADER_CODE #endif // !USE_SHADOW_TO_OPACITY #ifdef BASE_PASS - { - // IBL precalculations - float ndotv = clamp(dot(normal, eye_position), 0.0, 1.0); - vec3 f0 = F0(metallic, specular, albedo); - vec3 F = f0 + (max(vec3(1.0 - roughness), f0) - f0) * pow(1.0 - ndotv, 5.0); + + // IBL precalculations + float ndotv = clamp(dot(normal, eye_position), 0.0, 1.0); + vec3 f0 = F0(metallic, specular, albedo); + vec3 F = f0 + (max(vec3(1.0 - roughness), f0) - f0) * pow(1.0 - ndotv, 5.0); #ifdef AMBIENT_LIGHT_DISABLED - ambient_light = vec3(0.0, 0.0, 0.0); + ambient_light = vec3(0.0, 0.0, 0.0); #else #ifdef USE_RADIANCE_MAP - vec3 ref_vec = reflect(-eye_position, N); - ref_vec = normalize((radiance_inverse_xform * vec4(ref_vec, 0.0)).xyz); + vec3 ref_vec = reflect(-eye_position, N); + ref_vec = normalize((radiance_inverse_xform * vec4(ref_vec, 0.0)).xyz); - ref_vec.z *= -1.0; + ref_vec.z *= -1.0; - specular_light = textureCubeLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).xyz * bg_energy; + specular_light = textureCubeLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).xyz * bg_energy; #ifndef USE_LIGHTMAP - { - vec3 ambient_dir = normalize((radiance_inverse_xform * vec4(normal, 0.0)).xyz); - vec3 env_ambient = textureCubeLod(radiance_map, ambient_dir, 4.0).xyz * bg_energy; - env_ambient *= 1.0 - F; + { + vec3 ambient_dir = normalize((radiance_inverse_xform * vec4(normal, 0.0)).xyz); + vec3 env_ambient = textureCubeLod(radiance_map, ambient_dir, 4.0).xyz * bg_energy; + env_ambient *= 1.0 - F; - ambient_light = mix(ambient_color.rgb, env_ambient, ambient_sky_contribution); - } + ambient_light = mix(ambient_color.rgb, env_ambient, ambient_sky_contribution); + } #endif #else - ambient_light = ambient_color.rgb; - specular_light = bg_color.rgb * bg_energy; + ambient_light = ambient_color.rgb; + specular_light = bg_color.rgb * bg_energy; #endif #endif // AMBIENT_LIGHT_DISABLED - ambient_light *= ambient_energy; + ambient_light *= ambient_energy; #if defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2) - vec4 ambient_accum = vec4(0.0); - vec4 reflection_accum = vec4(0.0); + vec4 ambient_accum = vec4(0.0); + vec4 reflection_accum = vec4(0.0); #ifdef USE_REFLECTION_PROBE1 - reflection_process(reflection_probe1, + reflection_process(reflection_probe1, #ifdef USE_VERTEX_LIGHTING - refprobe1_reflection_normal_blend.rgb, + refprobe1_reflection_normal_blend.rgb, #ifndef USE_LIGHTMAP - refprobe1_ambient_normal, + refprobe1_ambient_normal, #endif - refprobe1_reflection_normal_blend.a, + refprobe1_reflection_normal_blend.a, #else - normal_interp, vertex_interp, refprobe1_local_matrix, - refprobe1_use_box_project, refprobe1_box_extents, refprobe1_box_offset, + normal_interp, vertex_interp, refprobe1_local_matrix, + refprobe1_use_box_project, refprobe1_box_extents, refprobe1_box_offset, #endif - refprobe1_exterior, refprobe1_intensity, refprobe1_ambient, roughness, - ambient_light, specular_light, reflection_accum, ambient_accum); + refprobe1_exterior, refprobe1_intensity, refprobe1_ambient, roughness, + ambient_light, specular_light, reflection_accum, ambient_accum); #endif // USE_REFLECTION_PROBE1 #ifdef USE_REFLECTION_PROBE2 - reflection_process(reflection_probe2, + reflection_process(reflection_probe2, #ifdef USE_VERTEX_LIGHTING - refprobe2_reflection_normal_blend.rgb, + refprobe2_reflection_normal_blend.rgb, #ifndef USE_LIGHTMAP - refprobe2_ambient_normal, + refprobe2_ambient_normal, #endif - refprobe2_reflection_normal_blend.a, + refprobe2_reflection_normal_blend.a, #else - normal_interp, vertex_interp, refprobe2_local_matrix, - refprobe2_use_box_project, refprobe2_box_extents, refprobe2_box_offset, + normal_interp, vertex_interp, refprobe2_local_matrix, + refprobe2_use_box_project, refprobe2_box_extents, refprobe2_box_offset, #endif - refprobe2_exterior, refprobe2_intensity, refprobe2_ambient, roughness, - ambient_light, specular_light, reflection_accum, ambient_accum); + refprobe2_exterior, refprobe2_intensity, refprobe2_ambient, roughness, + ambient_light, specular_light, reflection_accum, ambient_accum); #endif // USE_REFLECTION_PROBE2 - if (reflection_accum.a > 0.0) { - specular_light = reflection_accum.rgb / reflection_accum.a; - } + if (reflection_accum.a > 0.0) { + specular_light = reflection_accum.rgb / reflection_accum.a; + } #ifndef USE_LIGHTMAP - if (ambient_accum.a > 0.0) { - ambient_light = ambient_accum.rgb / ambient_accum.a; - } + if (ambient_accum.a > 0.0) { + ambient_light = ambient_accum.rgb / ambient_accum.a; + } #endif #endif // defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2) - // environment BRDF approximation - { + // environment BRDF approximation + { #if defined(DIFFUSE_TOON) - //simplify for toon, as - specular_light *= specular * metallic * albedo * 2.0; + //simplify for toon, as + specular_light *= specular * metallic * albedo * 2.0; #else - // scales the specular reflections, needs to be be computed before lighting happens, - // but after environment and reflection probes are added - //TODO: this curve is not really designed for gammaspace, should be adjusted - const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022); - const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04); - vec4 r = roughness * c0 + c1; - float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y; - vec2 env = vec2(-1.04, 1.04) * a004 + r.zw; - specular_light *= env.x * F + env.y; + // scales the specular reflections, needs to be be computed before lighting happens, + // but after environment and reflection probes are added + //TODO: this curve is not really designed for gammaspace, should be adjusted + const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022); + const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04); + vec4 r = roughness * c0 + c1; + float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y; + vec2 env = vec2(-1.04, 1.04) * a004 + r.zw; + specular_light *= env.x * F + env.y; #endif - } + } #ifdef USE_LIGHTMAP - //ambient light will come entirely from lightmap is lightmap is used - ambient_light = texture2D(lightmap, uv2_interp).rgb * lightmap_energy; + //ambient light will come entirely from lightmap is lightmap is used + ambient_light = texture2D(lightmap, uv2_interp).rgb * lightmap_energy; #endif #ifdef USE_LIGHTMAP_CAPTURE - { - vec3 cone_dirs[12] = vec3[]( - vec3(0.0, 0.0, 1.0), - vec3(0.866025, 0.0, 0.5), - vec3(0.267617, 0.823639, 0.5), - vec3(-0.700629, 0.509037, 0.5), - vec3(-0.700629, -0.509037, 0.5), - vec3(0.267617, -0.823639, 0.5), - vec3(0.0, 0.0, -1.0), - vec3(0.866025, 0.0, -0.5), - vec3(0.267617, 0.823639, -0.5), - vec3(-0.700629, 0.509037, -0.5), - vec3(-0.700629, -0.509037, -0.5), - vec3(0.267617, -0.823639, -0.5)); - - vec3 local_normal = normalize(camera_matrix * vec4(normal, 0.0)).xyz; - vec4 captured = vec4(0.0); - float sum = 0.0; - for (int i = 0; i < 12; i++) { - float amount = max(0.0, dot(local_normal, cone_dirs[i])); //not correct, but creates a nice wrap around effect - captured += lightmap_captures[i] * amount; - sum += amount; - } + { + vec3 cone_dirs[12] = vec3[]( + vec3(0.0, 0.0, 1.0), + vec3(0.866025, 0.0, 0.5), + vec3(0.267617, 0.823639, 0.5), + vec3(-0.700629, 0.509037, 0.5), + vec3(-0.700629, -0.509037, 0.5), + vec3(0.267617, -0.823639, 0.5), + vec3(0.0, 0.0, -1.0), + vec3(0.866025, 0.0, -0.5), + vec3(0.267617, 0.823639, -0.5), + vec3(-0.700629, 0.509037, -0.5), + vec3(-0.700629, -0.509037, -0.5), + vec3(0.267617, -0.823639, -0.5)); + + vec3 local_normal = normalize(camera_matrix * vec4(normal, 0.0)).xyz; + vec4 captured = vec4(0.0); + float sum = 0.0; + for (int i = 0; i < 12; i++) { + float amount = max(0.0, dot(local_normal, cone_dirs[i])); //not correct, but creates a nice wrap around effect + captured += lightmap_captures[i] * amount; + sum += amount; + } - captured /= sum; + captured /= sum; - if (lightmap_capture_sky) { - ambient_light = mix(ambient_light, captured.rgb, captured.a); - } else { - ambient_light = captured.rgb; - } + if (lightmap_capture_sky) { + ambient_light = mix(ambient_light, captured.rgb, captured.a); + } else { + ambient_light = captured.rgb; } -#endif } +#endif + #endif //BASE PASS // @@ -2052,17 +2050,6 @@ FRAGMENT_SHADER_CODE specular_light += specular_interp * specular_blob_intensity * light_att; diffuse_light += diffuse_interp * albedo * light_att; - // Same as above, needed for VERTEX_LIGHTING or else lights are too bright - const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022); - const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04); - vec4 r = roughness * c0 + c1; - float ndotv = clamp(dot(normal, eye_position), 0.0, 1.0); - float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y; - vec2 env = vec2(-1.04, 1.04) * a004 + r.zw; - - vec3 f0 = F0(metallic, specular, albedo); - specular_light *= env.x * f0 + env.y; - #else //fragment lighting light_compute( diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 55d16a6c2e..b3263ce41c 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -327,9 +327,8 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer); #ifndef GLES_OVER_GL - // Orphan the buffers to avoid CPU/GPU sync points caused by glBufferSubData + // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData glBufferData(GL_ARRAY_BUFFER, data.polygon_buffer_size, NULL, GL_DYNAMIC_DRAW); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer_size, NULL, GL_DYNAMIC_DRAW); #endif uint32_t buffer_ofs = 0; @@ -402,6 +401,10 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun //bind the indices buffer. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer); +#ifndef GLES_OVER_GL + // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData + glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer_size, NULL, GL_DYNAMIC_DRAW); +#endif glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(int) * p_index_count, p_indices); //draw the triangles. @@ -424,9 +427,8 @@ void RasterizerCanvasGLES3::_draw_generic(GLuint p_primitive, int p_vertex_count glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer); #ifndef GLES_OVER_GL - // Orphan the buffers to avoid CPU/GPU sync points caused by glBufferSubData + // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData glBufferData(GL_ARRAY_BUFFER, data.polygon_buffer_size, NULL, GL_DYNAMIC_DRAW); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer_size, NULL, GL_DYNAMIC_DRAW); #endif uint32_t buffer_ofs = 0; @@ -471,6 +473,78 @@ void RasterizerCanvasGLES3::_draw_generic(GLuint p_primitive, int p_vertex_count glBindVertexArray(0); } +void RasterizerCanvasGLES3::_draw_generic_indices(GLuint p_primitive, const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor) { + + glBindVertexArray(data.polygon_buffer_pointer_array); + glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer); + +#ifndef GLES_OVER_GL + // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData + glBufferData(GL_ARRAY_BUFFER, data.polygon_buffer_size, NULL, GL_DYNAMIC_DRAW); +#endif + + uint32_t buffer_ofs = 0; + + //vertex + glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_vertices); + glEnableVertexAttribArray(VS::ARRAY_VERTEX); + glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); + buffer_ofs += sizeof(Vector2) * p_vertex_count; + //color +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); +#endif + + if (p_singlecolor) { + glDisableVertexAttribArray(VS::ARRAY_COLOR); + Color m = *p_colors; + glVertexAttrib4f(VS::ARRAY_COLOR, m.r, m.g, m.b, m.a); + } else if (!p_colors) { + glDisableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); + } else { + + glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors); + glEnableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); + buffer_ofs += sizeof(Color) * p_vertex_count; + } + +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); +#endif + + if (p_uvs) { + + glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs); + glEnableVertexAttribArray(VS::ARRAY_TEX_UV); + glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); + buffer_ofs += sizeof(Vector2) * p_vertex_count; + + } else { + glDisableVertexAttribArray(VS::ARRAY_TEX_UV); + } + +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); +#endif + + //bind the indices buffer. + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer); +#ifndef GLES_OVER_GL + // Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData + glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer_size, NULL, GL_DYNAMIC_DRAW); +#endif + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(int) * p_index_count, p_indices); + + //draw the triangles. + glDrawElements(p_primitive, p_index_count, GL_UNSIGNED_INT, 0); + + storage->frame.canvas_draw_commands++; + + glBindVertexArray(0); +} + void RasterizerCanvasGLES3::_draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs) { static const GLenum prim[5] = { GL_POINTS, GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_FAN }; @@ -824,7 +898,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur #ifdef GLES_OVER_GL if (polygon->antialiased) { glEnable(GL_LINE_SMOOTH); - _draw_generic(GL_LINE_LOOP, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1); + _draw_generic_indices(GL_LINE_STRIP, polygon->indices.ptr(), polygon->count, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1); glDisable(GL_LINE_SMOOTH); } #endif diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index 382b1e5640..b1671a6d1c 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -132,6 +132,7 @@ public: _FORCE_INLINE_ void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs); _FORCE_INLINE_ void _draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor, const int *p_bones, const float *p_weights); _FORCE_INLINE_ void _draw_generic(GLuint p_primitive, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor); + _FORCE_INLINE_ void _draw_generic_indices(GLuint p_primitive, const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor); _FORCE_INLINE_ void _canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip); _FORCE_INLINE_ void _copy_texscreen(const Rect2 &p_rect); diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 9815936d1e..66ff0a1845 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -4147,7 +4147,11 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_reflection_atlas); - if (shadow_atlas && shadow_atlas->size) { + bool use_shadows = shadow_atlas && shadow_atlas->size; + + state.scene_shader.set_conditional(SceneShaderGLES3::USE_SHADOW, use_shadows); + + if (use_shadows) { glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 5); glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); @@ -4521,15 +4525,15 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const if (state.directional_light_count == 0) { directional_light = NULL; - _render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, sky, false, false, false, false, shadow_atlas != NULL); + _render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, sky, false, false, false, false, use_shadows); } else { for (int i = 0; i < state.directional_light_count; i++) { directional_light = directional_lights[i]; if (i > 0) { glEnable(GL_BLEND); } - _setup_directional_light(i, p_cam_transform.affine_inverse(), shadow_atlas != NULL && shadow_atlas->size > 0); - _render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, sky, false, false, false, i > 0, shadow_atlas != NULL); + _setup_directional_light(i, p_cam_transform.affine_inverse(), use_shadows); + _render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, sky, false, false, false, i > 0, use_shadows); } } @@ -4607,12 +4611,12 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const if (state.directional_light_count == 0) { directional_light = NULL; - _render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, sky, false, true, false, false, shadow_atlas != NULL); + _render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, sky, false, true, false, false, use_shadows); } else { for (int i = 0; i < state.directional_light_count; i++) { directional_light = directional_lights[i]; - _setup_directional_light(i, p_cam_transform.affine_inverse(), shadow_atlas != NULL && shadow_atlas->size > 0); - _render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, sky, false, true, false, i > 0, shadow_atlas != NULL); + _setup_directional_light(i, p_cam_transform.affine_inverse(), use_shadows); + _render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, sky, false, true, false, i > 0, use_shadows); } } diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index e1b0e9f595..b4ceb7dcfd 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -213,12 +213,10 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float roughness, in //normalized blinn always unless disabled vec3 H = normalize(V + L); float cNdotH = max(dot(N, H), 0.0); - float cVdotH = max(dot(V, H), 0.0); - float cLdotH = max(dot(L, H), 0.0); float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; - float blinn = pow(cNdotH, shininess); + float blinn = pow(cNdotH, shininess) * cNdotL; blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); - specular_brdf_NL = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75); + specular_brdf_NL = blinn; #endif specular += specular_brdf_NL * light_color * (1.0 / M_PI); @@ -1094,9 +1092,9 @@ LIGHT_SHADER_CODE //normalized blinn float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; - float blinn = pow(cNdotH, shininess); + float blinn = pow(cNdotH, shininess) * cNdotL; blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); - float intensity = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75); + float intensity = blinn; specular_light += light_color * intensity * specular_blob_intensity * attenuation; @@ -1256,6 +1254,7 @@ void light_process_omni(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 bi vec3 light_attenuation = vec3(omni_attenuation); #if !defined(SHADOWS_DISABLED) +#ifdef USE_SHADOW if (omni_lights[idx].light_params.w > 0.5) { // there is a shadowmap @@ -1300,6 +1299,7 @@ void light_process_omni(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 bi #endif light_attenuation *= mix(omni_lights[idx].shadow_color_contact.rgb, vec3(1.0), shadow); } +#endif //USE_SHADOW #endif //SHADOWS_DISABLED light_compute(normal, normalize(light_rel_vec), eye_vec, binormal, tangent, omni_lights[idx].light_color_energy.rgb, light_attenuation, albedo, transmission, omni_lights[idx].light_params.z * p_blob_intensity, roughness, metallic, specular, rim * omni_attenuation, rim_tint, clearcoat, clearcoat_gloss, anisotropy, diffuse_light, specular_light, alpha); } @@ -1318,6 +1318,7 @@ void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 bi vec3 light_attenuation = vec3(spot_attenuation); #if !defined(SHADOWS_DISABLED) +#ifdef USE_SHADOW if (spot_lights[idx].light_params.w > 0.5) { //there is a shadowmap highp vec4 splane = (spot_lights[idx].shadow_matrix * vec4(vertex, 1.0)); @@ -1334,6 +1335,7 @@ void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 bi #endif light_attenuation *= mix(spot_lights[idx].shadow_color_contact.rgb, vec3(1.0), shadow); } +#endif //USE_SHADOW #endif //SHADOWS_DISABLED light_compute(normal, normalize(light_rel_vec), eye_vec, binormal, tangent, spot_lights[idx].light_color_energy.rgb, light_attenuation, albedo, transmission, spot_lights[idx].light_params.z * p_blob_intensity, roughness, metallic, specular, rim * spot_attenuation, rim_tint, clearcoat, clearcoat_gloss, anisotropy, diffuse_light, specular_light, alpha); diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 16780a795f..e3138dc1e5 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -1565,6 +1565,7 @@ void CodeTextEditor::goto_next_bookmark() { if (bline > line) { text_editor->unfold_line(bline); text_editor->cursor_set_line(bline); + text_editor->center_viewport_to_cursor(); return; } } @@ -1589,6 +1590,7 @@ void CodeTextEditor::goto_prev_bookmark() { if (bline < line) { text_editor->unfold_line(bline); text_editor->cursor_set_line(bline); + text_editor->center_viewport_to_cursor(); return; } } diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index 80353bab01..718156f12a 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -85,6 +85,9 @@ void AnimationPlayerEditor::_notification(int p_what) { track_editor->set_anim_pos(player->get_current_animation_position()); EditorNode::get_singleton()->get_inspector()->refresh(); + } else if (!player->is_valid()) { + // Reset timeline when the player has been stopped externally + frame->set_value(0); } else if (last_active) { // Need the last frame after it stopped. frame->set_value(player->get_current_animation_position()); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 9894c8c562..de9efaf8ba 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -1111,7 +1111,11 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_eve if (dragged_guide_index >= 0) { vguides.remove(dragged_guide_index); undo_redo->create_action(TTR("Remove Vertical Guide")); - undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides); + if (vguides.empty()) { + undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "remove_meta", "_edit_vertical_guides_"); + } else { + undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides); + } undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides); undo_redo->add_undo_method(viewport, "update"); undo_redo->commit_action(); @@ -1140,7 +1144,11 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_eve if (dragged_guide_index >= 0) { hguides.remove(dragged_guide_index); undo_redo->create_action(TTR("Remove Horizontal Guide")); - undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides); + if (hguides.empty()) { + undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "remove_meta", "_edit_horizontal_guides_"); + } else { + undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides); + } undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides); undo_redo->add_undo_method(viewport, "update"); undo_redo->commit_action(); @@ -4752,19 +4760,21 @@ void CanvasItemEditor::_popup_callback(int p_op) { } break; case CLEAR_GUIDES: { - if (EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_horizontal_guides_") || EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) { + Node *const root = EditorNode::get_singleton()->get_edited_scene(); + + if (root && (root->has_meta("_edit_horizontal_guides_") || root->has_meta("_edit_vertical_guides_"))) { undo_redo->create_action(TTR("Clear Guides")); - if (EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_horizontal_guides_")) { - Array hguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_horizontal_guides_"); + if (root->has_meta("_edit_horizontal_guides_")) { + Array hguides = root->get_meta("_edit_horizontal_guides_"); - undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", Array()); - undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides); + undo_redo->add_do_method(root, "remove_meta", "_edit_horizontal_guides_"); + undo_redo->add_undo_method(root, "set_meta", "_edit_horizontal_guides_", hguides); } - if (EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) { - Array vguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_vertical_guides_"); + if (root->has_meta("_edit_vertical_guides_")) { + Array vguides = root->get_meta("_edit_vertical_guides_"); - undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", Array()); - undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides); + undo_redo->add_do_method(root, "remove_meta", "_edit_vertical_guides_"); + undo_redo->add_undo_method(root, "set_meta", "_edit_vertical_guides_", vguides); } undo_redo->add_undo_method(viewport, "update"); undo_redo->commit_action(); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index f63445dab8..2e41801637 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -707,6 +707,7 @@ void ScriptTextEditor::_bookmark_item_pressed(int p_idx) { _edit_option(bookmarks_menu->get_item_id(p_idx)); } else { code_editor->goto_line(bookmarks_menu->get_item_metadata(p_idx)); + code_editor->get_text_edit()->call_deferred("center_viewport_to_cursor"); //Need to be deferred, because goto uses call_deferred(). } } @@ -856,6 +857,7 @@ void ScriptTextEditor::_breakpoint_item_pressed(int p_idx) { _edit_option(breakpoints_menu->get_item_id(p_idx)); } else { code_editor->goto_line(breakpoints_menu->get_item_metadata(p_idx)); + code_editor->get_text_edit()->call_deferred("center_viewport_to_cursor"); //Need to be deferred, because goto uses call_deferred(). } } @@ -1307,6 +1309,7 @@ void ScriptTextEditor::_edit_option(int p_op) { if (bline > line) { tx->unfold_line(bline); tx->cursor_set_line(bline); + tx->center_viewport_to_cursor(); return; } } @@ -1332,6 +1335,7 @@ void ScriptTextEditor::_edit_option(int p_op) { if (bline < line) { tx->unfold_line(bline); tx->cursor_set_line(bline); + tx->center_viewport_to_cursor(); return; } } diff --git a/editor/plugins/skeleton_editor_plugin.cpp b/editor/plugins/skeleton_editor_plugin.cpp index cd360d4caf..1adf0be108 100644 --- a/editor/plugins/skeleton_editor_plugin.cpp +++ b/editor/plugins/skeleton_editor_plugin.cpp @@ -65,7 +65,6 @@ void SkeletonEditor::create_physical_skeleton() { for (int bone_id = 0; bc > bone_id; ++bone_id) { const int parent = skeleton->get_bone_parent(bone_id); - const int parent_parent = skeleton->get_bone_parent(parent); if (parent < 0) { @@ -73,6 +72,8 @@ void SkeletonEditor::create_physical_skeleton() { } else { + const int parent_parent = skeleton->get_bone_parent(parent); + bones_infos.write[bone_id].relative_rest = bones_infos[parent].relative_rest * skeleton->get_bone_rest(bone_id); /// create physical bone on parent diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index ab62a59be1..d3bab64ccf 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -2466,9 +2466,9 @@ ProjectManager::ProjectManager() { sort_label->set_text(TTR("Sort:")); sort_filters->add_child(sort_label); Vector<String> sort_filter_titles; - sort_filter_titles.push_back("Name"); - sort_filter_titles.push_back("Path"); - sort_filter_titles.push_back("Last Modified"); + sort_filter_titles.push_back(TTR("Name")); + sort_filter_titles.push_back(TTR("Path")); + sort_filter_titles.push_back(TTR("Last Modified")); project_order_filter = memnew(ProjectListFilter); project_order_filter->add_filter_option(); project_order_filter->_setup_filters(sort_filter_titles); @@ -2696,7 +2696,7 @@ void ProjectListFilter::_setup_filters(Vector<String> options) { filter_option->clear(); for (int i = 0; i < options.size(); i++) - filter_option->add_item(TTR(options[i])); + filter_option->add_item(options[i]); } void ProjectListFilter::_search_text_changed(const String &p_newtext) { diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index 8e7aac896a..f854af0c8d 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -846,7 +846,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da time_vals.push_back(err[2]); time_vals.push_back(err[3]); bool e; - String time = String("%d:%02d:%02d:%04d").sprintf(time_vals, &e); + String time = String("%d:%02d:%02d.%03d").sprintf(time_vals, &e); // Rest of the error data. String method = err[4]; diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp index cfd9ec19d2..fd9e44cd5f 100644 --- a/editor/spatial_editor_gizmos.cpp +++ b/editor/spatial_editor_gizmos.cpp @@ -202,6 +202,9 @@ void EditorSpatialGizmo::add_mesh(const Ref<ArrayMesh> &p_mesh, bool p_billboard } void EditorSpatialGizmo::add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material, bool p_billboard) { + if (p_lines.empty()) { + return; + } ERR_FAIL_COND(!spatial_node); Instance ins; @@ -4190,8 +4193,19 @@ void JointSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->clear(); - const Spatial *node_body_a = Object::cast_to<Spatial>(joint->get_node(joint->get_node_a())); - const Spatial *node_body_b = Object::cast_to<Spatial>(joint->get_node(joint->get_node_b())); + Spatial *node_body_a = NULL; + if (!joint->get_node_a().is_empty()) { + node_body_a = Object::cast_to<Spatial>(joint->get_node(joint->get_node_a())); + } + + Spatial *node_body_b = NULL; + if (!joint->get_node_b().is_empty()) { + node_body_b = Object::cast_to<Spatial>(joint->get_node(joint->get_node_b())); + } + + if (!node_body_a && !node_body_b) { + return; + } Ref<Material> common_material = get_material("joint_material", p_gizmo); Ref<Material> body_a_material = get_material("joint_body_a_material", p_gizmo); diff --git a/editor/translations/af.po b/editor/translations/af.po index bbcaf092e7..329d165510 100644 --- a/editor/translations/af.po +++ b/editor/translations/af.po @@ -1009,7 +1009,7 @@ msgid "Resource" msgstr "Hulpbron" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Pad" @@ -1500,7 +1500,8 @@ msgid "Node Name:" msgstr "Nodus Naam:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Naam" @@ -9500,6 +9501,10 @@ msgid "Projects" msgstr "Projek Stigters" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/ar.po b/editor/translations/ar.po index 6be373b1f1..9ffb777a0f 100644 --- a/editor/translations/ar.po +++ b/editor/translations/ar.po @@ -1007,7 +1007,7 @@ msgid "Resource" msgstr "مورد" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "المسار" @@ -1488,7 +1488,8 @@ msgid "Node Name:" msgstr "إسم العقدة:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "الأسم" @@ -9721,6 +9722,10 @@ msgid "Projects" msgstr "مشروع" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/bg.po b/editor/translations/bg.po index 9f82d5e72d..da370687cb 100644 --- a/editor/translations/bg.po +++ b/editor/translations/bg.po @@ -990,7 +990,7 @@ msgid "Resource" msgstr "" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "" @@ -1461,7 +1461,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9577,6 +9578,10 @@ msgid "Projects" msgstr "Проект" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "Сканиране" diff --git a/editor/translations/bn.po b/editor/translations/bn.po index da5e8b41ac..fda8528844 100644 --- a/editor/translations/bn.po +++ b/editor/translations/bn.po @@ -1035,7 +1035,7 @@ msgid "Resource" msgstr "রিসোর্স" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "পথ" @@ -1529,7 +1529,8 @@ msgid "Node Name:" msgstr "নোডের নাম:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "নাম" @@ -10083,6 +10084,10 @@ msgid "Projects" msgstr "নতুন প্রকল্প" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "স্ক্যান" diff --git a/editor/translations/ca.po b/editor/translations/ca.po index 4740b9ac89..db3074ef51 100644 --- a/editor/translations/ca.po +++ b/editor/translations/ca.po @@ -978,7 +978,7 @@ msgid "Resource" msgstr "Recurs" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Camí" @@ -1461,7 +1461,8 @@ msgid "Node Name:" msgstr "Nom del node:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Nom" @@ -9693,6 +9694,10 @@ msgid "Projects" msgstr "Projecte" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "Explora" diff --git a/editor/translations/cs.po b/editor/translations/cs.po index d359c22f28..dfe9b3b4e9 100644 --- a/editor/translations/cs.po +++ b/editor/translations/cs.po @@ -987,7 +987,7 @@ msgid "Resource" msgstr "Zdroj" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Cesta" @@ -1472,7 +1472,8 @@ msgid "Node Name:" msgstr "Název uzlu:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Název" @@ -9597,6 +9598,10 @@ msgid "Projects" msgstr "Projekt" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "Skenovat" diff --git a/editor/translations/da.po b/editor/translations/da.po index cd37bbc5f9..8c28f898aa 100644 --- a/editor/translations/da.po +++ b/editor/translations/da.po @@ -1014,7 +1014,7 @@ msgid "Resource" msgstr "Ressource" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Sti" @@ -1501,7 +1501,8 @@ msgid "Node Name:" msgstr "Node Navn:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Navn" @@ -9692,6 +9693,10 @@ msgid "Projects" msgstr "Projekt" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/de.po b/editor/translations/de.po index ab157ee779..76dc2130bc 100644 --- a/editor/translations/de.po +++ b/editor/translations/de.po @@ -1015,7 +1015,7 @@ msgid "Resource" msgstr "Ressource" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Pfad" @@ -1491,7 +1491,8 @@ msgid "Node Name:" msgstr "Node-Name:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Name" @@ -9562,6 +9563,11 @@ msgid "Projects" msgstr "Projekte" #: editor/project_manager.cpp +#, fuzzy +msgid "Last Modified" +msgstr "Bearbeitet" + +#: editor/project_manager.cpp msgid "Scan" msgstr "Scannen" diff --git a/editor/translations/de_CH.po b/editor/translations/de_CH.po index 5b8d7da474..1ad8fb046f 100644 --- a/editor/translations/de_CH.po +++ b/editor/translations/de_CH.po @@ -984,7 +984,7 @@ msgid "Resource" msgstr "" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "" @@ -1459,7 +1459,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9527,6 +9528,10 @@ msgid "Projects" msgstr "Projektname:" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/editor.pot b/editor/translations/editor.pot index d2a8b188f4..34ff822dc4 100644 --- a/editor/translations/editor.pot +++ b/editor/translations/editor.pot @@ -935,7 +935,7 @@ msgid "Resource" msgstr "" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "" @@ -1400,7 +1400,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9092,6 +9093,10 @@ msgid "Projects" msgstr "" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/el.po b/editor/translations/el.po index 7aea9126c6..969f63fbd1 100644 --- a/editor/translations/el.po +++ b/editor/translations/el.po @@ -982,7 +982,7 @@ msgid "Resource" msgstr "Πόρος" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Διαδρομή" @@ -1457,7 +1457,8 @@ msgid "Node Name:" msgstr "Όνομα κόμβου:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Όνομα" @@ -9593,6 +9594,10 @@ msgid "Projects" msgstr "Έργο" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "Σάρωση" diff --git a/editor/translations/eo.po b/editor/translations/eo.po index 13b053c4f8..8ce8f7c298 100644 --- a/editor/translations/eo.po +++ b/editor/translations/eo.po @@ -971,7 +971,7 @@ msgid "Resource" msgstr "Rimedo" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "dosierindiko" @@ -1436,7 +1436,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Nomo" @@ -9217,6 +9218,11 @@ msgid "Projects" msgstr "Projektoj" #: editor/project_manager.cpp +#, fuzzy +msgid "Last Modified" +msgstr "Modifita" + +#: editor/project_manager.cpp msgid "Scan" msgstr "Esplori" diff --git a/editor/translations/es.po b/editor/translations/es.po index a520f0c46e..0c04cb5fff 100644 --- a/editor/translations/es.po +++ b/editor/translations/es.po @@ -1013,7 +1013,7 @@ msgid "Resource" msgstr "Recursos" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Ruta" @@ -1486,7 +1486,8 @@ msgid "Node Name:" msgstr "Nombre del Nodo:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Nombre" @@ -9549,6 +9550,11 @@ msgid "Projects" msgstr "Proyectos" #: editor/project_manager.cpp +#, fuzzy +msgid "Last Modified" +msgstr "Modificado/s" + +#: editor/project_manager.cpp msgid "Scan" msgstr "Escanear" diff --git a/editor/translations/es_AR.po b/editor/translations/es_AR.po index 0bf176e0af..eea6a6da6b 100644 --- a/editor/translations/es_AR.po +++ b/editor/translations/es_AR.po @@ -982,7 +982,7 @@ msgid "Resource" msgstr "Recursos" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Ruta" @@ -1455,7 +1455,8 @@ msgid "Node Name:" msgstr "Nombre de Nodo:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Nombre" @@ -9514,6 +9515,11 @@ msgid "Projects" msgstr "Proyectos" #: editor/project_manager.cpp +#, fuzzy +msgid "Last Modified" +msgstr "Modificado/s" + +#: editor/project_manager.cpp msgid "Scan" msgstr "Examinar" diff --git a/editor/translations/et.po b/editor/translations/et.po index 82bf543b18..05e6e4fb73 100644 --- a/editor/translations/et.po +++ b/editor/translations/et.po @@ -943,7 +943,7 @@ msgid "Resource" msgstr "" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "" @@ -1408,7 +1408,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9114,6 +9115,10 @@ msgid "Projects" msgstr "" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/eu.po b/editor/translations/eu.po index a545199e07..af877a08a2 100644 --- a/editor/translations/eu.po +++ b/editor/translations/eu.po @@ -3,18 +3,19 @@ # Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) # This file is distributed under the same license as the Godot source code. # Julen Irazoki <rktzbkr.julen@gmail.com>, 2019. +# Osoitz <oelkoro@gmail.com>, 2019. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2019-08-15 10:23+0000\n" -"Last-Translator: Julen Irazoki <rktzbkr.julen@gmail.com>\n" +"PO-Revision-Date: 2019-12-03 14:05+0000\n" +"Last-Translator: Osoitz <oelkoro@gmail.com>\n" "Language-Team: Basque <https://hosted.weblate.org/projects/godot-engine/" "godot/eu/>\n" "Language: eu\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 3.8\n" +"X-Generator: Weblate 3.10-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -25,8 +26,7 @@ msgstr "" #: modules/mono/glue/gd_glue.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp msgid "Not enough bytes for decoding bytes, or invalid format." -msgstr "" -"Ez daude byte nahikoa byte-ak dekodetzeko, edota formatua ez da zuzena." +msgstr "Ez daude byte nahikoa byteak deskodetzeko, edo formatua ez da zuzena." #: core/math/expression.cpp msgid "Invalid input %i (not passed) in expression" @@ -940,7 +940,7 @@ msgid "Resource" msgstr "" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "" @@ -1405,7 +1405,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9097,6 +9098,10 @@ msgid "Projects" msgstr "" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/fa.po b/editor/translations/fa.po index 6ec85e861e..2376b0ac59 100644 --- a/editor/translations/fa.po +++ b/editor/translations/fa.po @@ -1009,7 +1009,7 @@ msgid "Resource" msgstr "منبع" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "مسیر" @@ -1490,7 +1490,8 @@ msgid "Node Name:" msgstr "نام گره:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9644,6 +9645,10 @@ msgid "Projects" msgstr "پروژه" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "پویش" diff --git a/editor/translations/fi.po b/editor/translations/fi.po index 517733d566..dd1d867ae2 100644 --- a/editor/translations/fi.po +++ b/editor/translations/fi.po @@ -967,7 +967,7 @@ msgid "Resource" msgstr "Resurssi" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Polku" @@ -1442,7 +1442,8 @@ msgid "Node Name:" msgstr "Solmun nimi:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Nimi" @@ -9462,6 +9463,11 @@ msgid "Projects" msgstr "Projektit" #: editor/project_manager.cpp +#, fuzzy +msgid "Last Modified" +msgstr "Muutettu" + +#: editor/project_manager.cpp msgid "Scan" msgstr "Tutki" diff --git a/editor/translations/fil.po b/editor/translations/fil.po index 6c9950261b..3568aed2ea 100644 --- a/editor/translations/fil.po +++ b/editor/translations/fil.po @@ -947,7 +947,7 @@ msgid "Resource" msgstr "" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "" @@ -1412,7 +1412,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9113,6 +9114,10 @@ msgid "Projects" msgstr "" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/fr.po b/editor/translations/fr.po index 423452a065..23b73c25b0 100644 --- a/editor/translations/fr.po +++ b/editor/translations/fr.po @@ -68,12 +68,13 @@ # Xavier Sellier <contact@binogure-studio.com>, 2019. # Sofiane <Sofiane-77@caramail.fr>, 2019. # Camille Mohr-Daurat <pouleyketchoup@gmail.com>, 2019. +# Pierre Stempin <pierre.stempin@gmail.com>, 2019. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2019-11-29 14:49+0000\n" -"Last-Translator: Camille Mohr-Daurat <pouleyketchoup@gmail.com>\n" +"PO-Revision-Date: 2019-12-03 14:05+0000\n" +"Last-Translator: Pierre Stempin <pierre.stempin@gmail.com>\n" "Language-Team: French <https://hosted.weblate.org/projects/godot-engine/" "godot/fr/>\n" "Language: fr\n" @@ -1040,7 +1041,7 @@ msgid "Resource" msgstr "Ressource" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Chemin" @@ -1515,7 +1516,8 @@ msgid "Node Name:" msgstr "Nom de nœud :" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Nom" @@ -6298,7 +6300,7 @@ msgstr "Déplacer de points" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Ctrl: Rotate" -msgstr "Contrôle : Tourner" +msgstr "Ctrl : Tourner" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Shift: Move All" @@ -9051,7 +9053,6 @@ msgstr "" "et de la direction de la caméra (transmettez-lui les entrées associées)." #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "" "Custom Godot Shader Language expression, which is placed on top of the " "resulted shader. You can place various function definitions inside and call " @@ -9608,6 +9609,11 @@ msgid "Projects" msgstr "Projets" #: editor/project_manager.cpp +#, fuzzy +msgid "Last Modified" +msgstr "Modifié" + +#: editor/project_manager.cpp msgid "Scan" msgstr "Scanner" @@ -11436,7 +11442,6 @@ msgstr "" "fonctions." #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Select at least one node with sequence port." msgstr "Sélectionnez au moins un nœud avec un port de séquence." diff --git a/editor/translations/ga.po b/editor/translations/ga.po index 0994c769e1..8b96d258ad 100644 --- a/editor/translations/ga.po +++ b/editor/translations/ga.po @@ -941,7 +941,7 @@ msgid "Resource" msgstr "Acmhainn" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Cosán" @@ -1406,7 +1406,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9107,6 +9108,10 @@ msgid "Projects" msgstr "" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/he.po b/editor/translations/he.po index b438d8656d..db308bff70 100644 --- a/editor/translations/he.po +++ b/editor/translations/he.po @@ -1006,7 +1006,7 @@ msgid "Resource" msgstr "משאב" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "נתיב" @@ -1483,7 +1483,8 @@ msgid "Node Name:" msgstr "שם המפרק:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "שם" @@ -9610,6 +9611,10 @@ msgid "Projects" msgstr "מיזם" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/hi.po b/editor/translations/hi.po index 5ea73e6e98..267e705a88 100644 --- a/editor/translations/hi.po +++ b/editor/translations/hi.po @@ -1000,7 +1000,7 @@ msgid "Resource" msgstr "संसाधन" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "पथ" @@ -1489,7 +1489,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9357,6 +9358,10 @@ msgid "Projects" msgstr "परियोजना के संस्थापक" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/hr.po b/editor/translations/hr.po index 5467aa1523..33566267a1 100644 --- a/editor/translations/hr.po +++ b/editor/translations/hr.po @@ -952,7 +952,7 @@ msgid "Resource" msgstr "Resurs" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "" @@ -1420,7 +1420,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9138,6 +9139,10 @@ msgid "Projects" msgstr "" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/hu.po b/editor/translations/hu.po index 0f20323033..244d3c903e 100644 --- a/editor/translations/hu.po +++ b/editor/translations/hu.po @@ -1019,7 +1019,7 @@ msgid "Resource" msgstr "Forrás" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Útvonal" @@ -1504,7 +1504,8 @@ msgid "Node Name:" msgstr "Node neve:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Név" @@ -9802,6 +9803,10 @@ msgid "Projects" msgstr "Projekt" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/id.po b/editor/translations/id.po index cf2c3bb271..68edb05284 100644 --- a/editor/translations/id.po +++ b/editor/translations/id.po @@ -987,7 +987,7 @@ msgid "Resource" msgstr "Resource" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Path" @@ -1459,7 +1459,8 @@ msgid "Node Name:" msgstr "Nama Node:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Nama" @@ -9500,6 +9501,10 @@ msgid "Projects" msgstr "Proyek" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "Pindai" diff --git a/editor/translations/is.po b/editor/translations/is.po index 6f06c5a142..50e5bfac37 100644 --- a/editor/translations/is.po +++ b/editor/translations/is.po @@ -974,7 +974,7 @@ msgid "Resource" msgstr "" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "" @@ -1440,7 +1440,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9211,6 +9212,10 @@ msgid "Projects" msgstr "Verkefna Stjóri" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/it.po b/editor/translations/it.po index 642723f8bb..77b9437753 100644 --- a/editor/translations/it.po +++ b/editor/translations/it.po @@ -1005,7 +1005,7 @@ msgid "Resource" msgstr "Risorsa" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Percorso" @@ -1479,7 +1479,8 @@ msgid "Node Name:" msgstr "Nome nodo:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Nome" @@ -9560,6 +9561,11 @@ msgid "Projects" msgstr "Progetti" #: editor/project_manager.cpp +#, fuzzy +msgid "Last Modified" +msgstr "Modificato" + +#: editor/project_manager.cpp msgid "Scan" msgstr "Esamina" diff --git a/editor/translations/ja.po b/editor/translations/ja.po index de6d6822ca..a5697f71d9 100644 --- a/editor/translations/ja.po +++ b/editor/translations/ja.po @@ -993,7 +993,7 @@ msgid "Resource" msgstr "リソース" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "パス" @@ -1465,7 +1465,8 @@ msgid "Node Name:" msgstr "ノード名:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "名前" @@ -9517,6 +9518,11 @@ msgid "Projects" msgstr "プロジェクト" #: editor/project_manager.cpp +#, fuzzy +msgid "Last Modified" +msgstr "変更された箇所" + +#: editor/project_manager.cpp msgid "Scan" msgstr "スキャン" diff --git a/editor/translations/ka.po b/editor/translations/ka.po index 839ad533f5..d4710402f2 100644 --- a/editor/translations/ka.po +++ b/editor/translations/ka.po @@ -1012,7 +1012,7 @@ msgid "Resource" msgstr "რესურსი" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "გზა" @@ -1492,7 +1492,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9389,6 +9390,10 @@ msgid "Projects" msgstr "პროექტის დამფუძნებლები" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/ko.po b/editor/translations/ko.po index 63fd0fe16c..3aac1a2e39 100644 --- a/editor/translations/ko.po +++ b/editor/translations/ko.po @@ -974,7 +974,7 @@ msgid "Resource" msgstr "리소스" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "경로" @@ -1444,7 +1444,8 @@ msgid "Node Name:" msgstr "노드 이름:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "이름" @@ -9389,6 +9390,11 @@ msgid "Projects" msgstr "프로젝트" #: editor/project_manager.cpp +#, fuzzy +msgid "Last Modified" +msgstr "수정됨" + +#: editor/project_manager.cpp msgid "Scan" msgstr "스캔" diff --git a/editor/translations/lt.po b/editor/translations/lt.po index 681bae9d5a..5971331785 100644 --- a/editor/translations/lt.po +++ b/editor/translations/lt.po @@ -989,7 +989,7 @@ msgid "Resource" msgstr "" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "" @@ -1455,7 +1455,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9380,6 +9381,10 @@ msgid "Projects" msgstr "" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/lv.po b/editor/translations/lv.po index a0b68a3a64..97c80f9a22 100644 --- a/editor/translations/lv.po +++ b/editor/translations/lv.po @@ -976,7 +976,7 @@ msgid "Resource" msgstr "Resurs" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "" @@ -1464,7 +1464,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Nosaukums" @@ -9346,6 +9347,10 @@ msgid "Projects" msgstr "Projekta Dibinātāji" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/mi.po b/editor/translations/mi.po index dbd85cdd3a..693a0f1535 100644 --- a/editor/translations/mi.po +++ b/editor/translations/mi.po @@ -933,7 +933,7 @@ msgid "Resource" msgstr "" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "" @@ -1398,7 +1398,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9090,6 +9091,10 @@ msgid "Projects" msgstr "" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/ml.po b/editor/translations/ml.po index 255a961ea7..0ea1566617 100644 --- a/editor/translations/ml.po +++ b/editor/translations/ml.po @@ -943,7 +943,7 @@ msgid "Resource" msgstr "" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "" @@ -1408,7 +1408,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9103,6 +9104,10 @@ msgid "Projects" msgstr "" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/ms.po b/editor/translations/ms.po index 7ff31a456c..cef1d6dcc0 100644 --- a/editor/translations/ms.po +++ b/editor/translations/ms.po @@ -961,7 +961,7 @@ msgid "Resource" msgstr "" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "" @@ -1426,7 +1426,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9159,6 +9160,10 @@ msgid "Projects" msgstr "" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/nb.po b/editor/translations/nb.po index b7422a2f92..59a2d5553d 100644 --- a/editor/translations/nb.po +++ b/editor/translations/nb.po @@ -1027,7 +1027,7 @@ msgid "Resource" msgstr "Ressurs" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Bane" @@ -1518,7 +1518,8 @@ msgid "Node Name:" msgstr "Nodenavn:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Navn" @@ -9891,6 +9892,10 @@ msgid "Projects" msgstr "Prosjekt" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "Skann" diff --git a/editor/translations/nl.po b/editor/translations/nl.po index 10d32da522..3f5fb5908a 100644 --- a/editor/translations/nl.po +++ b/editor/translations/nl.po @@ -1007,7 +1007,7 @@ msgid "Resource" msgstr "Bron" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Pad" @@ -1481,7 +1481,8 @@ msgid "Node Name:" msgstr "Node Naam:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Naam" @@ -9777,6 +9778,10 @@ msgid "Projects" msgstr "Project" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "Scannen" diff --git a/editor/translations/or.po b/editor/translations/or.po index 6b52bb709a..9585062994 100644 --- a/editor/translations/or.po +++ b/editor/translations/or.po @@ -939,7 +939,7 @@ msgid "Resource" msgstr "" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "" @@ -1404,7 +1404,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9096,6 +9097,10 @@ msgid "Projects" msgstr "" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/pl.po b/editor/translations/pl.po index fc8ae9f5dc..43b4580dd8 100644 --- a/editor/translations/pl.po +++ b/editor/translations/pl.po @@ -1002,7 +1002,7 @@ msgid "Resource" msgstr "Zasoby" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Ścieżka" @@ -1473,7 +1473,8 @@ msgid "Node Name:" msgstr "Nazwa węzła:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Nazwa" @@ -9498,6 +9499,11 @@ msgid "Projects" msgstr "Projekty" #: editor/project_manager.cpp +#, fuzzy +msgid "Last Modified" +msgstr "Zmodyfikowany" + +#: editor/project_manager.cpp msgid "Scan" msgstr "Skanuj" diff --git a/editor/translations/pr.po b/editor/translations/pr.po index f20178f8bb..fc619b3da7 100644 --- a/editor/translations/pr.po +++ b/editor/translations/pr.po @@ -981,7 +981,7 @@ msgid "Resource" msgstr "" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "" @@ -1451,7 +1451,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9400,6 +9401,10 @@ msgid "Projects" msgstr "Rename Function" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/pt_BR.po b/editor/translations/pt_BR.po index 88953ef6e5..8ec43fd0e0 100644 --- a/editor/translations/pt_BR.po +++ b/editor/translations/pt_BR.po @@ -76,7 +76,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: 2016-05-30\n" -"PO-Revision-Date: 2019-11-20 14:07+0000\n" +"PO-Revision-Date: 2019-12-03 14:05+0000\n" "Last-Translator: Joaquim Ferreira <joaquimferreira1996@bol.com.br>\n" "Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/" "godot-engine/godot/pt_BR/>\n" @@ -1037,7 +1037,7 @@ msgid "Resource" msgstr "Recurso" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Caminho" @@ -1509,7 +1509,8 @@ msgid "Node Name:" msgstr "Nome do nó:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Nome" @@ -2130,7 +2131,7 @@ msgstr "Nó" #: editor/editor_network_profiler.cpp msgid "Incoming RPC" -msgstr "Incoming RPC" +msgstr "RPC recebido" #: editor/editor_network_profiler.cpp msgid "Incoming RSET" @@ -2952,7 +2953,7 @@ msgstr "Tocar" #: editor/editor_node.cpp msgid "Pause the scene execution for debugging." -msgstr "" +msgstr "Pausar a execução da cena para depuração." #: editor/editor_node.cpp msgid "Pause Scene" @@ -3043,6 +3044,14 @@ msgid "" "the \"Use Custom Build\" option should be enabled in the Android export " "preset." msgstr "" +"Isso irá configurar seu projeto para compilações customizadas do Android " +"instalando o modelo de origem para \"res://android/build\".\n" +"Em seguida, você pode aplicar modificações e compilar seu próprio APK " +"customizado na exportação (Adicionando módulos, alterando o AndroidManifest." +"xml, etc.).\n" +"Note que para fazer uma compilação customizada, em vez de usar APKs pre-" +"compilados, a opção \"Usar compilação customizada\" deve estar ativa nas " +"predefinições de exportação do Android." #: editor/editor_node.cpp #, fuzzy @@ -4390,9 +4399,8 @@ msgid "Audio Clips" msgstr "Clipes de Áudio:" #: editor/plugins/animation_blend_tree_editor_plugin.cpp -#, fuzzy msgid "Functions" -msgstr "Funções:" +msgstr "Funções" #: editor/plugins/animation_blend_tree_editor_plugin.cpp #: editor/plugins/animation_state_machine_editor.cpp @@ -5077,7 +5085,7 @@ msgstr "Passo de grade:" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Primary Line Every:" -msgstr "" +msgstr "Linha Primária a Cada:" #: editor/plugins/canvas_item_editor_plugin.cpp #, fuzzy @@ -5188,6 +5196,8 @@ msgid "" "Game Camera Override\n" "Overrides game camera with editor viewport camera." msgstr "" +"Substituir Câmera do Jogo\n" +"Substitui a câmera do jogo com a câmera de visualização do editor." #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -5195,6 +5205,8 @@ msgid "" "Game Camera Override\n" "No game instance running." msgstr "" +"Substituir Câmera do Jogo\n" +"Nenhuma instância de jogo em execução." #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -7810,7 +7822,7 @@ msgstr "Filtrar Arquivos..." #: editor/plugins/tile_map_editor_plugin.cpp msgid "Give a TileSet resource to this TileMap to use its tiles." -msgstr "" +msgstr "Atribua um recurso TileSet a este TileMap para usar seus tiles." #: editor/plugins/tile_map_editor_plugin.cpp msgid "Paint Tile" @@ -7948,6 +7960,8 @@ msgstr "Exibir nomes de mosaico (segure a tecla Alt)" msgid "" "Add or select a texture on the left panel to edit the tiles bound to it." msgstr "" +"Adicione ou selecione uma textura no painel esquerdo para editar os tiles " +"vinculados." #: editor/plugins/tile_set_editor_plugin.cpp msgid "Remove selected texture? This will remove all tiles which use it." @@ -8135,7 +8149,7 @@ msgstr "Nenhum nome fornecido" #: editor/plugins/version_control_editor_plugin.cpp msgid "No files added to stage" -msgstr "" +msgstr "Nenhum arquivo adicionado ao palco" #: editor/plugins/version_control_editor_plugin.cpp #, fuzzy @@ -8144,11 +8158,11 @@ msgstr "Comunidade" #: editor/plugins/version_control_editor_plugin.cpp msgid "VCS Addon is not initialized" -msgstr "" +msgstr "Extensão VCS não inicializado" #: editor/plugins/version_control_editor_plugin.cpp msgid "Version Control System" -msgstr "" +msgstr "Sistema de Controle de Versionamento" #: editor/plugins/version_control_editor_plugin.cpp #, fuzzy @@ -8157,7 +8171,7 @@ msgstr "Capitalizar" #: editor/plugins/version_control_editor_plugin.cpp msgid "Staging area" -msgstr "" +msgstr "Área Temporária" #: editor/plugins/version_control_editor_plugin.cpp #, fuzzy @@ -8200,7 +8214,7 @@ msgstr "Salvar Tudo" #: editor/plugins/version_control_editor_plugin.cpp msgid "Add a commit message" -msgstr "" +msgstr "Adicione uma mensagem de confirmação" #: editor/plugins/version_control_editor_plugin.cpp #, fuzzy @@ -8214,7 +8228,7 @@ msgstr "Estado" #: editor/plugins/version_control_editor_plugin.cpp msgid "View file diffs before committing them to the latest version" -msgstr "" +msgstr "Ver aquivos diff antes do commit para a última versão" #: editor/plugins/version_control_editor_plugin.cpp #, fuzzy @@ -8223,7 +8237,7 @@ msgstr "Nenhum arquivo selecionado!" #: editor/plugins/version_control_editor_plugin.cpp msgid "Detect changes in file diff" -msgstr "" +msgstr "Detectar mudanças no arquivo diff" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "(GLES3 only)" @@ -8761,14 +8775,12 @@ msgid "Multiplies scalar by scalar." msgstr "Multiplica escalar por escalar." #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Returns the remainder of the two scalars." -msgstr "Retorna o resto de dois escalares." +msgstr "Retorna o resto dos dois escalares." #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Subtracts scalar from scalar." -msgstr "Subtrai escalar de escalar." +msgstr "Subtrai o escalar do escalar." #: editor/plugins/visual_shader_editor_plugin.cpp #, fuzzy @@ -8781,9 +8793,8 @@ msgid "Scalar uniform." msgstr "Alterar Uniforme Escalar" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Perform the cubic texture lookup." -msgstr "Faça a pesquisa da textura cúbica." +msgstr "Execute a pesquisa de textura cúbica." #: editor/plugins/visual_shader_editor_plugin.cpp #, fuzzy @@ -8852,14 +8863,12 @@ msgid "Calculates the transpose of a transform." msgstr "(Somente em GLES3) Calcula a transposta da transform." #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Multiplies transform by transform." -msgstr "Multiplica transform por transform." +msgstr "Multiplica a transformação por transformação." #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Multiplies vector by transform." -msgstr "Multiplica vetor por transform." +msgstr "Multiplica vetor por transformação." #: editor/plugins/visual_shader_editor_plugin.cpp #, fuzzy @@ -9062,50 +9071,64 @@ msgid "" "it later in the Expressions. You can also declare varyings, uniforms and " "constants." msgstr "" +"Expressão customizada da Godot Shader Language, que é colocada em cima do " +"shader resultante. Você pode colocar várias definições de funções dentro e " +"chamá-lo posteriormente nas Expressões. Você também pode declarar variações, " +"uniformes e constantes." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "(Fragment/Light mode only) Scalar derivative function." -msgstr "" +msgstr "(Apenas modo Fragmento/Luz) Função derivada escalar." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "(Fragment/Light mode only) Vector derivative function." -msgstr "" +msgstr "(Apenas modo Fragmento/Luz) Função derivada de vetor." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "" "(Fragment/Light mode only) (Vector) Derivative in 'x' using local " "differencing." msgstr "" +"(Apenas modo Fragmento/Luz) (Vetor) Derivada em 'x' usando diferenciação " +"local." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "" "(Fragment/Light mode only) (Scalar) Derivative in 'x' using local " "differencing." msgstr "" +"(Apenas modo Fragmento/Luz) (Escalar) Derivada em 'x' usando diferenciação " +"local." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "" "(Fragment/Light mode only) (Vector) Derivative in 'y' using local " "differencing." msgstr "" +"(Apenas modo Fragmento/Luz) (Vetor) Derivada em 'y' usando diferenciação " +"local." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "" "(Fragment/Light mode only) (Scalar) Derivative in 'y' using local " "differencing." msgstr "" +"(Apenas modo Fragmento/Luz) (Escalar) Derivada em 'y' usando diferenciação " +"local." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "" "(Fragment/Light mode only) (Vector) Sum of absolute derivative in 'x' and " "'y'." msgstr "" +"(Apenas modo Fragmento/Luz) (Vetor) Soma da derivada absoluta em 'x' e 'y'." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "" "(Fragment/Light mode only) (Scalar) Sum of absolute derivative in 'x' and " "'y'." msgstr "" +"(Apenas modo Fragmento/Luz) (Escalar) Soma da derivada absoluta em 'x' e 'y'." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "VisualShader" @@ -9180,6 +9203,9 @@ msgid "" "If checked, the preset will be available for use in one-click deploy.\n" "Only one preset per platform may be marked as runnable." msgstr "" +"Se marcada, a predefinição estará disponível para uso na implantação em um " +"clique.\n" +"Somente uma predefinição por plataforma pode ser marcada como executável." #: editor/project_export.cpp msgid "Export Path" @@ -9461,7 +9487,7 @@ msgstr "Importar Projeto Existente" #: editor/project_manager.cpp msgid "Error: Project is missing on the filesystem." -msgstr "" +msgstr "Erro: O Projeto está ausente no sistema de arquivos." #: editor/project_manager.cpp msgid "Can't open project at '%s'." @@ -9595,6 +9621,11 @@ msgid "Projects" msgstr "Projeto" #: editor/project_manager.cpp +#, fuzzy +msgid "Last Modified" +msgstr "Modificado" + +#: editor/project_manager.cpp msgid "Scan" msgstr "Escanear" @@ -9950,7 +9981,7 @@ msgstr "Idiomas:" #: editor/project_settings_editor.cpp msgid "AutoLoad" -msgstr "AutoLoad" +msgstr "Carregamento Automático" #: editor/project_settings_editor.cpp msgid "Plugins" @@ -10244,7 +10275,7 @@ msgstr "Deletar Nó(s) de Shader Graph(s)" #: editor/scene_tree_dock.cpp msgid "Delete node \"%s\" and its children?" -msgstr "" +msgstr "Deletar nó \"%s\" e seus filhos?" #: editor/scene_tree_dock.cpp #, fuzzy @@ -10746,9 +10777,8 @@ msgid "Profiler" msgstr "Profilador" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "Network Profiler" -msgstr "Exportar Perfil" +msgstr "Perfis de rede" #: editor/script_editor_debugger.cpp msgid "Monitor" @@ -10951,9 +10981,8 @@ msgid "GDNativeLibrary" msgstr "GDNativeLibrary" #: modules/gdnative/gdnative_library_singleton_editor.cpp -#, fuzzy msgid "Enabled GDNative Singleton" -msgstr "Singleton GDBNative ativado" +msgstr "Singleton GDNative ativado" #: modules/gdnative/gdnative_library_singleton_editor.cpp #, fuzzy @@ -10974,7 +11003,7 @@ msgstr "GDNative" #: modules/gdscript/gdscript_functions.cpp msgid "Expected a string of length 1 (a character)." -msgstr "" +msgstr "Esperado string de comprimento 1 (a caractere)." #: modules/gdscript/gdscript_functions.cpp msgid "Step argument is zero!" @@ -11138,7 +11167,7 @@ msgstr "Métodos de filtragem" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Give a MeshLibrary resource to this GridMap to use its meshes." -msgstr "" +msgstr "Atribua um recurso MeshLibrary a este GridMap para usar seus meshes." #: modules/mono/csharp_script.cpp msgid "Class name can't be a reserved keyword" @@ -11396,6 +11425,7 @@ msgstr "Adicionar Nó de Pré-carregamento" #: modules/visual_script/visual_script_editor.cpp msgid "Can't drop nodes because script '%s' is not used in this scene." msgstr "" +"Não é possível descartar nós porque o script '% s' não é usado nesta cena." #: modules/visual_script/visual_script_editor.cpp msgid "Add Node(s) From Tree" @@ -11406,6 +11436,9 @@ msgid "" "Can't drop properties because script '%s' is not used in this scene.\n" "Drop holding 'Shift' to just copy the signature." msgstr "" +"Não é possível descartar as propriedades porque o script '% s' não é usado " +"nesta cena.\n" +"Solte segurando 'Shift' para copiar apenas a assinatura." #: modules/visual_script/visual_script_editor.cpp msgid "Add Getter Property" @@ -11476,14 +11509,15 @@ msgstr "Não é possível copiar o nó de função." #: modules/visual_script/visual_script_editor.cpp msgid "Can't create function of nodes from nodes of multiple functions." msgstr "" +"Não é possível criar uma função de nós a partir de nós de múltiplas funções." #: modules/visual_script/visual_script_editor.cpp msgid "Select at least one node with sequence port." -msgstr "" +msgstr "Selecione pelo menos um nó com porta de sequência." #: modules/visual_script/visual_script_editor.cpp msgid "Try to only have one sequence input in selection." -msgstr "" +msgstr "Tente ter apenas uma entrada de sequência na seleção." #: modules/visual_script/visual_script_editor.cpp #, fuzzy @@ -11677,10 +11711,14 @@ msgstr "" #: platform/android/export/export.cpp msgid "Custom build requires a valid Android SDK path in Editor Settings." msgstr "" +"Compilação personalizada requer um caminho do Android SDK válido para as " +"Configurações do Editor." #: platform/android/export/export.cpp msgid "Invalid Android SDK path for custom build in Editor Settings." msgstr "" +"Caminho SDK do Android inválido para a compilação personalizada nas " +"Configurações do Editor." #: platform/android/export/export.cpp #, fuzzy @@ -11704,6 +11742,9 @@ msgid "" "Trying to build from a custom built template, but no version info for it " "exists. Please reinstall from the 'Project' menu." msgstr "" +"Tentando compilar a partir de um modelo compilado personalizado, mas nenhuma " +"informação de versão para ele existe. Por favor, reinstale pelo menu " +"'Projeto'." #: platform/android/export/export.cpp msgid "" @@ -11712,6 +11753,10 @@ msgid "" " Godot Version: %s\n" "Please reinstall Android build template from 'Project' menu." msgstr "" +"Diferença de versão da compilação do Android:\n" +" Modelo instalado: %s\n" +" Versão do Godot: %s\n" +"Por favor reinstale o modelo de compilação do Android pelo menu 'Projeto'." #: platform/android/export/export.cpp msgid "Building Android Project (gradle)" @@ -12406,6 +12451,9 @@ msgid "" "The Hint Tooltip won't be displayed as the control's Mouse Filter is set to " "\"Ignore\". To solve this, set the Mouse Filter to \"Stop\" or \"Pass\"." msgstr "" +"A Dica não será exibida quando o controle de Filtro do Mouse estiver " +"definido como \"Ignorar\". Para resolver, defina o Filtro do Mouse como " +"\"Parar\" ou \"Continuar\"." #: scene/gui/dialogs.cpp msgid "Alert!" diff --git a/editor/translations/pt_PT.po b/editor/translations/pt_PT.po index 03976ebf0c..f739893486 100644 --- a/editor/translations/pt_PT.po +++ b/editor/translations/pt_PT.po @@ -979,7 +979,7 @@ msgid "Resource" msgstr "Recurso" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Caminho" @@ -1452,7 +1452,8 @@ msgid "Node Name:" msgstr "Nome do Nó:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Nome" @@ -9467,6 +9468,11 @@ msgid "Projects" msgstr "Projetos" #: editor/project_manager.cpp +#, fuzzy +msgid "Last Modified" +msgstr "Modificado" + +#: editor/project_manager.cpp msgid "Scan" msgstr "Analisar" diff --git a/editor/translations/ro.po b/editor/translations/ro.po index 266f95691e..f16520008f 100644 --- a/editor/translations/ro.po +++ b/editor/translations/ro.po @@ -1012,7 +1012,7 @@ msgid "Resource" msgstr "Resursă" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Cale" @@ -1502,7 +1502,8 @@ msgid "Node Name:" msgstr "Nume Nod:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Nume" @@ -9773,6 +9774,10 @@ msgid "Projects" msgstr "Proiect" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/ru.po b/editor/translations/ru.po index 0f8b7da452..3cfe0f6353 100644 --- a/editor/translations/ru.po +++ b/editor/translations/ru.po @@ -1028,7 +1028,7 @@ msgid "Resource" msgstr "Ресурс" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Путь" @@ -1499,7 +1499,8 @@ msgid "Node Name:" msgstr "Имя Узла:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Название" @@ -9544,6 +9545,11 @@ msgid "Projects" msgstr "Проекты" #: editor/project_manager.cpp +#, fuzzy +msgid "Last Modified" +msgstr "Изменён" + +#: editor/project_manager.cpp msgid "Scan" msgstr "Сканировать" diff --git a/editor/translations/si.po b/editor/translations/si.po index 85973b455c..357ae506ad 100644 --- a/editor/translations/si.po +++ b/editor/translations/si.po @@ -962,7 +962,7 @@ msgid "Resource" msgstr "" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "" @@ -1427,7 +1427,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9162,6 +9163,10 @@ msgid "Projects" msgstr "" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/sk.po b/editor/translations/sk.po index 62811488f9..ec290311e0 100644 --- a/editor/translations/sk.po +++ b/editor/translations/sk.po @@ -985,7 +985,7 @@ msgid "Resource" msgstr "Prostriedok" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Cesta" @@ -1461,7 +1461,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9430,6 +9431,10 @@ msgid "Projects" msgstr "Zakladatelia Projektu" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/sl.po b/editor/translations/sl.po index 238d4da365..ad23f0c63b 100644 --- a/editor/translations/sl.po +++ b/editor/translations/sl.po @@ -1023,7 +1023,7 @@ msgid "Resource" msgstr "Viri" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Pot" @@ -1509,7 +1509,8 @@ msgid "Node Name:" msgstr "Ime Gradnika:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Ime" @@ -9747,6 +9748,10 @@ msgid "Projects" msgstr "Projekt" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "Preglej" diff --git a/editor/translations/sq.po b/editor/translations/sq.po index 49b45241ed..1c78705413 100644 --- a/editor/translations/sq.po +++ b/editor/translations/sq.po @@ -962,7 +962,7 @@ msgid "Resource" msgstr "Resursi" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Rrugë" @@ -1446,7 +1446,8 @@ msgid "Node Name:" msgstr "Emri i Nyjes:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Emri" @@ -9411,6 +9412,10 @@ msgid "Projects" msgstr "Projekti" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/sr_Cyrl.po b/editor/translations/sr_Cyrl.po index e868067d39..24eb88b805 100644 --- a/editor/translations/sr_Cyrl.po +++ b/editor/translations/sr_Cyrl.po @@ -1023,7 +1023,7 @@ msgid "Resource" msgstr "Ресурс" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Пут" @@ -1510,7 +1510,8 @@ msgid "Node Name:" msgstr "Име чвора:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Име" @@ -9866,6 +9867,10 @@ msgid "Projects" msgstr "Пројекат" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/sr_Latn.po b/editor/translations/sr_Latn.po index e4298b2aa5..22b3059a68 100644 --- a/editor/translations/sr_Latn.po +++ b/editor/translations/sr_Latn.po @@ -971,7 +971,7 @@ msgid "Resource" msgstr "" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "" @@ -1436,7 +1436,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9234,6 +9235,10 @@ msgid "Projects" msgstr "" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/sv.po b/editor/translations/sv.po index c1cc6a8a62..02197303ce 100644 --- a/editor/translations/sv.po +++ b/editor/translations/sv.po @@ -1010,7 +1010,7 @@ msgid "Resource" msgstr "Resurs" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Sökväg" @@ -1501,7 +1501,8 @@ msgid "Node Name:" msgstr "Node Namn:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Namn" @@ -9690,6 +9691,10 @@ msgid "Projects" msgstr "Projekt" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "Skanna" diff --git a/editor/translations/ta.po b/editor/translations/ta.po index 5035e886c5..7015199f0c 100644 --- a/editor/translations/ta.po +++ b/editor/translations/ta.po @@ -963,7 +963,7 @@ msgid "Resource" msgstr "" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "" @@ -1428,7 +1428,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9166,6 +9167,10 @@ msgid "Projects" msgstr "" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/te.po b/editor/translations/te.po index 4ad5ae8777..d9136f04b0 100644 --- a/editor/translations/te.po +++ b/editor/translations/te.po @@ -941,7 +941,7 @@ msgid "Resource" msgstr "" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "" @@ -1406,7 +1406,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9099,6 +9100,10 @@ msgid "Projects" msgstr "" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/th.po b/editor/translations/th.po index af1bb53b9e..db9cd3f577 100644 --- a/editor/translations/th.po +++ b/editor/translations/th.po @@ -1025,7 +1025,7 @@ msgid "Resource" msgstr "รีซอร์ส" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "ตำแหน่ง" @@ -1508,7 +1508,8 @@ msgid "Node Name:" msgstr "ชื่อโหนด:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "ชื่อ" @@ -9820,6 +9821,10 @@ msgid "Projects" msgstr "โปรเจกต์" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "สแกน" diff --git a/editor/translations/tr.po b/editor/translations/tr.po index 6ef831b3be..1cbce49f6d 100644 --- a/editor/translations/tr.po +++ b/editor/translations/tr.po @@ -1005,7 +1005,7 @@ msgid "Resource" msgstr "Kaynak" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Yol" @@ -1477,7 +1477,8 @@ msgid "Node Name:" msgstr "Düğüm adı:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "İsim" @@ -9460,6 +9461,11 @@ msgid "Projects" msgstr "Proje" #: editor/project_manager.cpp +#, fuzzy +msgid "Last Modified" +msgstr "Değişti" + +#: editor/project_manager.cpp msgid "Scan" msgstr "Tara" diff --git a/editor/translations/uk.po b/editor/translations/uk.po index 881e8f1911..1b8d883ca1 100644 --- a/editor/translations/uk.po +++ b/editor/translations/uk.po @@ -981,7 +981,7 @@ msgid "Resource" msgstr "Ресурс" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Шлях" @@ -1454,7 +1454,8 @@ msgid "Node Name:" msgstr "Ім'я Вузла:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Назва" @@ -9497,6 +9498,11 @@ msgid "Projects" msgstr "Проєкти" #: editor/project_manager.cpp +#, fuzzy +msgid "Last Modified" +msgstr "Змінено" + +#: editor/project_manager.cpp msgid "Scan" msgstr "Сканувати" diff --git a/editor/translations/ur_PK.po b/editor/translations/ur_PK.po index 74a0013d39..e0c20b597a 100644 --- a/editor/translations/ur_PK.po +++ b/editor/translations/ur_PK.po @@ -959,7 +959,7 @@ msgid "Resource" msgstr "" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "" @@ -1429,7 +1429,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "" @@ -9317,6 +9318,10 @@ msgid "Projects" msgstr ".تمام کا انتخاب" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/vi.po b/editor/translations/vi.po index d92251b862..c20e09409b 100644 --- a/editor/translations/vi.po +++ b/editor/translations/vi.po @@ -978,7 +978,7 @@ msgid "Resource" msgstr "Tài nguyên" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "Đường dẫn" @@ -1452,7 +1452,8 @@ msgid "Node Name:" msgstr "Tên Node:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "Tên" @@ -9419,6 +9420,10 @@ msgid "Projects" msgstr "Dự án" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "Quét" diff --git a/editor/translations/zh_CN.po b/editor/translations/zh_CN.po index 0436963e5a..397f17a1cd 100644 --- a/editor/translations/zh_CN.po +++ b/editor/translations/zh_CN.po @@ -1008,7 +1008,7 @@ msgid "Resource" msgstr "资源" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "路径" @@ -1475,7 +1475,8 @@ msgid "Node Name:" msgstr "节点名称:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "名称" @@ -9327,6 +9328,11 @@ msgid "Projects" msgstr "工程" #: editor/project_manager.cpp +#, fuzzy +msgid "Last Modified" +msgstr "已修改" + +#: editor/project_manager.cpp msgid "Scan" msgstr "扫描" diff --git a/editor/translations/zh_HK.po b/editor/translations/zh_HK.po index c05494212b..59b5a5b7a2 100644 --- a/editor/translations/zh_HK.po +++ b/editor/translations/zh_HK.po @@ -1026,7 +1026,7 @@ msgid "Resource" msgstr "資源" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "路徑" @@ -1532,7 +1532,8 @@ msgid "Node Name:" msgstr "" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "名稱" @@ -9773,6 +9774,10 @@ msgid "Projects" msgstr "專案" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/editor/translations/zh_TW.po b/editor/translations/zh_TW.po index 622e04b34f..5b360169e1 100644 --- a/editor/translations/zh_TW.po +++ b/editor/translations/zh_TW.po @@ -1022,7 +1022,7 @@ msgid "Resource" msgstr "資源" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp -#: editor/project_settings_editor.cpp +#: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" msgstr "路徑" @@ -1523,7 +1523,8 @@ msgid "Node Name:" msgstr "節點名稱:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp -#: editor/editor_profiler.cpp editor/settings_config_dialog.cpp +#: editor/editor_profiler.cpp editor/project_manager.cpp +#: editor/settings_config_dialog.cpp msgid "Name" msgstr "名稱" @@ -9742,6 +9743,10 @@ msgid "Projects" msgstr "專案" #: editor/project_manager.cpp +msgid "Last Modified" +msgstr "" + +#: editor/project_manager.cpp msgid "Scan" msgstr "" diff --git a/main/main.cpp b/main/main.cpp index 22a31d597e..cdaee06135 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -65,6 +65,7 @@ #include "scene/resources/packed_scene.h" #include "servers/arvr_server.h" #include "servers/audio_server.h" +#include "servers/camera_server.h" #include "servers/physics_2d_server.h" #include "servers/physics_server.h" #include "servers/register_server_types.h" @@ -97,6 +98,7 @@ static MessageQueue *message_queue = NULL; // Initialized in setup2() static AudioServer *audio_server = NULL; +static CameraServer *camera_server = NULL; static ARVRServer *arvr_server = NULL; static PhysicsServer *physics_server = NULL; static Physics2DServer *physics_2d_server = NULL; @@ -257,6 +259,8 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print(" --position <X>,<Y> Request window position.\n"); OS::get_singleton()->print(" --low-dpi Force low-DPI mode (macOS and Windows only).\n"); OS::get_singleton()->print(" --no-window Disable window creation (Windows only). Useful together with --script.\n"); + OS::get_singleton()->print(" --enable-vsync-via-compositor When vsync is enabled, vsync via the OS' window compositor (Windows only).\n"); + OS::get_singleton()->print(" --disable-vsync-via-compositor Disable vsync via the OS' window compositor (Windows only).\n"); OS::get_singleton()->print("\n"); #endif @@ -397,6 +401,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph Vector<String> breakpoints; bool use_custom_res = true; bool force_res = false; + bool saw_vsync_via_compositor_override = false; #ifdef TOOLS_ENABLED bool found_project = false; #endif @@ -588,6 +593,14 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph } else if (I->get() == "--no-window") { // disable window creation (Windows only) OS::get_singleton()->set_no_window_mode(true); + } else if (I->get() == "--enable-vsync-via-compositor") { + + video_mode.vsync_via_compositor = true; + saw_vsync_via_compositor_override = true; + } else if (I->get() == "--disable-vsync-via-compositor") { + + video_mode.vsync_via_compositor = false; + saw_vsync_via_compositor_override = true; #endif } else if (I->get() == "--profiling") { // enable profiling @@ -1007,6 +1020,16 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph video_mode.use_vsync = GLOBAL_DEF_RST("display/window/vsync/use_vsync", true); OS::get_singleton()->_use_vsync = video_mode.use_vsync; + if (!saw_vsync_via_compositor_override) { + // If one of the command line options to enable/disable vsync via the + // window compositor ("--enable-vsync-via-compositor" or + // "--disable-vsync-via-compositor") was present then it overrides the + // project setting. + video_mode.vsync_via_compositor = GLOBAL_DEF("display/window/vsync/vsync_via_compositor", false); + } + + OS::get_singleton()->_vsync_via_compositor = video_mode.vsync_via_compositor; + OS::get_singleton()->_allow_layered = GLOBAL_DEF("display/window/per_pixel_transparency/allowed", false); video_mode.layered = GLOBAL_DEF("display/window/per_pixel_transparency/enabled", false); @@ -1318,6 +1341,8 @@ Error Main::setup2(Thread::ID p_main_tid_override) { register_platform_apis(); register_module_types(); + camera_server = CameraServer::create(); + initialize_physics(); register_server_singletons(); @@ -2090,6 +2115,11 @@ void Main::cleanup() { ERR_FAIL_COND(!_start_success); + if (script_debugger) { + // Flush any remaining messages + script_debugger->idle_poll(); + } + ResourceLoader::remove_custom_loaders(); ResourceSaver::remove_custom_savers(); @@ -2137,6 +2167,10 @@ void Main::cleanup() { memdelete(audio_server); } + if (camera_server) { + memdelete(camera_server); + } + OS::get_singleton()->finalize(); finalize_physics(); diff --git a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj index b375293ca6..0b8a508d2f 100644 --- a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj +++ b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj @@ -19,6 +19,7 @@ 1FE926A11FBBF86D00F53A6F /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE9268F1FBBF77F00F53A6F /* CoreAudio.framework */; }; E360193721F32F38009258C1 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E360193621F32F37009258C1 /* CoreVideo.framework */; }; DEADBEEF2F582BE20003B888 /* $binary.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DEADBEEF1F582BE20003B888 /* $binary.a */; }; + $modules_buildfile 1FF8DBB11FBA9DE1009DE660 /* dummy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FF8DBB01FBA9DE1009DE660 /* dummy.cpp */; }; 1FF4C1851F584E3F00A41E41 /* GameKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FF4C1841F584E3F00A41E41 /* GameKit.framework */; }; 1FF4C1871F584E5600A41E41 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FF4C1861F584E5600A41E41 /* StoreKit.framework */; }; @@ -45,6 +46,7 @@ 1FE926951FBBF7C400F53A6F /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; 1FE926961FBBF7D400F53A6F /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; DEADBEEF1F582BE20003B888 /* $binary.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = godot; path = "$binary.a"; sourceTree = "<group>"; }; + $modules_fileref 1FF4C1841F584E3F00A41E41 /* GameKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameKit.framework; path = System/Library/Frameworks/GameKit.framework; sourceTree = SDKROOT; }; 1FF4C1861F584E5600A41E41 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; }; 1FF4C1881F584E7600A41E41 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; @@ -89,6 +91,7 @@ D0BCFE3E18AEBDA2004A7AAE /* GLKit.framework in Frameworks */, D0BCFE3818AEBDA2004A7AAE /* Foundation.framework in Frameworks */, DEADBEEF2F582BE20003B888 /* $binary.a */, + $modules_buildphase $additional_pbx_frameworks_build ); runOnlyForDeploymentPostprocessing = 0; @@ -138,6 +141,7 @@ D0BCFE3D18AEBDA2004A7AAE /* GLKit.framework */, D0BCFE3F18AEBDA2004A7AAE /* OpenGLES.framework */, DEADBEEF1F582BE20003B888 /* $binary.a */, + $modules_buildgrp $additional_pbx_frameworks_refs ); name = Frameworks; @@ -427,6 +431,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.0; LIBRARY_SEARCH_PATHS = ( "$(inherited)", + "$(PROJECT_DIR)", ); PRODUCT_BUNDLE_IDENTIFIER = $identifier; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -452,6 +457,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.0; LIBRARY_SEARCH_PATHS = ( "$(inherited)", + "$(PROJECT_DIR)", ); PRODUCT_BUNDLE_IDENTIFIER = $identifier; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist b/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist index e7c4f8f340..add2f6c084 100644 --- a/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist +++ b/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist @@ -28,6 +28,10 @@ <string>$version</string> <key>LSRequiresIPhoneOS</key> <true/> + <key>LSSupportsOpeningDocumentsInPlace</key> + $docs_in_place + <key>UIFileSharingEnabled</key> + $docs_sharing <key>UIRequiredDeviceCapabilities</key> <array> $required_device_capabilities diff --git a/modules/arkit/SCsub b/modules/arkit/SCsub index b43d936768..e605703a72 100644 --- a/modules/arkit/SCsub +++ b/modules/arkit/SCsub @@ -5,6 +5,8 @@ Import('env_modules') env_arkit = env_modules.Clone() -# Add source files -env_arkit.add_source_files(env.modules_sources, "*.cpp") -env_arkit.add_source_files(env.modules_sources, "*.mm") +# (iOS) Build as separate static library +modules_sources = [] +env_arkit.add_source_files(modules_sources, "*.cpp") +env_arkit.add_source_files(modules_sources, "*.mm") +mod_lib = env_modules.add_library('#bin/libgodot_arkit_module' + env['LIBSUFFIX'], modules_sources)
\ No newline at end of file diff --git a/modules/arkit/arkit_interface.mm b/modules/arkit/arkit_interface.mm index 71642cfc30..3408477458 100644 --- a/modules/arkit/arkit_interface.mm +++ b/modules/arkit/arkit_interface.mm @@ -28,7 +28,6 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "camera_ios.h" #include "core/os/input.h" #include "core/os/os.h" #include "scene/resources/surface_tool.h" diff --git a/modules/camera/SCsub b/modules/camera/SCsub new file mode 100644 index 0000000000..23f031f06e --- /dev/null +++ b/modules/camera/SCsub @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +Import('env') +Import('env_modules') + +env_camera = env_modules.Clone() + +if env["platform"] == "iphone": + # (iOS) Build as separate static library + modules_sources = [] + env_camera.add_source_files(modules_sources, "register_types.cpp") + env_camera.add_source_files(modules_sources, "camera_ios.mm") + mod_lib = env_modules.add_library('#bin/libgodot_camera_module' + env['LIBSUFFIX'], modules_sources) + +elif env["platform"] == "windows": + env_camera.add_source_files(env.modules_sources, "register_types.cpp") + env_camera.add_source_files(env.modules_sources, "camera_win.cpp") + +elif env["platform"] == "osx": + env_camera.add_source_files(env.modules_sources, "register_types.cpp") + env_camera.add_source_files(env.modules_sources, "camera_osx.mm") + diff --git a/platform/iphone/camera_ios.h b/modules/camera/camera_ios.h index ceabdba6a3..ceabdba6a3 100644 --- a/platform/iphone/camera_ios.h +++ b/modules/camera/camera_ios.h diff --git a/platform/iphone/camera_ios.mm b/modules/camera/camera_ios.mm index 5636ed6262..dcf09b28fd 100644 --- a/platform/iphone/camera_ios.mm +++ b/modules/camera/camera_ios.mm @@ -359,7 +359,7 @@ void CameraIOS::update_feeds() { // this way of doing things is deprecated but still works, // rewrite to using AVCaptureDeviceDiscoverySession - AVCaptureDeviceDiscoverySession *session = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:[NSArray arrayWithObjects:AVCaptureDeviceTypeBuiltInTelephotoCamera, AVCaptureDeviceTypeBuiltInDualCamera, AVCaptureDeviceTypeBuiltInTrueDepthCamera, AVCaptureDeviceTypeBuiltInWideAngleCamera] mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified]; + AVCaptureDeviceDiscoverySession *session = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:[NSArray arrayWithObjects:AVCaptureDeviceTypeBuiltInTelephotoCamera, AVCaptureDeviceTypeBuiltInDualCamera, AVCaptureDeviceTypeBuiltInTrueDepthCamera, AVCaptureDeviceTypeBuiltInWideAngleCamera, nil] mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified]; // remove devices that are gone.. for (int i = feeds.size() - 1; i >= 0; i--) { diff --git a/platform/osx/camera_osx.h b/modules/camera/camera_osx.h index 7477d8e647..7477d8e647 100644 --- a/platform/osx/camera_osx.h +++ b/modules/camera/camera_osx.h diff --git a/platform/osx/camera_osx.mm b/modules/camera/camera_osx.mm index 2b0f4906fc..2b0f4906fc 100644 --- a/platform/osx/camera_osx.mm +++ b/modules/camera/camera_osx.mm diff --git a/platform/windows/camera_win.cpp b/modules/camera/camera_win.cpp index 10787d0d0a..10787d0d0a 100644 --- a/platform/windows/camera_win.cpp +++ b/modules/camera/camera_win.cpp diff --git a/platform/windows/camera_win.h b/modules/camera/camera_win.h index 22ce9aa43f..22ce9aa43f 100644 --- a/platform/windows/camera_win.h +++ b/modules/camera/camera_win.h diff --git a/modules/camera/config.py b/modules/camera/config.py new file mode 100644 index 0000000000..d308c04195 --- /dev/null +++ b/modules/camera/config.py @@ -0,0 +1,5 @@ +def can_build(env, platform): + return platform == 'iphone' or platform == 'osx' or platform == 'windows' + +def configure(env): + pass diff --git a/modules/camera/register_types.cpp b/modules/camera/register_types.cpp new file mode 100644 index 0000000000..313df40112 --- /dev/null +++ b/modules/camera/register_types.cpp @@ -0,0 +1,56 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 "register_types.h" + +#if defined(WINDOWS_ENABLED) +#include "camera_win.h" +#endif +#if defined(IPHONE_ENABLED) +#include "camera_ios.h" +#endif +#if defined(OSX_ENABLED) +#include "camera_osx.h" +#endif + +void register_camera_types() { +#if defined(WINDOWS_ENABLED) + CameraServer::make_default<CameraWindows>(); +#endif +#if defined(IPHONE_ENABLED) + CameraServer::make_default<CameraIOS>(); +#endif +#if defined(OSX_ENABLED) + CameraServer::make_default<CameraOSX>(); +#endif +} + +void unregister_camera_types() { +} diff --git a/modules/camera/register_types.h b/modules/camera/register_types.h new file mode 100644 index 0000000000..0ccb0885d0 --- /dev/null +++ b/modules/camera/register_types.h @@ -0,0 +1,32 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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. */ +/*************************************************************************/ + +void register_camera_types(); +void unregister_camera_types(); diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp index 7c313c983f..768b12baea 100644 --- a/modules/gdnative/nativescript/nativescript.cpp +++ b/modules/gdnative/nativescript/nativescript.cpp @@ -119,7 +119,10 @@ String NativeScript::get_class_name() const { void NativeScript::set_library(Ref<GDNativeLibrary> p_library) { if (!library.is_null()) { - WARN_PRINT("library on NativeScript already set. Do nothing."); + WARN_PRINT("Library in NativeScript already set. Do nothing."); + return; + } + if (p_library.is_null()) { return; } library = p_library; diff --git a/modules/gdnative/pluginscript/pluginscript_script.cpp b/modules/gdnative/pluginscript/pluginscript_script.cpp index f7c961d38b..6bb521173f 100644 --- a/modules/gdnative/pluginscript/pluginscript_script.cpp +++ b/modules/gdnative/pluginscript/pluginscript_script.cpp @@ -251,7 +251,19 @@ Error PluginScript::reload(bool p_keep_state) { (godot_string *)&_path, (godot_string *)&_source, (godot_error *)&err); +// Manifest's attributes must be explicitly freed +#define FREE_SCRIPT_MANIFEST(manifest) \ + { \ + godot_string_name_destroy(&manifest.name); \ + godot_string_name_destroy(&manifest.base); \ + godot_dictionary_destroy(&manifest.member_lines); \ + godot_array_destroy(&manifest.methods); \ + godot_array_destroy(&manifest.signals); \ + godot_array_destroy(&manifest.properties); \ + } + if (err) { + FREE_SCRIPT_MANIFEST(manifest); // TODO: GDscript uses `ScriptDebugger` here to jump into the parsing error return err; } @@ -269,6 +281,7 @@ Error PluginScript::reload(bool p_keep_state) { _ref_base_parent = res; } else { String name = *(StringName *)&manifest.name; + FREE_SCRIPT_MANIFEST(manifest); ERR_FAIL_V_MSG(ERR_PARSE_ERROR, _path + ": Script '" + name + "' has an invalid parent '" + *base_name + "'."); } } @@ -317,13 +330,6 @@ Error PluginScript::reload(bool p_keep_state) { _methods_rpc_mode[pi.name] = MultiplayerAPI::RPCMode(int(var)); } } - // Manifest's attributes must be explicitly freed - godot_string_name_destroy(&manifest.name); - godot_string_name_destroy(&manifest.base); - godot_dictionary_destroy(&manifest.member_lines); - godot_array_destroy(&manifest.methods); - godot_array_destroy(&manifest.signals); - godot_array_destroy(&manifest.properties); #ifdef TOOLS_ENABLED /*for (Set<PlaceHolderScriptInstance*>::Element *E=placeholders.front();E;E=E->next()) { @@ -331,7 +337,10 @@ Error PluginScript::reload(bool p_keep_state) { _update_placeholder(E->get()); }*/ #endif + + FREE_SCRIPT_MANIFEST(manifest); return OK; +#undef FREE_SCRIPT_MANIFEST } void PluginScript::get_script_method_list(List<MethodInfo> *r_methods) const { diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index a22d18b970..2a8453116e 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -336,11 +336,12 @@ <description> Rounds [code]s[/code] to the closest smaller integer and returns it. [codeblock] - # a is 2 + # a is 2.0 a = floor(2.99) - # a is -3 + # a is -3.0 a = floor(-2.99) [/codeblock] + [b]Note:[/b] This method returns a float. If you need an integer, you can use [code]int(s)[/code] directly. </description> </method> <method name="fmod"> @@ -502,7 +503,7 @@ <argument index="1" name="b" type="float"> </argument> <description> - Returns True/False whether [code]a[/code] and [code]b[/code] are approximately equal to each other. + Returns [code]true[/code] if [code]a[/code] and [code]b[/code] are approximately equal to each other. </description> </method> <method name="is_inf"> @@ -538,7 +539,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns True/False whether [code]s[/code] is zero or almost zero. + Returns [code]true[/code] if [code]s[/code] is zero or almost zero. </description> </method> <method name="len"> diff --git a/modules/gdscript/doc_classes/GDScript.xml b/modules/gdscript/doc_classes/GDScript.xml index 6f43361914..8e175a7ab8 100644 --- a/modules/gdscript/doc_classes/GDScript.xml +++ b/modules/gdscript/doc_classes/GDScript.xml @@ -4,7 +4,7 @@ A script implemented in the GDScript programming language. </brief_description> <description> - A script implemented in the GDScript programming language. The script exends the functionality of all objects that instance it. + A script implemented in the GDScript programming language. The script extends the functionality of all objects that instance it. [method new] creates a new instance of the script. [method Object.set_script] extends an existing object, if that object's class matches one of the script's base classes. </description> <tutorials> diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 6ef3ab67ae..ef1a282e51 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -3349,7 +3349,12 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { } p_block->statements.push_back(expression); if (!_end_statement()) { - _set_error("Expected end of statement after expression."); + // Attempt to guess a better error message if the user "retypes" a variable + if (tokenizer->get_token() == GDScriptTokenizer::TK_COLON && tokenizer->get_token(1) == GDScriptTokenizer::TK_OP_ASSIGN) { + _set_error("Unexpected ':=', use '=' instead. Expected end of statement after expression."); + } else { + _set_error(String() + "Expected end of statement after expression, got " + tokenizer->get_token_name(tokenizer->get_token()) + " instead"); + } return; } diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml index b762868f2c..3de971db6d 100644 --- a/modules/gridmap/doc_classes/GridMap.xml +++ b/modules/gridmap/doc_classes/GridMap.xml @@ -4,10 +4,10 @@ Node for 3D tile-based maps. </brief_description> <description> - GridMap lets you place meshes on a grid interactively. It works both from the editor and can help you create in-game level editors. - GridMaps use a [MeshLibrary] which contain a list of tiles: meshes with materials plus optional collisions and extra elements. - A GridMap contains a collection of cells. Each grid cell refers to a [MeshLibrary] item. All cells in the map have the same dimensions. - A GridMap is split into a sparse collection of octants for efficient rendering and physics processing. Every octant has the same dimensions and can contain several cells. + GridMap lets you place meshes on a grid interactively. It works both from the editor and from scripts, which can help you create in-game level editors. + GridMaps use a [MeshLibrary] which contains a list of tiles. Each tile is a mesh with materials plus optional collision and navigation shapes. + A GridMap contains a collection of cells. Each grid cell refers to a tile in the [MeshLibrary]. All cells in the map have the same dimensions. + Internally, a GridMap is split into a sparse collection of octants for efficient rendering and physics processing. Every octant has the same dimensions and can contain several cells. </description> <tutorials> <link>https://docs.godotengine.org/en/latest/tutorials/3d/using_gridmaps.html</link> @@ -72,6 +72,7 @@ <argument index="0" name="bit" type="int"> </argument> <description> + Returns an individual bit on the [member collision_layer]. </description> </method> <method name="get_collision_mask_bit" qualifiers="const"> @@ -80,20 +81,21 @@ <argument index="0" name="bit" type="int"> </argument> <description> + Returns an individual bit on the [member collision_mask]. </description> </method> <method name="get_meshes"> <return type="Array"> </return> <description> - Array of [Transform] and [Mesh] references corresponding to the non-empty cells in the grid. The transforms are specified in world space. + Returns an array of [Transform] and [Mesh] references corresponding to the non-empty cells in the grid. The transforms are specified in world space. </description> </method> <method name="get_used_cells" qualifiers="const"> <return type="Array"> </return> <description> - Array of [Vector3] with the non-empty cell coordinates in the grid map. + Returns an array of [Vector3] with the non-empty cell coordinates in the grid map. </description> </method> <method name="make_baked_meshes"> @@ -116,6 +118,7 @@ <argument index="2" name="z" type="int"> </argument> <description> + Returns the position of a grid cell in the GridMap's local coordinate space. </description> </method> <method name="resource_changed"> @@ -140,9 +143,9 @@ <argument index="4" name="orientation" type="int" default="0"> </argument> <description> - Set the mesh index for the cell referenced by its grid-based X, Y and Z coordinates. - A negative item index will clear the cell. - Optionally, the item's orientation can be passed. + Sets the mesh index for the cell referenced by its grid-based X, Y and Z coordinates. + A negative item index such as [constant INVALID_CELL_ITEM] will clear the cell. + Optionally, the item's orientation can be passed. For valid orientation values, see [method Basis.get_orthogonal_index]. </description> </method> <method name="set_clip"> @@ -167,6 +170,7 @@ <argument index="1" name="value" type="bool"> </argument> <description> + Sets an individual bit on the [member collision_layer]. </description> </method> <method name="set_collision_mask_bit"> @@ -177,6 +181,7 @@ <argument index="1" name="value" type="bool"> </argument> <description> + Sets an individual bit on the [member collision_mask]. </description> </method> <method name="world_to_map" qualifiers="const"> @@ -185,6 +190,8 @@ <argument index="0" name="pos" type="Vector3"> </argument> <description> + Returns the coordinates of the grid cell containing the given point. + [code]pos[/code] should be in the GridMap's local coordinate space. </description> </method> </methods> @@ -202,26 +209,30 @@ The size of each octant measured in number of cells. This applies to all three axis. </member> <member name="cell_scale" type="float" setter="set_cell_scale" getter="get_cell_scale" default="1.0"> + The scale of the cell items. + This does not affect the size of the grid cells themselves, only the items in them. This can be used to make cell items overlap their neighbors. </member> <member name="cell_size" type="Vector3" setter="set_cell_size" getter="get_cell_size" default="Vector3( 2, 2, 2 )"> The dimensions of the grid's cells. + This does not affect the size of the meshes. See [member cell_scale]. </member> <member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer" default="1"> + The physics layers this GridMap is in. + GridMaps act as static bodies, meaning they aren't affected by gravity or other forces. They only affect other physics bodies that collide with them. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1"> + The physics layers this GridMap detects collisions in. </member> <member name="mesh_library" type="MeshLibrary" setter="set_mesh_library" getter="get_mesh_library"> The assigned [MeshLibrary]. </member> - <member name="theme" type="MeshLibrary" setter="set_theme" getter="get_theme"> - Deprecated, use [member mesh_library] instead. - </member> </members> <signals> <signal name="cell_size_changed"> <argument index="0" name="cell_size" type="Vector3"> </argument> <description> + Emitted when [member cell_size] changes. </description> </signal> </signals> diff --git a/modules/mono/build_scripts/mono_android_config.xml b/modules/mono/build_scripts/mono_android_config.xml new file mode 100644 index 0000000000..e79670afd2 --- /dev/null +++ b/modules/mono/build_scripts/mono_android_config.xml @@ -0,0 +1,28 @@ +<configuration> + <dllmap wordsize="32" dll="i:cygwin1.dll" target="/system/lib/libc.so" /> + <dllmap wordsize="64" dll="i:cygwin1.dll" target="/system/lib64/libc.so" /> + <dllmap wordsize="32" dll="libc" target="/system/lib/libc.so" /> + <dllmap wordsize="64" dll="libc" target="/system/lib64/libc.so" /> + <dllmap wordsize="32" dll="intl" target="/system/lib/libc.so" /> + <dllmap wordsize="64" dll="intl" target="/system/lib64/libc.so" /> + <dllmap wordsize="32" dll="libintl" target="/system/lib/libc.so" /> + <dllmap wordsize="64" dll="libintl" target="/system/lib64/libc.so" /> + <dllmap dll="MonoPosixHelper" target="libMonoPosixHelper.so" /> + <dllmap dll="System.Native" target="libmono-native.so" /> + <dllmap wordsize="32" dll="i:msvcrt" target="/system/lib/libc.so" /> + <dllmap wordsize="64" dll="i:msvcrt" target="/system/lib64/libc.so" /> + <dllmap wordsize="32" dll="i:msvcrt.dll" target="/system/lib/libc.so" /> + <dllmap wordsize="64" dll="i:msvcrt.dll" target="/system/lib64/libc.so" /> + <dllmap wordsize="32" dll="sqlite" target="/system/lib/libsqlite.so" /> + <dllmap wordsize="64" dll="sqlite" target="/system/lib64/libsqlite.so" /> + <dllmap wordsize="32" dll="sqlite3" target="/system/lib/libsqlite.so" /> + <dllmap wordsize="64" dll="sqlite3" target="/system/lib64/libsqlite.so" /> + <dllmap wordsize="32" dll="liblog" target="/system/lib/liblog.so" /> + <dllmap wordsize="64" dll="liblog" target="/system/lib64/liblog.so" /> + <dllmap dll="i:kernel32.dll"> + <dllentry dll="__Internal" name="CopyMemory" target="mono_win32_compat_CopyMemory"/> + <dllentry dll="__Internal" name="FillMemory" target="mono_win32_compat_FillMemory"/> + <dllentry dll="__Internal" name="MoveMemory" target="mono_win32_compat_MoveMemory"/> + <dllentry dll="__Internal" name="ZeroMemory" target="mono_win32_compat_ZeroMemory"/> + </dllmap> +</configuration> diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py index c09690ba6d..89d56def7d 100644 --- a/modules/mono/build_scripts/mono_configure.py +++ b/modules/mono/build_scripts/mono_configure.py @@ -206,6 +206,8 @@ def configure(env, env_mono): env_mono.Append(CPPDEFINES=['_REENTRANT']) if mono_static: + env.Append(LINKFLAGS=['-rdynamic']) + mono_lib_file = os.path.join(mono_lib_path, 'lib' + mono_lib + '.a') if is_apple: @@ -281,8 +283,6 @@ def configure(env, env_mono): libs_output_dir = get_android_out_dir(env) if is_android else '#bin' copy_file(mono_lib_path, libs_output_dir, 'lib' + mono_so_name + sharedlib_ext) - env.Append(LINKFLAGS='-rdynamic') - if not tools_enabled: if is_desktop(env['platform']): if not mono_root: @@ -292,7 +292,8 @@ def configure(env, env_mono): elif is_android: # Compress Android Mono Config from . import make_android_mono_config - config_file_path = os.path.join(mono_root, 'etc', 'mono', 'config') + module_dir = os.getcwd() + config_file_path = os.path.join(module_dir, 'build_scripts', 'mono_android_config.xml') make_android_mono_config.generate_compressed_config(config_file_path, 'mono_gd/') # Copy the required shared libraries diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs index aed25f5ac5..c7e8ea511a 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs @@ -125,12 +125,20 @@ namespace GodotTools.Export dependencies[projectDllName] = projectDllSrcPath; + if (platform == OS.Platforms.Android) { - string platformBclDir = DeterminePlatformBclDir(platform); + string godotAndroidExtProfileDir = GetBclProfileDir("godot_android_ext"); + string monoAndroidAssemblyPath = Path.Combine(godotAndroidExtProfileDir, "Mono.Android.dll"); + + if (!File.Exists(monoAndroidAssemblyPath)) + throw new FileNotFoundException("Assembly not found: 'Mono.Android'", monoAndroidAssemblyPath); - internal_GetExportedAssemblyDependencies(projectDllName, projectDllSrcPath, buildConfig, platformBclDir, dependencies); + dependencies["Mono.Android"] = monoAndroidAssemblyPath; } + var initialDependencies = dependencies.Duplicate(); + internal_GetExportedAssemblyDependencies(initialDependencies, buildConfig, DeterminePlatformBclDir(platform), dependencies); + string outputDataDir = null; if (PlatformHasTemplateDir(platform)) @@ -201,23 +209,25 @@ namespace GodotTools.Export string TemplateDirName() => $"data.mono.{platform}.{bits}.{target}"; string templateDirPath = Path.Combine(Internal.FullTemplatesDir, TemplateDirName()); + bool validTemplatePathFound = true; if (!Directory.Exists(templateDirPath)) { - templateDirPath = null; + validTemplatePathFound = false; if (isDebug) { target = "debug"; // Support both 'release_debug' and 'debug' for the template data directory name templateDirPath = Path.Combine(Internal.FullTemplatesDir, TemplateDirName()); + validTemplatePathFound = true; if (!Directory.Exists(templateDirPath)) - templateDirPath = null; + validTemplatePathFound = false; } } - if (templateDirPath == null) - throw new FileNotFoundException("Data template directory not found"); + if (!validTemplatePathFound) + throw new FileNotFoundException("Data template directory not found", templateDirPath); string outputDataDir = Path.Combine(outputDir, DataDirName); @@ -579,6 +589,12 @@ namespace GodotTools.Export return null; } + private static string GetBclProfileDir(string profile) + { + string templatesDir = Internal.FullTemplatesDir; + return Path.Combine(templatesDir, "bcl", profile); + } + private static string DeterminePlatformBclDir(string platform) { string templatesDir = Internal.FullTemplatesDir; @@ -590,18 +606,45 @@ namespace GodotTools.Export platformBclDir = Path.Combine(templatesDir, "bcl", profile); if (!File.Exists(Path.Combine(platformBclDir, "mscorlib.dll"))) + { + if (PlatformRequiresCustomBcl(platform)) + throw new FileNotFoundException($"Missing BCL (Base Class Library) for platform: {platform}"); + platformBclDir = null; // Use the one we're running on + } } return platformBclDir; } + /// <summary> + /// Determines whether the BCL bundled with the Godot editor can be used for the target platform, + /// or if it requires a custom BCL that must be distributed with the export templates. + /// </summary> + private static bool PlatformRequiresCustomBcl(string platform) + { + if (new[] {OS.Platforms.Android, OS.Platforms.HTML5}.Contains(platform)) + return true; + + // The 'net_4_x' BCL is not compatible between Windows and the other platforms. + // We use the names 'net_4_x_win' and 'net_4_x' to differentiate between the two. + + bool isWinOrUwp = new[] + { + OS.Platforms.Windows, + OS.Platforms.UWP + }.Contains(platform); + + return OS.IsWindows ? !isWinOrUwp : isWinOrUwp; + } + private static string DeterminePlatformBclProfile(string platform) { switch (platform) { case OS.Platforms.Windows: case OS.Platforms.UWP: + return "net_4_x_win"; case OS.Platforms.OSX: case OS.Platforms.X11: case OS.Platforms.Server: @@ -627,7 +670,7 @@ namespace GodotTools.Export } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void internal_GetExportedAssemblyDependencies(string projectDllName, string projectDllSrcPath, + private static extern void internal_GetExportedAssemblyDependencies(Godot.Collections.Dictionary<string, string> initialDependencies, string buildConfig, string customBclDir, Godot.Collections.Dictionary<string, string> dependencies); } } diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs index 1a8c26acd7..e89ea0c476 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs @@ -65,7 +65,7 @@ namespace GodotTools.Utils private static readonly Lazy<bool> _isAndroid = new Lazy<bool>(() => IsOS(Names.Android)); private static readonly Lazy<bool> _isHTML5 = new Lazy<bool>(() => IsOS(Names.HTML5)); - public static bool IsWindows => _isWindows.Value; + public static bool IsWindows => _isWindows.Value || IsUWP; public static bool IsOSX => _isOSX.Value; public static bool IsX11 => _isX11.Value; public static bool IsServer => _isServer.Value; diff --git a/modules/mono/editor/editor_internal_calls.cpp b/modules/mono/editor/editor_internal_calls.cpp index 4055ec005a..443b4ba841 100644 --- a/modules/mono/editor/editor_internal_calls.cpp +++ b/modules/mono/editor/editor_internal_calls.cpp @@ -219,15 +219,14 @@ int32_t godot_icall_ScriptClassParser_ParseFile(MonoString *p_filepath, MonoObje return err; } -uint32_t godot_icall_ExportPlugin_GetExportedAssemblyDependencies(MonoString *p_project_dll_name, MonoString *p_project_dll_src_path, +uint32_t godot_icall_ExportPlugin_GetExportedAssemblyDependencies(MonoObject *p_initial_dependencies, MonoString *p_build_config, MonoString *p_custom_bcl_dir, MonoObject *r_dependencies) { - String project_dll_name = GDMonoMarshal::mono_string_to_godot(p_project_dll_name); - String project_dll_src_path = GDMonoMarshal::mono_string_to_godot(p_project_dll_src_path); + Dictionary initial_dependencies = GDMonoMarshal::mono_object_to_variant(p_initial_dependencies); String build_config = GDMonoMarshal::mono_string_to_godot(p_build_config); String custom_bcl_dir = GDMonoMarshal::mono_string_to_godot(p_custom_bcl_dir); Dictionary dependencies = GDMonoMarshal::mono_object_to_variant(r_dependencies); - return GodotSharpExport::get_exported_assembly_dependencies(project_dll_name, project_dll_src_path, build_config, custom_bcl_dir, dependencies); + return GodotSharpExport::get_exported_assembly_dependencies(initial_dependencies, build_config, custom_bcl_dir, dependencies); } MonoString *godot_icall_Internal_UpdateApiAssembliesFromPrebuilt(MonoString *p_config) { diff --git a/modules/mono/editor/godotsharp_export.cpp b/modules/mono/editor/godotsharp_export.cpp index 9ae9399e1d..e02bd3be58 100644 --- a/modules/mono/editor/godotsharp_export.cpp +++ b/modules/mono/editor/godotsharp_export.cpp @@ -101,23 +101,32 @@ Error get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String> return OK; } -Error get_exported_assembly_dependencies(const String &p_project_dll_name, const String &p_project_dll_src_path, const String &p_build_config, const String &p_custom_bcl_dir, Dictionary &r_dependencies) { +Error get_exported_assembly_dependencies(const Dictionary &p_initial_dependencies, + const String &p_build_config, const String &p_custom_bcl_dir, Dictionary &r_dependencies) { MonoDomain *export_domain = GDMonoUtils::create_domain("GodotEngine.Domain.ProjectExport"); ERR_FAIL_NULL_V(export_domain, FAILED); _GDMONO_SCOPE_EXIT_DOMAIN_UNLOAD_(export_domain); _GDMONO_SCOPE_DOMAIN_(export_domain); - GDMonoAssembly *scripts_assembly = NULL; - bool load_success = GDMono::get_singleton()->load_assembly_from(p_project_dll_name, - p_project_dll_src_path, &scripts_assembly, /* refonly: */ true); - - ERR_FAIL_COND_V_MSG(!load_success, ERR_CANT_RESOLVE, "Cannot load assembly (refonly): '" + p_project_dll_name + "'."); - Vector<String> search_dirs; GDMonoAssembly::fill_search_dirs(search_dirs, p_build_config, p_custom_bcl_dir); - return get_assembly_dependencies(scripts_assembly, search_dirs, r_dependencies); + for (const Variant *key = p_initial_dependencies.next(); key; key = p_initial_dependencies.next(key)) { + String assembly_name = *key; + String assembly_path = p_initial_dependencies[*key]; + + GDMonoAssembly *assembly = NULL; + bool load_success = GDMono::get_singleton()->load_assembly_from(assembly_name, assembly_path, &assembly, /* refonly: */ true); + + ERR_FAIL_COND_V_MSG(!load_success, ERR_CANT_RESOLVE, "Cannot load assembly (refonly): '" + assembly_name + "'."); + + Error err = get_assembly_dependencies(assembly, search_dirs, r_dependencies); + if (err != OK) + return err; + } + + return OK; } } // namespace GodotSharpExport diff --git a/modules/mono/editor/godotsharp_export.h b/modules/mono/editor/godotsharp_export.h index 58e46e2f2d..8eb5a4d9dc 100644 --- a/modules/mono/editor/godotsharp_export.h +++ b/modules/mono/editor/godotsharp_export.h @@ -41,9 +41,8 @@ namespace GodotSharpExport { Error get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String> &p_search_dirs, Dictionary &r_dependencies); -Error get_exported_assembly_dependencies(const String &p_project_dll_name, - const String &p_project_dll_src_path, const String &p_build_config, - const String &p_custom_lib_dir, Dictionary &r_dependencies); +Error get_exported_assembly_dependencies(const Dictionary &p_initial_dependencies, + const String &p_build_config, const String &p_custom_lib_dir, Dictionary &r_dependencies); } // namespace GodotSharpExport diff --git a/modules/mono/glue/Managed/Files/Array.cs b/modules/mono/glue/Managed/Files/Array.cs index 0e7b0362e0..aba1065498 100644 --- a/modules/mono/glue/Managed/Files/Array.cs +++ b/modules/mono/glue/Managed/Files/Array.cs @@ -64,6 +64,11 @@ namespace Godot.Collections return safeHandle.DangerousGetHandle(); } + public Array Duplicate(bool deep = false) + { + return new Array(godot_icall_Array_Duplicate(GetPtr(), deep)); + } + public Error Resize(int newSize) { return godot_icall_Array_Resize(GetPtr(), newSize); @@ -179,6 +184,9 @@ namespace Godot.Collections internal extern static void godot_icall_Array_CopyTo(IntPtr ptr, System.Array array, int arrayIndex); [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static IntPtr godot_icall_Array_Duplicate(IntPtr ptr, bool deep); + + [MethodImpl(MethodImplOptions.InternalCall)] internal extern static int godot_icall_Array_IndexOf(IntPtr ptr, object item); [MethodImpl(MethodImplOptions.InternalCall)] @@ -250,6 +258,11 @@ namespace Godot.Collections return from.objectArray; } + public Array<T> Duplicate(bool deep = false) + { + return new Array<T>(objectArray.Duplicate(deep)); + } + public Error Resize(int newSize) { return objectArray.Resize(newSize); diff --git a/modules/mono/glue/Managed/Files/Dictionary.cs b/modules/mono/glue/Managed/Files/Dictionary.cs index 6ab8549a01..d72109de92 100644 --- a/modules/mono/glue/Managed/Files/Dictionary.cs +++ b/modules/mono/glue/Managed/Files/Dictionary.cs @@ -80,6 +80,11 @@ namespace Godot.Collections disposed = true; } + public Dictionary Duplicate(bool deep = false) + { + return new Dictionary(godot_icall_Dictionary_Duplicate(GetPtr(), deep)); + } + // IDictionary public ICollection Keys @@ -235,6 +240,9 @@ namespace Godot.Collections internal extern static bool godot_icall_Dictionary_ContainsKey(IntPtr ptr, object key); [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static IntPtr godot_icall_Dictionary_Duplicate(IntPtr ptr, bool deep); + + [MethodImpl(MethodImplOptions.InternalCall)] internal extern static bool godot_icall_Dictionary_RemoveKey(IntPtr ptr, object key); [MethodImpl(MethodImplOptions.InternalCall)] @@ -313,6 +321,11 @@ namespace Godot.Collections return objectDict.GetPtr(); } + public Dictionary<TKey, TValue> Duplicate(bool deep = false) + { + return new Dictionary<TKey, TValue>(objectDict.Duplicate(deep)); + } + // IDictionary<TKey, TValue> public TValue this[TKey key] diff --git a/modules/mono/glue/collections_glue.cpp b/modules/mono/glue/collections_glue.cpp index bfb7b0f775..e84a5becd6 100644 --- a/modules/mono/glue/collections_glue.cpp +++ b/modules/mono/glue/collections_glue.cpp @@ -103,6 +103,10 @@ void godot_icall_Array_CopyTo(Array *ptr, MonoArray *array, int array_index) { } } +Array *godot_icall_Array_Duplicate(Array *ptr, MonoBoolean deep) { + return memnew(Array(ptr->duplicate(deep))); +} + int godot_icall_Array_IndexOf(Array *ptr, MonoObject *item) { return ptr->find(GDMonoMarshal::mono_object_to_variant(item)); } @@ -224,6 +228,10 @@ MonoBoolean godot_icall_Dictionary_ContainsKey(Dictionary *ptr, MonoObject *key) return ptr->has(GDMonoMarshal::mono_object_to_variant(key)); } +Dictionary *godot_icall_Dictionary_Duplicate(Dictionary *ptr, MonoBoolean deep) { + return memnew(Dictionary(ptr->duplicate(deep))); +} + MonoBoolean godot_icall_Dictionary_RemoveKey(Dictionary *ptr, MonoObject *key) { return ptr->erase(GDMonoMarshal::mono_object_to_variant(key)); } @@ -284,6 +292,7 @@ void godot_register_collections_icalls() { mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Clear", (void *)godot_icall_Array_Clear); mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Contains", (void *)godot_icall_Array_Contains); mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_CopyTo", (void *)godot_icall_Array_CopyTo); + mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Duplicate", (void *)godot_icall_Array_Duplicate); mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_IndexOf", (void *)godot_icall_Array_IndexOf); mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Insert", (void *)godot_icall_Array_Insert); mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Remove", (void *)godot_icall_Array_Remove); @@ -304,6 +313,7 @@ void godot_register_collections_icalls() { mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Clear", (void *)godot_icall_Dictionary_Clear); mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Contains", (void *)godot_icall_Dictionary_Contains); mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_ContainsKey", (void *)godot_icall_Dictionary_ContainsKey); + mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Duplicate", (void *)godot_icall_Dictionary_Duplicate); mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_RemoveKey", (void *)godot_icall_Dictionary_RemoveKey); mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Remove", (void *)godot_icall_Dictionary_Remove); mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_TryGetValue", (void *)godot_icall_Dictionary_TryGetValue); diff --git a/modules/mono/glue/collections_glue.h b/modules/mono/glue/collections_glue.h index 54ed42c3b6..a79a651fcd 100644 --- a/modules/mono/glue/collections_glue.h +++ b/modules/mono/glue/collections_glue.h @@ -59,6 +59,8 @@ MonoBoolean godot_icall_Array_Contains(Array *ptr, MonoObject *item); void godot_icall_Array_CopyTo(Array *ptr, MonoArray *array, int array_index); +Array *godot_icall_Array_Duplicate(Array *ptr, MonoBoolean deep); + int godot_icall_Array_IndexOf(Array *ptr, MonoObject *item); void godot_icall_Array_Insert(Array *ptr, int index, MonoObject *item); @@ -99,6 +101,8 @@ MonoBoolean godot_icall_Dictionary_Contains(Dictionary *ptr, MonoObject *key, Mo MonoBoolean godot_icall_Dictionary_ContainsKey(Dictionary *ptr, MonoObject *key); +Dictionary *godot_icall_Dictionary_Duplicate(Dictionary *ptr, MonoBoolean deep); + MonoBoolean godot_icall_Dictionary_RemoveKey(Dictionary *ptr, MonoObject *key); MonoBoolean godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, MonoObject *value); diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index a43311d281..33ba877352 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -330,7 +330,7 @@ void GDMono::initialize() { #endif #if defined(ANDROID_ENABLED) - GDMonoAndroid::register_android_dl_fallback(); + GDMonoAndroid::initialize(); #endif GDMonoAssembly::initialize(); @@ -363,6 +363,9 @@ void GDMono::initialize() { } #endif + // NOTE: Internal calls must be registered after the Mono runtime initialization. + // Otherwise registration fails with the error: 'assertion 'hash != NULL' failed'. + root_domain = gd_initialize_mono_runtime(); ERR_FAIL_NULL_MSG(root_domain, "Mono: Failed to initialize runtime."); @@ -376,6 +379,10 @@ void GDMono::initialize() { print_verbose("Mono: Runtime initialized"); +#if defined(ANDROID_ENABLED) + GDMonoAndroid::register_internal_calls(); +#endif + // mscorlib assembly MUST be present at initialization bool corlib_loaded = _load_corlib_assembly(); ERR_FAIL_COND_MSG(!corlib_loaded, "Mono: Failed to load mscorlib assembly."); @@ -1253,6 +1260,10 @@ GDMono::~GDMono() { mono_jit_cleanup(root_domain); +#if defined(ANDROID_ENABLED) + GDMonoAndroid::cleanup(); +#endif + print_verbose("Mono: Finalized"); runtime_initialized = false; diff --git a/modules/mono/mono_gd/gd_mono_android.cpp b/modules/mono/mono_gd/gd_mono_android.cpp index 1ee035589d..86af8d1812 100644 --- a/modules/mono/mono_gd/gd_mono_android.cpp +++ b/modules/mono/mono_gd/gd_mono_android.cpp @@ -34,38 +34,97 @@ #include <dlfcn.h> // dlopen, dlsym #include <mono/utils/mono-dl-fallback.h> +#include <sys/system_properties.h> +#include <cstddef> + +#if __ANDROID_API__ < 24 +#include "thirdparty/misc/ifaddrs-android.h" +#else +#include <ifaddrs.h> +#endif #include "core/os/os.h" #include "core/ustring.h" +#include "platform/android/java_godot_wrapper.h" +#include "platform/android/os_android.h" #include "platform/android/thread_jandroid.h" #include "../utils/path_utils.h" #include "../utils/string_utils.h" +#include "gd_mono_cache.h" +#include "gd_mono_marshal.h" + +// Warning: JNI boilerplate ahead... continue at your own risk namespace GDMonoAndroid { +template <typename T> +struct ScopedLocalRef { + JNIEnv *env; + T local_ref; + + _FORCE_INLINE_ T get() const { return local_ref; } + _FORCE_INLINE_ operator T() const { return local_ref; } + _FORCE_INLINE_ operator jvalue() const { return (jvalue)local_ref; } + + _FORCE_INLINE_ operator bool() const { return local_ref != NULL; } + + _FORCE_INLINE_ bool operator==(std::nullptr_t) const { + return local_ref == nullptr; + } + + _FORCE_INLINE_ bool operator!=(std::nullptr_t) const { + return local_ref != nullptr; + } + + ScopedLocalRef(const ScopedLocalRef &) = delete; + ScopedLocalRef &operator=(const ScopedLocalRef &) = delete; + + ScopedLocalRef(JNIEnv *p_env, T p_local_ref) : + env(p_env), local_ref(p_local_ref) { + } + + ~ScopedLocalRef() { + if (local_ref) { + env->DeleteLocalRef(local_ref); + } + } +}; + +bool jni_exception_check(JNIEnv *p_env) { + if (p_env->ExceptionCheck()) { + // Print the exception to logcat + p_env->ExceptionDescribe(); + + p_env->ExceptionClear(); + return true; + } + + return false; +} + String app_native_lib_dir_cache; String determine_app_native_lib_dir() { JNIEnv *env = ThreadAndroid::get_env(); - jclass activityThreadClass = env->FindClass("android/app/ActivityThread"); + ScopedLocalRef<jclass> activityThreadClass(env, env->FindClass("android/app/ActivityThread")); jmethodID currentActivityThread = env->GetStaticMethodID(activityThreadClass, "currentActivityThread", "()Landroid/app/ActivityThread;"); - jobject activityThread = env->CallStaticObjectMethod(activityThreadClass, currentActivityThread); + ScopedLocalRef<jobject> activityThread(env, env->CallStaticObjectMethod(activityThreadClass, currentActivityThread)); jmethodID getApplication = env->GetMethodID(activityThreadClass, "getApplication", "()Landroid/app/Application;"); - jobject ctx = env->CallObjectMethod(activityThread, getApplication); + ScopedLocalRef<jobject> ctx(env, env->CallObjectMethod(activityThread, getApplication)); jmethodID getApplicationInfo = env->GetMethodID(env->GetObjectClass(ctx), "getApplicationInfo", "()Landroid/content/pm/ApplicationInfo;"); - jobject applicationInfo = env->CallObjectMethod(ctx, getApplicationInfo); + ScopedLocalRef<jobject> applicationInfo(env, env->CallObjectMethod(ctx, getApplicationInfo)); jfieldID nativeLibraryDirField = env->GetFieldID(env->GetObjectClass(applicationInfo), "nativeLibraryDir", "Ljava/lang/String;"); - jstring nativeLibraryDir = (jstring)env->GetObjectField(applicationInfo, nativeLibraryDirField); + ScopedLocalRef<jstring> nativeLibraryDir(env, (jstring)env->GetObjectField(applicationInfo, nativeLibraryDirField)); String result; - const char *const nativeLibraryDir_utf8 = env->GetStringUTFChars(nativeLibraryDir, NULL); - if (nativeLibraryDir_utf8) { - result.parse_utf8(nativeLibraryDir_utf8); - env->ReleaseStringUTFChars(nativeLibraryDir, nativeLibraryDir_utf8); + const char *const nativeLibraryDirUtf8 = env->GetStringUTFChars(nativeLibraryDir, NULL); + if (nativeLibraryDirUtf8) { + result.parse_utf8(nativeLibraryDirUtf8); + env->ReleaseStringUTFChars(nativeLibraryDir, nativeLibraryDirUtf8); } return result; @@ -90,7 +149,53 @@ int gd_mono_convert_dl_flags(int flags) { return lflags; } +#ifndef GD_MONO_ANDROID_SO_NAME +#define GD_MONO_ANDROID_SO_NAME "libmonosgen-2.0.so" +#endif + +const char *mono_so_name = GD_MONO_ANDROID_SO_NAME; +const char *godot_so_name = "libgodot_android.so"; + +void *mono_dl_handle = NULL; +void *godot_dl_handle = NULL; + +void *try_dlopen(const String &p_so_path, int p_flags) { + if (!FileAccess::exists(p_so_path)) { + if (OS::get_singleton()->is_stdout_verbose()) + OS::get_singleton()->print("Cannot find shared library: '%s'\n", p_so_path.utf8().get_data()); + return NULL; + } + + int lflags = gd_mono_convert_dl_flags(p_flags); + + void *handle = dlopen(p_so_path.utf8().get_data(), lflags); + + if (!handle) { + if (OS::get_singleton()->is_stdout_verbose()) + OS::get_singleton()->print("Failed to open shared library: '%s'. Error: '%s'\n", p_so_path.utf8().get_data(), dlerror()); + return NULL; + } + + if (OS::get_singleton()->is_stdout_verbose()) + OS::get_singleton()->print("Successfully loaded shared library: '%s'\n", p_so_path.utf8().get_data()); + + return handle; +} + void *gd_mono_android_dlopen(const char *p_name, int p_flags, char **r_err, void *p_user_data) { + if (p_name == NULL) { + // __Internal + + if (!mono_dl_handle) { + String app_native_lib_dir = get_app_native_lib_dir(); + String so_path = path::join(app_native_lib_dir, mono_so_name); + + mono_dl_handle = try_dlopen(so_path, p_flags); + } + + return mono_dl_handle; + } + String name = String::utf8(p_name); if (name.ends_with(".dll.so") || name.ends_with(".exe.so")) { @@ -100,26 +205,7 @@ void *gd_mono_android_dlopen(const char *p_name, int p_flags, char **r_err, void String so_name = "lib-aot-" + orig_so_name; String so_path = path::join(app_native_lib_dir, so_name); - if (!FileAccess::exists(so_path)) { - if (OS::get_singleton()->is_stdout_verbose()) - OS::get_singleton()->print("Cannot find shared library: '%s'\n", so_path.utf8().get_data()); - return NULL; - } - - int lflags = gd_mono_convert_dl_flags(p_flags); - - void *handle = dlopen(so_path.utf8().get_data(), lflags); - - if (!handle) { - if (OS::get_singleton()->is_stdout_verbose()) - OS::get_singleton()->print("Failed to open shared library: '%s'. Error: '%s'\n", so_path.utf8().get_data(), dlerror()); - return NULL; - } - - if (OS::get_singleton()->is_stdout_verbose()) - OS::get_singleton()->print("Successfully loaded AOT shared library: '%s'\n", so_path.utf8().get_data()); - - return handle; + return try_dlopen(so_path, p_flags); } return NULL; @@ -131,16 +217,469 @@ void *gd_mono_android_dlsym(void *p_handle, const char *p_name, char **r_err, vo if (sym_addr) return sym_addr; + if (p_handle == mono_dl_handle && godot_dl_handle) { + // Looking up for '__Internal' P/Invoke. We want to search in both the Mono and Godot shared libraries. + // This is needed to resolve the monodroid P/Invoke functions that are defined at the bottom of the file. + sym_addr = dlsym(godot_dl_handle, p_name); + + if (sym_addr) + return sym_addr; + } + if (r_err) *r_err = str_format_new("%s\n", dlerror()); return NULL; } -void register_android_dl_fallback() { - mono_dl_fallback_register(gd_mono_android_dlopen, gd_mono_android_dlsym, NULL, NULL); +void *gd_mono_android_dlclose(void *p_handle, void *p_user_data) { + dlclose(p_handle); + + // Not sure if this ever happens. Does Mono close the handle for the main module? + if (p_handle == mono_dl_handle) + mono_dl_handle = NULL; + + return NULL; +} + +int32_t build_version_sdk_int = 0; + +int32_t get_build_version_sdk_int() { + // The JNI code is the equivalent of: + // + // android.os.Build.VERSION.SDK_INT + + if (build_version_sdk_int == 0) { + JNIEnv *env = ThreadAndroid::get_env(); + + jclass versionClass = env->FindClass("android/os/Build$VERSION"); + ERR_FAIL_NULL_V(versionClass, 0); + + jfieldID sdkIntField = env->GetStaticFieldID(versionClass, "SDK_INT", "I"); + ERR_FAIL_NULL_V(sdkIntField, 0); + + build_version_sdk_int = (int32_t)env->GetStaticIntField(versionClass, sdkIntField); + } + + return build_version_sdk_int; +} + +jobject certStore = NULL; // KeyStore + +MonoBoolean _gd_mono_init_cert_store() { + // The JNI code is the equivalent of: + // + // try { + // certStoreLocal = KeyStore.getInstance("AndroidCAStore"); + // certStoreLocal.load(null); + // certStore = certStoreLocal; + // return true; + // } catch (Exception e) { + // return false; + // } + + JNIEnv *env = ThreadAndroid::get_env(); + + ScopedLocalRef<jclass> keyStoreClass(env, env->FindClass("java/security/KeyStore")); + + jmethodID getInstance = env->GetStaticMethodID(keyStoreClass, "getInstance", "(Ljava/lang/String;)Ljava/security/KeyStore;"); + jmethodID load = env->GetMethodID(keyStoreClass, "load", "(Ljava/security/KeyStore$LoadStoreParameter;)V"); + + ScopedLocalRef<jstring> androidCAStoreString(env, env->NewStringUTF("AndroidCAStore")); + + ScopedLocalRef<jobject> certStoreLocal(env, env->CallStaticObjectMethod(keyStoreClass, getInstance, androidCAStoreString.get())); + + if (jni_exception_check(env)) + return 0; + + env->CallVoidMethod(certStoreLocal, load, NULL); + + if (jni_exception_check(env)) + return 0; + + certStore = env->NewGlobalRef(certStoreLocal); + + return 1; +} + +MonoArray *_gd_mono_android_cert_store_lookup(MonoString *p_alias) { + // The JNI code is the equivalent of: + // + // Certificate certificate = certStore.getCertificate(alias); + // if (certificate == null) + // return null; + // return certificate.getEncoded(); + + MonoError mono_error; + char *alias_utf8 = mono_string_to_utf8_checked(p_alias, &mono_error); + + if (!mono_error_ok(&mono_error)) { + ERR_PRINTS(String() + "Failed to convert MonoString* to UTF-8: '" + mono_error_get_message(&mono_error) + "'."); + mono_error_cleanup(&mono_error); + return NULL; + } + + JNIEnv *env = ThreadAndroid::get_env(); + + ScopedLocalRef<jstring> js_alias(env, env->NewStringUTF(alias_utf8)); + mono_free(alias_utf8); + + ScopedLocalRef<jclass> keyStoreClass(env, env->FindClass("java/security/KeyStore")); + ERR_FAIL_NULL_V(keyStoreClass, NULL); + ScopedLocalRef<jclass> certificateClass(env, env->FindClass("java/security/cert/Certificate")); + ERR_FAIL_NULL_V(certificateClass, NULL); + + jmethodID getCertificate = env->GetMethodID(keyStoreClass, "getCertificate", "(Ljava/lang/String;)Ljava/security/cert/Certificate;"); + ERR_FAIL_NULL_V(getCertificate, NULL); + + jmethodID getEncoded = env->GetMethodID(certificateClass, "getEncoded", "()[B"); + ERR_FAIL_NULL_V(getEncoded, NULL); + + ScopedLocalRef<jobject> certificate(env, env->CallObjectMethod(certStore, getCertificate, js_alias.get())); + + if (!certificate) + return NULL; + + ScopedLocalRef<jbyteArray> encoded(env, (jbyteArray)env->CallObjectMethod(certificate, getEncoded)); + jsize encodedLength = env->GetArrayLength(encoded); + + MonoArray *encoded_ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(uint8_t), encodedLength); + uint8_t *dest = (uint8_t *)mono_array_addr(encoded_ret, uint8_t, 0); + + env->GetByteArrayRegion(encoded, 0, encodedLength, reinterpret_cast<jbyte *>(dest)); + + return encoded_ret; +} + +void initialize() { + // We need to set this environment variable to make the monodroid BCL use btls instead of legacy as the default provider + OS::get_singleton()->set_environment("XA_TLS_PROVIDER", "btls"); + + mono_dl_fallback_register(gd_mono_android_dlopen, gd_mono_android_dlsym, gd_mono_android_dlclose, NULL); + + String app_native_lib_dir = get_app_native_lib_dir(); + String so_path = path::join(app_native_lib_dir, godot_so_name); + + godot_dl_handle = try_dlopen(so_path, gd_mono_convert_dl_flags(MONO_DL_LAZY)); +} + +void register_internal_calls() { + mono_add_internal_call("Android.Runtime.AndroidEnvironment::_gd_mono_init_cert_store", (void *)_gd_mono_init_cert_store); + mono_add_internal_call("Android.Runtime.AndroidEnvironment::_gd_mono_android_cert_store_lookup", (void *)_gd_mono_android_cert_store_lookup); +} + +void cleanup() { + // This is called after shutting down the Mono runtime + + if (mono_dl_handle) + gd_mono_android_dlclose(mono_dl_handle, NULL); + + if (godot_dl_handle) + gd_mono_android_dlclose(godot_dl_handle, NULL); + + JNIEnv *env = ThreadAndroid::get_env(); + + if (certStore) { + env->DeleteGlobalRef(certStore); + certStore = NULL; + } } } // namespace GDMonoAndroid +using namespace GDMonoAndroid; + +// The following are P/Invoke functions required by the monodroid profile of the BCL. +// These are P/Invoke functions and not internal calls, hence why they use +// 'mono_bool' and 'const char*' instead of 'MonoBoolean' and 'MonoString*'. + +#define GD_PINVOKE_EXPORT extern "C" __attribute__((visibility("default"))) + +GD_PINVOKE_EXPORT int32_t _monodroid_get_android_api_level() { + return get_build_version_sdk_int(); +} + +GD_PINVOKE_EXPORT void monodroid_free(void *ptr) { + free(ptr); +} + +GD_PINVOKE_EXPORT int32_t monodroid_get_system_property(const char *p_name, char **r_value) { + char prop_value_str[PROP_VALUE_MAX + 1] = { 0 }; + + int len = __system_property_get(p_name, prop_value_str); + + if (r_value) { + if (len >= 0) { + *r_value = (char *)malloc(len + 1); + if (!*r_value) + return -1; + memcpy(*r_value, prop_value_str, len); + (*r_value)[len] = '\0'; + } else { + *r_value = NULL; + } + } + + return len; +} + +GD_PINVOKE_EXPORT mono_bool _monodroid_get_network_interface_up_state(const char *p_ifname, mono_bool *r_is_up) { + // The JNI code is the equivalent of: + // + // NetworkInterface.getByName(p_ifname).isUp() + + if (!r_is_up || !p_ifname || strlen(p_ifname) == 0) + return 0; + + *r_is_up = 0; + + JNIEnv *env = ThreadAndroid::get_env(); + + jclass networkInterfaceClass = env->FindClass("java/net/NetworkInterface"); + ERR_FAIL_NULL_V(networkInterfaceClass, 0); + + jmethodID getByName = env->GetStaticMethodID(networkInterfaceClass, "getByName", "(Ljava/lang/String;)Ljava/net/NetworkInterface;"); + ERR_FAIL_NULL_V(getByName, 0); + + jmethodID isUp = env->GetMethodID(networkInterfaceClass, "isUp", "()Z"); + ERR_FAIL_NULL_V(isUp, 0); + + ScopedLocalRef<jstring> js_ifname(env, env->NewStringUTF(p_ifname)); + ScopedLocalRef<jobject> networkInterface(env, env->CallStaticObjectMethod(networkInterfaceClass, getByName, js_ifname.get())); + + if (!networkInterface) + return 0; + + *r_is_up = (mono_bool)env->CallBooleanMethod(networkInterface, isUp); + + return 1; +} + +GD_PINVOKE_EXPORT mono_bool _monodroid_get_network_interface_supports_multicast(const char *p_ifname, mono_bool *r_supports_multicast) { + // The JNI code is the equivalent of: + // + // NetworkInterface.getByName(p_ifname).supportsMulticast() + + if (!r_supports_multicast || !p_ifname || strlen(p_ifname) == 0) + return 0; + + *r_supports_multicast = 0; + + JNIEnv *env = ThreadAndroid::get_env(); + + jclass networkInterfaceClass = env->FindClass("java/net/NetworkInterface"); + ERR_FAIL_NULL_V(networkInterfaceClass, 0); + + jmethodID getByName = env->GetStaticMethodID(networkInterfaceClass, "getByName", "(Ljava/lang/String;)Ljava/net/NetworkInterface;"); + ERR_FAIL_NULL_V(getByName, 0); + + jmethodID supportsMulticast = env->GetMethodID(networkInterfaceClass, "supportsMulticast", "()Z"); + ERR_FAIL_NULL_V(supportsMulticast, 0); + + ScopedLocalRef<jstring> js_ifname(env, env->NewStringUTF(p_ifname)); + ScopedLocalRef<jobject> networkInterface(env, env->CallStaticObjectMethod(networkInterfaceClass, getByName, js_ifname.get())); + + if (!networkInterface) + return 0; + + *r_supports_multicast = (mono_bool)env->CallBooleanMethod(networkInterface, supportsMulticast); + + return 1; +} + +static const int dns_servers_len = 8; + +static void interop_get_active_network_dns_servers(char **r_dns_servers, int *dns_servers_count) { + // The JNI code is the equivalent of: + // + // ConnectivityManager connectivityManager = (ConnectivityManager)getApplicationContext() + // .getSystemService(Context.CONNECTIVITY_SERVICE); + // Network activeNerwork = connectivityManager.getActiveNetwork(); + // LinkProperties linkProperties = connectivityManager.getLinkProperties(activeNerwork); + // List<String> dnsServers = linkProperties.getDnsServers().stream() + // .map(inetAddress -> inetAddress.getHostAddress()).collect(Collectors.toList()); + +#ifdef DEBUG_ENABLED + CRASH_COND(get_build_version_sdk_int() < 23); +#endif + + JNIEnv *env = ThreadAndroid::get_env(); + + GodotJavaWrapper *godot_java = ((OS_Android *)OS::get_singleton())->get_godot_java(); + jobject activity = godot_java->get_activity(); + + ScopedLocalRef<jclass> activityClass(env, env->GetObjectClass(activity)); + ERR_FAIL_NULL(activityClass); + + jmethodID getApplicationContext = env->GetMethodID(activityClass, "getApplicationContext", "()Landroid/content/Context;"); + + ScopedLocalRef<jobject> applicationContext(env, env->CallObjectMethod(activity, getApplicationContext)); + + ScopedLocalRef<jclass> contextClass(env, env->FindClass("android/content/Context")); + ERR_FAIL_NULL(contextClass); + + jfieldID connectivityServiceField = env->GetStaticFieldID(contextClass, "CONNECTIVITY_SERVICE", "Ljava/lang/String;"); + ScopedLocalRef<jstring> connectivityServiceString(env, (jstring)env->GetStaticObjectField(contextClass, connectivityServiceField)); + + jmethodID getSystemService = env->GetMethodID(contextClass, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;"); + + ScopedLocalRef<jobject> connectivityManager(env, env->CallObjectMethod(applicationContext, getSystemService, connectivityServiceString.get())); + + if (!connectivityManager) + return; + + ScopedLocalRef<jclass> connectivityManagerClass(env, env->FindClass("android/net/ConnectivityManager")); + ERR_FAIL_NULL(connectivityManagerClass); + + jmethodID getActiveNetwork = env->GetMethodID(connectivityManagerClass, "getActiveNetwork", "()Landroid/net/Network;"); + ERR_FAIL_NULL(getActiveNetwork); + + ScopedLocalRef<jobject> activeNetwork(env, env->CallObjectMethod(connectivityManager, getActiveNetwork)); + + if (!activeNetwork) + return; + + jmethodID getLinkProperties = env->GetMethodID(connectivityManagerClass, + "getLinkProperties", "(Landroid/net/Network;)Landroid/net/LinkProperties;"); + ERR_FAIL_NULL(getLinkProperties); + + ScopedLocalRef<jobject> linkProperties(env, env->CallObjectMethod(connectivityManager, getLinkProperties, activeNetwork.get())); + + if (!linkProperties) + return; + + ScopedLocalRef<jclass> linkPropertiesClass(env, env->FindClass("android/net/LinkProperties")); + ERR_FAIL_NULL(linkPropertiesClass); + + jmethodID getDnsServers = env->GetMethodID(linkPropertiesClass, "getDnsServers", "()Ljava/util/List;"); + ERR_FAIL_NULL(getDnsServers); + + ScopedLocalRef<jobject> dnsServers(env, env->CallObjectMethod(linkProperties, getDnsServers)); + + if (!dnsServers) + return; + + ScopedLocalRef<jclass> listClass(env, env->FindClass("java/util/List")); + ERR_FAIL_NULL(listClass); + + jmethodID listSize = env->GetMethodID(listClass, "size", "()I"); + ERR_FAIL_NULL(listSize); + + int dnsServersCount = env->CallIntMethod(dnsServers, listSize); + + if (dnsServersCount > dns_servers_len) + dnsServersCount = dns_servers_len; + + if (dnsServersCount <= 0) + return; + + jmethodID listGet = env->GetMethodID(listClass, "get", "(I)Ljava/lang/Object;"); + ERR_FAIL_NULL(listGet); + + ScopedLocalRef<jclass> inetAddressClass(env, env->FindClass("java/net/InetAddress")); + ERR_FAIL_NULL(inetAddressClass); + + jmethodID getHostAddress = env->GetMethodID(inetAddressClass, "getHostAddress", "()Ljava/lang/String;"); + ERR_FAIL_NULL(getHostAddress); + + for (int i = 0; i < dnsServersCount; i++) { + ScopedLocalRef<jobject> dnsServer(env, env->CallObjectMethod(dnsServers, listGet, (jint)i)); + if (!dnsServer) + continue; + + ScopedLocalRef<jstring> hostAddress(env, (jstring)env->CallObjectMethod(dnsServer, getHostAddress)); + const char *host_address = env->GetStringUTFChars(hostAddress, 0); + + r_dns_servers[i] = strdup(host_address); // freed by the BCL + (*dns_servers_count)++; + + env->ReleaseStringUTFChars(hostAddress, host_address); + } + + // jesus... +} + +GD_PINVOKE_EXPORT int32_t _monodroid_get_dns_servers(void **r_dns_servers_array) { + if (!r_dns_servers_array) + return -1; + + *r_dns_servers_array = NULL; + + char *dns_servers[dns_servers_len]; + int dns_servers_count = 0; + + if (_monodroid_get_android_api_level() < 26) { + // The 'net.dns*' system properties are no longer available in Android 8.0 (API level 26) and greater: + // https://developer.android.com/about/versions/oreo/android-8.0-changes.html#o-pri + + char prop_name[] = "net.dns*"; + + for (int i = 0; i < dns_servers_len; i++) { + prop_name[7] = (char)(i + 0x31); + char *prop_value; + int32_t len = monodroid_get_system_property(prop_name, &prop_value); + + if (len > 0) { + dns_servers[dns_servers_count] = strndup(prop_value, (size_t)len); // freed by the BCL + dns_servers_count++; + free(prop_value); + } + } + } else { + // Alternative for Oreo and greater + interop_get_active_network_dns_servers(dns_servers, &dns_servers_count); + } + + if (dns_servers_count > 0) { + size_t ret_size = sizeof(char *) * (size_t)dns_servers_count; + *r_dns_servers_array = malloc(ret_size); // freed by the BCL + memcpy(*r_dns_servers_array, dns_servers, ret_size); + } + + return dns_servers_count; +} + +GD_PINVOKE_EXPORT const char *_monodroid_timezone_get_default_id() { + // The JNI code is the equivalent of: + // + // TimeZone.getDefault().getID() + + JNIEnv *env = ThreadAndroid::get_env(); + + ScopedLocalRef<jclass> timeZoneClass(env, env->FindClass("java/util/TimeZone")); + ERR_FAIL_NULL_V(timeZoneClass, NULL); + + jmethodID getDefault = env->GetStaticMethodID(timeZoneClass, "getDefault", "()Ljava/util/TimeZone;"); + ERR_FAIL_NULL_V(getDefault, NULL); + + jmethodID getID = env->GetMethodID(timeZoneClass, "getID", "()Ljava/lang/String;"); + ERR_FAIL_NULL_V(getID, NULL); + + ScopedLocalRef<jobject> defaultTimeZone(env, env->CallStaticObjectMethod(timeZoneClass, getDefault)); + + if (!defaultTimeZone) + return NULL; + + ScopedLocalRef<jstring> defaultTimeZoneID(env, (jstring)env->CallObjectMethod(defaultTimeZone, getID)); + + if (!defaultTimeZoneID) + return NULL; + + const char *default_time_zone_id = env->GetStringUTFChars(defaultTimeZoneID, 0); + + char *result = strdup(default_time_zone_id); // freed by the BCL + + env->ReleaseStringUTFChars(defaultTimeZoneID, default_time_zone_id); + + return result; +} + +GD_PINVOKE_EXPORT int32_t _monodroid_getifaddrs(struct ifaddrs **p_ifap) { + return getifaddrs(p_ifap); +} + +GD_PINVOKE_EXPORT void _monodroid_freeifaddrs(struct ifaddrs *p_ifap) { + freeifaddrs(p_ifap); +} + #endif diff --git a/modules/mono/mono_gd/gd_mono_android.h b/modules/mono/mono_gd/gd_mono_android.h index 72bc799bfd..20ca266428 100644 --- a/modules/mono/mono_gd/gd_mono_android.h +++ b/modules/mono/mono_gd/gd_mono_android.h @@ -39,7 +39,11 @@ namespace GDMonoAndroid { String get_app_native_lib_dir(); -void register_android_dl_fallback(); +void initialize(); + +void register_internal_calls(); + +void cleanup(); } // namespace GDMonoAndroid diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h index b21f92cdd8..a6d6da4f2b 100644 --- a/modules/mono/mono_gd/gd_mono_cache.h +++ b/modules/mono/mono_gd/gd_mono_cache.h @@ -42,20 +42,20 @@ struct CachedData { // corlib classes // Let's use the no-namespace format for these too - GDMonoClass *class_MonoObject; - GDMonoClass *class_bool; - GDMonoClass *class_int8_t; - GDMonoClass *class_int16_t; - GDMonoClass *class_int32_t; - GDMonoClass *class_int64_t; - GDMonoClass *class_uint8_t; - GDMonoClass *class_uint16_t; - GDMonoClass *class_uint32_t; - GDMonoClass *class_uint64_t; - GDMonoClass *class_float; - GDMonoClass *class_double; - GDMonoClass *class_String; - GDMonoClass *class_IntPtr; + GDMonoClass *class_MonoObject; // object + GDMonoClass *class_bool; // bool + GDMonoClass *class_int8_t; // sbyte + GDMonoClass *class_int16_t; // short + GDMonoClass *class_int32_t; // int + GDMonoClass *class_int64_t; // long + GDMonoClass *class_uint8_t; // byte + GDMonoClass *class_uint16_t; // ushort + GDMonoClass *class_uint32_t; // uint + GDMonoClass *class_uint64_t; // ulong + GDMonoClass *class_float; // float + GDMonoClass *class_double; // double + GDMonoClass *class_String; // string + GDMonoClass *class_IntPtr; // System.IntPtr GDMonoClass *class_System_Collections_IEnumerable; GDMonoClass *class_System_Collections_IDictionary; diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp index 3827960e6b..f74fe5715c 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.cpp +++ b/modules/mono/mono_gd/gd_mono_marshal.cpp @@ -935,6 +935,8 @@ Array mono_array_to_Array(MonoArray *p_array) { return ret; } +// TODO: Use memcpy where possible + MonoArray *PoolIntArray_to_mono_array(const PoolIntArray &p_array) { PoolIntArray::Read r = p_array.read(); diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index b2791cfc8b..bf353d287f 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -3464,6 +3464,7 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri ofs = ofs.snapped(Vector2(snap, snap)); } ofs /= EDSCALE; + ofs /= graph->get_zoom(); Set<int> vn; diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index defee8f1f1..9068b76cfb 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -175,9 +175,6 @@ Error OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int input = memnew(InputDefault); input->set_fallback_mapping(godot_java->get_input_fallback_mapping()); - ///@TODO implement a subclass for Android and instantiate that instead - camera_server = memnew(CameraServer); - //power_manager = memnew(PowerAndroid); return OK; @@ -196,8 +193,6 @@ void OS_Android::delete_main_loop() { void OS_Android::finalize() { - memdelete(camera_server); - memdelete(input); } diff --git a/platform/android/os_android.h b/platform/android/os_android.h index a290c0cedd..16b5c8c3a3 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -39,7 +39,6 @@ #include "main/input_default.h" //#include "power_android.h" #include "servers/audio_server.h" -#include "servers/camera_server.h" #include "servers/visual/rasterizer.h" class GodotJavaWrapper; @@ -79,8 +78,6 @@ private: VisualServer *visual_server; - CameraServer *camera_server; - mutable String data_dir_cache; //AudioDriverAndroid audio_driver_android; diff --git a/platform/haiku/os_haiku.cpp b/platform/haiku/os_haiku.cpp index 9c07535c85..438b50053f 100644 --- a/platform/haiku/os_haiku.cpp +++ b/platform/haiku/os_haiku.cpp @@ -133,8 +133,6 @@ Error OS_Haiku::initialize(const VideoMode &p_desired, int p_video_driver, int p window->Show(); visual_server->init(); - camera_server = memnew(CameraServer); - AudioDriverManager::initialize(p_audio_driver); return OK; @@ -150,8 +148,6 @@ void OS_Haiku::finalize() { visual_server->finish(); memdelete(visual_server); - memdelete(camera_server); - memdelete(input); #if defined(OPENGL_ENABLED) diff --git a/platform/haiku/os_haiku.h b/platform/haiku/os_haiku.h index 70d78a1978..e1d4cf8d87 100644 --- a/platform/haiku/os_haiku.h +++ b/platform/haiku/os_haiku.h @@ -38,7 +38,6 @@ #include "haiku_direct_window.h" #include "main/input_default.h" #include "servers/audio_server.h" -#include "servers/camera_server.h" #include "servers/visual_server.h" class OS_Haiku : public OS_Unix { @@ -50,7 +49,6 @@ private: VisualServer *visual_server; VideoMode current_video_mode; int video_driver_index; - CameraServer *camera_server; #ifdef MEDIA_KIT_ENABLED AudioDriverMediaKit driver_media_kit; diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub index 85ba56165b..fa1b124561 100644 --- a/platform/iphone/SCsub +++ b/platform/iphone/SCsub @@ -14,7 +14,6 @@ iphone_lib = [ 'in_app_store.mm', 'icloud.mm', 'ios.mm', - 'camera_ios.mm', ] env_ios = env.Clone() diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp index baae13c53d..82c9508fdb 100644 --- a/platform/iphone/export/export.cpp +++ b/platform/iphone/export/export.cpp @@ -63,6 +63,10 @@ class EditorExportPlatformIOS : public EditorExportPlatform { String architectures; String linker_flags; String cpp_code; + String modules_buildfile; + String modules_fileref; + String modules_buildphase; + String modules_buildgrp; }; struct ExportArchitecture { @@ -178,6 +182,7 @@ public: return list; } virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0); + virtual void add_module_code(const Ref<EditorExportPreset> &p_preset, IOSConfigData &p_config_data, const String &p_name, const String &p_fid, const String &p_gid); virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const; @@ -263,11 +268,16 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/arkit"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/camera"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/access_wifi"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/game_center"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/in_app_purchases"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/push_notifications"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "user_data/accessible_from_files_app"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "user_data/accessible_from_itunes_sharing"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/camera_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the camera"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/microphone_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the microphone"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/photolibrary_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need access to the photo library"), "")); @@ -311,6 +321,14 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ for (int i = 0; i < lines.size(); i++) { if (lines[i].find("$binary") != -1) { strnew += lines[i].replace("$binary", p_config.binary_name) + "\n"; + } else if (lines[i].find("$modules_buildfile") != -1) { + strnew += lines[i].replace("$modules_buildfile", p_config.modules_buildfile) + "\n"; + } else if (lines[i].find("$modules_fileref") != -1) { + strnew += lines[i].replace("$modules_fileref", p_config.modules_fileref) + "\n"; + } else if (lines[i].find("$modules_buildphase") != -1) { + strnew += lines[i].replace("$modules_buildphase", p_config.modules_buildphase) + "\n"; + } else if (lines[i].find("$modules_buildgrp") != -1) { + strnew += lines[i].replace("$modules_buildgrp", p_config.modules_buildgrp) + "\n"; } else if (lines[i].find("$name") != -1) { strnew += lines[i].replace("$name", p_config.pkg_name) + "\n"; } else if (lines[i].find("$info") != -1) { @@ -349,6 +367,10 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ strnew += lines[i].replace("$linker_flags", p_config.linker_flags) + "\n"; } else if (lines[i].find("$cpp_code") != -1) { strnew += lines[i].replace("$cpp_code", p_config.cpp_code) + "\n"; + } else if (lines[i].find("$docs_in_place") != -1) { + strnew += lines[i].replace("$docs_in_place", ((bool)p_preset->get("user_data/accessible_from_files_app")) ? "<true/>" : "<false/>") + "\n"; + } else if (lines[i].find("$docs_sharing") != -1) { + strnew += lines[i].replace("$docs_sharing", ((bool)p_preset->get("user_data/accessible_from_itunes_sharing")) ? "<true/>" : "<false/>") + "\n"; } else if (lines[i].find("$access_wifi") != -1) { bool is_on = p_preset->get("capabilities/access_wifi"); strnew += lines[i].replace("$access_wifi", is_on ? "1" : "0") + "\n"; @@ -837,6 +859,22 @@ Vector<String> EditorExportPlatformIOS::_get_preset_architectures(const Ref<Edit return enabled_archs; } +void EditorExportPlatformIOS::add_module_code(const Ref<EditorExportPreset> &p_preset, EditorExportPlatformIOS::IOSConfigData &p_config_data, const String &p_name, const String &p_fid, const String &p_gid) { + if ((bool)p_preset->get("capabilities/" + p_name)) { + //add module static library + print_line("ADDING MODULE: " + p_name); + + p_config_data.modules_buildfile += p_gid + " /* libgodot_" + p_name + "_module.a in Frameworks */ = {isa = PBXBuildFile; fileRef = " + p_fid + " /* libgodot_" + p_name + "_module.a */; };\n\t\t"; + p_config_data.modules_fileref += p_fid + " /* libgodot_" + p_name + "_module.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = godot_" + p_name + "_module ; path = \"libgodot_" + p_name + "_module.a\"; sourceTree = \"<group>\"; };\n\t\t"; + p_config_data.modules_buildphase += p_gid + " /* libgodot_" + p_name + "_module.a */,\n\t\t\t\t"; + p_config_data.modules_buildgrp += p_fid + " /* libgodot_" + p_name + "_module.a */,\n\t\t\t\t"; + } else { + //add stub function for disabled module + p_config_data.cpp_code += "void register_" + p_name + "_types() { /*stub*/ };\n"; + p_config_data.cpp_code += "void unregister_" + p_name + "_types() { /*stub*/ };\n"; + } +} + Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags); @@ -934,7 +972,11 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p _get_additional_plist_content(), String(" ").join(_get_preset_architectures(p_preset)), _get_linker_flags(), - _get_cpp_code() + _get_cpp_code(), + "", + "", + "", + "" }; DirAccess *tmp_app_path = DirAccess::create_for_path(dest_dir); @@ -949,6 +991,10 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p return ERR_CANT_OPEN; } + add_module_code(p_preset, config_data, "arkit", "F9B95E6E2391205500AF0000", "F9C95E812391205C00BF0000"); + add_module_code(p_preset, config_data, "camera", "F9B95E6E2391205500AF0001", "F9C95E812391205C00BF0001"); + + //export rest of the files int ret = unzGoToFirstFile(src_pkg_zip); Vector<uint8_t> project_file_data; while (ret == UNZ_OK) { @@ -988,6 +1034,20 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p is_execute = true; #endif file = "godot_ios.a"; + } else if (file.begins_with("libgodot_arkit")) { + if ((bool)p_preset->get("capabilities/arkit") && file.ends_with(String(p_debug ? "debug" : "release") + ".fat.a")) { + file = "libgodot_arkit_module.a"; + } else { + ret = unzGoToNextFile(src_pkg_zip); + continue; //ignore! + } + } else if (file.begins_with("libgodot_camera")) { + if ((bool)p_preset->get("capabilities/camera") && file.ends_with(String(p_debug ? "debug" : "release") + ".fat.a")) { + file = "libgodot_camera_module.a"; + } else { + ret = unzGoToNextFile(src_pkg_zip); + continue; //ignore! + } } if (file == project_file) { project_file_data = data; diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp index 83b0660ef7..8984ed1d7b 100644 --- a/platform/iphone/os_iphone.cpp +++ b/platform/iphone/os_iphone.cpp @@ -164,8 +164,6 @@ Error OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p input = memnew(InputDefault); - camera_server = memnew(CameraIOS); - #ifdef GAME_CENTER_ENABLED game_center = memnew(GameCenter); Engine::get_singleton()->add_singleton(Engine::Singleton("GameCenter", game_center)); @@ -361,11 +359,6 @@ void OSIPhone::finalize() { if (main_loop) // should not happen? memdelete(main_loop); - if (camera_server) { - memdelete(camera_server); - camera_server = NULL; - } - visual_server->finish(); memdelete(visual_server); // memdelete(rasterizer); diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h index 63799bbae8..1f49062cfc 100644 --- a/platform/iphone/os_iphone.h +++ b/platform/iphone/os_iphone.h @@ -37,7 +37,6 @@ #include "drivers/coreaudio/audio_driver_coreaudio.h" #include "drivers/unix/os_unix.h" -#include "camera_ios.h" #include "game_center.h" #include "icloud.h" #include "in_app_store.h" @@ -62,8 +61,6 @@ private: AudioDriverCoreAudio audio_driver; - CameraServer *camera_server; - #ifdef GAME_CENTER_ENABLED GameCenter *game_center; #endif diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py index c05b765c5e..7bf3e1bc1d 100644 --- a/platform/javascript/detect.py +++ b/platform/javascript/detect.py @@ -131,6 +131,13 @@ def configure(env): env.Append(LINKFLAGS=['-s', 'BINARYEN=1']) + # This needs to be defined for Emscripten using 'fastcomp' (default pre-1.39.0) + # and undefined if using 'upstream'. And to make things simple, earlier + # Emscripten versions didn't include 'fastcomp' in their path, so we check + # against the presence of 'upstream' to conditionally add the flag. + if not "upstream" in em_config['EMSCRIPTEN_ROOT']: + env.Append(LINKFLAGS=['-s', 'BINARYEN_TRAP_MODE=\'clamp\'']) + # Allow increasing memory buffer size during runtime. This is efficient # when using WebAssembly (in comparison to asm.js) and works well for # us since we don't know requirements at compile-time. diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index 652f6a1ce1..61919bb24a 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -970,8 +970,6 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, VisualServer *visual_server = memnew(VisualServerRaster()); input = memnew(InputDefault); - camera_server = memnew(CameraServer); - EMSCRIPTEN_RESULT result; #define EM_CHECK(ev) \ if (result != EMSCRIPTEN_RESULT_SUCCESS) \ @@ -1106,7 +1104,6 @@ void OS_JavaScript::delete_main_loop() { void OS_JavaScript::finalize() { - memdelete(camera_server); memdelete(input); } diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h index 10676c49f7..7c97e302e9 100644 --- a/platform/javascript/os_javascript.h +++ b/platform/javascript/os_javascript.h @@ -35,7 +35,6 @@ #include "drivers/unix/os_unix.h" #include "main/input_default.h" #include "servers/audio_server.h" -#include "servers/camera_server.h" #include "servers/visual/rasterizer.h" #include <emscripten/html5.h> @@ -67,8 +66,6 @@ class OS_JavaScript : public OS_Unix { int64_t sync_wait_time; int64_t last_sync_check_time; - CameraServer *camera_server; - static EM_BOOL fullscreen_change_callback(int p_event_type, const EmscriptenFullscreenChangeEvent *p_event, void *p_user_data); static EM_BOOL keydown_callback(int p_event_type, const EmscriptenKeyboardEvent *p_event, void *p_user_data); diff --git a/platform/osx/SCsub b/platform/osx/SCsub index 9620863b96..e15b4339a7 100644 --- a/platform/osx/SCsub +++ b/platform/osx/SCsub @@ -13,7 +13,6 @@ files = [ 'dir_access_osx.mm', 'joypad_osx.cpp', 'power_osx.cpp', - 'camera_osx.mm', ] prog = env.add_program('#bin/godot', files) diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index a61b9234d1..78e1aa6c0a 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -33,7 +33,6 @@ #define BitMap _QDBitMap // Suppress deprecated QuickDraw definition. -#include "camera_osx.h" #include "core/os/input.h" #include "crash_handler_osx.h" #include "drivers/coreaudio/audio_driver_coreaudio.h" @@ -74,8 +73,6 @@ public: //Rasterizer *rasterizer; VisualServer *visual_server; - CameraServer *camera_server; - List<String> args; MainLoop *main_loop; diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index dac6721fb4..4dfb93568f 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -1632,8 +1632,6 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a visual_server->init(); AudioDriverManager::initialize(p_audio_driver); - camera_server = memnew(CameraOSX); - input = memnew(InputDefault); joypad_osx = memnew(JoypadOSX); @@ -1663,11 +1661,6 @@ void OS_OSX::finalize() { delete_main_loop(); - if (camera_server) { - memdelete(camera_server); - camera_server = NULL; - } - memdelete(joypad_osx); memdelete(input); diff --git a/platform/server/os_server.cpp b/platform/server/os_server.cpp index 87dc6421ac..12e53054bc 100644 --- a/platform/server/os_server.cpp +++ b/platform/server/os_server.cpp @@ -88,8 +88,6 @@ Error OS_Server::initialize(const VideoMode &p_desired, int p_video_driver, int visual_server = memnew(VisualServerRaster); visual_server->init(); - camera_server = memnew(CameraServer); - AudioDriverManager::initialize(p_audio_driver); input = memnew(InputDefault); @@ -119,8 +117,6 @@ void OS_Server::finalize() { memdelete(input); - memdelete(camera_server); - memdelete(power_manager); ResourceLoader::remove_resource_format_loader(resource_loader_dummy); diff --git a/platform/server/os_server.h b/platform/server/os_server.h index b8119288ff..6d975ca7e0 100644 --- a/platform/server/os_server.h +++ b/platform/server/os_server.h @@ -71,7 +71,6 @@ class OS_Server : public OS_Unix { #endif CrashHandler crash_handler; - CameraServer *camera_server; int video_driver_index; diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index 60f2290355..eb0ae96111 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -303,9 +303,6 @@ Error OS_UWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_a visual_server->init(); - ///@TODO implement a subclass for UWP and instantiate that instead - camera_server = memnew(CameraServer); - input = memnew(InputDefault); joypad = ref new JoypadUWP(input); @@ -404,8 +401,6 @@ void OS_UWP::finalize() { memdelete(input); - memdelete(camera_server); - joypad = nullptr; } diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h index 370cab6a9b..adca7d18cc 100644 --- a/platform/uwp/os_uwp.h +++ b/platform/uwp/os_uwp.h @@ -41,7 +41,6 @@ #include "main/input_default.h" #include "power_uwp.h" #include "servers/audio_server.h" -#include "servers/camera_server.h" #include "servers/visual/rasterizer.h" #include "servers/visual_server.h" @@ -93,8 +92,6 @@ private: VisualServer *visual_server; int pressrc; - CameraServer *camera_server; - ContextEGL_UWP *gl_context; Windows::UI::Core::CoreWindow ^ window; diff --git a/platform/windows/SCsub b/platform/windows/SCsub index 8426ccbb89..892d734734 100644 --- a/platform/windows/SCsub +++ b/platform/windows/SCsub @@ -8,7 +8,6 @@ import platform_windows_builders common_win = [ "godot_windows.cpp", - "camera_win.cpp", "context_gl_windows.cpp", "crash_handler_windows.cpp", "os_windows.cpp", diff --git a/platform/windows/context_gl_windows.cpp b/platform/windows/context_gl_windows.cpp index e715999378..34a5698394 100644 --- a/platform/windows/context_gl_windows.cpp +++ b/platform/windows/context_gl_windows.cpp @@ -34,6 +34,8 @@ #include "context_gl_windows.h" +#include <dwmapi.h> + #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 #define WGL_CONTEXT_FLAGS_ARB 0x2094 @@ -63,16 +65,52 @@ int ContextGL_Windows::get_window_height() { return OS::get_singleton()->get_video_mode().height; } +bool ContextGL_Windows::should_vsync_via_compositor() { + + if (OS::get_singleton()->is_window_fullscreen() || !OS::get_singleton()->is_vsync_via_compositor_enabled()) { + return false; + } + + // Note: All Windows versions supported by Godot have a compositor. + // It can be disabled on earlier Windows versions. + BOOL dwm_enabled; + + if (SUCCEEDED(DwmIsCompositionEnabled(&dwm_enabled))) { + return dwm_enabled; + } + + return false; +} + void ContextGL_Windows::swap_buffers() { SwapBuffers(hDC); + + if (use_vsync) { + bool vsync_via_compositor_now = should_vsync_via_compositor(); + + if (vsync_via_compositor_now) { + DwmFlush(); + } + + if (vsync_via_compositor_now != vsync_via_compositor) { + // The previous frame had a different operating mode than this + // frame. Set the 'vsync_via_compositor' member variable and the + // OpenGL swap interval to their proper values. + set_use_vsync(true); + } + } } void ContextGL_Windows::set_use_vsync(bool p_use) { + vsync_via_compositor = p_use && should_vsync_via_compositor(); + if (wglSwapIntervalEXT) { - wglSwapIntervalEXT(p_use ? 1 : 0); + int swap_interval = (p_use && !vsync_via_compositor) ? 1 : 0; + wglSwapIntervalEXT(swap_interval); } + use_vsync = p_use; } @@ -177,6 +215,7 @@ ContextGL_Windows::ContextGL_Windows(HWND hwnd, bool p_opengl_3_context) { opengl_3_context = p_opengl_3_context; hWnd = hwnd; use_vsync = false; + vsync_via_compositor = false; } ContextGL_Windows::~ContextGL_Windows() { diff --git a/platform/windows/context_gl_windows.h b/platform/windows/context_gl_windows.h index d23fba50e1..e65ea1928f 100644 --- a/platform/windows/context_gl_windows.h +++ b/platform/windows/context_gl_windows.h @@ -50,9 +50,12 @@ class ContextGL_Windows { HWND hWnd; bool opengl_3_context; bool use_vsync; + bool vsync_via_compositor; PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT; + static bool should_vsync_via_compositor(); + public: void release_current(); diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 9a2b2bcb98..b37a21f37f 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -221,7 +221,8 @@ def configure_msvc(env, manual_msvc_config): LIBS = ['winmm', 'opengl32', 'dsound', 'kernel32', 'ole32', 'oleaut32', 'user32', 'gdi32', 'IPHLPAPI', 'Shlwapi', 'wsock32', 'Ws2_32', - 'shell32', 'advapi32', 'dinput8', 'dxguid', 'imm32', 'bcrypt','Avrt'] + 'shell32', 'advapi32', 'dinput8', 'dxguid', 'imm32', 'bcrypt','Avrt', + 'dwmapi'] env.Append(LINKFLAGS=[p + env["LIBSUFFIX"] for p in LIBS]) if manual_msvc_config: @@ -348,7 +349,7 @@ def configure_mingw(env): env.Append(CCFLAGS=['-mwindows']) env.Append(CPPDEFINES=['WINDOWS_ENABLED', 'OPENGL_ENABLED', 'WASAPI_ENABLED', 'WINMIDI_ENABLED']) env.Append(CPPDEFINES=[('WINVER', env['target_win_version']), ('_WIN32_WINNT', env['target_win_version'])]) - env.Append(LIBS=['mingw32', 'opengl32', 'dsound', 'ole32', 'd3d9', 'winmm', 'gdi32', 'iphlpapi', 'shlwapi', 'wsock32', 'ws2_32', 'kernel32', 'oleaut32', 'dinput8', 'dxguid', 'ksuser', 'imm32', 'bcrypt', 'avrt', 'uuid']) + env.Append(LIBS=['mingw32', 'opengl32', 'dsound', 'ole32', 'd3d9', 'winmm', 'gdi32', 'iphlpapi', 'shlwapi', 'wsock32', 'ws2_32', 'kernel32', 'oleaut32', 'dinput8', 'dxguid', 'ksuser', 'imm32', 'bcrypt', 'avrt', 'uuid', 'dwmapi']) env.Append(CPPDEFINES=['MINGW_ENABLED', ('MINGW_HAS_SECURE_API', 1)]) diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp index 3abb05b494..858453ddfd 100644 --- a/platform/windows/export/export.cpp +++ b/platform/windows/export/export.cpp @@ -39,6 +39,7 @@ static Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, class EditorExportPlatformWindows : public EditorExportPlatformPC { + void _rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path); Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path); public: @@ -62,15 +63,50 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> return err; } + _rcedit_add_data(p_preset, p_path); + + if (p_preset->get("codesign/enable") && err == OK) { + err = _code_sign(p_preset, p_path); + } + + return err; +} + +void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_options) { + EditorExportPlatformPC::get_export_options(r_options); + + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/enable"), false)); +#ifdef WINDOWS_ENABLED + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/identity_type", PROPERTY_HINT_ENUM, "Select automatically,Use PKCS12 file (specify *.PFX/*.P12 file),Use certificate store (specify SHA1 hash)"), 0)); +#endif + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_GLOBAL_FILE, "*.pfx,*.p12"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/password"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/timestamp"), true)); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/timestamp_server_url"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/digest_algorithm", PROPERTY_HINT_ENUM, "SHA1,SHA256"), 1)); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/description"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::POOL_STRING_ARRAY, "codesign/custom_options"), PoolStringArray())); + + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.ico"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/company_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Company Name"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_description"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/trademarks"), "")); +} + +void EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path) { String rcedit_path = EditorSettings::get_singleton()->get("export/windows/rcedit"); if (rcedit_path == String()) { - return OK; + return; } if (!FileAccess::exists(rcedit_path)) { - ERR_PRINTS("Could not find rcedit executable at " + rcedit_path + ", aborting."); - return ERR_FILE_NOT_FOUND; + ERR_PRINTS("Could not find rcedit executable at " + rcedit_path + ", no icon or app information data will be included."); + return; } #ifndef WINDOWS_ENABLED @@ -78,8 +114,8 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> String wine_path = EditorSettings::get_singleton()->get("export/windows/wine"); if (wine_path != String() && !FileAccess::exists(wine_path)) { - ERR_PRINTS("Could not find wine executable at " + wine_path + ", aborting."); - return ERR_FILE_NOT_FOUND; + ERR_PRINTS("Could not find wine executable at " + wine_path + ", no icon or app information data will be included."); + return; } if (wine_path == String()) { @@ -144,37 +180,6 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> args.push_front(rcedit_path); OS::get_singleton()->execute(wine_path, args, true); #endif - - if (p_preset->get("codesign/enable") && err == OK) { - err = _code_sign(p_preset, p_path); - } - - return err; -} - -void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_options) { - EditorExportPlatformPC::get_export_options(r_options); - - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/enable"), false)); -#ifdef WINDOWS_ENABLED - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/identity_type", PROPERTY_HINT_ENUM, "Select automatically,Use PKCS12 file (specify *.PFX/*.P12 file),Use certificate store (specify SHA1 hash)"), 0)); -#endif - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_GLOBAL_FILE, "*.pfx,*.p12"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/password"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/timestamp"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/timestamp_server_url"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/digest_algorithm", PROPERTY_HINT_ENUM, "SHA1,SHA256"), 1)); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/description"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::POOL_STRING_ARRAY, "codesign/custom_options"), PoolStringArray())); - - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.ico"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/company_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Company Name"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_description"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/trademarks"), "")); } Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path) { diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 429657f332..f749134f3c 100755 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -1480,6 +1480,7 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int video_driver_index = p_video_driver; gl_context->set_use_vsync(video_mode.use_vsync); + set_vsync_via_compositor(video_mode.vsync_via_compositor); #endif visual_server = memnew(VisualServerRaster); @@ -1494,8 +1495,6 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int power_manager = memnew(PowerWindows); - camera_server = memnew(CameraWindows); - AudioDriverManager::initialize(p_audio_driver); TRACKMOUSEEVENT tme; @@ -1649,7 +1648,6 @@ void OS_Windows::finalize() { memdelete(joypad); memdelete(input); - memdelete(camera_server); touch_state.clear(); cursors_cache.clear(); diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index ce279fb033..28fec27216 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -31,7 +31,6 @@ #ifndef OS_WINDOWS_H #define OS_WINDOWS_H -#include "camera_win.h" #include "context_gl_windows.h" #include "core/os/input.h" #include "core/os/os.h" @@ -175,7 +174,6 @@ class OS_Windows : public OS { ContextGL_Windows *gl_context; #endif VisualServer *visual_server; - CameraWindows *camera_server; int pressrc; HINSTANCE hInstance; // Holds The Instance Of The Application HWND hWnd; diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 54d3759cc5..39d5c0e84e 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -596,9 +596,6 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a AudioDriverManager::initialize(p_audio_driver); - ///@TODO implement a subclass for Linux and instantiate that instead - camera_server = memnew(CameraServer); - input = memnew(InputDefault); window_has_focus = true; // Set focus to true at init @@ -832,8 +829,6 @@ void OS_X11::finalize() { memdelete(input); - memdelete(camera_server); - cursors_cache.clear(); visual_server->finish(); memdelete(visual_server); diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index a5576f4402..d02160fab7 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -42,7 +42,6 @@ #include "main/input_default.h" #include "power_x11.h" #include "servers/audio_server.h" -#include "servers/camera_server.h" #include "servers/visual/rasterizer.h" #include "servers/visual_server.h" //#include "servers/visual/visual_server_wrap_mt.h" @@ -150,8 +149,6 @@ class OS_X11 : public OS_Unix { void get_key_modifier_state(unsigned int p_x11_state, Ref<InputEventWithModifiers> state); void flush_mouse_motion(); - CameraServer *camera_server; - MouseMode mouse_mode; Point2i center; diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp index ad405fabbb..af3ed671aa 100644 --- a/scene/2d/line_2d.cpp +++ b/scene/2d/line_2d.cpp @@ -47,6 +47,7 @@ Line2D::Line2D() { _texture_mode = LINE_TEXTURE_NONE; _sharp_limit = 2.f; _round_precision = 8; + _antialiased = false; } Rect2 Line2D::_edit_get_rect() const { @@ -260,6 +261,15 @@ int Line2D::get_round_precision() const { return _round_precision; } +void Line2D::set_antialiased(bool p_antialiased) { + _antialiased = p_antialiased; + update(); +} + +bool Line2D::get_antialiased() const { + return _antialiased; +} + void Line2D::_draw() { if (_points.size() <= 1 || _width == 0.f) return; @@ -305,8 +315,8 @@ void Line2D::_draw() { lb.vertices, lb.colors, lb.uvs, Vector<int>(), Vector<float>(), - - texture_rid); + texture_rid, -1, RID(), + _antialiased); // DEBUG // Draw wireframe @@ -386,6 +396,9 @@ void Line2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_round_precision", "precision"), &Line2D::set_round_precision); ClassDB::bind_method(D_METHOD("get_round_precision"), &Line2D::get_round_precision); + ClassDB::bind_method(D_METHOD("set_antialiased", "antialiased"), &Line2D::set_antialiased); + ClassDB::bind_method(D_METHOD("get_antialiased"), &Line2D::get_antialiased); + ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "points"), "set_points", "get_points"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "width"), "set_width", "get_width"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "width_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve", "get_curve"); @@ -401,6 +414,7 @@ void Line2D::_bind_methods() { ADD_GROUP("Border", ""); ADD_PROPERTY(PropertyInfo(Variant::REAL, "sharp_limit"), "set_sharp_limit", "get_sharp_limit"); ADD_PROPERTY(PropertyInfo(Variant::INT, "round_precision"), "set_round_precision", "get_round_precision"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "antialiased"), "set_antialiased", "get_antialiased"); BIND_ENUM_CONSTANT(LINE_JOINT_SHARP); BIND_ENUM_CONSTANT(LINE_JOINT_BEVEL); diff --git a/scene/2d/line_2d.h b/scene/2d/line_2d.h index 14afa463ba..10b2bf16e4 100644 --- a/scene/2d/line_2d.h +++ b/scene/2d/line_2d.h @@ -108,6 +108,9 @@ public: void set_round_precision(int precision); int get_round_precision() const; + void set_antialiased(bool p_antialiased); + bool get_antialiased() const; + protected: void _notification(int p_what); void _draw(); @@ -131,6 +134,7 @@ private: LineTextureMode _texture_mode; float _sharp_limit; int _round_precision; + bool _antialiased; }; #endif // LINE2D_H diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp index 55c8c7f229..18ace5892a 100644 --- a/scene/2d/path_2d.cpp +++ b/scene/2d/path_2d.cpp @@ -173,16 +173,10 @@ void PathFollow2D::_update_transform() { if (path_length == 0) { return; } - float bounded_offset = offset; - if (loop) - bounded_offset = Math::fposmod(bounded_offset, path_length); - else - bounded_offset = CLAMP(bounded_offset, 0, path_length); - - Vector2 pos = c->interpolate_baked(bounded_offset, cubic); + Vector2 pos = c->interpolate_baked(offset, cubic); if (rotate) { - float ahead = bounded_offset + lookahead; + float ahead = offset + lookahead; if (loop && ahead >= path_length) { // If our lookahead will loop, we need to check if the path is closed. @@ -206,7 +200,7 @@ void PathFollow2D::_update_transform() { // This will happen at the end of non-looping or non-closed paths. // We'll try a look behind instead, in order to get a meaningful angle. tangent_to_curve = - (pos - c->interpolate_baked(bounded_offset - lookahead, cubic)).normalized(); + (pos - c->interpolate_baked(offset - lookahead, cubic)).normalized(); } else { tangent_to_curve = (ahead_pos - pos).normalized(); } diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 3a4f397fe0..a57bfd4cbe 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -1214,18 +1214,20 @@ bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { - Vector2 floor_motion = floor_velocity; + Vector2 body_velocity = p_linear_velocity; + Vector2 body_velocity_normal = body_velocity.normalized(); + + Vector2 current_floor_velocity = floor_velocity; if (on_floor && on_floor_body.is_valid()) { //this approach makes sure there is less delay between the actual body velocity and the one we saved Physics2DDirectBodyState *bs = Physics2DServer::get_singleton()->body_get_direct_state(on_floor_body); if (bs) { - floor_motion = bs->get_linear_velocity(); + current_floor_velocity = bs->get_linear_velocity(); } } // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky - Vector2 motion = (floor_motion + p_linear_velocity) * (Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time()); - Vector2 lv = p_linear_velocity; + Vector2 motion = (current_floor_velocity + body_velocity) * (Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time()); on_floor = false; on_floor_body = RID(); @@ -1234,14 +1236,12 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const colliders.clear(); floor_velocity = Vector2(); - Vector2 lv_n = p_linear_velocity.normalized(); - while (p_max_slides) { Collision collision; bool found_collision = false; - for (int i = 0; i < 2; i++) { + for (int i = 0; i < 2; ++i) { bool collided; if (i == 0) { //collide collided = move_and_collide(motion, p_infinite_inertia, collision); @@ -1273,14 +1273,13 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const floor_velocity = collision.collider_vel; if (p_stop_on_slope) { - if ((lv_n + p_floor_direction).length() < 0.01 && collision.travel.length() < 1) { + if ((body_velocity_normal + p_floor_direction).length() < 0.01 && collision.travel.length() < 1) { Transform2D gt = get_global_transform(); - gt.elements[2] -= collision.travel.project(p_floor_direction.tangent()); + gt.elements[2] -= collision.travel.slide(p_floor_direction); set_global_transform(gt); return Vector2(); } } - } else if (Math::acos(collision.normal.dot(-p_floor_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling on_ceiling = true; } else { @@ -1288,21 +1287,18 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const } } - Vector2 n = collision.normal; - motion = motion.slide(n); - lv = lv.slide(n); + motion = motion.slide(collision.normal); + body_velocity = body_velocity.slide(collision.normal); } } - if (!found_collision) { - break; - } - p_max_slides--; - if (motion == Vector2()) + if (!found_collision || motion == Vector2()) break; + + --p_max_slides; } - return lv; + return body_velocity; } Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_floor_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp index 5e14959e9d..9fe67a4d7e 100644 --- a/scene/2d/polygon_2d.cpp +++ b/scene/2d/polygon_2d.cpp @@ -308,7 +308,7 @@ void Polygon2D::_notification(int p_what) { if (invert || polygons.size() == 0) { Vector<int> indices = Geometry::triangulate_polygon(points); if (indices.size()) { - VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID()); + VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID(), -1, RID(), antialiased); } } else { //draw individual polygons @@ -342,7 +342,7 @@ void Polygon2D::_notification(int p_what) { } if (total_indices.size()) { - VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), total_indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID()); + VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), total_indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID(), -1, RID(), antialiased); } #if 0 diff --git a/scene/3d/path.cpp b/scene/3d/path.cpp index d55c795d38..62684bd1e1 100644 --- a/scene/3d/path.cpp +++ b/scene/3d/path.cpp @@ -111,18 +111,15 @@ void PathFollow::_update_transform() { return; } float bi = c->get_bake_interval(); - float o = offset; float o_next = offset + bi; if (loop) { - o = Math::fposmod(o, bl); o_next = Math::fposmod(o_next, bl); } else if (rotation_mode == ROTATION_ORIENTED && o_next >= bl) { - o = bl - bi; o_next = bl; } - Vector3 pos = c->interpolate_baked(o, cubic); + Vector3 pos = c->interpolate_baked(offset, cubic); Transform t = get_transform(); // Vector3 pos_offset = Vector3(h_offset, v_offset, 0); not used in all cases // will be replaced by "Vector3(h_offset, v_offset, 0)" where it was formerly used @@ -136,9 +133,9 @@ void PathFollow::_update_transform() { else forward.normalize(); - Vector3 up = c->interpolate_baked_up_vector(o, true); + Vector3 up = c->interpolate_baked_up_vector(offset, true); - if (o_next < o) { + if (o_next < offset) { Vector3 up1 = c->interpolate_baked_up_vector(o_next, true); Vector3 axis = up.cross(up1); @@ -166,8 +163,8 @@ void PathFollow::_update_transform() { t.origin = pos; - Vector3 t_prev = (pos - c->interpolate_baked(o - delta_offset, cubic)).normalized(); - Vector3 t_cur = (c->interpolate_baked(o + delta_offset, cubic) - pos).normalized(); + Vector3 t_prev = (pos - c->interpolate_baked(offset - delta_offset, cubic)).normalized(); + Vector3 t_cur = (c->interpolate_baked(offset + delta_offset, cubic) - pos).normalized(); Vector3 axis = t_prev.cross(t_cur); float dot = t_prev.dot(t_cur); @@ -190,7 +187,7 @@ void PathFollow::_update_transform() { } // do the additional tilting - float tilt_angle = c->interpolate_baked_tilt(o); + float tilt_angle = c->interpolate_baked_tilt(offset); Vector3 tilt_axis = t_cur; // not sure what tilt is supposed to do, is this correct?? if (likely(!Math::is_zero_approx(Math::abs(tilt_angle)))) { @@ -256,7 +253,7 @@ void PathFollow::_validate_property(PropertyInfo &property) const { if (path && path->get_curve().is_valid()) max = path->get_curve()->get_baked_length(); - property.hint_string = "0," + rtos(max) + ",0.01,or_greater"; + property.hint_string = "0," + rtos(max) + ",0.01,or_lesser"; } } @@ -300,8 +297,8 @@ void PathFollow::_bind_methods() { ClassDB::bind_method(D_METHOD("set_loop", "loop"), &PathFollow::set_loop); ClassDB::bind_method(D_METHOD("has_loop"), &PathFollow::has_loop); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "offset", PROPERTY_HINT_RANGE, "0,10000,0.01,or_greater"), "set_offset", "get_offset"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_offset", PROPERTY_HINT_RANGE, "0,1,0.0001,or_greater", PROPERTY_USAGE_EDITOR), "set_unit_offset", "get_unit_offset"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "offset", PROPERTY_HINT_RANGE, "0,10000,0.01,or_lesser"), "set_offset", "get_offset"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_offset", PROPERTY_HINT_RANGE, "0,1,0.0001,or_lesser", PROPERTY_USAGE_EDITOR), "set_unit_offset", "get_unit_offset"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "h_offset"), "set_h_offset", "get_h_offset"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "v_offset"), "set_v_offset", "get_v_offset"); ADD_PROPERTY(PropertyInfo(Variant::INT, "rotation_mode", PROPERTY_HINT_ENUM, "None,Y,XY,XYZ,Oriented"), "set_rotation_mode", "get_rotation_mode"); @@ -319,8 +316,24 @@ void PathFollow::set_offset(float p_offset) { delta_offset = p_offset - offset; offset = p_offset; - if (path) + if (path) { + if (path->get_curve().is_valid() && path->get_curve()->get_baked_length()) { + float path_length = path->get_curve()->get_baked_length(); + + if (loop) { + while (offset > path_length) + offset -= path_length; + + while (offset < 0) + offset += path_length; + + } else { + offset = CLAMP(offset, 0, path_length); + } + } + _update_transform(); + } _change_notify("offset"); _change_notify("unit_offset"); } diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index a107c3bf7a..6049b6cdb4 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -1142,25 +1142,34 @@ bool KinematicBody::move_and_collide(const Vector3 &p_motion, bool p_infinite_in Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { - Vector3 lv = p_linear_velocity; + Vector3 body_velocity = p_linear_velocity; + Vector3 body_velocity_normal = body_velocity.normalized(); for (int i = 0; i < 3; i++) { if (locked_axis & (1 << i)) { - lv[i] = 0; + body_velocity[i] = 0; + } + } + + Vector3 current_floor_velocity = floor_velocity; + if (on_floor && on_floor_body.is_valid()) { + //this approach makes sure there is less delay between the actual body velocity and the one we saved + PhysicsDirectBodyState *bs = PhysicsServer::get_singleton()->body_get_direct_state(on_floor_body); + if (bs) { + current_floor_velocity = bs->get_linear_velocity(); } } // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky - Vector3 motion = (floor_velocity + lv) * (Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time()); + Vector3 motion = (current_floor_velocity + body_velocity) * (Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time()); on_floor = false; + on_floor_body = RID(); on_ceiling = false; on_wall = false; colliders.clear(); floor_velocity = Vector3(); - Vector3 lv_n = p_linear_velocity.normalized(); - while (p_max_slides) { Collision collision; @@ -1187,7 +1196,6 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve colliders.push_back(collision); motion = collision.remainder; - bool is_on_slope = false; if (p_floor_direction == Vector3()) { //all is a wall on_wall = true; @@ -1199,16 +1207,13 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve floor_velocity = collision.collider_vel; if (p_stop_on_slope) { - if ((lv_n + p_floor_direction).length() < 0.01 && collision.travel.length() < 1) { + if ((body_velocity_normal + p_floor_direction).length() < 0.01 && collision.travel.length() < 1) { Transform gt = get_global_transform(); gt.origin -= collision.travel.slide(p_floor_direction); set_global_transform(gt); return Vector3(); } } - - is_on_slope = true; - } else if (Math::acos(collision.normal.dot(-p_floor_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling on_ceiling = true; } else { @@ -1216,18 +1221,12 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve } } - if (p_stop_on_slope && is_on_slope) { - motion = motion.slide(p_floor_direction); - lv = lv.slide(p_floor_direction); - } else { - Vector3 n = collision.normal; - motion = motion.slide(n); - lv = lv.slide(n); - } + motion = motion.slide(collision.normal); + body_velocity = body_velocity.slide(collision.normal); for (int j = 0; j < 3; j++) { if (locked_axis & (1 << j)) { - lv[j] = 0; + body_velocity[j] = 0; } } } @@ -1239,7 +1238,7 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve --p_max_slides; } - return lv; + return body_velocity; } Vector3 KinematicBody::move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_floor_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { @@ -2161,6 +2160,9 @@ void PhysicalBone::_notification(int p_what) { update_bone_id(); reset_to_rest_position(); _reset_physics_simulation_state(); + if (!joint.is_valid() && joint_data) { + _reload_joint(); + } break; case NOTIFICATION_EXIT_TREE: if (parent_skeleton) { @@ -2169,7 +2171,10 @@ void PhysicalBone::_notification(int p_what) { } } parent_skeleton = NULL; - update_bone_id(); + if (joint.is_valid()) { + PhysicsServer::get_singleton()->free(joint); + joint = RID(); + } break; case NOTIFICATION_TRANSFORM_CHANGED: if (Engine::get_singleton()->is_editor_hint()) { diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp index 9a659ef4af..043d5d5548 100644 --- a/scene/3d/spatial.cpp +++ b/scene/3d/spatial.cpp @@ -322,6 +322,7 @@ Transform Spatial::get_relative_transform(const Node *p_parent) const { void Spatial::set_translation(const Vector3 &p_translation) { data.local_transform.origin = p_translation; + _change_notify("transform"); _propagate_transform_changed(this); if (data.notify_local_transform) { notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); @@ -337,6 +338,7 @@ void Spatial::set_rotation(const Vector3 &p_euler_rad) { data.rotation = p_euler_rad; data.dirty |= DIRTY_LOCAL; + _change_notify("transform"); _propagate_transform_changed(this); if (data.notify_local_transform) { notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); @@ -357,6 +359,7 @@ void Spatial::set_scale(const Vector3 &p_scale) { data.scale = p_scale; data.dirty |= DIRTY_LOCAL; + _change_notify("transform"); _propagate_transform_changed(this); if (data.notify_local_transform) { notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp index 65bf1e0134..a37b75d428 100644 --- a/scene/animation/animation_node_state_machine.cpp +++ b/scene/animation/animation_node_state_machine.cpp @@ -312,27 +312,36 @@ float AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_st bool play_start = false; if (start_request != StringName()) { - if (start_request_travel) { if (!playing) { - String node_name = start_request; - start_request = StringName(); - ERR_FAIL_V_MSG(0, "Can't travel to '" + node_name + "' if state machine is not playing."); - } - - if (!_travel(p_state_machine, start_request)) { - //can't travel, then teleport - path.clear(); - current = start_request; + if (!stop_request && p_state_machine->start_node) { + // can restart, just postpone traveling + path.clear(); + current = p_state_machine->start_node; + playing = true; + play_start = true; + } else { + // stopped, invalid state + String node_name = start_request; + start_request = StringName(); //clear start request + ERR_FAIL_V_MSG(0, "Can't travel to '" + node_name + "' if state machine is not playing."); + } + } else { + if (!_travel(p_state_machine, start_request)) { + // can't travel, then teleport + path.clear(); + current = start_request; + } + start_request = StringName(); //clear start request } } else { + // teleport to start path.clear(); current = start_request; playing = true; play_start = true; + start_request = StringName(); //clear start request } - - start_request = StringName(); //clear start request } bool do_start = (p_seek && p_time == 0) || play_start || current == StringName(); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index ab6f80bfa9..e6a27aa63f 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -823,7 +823,7 @@ void LineEdit::_notification(int p_what) { int yofs = y_ofs + (caret_height - font->get_height()) / 2; drawer.draw_char(ci, Point2(x_ofs, yofs + font_ascent), cchar, next, selected ? font_color_selected : font_color); - if (char_ofs == cursor_pos && draw_caret) { + if (char_ofs == cursor_pos && draw_caret && !using_placeholder) { if (ime_text.length() == 0) { #ifdef TOOLS_ENABLED VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(Math::round(EDSCALE), caret_height)), cursor_color); @@ -866,12 +866,27 @@ void LineEdit::_notification(int p_what) { } } - if (char_ofs == cursor_pos && draw_caret) { // May be at the end. + if ((char_ofs == cursor_pos || using_placeholder) && draw_caret) { // May be at the end, or placeholder. if (ime_text.length() == 0) { + int caret_x_ofs = x_ofs; + if (using_placeholder) { + switch (align) { + case ALIGN_LEFT: + case ALIGN_FILL: { + caret_x_ofs = style->get_offset().x; + } break; + case ALIGN_CENTER: { + caret_x_ofs = ofs_max / 2; + } break; + case ALIGN_RIGHT: { + caret_x_ofs = ofs_max; + } break; + } + } #ifdef TOOLS_ENABLED - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(Math::round(EDSCALE), caret_height)), cursor_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(caret_x_ofs, y_ofs), Size2(Math::round(EDSCALE), caret_height)), cursor_color); #else - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(1, caret_height)), cursor_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(caret_x_ofs, y_ofs), Size2(1, caret_height)), cursor_color); #endif } } @@ -970,6 +985,8 @@ void LineEdit::undo() { undo_stack_pos = undo_stack_pos->prev(); TextOperation op = undo_stack_pos->get(); text = op.text; + cached_width = op.cached_width; + window_pos = op.window_pos; set_cursor_position(op.cursor_pos); if (expand_to_text_length) @@ -988,6 +1005,8 @@ void LineEdit::redo() { undo_stack_pos = undo_stack_pos->next(); TextOperation op = undo_stack_pos->get(); text = op.text; + cached_width = op.cached_width; + window_pos = op.window_pos; set_cursor_position(op.cursor_pos); if (expand_to_text_length) @@ -1169,6 +1188,10 @@ void LineEdit::delete_char() { set_cursor_position(get_cursor_position() - 1); + if (align == ALIGN_CENTER || align == ALIGN_RIGHT) { + window_pos = CLAMP(window_pos - 1, 0, text.length() - 1); + } + _text_changed(); } @@ -1196,6 +1219,10 @@ void LineEdit::delete_text(int p_from_column, int p_to_column) { window_pos = cursor_pos; } + if (align == ALIGN_CENTER || align == ALIGN_RIGHT) { + window_pos = CLAMP(window_pos - (p_to_column - p_from_column), 0, text.length() - 1); + } + if (!text_changed_dirty) { if (is_inside_tree()) { MessageQueue::get_singleton()->push_call(this, "_text_changed"); @@ -1677,7 +1704,9 @@ void LineEdit::_clear_undo_stack() { void LineEdit::_create_undo_state() { TextOperation op; op.text = text; + op.cached_width = cached_width; op.cursor_pos = cursor_pos; + op.window_pos = window_pos; undo_stack.push_back(op); } diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 3424131dad..ebe49091eb 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -106,6 +106,8 @@ private: struct TextOperation { int cursor_pos; + int window_pos; + int cached_width; String text; }; List<TextOperation> undo_stack; diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index 7d62873bbd..5ce269fff9 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -397,6 +397,9 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map if (p_owner->get_scene_inherited_state().is_null() && (p_node == p_owner || (p_node->get_owner() == p_owner && (p_node->get_parent() == p_owner || p_node->get_parent()->get_owner() == p_owner)))) { //do not save index, because it belongs to saved scene and scene is not inherited nd.index = -1; + } else if (p_node == p_owner) { + //This (hopefully) happens if the node is a scene root, so its index is irrelevant. + nd.index = -1; } else { //part of an inherited scene, or parent is from an instanced scene nd.index = p_node->get_index(); diff --git a/servers/camera_server.cpp b/servers/camera_server.cpp index 0f93221072..6912a37fc5 100644 --- a/servers/camera_server.cpp +++ b/servers/camera_server.cpp @@ -35,6 +35,8 @@ //////////////////////////////////////////////////////// // CameraServer +CameraServer::CreateFunc CameraServer::create_func = NULL; + void CameraServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_feed", "index"), &CameraServer::get_feed); ClassDB::bind_method(D_METHOD("get_feed_count"), &CameraServer::get_feed_count); diff --git a/servers/camera_server.h b/servers/camera_server.h index c76d046e58..aa10f4dbb9 100644 --- a/servers/camera_server.h +++ b/servers/camera_server.h @@ -59,17 +59,36 @@ public: FEED_IMAGES = 2 }; + typedef CameraServer *(*CreateFunc)(); + private: protected: + static CreateFunc create_func; + Vector<Ref<CameraFeed> > feeds; static CameraServer *singleton; static void _bind_methods(); + template <class T> + static CameraServer *_create_builtin() { + return memnew(T); + } + public: static CameraServer *get_singleton(); + template <class T> + static void make_default() { + create_func = _create_builtin<T>; + } + + static CameraServer *create() { + CameraServer *server = create_func ? create_func() : memnew(CameraServer); + return server; + }; + // Right now we identify our feed by it's ID when it's used in the background. // May see if we can change this to purely relying on CameraFeed objects or by name. int get_free_id(); diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 316a94556d..a7ff4f35db 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -5099,7 +5099,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (!expr) return ERR_PARSE_ERROR; - if (expr->type != Node::TYPE_CONSTANT) { + if (expr->type == Node::TYPE_OPERATOR && ((OperatorNode *)expr)->op == OP_CALL) { _set_error("Expected constant expression after '='"); return ERR_PARSE_ERROR; } diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp index 7bb97e0577..49b5562b6c 100644 --- a/servers/visual/visual_server_canvas.cpp +++ b/servers/visual/visual_server_canvas.cpp @@ -783,7 +783,7 @@ void VisualServerCanvas::canvas_item_add_polygon(RID p_item, const Vector<Point2 canvas_item->commands.push_back(polygon); } -void VisualServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, const Vector<int> &p_bones, const Vector<float> &p_weights, RID p_texture, int p_count, RID p_normal_map) { +void VisualServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, const Vector<int> &p_bones, const Vector<float> &p_weights, RID p_texture, int p_count, RID p_normal_map, bool p_antialiased) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -822,7 +822,7 @@ void VisualServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vector polygon->weights = p_weights; polygon->indices = indices; polygon->count = count; - polygon->antialiased = false; + polygon->antialiased = p_antialiased; canvas_item->rect_dirty = true; canvas_item->commands.push_back(polygon); diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h index 822e3f8ce3..cf2eefdec6 100644 --- a/servers/visual/visual_server_canvas.h +++ b/servers/visual/visual_server_canvas.h @@ -200,7 +200,7 @@ public: void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, VS::NinePatchAxisMode p_x_axis_mode = VS::NINE_PATCH_STRETCH, VS::NinePatchAxisMode p_y_axis_mode = VS::NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1), RID p_normal_map = RID()); void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID()); void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), RID p_normal_map = RID(), bool p_antialiased = false); - void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID()); + void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID(), bool p_antialiased = false); void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID(), RID p_normal_map = RID()); void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID()); void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal); diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 06096781fe..4cef86db30 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -602,7 +602,7 @@ public: BIND11(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &, RID) BIND7(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float, RID) BIND7(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, RID, bool) - BIND10(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID) + BIND11(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID, bool) BIND6(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID, RID) BIND4(canvas_item_add_multimesh, RID, RID, RID, RID) BIND4(canvas_item_add_particles, RID, RID, RID, RID) diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index 59df51ff19..ff42dcf00b 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -520,7 +520,7 @@ public: FUNC11(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &, RID) FUNC7(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float, RID) FUNC7(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, RID, bool) - FUNC10(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID) + FUNC11(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID, bool) FUNC6(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID, RID) FUNC4(canvas_item_add_multimesh, RID, RID, RID, RID) FUNC4(canvas_item_add_particles, RID, RID, RID, RID) diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index a1ba946d8c..2c1d28e32c 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -1717,6 +1717,7 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("mesh_get_custom_aabb", "mesh"), &VisualServer::mesh_get_custom_aabb); ClassDB::bind_method(D_METHOD("mesh_clear", "mesh"), &VisualServer::mesh_clear); + ClassDB::bind_method(D_METHOD("multimesh_create"), &VisualServer::multimesh_create); ClassDB::bind_method(D_METHOD("multimesh_allocate", "multimesh", "instances", "transform_format", "color_format", "custom_data_format"), &VisualServer::multimesh_allocate, DEFVAL(MULTIMESH_CUSTOM_DATA_NONE)); ClassDB::bind_method(D_METHOD("multimesh_get_instance_count", "multimesh"), &VisualServer::multimesh_get_instance_count); ClassDB::bind_method(D_METHOD("multimesh_set_mesh", "multimesh", "mesh"), &VisualServer::multimesh_set_mesh); @@ -1973,7 +1974,7 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("canvas_item_add_nine_patch", "item", "rect", "source", "texture", "topleft", "bottomright", "x_axis_mode", "y_axis_mode", "draw_center", "modulate", "normal_map"), &VisualServer::canvas_item_add_nine_patch, DEFVAL(NINE_PATCH_STRETCH), DEFVAL(NINE_PATCH_STRETCH), DEFVAL(true), DEFVAL(Color(1, 1, 1)), DEFVAL(RID())); ClassDB::bind_method(D_METHOD("canvas_item_add_primitive", "item", "points", "colors", "uvs", "texture", "width", "normal_map"), &VisualServer::canvas_item_add_primitive, DEFVAL(1.0), DEFVAL(RID())); ClassDB::bind_method(D_METHOD("canvas_item_add_polygon", "item", "points", "colors", "uvs", "texture", "normal_map", "antialiased"), &VisualServer::canvas_item_add_polygon, DEFVAL(Vector<Point2>()), DEFVAL(RID()), DEFVAL(RID()), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("canvas_item_add_triangle_array", "item", "indices", "points", "colors", "uvs", "bones", "weights", "texture", "count", "normal_map"), &VisualServer::canvas_item_add_triangle_array, DEFVAL(Vector<Point2>()), DEFVAL(Vector<int>()), DEFVAL(Vector<float>()), DEFVAL(RID()), DEFVAL(-1), DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("canvas_item_add_triangle_array", "item", "indices", "points", "colors", "uvs", "bones", "weights", "texture", "count", "normal_map", "antialiased"), &VisualServer::canvas_item_add_triangle_array, DEFVAL(Vector<Point2>()), DEFVAL(Vector<int>()), DEFVAL(Vector<float>()), DEFVAL(RID()), DEFVAL(-1), DEFVAL(RID()), DEFVAL(false)); ClassDB::bind_method(D_METHOD("canvas_item_add_mesh", "item", "mesh", "transform", "modulate", "texture", "normal_map"), &VisualServer::canvas_item_add_mesh, DEFVAL(Transform2D()), DEFVAL(Color(1, 1, 1)), DEFVAL(RID()), DEFVAL(RID())); ClassDB::bind_method(D_METHOD("canvas_item_add_multimesh", "item", "mesh", "texture", "normal_map"), &VisualServer::canvas_item_add_multimesh, DEFVAL(RID())); ClassDB::bind_method(D_METHOD("canvas_item_add_particles", "item", "particles", "texture", "normal_map"), &VisualServer::canvas_item_add_particles); diff --git a/servers/visual_server.h b/servers/visual_server.h index b1daf87e56..acf02eee56 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -903,7 +903,7 @@ public: virtual void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, NinePatchAxisMode p_x_axis_mode = NINE_PATCH_STRETCH, NinePatchAxisMode p_y_axis_mode = NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1), RID p_normal_map = RID()) = 0; virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID()) = 0; virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), RID p_normal_map = RID(), bool p_antialiased = false) = 0; - virtual void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID()) = 0; + virtual void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID(), bool p_antialiased = false) = 0; virtual void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID(), RID p_normal_map = RID()) = 0; virtual void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID()) = 0; virtual void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal_map) = 0; diff --git a/thirdparty/misc/ifaddrs-android.h b/thirdparty/misc/ifaddrs-android.h index 6e204af26f..8de94324b8 100644 --- a/thirdparty/misc/ifaddrs-android.h +++ b/thirdparty/misc/ifaddrs-android.h @@ -32,6 +32,11 @@ // Fills out a list of ifaddr structs (see below) which contain information // about every network interface available on the host. // See 'man getifaddrs' on Linux or OS X (nb: it is not a POSIX function). +// -- GODOT start -- +#ifdef __cplusplus +extern "C" { +#endif +// -- GODOT end -- struct ifaddrs { struct ifaddrs* ifa_next; char* ifa_name; @@ -40,7 +45,21 @@ struct ifaddrs { struct sockaddr* ifa_netmask; // Real ifaddrs has broadcast, point to point and data members. // We don't need them (yet?). + // -- GODOT start -- + // We never initialize the following members. We only define them to match the ifaddrs struct. + union + { + struct sockaddr *ifu_broadaddr; + struct sockaddr *ifu_dstaddr; + } ifa_ifu; + void *ifa_data; + // -- GODOT end -- }; +// -- GODOT start -- +#ifdef __cplusplus +} +#endif +// -- GODOT end -- int getifaddrs(struct ifaddrs** result); void freeifaddrs(struct ifaddrs* addrs); #endif // TALK_BASE_IFADDRS_ANDROID_H_ |