diff options
214 files changed, 2237 insertions, 1264 deletions
diff --git a/AUTHORS.md b/AUTHORS.md index 9666145582..13a67ce3f5 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -45,9 +45,11 @@ name is available. Bojidar Marinov (bojidar-bg) bruvzg Carl Olsson (not-surt) + Chris Bradfield (cbscribe) Dana Olson (adolson) Daniel J. Ramirez (djrm) Dmitry Koteroff (Krakean) + DualMatrix Emmanuel Leblond (touilleMan) Eric Lasota (elasota) est31 @@ -111,9 +113,9 @@ name is available. Ramesh Ravone (RameshRavone) Ray Koopa (RayKoopa) Rémi Verschelde (akien-mga) + Rhody Lugo (rraallvv) Roberto F. Arroyo (robfram) romulox-x - rraallvv Ruslan Mustakov (endragor) Saniko (sanikoyes) SaracenOne diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 68ec20a525..2ea2ed6bba 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -70,11 +70,15 @@ Similar rules can be applied when contributing bug fixes - it's always best to discuss the implementation in the bug report first if you are not 100% about what would be the best fix. +In addition to the following tips, also take a look at the +[Engine development guide](http://docs.godotengine.org/en/latest/development/cpp/) +for an introduction to developing on Godot. + #### Be nice to the git history -Try to make simple PRs with that handle one specific topic. Just like for -reporting issues, it's better to open 3 different PRs that each address a -different issue than one big PR with three commits. +Try to make simple PRs that handle one specific topic. Just like for reporting +issues, it's better to open 3 different PRs that each address a different issue +than one big PR with three commits. When updating your fork with upstream changes, please use ``git pull --rebase`` to avoid creating "merge commits". Those commits unnecessarily pollute the git @@ -21,40 +21,43 @@ generous deed immortalized in the next stable release of Godot Engine. ## Mini sponsors + Andrew Dunai Brandon Lamb Christian Uldall Pedersen Christopher Igoe Christoph Woinke GameDev.net Hein-Pieter van Braam + iDev.Network Studios Jamal Alyafei Jay Sistar + Leona Eden Matthieu Huvé Mike King Nathan Warden Neal Gompa (Conan Kudo) Pascal Julien Patrick Aarstad - rottis Ruslan Mustakov Slobodan Milnovic Stephan Lanfermann Stoney Meyerhoeffer + thechris Thomas Mathews VilliHaukka ## Gold donors - 3Dexplorer Asdf cheese65536 K9Kraken - Kris Michael Manuele Finocchiaro Nathanael Beisiegel Officine Pixel S.n.c. + Retro Village Zaven Muradyan + 13MHz Allen Schade Andreas Schüle Austen McRae @@ -62,12 +65,14 @@ generous deed immortalized in the next stable release of Godot Engine. David Gehrig Florian Breisch Gary Oberbrunner + Jay Horton Johannes Wuensch Josep G. Camarasa Joshua Lesperance Krzysztof Dluzniewski Kyle Szklenski Mohammad Taleb + Moonwards Paul LaMotte Ranoller Sergey @@ -91,7 +96,6 @@ generous deed immortalized in the next stable release of Godot Engine. Rami Robert Willes Robin Arys - Rodrigo Loli Ronnie Ashlock ScottMakesGames Thomas Bjarnelöf @@ -102,8 +106,8 @@ generous deed immortalized in the next stable release of Godot Engine. Alessandra Pereyra Alexey Dyadchenko Amanda Haldy - Anthony Ryan Branwen Danielle Zakariasen + Chau Siu Hung Chris Brown Chris Petrich Cody Parker @@ -112,15 +116,16 @@ generous deed immortalized in the next stable release of Godot Engine. E.G. Eric Eric Monson + Ethan Bennis Fidget Sinner flesk G Barnes + Gero GGGames.org Giovanni Solimeno Guilherme Felipe de C. G. da Silva Hasen Judy Heath Hayes - Jay Horton Jeppe Zapp joe513 Juraj Móza @@ -130,10 +135,8 @@ generous deed immortalized in the next stable release of Godot Engine. Markus Wiesner Marvin Nahuel Sacchetti - Neal Barry Nick Nikitin Pablo Cholaky - Patrick Schnorbus Pete Goodwin ray-tracer Ruben Soares Luis @@ -141,10 +144,9 @@ generous deed immortalized in the next stable release of Godot Engine. Sindre Sømme Sofox Stoned Xander - Tim Dalporto Trent McPheron - Wilfrid ARNOLD WytRabbit + Zachariah Gibbons ## Silver donors @@ -177,7 +179,6 @@ generous deed immortalized in the next stable release of Godot Engine. Christian Baune Christian Winter Christopher Schmitt - Chris Wilson Collin Shooltz Daniel Johnson Daniel Kaplan @@ -187,16 +188,14 @@ generous deed immortalized in the next stable release of Godot Engine. David May Disktra Dominik Wetzel - dRez Games Duy Kevin Nguyen Edward Herbert Elias Nykrem Eric Martini Eugenio Hugo Salgüero Jáñez - Extarys Fabian Becker fengjiongmax - Francesco Lisi + Foomf G3Dev sà rl Gerrit Großkopf Gilberto K. Otubo @@ -207,7 +206,6 @@ generous deed immortalized in the next stable release of Godot Engine. ialex32x Jahn Johansen Jaime Ruiz-Borau Vizárraga - Jed Jeff Hungerford Joel Fivat Johan Lindberg @@ -237,7 +235,6 @@ generous deed immortalized in the next stable release of Godot Engine. magodev Manolis Makris Martin Eigel - Martins Odabi Max R.R. Collada Maxwell Mertcan Mermerkaya @@ -256,14 +253,15 @@ generous deed immortalized in the next stable release of Godot Engine. Nicolas SAN AGUSTIN Niko Leopold Noi Sek - Pablo Seibelt Pan Ip Pascal Grüter Pat LaBine Patrick Nafarrete Paul E Hansen + Paul Gieske Paul Mason Paweł Kowal + Phillip Ryals Pierre-Igor Berthet Pietro Vertechi Piotr Kaczmarski @@ -287,9 +285,11 @@ generous deed immortalized in the next stable release of Godot Engine. Tim Tom Larrow Tristan Crawford + Tryggve Sollid Trym Nilsen Tyler Stafos UltyX + Vaiktorg Victor Viktor Ferenczi waka nya @@ -40,7 +40,7 @@ Official binaries for the Godot editor and the export templates can be found [See the official docs](http://docs.godotengine.org/en/latest/development/compiling/) for compilation instructions for every supported platform. -### Community +### Community and contributing Godot is not only an engine but an ever-growing community of users and engine developers. The main community channels are listed [on the homepage](https://godotengine.org/community). @@ -49,6 +49,8 @@ To get in touch with the developers, the best way is to join the [#godotengine IRC channel](https://webchat.freenode.net/?channels=godotengine) on Freenode. +To get started contributing to the project, see the [contributing guide](CONTRIBUTING.md). + ### Documentation and demos The official documentation is hosted on [ReadTheDocs](http://docs.godotengine.org). diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 57654e96dc..02b8c71465 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -2487,7 +2487,7 @@ _Thread::~_Thread() { if (active) { ERR_EXPLAIN("Reference to a Thread object object was lost while the thread is still running..."); } - ERR_FAIL_COND(active == true); + ERR_FAIL_COND(active); } ///////////////////////////////////// diff --git a/core/cowdata.h b/core/cowdata.h index 9e75d4ed55..54ece4c856 100644 --- a/core/cowdata.h +++ b/core/cowdata.h @@ -87,7 +87,10 @@ private: #if defined(_add_overflow) && defined(_mul_overflow) size_t o; size_t p; - if (_mul_overflow(p_elements, sizeof(T), &o)) return false; + if (_mul_overflow(p_elements, sizeof(T), &o)) { + *out = 0; + return false; + } *out = next_power_of_2(o); if (_add_overflow(o, static_cast<size_t>(32), &p)) return false; //no longer allocated here return true; diff --git a/core/dictionary.cpp b/core/dictionary.cpp index ba32606819..ccbdff3816 100644 --- a/core/dictionary.cpp +++ b/core/dictionary.cpp @@ -145,6 +145,11 @@ bool Dictionary::operator==(const Dictionary &p_dictionary) const { return _p == p_dictionary._p; } +bool Dictionary::operator!=(const Dictionary &p_dictionary) const { + + return _p != p_dictionary._p; +} + void Dictionary::_ref(const Dictionary &p_from) const { //make a copy first (thread safe) diff --git a/core/dictionary.h b/core/dictionary.h index 9950fb6361..d3b98c2f63 100644 --- a/core/dictionary.h +++ b/core/dictionary.h @@ -69,6 +69,7 @@ public: bool erase(const Variant &p_key); bool operator==(const Dictionary &p_dictionary) const; + bool operator!=(const Dictionary &p_dictionary) const; uint32_t hash() const; void operator=(const Dictionary &p_dictionary); diff --git a/core/dvector.h b/core/dvector.h index 0d0848a19a..2830c57ec0 100644 --- a/core/dvector.h +++ b/core/dvector.h @@ -149,7 +149,7 @@ class PoolVector { } } - if (old_alloc->refcount.unref() == true) { + if (old_alloc->refcount.unref()) { //this should never happen but.. #ifdef DEBUG_ENABLED @@ -209,7 +209,7 @@ class PoolVector { if (!alloc) return; - if (alloc->refcount.unref() == false) { + if (!alloc->refcount.unref()) { alloc = NULL; return; } diff --git a/core/image.cpp b/core/image.cpp index e2b56c51dc..172f5e517a 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -1198,7 +1198,9 @@ void Image::expand_x2_hq2x() { if (current != FORMAT_RGBA8) convert(current); - if (used_mipmaps) { + // FIXME: This is likely meant to use "used_mipmaps" as defined above, but if we do, + // we end up with a regression: GH-22747 + if (mipmaps) { generate_mipmaps(); } } @@ -1471,7 +1473,8 @@ void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_forma void Image::create(const char **p_xpm) { - int size_width, size_height; + int size_width = 0; + int size_height = 0; int pixelchars = 0; mipmaps = false; bool has_alpha = false; @@ -1487,8 +1490,8 @@ void Image::create(const char **p_xpm) { int line = 0; HashMap<String, Color> colormap; - int colormap_size; - uint32_t pixel_size; + int colormap_size = 0; + uint32_t pixel_size = 0; PoolVector<uint8_t>::Write w; while (status != DONE) { diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp index f202320043..3ae9ff676c 100644 --- a/core/io/image_loader.cpp +++ b/core/io/image_loader.cpp @@ -118,7 +118,6 @@ RES ResourceFormatLoaderImage::load(const String &p_path, const String &p_origin if (r_error) { *r_error = ERR_CANT_OPEN; } - memdelete(f); return RES(); } diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp index ec430d41a9..6338cee39d 100644 --- a/core/io/marshalls.cpp +++ b/core/io/marshalls.cpp @@ -850,17 +850,16 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; case Variant::INT: { - int64_t val = p_variant; if (flags & ENCODE_FLAG_64) { //64 bits if (buf) { - encode_uint64(val, buf); + encode_uint64(p_variant.operator int64_t(), buf); } r_len += 8; } else { if (buf) { - encode_uint32(int32_t(val), buf); + encode_uint32(p_variant.operator int32_t(), buf); } r_len += 4; diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp index 17b77bc535..b3f0a76a80 100644 --- a/core/io/multiplayer_api.cpp +++ b/core/io/multiplayer_api.cpp @@ -416,7 +416,7 @@ bool MultiplayerAPI::_send_confirm_path(NodePath p_path, PathSentCache *psc, int Map<int, bool>::Element *F = psc->confirmed_peers.find(E->get()); - if (!F || F->get() == false) { + if (!F || !F->get()) { // Path was not cached, or was cached but is unconfirmed. if (!F) { // Not cached at all, take note. @@ -578,7 +578,7 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p network_peer->set_target_peer(E->get()); // To this one specifically. - if (F->get() == true) { + if (F->get()) { // This one confirmed path, so use id. encode_uint32(psc->id, &(packet_cache.write[1])); network_peer->put_packet(packet_cache.ptr(), ofs); diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 8c56d55e85..d156a9f4bd 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -647,3 +647,5 @@ bool ResourceLoader::timestamp_on_load = false; SelfList<Resource>::List ResourceLoader::remapped_list; HashMap<String, Vector<String> > ResourceLoader::translation_remaps; HashMap<String, String> ResourceLoader::path_remaps; + +ResourceLoaderImport ResourceLoader::import = NULL; diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index de0981350d..96bc6fa8dd 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -77,6 +77,8 @@ public: typedef void (*ResourceLoadErrorNotify)(void *p_ud, const String &p_text); typedef void (*DependencyErrorNotify)(void *p_ud, const String &p_loading, const String &p_which, const String &p_type); +typedef Error (*ResourceLoaderImport)(const String &p_path); + class ResourceLoader { enum { @@ -147,6 +149,8 @@ public: static void reload_translation_remaps(); static void load_translation_remaps(); static void clear_translation_remaps(); + + static ResourceLoaderImport import; }; #endif diff --git a/core/math/face3.cpp b/core/math/face3.cpp index aa46fde7f7..8366137131 100644 --- a/core/math/face3.cpp +++ b/core/math/face3.cpp @@ -202,11 +202,12 @@ bool Face3::intersects_aabb(const AABB &p_aabb) const { { \ real_t aabb_min = p_aabb.position.m_ax; \ real_t aabb_max = p_aabb.position.m_ax + p_aabb.size.m_ax; \ - real_t tri_min, tri_max; \ - for (int i = 0; i < 3; i++) { \ - if (i == 0 || vertex[i].m_ax > tri_max) \ + real_t tri_min = vertex[0].m_ax; \ + real_t tri_max = vertex[0].m_ax; \ + for (int i = 1; i < 3; i++) { \ + if (vertex[i].m_ax > tri_max) \ tri_max = vertex[i].m_ax; \ - if (i == 0 || vertex[i].m_ax < tri_min) \ + if (vertex[i].m_ax < tri_min) \ tri_min = vertex[i].m_ax; \ } \ \ diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 472baf0484..9a486a49d0 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -46,7 +46,7 @@ class Math { public: Math() {} // useless to instance - static const uint64_t RANDOM_MAX = 4294967295; + static const uint64_t RANDOM_MAX = 0xFFFFFFFF; static _ALWAYS_INLINE_ double sin(double p_x) { return ::sin(p_x); } static _ALWAYS_INLINE_ float sin(float p_x) { return ::sinf(p_x); } diff --git a/core/math/matrix3.cpp b/core/math/matrix3.cpp index fca54b1556..925a7b3f1e 100644 --- a/core/math/matrix3.cpp +++ b/core/math/matrix3.cpp @@ -299,14 +299,14 @@ Vector3 Basis::rotref_posscale_decomposition(Basis &rotref) const { ERR_FAIL_COND_V(determinant() == 0, Vector3()); Basis m = transposed() * (*this); - ERR_FAIL_COND_V(m.is_diagonal() == false, Vector3()); + ERR_FAIL_COND_V(!m.is_diagonal(), Vector3()); #endif Vector3 scale = get_scale(); Basis inv_scale = Basis().scaled(scale.inverse()); // this will also absorb the sign of scale rotref = (*this) * inv_scale; #ifdef MATH_CHECKS - ERR_FAIL_COND_V(rotref.is_orthogonal() == false, Vector3()); + ERR_FAIL_COND_V(!rotref.is_orthogonal(), Vector3()); #endif return scale.abs(); } @@ -430,7 +430,7 @@ Vector3 Basis::get_euler_xyz() const { Vector3 euler; #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_rotation() == false, euler); + ERR_FAIL_COND_V(!is_rotation(), euler); #endif real_t sy = elements[0][2]; if (sy < 1.0) { @@ -497,7 +497,7 @@ Vector3 Basis::get_euler_yxz() const { Vector3 euler; #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_rotation() == false, euler); + ERR_FAIL_COND_V(!is_rotation(), euler); #endif real_t m12 = elements[1][2]; @@ -556,7 +556,7 @@ bool Basis::is_equal_approx(const Basis &a, const Basis &b) const { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { - if (Math::is_equal_approx(a.elements[i][j], b.elements[i][j]) == false) + if (!Math::is_equal_approx(a.elements[i][j], b.elements[i][j])) return false; } } @@ -600,7 +600,7 @@ Basis::operator String() const { Quat Basis::get_quat() const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_rotation() == false, Quat()); + ERR_FAIL_COND_V(!is_rotation(), Quat()); #endif real_t trace = elements[0][0] + elements[1][1] + elements[2][2]; real_t temp[4]; @@ -697,7 +697,7 @@ void Basis::set_orthogonal_index(int p_index) { void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const { #ifdef MATH_CHECKS - ERR_FAIL_COND(is_rotation() == false); + ERR_FAIL_COND(!is_rotation()); #endif real_t angle, x, y, z; // variables for result real_t epsilon = 0.01; // margin to allow for rounding errors @@ -785,7 +785,7 @@ void Basis::set_quat(const Quat &p_quat) { void Basis::set_axis_angle(const Vector3 &p_axis, real_t p_phi) { // Rotation matrix from axis and angle, see https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_angle #ifdef MATH_CHECKS - ERR_FAIL_COND(p_axis.is_normalized() == false); + ERR_FAIL_COND(!p_axis.is_normalized()); #endif Vector3 axis_sq(p_axis.x * p_axis.x, p_axis.y * p_axis.y, p_axis.z * p_axis.z); @@ -837,8 +837,8 @@ void Basis::set_diagonal(const Vector3 p_diag) { Basis Basis::slerp(const Basis &target, const real_t &t) const { // TODO: implement this directly without using quaternions to make it more efficient #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_rotation() == false, Basis()); - ERR_FAIL_COND_V(target.is_rotation() == false, Basis()); + ERR_FAIL_COND_V(!is_rotation(), Basis()); + ERR_FAIL_COND_V(!target.is_rotation(), Basis()); #endif Quat from(*this); diff --git a/core/math/quat.cpp b/core/math/quat.cpp index d660ce4553..791e84f089 100644 --- a/core/math/quat.cpp +++ b/core/math/quat.cpp @@ -100,7 +100,7 @@ void Quat::set_euler_yxz(const Vector3 &p_euler) { // This implementation uses YXZ convention (Z is the first rotation). Vector3 Quat::get_euler_yxz() const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_normalized() == false, Vector3(0, 0, 0)); + ERR_FAIL_COND_V(!is_normalized(), Vector3(0, 0, 0)); #endif Basis m(*this); return m.get_euler_yxz(); @@ -140,15 +140,15 @@ bool Quat::is_normalized() const { Quat Quat::inverse() const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_normalized() == false, Quat()); + ERR_FAIL_COND_V(!is_normalized(), Quat()); #endif return Quat(-x, -y, -z, w); } Quat Quat::slerp(const Quat &q, const real_t &t) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_normalized() == false, Quat()); - ERR_FAIL_COND_V(q.is_normalized() == false, Quat()); + ERR_FAIL_COND_V(!is_normalized(), Quat()); + ERR_FAIL_COND_V(!q.is_normalized(), Quat()); #endif Quat to1; real_t omega, cosom, sinom, scale0, scale1; @@ -194,8 +194,8 @@ Quat Quat::slerp(const Quat &q, const real_t &t) const { Quat Quat::slerpni(const Quat &q, const real_t &t) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_normalized() == false, Quat()); - ERR_FAIL_COND_V(q.is_normalized() == false, Quat()); + ERR_FAIL_COND_V(!is_normalized(), Quat()); + ERR_FAIL_COND_V(!q.is_normalized(), Quat()); #endif const Quat &from = *this; @@ -216,8 +216,8 @@ Quat Quat::slerpni(const Quat &q, const real_t &t) const { Quat Quat::cubic_slerp(const Quat &q, const Quat &prep, const Quat &postq, const real_t &t) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_normalized() == false, Quat()); - ERR_FAIL_COND_V(q.is_normalized() == false, Quat()); + ERR_FAIL_COND_V(!is_normalized(), Quat()); + ERR_FAIL_COND_V(!q.is_normalized(), Quat()); #endif //the only way to do slerp :| real_t t2 = (1.0 - t) * t * 2; @@ -233,7 +233,7 @@ Quat::operator String() const { void Quat::set_axis_angle(const Vector3 &axis, const real_t &angle) { #ifdef MATH_CHECKS - ERR_FAIL_COND(axis.is_normalized() == false); + ERR_FAIL_COND(!axis.is_normalized()); #endif real_t d = axis.length(); if (d == 0) diff --git a/core/math/quat.h b/core/math/quat.h index 10d3846c87..c4f9b3a732 100644 --- a/core/math/quat.h +++ b/core/math/quat.h @@ -87,7 +87,7 @@ public: _FORCE_INLINE_ Vector3 xform(const Vector3 &v) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_normalized() == false, v); + ERR_FAIL_COND_V(!is_normalized(), v); #endif Vector3 u(x, y, z); Vector3 uv = u.cross(v); diff --git a/core/math/vector2.cpp b/core/math/vector2.cpp index 84c9f0fca6..7c6f056f09 100644 --- a/core/math/vector2.cpp +++ b/core/math/vector2.cpp @@ -167,7 +167,7 @@ Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, c // slide returns the component of the vector along the given plane, specified by its normal vector. Vector2 Vector2::slide(const Vector2 &p_normal) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(p_normal.is_normalized() == false, Vector2()); + ERR_FAIL_COND_V(!p_normal.is_normalized(), Vector2()); #endif return *this - p_normal * this->dot(p_normal); } @@ -178,7 +178,7 @@ Vector2 Vector2::bounce(const Vector2 &p_normal) const { Vector2 Vector2::reflect(const Vector2 &p_normal) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(p_normal.is_normalized() == false, Vector2()); + ERR_FAIL_COND_V(!p_normal.is_normalized(), Vector2()); #endif return 2.0 * p_normal * this->dot(p_normal) - *this; } diff --git a/core/math/vector2.h b/core/math/vector2.h index df49484aaf..e5e555597d 100644 --- a/core/math/vector2.h +++ b/core/math/vector2.h @@ -230,7 +230,7 @@ Vector2 Vector2::linear_interpolate(const Vector2 &p_b, real_t p_t) const { Vector2 Vector2::slerp(const Vector2 &p_b, real_t p_t) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_normalized() == false, Vector2()); + ERR_FAIL_COND_V(!is_normalized(), Vector2()); #endif real_t theta = angle_to(p_b); return rotated(theta * p_t); diff --git a/core/math/vector3.h b/core/math/vector3.h index 5302832eeb..16feba6a0c 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -218,7 +218,7 @@ Vector3 Vector3::linear_interpolate(const Vector3 &p_b, real_t p_t) const { Vector3 Vector3::slerp(const Vector3 &p_b, real_t p_t) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_normalized() == false, Vector3()); + ERR_FAIL_COND_V(!is_normalized(), Vector3()); #endif real_t theta = angle_to(p_b); @@ -430,7 +430,7 @@ void Vector3::zero() { // slide returns the component of the vector along the given plane, specified by its normal vector. Vector3 Vector3::slide(const Vector3 &p_normal) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(p_normal.is_normalized() == false, Vector3()); + ERR_FAIL_COND_V(!p_normal.is_normalized(), Vector3()); #endif return *this - p_normal * this->dot(p_normal); } @@ -441,7 +441,7 @@ Vector3 Vector3::bounce(const Vector3 &p_normal) const { Vector3 Vector3::reflect(const Vector3 &p_normal) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(p_normal.is_normalized() == false, Vector3()); + ERR_FAIL_COND_V(!p_normal.is_normalized(), Vector3()); #endif return 2.0 * p_normal * this->dot(p_normal) - *this; } diff --git a/core/oa_hash_map.h b/core/oa_hash_map.h index 3705762d6c..9840442519 100644 --- a/core/oa_hash_map.h +++ b/core/oa_hash_map.h @@ -125,7 +125,7 @@ private: while (42) { if (hashes[pos] == EMPTY_HASH) { - _construct(pos, hash, p_key, p_value); + _construct(pos, hash, key, value); return; } @@ -136,7 +136,7 @@ private: if (hashes[pos] & DELETED_HASH_BIT) { // we found a place where we can fit in! - _construct(pos, hash, p_key, p_value); + _construct(pos, hash, key, value); return; } diff --git a/core/os/rw_lock.h b/core/os/rw_lock.h index 8d1029723b..4333d9a016 100644 --- a/core/os/rw_lock.h +++ b/core/os/rw_lock.h @@ -57,9 +57,7 @@ class RWLockRead { public: RWLockRead(const RWLock *p_lock) { - if (p_lock) { - lock = const_cast<RWLock *>(p_lock); - } + lock = const_cast<RWLock *>(p_lock); if (lock) lock->read_lock(); } ~RWLockRead() { diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp index 388e3b77a3..3e984fae32 100644 --- a/core/script_debugger_remote.cpp +++ b/core/script_debugger_remote.cpp @@ -578,8 +578,14 @@ void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) { for (ScriptConstantsMap::Element *sc = constants.front(); sc; sc = sc->next()) { for (Map<StringName, Variant>::Element *E = sc->get().front(); E; E = E->next()) { String script_path = sc->key() == si->get_script().ptr() ? "" : sc->key()->get_path().get_file() + "/"; - PropertyInfo pi(E->value().get_type(), "Constants/" + script_path + E->key()); - properties.push_back(PropertyDesc(pi, E->value())); + if (E->value().get_type() == Variant::OBJECT) { + Variant id = ((Object *)E->value())->get_instance_id(); + PropertyInfo pi(id.get_type(), "Constants/" + E->key(), PROPERTY_HINT_OBJECT_ID, "Object"); + properties.push_back(PropertyDesc(pi, id)); + } else { + PropertyInfo pi(E->value().get_type(), "Constants/" + script_path + E->key()); + properties.push_back(PropertyDesc(pi, E->value())); + } } } } @@ -592,8 +598,14 @@ void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) { Map<StringName, Variant> constants; s->get_constants(&constants); for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) { - PropertyInfo pi(E->value().get_type(), String("Constants/") + E->key()); - properties.push_front(PropertyDesc(pi, E->value())); + if (E->value().get_type() == Variant::OBJECT) { + Variant id = ((Object *)E->value())->get_instance_id(); + PropertyInfo pi(id.get_type(), "Constants/" + E->key(), PROPERTY_HINT_OBJECT_ID, "Object"); + properties.push_front(PropertyDesc(pi, E->value())); + } else { + PropertyInfo pi(E->value().get_type(), String("Constants/") + E->key()); + properties.push_front(PropertyDesc(pi, E->value())); + } } } } @@ -634,10 +646,9 @@ void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) { prop.push_back(pi.hint); prop.push_back(pi.hint_string); prop.push_back(pi.usage); + if (!res.is_null()) { - var = String("PATH") + res->get_path(); - } else if (var.get_type() == Variant::STRING) { - var = String("DATA") + var; + var = res->get_path(); } prop.push_back(var); diff --git a/core/ustring.cpp b/core/ustring.cpp index 3f073b181f..b55607946d 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -586,6 +586,8 @@ String String::camelcase_to_underscore(bool lowercase) const { bool is_upper = cstr[i] >= A && cstr[i] <= Z; bool is_number = cstr[i] >= '0' && cstr[i] <= '9'; bool are_next_2_lower = false; + bool is_next_lower = false; + bool is_next_number = false; bool was_precedent_upper = cstr[i - 1] >= A && cstr[i - 1] <= Z; bool was_precedent_number = cstr[i - 1] >= '0' && cstr[i - 1] <= '9'; @@ -593,7 +595,18 @@ String String::camelcase_to_underscore(bool lowercase) const { are_next_2_lower = cstr[i + 1] >= a && cstr[i + 1] <= z && cstr[i + 2] >= a && cstr[i + 2] <= z; } - bool should_split = ((is_upper && !was_precedent_upper && !was_precedent_number) || (was_precedent_upper && is_upper && are_next_2_lower) || (is_number && !was_precedent_number)); + if (i + 1 < this->size()) { + is_next_lower = cstr[i + 1] >= a && cstr[i + 1] <= z; + is_next_number = cstr[i + 1] >= '0' && cstr[i + 1] <= '9'; + } + + const bool a = is_upper && !was_precedent_upper && !was_precedent_number; + const bool b = was_precedent_upper && is_upper && are_next_2_lower; + const bool c = is_number && !was_precedent_number; + const bool can_break_number_letter = is_number && !was_precedent_number && is_next_lower; + const bool can_break_letter_number = !is_number && was_precedent_number && (is_next_lower || is_next_number); + + bool should_split = a || b || c || can_break_number_letter || can_break_letter_number; if (should_split) { new_string += this->substr(start_index, i - start_index) + "_"; start_index = i; @@ -3092,7 +3105,7 @@ String String::simplify_path() const { } else if (s.begins_with("user://")) { drive = "user://"; - s = s.substr(6, s.length()); + s = s.substr(7, s.length()); } else if (s.begins_with("/") || s.begins_with("\\")) { drive = s.substr(0, 1); diff --git a/core/variant.cpp b/core/variant.cpp index 7d75c2243b..edbe66ba31 100644 --- a/core/variant.cpp +++ b/core/variant.cpp @@ -858,7 +858,7 @@ bool Variant::is_one() const { // atomic types case BOOL: { - return _data._bool == true; + return _data._bool; } break; case INT: { diff --git a/core/variant_call.cpp b/core/variant_call.cpp index f7fa2ebc70..8693a584f2 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -1895,6 +1895,7 @@ void register_variant_methods() { _VariantCall::add_constant(Variant::VECTOR3, "AXIS_Z", Vector3::AXIS_Z); _VariantCall::add_variant_constant(Variant::VECTOR3, "ZERO", Vector3(0, 0, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR3, "ONE", Vector3(1, 1, 1)); _VariantCall::add_variant_constant(Variant::VECTOR3, "INF", Vector3(Math_INF, Math_INF, Math_INF)); _VariantCall::add_variant_constant(Variant::VECTOR3, "LEFT", Vector3(-1, 0, 0)); _VariantCall::add_variant_constant(Variant::VECTOR3, "RIGHT", Vector3(1, 0, 0)); @@ -1904,6 +1905,7 @@ void register_variant_methods() { _VariantCall::add_variant_constant(Variant::VECTOR3, "BACK", Vector3(0, 0, 1)); _VariantCall::add_variant_constant(Variant::VECTOR2, "ZERO", Vector2(0, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR2, "ONE", Vector2(1, 1)); _VariantCall::add_variant_constant(Variant::VECTOR2, "INF", Vector2(Math_INF, Math_INF)); _VariantCall::add_variant_constant(Variant::VECTOR2, "LEFT", Vector2(-1, 0)); _VariantCall::add_variant_constant(Variant::VECTOR2, "RIGHT", Vector2(1, 0)); diff --git a/core/variant_op.cpp b/core/variant_op.cpp index 9afc31a772..d193858966 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -521,7 +521,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, const Dictionary *arr_a = reinterpret_cast<const Dictionary *>(p_a._data._mem); const Dictionary *arr_b = reinterpret_cast<const Dictionary *>(p_b._data._mem); - _RETURN((*arr_a == *arr_b) == false); + _RETURN(*arr_a != *arr_b); } CASE_TYPE(math, OP_NOT_EQUAL, ARRAY) { @@ -3521,7 +3521,7 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & //not as efficient but.. real_t va = a; real_t vb = b; - r_dst = (1.0 - c) * va + vb * c; + r_dst = va + (vb - va) * c; } else { r_dst = a; @@ -3542,13 +3542,13 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & case INT: { int64_t va = a._data._int; int64_t vb = b._data._int; - r_dst = int((1.0 - c) * va + vb * c); + r_dst = int(va + (vb - va) * c); } return; case REAL: { real_t va = a._data._real; real_t vb = b._data._real; - r_dst = (1.0 - c) * va + vb * c; + r_dst = va + (vb - va) * c; } return; case STRING: { @@ -3556,7 +3556,9 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & String sa = *reinterpret_cast<const String *>(a._data._mem); String sb = *reinterpret_cast<const String *>(b._data._mem); String dst; - int csize = sb.length() * c + sa.length() * (1.0 - c); + int sa_len = sa.length(); + int sb_len = sb.length(); + int csize = sa_len + (sb_len - sa_len) * c; if (csize == 0) { r_dst = ""; return; diff --git a/doc/classes/ArrayMesh.xml b/doc/classes/ArrayMesh.xml index ed3d2d2205..7806cf4ce4 100644 --- a/doc/classes/ArrayMesh.xml +++ b/doc/classes/ArrayMesh.xml @@ -47,7 +47,7 @@ </argument> <description> Creates a new surface. - Surfaces are created to be rendered using a "primitive", which may be PRIMITIVE_POINTS, PRIMITIVE_LINES, PRIMITIVE_LINE_STRIP, PRIMITIVE_LINE_LOOP, PRIMITIVE_TRIANGLES, PRIMITIVE_TRIANGLE_STRIP, PRIMITIVE_TRIANGLE_FAN. See [Mesh] for details. (As a note, when using indices, it is recommended to only use points, lines or triangles). [method get_surface_count] will become the surf_idx for this new surface. + Surfaces are created to be rendered using a "primitive", which may be PRIMITIVE_POINTS, PRIMITIVE_LINES, PRIMITIVE_LINE_STRIP, PRIMITIVE_LINE_LOOP, PRIMITIVE_TRIANGLES, PRIMITIVE_TRIANGLE_STRIP, PRIMITIVE_TRIANGLE_FAN. See [Mesh] for details. (As a note, when using indices, it is recommended to only use points, lines or triangles). [method Mesh.get_surface_count] will become the [code]surf_idx[/code] for this new surface. The [code]arrays[/code] argument is an array of arrays. See [enum ArrayType] for the values used in this array. For example, [code]arrays[0][/code] is the array of vertices. That first vertex sub-array is always required; the others are optional. Adding an index array puts this function into "index mode" where the vertex and other arrays become the sources of data and the index array defines the vertex order. All sub-arrays must have the same length as the vertex array or be empty, except for [code]ARRAY_INDEX[/code] if it is used. Adding an index array puts this function into "index mode" where the vertex and other arrays become the sources of data, and the index array defines the order of the vertices. Godot uses clockwise winding order for front faces of triangle primitive modes. diff --git a/doc/classes/AudioEffectBandLimitFilter.xml b/doc/classes/AudioEffectBandLimitFilter.xml index 9eba806ad5..c9ddbd5b9a 100644 --- a/doc/classes/AudioEffectBandLimitFilter.xml +++ b/doc/classes/AudioEffectBandLimitFilter.xml @@ -4,7 +4,7 @@ Adds a band limit filter to the Audio Bus. </brief_description> <description> - Limits the frequencies in a range around the [member cutoff_hz] and allows frequencies outside of this range to pass. + Limits the frequencies in a range around the [member AudioEffectFilter.cutoff_hz] and allows frequencies outside of this range to pass. </description> <tutorials> </tutorials> diff --git a/doc/classes/AudioEffectBandPassFilter.xml b/doc/classes/AudioEffectBandPassFilter.xml index 11aab3e86d..7f4c9f4632 100644 --- a/doc/classes/AudioEffectBandPassFilter.xml +++ b/doc/classes/AudioEffectBandPassFilter.xml @@ -4,7 +4,7 @@ Adds a band pass filter to the Audio Bus. </brief_description> <description> - Attenuates the frequencies inside of a range around the [member cutoff_hz] and cuts frequencies outside of this band. + Attenuates the frequencies inside of a range around the [member AudioEffectFilter.cutoff_hz] and cuts frequencies outside of this band. </description> <tutorials> </tutorials> diff --git a/doc/classes/AudioEffectHighPassFilter.xml b/doc/classes/AudioEffectHighPassFilter.xml index 3d487fc783..6c97199cb9 100644 --- a/doc/classes/AudioEffectHighPassFilter.xml +++ b/doc/classes/AudioEffectHighPassFilter.xml @@ -4,7 +4,7 @@ Adds a high pass filter to the Audio Bus. </brief_description> <description> - Cuts frequencies lower than the [member cutoff_hz] and allows higher frequencies to pass. + Cuts frequencies lower than the [member AudioEffectFilter.cutoff_hz] and allows higher frequencies to pass. </description> <tutorials> </tutorials> diff --git a/doc/classes/AudioEffectLowPassFilter.xml b/doc/classes/AudioEffectLowPassFilter.xml index 3facd8b665..7048a56e6c 100644 --- a/doc/classes/AudioEffectLowPassFilter.xml +++ b/doc/classes/AudioEffectLowPassFilter.xml @@ -4,7 +4,7 @@ Adds a low pass filter to the Audio Bus. </brief_description> <description> - Cuts frequencies higher than the [member cutoff_hz] and allows lower frequencies to pass. + Cuts frequencies higher than the [member AudioEffectFilter.cutoff_hz] and allows lower frequencies to pass. </description> <tutorials> </tutorials> diff --git a/doc/classes/AudioEffectNotchFilter.xml b/doc/classes/AudioEffectNotchFilter.xml index 741931f262..0378934890 100644 --- a/doc/classes/AudioEffectNotchFilter.xml +++ b/doc/classes/AudioEffectNotchFilter.xml @@ -4,7 +4,7 @@ Adds a notch filter to the Audio Bus. </brief_description> <description> - Attenuates frequencies in a narrow band around the [member cutoff_hz] and cuts frequencies outside of this range. + Attenuates frequencies in a narrow band around the [member AudioEffectFilter.cutoff_hz] and cuts frequencies outside of this range. </description> <tutorials> </tutorials> diff --git a/doc/classes/BaseButton.xml b/doc/classes/BaseButton.xml index 3ff8634010..3364770280 100644 --- a/doc/classes/BaseButton.xml +++ b/doc/classes/BaseButton.xml @@ -106,6 +106,8 @@ <constant name="DRAW_DISABLED" value="3" enum="DrawMode"> The state of buttons are disabled. </constant> + <constant name="DRAW_HOVER_PRESSED" value="4" enum="DrawMode"> + </constant> <constant name="ACTION_MODE_BUTTON_PRESS" value="0" enum="ActionMode"> Require just a press to consider the button clicked. </constant> diff --git a/doc/classes/CheckBox.xml b/doc/classes/CheckBox.xml index fb2cf64d98..a2a7cf85e8 100644 --- a/doc/classes/CheckBox.xml +++ b/doc/classes/CheckBox.xml @@ -31,10 +31,14 @@ </theme_item> <theme_item name="font_color_hover" type="Color"> </theme_item> + <theme_item name="font_color_hover_pressed" type="Color"> + </theme_item> <theme_item name="font_color_pressed" type="Color"> </theme_item> <theme_item name="hover" type="StyleBox"> </theme_item> + <theme_item name="hover_pressed" type="StyleBox"> + </theme_item> <theme_item name="hseparation" type="int"> </theme_item> <theme_item name="normal" type="StyleBox"> diff --git a/doc/classes/CheckButton.xml b/doc/classes/CheckButton.xml index deba9a17b6..24875017fe 100644 --- a/doc/classes/CheckButton.xml +++ b/doc/classes/CheckButton.xml @@ -29,10 +29,14 @@ </theme_item> <theme_item name="font_color_hover" type="Color"> </theme_item> + <theme_item name="font_color_hover_pressed" type="Color"> + </theme_item> <theme_item name="font_color_pressed" type="Color"> </theme_item> <theme_item name="hover" type="StyleBox"> </theme_item> + <theme_item name="hover_pressed" type="StyleBox"> + </theme_item> <theme_item name="hseparation" type="int"> </theme_item> <theme_item name="normal" type="StyleBox"> diff --git a/doc/classes/CollisionShape.xml b/doc/classes/CollisionShape.xml index 682c9340df..5639c14192 100644 --- a/doc/classes/CollisionShape.xml +++ b/doc/classes/CollisionShape.xml @@ -4,7 +4,7 @@ Node that represents collision shape data in 3D space. </brief_description> <description> - Editor facility for creating and editing collision shapes in 3D space. You can use this node to represent all sorts of collision shapes, for example, add this to an [Area] to give it a detection shape, or add it to a [PhysicsBody] to create a solid object. [b]IMPORTANT[/b]: this is an Editor-only helper to create shapes, use [method get_shape] to get the actual shape. + Editor facility for creating and editing collision shapes in 3D space. You can use this node to represent all sorts of collision shapes, for example, add this to an [Area] to give it a detection shape, or add it to a [PhysicsBody] to create a solid object. [b]IMPORTANT[/b]: this is an Editor-only helper to create shapes, use [method CollisionObject.shape_owner_get_shape] to get the actual shape. </description> <tutorials> <link>http://docs.godotengine.org/en/3.0/tutorials/physics/physics_introduction.html</link> diff --git a/doc/classes/CollisionShape2D.xml b/doc/classes/CollisionShape2D.xml index 3312fad99c..713cb8d098 100644 --- a/doc/classes/CollisionShape2D.xml +++ b/doc/classes/CollisionShape2D.xml @@ -4,7 +4,7 @@ Node that represents collision shape data in 2D space. </brief_description> <description> - Editor facility for creating and editing collision shapes in 2D space. You can use this node to represent all sorts of collision shapes, for example, add this to an [Area2D] to give it a detection shape, or add it to a [PhysicsBody2D] to create a solid object. [b]IMPORTANT[/b]: this is an Editor-only helper to create shapes, use [method get_shape] to get the actual shape. + Editor facility for creating and editing collision shapes in 2D space. You can use this node to represent all sorts of collision shapes, for example, add this to an [Area2D] to give it a detection shape, or add it to a [PhysicsBody2D] to create a solid object. [b]IMPORTANT[/b]: this is an Editor-only helper to create shapes, use [method CollisionObject2D.shape_owner_get_shape] to get the actual shape. </description> <tutorials> <link>http://docs.godotengine.org/en/3.0/tutorials/physics/physics_introduction.html</link> diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml index 1a27aea23f..ee82afd592 100644 --- a/doc/classes/Control.xml +++ b/doc/classes/Control.xml @@ -76,7 +76,7 @@ <argument index="1" name="constant" type="int"> </argument> <description> - Overrides an integer constant in the [member theme] resource the node uses. If the [code]constant[/code] is invalid, Godot clears the override. See [member Theme.INVALID_CONSTANT] for more information. + Overrides an integer constant in the [member theme] resource the node uses. If the [code]constant[/code] is invalid, Godot clears the override. </description> </method> <method name="add_font_override"> diff --git a/doc/classes/FileDialog.xml b/doc/classes/FileDialog.xml index 247228d265..29aa26b67f 100644 --- a/doc/classes/FileDialog.xml +++ b/doc/classes/FileDialog.xml @@ -17,7 +17,7 @@ <argument index="0" name="filter" type="String"> </argument> <description> - Add a custom filter. Filter format is: "mask ; description", example (C++): dialog->add_filter("*.png ; PNG Images"); + Add a custom filter. Example: [code]add_filter("*.png ; PNG Images")[/code] </description> </method> <method name="clear_filters"> @@ -31,12 +31,14 @@ <return type="void"> </return> <description> + Clear currently selected items in the dialog. </description> </method> <method name="get_line_edit"> <return type="LineEdit"> </return> <description> + Returns the LineEdit for the selected file. </description> </method> <method name="get_vbox"> @@ -56,6 +58,7 @@ </methods> <members> <member name="access" type="int" setter="set_access" getter="get_access" enum="FileDialog.Access"> + The file system access scope. See enum [code]Access[/code] constants. </member> <member name="current_dir" type="String" setter="set_current_dir" getter="get_current_dir"> The current working directory of the file dialog. @@ -67,13 +70,16 @@ The currently selected file path of the file dialog. </member> <member name="filters" type="PoolStringArray" setter="set_filters" getter="get_filters"> + Set file type filters. This example shows only .png and .gd files [code]set_filters(PoolStringArray(["*.png ; PNG Images","*.gd ; GD Script"]))[/code]. </member> <member name="mode" type="int" setter="set_mode" getter="get_mode" enum="FileDialog.Mode"> + Set dialog to open or save mode, changes selection behavior. See enum [code]Mode[/code] constants. </member> <member name="mode_overrides_title" type="bool" setter="set_mode_overrides_title" getter="is_mode_overriding_title"> - If [code]true[/code], changing the [code]mode[/code] property will set the window title accordingly (e. g. setting mode to [code]MODE_OPEN_FILE[/code] will change the window title to "Open a File"). + If [code]true[/code], changing the [code]Mode[/code] property will set the window title accordingly (e. g. setting mode to [code]MODE_OPEN_FILE[/code] will change the window title to "Open a File"). </member> <member name="show_hidden_files" type="bool" setter="set_show_hidden_files" getter="is_showing_hidden_files"> + If [code]true[/code], the dialog will show hidden files. </member> </members> <signals> diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index 338d01ae5f..10ec15b99d 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -55,6 +55,7 @@ <argument index="0" name="action" type="String"> </argument> <description> + Returns a value between 0 and 1 representing the intensity of the given action. In a joypad, for example, the further away the axis (analog sticks or L2, R2 triggers) is from the dead zone, the closer the value will be to 1. If the action is mapped to a control that has no axis as the keyboard, the value returned will be 0 or 1. </description> </method> <method name="get_connected_joypads"> diff --git a/doc/classes/KinematicBody.xml b/doc/classes/KinematicBody.xml index 17310ab4dc..82638fc57a 100644 --- a/doc/classes/KinematicBody.xml +++ b/doc/classes/KinematicBody.xml @@ -69,7 +69,7 @@ </argument> <description> Moves the body along the vector [code]rel_vec[/code]. The body will stop if it collides. Returns a [KinematicCollision], which contains information about the collision. - If [code]test_only[/code] is [code]true[/true], the body does not move but the would-be collision information is given. + If [code]test_only[/code] is [code]true[/code], the body does not move but the would-be collision information is given. </description> </method> <method name="move_and_slide"> diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml index c244b8b7a7..f842dd8311 100644 --- a/doc/classes/LineEdit.xml +++ b/doc/classes/LineEdit.xml @@ -89,6 +89,7 @@ The cursor's position inside the [code]LineEdit[/code]. When set, the text may scroll to accommodate it. </member> <member name="clear_button_enabled" type="bool" setter="set_clear_button_enabled" getter="is_clear_button_enabled"> + If [code]true[/code] the [code]LineEdit[/code] will show a clear button if [code]text[/code] is not empty. </member> <member name="context_menu_enabled" type="bool" setter="set_context_menu_enabled" getter="is_context_menu_enabled"> If [code]true[/code] the context menu will appear when right clicked. @@ -169,6 +170,7 @@ Undoes the previous action. </constant> <constant name="MENU_REDO" value="6" enum="MenuItems"> + Reverse the last undo action. </constant> <constant name="MENU_MAX" value="7" enum="MenuItems"> </constant> diff --git a/doc/classes/MeshDataTool.xml b/doc/classes/MeshDataTool.xml index 43d94004a8..5c3af3e2e1 100644 --- a/doc/classes/MeshDataTool.xml +++ b/doc/classes/MeshDataTool.xml @@ -1,8 +1,22 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="MeshDataTool" inherits="Reference" category="Core" version="3.1"> <brief_description> + Helper tool to access and edit [Mesh] data. </brief_description> <description> + The MeshDataTool provides access to individual vertices in a [Mesh]. It allows users to read and edit vertex data of meshes. It also creates an array of faces and edges. + To use the MeshDataTool, load a mesh with [method create_from_surface]. When you are finished editing the data commit the data to a mesh with [method commit_to_surface]. + Below is an example of how the MeshDataTool may be used. + [codeblock] + var mdt = MeshDataTool.new() + mdt.create_from_surface(mesh, 0) + for i in range(mdt.get_vertex_count()): + var vertex = mdt.get_vertex(i) + ... + mdt.set_vertex(i, vertex) + mesh.surface_remove(0) + mdt.commit_to_surface(mesh) + [/codeblock] </description> <tutorials> </tutorials> @@ -13,6 +27,7 @@ <return type="void"> </return> <description> + Clears all data currently in MeshDataTool. </description> </method> <method name="commit_to_surface"> @@ -21,6 +36,7 @@ <argument index="0" name="mesh" type="ArrayMesh"> </argument> <description> + Adds a new surface to specified [Mesh] with edited data. </description> </method> <method name="create_from_surface"> @@ -31,12 +47,15 @@ <argument index="1" name="surface" type="int"> </argument> <description> + Uses specified surface of given [Mesh] to populate data for MeshDataTool. + Requires [Mesh] with primitive type [code]PRIMITIVE_TRIANGLES[/code]. </description> </method> <method name="get_edge_count" qualifiers="const"> <return type="int"> </return> <description> + Returns the number of edges in this [Mesh]. </description> </method> <method name="get_edge_faces" qualifiers="const"> @@ -45,6 +64,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns array of faces that touch given edge. </description> </method> <method name="get_edge_meta" qualifiers="const"> @@ -53,6 +73,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns meta information assigned to given edge. </description> </method> <method name="get_edge_vertex" qualifiers="const"> @@ -63,12 +84,15 @@ <argument index="1" name="vertex" type="int"> </argument> <description> + Returns index of specified vertex connected to given edge. + Vertex argument can only be 0 or 1 because edges are comprised of two vertices. </description> </method> <method name="get_face_count" qualifiers="const"> <return type="int"> </return> <description> + Returns the number of faces in this [Mesh]. </description> </method> <method name="get_face_edge" qualifiers="const"> @@ -79,6 +103,8 @@ <argument index="1" name="edge" type="int"> </argument> <description> + Returns specified edge associated with given face. + Edge argument must 2 or less becuase a face only has three edges. </description> </method> <method name="get_face_meta" qualifiers="const"> @@ -87,6 +113,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns meta data associated with given face. </description> </method> <method name="get_face_normal" qualifiers="const"> @@ -95,6 +122,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Calculates and returns face normal of given face. </description> </method> <method name="get_face_vertex" qualifiers="const"> @@ -105,18 +133,23 @@ <argument index="1" name="vertex" type="int"> </argument> <description> + Returns specified vertex of given face. + Vertex argument must be 2 or less becuase faces contain three vertices. </description> </method> <method name="get_format" qualifiers="const"> <return type="int"> </return> <description> + Returns format of [Mesh]. Format is an integer made up of [Mesh] format flags combined together. For example, a mesh containing both vertices and normals would return a format of [code]3[/code] becuase [code]ARRAY_FORMAT_VERTEX[/code] is [code]1[/code] and [code]ARRAY_FORMAT_NORMAL[/code] is [code]2[/code]. + For list of format flags see [ArrayMesh]. </description> </method> <method name="get_material" qualifiers="const"> <return type="Material"> </return> <description> + Returns material assigned to the [Mesh]. </description> </method> <method name="get_vertex" qualifiers="const"> @@ -125,6 +158,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns the vertex at given index. </description> </method> <method name="get_vertex_bones" qualifiers="const"> @@ -133,6 +167,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns the bones of the given vertex. </description> </method> <method name="get_vertex_color" qualifiers="const"> @@ -141,12 +176,14 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns the color of the given vertex. </description> </method> <method name="get_vertex_count" qualifiers="const"> <return type="int"> </return> <description> + Returns the total number of vertices in [Mesh]. </description> </method> <method name="get_vertex_edges" qualifiers="const"> @@ -155,6 +192,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns array of edges that share given vertex. </description> </method> <method name="get_vertex_faces" qualifiers="const"> @@ -163,6 +201,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns array of faces that share given vertex. </description> </method> <method name="get_vertex_meta" qualifiers="const"> @@ -171,6 +210,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns meta data associated with given vertex. </description> </method> <method name="get_vertex_normal" qualifiers="const"> @@ -179,6 +219,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns normal of given vertex. </description> </method> <method name="get_vertex_tangent" qualifiers="const"> @@ -187,6 +228,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns tangent of given vertex. </description> </method> <method name="get_vertex_uv" qualifiers="const"> @@ -195,6 +237,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns UV of given vertex. </description> </method> <method name="get_vertex_uv2" qualifiers="const"> @@ -203,6 +246,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns UV2 of given vertex. </description> </method> <method name="get_vertex_weights" qualifiers="const"> @@ -211,6 +255,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns bone weights of given vertex. </description> </method> <method name="set_edge_meta"> @@ -221,6 +266,7 @@ <argument index="1" name="meta" type="Variant"> </argument> <description> + Sets the meta data of given edge. </description> </method> <method name="set_face_meta"> @@ -231,6 +277,7 @@ <argument index="1" name="meta" type="Variant"> </argument> <description> + Sets the meta data of given face. </description> </method> <method name="set_material"> @@ -239,6 +286,7 @@ <argument index="0" name="material" type="Material"> </argument> <description> + Sets the material to be used by newly constructed [Mesh]. </description> </method> <method name="set_vertex"> @@ -249,6 +297,7 @@ <argument index="1" name="vertex" type="Vector3"> </argument> <description> + Sets the position of given vertex. </description> </method> <method name="set_vertex_bones"> @@ -259,6 +308,7 @@ <argument index="1" name="bones" type="PoolIntArray"> </argument> <description> + Sets the bones of given vertex. </description> </method> <method name="set_vertex_color"> @@ -269,6 +319,7 @@ <argument index="1" name="color" type="Color"> </argument> <description> + Sets the color of given vertex. </description> </method> <method name="set_vertex_meta"> @@ -279,6 +330,7 @@ <argument index="1" name="meta" type="Variant"> </argument> <description> + Sets the meta data associated with given vertex. </description> </method> <method name="set_vertex_normal"> @@ -289,6 +341,7 @@ <argument index="1" name="normal" type="Vector3"> </argument> <description> + Sets the normal of given vertex. </description> </method> <method name="set_vertex_tangent"> @@ -299,6 +352,7 @@ <argument index="1" name="tangent" type="Plane"> </argument> <description> + Sets the tangent of given vertex. </description> </method> <method name="set_vertex_uv"> @@ -309,6 +363,7 @@ <argument index="1" name="uv" type="Vector2"> </argument> <description> + Sets the UV of given vertex. </description> </method> <method name="set_vertex_uv2"> @@ -319,6 +374,7 @@ <argument index="1" name="uv2" type="Vector2"> </argument> <description> + Sets the UV2 of given vertex. </description> </method> <method name="set_vertex_weights"> @@ -329,6 +385,7 @@ <argument index="1" name="weights" type="PoolRealArray"> </argument> <description> + Sets the bone weights of given vertex. </description> </method> </methods> diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index dc754b4628..a33ee5c363 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -12,7 +12,7 @@ [b]Processing:[/b] Nodes can override the "process" state, so that they receive a callback on each frame requesting them to process (do something). Normal processing (callback [method _process], toggled with [method set_process]) happens as fast as possible and is dependent on the frame rate, so the processing time [i]delta[/i] is passed as an argument. Physics processing (callback [method _physics_process], toggled with [method set_physics_process]) happens a fixed number of times per second (60 by default) and is useful for code related to the physics engine. Nodes can also process input events. When present, the [method _input] function will be called for each input that the program receives. In many cases, this can be overkill (unless used for simple projects), and the [method _unhandled_input] function might be preferred; it is called when the input event was not handled by anyone else (typically, GUI [Control] nodes), ensuring that the node only receives the events that were meant for it. To keep track of the scene hierarchy (especially when instancing scenes into other scenes), an "owner" can be set for the node with [method set_owner]. This keeps track of who instanced what. This is mostly useful when writing editors and tools, though. - Finally, when a node is freed with [method free] or [method queue_free], it will also free all its children. + Finally, when a node is freed with [method Object.free] or [method queue_free], it will also free all its children. [b]Groups:[/b] Nodes can be added to as many groups as you want to be easy to manage, you could create groups like "enemies" or "collectables" for example, depending on your game. See [method add_to_group], [method is_in_group] and [method remove_from_group]. You can then retrieve all nodes in these groups, iterate them and even call methods on groups via the methods on [SceneTree]. [b]Networking with nodes:[/b] After connecting to a server (or making one, see [NetworkedMultiplayerENet]) it is possible to use the built-in RPC (remote procedure call) system to communicate over the network. By calling [method rpc] with a method name, it will be called locally and in all connected peers (peers = clients and the server that accepts connections). To identify which node receives the RPC call Godot will use its [NodePath] (make sure node names are the same on all peers). Also take a look at the high-level networking tutorial and corresponding demos. </description> diff --git a/doc/classes/PackedScene.xml b/doc/classes/PackedScene.xml index 0d58e61c3a..08df3f0ad6 100644 --- a/doc/classes/PackedScene.xml +++ b/doc/classes/PackedScene.xml @@ -39,7 +39,7 @@ <argument index="0" name="edit_state" type="int" enum="PackedScene.GenEditState" default="0"> </argument> <description> - Instantiates the scene's node hierarchy. Triggers child scene instantiation(s). Triggers the [enum Object.NOTIFICATION_INSTANCED] notification on the root node. + Instantiates the scene's node hierarchy. Triggers child scene instantiation(s). Triggers the [enum Node.NOTIFICATION_INSTANCED] notification on the root node. </description> </method> <method name="pack"> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 0b7c0a63ad..4516fc522a 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -102,7 +102,7 @@ <argument index="0" name="name" type="String"> </argument> <description> - Returns true if the specified property exists and its initial value differs from the current value. + Returns true if the specified property exists and its initial value differs from the current value. </description> </method> <method name="property_get_revert"> @@ -111,14 +111,14 @@ <argument index="0" name="name" type="String"> </argument> <description> - Returns the initial value of the specified property. Returns null if the property does not exist. + Returns the initial value of the specified property. Returns null if the property does not exist. </description> </method> <method name="save"> <return type="int" enum="Error"> </return> <description> - Saves the configuration to the project.godot file. + Saves the configuration to the project.godot file. </description> </method> <method name="save_custom"> @@ -127,7 +127,7 @@ <argument index="0" name="file" type="String"> </argument> <description> - Saves the configuration to a custom file. + Saves the configuration to a custom file. </description> </method> <method name="set_initial_value"> @@ -213,8 +213,6 @@ <member name="audio/mix_rate" type="int" setter="" getter=""> Mix rate used for audio. In general, it's better to not touch this and leave it to the host operating system. </member> - <member name="audio/output_latency" type="int" setter="" getter=""> - </member> <member name="audio/video_delay_compensation_ms" type="int" setter="" getter=""> Setting to hardcode audio delay when playing video. Best to leave this untouched unless you know what you are doing. </member> @@ -697,6 +695,14 @@ </member> <member name="rendering/quality/reflections/texture_array_reflections.mobile" type="bool" setter="" getter=""> </member> + <member name="rendering/quality/shading/force_blinn_over_ggx" type="bool" setter="" getter=""> + </member> + <member name="rendering/quality/shading/force_blinn_over_ggx.mobile" type="bool" setter="" getter=""> + </member> + <member name="rendering/quality/shading/force_lambert_over_burley" type="bool" setter="" getter=""> + </member> + <member name="rendering/quality/shading/force_lambert_over_burley.mobile" type="bool" setter="" getter=""> + </member> <member name="rendering/quality/shading/force_vertex_shading" type="bool" setter="" getter=""> Force vertex shading for all rendering. This can increase performance a lot, but also reduces quality inmensely. Can work to optimize on very low end mobile. </member> diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml index 618f2f42b2..357d2e7a15 100644 --- a/doc/classes/RichTextLabel.xml +++ b/doc/classes/RichTextLabel.xml @@ -166,6 +166,12 @@ Adds a meta tag to the tag stack. Similar to the bbcode [code][url=something]{text}[/url][/code], but supports non-[String] metadata types. </description> </method> + <method name="push_strikethrough"> + <return type="void"> + </return> + <description> + </description> + </method> <method name="push_table"> <return type="void"> </return> @@ -304,15 +310,17 @@ </constant> <constant name="ITEM_UNDERLINE" value="6" enum="ItemType"> </constant> - <constant name="ITEM_ALIGN" value="7" enum="ItemType"> + <constant name="ITEM_STRIKETHROUGH" value="7" enum="ItemType"> + </constant> + <constant name="ITEM_ALIGN" value="8" enum="ItemType"> </constant> - <constant name="ITEM_INDENT" value="8" enum="ItemType"> + <constant name="ITEM_INDENT" value="9" enum="ItemType"> </constant> - <constant name="ITEM_LIST" value="9" enum="ItemType"> + <constant name="ITEM_LIST" value="10" enum="ItemType"> </constant> - <constant name="ITEM_TABLE" value="10" enum="ItemType"> + <constant name="ITEM_TABLE" value="11" enum="ItemType"> </constant> - <constant name="ITEM_META" value="11" enum="ItemType"> + <constant name="ITEM_META" value="12" enum="ItemType"> </constant> </constants> <theme_items> diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml index 1985845552..b89ecd1de9 100644 --- a/doc/classes/SceneTree.xml +++ b/doc/classes/SceneTree.xml @@ -278,6 +278,10 @@ </member> <member name="paused" type="bool" setter="set_pause" getter="is_paused"> If [code]true[/code] the SceneTree is paused. + Doing so will have the following behavior: + * 2D and 3D physics will be stopped. + * _process and _physics_process will not be called anymore in nodes. + * _input and _input_event will not be called anymore either. </member> <member name="refuse_new_network_connections" type="bool" setter="set_refuse_new_network_connections" getter="is_refusing_new_network_connections"> If [code]true[/code] the SceneTree's [member network_peer] refuses new incoming connections. diff --git a/doc/classes/ScriptCreateDialog.xml b/doc/classes/ScriptCreateDialog.xml index 3de068dbcb..67ce9a8e87 100644 --- a/doc/classes/ScriptCreateDialog.xml +++ b/doc/classes/ScriptCreateDialog.xml @@ -24,6 +24,8 @@ </argument> <argument index="1" name="path" type="String"> </argument> + <argument index="2" name="built_in_enabled" type="bool" default="true"> + </argument> <description> Prefills required fields to configure the ScriptCreateDialog for use. </description> diff --git a/doc/classes/SpatialMaterial.xml b/doc/classes/SpatialMaterial.xml index 354c6686bb..57fb267e91 100644 --- a/doc/classes/SpatialMaterial.xml +++ b/doc/classes/SpatialMaterial.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="SpatialMaterial" inherits="Material" category="Core" version="3.1"> <brief_description> + Default 3D rendering material. </brief_description> <description> + This provides a default material with a wide variety of rendering features and properties without the need to write shader code. See the tutorial below for details. </description> <tutorials> <link>http://docs.godotengine.org/en/3.0/tutorials/3d/spatial_material.html</link> @@ -13,16 +15,20 @@ </methods> <members> <member name="albedo_color" type="Color" setter="set_albedo" getter="get_albedo"> + The material's base color. </member> <member name="albedo_texture" type="Texture" setter="set_texture" getter="get_texture"> </member> <member name="anisotropy" type="float" setter="set_anisotropy" getter="get_anisotropy"> + The strength of the anisotropy effect. </member> <member name="anisotropy_enabled" type="bool" setter="set_feature" getter="get_feature"> + If [code]true[/code] anisotropy is enabled. Changes the shape of the specular blob and aligns it to tangent space. Default value: [code]false[/code]. </member> <member name="anisotropy_flowmap" type="Texture" setter="set_texture" getter="get_texture"> </member> <member name="ao_enabled" type="bool" setter="set_feature" getter="get_feature"> + If [code]true[/code] ambient occlusion is enabled. </member> <member name="ao_light_affect" type="float" setter="set_ao_light_affect" getter="get_ao_light_affect"> </member> @@ -35,6 +41,7 @@ <member name="clearcoat" type="float" setter="set_clearcoat" getter="get_clearcoat"> </member> <member name="clearcoat_enabled" type="bool" setter="set_feature" getter="get_feature"> + If [code]true[/code] clearcoat rendering is enabled. Adds a secondary transparent pass to the material. Default value: [code]false[/code]. </member> <member name="clearcoat_gloss" type="float" setter="set_clearcoat_gloss" getter="get_clearcoat_gloss"> </member> @@ -43,6 +50,7 @@ <member name="depth_deep_parallax" type="bool" setter="set_depth_deep_parallax" getter="is_depth_deep_parallax_enabled"> </member> <member name="depth_enabled" type="bool" setter="set_feature" getter="get_feature"> + If [code]true[/code] Depth mapping is enabled. See also [member normal_enabled]. </member> <member name="depth_max_layers" type="int" setter="set_depth_deep_parallax_max_layers" getter="get_depth_deep_parallax_max_layers"> </member> @@ -71,10 +79,13 @@ <member name="distance_fade_mode" type="int" setter="set_distance_fade" getter="get_distance_fade" enum="SpatialMaterial.DistanceFadeMode"> </member> <member name="emission" type="Color" setter="set_emission" getter="get_emission"> + The emitted light's color. See [member emission_enabled]. </member> <member name="emission_enabled" type="bool" setter="set_feature" getter="get_feature"> + If [code]true[/code] the body emits light. </member> <member name="emission_energy" type="float" setter="set_emission_energy" getter="get_emission_energy"> + The emitted light's strength. See [member emission_enabled]. </member> <member name="emission_on_uv2" type="bool" setter="set_flag" getter="get_flag"> </member> @@ -85,36 +96,49 @@ <member name="flags_albedo_tex_force_srgb" type="bool" setter="set_flag" getter="get_flag"> </member> <member name="flags_disable_ambient_light" type="bool" setter="set_flag" getter="get_flag"> + If [code]true[/code] the object receives no ambient light. Default value: [code]false[/code]. </member> <member name="flags_do_not_receive_shadows" type="bool" setter="set_flag" getter="get_flag"> + If [code]true[/code] the object receives no shadow that would otherwise be cast onto it. Default value: [code]false[/code]. </member> <member name="flags_ensure_correct_normals" type="bool" setter="set_flag" getter="get_flag"> </member> <member name="flags_fixed_size" type="bool" setter="set_flag" getter="get_flag"> + If [code]true[/code] the object is rendered at the same size regardless of distance. Default value: [code]false[/code]. </member> <member name="flags_no_depth_test" type="bool" setter="set_flag" getter="get_flag"> + If [code]true[/code] depth testing is disabled and the object will be drawn in render order. </member> <member name="flags_transparent" type="bool" setter="set_feature" getter="get_feature"> + If [code]true[/code] transparency is enabled on the body. Default value: [code]false[/code]. See also [member params_blend_mode]. </member> <member name="flags_unshaded" type="bool" setter="set_flag" getter="get_flag"> + If [code]true[/code] the object is unaffected by lighting. Default value: [code]false[/code]. </member> <member name="flags_use_point_size" type="bool" setter="set_flag" getter="get_flag"> + If [code]true[/code] render point size can be changed. Note: this is only effective for objects whose geometry is point-based rather than triangle-based. See also [member params_point_size]. </member> <member name="flags_vertex_lighting" type="bool" setter="set_flag" getter="get_flag"> + If [code]true[/code] lighting is calculated per vertex rather than per pixel. This may increase performance on low-end devices. Default value: [code]false[/code]. </member> <member name="flags_world_triplanar" type="bool" setter="set_flag" getter="get_flag"> + If [code]true[/code] triplanar mapping is calculated in world space rather than object local space. See also [member uv1_triplanar]. Default value: [code]false[/code]. </member> <member name="metallic" type="float" setter="set_metallic" getter="get_metallic"> + The reflectivity of the object's surface. The higher the value the more light is reflected. </member> <member name="metallic_specular" type="float" setter="set_specular" getter="get_specular"> + General reflectivity amount. Note: unlike [member metallic], this is not energy-conserving, so it should be left at [code]0.5[/code] in most cases. See also [member roughness]. </member> <member name="metallic_texture" type="Texture" setter="set_texture" getter="get_texture"> </member> <member name="metallic_texture_channel" type="int" setter="set_metallic_texture_channel" getter="get_metallic_texture_channel" enum="SpatialMaterial.TextureChannel"> </member> <member name="normal_enabled" type="bool" setter="set_feature" getter="get_feature"> + If [code]true[/code] normal mapping is enabled. </member> <member name="normal_scale" type="float" setter="set_normal_scale" getter="get_normal_scale"> + The strength of the normal map's effect. </member> <member name="normal_texture" type="Texture" setter="set_texture" getter="get_texture"> </member> @@ -123,40 +147,55 @@ <member name="params_billboard_keep_scale" type="bool" setter="set_flag" getter="get_flag"> </member> <member name="params_billboard_mode" type="int" setter="set_billboard_mode" getter="get_billboard_mode" enum="SpatialMaterial.BillboardMode"> + Controls how the object faces the camera. See [enum BillboardMode]. </member> <member name="params_blend_mode" type="int" setter="set_blend_mode" getter="get_blend_mode" enum="SpatialMaterial.BlendMode"> + The material's blend mode. Note that values other than [code]Mix[/code] force the object into the transparent pipeline. See [enum BlendMode]. </member> <member name="params_cull_mode" type="int" setter="set_cull_mode" getter="get_cull_mode" enum="SpatialMaterial.CullMode"> + Which side of the object is not drawn when backfaces are rendered. See [enum CullMode]. </member> <member name="params_depth_draw_mode" type="int" setter="set_depth_draw_mode" getter="get_depth_draw_mode" enum="SpatialMaterial.DepthDrawMode"> + Determines when depth rendering takes place. See [enum DepthDrawMode]. See also [member flags_transparent]. </member> <member name="params_diffuse_mode" type="int" setter="set_diffuse_mode" getter="get_diffuse_mode" enum="SpatialMaterial.DiffuseMode"> + The algorithm used for diffuse light scattering. See [enum DiffuseMode]. </member> <member name="params_grow" type="bool" setter="set_grow_enabled" getter="is_grow_enabled"> + If [code]true[/code] enables the vertex grow setting. See [member params_grow_amount]. </member> <member name="params_grow_amount" type="float" setter="set_grow" getter="get_grow"> + Grows object vertices in the direction of their normals. </member> <member name="params_line_width" type="float" setter="set_line_width" getter="get_line_width"> </member> <member name="params_point_size" type="float" setter="set_point_size" getter="get_point_size"> + The point size in pixels. See [member flags_use_point_size]. </member> <member name="params_specular_mode" type="int" setter="set_specular_mode" getter="get_specular_mode" enum="SpatialMaterial.SpecularMode"> + The method for rendering the specular blob. See [enum SpecularMode]. </member> <member name="params_use_alpha_scissor" type="bool" setter="set_flag" getter="get_flag"> </member> <member name="particles_anim_h_frames" type="int" setter="set_particles_anim_h_frames" getter="get_particles_anim_h_frames"> + The number of horizontal frames in the particle spritesheet. Only enabled when using [code]BillboardMode.BILLBOARD_PARTICLES[/code]. See [member params_billboard_mode]. </member> <member name="particles_anim_loop" type="int" setter="set_particles_anim_loop" getter="get_particles_anim_loop"> + If [code]true[/code] particle animations are looped. Only enabled when using [code]BillboardMode.BILLBOARD_PARTICLES[/code]. See [member params_billboard_mode]. </member> <member name="particles_anim_v_frames" type="int" setter="set_particles_anim_v_frames" getter="get_particles_anim_v_frames"> + The number of vertical frames in the particle spritesheet. Only enabled when using [code]BillboardMode.BILLBOARD_PARTICLES[/code]. See [member params_billboard_mode]. </member> <member name="proximity_fade_distance" type="float" setter="set_proximity_fade_distance" getter="get_proximity_fade_distance"> </member> <member name="proximity_fade_enable" type="bool" setter="set_proximity_fade" getter="is_proximity_fade_enabled"> + If [code]true[/code] the proximity and distance fade effect is enabled. Default value: [code]false[/code]. </member> <member name="refraction_enabled" type="bool" setter="set_feature" getter="get_feature"> + If [code]true[/code] the refraction effect is enabled. Distorts transparency based on light from behind the object. Default value: [code]false[/code]. </member> <member name="refraction_scale" type="float" setter="set_refraction" getter="get_refraction"> + The strength of the refraction effect. </member> <member name="refraction_texture" type="Texture" setter="set_texture" getter="get_texture"> </member> @@ -165,26 +204,33 @@ <member name="rim" type="float" setter="set_rim" getter="get_rim"> </member> <member name="rim_enabled" type="bool" setter="set_feature" getter="get_feature"> + If [code]true[/code] rim effect is enabled. Default value: [code]false[/code]. </member> <member name="rim_texture" type="Texture" setter="set_texture" getter="get_texture"> </member> <member name="rim_tint" type="float" setter="set_rim_tint" getter="get_rim_tint"> + The amount of to blend light and albedo color when rendering rim effect. If [code]0[/code] the light color is used, while [code]1[/code] means albedo color is used. An intermediate value generally works best. </member> <member name="roughness" type="float" setter="set_roughness" getter="get_roughness"> + Surface reflection. A value of [code]0[/code] represents a perfect mirror while a value of [code]1[/code] completely blurs the reflection. See also [member metallic]. </member> <member name="roughness_texture" type="Texture" setter="set_texture" getter="get_texture"> </member> <member name="roughness_texture_channel" type="int" setter="set_roughness_texture_channel" getter="get_roughness_texture_channel" enum="SpatialMaterial.TextureChannel"> </member> <member name="subsurf_scatter_enabled" type="bool" setter="set_feature" getter="get_feature"> + If [code]true[/code] subsurface scattering is enabled. Emulates light that penetrates an object's surface, is scattered, and then emerges. </member> <member name="subsurf_scatter_strength" type="float" setter="set_subsurface_scattering_strength" getter="get_subsurface_scattering_strength"> + The strength of the subsurface scattering effect. </member> <member name="subsurf_scatter_texture" type="Texture" setter="set_texture" getter="get_texture"> </member> <member name="transmission" type="Color" setter="set_transmission" getter="get_transmission"> + The color used by the transmission effect. Represents the light passing through an object. </member> <member name="transmission_enabled" type="bool" setter="set_feature" getter="get_feature"> + If [code]true[/code] the transmission effect is enabled. Default value: [code]false[/code]. </member> <member name="transmission_texture" type="Texture" setter="set_texture" getter="get_texture"> </member> @@ -205,8 +251,10 @@ <member name="uv2_triplanar_sharpness" type="float" setter="set_uv2_triplanar_blend_sharpness" getter="get_uv2_triplanar_blend_sharpness"> </member> <member name="vertex_color_is_srgb" type="bool" setter="set_flag" getter="get_flag"> + If [code]true[/code] the model's vertex colors are processed as sRGB mode. Default value: [code]false[/code]. </member> <member name="vertex_color_use_as_albedo" type="bool" setter="set_flag" getter="get_flag"> + If [code]true[/code] the vertex color is used as albedo color. Default value: [code]false[/code]. </member> </members> <constants> @@ -275,6 +323,7 @@ <constant name="FEATURE_MAX" value="12" enum="Feature"> </constant> <constant name="BLEND_MODE_MIX" value="0" enum="BlendMode"> + Default blend mode. </constant> <constant name="BLEND_MODE_ADD" value="1" enum="BlendMode"> </constant> @@ -283,18 +332,25 @@ <constant name="BLEND_MODE_MUL" value="3" enum="BlendMode"> </constant> <constant name="DEPTH_DRAW_OPAQUE_ONLY" value="0" enum="DepthDrawMode"> + Default depth draw mode. Depth is drawn only for opaque objects. </constant> <constant name="DEPTH_DRAW_ALWAYS" value="1" enum="DepthDrawMode"> + Depth draw is calculated for both opaque and transparent objects. </constant> <constant name="DEPTH_DRAW_DISABLED" value="2" enum="DepthDrawMode"> + No depth draw. </constant> <constant name="DEPTH_DRAW_ALPHA_OPAQUE_PREPASS" value="3" enum="DepthDrawMode"> + For transparent objects, an opaque pass is made first with the opaque parts, then transparency is drawn. </constant> <constant name="CULL_BACK" value="0" enum="CullMode"> + Default cull mode. The back of the object is culled when not visible. </constant> <constant name="CULL_FRONT" value="1" enum="CullMode"> + The front of the object is culled when not visible. </constant> <constant name="CULL_DISABLED" value="2" enum="CullMode"> + No culling is performed. </constant> <constant name="FLAG_UNSHADED" value="0" enum="Flags"> </constant> @@ -335,32 +391,46 @@ <constant name="FLAG_MAX" value="18" enum="Flags"> </constant> <constant name="DIFFUSE_BURLEY" value="0" enum="DiffuseMode"> + Default diffuse scattering algorithm. </constant> <constant name="DIFFUSE_LAMBERT" value="1" enum="DiffuseMode"> + Diffuse scattering ignores roughness. </constant> <constant name="DIFFUSE_LAMBERT_WRAP" value="2" enum="DiffuseMode"> + Extends Lambert to cover more than 90 degrees when roughness increases. </constant> <constant name="DIFFUSE_OREN_NAYAR" value="3" enum="DiffuseMode"> + Attempts to use roughness to emulate microsurfacing. </constant> <constant name="DIFFUSE_TOON" value="4" enum="DiffuseMode"> + Uses a hard cut for lighting, with smoothing affected by roughness. </constant> <constant name="SPECULAR_SCHLICK_GGX" value="0" enum="SpecularMode"> + Default specular blob. </constant> <constant name="SPECULAR_BLINN" value="1" enum="SpecularMode"> + Older specular algorithm, included for compatibility. </constant> <constant name="SPECULAR_PHONG" value="2" enum="SpecularMode"> + Older specular algorithm, included for compatibility. </constant> <constant name="SPECULAR_TOON" value="3" enum="SpecularMode"> + Toon blob which changes size based on roughness. </constant> <constant name="SPECULAR_DISABLED" value="4" enum="SpecularMode"> + No specular blob. </constant> <constant name="BILLBOARD_DISABLED" value="0" enum="BillboardMode"> + Default value. </constant> <constant name="BILLBOARD_ENABLED" value="1" enum="BillboardMode"> + The object's z-axis will always face the camera. </constant> <constant name="BILLBOARD_FIXED_Y" value="2" enum="BillboardMode"> + The object's x-axis will always face the camera. </constant> <constant name="BILLBOARD_PARTICLES" value="3" enum="BillboardMode"> + Used for particle systems. Enables particle animation options. </constant> <constant name="TEXTURE_CHANNEL_RED" value="0" enum="TextureChannel"> </constant> diff --git a/doc/classes/SpinBox.xml b/doc/classes/SpinBox.xml index 0fcd5bbaf5..5087cf355a 100644 --- a/doc/classes/SpinBox.xml +++ b/doc/classes/SpinBox.xml @@ -19,6 +19,8 @@ </method> </methods> <members> + <member name="align" type="int" setter="set_align" getter="get_align" enum="LineEdit.Align"> + </member> <member name="editable" type="bool" setter="set_editable" getter="is_editable"> </member> <member name="prefix" type="String" setter="set_prefix" getter="get_prefix"> diff --git a/doc/classes/StreamPeerSSL.xml b/doc/classes/StreamPeerSSL.xml index cf8769d22b..33948df509 100644 --- a/doc/classes/StreamPeerSSL.xml +++ b/doc/classes/StreamPeerSSL.xml @@ -63,6 +63,8 @@ <constant name="STATUS_DISCONNECTED" value="0" enum="Status"> A status representing a [code]StreamPeerSSL[/code] that is disconnected. </constant> + <constant name="STATUS_HANDSHAKING" value="1" enum="Status"> + </constant> <constant name="STATUS_CONNECTED" value="2" enum="Status"> A status representing a [code]StreamPeerSSL[/code] that is connected to a host. </constant> diff --git a/doc/classes/String.xml b/doc/classes/String.xml index d404c32b38..536165487d 100644 --- a/doc/classes/String.xml +++ b/doc/classes/String.xml @@ -671,6 +671,7 @@ <return type="PoolByteArray"> </return> <description> + Returns the SHA-256 hash of the string as an array of bytes. </description> </method> <method name="sha256_text"> diff --git a/doc/classes/SurfaceTool.xml b/doc/classes/SurfaceTool.xml index deda7bc292..4f9ac68e47 100644 --- a/doc/classes/SurfaceTool.xml +++ b/doc/classes/SurfaceTool.xml @@ -14,6 +14,7 @@ [/codeblock] The [code]SurfaceTool[/code] now contains one vertex of a triangle which has a UV coordinate and a specified [Color]. If another vertex were added without calls to [method add_uv] or [method add_color] then the last values would be used. It is very important that vertex attributes are passed [b]before[/b] the call to [method add_vertex], failure to do this will result in an error when committing the vertex information to a mesh. + Additionally, the attributes used before the first vertex is added determine the format of the mesh. For example if you only add UVs to the first vertex, you cannot add color to any of the subsequent vertices. </description> <tutorials> </tutorials> @@ -26,7 +27,7 @@ <argument index="0" name="bones" type="PoolIntArray"> </argument> <description> - Add an array of bones for the next Vertex to use. + Add an array of bones for the next Vertex to use. Array must contain 4 integers. </description> </method> <method name="add_color"> @@ -99,6 +100,7 @@ </argument> <description> Insert a triangle fan made of array data into [Mesh] being constructed. + Requires primitive type be set to [code]PRIMITIVE_TRIANGLES[/code]. </description> </method> <method name="add_uv"> @@ -134,7 +136,7 @@ <argument index="0" name="weights" type="PoolRealArray"> </argument> <description> - Specify weight value for next Vertex to use. + Specify weight values for next Vertex to use. Array must contain 4 values. </description> </method> <method name="append_from"> @@ -147,6 +149,7 @@ <argument index="2" name="transform" type="Transform"> </argument> <description> + Append vertices from a given [Mesh] surface onto the current vertex array with specified [Transform]. </description> </method> <method name="begin"> @@ -184,6 +187,7 @@ <argument index="1" name="surface" type="int"> </argument> <description> + Creates a vertex array from an existing [Mesh]. </description> </method> <method name="deindex"> @@ -201,12 +205,15 @@ <description> Generates normals from Vertices so you do not have to do it manually. Setting "flip" [code]true[/code] inverts resulting normals. + Requires primitive type to be set to [code]PRIMITIVE_TRIANGLES[/code]. </description> </method> <method name="generate_tangents"> <return type="void"> </return> <description> + Generates a tangent vector for each vertex. + Requires that each vertex have UVs and normals set already. </description> </method> <method name="index"> diff --git a/doc/classes/TabContainer.xml b/doc/classes/TabContainer.xml index 5acfd6194e..f17c10b31e 100644 --- a/doc/classes/TabContainer.xml +++ b/doc/classes/TabContainer.xml @@ -82,6 +82,7 @@ <return type="int"> </return> <description> + Returns the [code]TabContainer[/code] rearrange group id. </description> </method> <method name="set_popup"> @@ -132,6 +133,7 @@ <argument index="0" name="group_id" type="int"> </argument> <description> + Defines rearrange group id, choose for each [code]TabContainer[/code] the same value to enable tab drag between [code]TabContainer[/code]. Enable drag with [code]set_drag_to_rearrange_enabled(true)[/code]. </description> </method> </methods> @@ -140,6 +142,7 @@ The current tab index. When set, this index's [Control] node's [code]visible[/code] property is set to [code]true[/code] and all others are set to [code]false[/code]. </member> <member name="drag_to_rearrange_enabled" type="bool" setter="set_drag_to_rearrange_enabled" getter="get_drag_to_rearrange_enabled"> + If [code]true[/code], tabs can be rearranged with mouse drag. </member> <member name="tab_align" type="int" setter="set_tab_align" getter="get_tab_align" enum="TabContainer.TabAlign"> The alignment of all tabs in the tab container. See the [code]ALIGN_*[/code] constants for details. @@ -171,10 +174,13 @@ </signals> <constants> <constant name="ALIGN_LEFT" value="0" enum="TabAlign"> + Align the tabs to the left. </constant> <constant name="ALIGN_CENTER" value="1" enum="TabAlign"> + Align the tabs to the center. </constant> <constant name="ALIGN_RIGHT" value="2" enum="TabAlign"> + Align the tabs to the right. </constant> </constants> <theme_items> diff --git a/doc/classes/Tabs.xml b/doc/classes/Tabs.xml index fc1d0476ed..350b49513d 100644 --- a/doc/classes/Tabs.xml +++ b/doc/classes/Tabs.xml @@ -19,6 +19,7 @@ <argument index="1" name="icon" type="Texture" default="null"> </argument> <description> + Adds a new tab. </description> </method> <method name="ensure_tab_visible"> @@ -27,6 +28,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Moves the Scroll view to make the tab visible. </description> </method> <method name="get_offset_buttons_visible" qualifiers="const"> @@ -39,12 +41,14 @@ <return type="bool"> </return> <description> + Returns [code]true[/code] if select with right mouse button is enabled. </description> </method> <method name="get_tab_count" qualifiers="const"> <return type="int"> </return> <description> + Returns the number of tabs. </description> </method> <method name="get_tab_disabled" qualifiers="const"> @@ -53,6 +57,7 @@ <argument index="0" name="tab_idx" type="int"> </argument> <description> + Returns [code]true[/code] if the tab at index [code]tab_idx[/code] is disabled. </description> </method> <method name="get_tab_icon" qualifiers="const"> @@ -61,6 +66,7 @@ <argument index="0" name="tab_idx" type="int"> </argument> <description> + Returns the [Texture] for the tab at index [code]tab_idx[/code] or null if the tab has no [Texture]. </description> </method> <method name="get_tab_offset" qualifiers="const"> @@ -84,12 +90,14 @@ <argument index="0" name="tab_idx" type="int"> </argument> <description> + Returns the title of the tab at index [code]tab_idx[/code]. Tab titles default to the name of the indexed child node, but this can be overridden with [method set_tab_title]. </description> </method> <method name="get_tabs_rearrange_group" qualifiers="const"> <return type="int"> </return> <description> + Returns the [code]Tabs[/code] rearrange group id. </description> </method> <method name="move_tab"> @@ -109,6 +117,7 @@ <argument index="0" name="tab_idx" type="int"> </argument> <description> + Removes tab at index [code]tab_idx[/code] </description> </method> <method name="set_select_with_rmb"> @@ -117,6 +126,7 @@ <argument index="0" name="enabled" type="bool"> </argument> <description> + If [code]true[/code] enables selecting a tab with right mouse button. </description> </method> <method name="set_tab_disabled"> @@ -127,6 +137,7 @@ <argument index="1" name="disabled" type="bool"> </argument> <description> + If [code]disabled[/code] is false, hides the tab at index [code]tab_idx[/code]. Note that its title text will remain, unless also removed with [method set_tab_title]. </description> </method> <method name="set_tab_icon"> @@ -137,6 +148,7 @@ <argument index="1" name="icon" type="Texture"> </argument> <description> + Sets an icon for the tab at index [code]tab_idx[/code]. </description> </method> <method name="set_tab_title"> @@ -147,6 +159,7 @@ <argument index="1" name="title" type="String"> </argument> <description> + Sets a title for the tab at index [code]tab_idx[/code]. </description> </method> <method name="set_tabs_rearrange_group"> @@ -155,17 +168,21 @@ <argument index="0" name="group_id" type="int"> </argument> <description> + Defines rearrange group id, choose for each [code]Tabs[/code] the same value to enable tab drag between [code]Tabs[/code]. Enable drag with [code]set_drag_to_rearrange_enabled(true)[/code]. </description> </method> </methods> <members> <member name="current_tab" type="int" setter="set_current_tab" getter="get_current_tab"> + Select tab at index [code]tab_idx[/code]. </member> <member name="drag_to_rearrange_enabled" type="bool" setter="set_drag_to_rearrange_enabled" getter="get_drag_to_rearrange_enabled"> + If [code]true[/code], tabs can be rearranged with mouse drag. </member> <member name="scrolling_enabled" type="bool" setter="set_scrolling_enabled" getter="get_scrolling_enabled"> </member> <member name="tab_align" type="int" setter="set_tab_align" getter="get_tab_align" enum="Tabs.TabAlign"> + The alignment of all tabs. See enum [code]TabAlign[/code] constants for details. </member> <member name="tab_close_display_policy" type="int" setter="set_tab_close_display_policy" getter="get_tab_close_display_policy" enum="Tabs.CloseButtonDisplayPolicy"> </member> @@ -210,10 +227,13 @@ </signals> <constants> <constant name="ALIGN_LEFT" value="0" enum="TabAlign"> + Align the tabs to the left. </constant> <constant name="ALIGN_CENTER" value="1" enum="TabAlign"> + Align the tabs to the center. </constant> <constant name="ALIGN_RIGHT" value="2" enum="TabAlign"> + Align the tabs to the right. </constant> <constant name="ALIGN_MAX" value="3" enum="TabAlign"> </constant> diff --git a/doc/classes/TileSet.xml b/doc/classes/TileSet.xml index 3f0d6317a6..ffd15e8d8b 100644 --- a/doc/classes/TileSet.xml +++ b/doc/classes/TileSet.xml @@ -268,7 +268,7 @@ <argument index="1" name="shape_id" type="int"> </argument> <description> - Returns the [Transform2D] of a tile's sahpe. + Returns the [Transform2D] of a tile's shape. </description> </method> <method name="tile_get_shapes" qualifiers="const"> diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml index 0431718066..8051062fc4 100644 --- a/doc/classes/Tree.xml +++ b/doc/classes/Tree.xml @@ -230,7 +230,7 @@ The amount of columns. </member> <member name="drop_mode_flags" type="int" setter="set_drop_mode_flags" getter="get_drop_mode_flags"> - The drop mode as an OR combination of flags. See [code]DROP_MODE_*[/code] constants. Once dropping is done, reverts to [code]DROP_MODE_DISABLED[/code]. Setting this during [method can_drop_data] is recommended. + The drop mode as an OR combination of flags. See [code]DROP_MODE_*[/code] constants. Once dropping is done, reverts to [code]DROP_MODE_DISABLED[/code]. Setting this during [method Control.can_drop_data] is recommended. </member> <member name="hide_folding" type="bool" setter="set_hide_folding" getter="is_folding_hidden"> If [code]true[/code] the folding arrow is hidden. diff --git a/doc/classes/TreeItem.xml b/doc/classes/TreeItem.xml index c5a63b1acb..b4227b34be 100644 --- a/doc/classes/TreeItem.xml +++ b/doc/classes/TreeItem.xml @@ -25,7 +25,7 @@ <argument index="4" name="tooltip" type="String" default=""""> </argument> <description> - Adds a button with [Texture] [code]button[/code] at column [code]column[/code]. The [code]button_idx[/code] index is used to identify the button when calling other methods. If not specified, the next available index is used, which may be retrieved by calling [code]get_buton_count()[/code] immediately after this method. Optionally, the button can be [code]disabled[/code] and have a [code]tooltip[/code]. + Adds a button with [Texture] [code]button[/code] at column [code]column[/code]. The [code]button_idx[/code] index is used to identify the button when calling other methods. If not specified, the next available index is used, which may be retrieved by calling [method get_button_count] immediately after this method. Optionally, the button can be [code]disabled[/code] and have a [code]tooltip[/code]. </description> </method> <method name="clear_custom_bg_color"> @@ -559,13 +559,10 @@ <constant name="CELL_MODE_RANGE" value="2" enum="TreeCellMode"> Cell contains a range. </constant> - <constant name="CELL_MODE_RANGE_EXPRESSION" value="3" enum="TreeCellMode"> - Cell contains a range expression. - </constant> - <constant name="CELL_MODE_ICON" value="4" enum="TreeCellMode"> + <constant name="CELL_MODE_ICON" value="3" enum="TreeCellMode"> Cell contains an icon. </constant> - <constant name="CELL_MODE_CUSTOM" value="5" enum="TreeCellMode"> + <constant name="CELL_MODE_CUSTOM" value="4" enum="TreeCellMode"> </constant> <constant name="ALIGN_LEFT" value="0" enum="TextAlign"> Align text to the left. See [code]set_text_align()[/code]. diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml index 7e03e7f0fe..c323cf6992 100644 --- a/doc/classes/Vector2.xml +++ b/doc/classes/Vector2.xml @@ -267,7 +267,10 @@ </members> <constants> <constant name="ZERO" value="Vector2( 0, 0 )"> - Null vector. + Zero vector. + </constant> + <constant name="ONE" value="Vector2( 1, 1 )"> + One vector. </constant> <constant name="INF" value="Vector2( inf, inf )"> Infinite vector. diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml index 4211c34d8e..8c4e08778d 100644 --- a/doc/classes/Vector3.xml +++ b/doc/classes/Vector3.xml @@ -280,7 +280,10 @@ Enumerated value for the Z axis. </constant> <constant name="ZERO" value="Vector3( 0, 0, 0 )"> - Null vector. + Zero vector. + </constant> + <constant name="ONE" value="Vector3( 1, 1, 1 )"> + One vector. </constant> <constant name="INF" value="Vector3( inf, inf, inf )"> Infinite vector. diff --git a/doc/classes/VisualServer.xml b/doc/classes/VisualServer.xml index 58b3d33cdb..225a1f2bba 100644 --- a/doc/classes/VisualServer.xml +++ b/doc/classes/VisualServer.xml @@ -4380,7 +4380,7 @@ </constant> <constant name="ENV_TONE_MAPPER_LINEAR" value="0" enum="EnvironmentToneMapper"> </constant> - <constant name="ENV_TONE_MAPPER_REINHARDT" value="1" enum="EnvironmentToneMapper"> + <constant name="ENV_TONE_MAPPER_REINHARD" value="1" enum="EnvironmentToneMapper"> </constant> <constant name="ENV_TONE_MAPPER_FILMIC" value="2" enum="EnvironmentToneMapper"> </constant> diff --git a/drivers/coreaudio/audio_driver_coreaudio.cpp b/drivers/coreaudio/audio_driver_coreaudio.cpp index 09e50e4aaa..aaec63d7ff 100644 --- a/drivers/coreaudio/audio_driver_coreaudio.cpp +++ b/drivers/coreaudio/audio_driver_coreaudio.cpp @@ -95,11 +95,6 @@ Error AudioDriverCoreAudio::init() { result = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &prop, &output_device_address_cb, this); ERR_FAIL_COND_V(result != noErr, FAILED); - - prop.mSelector = kAudioHardwarePropertyDefaultInputDevice; - - result = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &prop, &input_device_address_cb, this); - ERR_FAIL_COND_V(result != noErr, FAILED); #endif AudioStreamBasicDescription strdesc; @@ -123,26 +118,6 @@ Error AudioDriverCoreAudio::init() { break; } - zeromem(&strdesc, sizeof(strdesc)); - size = sizeof(strdesc); - result = AudioUnitGetProperty(audio_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &strdesc, &size); - ERR_FAIL_COND_V(result != noErr, FAILED); - - switch (strdesc.mChannelsPerFrame) { - case 1: // Mono - capture_channels = 1; - break; - - case 2: // Stereo - capture_channels = 2; - break; - - default: - // Unknown number of channels, default to stereo - capture_channels = 2; - break; - } - mix_rate = GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE); zeromem(&strdesc, sizeof(strdesc)); @@ -158,11 +133,6 @@ Error AudioDriverCoreAudio::init() { result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, kOutputBus, &strdesc, sizeof(strdesc)); ERR_FAIL_COND_V(result != noErr, FAILED); - strdesc.mChannelsPerFrame = capture_channels; - - result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &strdesc, sizeof(strdesc)); - ERR_FAIL_COND_V(result != noErr, FAILED); - int latency = GLOBAL_DEF_RST("audio/output_latency", DEFAULT_OUTPUT_LATENCY); // Sample rate is independent of channels (ref: https://stackoverflow.com/questions/11048825/audio-sample-frequency-rely-on-channels) buffer_frames = closest_power_of_2(latency * mix_rate / 1000); @@ -189,16 +159,10 @@ Error AudioDriverCoreAudio::init() { result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, kOutputBus, &callback, sizeof(callback)); ERR_FAIL_COND_V(result != noErr, FAILED); - zeromem(&callback, sizeof(AURenderCallbackStruct)); - callback.inputProc = &AudioDriverCoreAudio::input_callback; - callback.inputProcRefCon = this; - result = AudioUnitSetProperty(audio_unit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &callback, sizeof(callback)); - ERR_FAIL_COND_V(result != noErr, FAILED); - result = AudioUnitInitialize(audio_unit); ERR_FAIL_COND_V(result != noErr, FAILED); - return OK; + return capture_init(); } OSStatus AudioDriverCoreAudio::output_callback(void *inRefCon, @@ -265,7 +229,7 @@ OSStatus AudioDriverCoreAudio::input_callback(void *inRefCon, bufferList.mBuffers[0].mNumberChannels = ad->capture_channels; bufferList.mBuffers[0].mDataByteSize = ad->input_buf.size() * sizeof(int16_t); - OSStatus result = AudioUnitRender(ad->audio_unit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &bufferList); + OSStatus result = AudioUnitRender(ad->input_unit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &bufferList); if (result == noErr) { for (int i = 0; i < inNumberFrames * ad->capture_channels; i++) { int32_t sample = ad->input_buf[i] << 16; @@ -277,7 +241,7 @@ OSStatus AudioDriverCoreAudio::input_callback(void *inRefCon, } } } else { - ERR_PRINT(("AudioUnitRender failed, code: " + itos(result)).utf8().get_data()); + ERR_PRINTS("AudioUnitRender failed, code: " + itos(result)); } ad->unlock(); @@ -289,7 +253,7 @@ void AudioDriverCoreAudio::start() { if (!active) { OSStatus result = AudioOutputUnitStart(audio_unit); if (result != noErr) { - ERR_PRINT(("AudioOutputUnitStart failed, code: " + itos(result)).utf8().get_data()); + ERR_PRINTS("AudioOutputUnitStart failed, code: " + itos(result)); } else { active = true; } @@ -300,7 +264,7 @@ void AudioDriverCoreAudio::stop() { if (active) { OSStatus result = AudioOutputUnitStop(audio_unit); if (result != noErr) { - ERR_PRINT(("AudioOutputUnitStop failed, code: " + itos(result)).utf8().get_data()); + ERR_PRINTS("AudioOutputUnitStop failed, code: " + itos(result)); } else { active = false; } @@ -332,6 +296,8 @@ bool AudioDriverCoreAudio::try_lock() { } void AudioDriverCoreAudio::finish() { + capture_finish(); + if (audio_unit) { OSStatus result; @@ -375,6 +341,7 @@ void AudioDriverCoreAudio::finish() { ERR_PRINT("AudioComponentInstanceDispose failed"); } + audio_unit = NULL; unlock(); } @@ -384,20 +351,158 @@ void AudioDriverCoreAudio::finish() { } } -Error AudioDriverCoreAudio::capture_start() { +Error AudioDriverCoreAudio::capture_init() { + AudioComponentDescription desc; + zeromem(&desc, sizeof(desc)); + desc.componentType = kAudioUnitType_Output; +#ifdef OSX_ENABLED + desc.componentSubType = kAudioUnitSubType_HALOutput; +#else + desc.componentSubType = kAudioUnitSubType_RemoteIO; +#endif + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + + AudioComponent comp = AudioComponentFindNext(NULL, &desc); + ERR_FAIL_COND_V(comp == NULL, FAILED); + + OSStatus result = AudioComponentInstanceNew(comp, &input_unit); + ERR_FAIL_COND_V(result != noErr, FAILED); + +#ifdef OSX_ENABLED + AudioObjectPropertyAddress prop; + prop.mSelector = kAudioHardwarePropertyDefaultInputDevice; + prop.mScope = kAudioObjectPropertyScopeGlobal; + prop.mElement = kAudioObjectPropertyElementMaster; + + result = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &prop, &input_device_address_cb, this); + ERR_FAIL_COND_V(result != noErr, FAILED); +#endif UInt32 flag = 1; - OSStatus result = AudioUnitSetProperty(audio_unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &flag, sizeof(flag)); + result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &flag, sizeof(flag)); + ERR_FAIL_COND_V(result != noErr, FAILED); + flag = 0; + result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, kOutputBus, &flag, sizeof(flag)); + ERR_FAIL_COND_V(result != noErr, FAILED); + + UInt32 size; +#ifdef OSX_ENABLED + AudioDeviceID deviceId; + size = sizeof(AudioDeviceID); + AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; + + result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &property, 0, NULL, &size, &deviceId); ERR_FAIL_COND_V(result != noErr, FAILED); + result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &deviceId, sizeof(AudioDeviceID)); + ERR_FAIL_COND_V(result != noErr, FAILED); +#endif + + AudioStreamBasicDescription strdesc; + zeromem(&strdesc, sizeof(strdesc)); + size = sizeof(strdesc); + result = AudioUnitGetProperty(input_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &strdesc, &size); + ERR_FAIL_COND_V(result != noErr, FAILED); + + switch (strdesc.mChannelsPerFrame) { + case 1: // Mono + capture_channels = 1; + break; + + case 2: // Stereo + capture_channels = 2; + break; + + default: + // Unknown number of channels, default to stereo + capture_channels = 2; + break; + } + + mix_rate = GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE); + + zeromem(&strdesc, sizeof(strdesc)); + strdesc.mFormatID = kAudioFormatLinearPCM; + strdesc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; + strdesc.mChannelsPerFrame = capture_channels; + strdesc.mSampleRate = mix_rate; + strdesc.mFramesPerPacket = 1; + strdesc.mBitsPerChannel = 16; + strdesc.mBytesPerFrame = strdesc.mBitsPerChannel * strdesc.mChannelsPerFrame / 8; + strdesc.mBytesPerPacket = strdesc.mBytesPerFrame * strdesc.mFramesPerPacket; + + result = AudioUnitSetProperty(input_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &strdesc, sizeof(strdesc)); + ERR_FAIL_COND_V(result != noErr, FAILED); + + AURenderCallbackStruct callback; + zeromem(&callback, sizeof(AURenderCallbackStruct)); + callback.inputProc = &AudioDriverCoreAudio::input_callback; + callback.inputProcRefCon = this; + result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, kInputBus, &callback, sizeof(callback)); + ERR_FAIL_COND_V(result != noErr, FAILED); + + result = AudioUnitInitialize(input_unit); + ERR_FAIL_COND_V(result != noErr, FAILED); + + return OK; +} + +void AudioDriverCoreAudio::capture_finish() { + if (input_unit) { + lock(); + + AURenderCallbackStruct callback; + zeromem(&callback, sizeof(AURenderCallbackStruct)); + OSStatus result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &callback, sizeof(callback)); + if (result != noErr) { + ERR_PRINT("AudioUnitSetProperty failed"); + } + + result = AudioUnitUninitialize(input_unit); + if (result != noErr) { + ERR_PRINT("AudioUnitUninitialize failed"); + } + +#ifdef OSX_ENABLED + AudioObjectPropertyAddress prop; + prop.mSelector = kAudioHardwarePropertyDefaultInputDevice; + prop.mScope = kAudioObjectPropertyScopeGlobal; + prop.mElement = kAudioObjectPropertyElementMaster; + + result = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &prop, &input_device_address_cb, this); + if (result != noErr) { + ERR_PRINT("AudioObjectRemovePropertyListener failed"); + } +#endif + + result = AudioComponentInstanceDispose(input_unit); + if (result != noErr) { + ERR_PRINT("AudioComponentInstanceDispose failed"); + } + + input_unit = NULL; + unlock(); + } +} + +Error AudioDriverCoreAudio::capture_start() { + + OSStatus result = AudioOutputUnitStart(input_unit); + if (result != noErr) { + ERR_PRINTS("AudioOutputUnitStart failed, code: " + itos(result)); + } + return OK; } Error AudioDriverCoreAudio::capture_stop() { - UInt32 flag = 0; - OSStatus result = AudioUnitSetProperty(audio_unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &flag, sizeof(flag)); - ERR_FAIL_COND_V(result != noErr, FAILED); + if (input_unit) { + OSStatus result = AudioOutputUnitStop(input_unit); + if (result != noErr) { + ERR_PRINTS("AudioOutputUnitStop failed, code: " + itos(result)); + } + } return OK; } @@ -531,12 +636,14 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) { } if (found) { - OSStatus result = AudioUnitSetProperty(audio_unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, capture ? kInputBus : kOutputBus, &deviceId, sizeof(AudioDeviceID)); + OSStatus result = AudioUnitSetProperty(capture ? input_unit : audio_unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &deviceId, sizeof(AudioDeviceID)); ERR_FAIL_COND(result != noErr); - // Reset audio input to keep synchronisation. - input_position = 0; - input_size = 0; + if (capture) { + // Reset audio input to keep synchronisation. + input_position = 0; + input_size = 0; + } } } @@ -580,6 +687,7 @@ String AudioDriverCoreAudio::capture_get_device() { AudioDriverCoreAudio::AudioDriverCoreAudio() { audio_unit = NULL; + input_unit = NULL; active = false; mutex = NULL; diff --git a/drivers/coreaudio/audio_driver_coreaudio.h b/drivers/coreaudio/audio_driver_coreaudio.h index d3f7c8d596..474a9e43ae 100644 --- a/drivers/coreaudio/audio_driver_coreaudio.h +++ b/drivers/coreaudio/audio_driver_coreaudio.h @@ -43,6 +43,7 @@ class AudioDriverCoreAudio : public AudioDriver { AudioComponentInstance audio_unit; + AudioComponentInstance input_unit; bool active; Mutex *mutex; @@ -83,6 +84,9 @@ class AudioDriverCoreAudio : public AudioDriver { UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData); + Error capture_init(); + void capture_finish(); + public: const char *get_name() const { return "CoreAudio"; diff --git a/drivers/coremidi/core_midi.cpp b/drivers/coremidi/core_midi.cpp index e8106c4543..2ebbabaa38 100644 --- a/drivers/coremidi/core_midi.cpp +++ b/drivers/coremidi/core_midi.cpp @@ -51,13 +51,13 @@ Error MIDIDriverCoreMidi::open() { OSStatus result = MIDIClientCreate(name, NULL, NULL, &client); CFRelease(name); if (result != noErr) { - ERR_PRINTS("MIDIClientCreate failed: " + String(GetMacOSStatusErrorString(result))); + ERR_PRINTS("MIDIClientCreate failed, code: " + itos(result)); return ERR_CANT_OPEN; } result = MIDIInputPortCreate(client, CFSTR("Godot Input"), MIDIDriverCoreMidi::read, (void *)this, &port_in); if (result != noErr) { - ERR_PRINTS("MIDIInputPortCreate failed: " + String(GetMacOSStatusErrorString(result))); + ERR_PRINTS("MIDIInputPortCreate failed, code: " + itos(result)); return ERR_CANT_OPEN; } @@ -65,7 +65,7 @@ Error MIDIDriverCoreMidi::open() { for (int i = 0; i < sources; i++) { MIDIEndpointRef source = MIDIGetSource(i); - if (source != NULL) { + if (source) { MIDIPortConnectSource(port_in, source, (void *)this); connected_sources.insert(i, source); } diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h index b42e2dfb1f..c928f753b1 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -43,7 +43,6 @@ /* #include "shaders/blend_shape.glsl.gen.h" #include "shaders/canvas.glsl.gen.h" -#include "shaders/copy.glsl.gen.h" #include "shaders/particles.glsl.gen.h" */ diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl index fae010b003..7b57f5d497 100644 --- a/drivers/gles2/shaders/scene.glsl +++ b/drivers/gles2/shaders/scene.glsl @@ -75,12 +75,12 @@ attribute highp vec4 instance_custom_data; // attrib:12 // uniforms // -uniform mat4 camera_matrix; -uniform mat4 camera_inverse_matrix; -uniform mat4 projection_matrix; -uniform mat4 projection_inverse_matrix; +uniform highp mat4 camera_matrix; +uniform highp mat4 camera_inverse_matrix; +uniform highp mat4 projection_matrix; +uniform highp mat4 projection_inverse_matrix; -uniform mat4 world_transform; +uniform highp mat4 world_transform; uniform highp float time; @@ -156,22 +156,22 @@ varying highp vec3 diffuse_interp; varying highp vec3 specular_interp; // general for all lights -uniform vec4 light_color; -uniform float light_specular; +uniform highp vec4 light_color; +uniform highp float light_specular; // directional -uniform vec3 light_direction; +uniform highp vec3 light_direction; // omni -uniform vec3 light_position; +uniform highp vec3 light_position; -uniform float light_range; -uniform float light_attenuation; +uniform highp float light_range; +uniform highp float light_attenuation; // spot -uniform float light_spot_attenuation; -uniform float light_spot_range; -uniform float light_spot_angle; +uniform highp float light_spot_attenuation; +uniform highp float light_spot_range; +uniform highp float light_spot_angle; void light_compute( vec3 N, @@ -262,9 +262,9 @@ void light_compute( #ifdef USE_REFLECTION_PROBE1 -uniform mat4 refprobe1_local_matrix; +uniform highp mat4 refprobe1_local_matrix; varying mediump vec4 refprobe1_reflection_normal_blend; -uniform vec3 refprobe1_box_extents; +uniform highp vec3 refprobe1_box_extents; #ifndef USE_LIGHTMAP varying mediump vec3 refprobe1_ambient_normal; @@ -274,9 +274,9 @@ varying mediump vec3 refprobe1_ambient_normal; #ifdef USE_REFLECTION_PROBE2 -uniform mat4 refprobe2_local_matrix; +uniform highp mat4 refprobe2_local_matrix; varying mediump vec4 refprobe2_reflection_normal_blend; -uniform vec3 refprobe2_box_extents; +uniform highp vec3 refprobe2_box_extents; #ifndef USE_LIGHTMAP varying mediump vec3 refprobe2_ambient_normal; @@ -310,7 +310,6 @@ uniform highp float fog_height_max; uniform mediump float fog_height_curve; #endif - #endif //fog void main() { @@ -625,19 +624,19 @@ VERTEX_SHADER_CODE { - float fog_z = smoothstep(fog_depth_begin, fog_max_distance, length(vertex)); + float fog_z = smoothstep(fog_depth_begin, fog_max_distance, length(vertex)); - fog_amount = pow(fog_z, fog_depth_curve); + fog_amount = pow(fog_z, fog_depth_curve); } #endif #ifdef FOG_HEIGHT_ENABLED { - float y = (camera_matrix * vec4(vertex_interp, 1.0)).y; - fog_amount = max(fog_amount, pow(smoothstep(fog_height_min, fog_height_max, y), fog_height_curve)); + float y = (camera_matrix * vec4(vertex_interp, 1.0)).y; + fog_amount = max(fog_amount, pow(smoothstep(fog_height_min, fog_height_max, y), fog_height_curve)); } #endif - fog_interp = vec4(fog_color,fog_amount); + fog_interp = vec4(fog_color, fog_amount); #endif //fog @@ -671,13 +670,13 @@ precision highp int; // uniforms // -uniform mat4 camera_matrix; +uniform highp mat4 camera_matrix; /* clang-format on */ -uniform mat4 camera_inverse_matrix; -uniform mat4 projection_matrix; -uniform mat4 projection_inverse_matrix; +uniform highp mat4 camera_inverse_matrix; +uniform highp mat4 projection_matrix; +uniform highp mat4 projection_inverse_matrix; -uniform mat4 world_transform; +uniform highp mat4 world_transform; uniform highp float time; @@ -704,9 +703,9 @@ varying mediump vec3 refprobe1_ambient_normal; #else uniform bool refprobe1_use_box_project; -uniform vec3 refprobe1_box_extents; +uniform highp vec3 refprobe1_box_extents; uniform vec3 refprobe1_box_offset; -uniform mat4 refprobe1_local_matrix; +uniform highp mat4 refprobe1_local_matrix; #endif //use vertex lighting @@ -731,9 +730,9 @@ varying mediump vec3 refprobe2_ambient_normal; #else uniform bool refprobe2_use_box_project; -uniform vec3 refprobe2_box_extents; +uniform highp vec3 refprobe2_box_extents; uniform vec3 refprobe2_box_offset; -uniform mat4 refprobe2_local_matrix; +uniform highp mat4 refprobe2_local_matrix; #endif //use vertex lighting @@ -874,29 +873,29 @@ uniform float ambient_energy; varying highp vec3 diffuse_interp; varying highp vec3 specular_interp; -uniform vec3 light_direction; //may be used by fog, so leave here +uniform highp vec3 light_direction; //may be used by fog, so leave here #else //done in fragment // general for all lights -uniform vec4 light_color; -uniform float light_specular; +uniform highp vec4 light_color; +uniform highp float light_specular; // directional -uniform vec3 light_direction; +uniform highp vec3 light_direction; // omni -uniform vec3 light_position; +uniform highp vec3 light_position; -uniform float light_attenuation; +uniform highp float light_attenuation; // spot -uniform float light_spot_attenuation; -uniform float light_spot_range; -uniform float light_spot_angle; +uniform highp float light_spot_attenuation; +uniform highp float light_spot_range; +uniform highp float light_spot_angle; #endif //this is needed outside above if because dual paraboloid wants it -uniform float light_range; +uniform highp float light_range; #ifdef USE_SHADOW @@ -2021,8 +2020,8 @@ FRAGMENT_SHADER_CODE #if defined(USE_VERTEX_LIGHTING) - gl_FragColor.rgb = mix(gl_FragColor.rgb,fog_interp.rgb,fog_interp.a); -#else //pixel based fog + gl_FragColor.rgb = mix(gl_FragColor.rgb, fog_interp.rgb, fog_interp.a); +#else //pixel based fog float fog_amount = 0.0; #ifdef LIGHT_MODE_DIRECTIONAL @@ -2036,26 +2035,26 @@ FRAGMENT_SHADER_CODE { - float fog_z = smoothstep(fog_depth_begin, fog_max_distance, length(vertex)); + float fog_z = smoothstep(fog_depth_begin, fog_max_distance, length(vertex)); - fog_amount = pow(fog_z, fog_depth_curve); + fog_amount = pow(fog_z, fog_depth_curve); - if (fog_transmit_enabled) { - vec3 total_light = gl_FragColor.rgb; - float transmit = pow(fog_z, fog_transmit_curve); - fog_color = mix(max(total_light, fog_color), fog_color, transmit); - } + if (fog_transmit_enabled) { + vec3 total_light = gl_FragColor.rgb; + float transmit = pow(fog_z, fog_transmit_curve); + fog_color = mix(max(total_light, fog_color), fog_color, transmit); + } } #endif #ifdef FOG_HEIGHT_ENABLED { - float y = (camera_matrix * vec4(vertex, 1.0)).y; - fog_amount = max(fog_amount, pow(smoothstep(fog_height_min, fog_height_max, y), fog_height_curve)); + float y = (camera_matrix * vec4(vertex, 1.0)).y; + fog_amount = max(fog_amount, pow(smoothstep(fog_height_min, fog_height_max, y), fog_height_curve)); } #endif - gl_FragColor.rgb = mix(gl_FragColor.rgb,fog_color,fog_amount); + gl_FragColor.rgb = mix(gl_FragColor.rgb, fog_color, fog_amount); #endif //use vertex lit diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 14c436fd00..ed2b39a17d 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -653,7 +653,7 @@ bool RasterizerSceneGLES3::reflection_probe_instance_begin_render(RID p_instance int best_free = -1; int best_used = -1; - uint64_t best_used_frame; + uint64_t best_used_frame = 0; for (int i = 0; i < reflection_atlas->reflections.size(); i++) { if (reflection_atlas->reflections[i].owner == RID()) { @@ -2519,7 +2519,7 @@ void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const C storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_PANORAMA, false); } -void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform) { +void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog) { //store camera into ubo store_camera(p_cam_projection, state.ubo_data.projection_matrix); @@ -2570,7 +2570,7 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatr state.ubo_data.fog_color_enabled[0] = linear_fog.r; state.ubo_data.fog_color_enabled[1] = linear_fog.g; state.ubo_data.fog_color_enabled[2] = linear_fog.b; - state.ubo_data.fog_color_enabled[3] = env->fog_enabled ? 1.0 : 0.0; + state.ubo_data.fog_color_enabled[3] = (!p_no_fog && env->fog_enabled) ? 1.0 : 0.0; Color linear_sun = env->fog_sun_color.to_linear(); state.ubo_data.fog_sun_color_amount[0] = linear_sun.r; @@ -4083,7 +4083,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const state.ubo_data.screen_pixel_size[1] = 1.0 / storage->frame.current_rt->height; } - _setup_environment(env, p_cam_projection, p_cam_transform); + _setup_environment(env, p_cam_projection, p_cam_transform, p_reflection_probe.is_valid()); bool fb_cleared = false; diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index b4c4a0558f..4b4a0b9303 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -831,7 +831,7 @@ public: void _draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy); - void _setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform); + void _setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog = false); void _setup_directional_light(int p_index, const Transform &p_camera_inverse_transform, bool p_use_shadows); void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, const CameraMatrix &p_camera_projection, RID p_shadow_atlas); void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, const CameraMatrix &p_camera_projection, RID p_reflection_atlas, Environment *p_env); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 58c0a104c1..a9aa152f10 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -730,7 +730,7 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p } }; - GLenum blit_target; + GLenum blit_target = GL_TEXTURE_2D; switch (texture->type) { case VS::TEXTURE_TYPE_2D: { @@ -948,7 +948,7 @@ void RasterizerStorageGLES3::texture_set_data_partial(RID p_texture, const Ref<I Image::Format real_format; Ref<Image> img = _get_gl_image_and_format(p_sub_img, p_sub_img->get_format(), texture->flags, real_format, format, internal_format, type, compressed, srgb); - GLenum blit_target; + GLenum blit_target = GL_TEXTURE_2D; switch (texture->type) { case VS::TEXTURE_TYPE_2D: { @@ -4066,35 +4066,37 @@ void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances multimesh->data.resize(format_floats * p_instances); + float *dataptr = multimesh->data.ptrw(); + for (int i = 0; i < p_instances * format_floats; i += format_floats) { int color_from = 0; int custom_data_from = 0; if (multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D) { - multimesh->data.write[i + 0] = 1.0; - multimesh->data.write[i + 1] = 0.0; - multimesh->data.write[i + 2] = 0.0; - multimesh->data.write[i + 3] = 0.0; - multimesh->data.write[i + 4] = 0.0; - multimesh->data.write[i + 5] = 1.0; - multimesh->data.write[i + 6] = 0.0; - multimesh->data.write[i + 7] = 0.0; + dataptr[i + 0] = 1.0; + dataptr[i + 1] = 0.0; + dataptr[i + 2] = 0.0; + dataptr[i + 3] = 0.0; + dataptr[i + 4] = 0.0; + dataptr[i + 5] = 1.0; + dataptr[i + 6] = 0.0; + dataptr[i + 7] = 0.0; color_from = 8; custom_data_from = 8; } else { - multimesh->data.write[i + 0] = 1.0; - multimesh->data.write[i + 1] = 0.0; - multimesh->data.write[i + 2] = 0.0; - multimesh->data.write[i + 3] = 0.0; - multimesh->data.write[i + 4] = 0.0; - multimesh->data.write[i + 5] = 1.0; - multimesh->data.write[i + 6] = 0.0; - multimesh->data.write[i + 7] = 0.0; - multimesh->data.write[i + 8] = 0.0; - multimesh->data.write[i + 9] = 0.0; - multimesh->data.write[i + 10] = 1.0; - multimesh->data.write[i + 11] = 0.0; + dataptr[i + 0] = 1.0; + dataptr[i + 1] = 0.0; + dataptr[i + 2] = 0.0; + dataptr[i + 3] = 0.0; + dataptr[i + 4] = 0.0; + dataptr[i + 5] = 1.0; + dataptr[i + 6] = 0.0; + dataptr[i + 7] = 0.0; + dataptr[i + 8] = 0.0; + dataptr[i + 9] = 0.0; + dataptr[i + 10] = 1.0; + dataptr[i + 11] = 0.0; color_from = 12; custom_data_from = 12; } @@ -4109,14 +4111,14 @@ void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances } cu; cu.colu = 0xFFFFFFFF; - multimesh->data.write[i + color_from + 0] = cu.colf; + dataptr[i + color_from + 0] = cu.colf; custom_data_from = color_from + 1; } else if (multimesh->color_format == VS::MULTIMESH_COLOR_FLOAT) { - multimesh->data.write[i + color_from + 0] = 1.0; - multimesh->data.write[i + color_from + 1] = 1.0; - multimesh->data.write[i + color_from + 2] = 1.0; - multimesh->data.write[i + color_from + 3] = 1.0; + dataptr[i + color_from + 0] = 1.0; + dataptr[i + color_from + 1] = 1.0; + dataptr[i + color_from + 2] = 1.0; + dataptr[i + color_from + 3] = 1.0; custom_data_from = color_from + 4; } @@ -4130,13 +4132,13 @@ void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances } cu; cu.colu = 0; - multimesh->data.write[i + custom_data_from + 0] = cu.colf; + dataptr[i + custom_data_from + 0] = cu.colf; } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) { - multimesh->data.write[i + custom_data_from + 0] = 0.0; - multimesh->data.write[i + custom_data_from + 1] = 0.0; - multimesh->data.write[i + custom_data_from + 2] = 0.0; - multimesh->data.write[i + custom_data_from + 3] = 0.0; + dataptr[i + custom_data_from + 0] = 0.0; + dataptr[i + custom_data_from + 1] = 0.0; + dataptr[i + custom_data_from + 2] = 0.0; + dataptr[i + custom_data_from + 3] = 0.0; } } @@ -6841,7 +6843,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level); glDisable(GL_SCISSOR_TEST); glColorMask(1, 1, 1, 1); - if (rt->buffers.active == false) { + if (!rt->buffers.active) { glDepthMask(GL_TRUE); } diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index dbc8507951..be36b41417 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -872,6 +872,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"] = "screen_uv"; actions[VS::SHADER_SPATIAL].renames["SCREEN_TEXTURE"] = "screen_texture"; actions[VS::SHADER_SPATIAL].renames["DEPTH_TEXTURE"] = "depth_buffer"; + actions[VS::SHADER_SPATIAL].renames["DEPTH"] = "gl_FragDepth"; actions[VS::SHADER_SPATIAL].renames["ALPHA_SCISSOR"] = "alpha_scissor"; actions[VS::SHADER_SPATIAL].renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h index 9db4942163..0d360e8453 100644 --- a/drivers/gles3/shader_gles3.h +++ b/drivers/gles3/shader_gles3.h @@ -128,11 +128,13 @@ private: Vector<GLint> texture_uniform_locations; uint32_t code_version; bool ok; - Version() { - code_version = 0; - ok = false; - uniform_location = NULL; - } + Version() : + id(0), + vert_id(0), + frag_id(0), + uniform_location(NULL), + code_version(0), + ok(false) {} }; Version *version; diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 598bd3465e..8388b15edb 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -1340,7 +1340,7 @@ void reflection_process(int idx, vec3 vertex, vec3 normal, vec3 binormal, vec3 t reflection_accum += reflection; } -#ifndef USE_LIGHTMAP +#if !defined(USE_LIGHTMAP) && !defined(USE_LIGHTMAP_CAPTURE) if (reflections[idx].ambient.a > 0.0) { //compute ambient using skybox vec3 local_amb_vec = (reflections[idx].local_matrix * vec4(normal, 0.0)).xyz; @@ -1957,7 +1957,7 @@ FRAGMENT_SHADER_CODE } else { specular_light += env_reflection_light; } -#ifndef USE_LIGHTMAP +#if !defined(USE_LIGHTMAP) && !defined(USE_LIGHTMAP_CAPTURE) if (ambient_accum.a > 0.0) { ambient_light = ambient_accum.rgb / ambient_accum.a; } diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp index 48b4369b7e..929e67faa9 100644 --- a/drivers/unix/dir_access_unix.cpp +++ b/drivers/unix/dir_access_unix.cpp @@ -309,7 +309,7 @@ Error DirAccessUnix::change_dir(String p_dir) { // prev_dir is the directory we are changing out of String prev_dir; char real_current_dir_name[2048]; - getcwd(real_current_dir_name, 2048); + ERR_FAIL_COND_V(getcwd(real_current_dir_name, 2048) == NULL, ERR_BUG); if (prev_dir.parse_utf8(real_current_dir_name)) prev_dir = real_current_dir_name; //no utf8, maybe latin? @@ -330,7 +330,7 @@ Error DirAccessUnix::change_dir(String p_dir) { // the directory exists, so set current_dir to try_dir current_dir = try_dir; - chdir(prev_dir.utf8().get_data()); + ERR_FAIL_COND_V(chdir(prev_dir.utf8().get_data()) != 0, ERR_BUG); return OK; } @@ -405,7 +405,7 @@ DirAccessUnix::DirAccessUnix() { // set current directory to an absolute path of the current directory char real_current_dir_name[2048]; - getcwd(real_current_dir_name, 2048); + ERR_FAIL_COND(getcwd(real_current_dir_name, 2048) == NULL); if (current_dir.parse_utf8(real_current_dir_name)) current_dir = real_current_dir_name; diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_posix.cpp index 3f03175403..2cc2032cbb 100644 --- a/drivers/unix/net_socket_posix.cpp +++ b/drivers/unix/net_socket_posix.cpp @@ -42,12 +42,8 @@ #include <sys/types.h> #include <unistd.h> #ifndef NO_FCNTL -#ifdef __HAIKU__ #include <fcntl.h> #else -#include <sys/fcntl.h> -#endif -#else #include <sys/ioctl.h> #endif #include <netinet/in.h> diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 6c70934bc6..7ff27be501 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -487,9 +487,11 @@ String OS_Unix::get_executable_path() const { //fix for running from a symlink char buf[256]; memset(buf, 0, 256); - readlink("/proc/self/exe", buf, sizeof(buf)); + ssize_t len = readlink("/proc/self/exe", buf, sizeof(buf)); String b; - b.parse_utf8(buf); + if (len > 0) { + b.parse_utf8(buf, len); + } if (b == "") { WARN_PRINT("Couldn't get executable path from /proc/self/exe, using argv[0]"); return OS::get_executable_path(); diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp index 3d4979175b..a91e41b008 100644 --- a/drivers/wasapi/audio_driver_wasapi.cpp +++ b/drivers/wasapi/audio_driver_wasapi.cpp @@ -796,19 +796,18 @@ Error AudioDriverWASAPI::capture_start() { return err; } - if (audio_input.active == false) { - audio_input.audio_client->Start(); - audio_input.active = true; - - return OK; + if (audio_input.active) { + return FAILED; } - return FAILED; + audio_input.audio_client->Start(); + audio_input.active = true; + return OK; } Error AudioDriverWASAPI::capture_stop() { - if (audio_input.active == true) { + if (audio_input.active) { audio_input.audio_client->Stop(); audio_input.active = false; diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 79c22f667a..aeb304d3b9 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -1039,6 +1039,8 @@ void CodeTextEditor::delete_lines() { int to_line = text_editor->get_selection_to_line(); int from_line = text_editor->get_selection_from_line(); int count = Math::abs(to_line - from_line) + 1; + + text_editor->cursor_set_line(to_line, false); while (count) { text_editor->set_line(text_editor->cursor_get_line(), ""); text_editor->backspace_at_cursor(); diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index eb11aea9cc..c4516c1f17 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -558,6 +558,7 @@ void CreateDialog::_history_selected() { return; search_box->set_text(item->get_text(0).get_slicec(' ', 0)); + favorites->deselect_all(); _update_search(); } @@ -568,6 +569,7 @@ void CreateDialog::_favorite_selected() { return; search_box->set_text(item->get_text(0).get_slicec(' ', 0)); + recent->deselect_all(); _update_search(); } diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index 38bdba31ea..f425d0a995 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -501,7 +501,7 @@ void EditorFileDialog::_items_clear_selection() { case MODE_OPEN_FILE: case MODE_OPEN_FILES: get_ok()->set_text(TTR("Open")); - get_ok()->set_disabled(item_list->is_anything_selected() == false); + get_ok()->set_disabled(!item_list->is_anything_selected()); break; case MODE_OPEN_DIR: diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index ee20d95f25..d73bf86f64 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -1705,6 +1705,17 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) { emit_signal("resources_reimported", p_files); } +Error EditorFileSystem::_resource_import(const String &p_path) { + + Vector<String> files; + files.push_back(p_path); + + singleton->update_file(p_path); + singleton->reimport_files(files); + + return OK; +} + void EditorFileSystem::_bind_methods() { ClassDB::bind_method(D_METHOD("get_filesystem"), &EditorFileSystem::get_filesystem); @@ -1744,6 +1755,7 @@ void EditorFileSystem::_update_extensions() { EditorFileSystem::EditorFileSystem() { + ResourceLoader::import = _resource_import; reimport_on_missing_imported_files = GLOBAL_DEF("editor/reimport_missing_imported_files", true); singleton = this; diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h index f2f72eddbd..47077425a1 100644 --- a/editor/editor_file_system.h +++ b/editor/editor_file_system.h @@ -230,6 +230,8 @@ class EditorFileSystem : public Node { String _get_global_script_class(const String &p_type, const String &p_path, String *r_extends, String *r_icon_path) const; + static Error _resource_import(const String &p_path); + protected: void _notification(int p_what); static void _bind_methods(); diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index c6258c8493..a90f15004a 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -2139,6 +2139,13 @@ void EditorInspector::_notification(int p_what) { } if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { + + if (use_sub_inspector_bg) { + add_style_override("bg", get_stylebox("sub_inspector_bg", "Editor")); + } else if (is_inside_tree()) { + add_style_override("bg", get_stylebox("bg", "Tree")); + } + update_tree(); } } diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 790e38afca..18dd85617b 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -227,12 +227,6 @@ void EditorNode::_unhandled_input(const Ref<InputEvent> &p_event) { _editor_select_prev(); } - if (k->get_scancode() == KEY_ESCAPE) { - for (int i = 0; i < bottom_panel_items.size(); i++) { - _bottom_panel_switch(false, i); - } - } - if (old_editor != editor_plugin_screen) { get_tree()->set_input_as_handled(); } @@ -3889,7 +3883,7 @@ void EditorNode::_scene_tab_closed(int p_tab) { } void EditorNode::_scene_tab_hover(int p_tab) { - if (bool(EDITOR_GET("interface/scene_tabs/show_thumbnail_on_hover")) == false) { + if (!bool(EDITOR_GET("interface/scene_tabs/show_thumbnail_on_hover"))) { return; } int current_tab = scene_tabs->get_current_tab(); diff --git a/editor/editor_profiler.cpp b/editor/editor_profiler.cpp index b57e3826c6..d3978749c0 100644 --- a/editor/editor_profiler.cpp +++ b/editor/editor_profiler.cpp @@ -257,7 +257,7 @@ void EditorProfiler::_update_plot() { //get const Metric &m = frame_metrics[idx]; - if (m.valid == false) + if (!m.valid) continue; //skip because invalid float value = 0; diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index c5c78b2590..96d482f47e 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -477,33 +477,16 @@ EditorPropertyCheck::EditorPropertyCheck() { void EditorPropertyEnum::_option_selected(int p_which) { - String text = options->get_item_text(p_which); - Vector<String> text_split = text.split(":"); - if (text_split.size() == 1) { - emit_signal("property_changed", get_edited_property(), p_which); - return; - } - String name = text_split[1]; - emit_signal("property_changed", get_edited_property(), name.to_int()); + int val = options->get_item_metadata(p_which); + emit_signal("property_changed", get_edited_property(), val); } void EditorPropertyEnum::update_property() { int which = get_edited_object()->get(get_edited_property()); - if (which == 0) { - options->select(which); - return; - } for (int i = 0; i < options->get_item_count(); i++) { - String text = options->get_item_text(i); - Vector<String> text_split = text.split(":"); - if (text_split.size() == 1) { - options->select(which); - return; - } - String name = text_split[1]; - if (itos(which) == name) { + if (which == (int)options->get_item_metadata(i)) { options->select(i); return; } @@ -511,8 +494,15 @@ void EditorPropertyEnum::update_property() { } void EditorPropertyEnum::setup(const Vector<String> &p_options) { + + int current_val = 0; for (int i = 0; i < p_options.size(); i++) { - options->add_item(p_options[i], i); + Vector<String> text_split = p_options[i].split(":"); + if (text_split.size() != 1) + current_val = text_split[1].to_int(); + options->add_item(text_split[0]); + options->set_item_metadata(i, current_val); + current_val += 1; } } @@ -1779,7 +1769,7 @@ void EditorPropertyColor::_color_changed(const Color &p_color) { void EditorPropertyColor::_popup_closed() { - emit_signal("property_changed", get_edited_property(), picker->get_pick_color(), true); + emit_signal("property_changed", get_edited_property(), picker->get_pick_color(), false); } void EditorPropertyColor::_bind_methods() { @@ -2102,12 +2092,18 @@ void EditorPropertyResource::_menu_option(int p_which) { } } -void EditorPropertyResource::_resource_preview(const String &p_path, const Ref<Texture> &p_preview, ObjectID p_obj) { +void EditorPropertyResource::_resource_preview(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, ObjectID p_obj) { RES p = get_edited_object()->get(get_edited_property()); if (p.is_valid() && p->get_instance_id() == p_obj) { + String type = p->get_class_name(); + + if (ClassDB::is_parent_class(type, "Script")) { + assign->set_text(p->get_path().get_file()); + return; + } + if (p_preview.is_valid()) { - String type = p->get_class_name(); preview->set_margin(MARGIN_LEFT, assign->get_icon()->get_width() + assign->get_stylebox("normal")->get_default_margin(MARGIN_LEFT) + get_constant("hseparation", "Button")); if (type == "GradientTexture") { preview->set_stretch_mode(TextureRect::STRETCH_SCALE); @@ -2374,7 +2370,7 @@ void EditorPropertyResource::update_property() { if (res->get_name() != String()) { assign->set_text(res->get_name()); } else if (res->get_path().is_resource_file()) { - assign->set_text(res->get_name()); + assign->set_text(res->get_path().get_file()); assign->set_tooltip(res->get_path()); } else { assign->set_text(res->get_class()); diff --git a/editor/editor_properties.h b/editor/editor_properties.h index 18e70345aa..35d8f4d306 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -548,7 +548,7 @@ class EditorPropertyResource : public EditorProperty { void _file_selected(const String &p_path); void _menu_option(int p_which); - void _resource_preview(const String &p_path, const Ref<Texture> &p_preview, ObjectID p_obj); + void _resource_preview(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, ObjectID p_obj); void _resource_selected(); void _viewport_selected(const NodePath &p_path); diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 768a8fc066..36053d7534 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -635,7 +635,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_icon("visibility_hidden", "PopupMenu", theme->get_icon("GuiVisibilityHidden", "EditorIcons")); theme->set_icon("visibility_visible", "PopupMenu", theme->get_icon("GuiVisibilityVisible", "EditorIcons")); theme->set_icon("visibility_xray", "PopupMenu", theme->get_icon("GuiVisibilityXray", "EditorIcons")); - theme->set_constant("vseparation", "PopupMenu", (extra_spacing + default_margin_size) * EDSCALE); + theme->set_constant("vseparation", "PopupMenu", (extra_spacing + default_margin_size + 1) * EDSCALE); Ref<StyleBoxFlat> sub_inspector_bg = make_flat_stylebox(dark_color_1, 2, 0, 0, 0); sub_inspector_bg->set_border_width(MARGIN_LEFT, 2); @@ -734,10 +734,10 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("font_color", "ItemList", font_color); theme->set_color("font_color_selected", "ItemList", mono_color); theme->set_color("guide_color", "ItemList", guide_color); - theme->set_constant("vseparation", "ItemList", 2 * EDSCALE); - theme->set_constant("hseparation", "ItemList", 2 * EDSCALE); + theme->set_constant("vseparation", "ItemList", 3 * EDSCALE); + theme->set_constant("hseparation", "ItemList", 3 * EDSCALE); theme->set_constant("icon_margin", "ItemList", default_margin_size * EDSCALE); - theme->set_constant("line_separation", "ItemList", 2 * EDSCALE); + theme->set_constant("line_separation", "ItemList", 3 * EDSCALE); // Tabs & TabContainer theme->set_stylebox("tab_fg", "TabContainer", style_tab_selected); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 2c69909f23..4d386c1af6 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -1953,7 +1953,7 @@ void FileSystemDock::_get_drag_target_folder(String &target, bool &target_favori } String ltarget = files->get_item_metadata(pos); - target = ltarget.ends_with("/") ? ltarget : path; + target = ltarget.ends_with("/") ? ltarget : path.get_base_dir(); return; } diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp index 2af81b8ac7..0ccaa95fb7 100644 --- a/editor/find_in_files.cpp +++ b/editor/find_in_files.cpp @@ -31,6 +31,7 @@ #include "find_in_files.h" #include "core/os/dir_access.h" #include "core/os/os.h" +#include "editor_node.h" #include "editor_scale.h" #include "scene/gui/box_container.h" #include "scene/gui/button.h" @@ -300,7 +301,7 @@ const char *FindInFilesDialog::SIGNAL_REPLACE_REQUESTED = "replace_requested"; FindInFilesDialog::FindInFilesDialog() { - set_custom_minimum_size(Size2(400, 190)); + set_custom_minimum_size(Size2(400, 190) * EDSCALE); set_resizable(true); set_title(TTR("Find in Files")); @@ -334,13 +335,11 @@ FindInFilesDialog::FindInFilesDialog() { HBoxContainer *hbc = memnew(HBoxContainer); _whole_words_checkbox = memnew(CheckBox); - _whole_words_checkbox->set_text(TTR("Whole words")); - _whole_words_checkbox->set_pressed(true); + _whole_words_checkbox->set_text(TTR("Whole Words")); hbc->add_child(_whole_words_checkbox); _match_case_checkbox = memnew(CheckBox); - _match_case_checkbox->set_text(TTR("Match case")); - _match_case_checkbox->set_pressed(true); + _match_case_checkbox->set_text(TTR("Match Case")); hbc->add_child(_match_case_checkbox); gc->add_child(hbc); @@ -548,7 +547,7 @@ FindInFilesPanel::FindInFilesPanel() { hbc->add_child(find_label); _search_text_label = memnew(Label); - _search_text_label->add_font_override("font", get_font("source", "EditorFonts")); + _search_text_label->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("source", "EditorFonts")); hbc->add_child(_search_text_label); _progress_bar = memnew(ProgressBar); @@ -562,14 +561,14 @@ FindInFilesPanel::FindInFilesPanel() { _cancel_button = memnew(Button); _cancel_button->set_text(TTR("Cancel")); _cancel_button->connect("pressed", this, "_on_cancel_button_clicked"); - _cancel_button->set_disabled(true); + _cancel_button->hide(); hbc->add_child(_cancel_button); vbc->add_child(hbc); } _results_display = memnew(Tree); - _results_display->add_font_override("font", get_font("source", "EditorFonts")); + _results_display->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("source", "EditorFonts")); _results_display->set_v_size_flags(SIZE_EXPAND_FILL); _results_display->connect("item_selected", this, "_on_result_selected"); _results_display->connect("item_edited", this, "_on_item_edited"); @@ -641,7 +640,7 @@ void FindInFilesPanel::start_search() { _finder->start(); update_replace_buttons(); - _cancel_button->set_disabled(false); + _cancel_button->show(); } void FindInFilesPanel::stop_search() { @@ -651,7 +650,7 @@ void FindInFilesPanel::stop_search() { _status_label->set_text(""); update_replace_buttons(); set_progress_visible(false); - _cancel_button->set_disabled(true); + _cancel_button->hide(); } void FindInFilesPanel::_notification(int p_what) { @@ -687,7 +686,7 @@ void FindInFilesPanel::_on_result_found(String fpath, int line_number, int begin // Do this first because it resets properties of the cell... item->set_cell_mode(text_index, TreeItem::CELL_MODE_CUSTOM); - String item_text = String::num_int64(line_number) + ": " + text.replace("\t", " "); + String item_text = vformat("%3s: %s", line_number, text.replace("\t", " ")); item->set_text(text_index, item_text); item->set_custom_draw(text_index, this, "_draw_result_text"); @@ -702,7 +701,7 @@ void FindInFilesPanel::_on_result_found(String fpath, int line_number, int begin r.begin = begin; r.end = end; r.draw_begin = (item_text_width - raw_text_width) + font->get_string_size(text.left(r.begin)).x; - r.draw_width = font->get_string_size(text.substr(r.begin, r.end - r.begin + 1)).x; + r.draw_width = font->get_string_size(text.substr(r.begin, r.end - r.begin)).x; _result_items[item] = r; if (_with_replace) { @@ -753,7 +752,7 @@ void FindInFilesPanel::_on_finished() { _status_label->set_text(TTR("Search complete")); update_replace_buttons(); set_progress_visible(false); - _cancel_button->set_disabled(true); + _cancel_button->hide(); } void FindInFilesPanel::_on_cancel_button_clicked() { diff --git a/editor/icons/icon_noise_texture.svg b/editor/icons/icon_noise_texture.svg new file mode 100644 index 0000000000..5908c2b2d4 --- /dev/null +++ b/editor/icons/icon_noise_texture.svg @@ -0,0 +1,3 @@ +<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<path d="m2 1c-0.55228 0-1 0.44772-1 1v12c0 0.55228 0.44772 1 1 1h12c0.55228 0 1-0.44772 1-1v-12c0-0.55228-0.44772-1-1-1zm1 2h10v8h-10zm3 1v2h2v-2zm2 2v2h2v2h2v-6h-2v2zm0 2h-2v-2h-2v4h4z" fill="#e0e0e0" fill-opacity=".99608"/> +</svg> diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index 60ca66e464..e8bb772a64 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -321,7 +321,7 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) { } else { //mesh since nothing else node = memnew(MeshInstance); - Object::cast_to<MeshInstance>(node)->set_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT, true); + //Object::cast_to<MeshInstance>(node)->set_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT, true); } } break; case Collada::Node::TYPE_SKELETON: { diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp index a6b754de3b..cb15be35f2 100644 --- a/editor/import/editor_scene_importer_gltf.cpp +++ b/editor/import/editor_scene_importer_gltf.cpp @@ -1793,22 +1793,22 @@ template <> struct EditorSceneImporterGLTFInterpolate<Quat> { Quat lerp(const Quat &a, const Quat &b, float c) const { - ERR_FAIL_COND_V(a.is_normalized() == false, Quat()); - ERR_FAIL_COND_V(b.is_normalized() == false, Quat()); + ERR_FAIL_COND_V(!a.is_normalized(), Quat()); + ERR_FAIL_COND_V(!b.is_normalized(), Quat()); return a.slerp(b, c).normalized(); } Quat catmull_rom(const Quat &p0, const Quat &p1, const Quat &p2, const Quat &p3, float c) { - ERR_FAIL_COND_V(p1.is_normalized() == false, Quat()); - ERR_FAIL_COND_V(p2.is_normalized() == false, Quat()); + ERR_FAIL_COND_V(!p1.is_normalized(), Quat()); + ERR_FAIL_COND_V(!p2.is_normalized(), Quat()); return p1.slerp(p2, c).normalized(); } Quat bezier(Quat start, Quat control_1, Quat control_2, Quat end, float t) { - ERR_FAIL_COND_V(start.is_normalized() == false, Quat()); - ERR_FAIL_COND_V(end.is_normalized() == false, Quat()); + ERR_FAIL_COND_V(!start.is_normalized(), Quat()); + ERR_FAIL_COND_V(!end.is_normalized(), Quat()); return start.slerp(end, t).normalized(); } diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 6d72cb4909..c5a5980fc1 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -365,29 +365,37 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Array return p_node; MeshInstance *mi = Object::cast_to<MeshInstance>(p_node); if (mi) { - Node *col; + Node *col = NULL; if (_teststr(name, "colonly")) { col = mi->create_trimesh_collision_node(); - ERR_FAIL_COND_V(!col, NULL); + if (col == NULL) { + ERR_PRINTS("Error generating collision for mesh: " + name); + } else { - col->set_name(_fixstr(name, "colonly")); + col->set_name(_fixstr(name, "colonly")); + } } else { col = mi->create_convex_collision_node(); - ERR_FAIL_COND_V(!col, NULL); + if (col == NULL) { + ERR_PRINTS("Error generating collision for mesh: " + name); + } else { - col->set_name(_fixstr(name, "convcolonly")); + col->set_name(_fixstr(name, "convcolonly")); + } } - Object::cast_to<Spatial>(col)->set_transform(mi->get_transform()); - p_node->replace_by(col); - memdelete(p_node); - p_node = col; + if (col) { + Object::cast_to<Spatial>(col)->set_transform(mi->get_transform()); + p_node->replace_by(col); + memdelete(p_node); + p_node = col; - StaticBody *sb = Object::cast_to<StaticBody>(col); - CollisionShape *colshape = Object::cast_to<CollisionShape>(sb->get_child(0)); - colshape->set_name("shape"); - colshape->set_owner(p_node->get_owner()); + StaticBody *sb = Object::cast_to<StaticBody>(col); + CollisionShape *colshape = Object::cast_to<CollisionShape>(sb->get_child(0)); + colshape->set_name("shape"); + colshape->set_owner(p_node->get_owner()); + } } else if (p_node->has_meta("empty_draw_type")) { String empty_draw_type = String(p_node->get_meta("empty_draw_type")); StaticBody *sb = memnew(StaticBody); diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index b046e2e975..b81a52ab70 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -116,7 +116,7 @@ class ResourceImporterScene : public ResourceImporter { enum LightBakeMode { LIGHT_BAKE_DISABLED, LIGHT_BAKE_ENABLE, - //LIGHT_BAKE_LIGHTMAPS + LIGHT_BAKE_LIGHTMAPS }; void _replace_owner(Node *p_node, Node *p_scene, Node *p_new_owner); diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index 4f4980d83c..750fca2852 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -328,6 +328,21 @@ Container *InspectorDock::get_addon_area() { return this; } +void InspectorDock::_notification(int p_what) { + switch (p_what) { + case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { + set_theme(editor->get_gui_base()->get_theme()); + resource_new_button->set_icon(get_icon("New", "EditorIcons")); + resource_load_button->set_icon(get_icon("Load", "EditorIcons")); + backward_button->set_icon(get_icon("Back", "EditorIcons")); + forward_button->set_icon(get_icon("Forward", "EditorIcons")); + history_menu->set_icon(get_icon("History", "EditorIcons")); + object_menu->set_icon(get_icon("Tools", "EditorIcons")); + warning->set_icon(get_icon("NodeWarning", "EditorIcons")); + } break; + } +} + void InspectorDock::_bind_methods() { ClassDB::bind_method("_menu_option", &InspectorDock::_menu_option); diff --git a/editor/inspector_dock.h b/editor/inspector_dock.h index 97ef6899dc..57d2a03295 100644 --- a/editor/inspector_dock.h +++ b/editor/inspector_dock.h @@ -118,6 +118,7 @@ class InspectorDock : public VBoxContainer { protected: static void _bind_methods(); + void _notification(int p_what); public: void go_back(); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index e8f00ce0ba..a9bc5e77ac 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -5113,7 +5113,7 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian type == "AtlasTexture" || type == "LargeTexture") { Ref<Texture> texture = Ref<Texture>(Object::cast_to<Texture>(*res)); - if (texture.is_valid() == false) { + if (!texture.is_valid()) { continue; } } else { diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp index dd327d0a2c..bd4a35c9d8 100644 --- a/editor/plugins/resource_preloader_editor_plugin.cpp +++ b/editor/plugins/resource_preloader_editor_plugin.cpp @@ -44,7 +44,6 @@ void ResourcePreloaderEditor::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { load->set_icon(get_icon("Folder", "EditorIcons")); - _delete->set_icon(get_icon("Remove", "EditorIcons")); } if (p_what == NOTIFICATION_READY) { @@ -138,15 +137,11 @@ void ResourcePreloaderEditor::_item_edited() { } } -void ResourcePreloaderEditor::_delete_confirm_pressed() { +void ResourcePreloaderEditor::_remove_resource(const String &p_to_remove) { - if (!tree->get_selected()) - return; - - String to_remove = tree->get_selected()->get_text(0); undo_redo->create_action(TTR("Delete Resource")); - undo_redo->add_do_method(preloader, "remove_resource", to_remove); - undo_redo->add_undo_method(preloader, "add_resource", to_remove, preloader->get_resource(to_remove)); + undo_redo->add_do_method(preloader, "remove_resource", p_to_remove); + undo_redo->add_undo_method(preloader, "add_resource", p_to_remove, preloader->get_resource(p_to_remove)); undo_redo->add_do_method(this, "_update_library"); undo_redo->add_undo_method(this, "_update_library"); undo_redo->commit_action(); @@ -184,21 +179,6 @@ void ResourcePreloaderEditor::_paste_pressed() { undo_redo->commit_action(); } -void ResourcePreloaderEditor::_delete_pressed() { - - if (!tree->get_selected()) - return; - - _delete_confirm_pressed(); //it has undo.. why bother with a dialog.. - /* - dialog->set_title("Confirm..."); - dialog->set_text("Remove Resource '"+tree->get_selected()->get_text(0)+"' ?"); - //dialog->get_cancel()->set_text("Cancel"); - //dialog->get_ok()->show(); - dialog->get_ok()->set_text("Remove"); - dialog->popup_centered(Size2(300,60));*/ -} - void ResourcePreloaderEditor::_update_library() { tree->clear(); @@ -228,17 +208,20 @@ void ResourcePreloaderEditor::_update_library() { ERR_CONTINUE(r.is_null()); - ti->set_tooltip(0, r->get_path()); + String type = r->get_class(); + ti->set_icon(0, EditorNode::get_singleton()->get_class_icon(type, "Object")); + ti->set_tooltip(0, TTR("Instance:") + " " + r->get_path() + "\n" + TTR("Type:") + " " + type); + ti->set_text(1, r->get_path()); - ti->add_button(1, get_icon("InstanceOptions", "EditorIcons"), BUTTON_SUBSCENE, false, TTR("Open in Editor")); - ti->set_tooltip(1, TTR("Instance:") + " " + r->get_path() + "\n" + TTR("Type:") + " " + r->get_class()); ti->set_editable(1, false); ti->set_selectable(1, false); - String type = r->get_class(); - ti->set_text(2, type); - ti->set_selectable(2, false); - ti->set_icon(2, EditorNode::get_singleton()->get_class_icon(type, "")); + if (type == "PackedScene") { + ti->add_button(1, get_icon("InstanceOptions", "EditorIcons"), BUTTON_OPEN_SCENE, false, TTR("Open in Editor")); + } else { + ti->add_button(1, get_icon("Load", "EditorIcons"), BUTTON_EDIT_RESOURCE, false, TTR("Open in Editor")); + } + ti->add_button(1, get_icon("Remove", "EditorIcons"), BUTTON_REMOVE, false, TTR("Remove")); } //player->add_resource("default",resource); @@ -249,10 +232,16 @@ void ResourcePreloaderEditor::_cell_button_pressed(Object *p_item, int p_column, TreeItem *item = Object::cast_to<TreeItem>(p_item); ERR_FAIL_COND(!item); - String rpath = item->get_text(p_column); - - if (p_id == BUTTON_SUBSCENE) { + if (p_id == BUTTON_OPEN_SCENE) { + String rpath = item->get_text(p_column); EditorInterface::get_singleton()->open_scene_from_path(rpath); + + } else if (p_id == BUTTON_EDIT_RESOURCE) { + RES r = preloader->get_resource(item->get_text(0)); + EditorInterface::get_singleton()->edit_resource(r); + + } else if (p_id == BUTTON_REMOVE) { + _remove_resource(item->get_text(0)); } } @@ -365,12 +354,11 @@ void ResourcePreloaderEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_gui_input"), &ResourcePreloaderEditor::_gui_input); ClassDB::bind_method(D_METHOD("_load_pressed"), &ResourcePreloaderEditor::_load_pressed); ClassDB::bind_method(D_METHOD("_item_edited"), &ResourcePreloaderEditor::_item_edited); - ClassDB::bind_method(D_METHOD("_delete_pressed"), &ResourcePreloaderEditor::_delete_pressed); ClassDB::bind_method(D_METHOD("_paste_pressed"), &ResourcePreloaderEditor::_paste_pressed); - ClassDB::bind_method(D_METHOD("_delete_confirm_pressed"), &ResourcePreloaderEditor::_delete_confirm_pressed); ClassDB::bind_method(D_METHOD("_files_load_request"), &ResourcePreloaderEditor::_files_load_request); ClassDB::bind_method(D_METHOD("_update_library"), &ResourcePreloaderEditor::_update_library); ClassDB::bind_method(D_METHOD("_cell_button_pressed"), &ResourcePreloaderEditor::_cell_button_pressed); + ClassDB::bind_method(D_METHOD("_remove_resource", "to_remove"), &ResourcePreloaderEditor::_remove_resource); ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &ResourcePreloaderEditor::get_drag_data_fw); ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &ResourcePreloaderEditor::can_drop_data_fw); @@ -391,9 +379,6 @@ ResourcePreloaderEditor::ResourcePreloaderEditor() { load->set_tooltip(TTR("Load Resource")); hbc->add_child(load); - _delete = memnew(Button); - hbc->add_child(_delete); - paste = memnew(Button); paste->set_text(TTR("Paste")); hbc->add_child(paste); @@ -403,13 +388,11 @@ ResourcePreloaderEditor::ResourcePreloaderEditor() { tree = memnew(Tree); tree->connect("button_pressed", this, "_cell_button_pressed"); - tree->set_columns(3); - tree->set_column_min_width(0, 3); - tree->set_column_min_width(1, 1); - tree->set_column_min_width(2, 1); + tree->set_columns(2); + tree->set_column_min_width(0, 2); + tree->set_column_min_width(1, 3); tree->set_column_expand(0, true); tree->set_column_expand(1, true); - tree->set_column_expand(2, true); tree->set_v_size_flags(SIZE_EXPAND_FILL); tree->set_drag_forwarding(this); @@ -419,10 +402,8 @@ ResourcePreloaderEditor::ResourcePreloaderEditor() { add_child(dialog); load->connect("pressed", this, "_load_pressed"); - _delete->connect("pressed", this, "_delete_pressed"); paste->connect("pressed", this, "_paste_pressed"); file->connect("files_selected", this, "_files_load_request"); - //dialog->connect("confirmed", this,"_delete_confirm_pressed"); tree->connect("item_edited", this, "_item_edited"); loading_scene = false; } diff --git a/editor/plugins/resource_preloader_editor_plugin.h b/editor/plugins/resource_preloader_editor_plugin.h index e737157785..0a8238ce18 100644 --- a/editor/plugins/resource_preloader_editor_plugin.h +++ b/editor/plugins/resource_preloader_editor_plugin.h @@ -43,11 +43,12 @@ class ResourcePreloaderEditor : public PanelContainer { GDCLASS(ResourcePreloaderEditor, PanelContainer); enum { - BUTTON_SUBSCENE = 0, + BUTTON_OPEN_SCENE, + BUTTON_EDIT_RESOURCE, + BUTTON_REMOVE }; Button *load; - Button *_delete; Button *paste; Tree *tree; bool loading_scene; @@ -62,8 +63,7 @@ class ResourcePreloaderEditor : public PanelContainer { void _load_scene_pressed(); void _files_load_request(const Vector<String> &p_paths); void _paste_pressed(); - void _delete_pressed(); - void _delete_confirm_pressed(); + void _remove_resource(const String &p_to_remove); void _update_library(); void _cell_button_pressed(Object *p_item, int p_column, int p_id); void _item_edited(); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 7cda15bdc6..7e11c4a253 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -1960,7 +1960,7 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra // doesn't have it, make a new one - ScriptEditorBase *se; + ScriptEditorBase *se = NULL; for (int i = script_editor_func_count - 1; i >= 0; i--) { se = script_editor_funcs[i](p_resource); @@ -3173,9 +3173,9 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { find_in_files_dialog->connect(FindInFilesDialog::SIGNAL_REPLACE_REQUESTED, this, "_start_find_in_files", varray(true)); add_child(find_in_files_dialog); find_in_files = memnew(FindInFilesPanel); - find_in_files_button = editor->add_bottom_panel_item(TTR("Search results"), find_in_files); + find_in_files_button = editor->add_bottom_panel_item(TTR("Search Results"), find_in_files); find_in_files_button->set_tooltip(TTR("Search in files")); - find_in_files->set_custom_minimum_size(Size2(0, 200)); + find_in_files->set_custom_minimum_size(Size2(0, 200) * EDSCALE); find_in_files->connect(FindInFilesPanel::SIGNAL_RESULT_SELECTED, this, "_on_find_in_files_result_selected"); find_in_files->connect(FindInFilesPanel::SIGNAL_FILES_MODIFIED, this, "_on_find_in_files_modified_files"); find_in_files->hide(); diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 114610c562..f57614b3b3 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -534,9 +534,9 @@ void SpatialEditorViewport::_update_name() { String view_mode = orthogonal ? TTR("Orthogonal") : TTR("Perspective"); if (name != "") - view_menu->set_text("[ " + name + " " + view_mode + " ]"); + view_menu->set_text(name + " " + view_mode); else - view_menu->set_text("[ " + view_mode + " ]"); + view_menu->set_text(view_mode); view_menu->set_size(Vector2(0, 0)); // resets the button size } @@ -2124,7 +2124,7 @@ void SpatialEditorViewport::_notification(int p_what) { _update_freelook(delta); Node *scene_root = editor->get_scene_tree_dock()->get_editor_data()->get_edited_scene_root(); - if (previewing_cinema == true && scene_root != NULL) { + if (previewing_cinema && scene_root != NULL) { Camera *cam = scene_root->get_viewport()->get_camera(); if (cam != NULL && cam != previewing) { //then switch the viewport's camera to the scene's viewport camera @@ -2260,6 +2260,12 @@ void SpatialEditorViewport::_notification(int p_what) { surface->connect("mouse_exited", this, "_surface_mouse_exit"); surface->connect("focus_entered", this, "_surface_focus_enter"); surface->connect("focus_exited", this, "_surface_focus_exit"); + view_menu->set_flat(false); + view_menu->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); + view_menu->add_style_override("hover", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); + view_menu->add_style_override("pressed", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); + view_menu->add_style_override("focus", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); + view_menu->add_style_override("disabled", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); info_label->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); fps_label->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); cinema_label->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); @@ -3421,7 +3427,6 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed view_menu = memnew(MenuButton); surface->add_child(view_menu); view_menu->set_position(Point2(4, 4) * EDSCALE); - view_menu->set_self_modulate(Color(1, 1, 1, 0.5)); view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/top_view"), VIEW_TOP); view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/bottom_view"), VIEW_BOTTOM); view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/left_view"), VIEW_LEFT); diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index 3de2284cea..9988d82fb8 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -569,6 +569,10 @@ void TileSetEditor::_on_textures_added(const PoolStringArray &p_paths) { int invalid_count = 0; for (int i = 0; i < p_paths.size(); i++) { Ref<Texture> t = Ref<Texture>(ResourceLoader::load(p_paths[i])); + + ERR_EXPLAIN("'" + p_paths[i] + "' is not a valid texture."); + ERR_CONTINUE(!t.is_valid()); + if (texture_map.has(t->get_rid())) { invalid_count++; } else { @@ -577,9 +581,13 @@ void TileSetEditor::_on_textures_added(const PoolStringArray &p_paths) { texture_list->set_item_metadata(texture_list->get_item_count() - 1, t->get_rid()); } } - update_texture_list_icon(); - texture_list->select(texture_list->get_item_count() - 1); - _on_texture_list_selected(texture_list->get_item_count() - 1); + + if (texture_list->get_item_count() > 0) { + update_texture_list_icon(); + texture_list->select(texture_list->get_item_count() - 1); + _on_texture_list_selected(texture_list->get_item_count() - 1); + } + if (invalid_count > 0) { err_dialog->set_text(vformat(TTR("%s file(s) were not added because was already on the list."), String::num(invalid_count, 0))); err_dialog->popup_centered(Size2(300, 60)); diff --git a/editor/project_export.cpp b/editor/project_export.cpp index fa6dce1771..3ec49e187f 100644 --- a/editor/project_export.cpp +++ b/editor/project_export.cpp @@ -638,10 +638,10 @@ bool ProjectExportDialog::_fill_tree(EditorFileSystemDirectory *p_dir, TreeItem for (int i = 0; i < p_dir->get_subdir_count(); i++) { TreeItem *subdir = include_files->create_item(p_item); - if (_fill_tree(p_dir->get_subdir(i), subdir, current, p_only_scenes) == false) { - memdelete(subdir); - } else { + if (_fill_tree(p_dir->get_subdir(i), subdir, current, p_only_scenes)) { used = true; + } else { + memdelete(subdir); } } diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index c611327a31..9ef6e4332c 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -132,7 +132,7 @@ void CustomPropertyEditor::_menu_option(int p_which) { emit_signal("variant_changed"); } else if (hint == PROPERTY_HINT_ENUM) { - v = p_which; + v = menu->get_item_metadata(p_which); emit_signal("variant_changed"); } } break; @@ -427,12 +427,14 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: } else if (hint == PROPERTY_HINT_ENUM) { Vector<String> options = hint_text.split(","); + int current_val = 0; for (int i = 0; i < options.size(); i++) { - if (options[i].find(":") != -1) { - menu->add_item(options[i].get_slicec(':', 0), options[i].get_slicec(':', 1).to_int()); - } else { - menu->add_item(options[i], i); - } + Vector<String> text_split = options[i].split(":"); + if (text_split.size() != 1) + current_val = text_split[1].to_int(); + menu->add_item(text_split[0]); + menu->set_item_metadata(i, current_val); + current_val += 1; } menu->set_position(get_position()); menu->popup(); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 08f1ece2d4..a6a014f3bd 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -797,7 +797,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { case TOOL_CREATE_USER_INTERFACE: case TOOL_CREATE_FAVORITE: { - Node *new_node; + Node *new_node = NULL; if (TOOL_CREATE_FAVORITE == p_tool) { String name = selected_favorite_root.get_slicec(' ', 0); diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index 07670bb420..848e4def6d 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -73,7 +73,7 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i undo_redo->create_action(TTR("Toggle Visible")); _toggle_visible(n); List<Node *> selection = editor_selection->get_selected_node_list(); - if (selection.size() > 1) { + if (selection.size() > 1 && selection.find(n) != NULL) { for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { Node *nv = E->get(); ERR_FAIL_COND(!nv); diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index eb72d0aa6e..6fbac0d4b5 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -493,23 +493,29 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da pinfo.usage = PropertyUsageFlags(int(prop[4])); Variant var = prop[5]; + if (pinfo.type == Variant::OBJECT) { + if (var.is_zero()) { + var = RES(); + } else if (var.get_type() == Variant::STRING) { + var = ResourceLoader::load(var); + + if (pinfo.hint_string == "Script") + debugObj->set_script(var); + } else if (var.get_type() == Variant::OBJECT) { + if (((Object *)var)->is_class("EncodedObjectAsID")) { + var = Object::cast_to<EncodedObjectAsID>(var)->get_object_id(); + pinfo.type = var.get_type(); + pinfo.hint = PROPERTY_HINT_OBJECT_ID; + pinfo.hint_string = "Object"; + } + } + } + if (is_new_object) { //don't update.. it's the same, instead refresh debugObj->prop_list.push_back(pinfo); } - if (var.get_type() == Variant::STRING) { - String str = var; - var = str.substr(4, str.length()); - - if (str.begins_with("PATH")) { - if (String(var).empty()) - var = RES(); - else - var = ResourceLoader::load(var); - } - } - debugObj->prop_values[pinfo.name] = var; } diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp index 96bca86f83..a321cb16c5 100644 --- a/editor/spatial_editor_gizmos.cpp +++ b/editor/spatial_editor_gizmos.cpp @@ -4201,21 +4201,16 @@ void JointSpatialGizmoPlugin::CreateGeneric6DOFJointGizmo( float cs = 0.25; for (int ax = 0; ax < 3; ax++) { - /*r_points.push_back(p_offset.translated(Vector3(+cs,0,0)).origin); - r_points.push_back(p_offset.translated(Vector3(-cs,0,0)).origin); - r_points.push_back(p_offset.translated(Vector3(0,+cs,0)).origin); - r_points.push_back(p_offset.translated(Vector3(0,-cs,0)).origin); - r_points.push_back(p_offset.translated(Vector3(0,0,+cs*2)).origin); - r_points.push_back(p_offset.translated(Vector3(0,0,-cs*2)).origin); */ - - float ll; - float ul; - float lll; - float lul; - - int a1, a2, a3; - bool enable_ang; - bool enable_lin; + float ll = 0; + float ul = 0; + float lll = 0; + float lul = 0; + + int a1 = 0; + int a2 = 0; + int a3 = 0; + bool enable_ang = false; + bool enable_lin = false; switch (ax) { case 0: diff --git a/main/tests/test_oa_hash_map.cpp b/main/tests/test_oa_hash_map.cpp index 26e728d3aa..deaba285cf 100644 --- a/main/tests/test_oa_hash_map.cpp +++ b/main/tests/test_oa_hash_map.cpp @@ -92,6 +92,35 @@ MainLoop *test() { } } + // stress test / test for issue #22928 + { + OAHashMap<int, int> map; + int dummy; + const int N = 1000; + uint32_t *keys = new uint32_t[N]; + + Math::seed(0); + + // insert a couple of random keys (with a dummy value, which is ignored) + for (int i = 0; i < N; i++) { + keys[i] = Math::rand(); + map.set(keys[i], dummy); + + if (!map.lookup(keys[i], dummy)) + OS::get_singleton()->print("could not find 0x%X despite it was just inserted!\n", unsigned(keys[i])); + } + + // check whether the keys are still present + for (int i = 0; i < N; i++) { + if (!map.lookup(keys[i], dummy)) { + OS::get_singleton()->print("could not find 0x%X despite it has been inserted previously! (not checking the other keys, breaking...)\n", unsigned(keys[i])); + break; + } + } + + delete[] keys; + } + return NULL; } } // namespace TestOAHashMap diff --git a/main/tests/test_string.cpp b/main/tests/test_string.cpp index 74157d63c9..7e19c7bf3e 100644 --- a/main/tests/test_string.cpp +++ b/main/tests/test_string.cpp @@ -480,7 +480,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish % frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; //////// INTS @@ -491,7 +491,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 5 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Int left padded with zeroes. format = "fish %05d frog"; @@ -500,7 +500,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 00005 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Int left padded with spaces. format = "fish %5d frog"; @@ -509,7 +509,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 5 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Int right padded with spaces. format = "fish %-5d frog"; @@ -518,7 +518,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 5 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Int with sign (positive). format = "fish %+d frog"; @@ -527,7 +527,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish +5 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Negative int. format = "fish %d frog"; @@ -536,7 +536,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish -5 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Hex (lower) format = "fish %x frog"; @@ -545,7 +545,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 2d frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Hex (upper) format = "fish %X frog"; @@ -554,7 +554,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 2D frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Octal format = "fish %o frog"; @@ -563,7 +563,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 143 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ////// REALS @@ -574,7 +574,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 99.990000 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Real left-padded format = "fish %11f frog"; @@ -583,7 +583,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 99.990000 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Real right-padded format = "fish %-11f frog"; @@ -592,7 +592,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 99.990000 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Real given int. format = "fish %f frog"; @@ -601,7 +601,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 99.000000 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Real with sign (positive). format = "fish %+f frog"; @@ -610,7 +610,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish +99.990000 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Real with 1 decimals. format = "fish %.1f frog"; @@ -619,7 +619,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 100.0 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Real with 12 decimals. format = "fish %.12f frog"; @@ -628,7 +628,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 99.990000000000 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Real with no decimals. format = "fish %.f frog"; @@ -637,7 +637,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 100 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; /////// Strings. @@ -648,7 +648,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish cheese frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // String left-padded format = "fish %10s frog"; @@ -657,7 +657,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish cheese frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // String right-padded format = "fish %-10s frog"; @@ -666,7 +666,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish cheese frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ///// Characters @@ -677,7 +677,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish A frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Character as int. format = "fish %c frog"; @@ -686,7 +686,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish A frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ///// Dynamic width @@ -698,7 +698,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish cheese frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Int dynamic width format = "fish %*d frog"; @@ -708,7 +708,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 99 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Float dynamic width format = "fish %*.*f frog"; @@ -719,7 +719,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 99.990 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ///// Errors @@ -730,7 +730,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "not enough arguments for format string" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // More arguments than formats. format = "fish %s frog"; @@ -740,7 +740,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "not all arguments converted during string formatting" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Incomplete format. format = "fish %10"; @@ -749,7 +749,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "incomplete format" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Bad character in format string format = "fish %&f frog"; @@ -758,7 +758,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "unsupported format character" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Too many decimals. format = "fish %2.2.2f frog"; @@ -767,7 +767,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "too many decimal points in format" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // * not a number format = "fish %*f frog"; @@ -777,7 +777,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "* wants number" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Character too long. format = "fish %c frog"; @@ -786,7 +786,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "%c requires number or single-character string" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Character bad type. format = "fish %c frog"; @@ -795,7 +795,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "%c requires number or single-character string" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; return state; } @@ -819,37 +819,127 @@ bool test_29() { String ip4 = "192.168.0.1"; bool success = ip4.is_valid_ip_address(); OS::get_singleton()->print("Is valid ipv4: %ls, %s\n", ip4.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ip4 = "192.368.0.1"; success = (!ip4.is_valid_ip_address()); OS::get_singleton()->print("Is invalid ipv4: %ls, %s\n", ip4.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; String ip6 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; success = ip6.is_valid_ip_address(); OS::get_singleton()->print("Is valid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ip6 = "2001:0db8:85j3:0000:0000:8a2e:0370:7334"; success = (!ip6.is_valid_ip_address()); OS::get_singleton()->print("Is invalid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ip6 = "2001:0db8:85f345:0000:0000:8a2e:0370:7334"; success = (!ip6.is_valid_ip_address()); OS::get_singleton()->print("Is invalid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ip6 = "2001:0db8::0:8a2e:370:7334"; success = (ip6.is_valid_ip_address()); OS::get_singleton()->print("Is valid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ip6 = "::ffff:192.168.0.1"; success = (ip6.is_valid_ip_address()); OS::get_singleton()->print("Is valid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; + + return state; +}; + +bool test_30() { + bool state = true; + bool success = true; + String input = "bytes2var"; + String output = "Bytes 2 Var"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "linear2db"; + output = "Linear 2 Db"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "vector3"; + output = "Vector 3"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "sha256"; + output = "Sha 256"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "2db"; + output = "2 Db"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "PascalCase"; + output = "Pascal Case"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "PascalPascalCase"; + output = "Pascal Pascal Case"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "snake_case"; + output = "Snake Case"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "snake_snake_case"; + output = "Snake Snake Case"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "sha256sum"; + output = "Sha 256 Sum"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "cat2dog"; + output = "Cat 2 Dog"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "function(name)"; + output = "Function(name)"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls (existing incorrect behavior): %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "snake_case_function(snake_case_arg)"; + output = "Snake Case Function(snake Case Arg)"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls (existing incorrect behavior): %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "snake_case_function( snake_case_arg )"; + output = "Snake Case Function( Snake Case Arg )"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); return state; }; @@ -887,6 +977,7 @@ TestFunc test_funcs[] = { test_27, test_28, test_29, + test_30, 0 }; diff --git a/modules/bullet/area_bullet.cpp b/modules/bullet/area_bullet.cpp index a3ba3aa0bf..a0486443c2 100644 --- a/modules/bullet/area_bullet.cpp +++ b/modules/bullet/area_bullet.cpp @@ -58,7 +58,7 @@ AreaBullet::AreaBullet() : isScratched(false) { btGhost = bulletnew(btGhostObject); - btGhost->setCollisionShape(BulletPhysicsServer::get_empty_shape()); + reload_shapes(); setupBulletCollisionObject(btGhost); /// Collision objects with a callback still have collision response with dynamic rigid bodies. /// In order to use collision objects as trigger, you have to disable the collision response. @@ -166,11 +166,9 @@ bool AreaBullet::is_monitoring() const { return get_godot_object_flags() & GOF_IS_MONITORING_AREA; } -void AreaBullet::main_shape_resetted() { - if (get_main_shape()) - btGhost->setCollisionShape(get_main_shape()); - else - btGhost->setCollisionShape(BulletPhysicsServer::get_empty_shape()); +void AreaBullet::main_shape_changed() { + CRASH_COND(!get_main_shape()) + btGhost->setCollisionShape(get_main_shape()); } void AreaBullet::reload_body() { diff --git a/modules/bullet/area_bullet.h b/modules/bullet/area_bullet.h index a6bf73906c..1c5962cfe3 100644 --- a/modules/bullet/area_bullet.h +++ b/modules/bullet/area_bullet.h @@ -142,7 +142,7 @@ public: _FORCE_INLINE_ void set_spOv_priority(int p_priority) { spOv_priority = p_priority; } _FORCE_INLINE_ int get_spOv_priority() { return spOv_priority; } - virtual void main_shape_resetted(); + virtual void main_shape_changed(); virtual void reload_body(); virtual void set_space(SpaceBullet *p_space); @@ -157,6 +157,7 @@ public: virtual void on_collision_filters_change(); virtual void on_collision_checker_start() {} + virtual void on_collision_checker_end() { isTransformChanged = false; } void add_overlap(CollisionObjectBullet *p_otherObject); void put_overlap_as_exit(int p_index); diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp index 53a38967c3..315afe3d72 100644 --- a/modules/bullet/bullet_physics_server.cpp +++ b/modules/bullet/bullet_physics_server.cpp @@ -74,12 +74,6 @@ body->get_space()->add_constraint(joint, joint->is_disabled_collisions_between_bodies()); // <--------------- Joint creation asserts -btEmptyShape *BulletPhysicsServer::emptyShape(ShapeBullet::create_shape_empty()); - -btEmptyShape *BulletPhysicsServer::get_empty_shape() { - return emptyShape; -} - void BulletPhysicsServer::_bind_methods() { //ClassDB::bind_method(D_METHOD("DoTest"), &BulletPhysicsServer::DoTest); } @@ -89,9 +83,7 @@ BulletPhysicsServer::BulletPhysicsServer() : active(true), active_spaces_count(0) {} -BulletPhysicsServer::~BulletPhysicsServer() { - bulletdelete(emptyShape); -} +BulletPhysicsServer::~BulletPhysicsServer() {} RID BulletPhysicsServer::shape_create(ShapeType p_shape) { ShapeBullet *shape = NULL; @@ -338,7 +330,7 @@ Transform BulletPhysicsServer::area_get_shape_transform(RID p_area, int p_shape_ void BulletPhysicsServer::area_remove_shape(RID p_area, int p_shape_idx) { AreaBullet *area = area_owner.get(p_area); ERR_FAIL_COND(!area); - return area->remove_shape(p_shape_idx); + return area->remove_shape_full(p_shape_idx); } void BulletPhysicsServer::area_clear_shapes(RID p_area) { @@ -346,7 +338,7 @@ void BulletPhysicsServer::area_clear_shapes(RID p_area) { ERR_FAIL_COND(!area); for (int i = area->get_shape_count(); 0 < i; --i) - area->remove_shape(0); + area->remove_shape_full(0); } void BulletPhysicsServer::area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) { @@ -567,7 +559,7 @@ void BulletPhysicsServer::body_remove_shape(RID p_body, int p_shape_idx) { RigidBodyBullet *body = rigid_body_owner.get(p_body); ERR_FAIL_COND(!body); - body->remove_shape(p_shape_idx); + body->remove_shape_full(p_shape_idx); } void BulletPhysicsServer::body_clear_shapes(RID p_body) { @@ -1486,7 +1478,7 @@ void BulletPhysicsServer::free(RID p_rid) { // Notify the shape is configured for (Map<ShapeOwnerBullet *, int>::Element *element = shape->get_owners().front(); element; element = element->next()) { - static_cast<ShapeOwnerBullet *>(element->key())->remove_shape(shape); + static_cast<ShapeOwnerBullet *>(element->key())->remove_shape_full(shape); } shape_owner.free(p_rid); @@ -1497,7 +1489,7 @@ void BulletPhysicsServer::free(RID p_rid) { body->set_space(NULL); - body->remove_all_shapes(true); + body->remove_all_shapes(true, true); rigid_body_owner.free(p_rid); bulletdelete(body); @@ -1517,7 +1509,7 @@ void BulletPhysicsServer::free(RID p_rid) { area->set_space(NULL); - area->remove_all_shapes(true); + area->remove_all_shapes(true, true); area_owner.free(p_rid); bulletdelete(area); diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h index 4c52cace67..6b7dcd86e6 100644 --- a/modules/bullet/bullet_physics_server.h +++ b/modules/bullet/bullet_physics_server.h @@ -60,13 +60,6 @@ class BulletPhysicsServer : public PhysicsServer { mutable RID_Owner<SoftBodyBullet> soft_body_owner; mutable RID_Owner<JointBullet> joint_owner; -private: - /// This is used as replacement of collision shape inside a compound or main shape - static btEmptyShape *emptyShape; - -public: - static btEmptyShape *get_empty_shape(); - protected: static void _bind_methods(); diff --git a/modules/bullet/bullet_utilities.h b/modules/bullet/bullet_utilities.h index 029eb6691a..553c1d0384 100644 --- a/modules/bullet/bullet_utilities.h +++ b/modules/bullet/bullet_utilities.h @@ -39,7 +39,8 @@ new cl #define bulletdelete(cl) \ - delete cl; \ - cl = NULL; - + { \ + delete cl; \ + cl = NULL; \ + } #endif diff --git a/modules/bullet/collision_object_bullet.cpp b/modules/bullet/collision_object_bullet.cpp index 61834b8e3f..402a276f95 100644 --- a/modules/bullet/collision_object_bullet.cpp +++ b/modules/bullet/collision_object_bullet.cpp @@ -43,8 +43,7 @@ @author AndreaCatania */ -#define enableDynamicAabbTree true -#define initialChildCapacity 1 +#define enableDynamicAabbTree false CollisionObjectBullet::ShapeWrapper::~ShapeWrapper() {} @@ -60,7 +59,10 @@ void CollisionObjectBullet::ShapeWrapper::set_transform(const btTransform &p_tra void CollisionObjectBullet::ShapeWrapper::claim_bt_shape(const btVector3 &body_scale) { if (!bt_shape) { - bt_shape = shape->create_bt_shape(scale * body_scale); + if (active) + bt_shape = shape->create_bt_shape(scale * body_scale); + else + bt_shape = ShapeBullet::create_shape_empty(); } } @@ -72,7 +74,8 @@ CollisionObjectBullet::CollisionObjectBullet(Type p_type) : bt_collision_object(NULL), body_scale(1., 1., 1.), force_shape_reset(false), - space(NULL) {} + space(NULL), + isTransformChanged(false) {} CollisionObjectBullet::~CollisionObjectBullet() { // Remove all overlapping, notify is not required since godot take care of it @@ -90,7 +93,7 @@ bool equal(real_t first, real_t second) { void CollisionObjectBullet::set_body_scale(const Vector3 &p_new_scale) { if (!equal(p_new_scale[0], body_scale[0]) || !equal(p_new_scale[1], body_scale[1]) || !equal(p_new_scale[2], body_scale[2])) { body_scale = p_new_scale; - on_body_scale_changed(); + body_scale_changed(); } } @@ -100,7 +103,7 @@ btVector3 CollisionObjectBullet::get_bt_body_scale() const { return s; } -void CollisionObjectBullet::on_body_scale_changed() { +void CollisionObjectBullet::body_scale_changed() { force_shape_reset = true; } @@ -186,49 +189,33 @@ Transform CollisionObjectBullet::get_transform() const { void CollisionObjectBullet::set_transform__bullet(const btTransform &p_global_transform) { bt_collision_object->setWorldTransform(p_global_transform); + notify_transform_changed(); } const btTransform &CollisionObjectBullet::get_transform__bullet() const { return bt_collision_object->getWorldTransform(); } +void CollisionObjectBullet::notify_transform_changed() { + isTransformChanged = true; +} + RigidCollisionObjectBullet::RigidCollisionObjectBullet(Type p_type) : CollisionObjectBullet(p_type), mainShape(NULL) { } RigidCollisionObjectBullet::~RigidCollisionObjectBullet() { - remove_all_shapes(true); + remove_all_shapes(true, true); if (mainShape && mainShape->isCompound()) { bulletdelete(mainShape); } } -/* Not used -void RigidCollisionObjectBullet::_internal_replaceShape(btCollisionShape *p_old_shape, btCollisionShape *p_new_shape) { - bool at_least_one_was_changed = false; - btTransform old_transf; - // Inverse because I need remove the shapes - // Fetch all shapes to be sure to remove all shapes - for (int i = compoundShape->getNumChildShapes() - 1; 0 <= i; --i) { - if (compoundShape->getChildShape(i) == p_old_shape) { - - old_transf = compoundShape->getChildTransform(i); - compoundShape->removeChildShapeByIndex(i); - compoundShape->addChildShape(old_transf, p_new_shape); - at_least_one_was_changed = true; - } - } - - if (at_least_one_was_changed) { - on_shapes_changed(); - } -}*/ - void RigidCollisionObjectBullet::add_shape(ShapeBullet *p_shape, const Transform &p_transform) { shapes.push_back(ShapeWrapper(p_shape, p_transform, true)); p_shape->add_owner(this); - on_shapes_changed(); + reload_shapes(); } void RigidCollisionObjectBullet::set_shape(int p_index, ShapeBullet *p_shape) { @@ -236,17 +223,31 @@ void RigidCollisionObjectBullet::set_shape(int p_index, ShapeBullet *p_shape) { shp.shape->remove_owner(this); p_shape->add_owner(this); shp.shape = p_shape; - on_shapes_changed(); + reload_shapes(); } -void RigidCollisionObjectBullet::set_shape_transform(int p_index, const Transform &p_transform) { - ERR_FAIL_INDEX(p_index, get_shape_count()); +int RigidCollisionObjectBullet::get_shape_count() const { + return shapes.size(); +} - shapes.write[p_index].set_transform(p_transform); - on_shape_changed(shapes.write[p_index].shape); +ShapeBullet *RigidCollisionObjectBullet::get_shape(int p_index) const { + return shapes[p_index].shape; } -void RigidCollisionObjectBullet::remove_shape(ShapeBullet *p_shape) { +btCollisionShape *RigidCollisionObjectBullet::get_bt_shape(int p_index) const { + return shapes[p_index].bt_shape; +} + +int RigidCollisionObjectBullet::find_shape(ShapeBullet *p_shape) const { + const int size = shapes.size(); + for (int i = 0; i < size; ++i) { + if (shapes[i].shape == p_shape) + return i; + } + return -1; +} + +void RigidCollisionObjectBullet::remove_shape_full(ShapeBullet *p_shape) { // Remove the shape, all the times it appears // Reverse order required for delete. for (int i = shapes.size() - 1; 0 <= i; --i) { @@ -255,35 +256,32 @@ void RigidCollisionObjectBullet::remove_shape(ShapeBullet *p_shape) { shapes.remove(i); } } - on_shapes_changed(); + reload_shapes(); } -void RigidCollisionObjectBullet::remove_shape(int p_index) { +void RigidCollisionObjectBullet::remove_shape_full(int p_index) { ERR_FAIL_INDEX(p_index, get_shape_count()); internal_shape_destroy(p_index); shapes.remove(p_index); - on_shapes_changed(); + reload_shapes(); } -void RigidCollisionObjectBullet::remove_all_shapes(bool p_permanentlyFromThisBody) { +void RigidCollisionObjectBullet::remove_all_shapes(bool p_permanentlyFromThisBody, bool p_force_not_reload) { // Reverse order required for delete. for (int i = shapes.size() - 1; 0 <= i; --i) { internal_shape_destroy(i, p_permanentlyFromThisBody); } shapes.clear(); - on_shapes_changed(); -} - -int RigidCollisionObjectBullet::get_shape_count() const { - return shapes.size(); + if (!p_force_not_reload) + reload_shapes(); } -ShapeBullet *RigidCollisionObjectBullet::get_shape(int p_index) const { - return shapes[p_index].shape; -} +void RigidCollisionObjectBullet::set_shape_transform(int p_index, const Transform &p_transform) { + ERR_FAIL_INDEX(p_index, get_shape_count()); -btCollisionShape *RigidCollisionObjectBullet::get_bt_shape(int p_index) const { - return shapes[p_index].bt_shape; + shapes.write[p_index].set_transform(p_transform); + // Note, enableDynamicAabbTree is false because on transform change compound is destroyed + reload_shapes(); } const btTransform &RigidCollisionObjectBullet::get_bt_shape_transform(int p_index) const { @@ -296,21 +294,27 @@ Transform RigidCollisionObjectBullet::get_shape_transform(int p_index) const { return trs; } -void RigidCollisionObjectBullet::on_shape_changed(const ShapeBullet *const p_shape) { - const int size = shapes.size(); - for (int i = 0; i < size; ++i) { - if (shapes[i].shape == p_shape) { - bulletdelete(shapes.write[i].bt_shape); - } - } - on_shapes_changed(); +void RigidCollisionObjectBullet::set_shape_disabled(int p_index, bool p_disabled) { + shapes.write[p_index].active = !p_disabled; + shape_changed(p_index); +} + +bool RigidCollisionObjectBullet::is_shape_disabled(int p_index) { + return !shapes[p_index].active; } -void RigidCollisionObjectBullet::on_shapes_changed() { +void RigidCollisionObjectBullet::shape_changed(int p_shape_index) { + bulletdelete(shapes.write[p_shape_index].bt_shape); + reload_shapes(); +} + +void RigidCollisionObjectBullet::reload_shapes() { if (mainShape && mainShape->isCompound()) { + // Destroy compound bulletdelete(mainShape); } + mainShape = NULL; ShapeWrapper *shpWrapper; @@ -325,55 +329,38 @@ void RigidCollisionObjectBullet::on_shapes_changed() { force_shape_reset = false; } - btVector3 body_scale(get_bt_body_scale()); - - if (!shape_count) - return; + const btVector3 body_scale(get_bt_body_scale()); // Try to optimize by not using compound if (1 == shape_count) { shpWrapper = &shapes.write[0]; - if (shpWrapper->active && shpWrapper->transform.getOrigin().isZero() && shpWrapper->transform.getBasis() == shpWrapper->transform.getBasis().getIdentity()) { + if (shpWrapper->transform.getOrigin().isZero() && shpWrapper->transform.getBasis() == shpWrapper->transform.getBasis().getIdentity()) { shpWrapper->claim_bt_shape(body_scale); mainShape = shpWrapper->bt_shape; - main_shape_resetted(); + main_shape_changed(); return; } } - btCompoundShape *compoundShape = bulletnew(btCompoundShape(enableDynamicAabbTree, initialChildCapacity)); + // Optimization not possible use a compound shape + btCompoundShape *compoundShape = bulletnew(btCompoundShape(enableDynamicAabbTree, shape_count)); - // Insert all shapes into compound for (int i(0); i < shape_count; ++i) { shpWrapper = &shapes.write[i]; - if (shpWrapper->active) { - shpWrapper->claim_bt_shape(body_scale); - - btTransform scaled_shape_transform(shpWrapper->transform); - scaled_shape_transform.getOrigin() *= body_scale; - compoundShape->addChildShape(scaled_shape_transform, shpWrapper->bt_shape); - } else { - compoundShape->addChildShape(btTransform(), BulletPhysicsServer::get_empty_shape()); - } + shpWrapper->claim_bt_shape(body_scale); + btTransform scaled_shape_transform(shpWrapper->transform); + scaled_shape_transform.getOrigin() *= body_scale; + compoundShape->addChildShape(scaled_shape_transform, shpWrapper->bt_shape); } compoundShape->recalculateLocalAabb(); mainShape = compoundShape; - main_shape_resetted(); -} - -void RigidCollisionObjectBullet::set_shape_disabled(int p_index, bool p_disabled) { - shapes.write[p_index].active = !p_disabled; - on_shapes_changed(); -} - -bool RigidCollisionObjectBullet::is_shape_disabled(int p_index) { - return !shapes[p_index].active; + main_shape_changed(); } -void RigidCollisionObjectBullet::on_body_scale_changed() { - CollisionObjectBullet::on_body_scale_changed(); - on_shapes_changed(); +void RigidCollisionObjectBullet::body_scale_changed() { + CollisionObjectBullet::body_scale_changed(); + reload_shapes(); } void RigidCollisionObjectBullet::internal_shape_destroy(int p_index, bool p_permanentlyFromThisBody) { diff --git a/modules/bullet/collision_object_bullet.h b/modules/bullet/collision_object_bullet.h index ea06cecb17..4a0c805ce5 100644 --- a/modules/bullet/collision_object_bullet.h +++ b/modules/bullet/collision_object_bullet.h @@ -132,6 +132,7 @@ protected: /// New area is added when overlap with new area (AreaBullet::addOverlap), then is removed when it exit (CollisionObjectBullet::onExitArea) /// This array is used mainly to know which area hold the pointer of this object Vector<AreaBullet *> areasOverlapped; + bool isTransformChanged; public: CollisionObjectBullet(Type p_type); @@ -157,7 +158,7 @@ public: void set_body_scale(const Vector3 &p_new_scale); const Vector3 &get_body_scale() const { return body_scale; } btVector3 get_bt_body_scale() const; - virtual void on_body_scale_changed(); + virtual void body_scale_changed(); void add_collision_exception(const CollisionObjectBullet *p_ignoreCollisionObject); void remove_collision_exception(const CollisionObjectBullet *p_ignoreCollisionObject); @@ -185,8 +186,9 @@ public: virtual void reload_body() = 0; virtual void set_space(SpaceBullet *p_space) = 0; _FORCE_INLINE_ SpaceBullet *get_space() const { return space; } - /// This is an event that is called when a collision checker starts + virtual void on_collision_checker_start() = 0; + virtual void on_collision_checker_end() = 0; virtual void dispatch_callbacks() = 0; @@ -197,7 +199,6 @@ public: virtual void on_enter_area(AreaBullet *p_area) = 0; virtual void on_exit_area(AreaBullet *p_area); - /// GodotObjectFlags void set_godot_object_flags(int flags); int get_godot_object_flags() const; @@ -205,11 +206,13 @@ public: Transform get_transform() const; virtual void set_transform__bullet(const btTransform &p_global_transform); virtual const btTransform &get_transform__bullet() const; + + bool is_transform_changed() const { return isTransformChanged; } + virtual void notify_transform_changed(); }; class RigidCollisionObjectBullet : public CollisionObjectBullet, public ShapeOwnerBullet { protected: - /// This could be a compound shape in case multi please collision are found btCollisionShape *mainShape; Vector<ShapeWrapper> shapes; @@ -219,31 +222,34 @@ public: _FORCE_INLINE_ const Vector<ShapeWrapper> &get_shapes_wrappers() const { return shapes; } - /// This is used to set new shape or replace existing - //virtual void _internal_replaceShape(btCollisionShape *p_old_shape, btCollisionShape *p_new_shape) = 0; + _FORCE_INLINE_ btCollisionShape *get_main_shape() const { return mainShape; } + void add_shape(ShapeBullet *p_shape, const Transform &p_transform = Transform()); void set_shape(int p_index, ShapeBullet *p_shape); - void set_shape_transform(int p_index, const Transform &p_transform); - virtual void remove_shape(ShapeBullet *p_shape); - void remove_shape(int p_index); - void remove_all_shapes(bool p_permanentlyFromThisBody = false); - - virtual void on_shape_changed(const ShapeBullet *const p_shape); - virtual void on_shapes_changed(); - - _FORCE_INLINE_ btCollisionShape *get_main_shape() const { return mainShape; } int get_shape_count() const; ShapeBullet *get_shape(int p_index) const; btCollisionShape *get_bt_shape(int p_index) const; + + int find_shape(ShapeBullet *p_shape) const; + + virtual void remove_shape_full(ShapeBullet *p_shape); + void remove_shape_full(int p_index); + void remove_all_shapes(bool p_permanentlyFromThisBody = false, bool p_force_not_reload = false); + + void set_shape_transform(int p_index, const Transform &p_transform); + const btTransform &get_bt_shape_transform(int p_index) const; Transform get_shape_transform(int p_index) const; void set_shape_disabled(int p_index, bool p_disabled); bool is_shape_disabled(int p_index); - virtual void main_shape_resetted() = 0; - virtual void on_body_scale_changed(); + virtual void shape_changed(int p_shape_index); + virtual void reload_shapes(); + + virtual void main_shape_changed() = 0; + virtual void body_scale_changed(); private: void internal_shape_destroy(int p_index, bool p_permanentlyFromThisBody = false); diff --git a/modules/bullet/godot_motion_state.h b/modules/bullet/godot_motion_state.h index fa58e86589..5844ef8bf3 100644 --- a/modules/bullet/godot_motion_state.h +++ b/modules/bullet/godot_motion_state.h @@ -82,7 +82,7 @@ public: virtual void setWorldTransform(const btTransform &worldTrans) { bodyCurrentWorldTransform = worldTrans; - owner->scratch(); + owner->notify_transform_changed(); } public: diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp index d9a77885b3..37e7718969 100644 --- a/modules/bullet/rigid_body_bullet.cpp +++ b/modules/bullet/rigid_body_bullet.cpp @@ -265,13 +265,13 @@ RigidBodyBullet::RigidBodyBullet() : angularDamp(0), can_sleep(true), omit_forces_integration(false), + can_integrate_forces(false), maxCollisionsDetection(0), collisionsCount(0), maxAreasWhereIam(10), areaWhereIamCount(0), countGravityPointSpaces(0), isScratchedSpaceOverrideModificator(false), - isTransformChanged(false), previousActiveState(true), force_integration_callback(NULL) { @@ -279,9 +279,10 @@ RigidBodyBullet::RigidBodyBullet() : // Initial properties const btVector3 localInertia(0, 0, 0); - btRigidBody::btRigidBodyConstructionInfo cInfo(mass, godotMotionState, BulletPhysicsServer::get_empty_shape(), localInertia); + btRigidBody::btRigidBodyConstructionInfo cInfo(mass, godotMotionState, NULL, localInertia); btBody = bulletnew(btRigidBody(cInfo)); + reload_shapes(); setupBulletCollisionObject(btBody); set_mode(PhysicsServer::BODY_MODE_RIGID); @@ -314,11 +315,9 @@ void RigidBodyBullet::destroy_kinematic_utilities() { } } -void RigidBodyBullet::main_shape_resetted() { - if (get_main_shape()) - btBody->setCollisionShape(get_main_shape()); - else - btBody->setCollisionShape(BulletPhysicsServer::get_empty_shape()); +void RigidBodyBullet::main_shape_changed() { + CRASH_COND(!get_main_shape()) + btBody->setCollisionShape(get_main_shape()); set_continuous_collision_detection(is_continuous_collision_detection_enabled()); // Reset } @@ -333,7 +332,7 @@ void RigidBodyBullet::reload_body() { void RigidBodyBullet::set_space(SpaceBullet *p_space) { // Clear the old space if there is one if (space) { - isTransformChanged = false; + can_integrate_forces = false; // Remove all eventual constraints assert_no_constraints(); @@ -350,8 +349,8 @@ void RigidBodyBullet::set_space(SpaceBullet *p_space) { } void RigidBodyBullet::dispatch_callbacks() { - /// The check isTransformChanged is necessary in order to call integrated forces only when the first transform is sent - if ((btBody->isKinematicObject() || btBody->isActive() || previousActiveState != btBody->isActive()) && force_integration_callback && isTransformChanged) { + /// The check isFirstTransformChanged is necessary in order to call integrated forces only when the first transform is sent + if ((btBody->isKinematicObject() || btBody->isActive() || previousActiveState != btBody->isActive()) && force_integration_callback && can_integrate_forces) { if (omit_forces_integration) btBody->clearForces(); @@ -400,10 +399,6 @@ void RigidBodyBullet::set_force_integration_callback(ObjectID p_id, const String } } -void RigidBodyBullet::scratch() { - isTransformChanged = true; -} - void RigidBodyBullet::scratch_space_override_modificator() { isScratchedSpaceOverrideModificator = true; } @@ -418,6 +413,11 @@ void RigidBodyBullet::on_collision_checker_start() { collisionsCount = 0; } +void RigidBodyBullet::on_collision_checker_end() { + // Always true if active and not a static or kinematic body + isTransformChanged = btBody->isActive() && !btBody->isStaticOrKinematicObject(); +} + bool RigidBodyBullet::add_collision_object(RigidBodyBullet *p_otherObject, const Vector3 &p_hitWorldLocation, const Vector3 &p_hitLocalLocation, const Vector3 &p_hitNormal, const float &p_appliedImpulse, int p_other_shape_index, int p_local_shape_index) { if (collisionsCount >= maxCollisionsDetection) { @@ -520,7 +520,7 @@ real_t RigidBodyBullet::get_param(PhysicsServer::BodyParameter p_param) const { void RigidBodyBullet::set_mode(PhysicsServer::BodyMode p_mode) { // This is necessary to block force_integration untile next move - isTransformChanged = false; + can_integrate_forces = false; destroy_kinematic_utilities(); // The mode change is relevant to its mass switch (p_mode) { @@ -777,8 +777,7 @@ void RigidBodyBullet::set_transform__bullet(const btTransform &p_global_transfor // The kinematic use MotionState class godotMotionState->moveBody(p_global_transform); } - btBody->setWorldTransform(p_global_transform); - scratch(); + CollisionObjectBullet::set_transform__bullet(p_global_transform); } const btTransform &RigidBodyBullet::get_transform__bullet() const { @@ -791,8 +790,8 @@ const btTransform &RigidBodyBullet::get_transform__bullet() const { } } -void RigidBodyBullet::on_shapes_changed() { - RigidCollisionObjectBullet::on_shapes_changed(); +void RigidBodyBullet::reload_shapes() { + RigidCollisionObjectBullet::reload_shapes(); const btScalar invMass = btBody->getInvMass(); const btScalar mass = invMass == 0 ? 0 : 1 / invMass; @@ -987,6 +986,11 @@ void RigidBodyBullet::reload_kinematic_shapes() { kinematic_utilities->copyAllOwnerShapes(); } +void RigidBodyBullet::notify_transform_changed() { + RigidCollisionObjectBullet::notify_transform_changed(); + can_integrate_forces = true; +} + void RigidBodyBullet::_internal_set_mass(real_t p_mass) { btVector3 localInertia(0, 0, 0); diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h index 25dac30951..26e5018c87 100644 --- a/modules/bullet/rigid_body_bullet.h +++ b/modules/bullet/rigid_body_bullet.h @@ -202,6 +202,7 @@ private: real_t angularDamp; bool can_sleep; bool omit_forces_integration; + bool can_integrate_forces; Vector<CollisionData> collisions; // these parameters are used to avoid vector resize @@ -216,7 +217,6 @@ private: int countGravityPointSpaces; bool isScratchedSpaceOverrideModificator; - bool isTransformChanged; bool previousActiveState; // Last check state ForceIntegrationCallback *force_integration_callback; @@ -231,17 +231,18 @@ public: _FORCE_INLINE_ btRigidBody *get_bt_rigid_body() { return btBody; } - virtual void main_shape_resetted(); + virtual void main_shape_changed(); virtual void reload_body(); virtual void set_space(SpaceBullet *p_space); virtual void dispatch_callbacks(); void set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata = Variant()); - void scratch(); void scratch_space_override_modificator(); virtual void on_collision_filters_change(); virtual void on_collision_checker_start(); + virtual void on_collision_checker_end(); + void set_max_collisions_detection(int p_maxCollisionsDetection) { maxCollisionsDetection = p_maxCollisionsDetection; collisions.resize(p_maxCollisionsDetection); @@ -302,7 +303,7 @@ public: virtual void set_transform__bullet(const btTransform &p_global_transform); virtual const btTransform &get_transform__bullet() const; - virtual void on_shapes_changed(); + virtual void reload_shapes(); virtual void on_enter_area(AreaBullet *p_area); virtual void on_exit_area(AreaBullet *p_area); @@ -311,6 +312,8 @@ public: /// Kinematic void reload_kinematic_shapes(); + virtual void notify_transform_changed(); + private: void _internal_set_mass(real_t p_mass); }; diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp index 4a2263407c..8bb621a863 100644 --- a/modules/bullet/shape_bullet.cpp +++ b/modules/bullet/shape_bullet.cpp @@ -34,6 +34,7 @@ #include "bullet_physics_server.h" #include "bullet_types_converter.h" #include "bullet_utilities.h" +#include "core/project_settings.h" #include "shape_owner_bullet.h" #include <BulletCollision/CollisionDispatch/btInternalEdgeUtility.h> @@ -64,7 +65,8 @@ btCollisionShape *ShapeBullet::prepare(btCollisionShape *p_btShape) const { void ShapeBullet::notifyShapeChanged() { for (Map<ShapeOwnerBullet *, int>::Element *E = owners.front(); E; E = E->next()) { - static_cast<ShapeOwnerBullet *>(E->key())->on_shape_changed(this); + ShapeOwnerBullet *owner = static_cast<ShapeOwnerBullet *>(E->key()); + owner->shape_changed(owner->find_shape(this)); } } @@ -400,18 +402,22 @@ void ConcavePolygonShapeBullet::setup(PoolVector<Vector3> p_faces) { btVector3 supVec_1; btVector3 supVec_2; for (int i = 0; i < src_face_count; ++i) { - G_TO_B(facesr[i * 3], supVec_0); + G_TO_B(facesr[i * 3 + 0], supVec_0); G_TO_B(facesr[i * 3 + 1], supVec_1); G_TO_B(facesr[i * 3 + 2], supVec_2); - shapeInterface->addTriangle(supVec_0, supVec_1, supVec_2); + // Inverted from standard godot otherwise btGenerateInternalEdgeInfo generates wrong edge info + shapeInterface->addTriangle(supVec_2, supVec_1, supVec_0); } const bool useQuantizedAabbCompression = true; meshShape = bulletnew(btBvhTriangleMeshShape(shapeInterface, useQuantizedAabbCompression)); - btTriangleInfoMap *triangleInfoMap = new btTriangleInfoMap(); - btGenerateInternalEdgeInfo(meshShape, triangleInfoMap); + + if (GLOBAL_DEF("physics/3d/smooth_trimesh_collision", false)) { + btTriangleInfoMap *triangleInfoMap = new btTriangleInfoMap(); + btGenerateInternalEdgeInfo(meshShape, triangleInfoMap); + } } else { meshShape = NULL; ERR_PRINT("The faces count are 0, the mesh shape cannot be created"); @@ -426,6 +432,7 @@ btCollisionShape *ConcavePolygonShapeBullet::create_bt_shape(const btVector3 &p_ cs = ShapeBullet::create_shape_empty(); cs->setLocalScaling(p_implicit_scale); prepare(cs); + cs->setMargin(0); return cs; } diff --git a/modules/bullet/shape_owner_bullet.h b/modules/bullet/shape_owner_bullet.h index 29d42d12f2..72ddbc482c 100644 --- a/modules/bullet/shape_owner_bullet.h +++ b/modules/bullet/shape_owner_bullet.h @@ -45,11 +45,10 @@ class CollisionObjectBullet; /// E.G. BodyShape is a child of this class ShapeOwnerBullet { public: - /// This is used to set new shape or replace existing - //virtual void _internal_replaceShape(btCollisionShape *p_old_shape, btCollisionShape *p_new_shape) = 0; - virtual void on_shape_changed(const ShapeBullet *const p_shape) = 0; - virtual void on_shapes_changed() = 0; - virtual void remove_shape(class ShapeBullet *p_shape) = 0; + virtual int find_shape(ShapeBullet *p_shape) const = 0; + virtual void shape_changed(int p_shape_index) = 0; + virtual void reload_shapes() = 0; + virtual void remove_shape_full(class ShapeBullet *p_shape) = 0; virtual ~ShapeOwnerBullet() {} }; #endif diff --git a/modules/bullet/soft_body_bullet.cpp b/modules/bullet/soft_body_bullet.cpp index f373ce5db4..94f350210f 100644 --- a/modules/bullet/soft_body_bullet.cpp +++ b/modules/bullet/soft_body_bullet.cpp @@ -72,12 +72,6 @@ void SoftBodyBullet::set_space(SpaceBullet *p_space) { } } -void SoftBodyBullet::dispatch_callbacks() {} - -void SoftBodyBullet::on_collision_filters_change() {} - -void SoftBodyBullet::on_collision_checker_start() {} - void SoftBodyBullet::on_enter_area(AreaBullet *p_area) {} void SoftBodyBullet::on_exit_area(AreaBullet *p_area) {} diff --git a/modules/bullet/soft_body_bullet.h b/modules/bullet/soft_body_bullet.h index c775193584..d04bfca046 100644 --- a/modules/bullet/soft_body_bullet.h +++ b/modules/bullet/soft_body_bullet.h @@ -91,9 +91,10 @@ public: virtual void reload_body(); virtual void set_space(SpaceBullet *p_space); - virtual void dispatch_callbacks(); - virtual void on_collision_filters_change(); - virtual void on_collision_checker_start(); + virtual void dispatch_callbacks() {} + virtual void on_collision_filters_change() {} + virtual void on_collision_checker_start() {} + virtual void on_collision_checker_end() {} virtual void on_enter_area(AreaBullet *p_area); virtual void on_exit_area(AreaBullet *p_area); diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index ba4c72f4c7..ab2d1781ad 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -175,7 +175,7 @@ bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transf btResult.m_collisionFilterGroup = 0; btResult.m_collisionFilterMask = p_collision_mask; - space->dynamicsWorld->convexSweepTest(bt_convex_shape, bt_xform_from, bt_xform_to, btResult, 0.002); + space->dynamicsWorld->convexSweepTest(bt_convex_shape, bt_xform_from, bt_xform_to, btResult, space->dynamicsWorld->getDispatchInfo().m_allowedCcdPenetration); r_closest_unsafe = 1.0; r_closest_safe = 1.0; @@ -540,17 +540,20 @@ void onBulletPreTickCallback(btDynamicsWorld *p_dynamicsWorld, btScalar timeStep void onBulletTickCallback(btDynamicsWorld *p_dynamicsWorld, btScalar timeStep) { - // Notify all Collision objects the collision checker is started const btCollisionObjectArray &colObjArray = p_dynamicsWorld->getCollisionObjectArray(); + + // Notify all Collision objects the collision checker is started for (int i = colObjArray.size() - 1; 0 <= i; --i) { - CollisionObjectBullet *colObj = static_cast<CollisionObjectBullet *>(colObjArray[i]->getUserPointer()); - assert(NULL != colObj); - colObj->on_collision_checker_start(); + static_cast<CollisionObjectBullet *>(colObjArray[i]->getUserPointer())->on_collision_checker_start(); } SpaceBullet *sb = static_cast<SpaceBullet *>(p_dynamicsWorld->getWorldUserInfo()); sb->check_ghost_overlaps(); sb->check_body_collision(); + + for (int i = colObjArray.size() - 1; 0 <= i; --i) { + static_cast<CollisionObjectBullet *>(colObjArray[i]->getUserPointer())->on_collision_checker_end(); + } } BulletPhysicsDirectSpaceState *SpaceBullet::get_direct_state() { @@ -571,7 +574,6 @@ void SpaceBullet::create_empty_world(bool p_create_soft_world) { gjk_epa_pen_solver = bulletnew(btGjkEpaPenetrationDepthSolver); gjk_simplex_solver = bulletnew(btVoronoiSimplexSolver); - gjk_simplex_solver->setEqualVertexThreshold(0.f); void *world_mem; if (p_create_soft_world) { @@ -650,7 +652,6 @@ void SpaceBullet::check_ghost_overlaps() { btConvexShape *area_shape; btGjkPairDetector::ClosestPointInput gjk_input; AreaBullet *area; - RigidCollisionObjectBullet *otherObject; int x(-1), i(-1), y(-1), z(-1), indexOverlap(-1); /// For each areas @@ -677,13 +678,17 @@ void SpaceBullet::check_ghost_overlaps() { // For each overlapping for (i = ghostOverlaps.size() - 1; 0 <= i; --i) { - if (ghostOverlaps[i]->getUserIndex() == CollisionObjectBullet::TYPE_AREA) { - if (!static_cast<AreaBullet *>(ghostOverlaps[i]->getUserPointer())->is_monitorable()) - continue; - } else if (ghostOverlaps[i]->getUserIndex() != CollisionObjectBullet::TYPE_RIGID_BODY) + btCollisionObject *overlapped_bt_co = ghostOverlaps[i]; + RigidCollisionObjectBullet *otherObject = static_cast<RigidCollisionObjectBullet *>(overlapped_bt_co->getUserPointer()); + + if (!area->is_transform_changed() && !otherObject->is_transform_changed()) continue; - otherObject = static_cast<RigidCollisionObjectBullet *>(ghostOverlaps[i]->getUserPointer()); + if (overlapped_bt_co->getUserIndex() == CollisionObjectBullet::TYPE_AREA) { + if (!static_cast<AreaBullet *>(overlapped_bt_co->getUserPointer())->is_monitorable()) + continue; + } else if (overlapped_bt_co->getUserIndex() != CollisionObjectBullet::TYPE_RIGID_BODY) + continue; bool hasOverlap = false; diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp index f0103bb71d..88f3c0338a 100644 --- a/modules/csg/csg.cpp +++ b/modules/csg/csg.cpp @@ -805,7 +805,7 @@ void CSGBrushOperation::_merge_poly(MeshMerge &mesh, int p_face_idx, const Build //process points that were not processed for (int i = 0; i < edge_process.size(); i++) { - if (edge_process[i] == true) + if (edge_process[i]) continue; //already processed int intersect_poly = -1; diff --git a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml index 76c551e8d7..6d990f6f6f 100644 --- a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml +++ b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml @@ -76,7 +76,7 @@ <return type="int"> </return> <description> - Returns the channel of the next packet that will be retrieved via [method PacketPeer.get_packet_peer] + Returns the channel of the next packet that will be retrieved via [method PacketPeer.get_packet] </description> </method> <method name="get_peer_address" qualifiers="const"> diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index c199667270..e4aee842ba 100644 --- a/modules/gdscript/editor/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -72,6 +72,7 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_ bool in_word = false; bool in_function_name = false; bool in_variable_declaration = false; + bool in_function_args = false; bool in_member_variable = false; bool in_node_path = false; bool is_hex_notation = false; @@ -220,17 +221,24 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_ } if (is_symbol) { - in_function_name = false; - in_member_variable = false; - if (expect_type && str[j] != ' ' && str[j] != '\t' && str[j] != ':') { + if (in_function_name) { + in_function_args = true; + } + + if (in_function_args && str[j] == ')') { + in_function_args = false; + } + + if (expect_type && prev_is_char) { expect_type = false; } + if (j > 0 && str[j] == '>' && str[j - 1] == '-') { expect_type = true; } - if (in_variable_declaration || previous_text == "(" || previous_text == ",") { + if (in_variable_declaration || in_function_args) { int k = j; // Skip space while (k < str.length() && (str[k] == '\t' || str[k] == ' ')) { @@ -244,6 +252,8 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_ } in_variable_declaration = false; + in_function_name = false; + in_member_variable = false; } if (!in_node_path && in_region == -1 && str[j] == '$') { diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index 8088dcf17d..f09ff224e8 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -419,8 +419,8 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a profile.call_count++; profile.frame_call_count++; } -#endif bool exit_ok = false; +#endif #ifdef DEBUG_ENABLED OPCODE_WHILE(ip < _code_size) { @@ -673,13 +673,15 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_SET_MEMBER) { CHECK_SPACE(3); -#ifdef DEBUG_ENABLED int indexname = _code_ptr[ip + 1]; GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count); const StringName *index = &_global_names_ptr[indexname]; GET_VARIANT_PTR(src, 2); bool valid; +#ifndef DEBUG_ENABLED + ClassDB::set_property(p_instance->owner, *index, *src, &valid); +#else bool ok = ClassDB::set_property(p_instance->owner, *index, *src, &valid); if (!ok) { err_text = "Internal error setting property: " + String(*index); @@ -696,12 +698,14 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_GET_MEMBER) { CHECK_SPACE(3); -#ifdef DEBUG_ENABLED int indexname = _code_ptr[ip + 1]; GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count); const StringName *index = &_global_names_ptr[indexname]; GET_VARIANT_PTR(dst, 2); +#ifndef DEBUG_ENABLED + ClassDB::get_property(p_instance->owner, *index, *dst); +#else bool ok = ClassDB::get_property(p_instance->owner, *index, *dst); if (!ok) { err_text = "Internal error getting property: " + String(*index); @@ -779,11 +783,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_ASSIGN_TYPED_NATIVE) { CHECK_SPACE(4); - GET_VARIANT_PTR(type, 1); GET_VARIANT_PTR(dst, 2); GET_VARIANT_PTR(src, 3); #ifdef DEBUG_ENABLED + GET_VARIANT_PTR(type, 1); GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(type->operator Object *()); GD_ERR_BREAK(!nc); if (src->get_type() != Variant::OBJECT && src->get_type() != Variant::NIL) { @@ -808,11 +812,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_ASSIGN_TYPED_SCRIPT) { CHECK_SPACE(4); - GET_VARIANT_PTR(type, 1); GET_VARIANT_PTR(dst, 2); GET_VARIANT_PTR(src, 3); #ifdef DEBUG_ENABLED + GET_VARIANT_PTR(type, 1); Script *base_type = Object::cast_to<Script>(type->operator Object *()); GD_ERR_BREAK(!base_type); @@ -1310,7 +1314,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a #endif } +#ifdef DEBUG_ENABLED exit_ok = true; +#endif OPCODE_BREAK; } @@ -1387,7 +1393,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a CHECK_SPACE(2); GET_VARIANT_PTR(r, 1); retvalue = *r; +#ifdef DEBUG_ENABLED exit_ok = true; +#endif OPCODE_BREAK; } @@ -1459,9 +1467,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_ASSERT) { CHECK_SPACE(2); - GET_VARIANT_PTR(test, 1); #ifdef DEBUG_ENABLED + GET_VARIANT_PTR(test, 1); bool result = test->booleanize(); if (!result) { @@ -1516,8 +1524,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_END) { - +#ifdef DEBUG_ENABLED exit_ok = true; +#endif OPCODE_BREAK; } diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index a79fcccaeb..5f2655eb92 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -679,7 +679,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s if (tokenizer->get_token() == GDScriptTokenizer::TK_BUILT_IN_TYPE) { Variant::Type ct = tokenizer->get_token_type(); - if (p_parsing_constant == false) { + if (!p_parsing_constant) { if (ct == Variant::ARRAY) { if (tokenizer->get_token(2) == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { ArrayNode *arr = alloc_node<ArrayNode>(); diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index 77e1b7290e..c37142b3c1 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -128,8 +128,8 @@ const char *GDScriptTokenizer::token_names[TK_MAX] = { "'.'", "'?'", "':'", - "'->'", "'$'", + "'->'", "'\\n'", "PI", "TAU", diff --git a/modules/mono/SCsub b/modules/mono/SCsub index 1d5c145027..e4691ee5c8 100644 --- a/modules/mono/SCsub +++ b/modules/mono/SCsub @@ -244,16 +244,13 @@ def mono_build_solution(source, target, env): copyfile(os.path.join(src_dir, asm_file), os.path.join(dst_dir, asm_file)) -output_dir = Dir('#bin').abspath -assemblies_output_dir = Dir(env['mono_assemblies_output_dir']).abspath - -mono_sln_builder = Builder(action=mono_build_solution) -env_mono.Append(BUILDERS={'MonoBuildSolution': mono_sln_builder}) -env_mono.MonoBuildSolution( - os.path.join(assemblies_output_dir, 'GodotSharpTools.dll'), - 'editor/GodotSharpTools/GodotSharpTools.sln' -) - -if os.path.normpath(output_dir) != os.path.normpath(assemblies_output_dir): - rel_assemblies_output_dir = os.path.relpath(assemblies_output_dir, output_dir) - env_mono.Append(CPPDEFINES={'GD_MONO_EDITOR_ASSEMBLIES_DIR': rel_assemblies_output_dir}) +if env['tools']: + output_dir = Dir('#bin').abspath + editor_tools_dir = os.path.join(output_dir, 'GodotSharp', 'Tools') + + mono_sln_builder = Builder(action=mono_build_solution) + env_mono.Append(BUILDERS={'MonoBuildSolution': mono_sln_builder}) + env_mono.MonoBuildSolution( + os.path.join(editor_tools_dir, 'GodotSharpTools.dll'), + 'editor/GodotSharpTools/GodotSharpTools.sln' + ) diff --git a/modules/mono/config.py b/modules/mono/config.py index 01649a972e..8427103ee7 100644 --- a/modules/mono/config.py +++ b/modules/mono/config.py @@ -5,7 +5,7 @@ import sys import subprocess from distutils.version import LooseVersion -from SCons.Script import BoolVariable, Dir, Environment, File, PathVariable, SCons, Variables +from SCons.Script import BoolVariable, Dir, Environment, File, SCons, Variables monoreg = imp.load_source('mono_reg_utils', 'modules/mono/mono_reg_utils.py') @@ -55,30 +55,20 @@ def copy_file(src_dir, dst_dir, name): copyfile(src_path, dst_path) -def custom_path_is_dir_create(key, val, env): - """Validator to check if Path is a directory, creating it if it does not exist. - Similar to PathIsDirCreate, except it uses SCons.Script.Dir() and - SCons.Script.File() in order to support the '#' top level directory token. - """ - # Dir constructor will throw an error if the path points to a file - fsDir = Dir(val) - if not fsDir.exists: - os.makedirs(fsDir.abspath) - - def configure(env): env.use_ptrcall = True env.add_module_version_string('mono') envvars = Variables() envvars.Add(BoolVariable('mono_static', 'Statically link mono', False)) - envvars.Add(PathVariable('mono_assemblies_output_dir', 'Path to the assemblies output directory', '#bin', custom_path_is_dir_create)) + envvars.Add(BoolVariable('copy_mono_root', 'Make a copy of the mono installation directory to bundle with the editor', False)) envvars.Update(env) bits = env['bits'] + tools_enabled = env['tools'] mono_static = env['mono_static'] - assemblies_output_dir = Dir(env['mono_assemblies_output_dir']).abspath + copy_mono_root = env['copy_mono_root'] mono_lib_names = ['mono-2.0-sgen', 'monosgen-2.0'] @@ -151,8 +141,6 @@ def configure(env): raise RuntimeError('Could not find mono shared library in: ' + mono_bin_path) copy_file(mono_bin_path, 'bin', mono_dll_name + '.dll') - - copy_file(os.path.join(mono_lib_path, 'mono', '4.5'), assemblies_output_dir, 'mscorlib.dll') else: sharedlib_ext = '.dylib' if sys.platform == 'darwin' else '.so' @@ -204,16 +192,14 @@ def configure(env): if sys.platform == 'darwin': env.Append(LINKFLAGS=['-Wl,-force_load,' + mono_lib_file]) - elif sys.platform == 'linux' or sys.platform == 'linux2': - env.Append(LINKFLAGS=['-Wl,-whole-archive', mono_lib_file, '-Wl,-no-whole-archive']) else: - raise RuntimeError('mono-static: Not supported on this platform') + env.Append(LINKFLAGS=['-Wl,-whole-archive', mono_lib_file, '-Wl,-no-whole-archive']) else: env.Append(LIBS=[mono_lib]) if sys.platform == 'darwin': env.Append(LIBS=['iconv', 'pthread']) - elif sys.platform == 'linux' or sys.platform == 'linux2': + else: env.Append(LIBS=['m', 'rt', 'dl', 'pthread']) if not mono_static: @@ -223,8 +209,6 @@ def configure(env): raise RuntimeError('Could not find mono shared library in: ' + mono_lib_path) copy_file(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext) - - copy_file(os.path.join(mono_lib_path, 'mono', '4.5'), assemblies_output_dir, 'mscorlib.dll') else: assert not mono_static @@ -238,7 +222,6 @@ def configure(env): mono_lib_path = '' mono_so_name = '' - mono_prefix = subprocess.check_output(['pkg-config', 'mono-2', '--variable=prefix']).decode('utf8').strip() tmpenv = Environment() tmpenv.AppendENVPath('PKG_CONFIG_PATH', os.getenv('PKG_CONFIG_PATH')) @@ -255,16 +238,163 @@ def configure(env): raise RuntimeError('Could not find mono shared library in: ' + str(tmpenv['LIBPATH'])) copy_file(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext) - copy_file(os.path.join(mono_prefix, 'lib', 'mono', '4.5'), assemblies_output_dir, 'mscorlib.dll') env.Append(LINKFLAGS='-rdynamic') + if not tools_enabled: + if not mono_root: + mono_root = subprocess.check_output(['pkg-config', 'mono-2', '--variable=prefix']).decode('utf8').strip() + + make_template_dir(env, mono_root) + + if copy_mono_root: + if not mono_root: + mono_root = subprocess.check_output(['pkg-config', 'mono-2', '--variable=prefix']).decode('utf8').strip() + + if tools_enabled: + copy_mono_root_files(env, mono_root) + else: + print("Ignoring option: 'copy_mono_root'. Only available for builds with 'tools' enabled.") + + +def make_template_dir(env, mono_root): + from shutil import rmtree + + platform = env['platform'] + target = env['target'] + + template_dir_name = '' + + if platform == 'windows': + template_dir_name = 'data.mono.%s.%s.%s' % (platform, env['bits'], target) + elif platform == 'osx': + template_dir_name = 'data.mono.%s.%s' % (platform, target) + elif platform == 'x11': + template_dir_name = 'data.mono.%s.%s.%s' % (platform, env['bits'], target) + else: + assert False + + output_dir = Dir('#bin').abspath + template_dir = os.path.join(output_dir, template_dir_name) + + template_mono_root_dir = os.path.join(template_dir, 'Mono') + + if os.path.isdir(template_mono_root_dir): + rmtree(template_mono_root_dir) # Clean first + + # Copy etc/mono/ + + template_mono_config_dir = os.path.join(template_mono_root_dir, 'etc', 'mono') + copy_mono_etc_dir(mono_root, template_mono_config_dir, env['platform']) + + # Copy the required shared libraries + + copy_mono_shared_libs(mono_root, template_mono_root_dir, env['platform']) + + +def copy_mono_root_files(env, mono_root): + from glob import glob + from shutil import copy + from shutil import rmtree + + if not mono_root: + raise RuntimeError('Mono installation directory not found') + + output_dir = Dir('#bin').abspath + editor_mono_root_dir = os.path.join(output_dir, 'GodotSharp', 'Mono') + + if os.path.isdir(editor_mono_root_dir): + rmtree(editor_mono_root_dir) # Clean first + + # Copy etc/mono/ + + editor_mono_config_dir = os.path.join(editor_mono_root_dir, 'etc', 'mono') + copy_mono_etc_dir(mono_root, editor_mono_config_dir, env['platform']) + + # Copy the required shared libraries + + copy_mono_shared_libs(mono_root, editor_mono_root_dir, env['platform']) + + # Copy framework assemblies + + mono_framework_dir = os.path.join(mono_root, 'lib', 'mono', '4.5') + mono_framework_facades_dir = os.path.join(mono_framework_dir, 'Facades') + + editor_mono_framework_dir = os.path.join(editor_mono_root_dir, 'lib', 'mono', '4.5') + editor_mono_framework_facades_dir = os.path.join(editor_mono_framework_dir, 'Facades') + + if not os.path.isdir(editor_mono_framework_dir): + os.makedirs(editor_mono_framework_dir) + if not os.path.isdir(editor_mono_framework_facades_dir): + os.makedirs(editor_mono_framework_facades_dir) + + for assembly in glob(os.path.join(mono_framework_dir, '*.dll')): + copy(assembly, editor_mono_framework_dir) + for assembly in glob(os.path.join(mono_framework_facades_dir, '*.dll')): + copy(assembly, editor_mono_framework_facades_dir) + + +def copy_mono_etc_dir(mono_root, target_mono_config_dir, platform): + from distutils.dir_util import copy_tree + from glob import glob + from shutil import copy + + if not os.path.isdir(target_mono_config_dir): + os.makedirs(target_mono_config_dir) + + mono_etc_dir = os.path.join(mono_root, 'etc', 'mono') + if not os.path.isdir(mono_etc_dir): + mono_etc_dir = '' + etc_hint_dirs = [] + if platform != 'windows': + etc_hint_dirs += ['/etc/mono', '/usr/local/etc/mono'] + if 'MONO_CFG_DIR' in os.environ: + etc_hint_dirs += [os.path.join(os.environ['MONO_CFG_DIR'], 'mono')] + for etc_hint_dir in etc_hint_dirs: + if os.path.isdir(etc_hint_dir): + mono_etc_dir = etc_hint_dir + break + if not mono_etc_dir: + raise RuntimeError('Mono installation etc directory not found') + + copy_tree(os.path.join(mono_etc_dir, '2.0'), os.path.join(target_mono_config_dir, '2.0')) + copy_tree(os.path.join(mono_etc_dir, '4.0'), os.path.join(target_mono_config_dir, '4.0')) + copy_tree(os.path.join(mono_etc_dir, '4.5'), os.path.join(target_mono_config_dir, '4.5')) + copy_tree(os.path.join(mono_etc_dir, 'mconfig'), os.path.join(target_mono_config_dir, 'mconfig')) + + for file in glob(os.path.join(mono_etc_dir, '*')): + if os.path.isfile(file): + copy(file, target_mono_config_dir) + + +def copy_mono_shared_libs(mono_root, target_mono_root_dir, platform): + from shutil import copy + + if platform == 'windows': + target_mono_bin_dir = os.path.join(target_mono_root_dir, 'bin') + + if not os.path.isdir(target_mono_bin_dir): + os.makedirs(target_mono_bin_dir) + + copy(os.path.join(mono_root, 'bin', 'MonoPosixHelper.dll'), os.path.join(target_mono_bin_dir, 'MonoPosixHelper.dll')) + else: + target_mono_lib_dir = os.path.join(target_mono_root_dir, 'lib') + + if not os.path.isdir(target_mono_lib_dir): + os.makedirs(target_mono_lib_dir) + + if platform == 'osx': + copy(os.path.join(mono_root, 'lib', 'libMonoPosixHelper.dylib'), os.path.join(target_mono_lib_dir, 'libMonoPosixHelper.dylib')) + elif platform == 'x11': + copy(os.path.join(mono_root, 'lib', 'libmono-btls-shared.so'), os.path.join(target_mono_lib_dir, 'libmono-btls-shared.so')) + copy(os.path.join(mono_root, 'lib', 'libMonoPosixHelper.so'), os.path.join(target_mono_lib_dir, 'libMonoPosixHelper.so')) + def configure_for_mono_version(env, mono_version): if mono_version is None: raise RuntimeError('Mono JIT compiler version not found') print('Found Mono JIT compiler version: ' + str(mono_version)) - if mono_version >= LooseVersion("5.12.0"): + if mono_version >= LooseVersion('5.12.0'): env.Append(CPPFLAGS=['-DHAS_PENDING_EXCEPTIONS']) diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 91fd482235..5160d42367 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -1194,7 +1194,7 @@ bool CSharpInstance::set(const StringName &p_name, const Variant &p_value) { MonoObject *ret = method->invoke(mono_object, args); - if (ret && GDMonoMarshal::unbox<MonoBoolean>(ret) == true) + if (ret && GDMonoMarshal::unbox<MonoBoolean>(ret)) return true; break; @@ -1459,7 +1459,7 @@ MonoObject *CSharpInstance::_internal_new_managed() { void CSharpInstance::mono_object_disposed(MonoObject *p_obj) { #ifdef DEBUG_ENABLED - CRASH_COND(base_ref == true); + CRASH_COND(base_ref); CRASH_COND(gchandle.is_null()); #endif CSharpLanguage::get_singleton()->release_script_gchandle(p_obj, gchandle); @@ -1468,7 +1468,7 @@ void CSharpInstance::mono_object_disposed(MonoObject *p_obj) { void CSharpInstance::mono_object_disposed_baseref(MonoObject *p_obj, bool p_is_finalizer, bool &r_owner_deleted) { #ifdef DEBUG_ENABLED - CRASH_COND(base_ref == false); + CRASH_COND(!base_ref); CRASH_COND(gchandle.is_null()); #endif if (_unreference_owner_unsafe()) { diff --git a/modules/mono/doc_classes/GodotSharp.xml b/modules/mono/doc_classes/GodotSharp.xml index 985c66464b..921c1ca825 100644 --- a/modules/mono/doc_classes/GodotSharp.xml +++ b/modules/mono/doc_classes/GodotSharp.xml @@ -23,18 +23,44 @@ Detaches the current thread from the mono runtime. </description> </method> - <method name="is_domain_loaded"> + <method name="get_domain_id"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="get_scripts_domain_id"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="is_domain_finalizing_for_unload"> + <return type="bool"> + </return> + <argument index="0" name="domain_id" type="int"> + </argument> + <description> + Returns whether the domain is being finalized. + </description> + </method> + <method name="is_runtime_initialized"> + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="is_runtime_shutting_down"> <return type="bool"> </return> <description> - Returns whether the scripts domain is loaded. </description> </method> - <method name="is_finalizing_domain"> + <method name="is_scripts_domain_loaded"> <return type="bool"> </return> <description> - Returns whether the scripts domain is being finalized. + Returns whether the scripts domain is loaded. </description> </method> </methods> diff --git a/modules/mono/editor/GodotSharpTools/Editor/GodotSharpExport.cs b/modules/mono/editor/GodotSharpTools/Editor/GodotSharpExport.cs new file mode 100644 index 0000000000..5fd708d539 --- /dev/null +++ b/modules/mono/editor/GodotSharpTools/Editor/GodotSharpExport.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.CompilerServices; + +namespace GodotSharpTools.Editor +{ + public static class GodotSharpExport + { + public static void _ExportBegin(string[] features, bool debug, string path, int flags) + { + var featureSet = new HashSet<string>(features); + + if (PlatformHasTemplateDir(featureSet)) + { + string templateDirName = "data.mono"; + + if (featureSet.Contains("Windows")) + { + templateDirName += ".windows"; + templateDirName += featureSet.Contains("64") ? ".64" : ".32"; + } + else if (featureSet.Contains("X11")) + { + templateDirName += ".x11"; + templateDirName += featureSet.Contains("64") ? ".64" : ".32"; + } + else + { + throw new NotSupportedException("Target platform not supported"); + } + + templateDirName += debug ? ".debug" : ".release"; + + string templateDirPath = Path.Combine(GetTemplatesDir(), templateDirName); + + if (!Directory.Exists(templateDirPath)) + throw new FileNotFoundException("Data template directory not found"); + + string outputDir = new FileInfo(path).Directory.FullName; + + string outputDataDir = Path.Combine(outputDir, GetDataDirName()); + + if (Directory.Exists(outputDataDir)) + Directory.Delete(outputDataDir, recursive: true); // Clean first + + Directory.CreateDirectory(outputDataDir); + + foreach (string dir in Directory.GetDirectories(templateDirPath, "*", SearchOption.AllDirectories)) + { + Directory.CreateDirectory(Path.Combine(outputDataDir, dir.Substring(templateDirPath.Length + 1))); + } + + foreach (string file in Directory.GetFiles(templateDirPath, "*", SearchOption.AllDirectories)) + { + File.Copy(file, Path.Combine(outputDataDir, file.Substring(templateDirPath.Length + 1))); + } + } + } + + public static bool PlatformHasTemplateDir(HashSet<string> featureSet) + { + // OSX export templates are contained in a zip, so we place + // our custom template inside it and let Godot do the rest. + return !featureSet.Contains("OSX"); + } + + [MethodImpl(MethodImplOptions.InternalCall)] + extern static string GetTemplatesDir(); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern static string GetDataDirName(); + } +} diff --git a/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj b/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj index 773e8196f7..fceb732426 100644 --- a/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj +++ b/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj @@ -41,6 +41,7 @@ <Compile Include="Project\ProjectUtils.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Utils\OS.cs" /> + <Compile Include="Editor\GodotSharpExport.cs" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> </Project>
\ No newline at end of file diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 2c3435fc1c..bcf08026bc 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -1269,12 +1269,12 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { output.push_back("namespace GodotSharpBindings\n" OPEN_BLOCK "\n"); output.push_back("uint64_t get_core_api_hash() { return "); - output.push_back(String::num_uint64(GDMono::get_singleton()->get_api_core_hash()) + "; }\n"); + output.push_back(String::num_uint64(GDMono::get_singleton()->get_api_core_hash()) + "U; }\n"); output.push_back("#ifdef TOOLS_ENABLED\n" "uint64_t get_editor_api_hash() { return "); - output.push_back(String::num_uint64(GDMono::get_singleton()->get_api_editor_hash()) + - "; }\n#endif // TOOLS_ENABLED\n"); + output.push_back(String::num_uint64(GDMono::get_singleton()->get_api_editor_hash()) + "U; }\n"); + output.push_back("#endif // TOOLS_ENABLED\n"); output.push_back("uint32_t get_bindings_version() { return "); output.push_back(String::num_uint64(BINDINGS_GENERATOR_VERSION) + "; }\n"); @@ -2019,7 +2019,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { // bool itype = TypeInterface::create_value_type(String("bool")); - itype.c_arg_in = "&%s"; + itype.c_arg_in = "&%s_in"; // /* MonoBoolean <---> bool itype.c_in = "\t%0 %1_in = (%0)%1;\n"; itype.c_out = "\treturn (%0)%1;\n"; diff --git a/modules/mono/editor/csharp_project.cpp b/modules/mono/editor/csharp_project.cpp index 4764cbe941..6f223b75a3 100644 --- a/modules/mono/editor/csharp_project.cpp +++ b/modules/mono/editor/csharp_project.cpp @@ -51,7 +51,7 @@ String generate_core_api_project(const String &p_dir, const Vector<String> &p_fi MonoObject *ret = klass->get_method("GenCoreApiProject", 2)->invoke(NULL, args, &exc); if (exc) { - GDMonoUtils::debug_unhandled_exception(exc); + GDMonoUtils::debug_print_unhandled_exception(exc); ERR_FAIL_V(String()); } @@ -72,7 +72,7 @@ String generate_editor_api_project(const String &p_dir, const String &p_core_dll MonoObject *ret = klass->get_method("GenEditorApiProject", 3)->invoke(NULL, args, &exc); if (exc) { - GDMonoUtils::debug_unhandled_exception(exc); + GDMonoUtils::debug_print_unhandled_exception(exc); ERR_FAIL_V(String()); } @@ -93,7 +93,7 @@ String generate_game_project(const String &p_dir, const String &p_name, const Ve MonoObject *ret = klass->get_method("GenGameProject", 3)->invoke(NULL, args, &exc); if (exc) { - GDMonoUtils::debug_unhandled_exception(exc); + GDMonoUtils::debug_print_unhandled_exception(exc); ERR_FAIL_V(String()); } @@ -114,7 +114,7 @@ void add_item(const String &p_project_path, const String &p_item_type, const Str klass->get_method("AddItemToProjectChecked", 3)->invoke(NULL, args, &exc); if (exc) { - GDMonoUtils::debug_unhandled_exception(exc); + GDMonoUtils::debug_print_unhandled_exception(exc); ERR_FAIL(); } } diff --git a/modules/mono/editor/godotsharp_builds.cpp b/modules/mono/editor/godotsharp_builds.cpp index d397814fa7..8fe6e46b60 100644 --- a/modules/mono/editor/godotsharp_builds.cpp +++ b/modules/mono/editor/godotsharp_builds.cpp @@ -249,6 +249,18 @@ bool GodotSharpBuilds::build_api_sln(const String &p_name, const String &p_api_s bool GodotSharpBuilds::copy_api_assembly(const String &p_src_dir, const String &p_dst_dir, const String &p_assembly_name, APIAssembly::Type p_api_type) { + // Create destination directory if needed + if (!DirAccess::exists(p_dst_dir)) { + DirAccess *da = DirAccess::create_for_path(p_dst_dir); + Error err = da->make_dir_recursive(p_dst_dir); + memdelete(da); + + if (err != OK) { + show_build_error_dialog("Failed to create destination directory for the API assemblies. Error: " + itos(err)); + return false; + } + } + String assembly_file = p_assembly_name + ".dll"; String assembly_src = p_src_dir.plus_file(assembly_file); String assembly_dst = p_dst_dir.plus_file(assembly_file); @@ -296,9 +308,9 @@ bool GodotSharpBuilds::make_api_sln(APIAssembly::Type p_api_type) { String api_name = p_api_type == APIAssembly::API_CORE ? API_ASSEMBLY_NAME : EDITOR_API_ASSEMBLY_NAME; String api_build_config = "Release"; - EditorProgress pr("mono_build_release_" + api_name, "Building " + api_name + " solution...", 4); + EditorProgress pr("mono_build_release_" + api_name, "Building " + api_name + " solution...", 3); - pr.step("Generating " + api_name + " solution"); + pr.step("Generating " + api_name + " solution", 0); String core_api_sln_dir = GodotSharpDirs::get_mono_solutions_dir() .plus_file(_api_folder_name(APIAssembly::API_CORE)) @@ -336,34 +348,19 @@ bool GodotSharpBuilds::make_api_sln(APIAssembly::Type p_api_type) { } } - pr.step("Building " + api_name + " solution"); + pr.step("Building " + api_name + " solution", 1); if (!GodotSharpBuilds::build_api_sln(api_name, api_sln_dir, api_build_config)) return false; - pr.step("Copying " + api_name + " assembly"); - - String res_assemblies_dir = GodotSharpDirs::get_res_assemblies_dir(); - - // Create assemblies directory if needed - if (!DirAccess::exists(res_assemblies_dir)) { - DirAccess *da = DirAccess::create_for_path(res_assemblies_dir); - Error err = da->make_dir_recursive(res_assemblies_dir); - memdelete(da); - - if (err != OK) { - show_build_error_dialog("Failed to create assemblies directory. Error: " + itos(err)); - return false; - } - } + pr.step("Copying " + api_name + " assembly", 2); // Copy the built assembly to the assemblies directory String api_assembly_dir = api_sln_dir.plus_file("bin").plus_file(api_build_config); + String res_assemblies_dir = GodotSharpDirs::get_res_assemblies_dir(); if (!GodotSharpBuilds::copy_api_assembly(api_assembly_dir, res_assemblies_dir, api_name, p_api_type)) return false; - pr.step("Done"); - return true; } @@ -372,15 +369,39 @@ bool GodotSharpBuilds::build_project_blocking(const String &p_config) { if (!FileAccess::exists(GodotSharpDirs::get_project_sln_path())) return true; // No solution to build - if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_CORE)) - return false; + String editor_prebuilt_api_dir = GodotSharpDirs::get_data_editor_prebuilt_api_dir(); + String res_assemblies_dir = GodotSharpDirs::get_res_assemblies_dir(); - if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_EDITOR)) - return false; + if (FileAccess::exists(editor_prebuilt_api_dir.plus_file(API_ASSEMBLY_NAME ".dll"))) { + EditorProgress pr("mono_copy_prebuilt_api_assemblies", + "Copying prebuilt " API_ASSEMBLY_NAME " assemblies...", 1); + pr.step("Copying " API_ASSEMBLY_NAME " assembly", 0); - EditorProgress pr("mono_project_debug_build", "Building project solution...", 2); + if (!GodotSharpBuilds::copy_api_assembly(editor_prebuilt_api_dir, res_assemblies_dir, + API_ASSEMBLY_NAME, APIAssembly::API_CORE)) { + return false; + } + } else { + if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_CORE)) + return false; + } - pr.step("Building project solution"); + if (DirAccess::exists(editor_prebuilt_api_dir.plus_file(EDITOR_API_ASSEMBLY_NAME ".dll"))) { + EditorProgress pr("mono_copy_prebuilt_api_assemblies", + "Copying prebuilt " EDITOR_API_ASSEMBLY_NAME " assemblies...", 1); + pr.step("Copying " EDITOR_API_ASSEMBLY_NAME " assembly", 0); + + if (!GodotSharpBuilds::copy_api_assembly(editor_prebuilt_api_dir, res_assemblies_dir, + EDITOR_API_ASSEMBLY_NAME, APIAssembly::API_EDITOR)) { + return false; + } + } else { + if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_EDITOR)) + return false; + } + + EditorProgress pr("mono_project_debug_build", "Building project solution...", 1); + pr.step("Building project solution", 0); MonoBuildInfo build_info(GodotSharpDirs::get_project_sln_path(), p_config); if (!GodotSharpBuilds::get_singleton()->build(build_info)) { @@ -388,8 +409,6 @@ bool GodotSharpBuilds::build_project_blocking(const String &p_config) { return false; } - pr.step("Done"); - return true; } diff --git a/modules/mono/editor/godotsharp_editor.cpp b/modules/mono/editor/godotsharp_editor.cpp index 3ee38515bf..fca88a7164 100644 --- a/modules/mono/editor/godotsharp_editor.cpp +++ b/modules/mono/editor/godotsharp_editor.cpp @@ -197,6 +197,7 @@ void GodotSharpEditor::register_internal_calls() { mono_add_internal_call("GodotSharpTools.Utils.OS::GetPlatformName", (void *)godot_icall_Utils_OS_GetPlatformName); GodotSharpBuilds::register_internal_calls(); + GodotSharpExport::register_internal_calls(); } void GodotSharpEditor::show_error_dialog(const String &p_message, const String &p_title) { diff --git a/modules/mono/editor/godotsharp_export.cpp b/modules/mono/editor/godotsharp_export.cpp index cd09e6516a..933ede93dc 100644 --- a/modules/mono/editor/godotsharp_export.cpp +++ b/modules/mono/editor/godotsharp_export.cpp @@ -30,12 +30,37 @@ #include "godotsharp_export.h" +#include "core/version.h" + #include "../csharp_script.h" #include "../godotsharp_defs.h" #include "../godotsharp_dirs.h" +#include "../mono_gd/gd_mono_class.h" +#include "../mono_gd/gd_mono_marshal.h" #include "godotsharp_builds.h" -void GodotSharpExport::_export_file(const String &p_path, const String &p_type, const Set<String> &p_features) { +static MonoString *godot_icall_GodotSharpExport_GetTemplatesDir() { + String current_version = VERSION_FULL_CONFIG; + String templates_dir = EditorSettings::get_singleton()->get_templates_dir().plus_file(current_version); + return GDMonoMarshal::mono_string_from_godot(ProjectSettings::get_singleton()->globalize_path(templates_dir)); +} + +static MonoString *godot_icall_GodotSharpExport_GetDataDirName() { + String appname = ProjectSettings::get_singleton()->get("application/config/name"); + String appname_safe = OS::get_singleton()->get_safe_dir_name(appname); + return GDMonoMarshal::mono_string_from_godot("data_" + appname_safe); +} + +void GodotSharpExport::register_internal_calls() { + static bool registered = false; + ERR_FAIL_COND(registered); + registered = true; + + mono_add_internal_call("GodotSharpTools.Editor.GodotSharpExport::GetTemplatesDir", (void *)godot_icall_GodotSharpExport_GetTemplatesDir); + mono_add_internal_call("GodotSharpTools.Editor.GodotSharpExport::GetDataDirName", (void *)godot_icall_GodotSharpExport_GetDataDirName); +} + +void GodotSharpExport::_export_file(const String &p_path, const String &p_type, const Set<String> &) { if (p_type != CSharpLanguage::get_singleton()->get_type()) return; @@ -56,59 +81,78 @@ void GodotSharpExport::_export_begin(const Set<String> &p_features, bool p_debug // TODO right now there is no way to stop the export process with an error ERR_FAIL_COND(!GDMono::get_singleton()->is_runtime_initialized()); - ERR_FAIL_NULL(GDMono::get_singleton()->get_tools_domain()); + ERR_FAIL_NULL(TOOLS_DOMAIN); + ERR_FAIL_NULL(GDMono::get_singleton()->get_editor_tools_assembly()); String build_config = p_debug ? "Debug" : "Release"; ERR_FAIL_COND(!GodotSharpBuilds::build_project_blocking(build_config)); - // Add API assemblies - - String core_api_dll_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(API_ASSEMBLY_NAME ".dll"); - ERR_FAIL_COND(!_add_assembly(core_api_dll_path, core_api_dll_path)); - - String editor_api_dll_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(EDITOR_API_ASSEMBLY_NAME ".dll"); - ERR_FAIL_COND(!_add_assembly(editor_api_dll_path, editor_api_dll_path)); + // Add dependency assemblies - // Add project assembly + Map<String, String> dependencies; String project_dll_name = ProjectSettings::get_singleton()->get("application/config/name"); if (project_dll_name.empty()) { project_dll_name = "UnnamedProject"; } - String project_dll_src_path = GodotSharpDirs::get_res_temp_assemblies_base_dir().plus_file(build_config).plus_file(project_dll_name + ".dll"); - String project_dll_dst_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(project_dll_name + ".dll"); - ERR_FAIL_COND(!_add_assembly(project_dll_src_path, project_dll_dst_path)); - - // Add dependencies - - MonoDomain *prev_domain = mono_domain_get(); - MonoDomain *export_domain = GDMonoUtils::create_domain("GodotEngine.ProjectExportDomain"); + String project_dll_src_dir = GodotSharpDirs::get_res_temp_assemblies_base_dir().plus_file(build_config); + String project_dll_src_path = project_dll_src_dir.plus_file(project_dll_name + ".dll"); + dependencies.insert(project_dll_name, project_dll_src_path); - ERR_FAIL_COND(!export_domain); - ERR_FAIL_COND(!mono_domain_set(export_domain, false)); + { + MonoDomain *export_domain = GDMonoUtils::create_domain("GodotEngine.ProjectExportDomain"); + ERR_FAIL_NULL(export_domain); + _GDMONO_SCOPE_EXIT_DOMAIN_UNLOAD_(export_domain); - Map<String, String> dependencies; - dependencies.insert("mscorlib", GDMono::get_singleton()->get_corlib_assembly()->get_path()); - - GDMonoAssembly *scripts_assembly = GDMonoAssembly::load_from(project_dll_name, project_dll_src_path, /* refonly: */ true); + _GDMONO_SCOPE_DOMAIN_(export_domain); - ERR_EXPLAIN("Cannot load refonly assembly: " + project_dll_name); - ERR_FAIL_COND(!scripts_assembly); + GDMonoAssembly *scripts_assembly = NULL; + bool load_success = GDMono::get_singleton()->load_assembly_from(project_dll_name, + project_dll_src_dir, &scripts_assembly, /* refonly: */ true); - Error depend_error = _get_assembly_dependencies(scripts_assembly, dependencies); + ERR_EXPLAIN("Cannot load refonly assembly: " + project_dll_name); + ERR_FAIL_COND(!load_success); - GDMono::get_singleton()->finalize_and_unload_domain(export_domain); - mono_domain_set(prev_domain, false); - - ERR_FAIL_COND(depend_error != OK); + Vector<String> search_dirs; + GDMonoAssembly::fill_search_dirs(search_dirs); + Error depend_error = _get_assembly_dependencies(scripts_assembly, search_dirs, dependencies); + ERR_FAIL_COND(depend_error != OK); + } for (Map<String, String>::Element *E = dependencies.front(); E; E = E->next()) { String depend_src_path = E->value(); String depend_dst_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(depend_src_path.get_file()); ERR_FAIL_COND(!_add_assembly(depend_src_path, depend_dst_path)); } + + // Mono specific export template extras (data dir) + + GDMonoClass *export_class = GDMono::get_singleton()->get_editor_tools_assembly()->get_class("GodotSharpTools.Editor", "GodotSharpExport"); + ERR_FAIL_NULL(export_class); + GDMonoMethod *export_begin_method = export_class->get_method("_ExportBegin", 4); + ERR_FAIL_NULL(export_begin_method); + + MonoArray *features = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(String), p_features.size()); + int i = 0; + for (const Set<String>::Element *E = p_features.front(); E; E = E->next()) { + MonoString *boxed = GDMonoMarshal::mono_string_from_godot(E->get()); + mono_array_set(features, MonoString *, i, boxed); + i++; + } + + MonoBoolean debug = p_debug; + MonoString *path = GDMonoMarshal::mono_string_from_godot(p_path); + uint32_t flags = p_flags; + void *args[4] = { features, &debug, path, &flags }; + MonoException *exc = NULL; + export_begin_method->invoke_raw(NULL, args, &exc); + + if (exc) { + GDMonoUtils::debug_print_unhandled_exception(exc); + ERR_FAIL(); + } } bool GodotSharpExport::_add_assembly(const String &p_src_path, const String &p_dst_path) { @@ -125,7 +169,7 @@ bool GodotSharpExport::_add_assembly(const String &p_src_path, const String &p_d return true; } -Error GodotSharpExport::_get_assembly_dependencies(GDMonoAssembly *p_assembly, Map<String, String> &r_dependencies) { +Error GodotSharpExport::_get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String> &p_search_dirs, Map<String, String> &r_dependencies) { MonoImage *image = p_assembly->get_image(); @@ -134,18 +178,48 @@ Error GodotSharpExport::_get_assembly_dependencies(GDMonoAssembly *p_assembly, M mono_assembly_get_assemblyref(image, i, ref_aname); String ref_name = mono_assembly_name_get_name(ref_aname); - if (ref_name == "mscorlib" || r_dependencies.find(ref_name)) + if (r_dependencies.find(ref_name)) continue; GDMonoAssembly *ref_assembly = NULL; - if (!GDMono::get_singleton()->load_assembly(ref_name, ref_aname, &ref_assembly, /* refonly: */ true)) { - ERR_EXPLAIN("Cannot load refonly assembly: " + ref_name); + String path; + bool has_extension = ref_name.ends_with(".dll") || ref_name.ends_with(".exe"); + + for (int i = 0; i < p_search_dirs.size(); i++) { + const String &search_dir = p_search_dirs[i]; + + if (has_extension) { + path = search_dir.plus_file(ref_name); + if (FileAccess::exists(path)) { + GDMono::get_singleton()->load_assembly_from(ref_name.get_basename(), search_dir, ref_aname, &ref_assembly, true); + if (ref_assembly != NULL) + break; + } + } else { + path = search_dir.plus_file(ref_name + ".dll"); + if (FileAccess::exists(path)) { + GDMono::get_singleton()->load_assembly_from(ref_name, search_dir, ref_aname, &ref_assembly, true); + if (ref_assembly != NULL) + break; + } + + path = search_dir.plus_file(ref_name + ".exe"); + if (FileAccess::exists(path)) { + GDMono::get_singleton()->load_assembly_from(ref_name, search_dir, ref_aname, &ref_assembly, true); + if (ref_assembly != NULL) + break; + } + } + } + + if (!ref_assembly) { + ERR_EXPLAIN("Cannot load assembly (refonly): " + ref_name); ERR_FAIL_V(ERR_CANT_RESOLVE); } r_dependencies.insert(ref_name, ref_assembly->get_path()); - Error err = _get_assembly_dependencies(ref_assembly, r_dependencies); + Error err = _get_assembly_dependencies(ref_assembly, p_search_dirs, r_dependencies); if (err != OK) return err; } diff --git a/modules/mono/editor/godotsharp_export.h b/modules/mono/editor/godotsharp_export.h index b38db9660c..f007016578 100644 --- a/modules/mono/editor/godotsharp_export.h +++ b/modules/mono/editor/godotsharp_export.h @@ -43,13 +43,15 @@ class GodotSharpExport : public EditorExportPlugin { bool _add_assembly(const String &p_src_path, const String &p_dst_path); - Error _get_assembly_dependencies(GDMonoAssembly *p_assembly, Map<String, String> &r_dependencies); + Error _get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String> &p_search_dirs, Map<String, String> &r_dependencies); protected: virtual void _export_file(const String &p_path, const String &p_type, const Set<String> &p_features); virtual void _export_begin(const Set<String> &p_features, bool p_debug, const String &p_path, int p_flags); public: + static void register_internal_calls(); + GodotSharpExport(); ~GodotSharpExport(); }; diff --git a/modules/mono/editor/mono_bottom_panel.cpp b/modules/mono/editor/mono_bottom_panel.cpp index 8d9b345a92..0ac59a1be8 100644 --- a/modules/mono/editor/mono_bottom_panel.cpp +++ b/modules/mono/editor/mono_bottom_panel.cpp @@ -63,7 +63,7 @@ void MonoBottomPanel::_update_build_tabs_list() { item_tooltip += "Running"; } - if (!tab->build_exited || !tab->build_result == MonoBuildTab::RESULT_SUCCESS) { + if (!tab->build_exited || tab->build_result == MonoBuildTab::RESULT_ERROR) { item_tooltip += "\nErrors: " + itos(tab->error_count); } diff --git a/modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs b/modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs index 71534d7782..366d89b1c2 100644 --- a/modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs +++ b/modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs @@ -2,42 +2,42 @@ namespace Godot { public partial class Node { - public T GetNode<T>(NodePath path) where T : Godot.Node + public T GetNode<T>(NodePath path) where T : class { - return (T)GetNode(path); + return (T)(object)GetNode(path); } - public T GetNodeOrNull<T>(NodePath path) where T : Godot.Node + public T GetNodeOrNull<T>(NodePath path) where T : class { return GetNode(path) as T; } - public T GetChild<T>(int idx) where T : Godot.Node + public T GetChild<T>(int idx) where T : class { - return (T)GetChild(idx); + return (T)(object)GetChild(idx); } - public T GetChildOrNull<T>(int idx) where T : Godot.Node + public T GetChildOrNull<T>(int idx) where T : class { return GetChild(idx) as T; } - public T GetOwner<T>() where T : Godot.Node + public T GetOwner<T>() where T : class { - return (T)GetOwner(); + return (T)(object)GetOwner(); } - public T GetOwnerOrNull<T>() where T : Godot.Node + public T GetOwnerOrNull<T>() where T : class { return GetOwner() as T; } - public T GetParent<T>() where T : Godot.Node + public T GetParent<T>() where T : class { - return (T)GetParent(); + return (T)(object)GetParent(); } - public T GetParentOrNull<T>() where T : Godot.Node + public T GetParentOrNull<T>() where T : class { return GetParent() as T; } diff --git a/modules/mono/glue/Managed/Files/Extensions/ResourceLoaderExtensions.cs b/modules/mono/glue/Managed/Files/Extensions/ResourceLoaderExtensions.cs index ceecc589e6..684d160b57 100644 --- a/modules/mono/glue/Managed/Files/Extensions/ResourceLoaderExtensions.cs +++ b/modules/mono/glue/Managed/Files/Extensions/ResourceLoaderExtensions.cs @@ -2,9 +2,9 @@ namespace Godot { public static partial class ResourceLoader { - public static T Load<T>(string path) where T : Godot.Resource + public static T Load<T>(string path) where T : class { - return (T) Load(path); + return (T)(object)Load(path); } } } diff --git a/modules/mono/glue/Managed/Files/GD.cs b/modules/mono/glue/Managed/Files/GD.cs index 264be23588..e4818e186c 100644 --- a/modules/mono/glue/Managed/Files/GD.cs +++ b/modules/mono/glue/Managed/Files/GD.cs @@ -65,9 +65,9 @@ namespace Godot return ResourceLoader.Load(path); } - public static T Load<T>(string path) where T : Godot.Resource + public static T Load<T>(string path) where T : class { - return (T) ResourceLoader.Load(path); + return ResourceLoader.Load<T>(path); } public static void Print(params object[] what) diff --git a/modules/mono/glue/nodepath_glue.cpp b/modules/mono/glue/nodepath_glue.cpp index 4b7648a4f9..422d73104d 100644 --- a/modules/mono/glue/nodepath_glue.cpp +++ b/modules/mono/glue/nodepath_glue.cpp @@ -40,7 +40,7 @@ NodePath *godot_icall_NodePath_Ctor(MonoString *p_path) { void godot_icall_NodePath_Dtor(NodePath *p_ptr) { ERR_FAIL_NULL(p_ptr); - _GodotSharp::get_singleton()->queue_dispose(p_ptr); + memdelete(p_ptr); } MonoString *godot_icall_NodePath_operator_String(NodePath *p_np) { diff --git a/modules/mono/glue/rid_glue.cpp b/modules/mono/glue/rid_glue.cpp index 5d66b8aa6f..6c002b5b9d 100644 --- a/modules/mono/glue/rid_glue.cpp +++ b/modules/mono/glue/rid_glue.cpp @@ -45,7 +45,7 @@ RID *godot_icall_RID_Ctor(Object *p_from) { void godot_icall_RID_Dtor(RID *p_ptr) { ERR_FAIL_NULL(p_ptr); - _GodotSharp::get_singleton()->queue_dispose(p_ptr); + memdelete(p_ptr); } uint32_t godot_icall_RID_get_id(RID *p_ptr) { diff --git a/modules/mono/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp index 2570e68f13..d3fb2cb640 100644 --- a/modules/mono/godotsharp_dirs.cpp +++ b/modules/mono/godotsharp_dirs.cpp @@ -30,11 +30,11 @@ #include "godotsharp_dirs.h" +#include "core/os/dir_access.h" #include "core/os/os.h" +#include "core/project_settings.h" #ifdef TOOLS_ENABLED -#include "core/os/dir_access.h" -#include "core/project_settings.h" #include "core/version.h" #include "editor/editor_settings.h" #endif @@ -95,10 +95,18 @@ public: #ifdef TOOLS_ENABLED String mono_solutions_dir; String build_logs_dir; + String sln_filepath; String csproj_filepath; + + String data_mono_bin_dir; + String data_editor_tools_dir; + String data_editor_prebuilt_api_dir; #endif + String data_mono_etc_dir; + String data_mono_lib_dir; + private: _GodotSharpDirs() { res_data_dir = "res://.mono"; @@ -123,10 +131,60 @@ private: name = "UnnamedProject"; } - String base_path = String("res://") + name; + String base_path = ProjectSettings::get_singleton()->globalize_path("res://"); + + sln_filepath = base_path.plus_file(name + ".sln"); + csproj_filepath = base_path.plus_file(name + ".csproj"); +#endif + + String exe_dir = OS::get_singleton()->get_executable_path().get_base_dir(); + +#ifdef TOOLS_ENABLED + + String data_dir_root = exe_dir.plus_file("GodotSharp"); + data_editor_tools_dir = data_dir_root.plus_file("Tools"); + data_editor_prebuilt_api_dir = data_dir_root.plus_file("Api"); + + String data_mono_root_dir = data_dir_root.plus_file("Mono"); + data_mono_bin_dir = data_mono_root_dir.plus_file("bin"); + data_mono_etc_dir = data_mono_root_dir.plus_file("etc"); + data_mono_lib_dir = data_mono_root_dir.plus_file("lib"); + +#ifdef OSX_ENABLED + if (!DirAccess::exists(data_editor_tools_dir)) { + data_editor_tools_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Tools"); + } + + if (!DirAccess::exists(data_editor_prebuilt_api_dir)) { + data_editor_prebuilt_api_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Api"); + } + + if (!DirAccess::exists(data_mono_root_dir)) { + data_mono_bin_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Mono/bin"); + data_mono_etc_dir = exe_dir.plus_file("../Resources/GodotSharp/Mono/etc"); + data_mono_lib_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Mono/lib"); + } +#endif + +#else + + String appname = OS::get_singleton()->get_safe_dir_name(ProjectSettings::get_singleton()->get("application/config/name")); + String data_dir_root = exe_dir.plus_file("data_" + appname); + if (!DirAccess::exists(data_dir_root)) { + data_dir_root = exe_dir.plus_file("data_Godot"); + } + + String data_mono_root_dir = data_dir_root.plus_file("Mono"); + data_mono_etc_dir = data_mono_root_dir.plus_file("etc"); + data_mono_lib_dir = data_mono_root_dir.plus_file("lib"); + +#ifdef OSX_ENABLED + if (!DirAccess::exists(data_mono_root_dir)) { + data_mono_etc_dir = exe_dir.plus_file("../Resources/GodotSharp/Mono/etc"); + data_mono_lib_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Mono/lib"); + } +#endif - sln_filepath = ProjectSettings::get_singleton()->globalize_path(base_path + ".sln"); - csproj_filepath = ProjectSettings::get_singleton()->globalize_path(base_path + ".csproj"); #endif } @@ -192,5 +250,26 @@ String get_project_sln_path() { String get_project_csproj_path() { return _GodotSharpDirs::get_singleton().csproj_filepath; } + +String get_data_mono_bin_dir() { + return _GodotSharpDirs::get_singleton().data_mono_bin_dir; +} + +String get_data_editor_tools_dir() { + return _GodotSharpDirs::get_singleton().data_editor_tools_dir; +} + +String get_data_editor_prebuilt_api_dir() { + return _GodotSharpDirs::get_singleton().data_editor_prebuilt_api_dir; +} #endif + +String get_data_mono_etc_dir() { + return _GodotSharpDirs::get_singleton().data_mono_etc_dir; +} + +String get_data_mono_lib_dir() { + return _GodotSharpDirs::get_singleton().data_mono_lib_dir; +} + } // namespace GodotSharpDirs diff --git a/modules/mono/godotsharp_dirs.h b/modules/mono/godotsharp_dirs.h index 3466cb271d..35b564be30 100644 --- a/modules/mono/godotsharp_dirs.h +++ b/modules/mono/godotsharp_dirs.h @@ -49,11 +49,18 @@ String get_mono_logs_dir(); #ifdef TOOLS_ENABLED String get_mono_solutions_dir(); String get_build_logs_dir(); -String get_custom_project_settings_dir(); -#endif String get_project_sln_path(); String get_project_csproj_path(); + +String get_data_mono_bin_dir(); +String get_data_editor_tools_dir(); +String get_data_editor_prebuilt_api_dir(); +#endif + +String get_data_mono_etc_dir(); +String get_data_mono_lib_dir(); + } // namespace GodotSharpDirs #endif // GODOTSHARP_DIRS_H diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index 9311aa3930..0c4433112d 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -162,50 +162,63 @@ void GDMono::initialize() { mono_trace_set_printerr_handler(gdmono_MonoPrintCallback); #endif + String assembly_rootdir; + String config_dir; + +#ifdef TOOLS_ENABLED #ifdef WINDOWS_ENABLED mono_reg_info = MonoRegUtils::find_mono(); - CharString assembly_dir; - CharString config_dir; - if (mono_reg_info.assembly_dir.length() && DirAccess::exists(mono_reg_info.assembly_dir)) { - assembly_dir = mono_reg_info.assembly_dir.utf8(); + assembly_rootdir = mono_reg_info.assembly_dir; } if (mono_reg_info.config_dir.length() && DirAccess::exists(mono_reg_info.config_dir)) { - config_dir = mono_reg_info.config_dir.utf8(); + config_dir = mono_reg_info.config_dir; } - - mono_set_dirs(assembly_dir.length() ? assembly_dir.get_data() : NULL, - config_dir.length() ? config_dir.get_data() : NULL); #elif OSX_ENABLED - mono_set_dirs(NULL, NULL); - - { - const char *assembly_rootdir = mono_assembly_getrootdir(); - const char *config_dir = mono_get_config_dir(); - - if (!assembly_rootdir || !config_dir || !DirAccess::exists(assembly_rootdir) || !DirAccess::exists(config_dir)) { - Vector<const char *> locations; - locations.push_back("/Library/Frameworks/Mono.framework/Versions/Current/"); - locations.push_back("/usr/local/var/homebrew/linked/mono/"); - - for (int i = 0; i < locations.size(); i++) { - String hint_assembly_rootdir = path_join(locations[i], "lib"); - String hint_mscorlib_path = path_join(hint_assembly_rootdir, "mono", "4.5", "mscorlib.dll"); - String hint_config_dir = path_join(locations[i], "etc"); - - if (FileAccess::exists(hint_mscorlib_path) && DirAccess::exists(hint_config_dir)) { - mono_set_dirs(hint_assembly_rootdir.utf8().get_data(), hint_config_dir.utf8().get_data()); - break; - } + const char *c_assembly_rootdir = mono_assembly_getrootdir(); + const char *c_config_dir = mono_get_config_dir(); + + if (!c_assembly_rootdir || !c_config_dir || !DirAccess::exists(c_assembly_rootdir) || !DirAccess::exists(c_config_dir)) { + Vector<const char *> locations; + locations.push_back("/Library/Frameworks/Mono.framework/Versions/Current/"); + locations.push_back("/usr/local/var/homebrew/linked/mono/"); + + for (int i = 0; i < locations.size(); i++) { + String hint_assembly_rootdir = path_join(locations[i], "lib"); + String hint_mscorlib_path = path_join(hint_assembly_rootdir, "mono", "4.5", "mscorlib.dll"); + String hint_config_dir = path_join(locations[i], "etc"); + + if (FileAccess::exists(hint_mscorlib_path) && DirAccess::exists(hint_config_dir)) { + need_set_mono_dirs = false; + assembly_rootdir = hint_assembly_rootdir; + config_dir = hint_config_dir; + break; } } } +#endif +#endif // TOOLS_ENABLED + + String bundled_assembly_rootdir = GodotSharpDirs::get_data_mono_lib_dir(); + String bundled_config_dir = GodotSharpDirs::get_data_mono_etc_dir(); + +#ifdef TOOLS_ENABLED + if (DirAccess::exists(bundled_assembly_rootdir) && DirAccess::exists(bundled_config_dir)) { + assembly_rootdir = bundled_assembly_rootdir; + config_dir = bundled_config_dir; + } #else - mono_set_dirs(NULL, NULL); + // These are always the directories in export templates + assembly_rootdir = bundled_assembly_rootdir; + config_dir = bundled_config_dir; #endif + // Leak if we call mono_set_dirs more than once + mono_set_dirs(assembly_rootdir.length() ? assembly_rootdir.utf8().get_data() : NULL, + config_dir.length() ? config_dir.utf8().get_data() : NULL); + GDMonoAssembly::initialize(); #ifdef DEBUG_ENABLED @@ -262,8 +275,11 @@ void GDMono::initialize() { // Everything is fine with the api assemblies, load the project assembly _load_project_assembly(); } else { - if ((core_api_assembly && (core_api_assembly_out_of_sync || !GDMonoUtils::mono_cache.godot_api_cache_updated)) || - (editor_api_assembly && editor_api_assembly_out_of_sync)) { + if ((core_api_assembly && (core_api_assembly_out_of_sync || !GDMonoUtils::mono_cache.godot_api_cache_updated)) +#ifdef TOOLS_ENABLED + || (editor_api_assembly && editor_api_assembly_out_of_sync) +#endif + ) { #ifdef TOOLS_ENABLED // The assembly was successfully loaded, but the full api could not be cached. // This is most likely an outdated assembly loaded because of an invalid version in the @@ -362,24 +378,34 @@ GDMonoAssembly **GDMono::get_loaded_assembly(const String &p_name) { bool GDMono::load_assembly(const String &p_name, GDMonoAssembly **r_assembly, bool p_refonly) { + return load_assembly_from(p_name, String(), r_assembly, p_refonly); +} + +bool GDMono::load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly) { + + return load_assembly_from(p_name, String(), p_aname, r_assembly, p_refonly); +} + +bool GDMono::load_assembly_from(const String &p_name, const String &p_basedir, GDMonoAssembly **r_assembly, bool p_refonly) { + CRASH_COND(!r_assembly); MonoAssemblyName *aname = mono_assembly_name_new(p_name.utf8()); - bool result = load_assembly(p_name, aname, r_assembly, p_refonly); + bool result = load_assembly_from(p_name, p_basedir, aname, r_assembly, p_refonly); mono_assembly_name_free(aname); mono_free(aname); return result; } -bool GDMono::load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly) { +bool GDMono::load_assembly_from(const String &p_name, const String &p_basedir, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly) { CRASH_COND(!r_assembly); print_verbose("Mono: Loading assembly " + p_name + (p_refonly ? " (refonly)" : "") + "..."); MonoImageOpenStatus status = MONO_IMAGE_OK; - MonoAssembly *assembly = mono_assembly_load_full(p_aname, NULL, &status, p_refonly); + MonoAssembly *assembly = mono_assembly_load_full(p_aname, p_basedir.length() ? p_basedir.utf8().get_data() : NULL, &status, p_refonly); if (!assembly) return false; @@ -480,12 +506,10 @@ bool GDMono::_load_editor_api_assembly() { if (editor_api_assembly) return true; -#ifdef TOOLS_ENABLED if (metadata_is_api_assembly_invalidated(APIAssembly::API_EDITOR)) { print_verbose("Mono: Skipping loading of Editor API assembly because it was invalidated"); return false; } -#endif bool success = load_assembly(EDITOR_API_ASSEMBLY_NAME, &editor_api_assembly); @@ -647,14 +671,18 @@ Error GDMono::_unload_scripts_domain() { print_verbose("Mono: Unloading scripts domain..."); - _GodotSharp::get_singleton()->_dispose_callback(); - if (mono_domain_get() != root_domain) mono_domain_set(root_domain, true); mono_gc_collect(mono_gc_max_generation()); - mono_domain_finalize(scripts_domain, 2000); + finalizing_scripts_domain = true; + + if (!mono_domain_finalize(scripts_domain, 2000)) { + ERR_PRINT("Mono: Domain finalization timeout"); + } + + finalizing_scripts_domain = false; mono_gc_collect(mono_gc_max_generation()); @@ -672,8 +700,6 @@ Error GDMono::_unload_scripts_domain() { MonoDomain *domain = scripts_domain; scripts_domain = NULL; - _GodotSharp::get_singleton()->_dispose_callback(); - MonoException *exc = NULL; mono_domain_try_unload(domain, (MonoObject **)&exc); @@ -772,11 +798,13 @@ Error GDMono::finalize_and_unload_domain(MonoDomain *p_domain) { print_verbose("Mono: Unloading domain `" + domain_name + "`..."); - if (mono_domain_get() != root_domain) + if (mono_domain_get() == p_domain) mono_domain_set(root_domain, true); mono_gc_collect(mono_gc_max_generation()); - mono_domain_finalize(p_domain, 2000); + if (!mono_domain_finalize(p_domain, 2000)) { + ERR_PRINT("Mono: Domain finalization timeout"); + } mono_gc_collect(mono_gc_max_generation()); _domain_assemblies_cleanup(mono_domain_get_id(p_domain)); @@ -851,6 +879,7 @@ GDMono::GDMono() { gdmono_log = memnew(GDMonoLog); runtime_initialized = false; + finalizing_scripts_domain = false; root_domain = NULL; scripts_domain = NULL; @@ -917,29 +946,6 @@ GDMono::~GDMono() { _GodotSharp *_GodotSharp::singleton = NULL; -void _GodotSharp::_dispose_callback() { - -#ifndef NO_THREADS - queue_mutex->lock(); -#endif - - for (List<NodePath *>::Element *E = np_delete_queue.front(); E; E = E->next()) { - memdelete(E->get()); - } - - for (List<RID *>::Element *E = rid_delete_queue.front(); E; E = E->next()) { - memdelete(E->get()); - } - - np_delete_queue.clear(); - rid_delete_queue.clear(); - queue_empty = true; - -#ifndef NO_THREADS - queue_mutex->unlock(); -#endif -} - void _GodotSharp::attach_thread() { GDMonoUtils::attach_current_thread(); @@ -988,6 +994,8 @@ bool _GodotSharp::is_domain_finalizing_for_unload(MonoDomain *p_domain) { if (!p_domain) return true; + if (p_domain == SCRIPTS_DOMAIN && GDMono::get_singleton()->is_finalizing_scripts_domain()) + return true; return mono_domain_is_unloading(p_domain); } @@ -1001,49 +1009,6 @@ bool _GodotSharp::is_runtime_initialized() { return GDMono::get_singleton()->is_runtime_initialized(); } -#define ENQUEUE_FOR_DISPOSAL(m_queue, m_inst) \ - m_queue.push_back(m_inst); \ - if (queue_empty) { \ - queue_empty = false; \ - if (!is_domain_finalizing_for_unload(SCRIPTS_DOMAIN)) { /* call_deferred may not be safe here */ \ - call_deferred("_dispose_callback"); \ - } \ - } - -void _GodotSharp::queue_dispose(NodePath *p_node_path) { - - if (GDMonoUtils::is_main_thread() && !is_domain_finalizing_for_unload(SCRIPTS_DOMAIN)) { - memdelete(p_node_path); - } else { -#ifndef NO_THREADS - queue_mutex->lock(); -#endif - - ENQUEUE_FOR_DISPOSAL(np_delete_queue, p_node_path); - -#ifndef NO_THREADS - queue_mutex->unlock(); -#endif - } -} - -void _GodotSharp::queue_dispose(RID *p_rid) { - - if (GDMonoUtils::is_main_thread() && !is_domain_finalizing_for_unload(SCRIPTS_DOMAIN)) { - memdelete(p_rid); - } else { -#ifndef NO_THREADS - queue_mutex->lock(); -#endif - - ENQUEUE_FOR_DISPOSAL(rid_delete_queue, p_rid); - -#ifndef NO_THREADS - queue_mutex->unlock(); -#endif - } -} - void _GodotSharp::_bind_methods() { ClassDB::bind_method(D_METHOD("attach_thread"), &_GodotSharp::attach_thread); @@ -1056,8 +1021,6 @@ void _GodotSharp::_bind_methods() { ClassDB::bind_method(D_METHOD("is_runtime_shutting_down"), &_GodotSharp::is_runtime_shutting_down); ClassDB::bind_method(D_METHOD("is_runtime_initialized"), &_GodotSharp::is_runtime_initialized); - - ClassDB::bind_method(D_METHOD("_dispose_callback"), &_GodotSharp::_dispose_callback); } _GodotSharp::_GodotSharp() { diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h index 0c5503d28e..745dcc34eb 100644 --- a/modules/mono/mono_gd/gd_mono.h +++ b/modules/mono/mono_gd/gd_mono.h @@ -142,7 +142,7 @@ class GDMono { GDMonoLog *gdmono_log; -#ifdef WINDOWS_ENABLED +#if defined(WINDOWS_ENABLED) && defined(TOOLS_ENABLED) MonoRegInfo mono_reg_info; #endif @@ -172,6 +172,8 @@ public: _FORCE_INLINE_ bool is_runtime_initialized() const { return runtime_initialized && !mono_runtime_is_shutting_down() /* stays true after shutdown finished */; } + _FORCE_INLINE_ bool is_finalizing_scripts_domain() { return finalizing_scripts_domain; } + _FORCE_INLINE_ MonoDomain *get_scripts_domain() { return scripts_domain; } #ifdef TOOLS_ENABLED _FORCE_INLINE_ MonoDomain *get_tools_domain() { return tools_domain; } @@ -185,7 +187,7 @@ public: _FORCE_INLINE_ GDMonoAssembly *get_editor_tools_assembly() const { return editor_tools_assembly; } #endif -#ifdef WINDOWS_ENABLED +#if defined(WINDOWS_ENABLED) && defined(TOOLS_ENABLED) const MonoRegInfo &get_mono_reg_info() { return mono_reg_info; } #endif @@ -197,6 +199,9 @@ public: bool load_assembly(const String &p_name, GDMonoAssembly **r_assembly, bool p_refonly = false); bool load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly = false); + bool load_assembly_from(const String &p_name, const String &p_basedir, GDMonoAssembly **r_assembly, bool p_refonly = false); + bool load_assembly_from(const String &p_name, const String &p_basedir, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly = false); + Error finalize_and_unload_domain(MonoDomain *p_domain); void initialize(); @@ -205,12 +210,14 @@ public: ~GDMono(); }; -class GDMonoScopeDomain { +namespace gdmono { + +class ScopeDomain { MonoDomain *prev_domain; public: - GDMonoScopeDomain(MonoDomain *p_domain) { + ScopeDomain(MonoDomain *p_domain) { MonoDomain *prev_domain = mono_domain_get(); if (prev_domain != p_domain) { this->prev_domain = prev_domain; @@ -220,23 +227,41 @@ public: } } - ~GDMonoScopeDomain() { + ~ScopeDomain() { if (prev_domain) mono_domain_set(prev_domain, false); } }; -#define _GDMONO_SCOPE_DOMAIN_(m_mono_domain) \ - GDMonoScopeDomain __gdmono__scope__domain__(m_mono_domain); \ +class ScopeExitDomainUnload { + MonoDomain *domain; + +public: + ScopeExitDomainUnload(MonoDomain *p_domain) : + domain(p_domain) { + } + + ~ScopeExitDomainUnload() { + if (domain) + GDMono::get_singleton()->finalize_and_unload_domain(domain); + } +}; + +} // namespace gdmono + +#define _GDMONO_SCOPE_DOMAIN_(m_mono_domain) \ + gdmono::ScopeDomain __gdmono__scope__domain__(m_mono_domain); \ (void)__gdmono__scope__domain__; +#define _GDMONO_SCOPE_EXIT_DOMAIN_UNLOAD_(m_mono_domain) \ + gdmono::ScopeExitDomainUnload __gdmono__scope__exit__domain__unload__(m_mono_domain); \ + (void)__gdmono__scope__exit__domain__unload__; + class _GodotSharp : public Object { GDCLASS(_GodotSharp, Object) friend class GDMono; - void _dispose_callback(); - bool _is_domain_finalizing_for_unload(int32_t p_domain_id); List<NodePath *> np_delete_queue; @@ -270,9 +295,6 @@ public: bool is_runtime_shutting_down(); bool is_runtime_initialized(); - void queue_dispose(NodePath *p_node_path); - void queue_dispose(RID *p_rid); - _GodotSharp(); ~_GodotSharp(); }; diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp index 27ce39b6d7..1067c11e0e 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.cpp +++ b/modules/mono/mono_gd/gd_mono_assembly.cpp @@ -46,6 +46,29 @@ bool GDMonoAssembly::in_preload = false; Vector<String> GDMonoAssembly::search_dirs; +void GDMonoAssembly::fill_search_dirs(Vector<String> &r_search_dirs, const String &p_custom_config) { + + const char *rootdir = mono_assembly_getrootdir(); + if (rootdir) { + String framework_dir = String(rootdir).plus_file("mono").plus_file("4.5"); + r_search_dirs.push_back(framework_dir); + r_search_dirs.push_back(framework_dir.plus_file("Facades")); + } + + if (p_custom_config.length()) { + r_search_dirs.push_back(GodotSharpDirs::get_res_temp_assemblies_base_dir().plus_file(p_custom_config)); + } else { + r_search_dirs.push_back(GodotSharpDirs::get_res_temp_assemblies_dir()); + } + + r_search_dirs.push_back(GodotSharpDirs::get_res_assemblies_dir()); + r_search_dirs.push_back(OS::get_singleton()->get_resource_dir()); + r_search_dirs.push_back(OS::get_singleton()->get_executable_path().get_base_dir()); +#ifdef TOOLS_ENABLED + r_search_dirs.push_back(GodotSharpDirs::get_data_editor_tools_dir()); +#endif +} + void GDMonoAssembly::assembly_load_hook(MonoAssembly *assembly, void *user_data) { if (no_search) @@ -93,35 +116,7 @@ MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_d no_search = true; // Avoid the recursion madness - String path; - GDMonoAssembly *res = NULL; - - for (int i = 0; i < search_dirs.size(); i++) { - const String &search_dir = search_dirs[i]; - - if (has_extension) { - path = search_dir.plus_file(name); - if (FileAccess::exists(path)) { - res = _load_assembly_from(name.get_basename(), path, refonly); - if (res != NULL) - break; - } - } else { - path = search_dir.plus_file(name + ".dll"); - if (FileAccess::exists(path)) { - res = _load_assembly_from(name, path, refonly); - if (res != NULL) - break; - } - - path = search_dir.plus_file(name + ".exe"); - if (FileAccess::exists(path)) { - res = _load_assembly_from(name, path, refonly); - if (res != NULL) - break; - } - } - } + GDMonoAssembly *res = _load_assembly_search(name, search_dirs, refonly); no_search = false; @@ -130,31 +125,12 @@ MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_d static _THREAD_LOCAL_(MonoImage *) image_corlib_loading = NULL; -MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data, bool refonly) { +MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **, void *user_data, bool refonly) { (void)user_data; // UNUSED if (search_dirs.empty()) { - search_dirs.push_back(GodotSharpDirs::get_res_temp_assemblies_dir()); - search_dirs.push_back(GodotSharpDirs::get_res_assemblies_dir()); - search_dirs.push_back(OS::get_singleton()->get_resource_dir()); - search_dirs.push_back(OS::get_singleton()->get_executable_path().get_base_dir()); -#ifdef GD_MONO_EDITOR_ASSEMBLIES_DIR - search_dirs.push_back(OS::get_singleton()->get_executable_path().get_base_dir().plus_file(_MKSTR(GD_MONO_EDITOR_ASSEMBLIES_DIR)).simplify_path()); -#endif - - const char *rootdir = mono_assembly_getrootdir(); - if (rootdir) { - search_dirs.push_back(String(rootdir).plus_file("mono").plus_file("4.5")); - search_dirs.push_back(String(rootdir).plus_file("mono").plus_file("4.5").plus_file("Facades")); - } - - if (assemblies_path) { - while (*assemblies_path) { - search_dirs.push_back(*assemblies_path); - ++assemblies_path; - } - } + fill_search_dirs(search_dirs); } { @@ -188,27 +164,7 @@ MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **asse if (stored_assembly) return (*stored_assembly)->get_assembly(); - String path; - - for (int i = 0; i < search_dirs.size(); i++) { - const String &search_dir = search_dirs[i]; - - if (has_extension) { - path = search_dir.plus_file(name); - if (FileAccess::exists(path)) { - res = _load_assembly_from(name.get_basename(), path, refonly); - if (res != NULL) - break; - } - } else { - path = search_dir.plus_file(name + ".dll"); - if (FileAccess::exists(path)) { - res = _load_assembly_from(name, path, refonly); - if (res != NULL) - break; - } - } - } + res = _load_assembly_search("mscorlib.dll", search_dirs, refonly); } no_search = false; @@ -217,6 +173,43 @@ MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **asse return res ? res->get_assembly() : NULL; } +GDMonoAssembly *GDMonoAssembly::_load_assembly_search(const String &p_name, const Vector<String> &p_search_dirs, bool p_refonly) { + + GDMonoAssembly *res = NULL; + String path; + + bool has_extension = p_name.ends_with(".dll") || p_name.ends_with(".exe"); + + for (int i = 0; i < p_search_dirs.size(); i++) { + const String &search_dir = p_search_dirs[i]; + + if (has_extension) { + path = search_dir.plus_file(p_name); + if (FileAccess::exists(path)) { + res = _load_assembly_from(p_name.get_basename(), path, p_refonly); + if (res != NULL) + return res; + } + } else { + path = search_dir.plus_file(p_name + ".dll"); + if (FileAccess::exists(path)) { + res = _load_assembly_from(p_name, path, p_refonly); + if (res != NULL) + return res; + } + + path = search_dir.plus_file(p_name + ".exe"); + if (FileAccess::exists(path)) { + res = _load_assembly_from(p_name, path, p_refonly); + if (res != NULL) + return res; + } + } + } + + return NULL; +} + GDMonoAssembly *GDMonoAssembly::_load_assembly_from(const String &p_name, const String &p_path, bool p_refonly) { GDMonoAssembly *assembly = memnew(GDMonoAssembly(p_name, p_path)); @@ -464,19 +457,6 @@ GDMonoClass *GDMonoAssembly::get_object_derived_class(const StringName &p_class) return match; } -GDMonoAssembly *GDMonoAssembly::load_from(const String &p_name, const String &p_path, bool p_refonly) { - - GDMonoAssembly **loaded_asm = GDMono::get_singleton()->get_loaded_assembly(p_name); - if (loaded_asm) - return *loaded_asm; - - no_search = true; - GDMonoAssembly *res = _load_assembly_from(p_name, p_path, p_refonly); - no_search = false; - - return res; -} - GDMonoAssembly::GDMonoAssembly(const String &p_name, const String &p_path) { loaded = false; diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h index 0ba11ac412..4c9b1cb10d 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.h +++ b/modules/mono/mono_gd/gd_mono_assembly.h @@ -102,6 +102,7 @@ class GDMonoAssembly { static MonoAssembly *_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data, bool refonly); static GDMonoAssembly *_load_assembly_from(const String &p_name, const String &p_path, bool p_refonly); + static GDMonoAssembly *_load_assembly_search(const String &p_name, const Vector<String> &p_search_dirs, bool p_refonly); static void _wrap_mono_assembly(MonoAssembly *assembly); friend class GDMono; @@ -125,7 +126,7 @@ public: GDMonoClass *get_object_derived_class(const StringName &p_class); - static GDMonoAssembly *load_from(const String &p_name, const String &p_path, bool p_refonly); + static void fill_search_dirs(Vector<String> &r_search_dirs, const String &p_custom_config = String()); GDMonoAssembly(const String &p_name, const String &p_path = String()); ~GDMonoAssembly(); diff --git a/modules/opensimplex/doc_classes/NoiseTexture.xml b/modules/opensimplex/doc_classes/NoiseTexture.xml index 9642865c43..d88abb3180 100644 --- a/modules/opensimplex/doc_classes/NoiseTexture.xml +++ b/modules/opensimplex/doc_classes/NoiseTexture.xml @@ -12,24 +12,6 @@ <demos> </demos> <methods> - <method name="set_height"> - <return type="void"> - </return> - <argument index="0" name="height" type="int"> - </argument> - <description> - Set texture height. - </description> - </method> - <method name="set_width"> - <return type="void"> - </return> - <argument index="0" name="width" type="int"> - </argument> - <description> - Set texture width. - </description> - </method> </methods> <members> <member name="as_normalmap" type="bool" setter="set_as_normalmap" getter="is_normalmap"> diff --git a/modules/thekla_unwrap/config.py b/modules/thekla_unwrap/config.py index bd092bdc16..fad6095064 100644 --- a/modules/thekla_unwrap/config.py +++ b/modules/thekla_unwrap/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): - return (env['tools'] and platform not in ["android", "ios"]) + #return (env['tools'] and platform not in ["android", "ios"]) + return False def configure(env): pass diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp index d72d74cf79..2a6bb0783b 100644 --- a/modules/theora/video_stream_theora.cpp +++ b/modules/theora/video_stream_theora.cpp @@ -730,7 +730,6 @@ RES ResourceFormatLoaderTheora::load(const String &p_path, const String &p_origi if (r_error) { *r_error = ERR_CANT_OPEN; } - memdelete(f); return RES(); } diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index ff97c21fd9..52a30baaec 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -48,20 +48,22 @@ bool VisualScriptNode::is_breakpoint() const { void VisualScriptNode::_notification(int p_what) { if (p_what == NOTIFICATION_POSTINITIALIZE) { - - int dvc = get_input_value_port_count(); - for (int i = 0; i < dvc; i++) { - Variant::Type expected = get_input_value_port_info(i).type; - Variant::CallError ce; - default_input_values.push_back(Variant::construct(expected, NULL, 0, ce, false)); - } + _update_input_ports(); } } -void VisualScriptNode::ports_changed_notify() { - +void VisualScriptNode::_update_input_ports() { default_input_values.resize(MAX(default_input_values.size(), get_input_value_port_count())); //let it grow as big as possible, we don't want to lose values on resize + int port_count = get_input_value_port_count(); + for (int i = 0; i < port_count; i++) { + Variant::Type expected = get_input_value_port_info(i).type; + Variant::CallError ce; + set_default_input_value(i, Variant::construct(expected, NULL, 0, ce, false)); + } +} +void VisualScriptNode::ports_changed_notify() { + _update_input_ports(); emit_signal("ports_changed"); } diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h index ea99ce4970..bd666447a3 100644 --- a/modules/visual_script/visual_script.h +++ b/modules/visual_script/visual_script.h @@ -52,6 +52,7 @@ class VisualScriptNode : public Resource { Array _get_default_input_values() const; void validate_input_default_values(); + void _update_input_ports(); protected: void _notification(int p_what); diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 79f71535ad..7fdd7fe446 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -1940,7 +1940,7 @@ void VisualScriptEditor::_draw_color_over_button(Object *obj, Color p_color) { button->draw_rect(Rect2(normal->get_offset(), button->get_size() - normal->get_minimum_size()), p_color); } -void VisualScriptEditor::_button_resource_previewed(const String &p_path, const Ref<Texture> &p_preview, Variant p_ud) { +void VisualScriptEditor::_button_resource_previewed(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, Variant p_ud) { Array ud = p_ud; ERR_FAIL_COND(ud.size() != 2); @@ -2639,7 +2639,7 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri } undo_redo->create_action(TTR("Add Node")); undo_redo->add_do_method(script.ptr(), "add_node", edited_func, new_id, vnode_new, ofs); - if (vnode_old.is_valid() && p_connecting == true) { + if (vnode_old.is_valid() && p_connecting) { connect_seq(vnode_old, vnode_new, new_id); connect_data(vnode_old, vnode_new, new_id); } @@ -2806,7 +2806,7 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri } } Ref<VisualScriptNode> vnode_old = script->get_node(edited_func, port_action_node); - if (vnode_old.is_valid() && p_connecting == true) { + if (vnode_old.is_valid() && p_connecting) { connect_seq(vnode_old, vnode, port_action_new_node); connect_data(vnode_old, vnode, port_action_new_node); } @@ -2816,7 +2816,7 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri void VisualScriptEditor::connect_seq(Ref<VisualScriptNode> vnode_old, Ref<VisualScriptNode> vnode_new, int new_id) { VisualScriptOperator *vnode_operator = Object::cast_to<VisualScriptOperator>(vnode_new.ptr()); - if (vnode_operator != NULL && vnode_operator->has_input_sequence_port() == false) { + if (vnode_operator != NULL && !vnode_operator->has_input_sequence_port()) { return; } VisualScriptConstructor *vnode_constructor = Object::cast_to<VisualScriptConstructor>(vnode_new.ptr()); @@ -2826,7 +2826,7 @@ void VisualScriptEditor::connect_seq(Ref<VisualScriptNode> vnode_old, Ref<Visual if (vnode_old->get_output_sequence_port_count() <= 0) { return; } - if (vnode_new->has_input_sequence_port() == false) { + if (!vnode_new->has_input_sequence_port()) { return; } diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h index fb90e346a4..97c75dae94 100644 --- a/modules/visual_script/visual_script_editor.h +++ b/modules/visual_script/visual_script_editor.h @@ -237,7 +237,7 @@ class VisualScriptEditor : public ScriptEditorBase { void _selected_method(const String &p_method, const String &p_type); void _draw_color_over_button(Object *obj, Color p_color); - void _button_resource_previewed(const String &p_path, const Ref<Texture> &p_preview, Variant p_ud); + void _button_resource_previewed(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, Variant p_ud); VisualScriptNode::TypeGuess _guess_output_type(int p_port_action_node, int p_port_action_output, Set<int> &visited_nodes); diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index 5c880f48d1..99748af8a1 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -853,7 +853,7 @@ public: virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Variant::CallError &r_error, String &r_error_str) { - if (instance->get_variable(variable, p_outputs[0]) == false) { + if (!instance->get_variable(variable, p_outputs[0])) { r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; r_error_str = RTR("VariableGet not found in script: ") + "'" + String(variable) + "'"; return false; @@ -975,7 +975,7 @@ public: virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Variant::CallError &r_error, String &r_error_str) { - if (instance->set_variable(variable, *p_inputs[0]) == false) { + if (!instance->set_variable(variable, *p_inputs[0])) { r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; r_error_str = RTR("VariableSet not found in script: ") + "'" + String(variable) + "'"; @@ -3708,18 +3708,18 @@ void register_visual_script_nodes() { for (List<MethodInfo>::Element *E = constructors.front(); E; E = E->next()) { if (E->get().arguments.size() > 0) { - - String name = "functions/constructors/" + Variant::get_type_name(Variant::Type(i)) + " ( "; + String name = "functions/constructors/" + Variant::get_type_name(Variant::Type(i)) + "("; for (int j = 0; j < E->get().arguments.size(); j++) { - if (j > 0) + if (j > 0) { name += ", "; - if (E->get().arguments.size() == 1) + } + if (E->get().arguments.size() == 1) { name += Variant::get_type_name(E->get().arguments[j].type); - else + } else { name += E->get().arguments[j].name; + } } - name += ") "; - + name += ")"; VisualScriptLanguage::singleton->add_register_func(name, create_constructor_node); Pair<Variant::Type, MethodInfo> pair; pair.first = Variant::Type(i); diff --git a/modules/visual_script/visual_script_property_selector.cpp b/modules/visual_script/visual_script_property_selector.cpp index cd29df9855..e5d12cb495 100644 --- a/modules/visual_script/visual_script_property_selector.cpp +++ b/modules/visual_script/visual_script_property_selector.cpp @@ -149,7 +149,7 @@ void VisualScriptPropertySelector::_update_search() { Control::get_icon("PoolColorArray", "EditorIcons") }; - if (!seq_connect && visual_script_generic == false) { + if (!seq_connect && !visual_script_generic) { get_visual_node_names("flow_control/type_cast", Set<String>(), found, root, search_box); get_visual_node_names("functions/built_in/print", Set<String>(), found, root, search_box); get_visual_node_names("functions/by_type/" + Variant::get_type_name(type), Set<String>(), found, root, search_box); @@ -228,7 +228,7 @@ void VisualScriptPropertySelector::_update_search() { } } - if (seq_connect == true && visual_script_generic == false) { + if (seq_connect && !visual_script_generic) { String text = search_box->get_text(); create_visualscript_item(String("VisualScriptCondition"), root, text, String("Condition")); create_visualscript_item(String("VisualScriptSwitch"), root, text, String("Switch")); @@ -304,31 +304,36 @@ void VisualScriptPropertySelector::_update_search() { continue; MethodInfo mi = E->get(); - String desc = mi.name.capitalize() + " ("; + String desc_arguments; + if (mi.arguments.size() > 0) { + desc_arguments = "("; + for (int i = 0; i < mi.arguments.size(); i++) { + + if (i > 0) { + desc_arguments += ", "; + } + if (mi.arguments[i].type == Variant::NIL) { + desc_arguments += "var"; + } else if (mi.arguments[i].name.find(":") != -1) { + desc_arguments += mi.arguments[i].name.get_slice(":", 1); + mi.arguments[i].name = mi.arguments[i].name.get_slice(":", 0); + } else { + desc_arguments += Variant::get_type_name(mi.arguments[i].type); + } + } + desc_arguments += ")"; + } + String desc_raw = mi.name + desc_arguments; + String desc = desc_raw.capitalize().replace("( ", "("); if (search_box->get_text() != String() && name.findn(search_box->get_text()) == -1 && - desc.findn(search_box->get_text()) == -1) + desc.findn(search_box->get_text()) == -1 && + desc_raw.findn(search_box->get_text()) == -1) { continue; - - TreeItem *item = search_options->create_item(category ? category : root); - - for (int i = 0; i < mi.arguments.size(); i++) { - - if (i > 0) - desc += ", "; - - if (mi.arguments[i].type == Variant::NIL) - desc += "var"; - else if (mi.arguments[i].name.find(":") != -1) { - desc += mi.arguments[i].name.get_slice(":", 1); - mi.arguments[i].name = mi.arguments[i].name.get_slice(":", 0); - } else - desc += Variant::get_type_name(mi.arguments[i].type); } - desc += ")"; - + TreeItem *item = search_options->create_item(category ? category : root); item->set_text(0, desc); item->set_icon(0, get_icon("MemberMethod", "EditorIcons")); item->set_metadata(0, name); @@ -392,7 +397,7 @@ void VisualScriptPropertySelector::get_visual_node_names(const String &root_filt break; } } - if (is_filter == true) { + if (is_filter) { continue; } @@ -414,11 +419,16 @@ void VisualScriptPropertySelector::get_visual_node_names(const String &root_filt String basic_type = Variant::get_type_name(vnode_function_call->get_basic_type()); type_name = basic_type.capitalize() + " "; } - VisualScriptBuiltinFunc *vnode_builtin_function_call = Object::cast_to<VisualScriptBuiltinFunc>(*VisualScriptLanguage::singleton->create_node_from_name(E->get())); - if (vnode_builtin_function_call != NULL) { - type_name = "Builtin "; + + Vector<String> desc = path[path.size() - 1].replace("(", "( ").replace(")", " )").replace(",", ", ").split(" "); + for (size_t i = 0; i < desc.size(); i++) { + desc.write[i] = desc[i].capitalize(); + if (desc[i].ends_with(",")) { + desc.write[i] = desc[i].replace(",", ", "); + } } - item->set_text(0, type_name + path[path.size() - 1].capitalize()); + + item->set_text(0, type_name + String("").join(desc)); item->set_icon(0, get_icon("VisualScript", "EditorIcons")); item->set_selectable(0, true); item->set_metadata(0, E->get()); diff --git a/modules/webm/video_stream_webm.cpp b/modules/webm/video_stream_webm.cpp index d9a6ece085..675fc97b55 100644 --- a/modules/webm/video_stream_webm.cpp +++ b/modules/webm/video_stream_webm.cpp @@ -453,7 +453,6 @@ RES ResourceFormatLoaderWebm::load(const String &p_path, const String &p_origina if (r_error) { *r_error = ERR_CANT_OPEN; } - memdelete(f); return RES(); } diff --git a/modules/websocket/lws_client.cpp b/modules/websocket/lws_client.cpp index cd814760e6..b3e5f6ffab 100644 --- a/modules/websocket/lws_client.cpp +++ b/modules/websocket/lws_client.cpp @@ -80,9 +80,12 @@ Error LWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port, char hbuf[1024]; char pbuf[2048]; String addr_str = (String)addr; - strncpy(abuf, addr_str.ascii().get_data(), 1024); - strncpy(hbuf, p_host.utf8().get_data(), 1024); - strncpy(pbuf, p_path.utf8().get_data(), 2048); + strncpy(abuf, addr_str.ascii().get_data(), 1023); + abuf[1023] = '\0'; + strncpy(hbuf, p_host.utf8().get_data(), 1023); + hbuf[1023] = '\0'; + strncpy(pbuf, p_path.utf8().get_data(), 2047); + pbuf[2047] = '\0'; i.context = context; if (p_protocols.size() > 0) diff --git a/modules/xatlas_unwrap/config.py b/modules/xatlas_unwrap/config.py index 962d33280f..2dda5db7e0 100644 --- a/modules/xatlas_unwrap/config.py +++ b/modules/xatlas_unwrap/config.py @@ -1,6 +1,6 @@ def can_build(env, platform): - return False #xatlas is buggy - #return (env['tools'] and platform not in ["android", "ios"]) + #return False #xatlas is buggy + return (env['tools'] and platform not in ["android", "ios"]) def configure(env): pass diff --git a/modules/xatlas_unwrap/register_types.cpp b/modules/xatlas_unwrap/register_types.cpp index 9df16aac70..57eea4eda6 100644 --- a/modules/xatlas_unwrap/register_types.cpp +++ b/modules/xatlas_unwrap/register_types.cpp @@ -75,8 +75,9 @@ bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_ver xatlas::CharterOptions chart_options; xatlas::PackerOptions pack_options; + pack_options.method = xatlas::PackMethod::TexelArea; pack_options.texelArea = 1.0 / p_texel_size; - pack_options.quality = 4; + pack_options.quality = 3; xatlas::Atlas *atlas = xatlas::Create(); printf("adding mesh..\n"); @@ -93,7 +94,10 @@ bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_ver float w = *r_size_hint_x; float h = *r_size_hint_y; - printf("final texsize: %f,%f\n", w, h); + if (w == 0 || h == 0) { + return false; //could not bake + } + const xatlas::OutputMesh *const *output_meshes = xatlas::GetOutputMeshes(atlas); const xatlas::OutputMesh *output = output_meshes[0]; @@ -102,11 +106,17 @@ bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_ver *r_uv = (float *)malloc(sizeof(float) * output->vertexCount * 2); *r_index = (int *)malloc(sizeof(int) * output->indexCount); + float max_x = 0; + float max_y = 0; for (int i = 0; i < output->vertexCount; i++) { (*r_vertex)[i] = output->vertexArray[i].xref; - (*r_uv)[i * 2 + 0] = output->vertexArray[i].uv[0]; - (*r_uv)[i * 2 + 1] = output->vertexArray[i].uv[1]; + (*r_uv)[i * 2 + 0] = output->vertexArray[i].uv[0] / w; + (*r_uv)[i * 2 + 1] = output->vertexArray[i].uv[1] / h; + max_x = MAX(max_x, output->vertexArray[i].uv[0]); + max_y = MAX(max_y, output->vertexArray[i].uv[1]); } + + printf("final texsize: %f,%f - max %f,%f\n", w, h, max_x, max_y); *r_vertex_count = output->vertexCount; for (int i = 0; i < output->indexCount; i++) { diff --git a/platform/android/build.gradle.template b/platform/android/build.gradle.template index cc45fee95f..1603ea70d9 100644 --- a/platform/android/build.gradle.template +++ b/platform/android/build.gradle.template @@ -1,10 +1,11 @@ buildscript { repositories { + google() jcenter() $$GRADLE_REPOSITORY_URLS$$ } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.2.0' $$GRADLE_CLASSPATH$$ } } @@ -32,7 +33,7 @@ android { } compileSdkVersion 27 - buildToolsVersion "27.0.3" + buildToolsVersion "28.0.3" useLibrary 'org.apache.http.legacy' packagingOptions { @@ -75,9 +76,11 @@ android { $$GRADLE_JNI_DIRS$$ ] } + applicationVariants.all { variant -> - // ApplicationVariant is undocumented, but this method is widely used; may break with another version of the Android Gradle plugin - variant.outputs.get(0).setOutputFile(new File("${projectDir}/../../../bin", "android_${variant.name}.apk")) + variant.outputs.all { output -> + output.outputFileName = "../../../../../../../bin/android_${variant.name}.apk" + } } } diff --git a/platform/android/godot_android.cpp b/platform/android/godot_android.cpp index 54692dc831..c46c6f7804 100644 --- a/platform/android/godot_android.cpp +++ b/platform/android/godot_android.cpp @@ -408,7 +408,7 @@ static void engine_draw_frame(struct engine *engine) { // Just fill the screen with a color. //glClearColor(0,1,0,1); //glClear(GL_COLOR_BUFFER_BIT); - if (engine->os && engine->os->main_loop_iterate() == true) { + if (engine->os && engine->os->main_loop_iterate()) { engine->requested_quit = true; return; //should exit instead diff --git a/platform/android/java/gradle/wrapper/gradle-wrapper.properties b/platform/android/java/gradle/wrapper/gradle-wrapper.properties index fe37fa74a9..6fb3a79546 100644 --- a/platform/android/java/gradle/wrapper/gradle-wrapper.properties +++ b/platform/android/java/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp index c3be3a3f11..07e4048c12 100644 --- a/platform/android/java_glue.cpp +++ b/platform/android/java_glue.cpp @@ -883,6 +883,8 @@ static void _initialize_java_modules() { ERR_EXPLAIN("Couldn't find proper initialize function 'public static Godot.SingletonBase Class::initialize(Activity p_activity)' initializer for singleton class: " + m); ERR_CONTINUE(!initialize); } + jobject obj = env->CallStaticObjectMethod(singletonClass, initialize, _godot_instance); + env->NewGlobalRef(obj); } } } @@ -974,7 +976,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, job os_android->process_gyroscope(gyroscope); - if (os_android->main_loop_iterate() == true) { + if (os_android->main_loop_iterate()) { jclass cls = env->FindClass("org/godotengine/godot/Godot"); jmethodID _finish = env->GetMethodID(cls, "forceQuit", "()V"); diff --git a/platform/haiku/haiku_direct_window.cpp b/platform/haiku/haiku_direct_window.cpp index 150e90be65..6b64082250 100644 --- a/platform/haiku/haiku_direct_window.cpp +++ b/platform/haiku/haiku_direct_window.cpp @@ -86,7 +86,7 @@ void HaikuDirectWindow::DirectConnected(direct_buffer_info *info) { void HaikuDirectWindow::MessageReceived(BMessage *message) { switch (message->what) { case REDRAW_MSG: - if (Main::iteration() == true) { + if (Main::iteration()) { view->EnableDirectMode(false); Quit(); } diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 1c693c9ea8..6ab433203f 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -1859,28 +1859,30 @@ bool OS_OSX::can_draw() const { void OS_OSX::set_clipboard(const String &p_text) { - NSArray *types = [NSArray arrayWithObjects:NSStringPboardType, nil]; + NSString *copiedString = [NSString stringWithUTF8String:p_text.utf8().get_data()]; + NSArray *copiedStringArray = [NSArray arrayWithObject:copiedString]; NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; - [pasteboard declareTypes:types owner:nil]; - [pasteboard setString:[NSString stringWithUTF8String:p_text.utf8().get_data()] - forType:NSStringPboardType]; + [pasteboard clearContents]; + [pasteboard writeObjects:copiedStringArray]; } String OS_OSX::get_clipboard() const { NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + NSArray *classArray = [NSArray arrayWithObject:[NSString class]]; + NSDictionary *options = [NSDictionary dictionary]; - if (![[pasteboard types] containsObject:NSStringPboardType]) { - return ""; - } + BOOL ok = [pasteboard canReadObjectForClasses:classArray options:options]; - NSString *object = [pasteboard stringForType:NSStringPboardType]; - if (!object) { + if (!ok) { return ""; } - char *utfs = strdup([object UTF8String]); + NSArray *objectsToPaste = [pasteboard readObjectsForClasses:classArray options:options]; + NSString *string = [objectsToPaste objectAtIndex:0]; + + char *utfs = strdup([string UTF8String]); String ret; ret.parse_utf8(utfs); free(utfs); diff --git a/platform/server/os_server.cpp b/platform/server/os_server.cpp index 1069d6bbed..6a7038e946 100644 --- a/platform/server/os_server.cpp +++ b/platform/server/os_server.cpp @@ -221,7 +221,7 @@ void OS_Server::run() { while (!force_quit) { - if (Main::iteration() == true) + if (Main::iteration()) break; }; diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index f489c0894f..6410378593 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -864,7 +864,7 @@ void OSUWP::run() { CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); if (managed_object->alert_close_handle) continue; process_events(); // get rid of pending events - if (Main::iteration() == true) + if (Main::iteration()) break; }; diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index e8c209c0fc..739fcbacda 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -1744,7 +1744,7 @@ void OS_Windows::set_window_size(const Size2 p_size) { RECT rect; GetWindowRect(hWnd, &rect); - if (video_mode.borderless_window == false) { + if (!video_mode.borderless_window) { RECT crect; GetClientRect(hWnd, &crect); @@ -2737,7 +2737,7 @@ void OS_Windows::run() { while (!force_quit) { process_events(); // get rid of pending events - if (Main::iteration() == true) + if (Main::iteration()) break; }; diff --git a/platform/x11/godot_x11.cpp b/platform/x11/godot_x11.cpp index 3241cbcbf9..21148f8e86 100644 --- a/platform/x11/godot_x11.cpp +++ b/platform/x11/godot_x11.cpp @@ -43,7 +43,7 @@ int main(int argc, char *argv[]) { setlocale(LC_CTYPE, ""); char *cwd = (char *)malloc(PATH_MAX); - getcwd(cwd, PATH_MAX); + char *ret = getcwd(cwd, PATH_MAX); Error err = Main::setup(argv[0], argc - 1, &argv[1]); if (err != OK) { @@ -55,7 +55,8 @@ int main(int argc, char *argv[]) { os.run(); // it is actually the OS that decides how to run Main::cleanup(); - chdir(cwd); + if (ret) + chdir(cwd); free(cwd); return os.get_exit_code(); diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 5be0b9304a..7c4c8f0eff 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -1096,7 +1096,7 @@ void OS_X11::set_window_size(const Size2 p_size) { int old_h = xwa.height; // If window resizable is disabled we need to update the attributes first - if (is_window_resizable() == false) { + if (!is_window_resizable()) { XSizeHints *xsh; xsh = XAllocSizeHints(); xsh->flags = PMinSize | PMaxSize; @@ -1688,7 +1688,7 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { } } else { //ignore - if (last_is_pressed == false) { + if (!last_is_pressed) { return; } } @@ -2814,7 +2814,7 @@ void OS_X11::run() { #ifdef JOYDEV_ENABLED joypad->process_joypads(); #endif - if (Main::iteration() == true) + if (Main::iteration()) break; }; diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp index a33fc844a5..8a5910c10e 100644 --- a/scene/2d/animated_sprite.cpp +++ b/scene/2d/animated_sprite.cpp @@ -395,15 +395,17 @@ void AnimatedSprite::_notification(int p_what) { int fc = frames->get_frame_count(animation); if (frame >= fc - 1) { if (frames->get_animation_loop(animation)) { + emit_signal(SceneStringNames::get_singleton()->animation_finished); frame = 0; } else { + if (!is_over) { + emit_signal(SceneStringNames::get_singleton()->animation_finished); + is_over = true; + } frame = fc - 1; } } else { frame++; - if (frame == fc - 1) { - emit_signal(SceneStringNames::get_singleton()->animation_finished); - } } update(); @@ -625,6 +627,7 @@ void AnimatedSprite::_reset_timeout() { return; timeout = _get_frame_duration(); + is_over = false; } void AnimatedSprite::set_animation(const StringName &p_animation) { @@ -712,4 +715,5 @@ AnimatedSprite::AnimatedSprite() { playing = false; animation = "default"; timeout = 0; + is_over = false; } diff --git a/scene/2d/animated_sprite.h b/scene/2d/animated_sprite.h index cc49465403..7270ee4d0e 100644 --- a/scene/2d/animated_sprite.h +++ b/scene/2d/animated_sprite.h @@ -135,6 +135,7 @@ class AnimatedSprite : public Node2D { bool centered; Point2 offset; + bool is_over; float timeout; bool hflip; diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index a1ae05d971..9de72a4fcd 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -179,7 +179,7 @@ void AudioStreamPlayer2D::_notification(int p_what) { Physics2DDirectSpaceState::ShapeResult sr[MAX_INTERSECT_AREAS]; - int areas = space_state->intersect_point(global_pos, sr, MAX_INTERSECT_AREAS, Set<RID>(), area_mask); + int areas = space_state->intersect_point(global_pos, sr, MAX_INTERSECT_AREAS, Set<RID>(), area_mask, false, true); for (int i = 0; i < areas; i++) { diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index d29c6b37d5..e6dcd643be 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -985,7 +985,7 @@ void CPUParticles2D::_notification(int p_what) { if (p_what == NOTIFICATION_INTERNAL_PROCESS) { - if (particles.size() == 0) + if (particles.size() == 0 || !is_visible_in_tree()) return; float delta = get_process_delta_time(); diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index abf022ecb3..7ad43b722d 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -290,7 +290,7 @@ void AudioStreamPlayer3D::_notification(int p_what) { PhysicsDirectSpaceState::ShapeResult sr[MAX_INTERSECT_AREAS]; - int areas = space_state->intersect_point(global_pos, sr, MAX_INTERSECT_AREAS, Set<RID>(), area_mask); + int areas = space_state->intersect_point(global_pos, sr, MAX_INTERSECT_AREAS, Set<RID>(), area_mask, false, true); Area *area = NULL; for (int i = 0; i < areas; i++) { diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp index 8f3fe8577e..62589bd67e 100644 --- a/scene/3d/baked_lightmap.cpp +++ b/scene/3d/baked_lightmap.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "baked_lightmap.h" +#include "core/io/config_file.h" #include "core/io/resource_saver.h" #include "core/os/dir_access.h" #include "core/os/os.h" @@ -526,21 +527,60 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, bool p_create_vi tex_flags |= Texture::FLAG_CONVERT_TO_LINEAR; } - Ref<ImageTexture> tex; - String image_path = save_path.plus_file(mesh_name + ".tex"); - bool set_path = true; - if (ResourceCache::has(image_path)) { - tex = Ref<Resource>((Resource *)ResourceCache::get(image_path)); - set_path = false; - } + String image_path = save_path.plus_file(mesh_name); + Ref<Texture> texture; - if (!tex.is_valid()) { - tex.instance(); - } + if (ResourceLoader::import) { + + bool srgb = false; + if (false && hdr) { + //save hdr + } else { + image_path += ".png"; + print_line("image path saving png: " + image_path); + image->save_png(image_path); + srgb = true; + } - tex->create_from_image(image, tex_flags); + if (!FileAccess::exists(image_path + ".import")) { + Ref<ConfigFile> config; + config.instance(); + config->set_value("remap", "importer", "texture"); + config->set_value("remap", "type", "StreamTexture"); + config->set_value("params", "compress/mode", 2); + config->set_value("params", "detect_3d", false); + config->set_value("params", "flags/repeat", false); + config->set_value("params", "flags/filter", true); + config->set_value("params", "flags/mipmaps", false); + config->set_value("params", "flags/srgb", srgb); + + config->save(image_path + ".import"); + } + + ResourceLoader::import(image_path); + texture = ResourceLoader::load(image_path); //if already loaded, it will be updated on refocus? + } else { - err = ResourceSaver::save(image_path, tex, ResourceSaver::FLAG_CHANGE_PATH); + image_path += ".text"; + Ref<ImageTexture> tex; + bool set_path = true; + if (ResourceCache::has(image_path)) { + tex = Ref<Resource>((Resource *)ResourceCache::get(image_path)); + set_path = false; + } + + if (!tex.is_valid()) { + tex.instance(); + } + + tex->create_from_image(image, tex_flags); + + err = ResourceSaver::save(image_path, tex, ResourceSaver::FLAG_CHANGE_PATH); + if (set_path) { + tex->set_path(image_path); + } + texture = tex; + } if (err != OK) { if (bake_end_function) { bake_end_function(); @@ -548,10 +588,7 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, bool p_create_vi ERR_FAIL_COND_V(err != OK, BAKE_ERROR_CANT_CREATE_IMAGE); } - if (set_path) { - tex->set_path(image_path); - } - new_light_data->add_user(E->get().path, tex, E->get().instance_idx); + new_light_data->add_user(E->get().path, texture, E->get().instance_idx); } } diff --git a/scene/3d/cpu_particles.cpp b/scene/3d/cpu_particles.cpp index ec51c31674..35a2049bda 100644 --- a/scene/3d/cpu_particles.cpp +++ b/scene/3d/cpu_particles.cpp @@ -592,7 +592,7 @@ void CPUParticles::_particles_process(float p_delta) { Vector3 direction_xz = Vector3(Math::sin(angle1_rad), 0, Math::cos(angle1_rad)); Vector3 direction_yz = Vector3(0, Math::sin(angle2_rad), Math::cos(angle2_rad)); - direction_yz.z = direction_yz.z / Math::sqrt(direction_yz.z); //better uniform distribution + direction_yz.z = direction_yz.z / MAX(0.0001, Math::sqrt(ABS(direction_yz.z))); //better uniform distribution Vector3 direction = Vector3(direction_xz.x * direction_yz.z, direction_yz.y, direction_xz.z * direction_yz.z); direction.normalize(); p.velocity = direction * parameters[PARAM_INITIAL_LINEAR_VELOCITY] * Math::lerp(1.0f, float(Math::randf()), randomness[PARAM_INITIAL_LINEAR_VELOCITY]); @@ -977,6 +977,8 @@ void CPUParticles::_update_particle_data_buffer() { ptr += 17; } + + can_update = true; } #ifndef NO_THREADS @@ -989,8 +991,10 @@ void CPUParticles::_update_render_thread() { #ifndef NO_THREADS update_mutex->lock(); #endif - - VS::get_singleton()->multimesh_set_as_bulk_array(multimesh, particle_data); + if (can_update) { + VS::get_singleton()->multimesh_set_as_bulk_array(multimesh, particle_data); + can_update = false; //wait for next time + } #ifndef NO_THREADS update_mutex->unlock(); @@ -1032,7 +1036,7 @@ void CPUParticles::_notification(int p_what) { if (p_what == NOTIFICATION_INTERNAL_PROCESS) { - if (particles.size() == 0) + if (particles.size() == 0 || !is_visible_in_tree()) return; float delta = get_process_delta_time(); @@ -1061,6 +1065,8 @@ void CPUParticles::_notification(int p_what) { } } + bool processed = false; + if (time == 0 && pre_process_time > 0.0) { float frame_time; @@ -1073,6 +1079,7 @@ void CPUParticles::_notification(int p_what) { while (todo >= 0) { _particles_process(frame_time); + processed = true; todo -= frame_time; } } @@ -1091,6 +1098,7 @@ void CPUParticles::_notification(int p_what) { while (todo >= frame_time) { _particles_process(frame_time); + processed = true; todo -= decr; } @@ -1098,9 +1106,12 @@ void CPUParticles::_notification(int p_what) { } else { _particles_process(delta); + processed = true; } - _update_particle_data_buffer(); + if (processed) { + _update_particle_data_buffer(); + } } } @@ -1424,6 +1435,8 @@ CPUParticles::CPUParticles() { flags[i] = false; } + can_update = false; + set_color(Color(1, 1, 1, 1)); #ifndef NO_THREADS diff --git a/scene/3d/cpu_particles.h b/scene/3d/cpu_particles.h index 4e29d8d4ce..77a144b70b 100644 --- a/scene/3d/cpu_particles.h +++ b/scene/3d/cpu_particles.h @@ -142,6 +142,8 @@ private: int fixed_fps; bool fractional_delta; + volatile bool can_update; + DrawOrder draw_order; Ref<Mesh> mesh; diff --git a/scene/3d/voxel_light_baker.cpp b/scene/3d/voxel_light_baker.cpp index 5580cabe30..f9bd905181 100644 --- a/scene/3d/voxel_light_baker.cpp +++ b/scene/3d/voxel_light_baker.cpp @@ -1587,8 +1587,8 @@ Vector3 VoxelLightBaker::_compute_pixel_light_at_pos(const Vector3 &p_pos, const Vector3 bitangent = tangent.cross(p_normal).normalized(); Basis normal_xform = Basis(tangent, bitangent, p_normal).transposed(); - const Vector3 *cone_dirs; - const float *cone_weights; + const Vector3 *cone_dirs = NULL; + const float *cone_weights = NULL; int cone_dir_count = 0; float cone_aperture = 0; diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index 71fb97c2c6..6dfaacc776 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -368,7 +368,7 @@ BaseButton::DrawMode BaseButton::get_draw_mode() const { return DRAW_DISABLED; }; - if (status.press_attempt == false && status.hovering) { + if (!status.press_attempt && status.hovering) { if (status.pressed) return DRAW_HOVER_PRESSED; diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 03eee9c6d8..c5d3def4c1 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -159,7 +159,10 @@ void ColorPicker::_html_entered(const String &p_html) { if (updating) return; + float last_alpha = color.a; color = Color::html(p_html); + if (!is_editing_alpha()) + color.a = last_alpha; if (!is_inside_tree()) return; diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index b90a4c17f4..e155d0ef86 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -769,7 +769,7 @@ void Control::force_drag(const Variant &p_data, Control *p_control) { void Control::set_drag_preview(Control *p_control) { ERR_FAIL_COND(!is_inside_tree()); - ERR_FAIL_COND(get_viewport()->gui_is_dragging()); + ERR_FAIL_COND(!get_viewport()->gui_is_dragging()); get_viewport()->_gui_set_drag_preview(this, p_control); } @@ -1079,7 +1079,7 @@ bool Control::has_constant_override(const StringName &p_name) const { bool Control::has_icon(const StringName &p_name, const StringName &p_type) const { if (p_type == StringName() || p_type == "") { - if (has_icon_override(p_name) == true) + if (has_icon_override(p_name)) return true; } @@ -1113,7 +1113,7 @@ bool Control::has_icon(const StringName &p_name, const StringName &p_type) const bool Control::has_shader(const StringName &p_name, const StringName &p_type) const { if (p_type == StringName() || p_type == "") { - if (has_shader_override(p_name) == true) + if (has_shader_override(p_name)) return true; } @@ -1146,7 +1146,7 @@ bool Control::has_shader(const StringName &p_name, const StringName &p_type) con bool Control::has_stylebox(const StringName &p_name, const StringName &p_type) const { if (p_type == StringName() || p_type == "") { - if (has_stylebox_override(p_name) == true) + if (has_stylebox_override(p_name)) return true; } @@ -1179,7 +1179,7 @@ bool Control::has_stylebox(const StringName &p_name, const StringName &p_type) c bool Control::has_font(const StringName &p_name, const StringName &p_type) const { if (p_type == StringName() || p_type == "") { - if (has_font_override(p_name) == true) + if (has_font_override(p_name)) return true; } @@ -1213,7 +1213,7 @@ bool Control::has_font(const StringName &p_name, const StringName &p_type) const bool Control::has_color(const StringName &p_name, const StringName &p_type) const { if (p_type == StringName() || p_type == "") { - if (has_color_override(p_name) == true) + if (has_color_override(p_name)) return true; } @@ -1247,7 +1247,7 @@ bool Control::has_color(const StringName &p_name, const StringName &p_type) cons bool Control::has_constant(const StringName &p_name, const StringName &p_type) const { if (p_type == StringName() || p_type == "") { - if (has_constant_override(p_name) == true) + if (has_constant_override(p_name)) return true; } diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp index 19ffe681ef..934b84ec0c 100644 --- a/scene/gui/gradient_edit.cpp +++ b/scene/gui/gradient_edit.cpp @@ -238,21 +238,21 @@ void GradientEdit::_gui_input(const Ref<InputEvent> &p_event) { if (mm->get_shift()) { float snap_treshhold = 0.03; float smallest_ofs = snap_treshhold; - bool founded = false; - int nearest_point; + bool found = false; + int nearest_point = 0; for (int i = 0; i < points.size(); ++i) { if (i != grabbed) { float temp_ofs = ABS(points[i].offset - newofs); if (temp_ofs < smallest_ofs) { smallest_ofs = temp_ofs; nearest_point = i; - if (founded) + if (found) break; - founded = true; + found = true; } } } - if (founded) { + if (found) { if (points[nearest_point].offset < newofs) newofs = points[nearest_point].offset + 0.00001; else diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp index 278e4123d7..bb1d1d7695 100644 --- a/scene/gui/grid_container.cpp +++ b/scene/gui/grid_container.cpp @@ -184,8 +184,6 @@ void GridContainer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_columns", "columns"), &GridContainer::set_columns); ClassDB::bind_method(D_METHOD("get_columns"), &GridContainer::get_columns); - ClassDB::bind_method(D_METHOD("get_child_control_at_cell", "row", "column"), - &GridContainer::get_child_control_at_cell); ADD_PROPERTY(PropertyInfo(Variant::INT, "columns", PROPERTY_HINT_RANGE, "1,1024,1"), "set_columns", "get_columns"); } @@ -241,21 +239,6 @@ Size2 GridContainer::get_minimum_size() const { return ms; } -Control *GridContainer::get_child_control_at_cell(int row, int column) { - Control *c; - int grid_index = row * columns + column; - for (int i = 0; i < get_child_count(); i++) { - c = Object::cast_to<Control>(get_child(i)); - if (!c || !c->is_visible_in_tree()) - continue; - - if (grid_index == i) { - break; - } - } - return c; -} - GridContainer::GridContainer() { set_mouse_filter(MOUSE_FILTER_PASS); diff --git a/scene/gui/grid_container.h b/scene/gui/grid_container.h index 7e3470dc89..243d06f034 100644 --- a/scene/gui/grid_container.h +++ b/scene/gui/grid_container.h @@ -47,7 +47,6 @@ public: void set_columns(int p_columns); int get_columns() const; virtual Size2 get_minimum_size() const; - Control *get_child_control_at_cell(int row, int column); GridContainer(); }; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index c390c60a8c..f8a5c4cea3 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -334,15 +334,12 @@ void TextEdit::_update_scrollbars() { h_scroll->set_begin(Point2(0, size.height - hmin.height)); h_scroll->set_end(Point2(size.width - vmin.width, size.height)); - int hscroll_rows = ((hmin.height - 1) / get_row_height()) + 1; int visible_rows = get_visible_rows(); - int total_rows = get_total_visible_rows(); if (scroll_past_end_of_file_enabled) { total_rows += visible_rows - 1; } - int vscroll_pixels = v_scroll->get_combined_minimum_size().width; int visible_width = size.width - cache.style_normal->get_minimum_size().width; int total_width = text.get_max_width(true) + vmin.x; @@ -367,12 +364,12 @@ void TextEdit::_update_scrollbars() { } else { - if (total_rows > visible_rows && total_width <= visible_width - vscroll_pixels) { + if (total_rows > visible_rows && total_width <= visible_width) { //thanks yessopie for this clever bit of logic use_hscroll = false; } - if (total_rows <= visible_rows - hscroll_rows && total_width > visible_width) { + if (total_rows <= visible_rows && total_width > visible_width) { //thanks yessopie for this clever bit of logic use_vscroll = false; } @@ -2334,9 +2331,9 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { // no need to indent if we are going upwards. if (auto_indent && !(k->get_command() && k->get_shift())) { - // indent once again if previous line will end with ':' or '{' + // indent once again if previous line will end with ':' or '{' and the line is not a comment // (i.e. colon/brace precedes current cursor position) - if (cursor.column > 0 && (text[cursor.line][cursor.column - 1] == ':' || text[cursor.line][cursor.column - 1] == '{')) { + if (cursor.column > 0 && (text[cursor.line][cursor.column - 1] == ':' || text[cursor.line][cursor.column - 1] == '{') && !is_line_comment(cursor.line)) { if (indent_using_spaces) { ins += space_indent; } else { @@ -3260,7 +3257,7 @@ void TextEdit::_scroll_down(real_t p_delta) { } if (smooth_scroll_enabled) { - int max_v_scroll = v_scroll->get_max() - v_scroll->get_page(); + int max_v_scroll = round(v_scroll->get_max() - v_scroll->get_page()); if (target_v_scroll > max_v_scroll) { target_v_scroll = max_v_scroll; v_scroll->set_value(target_v_scroll); diff --git a/scene/gui/texture_progress.cpp b/scene/gui/texture_progress.cpp index 7ecdccb0e4..75f88dc4e6 100644 --- a/scene/gui/texture_progress.cpp +++ b/scene/gui/texture_progress.cpp @@ -148,9 +148,9 @@ Point2 TextureProgress::unit_val_to_uv(float val) { float angle = (val * Math_TAU) - Math_PI * 0.5; Point2 dir = Vector2(Math::cos(angle), Math::sin(angle)); float t1 = 1.0; - float cp; - float cq; - float cr; + float cp = 0; + float cq = 0; + float cr = 0; float edgeLeft = 0.0; float edgeRight = 1.0; float edgeBottom = 0.0; diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 3a540d187b..0c11181f98 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -2183,6 +2183,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { Ref<InputEventKey> k = p_event; + bool is_command = k.is_valid() && k->get_command(); if (p_event->is_action("ui_right") && p_event->is_pressed()) { if (!cursor_can_exit_tree) accept_event(); @@ -2219,13 +2220,13 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { _go_left(); } - } else if (p_event->is_action("ui_up") && p_event->is_pressed() && !k->get_command()) { + } else if (p_event->is_action("ui_up") && p_event->is_pressed() && !is_command) { if (!cursor_can_exit_tree) accept_event(); _go_up(); - } else if (p_event->is_action("ui_down") && p_event->is_pressed() && !k->get_command()) { + } else if (p_event->is_action("ui_down") && p_event->is_pressed() && !is_command) { if (!cursor_can_exit_tree) accept_event(); @@ -2933,7 +2934,7 @@ void Tree::_notification(int p_what) { if (show_column_titles) { - //title butons + //title buttons int ofs = cache.bg->get_margin(MARGIN_LEFT); for (int i = 0; i < columns.size(); i++) { diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp index 6f67ba8af1..ba48982fda 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particles_material.cpp @@ -308,7 +308,7 @@ void ParticlesMaterial::_update_shader() { code += " float angle2_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad * (1.0 - flatness);\n"; code += " vec3 direction_xz = vec3(sin(angle1_rad), 0, cos(angle1_rad));\n"; code += " vec3 direction_yz = vec3(0, sin(angle2_rad), cos(angle2_rad));\n"; - code += " direction_yz.z = direction_yz.z / sqrt(direction_yz.z); // better uniform distribution\n"; + code += " direction_yz.z = direction_yz.z / max(0.0001,sqrt(abs(direction_yz.z))); // better uniform distribution\n"; code += " vec3 direction = vec3(direction_xz.x * direction_yz.z, direction_yz.y, direction_xz.z * direction_yz.z);\n"; code += " direction = normalize(direction);\n"; code += " VELOCITY = direction * initial_linear_velocity * mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; diff --git a/scene/resources/shape.cpp b/scene/resources/shape.cpp index 8ccca81acd..869f4a3a9b 100644 --- a/scene/resources/shape.cpp +++ b/scene/resources/shape.cpp @@ -101,7 +101,7 @@ void Shape::_bind_methods() { ClassDB::bind_method(D_METHOD("set_margin", "margin"), &Shape::set_margin); ClassDB::bind_method(D_METHOD("get_margin"), &Shape::get_margin); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "margin", PROPERTY_HINT_RANGE, "0.04,10,0.01"), "set_margin", "get_margin"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "margin", PROPERTY_HINT_RANGE, "0.04,10,0.001"), "set_margin", "get_margin"); } Shape::Shape() : diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index fead2f54da..d36057b465 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -1297,6 +1297,7 @@ void AudioServer::_bind_methods() { ADD_SIGNAL(MethodInfo("bus_layout_changed")); BIND_ENUM_CONSTANT(SPEAKER_MODE_STEREO); + BIND_ENUM_CONSTANT(SPEAKER_SURROUND_31); BIND_ENUM_CONSTANT(SPEAKER_SURROUND_51); BIND_ENUM_CONSTANT(SPEAKER_SURROUND_71); } diff --git a/servers/physics/collision_solver_sw.cpp b/servers/physics/collision_solver_sw.cpp index 2f2f6d2908..86ef719f6f 100644 --- a/servers/physics/collision_solver_sw.cpp +++ b/servers/physics/collision_solver_sw.cpp @@ -31,7 +31,6 @@ #include "collision_solver_sw.h" #include "collision_solver_sat.h" -#include "collision_solver_sat.h" #include "gjk_epa.h" #define collision_solver sat_calculate_penetration diff --git a/servers/physics/joints/generic_6dof_joint_sw.cpp b/servers/physics/joints/generic_6dof_joint_sw.cpp index 9b1a41e80d..60505c08c5 100644 --- a/servers/physics/joints/generic_6dof_joint_sw.cpp +++ b/servers/physics/joints/generic_6dof_joint_sw.cpp @@ -83,7 +83,7 @@ int G6DOFRotationalLimitMotorSW::testLimitValue(real_t test_value) { real_t G6DOFRotationalLimitMotorSW::solveAngularLimits( real_t timeStep, Vector3 &axis, real_t jacDiagABInv, BodySW *body0, BodySW *body1) { - if (needApplyTorques() == false) return 0.0f; + if (!needApplyTorques()) return 0.0f; real_t target_velocity = m_targetVelocity; real_t maxMotorForce = m_maxMotorForce; diff --git a/servers/physics/joints/generic_6dof_joint_sw.h b/servers/physics/joints/generic_6dof_joint_sw.h index b350546c5d..035525c9e6 100644 --- a/servers/physics/joints/generic_6dof_joint_sw.h +++ b/servers/physics/joints/generic_6dof_joint_sw.h @@ -118,14 +118,12 @@ public: //! Is limited bool isLimited() { - if (m_loLimit >= m_hiLimit) return false; - return true; + return (m_loLimit < m_hiLimit); } //! Need apply correction bool needApplyTorques() { - if (m_currentLimit == 0 && m_enableMotor == false) return false; - return true; + return (m_enableMotor || m_currentLimit != 0); } //! calculates error diff --git a/servers/physics/shape_sw.cpp b/servers/physics/shape_sw.cpp index e1c985f44f..e7fc821c2c 100644 --- a/servers/physics/shape_sw.cpp +++ b/servers/physics/shape_sw.cpp @@ -1047,7 +1047,7 @@ void FaceShapeSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_su /** FIND SUPPORT VERTEX **/ int vert_support_idx = -1; - real_t support_max; + real_t support_max = 0; for (int i = 0; i < 3; i++) { diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp index 2633edf7bb..93a05b74ef 100644 --- a/servers/physics_2d/body_pair_2d_sw.cpp +++ b/servers/physics_2d/body_pair_2d_sw.cpp @@ -138,7 +138,7 @@ void BodyPair2DSW::_validate_contacts() { Contact &c = contacts[i]; bool erase = false; - if (c.reused == false) { + if (!c.reused) { //was left behind in previous frame erase = true; } else { diff --git a/servers/physics_2d/step_2d_sw.cpp b/servers/physics_2d/step_2d_sw.cpp index 0fb7af0c94..e4e1b03623 100644 --- a/servers/physics_2d/step_2d_sw.cpp +++ b/servers/physics_2d/step_2d_sw.cpp @@ -222,7 +222,7 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) { Constraint2DSW *prev_ci = NULL; while (ci) { - if (_setup_island(ci, p_delta) == true) { + if (_setup_island(ci, p_delta)) { //removed the root from the island graph because it is not to be processed diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp index 57e8d86468..69acf52e17 100644 --- a/servers/visual/shader_types.cpp +++ b/servers/visual/shader_types.cpp @@ -109,6 +109,7 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["EMISSION"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_SCISSOR"] = ShaderLanguage::TYPE_FLOAT; diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index cd0702d20b..654994b83f 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -2831,7 +2831,7 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) { RID rid = E->key(); const InstanceGIProbeData::LightCache &lc = E->get(); - if ((!probe_data->dynamic.light_cache_changes.has(rid) || !(probe_data->dynamic.light_cache_changes[rid] == lc)) && lc.visible) { + if ((!probe_data->dynamic.light_cache_changes.has(rid) || probe_data->dynamic.light_cache_changes[rid] != lc) && lc.visible) { //erase light data _bake_gi_probe_light(header, cells, local_data, leaves, leaf_count, lc, -1); @@ -2844,7 +2844,7 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) { RID rid = E->key(); const InstanceGIProbeData::LightCache &lc = E->get(); - if ((!probe_data->dynamic.light_cache.has(rid) || !(probe_data->dynamic.light_cache[rid] == lc)) && lc.visible) { + if ((!probe_data->dynamic.light_cache.has(rid) || probe_data->dynamic.light_cache[rid] != lc) && lc.visible) { //add light data _bake_gi_probe_light(header, cells, local_data, leaves, leaf_count, lc, 1); @@ -3061,7 +3061,7 @@ bool VisualServerScene::_check_gi_probe(Instance *p_gi_probe) { lc.transform = probe_data->dynamic.light_to_cell_xform * E->get()->transform; lc.visible = E->get()->visible; - if (!probe_data->dynamic.light_cache.has(E->get()->self) || !(probe_data->dynamic.light_cache[E->get()->self] == lc)) { + if (!probe_data->dynamic.light_cache.has(E->get()->self) || probe_data->dynamic.light_cache[E->get()->self] != lc) { all_equal = false; } @@ -3081,7 +3081,7 @@ bool VisualServerScene::_check_gi_probe(Instance *p_gi_probe) { lc.transform = probe_data->dynamic.light_to_cell_xform * E->get()->transform; lc.visible = E->get()->visible; - if (!probe_data->dynamic.light_cache.has(E->get()->self) || !(probe_data->dynamic.light_cache[E->get()->self] == lc)) { + if (!probe_data->dynamic.light_cache.has(E->get()->self) || probe_data->dynamic.light_cache[E->get()->self] != lc) { all_equal = false; } @@ -3164,7 +3164,7 @@ void VisualServerScene::render_probes() { force_lighting = true; } - if (probe->invalid == false && probe->dynamic.enabled) { + if (!probe->invalid && probe->dynamic.enabled) { switch (probe->dynamic.updating_stage) { case GI_UPDATE_STAGE_CHECK: { diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h index bcd6d1d972..0d4737f268 100644 --- a/servers/visual/visual_server_scene.h +++ b/servers/visual/visual_server_scene.h @@ -355,6 +355,11 @@ public: visible == p_cache.visible); } + bool operator!=(const LightCache &p_cache) { + + return !operator==(p_cache); + } + LightCache() { type = VS::LIGHT_DIRECTIONAL; |